How to download boost using their SHA256 Hash through CMake? - c++

I am trying to add boost as an external project to my project. However when I add the URL to boosts releases and use their hash, I get a hash mismatch even if I have copied it straight from their website. Link here for latest release. Here is my boostExternal.cmake file:
#---------------------------------------------------------------------------
# Get and build boost
SET_PROPERTY(DIRECTORY PROPERTY "EP_BASE" ${ep_base})
SET(boost_GIT_TAG "origin/master")
set( Boost_Bootstrap_Command )
if( UNIX )
set( Boost_url "https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz")
set( Boost_Hash "SHA256=882b48708d211a5f48e60b0124cf5863c1534cd544ecd0664bb534a4b5d506e9")
set( Boost_Bootstrap_Command ./bootstrap.sh )
set( Boost_b2_Command ./b2 )
elseif( WIN32 )
set( Boost_url "https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.zip")
set( Boost_Hash "SHA256=48f379b2e90dd1084429aae87d6bdbde9670139fa7569ee856c8c86dd366039d")
set( Boost_Bootstrap_Command bootstrap.bat )
set( Boost_b2_Command b2.exe )
endif()
ExternalProject_Add(Boost_external_Download
URL ${Boost_url}
URL_HASH ${Boost_Hash}
BUILD_IN_SOURCE 1
UPDATE_COMMAND ""
PATCH_COMMAND ""
CONFIGURE_COMMAND ${Boost_Bootstrap_Command}
BUILD_COMMAND ${Boost_b2_Command} install
--with-system
--with-chrono
--with-filesystem
--disable-icu
--prefix=${CMAKE_BINARY_DIR}/Boost
--threading=single,multi
--link=shared
--variant=release
-j8
INSTALL_COMMAND ""
INSTALL_DIR ""
)
#CACHE PATH "" seems to write the path to a file that I can set
#library paths to.
set(Boost_LIBRARY_DIR ${CMAKE_BINARY_DIR}/Boost/lib CACHE PATH "")
if(WIN32)
set(Boost_INCLUDE_DIR ${CMAKE_BINARY_DIR}/Boost/include/boost-1_70 CACHE PATH "")
set(BOOST_ROOT ${CMAKE_BINARY_DIR}/Boost)
else()
set(Boost_INCLUDE_DIR ${CMAKE_BINARY_DIR}/Boost/include CACHE PATH "")
endif()
ExternalProject_Get_Property(Boost_external_Download BINARY_DIR)
SET(Boost_DIR ${BINARY_DIR} CACHE PATH "")
add_library(Boost_external SHARED IMPORTED)
message(STATUS "Boost_DIR: ${Boost_DIR}")
But when I call this cmake file, I get the error:
-- verifying file...
file='/home/sailanarmo/Documents/build/Superbuild/Download/Boost_external_Download/boost_1_70_0.tar.gz'
-- SHA256 hash of
/home/sailanarmo/Documents/build/Superbuild/Download/Boost_external_Download/boost_1_70_0.tar.gz
does not match expected value
expected: '882b48708d211a5f48e60b0124cf5863c1534cd544ecd0664bb534a4b5d506e9'
actual: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
-- File already exists but hash mismatch. Removing...
Which doesn't make sense because I have put in the correct hash and the correct protocol within the .cmake file. However the actual doesn't seem to match what I have pasted in. Am I doing something wrong?

I found the reason.
When building CMake, you have to configure SSL support otherwise CMake will not allow the https protocol to be used. To do that you will need to configure CMake as the following:
./bootstrap --system-curl
make
sudo make install
This will use Linux's system curl which should be configured with SSL Support. However, instead of re-installing CMake manually. I decided to drop the s in the https. Which means I changed https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz to http://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz and it downloaded and compiled just fine.

Related

How can I properly download Boost using (CMake SuperBuild Boost Windows)?

