I'm trying to manage my C++ project dependencies using CMake and gitsubmodules. I'm following the layout described here: http://foonathan.net/blog/2016/07/07/cmake-dependency-handling.html and it's worked really well for me on smaller projects. But I've started to use it on much larger projects and I'm hitting some issue with CMake.
My current setup
All my external build dependencies are in a contrib/ subfolder inside my main project. Each is a submodule and has its own separate directory.
/contrib
- /eigen
- /curl
- /leapserial
- /zlib
- /opencv
etc.
The contrib/CMakeListst.txt simply initializes the submodule and adds the subdirectory for each external dependency
# EIGEN
execute_process(COMMAND git submodule update --recursive --init -- eigen
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# options..
add_subdirectory(eigen EXCLUDE_FROM_ALL)
# CURL
execute_process(COMMAND git submodule update --recursive --init -- curl
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# Initialize cache with CMake build options..
add_subdirectory(curl EXCLUDE_FROM_ALL)
# LEAP SERIAL
execute_process(COMMAND git submodule update --recursive --init -- leapserial
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# Initialize cache with CMake build options..
add_subdirectory(leapserial EXCLUDE_FROM_ALL)
# ZLIB
execute_process(COMMAND git submodule update --recursive --init -- zlib
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# Initialize cache with CMake build options..
add_subdirectory(zlib EXCLUDE_FROM_ALL)
# OPENCV
execute_process(COMMAND git submodule update --recursive --init -- opencv
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# Initialize cache with CMake build options..
add_subdirectory(opencv EXCLUDE_FROM_ALL)
This setup has worked fantastically for me:
It's system/packagemanager independent. You don't need to install any libraries to get started developing
I can maintain the exact versions of my dependencies by setting the submodule to a particular commit. There are no surprises with some external library breaking your build
Adding the libraries to my build in the root CMakeListst.txt is trivial. Since I have the target available I just have something like
add_executable(someProjectImWorkingOn
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp )
target_link_libraries(someProjectImWorkingOn
opencv_world
eigen
zlib
etc.)
when you hook up an existing library target to your own target executable/library CMake will automatically (through the target interface) add include directories to your target and add any other necessary options the library target requires for it to be used
I can pick a toolchain/compiler-option/build-type in the root CMakeLists.txt and it'll propogate to all the subprojects (I need to build for multiple systems. So this is a big big deal)
Since it's all in one "mega-project" it makes it very easy to hook up to rtags/kdevelop/clion to navigate not on your own code, but also the library code
Some issues that I can't resolved:
1
Subdirectories will define targets with the same name. In the example I gave, both Eigen OpenCV as well as another library define an 'uninstall' target
I tried to update the
add_subdirectory(blah)
to
add_subdirectory(blah EXCLUDE_FROM_ALL)
but this doesn't fix the issue for some reason
Enabling the variable ALLOW_DUPLICATE_CUSTOM_TARGETS kinda works.. but this is a hack, only work with Make files, and the libraries are essentially still "mixing" so it's still an issue
2
The second issue came up in LeapSerial but illustrates a bigger issue. The project no longer knows it's own name. LeapSerial tried to determine the version of LeapSerial, but when it asks for the project version it's getting the root project version. Ie. when cmake code in a subproject asks for "what project am I in" it's getting the root project, and not the immediate project it's in.
So again, the parent "namespace"s are leaking everywhere. This is bound to create more and more issues down the line. I need to the submodules to be self-contained
Is there are a cleaner solution?
ExternalProjectAdd might solve some of these problems, but has a lot more issues of its own. It's a real non-starter b/c it doesn't do most of what I've listed. The central issue is that it doesn't expose the sub-project's targets - and just vomits back variables that you then have to juggle
As the asker said in the comments, they resolved their issue by using the Hunter package manager. The rest of this answer is about actually answering the question as posed.
Concerning your first issue with target name clashes when using add_subdirectory-based approaches to using dependencies, a very similar (or essentially the same?) question has also since been asked here: How to avoid namespace collision when using CMake FetchContent?. When the clashes are between targets from different project dependencies, there's nothing you can do right now except politely ask the project maintainers to consider modifying their non-import/export target names to be namespaced like.
For example, for a library target, that might look like:
add_library(projectname_targetnamepart)
add_library("importexportnamespacename::targetnamepart" ALIAS projectname_targetnamepart)
set_target_properties(projectname_targetnamepart PROPERTIES EXPORT_NAME targetnamepart)
set_target_properties(projectname_targetnamepart PROPERTIES OUTPUT_NAME targetnamepart)
install(TARGETS projectname_targetnamepart EXPORT projectname_targets ...)
install(EXPORT projectname_targets NAMESPACE "importexportnamespacename::" ...)
There's a Kitware issue ticket by Craig Scott proposing a CMake feature for Project-level namespaces. Here's an excerpt:
A common problem when pulling in subprojects using add_subdirectory() is that target names must be unique, but different subprojects might try to use the same target name, which results in a name clash. This issue proposes to introduce the concept of a project namespace to address this and related name uniqueness problems (this is the primary goal of this issue).
Sometimes the upstream maintainer will just decline to support the add_subdirectory / FetchContent use-case. That's the case with OpenCV, as shown in this issue ticket (#16896). As for eigen, there's an open ticket that hasn't had any activity in a while (#1892).
Concerning your second issue, there's not enough detail in your question post to confidently troubleshoot. What is LeapSerial? Are you referring to the leapmotion/leapserial GitHub repo? What version and what commit are you referring to? At the latest commit before the time of your question post, 41515db, it's not immediately obvious what's wrong.
Variables in CMake are scoped by directory, so even if a project is added by add_subdirectory and doesn't used the <PROJECT-NAME>_VERSION variable and instead uses the more general PROJECT_VERSION variable, it should be okay. It just shouldn't attempt to use the CMAKE_PROJECT_VERSION variable to get its own version, since that one is fixed to refer to the top-level project's version.
Related
I'm using CMake for a project and googletest for my test cases.
Looking around the internet, it seems to be common practise to just copy the googletest source into a subfolder of your repository and include it with "add_subdirectory(googletest)". I did that.
Now I'm using CPack to generate debian packages for my project. Unfortunately, the packages generated by CPack install googletest alongside with my project. This is of course not what I want.
Looking in the googletest directory, I found some INSTALL cmake commands there, so it is clear, why it happens. The question is now - how can I avoid it? I don't like modifying the CMakeLists.txt files from googletest, because I would have to remember re-applying my modifications on an update. Is there another way to disable these installs in CPack?
So there is the macro option #Tsyvarev mentioned that was originally suggested here:
# overwrite install() command with a dummy macro that is a nop
macro (install)
endmacro ()
# configure build system for external libraries
add_subdirectory(external)
# replace install macro by one which simply invokes the CMake
install() function with the given arguments
macro (install)
_install(${ARGV})
endmacro(install)
Note ${ARGV} and ${ARGN} are the same but the docs currently suggest using ${ARGN}. Also the fact that macro-overwriting prepends _ to the original macro name is not documented, but it is still the behaviour. See the code here.
However, I never got the above code to work properly. It does really weird things and often calls install() twice.
An alternative - also undocumented - is to use EXCLUDE_FROM_ALL:
add_subdirectory(external EXCLUDE_FROM_ALL)
According to some comment I found somewhere this disables install() for that subdirectory. I think what it actually does is set EXCLUDE_FROM_ALL by default for all the install() commands which also probably does what you want. I haven't really tested it, worth a shot though.
Updated: As noted in the other answer,
it seems that EXCLUDE_FROM_ALL option is the most direct and correct way for disable install in the subproject in the subdirectory:
add_subdirectory(googletest EXCLUDE_FROM_ALL)
Previous solutions
If you don't need tests in your project's release (which you want to deliver with CPack), then include googletest subdirectory conditionally, and set conditional to false when packaging:
...
if(NOT DISABLE_TESTS)
add_subdirectory(googletest)
endif()
packaging with
cmake -DDISABLE_TESTS=ON <source-dir>
cpack
Alternatively, if you want tests, but don't want to install testing infrastructure, you may disable install command via defining macro or function with same name:
# Replace install() to do-nothing macro.
macro(install)
endmacro()
# Include subproject (or any other CMake code) with "disabled" install().
add_subdirectory(googletest)
# Restore original install() behavior.
macro(install)
_install(${ARGN})
endmacro()
This approach has also been suggested in CMake mailing.
According to the comments, that way with replacing CMake command is very tricky one and may to not work in some cases: either parameters passed to the modified install are parsed incorrectly or restoring install is not work and even following installs are disabled.
A bit late reply, but I just spent too long a time figuring this out.
In the specific case of googletests, specifying this in your top level CMakeLists.txt does the trick.
option(INSTALL_GMOCK "Install Googletest's GMock?" OFF)
option(INSTALL_GTEST "Install Googletest's GTest?" OFF)
add_subdirectory(googletest)
I read on (I think) the CMake mailing list that making installation conditional on a INSTALL_<package name> inside your package is sort of a defacto standard (and one I'm certainly going to follow from now on!). But I can't find that link now.
I added the xgboost library as a git submodule of my project and I'm trying to add it to cmake as a subdirectory. Unfortunately it's not working. A simple hello world project with the following CMakeLists.txt replicates the error that I'm getting.
cmake_minimum_required(VERSION 3.2)
project(foo)
add_subdirectory(xgboost)
add_executable(${PROJECT_NAME} foo.cpp)
target_link_libraries(${PROJECT_NAME} xgboost)
After building the library there is nothing in the xgboost/lib directory so I get the following error.
clang: error: no such file or directory:
'/Users/.../myproject/xgboost/lib/libxgboost.dylib'
I think that the problem is generated in their CMakeLists file since they have two different targets. Maybe cmake is choosing the wrong target but I'm not familiar enough with cmake to figure it out. The following code is from xgboost's CMakeLists.
# Executable
add_executable(runxgboost $<TARGET_OBJECTS:objxgboost> src/cli_main.cc)
set_target_properties(runxgboost PROPERTIES
OUTPUT_NAME xgboost
)
set_output_directory(runxgboost ${PROJECT_SOURCE_DIR})
target_link_libraries(runxgboost ${LINK_LIBRARIES})
# Shared library
add_library(xgboost SHARED $<TARGET_OBJECTS:objxgboost>)
target_link_libraries(xgboost ${LINK_LIBRARIES})
set_output_directory(xgboost ${PROJECT_SOURCE_DIR}/lib)
#Ensure these two targets do not build simultaneously, as they produce outputs with conflicting names
add_dependencies(xgboost runxgboost)
My questions in order of importance are:
Is there any way to fix it without modifying xgboost's CMakeLists.txt file?
Is it reasonable to try to add xgboost to my project as a git submodule?
Is there any reason cmake is not instructing to build the library?
Note: There were several edits to this question since I tried to narrow down the problem and to provide more information.
(I would love to ask for few things beforehand in the comment section, but I have too low reputation to do so, so I will just give it a shot ;))
I have few suspects, and one of them is ${CMAKE_SOURCE_DIR} of the submodule's root CMakeLists.txt. Although the paths are set properly when you run that CMakeLists.txt alone, cmake gets confused the moment you add it as your subdirectory. Have you looked into another directories for your output binaries?
First I would suggest testing this hypothesis, and then I would suggest writing similar, but separate CMakeLists.txt file for xgboost library, and then substitute it in the project temporarily. Unfortunately the CMakeLists.txt filename is hardcoded and there is no possibility to have two files of that kind in one directory; so it seems that the answer to 1) is, that you rather have to change the file.
For the 2): as long as it does not require huge additional logic in your CMakeLists.txt, it makes sense. Other viable option is to create an install target, which you can use to install your xgboost library locally (using CMAKE_INSTALL_PREFIX(doc) variable), and then add the installation path to your CMAKE_LIBRARY_PATH(doc).
I'm using CMake for a project and googletest for my test cases.
Looking around the internet, it seems to be common practise to just copy the googletest source into a subfolder of your repository and include it with "add_subdirectory(googletest)". I did that.
Now I'm using CPack to generate debian packages for my project. Unfortunately, the packages generated by CPack install googletest alongside with my project. This is of course not what I want.
Looking in the googletest directory, I found some INSTALL cmake commands there, so it is clear, why it happens. The question is now - how can I avoid it? I don't like modifying the CMakeLists.txt files from googletest, because I would have to remember re-applying my modifications on an update. Is there another way to disable these installs in CPack?
So there is the macro option #Tsyvarev mentioned that was originally suggested here:
# overwrite install() command with a dummy macro that is a nop
macro (install)
endmacro ()
# configure build system for external libraries
add_subdirectory(external)
# replace install macro by one which simply invokes the CMake
install() function with the given arguments
macro (install)
_install(${ARGV})
endmacro(install)
Note ${ARGV} and ${ARGN} are the same but the docs currently suggest using ${ARGN}. Also the fact that macro-overwriting prepends _ to the original macro name is not documented, but it is still the behaviour. See the code here.
However, I never got the above code to work properly. It does really weird things and often calls install() twice.
An alternative - also undocumented - is to use EXCLUDE_FROM_ALL:
add_subdirectory(external EXCLUDE_FROM_ALL)
According to some comment I found somewhere this disables install() for that subdirectory. I think what it actually does is set EXCLUDE_FROM_ALL by default for all the install() commands which also probably does what you want. I haven't really tested it, worth a shot though.
Updated: As noted in the other answer,
it seems that EXCLUDE_FROM_ALL option is the most direct and correct way for disable install in the subproject in the subdirectory:
add_subdirectory(googletest EXCLUDE_FROM_ALL)
Previous solutions
If you don't need tests in your project's release (which you want to deliver with CPack), then include googletest subdirectory conditionally, and set conditional to false when packaging:
...
if(NOT DISABLE_TESTS)
add_subdirectory(googletest)
endif()
packaging with
cmake -DDISABLE_TESTS=ON <source-dir>
cpack
Alternatively, if you want tests, but don't want to install testing infrastructure, you may disable install command via defining macro or function with same name:
# Replace install() to do-nothing macro.
macro(install)
endmacro()
# Include subproject (or any other CMake code) with "disabled" install().
add_subdirectory(googletest)
# Restore original install() behavior.
macro(install)
_install(${ARGN})
endmacro()
This approach has also been suggested in CMake mailing.
According to the comments, that way with replacing CMake command is very tricky one and may to not work in some cases: either parameters passed to the modified install are parsed incorrectly or restoring install is not work and even following installs are disabled.
A bit late reply, but I just spent too long a time figuring this out.
In the specific case of googletests, specifying this in your top level CMakeLists.txt does the trick.
option(INSTALL_GMOCK "Install Googletest's GMock?" OFF)
option(INSTALL_GTEST "Install Googletest's GTest?" OFF)
add_subdirectory(googletest)
I read on (I think) the CMake mailing list that making installation conditional on a INSTALL_<package name> inside your package is sort of a defacto standard (and one I'm certainly going to follow from now on!). But I can't find that link now.
I would like to have the following structure A -> B -> C, where:
C is boilerplate code, wrappers for third-party libraries, very
basic code etc.
B is the common classes, functions and data
structures specific to the project's domain.
A is the project itself.
I would like to make it easy to reuse C or B(+C) in future in my other projects. In addition, I have the following requirements:
As all three projects are in-progress, I would like to have an ability to build C, C+B and C+B+A in one shot.
I would prefer the static linkage over dynamic, so that C and C+B would be static libraries, and C+B+A would be the executable
I would like to keep cmake lists and config files simple and clean. Examples which I found in the official wiki and over the internet are pretty big and monstrous.
It would be great if it won't require changing more than a couple of lines if I'd change the locations of A, B or C in the filesystem.
All these three components are using google-test, but I'm not sure if it is important for the project layout.
I am pretty new to cmake and I don't even understand is it better to write XXXConfig.cmake or FindXXX.cmake files. Also, I am not sure, how should I pass relative paths from subcomponent to the parent component using X_INCLUDE_DIRS.
First I have to admit that I agree with #Tsyvarev. Your CMake environment should fit to your processes/workflow and should take project sizes and team structure into account. Or generally speaking the environment CMake will be used in. And this tends to be - in a positive way - very alive.
So this part of your question is difficult to answer and I'll concentrate on the technical part:
CMake has to know the location of the dependencies - relative or absolute - by
having a monolithic source tree (the one you don't want anymore)
CMake share library with multiple executables
CMake: How to setup Source, Library and CMakeLists.txt dependencies?
a common directory location for includes/libraries/binaries
Custom Directory for CMake Library Output
cmake install not installing libraries on windows
getting the paths via config files/variable definitions
How can I get cmake to find my alternative boost installation?
How to add_custom_command() for the CMake build process itself?
using registration in or installation from a database provided on the host
Making cmake library accessible by other cmake packages automatically
cmake wont run build_command in ExternalProject_Add correctly
To keep your CMake files as simple as possible I would recommend to group your CMake code into separate dedicated files:
Prefer toolchain files over if(SomeCompiler) statements
Move common/repeating code parts as function() bodies into a shared CMake include file
Move complex non-target specific code parts into their own (CMake) script files
Example Code
Since you have specifically asked for the find_package() variant, taking Use CMake-enabled libraries in your CMake project and the things listed above:
MyCommonCode.cmake
cmake_policy(SET CMP0022 NEW)
function(my_export_target _target _include_dir)
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Config.cmake"
"
include(\"\$\{CMAKE_CURRENT_LIST_DIR\}/${_target}Targets.cmake\")
set_property(
TARGET ${_target}
APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES \"${_include_dir}\"
)
"
)
export(
TARGETS ${_target}
FILE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Targets.cmake"
EXPORT_LINK_INTERFACE_LIBRARIES
)
export(PACKAGE ${_target})
endfunction(my_export_target)
C/CMakeLists.txt
include(MyCommonCode.cmake)
...
my_export_target(C "${CMAKE_CURRENT_SOURCE_DIR}/include")
B/CMakeLists.txt
include(MyCommonCode.cmake)
find_package(C REQUIRED)
...
target_link_libraries(B C)
my_export_target(B "${CMAKE_CURRENT_SOURCE_DIR}/include")
A/CMakeLists.txt
include(MyCommonCode.cmake)
find_package(B REQUIRED)
...
target_link_libraries(A B)
This keeps all 3 build environments separate, only sharing the relatively static MyCommonCode.cmake file. So in this approach I have so far not covered your first point, but would recommend the use of a external script to chain/trigger your build steps for A/B/C.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Rather than include static libraries in my source tree in a cross-compiled project I'd like to add boost directly into cmake and build it. Is this available?
We've struggled with this a fair bit too at my workplace. While I certainly can't claim to know the "best" way, I can offer the following thoughts on my experiences.
We initially just required devs to install boost separately and had CMake do its normal checks in the form of a find_package(Boost...) call. This was easy, but not automated, and caused problems for devs with older versions of boost already installed.
We then changed tack and added a copy of the boost sources which we cloned from one of the projects you mentioned above. I can't recall the specifics, but I think it was a precursor to the one currently being worked on in the Ryppl project. The main point was that it already had support for CMake; the boost libraries were actual CMake targets added via add_library calls, which made them easier to work with in the CMake code.
While this solved the previous problems by automating the use of boost in our project, it ultimately became a maintenance nightmare. The boost project we had cloned from changed radically and is now very dependent on Ryppl-specific CMake functions. We didn't want to add Ryppl as a dependency, so we changed tack again!
We looked at the projects you mentioned in your question, and likewise found none of them to be usable.
Our current setup makes use of CMake's ExternalProject module. This allows us to download and build boost to our build tree.
Advantages:
Low maintenance
Automated, so all devs use the same version built with the same flags
Keeps our own source tree free from third-party code
Multiple copies of boost can happily co-exist (so no chance of accidentally linking to a copy built with a different compiler/stdlib combination)
Disadvantages
Deleting your build tree means having to download and build boost from scratch. This could be ameliorated by e.g. downloading to a fixed location (say, system temp dir), so the download/unzip step could be skipped if an existing copy of the boost sources is found.
The boost libraries are not proper CMake targets (i.e. they haven't been added via add_library calls)
Here's a link to our CMake code. There are a few ways in which this needs improved, but it currently works reasonably well for us.
I hope that soon this answer becomes out of date and a decent, modularised, CMake-compatible solution becomes available.
I found Fraser's answer above to be a good starting point, but ran into some issues using Boost 1.55.0 on our system.
First we wanted to have a self-contained source code package for our applications, so preferred not to use the CMake ExternalProject. We were only using the thread and date_time libraries from Boost, so we used bcp to create a subset of Boost with the build tools, thread and other dependent libraries:
$ bcp tools/build thread system date_time ../boost_1_55_0_threads_only
and checked this into our svn repository.
Next, I was able to adapt Fraser's CMake file to build on Linux, but ran into problems running the bootstrap.bat file on Windows with CMake's execute_process command. To run bootstrap.bat we first needed to run the relevant Visual Studio vcvarsall.bat script to set environment variables (we could probably figure out which individual variables need to be set, but it was easier to run the whole script). To run two .bat files in the same shell using execult_process, we used cmd /c and listed the files separated by a & as the argument.
Also bootstrap.bat did not set the exit code to non-zero in case of failure, so using the execute_process RESULT_VARIABLE to check for success didn't work. Instead we checked that the b2.exe executable had been created after the command was run.
One last issue: bootstrap.sh supports the --prefix= option, which bootstrap.bat does not. I also found that specifying the --prefix option for b2.exe on windows worked, but
using the --prefix option for b2 on Linux, without specifying it for bootstrap.sh gave errors. (I haven't understood why yet).
So the relevant part of our CMake file looks like:
#
# run bootstrap
#
if(WIN32)
if(MSVC10)
set(VCVARS_CMD "C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 10.0\\VC\\vcvarsall.bat")
elseif(MSVC11)
set(VCVARS_CMD "C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 11.0\\VC\\vcvarsall.bat")
elseif(MSVC12)
set(VCVARS_CMD "C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat")
# elseif(...)
# add more options here
endif(MSVC10)
set(BOOTSTRAP_CMD "${VCVARS_CMD} & bootstrap.bat")
message("Executing command: ${BOOTSTRAP_CMD}")
execute_process(COMMAND cmd /c "${BOOTSTRAP_CMD}" WORKING_DIRECTORY ${APT_BOOST_SRC}
RESULT_VARIABLE BS_RESULT OUTPUT_VARIABLE BS_OUTPUT ERROR_VARIABLE BS_ERROR)
if(NOT EXISTS ${APT_BOOST_SRC}/b2.exe)
message(FATAL_ERROR "Failed running cmd /c ${BOOTSTRAP_CMD} in ${APT_BOOST_SRC}:\n${BS_OUTPUT}\n${BS_ERROR}\n")
else(NOT EXISTS ${APT_BOOST_SRC}/b2.exe)
message("bootstrap output:\n${BS_OUTPUT}")
endif(NOT EXISTS ${APT_BOOST_SRC}/b2.exe)
else(WIN32)
set(BOOTSTRAP_CMD "./bootstrap.sh")
set(BOOTSTRAP_ARGS "--prefix=${APT_BOOST_BIN}")
message("Executing command: ${BOOTSTRAP_CMD} ${BOOTSTRAP_ARGS}")
execute_process(COMMAND "${BOOTSTRAP_CMD}" ${BOOTSTRAP_ARGS} WORKING_DIRECTORY ${APT_BOOST_SRC}
RESULT_VARIABLE BS_RESULT OUTPUT_VARIABLE BS_OUTPUT ERROR_VARIABLE BS_ERROR)
if(NOT BS_RESULT EQUAL 0)
message(FATAL_ERROR "Failed running ${BOOTSTRAP_CMD} ${BOOTSTRAP_ARGS} in ${APT_BOOST_SRC}:\n${BS_OUTPUT}\n${BS_ERROR}\n")
endif()
endif(WIN32)
#
# run b2
#
set(B2_ARGS "link=static" "threading=multi" "runtime-link=static" "variant=release")
foreach(COMP IN LISTS APT_BOOST_COMPONENTS)
set(B2_ARGS "--with-${COMP}" ${B2_ARGS})
endforeach(COMP IN LISTS APT_BOOST_COMPONENTS)
if(WIN32)
if(MSVC11)
set(B2_ARGS "--toolset=msvc-11.0" ${B2_ARGS})
elseif(MSVC12)
set(B2_ARGS "--toolset=msvc-12.0" ${B2_ARGS})
endif(MSVC11)
file(TO_NATIVE_PATH ${APT_BOOST_BIN} APT_BOOST_BIN_WIN)
set(B2_ARGS "--prefix=${APT_BOOST_BIN_WIN}" ${B2_ARGS} "architecture=x86" "address-model=64")
endif(WIN32)
set(B2_ARGS ${B2_ARGS} install)
set(B2_CMD "./b2")
message("Executing command: ${B2_CMD} ${B2_ARGS}")
execute_process(COMMAND ${B2_CMD} ${B2_ARGS} WORKING_DIRECTORY ${APT_BOOST_SRC}
RESULT_VARIABLE B2_RESULT OUTPUT_VARIABLE B2_OUTPUT ERROR_VARIABLE B2_ERROR)
if(NOT B2_RESULT EQUAL 0)
message(FATAL_ERROR "Failed running ${B2_CMD} in ${APT_BOOST_SRC}:\n${B2_OUTPUT}\n${B2_ERROR}\n")
endif()
In the above APT_BOOST_SRC is the location of the Boost subdirectory in our source directory, APT_BOOST_BIN is the location we use to store the libraries in our CMake build directory, and APT_BOOST_COMPONENTS is a list of the Boost libraries we are using.