-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
640 lines (592 loc) · 26.2 KB
/
Copy pathCMakeLists.txt
File metadata and controls
640 lines (592 loc) · 26.2 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
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
#
# Specify minimum CMake version and project name
#
cmake_minimum_required (VERSION 3.21)
set(DYNLEX_VERSION_FILE "${CMAKE_SOURCE_DIR}/metadata/VERSION")
if(NOT EXISTS "${DYNLEX_VERSION_FILE}")
message(FATAL_ERROR "Missing VERSION file at ${DYNLEX_VERSION_FILE}")
endif()
file(READ "${DYNLEX_VERSION_FILE}" DYNLEX_VERSION_RAW)
string(STRIP "${DYNLEX_VERSION_RAW}" DYNLEX_VERSION)
if(NOT DYNLEX_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+$")
message(FATAL_ERROR "Invalid version in VERSION file: '${DYNLEX_VERSION}'")
endif()
project (dynlex VERSION ${DYNLEX_VERSION})
include(GNUInstallDirs)
if(WIN32)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set(DYNLEX_WINDOWS_TARGET_VERSION 0x0A00)
add_compile_definitions(
_WIN32_WINNT=${DYNLEX_WINDOWS_TARGET_VERSION}
WINVER=${DYNLEX_WINDOWS_TARGET_VERSION}
)
endif()
# Homebrew Clang selects the macOS SDK through its driver configuration, but
# CMake does not always include that configured sysroot in its detected implicit
# header directories. LLVM's imported targets can then re-export SDK headers
# used by system libraries as explicit -isystem paths.
# Mark the active SDK headers as implicit so CMake omits them from every target's
# command line and preserves libc++'s wrapper-header ordering.
if(APPLE)
execute_process(
COMMAND xcrun --sdk macosx --show-sdk-path
OUTPUT_VARIABLE DYNLEX_MACOS_SDK
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE DYNLEX_MACOS_SDK_RESULT
ERROR_QUIET
)
set(DYNLEX_MACOS_SDK_SYSTEM_INCLUDE "${DYNLEX_MACOS_SDK}/usr/include")
if(NOT DYNLEX_MACOS_SDK_RESULT EQUAL 0 OR NOT IS_DIRECTORY "${DYNLEX_MACOS_SDK_SYSTEM_INCLUDE}")
message(FATAL_ERROR "Unable to locate the active macOS SDK headers through xcrun")
endif()
list(APPEND CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "${DYNLEX_MACOS_SDK_SYSTEM_INCLUDE}")
list(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "${DYNLEX_MACOS_SDK_SYSTEM_INCLUDE}")
list(REMOVE_DUPLICATES CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES)
list(REMOVE_DUPLICATES CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES)
endif()
#
# Enable ccache if available
#
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
message(STATUS "Using ccache: ${CCACHE_PROGRAM}")
endif()
#
# Generate compile_commands.json for clang-tidy
#
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# nlohmann_json is header-only, so Emscripten must use the host package. Keep
# LLVM and every compiled dependency restricted to the target sysroot.
if(EMSCRIPTEN)
find_package(nlohmann_json CONFIG REQUIRED NO_CMAKE_FIND_ROOT_PATH)
else()
find_package(nlohmann_json CONFIG REQUIRED)
endif()
if(TARGET nlohmann_json::nlohmann_json)
set(DYNLEX_NLOHMANN_TARGET nlohmann_json::nlohmann_json)
get_target_property(DYNLEX_NLOHMANN_ALIASED_TARGET nlohmann_json::nlohmann_json ALIASED_TARGET)
if(DYNLEX_NLOHMANN_ALIASED_TARGET)
set(DYNLEX_NLOHMANN_TARGET "${DYNLEX_NLOHMANN_ALIASED_TARGET}")
endif()
get_target_property(DYNLEX_NLOHMANN_INCLUDE_DIRS ${DYNLEX_NLOHMANN_TARGET} INTERFACE_INCLUDE_DIRECTORIES)
if(DYNLEX_NLOHMANN_INCLUDE_DIRS)
if(EMSCRIPTEN)
set(DYNLEX_NLOHMANN_STAGING_DIR "${CMAKE_BINARY_DIR}/dependencies/include")
set(DYNLEX_NLOHMANN_SOURCE_DIR "")
foreach(DYNLEX_NLOHMANN_INCLUDE_DIR IN LISTS DYNLEX_NLOHMANN_INCLUDE_DIRS)
if(EXISTS "${DYNLEX_NLOHMANN_INCLUDE_DIR}/nlohmann/json.hpp")
set(DYNLEX_NLOHMANN_SOURCE_DIR "${DYNLEX_NLOHMANN_INCLUDE_DIR}/nlohmann")
break()
endif()
endforeach()
if(NOT DYNLEX_NLOHMANN_SOURCE_DIR)
message(FATAL_ERROR "nlohmann_json does not provide its required nlohmann/json.hpp header")
endif()
file(REMOVE_RECURSE "${DYNLEX_NLOHMANN_STAGING_DIR}/nlohmann")
file(COPY "${DYNLEX_NLOHMANN_SOURCE_DIR}" DESTINATION "${DYNLEX_NLOHMANN_STAGING_DIR}")
set(DYNLEX_NLOHMANN_INCLUDE_DIRS "${DYNLEX_NLOHMANN_STAGING_DIR}")
set_target_properties(${DYNLEX_NLOHMANN_TARGET} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${DYNLEX_NLOHMANN_INCLUDE_DIRS}"
)
endif()
set_target_properties(${DYNLEX_NLOHMANN_TARGET} PROPERTIES
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${DYNLEX_NLOHMANN_INCLUDE_DIRS}"
)
endif()
endif()
set(DYNLEX_LLVM_METADATA_FILE "${CMAKE_SOURCE_DIR}/metadata/LLVM_TOOLCHAIN")
if(NOT EXISTS "${DYNLEX_LLVM_METADATA_FILE}")
message(FATAL_ERROR "Missing LLVM toolchain metadata at ${DYNLEX_LLVM_METADATA_FILE}")
endif()
file(STRINGS "${DYNLEX_LLVM_METADATA_FILE}" DYNLEX_LLVM_METADATA)
foreach(DYNLEX_LLVM_METADATA_LINE IN LISTS DYNLEX_LLVM_METADATA)
if(NOT DYNLEX_LLVM_METADATA_LINE MATCHES "^([a-z]+) (.+)$")
message(FATAL_ERROR "Invalid LLVM toolchain metadata: ${DYNLEX_LLVM_METADATA_LINE}")
endif()
string(TOUPPER "${CMAKE_MATCH_1}" DYNLEX_LLVM_METADATA_KEY)
set("DYNLEX_LLVM_${DYNLEX_LLVM_METADATA_KEY}" "${CMAKE_MATCH_2}")
endforeach()
foreach(DYNLEX_LLVM_REQUIRED_FIELD IN ITEMS REPOSITORY REVISION MAJOR BOOTSTRAP SCHEMA)
if(NOT DEFINED "DYNLEX_LLVM_${DYNLEX_LLVM_REQUIRED_FIELD}")
message(FATAL_ERROR "LLVM toolchain metadata is missing ${DYNLEX_LLVM_REQUIRED_FIELD}")
endif()
endforeach()
set(DYNLEX_REQUIRED_LLVM_VERSION "${DYNLEX_LLVM_MAJOR}")
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
if(NOT LLVM_PACKAGE_VERSION VERSION_EQUAL "${DYNLEX_REQUIRED_LLVM_VERSION}.0.0git")
message(FATAL_ERROR "DynLex requires the pinned LLVM ${DYNLEX_REQUIRED_LLVM_VERSION} development toolchain")
endif()
get_filename_component(DYNLEX_LLVM_INSTALL_LIB_DIR "${LLVM_DIR}/../.." ABSOLUTE)
get_filename_component(DYNLEX_LLVM_INSTALL_DIR "${DYNLEX_LLVM_INSTALL_LIB_DIR}/.." ABSOLUTE)
set(DYNLEX_LLVM_TOOLCHAIN_MARKER "${DYNLEX_LLVM_INSTALL_DIR}/.dynlex-llvm-toolchain")
if(NOT EXISTS "${DYNLEX_LLVM_TOOLCHAIN_MARKER}")
message(FATAL_ERROR "LLVM toolchain is missing its DynLex revision marker; run scripts/build_llvm.sh")
endif()
file(READ "${DYNLEX_LLVM_TOOLCHAIN_MARKER}" DYNLEX_LLVM_TOOLCHAIN_ID)
string(STRIP "${DYNLEX_LLVM_TOOLCHAIN_ID}" DYNLEX_LLVM_TOOLCHAIN_ID)
if(EMSCRIPTEN)
set(DYNLEX_LLVM_REQUIRED_PROFILE web)
else()
set(DYNLEX_LLVM_REQUIRED_PROFILE native)
endif()
set(DYNLEX_EXPECTED_LLVM_TOOLCHAIN_ID
"${DYNLEX_LLVM_REVISION}:${DYNLEX_LLVM_SCHEMA}:${DYNLEX_LLVM_REQUIRED_PROFILE}"
)
if(WIN32 AND DYNLEX_LLVM_REQUIRED_PROFILE STREQUAL "native")
string(APPEND DYNLEX_EXPECTED_LLVM_TOOLCHAIN_ID ":static-msvc-crt")
endif()
if(NOT DYNLEX_LLVM_TOOLCHAIN_ID STREQUAL DYNLEX_EXPECTED_LLVM_TOOLCHAIN_ID)
message(FATAL_ERROR "LLVM toolchain does not match the pinned DynLex ${DYNLEX_LLVM_REQUIRED_PROFILE} profile")
endif()
set(DYNLEX_LLVM_VCS_HEADER "${DYNLEX_LLVM_INSTALL_DIR}/include/llvm/Support/VCSRevision.h")
if(NOT EXISTS "${DYNLEX_LLVM_VCS_HEADER}")
message(FATAL_ERROR "LLVM toolchain is missing its embedded source revision")
endif()
file(READ "${DYNLEX_LLVM_VCS_HEADER}" DYNLEX_LLVM_VCS_ID)
set(DYNLEX_EXPECTED_LLVM_VCS_ID
"#define LLVM_REVISION R\"(${DYNLEX_LLVM_REVISION})\"\n#define LLVM_REPOSITORY R\"(${DYNLEX_LLVM_REPOSITORY})\"\n"
)
if(NOT DYNLEX_LLVM_VCS_ID STREQUAL DYNLEX_EXPECTED_LLVM_VCS_ID)
message(FATAL_ERROR "LLVM toolchain was not built from the pinned DynLex fork")
endif()
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
separate_arguments(DYNLEX_LLVM_COMPILE_OPTIONS NATIVE_COMMAND "${LLVM_DEFINITIONS}")
#
# CMake setup
#
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set (CMAKE_VERBOSE_MAKEFILE 0) # 1 should be used for debugging
set (CMAKE_SUPPRESS_REGENERATION TRUE) # Suppresses ZERO_CHECK
set(CMAKE_CXX_STANDARD 23)
option(DYNLEX_WEB "Build browser compiler target (Emscripten)" OFF)
# The normal compiler is optimized but keeps complete debug information and
# assertions. This is intentionally distinct from RelWithDebInfo, whose
# platform defaults define NDEBUG.
if(MSVC)
set(CMAKE_C_FLAGS_OPTIMIZED "/O2 /Zi" CACHE STRING "Flags for optimized DynLex C builds" FORCE)
set(CMAKE_CXX_FLAGS_OPTIMIZED "/O2 /Zi" CACHE STRING "Flags for optimized DynLex C++ builds" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_OPTIMIZED "/DEBUG" CACHE STRING "Linker flags for optimized DynLex builds" FORCE)
else()
set(CMAKE_C_FLAGS_OPTIMIZED "-O2 -g" CACHE STRING "Flags for optimized DynLex C builds" FORCE)
set(CMAKE_CXX_FLAGS_OPTIMIZED "-O2 -g" CACHE STRING "Flags for optimized DynLex C++ builds" FORCE)
endif()
if(CMAKE_CONFIGURATION_TYPES)
list(APPEND CMAKE_CONFIGURATION_TYPES Optimized)
list(REMOVE_DUPLICATES CMAKE_CONFIGURATION_TYPES)
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING "Available build configurations" FORCE)
endif()
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Werror")
if(NOT WIN32)
set(GLAD_LIBRARIES dl)
endif()
endif()
#
# GLFW options
#
option (GLFW_INSTALL OFF)
option (GLFW_BUILD_DOCS OFF)
option (GLFW_BUILD_EXAMPLES OFF)
option (GLFW_BUILD_TESTS OFF)
#add_subdirectory (gloom/vendor/glfw)
MACRO(HEADER_DIRECTORIES return_list)
FILE(GLOB_RECURSE new_list src/cpp/*.h)
SET(dir_list "")
FOREACH(file_path ${new_list})
GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
SET(dir_list ${dir_list} ${dir_path})
ENDFOREACH()
LIST(REMOVE_DUPLICATES dir_list)
SET(${return_list} ${dir_list})
ENDMACRO()
HEADER_DIRECTORIES(header_dir_list)
#
# Set include paths
#
include_directories (${header_dir_list})
include_directories (src/cpp)
#
# Add files
#
file (GLOB_RECURSE PROJECT_HEADERS src/cpp/*.hpp
src/cpp/*.h)
file (GLOB_RECURSE PROJECT_SOURCES src/cpp/*.cpp
src/cpp/*.cxx
src/cpp/*.cc
src/cpp/*.c)
file (GLOB_RECURSE DYNLEX_LIBRARY_SOURCES CONFIGURE_DEPENDS
"${CMAKE_SOURCE_DIR}/lib/*.dl")
file (GLOB PROJECT_CONFIGS CMakeLists.txt
README.md
.gitignore)
#
# Organizing files
#
source_group ("headers" FILES ${PROJECT_HEADERS})
source_group ("sources" FILES ${PROJECT_SOURCES})
#
# Set executable and target link libraries
#
add_definitions (-DGLFW_INCvLUDE_NONE
-DPROJECT_SOURCE_DIR=\"${PROJECT_SOURCE_DIR}\")
#target_include_directories(${PROJECT_NAME}
#PRIVATE ${Stb_INCLUDE_DIR}
#)
# The pinned DynLex LLVM distribution contains static component libraries.
function(dynlex_link_llvm target)
message(STATUS "Linking ${target} against LLVM component libraries")
target_compile_options(${target} PRIVATE ${DYNLEX_LLVM_COMPILE_OPTIONS})
llvm_config(${target} ${ARGN})
endfunction()
set(DYNLEX_LLVM_COMMON_COMPONENTS
core
support
irreader
passes
WebAssemblyCodeGen
WebAssemblyDesc
WebAssemblyInfo
WebAssemblyUtils
)
# The pinned LLVM 23 fork includes the SPIR-V and WebAssembly backends.
# Native builds additionally need the host backend.
set(DYNLEX_LLVM_NATIVE_COMPONENTS
${DYNLEX_LLVM_COMMON_COMPONENTS}
native
SPIRV
)
set(DYNLEX_NATIVE_SOURCES ${PROJECT_SOURCES})
# Web-only host bridge should only be part of the web module.
list(FILTER DYNLEX_NATIVE_SOURCES EXCLUDE REGEX "src/cpp/web/.*\\.cpp$")
if(EMSCRIPTEN AND NOT DYNLEX_WEB)
message(FATAL_ERROR "Emscripten builds must enable DYNLEX_WEB=ON.")
endif()
if(NOT EMSCRIPTEN)
if(WIN32)
foreach(DYNLEX_WINDOWS_REQUIRED_SETTING IN ITEMS
DYNLEX_WINDOWS_TOOLCHAIN_ROOT
DYNLEX_WINDOWS_TOOLCHAIN_TARGET
DYNLEX_WINDOWS_DEPENDENCY_ROOT
)
if(NOT DEFINED ${DYNLEX_WINDOWS_REQUIRED_SETTING})
message(FATAL_ERROR
"${DYNLEX_WINDOWS_REQUIRED_SETTING} is required; run scripts/install.ps1"
)
endif()
endforeach()
endif()
set(DYNLEX_RUNTIME_SOURCES
src/runtime/filesystemRuntime.c
src/runtime/hostRuntime.c
src/runtime/pathRuntime.c
src/runtime/pathUriRuntime.c
src/runtime/processRuntime.c
src/runtime/runtimeError.c
src/runtime/runtimeText.c
)
if(WIN32)
list(APPEND DYNLEX_RUNTIME_SOURCES
src/runtime/filesystemRuntimeWindows.c
src/runtime/filesystemTransactionWindows.c
src/runtime/hostRuntimeWindows.c
src/runtime/hostRuntimeWindowsPath.c
src/runtime/processRuntimeWindows.c
src/runtime/processRuntimeWindowsQuoting.c
)
else()
list(APPEND DYNLEX_RUNTIME_SOURCES
src/runtime/filesystemRuntimePosix.c
src/runtime/filesystemTransactionPosix.c
src/runtime/hostRuntimePosix.c
src/runtime/processRuntimePosix.c
src/runtime/processRuntimePosixWrite.c
)
endif()
set(DYNLEX_RUNTIME_HEADERS
src/runtime/filesystemRuntimeInternal.h
src/runtime/filesystemStatPosix.h
src/runtime/filesystemTransactionInternal.h
src/runtime/hostRuntimeInternal.h
src/runtime/hostRuntimeWindowsPath.h
src/runtime/pathRuntimeInternal.h
src/runtime/platformFeatureTest.h
src/runtime/processRuntimeInternal.h
src/runtime/processRuntimePosixWrite.h
src/runtime/processRuntimeWindowsQuoting.h
src/runtime/runtimeError.h
src/runtime/runtimeText.h
)
if(WIN32)
set(DYNLEX_WINDOWS_RUNTIME_COMPILER
"${DYNLEX_WINDOWS_TOOLCHAIN_ROOT}/bin/cc.exe"
)
set(DYNLEX_WINDOWS_RUNTIME_ARCHIVER
"${DYNLEX_WINDOWS_TOOLCHAIN_ROOT}/bin/llvm-ar.exe"
)
foreach(DYNLEX_WINDOWS_RUNTIME_TOOL IN ITEMS
DYNLEX_WINDOWS_RUNTIME_COMPILER
DYNLEX_WINDOWS_RUNTIME_ARCHIVER
)
if(NOT EXISTS "${${DYNLEX_WINDOWS_RUNTIME_TOOL}}")
message(FATAL_ERROR
"Windows runtime tool does not exist: ${${DYNLEX_WINDOWS_RUNTIME_TOOL}}"
)
endif()
endforeach()
set(DYNLEX_WINDOWS_RUNTIME_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/windows-runtime")
set(DYNLEX_WINDOWS_RUNTIME_ARCHIVE
"${DYNLEX_WINDOWS_RUNTIME_DIRECTORY}/libdynlex_runtime.a"
)
set(DYNLEX_WINDOWS_RUNTIME_OBJECTS)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DYNLEX_WINDOWS_RUNTIME_OPTIMIZATION -O0)
else()
set(DYNLEX_WINDOWS_RUNTIME_OPTIMIZATION -O2)
endif()
foreach(DYNLEX_RUNTIME_SOURCE IN LISTS DYNLEX_RUNTIME_SOURCES)
get_filename_component(
DYNLEX_RUNTIME_SOURCE_NAME
"${DYNLEX_RUNTIME_SOURCE}"
NAME_WE
)
set(DYNLEX_RUNTIME_OBJECT
"${DYNLEX_WINDOWS_RUNTIME_DIRECTORY}/${DYNLEX_RUNTIME_SOURCE_NAME}.o"
)
set(DYNLEX_RUNTIME_DEPENDENCIES
"${DYNLEX_WINDOWS_RUNTIME_DIRECTORY}/${DYNLEX_RUNTIME_SOURCE_NAME}.d"
)
add_custom_command(
OUTPUT "${DYNLEX_RUNTIME_OBJECT}"
COMMAND "${CMAKE_COMMAND}" -E make_directory
"${DYNLEX_WINDOWS_RUNTIME_DIRECTORY}"
COMMAND "${DYNLEX_WINDOWS_RUNTIME_COMPILER}"
"--target=${DYNLEX_WINDOWS_TOOLCHAIN_TARGET}"
-std=c11
"${DYNLEX_WINDOWS_RUNTIME_OPTIMIZATION}"
-g
-Wall
-Wextra
-Wpedantic
-Werror
"-D_WIN32_WINNT=${DYNLEX_WINDOWS_TARGET_VERSION}"
"-DWINVER=${DYNLEX_WINDOWS_TARGET_VERSION}"
-MMD
-MF "${DYNLEX_RUNTIME_DEPENDENCIES}"
-c "${CMAKE_SOURCE_DIR}/${DYNLEX_RUNTIME_SOURCE}"
-o "${DYNLEX_RUNTIME_OBJECT}"
DEPENDS
"${CMAKE_SOURCE_DIR}/${DYNLEX_RUNTIME_SOURCE}"
${DYNLEX_RUNTIME_HEADERS}
DEPFILE "${DYNLEX_RUNTIME_DEPENDENCIES}"
VERBATIM
)
list(APPEND DYNLEX_WINDOWS_RUNTIME_OBJECTS "${DYNLEX_RUNTIME_OBJECT}")
endforeach()
add_custom_command(
OUTPUT "${DYNLEX_WINDOWS_RUNTIME_ARCHIVE}"
COMMAND "${CMAKE_COMMAND}" -E rm -f "${DYNLEX_WINDOWS_RUNTIME_ARCHIVE}"
COMMAND "${DYNLEX_WINDOWS_RUNTIME_ARCHIVER}" rcs
"${DYNLEX_WINDOWS_RUNTIME_ARCHIVE}"
${DYNLEX_WINDOWS_RUNTIME_OBJECTS}
DEPENDS ${DYNLEX_WINDOWS_RUNTIME_OBJECTS}
VERBATIM
)
add_custom_target(
dynlex_runtime ALL
DEPENDS "${DYNLEX_WINDOWS_RUNTIME_ARCHIVE}"
)
set(DYNLEX_RUNTIME_LIBRARY_BUILD_PATH "${DYNLEX_WINDOWS_RUNTIME_ARCHIVE}")
set(DYNLEX_RUNTIME_LIBRARY_FILENAME "libdynlex_runtime.a")
else()
add_library(dynlex_runtime STATIC ${DYNLEX_RUNTIME_SOURCES})
set_target_properties(dynlex_runtime PROPERTIES
C_STANDARD 11
C_STANDARD_REQUIRED ON
POSITION_INDEPENDENT_CODE ON
)
target_compile_options(dynlex_runtime PRIVATE -Wall -Wextra -Wpedantic -Werror)
set(DYNLEX_RUNTIME_LIBRARY_BUILD_PATH "$<TARGET_FILE:dynlex_runtime>")
set(DYNLEX_RUNTIME_LIBRARY_FILENAME "$<TARGET_FILE_NAME:dynlex_runtime>")
endif()
add_executable (${PROJECT_NAME} ${DYNLEX_NATIVE_SOURCES} ${PROJECT_HEADERS}
${PROJECT_CONFIGS})
add_dependencies(${PROJECT_NAME} dynlex_runtime)
target_compile_definitions(${PROJECT_NAME} PRIVATE
DYNLEX_RUNTIME_LIBRARY_BUILD_PATH="${DYNLEX_RUNTIME_LIBRARY_BUILD_PATH}"
DYNLEX_RUNTIME_LIBRARY_FILENAME="${DYNLEX_RUNTIME_LIBRARY_FILENAME}"
DYNLEX_RUNTIME_LIBRARY_INSTALL_DIR="${CMAKE_INSTALL_LIBDIR}/dynlex"
)
if(WIN32)
file(TO_CMAKE_PATH "${DYNLEX_WINDOWS_TOOLCHAIN_ROOT}" DYNLEX_WINDOWS_TOOLCHAIN_ROOT_CMAKE)
file(TO_CMAKE_PATH "${DYNLEX_WINDOWS_DEPENDENCY_ROOT}" DYNLEX_WINDOWS_DEPENDENCY_ROOT_CMAKE)
target_compile_definitions(${PROJECT_NAME} PRIVATE
DYNLEX_WINDOWS_TARGET_TRIPLE="${DYNLEX_WINDOWS_TOOLCHAIN_TARGET}"
DYNLEX_WINDOWS_LINKER_BUILD_PATH="${DYNLEX_WINDOWS_TOOLCHAIN_ROOT_CMAKE}/bin/cc.exe"
DYNLEX_WINDOWS_TARGET_LIBRARY_BUILD_DIR="${DYNLEX_WINDOWS_TOOLCHAIN_ROOT_CMAKE}/${DYNLEX_WINDOWS_TOOLCHAIN_TARGET}/lib"
DYNLEX_WINDOWS_DEPENDENCY_LIBRARY_BUILD_DIR="${DYNLEX_WINDOWS_DEPENDENCY_ROOT_CMAKE}/lib"
DYNLEX_WINDOWS_RUNTIME_LIBRARY_BUILD_DIR="${DYNLEX_WINDOWS_DEPENDENCY_ROOT_CMAKE}/bin"
DYNLEX_WINDOWS_TOOLCHAIN_INSTALL_DIR="${CMAKE_INSTALL_LIBDIR}/dynlex/toolchain"
)
endif()
if(APPLE)
target_compile_definitions(${PROJECT_NAME} PRIVATE
DYNLEX_MACOS_DEPENDENCY_INSTALL_DIR="${CMAKE_INSTALL_LIBDIR}/dynlex/dependencies"
)
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json)
dynlex_link_llvm(${PROJECT_NAME} ${DYNLEX_LLVM_NATIVE_COMPONENTS})
if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32 shell32 ole32)
endif()
set_target_properties (${PROJECT_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
)
target_compile_definitions(${PROJECT_NAME} PRIVATE DYNLEX_VERSION="${PROJECT_VERSION}")
add_executable(
dynlex_class_layout_test EXCLUDE_FROM_ALL
tests/cpp/classLayoutTest.cpp
src/cpp/compiler/classLayout.cpp
)
target_include_directories(dynlex_class_layout_test PRIVATE src/cpp)
dynlex_link_llvm(dynlex_class_layout_test core support)
set_target_properties(dynlex_class_layout_test PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
# MinGW stores full DWARF in every COFF object for a normal Debug build.
# Keeping that data in the objects makes LLD spend an unbounded amount of
# time producing the final PE image. Split DWARF preserves the complete
# debugger information in adjacent .dwo files while leaving only the
# address-bearing skeleton records for the linker.
if(WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options(${PROJECT_NAME} PRIVATE
"$<$<OR:$<CONFIG:Debug>,$<CONFIG:Optimized>>:-gsplit-dwarf>"
)
endif()
add_executable(fbx_to_obj tools/fbx_to_obj.cpp third_party/ufbx/ufbx.c)
target_include_directories(
fbx_to_obj SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/third_party/ufbx ${CMAKE_SOURCE_DIR}/third_party/stb
)
set_target_properties(fbx_to_obj PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
endif()
if(DYNLEX_WEB)
if(NOT EMSCRIPTEN)
message(FATAL_ERROR "DYNLEX_WEB requires the Emscripten toolchain. Configure with emcmake.")
endif()
include(FetchContent)
set(SPIRV_CROSS_CLI OFF CACHE BOOL "" FORCE)
set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
set(SPIRV_CROSS_ENABLE_CPP OFF CACHE BOOL "" FORCE)
set(SPIRV_CROSS_ENABLE_GLSL ON CACHE BOOL "" FORCE)
set(SPIRV_CROSS_ENABLE_HLSL OFF CACHE BOOL "" FORCE)
set(SPIRV_CROSS_ENABLE_MSL OFF CACHE BOOL "" FORCE)
set(SPIRV_CROSS_ENABLE_C_API OFF CACHE BOOL "" FORCE)
set(SPIRV_CROSS_ENABLE_REFLECT OFF CACHE BOOL "" FORCE)
set(SPIRV_CROSS_ENABLE_UTIL OFF CACHE BOOL "" FORCE)
FetchContent_Declare(
spirv_cross
URL https://github.com/KhronosGroup/SPIRV-Cross/archive/a0fba56c34a6700f1724bf9b751da5b488a3775c.tar.gz
URL_HASH SHA256=1e79592b0a498ffb854f7d71e0d5811fcedb87a25201644bbf5dbba438e01264
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
FetchContent_MakeAvailable(spirv_cross)
set(DYNLEX_WEB_SOURCES ${PROJECT_SOURCES})
list(FILTER DYNLEX_WEB_SOURCES EXCLUDE REGEX "src/cpp/main\\.cpp$")
list(FILTER DYNLEX_WEB_SOURCES EXCLUDE REGEX "src/cpp/dap/.*\\.cpp$")
list(FILTER DYNLEX_WEB_SOURCES EXCLUDE REGEX "src/cpp/lsp/tcpTransport\\.cpp$")
list(FILTER DYNLEX_WEB_SOURCES EXCLUDE REGEX "src/cpp/lsp/stdioTransport\\.cpp$")
list(FILTER DYNLEX_WEB_SOURCES EXCLUDE REGEX "src/cpp/compiler/codegen/native\\.cpp$")
list(FILTER DYNLEX_WEB_SOURCES EXCLUDE REGEX "src/cpp/pexlit/rendering/.*\\.cpp$")
list(FILTER DYNLEX_WEB_SOURCES EXCLUDE REGEX "src/cpp/pexlit/safeInclude/implementations\\.cpp$")
add_executable(dynlex_web ${DYNLEX_WEB_SOURCES} ${PROJECT_HEADERS} ${PROJECT_CONFIGS})
set_target_properties(dynlex_web PROPERTIES
OUTPUT_NAME "dynlex_web"
SUFFIX ".js"
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
LINK_DEPENDS "${DYNLEX_LIBRARY_SOURCES}"
)
target_compile_definitions(dynlex_web PRIVATE DYNLEX_WEB=1 DYNLEX_VERSION="${PROJECT_VERSION}")
target_compile_options(dynlex_web PRIVATE "-fexceptions")
target_link_libraries(dynlex_web PRIVATE nlohmann_json::nlohmann_json spirv-cross-core spirv-cross-glsl)
dynlex_link_llvm(dynlex_web ${DYNLEX_LLVM_COMMON_COMPONENTS} SPIRV)
set(DYNLEX_WEB_EXPORTED_FUNCTIONS
"['_dynlex_web_init','_dynlex_web_set_main_source','_dynlex_web_compile_and_emit_wasm','_dynlex_web_compile_and_emit_shader_glsl','_dynlex_web_get_diagnostics_json','_dynlex_web_get_output_wasm_ptr','_dynlex_web_get_output_wasm_len','_dynlex_web_get_output_wasm_base64','_dynlex_web_get_output_shader_glsl','_dynlex_web_get_shader_uniforms_json','_dynlex_web_get_compiler_log_json','_dynlex_web_lsp_exchange_json']"
)
set(DYNLEX_WEB_EXPORTED_RUNTIME_METHODS "['ccall','cwrap','UTF8ToString']")
file(GLOB_RECURSE DYNLEX_WEB_EMBEDDED_LIBRARY_FILES
CONFIGURE_DEPENDS
LIST_DIRECTORIES false
"${CMAKE_SOURCE_DIR}/lib/*"
)
set_property(TARGET dynlex_web APPEND PROPERTY LINK_DEPENDS ${DYNLEX_WEB_EMBEDDED_LIBRARY_FILES})
target_link_options(dynlex_web PRIVATE
"-fexceptions"
"-sWASM=1"
"-sALLOW_MEMORY_GROWTH=1"
"-sSTACK_SIZE=8388608"
"-sMODULARIZE=1"
"-sEXPORT_ES6=1"
"-sENVIRONMENT=web,worker,node"
"-sNO_EXIT_RUNTIME=1"
"-sFILESYSTEM=1"
"-sEXPORTED_FUNCTIONS=${DYNLEX_WEB_EXPORTED_FUNCTIONS}"
"-sEXPORTED_RUNTIME_METHODS=${DYNLEX_WEB_EXPORTED_RUNTIME_METHODS}"
"--embed-file" "${CMAKE_SOURCE_DIR}/lib@/lib"
)
endif()
#
# Install targets
#
if(TARGET ${PROJECT_NAME})
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(TARGET dynlex_runtime)
if(WIN32)
install(FILES ${DYNLEX_WINDOWS_RUNTIME_ARCHIVE} DESTINATION ${CMAKE_INSTALL_LIBDIR}/dynlex)
else()
install(TARGETS dynlex_runtime ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/dynlex)
endif()
endif()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/ DESTINATION ${CMAKE_INSTALL_DATADIR}/dynlex/lib FILES_MATCHING PATTERN "*.dl")
if(WIN32 AND TARGET ${PROJECT_NAME})
# Bundle every DLL reported by the final link graph so the installation is self-contained.
install(FILES $<TARGET_RUNTIME_DLLS:${PROJECT_NAME}> DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
#
# CPack packaging
#
if(WIN32)
include("${CMAKE_SOURCE_DIR}/cmake/WindowsInstallerUpgradeCodes.cmake")
dynlex_read_windows_installer_upgrade_codes(
"${CMAKE_SOURCE_DIR}/metadata/WINDOWS_INSTALLER_UPGRADE_CODES"
)
set(CPACK_GENERATOR "WIX;ZIP")
set(CPACK_WIX_UPGRADE_GUID "${DYNLEX_WINDOWS_STABLE_UPGRADE_CODE}")
set(CPACK_WIX_PATCH_FILE "${CMAKE_SOURCE_DIR}/cmake/windows-installer-upgrades.xml")
list(APPEND CPACK_WIX_CANDLE_EXTRA_FLAGS
"-dDYNLEX_LEGACY_UPGRADE_CODE=${DYNLEX_WINDOWS_LEGACY_UPGRADE_CODE}"
)
elseif(APPLE)
set(CPACK_GENERATOR "productbuild;TGZ")
else()
set(CPACK_GENERATOR "DEB;TGZ")
endif()
set(CPACK_PACKAGE_NAME "dynlex")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "DynLex — a natural-language-like programming language")
set(CPACK_PACKAGE_CONTACT "DynLex maintainers <maintainers@dynlex.org>")
set(CPACK_PACKAGE_VENDOR "DynLex")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://dynlex.com")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_DEPENDS
"binutils, build-essential, clang, libc6-dev, libfreetype-dev, libgl-dev, libglfw3-dev"
)
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
include(CPack)