forked from Lamina-dev/Lamina
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
439 lines (385 loc) · 17.1 KB
/
CMakeLists.txt
File metadata and controls
439 lines (385 loc) · 17.1 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
cmake_minimum_required(VERSION 3.16.3)
project(lamina VERSION 1.1.0 LANGUAGES CXX)# lamina version here
include(GNUInstallDirs)
set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}/lamina)
# add sub directory
add_subdirectory(interpreter)
# Set C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(APPLE)
# 指定 macOS 最低部署版本(10.15+ 支持 _dyld_iterate_images 且兼容 ARM64)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum macOS version" FORCE)
# 确保架构正确(ARM64 或 X86_64)
set(CMAKE_OSX_ARCHITECTURES "${ARCH}" CACHE STRING "macOS architecture" FORCE)
# 添加编译器和链接器标志
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_DARWIN_C_SOURCE")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-undefined,dynamic_lookup")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-undefined,dynamic_lookup")
endif()
# Prioritize MSVC on Windows
if(WIN32)
if(MSVC)
# Set MSVC compile options - add exception handling, calling convention and parallel PDB write support
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /MD /Gz /FS /utf-8")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MD /Gz /FS")
# Set to multi-threaded dynamic link library
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
# Add additional definitions to ensure consistent calling convention
add_definitions(-D_ENABLE_EXTENDED_ALIGNED_STORAGE)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
message(STATUS "Using MSVC compiler (${CMAKE_CXX_COMPILER_VERSION})")
else()
# Settings for MinGW or other compilers
message(STATUS "Using MinGW/GCC compiler. Note: Some features may require additional configuration.")
# Add necessary link libraries for MinGW
if(MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
endif()
endif()
endif()
# Set output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
# 设置 RPATH 相关选项
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
if(APPLE)
set(CMAKE_INSTALL_RPATH "@executable_path/../${CMAKE_INSTALL_LIBDIR}")
else()
set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
endif()
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/interpreter
${CMAKE_CURRENT_BINARY_DIR} # version.hpp
)
include_directories(interpreter)
# Create lamina_core shared library
add_library(lamina_core SHARED
interpreter/lamina_api/ast.hpp
interpreter/lamina_api/bigint.hpp
interpreter/lamina_api/irrational.hpp
interpreter/lamina_api/rational.hpp
interpreter/lamina_api/value.hpp
interpreter/lamina_api/lamina.hpp
interpreter/lamina_api/symbolic.hpp
interpreter/lamina_api/symbolic.cpp
extensions/standard/math.cpp
extensions/standard/basic.cpp
extensions/standard/random.cpp
extensions/standard/times.cpp
extensions/standard/array.cpp
extensions/standard/string.cpp
extensions/standard/cas.hpp
extensions/standard/cas.cpp
extensions/standard/lmStruct.hpp
extensions/standard/lmStruct.cpp
extensions/standard/standard.hpp
extensions/standard/io.cpp
interpreter/eval.cpp
interpreter/interpreter.cpp
interpreter/interpreter.hpp
interpreter/lexer.cpp
interpreter/lexer.hpp
interpreter/parser.cpp
interpreter/parser.hpp
interpreter/parse_expr.cpp
interpreter/parse_factor.cpp
interpreter/parse_stmt.cpp
interpreter/cpp_module_loader.hpp
interpreter/utils/src_manger.cpp
interpreter/cpp_module_loader.hpp
interpreter/utils/properties_parser.hpp
interpreter/utils/src_manger.hpp
)
if (APPLE)
# 添加必要的框架和系统库
target_link_libraries(lamina_core PRIVATE
"-framework CoreFoundation"
"-framework CoreServices"
)
# 确保包含系统头文件
target_include_directories(lamina_core PRIVATE
/usr/include
/usr/include/mach-o
)
# 设置特定的编译选项
target_compile_options(lamina_core PRIVATE
-fPIC
-D_DARWIN_C_SOURCE
)
endif()
# Add version header
target_sources(lamina_core PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.hpp)
# Set lamina_core properties
set_target_properties(lamina_core PROPERTIES
# 关键修改:禁用自动导出所有符号
WINDOWS_EXPORT_ALL_SYMBOLS OFF
# 不使用版本号作为文件名,保持稳定的库名
VERSION ${PROJECT_VERSION}
SOVERSION 1
ENABLE_EXPORTS ON
PREFIX "" # Remove lib prefix on all platforms
OUTPUT_NAME "lamina_core" # 固定输出名称(无版本号)
# macOS 安装名设置为 @rpath/lamina_core.dylib
INSTALL_NAME_DIR "@rpath"
MACOSX_RPATH TRUE
)
# 针对 x86 架构的特殊处理
if(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4)
message(STATUS "Detected x86 (32-bit) build, applying compatibility fixes")
# 添加链接器选项,忽略特定警告
target_link_options(lamina_core PRIVATE
/IGNORE:4197 # 忽略多次导出警告
)
# 可选:如果仍有问题,取消下面的注释使用 .def 文件
# if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/lamina_core_x86.def")
# target_sources(lamina_core PRIVATE
# "${CMAKE_CURRENT_SOURCE_DIR}/lamina_core_x86.def"
# )
# endif()
endif()
# Define export macros
target_compile_definitions(lamina_core PRIVATE LAMINA_CORE_EXPORTS)
# Enable symbolic debug prints only in Debug configuration. CMake will define
# _SYMBOLIC_DEBUG=1 for Debug builds; other configs will not define it.
target_compile_definitions(lamina_core PRIVATE $<$<CONFIG:Debug>:_SYMBOLIC_DEBUG=1>)
# Add imagehlp library link for Windows
if(WIN32)
target_link_libraries(lamina_core PRIVATE imagehlp)
endif()
# Set compiler specific options
if(MSVC)
target_compile_options(lamina_core PRIVATE
/bigobj # 消除编译错误
/W4
/FS # Add /FS flag to resolve PDB file conflicts during parallel compilation
/wd4251 # 'class' needs to have dll-interface to be used by clients of class
/wd4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data
/wd4996 # This function or variable may be unsafe
/wd4702 # unreachable code
/wd4100 # unreferenced formal parameter
/wd4189 # local variable is initialized but not referenced
/wd4459 # declaration hides global declaration
/wd4244 # conversion from 'type1' to 'type2', possible loss of data
/wd4005 # macro redefinition
# 添加 x86 特有的警告抑制
/wd4305 # 'initializing': truncation from 'unsigned __int64' to 'const size_t'
/wd4309 # 'initializing': truncation of constant value
/wd4456 # declaration hides previous local declaration
/wd4101 # unreferenced local variable
/wd4715 # not all control paths return a value
/wd4701 # potentially uninitialized local variable used
)
else()
target_compile_options(lamina_core PRIVATE
-Wall -Wextra -Wpedantic
-Wno-unused-parameter
-Wno-unused-variable
)
endif()
# Create main executable
add_executable(lamina
interpreter/main.cpp
interpreter/utils/repl_input.hpp
interpreter/utils/repl_input.cpp
interpreter/console_ui.hpp
interpreter/console_ui.cpp
interpreter/utils/color_style.hpp
interpreter/utils/color_style.cpp
interpreter/eval.cpp
)
# Add version header
target_sources(lamina PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.hpp)
# Link to lamina_core
target_link_libraries(lamina PRIVATE lamina_core)
# Small unit test for symbolic simplifier (not installed)
#add_executable(test_symbolic
# interpreter/tests/test_symbolic.cpp
#)
#target_link_libraries(test_symbolic PRIVATE lamina_core)
#target_compile_definitions(test_symbolic PRIVATE LAMINA_CORE_EXPORTS)
#target_compile_definitions(test_symbolic PRIVATE $<$<CONFIG:Debug>:_SYMBOLIC_DEBUG=1>)
# Ensure the `lamina` executable also gets the _SYMBOLIC_DEBUG define in Debug builds
target_compile_definitions(lamina PRIVATE $<$<CONFIG:Debug>:_SYMBOLIC_DEBUG=1>)
# Platform specific link libraries
if(UNIX)
target_link_libraries(lamina PRIVATE dl)
endif()
# Ensure `lamina` executable can find `lamina_core` at runtime (set rpath)
if(APPLE)
set_target_properties(lamina PROPERTIES
INSTALL_RPATH "@executable_path/../${CMAKE_INSTALL_LIBDIR}"
BUILD_WITH_INSTALL_RPATH TRUE
MACOSX_RPATH TRUE
)
else()
set_target_properties(lamina PROPERTIES
INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}"
BUILD_WITH_INSTALL_RPATH TRUE
)
endif()
# Post-build actions: place the shared library and executable in stable, non-versioned locations
if(APPLE)
add_custom_command(TARGET lamina_core POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}
# Copy the produced dylib (which may include version suffix) to a stable non-versioned name first
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:lamina_core>" ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/lamina_core.dylib
# Then set the dylib id on the copied file to @rpath/lamina_core.dylib so executables can use @rpath
COMMAND install_name_tool -id "@rpath/lamina_core.dylib" "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/lamina_core.dylib"
COMMENT "Copying lamina_core to ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/lamina_core.dylib and setting install_name"
)
add_custom_command(TARGET lamina POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:lamina>" ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/lamina
# Update the executable to reference @rpath/lamina_core.dylib (replace original soname)
COMMAND install_name_tool -change "$<TARGET_FILE_NAME:lamina_core>" "@rpath/lamina_core.dylib" "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/lamina"
# Ensure the executable has an rpath pointing at ../lib/lamina
COMMAND install_name_tool -add_rpath "@executable_path/../${CMAKE_INSTALL_LIBDIR}" "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/lamina"
COMMENT "Copying lamina executable to ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/lamina and fixing rpath"
)
else()
add_custom_command(TARGET lamina_core POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:lamina_core>" ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/lamina_core.so
COMMENT "Copying lamina_core to ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/lamina_core.so"
)
add_custom_command(TARGET lamina POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:lamina>" ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/lamina
COMMENT "Copying lamina executable to ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/lamina"
)
endif()
# Copy lamina_core.dll on Windows
if(WIN32)
add_custom_command(TARGET lamina POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:lamina_core>
$<TARGET_FILE_DIR:lamina>
COMMENT "Copying lamina_core.dll to output directory"
)
endif()
# Extension/plugin system (supports Linux and Windows)
message(STATUS "Building extensions for ${CMAKE_SYSTEM_NAME}")
# 自动寻找并构建扩展
function(build_extension EXTENSION_PATH)
get_filename_component(EXTENSION_NAME ${EXTENSION_PATH} NAME)
get_filename_component(EXTENSION_DIR ${EXTENSION_PATH} DIRECTORY)
# 检查是否有对应的 .cpp 文件
set(EXTENSION_SOURCE "${EXTENSION_PATH}/${EXTENSION_NAME}.cpp")
if(EXISTS ${EXTENSION_SOURCE})
message(STATUS "Building extension: ${EXTENSION_NAME}")
# 创建共享库
add_library(${EXTENSION_NAME} SHARED ${EXTENSION_SOURCE})
# 设置包含目录
target_include_directories(${EXTENSION_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/interpreter
${CMAKE_CURRENT_SOURCE_DIR}/extensions
${EXTENSION_PATH}
)
# 设置输出目录和属性
set_target_properties(${EXTENSION_NAME} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/Debug
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/Debug
ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/Debug
LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/Release
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/Release
ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/Release
POSITION_INDEPENDENT_CODE ON
PREFIX "" # 去掉 lib 前缀
)
# 设置扩展的编译选项(抑制常见警告)
if(MSVC)
target_compile_options(${EXTENSION_NAME} PRIVATE
/W4
/wd4251 # 'class' needs to have dll-interface
/wd4267 # conversion from 'size_t' to 'type', possible loss of data
/wd4996 # This function or variable may be unsafe
/wd4702 # unreachable code
/wd4100 # unreferenced formal parameter
/wd4189 # local variable is initialized but not referenced
/wd4459 # declaration hides global declaration
/wd4244 # conversion possible loss of data
/wd4005 # macro redefinition
)
else()
target_compile_options(${EXTENSION_NAME} PRIVATE
-Wall -Wextra -Wpedantic
-Wno-unused-parameter
-Wno-unused-variable
)
endif()
# Windows 下自动复制 DLL,支持 MSVC 和 MinGW
if(WIN32)
if(MSVC)
# MSVC 构建,支持 Debug 配置的 PDB 文件
add_custom_command(TARGET ${EXTENSION_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:${EXTENSION_NAME}>
$<TARGET_FILE_DIR:${EXTENSION_NAME}>
COMMENT "Copying ${EXTENSION_NAME}.dll to output directory"
)
# 在 Debug 配置下复制 PDB 文件
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_custom_command(TARGET ${EXTENSION_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_PDB_FILE:${EXTENSION_NAME}>
$<TARGET_FILE_DIR:${EXTENSION_NAME}>
COMMENT "Copying ${EXTENSION_NAME}.pdb to output directory"
)
endif()
else()
# MinGW 构建,只复制 DLL
add_custom_command(TARGET ${EXTENSION_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:${EXTENSION_NAME}>
$<TARGET_FILE_DIR:${EXTENSION_NAME}>
COMMENT "Copying ${EXTENSION_NAME}.dll to output directory"
)
endif()
endif()
else()
message(STATUS "Skipping extension ${EXTENSION_NAME}: source file not found (${EXTENSION_SOURCE})")
endif()
endfunction()
# 自动寻找扩展目录(排除 standard 目录)
file(GLOB EXTENSION_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/extensions/*")
set(FOUND_EXTENSIONS 0)
foreach(EXTENSION_DIR ${EXTENSION_DIRS})
if(IS_DIRECTORY ${EXTENSION_DIR})
get_filename_component(DIR_NAME ${EXTENSION_DIR} NAME)
# 排除标准库扩展目录
if(NOT DIR_NAME STREQUAL "standard")
# 检查目录是否真实存在且包含源文件
get_filename_component(EXTENSION_NAME ${EXTENSION_DIR} NAME)
set(EXTENSION_SOURCE "${EXTENSION_DIR}/${EXTENSION_NAME}.cpp")
if(EXISTS ${EXTENSION_SOURCE})
build_extension(${EXTENSION_DIR})
math(EXPR FOUND_EXTENSIONS "${FOUND_EXTENSIONS} + 1")
endif()
endif()
endif()
endforeach()
if(FOUND_EXTENSIONS EQUAL 0)
message(STATUS "No additional extensions found to build")
else()
message(STATUS "Found and configured ${FOUND_EXTENSIONS} extension(s)")
endif()
# 确保可执行文件能找到库
set_target_properties(lamina PROPERTIES
INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}"
BUILD_WITH_INSTALL_RPATH True
)
# Installation rules
install(TARGETS lamina
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
# Install header files (for plugin development)
install(DIRECTORY interpreter/
DESTINATION include/lamina
FILES_MATCHING PATTERN "*.hpp"
)