-
Notifications
You must be signed in to change notification settings - Fork 0
/
cmake.txt
126 lines (87 loc) · 4.29 KB
/
cmake.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
#+title: CMake instructions that work for me in late 2024
!cmake !cheatsheet !process !build
==============================
What Works for Me in Late 2024
==============================
CMake builds build scripts. Given a project description in one
or more CMakeLists.txt files (one per directory, but you can
get by with just one file) you have CMake generate the build
commands for a backend. GNU Make, ninja, and meson are three
of probably many backends.
I've settled on ninja.
Commands to Know:
----------------
Create a the build scripting for a project:
cmake -G "Ninja Multi-Config" -S source -B build
Run the build.
cmake --build build --config Release or Debug or RelWithDebInfo ...
Though I usually just run ninja directly inside the build directory.
CMakeLists.txt Template:
-----------------------
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
PROJECT(
~name~
VERSION 0.0.0.1
DESCRIPTION "some text here"
HOMEPAGE_URL "url here"
LANGUAGES C
)
SET(
CMAKE_C_COMPILER "clang"
)
SET(MY_REL_OPT "-Wall -Werror -std=c18")
SET(MY_DEB_OPT "-Wall -Werror -stc=c18 -fsanitize=address")
SET(MY_REL_DEB_OPT" "-Wall -Werror -std=c18")
SET(MY_DEB_LINK_OPT "-fsanitize=address")
ADD_EXECUTABLE(~target~ "source dependency" "each a separate string" ...)
TARGET_INCLUDE_DIRECTORIES(~target~ PUBLIC "directory" "more if needed" ...)
TARGET_LINK_OPTIONS(~target~ PUBLIC ~generator_expression~) * usually just debug
TARGET_COMPILE_OPTIONS(~target~ PUBLIC "$<$<CONFIG:config>:...>") *for each config
Example From a Working Build:
----------------------------
SET(MY_RELEASE_OPTIONS "-Wall -Werror -pedantic-errors -std=c18")
SET(MY_RELWITHDEBINFO_OPTIONS "-Wall -Werror -pedantic-errors -std=c18 -g")
SET(MY_DEBUG_OPTIONS "-Wall -Werror -pedantic-errors -std=c18 -g -fsanitize=address")
SET(MY_DEBUG_LINK_OPTIONS "-fsanitize=address")
ADD_EXECUTABLE(minunit "${CMAKE_CURRENT_SOURCE_DIR}/src/minunit_example.c")
TARGET_INCLUDE_DIRECTORIES(minunit PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/inc")
TARGET_LINK_OPTIONS(minunit PUBLIC "$<$<CONFIG:DEBUG>:SHELL:${MY_DEBUG_LINK_OPTIONS}>")
TARGET_COMPILE_OPTIONS(minunit PUBLIC "$<$<CONFIG:RELWITHDEBINFO>:SHELL:${MY_REL_DEB_OPTIONS}>")
TARGET_COMPILE_OPTIONS(minunit PUBLIC "$<$<CONFIG:DEBUG>:SHELL:${MY_DEBUG_OPTIONS}>")
TARGET_COMPILE_OPTIONS(minunit PUBLIC "$<$<CONFIG:RELEASE>:SHELL:${MY_RELEASE_OPTIONS}>")
CMake Notes:
-----------
There is a lot of redundancy here, but I think of it like a linkdeck
from my mainframe days. Declarative and the repetition isn't very
expensive. The GNU Make scripting to do this on the fly is more hassle
than it was worth.
CMake is a moving target, and the compile options conditionals via
IF() don't work (if they ever did). The approach described here will
pass correct options to each build configuration as of October 2024.
Configurations are typically Debug, Release, and RelWithDebInfo when
using the Ninja Multi-Config generator.
Create options variable strings for each configuration.
eg: set(MY_REL_OPT "-Wall -Werror -std=c18")
set(MY_DEB_OPT "-Wall -Werror -stc=c18 -fsanitize=address")
set(MY_DEB_LINK_OPT "-fsanitize=address")
for each target (an executable usually), use the command
target_<step>_options() to pass values to the compiler
(<step>=compile) or linker (<step>=link).
target_compile_options(targ PUBLIC "$<$<CONFIG:DEBUG>:SHELL:${MY_DEB_OPT}>")
target_link_options(targ PUBLIC "$<$<CONFIG:DEBUG>:SHELL:${MY_DEB_LINK_OPT}>")
Where:
* targ is whichever target this is for.
* "$<$<CONFIG:configuration>...text to insert...>" is a generator
expression. when the scripting for a configuration is generated,
the text to insert will be used in the appropriate place.
* :SHELL: handles spaces in the options string, otherwise the whole
string is double quoted and that doesn't work well.
* target_<step>_options(generator_expression:replacement)
So far, for my builds that I will need the following for each target
(build artifact for release):
add_<target_type>(name source_dependency...)
target_include_directories(name directories...)
target_link_options(name generator expression) *only for debug atm
target_compile_options(name PUBLIC "$<$<CONFIG:config>:...>") *for each config
As I do more, say creating shared libraries, I may need additional
scripting, but this is sufficient for the time being.