Skip to content

Commit 081ed58

Browse files
authored
Merge pull request #57 from EmbeddedEnterprises/cross-compile-default
fix: fix detection of default cross-compilation
2 parents 8672e2c + 7704d38 commit 081ed58

3 files changed

Lines changed: 123 additions & 23 deletions

File tree

README.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,18 @@ cmake-ts can build the projects with built-in configurations that are selected d
2424
cmake-ts build --config debug
2525
```
2626

27-
You can cross-compile by specifying the built-in cross configs
27+
You can cross-compile by specifying the built-in cross configs:
2828

2929
```bash
3030
cmake-ts build --config cross-win32-arm64-release
3131
```
3232

33+
Or by specifying the `npm_config_target_os` and `npm_config_target_arch` environment variables:
34+
35+
```bash
36+
npm_config_target_os=linux npm_config_target_arch=arm64 cmake-ts build
37+
```
38+
3339
### CLI Arguments
3440

3541
`build` command:
@@ -81,11 +87,11 @@ Options:
8187
- `darwin-arm64-node-release`
8288
- `darwin-arm64-electron-relwithdebinfo`
8389

84-
To explicitly indicate cross-compilation, prefix the config name with \`cross-\`:
90+
To explicitly indicate cross-compilation, prefix the config name with `cross-`:
8591

86-
- \`cross-win32-ia32-node-release\`
87-
- \`cross-linux-arm64-node-release\`
88-
- \`cross-darwin-x64-electron-relwithdebinfo\`
92+
- `cross-win32-ia32-node-release`
93+
- `cross-linux-arm64-node-release`
94+
- `cross-darwin-x64-electron-relwithdebinfo`
8995

9096
You can also define your own configs in the config file (package.json).
9197

src/config.ts

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,10 @@ export async function getBuildConfig(
6262

6363
// Platform
6464

65+
config.cross = detectCrossCompilation(globalConfig, config)
66+
6567
config.os ??= globalConfig.os ?? process.platform
6668
config.arch ??= globalConfig.arch ?? process.arch
67-
config.cross ??=
68-
globalConfig.cross ??
69-
(process.platform !== config.os ||
70-
(process.env.npm_config_target_os !== undefined && process.env.npm_config_target_os !== config.os) ||
71-
process.arch !== config.arch ||
72-
(process.env.npm_config_target_arch !== undefined && process.env.npm_config_target_arch !== config.arch))
7369

7470
// Runtime
7571

@@ -111,6 +107,55 @@ export async function getBuildConfig(
111107
return config as BuildConfiguration
112108
}
113109

110+
export function detectCrossCompilation(
111+
globalConfig: Partial<BuildConfigurations>,
112+
config: Partial<BuildConfiguration>,
113+
) {
114+
if (globalConfig.cross === true) {
115+
logger.debug("Cross compilation detected: globalConfig.cross is true")
116+
return true
117+
}
118+
if (config.os !== undefined && platforms.has(config.os as NodeJS.Platform) && config.os !== process.platform) {
119+
// if the config os is set, check if the current os is different from the config os
120+
logger.debug(
121+
`Cross compilation detected: config.os (${config.os}) differs from process.platform (${process.platform})`,
122+
)
123+
return true
124+
}
125+
if (
126+
config.arch !== undefined &&
127+
architectures.has(config.arch as NodeJS.Architecture) &&
128+
config.arch !== process.arch
129+
) {
130+
// if the config arch is set, check if the current arch is different from the config arch
131+
logger.debug(`Cross compilation detected: config.arch (${config.arch}) differs from process.arch (${process.arch})`)
132+
return true
133+
}
134+
if (
135+
process.env.npm_config_target_os !== undefined &&
136+
platforms.has(process.env.npm_config_target_os as NodeJS.Platform) &&
137+
process.env.npm_config_target_os !== process.platform
138+
) {
139+
// if the target os is set via npm_config_target_os, check if it is different from the config os
140+
logger.debug(
141+
`Cross compilation detected: npm_config_target_os (${process.env.npm_config_target_os}) differs from process.platform (${process.platform})`,
142+
)
143+
return true
144+
}
145+
if (
146+
process.env.npm_config_target_arch !== undefined &&
147+
architectures.has(process.env.npm_config_target_arch as NodeJS.Architecture) &&
148+
process.env.npm_config_target_arch !== process.arch
149+
) {
150+
// if the target arch is set via npm_config_target_arch, check if it is different from the config arch
151+
logger.debug(
152+
`Cross compilation detected: npm_config_target_arch (${process.env.npm_config_target_arch}) differs from process.arch (${process.arch})`,
153+
)
154+
return true
155+
}
156+
return false
157+
}
158+
114159
export function parseBuiltInConfigs(configName: string) {
115160
const parts = configName.split("-")
116161

test/config.test.ts

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import { join } from "path"
22
import { writeJson } from "fs-extra"
3-
import { afterEach, beforeEach, expect, suite, test } from "vitest"
3+
import { afterEach, beforeEach, expect, suite, test, vi } from "vitest"
44
import type { BuildCommandOptions, BuildConfiguration, BuildConfigurations, Options } from "../src/config-types.d.js"
5-
import { getBuildConfig, getConfigFile, parseBuildConfigs, parseBuiltInConfigs } from "../src/config.js"
5+
import {
6+
detectCrossCompilation,
7+
getBuildConfig,
8+
getConfigFile,
9+
parseBuildConfigs,
10+
parseBuiltInConfigs,
11+
} from "../src/config.js"
12+
import { logger } from "../src/lib.js"
613

714
suite("Config Functions", () => {
15+
logger.setLevel("debug")
16+
817
const mockBuildOptions: BuildCommandOptions = {
918
configs: [],
1019
addonSubdirectory: "",
@@ -35,8 +44,10 @@ suite("Config Functions", () => {
3544

3645
beforeEach(async () => {
3746
// Reset environment variables
38-
process.env.npm_config_target_arch = undefined
39-
process.env.npm_config_target_os = undefined
47+
// biome-ignore lint/performance/noDelete: https://github.com/biomejs/biome/issues/5643
48+
delete process.env.npm_config_target_arch
49+
// biome-ignore lint/performance/noDelete: https://github.com/biomejs/biome/issues/5643
50+
delete process.env.npm_config_target_os
4051

4152
// Create test package.json
4253
await writeJson(testPackageJsonPath, {
@@ -48,8 +59,10 @@ suite("Config Functions", () => {
4859

4960
afterEach(async () => {
5061
// Clean up environment variables
51-
process.env.npm_config_target_arch = undefined
52-
process.env.npm_config_target_os = undefined
62+
// biome-ignore lint/performance/noDelete: https://github.com/biomejs/biome/issues/5643
63+
delete process.env.npm_config_target_arch
64+
// biome-ignore lint/performance/noDelete: https://github.com/biomejs/biome/issues/5643
65+
delete process.env.npm_config_target_os
5366

5467
// Remove test package.json
5568
try {
@@ -122,7 +135,7 @@ suite("Config Functions", () => {
122135

123136
test("should handle cross compilation flags", async () => {
124137
const partialConfig: Partial<BuildConfiguration> = {
125-
os: "win32",
138+
os: process.platform === "win32" ? "linux" : "win32",
126139
arch: "x64",
127140
}
128141

@@ -131,7 +144,7 @@ suite("Config Functions", () => {
131144
expect(result.cross).toBe(true)
132145
})
133146

134-
test("should set cross flag when npm_config_target_arch differs from process.arch", async () => {
147+
test("should respect npm_config_target_arch when it matches config.arch", async () => {
135148
// Set npm_config_target_arch to a different architecture than the current one
136149
process.env.npm_config_target_arch = process.arch === "x64" ? "arm64" : "x64"
137150

@@ -146,19 +159,55 @@ suite("Config Functions", () => {
146159
expect(result.arch).toBe(process.env.npm_config_target_arch)
147160
})
148161

149-
test("should set cross flag when npm_config_target_arch differs from process.arch when no config file is provided", async () => {
162+
test("should respect config.arch when it matches process.arch", async () => {
163+
// Mock process.arch
164+
vi.spyOn(process, "arch", "get").mockReturnValue("arm64")
165+
166+
const partialConfig: Partial<BuildConfiguration> = {
167+
os: process.platform,
168+
arch: process.arch,
169+
}
170+
171+
console.log(process.arch, detectCrossCompilation(mockConfigFile, partialConfig))
172+
173+
const result = await getBuildConfig(mockBuildOptions, partialConfig, mockConfigFile)
174+
175+
expect(result.cross).toBe(false)
176+
expect(result.arch).toBe(process.arch)
177+
178+
vi.restoreAllMocks()
179+
})
180+
181+
test("should respect config.arch when it differs from process.arch", async () => {
182+
// Mock process.arch
183+
vi.spyOn(process, "arch", "get").mockReturnValue("arm64")
184+
185+
const partialConfig: Partial<BuildConfiguration> = {
186+
os: process.platform,
187+
arch: "x64", // Different from process.arch
188+
}
189+
190+
const result = await getBuildConfig(mockBuildOptions, partialConfig, mockConfigFile)
191+
192+
expect(result.cross).toBe(true)
193+
expect(result.arch).toBe("x64")
194+
195+
vi.restoreAllMocks()
196+
})
197+
198+
test("should respect npm_config_target_arch when it differs from process.arch", async () => {
150199
// Set npm_config_target_arch to a different architecture than the current one
151200
process.env.npm_config_target_arch = process.arch === "x64" ? "arm64" : "x64"
152201

153202
const partialConfig: Partial<BuildConfiguration> = {
154203
os: process.platform,
155-
arch: process.env.npm_config_target_arch as NodeJS.Architecture,
204+
arch: process.arch,
156205
}
157206

158-
const result = await getBuildConfig(mockBuildOptions, partialConfig, {})
207+
const result = await getBuildConfig(mockBuildOptions, partialConfig, mockConfigFile)
159208

160209
expect(result.cross).toBe(true)
161-
expect(result.arch).toBe(process.env.npm_config_target_arch)
210+
expect(result.arch).toBe(process.arch)
162211
})
163212

164213
test("should use default values when no config file is provided", async () => {

0 commit comments

Comments
 (0)