问题
I am trying to build mongo-cxx-driver
in a CMake based project. This project is supposed to build on Windows, macOS and in an ubuntu container and I want to ensure that my software on all these platforms will use the same driver version so I cannot afford installing the driver and its dependencies via apt-get
, brew
etc. So I am left with one option: ExternalProject_Add
. But I am having difficulty making that work given how libmongoc
is setup.
Below is the CMake module I currently have.
include(ExternalProject)
set(libmongoc_CMAKE_ARGS
"-DCMAKE_BUILD_TYPE:STRIING=${CMAKE_BUILD_TYPE}"
"-DENABLE_TESTS:BOOL=OFF"
"-DENABLE_STATIC:BOOL=OFF"
"-DENABLE_EXAMPLES:BOOL=OFF"
"-DENABLE_EXTRA_ALIGNMENT:BOOL=OFF"
)
set(mongocxx_CMAKE_ARGS
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_BUILD_TYPE:STRIING=${CMAKE_BUILD_TYPE}"
"-DBUILD_SHARED_LIBS:BOOL=ON"
"-DENABLE_TESTS:BOOL=OFF"
"-DENABLE_EXAMPLES:BOOL=OFF"
"-DBSONCXX_POLY_USE_BOOST:BOOL=ON"
"-DBSONCXX_POLY_USE_MNMLSTC:BOOL=OFF"
"-Dlibbson-1.0_DIR:PATH=${OTS_DEPDENDENCIES_DIR}/libmongoc/src/libbson"
)
if (NOT TARGET libmongoc)
ExternalProject_Add(
libmongoc
GIT_REPOSITORY "https://github.com/mongodb/mongo-c-driver.git"
GIT_TAG "1.12.0"
SOURCE_DIR "${OTS_DEPDENDENCIES_DIR}/libmongoc"
BINARY_DIR "${OTS_DEPDENDENCIES_DIR}/libmongoc"
CMAKE_ARGS "${libmongoc_CMAKE_ARGS}"
INSTALL_COMMAND ""
)
endif()
if (NOT TARGET mongocxx)
ExternalProject_Add(
mongocxx
GIT_REPOSITORY "https://github.com/mongodb/mongo-cxx-driver.git"
GIT_TAG "r3.3.1"
SOURCE_DIR "${OTS_DEPDENDENCIES_DIR}/mongocxx"
BINARY_DIR "${OTS_DEPDENDENCIES_DIR}/mongocxx"
CMAKE_ARGS "${mongocxx_CMAKE_ARGS}"
INSTALL_COMMAND ""
DEPENDS libmongoc
)
endif()
Note the CMAKE option libbson-1.0_DIR
given as one of the CMAKE_ARGS
for mongo-cxx-driver
. I am skeptic about it and I believe that may be the culprit. With it I get the following error:
CMake Error at ${OTS_DEPENDENCIES_DIR}/libmongoc/src/libbson/libbson-1.0-config.cmake:30 (message):
File or directory
${OTS_DEPENDENCIES_DIR}/include/libbson-1.0
referenced by variable BSON_INCLUDE_DIRS does not exist !
Call Stack (most recent call first):
${OTS_DEPENDENCIES_DIR}/libmongoc/src/libbson/libbson-1.0-config.cmake:46 (set_and_check)
src/bsoncxx/CMakeLists.txt:81 (find_package)
which kind of makes sense because src/bsoncxx/CMakeLists.txt:81
reads:
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
set_and_check (BSON_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include/libbson-1.0")
which makes CMake end up looking for libbson-1.0 in ${OTS_DEPDENDENCIES_DIR}/include
that does not exist. If only, I could tell cmake, "hey don't run this find_package
" I can give you the path to INCLUDE_DIR
, LIBRARIES
and DEFINITIONS
myself.
If I remove this option, I get the following error:
CMake Error at src/bsoncxx/CMakeLists.txt:81 (find_package):
By not providing "Findlibbson-1.0.cmake" in CMAKE_MODULE_PATH this project
has asked CMake to find a package configuration file provided by
"libbson-1.0", but CMake did not find one.
Could not find a package configuration file provided by "libbson-1.0"
(requested version 1.10.0) with any of the following names:
libbson-1.0Config.cmake
libbson-1.0-config.cmake
Add the installation prefix of "libbson-1.0" to CMAKE_PREFIX_PATH or set
"libbson-1.0_DIR" to a directory containing one of the above files. If
"libbson-1.0" provides a separate development package or SDK, be sure it
has been installed.
which is not very odd either because CMake tries to find_package libbson-1.0 but cannot figure out where it is installed.
回答1:
preliminary remarks
While looking at the details, here are few preliminary comments:
- Use different directory for
SOURCE_DIR
andBINARY_DIR
- Instead of
CMAKE_ARG
, preferCMAKE_CACHE_ARGS
libbson-1.0_DIR
should NOT be set to a source directory, instead if should be set to a build directory containing aconfig-file
package (link below provide more details about this concept)- Make sure to always specify the type of CMake argument (
-DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER}
instead of-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
) - Do not set
CMAKE_BUILD_TYPE
for multi-configuration generator
Regarding this last point, this means that you should do the following:
set(EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS)
if(NOT DEFINED CMAKE_CONFIGURATION_TYPES)
list(APPEND EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
)
endif()
In this post, you can learn how you could structure your project: Correct way to use third-party libraries in cmake project
working project allowing to compile the mongocxx "test.cpp"
Below is the content of CMakeLists.txt
and test.cpp
allowing to build an executable named <build-dir>/Test-build/test_mongocxx
:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.12) set(CMAKE_CXX_STANDARD 11) project(Test) option(${PROJECT_NAME}_SUPERBUILD "Build ${PROJECT_NAME} and the projects it depends on." ON) if(${PROJECT_NAME}_SUPERBUILD) include(ExternalProject) set(common_cmake_cache_args -DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER} ) if(NOT DEFINED CMAKE_CONFIGURATION_TYPES) list(APPEND common_cmake_cache_args -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} ) endif() ExternalProject_Add(libmongoc GIT_REPOSITORY "https://github.com/mongodb/mongo-c-driver.git" GIT_TAG "1.12.0" GIT_PROGRESS 1 GIT_SHALLOW 1 SOURCE_DIR "${CMAKE_BINARY_DIR}/libmongoc" BINARY_DIR "${CMAKE_BINARY_DIR}/libmongoc-build" INSTALL_DIR "${CMAKE_BINARY_DIR}/libmongoc-install" CMAKE_CACHE_ARGS ${common_cmake_cache_args} -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/libmongoc-install -DENABLE_TESTS:BOOL=OFF -DENABLE_STATIC:BOOL=OFF -DENABLE_EXAMPLES:BOOL=OFF -DENABLE_EXTRA_ALIGNMENT:BOOL=OFF #INSTALL_COMMAND "" ) set(libmongoc-1.0_DIR "${CMAKE_BINARY_DIR}/libmongoc-install/lib/cmake/libmongoc-1.0/") set(libbson-1.0_DIR "${CMAKE_BINARY_DIR}/libmongoc-install/lib/cmake/libbson-1.0/") ExternalProject_Add(libmongocxx GIT_REPOSITORY "https://github.com/mongodb/mongo-cxx-driver.git" GIT_TAG "r3.3.1" GIT_PROGRESS 1 GIT_SHALLOW 1 SOURCE_DIR "${CMAKE_BINARY_DIR}/libmongocxx" BINARY_DIR "${CMAKE_BINARY_DIR}/libmongocxx-build" INSTALL_DIR "${CMAKE_BINARY_DIR}/libmongocxx-install" CMAKE_CACHE_ARGS ${common_cmake_cache_args} -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/libmongocxx-install -DBUILD_SHARED_LIBS:BOOL=ON -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 -Dlibmongoc-1.0_DIR:PATH=${libmongoc-1.0_DIR} -Dlibbson-1.0_DIR:PATH=${libbson-1.0_DIR} DEPENDS libmongoc ) set(libmongocxx_DIR "${CMAKE_BINARY_DIR}/libmongocxx-install/lib/cmake/libmongocxx-3.3.1/") set(libbsoncxx_DIR "${CMAKE_BINARY_DIR}/libmongocxx-install//lib/cmake/libbsoncxx-3.3.1/") function(ExternalProject_AlwaysConfigure proj) # This custom external project step forces the configure and later # steps to run. _ep_get_step_stampfile(${proj} "configure" stampfile) ExternalProject_Add_Step(${proj} forceconfigure COMMAND ${CMAKE_COMMAND} -E remove ${stampfile} COMMENT "Forcing configure step for '${proj}'" DEPENDEES build ALWAYS 1 ) endfunction() ExternalProject_Add(${PROJECT_NAME} SOURCE_DIR "${CMAKE_SOURCE_DIR}" BINARY_DIR "${CMAKE_BINARY_DIR}/${PROJECT_NAME}-build" DOWNLOAD_COMMAND "" UPDATE_COMMAND "" CMAKE_CACHE_ARGS ${common_cmake_cache_args} -D${PROJECT_NAME}_SUPERBUILD:BOOL=OFF -Dlibbsoncxx_DIR:PATH=${libbsoncxx_DIR} -Dlibmongocxx_DIR:PATH=${libmongocxx_DIR} INSTALL_COMMAND "" DEPENDS libmongocxx ) ExternalProject_AlwaysConfigure(${PROJECT_NAME}) return() endif() message(STATUS "Configuring inner-build") find_package(libmongocxx REQUIRED) add_executable(test_mongocxx test.cpp) target_link_libraries(test_mongocxx PUBLIC ${LIBMONGOCXX_LIBRARIES}) target_include_directories(test_mongocxx PUBLIC ${LIBMONGOCXX_INCLUDE_DIRS}) target_compile_definitions(test_mongocxx PUBLIC ${LIBMONGOCXX_DEFINITIONS})
test.cpp (copied from https://mongodb.github.io/mongo-cxx-driver/mongocxx-v3/installation/#step-6-test-your-installation):
#include <iostream> #include <bsoncxx/builder/stream/document.hpp> #include <bsoncxx/json.hpp> #include <mongocxx/client.hpp> #include <mongocxx/instance.hpp> int main(int, char**) { mongocxx::instance inst{}; mongocxx::client conn{mongocxx::uri{}}; bsoncxx::builder::stream::document document{}; auto collection = conn["testdb"]["testcollection"]; document << "hello" << "world"; collection.insert_one(document.view()); auto cursor = collection.find({}); for (auto&& doc : cursor) { std::cout << bsoncxx::to_json(doc) << std::endl; } }
来源:https://stackoverflow.com/questions/51717207/building-mongo-cxx-driver-using-cmake-externalproject-add