I am trying to install boost by ExternalProject_Add but I get error.
Question What does the error mean and how can I resolve it?
This is the error message I have:
Performing update step for 'boost-external'
No patch step for 'boost-external'
Performing configure step for 'boost-external'
'cp' is not recognized as an internal or external command,
operable program or batch file.
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Msbuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(241,5): e
rror MSB8066: Custom build for 'C:\IBOIS57\_Code\Software\CPP\CMAKE\super_build\Example_02_Boost\build\CMakeFiles\7a303cde471
9f69085ebded4413f3304\boost-external-mkdir.rule;C:\IBOIS57\_Code\Software\CPP\CMAKE\super_build\Example_02_Boost\build\CMakeF
iles\7a303cde4719f69085ebded4413f3304\boost-external-download.rule;C:\IBOIS57\_Code\Software\CPP\CMAKE\super_build\Example_02
_Boost\build\CMakeFiles\7a303cde4719f69085ebded4413f3304\boost-external-update.rule;C:\IBOIS57\_Code\Software\CPP\CMAKE\super
_build\Example_02_Boost\build\CMakeFiles\7a303cde4719f69085ebded4413f3304\boost-external-patch.rule;C:\IBOIS57\_Code\Software
\CPP\CMAKE\super_build\Example_02_Boost\build\CMakeFiles\7a303cde4719f69085ebded4413f3304\boost-external-configure.rule;C:\IB
OIS57\_Code\Software\CPP\CMAKE\super_build\Example_02_Boost\build\CMakeFiles\7a303cde4719f69085ebded4413f3304\boost-external-
build.rule;C:\IBOIS57\_Code\Software\CPP\CMAKE\super_build\Example_02_Boost\build\CMakeFiles\7a303cde4719f69085ebded4413f3304
\boost-external-install.rule;C:\IBOIS57\_Code\Software\CPP\CMAKE\super_build\Example_02_Boost\build\CMakeFiles\1a2a6d9ea64ba5
92f97cd191c1d5acb1\boost-external-complete.rule;C:\IBOIS57\_Code\Software\CPP\CMAKE\super_build\Example_02_Boost\build\CMakeF
iles\a70b522e33d20f4a0fb02fd1b3fdb173\boost-external.rule;C:\IBOIS57\_Code\Software\CPP\CMAKE\super_build\Example_02_Boost\CM
akeLists.txt' exited with code 9009. [C:\IBOIS57\_Code\Software\CPP\CMAKE\super_build\Example_02_Boost\build\boost-external.v
cxproj]
This is the screenshot:
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/HyrKM.jpg
This is my full CMakeLists.txt
###############################################################################
#cmake + project name
###############################################################################
cmake_minimum_required(VERSION 3.10)
project(boostdemo)
###############################################################################
#create executable
###############################################################################
add_executable(boostdemo ${PROJECT_SOURCE_DIR}/main.cpp)
###############################################################################
#boost
###############################################################################
#https://github.com/BBO-repo/cpp-boost-cmake-superbuild
set( Boost_Bootstrap_Command ${CMAKE_BINARY_DIR}/boost-download/src/boost-external/bootstrap.sh && cp ${CMAKE_BINARY_DIR}/boost-download/src/boost-external-build/b2 ${CMAKE_BINARY_DIR}/boost-download/src/boost-external/)
set( Boost_b2_Command cd ${CMAKE_BINARY_DIR}/boost-download/src/boost-external && ./b2 )
include(ExternalProject)
ExternalProject_Add(
boost-external #library name that will be used for linking in the executable
GIT_REPOSITORY https://github.com/boostorg/boost.git
GIT_TAG boost-1.79.0
PREFIX boost-download
CONFIGURE_COMMAND ${Boost_Bootstrap_Command}
BUILD_COMMAND ${Boost_b2_Command} install
--without-python
--without-mpi
--disable-icu
--prefix=${CMAKE_SOURCE_DIR}/thirdparty/boost/
--threading=single,multi
--link=shared
--variant=release
-j12
INSTALL_COMMAND ""
)
set(Boost_LIBS ${CMAKE_SOURCE_DIR}/thirdparty/boost/lib/${CMAKE_STATIC_LIBRARY_PREFIX}boost_chrono${CMAKE_SHARED_LIBRARY_SUFFIX})
set(Boost_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/boost/include/)
###############################################################################
#link boost
###############################################################################
add_dependencies(boostdemo boost-external)
include_directories(boostdemo ${Boost_INCLUDE_DIR})
target_link_libraries(boostdemo ${Boost_LIBS})
In case it helps someone, below is the cmake fragment I used to have for obtaining boost with ExternalProject_Add. I was focussed at the time on the header only parts so it may not be complete.
I was never entirely happy with this and in the end switched to obtaining all of our third party dependencies with vcpkg. I have been much happier ever since, especially with regard to boost. In fact I just deleted this file from our repo. So I strongly recommend looking at vcpkg (or conan or ...) instead of ExternalProject_Add.
if(WIN32)
set( Boost_Bootstrap_Command bootstrap.bat )
set( Boost_b2_Command b2.exe )
set( Boost_version_dir /boost-1_77 )
else()
set( Boost_Bootstrap_Command ./bootstrap.sh )
set( Boost_b2_Command ./b2 )
set( Boost_version_dir "")
endif()
ExternalProject_Add(git_boost
URL https://boostorg.jfrog.io/artifactory/main/release/1.77.0/source/boost_1_77_0.tar.gz
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ${Boost_Bootstrap_Command}
BUILD_COMMAND ""
INSTALL_COMMAND ${Boost_b2_Command} --with-headers --with-math install --prefix=${CMAKE_CURRENT_BINARY_DIR}/boost
TEST_COMMAND ""
)
add_library(ours_boost INTERFACE)
add_library(ours::boost ALIAS ours_boost)
target_include_directories(ours_boost INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/boost/include${Boost_version_dir})
message(${CMAKE_CURRENT_BINARY_DIR}/boost/include${Boost_version_dir})
add_dependencies(ours_boost git_boost)

