diff --git a/Android.bp b/Android.bp index 273f87e8c..d77d3185a 100644 --- a/Android.bp +++ b/Android.bp @@ -128,12 +128,24 @@ bootstrap_go_package { "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 000000000..d6b086c05 --- /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 12d9ed713..53345c53d 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -20,7 +20,6 @@ package cc import ( "fmt" - "path/filepath" "strings" "github.com/google/blueprint" @@ -32,27 +31,9 @@ import ( ) 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 @@ func init() { 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 @@ type Flags struct { 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 @@ type BaseProperties struct { 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 @@ func (c *Module) InstallInData() bool { 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 @@ func (*toolchainLibraryLinker) installable() bool { 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 000000000..8fcab8fa2 --- /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 000000000..ec0f57295 --- /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 000000000..7dc2b78d0 --- /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 000000000..d92a26796 --- /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 000000000..c6f13f229 --- /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 562186eaf..50db938e0 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -35,6 +35,30 @@ var ( }, "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 000000000..f66f5b5b0 --- /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 000000000..456e1bbcd --- /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 000000000..bc16bbc31 --- /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 000000000..9eb4e210e --- /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 0cb7c9cce..2e2ee5a43 100644 --- a/cc/toolchain.go +++ b/cc/toolchain.go @@ -16,7 +16,6 @@ package cc import ( "fmt" - "strings" "android/soong/android" ) @@ -140,13 +139,3 @@ type toolchain32Bit struct { 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", - }, " ") -}