forked from usnistgov/teqp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
378 lines (306 loc) · 15.5 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
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
if(CMAKE_GENERATOR STREQUAL Xcode)
set(CMAKE_OSX_ARCHITECTURES arm64 CACHE INTERNAL "archs for osx")
endif()
cmake_minimum_required(VERSION 3.16)
project(teqp)
enable_testing()
# Enable /bigobj for MSVC builds
if (MSVC)
add_compile_options(/bigobj)
add_compile_options(/permissive-)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
endif()
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
option (TEQP_NO_PYTHON
"Enable to NOT build the Python interface"
OFF)
option (TEQP_NO_TESTS
"Enable to NOT include the test targets at all"
OFF)
option (TEQP_NO_TEQPCPP
"Enable to NOT include the teqp C++ wrapper"
OFF)
option (TEQP_TESTTEQPCPP
"Enable to add a target with a test of the C++ interface"
OFF)
option (TEQP_TEQPC
"Enable to build the shared library with extern \"C\" interface"
OFF)
option (TEQP_COVERAGE
"Enable to build the GCOV tests of the catch tests"
OFF)
option (TEQP_JAVASCRIPT_HTML
"Enable to generate HTML files rather than js with the emscripten engine"
OFF)
option (TEQP_JAVASCRIPT_EMBIND
"Build C++ <-> Javascript interface with embind"
OFF)
option (TEQP_MULTIPRECISION_ENABLED
"Enable the use of boost::multiprecision"
OFF)
option (TEQP_MULTICOMPLEX_ENABLED
"Enable the use of multi-complex arithmetic for taking derivatives"
OFF)
option (TEQP_COMPLEXSTEP_ENABLED
"Enable the use of complex-step derivatives for taking first derivatives"
ON)
option (TEQP_ASAN
"Enable to pull in the flags needed to use address sanitizer"
OFF)
# Define -DTEQP_ASAN=ON to enable the option of using address sanitizer of clang
if (TEQP_ASAN)
# https://stackoverflow.com/a/64294837 (CC BY-SA 4.0)
if(isMultiConfig)
if(NOT "Asan" IN_LIST CMAKE_CONFIGURATION_TYPES)
list(APPEND CMAKE_CONFIGURATION_TYPES Asan)
endif()
else()
set(allowedBuildTypes Asan Debug Release RelWithDebInfo MinSizeRel)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowedBuildTypes}")
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE IN_LIST allowedBuildTypes)
message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
endif()
endif()
set(CMAKE_C_FLAGS_ASAN
"${CMAKE_C_FLAGS_RelWithDebInfo} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C compiler for Asan build type or configuration." FORCE)
set(CMAKE_CXX_FLAGS_ASAN
"${CMAKE_CXX_FLAGS_RelWithDebInfo} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C++ compiler for Asan build type or configuration." FORCE)
set(CMAKE_EXE_LINKER_FLAGS_ASAN
"${CMAKE_EXE_LINKER_FLAGS_RelWithDebInfo} -fsanitize=address" CACHE STRING
"Linker flags to be used to create executables for Asan build type." FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_ASAN
"${CMAKE_SHARED_LINKER_FLAGS_RelWithDebInfo} -fsanitize=address" CACHE STRING
"Linker lags to be used to create shared libraries for Asan build type." FORCE)
endif()
#### SETUP
set(CMAKE_CXX_STANDARD 20)
set(ZIPFN "${CMAKE_CURRENT_SOURCE_DIR}/dev/docker/boost_bcp_docker/boost_teqp.tar.xz")
set(OUTFN "${CMAKE_CURRENT_SOURCE_DIR}/boost_teqp/boost/version.hpp")
if (EXISTS ${ZIPFN})
if(NOT EXISTS ${OUTFN})
execute_process(COMMAND ${CMAKE_COMMAND} -E tar -xJf ${ZIPFN}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
message(STATUS "Untarred boost headers")
endif()
else()
message(FATAL_ERROR "tar.xz of boost sources needed for teqp cannot be found")
endif()
set(ZIPFN "${CMAKE_CURRENT_SOURCE_DIR}/dev/model_schemas.tar.xz")
if (EXISTS ${ZIPFN})
execute_process(COMMAND ${CMAKE_COMMAND} -E tar -xJf ${ZIPFN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP")
message(STATUS "Untarred model schemas")
else()
message(FATAL_ERROR "tar.xz of thermodynamic model schemas needed for teqp cannot be found")
endif()
add_library(teqpinterface INTERFACE)
target_include_directories(teqpinterface INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_include_directories(teqpinterface INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/externals/mcx/multicomplex/include")
target_include_directories(teqpinterface INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen")
target_include_directories(teqpinterface INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/externals/nlohmann_json")
target_include_directories(teqpinterface INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/boost_teqp")
target_include_directories(teqpinterface INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/externals/REFPROP-interop/include")
target_include_directories(teqpinterface INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/externals/stbrumme-hashing/include")
if (NOT TEQP_NO_TESTS)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/externals/Catch2")
endif()
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/externals/json-schema-validator")
set_property(TARGET nlohmann_json_schema_validator PROPERTY POSITION_INDEPENDENT_CODE ON)
set(EIGEN3_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen" CACHE INTERNAL "Path to Eigen, for autodiff")
set(EIGEN3_VERSION_OK TRUE CACHE BOOL "Yes eigen is fine")
set(Eigen3_DIR "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen/cmake" CACHE INTERNAL "Path to Eigen, for autodiff")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen/cmake" CACHE INTERNAL "Path to Eigen finder module, for autodiff")
set(AUTODIFF_BUILD_TESTS FALSE CACHE BOOL "No autodiff tests")
set(AUTODIFF_BUILD_PYTHON FALSE CACHE BOOL "No autodiff python")
set(AUTODIFF_BUILD_EXAMPLES FALSE CACHE BOOL "No autodiff examples")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/externals/autodiff")
# Turn on more useful diagnostic messages in nlohmann::json, for instance if you are accessing a field that doesn't exist
set(JSON_Diagnostics TRUE CACHE BOOL "Turn on more helpful diagnostics in nlohmann::json")
if (NOT TEQP_NO_TEQPCPP)
# Add a static library with the C++ interface that uses only STL
# types so that recompilation of a library that uses teqp
# doesn't require a full compile for a single LOC change
file(GLOB sources "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP/*.cpp")
add_library(teqpcpp STATIC ${sources})
target_link_libraries(teqpcpp PUBLIC nlohmann_json_schema_validator PUBLIC teqpinterface PUBLIC autodiff)
target_include_directories(teqpcpp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP")
target_include_directories(teqpcpp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_include_directories(teqpcpp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen")
set_property(TARGET teqpcpp PROPERTY POSITION_INDEPENDENT_CODE ON)
target_compile_definitions(teqpcpp PRIVATE -DMULTICOMPLEX_NO_MULTIPRECISION)
target_compile_definitions(teqpcpp PUBLIC -DUSE_AUTODIFF)
# Add the schema file
target_sources(teqpcpp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP/model_schemas.cpp")
# The data files too
target_sources(teqpcpp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/data/FEANN.cpp")
target_sources(teqpcpp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/data/Dufal_assoc.cpp")
target_sources(teqpcpp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/data/PCSAFT.cpp")
target_compile_definitions(teqpcpp PUBLIC -DTEQP_MULTIPRECISION_ENABLED)
# target_compile_options(teqpcpp PRIVATE
# $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
# -Wall -Wno-c++98-compat -Wno-c++98-compat-pedantic>
# $<$<CXX_COMPILER_ID:MSVC>:
# /W4 /wd4127 /wd4389 /wd4100>)
target_compile_options(teqpcpp PUBLIC
$<$<OR:$<CXX_COMPILER_ID:GNU>>:
-Wno-class-memaccess>)
if(MSVC)
target_compile_options(teqpcpp PRIVATE /W4 ) # or add /WX to turn warnings into errors
target_compile_options(teqpcpp PUBLIC /wd4127 /wd4389 /wd4100 /wd5054 /wd4702)
else()
# Turn on all warnings, and then disable selectively
target_compile_options(teqpcpp PRIVATE -Wall -Wextra -Wpedantic -Wno-deprecated-copy -Wno-language-extension-token) # or add -Werror to turn warnings into errors
target_compile_options(teqpcpp PUBLIC -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-parentheses)
endif()
if (TEQP_TESTTEQPCPP)
add_executable(test_teqpcpp "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP/test/test_teqpcpp.cpp")
target_link_libraries(test_teqpcpp PUBLIC teqpcpp)
add_executable(bench_teqpcpp "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP/test/bench_teqpcpp.cpp")
target_link_libraries(bench_teqpcpp PUBLIC teqpcpp PRIVATE Catch2WithMain)
endif()
endif()
if (TEQP_JAVASCRIPT_MODULE)
# cmake -DTEQP_JAVASCRIPT_MODULE=ON
# -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Platform/Emscripten.cmake
#
add_compile_options( -sDISABLE_EXCEPTION_CATCHING=0)
add_link_options( -sDISABLE_EXCEPTION_CATCHING=0 -sALLOW_MEMORY_GROWTH=1 -sASSERTIONS=1)
#add_compile_options( -gsource-map -fsanitize=address)
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -gsource-map -fsanitize=address ")
endif()
if (TEQP_MULTIPRECISION_ENABLED)
add_definitions(-DTEQP_MULTIPRECISION_ENABLED)
endif()
if (TEQP_MULTICOMPLEX_ENABLED)
add_definitions(-DTEQP_MULTICOMPLEX_ENABLED)
endif()
if (NOT TEQP_NO_PYTHON)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/externals/pybind11" "pybind11")
file(GLOB pybind11_files "${CMAKE_CURRENT_SOURCE_DIR}/interface/*.cpp")
pybind11_add_module(teqp "${pybind11_files}")
target_include_directories(teqp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/externals/pybind11_json/include")
target_link_libraries(teqp PRIVATE teqpcpp PRIVATE autodiff PRIVATE teqpinterface )
target_compile_definitions(teqp PUBLIC -DUSE_AUTODIFF)
if (MSVC)
target_compile_options(teqp PRIVATE "/Zm1000")
endif()
endif()
if (NOT TEQP_NO_TESTS)
file(GLOB catch_tests_files "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/*.cxx")
# Make all the catch and benchmarking tests
add_executable(catch_tests "${catch_tests_files}" "${CMAKE_CURRENT_SOURCE_DIR}/interface/C/teqpc.cpp")
if (MSVC)
target_sources(catch_tests PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen/debug/msvc/eigen.natvis")
endif()
# Add all the headers to the project for XCode use
file(GLOB_RECURSE headers "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
target_sources(catch_tests PUBLIC ${headers})
target_compile_definitions(catch_tests PRIVATE -DTEQPC_CATCH)
target_compile_definitions(catch_tests PRIVATE -DTEQP_MULTICOMPLEX_ENABLED)
target_compile_definitions(catch_tests PRIVATE -DTEQP_COMPLEXSTEP_ENABLED)
target_compile_definitions(catch_tests PRIVATE -DTEQP_MULTIPRECISION_ENABLED)
target_link_libraries(catch_tests PUBLIC teqpcpp PRIVATE autodiff PRIVATE teqpinterface PRIVATE Catch2WithMain)
add_test(normal_tests catch_tests)
endif()
if (TEQP_TEQPC)
# Make a shared extern "C" library
add_library(teqpc SHARED "${CMAKE_CURRENT_SOURCE_DIR}/interface/C/teqpc.cpp")
if (MSVC)
target_sources(teqpc PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen/debug/msvc/eigen.natvis")
endif()
target_compile_definitions(teqpc PRIVATE -DUSE_AUTODIFF)
target_link_libraries(teqpc PUBLIC teqpcpp PRIVATE autodiff PRIVATE teqpinterface )
if (NOT UNIX)
target_compile_definitions(teqpc PRIVATE -DEXTERN_C_DLLEXPORT)
else()
target_compile_definitions(teqpc PRIVATE -DEXTERN_C)
endif()
if(MSVC)
add_custom_command(
TARGET teqpc
POST_BUILD
COMMAND dumpbin /EXPORTS $<TARGET_FILE:teqpc> > ${CMAKE_CURRENT_BINARY_DIR}/exports.txt)
endif()
# And a little testing harness for extern "C" library
add_executable(teqpc_demo "${CMAKE_CURRENT_SOURCE_DIR}/interface/C/demo.cpp")
target_link_libraries(teqpc_demo PRIVATE teqpc PRIVATE teqpinterface)
# And a little benchmarking harness for extern "C" library
add_executable(teqpc_bench "${CMAKE_CURRENT_SOURCE_DIR}/interface/C/teqpc_bench.cpp")
target_link_libraries(teqpc_bench PRIVATE Catch2WithMain PRIVATE teqpc)
if(UNIX)
target_link_libraries (teqpc_bench PRIVATE ${CMAKE_DL_LIBS})
endif()
endif()
### TARGETS from src folder
if (TEQP_SNIPPETS)
add_definitions(-DUSE_TEQP_HMX)
# Collect all the snippets
file(GLOB_RECURSE snippets "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
message(STATUS "snippets found = ${snippets}")
foreach (snippet ${snippets})
get_filename_component(snippet_name ${snippet} NAME)
get_filename_component(snippet_exe ${snippet} NAME_WE)
message(STATUS "snippet_name = ${snippet_name}")
add_executable(${snippet_exe} ${snippet})
if (MSVC)
target_sources(${snippet_exe} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen/debug/msvc/eigen.natvis")
endif()
target_link_libraries(${snippet_exe} PRIVATE teqpcpp PRIVATE autodiff PRIVATE teqpinterface PRIVATE Catch2WithMain )
if(UNIX)
target_link_libraries (${snippet_exe} PRIVATE ${CMAKE_DL_LIBS})
endif()
target_compile_definitions(${snippet_exe} PRIVATE -DTEQP_MULTICOMPLEX_ENABLED)
target_compile_definitions(${snippet_exe} PRIVATE -DTEQP_COMPLEXSTEP_ENABLED)
target_compile_definitions(${snippet_exe} PRIVATE -DTEQP_MULTIPRECISION_ENABLED)
target_compile_definitions(${snippet_exe} PRIVATE -DUSE_AUTODIFF)
if(TEQP_JAVASCRIPT_HTML)
# All the generated executables will compile to HTML with no prefix and file extension of HTML
set_target_properties(${snippet_exe} PROPERTIES PREFIX "" SUFFIX .html)
endif()
endforeach()
else()
message(STATUS "No snippets will be compiled, pass -DTEQP_SNIPPETS=ON to build them")
endif()
if (TEQP_EMBIND)
# If you want a monolithic file with no async memory loading, define EMSCRIPTEN_NO_MEMORY_INIT_FILE
if(EMSCRIPTEN_NO_MEMORY_INIT_FILE)
set(EMSCRIPTEN_INIT_FLAG "--memory-init-file 0")
else()
set(EMSCRIPTEN_INIT_FLAG "--memory-init-file 1")
endif()
add_definitions( -sDISABLE_EXCEPTION_CATCHING=0)
set(CMAKE_EXE_LINKER_FLAGS "--bind ${EMSCRIPTEN_INIT_FLAG} -sASSERTIONS=1 -sDISABLE_EXCEPTION_CATCHING=0")
set(CMAKE_BUILD_TYPE Release)
set(APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/interface/js/emscripten_interface.cxx")
add_executable(teqpbind ${APP_SOURCES})
target_link_libraries(teqpbind PRIVATE autodiff PRIVATE teqpinterface)
SET_TARGET_PROPERTIES(teqpbind PROPERTIES PREFIX "" SUFFIX .js)
endif()
if (TEQP_EMBIND_MODULARIZE_ES6)
# If you want a monolithic file with no async memory loading, define EMSCRIPTEN_NO_MEMORY_INIT_FILE
if(EMSCRIPTEN_NO_MEMORY_INIT_FILE)
set(EMSCRIPTEN_INIT_FLAG "--memory-init-file 0")
else()
set(EMSCRIPTEN_INIT_FLAG "--memory-init-file 1")
endif()
add_definitions( -sDISABLE_EXCEPTION_CATCHING=0)
set(CMAKE_EXE_LINKER_FLAGS "--bind ${EMSCRIPTEN_INIT_FLAG} -sASSERTIONS=1 -sDISABLE_EXCEPTION_CATCHING=0 -s EXPORTED_RUNTIME_METHODS=['isotherm'] -s EXPORT_ES6=1 -s MODULARIZE=1 -s USE_ES6_IMPORT_META=0")
set(CMAKE_BUILD_TYPE Release)
set(APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/interface/js/emscripten_interface.cxx")
add_executable(teqpbind ${APP_SOURCES})
target_link_libraries(teqpbind PRIVATE autodiff PRIVATE teqpinterface)
SET_TARGET_PROPERTIES(teqpbind PROPERTIES PREFIX "" SUFFIX .js)
endif()
if (TEQP_COVERAGE)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_BINARY_DIR}" CACHE INTERNAL "This path")
# See also http://stackoverflow.com/a/16536401 (a detailed guide on using gcov with cmake)
include(CodeCoverage)
append_coverage_compiler_flags()
setup_target_for_coverage_gcovr_html(
NAME teqp_coverage
EXECUTABLE catch_tests
BASE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/"
)
endif()