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

Reply via email to