forked from igfuw/libcloudphxx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
359 lines (304 loc) · 12.6 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
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# needed for the OpenMP test to work in C++-only project
# (see http://public.kitware.com/Bug/view.php?id=11910)
cmake_minimum_required(VERSION 3.9 FATAL_ERROR) # 3.9 for OpenMP targets-based build
project(libcloudph++ LANGUAGES CXX)
# the policies we care about:
# - CMP0025 - make CMake distinguis between Apple and LLVM clang
# - CMP0042 - make CMake use RPATHs on OSX
# - CMP0060 - make CMake always keep absoult RPATHs, even if installing in implicit directory
#if(CMAKE_VERSION VERSION_GREATER 2.9)
# cmake_policy(VERSION 3.0)
#endif()
# put out custom find scripts first
list(INSERT CMAKE_MODULE_PATH 0 ${PROJECT_SOURCE_DIR}/cmake)
#set(CMAKE_MACOSX_RPATH ON) # explicit, since policy CMP0042 didn't work...
# using include() istead of find_package(libcloudph++) to use local CMake code
# and not the system-installed one
#include(${CMAKE_SOURCE_DIR}/libcloudph++-config.cmake)
#if (NOT libcloudphxx_FOUND)
# message(FATAL_ERROR "local libcloudph++-config.cmake not found!")
#endif()
# Set a default build type for single-configuration
# CMake generators if no build type is set.
IF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE Release)
ENDIF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
# clearing default config-specific flags
set(CMAKE_CXX_FLAGS_DEBUG "")
set(CMAKE_CXX_FLAGS_RELEASE "")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
############################################################################################
# see if CUDA is available
option(LIBCLOUDPHXX_DISABLE_CUDA "LIBCLOUDPHXX_DISABLE_CUDA" False)
if (NOT LIBCLOUDPHXX_DISABLE_CUDA)
include(CheckLanguage)
check_language(CUDA)
endif()
if (NOT CMAKE_CUDA_COMPILER)
message(STATUS "CUDA not found.
* CUDA support will not be compiled.
* To install CUDA, please try:
* Debian/Ubuntu: sudo apt-get install nvidia-cuda-toolkit
* Fedora: TODO
* Homebrew: TODO
")
else()
enable_language(CUDA)
set(CMAKE_CUDA_FLAGS_DEBUG "")
set(CMAKE_CUDA_FLAGS_RELEASE "")
set(CMAKE_CUDA_FLAGS_RELWITHDEBINFO "")
endif()
#############################################################################################
# see if OpenMP is available
find_package(OpenMP)
if(OPENMP_CXX_FOUND)
message(STATUS " OpenMP found")
else()
message(STATUS "CMAKE cant find OpenMP (known issue for AppleClang on OSX)")
# maybe some hints are here: https://github.com/src-d/kmcuda/issues/6
set(OpenMP_CXX_FLAGS " ")
endif()
############################################################################################
# allowing runtime choice between CUDA, CPP and OpenMP backends
set(files "")
set(files "${files};src/lib.cpp")
set(files "${files};src/lib_cpp.cpp")
if (OPENMP_CXX_FOUND)
set(files "${files};src/lib_omp.cpp")
endif()
if (CMAKE_CUDA_COMPILER)
set(files "${files};src/lib_cuda.cu")
endif()
############################################################################################
# create the library target
add_library(cloudphxx_lgrngn SHARED ${files})
############################################################################################
# pointing to library headers
target_include_directories(cloudphxx_lgrngn
PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
)
# enabling additional warnings
target_compile_options(cloudphxx_lgrngn PRIVATE $<$<COMPILE_LANGUAGE:CXX>: -Wextra>)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
# enabling c++11
target_compile_features(cloudphxx_lgrngn PUBLIC cxx_std_11)
# config-specific flags
target_compile_options(cloudphxx_lgrngn PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>: -g -Og -DTHRUST_DEBUG>)
target_compile_options(cloudphxx_lgrngn PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELWITHDEBINFO>>: -Ofast -march=native>)
target_compile_options(cloudphxx_lgrngn PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>: -DNDEBUG -Ofast -march=native -Winline>)
# add dependencies
if (CMAKE_CUDA_COMPILER)
target_link_libraries(cloudphxx_lgrngn PRIVATE curand)
endif()
if(OPENMP_CXX_FOUND)
# target_link_libraries would be preferable, but it adds -fopenmp to nvcc and that breaks the build
#target_link_libraries(cloudphxx_lgrngn PRIVATE OpenMP::OpenMP_CXX>)
target_compile_options(cloudphxx_lgrngn PUBLIC $<$<COMPILE_LANGUAGE:CXX>: ${OpenMP_CXX_FLAGS}>)
target_link_libraries(cloudphxx_lgrngn PUBLIC ${OpenMP_CXX_LIBRARIES})
endif()
############################################################################################
# figure out CUDA nvcc flags
if (CMAKE_CUDA_COMPILER)
# trying to figure out compute capability of the current
message(STATUS "Trying to obtain CUDA capability of local hardware...")
set(pfx "compute cabability check")
execute_process(COMMAND "mktemp" "-d" "/tmp/tmp.XXX" RESULT_VARIABLE status OUTPUT_VARIABLE tmpdir)
if (NOT status EQUAL 0)
message(FATAL_ERROR "${pfx}: mkdtemp failed")
endif()
file(WRITE "${tmpdir}/test.cu" "
#include <iostream>
int main()
{
int DeviceCount;
cudaGetDeviceCount(&DeviceCount);
for(int i = 0 ; i < DeviceCount; ++i)
{
cudaDeviceProp prop;
cudaError_t err = cudaGetDeviceProperties(&prop, i);
if (err == cudaSuccess)
std::cout << prop.major << prop.minor << \" \" ;
else
{
std::cerr << cudaGetErrorString(err);
std::cout << \"? \";
}
}
}
")
execute_process(COMMAND "${CMAKE_CUDA_COMPILER}" "test.cu" WORKING_DIRECTORY ${tmpdir} RESULT_VARIABLE status ERROR_VARIABLE msg)
if (NOT status EQUAL 0)
message(FATAL_ERROR "${pfx}: nvcc failed\n ${msg}")
endif()
execute_process(COMMAND "./a.out" WORKING_DIRECTORY ${tmpdir} RESULT_VARIABLE status OUTPUT_VARIABLE msg)
if (NOT status EQUAL 0)
message(FATAL_ERROR "${pfx}: test program failed")
endif()
separate_arguments(msg)
list(REMOVE_ITEM msg "")
list(LENGTH msg gpu_count)
if(gpu_count GREATER 1 OR LIBCLOUDPHXX_FORCE_MULTI_CUDA)
# compile the multi_CUDA backend
message(STATUS "Detected more than 1 GPU or LIBCLOUDPHXX_FORCE_MULTI_CUDA set, the multi_CUDA backend will be built.")
target_sources(cloudphxx_lgrngn PRIVATE src/lib_multicuda.cu)
target_compile_definitions(cloudphxx_lgrngn PRIVATE MULTICUDA_FOUND)
else()
message(STATUS "Number of GPUs detected <=1, the multi_CUDA backend will not be built. You can force compilation of this backend by setting LIBCLOUDPHXX_FORCE_MULTI_CUDA.")
endif()
list(REMOVE_DUPLICATES msg)
if(msg)
# find the lowest compute capability and set it as virtual architecture, see:
# https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-compilation
list(SORT msg)
list(GET msg 0 VIRT)
target_compile_options(cloudphxx_lgrngn PRIVATE $<$<COMPILE_LANGUAGE:CUDA>: --gpu-architecture=compute_${VIRT}>)
set(GPU_CODE_OPTIONS --gpu-code=)
foreach(code ${msg})
message(STATUS "CUDA capability: ${code}")
if (code STREQUAL "?")
set (code "20")
message(STATUS "CUDA capability check failed, assuming a default of ${code}")
endif()
set(arch ${code})
if (arch EQUAL "21") # see https://devtalk.nvidia.com/default/topic/606195/-solved-nvcc-fatal-unsupported-gpu-architecture-compute_21-/
set(arch "20")
endif()
set(GPU_CODE_OPTIONS ${GPU_CODE_OPTIONS}sm_${arch},)
endforeach(code)
target_compile_options(cloudphxx_lgrngn PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:${GPU_CODE_OPTIONS}>)
else()
message(STATUS "CUDA capability check didn't find any devices")
endif()
unset(pfx)
unset(tmpdir)
unset(msg)
unset(status)
# Release with debug info mode cuda flags, shouldn't cmake push CXX compiler flags as -Xcompiler=... ?
if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
target_compile_options(cloudphxx_lgrngn PRIVATE $<$<COMPILE_LANGUAGE:CUDA>: -O3 -use_fast_math -Xcompiler=-Ofast,-march=native,-fopenmp>)
# Debug mode cuda flags
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(cloudphxx_lgrngn PRIVATE $<$<COMPILE_LANGUAGE:CUDA>: -g -DTHRUST_DEBUG -lineinfo -Xcompiler=-fopenmp,-g,-Og,-rdynamic>)
# Release mode cuda flags
else()
target_compile_options(cloudphxx_lgrngn PRIVATE $<$<COMPILE_LANGUAGE:CUDA>: -DNDEBUG -O3 -use_fast_math -Xcompiler=-Ofast,-march=native,-DNDEBUG,-fopenmp>)
endif()
target_compile_definitions(cloudphxx_lgrngn PRIVATE CUDA_FOUND)
endif()
############################################################################################
# Thrust, location of Thrust can be hinted by setting THRUST_INCLUDE_DIR
find_package(Thrust)
if (NOT THRUST_INCLUDE_DIR)
message(FATAL_ERROR "Thrust library not found.
* To install Thrust, please try:
* Debian/Ubuntu: sudo apt-get install libthrust-dev
* Fedora: TODO
* Homebrew: TODO
")
endif()
# include thrust found here instead of the one shipped with cuda
target_include_directories(cloudphxx_lgrngn PRIVATE ${THRUST_INCLUDE_DIR})
############################################################################################
# Boost libraries
find_package(Boost COMPONENTS) # we only need header-only boost libs
if(Boost_FOUND)
target_link_libraries(cloudphxx_lgrngn
PUBLIC
Boost::boost
)
else()
#TODO: check separately for optional and mandatory components
message(FATAL_ERROR "Boost (or some of its components) not found.
* To insall Boost, please try:
* Debian/Ubuntu: sudo apt-get install libboost-all-dev
* Fedora: sudo yum install boost-devel
")
endif()
############################################################################################
# BOOST ODEINT VERSION TEST
message(STATUS "Testing if Boost ODEINT version >= 1.58")
set(pfx "boost odeint check")
execute_process(COMMAND "mktemp" "-d" "/tmp/tmp.XXX" RESULT_VARIABLE status OUTPUT_VARIABLE tmpdir)
if (NOT status EQUAL 0)
message(FATAL_ERROR "${pfx}: mkdtemp failed")
endif()
file(WRITE "${tmpdir}/test.cpp" "
#define THRUST_DEVICE_SYSTEM THRUST_DEVICE_SYSTEM_CPP
#include <thrust/system/cpp/vector.h>
#include <boost/numeric/odeint.hpp>
#include <boost/numeric/odeint/external/thrust/thrust_algebra.hpp>
#include <boost/numeric/odeint/external/thrust/thrust_operations.hpp>
#include <boost/numeric/odeint/external/thrust/thrust_resize.hpp>
struct rhs
{
void operator()(
const thrust::cpp::vector<float> &psi,
thrust::cpp::vector<float> &dot_psi,
const float /* t */
)
{
}
};
int main()
{
boost::numeric::odeint::euler<
thrust::cpp::vector<float>, // state_type
float, // value_type
thrust::cpp::vector<float>, // deriv_type
float, // time_type
boost::numeric::odeint::thrust_algebra,
boost::numeric::odeint::thrust_operations
> chem_stepper;
thrust::cpp::vector<float> v(11);
chem_stepper.do_step(rhs(), v, 0, 1);
}
")
execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "test.cpp" "-I${Boost_INCLUDE_DIR}" "-I${THRUST_INCLUDE_DIR}" WORKING_DIRECTORY ${tmpdir} RESULT_VARIABLE status ERROR_VARIABLE msg)
if (NOT status EQUAL 0)
message(FATAL_ERROR "${pfx}: c++ compiler failed\n ${msg}")
endif()
execute_process(COMMAND "./a.out" WORKING_DIRECTORY ${tmpdir} RESULT_VARIABLE status OUTPUT_VARIABLE msg)
if (NOT status EQUAL 0)
message(FATAL_ERROR "${pfx}: test program failed, install Boost odeint version >= 1.58")
endif()
unset(pfx)
unset(tmpdir)
unset(msg)
unset(status)
# generate a header file with git revision id
if (EXISTS "${CMAKE_SOURCE_DIR}/.git")
add_custom_target(git_revision.h ALL
git log -1 "--format=format:#define LIBCLOUDPHXX_GIT_REVISION \"%H\"%n" HEAD > include/libcloudph++/git_revision.h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} VERBATIM
)
endif()
enable_testing()
add_subdirectory(tests)
add_subdirectory(include)
add_subdirectory(bindings)
############################################################################################
# installation
set_target_properties(cloudphxx_lgrngn PROPERTIES DEBUG_POSTFIX _dbg RELWITHDEBINFO_POSTFIX _relwithdbg)
# install files and export targets
install(TARGETS cloudphxx_lgrngn EXPORT cloudphxx_lgrngn-targets
LIBRARY DESTINATION lib
INCLUDES DESTINATION include)
install(EXPORT cloudphxx_lgrngn-targets NAMESPACE clphxx:: DESTINATION share/libcloudph++)
# generate and install a config file
include(CMakePackageConfigHelpers)
#export(TARGETS cloudphxx_lgrngn FILE MyLibraryConfig.cmake)
configure_package_config_file(
libcloudph++-config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/libcloudph++-config.cmake"
INSTALL_DESTINATION
share/libcloudph++
)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/libcloudph++-config.cmake"
DESTINATION
share/libcloudph++
)
############################################################################################