Building mongo-cxx-driver using CMake ExternalProject_Add

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.
preliminary remarks
While looking at the details, here are few preliminary comments:
Use different directory for SOURCE_DIR and BINARY_DIR
Instead of CMAKE_ARG, prefer CMAKE_CACHE_ARGS
libbson-1.0_DIR should NOT be set to a source directory, instead if should be set to a build directory containing a config-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;
}
}

HelloWorld: downloading, building and linking Boost using CMake

I have a little Hello, World style program which I'd like to work on more in end-to-end fashion using CMake. In this case it means I could download Boost libraries, compile them and finally compile my little Hello, World and link the Boost libraries to it.
The Directory layout looks like this currently
cmaketest
|- build //I would like to have here the CMake generated IDE files.
|- src
|- main.cpp
|- hello.cpp
|- hello.hpp
|- depends //I would like to have here the built Boost libraries and headers.
|- downloads //This contains the downloaded zip file.
|- temp //Temporary files.
I have the following CMakeLists.txt, and currently I generate the Visual Studio 2015 project files like so: cmake build -G "Visual Studio 14 2015 Win64". All good and well, I'll start the solution, CMake complains it can't find Boost, goes to download it starts to build (in the following code I've set to fetch a file previously acquired). But then after building for a while, the problems emerge...
The Boost files seem to appear in \cmaketest\CMakeFiles\build\Boost-prefix\src\Boost as the root. How could I these so they'd be built to \depends\boost (or to that effect) and how to include the libraries to be linked to the solution? This linking is a separate problem I have, I know how to include the headers from this strange directory, but it's not really what I want.
It looks like the VS IDE gives first warning the Boost headers aren't to be found (see the main program shortly) first and then starts the Boost build. Can this be avoided?
How to make the Boost library disappear from the VS solution? I.e. not to make a project of it, but just a dependency on headers and libraries?
Is there a built-in way to avoid downloading the Boost package if it is already on the disk? It looks like it will be retrieved in any event, and I've thought about checking the existence of the file.
The main.cpp (I suppose this is the relevant file in this case)
//The Boost headers are included just to check the linker.
#include "hello.hpp"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <iostream>
using std::cout;
using std::endl;
int main()
{
hello helloer;
cout << helloer.greet("World here") << endl;
return EXIT_SUCCESS;
}
And then the CMakeLists.txt file.
cmake_minimum_required(VERSION 3.6 FATAL_ERROR)
set(CMAKE_VERBOSE_MAKEFILE ON)
project(Cmaketest)
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif()
if(POLICY CMP0066)
cmake_policy(SET CMP0066 NEW)
endif()
# Default build type if none was specified.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
message(STATUS "Setting build type to '${CMAKE_BUILD_TYPE} as none was specified.")
# Possible values of build type for CMake GUI.
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# The path to extra modules.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# Setup build locations.
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
set(CMAKE_CURRENT_BINARY_DIR
${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/build)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
include(ExternalProject)
include(ProcessorCount)
ProcessorCount(N)
if(NOT N EQUAL 0)
set(CMAKE_BUILD_FLAGS -j${N})
endif()
# set(BOOST_VERSION 1.63.0)
# Boost related settings:
# https://cmake.org/cmake/help/v3.6/module/FindBoost.html.
# Should one check the environment variables and flags here explicitly
# to remove the complaint about missing Boost library? Or should perhaps
# BOOST_ROOT be set? Point to what?
find_package(Boost)
if(NOT Boost_FOUND)
# It shouldn't hurt to enable extensive diagnostics, just in case.
# Also, a different set of files is downloaded for UNIX and WIN32
# due to file permissions and line-feeds (Windows should handle
# also Unix style line-feeds).
set(Boost_DETAILED_FAILURE_MSG on)
add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
set(Boost_Bootstrap_Command)
if(UNIX)
set(Boost_Url "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.gz")
set(Boost_Sha1 "2cecf1848a813de55e5770f324f084c568abca0a")
set(Boost_Bootstrap_Command ./bootstrap.sh)
set(Boost_b2_Command ./b2)
elseif(WIN32)
set(Boost_Url "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.zip")
set(Boost_Sha1 "4364989afbe6b11f2d5e59df902c3ca4d7851824")
set(Boost_Bootstrap_Command bootstrap.bat)
set(Boost_b2_Command b2.exe)
endif()
set(Config_Libraries "chrono,filesystem,program_options,system,thread,test")
ExternalProject_Add(Boost
TMP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/temp"
DOWNLOAD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/downloads"
URL "${CMAKE_CURRENT_SOURCE_DIR}/downloads/boost_1_63_0.zip"
URL_HASH "SHA1=${Boost_Sha1}"
BUILD_IN_SOURCE 1
UPDATE_COMMAND ""
PATCH_COMMAND ""
CONFIGURE_COMMAND ${Boost_Bootstrap_Command} --without-icu --with_libraries=${Config_Libraries}
BUILD_COMMAND ${Boost_b2_Command}
# --prefix="${CMAKE_CURRENT_SOURCE_DIR}/depends"
--without-python
--address-model=64
--architecture=x64
--threading=multi
--link=static
--variant=release
--layout=tagged
--build-type=complete
-j${N}
INSTALL_COMMAND ""
# INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/depends"
#As it happens, these directories are currently empty...
# set(BOOST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/depends/include/boost-1_63)
# set(Boost_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/depends/boost_1_63/include)
# set(Boost_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/depends/boost_1_63/lib)
)
endif()
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
include_directories(${CMAKE_SOURCE_DIR}/src)
# Grabbing just all the test project files.
file(GLOB SOURCES "src/*.*")
add_executable(cmaketest ${SOURCES})
# TARGET_LINK_LIBRARIES(cmaketest ${Boost_LIBRARY})
I will attempt to give you some hints, to try to answer your questions.
1) With this snippet you should be able to have sources and built files in the right directories. I kept TMP_DIR "${Cmaketest_SOURCE_DIR}/temp" but in my project I don't use that line.
ExternalProject_Add(Boost
TMP_DIR "${Cmaketest_SOURCE_DIR}/temp"
DOWNLOAD_DIR "${Cmaketest_SOURCE_DIR}/downloads"
URL "${Cmaketest_SOURCE_DIR}/downloads/boost_1_63_0.zip"
URL_HASH "SHA1=${Boost_Sha1}"
SOURCE_DIR ${Cmaketest_SOURCE_DIR}/downloads/boost_1_63_0
BUILD_IN_SOURCE 1
UPDATE_COMMAND ""
PATCH_COMMAND ""
CONFIGURE_COMMAND ${Boost_Bootstrap_Command} --without-icu --with_libraries=${Config_Libraries}
BUILD_COMMAND ${Boost_b2_Command}
--prefix="${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0"
--without-python
--address-model=64
--architecture=x64
--threading=multi
--link=static
--variant=release
--layout=tagged
--build-type=complete
-j${N}
INSTALL_COMMAND ${Boost_b2_Command} --prefix="${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0" --without-python
--address-model=64
--architecture=x64
--threading=multi
--link=static
--variant=release
--layout=tagged
--build-type=complete
-j${N} install
INSTALL_DIR "${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0"
)
set(BOOST_ROOT ${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0)
set(Boost_LIBRARY ${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0/lib)
set(Boost_INCLUDE_DIR ${Cmaketest_SOURCE_DIR}/depends/boost_1_63_0/include)
include_directories(${Boost_INCLUDE_DIR})
To notice that you were not calling "install" so once built in that "strange" directory, the files were not moved to the specified prefix. Notice also the use of ${Cmaketest_SOURCE_DIR} instead of the previous.
Try to print both and see if there's a difference.
2) To address the warning you get in case Boost is not found, you should write:
find_package(Boost QUIET)
3) To address this I guess you could not generate project files, i.e. instead of having
cmake build -G "Visual Studio 14 2015 Win64"
just have cmake . or cmake .. depending whether you will do an in-source or an out-of-source build. I suggest doing out-of-source builds, but that's your choice.
4) FindBoost.cmake (FindBoost.cmake) gives you the possibility to pass an arbitrary path to a Boost directory. You could use that at configuration to hint CMake to look for Boost in the location you give, e.g. you would call cmake in the following way:
cmake -DBOOST_ROOT=/path_to_cmaketest_dir/depends/boost_1_63_0 ..
and if your system might be picky you could specify all things:
cmake -DBOOST_ROOT=/path_to_cmaketest_dir/depends/boost_1_63_0 -DBOOST_LIBRARYDIR=/path_to_cmaketest_dir/depends/boost_1_63_0/lib DBOOST_INCLUDEDIR=/path_to_cmaketest_dir/depends/boost_1_63_0/include ..
Notice that in the last two snippets I assumed configuration of an out-of-source build.
Also notice that if you already installed or have the Boost package downloaded, using ${Cmaketest_SOURCE_DIR} in the snipped of code in 1) should solve also 4) so when it will not find Boost it will try to download but it will not, since now cmake should be able to see the file (.zip).
Please see CMaker_Boost, build the Boost with the CMake at a configure time. Now it is tested on the Linux and Android, gcc and clang. Other systems are not tested. I hope this helps.

