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<char, std::char_traits<char>, std::allocator<char> > 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 <d...@thiagocrepaldi.com> 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 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 <k...@lanl.gov> 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 <cmake-boun...@cmake.org> 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 > > > > -- > Thiago -- 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