diff --git a/compiler/bin/main.ml b/compiler/bin/main.ml index bf40073..67b502e 100644 --- a/compiler/bin/main.ml +++ b/compiler/bin/main.ml @@ -878,6 +878,16 @@ let build_mode ?(deps : (string * string) list = []) ~(runtime : string option) Printf.eprintf "woc: %s\n" msg; exit 2 in + (* a fresh checkout has no target/ directories: create the output's + parent, so `-o /` works the way every gate and README + invokes it instead of failing on the temp file below *) + let rec mkdir_p d = + if d <> "" && d <> "." && d <> "/" && not (Sys.file_exists d) then begin + mkdir_p (Filename.dirname d); + (try Sys.mkdir d 0o755 with Sys_error _ -> ()) + end + in + mkdir_p (Filename.dirname out); let tmp = out ^ ".woc-build.tmp" in (* stale tmp from an interrupted earlier build must not survive: its permission bits would leak through, since Open_creat on an diff --git a/scripts/single-binary-smoke.sh b/scripts/single-binary-smoke.sh index 5a4eb33..bcb47ce 100755 --- a/scripts/single-binary-smoke.sh +++ b/scripts/single-binary-smoke.sh @@ -62,6 +62,21 @@ else ok "single-binary/build" fi +# ---- -o into a directory that does not exist yet --------------------------- +# A fresh checkout has no target/ anywhere (gitignored), and every example +# gate builds with `-o /target/`: `woc build` must create the +# output's parent rather than fail on its own temp file there. +FRESH="$WORK/fresh/target/app" +if ! timeout "$TIMEOUT" "$WOC" build "$SRC" -o "$FRESH" --runtime "$WOVM" \ + >"$WORK/fresh.out" 2>"$WORK/fresh.err"; then + rc=$? + bad "single-binary/build-into-missing-dir" "woc build exited $rc: $(head -1 "$WORK/fresh.err")" +elif [[ ! -x "$FRESH" ]]; then + bad "single-binary/build-into-missing-dir" "output missing or not executable: $FRESH" +else + ok "single-binary/build-into-missing-dir" +fi + # ---- relocate outside the repo, run with no args, diff -------------------- if [[ -x "$APP" ]]; then cp "$APP" "$ELSEWHERE/app"