Skip to content

Commit 827be16

Browse files
cknittclaude
andauthored
Replace lib/bs and lib/ocaml with a flat lib/rescript (#9245)
* Write each package's build artifacts flat to lib/rescript Why: Every artifact existed in lib/bs, nested like the sources, and again in lib/ocaml, flat, and lib/bs also held copies of the sources and the generated JavaScript (#9151). The build now writes one flat lib/rescript. Layout modified (artifact directory of a package): Before (text): lib/bs/src/A.ast lib/bs/src/A.cmi lib/bs/src/A.res lib/bs/src/A.js lib/bs/.compiler.log lib/bs/compiler-info.json lib/bs/.sourcedirs.json lib/bs/build.ninja lib/ocaml/A.ast lib/ocaml/A.cmi lib/ocaml/A.cmj lib/ocaml/A.cmt lib/ocaml/A.res lib/build.lock lib/watch.lock After (text): lib/rescript/A.ast lib/rescript/A.cmi lib/rescript/A.cmj lib/rescript/A.cmt lib/rescript/.compiler.log lib/rescript/compiler-info.json lib/rescript/.sourcedirs.json lib/rescript/build.lock lib/rescript/watch.lock Before (text): bsc runs in lib/bs with -I ../ocaml; the stdlib is <runtime>/lib/ocaml After (text): bsc runs in lib/rescript with -I .; the stdlib is <runtime>/lib/rescript Publication modified (a compiled module's ASTs, interface and typed tree): Before (text): written to lib/bs by bsc, then copied to lib/ocaml After (text): held in the build file store until the request succeeded, then 1. the interface, only when it changed 2. the typed tree, which marks the module compiled each renamed into place, or written in place when the rename fails a failed compile: interface forgotten, AST dated back, partial typed tree published Freshness modified (Build_freshness, Compiler_info, namespace maps): Before (representation): source removed or must be parsed again ↦ AST removed no compiler-info.json, lib/ocaml/.compiler.log exists ↦ clean Ns.mlmap changed or Ns outputs missing ↦ compile namespace After (representation): source must be parsed again ↦ AST dated back to time 1, always parsed again compiler-info.json written once the clean decision is made compile namespace ↦ Ns.cmt removed until the compile publishes it lib/bs or lib/ocaml exists ↦ clean, which removes them The compiler keeps early cutoff with one copy of each interface: it replaces an interface it cannot read instead of failing, and a .cmj cut short after its digest no longer counts as unchanged. Stale public JavaScript is removed when an AST proves the build generated it; the JS mirror and the build.ninja marker are gone. Clean empties lib/rescript but for the lock files. Review: Why hold ASTs as well as interfaces? A failed parse used to leave its AST in lib/bs only; with one copy it would look current and the next build would skip the parse and lose the error. Review: Why rename into place, with an in-place write only as a fallback? A build killed during an in-place write leaves a truncated file, and a truncated typed tree with a fresh time counts as compiled for good. On Windows the rename fails while an editor has the file open without delete sharing, so the file is then written in place. Review: Why date an AST back instead of removing it? A later compile of the same build or watch session may still read it. Time 1 is below any real source time except the epoch, which is why such an AST is always parsed again. Review: What about a removed module's working .cmi, which cleanup deferred? It went to lib/bs, outside the include path. In lib/rescript it would let dependents compile against a deleted module, so it is removed at once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gGBR9g3DD93vrWbYzU Signed-off-by: Christoph Knittel <ck@cca.io> * Read compiled files from the flat lib/rescript in analysis and gentype Why: The tools found a module's compiled files through the nested lib/bs mirror of the sources and the source copies in lib/ocaml, which the previous commit removes. Each tool now looks a module up by its compiled file name: - analysis reads <pkg>/lib/rescript/<Module>[-Ns].cmt, the stdlib's compiled files from <runtime>/lib/rescript and its sources from the runtime package root, .sourcedirs.json from lib/rescript, and incremental files from lib/rescript/incremental; - reanalyze scans each package's lib/rescript, and its -cmt-root walk skips the editor's incremental directory; - gentype finds a dependency module's source directory in the header of its AST, read once per build, and maps a namespace module to its package root; it looks an imported module of the same package up as <Name>[-Ns].cmt, trying the compiler's spelling first, and reads typed trees through the build file store, which holds the one being compiled, without keeping them. Review: Why does the reanalyze snapshot move one line? The scan visited the nested source directories first and the build root last; one flat directory is scanned in name order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gGBR9g3DD93vrWbYzU Signed-off-by: Christoph Knittel <ck@cca.io> * Ship the runtime's lib/rescript and sources, and update CI, build tests and docs Why: The runtime package shipped lib/ocaml with copies of its sources; it now ships lib/rescript and its own sources at the package root, which analysis reads (#9151). The release artifact, its CI upload and the playground's cmij extraction take lib/rescript, its build state stays out of the package, and the ignore files name lib/rescript. Build tests read the in-source outputs that the JS mirror used to copy, and look for the debug IR, the belt interfaces and post-build paths under lib/rescript; the installation test looks for the watch lock there. The changelog fragment lists the new paths for tools that read the old ones and says that lib/rescript belongs in .gitignore. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gGBR9g3DD93vrWbYzU Signed-off-by: Christoph Knittel <ck@cca.io> --------- Signed-off-by: Christoph Knittel <ck@cca.io> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent cb4406e commit 827be16

127 files changed

Lines changed: 2539 additions & 2455 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/ci.yml‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -326,15 +326,16 @@ jobs:
326326
name: binaries-${{ matrix.node-target }}
327327
path: packages/@rescript/${{ matrix.node-target }}/bin
328328

329-
- name: "Upload artifacts: lib/ocaml"
329+
- name: "Upload artifacts: lib/rescript"
330330
if: matrix.upload_libs
331331
uses: actions/upload-artifact@v7
332332
with:
333-
name: lib-ocaml
333+
name: lib-rescript
334334
path: |
335-
packages/@rescript/runtime/lib/ocaml
336-
!packages/@rescript/runtime/lib/ocaml/*.ast
337-
!packages/@rescript/runtime/lib/ocaml/*.iast
335+
packages/@rescript/runtime/lib/rescript
336+
!packages/@rescript/runtime/lib/rescript/*.ast
337+
!packages/@rescript/runtime/lib/rescript/*.iast
338+
!packages/@rescript/runtime/lib/rescript/compiler-info.json
338339
339340
- name: Select API docs website branch
340341
id: api-docs-plan
@@ -423,7 +424,7 @@ jobs:
423424
- name: Download artifacts
424425
uses: actions/download-artifact@v8
425426
with:
426-
pattern: "@(binaries-*|lib-ocaml)"
427+
pattern: "@(binaries-*|lib-rescript)"
427428

428429
- name: Move artifacts into packages
429430
run: .github/workflows/moveArtifacts.sh

‎.github/workflows/moveArtifacts.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ check_statically_linked() {
2626
}
2727

2828
# rescript
29-
mv lib-ocaml packages/@rescript/runtime/lib/ocaml
29+
mv lib-rescript packages/@rescript/runtime/lib/rescript
3030

3131
# @rescript/{target}
3232
chmod +x binaries-*/*.exe

‎.github/workflows/publish.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ jobs:
112112
- name: Download artifacts
113113
uses: actions/download-artifact@v8
114114
with:
115-
pattern: "@(binaries-*|lib-ocaml)"
115+
pattern: "@(binaries-*|lib-rescript)"
116116

117117
- name: Move artifacts into packages
118118
run: .github/workflows/moveArtifacts.sh

‎.gitignore‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ node_modules
4949
_coverage/
5050
bisect*.coverage
5151

52-
lib/ocaml
52+
lib/rescript
5353
tests/build_tests/*/lib/
5454
#ignore temporary directory
5555
*.goog.js

‎CONTRIBUTING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ To view the typed tree of the file run:
262262
### Project
263263
264264
```sh
265-
make artifacts # Build compiler and standard library and populate lib/ocaml
265+
make artifacts # Build compiler and standard library and populate lib/rescript
266266
npm link
267267
cd myProject
268268
npm install

‎analysis/bin/main.ml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Options:
6464

6565
createInterface: print to stdout the interface file for src/MyFile.res
6666

67-
./rescript-editor-analysis.exe createInterface src/MyFile.res lib/bs/src/MyFile.cmi
67+
./rescript-editor-analysis.exe createInterface src/MyFile.res lib/rescript/MyFile.cmi
6868

6969
format: print to stdout the formatted version of the provided file
7070

@@ -127,10 +127,10 @@ let main () =
127127
let uri = Uri.from_path root_path in
128128
match Packages.find_root ~uri (Hashtbl.create 0) with
129129
| Some (`Bs root_path) -> (
130-
match Build_system.get_lib_bs root_path with
130+
match Build_system.get_artifact_dir root_path with
131131
| None -> print_endline "\"ERR\""
132-
| Some lib_bs ->
133-
Cache.delete_cache (Cache.target_file_from_lib_bs lib_bs);
132+
| Some artifact_dir ->
133+
Cache.delete_cache (Cache.target_file_from_artifact_dir artifact_dir);
134134
print_endline "\"OK\"")
135135
| _ -> print_endline "\"ERR: Did not find root \"")
136136
| [_; "completion"; path; line; col; current_file] ->

‎analysis/reanalyze/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Dead code analysis and other experimental analyses for ReScript.
1717
rescript-tools reanalyze -config
1818

1919
# Run DCE analysis on specific CMT directory
20-
rescript-tools reanalyze -dce-cmt path/to/lib/bs
20+
rescript-tools reanalyze -dce-cmt path/to/lib/rescript
2121

2222
# Run all analyses
2323
rescript-tools reanalyze -all

‎analysis/reanalyze/src/paths.ml‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,15 @@ type cmt_scan_entry = {
133133
This is a v2 extension produced by `rewatch` to support monorepos without requiring
134134
reanalyze-side package resolution.
135135
136-
The scan plan is a list of build roots (usually `<pkg>/lib/bs`) relative to the project root,
136+
The scan plan is a list of build roots (`<pkg>/lib/rescript`) relative to the project root,
137137
plus a list of subdirectories (relative to that build root) to scan for `.cmt/.cmti`.
138+
Build roots are flat, so the subdirectories are empty and each build root is scanned itself.
138139
139140
If missing, returns the empty list and callers should fall back to legacy behavior. *)
140141

141142
let read_cmt_scan () =
142143
let source_dirs_file =
143-
["lib"; "bs"; ".sourcedirs.json"]
144+
["lib"; "rescript"; ".sourcedirs.json"]
144145
|> List.fold_left Filename.concat run_config.bsb_project_root
145146
in
146147
let get_fn key fn json =

‎analysis/reanalyze/src/reanalyze.ml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ let collect_cmt_file_paths ~cmt_root : string list =
1515
let skip_dir =
1616
let base = Filename.basename dir in
1717
base = "node_modules" || base = "_esy"
18+
(* The editor's copies of compiled files. *)
19+
|| base = "incremental"
20+
&& Filename.basename (Filename.dirname dir) = "rescript"
1821
in
1922
if (not skip_dir) && Sys.file_exists abs_dir then
2023
if Sys.is_directory abs_dir then

‎analysis/src/build_system.ml‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,12 @@ let get_runtime_dir root_path =
4040
None))
4141
| true -> Some root_path
4242

43-
let get_lib_bs path = Files.if_exists (path /+ "lib" /+ "bs")
43+
(* A package's compiled files, flat in lib/rescript. *)
44+
let get_artifact_dir path = Files.if_exists (path /+ "lib" /+ "rescript")
4445

46+
(* The runtime's compiled files. Its sources are at the root of the runtime
47+
package, see [get_runtime_dir]. *)
4548
let get_stdlib base =
4649
match get_runtime_dir base with
4750
| None -> None
48-
| Some runtime_dir -> Some (runtime_dir /+ "lib" /+ "ocaml")
51+
| Some runtime_dir -> Some (runtime_dir /+ "lib" /+ "rescript")

0 commit comments

Comments
 (0)