Re: [CMake] Multiple occurrences of a library on linux (ldd)

2019-02-14 Thread Thiago Crepaldi
I might be getting close and the root cause might be related to a
conceptual question that I was saving for later: how transitive
linking should be done!

Returning to the build design: pytorch is compile if not installed in
the system, lib datareader_core consumes pytorch and standalone_gtests
consumes datareader_core
  (aka standalone_gtests --> lib_datareader.so --> libc10.so)

Here are the relevant snippets from all relevant cmake files:

***/CMakeLists.txt***
(...)
# pytorch will be compile here
add_subdirectory(external/upstream)

# datareader_core lib will consume torch during its build
ExternalProject_Add(${PROJECT_NAME}_core
   DEPENDS pytorch_external
   SOURCE_DIR (...)
   CMAKE_ARGS (...)
   CMAKE_CACHE_ARGS (...)
   BUILD_ALWAYS 1
)

# Consumes datareader_core, which consumes pytorch (libc10.so and libcaffe2.so)
ExternalProject_Add(${PROJECT_NAME}_core_test
   DEPENDS ${PROJECT_NAME}_core
   SOURCE_DIR (...)
   CMAKE_ARGS (...)
   CMAKE_CACHE_ARGS -DDATAREADER_CORE_ROOT:INTERNAL=${DATAREADER_CORE_ROOT}

-DDATAREADER_CORE_LIBRARYDIR:INTERNAL=${DATAREADER_CORE_LIBRARYDIR}

-DDATAREADER_CORE_INCLUDEDIR:INTERNAL=${DATAREADER_CORE_INCLUDEDIR}
   (...)
   BUILD_ALWAYS 1
)

***/external/upstream/CMakeLists.txt***
add_subdirectory(pytorch)

