-
Type: Improvement
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: None
-
Component/s: Documentation
-
None
I have been tinkering around with building a "superbuild" CMake project that downloads and builds the mongo-cxx driver for inclusion into a project.
To do this, I used the ExternalProject_Add and then manually linked the libmongocxx.so shared object to the final executable/library.
Here's what the CMakeLists.txt roughly looks like:
# Find mongoc, bson, and mongocxx library for use as MongoDB connector/driver. ExternalProject_Add(libmongoc GIT_REPOSITORY https://github.com/mongodb/mongo-c-driver.git GIT_TAG 1.17.0 GIT_PROGRESS 1 GIT_SHALLOW 1 UPDATE_COMMAND "" # Prevents a rebuild on every make. SOURCE_DIR "${CMAKE_BINARY_DIR}/libmongoc" BINARY_DIR "${CMAKE_BINARY_DIR}/libmongoc-build" INSTALL_DIR "${CMAKE_BINARY_DIR}/libmongoc-install" CMAKE_CACHE_ARGS -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH="${CMAKE_BINARY_DIR}/libmongoc-install;${CMAKE_BINARY_DIR}/libmongocxx-install" -DENABLE_TESTS:BOOL=OFF -DENABLE_STATIC:BOOL=OFF -DENABLE_EXAMPLES:BOOL=OFF -DENABLE_EXTRA_ALIGNMENT:BOOL=OFF)ExternalProject_Add(libmongocxx GIT_REPOSITORY "https://github.com/mongodb/mongo-cxx-driver.git" GIT_TAG r3.6.0 GIT_PROGRESS 1 GIT_SHALLOW 1 UPDATE_COMMAND "" # Prevents a rebuild on every make. SOURCE_DIR "${CMAKE_BINARY_DIR}/libmongocxx" BINARY_DIR "${CMAKE_BINARY_DIR}/libmongocxx-build" INSTALL_DIR "${CMAKE_BINARY_DIR}/libmongocxx-install" CMAKE_CACHE_ARGS -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_PREFIX_PATH:PATH=${CMAKE_BINARY_DIR}/libmongoc-install -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/libmongocxx-install -DENABLE_TESTS:BOOL=OFF -DENABLE_EXAMPLES:BOOL=OFF -DBSONCXX_POLY_USE_BOOST:BOOL=OFF -DBSONCXX_POLY_USE_MNMLSTC:BOOL=ON -DBSONCXX_POLY_USE_STD:BOOL=OFF DEPENDS libmongoc) # START NOTE set(_LIBMONGOCXX_LIBRARIES "${CMAKE_BINARY_DIR}/libmongocxx-install/lib/libmongocxx.so") # END NOTE set(_LIBMONGOCXX_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/libmongocxx-install/include/bsoncxx/v_noabi/" "${CMAKE_BINARY_DIR}/libmongocxx-install/include/mongocxx/v_noabi/") message(STATUS "Using mongocxx r3.6.0") add_executable(hello_world "src/hello_world.cc") target_link_libraries(hello_world ${_LIBMONGOCXX_LIBRARIES}) target_include_directories(hello_world PUBLIC "${_LIBMONGOCXX_INCLUDE_DIRS}")
This configuration builds the hello_world application correctly, but when I go to execute the application, the following error occurs:
error while loading shared libraries: libbsoncxx.so._noabi: cannot open shared object file: No such file or directory
When running ldd on the installed libmongocxx.so, it turns out, libbsoncxx.so._noabi is not found.
linux-vdso.so.1 (0x00007ffdd7524000) libmongoc-1.0.so.0 => /home/jpai/Documents/HelloWorld/cmake/build/libmongoc-install/lib/libmongoc-1.0.so.0 (0x00007fc9e3d39000) libbsoncxx.so._noabi => not found libbson-1.0.so.0 => /home/jpai/Documents/HelloWorld/cmake/build/libmongoc-install/lib/libbson-1.0.so.0 (0x00007fc9e3afb000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc9e3772000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc9e355a000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc9e3169000) libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007fc9e2edc000) libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007fc9e2a11000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fc9e2809000) libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fc9e25ee000) libz.so.1 => /usr/local/lib/libz.so.1 (0x00007fc9e23d1000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc9e21b2000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc9e1e14000) /lib64/ld-linux-x86-64.so.2 (0x00007fc9e428f000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc9e1c10000)
One way to work around it is to set the LD_LIBRARY_PATH to the same directory as libmongocxx.so (and libbsoncxx.so). But this isn't really a good solution since, this would mean the application must have specific environment settings just to get the application to point to the local/non-standard shared object location.
I have instead managed to work around this particular problem by linking the build output directory's version of libmongocxx.so. This version of libmongocxx.so links to the build directory's version of libbsoncxx.so.
So instead of using the NOTE section from above, I use the following variable setting:
set(_LIBMONGOCXX_LIBRARIES
"${CMAKE_BINARY_DIR}/libmongocxx-build/src/mongocxx/libmongocxx.so")
With this, the application works without the missing shared object error.
I wanted to ask why there was such a difference between the linking of the installed directory version of libmongocxx.so and the build directory version of libmongocxx.so.
Considering the install operation of the project seems to drop all the necessary shared objects into the same directory, I am not sure why the installed version of libmongocxx.so was not able to pick up libbsoncxx.so object next to it.
I wanted to see if there is a way to fix this so that the mongo-cxx-driver can be a bit more portable and not need to be directly installed into the system libraries. I don't think it is good practice to directly reference the build object when the project has an install target available for it.
Thanks!