Repository navigation
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
160 lines (145 loc) · 6.52 KB
/
Copy pathCMakeLists.txt
File metadata and controls
160 lines (145 loc) · 6.52 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
# See LICENSE in the repository root.
cmake_minimum_required(VERSION 3.28)
# Export an explicit SDK for non-Apple clang-tidy/clangd, including CMake 4.
if(CMAKE_HOST_APPLE AND NOT CMAKE_OSX_SYSROOT AND "$ENV{SDKROOT}" STREQUAL "")
set(CMAKE_OSX_SYSROOT macosx CACHE STRING "macOS SDK" FORCE)
endif()
project(remmy LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
include(CheckCXXCompilerFlag)
include(CheckIPOSupported)
include(CTest)
find_package(Threads REQUIRED)
set(REMMY_CLANG_TIDY_DEFAULT OFF)
if(CMAKE_CXX_COMPILER_ID MATCHES "^(Clang|AppleClang)$")
set(REMMY_CLANG_TIDY_DEFAULT ON)
endif()
option(REMMY_ENABLE_CLANG_TIDY "Run strict clang-tidy during compilation" ${REMMY_CLANG_TIDY_DEFAULT})
if(REMMY_ENABLE_CLANG_TIDY)
find_program(REMMY_CLANG_TIDY NAMES clang-tidy REQUIRED)
# .clang-tidy owns the check list and warnings-as-errors policy.
set(CMAKE_CXX_CLANG_TIDY "${REMMY_CLANG_TIDY}")
endif()
option(REMMY_NATIVE "Tune Release builds for the build host's CPU" ON)
option(REMMY_STATIC "Link remmy fully statically (Linux; macOS always links libSystem)" OFF)
# Nothing here throws; keep exceptions off for every target, not per target.
add_compile_options(-fno-exceptions)
# cutils is a dependency here; its test suite has a separate standalone build.
set(CUTILS_BUILD_TESTING OFF)
add_subdirectory(cutils)
set(REMMY_SOURCES src/main.cpp src/cli.cpp src/dir_node.cpp)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16)
add_executable(remmy ${REMMY_SOURCES})
target_link_libraries(remmy PRIVATE cutils::cutils)
# ld64 flag; ELF executables export nothing without -rdynamic anyway.
target_link_options(remmy PRIVATE -static-libstdc++ -static-libgcc
$<$<PLATFORM_ID:Darwin>:-Wl,-exported_symbol,_main>)
if(REMMY_STATIC AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_options(remmy PRIVATE -static)
endif()
cutils_harden(remmy)
# clang-tidy lints these sources in the Clang build below; it cannot take
# the GCC-only flags this target compiles with.
set_property(TARGET remmy PROPERTY CXX_CLANG_TIDY "")
elseif(REMMY_ENABLE_CLANG_TIDY AND CMAKE_CXX_COMPILER_ID MATCHES "^(Clang|AppleClang)$")
# The shipped binary is GCC's; under Clang, compile remmy's sources only so
# clang-tidy checks them alongside cutils.
message(STATUS "Clang: linting cutils and remmy's sources, not linking remmy")
add_library(remmy_lint OBJECT ${REMMY_SOURCES})
target_link_libraries(remmy_lint PRIVATE cutils::cutils)
cutils_harden(remmy_lint)
else()
message(FATAL_ERROR "remmy is built with GCC 16; use the release or debug preset")
endif()
set(REMMY_LINT_FILES)
if(BUILD_TESTING)
# End-to-end tests run the shipped executable; sanitizer coverage belongs to cutils.
if(TARGET remmy)
find_program(REMMY_UV NAMES uv)
if(REMMY_UV)
add_test(NAME e2e
COMMAND "${REMMY_UV}" run --project "${CMAKE_CURRENT_SOURCE_DIR}"
pytest "${CMAKE_CURRENT_SOURCE_DIR}/tests" -p no:cacheprovider -n auto
--remmy "$<TARGET_FILE:remmy>"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
else()
message(STATUS "uv not found; e2e test disabled")
endif()
endif()
endif()
if(TARGET remmy)
# Optimization flags must never bleed into Debug or sanitizer builds.
# Redistributed binaries turn REMMY_NATIVE off: they run on other CPUs.
set(REMMY_NATIVE_FLAG)
if(REMMY_NATIVE)
check_cxx_compiler_flag("-march=native" REMMY_HAS_MARCH_NATIVE)
if(REMMY_HAS_MARCH_NATIVE)
set(REMMY_NATIVE_FLAG -march=native)
else()
check_cxx_compiler_flag("-mcpu=native" REMMY_HAS_MCPU_NATIVE)
if(REMMY_HAS_MCPU_NATIVE)
set(REMMY_NATIVE_FLAG -mcpu=native)
endif()
endif()
endif()
check_ipo_supported(RESULT REMMY_IPO_OK OUTPUT REMMY_IPO_ERR)
if(NOT REMMY_IPO_OK)
message(STATUS "Release LTO unavailable: ${REMMY_IPO_ERR}")
endif()
target_compile_options(remmy PRIVATE
"$<$<CONFIG:Release>:-O3;-funroll-loops;${REMMY_NATIVE_FLAG};-fno-unwind-tables;-fno-asynchronous-unwind-tables>"
"$<$<NOT:$<CONFIG:Release>>:-fno-omit-frame-pointer>")
target_compile_definitions(remmy PRIVATE
"_LIBCPP_HARDENING_MODE=$<IF:$<CONFIG:Release>,_LIBCPP_HARDENING_MODE_FAST,_LIBCPP_HARDENING_MODE_DEBUG>"
"$<$<NOT:$<CONFIG:Release>>:_GLIBCXX_DEBUG=1>")
set_property(TARGET remmy PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE ${REMMY_IPO_OK})
endif()
if(REMMY_ENABLE_CLANG_TIDY AND REMMY_LINT_FILES)
add_custom_target(tidy
COMMAND "${REMMY_CLANG_TIDY}" -p "${CMAKE_BINARY_DIR}" ${REMMY_LINT_FILES}
VERBATIM)
endif()
# Formatting is explicit: never rewrite sources as a side effect of a build.
find_program(REMMY_CLANG_FORMAT NAMES clang-format)
if(REMMY_CLANG_FORMAT)
file(GLOB_RECURSE REMMY_FORMAT_FILES CONFIGURE_DEPENDS
cutils/*.hpp cutils/*.cpp
src/*.[ch] src/*.cpp src/*.hpp)
add_custom_target(format
COMMAND "${REMMY_CLANG_FORMAT}" --style=file -i ${REMMY_FORMAT_FILES}
VERBATIM)
add_custom_target(format-check
COMMAND "${REMMY_CLANG_FORMAT}" --style=file --dry-run --Werror ${REMMY_FORMAT_FILES}
VERBATIM)
else()
message(STATUS "clang-format not found; format/format-check targets unavailable")
endif()
option(REMMY_BUILD_DOCS "Enable Doxygen documentation targets" OFF)
if(REMMY_BUILD_DOCS)
find_package(Doxygen 1.9.8 REQUIRED COMPONENTS doxygen OPTIONAL_COMPONENTS dot)
set(DOXYGEN_GENERATE_HTML YES)
set(DOXYGEN_GENERATE_LATEX NO)
set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs")
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "${CMAKE_CURRENT_SOURCE_DIR}/TESTING.md")
set(DOXYGEN_EXTRACT_PRIVATE YES)
set(DOXYGEN_EXTRACT_STATIC YES)
set(DOXYGEN_EXTRACT_ANON_NSPACES YES)
set(DOXYGEN_WARN_AS_ERROR FAIL_ON_WARNINGS)
set(DOXYGEN_WARN_IF_DOC_ERROR YES)
# Preview all code while writing. Malformed documentation still fails.
set(DOXYGEN_EXTRACT_ALL YES)
doxygen_add_docs(docs cutils/include cutils/src src TESTING.md COMMENT "Generate the API reference")
# Separate completeness gate: undocumented API and parameters are errors.
set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs-check")
set(DOXYGEN_EXTRACT_ALL NO)
set(DOXYGEN_WARN_IF_UNDOCUMENTED YES)
set(DOXYGEN_WARN_IF_UNDOC_ENUM_VAL YES)
set(DOXYGEN_WARN_NO_PARAMDOC YES)
doxygen_add_docs(docs-check cutils/include cutils/src src TESTING.md COMMENT "Check API documentation completeness")
endif()