ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.03k stars 2.49k forks source link

`zig cc` incorrectly caching object file when using incbin #16919

Open Ivan-Velickovic opened 1 year ago

Ivan-Velickovic commented 1 year ago

Zig Version

0.12.0-dev.152+411462e1c

Steps to Reproduce and Observed Behavior

Create a file called embed_file.S with this contents:

.section .embedded_file, "aw", @progbits
.global _embedded_file, _embedded_file_end
_embedded_file:
.incbin EMBEDDED_FILE_PATH
_embedded_file_end:

Create a file called test.txt with this contents:

initial data

Compile:

zig cc -c embed_file.S -DEMBEDDED_FILE_PATH=\"test.txt\"

Observe the hash of the object file:

$ sha256sum embed_file.o
$ e1a22524a93e71d57f7c03aeda06baae27d863971c58e4ea78443d68eb909177  embed_file.o

Change the contents of test.txt and recompile, you will observe that sha256sum produces the same hash, indicating that the object file has not changed, despite the contents of test.txt changing.

For context, I ran into this issue when embedded artifacts/other files in a C program and saw that when I updated the artifacts, the final ELF that was executing and using the artifacts did not update.

For now, I can remove the global Zig cache rm -r ~/.cache/zig and I get the behaviour I expect.

Expected Behavior

That when re-compiling with the contents of test.txt changed, that the object file is actually recompiled instead of the cached object file being used.

Thanks!

Ivan-Velickovic commented 1 year ago

Actually, it's not the macro options that are being cached, it's (I assume) to do with how incbin takes in the same filename and so the object isn't re-compiled.

A smaller example of the bug can be done with having this in embed_file.S instead:

.section .embedded_file, "aw", @progbits
.incbin "test.txt"

and using just zig cc -c embed_file.S.

Ivan-Velickovic commented 10 months ago

Would anyone be able to help me solve this bug? If it's quite non-trivial I can wait for someone familiar with the Zig compiler to fix it, but if someone's willing to give me some pointers as to what could be going wrong and where, I'd be happy to give it a shot.

andrewrk commented 5 months ago

Zig learns about the transitive dependencies of files given to Clang, including C and asm files, by passing dep file arguments:

https://github.com/ziglang/zig/blob/956f53beb09c07925970453d4c178c6feb53ba70/src/Compilation.zig#L5516-L5518

If the embedded file is missing from this file, then it is a clang bug and the next step is to file a report on that project.

Ivan-Velickovic commented 5 months ago

Great, thank you. I will do some digging then.

Ivan-Velickovic commented 5 months ago

I believe the reason out_dep_path is null is from the call here https://github.com/ziglang/zig/blob/956f53beb09c07925970453d4c178c6feb53ba70/src/Compilation.zig#L4604 where clangSupportsDepFile will return false since it's an assembly file.

I guess it is a bug with Clang then.

Ivan-Velickovic commented 5 months ago

Looks like there is already an open issue https://github.com/llvm/llvm-project/issues/54996.

mtnygard commented 2 months ago

While we wait for an upstream fix, is there a workaround that we could use in build.zig?