Separate cc.go
Split cc.go into files per module type, plus files for the compiler,
linker, and installer stages.
Change-Id: Id44c03f42fcd180950ccd008d4de0c144ea3597b
diff --git a/Android.bp b/Android.bp
index 273f87e..d77d318 100644
--- a/Android.bp
+++ b/Android.bp
@@ -128,12 +128,24 @@
"cc/check.go",
"cc/clang.go",
"cc/gen.go",
+ "cc/global.go",
"cc/makevars.go",
"cc/sanitize.go",
"cc/stl.go",
+ "cc/strip.go",
"cc/toolchain.go",
"cc/util.go",
+ "cc/compiler.go",
+ "cc/installer.go",
+ "cc/linker.go",
+
+ "cc/binary.go",
+ "cc/library.go",
+ "cc/object.go",
+ "cc/test.go",
+
+ "cc/ndk_prebuilt.go",
"cc/ndk_headers.go",
"cc/ndk_library.go",
"cc/ndk_sysroot.go",
diff --git a/cc/binary.go b/cc/binary.go
new file mode 100644
index 0000000..d6b086c
--- /dev/null
+++ b/cc/binary.go
@@ -0,0 +1,282 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+ "github.com/google/blueprint"
+
+ "android/soong"
+ "android/soong/android"
+)
+
+type BinaryLinkerProperties struct {
+ // compile executable with -static
+ Static_executable *bool `android:"arch_variant"`
+
+ // set the name of the output
+ Stem string `android:"arch_variant"`
+
+ // append to the name of the output
+ Suffix string `android:"arch_variant"`
+
+ // if set, add an extra objcopy --prefix-symbols= step
+ Prefix_symbols string
+}
+
+func init() {
+ soong.RegisterModuleType("cc_binary", binaryFactory)
+ soong.RegisterModuleType("cc_binary_host", binaryHostFactory)
+}
+
+// Module factory for binaries
+func binaryFactory() (blueprint.Module, []interface{}) {
+ module := NewBinary(android.HostAndDeviceSupported)
+ return module.Init()
+}
+
+// Module factory for host binaries
+func binaryHostFactory() (blueprint.Module, []interface{}) {
+ module := NewBinary(android.HostSupported)
+ return module.Init()
+}
+
+//
+// Executables
+//
+
+type binaryLinker struct {
+ baseLinker
+ stripper
+
+ Properties BinaryLinkerProperties
+
+ hostToolPath android.OptionalPath
+}
+
+var _ linker = (*binaryLinker)(nil)
+
+func (binary *binaryLinker) props() []interface{} {
+ return append(binary.baseLinker.props(),
+ &binary.Properties,
+ &binary.stripper.StripProperties)
+
+}
+
+func (binary *binaryLinker) buildStatic() bool {
+ return binary.baseLinker.staticBinary()
+}
+
+func (binary *binaryLinker) buildShared() bool {
+ return !binary.baseLinker.staticBinary()
+}
+
+func (binary *binaryLinker) getStem(ctx BaseModuleContext) string {
+ stem := ctx.ModuleName()
+ if binary.Properties.Stem != "" {
+ stem = binary.Properties.Stem
+ }
+
+ return stem + binary.Properties.Suffix
+}
+
+func (binary *binaryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ deps = binary.baseLinker.deps(ctx, deps)
+ if ctx.Device() {
+ if !Bool(binary.baseLinker.Properties.Nocrt) {
+ if !ctx.sdk() {
+ if binary.buildStatic() {
+ deps.CrtBegin = "crtbegin_static"
+ } else {
+ deps.CrtBegin = "crtbegin_dynamic"
+ }
+ deps.CrtEnd = "crtend_android"
+ } else {
+ if binary.buildStatic() {
+ deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
+ } else {
+ if Bool(binary.Properties.Static_executable) {
+ deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
+ } else {
+ deps.CrtBegin = "ndk_crtbegin_dynamic." + ctx.sdkVersion()
+ }
+ deps.CrtEnd = "ndk_crtend_android." + ctx.sdkVersion()
+ }
+ }
+ }
+
+ if binary.buildStatic() {
+ if inList("libc++_static", deps.StaticLibs) {
+ deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
+ }
+ // static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with
+ // --start-group/--end-group along with libgcc. If they are in deps.StaticLibs,
+ // move them to the beginning of deps.LateStaticLibs
+ var groupLibs []string
+ deps.StaticLibs, groupLibs = filterList(deps.StaticLibs,
+ []string{"libc", "libc_nomalloc", "libcompiler_rt"})
+ deps.LateStaticLibs = append(groupLibs, deps.LateStaticLibs...)
+ }
+ }
+
+ if binary.buildShared() && inList("libc", deps.StaticLibs) {
+ ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
+ "from static libs or set static_executable: true")
+ }
+ return deps
+}
+
+func (*binaryLinker) installable() bool {
+ return true
+}
+
+func (binary *binaryLinker) isDependencyRoot() bool {
+ return true
+}
+
+func NewBinary(hod android.HostOrDeviceSupported) *Module {
+ module := newModule(hod, android.MultilibFirst)
+ module.compiler = &baseCompiler{}
+ module.linker = &binaryLinker{}
+ module.installer = &baseInstaller{
+ dir: "bin",
+ }
+ return module
+}
+
+func (binary *binaryLinker) begin(ctx BaseModuleContext) {
+ binary.baseLinker.begin(ctx)
+
+ static := Bool(binary.Properties.Static_executable)
+ if ctx.Host() {
+ if ctx.Os() == android.Linux {
+ if binary.Properties.Static_executable == nil && Bool(ctx.AConfig().ProductVariables.HostStaticBinaries) {
+ static = true
+ }
+ } else {
+ // Static executables are not supported on Darwin or Windows
+ static = false
+ }
+ }
+ if static {
+ binary.dynamicProperties.VariantIsStatic = true
+ binary.dynamicProperties.VariantIsStaticBinary = true
+ }
+}
+
+func (binary *binaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
+ flags = binary.baseLinker.flags(ctx, flags)
+
+ if ctx.Host() && !binary.staticBinary() {
+ flags.LdFlags = append(flags.LdFlags, "-pie")
+ if ctx.Os() == android.Windows {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup")
+ }
+ }
+
+ // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
+ // all code is position independent, and then those warnings get promoted to
+ // errors.
+ if ctx.Os() != android.Windows {
+ flags.CFlags = append(flags.CFlags, "-fpie")
+ }
+
+ if ctx.Device() {
+ if binary.buildStatic() {
+ // Clang driver needs -static to create static executable.
+ // However, bionic/linker uses -shared to overwrite.
+ // Linker for x86 targets does not allow coexistance of -static and -shared,
+ // so we add -static only if -shared is not used.
+ if !inList("-shared", flags.LdFlags) {
+ flags.LdFlags = append(flags.LdFlags, "-static")
+ }
+
+ flags.LdFlags = append(flags.LdFlags,
+ "-nostdlib",
+ "-Bstatic",
+ "-Wl,--gc-sections",
+ )
+
+ } else {
+ if flags.DynamicLinker == "" {
+ flags.DynamicLinker = "/system/bin/linker"
+ if flags.Toolchain.Is64Bit() {
+ flags.DynamicLinker += "64"
+ }
+ }
+
+ flags.LdFlags = append(flags.LdFlags,
+ "-pie",
+ "-nostdlib",
+ "-Bdynamic",
+ "-Wl,--gc-sections",
+ "-Wl,-z,nocopyreloc",
+ )
+ }
+ } else {
+ if binary.staticBinary() {
+ flags.LdFlags = append(flags.LdFlags, "-static")
+ }
+ if ctx.Darwin() {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names")
+ }
+ }
+
+ return flags
+}
+
+func (binary *binaryLinker) link(ctx ModuleContext,
+ flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+ fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
+ outputFile := android.PathForModuleOut(ctx, fileName)
+ ret := outputFile
+ if ctx.Os().Class == android.Host {
+ binary.hostToolPath = android.OptionalPathForPath(outputFile)
+ }
+
+ var linkerDeps android.Paths
+
+ sharedLibs := deps.SharedLibs
+ sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
+
+ if flags.DynamicLinker != "" {
+ flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
+ }
+
+ builderFlags := flagsToBuilderFlags(flags)
+
+ if binary.stripper.needsStrip(ctx) {
+ strippedOutputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
+ binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
+ }
+
+ if binary.Properties.Prefix_symbols != "" {
+ afterPrefixSymbols := outputFile
+ outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
+ TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile,
+ flagsToBuilderFlags(flags), afterPrefixSymbols)
+ }
+
+ TransformObjToDynamicBinary(ctx, objFiles, sharedLibs, deps.StaticLibs,
+ deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
+ builderFlags, outputFile)
+
+ return ret
+}
+
+func (binary *binaryLinker) HostToolPath() android.OptionalPath {
+ return binary.hostToolPath
+}
diff --git a/cc/cc.go b/cc/cc.go
index 12d9ed7..53345c5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -20,7 +20,6 @@
import (
"fmt"
- "path/filepath"
"strings"
"github.com/google/blueprint"
@@ -32,27 +31,9 @@
)
func init() {
- soong.RegisterModuleType("cc_library_static", libraryStaticFactory)
- soong.RegisterModuleType("cc_library_shared", librarySharedFactory)
- soong.RegisterModuleType("cc_library", libraryFactory)
- soong.RegisterModuleType("cc_object", objectFactory)
- soong.RegisterModuleType("cc_binary", binaryFactory)
- soong.RegisterModuleType("cc_test", testFactory)
- soong.RegisterModuleType("cc_test_library", testLibraryFactory)
- soong.RegisterModuleType("cc_benchmark", benchmarkFactory)
soong.RegisterModuleType("cc_defaults", defaultsFactory)
soong.RegisterModuleType("toolchain_library", toolchainLibraryFactory)
- soong.RegisterModuleType("ndk_prebuilt_library", ndkPrebuiltLibraryFactory)
- soong.RegisterModuleType("ndk_prebuilt_object", ndkPrebuiltObjectFactory)
- soong.RegisterModuleType("ndk_prebuilt_static_stl", ndkPrebuiltStaticStlFactory)
- soong.RegisterModuleType("ndk_prebuilt_shared_stl", ndkPrebuiltSharedStlFactory)
-
- soong.RegisterModuleType("cc_library_host_static", libraryHostStaticFactory)
- soong.RegisterModuleType("cc_library_host_shared", libraryHostSharedFactory)
- soong.RegisterModuleType("cc_binary_host", binaryHostFactory)
- soong.RegisterModuleType("cc_test_host", testHostFactory)
- soong.RegisterModuleType("cc_benchmark_host", benchmarkHostFactory)
// LinkageMutator must be registered after common.ArchMutator, but that is guaranteed by
// the Go initialization order because this package depends on common, so common's init
@@ -69,139 +50,6 @@
android.RegisterBottomUpMutator("tsan", sanitizerMutator(tsan))
}
-var (
- HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
-
- // These libraries have migrated over to the new ndk_library, which is added
- // as a variation dependency via depsMutator.
- ndkMigratedLibs = []string{}
-)
-
-// Flags used by lots of devices. Putting them in package static variables will save bytes in
-// build.ninja so they aren't repeated for every file
-var (
- commonGlobalCflags = []string{
- "-DANDROID",
- "-fmessage-length=0",
- "-W",
- "-Wall",
- "-Wno-unused",
- "-Winit-self",
- "-Wpointer-arith",
-
- // COMMON_RELEASE_CFLAGS
- "-DNDEBUG",
- "-UDEBUG",
- }
-
- deviceGlobalCflags = []string{
- "-fdiagnostics-color",
-
- // TARGET_ERROR_FLAGS
- "-Werror=return-type",
- "-Werror=non-virtual-dtor",
- "-Werror=address",
- "-Werror=sequence-point",
- "-Werror=date-time",
- }
-
- hostGlobalCflags = []string{}
-
- commonGlobalCppflags = []string{
- "-Wsign-promo",
- }
-
- noOverrideGlobalCflags = []string{
- "-Werror=int-to-pointer-cast",
- "-Werror=pointer-to-int-cast",
- }
-
- illegalFlags = []string{
- "-w",
- }
-
- ndkPrebuiltSharedLibs = []string{
- "android",
- "c",
- "dl",
- "EGL",
- "GLESv1_CM",
- "GLESv2",
- "GLESv3",
- "jnigraphics",
- "log",
- "mediandk",
- "m",
- "OpenMAXAL",
- "OpenSLES",
- "stdc++",
- "vulkan",
- "z",
- }
- ndkPrebuiltSharedLibraries = addPrefix(append([]string(nil), ndkPrebuiltSharedLibs...), "lib")
-)
-
-func init() {
- if android.BuildOs == android.Linux {
- commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
- }
-
- pctx.StaticVariable("commonGlobalCflags", strings.Join(commonGlobalCflags, " "))
- pctx.StaticVariable("deviceGlobalCflags", strings.Join(deviceGlobalCflags, " "))
- pctx.StaticVariable("hostGlobalCflags", strings.Join(hostGlobalCflags, " "))
- pctx.StaticVariable("noOverrideGlobalCflags", strings.Join(noOverrideGlobalCflags, " "))
-
- pctx.StaticVariable("commonGlobalCppflags", strings.Join(commonGlobalCppflags, " "))
-
- pctx.StaticVariable("commonClangGlobalCflags",
- strings.Join(append(clangFilterUnknownCflags(commonGlobalCflags), "${clangExtraCflags}"), " "))
- pctx.StaticVariable("deviceClangGlobalCflags",
- strings.Join(append(clangFilterUnknownCflags(deviceGlobalCflags), "${clangExtraTargetCflags}"), " "))
- pctx.StaticVariable("hostClangGlobalCflags",
- strings.Join(clangFilterUnknownCflags(hostGlobalCflags), " "))
- pctx.StaticVariable("noOverrideClangGlobalCflags",
- strings.Join(append(clangFilterUnknownCflags(noOverrideGlobalCflags), "${clangExtraNoOverrideCflags}"), " "))
-
- pctx.StaticVariable("commonClangGlobalCppflags",
- strings.Join(append(clangFilterUnknownCflags(commonGlobalCppflags), "${clangExtraCppflags}"), " "))
-
- // Everything in this list is a crime against abstraction and dependency tracking.
- // Do not add anything to this list.
- pctx.PrefixedPathsForOptionalSourceVariable("commonGlobalIncludes", "-isystem ",
- []string{
- "system/core/include",
- "system/media/audio/include",
- "hardware/libhardware/include",
- "hardware/libhardware_legacy/include",
- "hardware/ril/include",
- "libnativehelper/include",
- "frameworks/native/include",
- "frameworks/native/opengl/include",
- "frameworks/av/include",
- "frameworks/base/include",
- })
- // This is used by non-NDK modules to get jni.h. export_include_dirs doesn't help
- // with this, since there is no associated library.
- pctx.PrefixedPathsForOptionalSourceVariable("commonNativehelperInclude", "-I",
- []string{"libnativehelper/include/nativehelper"})
-
- pctx.SourcePathVariable("clangDefaultBase", "prebuilts/clang/host")
- pctx.VariableFunc("clangBase", func(config interface{}) (string, error) {
- if override := config.(android.Config).Getenv("LLVM_PREBUILTS_BASE"); override != "" {
- return override, nil
- }
- return "${clangDefaultBase}", nil
- })
- pctx.VariableFunc("clangVersion", func(config interface{}) (string, error) {
- if override := config.(android.Config).Getenv("LLVM_PREBUILTS_VERSION"); override != "" {
- return override, nil
- }
- return "clang-3016494", nil
- })
- pctx.StaticVariable("clangPath", "${clangBase}/${HostPrebuiltTag}/${clangVersion}")
- pctx.StaticVariable("clangBin", "${clangPath}/bin")
-}
-
type Deps struct {
SharedLibs, LateSharedLibs []string
StaticLibs, LateStaticLibs, WholeStaticLibs []string
@@ -251,191 +99,6 @@
CFlagsDeps android.Paths // Files depended on by compiler flags
}
-type BaseCompilerProperties struct {
- // list of source files used to compile the C/C++ module. May be .c, .cpp, or .S files.
- Srcs []string `android:"arch_variant"`
-
- // list of source files that should not be used to build the C/C++ module.
- // This is most useful in the arch/multilib variants to remove non-common files
- Exclude_srcs []string `android:"arch_variant"`
-
- // list of module-specific flags that will be used for C and C++ compiles.
- Cflags []string `android:"arch_variant"`
-
- // list of module-specific flags that will be used for C++ compiles
- Cppflags []string `android:"arch_variant"`
-
- // list of module-specific flags that will be used for C compiles
- Conlyflags []string `android:"arch_variant"`
-
- // list of module-specific flags that will be used for .S compiles
- Asflags []string `android:"arch_variant"`
-
- // list of module-specific flags that will be used for C and C++ compiles when
- // compiling with clang
- Clang_cflags []string `android:"arch_variant"`
-
- // list of module-specific flags that will be used for .S compiles when
- // compiling with clang
- Clang_asflags []string `android:"arch_variant"`
-
- // list of module-specific flags that will be used for .y and .yy compiles
- Yaccflags []string
-
- // the instruction set architecture to use to compile the C/C++
- // module.
- Instruction_set string `android:"arch_variant"`
-
- // list of directories relative to the root of the source tree that will
- // be added to the include path using -I.
- // If possible, don't use this. If adding paths from the current directory use
- // local_include_dirs, if adding paths from other modules use export_include_dirs in
- // that module.
- Include_dirs []string `android:"arch_variant"`
-
- // list of directories relative to the Blueprints file that will
- // be added to the include path using -I
- Local_include_dirs []string `android:"arch_variant"`
-
- // list of generated sources to compile. These are the names of gensrcs or
- // genrule modules.
- Generated_sources []string `android:"arch_variant"`
-
- // list of generated headers to add to the include path. These are the names
- // of genrule modules.
- Generated_headers []string `android:"arch_variant"`
-
- // pass -frtti instead of -fno-rtti
- Rtti *bool
-
- Debug, Release struct {
- // list of module-specific flags that will be used for C and C++ compiles in debug or
- // release builds
- Cflags []string `android:"arch_variant"`
- } `android:"arch_variant"`
-}
-
-type BaseLinkerProperties struct {
- // list of modules whose object files should be linked into this module
- // in their entirety. For static library modules, all of the .o files from the intermediate
- // directory of the dependency will be linked into this modules .a file. For a shared library,
- // the dependency's .a file will be linked into this module using -Wl,--whole-archive.
- Whole_static_libs []string `android:"arch_variant,variant_prepend"`
-
- // list of modules that should be statically linked into this module.
- Static_libs []string `android:"arch_variant,variant_prepend"`
-
- // list of modules that should be dynamically linked into this module.
- Shared_libs []string `android:"arch_variant"`
-
- // list of module-specific flags that will be used for all link steps
- Ldflags []string `android:"arch_variant"`
-
- // don't insert default compiler flags into asflags, cflags,
- // cppflags, conlyflags, ldflags, or include_dirs
- No_default_compiler_flags *bool
-
- // list of system libraries that will be dynamically linked to
- // shared library and executable modules. If unset, generally defaults to libc
- // and libm. Set to [] to prevent linking against libc and libm.
- System_shared_libs []string
-
- // allow the module to contain undefined symbols. By default,
- // modules cannot contain undefined symbols that are not satisified by their immediate
- // dependencies. Set this flag to true to remove --no-undefined from the linker flags.
- // This flag should only be necessary for compiling low-level libraries like libc.
- Allow_undefined_symbols *bool
-
- // don't link in libgcc.a
- No_libgcc *bool
-
- // -l arguments to pass to linker for host-provided shared libraries
- Host_ldlibs []string `android:"arch_variant"`
-
- // list of shared libraries to re-export include directories from. Entries must be
- // present in shared_libs.
- Export_shared_lib_headers []string `android:"arch_variant"`
-
- // list of static libraries to re-export include directories from. Entries must be
- // present in static_libs.
- Export_static_lib_headers []string `android:"arch_variant"`
-
- // don't link in crt_begin and crt_end. This flag should only be necessary for
- // compiling crt or libc.
- Nocrt *bool `android:"arch_variant"`
-}
-
-type LibraryCompilerProperties struct {
- Static struct {
- Srcs []string `android:"arch_variant"`
- Exclude_srcs []string `android:"arch_variant"`
- Cflags []string `android:"arch_variant"`
- } `android:"arch_variant"`
- Shared struct {
- Srcs []string `android:"arch_variant"`
- Exclude_srcs []string `android:"arch_variant"`
- Cflags []string `android:"arch_variant"`
- } `android:"arch_variant"`
-}
-
-type FlagExporterProperties struct {
- // list of directories relative to the Blueprints file that will
- // be added to the include path using -I for any module that links against this module
- Export_include_dirs []string `android:"arch_variant"`
-}
-
-type LibraryLinkerProperties struct {
- Static struct {
- Enabled *bool `android:"arch_variant"`
- Whole_static_libs []string `android:"arch_variant"`
- Static_libs []string `android:"arch_variant"`
- Shared_libs []string `android:"arch_variant"`
- } `android:"arch_variant"`
- Shared struct {
- Enabled *bool `android:"arch_variant"`
- Whole_static_libs []string `android:"arch_variant"`
- Static_libs []string `android:"arch_variant"`
- Shared_libs []string `android:"arch_variant"`
- } `android:"arch_variant"`
-
- // local file name to pass to the linker as --version_script
- Version_script *string `android:"arch_variant"`
- // local file name to pass to the linker as -unexported_symbols_list
- Unexported_symbols_list *string `android:"arch_variant"`
- // local file name to pass to the linker as -force_symbols_not_weak_list
- Force_symbols_not_weak_list *string `android:"arch_variant"`
- // local file name to pass to the linker as -force_symbols_weak_list
- Force_symbols_weak_list *string `android:"arch_variant"`
-
- // rename host libraries to prevent overlap with system installed libraries
- Unique_host_soname *bool
-
- VariantName string `blueprint:"mutated"`
-}
-
-type BinaryLinkerProperties struct {
- // compile executable with -static
- Static_executable *bool `android:"arch_variant"`
-
- // set the name of the output
- Stem string `android:"arch_variant"`
-
- // append to the name of the output
- Suffix string `android:"arch_variant"`
-
- // if set, add an extra objcopy --prefix-symbols= step
- Prefix_symbols string
-}
-
-type TestLinkerProperties struct {
- // if set, build against the gtest library. Defaults to true.
- Gtest bool
-
- // Create a separate binary for each source file. Useful when there is
- // global state that can not be torn down and reset between each test suite.
- Test_per_src *bool
-}
-
type ObjectLinkerProperties struct {
// names of other cc_object modules to link into this module using partial linking
Objs []string `android:"arch_variant"`
@@ -457,21 +120,6 @@
HideFromMake bool `blueprint:"mutated"`
}
-type InstallerProperties struct {
- // install to a subdirectory of the default install path for the module
- Relative_install_path string
-
- // install symlinks to the module
- Symlinks []string `android:"arch_variant"`
-}
-
-type StripProperties struct {
- Strip struct {
- None bool
- Keep_symbols bool
- }
-}
-
type UnusedProperties struct {
Native_coverage *bool
Required []string
@@ -1161,1394 +809,6 @@
return c.installer.inData()
}
-// Compiler
-
-type baseCompiler struct {
- Properties BaseCompilerProperties
-}
-
-var _ compiler = (*baseCompiler)(nil)
-
-func (compiler *baseCompiler) appendCflags(flags []string) {
- compiler.Properties.Cflags = append(compiler.Properties.Cflags, flags...)
-}
-
-func (compiler *baseCompiler) appendAsflags(flags []string) {
- compiler.Properties.Asflags = append(compiler.Properties.Asflags, flags...)
-}
-
-func (compiler *baseCompiler) props() []interface{} {
- return []interface{}{&compiler.Properties}
-}
-
-func (compiler *baseCompiler) begin(ctx BaseModuleContext) {}
-
-func (compiler *baseCompiler) deps(ctx BaseModuleContext, deps Deps) Deps {
- deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
- deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...)
-
- return deps
-}
-
-// Create a Flags struct that collects the compile flags from global values,
-// per-target values, module type values, and per-module Blueprints properties
-func (compiler *baseCompiler) flags(ctx ModuleContext, flags Flags) Flags {
- toolchain := ctx.toolchain()
-
- CheckBadCompilerFlags(ctx, "cflags", compiler.Properties.Cflags)
- CheckBadCompilerFlags(ctx, "cppflags", compiler.Properties.Cppflags)
- CheckBadCompilerFlags(ctx, "conlyflags", compiler.Properties.Conlyflags)
- CheckBadCompilerFlags(ctx, "asflags", compiler.Properties.Asflags)
-
- flags.CFlags = append(flags.CFlags, compiler.Properties.Cflags...)
- flags.CppFlags = append(flags.CppFlags, compiler.Properties.Cppflags...)
- flags.ConlyFlags = append(flags.ConlyFlags, compiler.Properties.Conlyflags...)
- flags.AsFlags = append(flags.AsFlags, compiler.Properties.Asflags...)
- flags.YaccFlags = append(flags.YaccFlags, compiler.Properties.Yaccflags...)
-
- // Include dir cflags
- rootIncludeDirs := android.PathsForSource(ctx, compiler.Properties.Include_dirs)
- localIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Local_include_dirs)
- flags.GlobalFlags = append(flags.GlobalFlags,
- includeDirsToFlags(localIncludeDirs),
- includeDirsToFlags(rootIncludeDirs))
-
- if !ctx.noDefaultCompilerFlags() {
- if !ctx.sdk() || ctx.Host() {
- flags.GlobalFlags = append(flags.GlobalFlags,
- "${commonGlobalIncludes}",
- toolchain.IncludeFlags(),
- "${commonNativehelperInclude}")
- }
-
- flags.GlobalFlags = append(flags.GlobalFlags, []string{
- "-I" + android.PathForModuleSrc(ctx).String(),
- "-I" + android.PathForModuleOut(ctx).String(),
- "-I" + android.PathForModuleGen(ctx).String(),
- }...)
- }
-
- if ctx.sdk() {
- // The NDK headers are installed to a common sysroot. While a more
- // typical Soong approach would be to only make the headers for the
- // library you're using available, we're trying to emulate the NDK
- // behavior here, and the NDK always has all the NDK headers available.
- flags.GlobalFlags = append(flags.GlobalFlags,
- "-isystem "+getCurrentIncludePath(ctx).String(),
- "-isystem "+getCurrentIncludePath(ctx).Join(ctx, toolchain.ClangTriple()).String())
-
- // Traditionally this has come from android/api-level.h, but with the
- // libc headers unified it must be set by the build system since we
- // don't have per-API level copies of that header now.
- flags.GlobalFlags = append(flags.GlobalFlags,
- "-D__ANDROID_API__="+ctx.sdkVersion())
-
- // Until the full NDK has been migrated to using ndk_headers, we still
- // need to add the legacy sysroot includes to get the full set of
- // headers.
- legacyIncludes := fmt.Sprintf(
- "prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/include",
- ctx.sdkVersion(), ctx.Arch().ArchType.String())
- flags.GlobalFlags = append(flags.GlobalFlags, "-isystem "+legacyIncludes)
- }
-
- instructionSet := compiler.Properties.Instruction_set
- if flags.RequiredInstructionSet != "" {
- instructionSet = flags.RequiredInstructionSet
- }
- instructionSetFlags, err := toolchain.InstructionSetFlags(instructionSet)
- if flags.Clang {
- instructionSetFlags, err = toolchain.ClangInstructionSetFlags(instructionSet)
- }
- if err != nil {
- ctx.ModuleErrorf("%s", err)
- }
-
- CheckBadCompilerFlags(ctx, "release.cflags", compiler.Properties.Release.Cflags)
-
- // TODO: debug
- flags.CFlags = append(flags.CFlags, compiler.Properties.Release.Cflags...)
-
- if flags.Clang {
- CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
- CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
-
- flags.CFlags = clangFilterUnknownCflags(flags.CFlags)
- flags.CFlags = append(flags.CFlags, compiler.Properties.Clang_cflags...)
- flags.AsFlags = append(flags.AsFlags, compiler.Properties.Clang_asflags...)
- flags.CppFlags = clangFilterUnknownCflags(flags.CppFlags)
- flags.ConlyFlags = clangFilterUnknownCflags(flags.ConlyFlags)
- flags.LdFlags = clangFilterUnknownCflags(flags.LdFlags)
-
- target := "-target " + toolchain.ClangTriple()
- var gccPrefix string
- if !ctx.Darwin() {
- gccPrefix = "-B" + filepath.Join(toolchain.GccRoot(), toolchain.GccTriple(), "bin")
- }
-
- flags.CFlags = append(flags.CFlags, target, gccPrefix)
- flags.AsFlags = append(flags.AsFlags, target, gccPrefix)
- flags.LdFlags = append(flags.LdFlags, target, gccPrefix)
- }
-
- hod := "host"
- if ctx.Os().Class == android.Device {
- hod = "device"
- }
-
- if !ctx.noDefaultCompilerFlags() {
- flags.GlobalFlags = append(flags.GlobalFlags, instructionSetFlags)
-
- if flags.Clang {
- flags.AsFlags = append(flags.AsFlags, toolchain.ClangAsflags())
- flags.CppFlags = append(flags.CppFlags, "${commonClangGlobalCppflags}")
- flags.GlobalFlags = append(flags.GlobalFlags,
- toolchain.ClangCflags(),
- "${commonClangGlobalCflags}",
- fmt.Sprintf("${%sClangGlobalCflags}", hod))
-
- flags.ConlyFlags = append(flags.ConlyFlags, "${clangExtraConlyflags}")
- } else {
- flags.CppFlags = append(flags.CppFlags, "${commonGlobalCppflags}")
- flags.GlobalFlags = append(flags.GlobalFlags,
- toolchain.Cflags(),
- "${commonGlobalCflags}",
- fmt.Sprintf("${%sGlobalCflags}", hod))
- }
-
- if Bool(ctx.AConfig().ProductVariables.Brillo) {
- flags.GlobalFlags = append(flags.GlobalFlags, "-D__BRILLO__")
- }
-
- if ctx.Device() {
- if Bool(compiler.Properties.Rtti) {
- flags.CppFlags = append(flags.CppFlags, "-frtti")
- } else {
- flags.CppFlags = append(flags.CppFlags, "-fno-rtti")
- }
- }
-
- flags.AsFlags = append(flags.AsFlags, "-D__ASSEMBLY__")
-
- if flags.Clang {
- flags.CppFlags = append(flags.CppFlags, toolchain.ClangCppflags())
- } else {
- flags.CppFlags = append(flags.CppFlags, toolchain.Cppflags())
- }
- }
-
- if flags.Clang {
- flags.GlobalFlags = append(flags.GlobalFlags, toolchain.ToolchainClangCflags())
- } else {
- flags.GlobalFlags = append(flags.GlobalFlags, toolchain.ToolchainCflags())
- }
-
- if !ctx.sdk() {
- if ctx.Host() && !flags.Clang {
- // The host GCC doesn't support C++14 (and is deprecated, so likely
- // never will). Build these modules with C++11.
- flags.CppFlags = append(flags.CppFlags, "-std=gnu++11")
- } else {
- flags.CppFlags = append(flags.CppFlags, "-std=gnu++14")
- }
- }
-
- // We can enforce some rules more strictly in the code we own. strict
- // indicates if this is code that we can be stricter with. If we have
- // rules that we want to apply to *our* code (but maybe can't for
- // vendor/device specific things), we could extend this to be a ternary
- // value.
- strict := true
- if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
- strict = false
- }
-
- // Can be used to make some annotations stricter for code we can fix
- // (such as when we mark functions as deprecated).
- if strict {
- flags.CFlags = append(flags.CFlags, "-DANDROID_STRICT")
- }
-
- return flags
-}
-
-func ndkPathDeps(ctx ModuleContext) android.Paths {
- if ctx.sdk() {
- // The NDK sysroot timestamp file depends on all the NDK sysroot files
- // (headers and libraries).
- return android.Paths{getNdkSysrootTimestampFile(ctx)}
- }
- return nil
-}
-
-func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
- pathDeps := deps.GeneratedHeaders
- pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
- // Compile files listed in c.Properties.Srcs into objects
- objFiles := compiler.compileObjs(ctx, flags, "",
- compiler.Properties.Srcs, compiler.Properties.Exclude_srcs,
- deps.GeneratedSources, pathDeps)
-
- if ctx.Failed() {
- return nil
- }
-
- return objFiles
-}
-
-// Compile a list of source files into objects a specified subdirectory
-func (compiler *baseCompiler) compileObjs(ctx android.ModuleContext, flags Flags,
- subdir string, srcFiles, excludes []string, extraSrcs, deps android.Paths) android.Paths {
-
- buildFlags := flagsToBuilderFlags(flags)
-
- inputFiles := ctx.ExpandSources(srcFiles, excludes)
- inputFiles = append(inputFiles, extraSrcs...)
- srcPaths, gendeps := genSources(ctx, inputFiles, buildFlags)
-
- deps = append(deps, gendeps...)
- deps = append(deps, flags.CFlagsDeps...)
-
- return TransformSourceToObj(ctx, subdir, srcPaths, buildFlags, deps)
-}
-
-// baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties
-type baseLinker struct {
- Properties BaseLinkerProperties
- dynamicProperties struct {
- VariantIsShared bool `blueprint:"mutated"`
- VariantIsStatic bool `blueprint:"mutated"`
- VariantIsStaticBinary bool `blueprint:"mutated"`
- RunPaths []string `blueprint:"mutated"`
- }
-}
-
-func (linker *baseLinker) appendLdflags(flags []string) {
- linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...)
-}
-
-func (linker *baseLinker) begin(ctx BaseModuleContext) {
- if ctx.toolchain().Is64Bit() {
- linker.dynamicProperties.RunPaths = []string{"../lib64", "lib64"}
- } else {
- linker.dynamicProperties.RunPaths = []string{"../lib", "lib"}
- }
-}
-
-func (linker *baseLinker) props() []interface{} {
- return []interface{}{&linker.Properties, &linker.dynamicProperties}
-}
-
-func (linker *baseLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
- deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
- deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
-
- deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...)
- deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
-
- if !ctx.sdk() && ctx.ModuleName() != "libcompiler_rt-extras" {
- deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras")
- }
-
- if ctx.Device() {
- // libgcc and libatomic have to be last on the command line
- deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
- if !Bool(linker.Properties.No_libgcc) {
- deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
- }
-
- if !linker.static() {
- if linker.Properties.System_shared_libs != nil {
- deps.LateSharedLibs = append(deps.LateSharedLibs,
- linker.Properties.System_shared_libs...)
- } else if !ctx.sdk() {
- deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm")
- }
- }
-
- if ctx.sdk() {
- deps.SharedLibs = append(deps.SharedLibs,
- "libc",
- "libm",
- )
- }
- }
-
- return deps
-}
-
-func (linker *baseLinker) flags(ctx ModuleContext, flags Flags) Flags {
- toolchain := ctx.toolchain()
-
- flags.Nocrt = Bool(linker.Properties.Nocrt)
-
- if !ctx.noDefaultCompilerFlags() {
- if ctx.Device() && !Bool(linker.Properties.Allow_undefined_symbols) {
- flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
- }
-
- if flags.Clang {
- flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
- } else {
- flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags())
- }
-
- if ctx.Host() {
- CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
-
- flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...)
- }
- }
-
- CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
-
- flags.LdFlags = append(flags.LdFlags, linker.Properties.Ldflags...)
-
- if ctx.Host() && !linker.static() {
- rpath_prefix := `\$$ORIGIN/`
- if ctx.Darwin() {
- rpath_prefix = "@loader_path/"
- }
-
- for _, rpath := range linker.dynamicProperties.RunPaths {
- flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
- }
- }
-
- if flags.Clang {
- flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
- } else {
- flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags())
- }
-
- return flags
-}
-
-func (linker *baseLinker) static() bool {
- return linker.dynamicProperties.VariantIsStatic
-}
-
-func (linker *baseLinker) staticBinary() bool {
- return linker.dynamicProperties.VariantIsStaticBinary
-}
-
-func (linker *baseLinker) setStatic(static bool) {
- linker.dynamicProperties.VariantIsStatic = static
-}
-
-func (linker *baseLinker) isDependencyRoot() bool {
- return false
-}
-
-type baseLinkerInterface interface {
- // Returns true if the build options for the module have selected a static or shared build
- buildStatic() bool
- buildShared() bool
-
- // Sets whether a specific variant is static or shared
- setStatic(bool)
-
- // Returns whether a specific variant is a static library or binary
- static() bool
-
- // Returns whether a module is a static binary
- staticBinary() bool
-
- // Returns true for dependency roots (binaries)
- // TODO(ccross): also handle dlopenable libraries
- isDependencyRoot() bool
-}
-
-type baseInstaller struct {
- Properties InstallerProperties
-
- dir string
- dir64 string
- data bool
-
- path android.OutputPath
-}
-
-var _ installer = (*baseInstaller)(nil)
-
-func (installer *baseInstaller) props() []interface{} {
- return []interface{}{&installer.Properties}
-}
-
-func (installer *baseInstaller) install(ctx ModuleContext, file android.Path) {
- subDir := installer.dir
- if ctx.toolchain().Is64Bit() && installer.dir64 != "" {
- subDir = installer.dir64
- }
- if !ctx.Host() && !ctx.Arch().Native {
- subDir = filepath.Join(subDir, ctx.Arch().ArchType.String())
- }
- dir := android.PathForModuleInstall(ctx, subDir, installer.Properties.Relative_install_path)
- installer.path = ctx.InstallFile(dir, file)
- for _, symlink := range installer.Properties.Symlinks {
- ctx.InstallSymlink(dir, symlink, installer.path)
- }
-}
-
-func (installer *baseInstaller) inData() bool {
- return installer.data
-}
-
-//
-// Combined static+shared libraries
-//
-
-type flagExporter struct {
- Properties FlagExporterProperties
-
- flags []string
-}
-
-func (f *flagExporter) exportIncludes(ctx ModuleContext, inc string) {
- includeDirs := android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
- for _, dir := range includeDirs.Strings() {
- f.flags = append(f.flags, inc+dir)
- }
-}
-
-func (f *flagExporter) reexportFlags(flags []string) {
- f.flags = append(f.flags, flags...)
-}
-
-func (f *flagExporter) exportedFlags() []string {
- return f.flags
-}
-
-type exportedFlagsProducer interface {
- exportedFlags() []string
-}
-
-var _ exportedFlagsProducer = (*flagExporter)(nil)
-
-type libraryCompiler struct {
- baseCompiler
-
- linker *libraryLinker
- Properties LibraryCompilerProperties
-
- // For reusing static library objects for shared library
- reuseObjFiles android.Paths
-}
-
-var _ compiler = (*libraryCompiler)(nil)
-
-func (library *libraryCompiler) props() []interface{} {
- props := library.baseCompiler.props()
- return append(props, &library.Properties)
-}
-
-func (library *libraryCompiler) flags(ctx ModuleContext, flags Flags) Flags {
- flags = library.baseCompiler.flags(ctx, flags)
-
- // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
- // all code is position independent, and then those warnings get promoted to
- // errors.
- if ctx.Os() != android.Windows {
- flags.CFlags = append(flags.CFlags, "-fPIC")
- }
-
- if library.linker.static() {
- flags.CFlags = append(flags.CFlags, library.Properties.Static.Cflags...)
- } else {
- flags.CFlags = append(flags.CFlags, library.Properties.Shared.Cflags...)
- }
-
- return flags
-}
-
-func (library *libraryCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
- var objFiles android.Paths
-
- objFiles = library.baseCompiler.compile(ctx, flags, deps)
- library.reuseObjFiles = objFiles
-
- pathDeps := deps.GeneratedHeaders
- pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
-
- if library.linker.static() {
- objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceStaticLibrary,
- library.Properties.Static.Srcs, library.Properties.Static.Exclude_srcs,
- nil, pathDeps)...)
- } else {
- objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceSharedLibrary,
- library.Properties.Shared.Srcs, library.Properties.Shared.Exclude_srcs,
- nil, pathDeps)...)
- }
-
- return objFiles
-}
-
-type libraryLinker struct {
- baseLinker
- flagExporter
- stripper
-
- Properties LibraryLinkerProperties
-
- dynamicProperties struct {
- BuildStatic bool `blueprint:"mutated"`
- BuildShared bool `blueprint:"mutated"`
- }
-
- // If we're used as a whole_static_lib, our missing dependencies need
- // to be given
- wholeStaticMissingDeps []string
-
- // For whole_static_libs
- objFiles android.Paths
-
- // Uses the module's name if empty, but can be overridden. Does not include
- // shlib suffix.
- libName string
-}
-
-var _ linker = (*libraryLinker)(nil)
-
-type libraryInterface interface {
- getWholeStaticMissingDeps() []string
- static() bool
- objs() android.Paths
-}
-
-func (library *libraryLinker) props() []interface{} {
- props := library.baseLinker.props()
- return append(props,
- &library.Properties,
- &library.dynamicProperties,
- &library.flagExporter.Properties,
- &library.stripper.StripProperties)
-}
-
-func (library *libraryLinker) getLibName(ctx ModuleContext) string {
- name := library.libName
- if name == "" {
- name = ctx.ModuleName()
- }
-
- if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
- if !strings.HasSuffix(name, "-host") {
- name = name + "-host"
- }
- }
-
- return name + library.Properties.VariantName
-}
-
-func (library *libraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
- flags = library.baseLinker.flags(ctx, flags)
-
- if !library.static() {
- libName := library.getLibName(ctx)
- // GCC for Android assumes that -shared means -Bsymbolic, use -Wl,-shared instead
- sharedFlag := "-Wl,-shared"
- if flags.Clang || ctx.Host() {
- sharedFlag = "-shared"
- }
- var f []string
- if ctx.Device() {
- f = append(f,
- "-nostdlib",
- "-Wl,--gc-sections",
- )
- }
-
- if ctx.Darwin() {
- f = append(f,
- "-dynamiclib",
- "-single_module",
- //"-read_only_relocs suppress",
- "-install_name @rpath/"+libName+flags.Toolchain.ShlibSuffix(),
- )
- } else {
- f = append(f,
- sharedFlag,
- "-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
- }
-
- flags.LdFlags = append(f, flags.LdFlags...)
- }
-
- return flags
-}
-
-func (library *libraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- deps = library.baseLinker.deps(ctx, deps)
- if library.static() {
- deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Static.Whole_static_libs...)
- deps.StaticLibs = append(deps.StaticLibs, library.Properties.Static.Static_libs...)
- deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
- } else {
- if ctx.Device() && !Bool(library.baseLinker.Properties.Nocrt) {
- if !ctx.sdk() {
- deps.CrtBegin = "crtbegin_so"
- deps.CrtEnd = "crtend_so"
- } else {
- deps.CrtBegin = "ndk_crtbegin_so." + ctx.sdkVersion()
- deps.CrtEnd = "ndk_crtend_so." + ctx.sdkVersion()
- }
- }
- deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Shared.Whole_static_libs...)
- deps.StaticLibs = append(deps.StaticLibs, library.Properties.Shared.Static_libs...)
- deps.SharedLibs = append(deps.SharedLibs, library.Properties.Shared.Shared_libs...)
- }
-
- return deps
-}
-
-func (library *libraryLinker) linkStatic(ctx ModuleContext,
- flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
- library.objFiles = append(android.Paths{}, deps.WholeStaticLibObjFiles...)
- library.objFiles = append(library.objFiles, objFiles...)
-
- outputFile := android.PathForModuleOut(ctx,
- ctx.ModuleName()+library.Properties.VariantName+staticLibraryExtension)
-
- if ctx.Darwin() {
- TransformDarwinObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
- } else {
- TransformObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
- }
-
- library.wholeStaticMissingDeps = ctx.GetMissingDependencies()
-
- ctx.CheckbuildFile(outputFile)
-
- return outputFile
-}
-
-func (library *libraryLinker) linkShared(ctx ModuleContext,
- flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
- var linkerDeps android.Paths
-
- versionScript := android.OptionalPathForModuleSrc(ctx, library.Properties.Version_script)
- unexportedSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Unexported_symbols_list)
- forceNotWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_not_weak_list)
- forceWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_weak_list)
- if !ctx.Darwin() {
- if versionScript.Valid() {
- flags.LdFlags = append(flags.LdFlags, "-Wl,--version-script,"+versionScript.String())
- linkerDeps = append(linkerDeps, versionScript.Path())
- }
- if unexportedSymbols.Valid() {
- ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
- }
- if forceNotWeakSymbols.Valid() {
- ctx.PropertyErrorf("force_symbols_not_weak_list", "Only supported on Darwin")
- }
- if forceWeakSymbols.Valid() {
- ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
- }
- } else {
- if versionScript.Valid() {
- ctx.PropertyErrorf("version_script", "Not supported on Darwin")
- }
- if unexportedSymbols.Valid() {
- flags.LdFlags = append(flags.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
- linkerDeps = append(linkerDeps, unexportedSymbols.Path())
- }
- if forceNotWeakSymbols.Valid() {
- flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_not_weak_list,"+forceNotWeakSymbols.String())
- linkerDeps = append(linkerDeps, forceNotWeakSymbols.Path())
- }
- if forceWeakSymbols.Valid() {
- flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_weak_list,"+forceWeakSymbols.String())
- linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
- }
- }
-
- fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
- outputFile := android.PathForModuleOut(ctx, fileName)
- ret := outputFile
-
- builderFlags := flagsToBuilderFlags(flags)
-
- if library.stripper.needsStrip(ctx) {
- strippedOutputFile := outputFile
- outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
- library.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
- }
-
- sharedLibs := deps.SharedLibs
- sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
-
- TransformObjToDynamicBinary(ctx, objFiles, sharedLibs,
- deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
- linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile)
-
- return ret
-}
-
-func (library *libraryLinker) link(ctx ModuleContext,
- flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
- objFiles = append(objFiles, deps.ObjFiles...)
-
- var out android.Path
- if library.static() {
- out = library.linkStatic(ctx, flags, deps, objFiles)
- } else {
- out = library.linkShared(ctx, flags, deps, objFiles)
- }
-
- library.exportIncludes(ctx, "-I")
- library.reexportFlags(deps.ReexportedFlags)
-
- return out
-}
-
-func (library *libraryLinker) buildStatic() bool {
- return library.dynamicProperties.BuildStatic &&
- (library.Properties.Static.Enabled == nil || *library.Properties.Static.Enabled)
-}
-
-func (library *libraryLinker) buildShared() bool {
- return library.dynamicProperties.BuildShared &&
- (library.Properties.Shared.Enabled == nil || *library.Properties.Shared.Enabled)
-}
-
-func (library *libraryLinker) getWholeStaticMissingDeps() []string {
- return library.wholeStaticMissingDeps
-}
-
-func (library *libraryLinker) installable() bool {
- return !library.static()
-}
-
-func (library *libraryLinker) objs() android.Paths {
- return library.objFiles
-}
-
-type libraryInstaller struct {
- baseInstaller
-
- linker *libraryLinker
- sanitize *sanitize
-}
-
-func (library *libraryInstaller) install(ctx ModuleContext, file android.Path) {
- if !library.linker.static() {
- library.baseInstaller.install(ctx, file)
- }
-}
-
-func (library *libraryInstaller) inData() bool {
- return library.baseInstaller.inData() || library.sanitize.inData()
-}
-
-func NewLibrary(hod android.HostOrDeviceSupported, shared, static bool) *Module {
- module := newModule(hod, android.MultilibBoth)
-
- linker := &libraryLinker{}
- linker.dynamicProperties.BuildShared = shared
- linker.dynamicProperties.BuildStatic = static
- module.linker = linker
-
- module.compiler = &libraryCompiler{
- linker: linker,
- }
- module.installer = &libraryInstaller{
- baseInstaller: baseInstaller{
- dir: "lib",
- dir64: "lib64",
- },
- linker: linker,
- sanitize: module.sanitize,
- }
-
- return module
-}
-
-func libraryFactory() (blueprint.Module, []interface{}) {
- module := NewLibrary(android.HostAndDeviceSupported, true, true)
- return module.Init()
-}
-
-//
-// Objects (for crt*.o)
-//
-
-type objectLinker struct {
- Properties ObjectLinkerProperties
-}
-
-func objectFactory() (blueprint.Module, []interface{}) {
- module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
- module.compiler = &baseCompiler{}
- module.linker = &objectLinker{}
- return module.Init()
-}
-
-func (object *objectLinker) appendLdflags(flags []string) {
- panic(fmt.Errorf("appendLdflags on object Linker not supported"))
-}
-
-func (object *objectLinker) props() []interface{} {
- return []interface{}{&object.Properties}
-}
-
-func (*objectLinker) begin(ctx BaseModuleContext) {}
-
-func (object *objectLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...)
- return deps
-}
-
-func (*objectLinker) flags(ctx ModuleContext, flags Flags) Flags {
- if flags.Clang {
- flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainClangLdflags())
- } else {
- flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainLdflags())
- }
-
- return flags
-}
-
-func (object *objectLinker) link(ctx ModuleContext,
- flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
- objFiles = append(objFiles, deps.ObjFiles...)
-
- var outputFile android.Path
- if len(objFiles) == 1 {
- outputFile = objFiles[0]
- } else {
- output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
- TransformObjsToObj(ctx, objFiles, flagsToBuilderFlags(flags), output)
- outputFile = output
- }
-
- ctx.CheckbuildFile(outputFile)
- return outputFile
-}
-
-func (*objectLinker) installable() bool {
- return false
-}
-
-//
-// Executables
-//
-
-type binaryLinker struct {
- baseLinker
- stripper
-
- Properties BinaryLinkerProperties
-
- hostToolPath android.OptionalPath
-}
-
-var _ linker = (*binaryLinker)(nil)
-
-func (binary *binaryLinker) props() []interface{} {
- return append(binary.baseLinker.props(),
- &binary.Properties,
- &binary.stripper.StripProperties)
-
-}
-
-func (binary *binaryLinker) buildStatic() bool {
- return binary.baseLinker.staticBinary()
-}
-
-func (binary *binaryLinker) buildShared() bool {
- return !binary.baseLinker.staticBinary()
-}
-
-func (binary *binaryLinker) getStem(ctx BaseModuleContext) string {
- stem := ctx.ModuleName()
- if binary.Properties.Stem != "" {
- stem = binary.Properties.Stem
- }
-
- return stem + binary.Properties.Suffix
-}
-
-func (binary *binaryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- deps = binary.baseLinker.deps(ctx, deps)
- if ctx.Device() {
- if !Bool(binary.baseLinker.Properties.Nocrt) {
- if !ctx.sdk() {
- if binary.buildStatic() {
- deps.CrtBegin = "crtbegin_static"
- } else {
- deps.CrtBegin = "crtbegin_dynamic"
- }
- deps.CrtEnd = "crtend_android"
- } else {
- if binary.buildStatic() {
- deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
- } else {
- if Bool(binary.Properties.Static_executable) {
- deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
- } else {
- deps.CrtBegin = "ndk_crtbegin_dynamic." + ctx.sdkVersion()
- }
- deps.CrtEnd = "ndk_crtend_android." + ctx.sdkVersion()
- }
- }
- }
-
- if binary.buildStatic() {
- if inList("libc++_static", deps.StaticLibs) {
- deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
- }
- // static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with
- // --start-group/--end-group along with libgcc. If they are in deps.StaticLibs,
- // move them to the beginning of deps.LateStaticLibs
- var groupLibs []string
- deps.StaticLibs, groupLibs = filterList(deps.StaticLibs,
- []string{"libc", "libc_nomalloc", "libcompiler_rt"})
- deps.LateStaticLibs = append(groupLibs, deps.LateStaticLibs...)
- }
- }
-
- if binary.buildShared() && inList("libc", deps.StaticLibs) {
- ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
- "from static libs or set static_executable: true")
- }
- return deps
-}
-
-func (*binaryLinker) installable() bool {
- return true
-}
-
-func (binary *binaryLinker) isDependencyRoot() bool {
- return true
-}
-
-func NewBinary(hod android.HostOrDeviceSupported) *Module {
- module := newModule(hod, android.MultilibFirst)
- module.compiler = &baseCompiler{}
- module.linker = &binaryLinker{}
- module.installer = &baseInstaller{
- dir: "bin",
- }
- return module
-}
-
-func binaryFactory() (blueprint.Module, []interface{}) {
- module := NewBinary(android.HostAndDeviceSupported)
- return module.Init()
-}
-
-func (binary *binaryLinker) begin(ctx BaseModuleContext) {
- binary.baseLinker.begin(ctx)
-
- static := Bool(binary.Properties.Static_executable)
- if ctx.Host() {
- if ctx.Os() == android.Linux {
- if binary.Properties.Static_executable == nil && Bool(ctx.AConfig().ProductVariables.HostStaticBinaries) {
- static = true
- }
- } else {
- // Static executables are not supported on Darwin or Windows
- static = false
- }
- }
- if static {
- binary.dynamicProperties.VariantIsStatic = true
- binary.dynamicProperties.VariantIsStaticBinary = true
- }
-}
-
-func (binary *binaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
- flags = binary.baseLinker.flags(ctx, flags)
-
- if ctx.Host() && !binary.staticBinary() {
- flags.LdFlags = append(flags.LdFlags, "-pie")
- if ctx.Os() == android.Windows {
- flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup")
- }
- }
-
- // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
- // all code is position independent, and then those warnings get promoted to
- // errors.
- if ctx.Os() != android.Windows {
- flags.CFlags = append(flags.CFlags, "-fpie")
- }
-
- if ctx.Device() {
- if binary.buildStatic() {
- // Clang driver needs -static to create static executable.
- // However, bionic/linker uses -shared to overwrite.
- // Linker for x86 targets does not allow coexistance of -static and -shared,
- // so we add -static only if -shared is not used.
- if !inList("-shared", flags.LdFlags) {
- flags.LdFlags = append(flags.LdFlags, "-static")
- }
-
- flags.LdFlags = append(flags.LdFlags,
- "-nostdlib",
- "-Bstatic",
- "-Wl,--gc-sections",
- )
-
- } else {
- if flags.DynamicLinker == "" {
- flags.DynamicLinker = "/system/bin/linker"
- if flags.Toolchain.Is64Bit() {
- flags.DynamicLinker += "64"
- }
- }
-
- flags.LdFlags = append(flags.LdFlags,
- "-pie",
- "-nostdlib",
- "-Bdynamic",
- "-Wl,--gc-sections",
- "-Wl,-z,nocopyreloc",
- )
- }
- } else {
- if binary.staticBinary() {
- flags.LdFlags = append(flags.LdFlags, "-static")
- }
- if ctx.Darwin() {
- flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names")
- }
- }
-
- return flags
-}
-
-func (binary *binaryLinker) link(ctx ModuleContext,
- flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
- fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
- outputFile := android.PathForModuleOut(ctx, fileName)
- ret := outputFile
- if ctx.Os().Class == android.Host {
- binary.hostToolPath = android.OptionalPathForPath(outputFile)
- }
-
- var linkerDeps android.Paths
-
- sharedLibs := deps.SharedLibs
- sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
-
- if flags.DynamicLinker != "" {
- flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
- }
-
- builderFlags := flagsToBuilderFlags(flags)
-
- if binary.stripper.needsStrip(ctx) {
- strippedOutputFile := outputFile
- outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
- binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
- }
-
- if binary.Properties.Prefix_symbols != "" {
- afterPrefixSymbols := outputFile
- outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
- TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile,
- flagsToBuilderFlags(flags), afterPrefixSymbols)
- }
-
- TransformObjToDynamicBinary(ctx, objFiles, sharedLibs, deps.StaticLibs,
- deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
- builderFlags, outputFile)
-
- return ret
-}
-
-func (binary *binaryLinker) HostToolPath() android.OptionalPath {
- return binary.hostToolPath
-}
-
-type stripper struct {
- StripProperties StripProperties
-}
-
-func (stripper *stripper) needsStrip(ctx ModuleContext) bool {
- return !ctx.AConfig().EmbeddedInMake() && !stripper.StripProperties.Strip.None
-}
-
-func (stripper *stripper) strip(ctx ModuleContext, in, out android.ModuleOutPath,
- flags builderFlags) {
- if ctx.Darwin() {
- TransformDarwinStrip(ctx, in, out)
- } else {
- flags.stripKeepSymbols = stripper.StripProperties.Strip.Keep_symbols
- // TODO(ccross): don't add gnu debuglink for user builds
- flags.stripAddGnuDebuglink = true
- TransformStrip(ctx, in, out, flags)
- }
-}
-
-func testPerSrcMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok {
- if test, ok := m.linker.(*testBinaryLinker); ok {
- if Bool(test.testLinker.Properties.Test_per_src) {
- testNames := make([]string, len(m.compiler.(*baseCompiler).Properties.Srcs))
- for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
- testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
- }
- tests := mctx.CreateLocalVariations(testNames...)
- for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
- tests[i].(*Module).compiler.(*baseCompiler).Properties.Srcs = []string{src}
- tests[i].(*Module).linker.(*testBinaryLinker).binaryLinker.Properties.Stem = testNames[i]
- }
- }
- }
- }
-}
-
-type testLinker struct {
- Properties TestLinkerProperties
-}
-
-func (test *testLinker) flags(ctx ModuleContext, flags Flags) Flags {
- if !test.Properties.Gtest {
- return flags
- }
-
- flags.CFlags = append(flags.CFlags, "-DGTEST_HAS_STD_STRING")
- if ctx.Host() {
- flags.CFlags = append(flags.CFlags, "-O0", "-g")
-
- switch ctx.Os() {
- case android.Windows:
- flags.CFlags = append(flags.CFlags, "-DGTEST_OS_WINDOWS")
- case android.Linux:
- flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX")
- flags.LdFlags = append(flags.LdFlags, "-lpthread")
- case android.Darwin:
- flags.CFlags = append(flags.CFlags, "-DGTEST_OS_MAC")
- flags.LdFlags = append(flags.LdFlags, "-lpthread")
- }
- } else {
- flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX_ANDROID")
- }
-
- return flags
-}
-
-func (test *testLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- if test.Properties.Gtest {
- if ctx.sdk() && ctx.Device() {
- switch ctx.selectedStl() {
- case "ndk_libc++_shared", "ndk_libc++_static":
- deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_libcxx", "libgtest_ndk_libcxx")
- case "ndk_libgnustl_static":
- deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_gnustl", "libgtest_ndk_gnustl")
- default:
- deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk", "libgtest_ndk")
- }
- } else {
- deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
- }
- }
- return deps
-}
-
-type testBinaryLinker struct {
- testLinker
- binaryLinker
-}
-
-func (test *testBinaryLinker) begin(ctx BaseModuleContext) {
- test.binaryLinker.begin(ctx)
- runpath := "../../lib"
- if ctx.toolchain().Is64Bit() {
- runpath += "64"
- }
- test.dynamicProperties.RunPaths = append([]string{runpath}, test.dynamicProperties.RunPaths...)
-}
-
-func (test *testBinaryLinker) props() []interface{} {
- return append(test.binaryLinker.props(), &test.testLinker.Properties)
-}
-
-func (test *testBinaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
- flags = test.binaryLinker.flags(ctx, flags)
- flags = test.testLinker.flags(ctx, flags)
- return flags
-}
-
-func (test *testBinaryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- deps = test.testLinker.deps(ctx, deps)
- deps = test.binaryLinker.deps(ctx, deps)
- return deps
-}
-
-type testLibraryLinker struct {
- testLinker
- *libraryLinker
-}
-
-func (test *testLibraryLinker) props() []interface{} {
- return append(test.libraryLinker.props(), &test.testLinker.Properties)
-}
-
-func (test *testLibraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
- flags = test.libraryLinker.flags(ctx, flags)
- flags = test.testLinker.flags(ctx, flags)
- return flags
-}
-
-func (test *testLibraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- deps = test.testLinker.deps(ctx, deps)
- deps = test.libraryLinker.deps(ctx, deps)
- return deps
-}
-
-type testInstaller struct {
- baseInstaller
-}
-
-func (installer *testInstaller) install(ctx ModuleContext, file android.Path) {
- installer.dir = filepath.Join(installer.dir, ctx.ModuleName())
- installer.dir64 = filepath.Join(installer.dir64, ctx.ModuleName())
- installer.baseInstaller.install(ctx, file)
-}
-
-func NewTest(hod android.HostOrDeviceSupported) *Module {
- module := newModule(hod, android.MultilibBoth)
- module.compiler = &baseCompiler{}
- linker := &testBinaryLinker{}
- linker.testLinker.Properties.Gtest = true
- module.linker = linker
- module.installer = &testInstaller{
- baseInstaller: baseInstaller{
- dir: "nativetest",
- dir64: "nativetest64",
- data: true,
- },
- }
- return module
-}
-
-func testFactory() (blueprint.Module, []interface{}) {
- module := NewTest(android.HostAndDeviceSupported)
- return module.Init()
-}
-
-func NewTestLibrary(hod android.HostOrDeviceSupported) *Module {
- module := NewLibrary(android.HostAndDeviceSupported, false, true)
- linker := &testLibraryLinker{
- libraryLinker: module.linker.(*libraryLinker),
- }
- linker.testLinker.Properties.Gtest = true
- module.linker = linker
- module.installer = &testInstaller{
- baseInstaller: baseInstaller{
- dir: "nativetest",
- dir64: "nativetest64",
- data: true,
- },
- }
- return module
-}
-
-func testLibraryFactory() (blueprint.Module, []interface{}) {
- module := NewTestLibrary(android.HostAndDeviceSupported)
- return module.Init()
-}
-
-type benchmarkLinker struct {
- testBinaryLinker
-}
-
-func (benchmark *benchmarkLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- deps = benchmark.testBinaryLinker.deps(ctx, deps)
- deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
- return deps
-}
-
-func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
- module := newModule(hod, android.MultilibFirst)
- module.compiler = &baseCompiler{}
- module.linker = &benchmarkLinker{}
- module.installer = &testInstaller{
- baseInstaller: baseInstaller{
- dir: "nativetest",
- dir64: "nativetest64",
- data: true,
- },
- }
- return module
-}
-
-func benchmarkFactory() (blueprint.Module, []interface{}) {
- module := NewBenchmark(android.HostAndDeviceSupported)
- return module.Init()
-}
-
-//
-// Static library
-//
-
-func libraryStaticFactory() (blueprint.Module, []interface{}) {
- module := NewLibrary(android.HostAndDeviceSupported, false, true)
- return module.Init()
-}
-
-//
-// Shared libraries
-//
-
-func librarySharedFactory() (blueprint.Module, []interface{}) {
- module := NewLibrary(android.HostAndDeviceSupported, true, false)
- return module.Init()
-}
-
-//
-// Host static library
-//
-
-func libraryHostStaticFactory() (blueprint.Module, []interface{}) {
- module := NewLibrary(android.HostSupported, false, true)
- return module.Init()
-}
-
-//
-// Host Shared libraries
-//
-
-func libraryHostSharedFactory() (blueprint.Module, []interface{}) {
- module := NewLibrary(android.HostSupported, true, false)
- return module.Init()
-}
-
-//
-// Host Binaries
-//
-
-func binaryHostFactory() (blueprint.Module, []interface{}) {
- module := NewBinary(android.HostSupported)
- return module.Init()
-}
-
-//
-// Host Tests
-//
-
-func testHostFactory() (blueprint.Module, []interface{}) {
- module := NewTest(android.HostSupported)
- return module.Init()
-}
-
-//
-// Host Benchmarks
-//
-
-func benchmarkHostFactory() (blueprint.Module, []interface{}) {
- module := NewBenchmark(android.HostSupported)
- return module.Init()
-}
-
//
// Defaults
//
@@ -2636,198 +896,6 @@
return false
}
-// NDK prebuilt libraries.
-//
-// These differ from regular prebuilts in that they aren't stripped and usually aren't installed
-// either (with the exception of the shared STLs, which are installed to the app's directory rather
-// than to the system image).
-
-func getNdkLibDir(ctx android.ModuleContext, toolchain Toolchain, version string) android.SourcePath {
- suffix := ""
- // Most 64-bit NDK prebuilts store libraries in "lib64", except for arm64 which is not a
- // multilib toolchain and stores the libraries in "lib".
- if toolchain.Is64Bit() && ctx.Arch().ArchType != android.Arm64 {
- suffix = "64"
- }
- return android.PathForSource(ctx, fmt.Sprintf("prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib%s",
- version, toolchain.Name(), suffix))
-}
-
-func ndkPrebuiltModuleToPath(ctx android.ModuleContext, toolchain Toolchain,
- ext string, version string) android.Path {
-
- // NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION.
- // We want to translate to just NAME.EXT
- name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0]
- dir := getNdkLibDir(ctx, toolchain, version)
- return dir.Join(ctx, name+ext)
-}
-
-type ndkPrebuiltObjectLinker struct {
- objectLinker
-}
-
-func (*ndkPrebuiltObjectLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- // NDK objects can't have any dependencies
- return deps
-}
-
-func ndkPrebuiltObjectFactory() (blueprint.Module, []interface{}) {
- module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
- module.linker = &ndkPrebuiltObjectLinker{}
- module.Properties.HideFromMake = true
- return module.Init()
-}
-
-func (c *ndkPrebuiltObjectLinker) link(ctx ModuleContext, flags Flags,
- deps PathDeps, objFiles android.Paths) android.Path {
- // A null build step, but it sets up the output path.
- if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") {
- ctx.ModuleErrorf("NDK prebuilts must have an ndk_crt prefixed name")
- }
-
- return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, ctx.sdkVersion())
-}
-
-type ndkPrebuiltLibraryLinker struct {
- libraryLinker
-}
-
-var _ baseLinkerInterface = (*ndkPrebuiltLibraryLinker)(nil)
-var _ exportedFlagsProducer = (*libraryLinker)(nil)
-
-func (ndk *ndkPrebuiltLibraryLinker) props() []interface{} {
- return append(ndk.libraryLinker.props(), &ndk.Properties, &ndk.flagExporter.Properties)
-}
-
-func (*ndkPrebuiltLibraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
- // NDK libraries can't have any dependencies
- return deps
-}
-
-func ndkPrebuiltLibraryFactory() (blueprint.Module, []interface{}) {
- module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
- linker := &ndkPrebuiltLibraryLinker{}
- linker.dynamicProperties.BuildShared = true
- module.linker = linker
- module.Properties.HideFromMake = true
- return module.Init()
-}
-
-func (ndk *ndkPrebuiltLibraryLinker) link(ctx ModuleContext, flags Flags,
- deps PathDeps, objFiles android.Paths) android.Path {
- // A null build step, but it sets up the output path.
- ndk.exportIncludes(ctx, "-isystem")
-
- return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(),
- ctx.sdkVersion())
-}
-
-// The NDK STLs are slightly different from the prebuilt system libraries:
-// * Are not specific to each platform version.
-// * The libraries are not in a predictable location for each STL.
-
-type ndkPrebuiltStlLinker struct {
- ndkPrebuiltLibraryLinker
-}
-
-func ndkPrebuiltSharedStlFactory() (blueprint.Module, []interface{}) {
- module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
- linker := &ndkPrebuiltStlLinker{}
- linker.dynamicProperties.BuildShared = true
- module.linker = linker
- module.Properties.HideFromMake = true
- return module.Init()
-}
-
-func ndkPrebuiltStaticStlFactory() (blueprint.Module, []interface{}) {
- module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
- linker := &ndkPrebuiltStlLinker{}
- linker.dynamicProperties.BuildStatic = true
- module.linker = linker
- module.Properties.HideFromMake = true
- return module.Init()
-}
-
-func getNdkStlLibDir(ctx android.ModuleContext, toolchain Toolchain, stl string) android.SourcePath {
- gccVersion := toolchain.GccVersion()
- var libDir string
- switch stl {
- case "libstlport":
- libDir = "cxx-stl/stlport/libs"
- case "libc++":
- libDir = "cxx-stl/llvm-libc++/libs"
- case "libgnustl":
- libDir = fmt.Sprintf("cxx-stl/gnu-libstdc++/%s/libs", gccVersion)
- }
-
- if libDir != "" {
- ndkSrcRoot := "prebuilts/ndk/current/sources"
- return android.PathForSource(ctx, ndkSrcRoot).Join(ctx, libDir, ctx.Arch().Abi[0])
- }
-
- ctx.ModuleErrorf("Unknown NDK STL: %s", stl)
- return android.PathForSource(ctx, "")
-}
-
-func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags,
- deps PathDeps, objFiles android.Paths) android.Path {
- // A null build step, but it sets up the output path.
- if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
- ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
- }
-
- ndk.exportIncludes(ctx, "-I")
-
- libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
- libExt := flags.Toolchain.ShlibSuffix()
- if ndk.dynamicProperties.BuildStatic {
- libExt = staticLibraryExtension
- }
-
- stlName := strings.TrimSuffix(libName, "_shared")
- stlName = strings.TrimSuffix(stlName, "_static")
- libDir := getNdkStlLibDir(ctx, flags.Toolchain, stlName)
- return libDir.Join(ctx, libName+libExt)
-}
-
-func linkageMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok {
- if m.linker != nil {
- if linker, ok := m.linker.(baseLinkerInterface); ok {
- var modules []blueprint.Module
- if linker.buildStatic() && linker.buildShared() {
- modules = mctx.CreateLocalVariations("static", "shared")
- static := modules[0].(*Module)
- shared := modules[1].(*Module)
-
- static.linker.(baseLinkerInterface).setStatic(true)
- shared.linker.(baseLinkerInterface).setStatic(false)
-
- if staticCompiler, ok := static.compiler.(*libraryCompiler); ok {
- sharedCompiler := shared.compiler.(*libraryCompiler)
- if len(staticCompiler.Properties.Static.Cflags) == 0 &&
- len(sharedCompiler.Properties.Shared.Cflags) == 0 {
- // Optimize out compiling common .o files twice for static+shared libraries
- mctx.AddInterVariantDependency(reuseObjTag, shared, static)
- sharedCompiler.baseCompiler.Properties.Srcs = nil
- sharedCompiler.baseCompiler.Properties.Generated_sources = nil
- }
- }
- } else if linker.buildStatic() {
- modules = mctx.CreateLocalVariations("static")
- modules[0].(*Module).linker.(baseLinkerInterface).setStatic(true)
- } else if linker.buildShared() {
- modules = mctx.CreateLocalVariations("shared")
- modules[0].(*Module).linker.(baseLinkerInterface).setStatic(false)
- } else {
- panic(fmt.Errorf("library %q not static or shared", mctx.ModuleName()))
- }
- }
- }
- }
-}
-
// lastUniqueElements returns all unique elements of a slice, keeping the last copy of each
// modifies the slice contents in place, and returns a subslice of the original slice
func lastUniqueElements(list []string) []string {
diff --git a/cc/compiler.go b/cc/compiler.go
new file mode 100644
index 0000000..8fcab8f
--- /dev/null
+++ b/cc/compiler.go
@@ -0,0 +1,338 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+
+ "android/soong/android"
+)
+
+// This file contains the basic C/C++/assembly to .o compliation steps
+
+type BaseCompilerProperties struct {
+ // list of source files used to compile the C/C++ module. May be .c, .cpp, or .S files.
+ Srcs []string `android:"arch_variant"`
+
+ // list of source files that should not be used to build the C/C++ module.
+ // This is most useful in the arch/multilib variants to remove non-common files
+ Exclude_srcs []string `android:"arch_variant"`
+
+ // list of module-specific flags that will be used for C and C++ compiles.
+ Cflags []string `android:"arch_variant"`
+
+ // list of module-specific flags that will be used for C++ compiles
+ Cppflags []string `android:"arch_variant"`
+
+ // list of module-specific flags that will be used for C compiles
+ Conlyflags []string `android:"arch_variant"`
+
+ // list of module-specific flags that will be used for .S compiles
+ Asflags []string `android:"arch_variant"`
+
+ // list of module-specific flags that will be used for C and C++ compiles when
+ // compiling with clang
+ Clang_cflags []string `android:"arch_variant"`
+
+ // list of module-specific flags that will be used for .S compiles when
+ // compiling with clang
+ Clang_asflags []string `android:"arch_variant"`
+
+ // list of module-specific flags that will be used for .y and .yy compiles
+ Yaccflags []string
+
+ // the instruction set architecture to use to compile the C/C++
+ // module.
+ Instruction_set string `android:"arch_variant"`
+
+ // list of directories relative to the root of the source tree that will
+ // be added to the include path using -I.
+ // If possible, don't use this. If adding paths from the current directory use
+ // local_include_dirs, if adding paths from other modules use export_include_dirs in
+ // that module.
+ Include_dirs []string `android:"arch_variant"`
+
+ // list of directories relative to the Blueprints file that will
+ // be added to the include path using -I
+ Local_include_dirs []string `android:"arch_variant"`
+
+ // list of generated sources to compile. These are the names of gensrcs or
+ // genrule modules.
+ Generated_sources []string `android:"arch_variant"`
+
+ // list of generated headers to add to the include path. These are the names
+ // of genrule modules.
+ Generated_headers []string `android:"arch_variant"`
+
+ // pass -frtti instead of -fno-rtti
+ Rtti *bool
+
+ Debug, Release struct {
+ // list of module-specific flags that will be used for C and C++ compiles in debug or
+ // release builds
+ Cflags []string `android:"arch_variant"`
+ } `android:"arch_variant"`
+}
+
+type baseCompiler struct {
+ Properties BaseCompilerProperties
+}
+
+var _ compiler = (*baseCompiler)(nil)
+
+func (compiler *baseCompiler) appendCflags(flags []string) {
+ compiler.Properties.Cflags = append(compiler.Properties.Cflags, flags...)
+}
+
+func (compiler *baseCompiler) appendAsflags(flags []string) {
+ compiler.Properties.Asflags = append(compiler.Properties.Asflags, flags...)
+}
+
+func (compiler *baseCompiler) props() []interface{} {
+ return []interface{}{&compiler.Properties}
+}
+
+func (compiler *baseCompiler) begin(ctx BaseModuleContext) {}
+
+func (compiler *baseCompiler) deps(ctx BaseModuleContext, deps Deps) Deps {
+ deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
+ deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...)
+
+ return deps
+}
+
+// Create a Flags struct that collects the compile flags from global values,
+// per-target values, module type values, and per-module Blueprints properties
+func (compiler *baseCompiler) flags(ctx ModuleContext, flags Flags) Flags {
+ toolchain := ctx.toolchain()
+
+ CheckBadCompilerFlags(ctx, "cflags", compiler.Properties.Cflags)
+ CheckBadCompilerFlags(ctx, "cppflags", compiler.Properties.Cppflags)
+ CheckBadCompilerFlags(ctx, "conlyflags", compiler.Properties.Conlyflags)
+ CheckBadCompilerFlags(ctx, "asflags", compiler.Properties.Asflags)
+
+ flags.CFlags = append(flags.CFlags, compiler.Properties.Cflags...)
+ flags.CppFlags = append(flags.CppFlags, compiler.Properties.Cppflags...)
+ flags.ConlyFlags = append(flags.ConlyFlags, compiler.Properties.Conlyflags...)
+ flags.AsFlags = append(flags.AsFlags, compiler.Properties.Asflags...)
+ flags.YaccFlags = append(flags.YaccFlags, compiler.Properties.Yaccflags...)
+
+ // Include dir cflags
+ rootIncludeDirs := android.PathsForSource(ctx, compiler.Properties.Include_dirs)
+ localIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Local_include_dirs)
+ flags.GlobalFlags = append(flags.GlobalFlags,
+ includeDirsToFlags(localIncludeDirs),
+ includeDirsToFlags(rootIncludeDirs))
+
+ if !ctx.noDefaultCompilerFlags() {
+ if !ctx.sdk() || ctx.Host() {
+ flags.GlobalFlags = append(flags.GlobalFlags,
+ "${commonGlobalIncludes}",
+ toolchain.IncludeFlags(),
+ "${commonNativehelperInclude}")
+ }
+
+ flags.GlobalFlags = append(flags.GlobalFlags, []string{
+ "-I" + android.PathForModuleSrc(ctx).String(),
+ "-I" + android.PathForModuleOut(ctx).String(),
+ "-I" + android.PathForModuleGen(ctx).String(),
+ }...)
+ }
+
+ if ctx.sdk() {
+ // The NDK headers are installed to a common sysroot. While a more
+ // typical Soong approach would be to only make the headers for the
+ // library you're using available, we're trying to emulate the NDK
+ // behavior here, and the NDK always has all the NDK headers available.
+ flags.GlobalFlags = append(flags.GlobalFlags,
+ "-isystem "+getCurrentIncludePath(ctx).String(),
+ "-isystem "+getCurrentIncludePath(ctx).Join(ctx, toolchain.ClangTriple()).String())
+
+ // Traditionally this has come from android/api-level.h, but with the
+ // libc headers unified it must be set by the build system since we
+ // don't have per-API level copies of that header now.
+ flags.GlobalFlags = append(flags.GlobalFlags,
+ "-D__ANDROID_API__="+ctx.sdkVersion())
+
+ // Until the full NDK has been migrated to using ndk_headers, we still
+ // need to add the legacy sysroot includes to get the full set of
+ // headers.
+ legacyIncludes := fmt.Sprintf(
+ "prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/include",
+ ctx.sdkVersion(), ctx.Arch().ArchType.String())
+ flags.GlobalFlags = append(flags.GlobalFlags, "-isystem "+legacyIncludes)
+ }
+
+ instructionSet := compiler.Properties.Instruction_set
+ if flags.RequiredInstructionSet != "" {
+ instructionSet = flags.RequiredInstructionSet
+ }
+ instructionSetFlags, err := toolchain.InstructionSetFlags(instructionSet)
+ if flags.Clang {
+ instructionSetFlags, err = toolchain.ClangInstructionSetFlags(instructionSet)
+ }
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ }
+
+ CheckBadCompilerFlags(ctx, "release.cflags", compiler.Properties.Release.Cflags)
+
+ // TODO: debug
+ flags.CFlags = append(flags.CFlags, compiler.Properties.Release.Cflags...)
+
+ if flags.Clang {
+ CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
+ CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
+
+ flags.CFlags = clangFilterUnknownCflags(flags.CFlags)
+ flags.CFlags = append(flags.CFlags, compiler.Properties.Clang_cflags...)
+ flags.AsFlags = append(flags.AsFlags, compiler.Properties.Clang_asflags...)
+ flags.CppFlags = clangFilterUnknownCflags(flags.CppFlags)
+ flags.ConlyFlags = clangFilterUnknownCflags(flags.ConlyFlags)
+ flags.LdFlags = clangFilterUnknownCflags(flags.LdFlags)
+
+ target := "-target " + toolchain.ClangTriple()
+ var gccPrefix string
+ if !ctx.Darwin() {
+ gccPrefix = "-B" + filepath.Join(toolchain.GccRoot(), toolchain.GccTriple(), "bin")
+ }
+
+ flags.CFlags = append(flags.CFlags, target, gccPrefix)
+ flags.AsFlags = append(flags.AsFlags, target, gccPrefix)
+ flags.LdFlags = append(flags.LdFlags, target, gccPrefix)
+ }
+
+ hod := "host"
+ if ctx.Os().Class == android.Device {
+ hod = "device"
+ }
+
+ if !ctx.noDefaultCompilerFlags() {
+ flags.GlobalFlags = append(flags.GlobalFlags, instructionSetFlags)
+
+ if flags.Clang {
+ flags.AsFlags = append(flags.AsFlags, toolchain.ClangAsflags())
+ flags.CppFlags = append(flags.CppFlags, "${commonClangGlobalCppflags}")
+ flags.GlobalFlags = append(flags.GlobalFlags,
+ toolchain.ClangCflags(),
+ "${commonClangGlobalCflags}",
+ fmt.Sprintf("${%sClangGlobalCflags}", hod))
+
+ flags.ConlyFlags = append(flags.ConlyFlags, "${clangExtraConlyflags}")
+ } else {
+ flags.CppFlags = append(flags.CppFlags, "${commonGlobalCppflags}")
+ flags.GlobalFlags = append(flags.GlobalFlags,
+ toolchain.Cflags(),
+ "${commonGlobalCflags}",
+ fmt.Sprintf("${%sGlobalCflags}", hod))
+ }
+
+ if Bool(ctx.AConfig().ProductVariables.Brillo) {
+ flags.GlobalFlags = append(flags.GlobalFlags, "-D__BRILLO__")
+ }
+
+ if ctx.Device() {
+ if Bool(compiler.Properties.Rtti) {
+ flags.CppFlags = append(flags.CppFlags, "-frtti")
+ } else {
+ flags.CppFlags = append(flags.CppFlags, "-fno-rtti")
+ }
+ }
+
+ flags.AsFlags = append(flags.AsFlags, "-D__ASSEMBLY__")
+
+ if flags.Clang {
+ flags.CppFlags = append(flags.CppFlags, toolchain.ClangCppflags())
+ } else {
+ flags.CppFlags = append(flags.CppFlags, toolchain.Cppflags())
+ }
+ }
+
+ if flags.Clang {
+ flags.GlobalFlags = append(flags.GlobalFlags, toolchain.ToolchainClangCflags())
+ } else {
+ flags.GlobalFlags = append(flags.GlobalFlags, toolchain.ToolchainCflags())
+ }
+
+ if !ctx.sdk() {
+ if ctx.Host() && !flags.Clang {
+ // The host GCC doesn't support C++14 (and is deprecated, so likely
+ // never will). Build these modules with C++11.
+ flags.CppFlags = append(flags.CppFlags, "-std=gnu++11")
+ } else {
+ flags.CppFlags = append(flags.CppFlags, "-std=gnu++14")
+ }
+ }
+
+ // We can enforce some rules more strictly in the code we own. strict
+ // indicates if this is code that we can be stricter with. If we have
+ // rules that we want to apply to *our* code (but maybe can't for
+ // vendor/device specific things), we could extend this to be a ternary
+ // value.
+ strict := true
+ if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
+ strict = false
+ }
+
+ // Can be used to make some annotations stricter for code we can fix
+ // (such as when we mark functions as deprecated).
+ if strict {
+ flags.CFlags = append(flags.CFlags, "-DANDROID_STRICT")
+ }
+
+ return flags
+}
+
+func ndkPathDeps(ctx ModuleContext) android.Paths {
+ if ctx.sdk() {
+ // The NDK sysroot timestamp file depends on all the NDK sysroot files
+ // (headers and libraries).
+ return android.Paths{getNdkSysrootTimestampFile(ctx)}
+ }
+ return nil
+}
+
+func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
+ pathDeps := deps.GeneratedHeaders
+ pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
+ // Compile files listed in c.Properties.Srcs into objects
+ objFiles := compiler.compileObjs(ctx, flags, "",
+ compiler.Properties.Srcs, compiler.Properties.Exclude_srcs,
+ deps.GeneratedSources, pathDeps)
+
+ if ctx.Failed() {
+ return nil
+ }
+
+ return objFiles
+}
+
+// Compile a list of source files into objects a specified subdirectory
+func (compiler *baseCompiler) compileObjs(ctx android.ModuleContext, flags Flags,
+ subdir string, srcFiles, excludes []string, extraSrcs, deps android.Paths) android.Paths {
+
+ buildFlags := flagsToBuilderFlags(flags)
+
+ inputFiles := ctx.ExpandSources(srcFiles, excludes)
+ inputFiles = append(inputFiles, extraSrcs...)
+ srcPaths, gendeps := genSources(ctx, inputFiles, buildFlags)
+
+ deps = append(deps, gendeps...)
+ deps = append(deps, flags.CFlagsDeps...)
+
+ return TransformSourceToObj(ctx, subdir, srcPaths, buildFlags, deps)
+}
diff --git a/cc/global.go b/cc/global.go
new file mode 100644
index 0000000..ec0f572
--- /dev/null
+++ b/cc/global.go
@@ -0,0 +1,138 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+// Flags used by lots of devices. Putting them in package static variables will save bytes in
+// build.ninja so they aren't repeated for every file
+var (
+ commonGlobalCflags = []string{
+ "-DANDROID",
+ "-fmessage-length=0",
+ "-W",
+ "-Wall",
+ "-Wno-unused",
+ "-Winit-self",
+ "-Wpointer-arith",
+
+ // COMMON_RELEASE_CFLAGS
+ "-DNDEBUG",
+ "-UDEBUG",
+ }
+
+ deviceGlobalCflags = []string{
+ "-fdiagnostics-color",
+
+ // TARGET_ERROR_FLAGS
+ "-Werror=return-type",
+ "-Werror=non-virtual-dtor",
+ "-Werror=address",
+ "-Werror=sequence-point",
+ "-Werror=date-time",
+ }
+
+ hostGlobalCflags = []string{}
+
+ commonGlobalCppflags = []string{
+ "-Wsign-promo",
+ }
+
+ noOverrideGlobalCflags = []string{
+ "-Werror=int-to-pointer-cast",
+ "-Werror=pointer-to-int-cast",
+ }
+
+ illegalFlags = []string{
+ "-w",
+ }
+)
+
+func init() {
+ if android.BuildOs == android.Linux {
+ commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
+ }
+
+ pctx.StaticVariable("commonGlobalCflags", strings.Join(commonGlobalCflags, " "))
+ pctx.StaticVariable("deviceGlobalCflags", strings.Join(deviceGlobalCflags, " "))
+ pctx.StaticVariable("hostGlobalCflags", strings.Join(hostGlobalCflags, " "))
+ pctx.StaticVariable("noOverrideGlobalCflags", strings.Join(noOverrideGlobalCflags, " "))
+
+ pctx.StaticVariable("commonGlobalCppflags", strings.Join(commonGlobalCppflags, " "))
+
+ pctx.StaticVariable("commonClangGlobalCflags",
+ strings.Join(append(clangFilterUnknownCflags(commonGlobalCflags), "${clangExtraCflags}"), " "))
+ pctx.StaticVariable("deviceClangGlobalCflags",
+ strings.Join(append(clangFilterUnknownCflags(deviceGlobalCflags), "${clangExtraTargetCflags}"), " "))
+ pctx.StaticVariable("hostClangGlobalCflags",
+ strings.Join(clangFilterUnknownCflags(hostGlobalCflags), " "))
+ pctx.StaticVariable("noOverrideClangGlobalCflags",
+ strings.Join(append(clangFilterUnknownCflags(noOverrideGlobalCflags), "${clangExtraNoOverrideCflags}"), " "))
+
+ pctx.StaticVariable("commonClangGlobalCppflags",
+ strings.Join(append(clangFilterUnknownCflags(commonGlobalCppflags), "${clangExtraCppflags}"), " "))
+
+ // Everything in this list is a crime against abstraction and dependency tracking.
+ // Do not add anything to this list.
+ pctx.PrefixedPathsForOptionalSourceVariable("commonGlobalIncludes", "-isystem ",
+ []string{
+ "system/core/include",
+ "system/media/audio/include",
+ "hardware/libhardware/include",
+ "hardware/libhardware_legacy/include",
+ "hardware/ril/include",
+ "libnativehelper/include",
+ "frameworks/native/include",
+ "frameworks/native/opengl/include",
+ "frameworks/av/include",
+ "frameworks/base/include",
+ })
+ // This is used by non-NDK modules to get jni.h. export_include_dirs doesn't help
+ // with this, since there is no associated library.
+ pctx.PrefixedPathsForOptionalSourceVariable("commonNativehelperInclude", "-I",
+ []string{"libnativehelper/include/nativehelper"})
+
+ pctx.SourcePathVariable("clangDefaultBase", "prebuilts/clang/host")
+ pctx.VariableFunc("clangBase", func(config interface{}) (string, error) {
+ if override := config.(android.Config).Getenv("LLVM_PREBUILTS_BASE"); override != "" {
+ return override, nil
+ }
+ return "${clangDefaultBase}", nil
+ })
+ pctx.VariableFunc("clangVersion", func(config interface{}) (string, error) {
+ if override := config.(android.Config).Getenv("LLVM_PREBUILTS_VERSION"); override != "" {
+ return override, nil
+ }
+ return "clang-3016494", nil
+ })
+ pctx.StaticVariable("clangPath", "${clangBase}/${HostPrebuiltTag}/${clangVersion}")
+ pctx.StaticVariable("clangBin", "${clangPath}/bin")
+}
+
+var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
+
+func bionicHeaders(bionicArch, kernelArch string) string {
+ return strings.Join([]string{
+ "-isystem bionic/libc/arch-" + bionicArch + "/include",
+ "-isystem bionic/libc/include",
+ "-isystem bionic/libc/kernel/uapi",
+ "-isystem bionic/libc/kernel/uapi/asm-" + kernelArch,
+ "-isystem bionic/libc/kernel/android/uapi",
+ }, " ")
+}
diff --git a/cc/installer.go b/cc/installer.go
new file mode 100644
index 0000000..7dc2b78
--- /dev/null
+++ b/cc/installer.go
@@ -0,0 +1,66 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+ "path/filepath"
+
+ "android/soong/android"
+)
+
+// This file handles installing files into their final location
+
+type InstallerProperties struct {
+ // install to a subdirectory of the default install path for the module
+ Relative_install_path string
+
+ // install symlinks to the module
+ Symlinks []string `android:"arch_variant"`
+}
+
+type baseInstaller struct {
+ Properties InstallerProperties
+
+ dir string
+ dir64 string
+ data bool
+
+ path android.OutputPath
+}
+
+var _ installer = (*baseInstaller)(nil)
+
+func (installer *baseInstaller) props() []interface{} {
+ return []interface{}{&installer.Properties}
+}
+
+func (installer *baseInstaller) install(ctx ModuleContext, file android.Path) {
+ subDir := installer.dir
+ if ctx.toolchain().Is64Bit() && installer.dir64 != "" {
+ subDir = installer.dir64
+ }
+ if !ctx.Host() && !ctx.Arch().Native {
+ subDir = filepath.Join(subDir, ctx.Arch().ArchType.String())
+ }
+ dir := android.PathForModuleInstall(ctx, subDir, installer.Properties.Relative_install_path)
+ installer.path = ctx.InstallFile(dir, file)
+ for _, symlink := range installer.Properties.Symlinks {
+ ctx.InstallSymlink(dir, symlink, installer.path)
+ }
+}
+
+func (installer *baseInstaller) inData() bool {
+ return installer.data
+}
diff --git a/cc/library.go b/cc/library.go
new file mode 100644
index 0000000..d92a267
--- /dev/null
+++ b/cc/library.go
@@ -0,0 +1,478 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+ "strings"
+
+ "github.com/google/blueprint"
+
+ "android/soong"
+ "android/soong/android"
+)
+
+type LibraryCompilerProperties struct {
+ Static struct {
+ Srcs []string `android:"arch_variant"`
+ Exclude_srcs []string `android:"arch_variant"`
+ Cflags []string `android:"arch_variant"`
+ } `android:"arch_variant"`
+ Shared struct {
+ Srcs []string `android:"arch_variant"`
+ Exclude_srcs []string `android:"arch_variant"`
+ Cflags []string `android:"arch_variant"`
+ } `android:"arch_variant"`
+}
+
+type FlagExporterProperties struct {
+ // list of directories relative to the Blueprints file that will
+ // be added to the include path using -I for any module that links against this module
+ Export_include_dirs []string `android:"arch_variant"`
+}
+
+type LibraryLinkerProperties struct {
+ Static struct {
+ Enabled *bool `android:"arch_variant"`
+ Whole_static_libs []string `android:"arch_variant"`
+ Static_libs []string `android:"arch_variant"`
+ Shared_libs []string `android:"arch_variant"`
+ } `android:"arch_variant"`
+ Shared struct {
+ Enabled *bool `android:"arch_variant"`
+ Whole_static_libs []string `android:"arch_variant"`
+ Static_libs []string `android:"arch_variant"`
+ Shared_libs []string `android:"arch_variant"`
+ } `android:"arch_variant"`
+
+ // local file name to pass to the linker as --version_script
+ Version_script *string `android:"arch_variant"`
+ // local file name to pass to the linker as -unexported_symbols_list
+ Unexported_symbols_list *string `android:"arch_variant"`
+ // local file name to pass to the linker as -force_symbols_not_weak_list
+ Force_symbols_not_weak_list *string `android:"arch_variant"`
+ // local file name to pass to the linker as -force_symbols_weak_list
+ Force_symbols_weak_list *string `android:"arch_variant"`
+
+ // rename host libraries to prevent overlap with system installed libraries
+ Unique_host_soname *bool
+
+ VariantName string `blueprint:"mutated"`
+}
+
+func init() {
+ soong.RegisterModuleType("cc_library_static", libraryStaticFactory)
+ soong.RegisterModuleType("cc_library_shared", librarySharedFactory)
+ soong.RegisterModuleType("cc_library", libraryFactory)
+ soong.RegisterModuleType("cc_library_host_static", libraryHostStaticFactory)
+ soong.RegisterModuleType("cc_library_host_shared", libraryHostSharedFactory)
+}
+
+// Module factory for combined static + shared libraries, device by default but with possible host
+// support
+func libraryFactory() (blueprint.Module, []interface{}) {
+ module := NewLibrary(android.HostAndDeviceSupported, true, true)
+ return module.Init()
+}
+
+// Module factory for static libraries
+func libraryStaticFactory() (blueprint.Module, []interface{}) {
+ module := NewLibrary(android.HostAndDeviceSupported, false, true)
+ return module.Init()
+}
+
+// Module factory for shared libraries
+func librarySharedFactory() (blueprint.Module, []interface{}) {
+ module := NewLibrary(android.HostAndDeviceSupported, true, false)
+ return module.Init()
+}
+
+// Module factory for host static libraries
+func libraryHostStaticFactory() (blueprint.Module, []interface{}) {
+ module := NewLibrary(android.HostSupported, false, true)
+ return module.Init()
+}
+
+// Module factory for host shared libraries
+func libraryHostSharedFactory() (blueprint.Module, []interface{}) {
+ module := NewLibrary(android.HostSupported, true, false)
+ return module.Init()
+}
+
+type flagExporter struct {
+ Properties FlagExporterProperties
+
+ flags []string
+}
+
+func (f *flagExporter) exportIncludes(ctx ModuleContext, inc string) {
+ includeDirs := android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
+ for _, dir := range includeDirs.Strings() {
+ f.flags = append(f.flags, inc+dir)
+ }
+}
+
+func (f *flagExporter) reexportFlags(flags []string) {
+ f.flags = append(f.flags, flags...)
+}
+
+func (f *flagExporter) exportedFlags() []string {
+ return f.flags
+}
+
+type exportedFlagsProducer interface {
+ exportedFlags() []string
+}
+
+var _ exportedFlagsProducer = (*flagExporter)(nil)
+
+type libraryCompiler struct {
+ baseCompiler
+
+ linker *libraryLinker
+ Properties LibraryCompilerProperties
+
+ // For reusing static library objects for shared library
+ reuseObjFiles android.Paths
+}
+
+var _ compiler = (*libraryCompiler)(nil)
+
+func (library *libraryCompiler) props() []interface{} {
+ props := library.baseCompiler.props()
+ return append(props, &library.Properties)
+}
+
+func (library *libraryCompiler) flags(ctx ModuleContext, flags Flags) Flags {
+ flags = library.baseCompiler.flags(ctx, flags)
+
+ // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
+ // all code is position independent, and then those warnings get promoted to
+ // errors.
+ if ctx.Os() != android.Windows {
+ flags.CFlags = append(flags.CFlags, "-fPIC")
+ }
+
+ if library.linker.static() {
+ flags.CFlags = append(flags.CFlags, library.Properties.Static.Cflags...)
+ } else {
+ flags.CFlags = append(flags.CFlags, library.Properties.Shared.Cflags...)
+ }
+
+ return flags
+}
+
+func (library *libraryCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
+ var objFiles android.Paths
+
+ objFiles = library.baseCompiler.compile(ctx, flags, deps)
+ library.reuseObjFiles = objFiles
+
+ pathDeps := deps.GeneratedHeaders
+ pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
+
+ if library.linker.static() {
+ objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceStaticLibrary,
+ library.Properties.Static.Srcs, library.Properties.Static.Exclude_srcs,
+ nil, pathDeps)...)
+ } else {
+ objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceSharedLibrary,
+ library.Properties.Shared.Srcs, library.Properties.Shared.Exclude_srcs,
+ nil, pathDeps)...)
+ }
+
+ return objFiles
+}
+
+type libraryLinker struct {
+ baseLinker
+ flagExporter
+ stripper
+
+ Properties LibraryLinkerProperties
+
+ dynamicProperties struct {
+ BuildStatic bool `blueprint:"mutated"`
+ BuildShared bool `blueprint:"mutated"`
+ }
+
+ // If we're used as a whole_static_lib, our missing dependencies need
+ // to be given
+ wholeStaticMissingDeps []string
+
+ // For whole_static_libs
+ objFiles android.Paths
+
+ // Uses the module's name if empty, but can be overridden. Does not include
+ // shlib suffix.
+ libName string
+}
+
+var _ linker = (*libraryLinker)(nil)
+
+type libraryInterface interface {
+ getWholeStaticMissingDeps() []string
+ static() bool
+ objs() android.Paths
+}
+
+func (library *libraryLinker) props() []interface{} {
+ props := library.baseLinker.props()
+ return append(props,
+ &library.Properties,
+ &library.dynamicProperties,
+ &library.flagExporter.Properties,
+ &library.stripper.StripProperties)
+}
+
+func (library *libraryLinker) getLibName(ctx ModuleContext) string {
+ name := library.libName
+ if name == "" {
+ name = ctx.ModuleName()
+ }
+
+ if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
+ if !strings.HasSuffix(name, "-host") {
+ name = name + "-host"
+ }
+ }
+
+ return name + library.Properties.VariantName
+}
+
+func (library *libraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
+ flags = library.baseLinker.flags(ctx, flags)
+
+ if !library.static() {
+ libName := library.getLibName(ctx)
+ // GCC for Android assumes that -shared means -Bsymbolic, use -Wl,-shared instead
+ sharedFlag := "-Wl,-shared"
+ if flags.Clang || ctx.Host() {
+ sharedFlag = "-shared"
+ }
+ var f []string
+ if ctx.Device() {
+ f = append(f,
+ "-nostdlib",
+ "-Wl,--gc-sections",
+ )
+ }
+
+ if ctx.Darwin() {
+ f = append(f,
+ "-dynamiclib",
+ "-single_module",
+ //"-read_only_relocs suppress",
+ "-install_name @rpath/"+libName+flags.Toolchain.ShlibSuffix(),
+ )
+ } else {
+ f = append(f,
+ sharedFlag,
+ "-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
+ }
+
+ flags.LdFlags = append(f, flags.LdFlags...)
+ }
+
+ return flags
+}
+
+func (library *libraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ deps = library.baseLinker.deps(ctx, deps)
+ if library.static() {
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Static.Whole_static_libs...)
+ deps.StaticLibs = append(deps.StaticLibs, library.Properties.Static.Static_libs...)
+ deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
+ } else {
+ if ctx.Device() && !Bool(library.baseLinker.Properties.Nocrt) {
+ if !ctx.sdk() {
+ deps.CrtBegin = "crtbegin_so"
+ deps.CrtEnd = "crtend_so"
+ } else {
+ deps.CrtBegin = "ndk_crtbegin_so." + ctx.sdkVersion()
+ deps.CrtEnd = "ndk_crtend_so." + ctx.sdkVersion()
+ }
+ }
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Shared.Whole_static_libs...)
+ deps.StaticLibs = append(deps.StaticLibs, library.Properties.Shared.Static_libs...)
+ deps.SharedLibs = append(deps.SharedLibs, library.Properties.Shared.Shared_libs...)
+ }
+
+ return deps
+}
+
+func (library *libraryLinker) linkStatic(ctx ModuleContext,
+ flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+ library.objFiles = append(android.Paths{}, deps.WholeStaticLibObjFiles...)
+ library.objFiles = append(library.objFiles, objFiles...)
+
+ outputFile := android.PathForModuleOut(ctx,
+ ctx.ModuleName()+library.Properties.VariantName+staticLibraryExtension)
+
+ if ctx.Darwin() {
+ TransformDarwinObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
+ } else {
+ TransformObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
+ }
+
+ library.wholeStaticMissingDeps = ctx.GetMissingDependencies()
+
+ ctx.CheckbuildFile(outputFile)
+
+ return outputFile
+}
+
+func (library *libraryLinker) linkShared(ctx ModuleContext,
+ flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+ var linkerDeps android.Paths
+
+ versionScript := android.OptionalPathForModuleSrc(ctx, library.Properties.Version_script)
+ unexportedSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Unexported_symbols_list)
+ forceNotWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_not_weak_list)
+ forceWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_weak_list)
+ if !ctx.Darwin() {
+ if versionScript.Valid() {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,--version-script,"+versionScript.String())
+ linkerDeps = append(linkerDeps, versionScript.Path())
+ }
+ if unexportedSymbols.Valid() {
+ ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
+ }
+ if forceNotWeakSymbols.Valid() {
+ ctx.PropertyErrorf("force_symbols_not_weak_list", "Only supported on Darwin")
+ }
+ if forceWeakSymbols.Valid() {
+ ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
+ }
+ } else {
+ if versionScript.Valid() {
+ ctx.PropertyErrorf("version_script", "Not supported on Darwin")
+ }
+ if unexportedSymbols.Valid() {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
+ linkerDeps = append(linkerDeps, unexportedSymbols.Path())
+ }
+ if forceNotWeakSymbols.Valid() {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_not_weak_list,"+forceNotWeakSymbols.String())
+ linkerDeps = append(linkerDeps, forceNotWeakSymbols.Path())
+ }
+ if forceWeakSymbols.Valid() {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_weak_list,"+forceWeakSymbols.String())
+ linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
+ }
+ }
+
+ fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
+ outputFile := android.PathForModuleOut(ctx, fileName)
+ ret := outputFile
+
+ builderFlags := flagsToBuilderFlags(flags)
+
+ if library.stripper.needsStrip(ctx) {
+ strippedOutputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
+ library.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
+ }
+
+ sharedLibs := deps.SharedLibs
+ sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
+
+ TransformObjToDynamicBinary(ctx, objFiles, sharedLibs,
+ deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
+ linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile)
+
+ return ret
+}
+
+func (library *libraryLinker) link(ctx ModuleContext,
+ flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+ objFiles = append(objFiles, deps.ObjFiles...)
+
+ var out android.Path
+ if library.static() {
+ out = library.linkStatic(ctx, flags, deps, objFiles)
+ } else {
+ out = library.linkShared(ctx, flags, deps, objFiles)
+ }
+
+ library.exportIncludes(ctx, "-I")
+ library.reexportFlags(deps.ReexportedFlags)
+
+ return out
+}
+
+func (library *libraryLinker) buildStatic() bool {
+ return library.dynamicProperties.BuildStatic &&
+ (library.Properties.Static.Enabled == nil || *library.Properties.Static.Enabled)
+}
+
+func (library *libraryLinker) buildShared() bool {
+ return library.dynamicProperties.BuildShared &&
+ (library.Properties.Shared.Enabled == nil || *library.Properties.Shared.Enabled)
+}
+
+func (library *libraryLinker) getWholeStaticMissingDeps() []string {
+ return library.wholeStaticMissingDeps
+}
+
+func (library *libraryLinker) installable() bool {
+ return !library.static()
+}
+
+func (library *libraryLinker) objs() android.Paths {
+ return library.objFiles
+}
+
+type libraryInstaller struct {
+ baseInstaller
+
+ linker *libraryLinker
+ sanitize *sanitize
+}
+
+func (library *libraryInstaller) install(ctx ModuleContext, file android.Path) {
+ if !library.linker.static() {
+ library.baseInstaller.install(ctx, file)
+ }
+}
+
+func (library *libraryInstaller) inData() bool {
+ return library.baseInstaller.inData() || library.sanitize.inData()
+}
+
+func NewLibrary(hod android.HostOrDeviceSupported, shared, static bool) *Module {
+ module := newModule(hod, android.MultilibBoth)
+
+ linker := &libraryLinker{}
+ linker.dynamicProperties.BuildShared = shared
+ linker.dynamicProperties.BuildStatic = static
+ module.linker = linker
+
+ module.compiler = &libraryCompiler{
+ linker: linker,
+ }
+ module.installer = &libraryInstaller{
+ baseInstaller: baseInstaller{
+ dir: "lib",
+ dir64: "lib64",
+ },
+ linker: linker,
+ sanitize: module.sanitize,
+ }
+
+ return module
+}
diff --git a/cc/linker.go b/cc/linker.go
new file mode 100644
index 0000000..c6f13f2
--- /dev/null
+++ b/cc/linker.go
@@ -0,0 +1,216 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+// This file contains the basic functionality for linking against static libraries and shared
+// libraries. Final linking into libraries or executables is handled in library.go, binary.go, etc.
+
+type BaseLinkerProperties struct {
+ // list of modules whose object files should be linked into this module
+ // in their entirety. For static library modules, all of the .o files from the intermediate
+ // directory of the dependency will be linked into this modules .a file. For a shared library,
+ // the dependency's .a file will be linked into this module using -Wl,--whole-archive.
+ Whole_static_libs []string `android:"arch_variant,variant_prepend"`
+
+ // list of modules that should be statically linked into this module.
+ Static_libs []string `android:"arch_variant,variant_prepend"`
+
+ // list of modules that should be dynamically linked into this module.
+ Shared_libs []string `android:"arch_variant"`
+
+ // list of module-specific flags that will be used for all link steps
+ Ldflags []string `android:"arch_variant"`
+
+ // don't insert default compiler flags into asflags, cflags,
+ // cppflags, conlyflags, ldflags, or include_dirs
+ No_default_compiler_flags *bool
+
+ // list of system libraries that will be dynamically linked to
+ // shared library and executable modules. If unset, generally defaults to libc
+ // and libm. Set to [] to prevent linking against libc and libm.
+ System_shared_libs []string
+
+ // allow the module to contain undefined symbols. By default,
+ // modules cannot contain undefined symbols that are not satisified by their immediate
+ // dependencies. Set this flag to true to remove --no-undefined from the linker flags.
+ // This flag should only be necessary for compiling low-level libraries like libc.
+ Allow_undefined_symbols *bool
+
+ // don't link in libgcc.a
+ No_libgcc *bool
+
+ // -l arguments to pass to linker for host-provided shared libraries
+ Host_ldlibs []string `android:"arch_variant"`
+
+ // list of shared libraries to re-export include directories from. Entries must be
+ // present in shared_libs.
+ Export_shared_lib_headers []string `android:"arch_variant"`
+
+ // list of static libraries to re-export include directories from. Entries must be
+ // present in static_libs.
+ Export_static_lib_headers []string `android:"arch_variant"`
+
+ // don't link in crt_begin and crt_end. This flag should only be necessary for
+ // compiling crt or libc.
+ Nocrt *bool `android:"arch_variant"`
+}
+
+// baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties
+type baseLinker struct {
+ Properties BaseLinkerProperties
+ dynamicProperties struct {
+ VariantIsShared bool `blueprint:"mutated"`
+ VariantIsStatic bool `blueprint:"mutated"`
+ VariantIsStaticBinary bool `blueprint:"mutated"`
+ RunPaths []string `blueprint:"mutated"`
+ }
+}
+
+func (linker *baseLinker) appendLdflags(flags []string) {
+ linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...)
+}
+
+func (linker *baseLinker) begin(ctx BaseModuleContext) {
+ if ctx.toolchain().Is64Bit() {
+ linker.dynamicProperties.RunPaths = []string{"../lib64", "lib64"}
+ } else {
+ linker.dynamicProperties.RunPaths = []string{"../lib", "lib"}
+ }
+}
+
+func (linker *baseLinker) props() []interface{} {
+ return []interface{}{&linker.Properties, &linker.dynamicProperties}
+}
+
+func (linker *baseLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
+ deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
+ deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
+
+ deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...)
+ deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
+
+ if !ctx.sdk() && ctx.ModuleName() != "libcompiler_rt-extras" {
+ deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras")
+ }
+
+ if ctx.Device() {
+ // libgcc and libatomic have to be last on the command line
+ deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
+ if !Bool(linker.Properties.No_libgcc) {
+ deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
+ }
+
+ if !linker.static() {
+ if linker.Properties.System_shared_libs != nil {
+ deps.LateSharedLibs = append(deps.LateSharedLibs,
+ linker.Properties.System_shared_libs...)
+ } else if !ctx.sdk() {
+ deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm")
+ }
+ }
+
+ if ctx.sdk() {
+ deps.SharedLibs = append(deps.SharedLibs,
+ "libc",
+ "libm",
+ )
+ }
+ }
+
+ return deps
+}
+
+func (linker *baseLinker) flags(ctx ModuleContext, flags Flags) Flags {
+ toolchain := ctx.toolchain()
+
+ flags.Nocrt = Bool(linker.Properties.Nocrt)
+
+ if !ctx.noDefaultCompilerFlags() {
+ if ctx.Device() && !Bool(linker.Properties.Allow_undefined_symbols) {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
+ }
+
+ if flags.Clang {
+ flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
+ } else {
+ flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags())
+ }
+
+ if ctx.Host() {
+ CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
+
+ flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...)
+ }
+ }
+
+ CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
+
+ flags.LdFlags = append(flags.LdFlags, linker.Properties.Ldflags...)
+
+ if ctx.Host() && !linker.static() {
+ rpath_prefix := `\$$ORIGIN/`
+ if ctx.Darwin() {
+ rpath_prefix = "@loader_path/"
+ }
+
+ for _, rpath := range linker.dynamicProperties.RunPaths {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
+ }
+ }
+
+ if flags.Clang {
+ flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
+ } else {
+ flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags())
+ }
+
+ return flags
+}
+
+func (linker *baseLinker) static() bool {
+ return linker.dynamicProperties.VariantIsStatic
+}
+
+func (linker *baseLinker) staticBinary() bool {
+ return linker.dynamicProperties.VariantIsStaticBinary
+}
+
+func (linker *baseLinker) setStatic(static bool) {
+ linker.dynamicProperties.VariantIsStatic = static
+}
+
+func (linker *baseLinker) isDependencyRoot() bool {
+ return false
+}
+
+type baseLinkerInterface interface {
+ // Returns true if the build options for the module have selected a static or shared build
+ buildStatic() bool
+ buildShared() bool
+
+ // Sets whether a specific variant is static or shared
+ setStatic(bool)
+
+ // Returns whether a specific variant is a static library or binary
+ static() bool
+
+ // Returns whether a module is a static binary
+ staticBinary() bool
+
+ // Returns true for dependency roots (binaries)
+ // TODO(ccross): also handle dlopenable libraries
+ isDependencyRoot() bool
+}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 562186e..50db938 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -35,6 +35,30 @@
}, "arch", "apiLevel")
ndkLibrarySuffix = ".ndk"
+
+ ndkPrebuiltSharedLibs = []string{
+ "android",
+ "c",
+ "dl",
+ "EGL",
+ "GLESv1_CM",
+ "GLESv2",
+ "GLESv3",
+ "jnigraphics",
+ "log",
+ "mediandk",
+ "m",
+ "OpenMAXAL",
+ "OpenSLES",
+ "stdc++",
+ "vulkan",
+ "z",
+ }
+ ndkPrebuiltSharedLibraries = addPrefix(append([]string(nil), ndkPrebuiltSharedLibs...), "lib")
+
+ // These libraries have migrated over to the new ndk_library, which is added
+ // as a variation dependency via depsMutator.
+ ndkMigratedLibs = []string{}
)
// Creates a stub shared library based on the provided version file.
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
new file mode 100644
index 0000000..f66f5b5
--- /dev/null
+++ b/cc/ndk_prebuilt.go
@@ -0,0 +1,224 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/google/blueprint"
+
+ "android/soong"
+ "android/soong/android"
+)
+
+func init() {
+ soong.RegisterModuleType("ndk_prebuilt_library", ndkPrebuiltLibraryFactory)
+ soong.RegisterModuleType("ndk_prebuilt_object", ndkPrebuiltObjectFactory)
+ soong.RegisterModuleType("ndk_prebuilt_static_stl", ndkPrebuiltStaticStlFactory)
+ soong.RegisterModuleType("ndk_prebuilt_shared_stl", ndkPrebuiltSharedStlFactory)
+}
+
+// NDK prebuilt libraries.
+//
+// These differ from regular prebuilts in that they aren't stripped and usually aren't installed
+// either (with the exception of the shared STLs, which are installed to the app's directory rather
+// than to the system image).
+
+func getNdkLibDir(ctx android.ModuleContext, toolchain Toolchain, version string) android.SourcePath {
+ suffix := ""
+ // Most 64-bit NDK prebuilts store libraries in "lib64", except for arm64 which is not a
+ // multilib toolchain and stores the libraries in "lib".
+ if toolchain.Is64Bit() && ctx.Arch().ArchType != android.Arm64 {
+ suffix = "64"
+ }
+ return android.PathForSource(ctx, fmt.Sprintf("prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib%s",
+ version, toolchain.Name(), suffix))
+}
+
+func ndkPrebuiltModuleToPath(ctx android.ModuleContext, toolchain Toolchain,
+ ext string, version string) android.Path {
+
+ // NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION.
+ // We want to translate to just NAME.EXT
+ name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0]
+ dir := getNdkLibDir(ctx, toolchain, version)
+ return dir.Join(ctx, name+ext)
+}
+
+type ndkPrebuiltObjectLinker struct {
+ objectLinker
+}
+
+func (*ndkPrebuiltObjectLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ // NDK objects can't have any dependencies
+ return deps
+}
+
+func ndkPrebuiltObjectFactory() (blueprint.Module, []interface{}) {
+ module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+ module.linker = &ndkPrebuiltObjectLinker{}
+ module.Properties.HideFromMake = true
+ return module.Init()
+}
+
+func (c *ndkPrebuiltObjectLinker) link(ctx ModuleContext, flags Flags,
+ deps PathDeps, objFiles android.Paths) android.Path {
+ // A null build step, but it sets up the output path.
+ if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") {
+ ctx.ModuleErrorf("NDK prebuilts must have an ndk_crt prefixed name")
+ }
+
+ return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, ctx.sdkVersion())
+}
+
+type ndkPrebuiltLibraryLinker struct {
+ libraryLinker
+}
+
+var _ baseLinkerInterface = (*ndkPrebuiltLibraryLinker)(nil)
+var _ exportedFlagsProducer = (*libraryLinker)(nil)
+
+func (ndk *ndkPrebuiltLibraryLinker) props() []interface{} {
+ return append(ndk.libraryLinker.props(), &ndk.Properties, &ndk.flagExporter.Properties)
+}
+
+func (*ndkPrebuiltLibraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ // NDK libraries can't have any dependencies
+ return deps
+}
+
+func ndkPrebuiltLibraryFactory() (blueprint.Module, []interface{}) {
+ module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+ linker := &ndkPrebuiltLibraryLinker{}
+ linker.dynamicProperties.BuildShared = true
+ module.linker = linker
+ module.Properties.HideFromMake = true
+ return module.Init()
+}
+
+func (ndk *ndkPrebuiltLibraryLinker) link(ctx ModuleContext, flags Flags,
+ deps PathDeps, objFiles android.Paths) android.Path {
+ // A null build step, but it sets up the output path.
+ ndk.exportIncludes(ctx, "-isystem")
+
+ return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(),
+ ctx.sdkVersion())
+}
+
+// The NDK STLs are slightly different from the prebuilt system libraries:
+// * Are not specific to each platform version.
+// * The libraries are not in a predictable location for each STL.
+
+type ndkPrebuiltStlLinker struct {
+ ndkPrebuiltLibraryLinker
+}
+
+func ndkPrebuiltSharedStlFactory() (blueprint.Module, []interface{}) {
+ module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+ linker := &ndkPrebuiltStlLinker{}
+ linker.dynamicProperties.BuildShared = true
+ module.linker = linker
+ module.Properties.HideFromMake = true
+ return module.Init()
+}
+
+func ndkPrebuiltStaticStlFactory() (blueprint.Module, []interface{}) {
+ module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+ linker := &ndkPrebuiltStlLinker{}
+ linker.dynamicProperties.BuildStatic = true
+ module.linker = linker
+ module.Properties.HideFromMake = true
+ return module.Init()
+}
+
+func getNdkStlLibDir(ctx android.ModuleContext, toolchain Toolchain, stl string) android.SourcePath {
+ gccVersion := toolchain.GccVersion()
+ var libDir string
+ switch stl {
+ case "libstlport":
+ libDir = "cxx-stl/stlport/libs"
+ case "libc++":
+ libDir = "cxx-stl/llvm-libc++/libs"
+ case "libgnustl":
+ libDir = fmt.Sprintf("cxx-stl/gnu-libstdc++/%s/libs", gccVersion)
+ }
+
+ if libDir != "" {
+ ndkSrcRoot := "prebuilts/ndk/current/sources"
+ return android.PathForSource(ctx, ndkSrcRoot).Join(ctx, libDir, ctx.Arch().Abi[0])
+ }
+
+ ctx.ModuleErrorf("Unknown NDK STL: %s", stl)
+ return android.PathForSource(ctx, "")
+}
+
+func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags,
+ deps PathDeps, objFiles android.Paths) android.Path {
+ // A null build step, but it sets up the output path.
+ if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
+ ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
+ }
+
+ ndk.exportIncludes(ctx, "-I")
+
+ libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
+ libExt := flags.Toolchain.ShlibSuffix()
+ if ndk.dynamicProperties.BuildStatic {
+ libExt = staticLibraryExtension
+ }
+
+ stlName := strings.TrimSuffix(libName, "_shared")
+ stlName = strings.TrimSuffix(stlName, "_static")
+ libDir := getNdkStlLibDir(ctx, flags.Toolchain, stlName)
+ return libDir.Join(ctx, libName+libExt)
+}
+
+func linkageMutator(mctx android.BottomUpMutatorContext) {
+ if m, ok := mctx.Module().(*Module); ok {
+ if m.linker != nil {
+ if linker, ok := m.linker.(baseLinkerInterface); ok {
+ var modules []blueprint.Module
+ if linker.buildStatic() && linker.buildShared() {
+ modules = mctx.CreateLocalVariations("static", "shared")
+ static := modules[0].(*Module)
+ shared := modules[1].(*Module)
+
+ static.linker.(baseLinkerInterface).setStatic(true)
+ shared.linker.(baseLinkerInterface).setStatic(false)
+
+ if staticCompiler, ok := static.compiler.(*libraryCompiler); ok {
+ sharedCompiler := shared.compiler.(*libraryCompiler)
+ if len(staticCompiler.Properties.Static.Cflags) == 0 &&
+ len(sharedCompiler.Properties.Shared.Cflags) == 0 {
+ // Optimize out compiling common .o files twice for static+shared libraries
+ mctx.AddInterVariantDependency(reuseObjTag, shared, static)
+ sharedCompiler.baseCompiler.Properties.Srcs = nil
+ sharedCompiler.baseCompiler.Properties.Generated_sources = nil
+ }
+ }
+ } else if linker.buildStatic() {
+ modules = mctx.CreateLocalVariations("static")
+ modules[0].(*Module).linker.(baseLinkerInterface).setStatic(true)
+ } else if linker.buildShared() {
+ modules = mctx.CreateLocalVariations("shared")
+ modules[0].(*Module).linker.(baseLinkerInterface).setStatic(false)
+ } else {
+ panic(fmt.Errorf("library %q not static or shared", mctx.ModuleName()))
+ }
+ }
+ }
+ }
+}
diff --git a/cc/object.go b/cc/object.go
new file mode 100644
index 0000000..456e1bb
--- /dev/null
+++ b/cc/object.go
@@ -0,0 +1,90 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+ "fmt"
+
+ "github.com/google/blueprint"
+
+ "android/soong"
+ "android/soong/android"
+)
+
+//
+// Objects (for crt*.o)
+//
+
+func init() {
+ soong.RegisterModuleType("cc_object", objectFactory)
+}
+
+type objectLinker struct {
+ Properties ObjectLinkerProperties
+}
+
+func objectFactory() (blueprint.Module, []interface{}) {
+ module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
+ module.compiler = &baseCompiler{}
+ module.linker = &objectLinker{}
+ return module.Init()
+}
+
+func (object *objectLinker) appendLdflags(flags []string) {
+ panic(fmt.Errorf("appendLdflags on object Linker not supported"))
+}
+
+func (object *objectLinker) props() []interface{} {
+ return []interface{}{&object.Properties}
+}
+
+func (*objectLinker) begin(ctx BaseModuleContext) {}
+
+func (object *objectLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...)
+ return deps
+}
+
+func (*objectLinker) flags(ctx ModuleContext, flags Flags) Flags {
+ if flags.Clang {
+ flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainClangLdflags())
+ } else {
+ flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainLdflags())
+ }
+
+ return flags
+}
+
+func (object *objectLinker) link(ctx ModuleContext,
+ flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+ objFiles = append(objFiles, deps.ObjFiles...)
+
+ var outputFile android.Path
+ if len(objFiles) == 1 {
+ outputFile = objFiles[0]
+ } else {
+ output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
+ TransformObjsToObj(ctx, objFiles, flagsToBuilderFlags(flags), output)
+ outputFile = output
+ }
+
+ ctx.CheckbuildFile(outputFile)
+ return outputFile
+}
+
+func (*objectLinker) installable() bool {
+ return false
+}
diff --git a/cc/strip.go b/cc/strip.go
new file mode 100644
index 0000000..bc16bbc
--- /dev/null
+++ b/cc/strip.go
@@ -0,0 +1,44 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import "android/soong/android"
+
+type StripProperties struct {
+ Strip struct {
+ None bool
+ Keep_symbols bool
+ }
+}
+
+type stripper struct {
+ StripProperties StripProperties
+}
+
+func (stripper *stripper) needsStrip(ctx ModuleContext) bool {
+ return !ctx.AConfig().EmbeddedInMake() && !stripper.StripProperties.Strip.None
+}
+
+func (stripper *stripper) strip(ctx ModuleContext, in, out android.ModuleOutPath,
+ flags builderFlags) {
+ if ctx.Darwin() {
+ TransformDarwinStrip(ctx, in, out)
+ } else {
+ flags.stripKeepSymbols = stripper.StripProperties.Strip.Keep_symbols
+ // TODO(ccross): don't add gnu debuglink for user builds
+ flags.stripAddGnuDebuglink = true
+ TransformStrip(ctx, in, out, flags)
+ }
+}
diff --git a/cc/test.go b/cc/test.go
new file mode 100644
index 0000000..9eb4e21
--- /dev/null
+++ b/cc/test.go
@@ -0,0 +1,256 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+ "path/filepath"
+ "strings"
+
+ "github.com/google/blueprint"
+
+ "android/soong"
+ "android/soong/android"
+)
+
+type TestLinkerProperties struct {
+ // if set, build against the gtest library. Defaults to true.
+ Gtest bool
+
+ // Create a separate binary for each source file. Useful when there is
+ // global state that can not be torn down and reset between each test suite.
+ Test_per_src *bool
+}
+
+func init() {
+ soong.RegisterModuleType("cc_test", testFactory)
+ soong.RegisterModuleType("cc_test_library", testLibraryFactory)
+ soong.RegisterModuleType("cc_benchmark", benchmarkFactory)
+ soong.RegisterModuleType("cc_test_host", testHostFactory)
+ soong.RegisterModuleType("cc_benchmark_host", benchmarkHostFactory)
+}
+
+// Module factory for tests
+func testFactory() (blueprint.Module, []interface{}) {
+ module := NewTest(android.HostAndDeviceSupported)
+ return module.Init()
+}
+
+// Module factory for test libraries
+func testLibraryFactory() (blueprint.Module, []interface{}) {
+ module := NewTestLibrary(android.HostAndDeviceSupported)
+ return module.Init()
+}
+
+// Module factory for benchmarks
+func benchmarkFactory() (blueprint.Module, []interface{}) {
+ module := NewBenchmark(android.HostAndDeviceSupported)
+ return module.Init()
+}
+
+// Module factory for host tests
+func testHostFactory() (blueprint.Module, []interface{}) {
+ module := NewTest(android.HostSupported)
+ return module.Init()
+}
+
+// Module factory for host benchmarks
+func benchmarkHostFactory() (blueprint.Module, []interface{}) {
+ module := NewBenchmark(android.HostSupported)
+ return module.Init()
+}
+
+func testPerSrcMutator(mctx android.BottomUpMutatorContext) {
+ if m, ok := mctx.Module().(*Module); ok {
+ if test, ok := m.linker.(*testBinaryLinker); ok {
+ if Bool(test.testLinker.Properties.Test_per_src) {
+ testNames := make([]string, len(m.compiler.(*baseCompiler).Properties.Srcs))
+ for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
+ testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
+ }
+ tests := mctx.CreateLocalVariations(testNames...)
+ for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
+ tests[i].(*Module).compiler.(*baseCompiler).Properties.Srcs = []string{src}
+ tests[i].(*Module).linker.(*testBinaryLinker).binaryLinker.Properties.Stem = testNames[i]
+ }
+ }
+ }
+ }
+}
+
+type testLinker struct {
+ Properties TestLinkerProperties
+}
+
+func (test *testLinker) flags(ctx ModuleContext, flags Flags) Flags {
+ if !test.Properties.Gtest {
+ return flags
+ }
+
+ flags.CFlags = append(flags.CFlags, "-DGTEST_HAS_STD_STRING")
+ if ctx.Host() {
+ flags.CFlags = append(flags.CFlags, "-O0", "-g")
+
+ switch ctx.Os() {
+ case android.Windows:
+ flags.CFlags = append(flags.CFlags, "-DGTEST_OS_WINDOWS")
+ case android.Linux:
+ flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX")
+ flags.LdFlags = append(flags.LdFlags, "-lpthread")
+ case android.Darwin:
+ flags.CFlags = append(flags.CFlags, "-DGTEST_OS_MAC")
+ flags.LdFlags = append(flags.LdFlags, "-lpthread")
+ }
+ } else {
+ flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX_ANDROID")
+ }
+
+ return flags
+}
+
+func (test *testLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ if test.Properties.Gtest {
+ if ctx.sdk() && ctx.Device() {
+ switch ctx.selectedStl() {
+ case "ndk_libc++_shared", "ndk_libc++_static":
+ deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_libcxx", "libgtest_ndk_libcxx")
+ case "ndk_libgnustl_static":
+ deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_gnustl", "libgtest_ndk_gnustl")
+ default:
+ deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk", "libgtest_ndk")
+ }
+ } else {
+ deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
+ }
+ }
+ return deps
+}
+
+type testBinaryLinker struct {
+ testLinker
+ binaryLinker
+}
+
+func (test *testBinaryLinker) begin(ctx BaseModuleContext) {
+ test.binaryLinker.begin(ctx)
+ runpath := "../../lib"
+ if ctx.toolchain().Is64Bit() {
+ runpath += "64"
+ }
+ test.dynamicProperties.RunPaths = append([]string{runpath}, test.dynamicProperties.RunPaths...)
+}
+
+func (test *testBinaryLinker) props() []interface{} {
+ return append(test.binaryLinker.props(), &test.testLinker.Properties)
+}
+
+func (test *testBinaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
+ flags = test.binaryLinker.flags(ctx, flags)
+ flags = test.testLinker.flags(ctx, flags)
+ return flags
+}
+
+func (test *testBinaryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ deps = test.testLinker.deps(ctx, deps)
+ deps = test.binaryLinker.deps(ctx, deps)
+ return deps
+}
+
+type testLibraryLinker struct {
+ testLinker
+ *libraryLinker
+}
+
+func (test *testLibraryLinker) props() []interface{} {
+ return append(test.libraryLinker.props(), &test.testLinker.Properties)
+}
+
+func (test *testLibraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
+ flags = test.libraryLinker.flags(ctx, flags)
+ flags = test.testLinker.flags(ctx, flags)
+ return flags
+}
+
+func (test *testLibraryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ deps = test.testLinker.deps(ctx, deps)
+ deps = test.libraryLinker.deps(ctx, deps)
+ return deps
+}
+
+type testInstaller struct {
+ baseInstaller
+}
+
+func (installer *testInstaller) install(ctx ModuleContext, file android.Path) {
+ installer.dir = filepath.Join(installer.dir, ctx.ModuleName())
+ installer.dir64 = filepath.Join(installer.dir64, ctx.ModuleName())
+ installer.baseInstaller.install(ctx, file)
+}
+
+func NewTest(hod android.HostOrDeviceSupported) *Module {
+ module := newModule(hod, android.MultilibBoth)
+ module.compiler = &baseCompiler{}
+ linker := &testBinaryLinker{}
+ linker.testLinker.Properties.Gtest = true
+ module.linker = linker
+ module.installer = &testInstaller{
+ baseInstaller: baseInstaller{
+ dir: "nativetest",
+ dir64: "nativetest64",
+ data: true,
+ },
+ }
+ return module
+}
+
+func NewTestLibrary(hod android.HostOrDeviceSupported) *Module {
+ module := NewLibrary(android.HostAndDeviceSupported, false, true)
+ linker := &testLibraryLinker{
+ libraryLinker: module.linker.(*libraryLinker),
+ }
+ linker.testLinker.Properties.Gtest = true
+ module.linker = linker
+ module.installer = &testInstaller{
+ baseInstaller: baseInstaller{
+ dir: "nativetest",
+ dir64: "nativetest64",
+ data: true,
+ },
+ }
+ return module
+}
+
+type benchmarkLinker struct {
+ testBinaryLinker
+}
+
+func (benchmark *benchmarkLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+ deps = benchmark.testBinaryLinker.deps(ctx, deps)
+ deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
+ return deps
+}
+
+func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
+ module := newModule(hod, android.MultilibFirst)
+ module.compiler = &baseCompiler{}
+ module.linker = &benchmarkLinker{}
+ module.installer = &testInstaller{
+ baseInstaller: baseInstaller{
+ dir: "nativetest",
+ dir64: "nativetest64",
+ data: true,
+ },
+ }
+ return module
+}
diff --git a/cc/toolchain.go b/cc/toolchain.go
index 0cb7c9c..2e2ee5a 100644
--- a/cc/toolchain.go
+++ b/cc/toolchain.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "strings"
"android/soong/android"
)
@@ -140,13 +139,3 @@
func (toolchain32Bit) Is64Bit() bool {
return false
}
-
-func bionicHeaders(bionicArch, kernelArch string) string {
- return strings.Join([]string{
- "-isystem bionic/libc/arch-" + bionicArch + "/include",
- "-isystem bionic/libc/include",
- "-isystem bionic/libc/kernel/uapi",
- "-isystem bionic/libc/kernel/uapi/asm-" + kernelArch,
- "-isystem bionic/libc/kernel/android/uapi",
- }, " ")
-}