-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
547 lines (513 loc) · 20.4 KB
/
Copy pathCMakeLists.txt
File metadata and controls
547 lines (513 loc) · 20.4 KB
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
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
cmake_minimum_required(VERSION 3.24)
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version.json VERSIONS)
string(JSON SKETCHER_VERSION GET ${VERSIONS} sketcher)
project(
schrodinger_sketcher
VERSION ${SKETCHER_VERSION}
LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
option(BUILD_SHARED_LIBS "Build using shared libraries" OFF)
option(ENABLE_TESTING "Build and enable tests" ON)
option(ENFORCE_DEPENDENCY_VERSIONS "Require versions.json enforcement" ON)
# Load dependency versions
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/external/versions.json VERSIONS)
if(${ENFORCE_DEPENDENCY_VERSIONS})
string(JSON BOOST_VERSION GET ${VERSIONS} boost)
string(JSON EIGEN_VERSION GET ${VERSIONS} eigen)
string(JSON EXPAT_VERSION GET ${VERSIONS} expat)
string(JSON FMT_VERSION GET ${VERSIONS} fmt)
string(JSON QT_VERSION GET ${VERSIONS} qt)
string(JSON RDKIT_VERSION GET ${VERSIONS} rdkit)
string(JSON SQLITE_VERSION GET ${VERSIONS} sqlite)
string(JSON ZLIB_VERSION GET ${VERSIONS} zlib)
string(JSON ZSTD_VERSION GET ${VERSIONS} zstd)
endif()
if(${BUILD_SHARED_LIBS})
set(ZSTD_LIB_NAME zstd::libzstd_shared)
set(Boost_USE_STATIC_LIBS OFF)
# RDKit needs the shared versions of maeparser and coordgen
find_package(maeparser REQUIRED)
find_package(coordgen REQUIRED)
else()
# we're building a static build
set(ZSTD_LIB_NAME zstd::libzstd_static)
set(Boost_USE_STATIC_LIBS ON)
endif()
if(CMAKE_FIND_ROOT_PATH)
# make sure we can always find the dependencies that we've built, even if
# emscripten is trying to prevent us from finding system libraries
list(APPEND CMAKE_FIND_ROOT_PATH ${CMAKE_CURRENT_BINARY_DIR})
endif()
if(EMSCRIPTEN)
set(QT_HOST_PATH ${CMAKE_CURRENT_BINARY_DIR}/external/host/qt-${QT_VERSION})
endif()
# we don't include boost::beast as a required component since GitHub builds use
# it as a non-built, headers-only library, which means that there's no
# associated config.cmake file for find_package to recognize
find_package(
Boost ${BOOST_VERSION} REQUIRED COMPONENTS filesystem iostreams json
serialization unit_test_framework)
find_package(Qt6 ${QT_VERSION} REQUIRED COMPONENTS Widgets Svg SvgWidgets Test)
# Workaround for Qt 6.5.8 AGL framework issue on modern macOS AGL (Apple
# Graphics Layer) was deprecated and removed from modern macOS SDKs This
# workaround can be removed after BLDMGR-10714
if(APPLE AND TARGET WrapOpenGL::WrapOpenGL)
get_target_property(_qt_opengl_libs WrapOpenGL::WrapOpenGL
INTERFACE_LINK_LIBRARIES)
if(_qt_opengl_libs)
list(FILTER _qt_opengl_libs EXCLUDE REGEX "AGL")
set_target_properties(
WrapOpenGL::WrapOpenGL PROPERTIES INTERFACE_LINK_LIBRARIES
"${_qt_opengl_libs}")
endif()
endif()
find_package(Eigen3 ${EIGEN_VERSION} REQUIRED)
find_package(EXPAT ${EXPAT_VERSION} REQUIRED)
find_package(RDKit ${RDKIT_VERSION} REQUIRED)
find_package(fmt ${FMT_VERSION} REQUIRED)
find_package(SQLite3 ${SQLITE_VERSION} REQUIRED)
find_package(ZLIB ${ZLIB_VERSION} REQUIRED)
find_package(zstd ${ZSTD_VERSION} REQUIRED)
# The EXPAT::EXPAT target used in RDKit only exists if FindEXPAT.cmake was used
# to find Expat. If CMAKE_FIND_PACKAGE_PREFER_CONFIG was passed and we instead
# used Expat's config file, then the target name is actually lowercase
# expat::expat. If that's happened, create an alias to satisfy rdkit's
# dependencies.
if(NOT TARGET EXPAT::EXPAT)
add_library(EXPAT::EXPAT ALIAS expat::expat)
endif()
# Common library/executable configuration
function(setup_target TARGET)
# Visibility settings for dynamic vs static builds
if(${BUILD_SHARED_LIBS})
set(VISIBILITY "default")
else()
set(VISIBILITY "hidden")
endif()
# Compilation optimization, warnings, and error handling
if(MSVC)
target_compile_options(${TARGET} PRIVATE -WX -EHsc)
if(${BUILD_SHARED_LIBS})
target_compile_definitions(${TARGET} PRIVATE RDKIT_DYN_LINK)
endif()
elseif(WIN32)
target_compile_options(
${TARGET} PRIVATE -Wall -Werror -Wswitch -O2 -fvisibility=${VISIBILITY}
-Wno-restrict)
else()
target_compile_options(${TARGET} PRIVATE -Wall -Werror -Wswitch -O2
-fvisibility=${VISIBILITY})
endif()
# Allow RDKit includes to be prefixed, and add all relevant and necessary
# sketcher-specific include directories
target_include_directories(
${TARGET}
PRIVATE ${RDKit_INCLUDE_DIRS} ${RDKit_INCLUDE_DIRS}/..
${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include
${PROJECT_SOURCE_DIR}/src)
target_compile_definitions(${TARGET} PRIVATE RDK_BUILD_MAEPARSER_SUPPORT)
if(NOT ${BUILD_SHARED_LIBS})
# force use of static libraries
target_compile_definitions(
${TARGET} PRIVATE RDKIT_EXTENSIONS_STATIC_DEFINE SKETCHER_STATIC_DEFINE
BOOST_BEAST_HEADER_ONLY)
if(WIN32)
if(MSVC)
# use the static version of the runtime library instead of the default
# shared version
set_property(
TARGET ${TARGET} PROPERTY MSVC_RUNTIME_LIBRARY
"MultiThreaded$<$<CONFIG:Debug>:Debug>")
else()
target_link_options(${TARGET} PUBLIC -static)
endif()
endif()
endif()
if(EMSCRIPTEN)
# We optimize for space in wasm builds because otherwise binaryen (run
# because of ASYNCIFY) runs out of memory
target_link_options(${TARGET} PRIVATE -sGL_ENABLE_GET_PROC_ADDRESS
-fexceptions -sDISABLE_EXCEPTION_CATCHING=0 -Os)
target_compile_options(${TARGET} PRIVATE -fexceptions
-sDISABLE_EXCEPTION_CATCHING=0 -Os)
endif()
endfunction()
# Add dependencies to Qt resource collection files (*.qrc). This ensures that
# changes to an icon, font, etc. will trigger a rebuild of the relevant .qrc
# file.
function(add_qrc_dependencies QRC_FILE)
get_filename_component(QRC_DIR ${QRC_FILE} DIRECTORY)
file(READ ${QRC_FILE} QRC_CONTENTS)
string(REGEX MATCHALL "<file[^>]*>[^<]+</file>" QRC_FILE_ENTRIES
${QRC_CONTENTS})
set(QRC_DEPENDENCIES)
foreach(QRC_FILE_ENTRY ${QRC_FILE_ENTRIES})
string(REGEX REPLACE "^<file[^>]*>" "" QRC_RESOURCE ${QRC_FILE_ENTRY})
string(REGEX REPLACE "</file>$" "" QRC_RESOURCE ${QRC_RESOURCE})
string(STRIP ${QRC_RESOURCE} QRC_RESOURCE)
cmake_path(
ABSOLUTE_PATH
QRC_RESOURCE
BASE_DIRECTORY
${QRC_DIR}
NORMALIZE
OUTPUT_VARIABLE
QRC_RESOURCE_PATH)
list(APPEND QRC_DEPENDENCIES ${QRC_RESOURCE_PATH})
endforeach()
set_property(
SOURCE ${QRC_FILE}
APPEND
PROPERTY OBJECT_DEPENDS "${QRC_DEPENDENCIES}")
endfunction()
# Configure the SKETCHER_LIB and RDKIT_EXTENSIONS_LIB libraries
function(build_schrodinger_library TARGET)
set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include/schrodinger/${TARGET})
set(SRC_DIR ${PROJECT_SOURCE_DIR}/src/schrodinger/${TARGET})
# Collect all headers and source; note we collect public headers so that Qt
# can build .moc files.
file(
GLOB_RECURSE
SOURCE_LIST
CONFIGURE_DEPENDS
${INCLUDE_DIR}/*.h
${SRC_DIR}/*.h
${SRC_DIR}/*.cpp
${SRC_DIR}/*.ui)
# Collect all resources
file(GLOB_RECURSE SOURCE_LIST_QRC CONFIGURE_DEPENDS ${SRC_DIR}/*.qrc)
list(APPEND SOURCE_LIST ${SOURCE_LIST_QRC})
foreach(QRC_FILE ${SOURCE_LIST_QRC})
add_qrc_dependencies(${QRC_FILE})
endforeach()
add_library(${TARGET} ${SOURCE_LIST})
add_library(schrodinger::${TARGET} ALIAS ${TARGET})
set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME schrodinger_${TARGET})
setup_target(${TARGET})
# Auto-generate compile definitions
string(TOUPPER ${TARGET} TARGET_UPPER)
target_compile_definitions(${TARGET} PRIVATE IN_${TARGET_UPPER}_DLL)
endfunction()
# Add direct dependencies from C++ sources to the .ui files whose generated
# headers they include. Without these edges, Ninja may decide that a source is
# up-to-date before AUTOUIC regenerates its header, requiring a second build
# before a ui change is incorporated.
function(add_ui_dependencies TARGET UI_DIR)
get_target_property(TARGET_SOURCES ${TARGET} SOURCES)
foreach(SOURCE_FILE ${TARGET_SOURCES})
if(SOURCE_FILE MATCHES "\\.(cc|cpp|cxx)$")
file(STRINGS ${SOURCE_FILE} UI_INCLUDES
REGEX "#[ \t]*include[ \t]*[<\"][^>\"]*ui_[A-Za-z0-9_]+\\.h[>\"]")
foreach(UI_INCLUDE ${UI_INCLUDES})
string(REGEX REPLACE ".*ui_([A-Za-z0-9_]+)\\.h.*" "\\1" UI_BASENAME
${UI_INCLUDE})
set(UI_FILE ${UI_DIR}/${UI_BASENAME}.ui)
if(EXISTS ${UI_FILE})
set_property(
SOURCE ${SOURCE_FILE}
APPEND
PROPERTY OBJECT_DEPENDS ${UI_FILE})
endif()
endforeach()
endif()
endforeach()
endfunction()
# Enable Qt's MOC and UIC features
function(enable_qt_moc TARGET)
set(UI_DIR ${PROJECT_SOURCE_DIR}/src/schrodinger/sketcher/ui)
add_ui_dependencies(${TARGET} ${UI_DIR})
set_target_properties(
${TARGET}
PROPERTIES AUTOMOC ON
AUTOUIC ON
AUTOUIC_SEARCH_PATHS ${UI_DIR}
AUTORCC ON)
endfunction()
# Add a dependency on the generated header
function(add_generated_header_dependency TARGET)
# The header is generated with a Python script, so we need to find the Python
# interpreter
find_package(
Python
COMPONENTS Interpreter
REQUIRED)
set(SRC_DIR ${PROJECT_SOURCE_DIR}/src/schrodinger/rdkit_extensions)
set(HDR_PATH
${PROJECT_BINARY_DIR}/include/schrodinger/rdkit_extensions/monomer_db_default_monomers.h
)
add_custom_command(
OUTPUT ${HDR_PATH}
COMMAND ${Python_EXECUTABLE} ${SRC_DIR}/generate_default_monomers_header.py
${SRC_DIR}/default_monomer_definitions.json ${HDR_PATH}
DEPENDS ${SRC_DIR}/default_monomer_definitions.json
${SRC_DIR}/generate_default_monomers_header.py
COMMENT "Generating monomer_db_default_monomers.h")
add_custom_target(generated_header DEPENDS ${HDR_PATH})
add_dependencies(${TARGET} generated_header)
endfunction()
# schrodinger::rdkit_extensions library
set(RDKIT_EXTENSIONS_TARGET rdkit_extensions)
build_schrodinger_library(${RDKIT_EXTENSIONS_TARGET})
add_generated_header_dependency(${RDKIT_EXTENSIONS_TARGET})
target_link_libraries(
${RDKIT_EXTENSIONS_TARGET}
PRIVATE Boost::filesystem
Boost::iostreams
Boost::json
Boost::serialization
fmt::fmt
RDKit::ChemReactions
RDKit::DetermineBonds
RDKit::DistGeomHelpers
RDKit::MarvinParser
RDKit::RDInchiLib
SQLite::SQLite3
ZLIB::ZLIB
${ZSTD_LIB_NAME})
# schrodinger::sketcher library
set(SKETCHER_TARGET sketcher)
build_schrodinger_library(${SKETCHER_TARGET})
target_link_libraries(
${SKETCHER_TARGET}
PRIVATE Boost::boost
Boost::filesystem
fmt::fmt
Qt6::Svg
Qt6::SvgWidgets
Qt6::Widgets
RDKit::CIPLabeler
RDKit::ChemReactions
${RDKIT_EXTENSIONS_TARGET})
# Configure and include version information for the sketcher
configure_file(${PROJECT_SOURCE_DIR}/include/schrodinger/sketcher/version.h.in
${PROJECT_BINARY_DIR}/include/schrodinger/sketcher/version.h)
enable_qt_moc(${SKETCHER_TARGET})
# Standalone executable
set(APP_TARGET schrodinger_sketcher)
file(GLOB APP_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/src/app/*.cpp)
if(WIN32)
list(APPEND APP_SOURCES src/app/sketcher.rc)
elseif(APPLE)
set(SKETCHER_ICNS ${CMAKE_CURRENT_SOURCE_DIR}/src/app/sketcher.icns)
list(APPEND APP_SOURCES ${SKETCHER_ICNS})
set_source_files_properties(${SKETCHER_ICNS}
PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
endif()
add_executable(${APP_TARGET} ${APP_SOURCES})
if(APPLE)
set_target_properties(
${APP_TARGET}
PROPERTIES MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_BUNDLE_NAME "Sketcher"
MACOSX_BUNDLE_GUI_IDENTIFIER "com.schrodinger.sketcher"
MACOSX_BUNDLE_ICON_FILE "sketcher.icns"
MACOSX_BUNDLE_BUNDLE_VERSION "${SKETCHER_VERSION}"
MACOSX_BUNDLE_SHORT_VERSION_STRING "${SKETCHER_VERSION}"
BUNDLE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/sketcher_app)
endif()
setup_target(${APP_TARGET})
set_target_properties(
${APP_TARGET}
PROPERTIES OUTPUT_NAME "Sketcher" RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/sketcher_app)
if(EMSCRIPTEN)
set(EXTRA_SKETCHER_APP_LINK_FLAGS
-sEXPORT_NAME=schrodinger_sketcher_entry
-sMODULARIZE=1
-sEXPORTED_RUNTIME_METHODS=[callMain,FS,JSEvents,specialHTMLTargets,stringToUTF8,stringToUTF16,UTF16ToString,lengthBytesUTF8,getExceptionMessage]
-sASYNCIFY
-lembind
-fexceptions
-sDISABLE_EXCEPTION_CATCHING=0
-sEXPORT_EXCEPTION_HANDLING_HELPERS)
endif()
target_link_libraries(
${APP_TARGET}
PRIVATE Boost::boost Boost::filesystem Qt6::Widgets
${RDKIT_EXTENSIONS_TARGET} ${SKETCHER_TARGET}
${EXTRA_SKETCHER_APP_LINK_FLAGS})
# Utility: smiles_to_helm
set(SMILES_TO_HELM_TARGET smiles_to_helm)
add_executable(${SMILES_TO_HELM_TARGET} src/utils/smiles_to_helm.cpp)
setup_target(${SMILES_TO_HELM_TARGET})
set_target_properties(
${SMILES_TO_HELM_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/sketcher_app)
target_link_libraries(
${SMILES_TO_HELM_TARGET}
PRIVATE Boost::boost Boost::filesystem Qt6::Core RDKit::SmilesParse
${RDKIT_EXTENSIONS_TARGET})
# Crash handler: configure Boost.Stacktrace backend per platform
if(NOT EMSCRIPTEN)
target_link_libraries(${APP_TARGET} PRIVATE fmt::fmt)
if(MSVC)
target_compile_definitions(${APP_TARGET}
PRIVATE BOOST_STACKTRACE_USE_WINDBG)
target_link_libraries(${APP_TARGET} PRIVATE dbghelp)
else()
target_compile_definitions(${APP_TARGET}
PRIVATE BOOST_STACKTRACE_USE_ADDR2LINE)
target_link_libraries(${APP_TARGET} PRIVATE dl)
if(APPLE)
target_compile_definitions(${APP_TARGET} PRIVATE _GNU_SOURCE)
endif()
endif()
endif()
# Copy over the necessary wasm files into the application directory
if(EMSCRIPTEN)
add_custom_target(
update_wasm_files ALL
DEPENDS ${APP_TARGET}
COMMAND
${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/external/qt-${QT_VERSION}/plugins/platforms/qtloader.js
${CMAKE_BINARY_DIR}/sketcher_app/qtloader.js
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/wasm/public/
${CMAKE_BINARY_DIR}/sketcher_app/
COMMAND
${CMAKE_COMMAND} -E copy_if_different
${CMAKE_SOURCE_DIR}/src/schrodinger/sketcher/icons/sketcher-logo.svg
${CMAKE_BINARY_DIR}/sketcher_app/sketcher-logo.svg
COMMAND
python3 ${CMAKE_SOURCE_DIR}/wasm/update_cache_bust.py --wasm-dir
${CMAKE_BINARY_DIR}/sketcher_app --app-target
$<TARGET_FILE_BASE_NAME:${APP_TARGET}>)
endif()
# Tests
if(ENABLE_TESTING)
enable_testing()
# Copy Python test directory to build directory so pytest can discover them
file(GLOB_RECURSE PYTHON_TEST_FILES CONFIGURE_DEPENDS
${PROJECT_SOURCE_DIR}/test/python/*)
foreach(PYTHON_TEST ${PYTHON_TEST_FILES})
cmake_path(RELATIVE_PATH PYTHON_TEST BASE_DIRECTORY
${PROJECT_SOURCE_DIR}/test OUTPUT_VARIABLE REL_TEST_PATH)
configure_file(${PYTHON_TEST} ${CMAKE_BINARY_DIR}/test/${REL_TEST_PATH}
COPYONLY)
endforeach()
set(SKETCHER_TEST ${PROJECT_SOURCE_DIR}/test/schrodinger)
file(GLOB_RECURSE TEST_SOURCE_LIST CONFIGURE_DEPENDS ${SKETCHER_TEST}/*.cpp)
set(TEST_DEPENDENCIES
Boost::filesystem
Boost::unit_test_framework
Eigen3::Eigen
fmt::fmt
Qt6::SvgWidgets
Qt6::Test
Qt6::Widgets
RDKit::ChemReactions
RDKit::FileParsers
${RDKIT_EXTENSIONS_TARGET}
${SKETCHER_TARGET})
file(GLOB GLOBAL_SUPPRESSIONS "test/valgrind_*suppressions*")
set(SUPPRESSION_FILE "test_valgrind.suppressions")
# Each memtest gets its own Xvfb display via xvfb-run -a (auto display
# selection) so parallel ctest runs don't share a single X server.
set(MEMTEST_COMMAND
"xvfb-run -a valgrind --tool=memcheck --time-stamp=yes --num-callers=20 \
--gen-suppressions=all --leak-check=full \
--keep-debuginfo=no --error-exitcode=29")
separate_arguments(MEMTEST_COMMAND)
# List of tests that require Qt MOC/UIC features (Q_OBJECT or UI files)
set(TESTS_REQUIRING_QT_MOC
test_abstract_undoable_model
test_atom_query_popup
test_bond_order_popup
test_bond_query_popup
test_nucleic_acid_symbol_popup
test_bracket_subgroup_dialog
test_draw_tools_widget
test_edit_atom_properties
test_enumeration_tool_widget
test_file_export_dialog
test_paste_in_text_dialog
test_periodic_table_widget
test_ring_tool_widget
test_select_options_widget
test_set_atom_widget
test_sketcher_top_bar
test_sketcher_widget
test_stereo_bond_popup)
foreach(TEST_SOURCE ${TEST_SOURCE_LIST})
cmake_path(GET TEST_SOURCE STEM TEST_STEM)
cmake_path(RELATIVE_PATH TEST_SOURCE OUTPUT_VARIABLE TEST_PATH)
cmake_path(GET TEST_PATH PARENT_PATH PREFIX_PATH)
# Create unique target name by replacing path separators
string(REPLACE "/" "-" TEST_PREFIX "${PREFIX_PATH}")
set(TEST_TARGET "${TEST_PREFIX}-${TEST_STEM}")
add_executable(${TEST_TARGET} ${TEST_SOURCE})
setup_target(${TEST_TARGET})
target_include_directories(${TEST_TARGET}
PRIVATE ${PROJECT_SOURCE_DIR}/test)
target_link_libraries(${TEST_TARGET} PRIVATE ${TEST_DEPENDENCIES})
if(NOT QT6_IS_SHARED_LIBS_BUILD)
# we use the offscreen platform to make sure that the tests don't pop up
# windows on the screen while they're running
qt_import_plugins(${TEST_TARGET} INCLUDE Qt6::QOffscreenIntegrationPlugin)
endif()
if(MSVC)
# ignore discarded [[nodiscard]] values for the tests
target_compile_options(${TEST_TARGET} PRIVATE -wd4834)
endif()
if(TEST_STEM IN_LIST TESTS_REQUIRING_QT_MOC)
enable_qt_moc(${TEST_TARGET})
endif()
if(EMSCRIPTEN)
set(TEST_COMMAND node $<TARGET_FILE:${TEST_TARGET}>)
else()
set(TEST_COMMAND ${TEST_TARGET})
endif()
set_target_properties(
${TEST_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PREFIX_PATH}
OUTPUT_NAME ${TEST_STEM})
# Create memtest target and command
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
# create the valgrind test
set(CURRENT_MEMTEST_COMMAND ${MEMTEST_COMMAND})
if(EXISTS "${PREFIX_PATH}/${SUPPRESSION_FILE}")
list(APPEND CURRENT_MEMTEST_COMMAND
"--suppressions=${PREFIX_PATH}/${SUPPRESSION_FILE}")
endif()
foreach(CURRENT_GLOBAL_SUPPRESSION ${GLOBAL_SUPPRESSIONS})
list(APPEND CURRENT_MEMTEST_COMMAND
"--suppressions=${CURRENT_GLOBAL_SUPPRESSION}")
endforeach()
list(APPEND CURRENT_MEMTEST_COMMAND "$<TARGET_FILE:${TEST_TARGET}>")
set(TEST_TARGET "memtest_${TEST_TARGET}")
set(TEST_COMMAND "${CURRENT_MEMTEST_COMMAND}")
endif()
# Add the test to CTest
add_test(NAME ${TEST_TARGET} COMMAND ${TEST_COMMAND})
set_tests_properties(
${TEST_TARGET} PROPERTIES ENVIRONMENT
"SKETCHER_SOURCE_DIR=${CMAKE_SOURCE_DIR}")
# Add label for memtest targets
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set_property(TEST ${TEST_TARGET} PROPERTY LABELS memtest)
endif()
endforeach()
endif()
# Install public headers, generated version header, libraries, and executable
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/schrodinger
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES ${PROJECT_BINARY_DIR}/include/schrodinger/sketcher/version.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/schrodinger/sketcher)
if(APPLE)
# Install the full .app bundle
install(
DIRECTORY $<TARGET_BUNDLE_DIR:${APP_TARGET}>
DESTINATION ${CMAKE_INSTALL_BINDIR}
USE_SOURCE_PERMISSIONS)
else()
# Install the application file preserving the build-time rpath
install(PROGRAMS $<TARGET_FILE:${APP_TARGET}>
$<TARGET_FILE:${SMILES_TO_HELM_TARGET}>
DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
install(
FILES $<TARGET_FILE:${SKETCHER_TARGET}>
$<TARGET_FILE:${RDKIT_EXTENSIONS_TARGET}>
$<TARGET_LINKER_FILE:${SKETCHER_TARGET}>
$<TARGET_LINKER_FILE:${RDKIT_EXTENSIONS_TARGET}>
DESTINATION ${CMAKE_INSTALL_LIBDIR})