Installing an ExternalProject with CMake

I have the following code in one of my CMakeLists.txt:
FIND_PACKAGE(sphinxbase)
if (${SPHINXBASE_FOUND})
INCLUDE_DIRECTORIES(${SPHINXBASE_INCLUDE_DIR}/sphinxbase/)
else ()
ExternalProject_Add(
sphinxbase
GIT_REPOSITORY "https://github.com/cmusphinx/sphinxbase.git"
GIT_TAG "e34b1c632392276101ed16e8a05862e43f038a7c"
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/sphinxbase
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lib/sphinxbase/autogen.sh
BUILD_COMMAND ${MAKE}
UPDATE_COMMAND ""
INSTALL_COMMAND ""
BUILD_IN_SOURCE ON
LOG_DOWNLOAD ON
LOG_UPDATE ON
LOG_CONFIGURE ON
LOG_BUILD ON
LOG_TEST ON
LOG_INSTALL ON
)
ExternalProject_Get_Property(sphinxbase SOURCE_DIR)
ExternalProject_Get_Property(sphinxbase BINARY_DIR)
SET(SPHINXBASE_SOURCE_DIR ${SOURCE_DIR})
SET(SPHINXBASE_BINARY_DIR ${BINARY_DIR})
SET(SPHINXBASE_LIBRARIES ${SPHINXBASE_BINARY_DIR}/src/libsphinxbase/.libs/libsphinxbase.a)
INCLUDE_DIRECTORIES(${SPHINXBASE_SOURCE_DIR}/include)
endif ()
SET(DEPENDENCIES ${DEPENDENCIES} sphinxbase)
SET(LIBS ${LIBS} ${SPHINXBASE_LIBRARIES})
In addition to the TARGET that I'm trying to install, how would I go about installing this ExternalProject? Right now I'm trying to do it like this:
install(TARGETS ${LIBS}
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
OPTIONAL
)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)
But I'm getting the following error thrown at me:
CMake Error at CMakeLists.txt:197 (install):
install TARGETS given target
"/Users/syb0rg/Dropbox/Development/Khronos/Khronos/lib/sphinxbase/src/libsphinxbase/.libs/libsphinxbase.a"
which does not exist in this directory.
Any suggestions?
Command flow install(TARGETS) installs targets, which are created with add_executable or add_library commands. For install concrete files, you need to use command flow install(FILES).
Instead of installing selected files from subproject's build directory, you may install subproject as is. For that you can use
make DESTDIR=<...> install
command as INSTALL option of ExeternalProject_Add. This command will install whole subproject into directory given as DESTDIR parameter for make (more information about this parameter can be found here).
Then you may use install(DIRECTORY) command for install all subproject's files at once:
# It is better to use binary directory for download or build 3d-party project
set(sphinxbase_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/lib/sphinxbase)
# This will be used as DESTDIR on subproject's `make install`.
set(sphinxbase_DESTDIR ${CMAKE_CURRENT_BINARY_DIR}/lib/sphinxbase_install)
ExternalProject_Add(
sphinxbase
GIT_REPOSITORY "https://github.com/cmusphinx/sphinxbase.git"
GIT_TAG "e34b1c632392276101ed16e8a05862e43f038a7c"
SOURCE_DIR ${sphinxbase_SOURCE_DIR}
# Specify installation prefix for configure.sh (autogen.sh).
CONFIGURE_COMMAND ./autogen.sh --prefix=${CMAKE_INSTALL_PREFIX}
BUILD_COMMAND ${MAKE}
UPDATE_COMMAND ""
# Fake installation: copy installed files into DESTDIR.
INSTALL_COMMAND make DESTDIR=${sphinxbase_DESTDIR} install
...
)
# Actually install subproject.
install(
DIRECTORY ${sphinxbase_DESTDIR}/
DESTINATION "/"
USE_SOURCE_PERMISSIONS # Remain permissions (rwx) for installed files
)
Note, that root directory is used as DESTINATION. This is because files under sphinxbase_DESTDIR directory already located in accordance to CMAKE_INSTALL_PREFIX, which is passed as --prefix option to configure.sh (autogen.sh in the given case).
If you know, that subprojects installs its files only under installation prefix (given by --prefix), you can make main project installation more packaging-friendly:
install(
DIRECTORY ${sphinxbase_DESTDIR}/${CMAKE_INSTALL_PREFIX}/
DESTINATION "."
USE_SOURCE_PERMISSIONS
)
Because now relative path is used for DESTINATION option, the project will correctly support packaging. For example, make DESTDIR=<...> install will work for main project too.
Note, that even if ExternalProject_Add is used for build CMake subproject, targets created in this subroject are not seen by the main project.

