Skip to content

Commit ae748d4

Browse files
committed
Add support for custom commands
1 parent 25f015b commit ae748d4

File tree

10 files changed

+893
-20
lines changed

10 files changed

+893
-20
lines changed

docs/cmake-toml.md

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,24 @@ link-options = [""] # linker flags
246246
private-link-options = [""]
247247
precompile-headers = [""] # precompiled headers
248248
private-precompile-headers = [""]
249+
dependencies = [""] # add_dependencies(target ...)
250+
251+
# Keys below are for type = "custom" (add_custom_target)
252+
all = false
253+
command = ["${CMAKE_COMMAND}", "-E", "echo", "Hello"] # one command line
254+
commands = [ # multiple command lines
255+
["${CMAKE_COMMAND}", "-E", "echo", "First"],
256+
["${CMAKE_COMMAND}", "-E", "echo", "Second"],
257+
]
258+
depends = ["generated.txt"] # add_custom_target(... DEPENDS ...)
259+
byproducts = ["generated.txt"]
260+
working-directory = "${CMAKE_CURRENT_BINARY_DIR}"
261+
comment = "Run custom target"
262+
job-pool = "pool"
263+
job-server-aware = true
264+
verbatim = true
265+
uses-terminal = true
266+
command-expand-lists = true
249267

