Skip to content

Commit 28eb6f6

Browse files
committed
feat(gyp-to-cmake): support cflags
1 parent 0a29fbd commit 28eb6f6

5 files changed

Lines changed: 120 additions & 3 deletions

File tree

.changeset/gyp-cflags.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"gyp-to-cmake": minor
3+
---
4+
5+
Translate target-level `cflags` from `binding.gyp` into private CMake compile
6+
options. The parser now validates that `cflags` is an array of strings, and the
7+
generated options preserve command expansion and escaped spaces.

packages/gyp-to-cmake/src/gyp.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,47 @@ describe("gyp.assertRoot", () => {
3838
assertBinding(input);
3939
assert(Array.isArray(input.targets));
4040
});
41+
42+
it("should accept target cflags", () => {
43+
assert.doesNotThrow(() => {
44+
assertBinding(
45+
{
46+
targets: [
47+
{
48+
target_name: "addon",
49+
sources: ["addon.cc"],
50+
cflags: ["-fPIC", "-Wall"],
51+
},
52+
],
53+
},
54+
true,
55+
);
56+
});
57+
});
58+
59+
it("should reject malformed target cflags", () => {
60+
assert.throws(() => {
61+
assertBinding({
62+
targets: [
63+
{
64+
target_name: "addon",
65+
sources: ["addon.cc"],
66+
cflags: "-fPIC",
67+
},
68+
],
69+
});
70+
}, /Expected 'cflags' to be an array/);
71+
72+
assert.throws(() => {
73+
assertBinding({
74+
targets: [
75+
{
76+
target_name: "addon",
77+
sources: ["addon.cc"],
78+
cflags: ["-fPIC", 42],
79+
},
80+
],
81+
});
82+
}, /Expected all cflags to be strings/);
83+
});
4184
});

packages/gyp-to-cmake/src/gyp.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export type GypTarget = {
88
sources: string[];
99
include_dirs?: string[];
1010
defines?: string[];
11+
cflags?: string[];
1112
};
1213

1314
export type GypBinding = {
@@ -49,8 +50,21 @@ export function assertTarget(
4950
"Expected all include_dirs to be strings",
5051
);
5152
}
53+
if ("cflags" in target) {
54+
const { cflags } = target;
55+
assert(Array.isArray(cflags), "Expected 'cflags' to be an array");
56+
assert(
57+
cflags.every((flag) => typeof flag === "string"),
58+
"Expected all cflags to be strings",
59+
);
60+
}
5261
if (disallowUnknownProperties) {
53-
assertNoExtraProperties(target, ["target_name", "sources", "include_dirs"]);
62+
assertNoExtraProperties(target, [
63+
"target_name",
64+
"sources",
65+
"include_dirs",
66+
"cflags",
67+
]);
5468
}
5569
}
5670

packages/gyp-to-cmake/src/transformer.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,50 @@ describe("bindingGypToCmakeLists", () => {
126126
});
127127
});
128128

129+
describe("cflags", () => {
130+
it("should add cflags as target-specific compile options", () => {
131+
const output = bindingGypToCmakeLists({
132+
projectName: "some-project",
133+
gyp: {
134+
targets: [
135+
{
136+
target_name: "foo",
137+
sources: ["foo.cc"],
138+
cflags: ["-fPIC", "-Wall", "-DNAME=value with space"],
139+
},
140+
],
141+
},
142+
});
143+
144+
assert(
145+
output.includes(
146+
"target_compile_options(foo PRIVATE -fPIC -Wall -DNAME=value\\ with\\ space)",
147+
),
148+
`Expected output to include target_compile_options:\n${output}`,
149+
);
150+
});
151+
152+
it("should expand cflags command output into compile options", () => {
153+
const output = bindingGypToCmakeLists({
154+
projectName: "some-project",
155+
gyp: {
156+
targets: [
157+
{
158+
target_name: "foo",
159+
sources: ["foo.cc"],
160+
cflags: ["<!@echo -fPIC -Wall"],
161+
},
162+
],
163+
},
164+
});
165+
166+
assert(
167+
output.includes("target_compile_options(foo PRIVATE -fPIC -Wall)"),
168+
`Expected expanded cflags in target_compile_options:\n${output}`,
169+
);
170+
});
171+
});
172+
129173
describe("namespaced targets", () => {
130174
const gyp = {
131175
targets: [{ target_name: "addon", sources: ["addon.cc"] }],
@@ -174,6 +218,7 @@ describe("bindingGypToCmakeLists", () => {
174218
sources: ["addon.cc"],
175219
include_dirs: ["include"],
176220
defines: ["FOO"],
221+
cflags: ["-fPIC"],
177222
},
178223
],
179224
},
@@ -186,6 +231,7 @@ describe("bindingGypToCmakeLists", () => {
186231
"target_link_libraries(some-project-addon PRIVATE weak-node-api)",
187232
"target_include_directories(some-project-addon PRIVATE include)",
188233
"target_compile_definitions(some-project-addon PRIVATE FOO)",
234+
"target_compile_options(some-project-addon PRIVATE -fPIC)",
189235
"target_compile_features(some-project-addon PRIVATE cxx_std_17)",
190236
]) {
191237
assert(

packages/gyp-to-cmake/src/transformer.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,9 @@ export function bindingGypToCmakeLists({
9595
}
9696

9797
for (const target of gyp.targets) {
98-
const { target_name: targetName, defines = [] } = target;
98+
const { target_name: targetName, defines = [], cflags = [] } = target;
9999

100100
// TODO: Handle "conditions"
101-
// TODO: Handle "cflags"
102101
// TODO: Handle "ldflags"
103102

104103
const escapedSources = target.sources
@@ -116,6 +115,8 @@ export function bindingGypToCmakeLists({
116115
.map(transformPath)
117116
.map(escapeSpaces);
118117

118+
const escapedCflags = cflags.flatMap(mapExpansion).map(escapeSpaces);
119+
119120
const libraries = [];
120121
if (weakNodeApi) {
121122
libraries.push("weak-node-api");
@@ -216,6 +217,12 @@ export function bindingGypToCmakeLists({
216217
);
217218
}
218219

220+
if (escapedCflags.length > 0) {
221+
lines.push(
222+
`target_compile_options(${actualTargetName} PRIVATE ${escapedCflags.join(" ")})`,
223+
);
224+
}
225+
219226
if (compileFeatures.length > 0) {
220227
lines.push(
221228
`target_compile_features(${actualTargetName} PRIVATE ${compileFeatures.join(" ")})`,

0 commit comments

Comments
 (0)