]>
Commit | Line | Data |
---|---|---|
1d09f67e | 1 | # This module builds Boost. It sets the following variables: |
31f18b77 FG |
2 | # |
3 | # Boost_FOUND : boolean - system has Boost | |
1d09f67e | 4 | # BOOST_ROOT : path |
31f18b77 | 5 | # Boost_LIBRARIES : list(filepath) - the libraries needed to use Boost |
1d09f67e | 6 | # Boost_LIBRARY_DIR_RELEASE : path - the library path |
31f18b77 FG |
7 | # Boost_INCLUDE_DIRS : list(path) - the Boost include directories |
8 | # | |
9 | # Following hints are respected | |
10 | # | |
11 | # Boost_USE_STATIC_LIBS : boolean (default: OFF) | |
12 | # Boost_USE_MULTITHREADED : boolean (default: OFF) | |
13 | # BOOST_J: integer (defanult 1) | |
14 | ||
11fdf7f2 TL |
15 | function(check_boost_version source_dir expected_version) |
16 | set(version_hpp "${source_dir}/boost/version.hpp") | |
17 | if(NOT EXISTS ${version_hpp}) | |
18 | message(FATAL_ERROR "${version_hpp} not found. Please either \"rm -rf ${source_dir}\" " | |
19 | "so I can download Boost v${expected_version} for you, or make sure ${source_dir} " | |
20 | "contains a full copy of Boost v${expected_version}.") | |
21 | endif() | |
22 | file(STRINGS "${version_hpp}" BOOST_VERSION_LINE | |
23 | REGEX "^#define[ \t]+BOOST_VERSION[ \t]+[0-9]+$") | |
24 | string(REGEX REPLACE "^#define[ \t]+BOOST_VERSION[ \t]+([0-9]+)$" | |
25 | "\\1" BOOST_VERSION "${BOOST_VERSION_LINE}") | |
26 | math(EXPR BOOST_VERSION_PATCH "${BOOST_VERSION} % 100") | |
27 | math(EXPR BOOST_VERSION_MINOR "${BOOST_VERSION} / 100 % 1000") | |
28 | math(EXPR BOOST_VERSION_MAJOR "${BOOST_VERSION} / 100000") | |
29 | set(version "${BOOST_VERSION_MAJOR}.${BOOST_VERSION_MINOR}.${BOOST_VERSION_PATCH}") | |
30 | if(version VERSION_LESS expected_version) | |
31 | message(FATAL_ERROR "Boost v${version} in ${source_dir} is not new enough. " | |
32 | "Please either \"rm -rf ${source_dir}\" so I can download Boost v${expected_version} " | |
33 | "for you, or make sure ${source_dir} contains a copy of Boost v${expected_version}.") | |
34 | else() | |
35 | message(STATUS "boost (${version} >= ${expected_version}) already in ${source_dir}") | |
36 | endif() | |
37 | endfunction() | |
38 | ||
39 | macro(list_replace list old new) | |
40 | list(FIND ${list} ${old} where) | |
41 | if(where GREATER -1) | |
42 | list(REMOVE_AT ${list} ${where}) | |
43 | list(INSERT ${list} ${where} ${new}) | |
44 | endif() | |
45 | unset(where) | |
46 | endmacro() | |
47 | ||
20effc67 | 48 | function(do_build_boost root_dir version) |
31f18b77 FG |
49 | cmake_parse_arguments(Boost_BUILD "" "" COMPONENTS ${ARGN}) |
50 | set(boost_features "variant=release") | |
51 | if(Boost_USE_MULTITHREADED) | |
52 | list(APPEND boost_features "threading=multi") | |
53 | else() | |
54 | list(APPEND boost_features "threading=single") | |
55 | endif() | |
56 | if(Boost_USE_STATIC_LIBS) | |
57 | list(APPEND boost_features "link=static") | |
58 | else() | |
59 | list(APPEND boost_features "link=shared") | |
60 | endif() | |
61 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) | |
62 | list(APPEND boost_features "address-model=64") | |
63 | else() | |
64 | list(APPEND boost_features "address-model=32") | |
65 | endif() | |
31f18b77 | 66 | |
11fdf7f2 TL |
67 | set(boost_with_libs) |
68 | foreach(c ${Boost_BUILD_COMPONENTS}) | |
69 | if(c MATCHES "^python([0-9])\$") | |
70 | set(with_python_version "${CMAKE_MATCH_1}") | |
71 | list(APPEND boost_with_libs "python") | |
20effc67 | 72 | elseif(c MATCHES "^python([0-9])\\.?([0-9]+)\$") |
11fdf7f2 TL |
73 | set(with_python_version "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}") |
74 | list(APPEND boost_with_libs "python") | |
75 | else() | |
76 | list(APPEND boost_with_libs ${c}) | |
77 | endif() | |
78 | endforeach() | |
79 | list_replace(boost_with_libs "unit_test_framework" "test") | |
80 | string(REPLACE ";" "," boost_with_libs "${boost_with_libs}") | |
2a845540 TL |
81 | |
82 | if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) | |
83 | set(toolset gcc) | |
84 | elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang) | |
85 | set(toolset clang) | |
86 | else() | |
87 | message(SEND_ERROR "unknown compiler: ${CMAKE_CXX_COMPILER_ID}") | |
88 | endif() | |
89 | ||
31f18b77 FG |
90 | # build b2 and prepare the project-config.jam for boost |
91 | set(configure_command | |
92 | ./bootstrap.sh --prefix=<INSTALL_DIR> | |
2a845540 TL |
93 | --with-libraries=${boost_with_libs} |
94 | --with-toolset=${toolset}) | |
31f18b77 FG |
95 | |
96 | set(b2 ./b2) | |
97 | if(BOOST_J) | |
98 | message(STATUS "BUILDING Boost Libraries at j ${BOOST_J}") | |
99 | list(APPEND b2 -j${BOOST_J}) | |
100 | endif() | |
11fdf7f2 TL |
101 | # suppress all debugging levels for b2 |
102 | list(APPEND b2 -d0) | |
103 | ||
11fdf7f2 TL |
104 | set(user_config ${CMAKE_BINARY_DIR}/user-config.jam) |
105 | # edit the user-config.jam so b2 will be able to use the specified | |
106 | # toolset and python | |
107 | file(WRITE ${user_config} | |
108 | "using ${toolset}" | |
109 | " : " | |
110 | " : ${CMAKE_CXX_COMPILER}" | |
1e59de90 | 111 | " : <compileflags>-fPIC <compileflags>-w <compileflags>-Wno-everything" |
11fdf7f2 TL |
112 | " ;\n") |
113 | if(with_python_version) | |
9f95a23c TL |
114 | find_package(Python3 ${with_python_version} QUIET REQUIRED |
115 | COMPONENTS Development) | |
116 | string(REPLACE ";" " " python3_includes "${Python3_INCLUDE_DIRS}") | |
11fdf7f2 TL |
117 | file(APPEND ${user_config} |
118 | "using python" | |
119 | " : ${with_python_version}" | |
9f95a23c TL |
120 | " : ${Python3_EXECUTABLE}" |
121 | " : ${python3_includes}" | |
122 | " : ${Python3_LIBRARIES}" | |
11fdf7f2 TL |
123 | " ;\n") |
124 | endif() | |
125 | list(APPEND b2 --user-config=${user_config}) | |
126 | ||
127 | list(APPEND b2 toolset=${toolset}) | |
128 | if(with_python_version) | |
129 | list(APPEND b2 python=${with_python_version}) | |
31f18b77 | 130 | endif() |
9f95a23c TL |
131 | if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|ARM") |
132 | list(APPEND b2 abi=aapcs) | |
133 | list(APPEND b2 architecture=arm) | |
134 | list(APPEND b2 binary-format=elf) | |
135 | endif() | |
f67539c2 TL |
136 | if(WITH_BOOST_VALGRIND) |
137 | list(APPEND b2 valgrind=on) | |
138 | endif() | |
31f18b77 FG |
139 | set(build_command |
140 | ${b2} headers stage | |
141 | #"--buildid=ceph" # changes lib names--can omit for static | |
142 | ${boost_features}) | |
143 | set(install_command | |
144 | ${b2} install) | |
3a9019d9 | 145 | if(EXISTS "${PROJECT_SOURCE_DIR}/src/boost/bootstrap.sh") |
11fdf7f2 | 146 | check_boost_version("${PROJECT_SOURCE_DIR}/src/boost" ${version}) |
31f18b77 FG |
147 | set(source_dir |
148 | SOURCE_DIR "${PROJECT_SOURCE_DIR}/src/boost") | |
1e59de90 | 149 | elseif(version VERSION_GREATER 1.79) |
31f18b77 FG |
150 | message(FATAL_ERROR "Unknown BOOST_REQUESTED_VERSION: ${version}") |
151 | else() | |
b32b8144 FG |
152 | message(STATUS "boost will be downloaded...") |
153 | # NOTE: If you change this version number make sure the package is available | |
154 | # at the three URLs below (may involve uploading to download.ceph.com) | |
1e59de90 TL |
155 | set(boost_version 1.79.0) |
156 | set(boost_sha256 475d589d51a7f8b3ba2ba4eda022b170e562ca3b760ee922c146b6c65856ef39) | |
31f18b77 | 157 | string(REPLACE "." "_" boost_version_underscore ${boost_version} ) |
1e59de90 TL |
158 | string(JOIN " " boost_url |
159 | https://boostorg.jfrog.io/artifactory/main/release/${boost_version}/source/boost_${boost_version_underscore}.tar.bz2 | |
160 | https://download.ceph.com/qa/boost_${boost_version_underscore}.tar.bz2) | |
31f18b77 FG |
161 | set(source_dir |
162 | URL ${boost_url} | |
11fdf7f2 TL |
163 | URL_HASH SHA256=${boost_sha256} |
164 | DOWNLOAD_NO_PROGRESS 1) | |
31f18b77 FG |
165 | endif() |
166 | # build all components in a single shot | |
167 | include(ExternalProject) | |
168 | ExternalProject_Add(Boost | |
169 | ${source_dir} | |
170 | CONFIGURE_COMMAND CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} ${configure_command} | |
171 | BUILD_COMMAND CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} ${build_command} | |
172 | BUILD_IN_SOURCE 1 | |
20effc67 | 173 | BUILD_BYPRODUCTS ${Boost_LIBRARIES} |
31f18b77 | 174 | INSTALL_COMMAND ${install_command} |
20effc67 | 175 | PREFIX "${root_dir}") |
31f18b77 FG |
176 | endfunction() |
177 | ||
11fdf7f2 TL |
178 | set(Boost_context_DEPENDENCIES thread chrono system date_time) |
179 | set(Boost_coroutine_DEPENDENCIES context system) | |
180 | set(Boost_filesystem_DEPENDENCIES system) | |
181 | set(Boost_iostreams_DEPENDENCIES regex) | |
182 | set(Boost_thread_DEPENDENCIES chrono system date_time atomic) | |
183 | ||
20effc67 | 184 | # define a macro, so the Boost_* variables are visible by its caller |
31f18b77 | 185 | macro(build_boost version) |
20effc67 TL |
186 | # add the Boost::${component} libraries, do this before adding the "Boost" |
187 | # target, so we can collect "Boost_LIBRARIES" which is then used by | |
188 | # ExternalProject_Add(Boost ...) | |
189 | set(install_dir "${CMAKE_BINARY_DIR}/boost") | |
1d09f67e | 190 | set(BOOST_ROOT ${install_dir}) |
31f18b77 FG |
191 | set(Boost_INCLUDE_DIRS ${install_dir}/include) |
192 | set(Boost_INCLUDE_DIR ${install_dir}/include) | |
1d09f67e | 193 | set(Boost_LIBRARY_DIR_RELEASE ${install_dir}/lib) |
11fdf7f2 | 194 | set(Boost_VERSION ${version}) |
31f18b77 FG |
195 | # create the directory so cmake won't complain when looking at the imported |
196 | # target | |
197 | file(MAKE_DIRECTORY ${Boost_INCLUDE_DIRS}) | |
198 | cmake_parse_arguments(Boost_BUILD "" "" COMPONENTS ${ARGN}) | |
11fdf7f2 TL |
199 | foreach(c ${Boost_BUILD_COMPONENTS}) |
200 | list(APPEND components ${c}) | |
201 | if(Boost_${c}_DEPENDENCIES) | |
202 | list(APPEND components ${Boost_${c}_DEPENDENCIES}) | |
203 | list(REMOVE_DUPLICATES components) | |
204 | endif() | |
205 | endforeach() | |
206 | set(Boost_BUILD_COMPONENTS ${components}) | |
207 | unset(components) | |
208 | ||
31f18b77 FG |
209 | foreach(c ${Boost_BUILD_COMPONENTS}) |
210 | string(TOUPPER ${c} upper_c) | |
211 | if(Boost_USE_STATIC_LIBS) | |
212 | add_library(Boost::${c} STATIC IMPORTED) | |
213 | else() | |
214 | add_library(Boost::${c} SHARED IMPORTED) | |
215 | endif() | |
11fdf7f2 | 216 | if(c MATCHES "^python") |
9f95a23c | 217 | set(c "python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR}") |
11fdf7f2 | 218 | endif() |
31f18b77 FG |
219 | if(Boost_USE_STATIC_LIBS) |
220 | set(Boost_${upper_c}_LIBRARY | |
221 | ${install_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}boost_${c}${CMAKE_STATIC_LIBRARY_SUFFIX}) | |
222 | else() | |
223 | set(Boost_${upper_c}_LIBRARY | |
224 | ${install_dir}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}boost_${c}${CMAKE_SHARED_LIBRARY_SUFFIX}) | |
225 | endif() | |
11fdf7f2 | 226 | unset(buildid) |
31f18b77 FG |
227 | set_target_properties(Boost::${c} PROPERTIES |
228 | INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}" | |
229 | IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" | |
230 | IMPORTED_LOCATION "${Boost_${upper_c}_LIBRARY}") | |
f67539c2 TL |
231 | if((c MATCHES "coroutine|context") AND (WITH_BOOST_VALGRIND)) |
232 | set_target_properties(Boost::${c} PROPERTIES | |
20effc67 | 233 | INTERFACE_COMPILE_DEFINITIONS "BOOST_USE_VALGRIND") |
f67539c2 | 234 | endif() |
31f18b77 FG |
235 | list(APPEND Boost_LIBRARIES ${Boost_${upper_c}_LIBRARY}) |
236 | endforeach() | |
11fdf7f2 TL |
237 | foreach(c ${Boost_BUILD_COMPONENTS}) |
238 | if(Boost_${c}_DEPENDENCIES) | |
239 | foreach(dep ${Boost_${c}_DEPENDENCIES}) | |
240 | list(APPEND dependencies Boost::${dep}) | |
241 | endforeach() | |
242 | set_target_properties(Boost::${c} PROPERTIES | |
243 | INTERFACE_LINK_LIBRARIES "${dependencies}") | |
244 | unset(dependencies) | |
245 | endif() | |
9f95a23c | 246 | set(Boost_${c}_FOUND "TRUE") |
11fdf7f2 | 247 | endforeach() |
31f18b77 | 248 | |
20effc67 TL |
249 | # download, bootstrap and build Boost |
250 | do_build_boost(${install_dir} ${version} ${ARGN}) | |
251 | ||
252 | # add dependencies from Boost::${component} to Boost | |
253 | foreach(c ${Boost_BUILD_COMPONENTS}) | |
254 | add_dependencies(Boost::${c} Boost) | |
255 | endforeach() | |
256 | ||
31f18b77 | 257 | # for header-only libraries |
11fdf7f2 TL |
258 | add_library(Boost::boost INTERFACE IMPORTED) |
259 | set_target_properties(Boost::boost PROPERTIES | |
260 | INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") | |
261 | add_dependencies(Boost::boost Boost) | |
31f18b77 FG |
262 | find_package_handle_standard_args(Boost DEFAULT_MSG |
263 | Boost_INCLUDE_DIRS Boost_LIBRARIES) | |
264 | mark_as_advanced(Boost_LIBRARIES BOOST_INCLUDE_DIRS) | |
265 | endmacro() | |
266 | ||
267 | function(maybe_add_boost_dep target) | |
31f18b77 FG |
268 | get_target_property(type ${target} TYPE) |
269 | if(NOT type MATCHES "OBJECT_LIBRARY|STATIC_LIBRARY|SHARED_LIBRARY|EXECUTABLE") | |
270 | return() | |
271 | endif() | |
272 | get_target_property(sources ${target} SOURCES) | |
11fdf7f2 | 273 | string(GENEX_STRIP "${sources}" sources) |
31f18b77 FG |
274 | foreach(src ${sources}) |
275 | get_filename_component(ext ${src} EXT) | |
276 | # assuming all cxx source files include boost header(s) | |
277 | if(ext MATCHES ".cc|.cpp|.cxx") | |
11fdf7f2 | 278 | add_dependencies(${target} Boost::boost) |
31f18b77 FG |
279 | return() |
280 | endif() | |
281 | endforeach() | |
282 | endfunction() | |
283 | ||
284 | # override add_library() to add Boost headers dependency | |
285 | function(add_library target) | |
286 | _add_library(${target} ${ARGN}) | |
11fdf7f2 TL |
287 | # can't add dependencies to aliases or imported libraries |
288 | if (NOT ";${ARGN};" MATCHES ";(ALIAS|IMPORTED);") | |
289 | maybe_add_boost_dep(${target}) | |
290 | endif() | |
31f18b77 FG |
291 | endfunction() |
292 | ||
293 | function(add_executable target) | |
294 | _add_executable(${target} ${ARGN}) | |
295 | maybe_add_boost_dep(${target}) | |
296 | endfunction() |