/external/upstream/CMakeLists.txt
find_package(Torch QUIET)
if(NOT Torch_FOUND)
   message(STATUS "Pytorch not found in the systemm. Looking in the
build environment")
   set(
  CMAKE_PREFIX_PATH "${EP_BASE}/Source/pytorch_external/torch/share/cmake"
  CACHE INTERNAL "Path to Pytorch cmake configs"
  FORCE
   )
   find_package(Torch QUIET)
endif()

if(Torch_FOUND)
   add_library(pytorch_external INTERFACE)
else()
   message(STATUS "Pytorch could not be located. Building instead")

   include(ExternalProject)
   ExternalProject_Add(pytorch_external (...)
endif()

***/datareader_src/CMakeLists.txt***
project(datareader_core)

   add_library(datareader SHARED ${DATAREADER_SRC})
   find_package(Torch REQUIRED)
   target_include_directories(datareader PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include)
   target_link_libraries(datareader PUBLIC ${TORCH_LIBRARIES})

***/datareader_test_src/CMakeLists.txt***
project(datareader_core_test)

enable_testing()
add_executable(standalone_gtests test.cpp)
find_package(GTest REQUIRED)
find_package(Threads REQUIRED)
target_include_directories(standalone_gtests PUBLIC
${DATAREADER_CORE_INCLUDEDIR}
${GOOGLETEST_INCLUDEDIR}
${CMAKE_CURRENT_SOURCE_DIR}/../)

target_link_libraries(standalone_gtests PUBLIC
${TORCH_LIBRARIES}
${DATAREADER}
${GTEST_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)

At this point, Pytorch is looked in the system by find_package(Torch),
if not found, it will be cloned and compiled. datareader_core lib
find_package(Torch) and link to it. Lastly, datareader_core_test app
will link to datareader_core lib.
If I ldd libdatareader.so, I can see libc10.so (from pytorch) is
properly linked. However, datareader_core_test compilation will fail
with an undefined reference to symbol inside libc10.so:
/usr/bin/ld: warning: libcaffe2.so, needed by
/home/dev/miniconda3/datareaders_py37/build/stage/datareader/lib/libdatareader.so,
not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libc10.so, needed by
/home/dev/miniconda3/datareaders_py37/build/stage/datareader/lib/libdatareader.so,
not found (try using -rpath or -rpath-link)
/home/dev/miniconda3/datareaders_py37/build/stage/datareader/lib/libdatareader.so:
undefined reference to `c10::Error::Error(c10::SourceLocation,
std::__cxx11::basic_string,
std::allocator > const&)'
collect2: error: ld returned 1 exit status

My understanding was that if datareader_core did
target_link_libraries(datareader PUBLIC ${TORCH_LIBRARIES}), then any
other target that depends on datareader target would be properly
linked to its public dependences libraries.
Where is my mistake? To work this around, I have added
find_package(Torch REQUIRED) and
target_link_libraries(standalone_gtests PUBLIC ${TORCH_LIBRARIES}) to
standalone_gtests, although it doesn't directly consume anything from
pytorch. That change lead to the original issue of having
standalone_gtests having two entries of libc10.so in the ldd output:
one because of the indirect lib datareader dependency (not fond) and
another due tot he direct linking (working)

Am I linking Torch incorrectly to datareader_core or maybe
ExternalProject_Add(datareader_core) hides linking information from
another target inside another
ExternalProject_Add(datareader_core_test)?
I am a bit confused by the explanation at
https://cmake.org/cmake/help/latest/command/target_link_libraries.html
and this build and your help might help solidify the private, public
and interface concepts.

Thanks again
Thiago
On Thu, Feb 14, 2019 at 7:42 AM Thiago Crepaldi  wrote:
>
> Thanks, Thompson, I will look into BUILD_RPATH and possibly INSTALL_RPATH.
>
> I just learned about `export LD_DEBUG=files` to debug linking issues
> on linux. It provides more det

Re: [CMake] Multiple occurrences of a library on linux (ldd)

2019-02-14 Thread Thiago Crepaldi
Thanks, Thompson, I will look into BUILD_RPATH and possibly INSTALL_RPATH.

I just learned about `export LD_DEBUG=files` to debug linking issues
on linux. It provides more detail on the ldd output, as below:

18843: file=libc10.so [0];  needed by
/home/dev/miniconda3/datareaders_py37/build/stage/datareader/lib/libdatareader.so
[0]
   (no linking information)
18843: file=libdatareader.so [0];  needed by
subprojects/Build/datareaders_core_test/standalone_gtests [0]
18843: file=libdatareader.so [0];  generating link map
(linking information)
(...)
18843: file=libc10.so [0];  needed by
/home/dev/miniconda3/datareaders_py37/build/subprojects/Source/pytorch_external/torch/lib/libcaffe2.so
[0]
18843: file=libc10.so [0];  generating link map
   (linking information)
18843: file=libcaffe2.so [0];  needed by
subprojects/Build/datareaders_core_test/standalone_gtests [0]
18843: file=libcaffe2.so [0];  generating link map
   (linking information)

Now I can see that the missing libc10.so is needed by
`libdatareader.so`, which was linked against `standalone_gtests`.

However, RUNPATH for both `libdatareader.so` and `standalone_gtests`
seems to be correct and point to the same torch/lib folder that has
libc10.so:
libdatareader.so:
RUNPATH=/home/dev/miniconda3/datareaders_py37/build/stage/boost/lib:/home/dev/miniconda3/datareaders_py37/build/subprojects/Source/pytorch_external/torch/lib:
standalone_gtests:
RUNPATH=/home/dev/miniconda3/datareaders_py37/build/stage/boost/lib:/home/dev/miniconda3/datareaders_py37/build/subprojects/Source/pytorch_external/torch/lib:/home/dev/miniconda3/datareaders_py37/build/stage/datareader/lib

So, libdatareader.so links to libcaffe2.so which links to libc10.so
successfully; standalone_gtests links to libcaffe2.so which links to
libc10.so successully too; however, when standalone_gtests links to
libdatareader.so, there is a transitive linking issue with
libdatareader.so dependency on libc10.so, like the diagram below:

libdatareader.so ---> libcaffe2.so ---> libc10.so (ok)

standalone_gtests 0 ---> libcaffe2.so ---> libc10.so (ok)
  |
  ---> libdatareader.so ---> libc10.so (not found)


Thanks again,
Thiago



On Thu, Feb 14, 2019 at 6:13 AM Thompson, KT  wrote:
>
> Thiago,
>
>
>
> I haven’t see the double entry pattern that you mention below.  However, you 
> might want to tell CMake to embed a BUILD_RPATH in your libraries.  This 
> should get around the issue of manually setting LD_LIBRARY_PATH.
>
>
>
> https://cmake.org/cmake/help/latest/prop_tgt/BUILD_RPATH.html?highlight=rpath
>
>
>
> -kt
>
>
>
> From: CMake  On Behalf Of Thiago Crepaldi
> Sent: Thursday, February 14, 2019 12:43 AM
> To: cmake@cmake.org
> Subject: [CMake] Multiple occurrences of a library on linux (ldd)
>
>
>
> Hello all,
>
>
>
> After reading CMake Cookbook I have written my first "complex" CMake build 
> script based on the superbuild pattern. I am excited to heave a better 
> understanding on CMake, but I definitely will learn much more from experience 
> and your kind help.
>
> In summary, the standalone google test application `standalone_gtests` 
> publicly links to `libdatareader.so` and to pytorch libraries 
> (`libc10.so`,`libcafee2.so`, `libtorch.so`).
>
> `libdatareader.so` also publicly links to pytorch libraries (I have a 
> theoretical question on why `standalone_gtests` had to link to pytorch 
> libraries if `libdatareader.so` already did, but that can wait).
>
>
>
> Compilation finishes successfully, but when I try to run `standalone_gtests`, 
> it aborts because it cant find `libc10.so`.
>
> After executing `ldd standalone_gtests`, the weird result was that there were 
> two entries for `libc10.so`.
>
> The first one maps to "not found" while the second had the correct path to 
> the library. `libcaffe2.so`, which is also a pytorch library, has a single 
> occurrence with full path.
>
> If I add the (...)/pytorch_external/(...) (see ldd output below) path to 
> LD_LIBRARY_PATH, then everything works, but I would like to avoid this, if 
> possible.
>
>
>
> `ldd ./subprojects/Build/datareaders_core_test/standalone_gtests
>
> libdatareader.so => 
> /home/dev/miniconda3/datareaders_py37/build/stage/datareader/lib/libdatareader.so
>
> libcaffe2.so => 
> /home/dev/miniconda3/datareaders_py37/build/subprojects/Source/pytorch_external/torch/lib/libcaffe2.so
>
> libc10.so => not found
>
> libc10.so => 
> /home/dev/miniconda3/datareaders_py37/build/subprojects/Source/pytorch_external/torch/lib/libc10.so
>
> (...)`
>
>
>
> Have anyone seen multiple entries for the same library on ldd before? Why is 
> that? Is it because `standalone_gtests` links to libc10.so and to 
> `libdatareader.so`, which in turn also links to `libc10.so`?
>
> Both CMakeLists.txt (libdatareader and standalone_gtests) succeeds at 
> find_package(Torch REQUIRED QUIET) commands (${TORCH_LIBRARY} returns the 
> correct path).
>
>
>
>
>
> I run the same 

Re: [CMake] Multiple occurrences of a library on linux (ldd)

2019-02-14 Thread Thompson, KT via CMake
Thiago,

I haven’t see the double entry pattern that you mention below.  However, you 
might want to tell CMake to embed a BUILD_RPATH in your libraries.  This should 
get around the issue of manually setting LD_LIBRARY_PATH.

https://cmake.org/cmake/help/latest/prop_tgt/BUILD_RPATH.html?highlight=rpath

-kt

From: CMake  On Behalf Of Thiago Crepaldi
Sent: Thursday, February 14, 2019 12:43 AM
To: cmake@cmake.org
Subject: [CMake] Multiple occurrences of a library on linux (ldd)

Hello all,

After reading CMake Cookbook I have written my first "complex" CMake build 
script based on the superbuild pattern. I am excited to heave a better 
understanding on CMake, but I definitely will learn much more from experience 
and your kind help.
In summary, the standalone google test application `standalone_gtests` publicly 
links to `libdatareader.so` and to pytorch libraries 
(`libc10.so`,`libcafee2.so`, `libtorch.so`).
`libdatareader.so` also publicly links to pytorch libraries (I have a 
theoretical question on why `standalone_gtests` had to link to pytorch 
libraries if `libdatareader.so` already did, but that can wait).

Compilation finishes successfully, but when I try to run `standalone_gtests`, 
it aborts because it cant find `libc10.so`.
After executing `ldd standalone_gtests`, the weird result was that there were 
two entries for `libc10.so`.
The first one maps to "not found" while the second had the correct path to the 
library. `libcaffe2.so`, which is also a pytorch library, has a single 
occurrence with full path.
If I add the (...)/pytorch_external/(...) (see ldd output below) path to 
LD_LIBRARY_PATH, then everything works, but I would like to avoid this, if 
possible.

`ldd ./subprojects/Build/datareaders_core_test/standalone_gtests
libdatareader.so => 
/home/dev/miniconda3/datareaders_py37/build/stage/datareader/lib/libdatareader.so
libcaffe2.so => 
/home/dev/miniconda3/datareaders_py37/build/subprojects/Source/pytorch_external/torch/lib/libcaffe2.so
libc10.so => not found
libc10.so => 
/home/dev/miniconda3/datareaders_py37/build/subprojects/Source/pytorch_external/torch/lib/libc10.so
(...)`

Have anyone seen multiple entries for the same library on ldd before? Why is 
that? Is it because `standalone_gtests` links to libc10.so and to 
`libdatareader.so`, which in turn also links to `libc10.so`?
Both CMakeLists.txt (libdatareader and standalone_gtests) succeeds at 
find_package(Torch REQUIRED QUIET) commands (${TORCH_LIBRARY} returns the 
correct path).


I run the same build on my Mac and everything works fine, so that is confined 
to linux environment. I have destroyed my conda environment and performed 
multiple clean builds in the process and no luck :(
Hoping this was some sort of ldconfig issue, I tried `sudo ldconfig` and `sudo 
rm /etc/ld.so.cache`, but that doesn't fix it.

Any ideas?

best regards,
Thiago
-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake