Skip to content

Commit 6cfac38

Browse files
authored
Rework Makefile; dependency tracking (#7975)
* Rework Makefile; dependency tracking * Review change * Restore "make build" as default target, use .yarn/install-state.gz as stamp * Try to fix build * Update AGENTS.md
1 parent f3bd0d0 commit 6cfac38

File tree

6 files changed

+210
-68
lines changed

6 files changed

+210
-68
lines changed

AGENTS.md

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,32 @@ This file provides guidance to AI coding assistants when working with code in th
55
## Quick Start: Essential Commands
66

77
```bash
8-
# Build and test
9-
make && make test
8+
# Build the platform toolchain (default target)
9+
make
10+
11+
# Build the platform toolchain + stdlib
12+
make lib
13+
14+
# Build the platform toolchain + stdlib and run tests
15+
make test
16+
17+
# Format code
18+
make format
1019

11-
# Format and check code
12-
make format && make checkformat
20+
# Check formatting
21+
make checkformat
1322
```
1423

24+
The Makefile’s targets build on each other in this order:
25+
26+
1. `yarn-install` runs automatically for targets that need JavaScript tooling (lib, playground, tests, formatting, etc.).
27+
2. `build` (default target) builds the toolchain binaries (all copied into `packages/@rescript/<platform>/bin`):
28+
- `compiler` builds the dune executables (`bsc`, `bsb_helper`, `rescript-*`, `ounit_tests`, etc.).
29+
- `rewatch` builds the Rust-based ReScript build system and CLI.
30+
- `ninja` bootstraps the ninja binary (part of the legacy build system).
31+
3. `lib` uses those toolchain outputs to build the runtime sources.
32+
4. Test targets (`make test`, `make test-syntax`, etc.) reuse everything above.
33+
1534
## ⚠️ Critical Guidelines & Common Pitfalls
1635

1736
- **We are NOT bound by OCaml compatibility** - The ReScript compiler originated as a fork of the OCaml compiler, but we maintain our own AST and can make breaking changes. Focus on what's best for ReScript's JavaScript compilation target.

CONTRIBUTING.md

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,39 +71,47 @@ You can also open this dev container with [GitHub Codespaces](https://github.com
7171

7272
## Building the Compiler
7373

74-
The compiler binaries themselves can be built directly with dune as follows:
74+
To build the compiler, the build tools (rewatch and ninja), and the ReScript runtime/standard library, just run:
75+
76+
Main targets:
7577

7678
```sh
77-
# One off build
78-
dune build
79+
# Build the compiler and the build tools (rewatch and ninja)
80+
make
81+
82+
# Build the runtime/standard library
83+
make lib
7984

80-
# Watch mode
81-
dune build -w
85+
# Run the tests
86+
make test
8287
```
8388

84-
For all additional operations, a Makefile is provided:
89+
Additional targets:
8590

8691
```sh
87-
# Build the compiler using dune and copy the exes into the platform dir
88-
make
92+
# Build the compiler executables only
93+
make compiler
8994

90-
# Build the ninja build tool
91-
make ninja
95+
# Build rewatch only
96+
make rewatch
9297

93-
# Build the ReScript standard library using ninja and the compiler
94-
make lib
95-
96-
# Run compiler tests
97-
make test
98+
# Build the ninja tool only
99+
make ninja
98100

99101
# Run syntax tests
100102
make test-syntax
101103

102104
# Run syntax tests including roundtrip tests
103105
make test-syntax-roundtrip
104106

105-
# Populate lib/ocaml and update artifact list
107+
# Update artifact list
106108
make artifacts
109+
110+
# Format code
111+
make format
112+
113+
# Check formatting
114+
make checkformat
107115
```
108116

109117
## Coding Style

Makefile

Lines changed: 161 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,217 @@
11
SHELL = /bin/bash
22

3+
ifeq ($(OS),Windows_NT)
4+
PLATFORM_EXE_EXT = .exe
5+
else
6+
PLATFORM_EXE_EXT =
7+
endif
8+
9+
ifneq ($(OS),Windows_NT)
10+
UNAME_S := $(shell uname -s)
11+
UNAME_M := $(shell uname -m)
12+
endif
13+
14+
ifeq ($(OS),Windows_NT)
15+
RESCRIPT_PLATFORM := win32-x64
16+
else ifeq ($(UNAME_S),Darwin)
17+
ifeq ($(UNAME_M),arm64)
18+
RESCRIPT_PLATFORM := darwin-arm64
19+
else
20+
RESCRIPT_PLATFORM := darwin-x64
21+
endif
22+
else ifeq ($(UNAME_S),Linux)
23+
ifeq ($(UNAME_M),aarch64)
24+
RESCRIPT_PLATFORM := linux-arm64
25+
else ifeq ($(UNAME_M),arm64)
26+
RESCRIPT_PLATFORM := linux-arm64
27+
else
28+
RESCRIPT_PLATFORM := linux-x64
29+
endif
30+
else
31+
$(error Unsupported platform $(UNAME_S)-$(UNAME_M))
32+
endif
33+
34+
define COPY_EXE
35+
cp $1 $2
36+
chmod 755 $2
37+
$(if $(filter Windows_NT,$(OS)),,strip $2)
38+
endef
39+
40+
# Directories
41+
42+
BIN_DIR := packages/@rescript/$(RESCRIPT_PLATFORM)/bin
43+
RUNTIME_DIR := packages/@rescript/runtime
344
DUNE_BIN_DIR = ./_build/install/default/bin
445

5-
build: ninja rewatch
46+
# Build stamps
47+
48+
# Yarn creates `.yarn/install-state.gz` whenever dependencies are installed.
49+
# Using that file as our stamp ensures manual `yarn install` runs are detected.
50+
YARN_INSTALL_STAMP := .yarn/install-state.gz
51+
# Dune updates `_build/log` for every build invocation, even when run manually.
52+
# Treat that log file as the compiler build stamp so manual `dune build`
53+
# keeps Make targets up to date.
54+
COMPILER_BUILD_STAMP := _build/log
55+
# Runtime workspace touches this stamp (packages/@rescript/runtime/.buildstamp)
56+
# after running `yarn workspace @rescript/runtime build`, which now runs `touch`
57+
# as part of its build script.
58+
RUNTIME_BUILD_STAMP := packages/@rescript/runtime/.buildstamp
59+
60+
# Default target
61+
62+
build: compiler rewatch ninja
63+
64+
# Yarn
65+
66+
WORKSPACE_PACKAGE_JSONS := $(shell find packages -path '*/lib' -prune -o -name package.json -print)
67+
YARN_INSTALL_SOURCES := package.json yarn.lock yarn.config.cjs .yarnrc.yml $(WORKSPACE_PACKAGE_JSONS)
68+
69+
yarn-install: $(YARN_INSTALL_STAMP)
70+
71+
$(YARN_INSTALL_STAMP): $(YARN_INSTALL_SOURCES)
72+
yarn install
73+
touch $@
74+
75+
# Ninja
76+
77+
NINJA_SOURCES = $(wildcard ninja/src/*.cc ninja/src/*.h) $(wildcard ninja/*.py)
78+
NINJA_EXE = $(BIN_DIR)/ninja.exe
79+
80+
ninja: $(NINJA_EXE)
81+
82+
ninja/ninja: $(NINJA_SOURCES)
83+
ifeq ($(OS),Darwin)
84+
export CXXFLAGS="-flto"
85+
endif
86+
cd ninja && python3 configure.py --bootstrap --verbose
87+
88+
$(NINJA_EXE): ninja/ninja
89+
$(call COPY_EXE,$<,$@)
90+
91+
clean-ninja:
92+
rm -rf $(NINJA_EXE) ninja/build.ninja ninja/build ninja/misc/__pycache__ ninja/ninja
93+
94+
# Rewatch
95+
96+
REWATCH_SOURCES = $(shell find rewatch/src -name '*.rs') rewatch/Cargo.toml rewatch/Cargo.lock rewatch/rust-toolchain.toml
97+
RESCRIPT_EXE = $(BIN_DIR)/rescript.exe
98+
99+
rewatch: $(RESCRIPT_EXE)
100+
101+
$(RESCRIPT_EXE): rewatch/target/debug/rescript$(PLATFORM_EXE_EXT)
102+
$(call COPY_EXE,$<,$@)
103+
104+
rewatch/target/debug/rescript$(PLATFORM_EXE_EXT): $(REWATCH_SOURCES)
105+
cargo build --manifest-path rewatch/Cargo.toml
106+
107+
clean-rewatch:
108+
cargo clean --manifest-path rewatch/Cargo.toml && rm -rf rewatch/target && rm -f $(RESCRIPT_EXE)
109+
110+
# Compiler
111+
112+
COMPILER_SOURCE_DIRS := compiler tests analysis tools
113+
COMPILER_SOURCES = $(shell find $(COMPILER_SOURCE_DIRS) -type f \( -name '*.ml' -o -name '*.mli' -o -name '*.dune' -o -name dune -o -name dune-project \))
114+
COMPILER_BIN_NAMES := bsc bsb_helper rescript-legacy rescript-editor-analysis rescript-tools
115+
COMPILER_EXES := $(addsuffix .exe,$(addprefix $(BIN_DIR)/,$(COMPILER_BIN_NAMES)))
116+
COMPILER_DUNE_BINS := $(addsuffix $(PLATFORM_EXE_EXT),$(addprefix $(DUNE_BIN_DIR)/,$(COMPILER_BIN_NAMES)))
117+
118+
compiler: $(COMPILER_EXES)
119+
120+
define MAKE_COMPILER_COPY_RULE
121+
$(BIN_DIR)/$(1).exe: $(DUNE_BIN_DIR)/$(1)$(PLATFORM_EXE_EXT)
122+
$$(call COPY_EXE,$$<,$$@)
123+
endef
124+
125+
$(foreach bin,$(COMPILER_BIN_NAMES),$(eval $(call MAKE_COMPILER_COPY_RULE,$(bin))))
126+
127+
# "touch" after dune build to make sure that the binaries' timestamps are updated
128+
# even if the actual content of the sources hasn't changed.
129+
$(COMPILER_BUILD_STAMP): $(COMPILER_SOURCES)
6130
dune build
7-
./scripts/copyExes.js --compiler
131+
@$(foreach bin,$(COMPILER_DUNE_BINS),touch $(bin);)
8132

9-
watch:
10-
dune build -w
133+
$(COMPILER_DUNE_BINS): $(COMPILER_BUILD_STAMP) ;
11134

12-
bench:
13-
$(DUNE_BIN_DIR)/syntax_benchmarks
135+
clean-compiler:
136+
dune clean && rm -f $(COMPILER_EXES) $(COMPILER_BUILD_STAMP)
137+
138+
# Runtime / stdlib
139+
140+
RUNTIME_SOURCES := $(shell find $(RUNTIME_DIR) -path '$(RUNTIME_DIR)/lib' -prune -o -type f \( -name '*.res' -o -name '*.resi' -o -name 'rescript.json' \) -print)
141+
142+
lib: $(RUNTIME_BUILD_STAMP)
14143

15-
dce:
16-
reanalyze.exe -dce-cmt _build/default/compiler
144+
$(RUNTIME_BUILD_STAMP): $(RUNTIME_SOURCES) $(COMPILER_EXES) $(RESCRIPT_EXE) | $(YARN_INSTALL_STAMP)
145+
yarn workspace @rescript/runtime build
146+
147+
clean-lib:
148+
yarn workspace @rescript/runtime rescript clean
149+
rm -f $(RUNTIME_BUILD_STAMP)
17150

18-
rewatch:
19-
cargo build --manifest-path rewatch/Cargo.toml --release
20-
./scripts/copyExes.js --rewatch
151+
# Tests / artifacts / analysis
21152

22-
ninja/ninja:
23-
./scripts/buildNinjaBinary.js
153+
artifacts: lib
154+
./scripts/updateArtifactList.js
24155

25-
ninja: ninja/ninja
26-
./scripts/copyExes.js --ninja
156+
bench: $(COMPILER_BUILD_STAMP)
157+
$(DUNE_BIN_DIR)/syntax_benchmarks
27158

28-
test: build lib
159+
test: lib ninja | $(YARN_INSTALL_STAMP)
29160
node scripts/test.js -all
30161

31-
test-analysis:
162+
test-analysis: | $(YARN_INSTALL_STAMP)
32163
make -C tests/analysis_tests clean test
33164

34-
test-tools:
165+
test-tools: | $(YARN_INSTALL_STAMP)
35166
make -C tests/tools_tests clean test
36167

37-
test-syntax:
168+
test-syntax: | $(YARN_INSTALL_STAMP)
38169
./scripts/test_syntax.sh
39170

40-
test-syntax-roundtrip:
171+
test-syntax-roundtrip: | $(YARN_INSTALL_STAMP)
41172
ROUNDTRIP_TEST=1 ./scripts/test_syntax.sh
42173

43-
test-gentype:
174+
test-gentype: | $(YARN_INSTALL_STAMP)
44175
make -C tests/gentype_tests/typescript-react-example clean test
45176
make -C tests/gentype_tests/stdlib-no-shims clean test
46177

47-
test-rewatch:
178+
test-rewatch: $(RESCRIPT_EXE) | $(YARN_INSTALL_STAMP)
48179
./rewatch/tests/suite-ci.sh
49180

50181
test-all: test test-gentype test-analysis test-tools test-rewatch
51182

52-
reanalyze:
53-
reanalyze.exe -set-exit-code -all-cmt _build/default/compiler _build/default/tests -exclude-paths compiler/outcome_printer,compiler/ml,compiler/frontend,compiler/ext,compiler/depends,compiler/core,compiler/common,compiler/cmij,compiler/bsb_helper,compiler/bsb
54-
55-
lib:
56-
yarn workspace @rescript/runtime build
57-
58-
artifacts: lib
59-
./scripts/updateArtifactList.js
60-
61183
# Builds the core playground bundle (without the relevant cmijs files for the runtime)
62-
playground:
184+
playground: | $(YARN_INSTALL_STAMP)
63185
dune build --profile browser
64186
cp -f ./_build/default/compiler/jsoo/jsoo_playground_main.bc.js packages/playground/compiler.js
65187

66188
# Creates all the relevant core and third party cmij files to side-load together with the playground bundle
67-
playground-cmijs: artifacts
189+
playground-cmijs: | $(YARN_INSTALL_STAMP) # should also depend on artifacts, but that causes an attempt to copy binaries for JSOO
68190
yarn workspace playground build
69191

70192
# Builds the playground, runs some e2e tests and releases the playground to the
71193
# Cloudflare R2 (requires Rclone `rescript:` remote)
72-
playground-release: playground playground-cmijs
194+
playground-release: playground playground-cmijs | $(YARN_INSTALL_STAMP)
73195
yarn workspace playground test
74196
yarn workspace playground upload-bundle
75197

76-
format:
198+
format: | $(YARN_INSTALL_STAMP)
77199
./scripts/format.sh
78200

79-
checkformat:
201+
checkformat: | $(YARN_INSTALL_STAMP)
80202
./scripts/format_check.sh
81203

82204
clean-gentype:
83205
make -C tests/gentype_tests/typescript-react-example clean
84206
make -C tests/gentype_tests/stdlib-no-shims clean
85207

86-
clean-rewatch:
87-
cargo clean --manifest-path rewatch/Cargo.toml && rm -f rewatch/rewatch
88-
89-
clean-lib:
90-
yarn workspace @rescript/runtime rescript clean
91-
92-
clean: clean-lib
93-
dune clean
208+
clean-tests: clean-gentype
94209

95-
clean-all: clean clean-gentype clean-rewatch
210+
clean: clean-lib clean-compiler clean-rewatch clean-ninja
96211

97212
dev-container:
98213
docker build -t rescript-dev-container docker
99214

100215
.DEFAULT_GOAL := build
101216

102-
.PHONY: build watch rewatch ninja bench dce test test-syntax test-syntax-roundtrip test-gentype test-analysis test-tools test-all lib playground playground-cmijs playground-release artifacts format checkformat clean-gentype clean-rewatch clean clean-all dev-container
217+
.PHONY: yarn-install build ninja rewatch compiler lib artifacts bench test test-analysis test-tools test-syntax test-syntax-roundtrip test-gentype test-rewatch test-all playground playground-cmijs playground-release format checkformat clean-ninja clean-rewatch clean-compiler clean-lib clean-gentype clean-tests clean dev-container
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
lib/bs
22
lib/ocaml
33
*.lock
4+
.buildstamp

packages/@rescript/runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
},
4141
"scripts": {
4242
"clean": "rescript clean",
43-
"build": "rescript build",
43+
"build": "rescript build && touch .buildstamp",
4444
"cppo": "node scripts/cppo.js"
4545
},
4646
"devDependencies": {

scripts/buildNinjaBinary.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,4 @@ if (platform === "win32") {
1616
process.env.CXXFLAGS = "-flto";
1717
}
1818
execSync(buildCommand, { stdio: [0, 1, 2], cwd: ninjaDir });
19-
execSync("strip ninja", { stdio: [0, 1, 2], cwd: ninjaDir });
2019
}

0 commit comments

Comments
 (0)