-
Notifications
You must be signed in to change notification settings - Fork 525
Open
Description
When using the cc
crate...
what is the proper way to set up build.rs
and/or Cargo.toml
so that cargo
will automatically recompile and relink the C/C++ files if they are changed since the last compilation? Maybe even list the local header files so changing them will trigger recompilation/relink as well?
Alternatively, what is the proper way to force cargo
to recompile all the C/C++ files?
Right now I can always remove the target/{debug,release}
directories to force recompilation but it seems like a hack.
Activity
dot-asm commentedon Dec 20, 2022
build.rs is executed whenever any file from the
cargo package --list
output is changed. So if you didn't list your C files in theinclude
directive in your Cargo.toml yet, it might be time. This is assuming that you'd eventually have to do that, as you're likely to publish your crate. If not, then you would findprintln!("cargo:rerun-if-changed=dir/ect/ory");
in your build.rs useful.It should be noted that none of this is actually cc-rs-specific, it's how cargo works in general.
orenbenkiki commentedon Dec 22, 2022
It sounds as though I should expect the C compiler to be invoked if any of the files in
cargo package --list
were changed. Did I understand this right?Two points then:
Even if it did work this way, that would be sub-optimal.
In principle there should be a separate list of files which trigger C compilation (which would make this a specific issue for the
cc
crate). Of course "ideally" there should be a list of dependencies for each separate.c
file to be compiled (that is, the list of.h
files it includes), so not all the.c
files would be compiled, just these that needed to. I guess it is a matter of deciding "how much likemake
do we wantcc
to be".It isn't a huge deal as long as these files are small. I can live with "all C object files depend on all the package files".
More importantly, it doesn't seem to work for me.
I ensured that
cargo package --list
did list the.c
files. It did even without an explicitinclude
directive inCargo.toml
, but I added one anyway and also listed the.h
files in it.Regardless, if I
touch
any of the.c
/.h
files, thencc
does not trigger re-compilation.I'm attaching a small with_c.zip file which demonstrates the problem - see
RUNME.sh
and the results I get inRUNME.log
.dot-asm commentedon Dec 22, 2022
As already implied, the question is when does cargo execute the build.rs. That's all to it. The fact that build.rs invokes C compiler is immaterial to the said decision.
Ah! It ought to be one of the recent modifications that broke it. It does work if you specify the dependency as
cc = "<=1.0.73"
... Not that I insist on doing this, but at least there is an explanation for why it stopped working the described way.It's by cargo's design, we have to accept it.
It sounds like you'd be better off using cmake-rs. Idea would be to have cargo detect a change and hand it off to cmake to identify what actually needs to be done. Replicating the make functionality in cc-rs would probably be deemed out of this project's scope...
dot-asm commentedon Dec 22, 2022
More specifically emission of
cargo:rerun-if-env-changed=<this-n-that>
in 1.0.74. Collateral problem here is that one single rerun-if apparently puts aside the internal cargo decision making mechanism. You can suppress the referred directives with.emit_rerun_if_env_changed(false)
method.orenbenkiki commentedon Dec 22, 2022
Thanks for the clarification. As long as my C code is trivial,
cc
will do the trick. For larger, more complex projects,cmake-rs
might be better. Good to know the options.Yes, using 1.0.73 does fix the issue for me. Thanks!
thomcc commentedon Dec 22, 2022
I’m on vacation now, but I’ll investigate what broke in 1.0.74 when I get back.
Note that pinning a version like that will cause problems for your users down the line, since if another crate in the dependency graph depends on a later version of cc, cargo will error (it only duplicates versions if they would be semver incompatible).
orenbenkiki commentedon Dec 22, 2022
Noted - thanks for the warning.
Happy holidays!
bw-itis-archival commentedon Feb 22, 2024
Is there anything more on this? I just ran into it in my project and it's quite a surprise when c files don't recompile (especially since they sometimes do - if you have errors and compilation fails, it will re-run on a new
cargo build
, but otherwise I need tocargo clean
and rebuild all the rust code as well to get c to recompile).I've tried adding
.emit_rerun_if_env_changed(false)
to thecc::Build
chain in mybuild.rs
but it doesn't seem to make any difference.bw-itis-archival commentedon Feb 22, 2024
If I add
println!("cargo:rerun-if-changed=src");
tobuild.rs
this does trigger a rebuild on changes (all my .c and .h files are insrc
).NobodyXu commentedon Feb 22, 2024
Maybe we could add a new function
emit_rerun_if_src_changed
for this that is set tofalse
by default for backwards compatibility?