Skip to content

Commit 718e986

Browse files
committed
Extract bsc arg collection for different systems. Apply RESCRIPT_RUNTIME to rewatch
1 parent b108dfb commit 718e986

File tree

4 files changed

+204
-204
lines changed

4 files changed

+204
-204
lines changed

server/src/bsc-args/bsb.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import * as path from "path";
2+
import fs from "fs";
3+
import { IncrementallyCompiledFileInfo } from "../incrementalCompilation";
4+
import { buildNinjaPartialPath } from "../constants";
5+
6+
export type BsbCompilerArgs = string[];
7+
8+
export async function getBsbBscArgs(
9+
entry: IncrementallyCompiledFileInfo,
10+
): Promise<BsbCompilerArgs | null> {
11+
const buildNinjaPath = path.resolve(
12+
entry.project.rootPath,
13+
buildNinjaPartialPath,
14+
);
15+
16+
let stat: fs.Stats;
17+
try {
18+
stat = await fs.promises.stat(buildNinjaPath);
19+
} catch {
20+
return null;
21+
}
22+
23+
const cache = entry.buildNinja;
24+
if (cache && cache.fileMtime >= stat.mtimeMs) {
25+
return cache.rawExtracted;
26+
}
27+
28+
const fh = await fs.promises.open(buildNinjaPath, "r");
29+
try {
30+
let captureNext = false;
31+
let haveAst = false;
32+
const captured: string[] = [];
33+
34+
for await (const rawLine of fh.readLines()) {
35+
const line = String(rawLine).trim();
36+
if (captureNext) {
37+
captured.push(line);
38+
captureNext = false;
39+
if (haveAst && captured.length === 2) break; // got ast + mij
40+
}
41+
if (line.startsWith("rule astj")) {
42+
captureNext = true;
43+
haveAst = true;
44+
} else if (line.startsWith("rule mij")) {
45+
captureNext = true;
46+
}
47+
}
48+
49+
if (captured.length !== 2) return null;
50+
51+
entry.buildNinja = {
52+
fileMtime: stat.mtimeMs,
53+
rawExtracted: captured,
54+
};
55+
return captured;
56+
} finally {
57+
await fh.close();
58+
}
59+
}

server/src/bsc-args/rewatch.ts

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import * as path from "path";
2+
import * as utils from "../utils";
3+
import * as cp from "node:child_process";
4+
import semver from "semver";
5+
import {
6+
debug,
7+
IncrementallyCompiledFileInfo,
8+
} from "../incrementalCompilation";
9+
import type { projectFiles } from "../projectFiles";
10+
import { findRuntime } from "../find-runtime";
11+
12+
export type RewatchCompilerArgs = {
13+
compiler_args: Array<string>;
14+
parser_args: Array<string>;
15+
};
16+
17+
export async function getRewatchBscArgs(
18+
projectsFiles: Map<string, projectFiles>,
19+
entry: IncrementallyCompiledFileInfo,
20+
): Promise<RewatchCompilerArgs | null> {
21+
const rewatchCacheEntry = entry.buildRewatch;
22+
23+
if (
24+
rewatchCacheEntry != null &&
25+
rewatchCacheEntry.lastFile === entry.file.sourceFilePath
26+
) {
27+
return Promise.resolve(rewatchCacheEntry.compilerArgs);
28+
}
29+
30+
try {
31+
const project = projectsFiles.get(entry.project.rootPath);
32+
if (project?.rescriptVersion == null) return null;
33+
let rewatchPath = path.resolve(
34+
entry.project.workspaceRootPath,
35+
"node_modules/@rolandpeelen/rewatch/rewatch",
36+
);
37+
let rescriptRewatchPath = null;
38+
if (
39+
semver.valid(project.rescriptVersion) &&
40+
semver.satisfies(project.rescriptVersion as string, ">11", {
41+
includePrerelease: true,
42+
})
43+
) {
44+
rescriptRewatchPath = await utils.findRewatchBinary(
45+
entry.project.workspaceRootPath,
46+
);
47+
}
48+
49+
if (
50+
semver.valid(project.rescriptVersion) &&
51+
semver.satisfies(project.rescriptVersion as string, ">=12.0.0-beta.1", {
52+
includePrerelease: true,
53+
})
54+
) {
55+
rescriptRewatchPath = await utils.findRescriptExeBinary(
56+
entry.project.workspaceRootPath,
57+
);
58+
}
59+
60+
if (rescriptRewatchPath != null) {
61+
rewatchPath = rescriptRewatchPath;
62+
if (debug()) {
63+
console.log(
64+
`Found rewatch binary bundled with v12: ${rescriptRewatchPath}`,
65+
);
66+
}
67+
} else {
68+
if (debug()) {
69+
console.log("Did not find rewatch binary bundled with v12");
70+
}
71+
}
72+
73+
const rewatchArguments = semver.satisfies(
74+
project.rescriptVersion,
75+
">=12.0.0-beta.2",
76+
{ includePrerelease: true },
77+
)
78+
? ["compiler-args", entry.file.sourceFilePath]
79+
: [
80+
"--rescript-version",
81+
project.rescriptVersion,
82+
"--compiler-args",
83+
entry.file.sourceFilePath,
84+
];
85+
const bscExe = await utils.findBscExeBinary(
86+
entry.project.workspaceRootPath,
87+
);
88+
const env = {};
89+
if (bscExe != null) {
90+
(env as any)["RESCRIPT_BSC_EXE"] = bscExe;
91+
}
92+
93+
// TODO: We should check a potential configured value
94+
// Users should be able to provide this themselves if they like.
95+
const rescriptRuntimes = await findRuntime(entry.project.workspaceRootPath);
96+
97+
if (debug()) {
98+
if (rescriptRuntimes.length === 0) {
99+
console.log(
100+
`Did not find @rescript/runtime directory for ${entry.project.workspaceRootPath}`,
101+
);
102+
} else if (rescriptRuntimes.length > 1) {
103+
console.warn(
104+
`Found multiple @rescript/runtime directories, using the first one as RESCRIPT_RUNTIME: ${rescriptRuntimes.join(", ")}`,
105+
);
106+
} else {
107+
console.log(
108+
`Found @rescript/runtime directory: ${rescriptRuntimes.join(", ")}`,
109+
);
110+
}
111+
}
112+
113+
if (rescriptRuntimes.length > 0) {
114+
(env as any)["RESCRIPT_RUNTIME"] = rescriptRuntimes[0];
115+
} else {
116+
// TODO: if no runtime was found, we should let the user know
117+
}
118+
119+
const compilerArgs = JSON.parse(
120+
cp.execFileSync(rewatchPath, rewatchArguments, { env }).toString().trim(),
121+
) as RewatchCompilerArgs;
122+
123+
entry.buildRewatch = {
124+
lastFile: entry.file.sourceFilePath,
125+
compilerArgs: compilerArgs,
126+
};
127+
128+
return compilerArgs;
129+
} catch (e) {
130+
console.error(e);
131+
return null;
132+
}
133+
}

0 commit comments

Comments
 (0)