CMakeLists configuration to link two C++ projects

I have the following situation: a Project A depends on a Project B, but both are built at the same time. Project A has to include the includes of project B and it needs also to link its libraries. Up to now I've tried this way:
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/other_project other_project)
and then:
INCLUDE_DIRECTORIES(includ ${CMAKE_SOURCE_DIR}/other_project/include})
LIST(APPEND LINK_LIBS other_project)
in the CMakeLists.txt of Project A
but it doesn't seem to work, the compiler also gives me error when including the headers of Project B saying that they do not exist.
What is the right way to add dependencies in A? How should the CMakeLists.txt look like?
EDIT:
as suggested in the comments, this question was addressed in this, however I'd like to see an example of how to use it in a CMakeList.txt file.
The following is a simple example which builds zlib and then builds libxml2 which depends on the zlib we build. One thing to note, I quickly pulled this example from stuff I've done before. The libxml2 example uses make, thus will only actually build on a system which has it, e.g. Linux, Mac ...
Here is the proposed directory structure for this example ...
src/
-- CMakeLists.txt
CMake/
---- External_ZLib.cmake
---- External_libxml2.cmake
Dowloads/ ( no need to create this directory, CMake will do it for you )
build/ ( Out of source build to prevent littering source tree )
Files:
CMakeLists.txt
# Any version that supports ExternalProject should do
cmake_minimum_required( VERSION 3.1)
project(test_ext_proj)
set(test_ext_proj_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
set(CMAKE_MODULE_PATH ${test_ext_proj_CMAKE_DIR} ${CMAKE_MODULE_PATH})
set(test_ext_proj_BUILD_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install)
set(test_ext_proj_DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Downloads CACHE PATH "Directory to store downloaded tarballs.")
include(ExternalProject)
include(External_ZLib)
include(External_libxml2)
External_ZLib.cmake:
set(ZLib_version 1.2.8)
set(ZLib_url "http://zlib.net/zlib-${ZLib_version}.tar.gz")
set(ZLib_md5 "44d667c142d7cda120332623eab69f40")
ExternalProject_Add(ZLib
URL ${ZLib_url}
URL_MD5 ${ZLib_md5}
PREFIX ${vision-tpl_BUILD_PREFIX}
DOWNLOAD_DIR ${test_ext_proj_DOWNLOAD_DIR}
INSTALL_DIR ${test_ext_proj_BUILD_INSTALL_PREFIX}
CMAKE_GENERATOR ${gen}
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=${test_ext_proj_BUILD_INSTALL_PREFIX}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
)
#This variable is required so other packages can find it.
set(ZLIB_ROOT ${test_ext_proj_BUILD_INSTALL_PREFIX} CACHE PATH "" FORCE)
External_libxml2.cmake:
set(libxml2_release "2.9")
set(libxml2_patch_version 0)
set(libxml2_url "ftp://xmlsoft.org/libxml2/libxml2-sources-${libxml2_release}.${libxml2_patch_version}.tar.gz")
set(libxml2_md5 "7da7af8f62e111497d5a2b61d01bd811")
#We need to state that we're dependent on ZLib so build order is correct
set(_XML2_DEPENDS ZLib)
#This build requires make, ensure we have it, or error out.
if(CMAKE_GENERATOR MATCHES ".*Makefiles")
set(MAKE_EXECUTABLE "$(MAKE)")
else()
find_program(MAKE_EXECUTABLE make)
if(NOT MAKE_EXECUTABLE)
message(FATAL_ERROR "Could not find 'make', required to build libxml2.")
endif()
endif()
ExternalProject_Add(libxml2
DEPENDS ${_XML2_DEPENDS}
URL ${libxml2_url}
URL_MD5 ${libxml2_md5}
PREFIX ${test_ext_proj_BUILD_PREFIX}
DOWNLOAD_DIR ${test_ext_proj_DOWNLOAD_DIR}
INSTALL_DIR ${test_ext_proj_BUILD_INSTALL_PREFIX}
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./configure
--prefix=${test_ext_proj_BUILD_INSTALL_PREFIX}
--with-zlib=${ZLIB_ROOT}
BUILD_COMMAND ${MAKE_EXECUTABLE}
INSTALL_COMMAND ${MAKE_EXECUTABLE} install
)