-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathCMakeLists.txt
309 lines (267 loc) · 12.7 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
#=============================================================================
# Adds the following DIY library targets:
# 1. diy: The main diy interface library and the only target for
# header-only mode.
# 2. diympi: Generated when `build_diy_mpi_lib` and `mpi` are turned on.
# Isolates the MPI dependent part of diy into a library.
# 3. diympi_nompi: Generated when `build_diy_mpi_lib` is on and either `mpi`
# is off or `build_diy_nompi_lib` is on.
#
# Both mpi and non-mpi libraries can be generated by turning on `build_diy_mpi_lib`
# and `build_diy_nompi_lib`. In this case, one of these targets must be explicitly
# specified when linking againts diy.
#=============================================================================
project (DIY)
cmake_minimum_required (VERSION 3.9)
list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include(CMakeDependentOption)
include(GNUInstallDirs)
# Provides an option if it is not already defined.
# This can be replaced when CMake 3.13 is our cmake_minimum_required
macro (diy_option variable)
if (NOT DEFINED "${variable}")
option("${variable}" ${ARGN})
endif ()
endmacro ()
macro (diy_dependent_option variable)
if (NOT DEFINED "${variable}")
cmake_dependent_option("${variable}" ${ARGN})
endif ()
endmacro ()
set (compiler_supports_sanitizers OFF)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR
CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (compiler_supports_sanitizers ON)
endif ()
diy_option (threads "Build DIY with threading" ON)
diy_option (log "Build DIY with logging" OFF)
diy_option (profile "Build DIY with profiling" OFF)
diy_option (caliper "Build DIY with caliper" OFF)
diy_option (mpi "Build DIY with mpi" ON)
diy_option (wrapped_mpi "MPI compiler wrapper requires no further MPI libraries" OFF)
diy_option (build_diy_mpi_lib "Build diy::mpi as a library" OFF)
diy_dependent_option (BUILD_SHARED_LIBS "Create shared libraries if on" ON "build_diy_mpi_lib" OFF)
diy_dependent_option (build_diy_nompi_lib "Also build the nompi version of diy::mpi" OFF "mpi;build_diy_mpi_lib" OFF)
diy_option (build_examples "Build DIY examples" ON)
diy_option (install_examples "Install DIY examples source code" ON)
diy_option (build_tests "Build DIY tests" ON)
diy_option (python "Build Python bindings" OFF)
cmake_dependent_option (enable_sanitizers "Build DIY with sanitizer support" OFF "compiler_supports_sanitizers" OFF)
# Default to Release
if (NOT CMAKE_BUILD_TYPE)
set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif (NOT CMAKE_BUILD_TYPE)
set (diy_definitions "")
set (diy_include_directories "")
set (diy_include_thirdparty_directories "")
set (diy_libraries "")
# Debugging
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR
${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
list (APPEND diy_definitions "-DDEBUG")
endif ()
# Logging
if (log)
list (APPEND diy_definitions "-DDIY_USE_SPDLOG")
find_package (spdlog REQUIRED)
endif()
# Profiling
if (profile)
list (APPEND diy_definitions "-DDIY_PROFILE")
endif()
if (caliper)
list (APPEND diy_definitions "-DDIY_USE_CALIPER")
find_package (caliper)
list (APPEND diy_include_thirdparty_directories $<BUILD_INTERFACE:${caliper_INCLUDE_DIR}>)
list (APPEND diy_libraries caliper)
endif()
# Threads
if (NOT threads)
list (APPEND diy_definitions "-DDIY_NO_THREADS")
else (NOT threads)
find_package (Threads)
list (APPEND diy_libraries ${CMAKE_THREAD_LIBS_INIT})
endif (NOT threads)
# MPI
if (mpi AND NOT wrapped_mpi)
find_package(MPI REQUIRED)
endif()
# configuration variables for diy build and install
# if diy is a sub-project, the following variables allow the parent project to
# easily customize the library
if (NOT DEFINED diy_prefix)
set(diy_prefix "diy")
endif()
if (NOT DEFINED diy_install_include_dir)
set(diy_install_include_dir "include")
endif()
if (NOT DEFINED diy_install_bin_dir)
set(diy_install_bin_dir "bin")
endif()
if (NOT DEFINED diy_install_lib_dir)
set(diy_install_lib_dir "lib")
endif()
if (NOT DEFINED diy_export_name)
set(diy_export_name "diy_targets")
endif()
if (NOT DEFINED diy_development_component)
set(diy_development_component "development")
endif()
if (NOT DEFINED diy_runtime_component)
set(diy_runtime_component "runtime")
endif()
if (NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
endif()
if (NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
endif()
# for diy_developer_flags
include(DIYCompilerFlags)
function(add_diy_mpi_library use_mpi)
set (sources
"include/${diy_prefix}/mpi/collectives.cpp"
"include/${diy_prefix}/mpi/communicator.cpp"
"include/${diy_prefix}/mpi/datatypes.cpp"
"include/${diy_prefix}/mpi/environment.cpp"
"include/${diy_prefix}/mpi/io.cpp"
"include/${diy_prefix}/mpi/operations.cpp"
"include/${diy_prefix}/mpi/point-to-point.cpp"
"include/${diy_prefix}/mpi/request.cpp"
"include/${diy_prefix}/mpi/status.cpp"
"include/${diy_prefix}/mpi/window.cpp")
if (use_mpi)
set (lib_name ${diy_prefix}mpi)
set (has_mpi_val 1)
else()
set (lib_name ${diy_prefix}mpi_nompi)
set (has_mpi_val 0)
endif()
add_library(${lib_name} ${sources})
target_compile_features(${lib_name} PRIVATE cxx_std_11)
target_compile_definitions(${lib_name}
PRIVATE -DDIY_HAS_MPI=${has_mpi_val}
PRIVATE ${diy_definitions})
target_include_directories(${lib_name} PRIVATE ${diy_include_directories}) # for mpitypes.hpp
target_include_directories(${lib_name} SYSTEM PRIVATE ${diy_include_thirdparty_directories})
target_link_libraries(${lib_name} PRIVATE diy_developer_flags)
if (log)
target_link_libraries(${lib_name} PUBLIC spdlog::spdlog_header_only)
endif ()
if (use_mpi AND TARGET MPI::MPI_CXX)
target_link_libraries(${lib_name} PRIVATE MPI::MPI_CXX)
endif()
endfunction()
# create the targets
set (diy_targets)
if (build_diy_mpi_lib)
include(DIYConfigureMPI)
# To be interchangeable, these libraries should only have PRIVATE properties.
# Properties that should be public should also be part of the core diy target.
list(APPEND diy_definitions -DDIY_MPI_AS_LIB)
list(APPEND diy_include_directories
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/${diy_prefix}/mpi>"
"$<INSTALL_INTERFACE:${diy_install_include_dir}/${diy_prefix}/mpi>")
# macro required for proper export macros for static vs shared builds
if (NOT BUILD_SHARED_LIBS)
list(APPEND diy_definitions -DDIY_MPI_STATIC_BUILD)
endif()
if (mpi)
add_diy_mpi_library(ON)
list(APPEND diy_targets ${diy_prefix}mpi)
endif()
if ((NOT mpi) OR build_diy_nompi_lib)
add_diy_mpi_library(OFF)
list(APPEND diy_targets ${diy_prefix}mpi_nompi)
endif()
endif() # build_diy_mpi_lib
add_library(${diy_prefix} INTERFACE)
target_compile_features(${diy_prefix} INTERFACE cxx_std_11)
target_compile_definitions(${diy_prefix} INTERFACE ${diy_definitions})
target_include_directories(${diy_prefix} INTERFACE
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${diy_install_include_dir}>")
target_include_directories(${diy_prefix} SYSTEM INTERFACE ${diy_include_thirdparty_directories})
if (diy_include_directories)
target_include_directories(${diy_prefix} INTERFACE ${diy_include_directories})
endif()
if (log)
target_link_libraries(${diy_prefix} INTERFACE spdlog::spdlog_header_only)
endif ()
target_link_libraries(${diy_prefix} INTERFACE ${diy_libraries})
if (NOT build_diy_mpi_lib)
if (mpi)
target_compile_definitions(${diy_prefix} INTERFACE -DDIY_HAS_MPI=1)
if (TARGET MPI::MPI_CXX)
target_link_libraries(${diy_prefix} INTERFACE MPI::MPI_CXX)
endif()
else()
target_compile_definitions(${diy_prefix} INTERFACE -DDIY_HAS_MPI=0)
endif()
elseif (NOT build_diy_nompi_lib)
if (mpi)
target_link_libraries(${diy_prefix} INTERFACE ${diy_prefix}mpi)
else()
target_link_libraries(${diy_prefix} INTERFACE ${diy_prefix}mpi_nompi)
endif()
endif()
list(APPEND diy_targets ${diy_prefix} diy_developer_flags)
# libraries used by examples and tests
set(libraries ${diy_prefix})
if (${diy_prefix}mpi IN_LIST diy_targets)
list(APPEND libraries ${diy_prefix}mpi)
elseif (${diy_prefix}mpi_nompi IN_LIST diy_targets)
list(APPEND libraries ${diy_prefix}mpi_nompi)
endif()
list(APPEND libraries diy_developer_flags)
# Sanitizers
if (enable_sanitizers)
set(sanitizer "address" CACHE STRING "The sanitizer to use")
string (APPEND CMAKE_CXX_FLAGS " -fsanitize=${sanitizer}")
string (APPEND CMAKE_C_FLAGS " -fsanitize=${sanitizer}")
string (APPEND CMAKE_EXE_LINKER_FLAGS " -fsanitize=${sanitizer}")
string (APPEND CMAKE_SHARED_LINKER_FLAGS " -fsanitize=${sanitizer}")
endif ()
# enable testing and CDash dashboard submission
enable_testing ()
include (CTest)
if (build_examples)
add_subdirectory (examples)
endif (build_examples)
if (install_examples)
install(DIRECTORY examples/smoke_test DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/DIY/examples)
endif (install_examples)
if (build_tests)
add_subdirectory (tests)
endif (build_tests)
# configure find_package script
include(CMakePackageConfigHelpers)
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/diy-config.cmake.in"
"${PROJECT_BINARY_DIR}/diy-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DIY")
# install targets
if (NOT DEFINED diy_install_only_libraries) # defined by parent project if building for binary distribution
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/${diy_prefix}
DESTINATION ${diy_install_include_dir}
COMPONENT ${diy_development_component})
if (build_diy_mpi_lib)
install(FILES ${PROJECT_BINARY_DIR}/include/${diy_prefix}/mpi/mpitypes.hpp
DESTINATION ${diy_install_include_dir}/${diy_prefix}/mpi
COMPONENT ${diy_development_component})
endif()
endif()
install(TARGETS ${diy_targets} EXPORT ${diy_export_name}
ARCHIVE DESTINATION ${diy_install_lib_dir} COMPONENT ${diy_development_component}
LIBRARY DESTINATION ${diy_install_lib_dir} COMPONENT ${diy_runtime_component}
RUNTIME DESTINATION ${diy_install_bin_dir} COMPONENT ${diy_runtime_component})
if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # Only generate these files when diy is the main project
export(EXPORT ${diy_export_name} NAMESPACE DIY:: FILE "${PROJECT_BINARY_DIR}/diy-targets.cmake")
install(EXPORT ${diy_export_name} NAMESPACE DIY:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DIY" FILE diy-targets.cmake COMPONENT ${diy_development_component})
install(FILES "${PROJECT_BINARY_DIR}/diy-config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/DIY" COMPONENT ${diy_development_component})
endif()
if (python)
add_subdirectory(bindings/python)
endif (python)