-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathtransformer.ts
More file actions
113 lines (98 loc) · 3.5 KB
/
transformer.ts
File metadata and controls
113 lines (98 loc) · 3.5 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
import cp from "node:child_process";
import path from "node:path";
import type { GypBinding } from "./gyp.js";
const DEFAULT_NAPI_VERSION = 8;
export type GypToCmakeListsOptions = {
gyp: GypBinding;
projectName: string;
napiVersion?: number;
executeCmdExpansions?: boolean;
unsupportedBehaviour?: "skip" | "warn" | "throw";
transformWinPathsToPosix?: boolean;
};
function isCmdExpansion(value: string) {
const trimmedValue = value.trim();
return trimmedValue.startsWith("<!");
}
function escapePath(source: string) {
return source.replace(/ /g, "\\ ");
}
/**
* @see {@link https://github.com/cmake-js/cmake-js?tab=readme-ov-file#usage} for details on the template used
* @returns The contents of a CMakeLists.txt file
*/
export function bindingGypToCmakeLists({
gyp,
projectName,
napiVersion = DEFAULT_NAPI_VERSION,
executeCmdExpansions = true,
unsupportedBehaviour = "skip",
transformWinPathsToPosix = true,
}: GypToCmakeListsOptions): string {
function mapExpansion(value: string): string[] {
if (!isCmdExpansion(value)) {
return [value];
} else if (executeCmdExpansions) {
const cmd = value.trim().replace(/^<!@?/, "");
const output = cp.execSync(cmd, { encoding: "utf-8" }).trim();
// Split on whitespace, if the expansion starts with "<!@"
return value.trim().startsWith("<!@") ? output.split(/\s/) : [output];
} else if (unsupportedBehaviour === "throw") {
throw new Error(`Unsupported command expansion: ${value}`);
} else if (unsupportedBehaviour === "warn") {
console.warn(`Unsupported command expansion: ${value}`);
}
return [value];
}
function transformPath(input: string) {
if (transformWinPathsToPosix) {
return input.split(path.win32.sep).join(path.posix.sep);
} else {
return input;
}
}
const lines: string[] = [
"cmake_minimum_required(VERSION 3.15)",
//"cmake_policy(SET CMP0091 NEW)",
//"cmake_policy(SET CMP0042 NEW)",
`project(${projectName})`,
"",
`add_compile_definitions(-DNAPI_VERSION=${napiVersion})`,
];
for (const target of gyp.targets) {
const { target_name: targetName } = target;
// TODO: Handle "conditions"
// TODO: Handle "defines"
// TODO: Handle "cflags"
// TODO: Handle "ldflags"
const escapedJoinedSources = target.sources
.flatMap(mapExpansion)
.map(transformPath)
.map(escapePath)
.join(" ");
const escapedJoinedIncludes = (target.include_dirs || [])
.flatMap(mapExpansion)
.map(transformPath)
.map(escapePath)
.join(" ");
lines.push(
"",
`add_library(${targetName} SHARED ${escapedJoinedSources} \${CMAKE_JS_SRC})`,
`set_target_properties(${targetName} PROPERTIES PREFIX "" SUFFIX ".node")`,
`target_include_directories(${targetName} PRIVATE ${escapedJoinedIncludes} \${CMAKE_JS_INC})`,
`target_link_libraries(${targetName} PRIVATE \${CMAKE_JS_LIB})`,
`target_compile_features(${targetName} PRIVATE cxx_std_17)`
// or
// `set_target_properties(${targetName} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO)`,
);
}
// Adding this post-amble from the template, although not used by react-native-node-api
lines.push(
"",
"if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)",
" # Generate node.lib",
" execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})",
"endif()"
);
return lines.join("\n");
}