Symlink prebuilt binaries on host.
This means binaries will run from their source location and look up shared libs relative to there. Test: m nothing Test: Set up a prebuilt binary with shared libs, check that it can be executed during build, and check that its symlinks get updated when a shared lib is touched. Bug: 145934348 Change-Id: I1a600c7163ce0ec34ee8caf0ffe87fef4feb3064
This commit is contained in:
@@ -324,35 +324,68 @@ func prebuiltObjectFactory() android.Module {
|
|||||||
type prebuiltBinaryLinker struct {
|
type prebuiltBinaryLinker struct {
|
||||||
*binaryDecorator
|
*binaryDecorator
|
||||||
prebuiltLinker
|
prebuiltLinker
|
||||||
|
|
||||||
|
toolPath android.OptionalPath
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ prebuiltLinkerInterface = (*prebuiltBinaryLinker)(nil)
|
var _ prebuiltLinkerInterface = (*prebuiltBinaryLinker)(nil)
|
||||||
|
|
||||||
|
func (p *prebuiltBinaryLinker) hostToolPath() android.OptionalPath {
|
||||||
|
return p.toolPath
|
||||||
|
}
|
||||||
|
|
||||||
func (p *prebuiltBinaryLinker) link(ctx ModuleContext,
|
func (p *prebuiltBinaryLinker) link(ctx ModuleContext,
|
||||||
flags Flags, deps PathDeps, objs Objects) android.Path {
|
flags Flags, deps PathDeps, objs Objects) android.Path {
|
||||||
// TODO(ccross): verify shared library dependencies
|
// TODO(ccross): verify shared library dependencies
|
||||||
if len(p.properties.Srcs) > 0 {
|
if len(p.properties.Srcs) > 0 {
|
||||||
stripFlags := flagsToStripFlags(flags)
|
|
||||||
|
|
||||||
fileName := p.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
|
fileName := p.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
|
||||||
in := p.Prebuilt.SingleSourcePath(ctx)
|
in := p.Prebuilt.SingleSourcePath(ctx)
|
||||||
|
outputFile := android.PathForModuleOut(ctx, fileName)
|
||||||
p.unstrippedOutputFile = in
|
p.unstrippedOutputFile = in
|
||||||
|
|
||||||
if p.stripper.NeedsStrip(ctx) {
|
if ctx.Host() {
|
||||||
stripped := android.PathForModuleOut(ctx, "stripped", fileName)
|
// Host binaries are symlinked to their prebuilt source locations. That
|
||||||
p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, stripFlags)
|
// way they are executed directly from there so the linker resolves their
|
||||||
in = stripped
|
// shared library dependencies relative to that location (using
|
||||||
}
|
// $ORIGIN/../lib(64):$ORIGIN/lib(64) as RUNPATH). This way the prebuilt
|
||||||
|
// repository can supply the expected versions of the shared libraries
|
||||||
|
// without interference from what is in the out tree.
|
||||||
|
|
||||||
// Copy binaries to a name matching the final installed name
|
// These shared lib paths may point to copies of the libs in
|
||||||
outputFile := android.PathForModuleOut(ctx, fileName)
|
// .intermediates, which isn't where the binary will load them from, but
|
||||||
ctx.Build(pctx, android.BuildParams{
|
// it's fine for dependency tracking. If a library dependency is updated,
|
||||||
Rule: android.CpExecutable,
|
// the symlink will get a new timestamp, along with any installed symlinks
|
||||||
Description: "prebuilt",
|
// handled in make.
|
||||||
Output: outputFile,
|
sharedLibPaths := deps.EarlySharedLibs
|
||||||
Input: in,
|
sharedLibPaths = append(sharedLibPaths, deps.SharedLibs...)
|
||||||
})
|
sharedLibPaths = append(sharedLibPaths, deps.LateSharedLibs...)
|
||||||
|
|
||||||
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
Rule: android.Symlink,
|
||||||
|
Output: outputFile,
|
||||||
|
Input: in,
|
||||||
|
Implicits: sharedLibPaths,
|
||||||
|
Args: map[string]string{
|
||||||
|
"fromPath": "$$PWD/" + in.String(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
p.toolPath = android.OptionalPathForPath(outputFile)
|
||||||
|
} else {
|
||||||
|
if p.stripper.NeedsStrip(ctx) {
|
||||||
|
stripped := android.PathForModuleOut(ctx, "stripped", fileName)
|
||||||
|
p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, flagsToStripFlags(flags))
|
||||||
|
in = stripped
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy binaries to a name matching the final installed name
|
||||||
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
Rule: android.CpExecutable,
|
||||||
|
Description: "prebuilt",
|
||||||
|
Output: outputFile,
|
||||||
|
Input: in,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return outputFile
|
return outputFile
|
||||||
}
|
}
|
||||||
@@ -379,6 +412,7 @@ func NewPrebuiltBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecor
|
|||||||
binaryDecorator: binary,
|
binaryDecorator: binary,
|
||||||
}
|
}
|
||||||
module.linker = prebuilt
|
module.linker = prebuilt
|
||||||
|
module.installer = prebuilt
|
||||||
|
|
||||||
module.AddProperties(&prebuilt.properties)
|
module.AddProperties(&prebuilt.properties)
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
package cc
|
package cc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
@@ -271,3 +272,48 @@ func TestPrebuiltLibrarySharedStem(t *testing.T) {
|
|||||||
shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
|
shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
|
||||||
assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
|
assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrebuiltSymlinkedHostBinary(t *testing.T) {
|
||||||
|
ctx := testPrebuilt(t, `
|
||||||
|
cc_prebuilt_library_shared {
|
||||||
|
name: "libfoo",
|
||||||
|
device_supported: false,
|
||||||
|
host_supported: true,
|
||||||
|
target: {
|
||||||
|
linux_glibc_x86_64: {
|
||||||
|
srcs: ["linux_glibc_x86_64/lib64/libfoo.so"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_prebuilt_binary {
|
||||||
|
name: "foo",
|
||||||
|
device_supported: false,
|
||||||
|
host_supported: true,
|
||||||
|
shared_libs: ["libfoo"],
|
||||||
|
target: {
|
||||||
|
linux_glibc_x86_64: {
|
||||||
|
srcs: ["linux_glibc_x86_64/bin/foo"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`, map[string][]byte{
|
||||||
|
"libfoo.so": nil,
|
||||||
|
"foo": nil,
|
||||||
|
})
|
||||||
|
|
||||||
|
fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink")
|
||||||
|
assertString(t, fooRule.Output.String(),
|
||||||
|
filepath.Join(buildDir, ".intermediates/foo/linux_glibc_x86_64/foo"))
|
||||||
|
assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo")
|
||||||
|
|
||||||
|
var libfooDep android.Path
|
||||||
|
for _, dep := range fooRule.Implicits {
|
||||||
|
if dep.Base() == "libfoo.so" {
|
||||||
|
libfooDep = dep
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertString(t, libfooDep.String(),
|
||||||
|
filepath.Join(buildDir, ".intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so"))
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user