-
Notifications
You must be signed in to change notification settings - Fork 12
/
CMakeLists.txt
296 lines (243 loc) · 11.9 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
set(CMAKE_OSX_ARCHITECTURES x86_64;arm64 CACHE INTERNAL "archs for osx")
cmake_minimum_required(VERSION 3.16)
project(teqp)
enable_testing()
# Enable /bigobj for MSVC builds
if (MSVC)
add_compile_options(-bigobj)
endif()
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)
#### SETUP
set(CMAKE_CXX_STANDARD 17)
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")
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")
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")
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>)
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()
target_compile_definitions(catch_tests PRIVATE -DTEQPC_CATCH)
target_compile_definitions(catch_tests PRIVATE -DTEQP_MULTICOMPLEX_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_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()