Skip to content

Commit

Permalink
Add .rlib as an allowed extension for static libraries for C++ rules
Browse files Browse the repository at this point in the history
With this change we can directly link Rust static libraries into C++ binaries. Without this change we would have to register a symlink action that "renames" the extension from .rlib to .a.

What exactly is rlib?

From https://doc.rust-lang.org/reference/linkage.html:

```
This [rlib] is used as an intermediate artifact and can be thought of as a "static Rust library". These rlib files, unlike staticlib files, are interpreted by the compiler in future linkage. This essentially means that rustc will look for metadata in rlib files like it looks for metadata in dynamic libraries. This form of output is used to produce statically linked executables as well as staticlib outputs.
```

This file is an ar archive, just like regular .a archives. This file can actually be used by linkers directly. Rlib contains an additional metadata file that is ignored by linkers but used by rustc compilations. From the high level, rlib can be thought of as a Clang module + object files in an ar archive.

RELNOTES: None.
PiperOrigin-RevId: 385139708
  • Loading branch information
hlopko authored and copybara-github committed Jul 16, 2021
1 parent 01c10e0 commit ad03823
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ public ImmutableList<String> getExtensions() {
return ImmutableList.of(ext, ".obj");
}
};
// Static library artifact created by rustc, can be used as a regular archive.
public static final FileType RUST_RLIB = FileType.of(".rlib");

// Minimized bitcode file emitted by the ThinLTO compile step and used just for LTO indexing.
public static final FileType LTO_INDEXING_OBJECT_FILE = FileType.of(".indexing.o");
Expand Down
19 changes: 10 additions & 9 deletions src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,16 @@ private Link() {} // uninstantiable
public static final FileTypeSet ONLY_INTERFACE_LIBRARY_FILETYPES =
FileTypeSet.of(CppFileTypes.INTERFACE_SHARED_LIBRARY);

public static final FileTypeSet ARCHIVE_LIBRARY_FILETYPES = FileTypeSet.of(
CppFileTypes.ARCHIVE,
CppFileTypes.PIC_ARCHIVE,
CppFileTypes.ALWAYS_LINK_LIBRARY,
CppFileTypes.ALWAYS_LINK_PIC_LIBRARY);

public static final FileTypeSet ARCHIVE_FILETYPES = FileTypeSet.of(
CppFileTypes.ARCHIVE,
CppFileTypes.PIC_ARCHIVE);
public static final FileTypeSet ARCHIVE_LIBRARY_FILETYPES =
FileTypeSet.of(
CppFileTypes.ARCHIVE,
CppFileTypes.PIC_ARCHIVE,
CppFileTypes.ALWAYS_LINK_LIBRARY,
CppFileTypes.ALWAYS_LINK_PIC_LIBRARY,
CppFileTypes.RUST_RLIB);

public static final FileTypeSet ARCHIVE_FILETYPES =
FileTypeSet.of(CppFileTypes.ARCHIVE, CppFileTypes.PIC_ARCHIVE, CppFileTypes.RUST_RLIB);

public static final FileTypeSet LINK_LIBRARY_FILETYPES = FileTypeSet.of(
CppFileTypes.ALWAYS_LINK_LIBRARY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ public void testTwoDotExtensions() {
assertThat(CppFileTypes.OBJECT_FILE.matches("test.pic.o")).isFalse();
}

@Test
public void testRlib() {
assertThat(CppFileTypes.RUST_RLIB.matches("foo.a")).isFalse();
assertThat(CppFileTypes.RUST_RLIB.matches("foo.rlib")).isTrue();
}

@Test
public void testVersionedSharedLibraries() {
assertThat(CppFileTypes.SHARED_LIBRARY.matches("somelibrary.so")).isTrue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1335,8 +1335,8 @@ public void testCcLinkingContextOnWindows() throws Exception {
CppRuleClasses.TARGETS_WINDOWS,
CppRuleClasses.SUPPORTS_DYNAMIC_LINKER));
doTestCcLinkingContext(
ImmutableList.of("a.a", "libdep2.a", "b.a", "c.a", "d.a", "libdep1.a"),
ImmutableList.of("a.pic.a", "b.pic.a", "c.pic.a", "e.pic.a"),
ImmutableList.of("a.a", "libdep2.a", "b.rlib", "c.a", "d.a", "libdep1.a"),
ImmutableList.of("a.pic.a", "b.rlib", "c.pic.a", "e.pic.a"),
// The suffix of dynamic library is caculated based on repository name and package path
// to avoid conflicts with dynamic library from other packages.
ImmutableList.of("a.so", "libdep2_c092dd9ce2.so", "b.so", "e.so", "libdep1_c092dd9ce2.so"));
Expand All @@ -1354,8 +1354,8 @@ public void testCcLinkingContext() throws Exception {
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_DYNAMIC_LINKER));
doTestCcLinkingContext(
ImmutableList.of("a.a", "b.a", "c.a", "d.a"),
ImmutableList.of("a.pic.a", "libdep2.a", "b.pic.a", "c.pic.a", "e.pic.a", "libdep1.a"),
ImmutableList.of("a.a", "b.rlib", "c.a", "d.a"),
ImmutableList.of("a.pic.a", "libdep2.a", "b.rlib", "c.pic.a", "e.pic.a", "libdep1.a"),
ImmutableList.of("a.so", "liba_Slibdep2.so", "b.so", "e.so", "liba_Slibdep1.so"));
}

