diff --git a/Android.bp b/Android.bp index 3ece11071..b7f969159 100644 --- a/Android.bp +++ b/Android.bp @@ -333,6 +333,7 @@ bootstrap_go_package { "soong-cc-config", ], srcs: [ + "rust/config/arm64_device.go", "rust/config/global.go", "rust/config/toolchain.go", "rust/config/whitelist.go", diff --git a/cc/cc.go b/cc/cc.go index e1d184a8a..5763d0c47 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -401,6 +401,14 @@ func StaticDepTag() dependencyTag { return staticDepTag } +func CrtBeginDepTag() dependencyTag { + return crtBeginDepTag +} + +func CrtEndDepTag() dependencyTag { + return crtEndDepTag +} + // Module contains the properties and members used by all C/C++ module types, and implements // the blueprint.Module interface. It delegates to compiler, linker, and installer interfaces // to construct the output file. Behavior can be customized with a Customizer interface diff --git a/rust/binary.go b/rust/binary.go index 279c6f50f..52f840e7a 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -71,6 +71,15 @@ func (binary *binaryDecorator) preferDynamic() bool { func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { flags = binary.baseCompiler.compilerFlags(ctx, flags) + + if ctx.toolchain().Bionic() { + // no-undefined-version breaks dylib compilation since __rust_*alloc* functions aren't defined, but we can apply this to binaries. + flags.LinkFlags = append(flags.LinkFlags, + "-Wl,--gc-sections", + "-Wl,-z,nocopyreloc", + "-Wl,--no-undefined-version") + } + if binary.preferDynamic() { flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic") } @@ -86,6 +95,12 @@ func (binary *binaryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { } } + if ctx.toolchain().Bionic() { + deps = binary.baseCompiler.bionicDeps(ctx, deps) + deps.CrtBegin = "crtbegin_dynamic" + deps.CrtEnd = "crtend_android" + } + return deps } diff --git a/rust/builder.go b/rust/builder.go index ef50701f8..66114928b 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -28,14 +28,14 @@ var ( blueprint.RuleParams{ Command: "$rustcCmd " + "-C linker=${config.RustLinker} " + - "-C link-args=\"${config.RustLinkerArgs} ${linkFlags}\" " + + "-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " + "-o $out $in ${libFlags} $rustcFlags " + "&& $rustcCmd --emit=dep-info -o $out.d $in ${libFlags} $rustcFlags", CommandDeps: []string{"$rustcCmd"}, Depfile: "$out.d", Deps: blueprint.DepsGCC, // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633 }, - "rustcFlags", "linkFlags", "libFlags") + "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd") ) func init() { @@ -43,19 +43,19 @@ func init() { } func TransformSrcToBinary(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) { - transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "bin", includeDirs) + transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "bin", includeDirs) } func TransformSrctoRlib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) { - transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "rlib", includeDirs) + transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "rlib", includeDirs) } func TransformSrctoDylib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) { - transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "dylib", includeDirs) + transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "dylib", includeDirs) } func TransformSrctoProcMacro(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) { - transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "proc-macro", includeDirs) + transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "proc-macro", includeDirs) } func rustLibsToPaths(libs RustLibraries) android.Paths { @@ -67,24 +67,28 @@ func rustLibsToPaths(libs RustLibraries) android.Paths { } func transformSrctoCrate(ctx android.ModuleContext, main android.Path, - rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string) { + rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, crtBegin, crtEnd android.OptionalPath, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string) { var inputs android.Paths var deps android.Paths - var libFlags, rustcFlags []string + var libFlags, rustcFlags, linkFlags []string crate_name := ctx.(ModuleContext).CrateName() targetTriple := ctx.(ModuleContext).toolchain().RustTriple() inputs = append(inputs, main) // Collect rustc flags - rustcFlags = append(rustcFlags, flags.GlobalFlags...) + rustcFlags = append(rustcFlags, flags.GlobalRustFlags...) rustcFlags = append(rustcFlags, flags.RustFlags...) rustcFlags = append(rustcFlags, "--crate-type="+crate_type) rustcFlags = append(rustcFlags, "--crate-name="+crate_name) if targetTriple != "" { rustcFlags = append(rustcFlags, "--target="+targetTriple) + linkFlags = append(linkFlags, "-target "+targetTriple) } + // Collect linker flags + linkFlags = append(linkFlags, flags.GlobalLinkFlags...) + linkFlags = append(linkFlags, flags.LinkFlags...) // Collect library/crate flags for _, lib := range rlibs { @@ -107,6 +111,9 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps = append(deps, rustLibsToPaths(proc_macros)...) deps = append(deps, static_libs...) deps = append(deps, shared_libs...) + if crtBegin.Valid() { + deps = append(deps, crtBegin.Path(), crtEnd.Path()) + } ctx.Build(pctx, android.BuildParams{ Rule: rustc, @@ -116,8 +123,10 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, Implicits: deps, Args: map[string]string{ "rustcFlags": strings.Join(rustcFlags, " "), - "linkFlags": strings.Join(flags.LinkFlags, " "), + "linkFlags": strings.Join(linkFlags, " "), "libFlags": strings.Join(libFlags, " "), + "crtBegin": crtBegin.String(), + "crtEnd": crtEnd.String(), }, }) diff --git a/rust/compiler.go b/rust/compiler.go index 87cf08b40..f45744b4d 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -113,7 +113,8 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flag flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...) flags.RustFlags = append(flags.RustFlags, "--edition="+*compiler.Properties.Edition) flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...) - flags.GlobalFlags = append(flags.GlobalFlags, ctx.toolchain().ToolchainRustFlags()) + flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags()) + flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags()) if ctx.Host() && !ctx.Windows() { rpath_prefix := `\$$ORIGIN/` @@ -148,6 +149,18 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { return deps } +func (compiler *baseCompiler) bionicDeps(ctx DepsContext, deps Deps) Deps { + deps.SharedLibs = append(deps.SharedLibs, "liblog") + deps.SharedLibs = append(deps.SharedLibs, "libc") + deps.SharedLibs = append(deps.SharedLibs, "libm") + deps.SharedLibs = append(deps.SharedLibs, "libdl") + + //TODO(b/141331117) libstd requires libgcc on Android + deps.StaticLibs = append(deps.StaticLibs, "libgcc") + + return deps +} + func (compiler *baseCompiler) crateName() string { return compiler.Properties.Crate_name } diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go new file mode 100644 index 000000000..0264052db --- /dev/null +++ b/rust/config/arm64_device.go @@ -0,0 +1,92 @@ +// Copyright 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "strings" + + "android/soong/android" +) + +var ( + Arm64RustFlags = []string{} + Arm64ArchFeatureRustFlags = map[string][]string{} + Arm64LinkFlags = []string{ + "-Wl,--icf=safe", + "-Wl,-z,max-page-size=4096", + + "-Wl,-execute-only", + } + + Arm64ArchVariantRustFlags = map[string][]string{ + "armv8-a": []string{}, + "armv8-2a": []string{}, + } +) + +func init() { + registerToolchainFactory(android.Android, android.Arm64, Arm64ToolchainFactory) + + pctx.StaticVariable("Arm64ToolchainRustFlags", strings.Join(Arm64RustFlags, " ")) + pctx.StaticVariable("Arm64ToolchainLinkFlags", strings.Join(Arm64LinkFlags, " ")) + + for variant, rustFlags := range Arm64ArchVariantRustFlags { + pctx.StaticVariable("Arm64"+variant+"VariantRustFlags", + strings.Join(rustFlags, " ")) + } + +} + +type toolchainArm64 struct { + toolchain64Bit + toolchainRustFlags string +} + +func (t *toolchainArm64) RustTriple() string { + return "aarch64-linux-android" +} + +func (t *toolchainArm64) ToolchainLinkFlags() string { + return "${config.DeviceGlobalLinkFlags} ${config.Arm64ToolchainLinkFlags}" +} + +func (t *toolchainArm64) ToolchainRustFlags() string { + return t.toolchainRustFlags +} + +func (t *toolchainArm64) RustFlags() string { + return "${config.Arm64ToolchainRustFlags}" +} + +func (t *toolchainArm64) Supported() bool { + return true +} + +func Arm64ToolchainFactory(arch android.Arch) Toolchain { + toolchainRustFlags := []string{ + "${config.Arm64ToolchainRustFlags}", + "${config.Arm64" + arch.ArchVariant + "VariantRustFlags}", + } + + toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...) + + for _, feature := range arch.ArchFeatures { + toolchainRustFlags = append(toolchainRustFlags, Arm64ArchFeatureRustFlags[feature]...) + } + + return &toolchainArm64{ + toolchainRustFlags: strings.Join(toolchainRustFlags, " "), + } +} diff --git a/rust/config/global.go b/rust/config/global.go index 903a424da..cec5a74f8 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -15,6 +15,8 @@ package config import ( + "strings" + "android/soong/android" _ "android/soong/cc/config" ) @@ -30,6 +32,24 @@ var ( "libterm", "libtest", } + + deviceGlobalRustFlags = []string{} + + deviceGlobalLinkFlags = []string{ + "-Bdynamic", + "-nostdlib", + "-Wl,-z,noexecstack", + "-Wl,-z,relro", + "-Wl,-z,now", + "-Wl,--build-id=md5", + "-Wl,--warn-shared-textrel", + "-Wl,--fatal-warnings", + + "-Wl,--pack-dyn-relocs=android+relr", + "-Wl,--use-android-relr-tags", + "-Wl,--no-undefined", + "-Wl,--hash-style=gnu", + } ) func init() { @@ -56,4 +76,7 @@ func init() { pctx.ImportAs("ccConfig", "android/soong/cc/config") pctx.StaticVariable("RustLinker", "${ccConfig.ClangBin}/clang++") pctx.StaticVariable("RustLinkerArgs", "-B ${ccConfig.ClangBin} -fuse-ld=lld") + + pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " ")) + } diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go index a36d61bfd..328bca3b9 100644 --- a/rust/config/toolchain.go +++ b/rust/config/toolchain.go @@ -32,6 +32,8 @@ type Toolchain interface { Is64Bit() bool Supported() bool + + Bionic() bool } type toolchainBase struct { @@ -53,6 +55,10 @@ func (toolchainBase) Is64Bit() bool { panic("toolchainBase cannot determine datapath width.") } +func (toolchainBase) Bionic() bool { + return true +} + type toolchain64Bit struct { toolchainBase } diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go index cb6bf1a22..5376e5ba5 100644 --- a/rust/config/x86_linux_host.go +++ b/rust/config/x86_linux_host.go @@ -61,6 +61,10 @@ func (toolchainLinuxX8664) Supported() bool { return true } +func (toolchainLinuxX8664) Bionic() bool { + return false +} + func (t *toolchainLinuxX8664) Name() string { return "x86_64" } @@ -85,6 +89,10 @@ func (toolchainLinuxX86) Supported() bool { return true } +func (toolchainLinuxX86) Bionic() bool { + return false +} + func (t *toolchainLinuxX86) Name() string { return "x86" } diff --git a/rust/library.go b/rust/library.go index 5cf8ac700..c831727c5 100644 --- a/rust/library.go +++ b/rust/library.go @@ -191,6 +191,16 @@ func (library *libraryDecorator) compilerProps() []interface{} { &library.MutatedProperties) } +func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { + deps = library.baseCompiler.compilerDeps(ctx, deps) + + if ctx.toolchain().Bionic() && library.dylib() { + deps = library.baseCompiler.bionicDeps(ctx, deps) + } + + return deps +} + func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path { var outputFile android.WritablePath diff --git a/rust/prebuilt.go b/rust/prebuilt.go index d4e631ba6..fa69fbb86 100644 --- a/rust/prebuilt.go +++ b/rust/prebuilt.go @@ -63,3 +63,8 @@ func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags return srcPath } + +func (prebuilt *prebuiltLibraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { + deps = prebuilt.baseCompiler.compilerDeps(ctx, deps) + return deps +} diff --git a/rust/rust.go b/rust/rust.go index 359e126d9..61b51e547 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -43,11 +43,12 @@ func init() { } type Flags struct { - GlobalFlags []string // Flags that apply globally - RustFlags []string // Flags that apply to rust - LinkFlags []string // Flags that apply to linker - RustFlagsDeps android.Paths // Files depended on by compiler flags - Toolchain config.Toolchain + GlobalRustFlags []string // Flags that apply globally to rust + GlobalLinkFlags []string // Flags that apply globally to linker + RustFlags []string // Flags that apply to rust + LinkFlags []string // Flags that apply to linker + RustFlagsDeps android.Paths // Files depended on by compiler flags + Toolchain config.Toolchain } type BaseProperties struct { @@ -92,6 +93,9 @@ type PathDeps struct { linkDirs []string depFlags []string //ReexportedDeps android.Paths + + CrtBegin android.OptionalPath + CrtEnd android.OptionalPath } type RustLibraries []RustLibrary @@ -398,6 +402,10 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { directSharedLibDeps = append(directSharedLibDeps, ccDep) mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName) exportDep = true + case cc.CrtBeginDepTag(): + depPaths.CrtBegin = linkFile + case cc.CrtEndDepTag(): + depPaths.CrtEnd = linkFile } // Make sure these dependencies are propagated @@ -480,6 +488,13 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), cc.SharedDepTag(), deps.SharedLibs...) actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "static"}), cc.StaticDepTag(), deps.StaticLibs...) + if deps.CrtBegin != "" { + actx.AddVariationDependencies(ccDepVariations, cc.CrtBeginDepTag(), deps.CrtBegin) + } + if deps.CrtEnd != "" { + actx.AddVariationDependencies(ccDepVariations, cc.CrtEndDepTag(), deps.CrtEnd) + } + // proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy. actx.AddFarVariationDependencies([]blueprint.Variation{{Mutator: "arch", Variation: ctx.Config().BuildOsVariant}}, procMacroDepTag, deps.ProcMacros...) }