250268
cmake-before = """
251269
message(STATUS "CMake injected before the target")
@@ -263,6 +281,51 @@ CXX_STANDARD_REQUIRED = true
263281
FOLDER = "MyFolder"
264282
```
265283

284+
### Custom commands
285+
286+
Use `[[target.<name>.custom-command]]` to map directly to [`add_custom_command`](https://cmake.org/cmake/help/latest/command/add_custom_command.html). A custom command can use either the `OUTPUT` form or the `TARGET` form:
287+
288+
```toml
289+
# OUTPUT form (add_custom_command(OUTPUT ...))
290+
[[target.mytarget.custom-command]]
291+
condition = "mycondition"
292+
outputs = ["${CMAKE_CURRENT_BINARY_DIR}/generated.cpp"]
293+
command = [
294+
"${CMAKE_COMMAND}",
295+
"-DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/generated.cpp",
296+
"-P",
297+
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate.cmake",
298+
]
299+
depends = ["cmake/generate.cmake"]
300+
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/generated.hpp"]
301+
main-dependency = "cmake/generate.cmake"
302+
implicit-depends = [["CXX", "src/input.idl"]]
303+
working-directory = "${CMAKE_CURRENT_BINARY_DIR}"
304+
comment = "Generate source"
305+
depfile = "${CMAKE_CURRENT_BINARY_DIR}/generated.d"
306+
job-pool = "pool"
307+
job-server-aware = true
308+
verbatim = true
309+
append = false
310+
uses-terminal = false
311+
codegen = false
312+
command-expand-lists = false
313+
depends-explicit-only = false
314+
315+
# TARGET form (add_custom_command(TARGET ...))
316+
[[target.mytarget.custom-command]]
317+
build-event = "post-build" # pre-build, pre-link, post-build
318+
command = ["${CMAKE_COMMAND}", "-E", "touch", "${CMAKE_CURRENT_BINARY_DIR}/post-build.stamp"]
319+
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/post-build.stamp"]
320+
working-directory = "${CMAKE_CURRENT_BINARY_DIR}"
321+
comment = "Post-build step"
322+
verbatim = true
323+
command-expand-lists = false
324+
uses-terminal = false
325+
```
326+
327+
For each custom command entry, exactly one of `outputs` or `build-event` is required.
328+
266329
A table mapping the cmkr features to the relevant CMake construct and the relevant documentation pages:
267330

268331
| cmkr | CMake construct | Description |
@@ -279,6 +342,9 @@ A table mapping the cmkr features to the relevant CMake construct and the releva
279342
| `link-libraries` | [`target_link_libraries`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html) | Adds library dependencies. Use `::mylib` to make sure a target exists. |
280343
| `link-options` | [`target_link_options`](https://cmake.org/cmake/help/latest/command/target_link_options.html) | Adds linker flags. |
281344
| `precompile-headers` | [`target_precompile_headers`](https://cmake.org/cmake/help/latest/command/target_precompile_headers.html) | Specifies precompiled headers. |
345+
| `dependencies` | [`add_dependencies`](https://cmake.org/cmake/help/latest/command/add_dependencies.html) | Adds target-level dependencies. |
346+
| `type = "custom"` + custom target keys | [`add_custom_target`](https://cmake.org/cmake/help/latest/command/add_custom_target.html) | Creates a custom target with command/dependency options. |
347+
| `[[target.<name>.custom-command]]` | [`add_custom_command`](https://cmake.org/cmake/help/latest/command/add_custom_command.html) | Supports both `OUTPUT` and `TARGET` forms. |
282348
| `properties` | [`set_target_properties`](https://cmake.org/cmake/help/latest/command/set_target_properties.html) | See [properties on targets](https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#properties-on-targets) for more information. |
283349

284350
The default [visibility](/basics) is as follows:
@@ -342,4 +408,4 @@ files = ["content/my.png"]
342408
dirs = ["include"]
343409
configs = ["Release", "Debug"]
344410
optional = false
345-
```
411+
```

docs/examples/custom-command.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
# Automatically generated from tests/custom-command/cmake.toml - DO NOT EDIT
3+
layout: default
4+
title: Tests add_custom_command and add_custom_target support
5+
permalink: /examples/custom-command
6+
parent: Examples
7+
nav_order: 12
8+
---
9+
10+
# Tests add_custom_command and add_custom_target support
11+
12+
13+
14+
```toml
15+
[project]
16+
name = "custom-command"
17+
description = "Tests add_custom_command and add_custom_target support"
18+
19+
[target.custom-command]
20+
type = "executable"
21+
sources = ["src/main.cpp"]
22+
include-directories = ["${CMAKE_CURRENT_BINARY_DIR}/generated"]
23+
24+
[[target.custom-command.custom-command]]
25+
outputs = ["${CMAKE_CURRENT_BINARY_DIR}/generated/generated.cpp"]
26+
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/generated/generated.hpp"]
27+
depends = ["cmake/generate_source.cmake"]
28+
command = [
29+
"${CMAKE_COMMAND}",
30+
"-DOUTPUT_CPP=${CMAKE_CURRENT_BINARY_DIR}/generated/generated.cpp",
31+
"-DOUTPUT_HPP=${CMAKE_CURRENT_BINARY_DIR}/generated/generated.hpp",
32+
"-P",
33+
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate_source.cmake",
34+
]
35+
comment = "Generate source files"
36+
verbatim = true
37+
38+
[[target.custom-command.custom-command]]
39+
build-event = "post-build"
40+
command = [
41+
"${CMAKE_COMMAND}",
42+
"-E",
43+
"touch",
44+
"${CMAKE_CURRENT_BINARY_DIR}/custom-command-post-build.stamp",
45+
]
46+
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/custom-command-post-build.stamp"]
47+
comment = "Create a post-build stamp file"
48+
verbatim = true
49+
50+
[target.custom-codegen]
51+
type = "custom"
52+
all = true
53+
command = [
54+
"${CMAKE_COMMAND}",
55+
"-E",
56+
"touch",
57+
"${CMAKE_CURRENT_BINARY_DIR}/custom-target.stamp",
58+
]
59+
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/custom-target.stamp"]
60+
comment = "Run custom target"
61+
verbatim = true
62+
```
63+
64+
65+
66+
<sup><sub>This page was automatically generated from [tests/custom-command/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/custom-command/cmake.toml).</sub></sup>

include/project_parser.hpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,105 @@ enum TargetType {
7474
extern const char *targetTypeNames[target_last];
7575

7676
struct Target {
77+
struct CustomTarget {
78+
bool has_all = false;
79+
bool all = false;
80+
81+
bool has_command = false;
82+
bool has_commands = false;
83+
std::vector<std::vector<std::string>> commands;
84+
std::vector<std::string> depends;
85+
std::vector<std::string> byproducts;
86+
87+
bool has_working_directory = false;
88+
std::string working_directory;
89+
90+
bool has_comment = false;
91+
std::string comment;
92+
93+
bool has_job_pool = false;
94+
std::string job_pool;
95+
96+
bool has_job_server_aware = false;
97+
bool job_server_aware = false;
98+
99+
bool has_verbatim = false;
100+
bool verbatim = false;
101+
102+
bool has_uses_terminal = false;
103+
bool uses_terminal = false;
104+
105+
bool has_command_expand_lists = false;
106+
bool command_expand_lists = false;
107+
108+
bool empty() const {
109+
return !has_all && !has_command && !has_commands && commands.empty() && depends.empty() && byproducts.empty() && !has_working_directory &&
110+
!has_comment &&
111+
!has_job_pool && !has_job_server_aware && !has_verbatim && !has_uses_terminal && !has_command_expand_lists;
112+
}
113+
};
114+
115+
struct CustomCommand {
116+
struct ImplicitDependency {
117+
std::string language;
118+
std::string file;
119+
};
120+
121+
std::string condition;
122+
std::vector<std::vector<std::string>> commands;
123+
124+
std::vector<std::string> outputs;
125+
std::string build_event;
126+
127+
bool has_append = false;
128+
bool append = false;
129+
130+
bool has_main_dependency = false;
131+
std::string main_dependency;
132+
133+
std::vector<std::string> depends;
134+
std::vector<std::string> byproducts;
135+
std::vector<ImplicitDependency> implicit_depends;
136+
137+
bool has_working_directory = false;
138+
std::string working_directory;
139+
140+
bool has_comment = false;
141+
std::string comment;
142+
143+
bool has_depfile = false;
144+
std::string depfile;
145+
146+
bool has_job_pool = false;
147+
std::string job_pool;
148+
149+
bool has_job_server_aware = false;
150+
bool job_server_aware = false;
151+
152+
bool has_verbatim = false;
153+
bool verbatim = false;
154+
155+
bool has_uses_terminal = false;
156+
bool uses_terminal = false;
157+
158+
bool has_codegen = false;
159+
bool codegen = false;
160+
161+
bool has_command_expand_lists = false;
162+
bool command_expand_lists = false;
163+
164+
bool has_depends_explicit_only = false;
165+
bool depends_explicit_only = false;
166+
167+
bool is_output_form() const {
168+
return !outputs.empty();
169+
}
170+
171+
bool is_target_form() const {
172+
return !build_event.empty();
173+
}
174+
};
175+
77176
std::string name;
78177
TargetType type = target_last;
79178
std::string type_name;
@@ -107,6 +206,9 @@ struct Target {
107206

108207
ConditionVector dependencies;
109208

209+
CustomTarget custom_target;
210+
std::vector<CustomCommand> custom_commands;
211+
110212
std::string condition;
111213
std::string alias;
112214
Condition<tsl::ordered_map<std::string, std::string>> properties;

0 commit comments

Comments
 (0)