Skip to content

rustc randomly fail to link with C program #111083

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
xclaesse opened this issue May 2, 2023 · 10 comments
Open

rustc randomly fail to link with C program #111083

xclaesse opened this issue May 2, 2023 · 10 comments
Labels
A-FFI Area: Foreign function interface (FFI) A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug.

Comments

@xclaesse
Copy link

xclaesse commented May 2, 2023

Here is a minimal test case to reproduce: https://github.com/xclaesse/rustc-bug.

I believe this is the same issue than #55931 initially discovered this issue while working on this Meson PR: mesonbuild/meson#11714.

I suspect the problem is when compiling both cdylib and staticlib for the same stuff.rs with the same crate name, they use some common intermediary files.

@jyn514 jyn514 added A-linkage Area: linking into static, shared libraries and binaries A-FFI Area: Foreign function interface (FFI) C-bug Category: This is a bug. labels May 2, 2023
@bjorn3
Copy link
Member

bjorn3 commented May 2, 2023

Are you using two separate rustc invocations or a single with two --crate-type arguments?

@xclaesse
Copy link
Author

xclaesse commented May 2, 2023

2 separate innovations running in parallel, see the makefile in my test case above.

@xclaesse
Copy link
Author

xclaesse commented May 2, 2023

If I'm right and rustc write temporary files (probably .o files) that could clash between both invocations, is there a way to tell rustc where to write its temp files? That way I can easily give a different dir to each invocations.

@bjorn3
Copy link
Member

bjorn3 commented May 2, 2023

You could add a different -Cmetadata argument between the two invocations. This should affect the name of the temporary files. However if possible I did recommend merging both rustc invocations. This cuts the required amount of cpu time almost in half as pretty much the only difference between the cdylib and staticlib crate types is the step in which the dynamic library is linked or the archive assembled. The rest of the compilation process is reused when you specify both crate types.

@xclaesse
Copy link
Author

xclaesse commented May 2, 2023

Ideally we should have a single invocation indeed, but that would require a bit more refactoring in Meson to work like that. I'll try -Cmetadata=value argument to see if that can work around the problem for now, thanks.

@xclaesse
Copy link
Author

xclaesse commented May 2, 2023

@bjorn3 I can confirm that passing -C metadata=foo to one command and -C metadata=bar to the other seems to fix the issue. I can also see that if I add --emit metadata both writes the same liba.rmeta file. However, I was expecting to get foo.rmeta and bar.rmeta, so I probably did not understand what -C metadata=foo does, is foo a temporary directory where it writes some files? Is there a way to tell rustc to not delete intermediary files?

@bjorn3
Copy link
Member

bjorn3 commented May 2, 2023

-Cmetadata doesn't affect the output name and location of the final artifact. It affects the "stable crate id" which is a hash that determines the identity of a crate. One of the things that determines the names of temporary artifacts is the "stable crate id". You can tell rustc to not delete temporary files using -Csave-temps. Most of them are stored in the directory passed to --out-dir (which defaults to the current working directory and is the location where the final cdylib/staticlib will be stored unless you explicitly give a different path), but some temporary files are stored in a random directory in /tmp.

@xclaesse
Copy link
Author

xclaesse commented May 2, 2023

Is there a downside in changing that "stable crate id" by adding the name of the final artifact to avoid conflicts? Like -Cmetadata=liba.a and -Cmetadata=liba.so?

Using different --out-dir also seems to fix the issue, but is there a way to only put temporary files there and not the final artifacts?

One thing I noticed with -Csave-temps is the conflicting liba.rmeta are automatically put in randimized temporary directory: rmetaN0c8S7/lib.rmeta and rmetapQ1cYv/lib.rmeta which makes sense, all other temporary files should be automatically moved to such directory IMHO. Or let CLI define that directory, Meson always create a per target private directory for similar cases when building C libraries.

@bjorn3
Copy link
Member

bjorn3 commented May 2, 2023

Is there a downside in changing that "stable crate id" by adding the name of the final artifact to avoid conflicts? Like -Cmetadata=liba.a and -Cmetadata=liba.so?

There shouldn't be. The "stable crate id" is only relevant when linking against a rust crate. The cdylib and staticlib crate types don't allow linking against it as rust crate anyway.

Using different --out-dir also seems to fix the issue, but is there a way to only put temporary files there and not the final artifacts?

You can combine --out-dir with --emit link=path/to/libfoo.a.

