diff --git a/cc/prebuilt.go b/cc/prebuilt.go index 2ef31950e..ac990f35f 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -43,6 +43,11 @@ type prebuiltLinkerProperties struct { // Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined // symbols, etc), default true. Check_elf_files *bool + + // Optionally provide an import library if this is a Windows PE DLL prebuilt. + // This is needed only if this library is linked by other modules in build time. + // Only makes sense for the Windows target. + Windows_import_lib *string `android:"path,arch_variant"` } type prebuiltLinker struct { @@ -109,9 +114,16 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, in := android.PathForModuleSrc(ctx, srcs[0]) + if p.static() { + return in + } + if p.shared() { p.unstrippedOutputFile = in libName := p.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix() + outputFile := android.PathForModuleOut(ctx, libName) + var implicits android.Paths + if p.needsStrip(ctx) { stripped := android.PathForModuleOut(ctx, "stripped", libName) p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags) @@ -122,10 +134,41 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, // depending on a table of contents file instead of the library itself. tocFile := android.PathForModuleOut(ctx, libName+".toc") p.tocFile = android.OptionalPathForPath(tocFile) - TransformSharedObjectToToc(ctx, in, tocFile, builderFlags) - } + TransformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags) - return in + if ctx.Windows() && p.properties.Windows_import_lib != nil { + // Consumers of this library actually links to the import library in build + // time and dynamically links to the DLL in run time. i.e. + // a.exe <-- static link --> foo.lib <-- dynamic link --> foo.dll + importLibSrc := android.PathForModuleSrc(ctx, String(p.properties.Windows_import_lib)) + importLibName := p.libraryDecorator.getLibName(ctx) + ".lib" + importLibOutputFile := android.PathForModuleOut(ctx, importLibName) + implicits = append(implicits, importLibOutputFile) + + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Description: "prebuilt import library", + Input: importLibSrc, + Output: importLibOutputFile, + Args: map[string]string{ + "cpFlags": "-L", + }, + }) + } + + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Description: "prebuilt shared library", + Implicits: implicits, + Input: in, + Output: outputFile, + Args: map[string]string{ + "cpFlags": "-L", + }, + }) + + return outputFile + } } return nil diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go index 0b018c10d..adb44bd71 100644 --- a/cc/prebuilt_test.go +++ b/cc/prebuilt_test.go @@ -184,7 +184,7 @@ func TestPrebuiltLibraryShared(t *testing.T) { }) shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module) - assertString(t, shared.OutputFile().String(), "libf.so") + assertString(t, shared.OutputFile().Path().Base(), "libtest.so") } func TestPrebuiltLibraryStatic(t *testing.T) { @@ -198,7 +198,7 @@ func TestPrebuiltLibraryStatic(t *testing.T) { }) static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module) - assertString(t, static.OutputFile().String(), "libf.a") + assertString(t, static.OutputFile().Path().Base(), "libf.a") } func TestPrebuiltLibrary(t *testing.T) { @@ -221,8 +221,53 @@ func TestPrebuiltLibrary(t *testing.T) { }) shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module) - assertString(t, shared.OutputFile().String(), "libf.so") + assertString(t, shared.OutputFile().Path().Base(), "libtest.so") static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module) - assertString(t, static.OutputFile().String(), "libf.a") + assertString(t, static.OutputFile().Path().Base(), "libf.a") +} + +func TestPrebuiltLibraryStem(t *testing.T) { + ctx := testPrebuilt(t, ` + cc_prebuilt_library { + name: "libfoo", + stem: "libbar", + static: { + srcs: ["libfoo.a"], + }, + shared: { + srcs: ["libfoo.so"], + }, + strip: { + none: true, + }, + } + `, map[string][]byte{ + "libfoo.a": nil, + "libfoo.so": nil, + }) + + static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module) + assertString(t, static.OutputFile().Path().Base(), "libfoo.a") + + shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module) + assertString(t, shared.OutputFile().Path().Base(), "libbar.so") +} + +func TestPrebuiltLibrarySharedStem(t *testing.T) { + ctx := testPrebuilt(t, ` + cc_prebuilt_library_shared { + name: "libfoo", + stem: "libbar", + srcs: ["libfoo.so"], + strip: { + none: true, + }, + } + `, map[string][]byte{ + "libfoo.so": nil, + }) + + shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module) + assertString(t, shared.OutputFile().Path().Base(), "libbar.so") }