Expand All @@ -1371,8 +1371,8 @@ public void testCcLinkingContextForExperimentalCcSharedLibrary() throws Exceptio
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_DYNAMIC_LINKER));
doTestCcLinkingContext(
ImmutableList.of("a.a", "b.a", "c.a", "d.a"),
ImmutableList.of("a.pic.a", "libdep2.a", "b.pic.a", "c.pic.a", "e.pic.a", "libdep1.a"),
ImmutableList.of("a.a", "b.rlib", "c.a", "d.a"),
ImmutableList.of("a.pic.a", "libdep2.a", "b.rlib", "c.pic.a", "e.pic.a", "libdep1.a"),
ImmutableList.of("a.so", "liba_Slibdep2.so", "b.so", "e.so", "liba_Slibdep1.so"));
}

Expand All @@ -1399,13 +1399,13 @@ public void testIncompatibleDepsetForLibrariesToLinkGetter() throws Exception {
.filter(x -> x.getStaticLibrary() != null)
.map(x -> x.getStaticLibrary().getFilename())
.collect(ImmutableList.toImmutableList()))
.containsExactly("a.a", "b.a", "c.a", "d.a");
.containsExactly("a.a", "b.rlib", "c.a", "d.a");
assertThat(
librariesToLink.toList(LibraryToLink.class).stream()
.filter(x -> x.getPicStaticLibrary() != null)
.map(x -> x.getPicStaticLibrary().getFilename())
.collect(ImmutableList.toImmutableList()))
.containsExactly("a.pic.a", "libdep2.a", "b.pic.a", "c.pic.a", "e.pic.a", "libdep1.a");
.containsExactly("a.pic.a", "libdep2.a", "b.rlib", "c.pic.a", "e.pic.a", "libdep1.a");
assertThat(
librariesToLink.toList(LibraryToLink.class).stream()
.filter(x -> x.getDynamicLibrary() != null)
Expand Down Expand Up @@ -1576,8 +1576,8 @@ private void setUpCcLinkingContextTest(boolean enableExperimentalCcImport) throw
" deps = [':c', ':dep2', ':b'],",
")",
"crule(name='b',",
" static_library = 'b.a',",
" pic_static_library = 'b.pic.a',",
" static_library = 'b.rlib',",
" pic_static_library = 'b.rlib',",
" dynamic_library = 'b.so',",
" deps = [':c', ':d'],",
" additional_inputs = ['b.lds'],",
Expand Down Expand Up @@ -5223,10 +5223,11 @@ public void testWrongExtensionThrowsError() throws Exception {
AssertionError e = assertThrows(AssertionError.class, () -> getConfiguredTarget("//foo:bin"));
assertThat(e)
.hasMessageThat()
.contains("'a.o' does not have any of the allowed extensions .a, .lib or .pic.a");
.contains("'a.o' does not have any of the allowed extensions .a, .lib, .pic.a or .rlib");
assertThat(e)
.hasMessageThat()
.contains("'a.pic.o' does not have any of the allowed extensions .a, .lib or .pic.a");
.contains(
"'a.pic.o' does not have any of the allowed extensions .a, .lib, .pic.a or .rlib");
assertThat(e)
.hasMessageThat()
.contains("'a.ifso' does not have any of the allowed extensions .so, .dylib or .dll");
Expand Down Expand Up @@ -7263,6 +7264,8 @@ public void testExpandedLibraryToLinkApiRaisesError() throws Exception {
}
}



@Test
public void testExpandedLinkstampApiRaisesError() throws Exception {
scratch.file(
Expand Down

0 comments on commit ad03823

Please sign in to comment.