One thing I noticed with -Csave-temps is the conflicting liba.rmeta are automatically put in randimized temporary directory: rmetaN0c8S7/lib.rmeta and rmetapQ1cYv/lib.rmeta which makes sense, all other temporary files should be automatically moved to such directory IMHO.

Makes sense.

@xclaesse
Copy link
Author

xclaesse commented May 2, 2023

You can combine --out-dir with --emit link=path/to/libfoo.a.

Awesome, that's a workable solution for me I think. Thanks.

I still think this should be fixed at rustc level, even if it's not the indented usage, by ensuring temp files are put in randomized temp directories.

xclaesse added a commit to xclaesse/meson that referenced this issue May 2, 2023
Rustc does not produce object files we can reuse to build both
libraries. Ideally this should be done with a single target that has
both `--crate-type` arguments instead of having 2 different build rules.

As temporary workaround, build twice and ensure they don't get conflicts
in intermediary files created by rustc by passing target's private
directory as --out-dir.

See rust-lang/rust#111083.
xclaesse added a commit to xclaesse/meson that referenced this issue Aug 6, 2023
Rustc does not produce object files we can reuse to build both
libraries. Ideally this should be done with a single target that has
both `--crate-type` arguments instead of having 2 different build rules.

As temporary workaround, build twice and ensure they don't get conflicts
in intermediary files created by rustc by passing target's private
directory as --out-dir.

See rust-lang/rust#111083.
xclaesse added a commit to xclaesse/meson that referenced this issue Aug 23, 2023
Rustc does not produce object files we can reuse to build both
libraries. Ideally this should be done with a single target that has
both `--crate-type` arguments instead of having 2 different build rules.

As temporary workaround, build twice and ensure they don't get conflicts
in intermediary files created by rustc by passing target's private
directory as --out-dir.

See rust-lang/rust#111083.
xclaesse added a commit to xclaesse/meson that referenced this issue Aug 23, 2023
Rustc does not produce object files we can reuse to build both
libraries. Ideally this should be done with a single target that has
both `--crate-type` arguments instead of having 2 different build rules.

As temporary workaround, build twice and ensure they don't get conflicts
in intermediary files created by rustc by passing target's private
directory as --out-dir.

See rust-lang/rust#111083.
xclaesse added a commit to xclaesse/meson that referenced this issue Aug 24, 2023
Rustc does not produce object files we can reuse to build both
libraries. Ideally this should be done with a single target that has
both `--crate-type` arguments instead of having 2 different build rules.

As temporary workaround, build twice and ensure they don't get conflicts
in intermediary files created by rustc by passing target's private
directory as --out-dir.

See rust-lang/rust#111083.
xclaesse added a commit to xclaesse/meson that referenced this issue Sep 7, 2023
Rustc does not produce object files we can reuse to build both
libraries. Ideally this should be done with a single target that has
both `--crate-type` arguments instead of having 2 different build rules.

As temporary workaround, build twice and ensure they don't get conflicts
in intermediary files created by rustc by passing target's private
directory as --out-dir.

See rust-lang/rust#111083.
xclaesse added a commit to xclaesse/meson that referenced this issue Sep 18, 2023
Rustc does not produce object files we can reuse to build both
libraries. Ideally this should be done with a single target that has
both `--crate-type` arguments instead of having 2 different build rules.

As temporary workaround, build twice and ensure they don't get conflicts
in intermediary files created by rustc by passing target's private
directory as --out-dir.

See rust-lang/rust#111083.
xclaesse added a commit to mesonbuild/meson that referenced this issue Sep 19, 2023
Rustc does not produce object files we can reuse to build both
libraries. Ideally this should be done with a single target that has
both `--crate-type` arguments instead of having 2 different build rules.

As temporary workaround, build twice and ensure they don't get conflicts
in intermediary files created by rustc by passing target's private
directory as --out-dir.

See rust-lang/rust#111083.
robtaylor pushed a commit to robtaylor/meson that referenced this issue Oct 14, 2023
Rustc does not produce object files we can reuse to build both
libraries. Ideally this should be done with a single target that has
both `--crate-type` arguments instead of having 2 different build rules.

As temporary workaround, build twice and ensure they don't get conflicts
in intermediary files created by rustc by passing target's private
directory as --out-dir.

See rust-lang/rust#111083.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-FFI Area: Foreign function interface (FFI) A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

3 participants