diff --git a/changes/build-ir-in-temp.md b/changes/build-ir-in-temp.md new file mode 100644 index 00000000..9d6f2cb5 --- /dev/null +++ b/changes/build-ir-in-temp.md @@ -0,0 +1,7 @@ +bump: patch +type: fix +**`ludic build` keeps its LLVM IR out of the project.** The intermediate `.ll` was written beside +the binary (`build/.ll`) and deleted after linking, so a project's tree held one for the +length of every build, and two builds at once deleted each other's - which surfaced as a +`clang: no such file` that read exactly like a compile error. It now goes to the run's own +temporary directory and goes with it. `--save-temps` still keeps it at `build/.ll`. diff --git a/tools/ludic-cli/build.ludic b/tools/ludic-cli/build.ludic index aade239d..4a1dbd2d 100644 --- a/tools/ludic-cli/build.ludic +++ b/tools/ludic-cli/build.ludic @@ -34,7 +34,11 @@ function compile_app(src: pointer, out: pointer, mode: int, save: bool) -> bool let odir = dir_of_path(out) if len(odir) > 0 { shell(`mkdir -p {odir}`) } shell("mkdir -p build") - let ll = `{out}.ll` + # The IR is a scratch file: it goes to this run's own temp directory, never beside the + # binary, so a project's tree never holds one and two builds at once cannot delete each + # other's. --save-temps asks to read it, and keeps it at {out}.ll. + var ll = `{out}.ll` + if not save { ll = tmp_path(`{file_of_path(out)}.ll`) } # On Windows the compiler links too: ludicc knows the Windows runtime's files and # libraries (win32.ll, xaudio2, opengl32 ...), so saying them again here would be a @@ -128,6 +132,13 @@ function threads_link_flags(ll: pointer) -> pointer { return ` {ludic_home()}runtime/native/threads.ll` } +# the file part of a path: everything after the last '/' +function file_of_path(p: pointer) -> pointer { + let d = dir_of_path(p) + if len(d) == 0 { return p } + return p[len(d) + 1..len(p)] +} + # the directory part of a path, without the trailing '/' ("" when there is none) function dir_of_path(p: pointer) -> pointer { var last = -1