forked from adobe/lagrange
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
334 lines (288 loc) · 14.8 KB
/
CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#
# Copyright 2016 Adobe. All rights reserved.
# This file is licensed to you under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
# OF ANY KIND, either express or implied. See the License for the specific language
# governing permissions and limitations under the License.
#
# Detects whether this is a top-level project
get_directory_property(HAS_PARENT PARENT_DIRECTORY)
if(HAS_PARENT)
set(LAGRANGE_TOPLEVEL_PROJECT OFF)
else()
set(LAGRANGE_TOPLEVEL_PROJECT ON)
endif()
# Check required CMake version
set(REQUIRED_CMAKE_VERSION "3.25.0")
if(LAGRANGE_TOPLEVEL_PROJECT)
cmake_minimum_required(VERSION ${REQUIRED_CMAKE_VERSION})
else()
# Don't use cmake_minimum_required here to avoid implicitly overriding parent policies
if(${CMAKE_VERSION} VERSION_LESS ${REQUIRED_CMAKE_VERSION})
message(FATAL_ERROR "CMake required version to build Lagrange is ${REQUIRED_CMAKE_VERSION}")
endif()
endif()
cmake_policy(SET CMP0054 NEW) # Only interpret if() arguments as variables or keywords when unquoted.
cmake_policy(SET CMP0076 NEW) # target_sources() command converts relative paths to absolute.
set(CMAKE_POLICY_DEFAULT_CMP0091 NEW) # MSVC runtime library flags are selected by an abstraction.
set(CMAKE_POLICY_DEFAULT_CMP0135 NEW) # Set the timestamps of all extracted contents to the time of the extraction.
# Include user-provided default options if available. We do that before the main
# `project()` so that we can define the C/C++ compilers from the option file.
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/LagrangeOptions.cmake)
if(LAGRANGE_TOPLEVEL_PROJECT)
message(STATUS "Using local options file: ${CMAKE_CURRENT_SOURCE_DIR}/LagrangeOptions.cmake")
include(${CMAKE_CURRENT_SOURCE_DIR}/LagrangeOptions.cmake)
else()
message(WARNING "Ignoring local options file for non-top-level build: "
"${CMAKE_CURRENT_SOURCE_DIR}/LagrangeOptions.cmake")
endif()
endif()
# Set default macOS deployment target
if(LAGRANGE_TOPLEVEL_PROJECT)
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum OS X deployment version")
endif()
#########################################
# Enable sccache or ccache if available #
#########################################
set(LAGRANGE_CACHE_DESCRIPTION "Cache program to use when building Lagrange (none, ccache or sccache)")
# Set compiler cache default based on available programs
find_program(SCCACHE_PROGRAM sccache)
if(SCCACHE_PROGRAM)
set(LAGRANGE_CACHE_PROGRAM "sccache" CACHE STRING ${LAGRANGE_CACHE_DESCRIPTION})
else()
find_program(CCACHE_PROGRAM ccache)
if(CACHE_PROGRAM)
set(LAGRANGE_CACHE_PROGRAM "ccache" CACHE STRING ${LAGRANGE_CACHE_DESCRIPTION})
else()
set(LAGRANGE_CACHE_PROGRAM "none" CACHE STRING ${LAGRANGE_CACHE_DESCRIPTION})
endif()
endif()
set(LAGRANGE_CACHE_CHOICES none ccache sccache)
set_property(CACHE LAGRANGE_CACHE_PROGRAM PROPERTY STRINGS ${LAGRANGE_CACHE_CHOICES})
message(STATUS "Compile cache program: ${LAGRANGE_CACHE_PROGRAM}")
# Now enable compiler cache based on requested option
if(LAGRANGE_CACHE_PROGRAM STREQUAL "sccache")
find_program(SCCACHE_PROGRAM sccache REQUIRED)
set(CMAKE_C_COMPILER_LAUNCHER ${SCCACHE_PROGRAM})
set(CMAKE_CXX_COMPILER_LAUNCHER ${SCCACHE_PROGRAM})
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
elseif(LAGRANGE_WITH_CCACHE AND CCACHE_PROGRAM)
find_program(CCACHE_PROGRAM ccache REQUIRED)
set(ccacheEnv
CCACHE_BASEDIR=${CMAKE_BINARY_DIR}
CCACHE_SLOPPINESS=clang_index_store,include_file_ctime,include_file_mtime,locale,pch_defines,time_macros
)
foreach(lang IN ITEMS C CXX)
set(CMAKE_${lang}_COMPILER_LAUNCHER
${CMAKE_COMMAND} -E env ${ccacheEnv} ${CCACHE_PROGRAM}
)
endforeach()
endif()
################################################################################
file(READ "VERSION" lagrange_version)
string(STRIP ${lagrange_version} lagrange_version)
project(Lagrange VERSION ${lagrange_version})
# Detects whether internal libs are available
if(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/cmake/recipes/internal")
set(LAGRANGE_NO_INTERNAL OFF)
else()
set(LAGRANGE_NO_INTERNAL ON)
endif()
# Define this first since other options defaults depend on this
option(LAGRANGE_JENKINS "Enable specific configs when building on Jenkins" OFF)
# Whether to enable compilation tests by default
if(WIN32 AND NOT LAGRANGE_JENKINS)
set(LAGRANGE_COMPILE_TESTS_DEFAULT NO)
else()
set(LAGRANGE_COMPILE_TESTS_DEFAULT ${LAGRANGE_TOPLEVEL_PROJECT})
endif()
# Meta target: ALL includes all optional modules and UI.
option(LAGRANGE_ALL "Build all lagrange modules" OFF)
# When building the usd module, we need to use TBB 2020
if(LAGRANGE_MODULE_USD OR (LAGRANGE_ALL AND NOT LAGRANGE_NO_INTERNAL))
option(LAGRANGE_WITH_ONETBB "Build Lagrange with OneTBB 2021 rather than TBB 2020" OFF)
option(TBB_PREFER_STATIC "Build with static TBB" OFF)
endif()
# General CMake options
option(LAGRANGE_ASSERT_DEBUG_BREAK "Assert will break into debugger on failure" ${LAGRANGE_TOPLEVEL_PROJECT})
option(LAGRANGE_COMPILE_TESTS "Enable compilation tests" ${LAGRANGE_COMPILE_TESTS_DEFAULT})
option(LAGRANGE_COPY_RUNTIME_DEPS "Copy runtime dependencies into executable folders" ${LAGRANGE_TOPLEVEL_PROJECT})
option(LAGRANGE_DISABLE_FPE "Disable floating point exception code" OFF)
option(LAGRANGE_DOCUMENTATION "Build Doxygen documentation" OFF)
option(LAGRANGE_ENABLE_GPU_TESTS "Enable unit tests that run on the GPU" ON)
option(LAGRANGE_ENABLE_LEGACY_FUNCTIONS "Enable support for legacy functions." ON)
option(LAGRANGE_EXAMPLES "Build all examples" ${LAGRANGE_TOPLEVEL_PROJECT})
option(LAGRANGE_INSTALL "Enable installation" ${LAGRANGE_TOPLEVEL_PROJECT})
option(LAGRANGE_LIMIT_PARALLELISM "Limit parallelism according to available cpu/memory" OFF)
option(LAGRANGE_MORE_WARNINGS "Increase the level of warnings when compiling" OFF)
option(LAGRANGE_PERFORMANCE_TESTS "Build all performance tests" OFF)
option(LAGRANGE_UNIT_TESTS "Build all unit tests" ${LAGRANGE_TOPLEVEL_PROJECT})
option(LAGRANGE_USE_PCH "Enable precompiled headers" OFF)
option(LAGRANGE_USE_WASM_EXCEPTIONS "Use -fwasm-exception flag with Emscripten" OFF)
option(LAGRANGE_WITH_ONETBB "Build Lagrange with OneTBB 2021 rather than TBB 2020" ON)
option(LAGRANGE_WITH_TRACY "Build tracy client with Lagrange" OFF)
# Specific override for building on Jenkins
if(LAGRANGE_JENKINS)
# IPO is very slow and not needed for CI purposes
option(TBB_ENABLE_IPO "Enable Interprocedural Optimization (IPO) during the compilation" OFF)
endif()
# When building Arpack from source, we need to enable Fortran support in the top-level directory
if(ARPACK_BUILD_FROM_SOURCE)
enable_language(Fortran)
endif()
# Allowlist/blocklist restricting which modules are allowed in the sub-project. This is an advanced
# option, targeted at users who wish to have explicit knowledge of which module is implicitly
# compiled by Lagrange. By default, an empty list means all modules are allowed.
set(LAGRANGE_ALLOWLIST "" CACHE STRING "List of modules allowed in the project (empty: allow everything)")
set(LAGRANGE_BLOCKLIST "" CACHE STRING "List of modules excluded from the project")
# Third-party dependency management
option(LAGRANGE_EXTERNAL_FIRST "Third-party libs: prefer public mirrors over corporate ones" OFF)
option(LAGRANGE_EXTERNAL_ONLY "Third-party libs: only download from public mirrors" ${LAGRANGE_NO_INTERNAL})
# Artifactory key file
set(LAGRANGE_ARTIFACTORY_KEYFILE "" CACHE FILEPATH "Path to secret artifactory key.")
# Website repository (extract & check code)
set(LAGRANGE_WEBSITE_REPO "" CACHE FILEPATH "Path to the website repository for markdown code extraction")
# Set default minimum C++ standard
if(LAGRANGE_TOPLEVEL_PROJECT)
set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard version to compile with")
set(CMAKE_CXX_STANDARD_REQUIRED ON CACHE BOOL "Whether the C++ standard version is a requirement")
set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Whether compiler specific extensions are requested")
endif()
if(LAGRANGE_EXTERNAL_ONLY)
list(PREPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/recipes/external/")
elseif(LAGRANGE_EXTERNAL_FIRST)
list(PREPEND CMAKE_MODULE_PATH
"${PROJECT_SOURCE_DIR}/cmake/recipes/external/"
"${PROJECT_SOURCE_DIR}/cmake/recipes/internal/"
)
else()
list(PREPEND CMAKE_MODULE_PATH
"${PROJECT_SOURCE_DIR}/cmake/recipes/internal/"
"${PROJECT_SOURCE_DIR}/cmake/recipes/external/"
)
endif()
list(PREPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/lagrange/")
# Lagrange folder prefix for IDE
if(LAGRANGE_TOPLEVEL_PROJECT)
set(LAGRANGE_IDE_PREFIX_DEFAULT "")
else()
set(LAGRANGE_IDE_PREFIX_DEFAULT "third_party/")
endif()
set(LAGRANGE_IDE_PREFIX ${LAGRANGE_IDE_PREFIX_DEFAULT} CACHE STRING "Folder prefix for Lagrange targets in MSVC/Xcode")
# When building anorigami module, defaults to pre-built Arpack and dynamic MKL/TBB
# When building python module, compile MKL/TBB as a shared library
if(LAGRANGE_MODULE_ANORIGAMI OR LAGRANGE_MODULE_MESHPROC OR LAGRANGE_MODULE_PYTHON
OR (LAGRANGE_ALL AND NOT LAGRANGE_NO_INTERNAL))
set(MKL_LINKING "dynamic" CACHE STRING "Linking strategy to use with MKL (static, dynamic or sdl)")
option(TBB_PREFER_STATIC "Build with static TBB" OFF)
option(TBB_BUILD_TBBMALLOC "Build TBB malloc library" ON)
endif()
# On Linux & Windows we use MKL to provide BLAS/LAPACK. Since it comes precompiled with /MD on Windows,
# we need to use the MSVC runtime library flag globally for the whole project.
file(READ "cmake/lagrange/lagrangeMklModules.txt" LAGRANGE_MKL_MODULES)
if(LAGRANGE_TOPLEVEL_PROJECT)
if(LAGRANGE_ALL AND NOT LAGRANGE_NO_INTERNAL)
# Set MSVC runtime library globally for all targets
message(STATUS "Forcing /MD globally due to LAGRANGE_ALL requiring MKL")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL" CACHE STRING "Select the MSVC runtime library")
else()
foreach(mkl_module_lc IN ITEMS ${LAGRANGE_MKL_MODULES})
string(TOUPPER ${mkl_module_lc} mkl_module_uc)
if(LAGRANGE_MODULE_${mkl_module_uc})
# Set MSVC runtime library globally for all targets
message(STATUS "Forcing /MD globally due to lagrange::${mkl_module_lc} requiring MKL")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL" CACHE STRING "Select the MSVC runtime library")
endif()
endforeach()
endif()
endif()
# Register project source/binary dir in global properties, so they can be
# retrieved from Lagrange CMake functions when called by client code.
set_property(GLOBAL PROPERTY __lagrange_source_dir ${PROJECT_SOURCE_DIR})
set_property(GLOBAL PROPERTY __lagrange_binary_dir ${PROJECT_BINARY_DIR})
set_property(GLOBAL PROPERTY __lagrange_module_path ${CMAKE_MODULE_PATH})
include(code-coverage)
include(lagrange_add_compile_test)
include(lagrange_add_example)
include(lagrange_add_executable)
include(lagrange_add_module)
include(lagrange_add_performance)
include(lagrange_add_python_binding)
include(lagrange_add_test)
include(lagrange_cpm_cache)
include(lagrange_download_data)
include(lagrange_global_flags)
include(lagrange_has_onetbb)
include(lagrange_include_modules)
include(lagrange_install)
include(lagrange_limit_parallelism)
include(lagrange_warnings)
include(sanitizers)
set(CMAKE_MACOSX_RPATH 1) # Set rpath for mac
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
if(LAGRANGE_LIMIT_PARALLELISM)
lagrange_limit_parallelism()
endif()
find_package(Threads REQUIRED)
# Include OneTBB early to provide TBB::tbb target
if(LAGRANGE_WITH_ONETBB)
set(MKL_VERSION 2021.3.0 CACHE STRING "MKL version to use (2020.4 or 2021.3.0)")
include(onetbb)
else()
set(MKL_VERSION 2020.4 CACHE STRING "MKL version to use (2020.4 or 2021.3.0)")
endif()
# Enable unit testing at the root level
if(LAGRANGE_UNIT_TESTS)
include(CTest)
# Include Catch2 and provide function `catch_discover_tests` to register tests.
include(catch2)
FetchContent_GetProperties(catch2)
include("${catch2_SOURCE_DIR}/extras/Catch.cmake")
# Global target for code coverage
if(LAGRANGE_TOPLEVEL_PROJECT)
add_code_coverage_all_targets()
endif()
endif()
# Build modules
add_subdirectory(modules)
# Build documentation
if(LAGRANGE_DOCUMENTATION)
add_subdirectory(docs)
endif()
# Build code extracted from markdown documentation
if(LAGRANGE_WEBSITE_REPO)
add_subdirectory(docs/code)
endif()
# Copy shared dependencies for executables created by Lagrange. Clients using Lagrange as a subfolder must use their
# own mechanism to copy shared dlls into their executable folder. One possibility is to register their executable using
# `lagrange_add_executable`, and install dependencies by calling `lagrange_copy_all_runtime_dependencies` at the end of
# their own CMake script. Please follow https://gitlab.kitware.com/cmake/cmake/-/issues/20417 for an official solution
# when available.
if(LAGRANGE_COPY_RUNTIME_DEPS)
lagrange_copy_all_runtime_dependencies()
endif()
################################################################################
# Install CMake config files
################################################################################
if(LAGRANGE_INSTALL)
include(GNUInstallDirs)
set(project_config_in "${PROJECT_SOURCE_DIR}/cmake/lagrange/lagrangeConfig.cmake.in")
set(project_config_out "${CMAKE_CURRENT_BINARY_DIR}/LagrangeConfig.cmake")
set(config_targets_file "LagrangeConfigTargets.cmake")
set(version_config_file "${CMAKE_CURRENT_BINARY_DIR}/LagrangeConfigVersion.cmake")
set(export_dest_dir "${CMAKE_INSTALL_LIBDIR}/cmake/lagrange")
install(EXPORT Lagrange_Targets
DESTINATION ${export_dest_dir}
NAMESPACE lagrange::
FILE ${config_targets_file}
COMPONENT Lagrange_Development
)
include(CMakePackageConfigHelpers)
configure_file("${project_config_in}" "${project_config_out}" @ONLY)
write_basic_package_version_file("${version_config_file}" COMPATIBILITY SameMajorVersion)
install(FILES "${project_config_out}" "${version_config_file}" DESTINATION "${export_dest_dir}")
endif()