Skip to content
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

Add rustc --emit=link-info for staticlib link-line output #31471

Open
rillian opened this issue Feb 7, 2016 · 9 comments
Open

Add rustc --emit=link-info for staticlib link-line output #31471

rillian opened this issue Feb 7, 2016 · 9 comments
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) C-feature-request Category: A feature request, i.e: not implemented / a PR. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@rillian
Copy link
Contributor

rillian commented Feb 7, 2016

When linking rust into C++ projects, I use rustc --crate-type=staticlib to generate a static library which I can link into the overall project. Since there's no standard for transitive dependency declaration in the C ABI for static libraries, rustc prints out a list of libraries which need to be linked along with the staticlib. (#25820 (comment))

This is very helpful in development, but not ideal for automation. I propose adding an --emit=link-info option (--emit=libs? --emit=ldflags?) to write the required link line out to a file for use later, similar to --emit=dep-info for makefile dependency generation.

Order of evaluation is a little trickier than with dep-info since it has to work the first time, but this should simplify funky stderr hacks like

libfoo.a libfoo.a.out: foo/lib.rs
    rustc -g --crate-type staticlib --crate-name foo \
      --emit dep-info,link=$@ $< \
      2> [email protected] || cat [email protected] >&2
-include foo.d

prog: RUST_LIBS = $(shell awk '/^note: library: / {print "-l"$$3}' libmp4parse.a.out)
prog: prog.o libfoo.a
    $(CXX) $(CXXFLAGS) -o $@ $^ $(RUST_LIBS)

into

libfoo.a libfoo.a.link: foo/lib.rs
    rustc -g --crate-type staticlib --crate-name foo \
      --emit dep-info,link=$@,[email protected] $<
-include foo.d

prog: prog.o libfoo.a
    $(CXX) $(CXXFLAGS) -o $@ $^ $(shell cat libfoo.a.link)
@rillian rillian changed the title Add rustc --emit=linkinfo Add rustc --emit=link-info for staticlib link-line output Feb 7, 2016
@alexcrichton
Copy link
Member

This seems reasonable to me, although I might prefer to call it something like --emit link-flags-ld or something where we can swap out link.exe, lld, ld, or all the other random linkers in there as well. That way we can hopefully pick the "right format" for the linker arguments.

I think we could even suppress the "warning, you gotta link these libs" message when you're emitting these as well. We may even be able to get crazy and put other flags in there (e.g. things like --gc-sections or something)

@steveklabnik steveklabnik added the A-frontend Area: Compiler frontend (errors, parsing and HIR) label Feb 15, 2016
rillian added a commit to rillian/rust that referenced this issue Feb 26, 2016
Generate an unix-style ldflags line when building with
--crate-type staticlib --emit link-flags-ld.

If a filename is given, write the link line there for
later use by an external build system in linking the
static library. If none is given, just modify the
normal informative message to print the flags line
instead of the library list.

Issue rust-lang#31471.
rillian added a commit to rillian/rust that referenced this issue Feb 26, 2016
Generate an unix-style ldflags line when building with
--crate-type staticlib --emit link-flags-ld.

If a filename is given, write the link line there for
later use by an external build system in linking the
static library. If none is given, just modify the
normal informative message to print the flags line
instead of the library list.

Issue rust-lang#31471.
@retep998
Copy link
Member

Since there's no standard for transitive dependency declaration in the C ABI for static libraries

While there might not be a standard for most compilers, msvc definitely does have a way for libraries to specify dependencies that are pulled in automatically.

@rillian
Copy link
Contributor Author

rillian commented Apr 24, 2016

Oh! That would be great. Can you share some documentation about how this works? As far as I knew msvc .lib static libraries were just ar archives of COFF object files--with no link metadata--the same as Linux and Mac.

@retep998
Copy link
Member

I can't find any documentation on it at the moment, just some other documentation that alludes to it.

https://msdn.microsoft.com/en-us/library/f1tbxcxh.aspx

By default, the compiler puts the name of the library into the .obj file to direct the linker to the correct library.

https://msdn.microsoft.com/en-us/library/229a6ysd.aspx

before default libraries named in .obj files.

So the capability is there in object files, I just have no idea how to add that information to the object file.

@rillian
Copy link
Contributor Author

rillian commented Apr 25, 2016

Thanks for the links. I still don't see a way to make this work though. /DEFAULTLIB is an option to LINK which make executables and dlls, and isn't accepted by LIB, the command for creating static libraries.

I think the /Zl option is about the run-time library. Maybe it's possible to abuse that for transitive dependencies in object files if it's possible to have more than one? I set up a simple test project, but couldn't make it work. https://github.com/rillian/msvc-staticlib Let me know if you have better luck, @retep998.

@retep998
Copy link
Member

Really it's just a matter of seeing whether LLVM can do it, since LLVM is what creates our object files, and is also what creates static libraries for us (Rust doesn't use LIB).

@BartMassey
Copy link
Contributor

As noted in #33173 just writing the libraries note to stdout instead of stderr would help a lot. Heck, create a .libs-needed file and write to that.

Better yet, can someone finish @rillian's #31875, or can we just merge it and add the lack of tests and docs as a separate issue? I feel like waiting for better tests and docs would be nice, but this is kind of an obnoxious situation and it looks like @rillian has dropped out of trying to get a fix in.

I'm currently working around this in my Makefile (because reasons) with

    rustc staticlib.rs 2>&1 | egrep -v '^note:' | cat

where the cat is to suppress the stupid exit status 1 from egrep when its output is empty. Uggh.

@rillian
Copy link
Contributor Author

rillian commented Jul 20, 2016

Yeah, I haven't been able to work more on this. Would be very happy to have someone finish it up!

@retep998
Copy link
Member

Ah, I figured out how to do the default lib stuff in LLVM, based on what clang does. This method lets you pass arbitrary arguments to the linker without having to explicitly pass them to the linker.

!0 = !{i32 6, !"Linker Options", !1}
!1 = !{!2, !3, !4, !5, !6, !7, !8}
!2 = !{!"/DEFAULTLIB:libcmt.lib"}
!3 = !{!"/DEFAULTLIB:oldnames.lib"}
!4 = !{!"/FAILIFMISMATCH:\22_MSC_VER=1900\22"}
!5 = !{!"/FAILIFMISMATCH:\22_ITERATOR_DEBUG_LEVEL=0\22"}
!6 = !{!"/FAILIFMISMATCH:\22RuntimeLibrary=MT_StaticRelease\22"}
!7 = !{!"/DEFAULTLIB:libcpmt.lib"}
!8 = !{!"/FAILIFMISMATCH:\22_CRT_STDIO_ISO_WIDE_SPECIFIERS=0\22"}

@Mark-Simulacrum Mark-Simulacrum added the C-feature-request Category: A feature request, i.e: not implemented / a PR. label Jul 24, 2017
@Enselic Enselic added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Sep 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) C-feature-request Category: A feature request, i.e: not implemented / a PR. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants