Merge "Have bpfix not remove empty lists"
diff --git a/Android.bp b/Android.bp
index ae31a60..32b89d1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -211,6 +211,7 @@
"java/java.go",
"java/proto.go",
"java/resources.go",
+ "java/system_modules.go",
],
testSrcs: [
"java/java_test.go",
@@ -228,6 +229,7 @@
srcs: [
"java/config/config.go",
"java/config/error_prone.go",
+ "java/config/kotlin.go",
"java/config/makevars.go",
],
}
diff --git a/android/androidmk.go b/android/androidmk.go
index 5ce486d..759d328 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -43,6 +43,7 @@
OutputFile OptionalPath
Disabled bool
Include string
+ Required []string
Custom func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData)
@@ -168,6 +169,8 @@
data.Include = "$(BUILD_PREBUILT)"
}
+ data.Required = amod.commonProperties.Required
+
// Make does not understand LinuxBionic
if amod.Os() == LinuxBionic {
return nil
@@ -197,8 +200,8 @@
fmt.Fprintln(&data.preamble, "LOCAL_MODULE_CLASS :=", data.Class)
fmt.Fprintln(&data.preamble, "LOCAL_PREBUILT_MODULE_FILE :=", data.OutputFile.String())
- if len(amod.commonProperties.Required) > 0 {
- fmt.Fprintln(&data.preamble, "LOCAL_REQUIRED_MODULES := "+strings.Join(amod.commonProperties.Required, " "))
+ if len(data.Required) > 0 {
+ fmt.Fprintln(&data.preamble, "LOCAL_REQUIRED_MODULES := "+strings.Join(data.Required, " "))
}
archStr := amod.Arch().ArchType.String()
diff --git a/android/arch.go b/android/arch.go
index db017fd..eaa35a4 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -468,7 +468,7 @@
"Android64",
"Android32",
"Bionic",
- // TODO(dwillemsen): "Linux",
+ "Linux",
"Not_windows",
"Arm_on_x86",
"Arm_on_x86_64",
@@ -479,7 +479,7 @@
for _, archType := range osArchTypeMap[os] {
targets = append(targets, os.Field+"_"+archType.Name)
- if false { // TODO(dwillemsen): os.Linux()
+ if os.Linux() {
target := "Linux_" + archType.Name
if !inList(target, targets) {
targets = append(targets, target)
@@ -696,7 +696,7 @@
// key: value,
// },
// }
- if false { // TODO(dwillemsen): os.Linux()
+ if os.Linux() {
field = "Linux"
prefix = "target.linux"
a.appendProperties(ctx, genProps, targetProp, field, prefix)
diff --git a/android/config.go b/android/config.go
index a70fa76..dca998f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -78,6 +78,7 @@
srcDir string // the path of the root source directory
buildDir string // the path of the build output directory
+ env map[string]string
envLock sync.Mutex
envDeps map[string]string
envFrozen bool
@@ -87,6 +88,9 @@
captureBuild bool // true for tests, saves build parameters for each module
ignoreEnvironment bool // true for tests, returns empty from all Getenv calls
+ useOpenJDK9 bool // Use OpenJDK9, but possibly target 1.8
+ targetOpenJDK9 bool // Use OpenJDK9 and target 1.9
+
OncePer
}
@@ -168,32 +172,36 @@
}
// TestConfig returns a Config object suitable for using for tests
-func TestConfig(buildDir string) Config {
+func TestConfig(buildDir string, env map[string]string) Config {
config := &config{
ProductVariables: productVariables{
DeviceName: stringPtr("test_device"),
},
- buildDir: buildDir,
- captureBuild: true,
- ignoreEnvironment: true,
+ buildDir: buildDir,
+ captureBuild: true,
+ env: env,
}
config.deviceConfig = &deviceConfig{
config: config,
}
+ if err := config.fromEnv(); err != nil {
+ panic(err)
+ }
+
return Config{config}
}
// TestConfig returns a Config object suitable for using for tests that need to run the arch mutator
-func TestArchConfig(buildDir string) Config {
- testConfig := TestConfig(buildDir)
+func TestArchConfig(buildDir string, env map[string]string) Config {
+ testConfig := TestConfig(buildDir, env)
config := testConfig.config
config.Targets = map[OsClass][]Target{
Device: []Target{
- {Android, Arch{ArchType: Arm64, Native: true}},
- {Android, Arch{ArchType: Arm, Native: true}},
+ {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true}},
+ {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true}},
},
Host: []Target{
{BuildOs, Arch{ArchType: X86_64}},
@@ -212,6 +220,8 @@
ConfigFileName: filepath.Join(buildDir, configFileName),
ProductVariablesFileName: filepath.Join(buildDir, productVariablesFileName),
+ env: originalEnv,
+
srcDir: srcDir,
buildDir: buildDir,
}
@@ -270,9 +280,31 @@
config.Targets = targets
config.BuildOsVariant = targets[Host][0].String()
+ if err := config.fromEnv(); err != nil {
+ return Config{}, err
+ }
+
return Config{config}, nil
}
+func (c *config) fromEnv() error {
+ switch c.Getenv("EXPERIMENTAL_USE_OPENJDK9") {
+ case "":
+ // Use OpenJDK8
+ case "1.8":
+ // Use OpenJDK9, but target 1.8
+ c.useOpenJDK9 = true
+ case "true":
+ // Use OpenJDK9 and target 1.9
+ c.useOpenJDK9 = true
+ c.targetOpenJDK9 = true
+ default:
+ return fmt.Errorf(`Invalid value for EXPERIMENTAL_USE_OPENJDK9, should be "", "1.8", or "true"`)
+ }
+
+ return nil
+}
+
func (c *config) RemoveAbandonedFiles() bool {
return false
}
@@ -335,9 +367,7 @@
if c.envFrozen {
panic("Cannot access new environment variables after envdeps are frozen")
}
- if !c.ignoreEnvironment {
- val, _ = originalEnv[key]
- }
+ val, _ = c.env[key]
c.envDeps[key] = val
}
return val
@@ -517,6 +547,16 @@
return Bool(c.ProductVariables.UseGoma)
}
+// Returns true if OpenJDK9 prebuilts are being used
+func (c *config) UseOpenJDK9() bool {
+ return c.useOpenJDK9
+}
+
+// Returns true if -source 1.9 -target 1.9 is being passed to javac
+func (c *config) TargetOpenJDK9() bool {
+ return c.targetOpenJDK9
+}
+
func (c *config) ClangTidy() bool {
return Bool(c.ProductVariables.ClangTidy)
}
diff --git a/android/module.go b/android/module.go
index 2890b60..9afc8a7 100644
--- a/android/module.go
+++ b/android/module.go
@@ -61,7 +61,7 @@
Windows() bool
Debug() bool
PrimaryArch() bool
- Vendor() bool
+ InstallOnVendorPartition() bool
AConfig() Config
DeviceConfig() DeviceConfig
}
@@ -99,7 +99,11 @@
type Module interface {
blueprint.Module
+ // GenerateAndroidBuildActions is analogous to Blueprints' GenerateBuildActions,
+ // but GenerateAndroidBuildActions also has access to Android-specific information.
+ // For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
GenerateAndroidBuildActions(ModuleContext)
+
DepsMutator(BottomUpMutatorContext)
base() *ModuleBase
@@ -690,7 +694,7 @@
return DeviceConfig{a.config.deviceConfig}
}
-func (a *androidBaseContextImpl) Vendor() bool {
+func (a *androidBaseContextImpl) InstallOnVendorPartition() bool {
return a.vendor
}
@@ -882,10 +886,10 @@
}
} else if pathtools.IsGlob(s) {
globbedSrcFiles := ctx.Glob(filepath.Join(prefix, s), excludes)
- expandedSrcFiles = append(expandedSrcFiles, globbedSrcFiles...)
- for i, s := range expandedSrcFiles {
- expandedSrcFiles[i] = s.(ModuleSrcPath).WithSubDir(ctx, subDir)
+ for i, s := range globbedSrcFiles {
+ globbedSrcFiles[i] = s.(ModuleSrcPath).WithSubDir(ctx, subDir)
}
+ expandedSrcFiles = append(expandedSrcFiles, globbedSrcFiles...)
} else {
s := PathForModuleSrc(ctx, s).WithSubDir(ctx, subDir)
expandedSrcFiles = append(expandedSrcFiles, s)
diff --git a/android/mutator.go b/android/mutator.go
index 04407eb..66a1bad 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -18,12 +18,13 @@
"github.com/google/blueprint"
)
-// Mutator phases:
-// Pre-arch
-// Arch
-// Pre-deps
-// Deps
-// PostDeps
+// Phases:
+// run Pre-arch mutators
+// run archMutator
+// run Pre-deps mutators
+// run depsMutator
+// run PostDeps mutators
+// continue on to GenerateAndroidBuildActions
func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) {
for _, t := range mutators {
diff --git a/android/paths.go b/android/paths.go
index 69a7b0d..f88d650 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -303,6 +303,39 @@
return list[:k]
}
+// HasExt returns true of any of the paths have extension ext, otherwise false
+func (p Paths) HasExt(ext string) bool {
+ for _, path := range p {
+ if path.Ext() == ext {
+ return true
+ }
+ }
+
+ return false
+}
+
+// FilterByExt returns the subset of the paths that have extension ext
+func (p Paths) FilterByExt(ext string) Paths {
+ ret := make(Paths, 0, len(p))
+ for _, path := range p {
+ if path.Ext() == ext {
+ ret = append(ret, path)
+ }
+ }
+ return ret
+}
+
+// FilterOutByExt returns the subset of the paths that do not have extension ext
+func (p Paths) FilterOutByExt(ext string) Paths {
+ ret := make(Paths, 0, len(p))
+ for _, path := range p {
+ if path.Ext() != ext {
+ ret = append(ret, path)
+ }
+ }
+ return ret
+}
+
// WritablePaths is a slice of WritablePaths, used for multiple outputs.
type WritablePaths []WritablePath
@@ -706,7 +739,7 @@
var partition string
if ctx.InstallInData() {
partition = "data"
- } else if ctx.Vendor() {
+ } else if ctx.InstallOnVendorPartition() {
partition = ctx.DeviceConfig().VendorPath()
} else {
partition = "system"
diff --git a/android/paths_test.go b/android/paths_test.go
index 3986b71..248f4d4 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -209,7 +209,7 @@
}
func TestPathForModuleInstall(t *testing.T) {
- testConfig := TestConfig("")
+ testConfig := TestConfig("", nil)
hostTarget := Target{Os: Linux}
deviceTarget := Target{Os: Android}
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 9a1de9c..93f5805 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -118,7 +118,7 @@
}
defer os.RemoveAll(buildDir)
- config := TestConfig(buildDir)
+ config := TestConfig(buildDir, nil)
for _, test := range prebuiltsTests {
t.Run(test.name, func(t *testing.T) {
diff --git a/android/variable.go b/android/variable.go
index 9dd9d25..16a6b11 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -92,8 +92,8 @@
}
Pdk struct {
- Enabled *bool
- }
+ Enabled *bool `android:"arch_variant"`
+ } `android:"arch_variant"`
Uml struct {
Cppflags []string
diff --git a/androidmk/cmd/androidmk/androidmk.go b/androidmk/cmd/androidmk/androidmk.go
index 5fad586..a49f620 100644
--- a/androidmk/cmd/androidmk/androidmk.go
+++ b/androidmk/cmd/androidmk/androidmk.go
@@ -2,6 +2,7 @@
import (
"bytes"
+ "flag"
"fmt"
"io/ioutil"
"os"
@@ -15,6 +16,13 @@
bpparser "github.com/google/blueprint/parser"
)
+var usage = func() {
+ fmt.Fprintf(os.Stderr, "usage: androidmk [flags] <inputFile>\n"+
+ "\nandroidmk parses <inputFile> as an Android.mk file and attempts to output an analogous Android.bp file (to standard out)\n")
+ flag.PrintDefaults()
+ os.Exit(1)
+}
+
// TODO: non-expanded variables with expressions
type bpFile struct {
@@ -85,7 +93,13 @@
}
func main() {
- b, err := ioutil.ReadFile(os.Args[1])
+ flag.Usage = usage
+ flag.Parse()
+ if len(flag.Args()) != 1 {
+ usage()
+ }
+ filePathToRead := flag.Arg(0)
+ b, err := ioutil.ReadFile(filePathToRead)
if err != nil {
fmt.Println(err.Error())
return
diff --git a/build_test.bash b/build_test.bash
index 065d7f6..4c43224 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -28,11 +28,14 @@
export TRACE_BEGIN_SOONG=$(date +%s%N)
export TOP=$(cd $(dirname ${BASH_SOURCE[0]})/../..; PWD= /bin/pwd)
+cd "${TOP}"
source "${TOP}/build/soong/scripts/microfactory.bash"
case $(uname) in
Linux)
export LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
+ export SEGFAULT_USE_ALTSTACK=1
+ ulimit -a
;;
esac
diff --git a/cc/androidmk.go b/cc/androidmk.go
index eb63065..194faab 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -30,7 +30,7 @@
type AndroidMkContext interface {
Target() android.Target
subAndroidMk(*android.AndroidMkData, interface{})
- vndk() bool
+ useVndk() bool
}
type subAndroidMkProvider interface {
@@ -64,14 +64,14 @@
if len(c.Properties.AndroidMkSharedLibs) > 0 {
fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES := "+strings.Join(c.Properties.AndroidMkSharedLibs, " "))
}
- if c.Target().Os == android.Android && c.Properties.Sdk_version != "" && !c.vndk() {
+ if c.Target().Os == android.Android && c.Properties.Sdk_version != "" && !c.useVndk() {
fmt.Fprintln(w, "LOCAL_SDK_VERSION := "+c.Properties.Sdk_version)
fmt.Fprintln(w, "LOCAL_NDK_STL_VARIANT := none")
} else {
// These are already included in LOCAL_SHARED_LIBRARIES
fmt.Fprintln(w, "LOCAL_CXX_STL := none")
}
- if c.vndk() {
+ if c.useVndk() {
fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
}
},
@@ -89,7 +89,7 @@
}
c.subAndroidMk(&ret, c.installer)
- if c.vndk() && Bool(c.VendorProperties.Vendor_available) {
+ if c.useVndk() && c.hasVendorVariant() {
// .vendor suffix is added only when we will have two variants: core and vendor.
// The suffix is not added for vendor-only module.
ret.SubName += vendorSuffix
@@ -161,7 +161,7 @@
}
fmt.Fprintln(w, "LOCAL_MODULE_HOST_OS :=", makeOs)
fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
- } else if ctx.vndk() {
+ } else if ctx.useVndk() {
fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
}
diff --git a/cc/binary.go b/cc/binary.go
index b2405b6..30e017f 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -108,7 +108,7 @@
deps = binary.baseLinker.linkerDeps(ctx, deps)
if ctx.toolchain().Bionic() {
if !Bool(binary.baseLinker.Properties.Nocrt) {
- if !ctx.sdk() {
+ if !ctx.useSdk() {
if binary.static() {
deps.CrtBegin = "crtbegin_static"
} else {
diff --git a/cc/builder.go b/cc/builder.go
index b5bdc3d..742f7fb 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -219,7 +219,7 @@
arFlags string
asFlags string
cFlags string
- toolingCFlags string // Seperate set of Cflags for clang LibTooling tools
+ toolingCFlags string // A separate set of Cflags for clang LibTooling tools
conlyFlags string
cppFlags string
ldFlags string
@@ -584,7 +584,7 @@
}
// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
-// and shared libraires, to a shared library (.so) or dynamic executable
+// and shared libraries, to a shared library (.so) or dynamic executable
func TransformObjToDynamicBinary(ctx android.ModuleContext,
objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath) {
@@ -714,8 +714,8 @@
return android.OptionalPathForPath(outputFile)
}
-// Generate a rule for extract a table of contents from a shared library (.so)
-func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.WritablePath,
+// Generate a rule for extracting a table of contents from a shared library (.so)
+func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path,
outputFile android.WritablePath, flags builderFlags) {
crossCompile := gccCmd(flags.toolchain, "")
diff --git a/cc/cc.go b/cc/cc.go
index 4f10a11..2fafaa2 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -34,9 +34,9 @@
android.RegisterModuleType("cc_defaults", defaultsFactory)
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("image", vendorMutator).Parallel()
ctx.BottomUp("link", linkageMutator).Parallel()
ctx.BottomUp("vndk", vndkMutator).Parallel()
- ctx.BottomUp("image", vendorMutator).Parallel()
ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
ctx.BottomUp("begin", beginMutator).Parallel()
@@ -168,16 +168,21 @@
}
type VendorProperties struct {
- // whether this module should be allowed to install onto /vendor as
- // well as /system. The two variants will be built separately, one
- // like normal, and the other limited to the set of libraries and
- // headers that are exposed to /vendor modules.
+ // whether this module should be allowed to be directly depended by other
+ // modules with `vendor: true`, `proprietary: true`, or `vendor_available:true`.
+ // If set to true, two variants will be built separately, one like
+ // normal, and the other limited to the set of libraries and headers
+ // that are exposed to /vendor modules.
//
// The vendor variant may be used with a different (newer) /system,
// so it shouldn't have any unversioned runtime dependencies, or
// make assumptions about the system that may not be true in the
// future.
//
+ // If set to false, this module becomes inaccessible from /vendor modules.
+ //
+ // Default value is true when vndk: {enabled: true} or vendor: true.
+ //
// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
Vendor_available *bool
}
@@ -192,9 +197,9 @@
clang() bool
toolchain() config.Toolchain
noDefaultCompilerFlags() bool
- sdk() bool
+ useSdk() bool
sdkVersion() string
- vndk() bool
+ useVndk() bool
isVndk() bool
isVndkSp() bool
createVndkSourceAbiDump() bool
@@ -377,7 +382,7 @@
return false
}
-func (c *Module) vndk() bool {
+func (c *Module) useVndk() bool {
return c.Properties.UseVndk
}
@@ -388,6 +393,12 @@
return false
}
+// Returns true only when this module is configured to have core and vendor
+// variants.
+func (c *Module) hasVendorVariant() bool {
+ return c.isVndk() || Bool(c.VendorProperties.Vendor_available)
+}
+
type baseModuleContext struct {
android.BaseContext
moduleContextImpl
@@ -403,10 +414,8 @@
moduleContextImpl
}
-// Vendor returns true for vendor modules excluding VNDK libraries so that
-// they get installed onto the correct partition
-func (ctx *moduleContext) Vendor() bool {
- return ctx.ModuleContext.Vendor() || (ctx.mod.vndk() && !ctx.mod.isVndk())
+func (ctx *moduleContext) InstallOnVendorPartition() bool {
+ return ctx.ModuleContext.InstallOnVendorPartition() || (ctx.mod.useVndk() && !ctx.mod.isVndk())
}
type moduleContextImpl struct {
@@ -444,8 +453,8 @@
return Bool(ctx.mod.Properties.No_default_compiler_flags)
}
-func (ctx *moduleContextImpl) sdk() bool {
- if ctx.ctx.Device() && !ctx.vndk() {
+func (ctx *moduleContextImpl) useSdk() bool {
+ if ctx.ctx.Device() && !ctx.useVndk() {
return ctx.mod.Properties.Sdk_version != ""
}
return false
@@ -453,7 +462,7 @@
func (ctx *moduleContextImpl) sdkVersion() string {
if ctx.ctx.Device() {
- if ctx.vndk() {
+ if ctx.useVndk() {
return "current"
} else {
return ctx.mod.Properties.Sdk_version
@@ -462,13 +471,12 @@
return ""
}
-func (ctx *moduleContextImpl) vndk() bool {
- return ctx.mod.vndk()
-}
-
func (ctx *moduleContextImpl) isVndk() bool {
return ctx.mod.isVndk()
}
+func (ctx *moduleContextImpl) useVndk() bool {
+ return ctx.mod.useVndk()
+}
func (ctx *moduleContextImpl) isVndkSp() bool {
if vndk := ctx.mod.vndkdep; vndk != nil {
@@ -479,7 +487,7 @@
// Create source abi dumps if the module belongs to the list of VndkLibraries.
func (ctx *moduleContextImpl) createVndkSourceAbiDump() bool {
- return ctx.ctx.Device() && ((ctx.vndk() && ctx.isVndk()) || inList(ctx.baseModuleName(), llndkLibraries))
+ return ctx.ctx.Device() && ((ctx.useVndk() && ctx.isVndk()) || inList(ctx.baseModuleName(), llndkLibraries))
}
func (ctx *moduleContextImpl) selectedStl() string {
@@ -533,6 +541,7 @@
}
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
+
ctx := &moduleContext{
ModuleContext: actx,
moduleContextImpl: moduleContextImpl{
@@ -658,7 +667,7 @@
for _, feature := range c.features {
feature.begin(ctx)
}
- if ctx.sdk() {
+ if ctx.useSdk() {
version, err := normalizeNdkApiLevel(ctx, ctx.sdkVersion(), ctx.Arch())
if err != nil {
ctx.PropertyErrorf("sdk_version", err.Error())
@@ -770,27 +779,31 @@
if ctx.Os() == android.Android {
version := ctx.sdkVersion()
- // Rewrites the names of shared libraries into the names of the NDK
- // libraries where appropriate. This returns two slices.
+ // rewriteNdkLibs takes a list of names of shared libraries and scans it for three types
+ // of names:
//
- // The first is a list of non-variant shared libraries (either rewritten
- // NDK libraries to the modules in prebuilts/ndk, or not rewritten
- // because they are not NDK libraries).
+ // 1. Name of an NDK library that refers to a prebuilt module.
+ // For each of these, it adds the name of the prebuilt module (which will be in
+ // prebuilts/ndk) to the list of nonvariant libs.
+ // 2. Name of an NDK library that refers to an ndk_library module.
+ // For each of these, it adds the name of the ndk_library module to the list of
+ // variant libs.
+ // 3. Anything else (so anything that isn't an NDK library).
+ // It adds these to the nonvariantLibs list.
//
- // The second is a list of ndk_library modules. These need to be
- // separated because they are a variation dependency and must be added
- // in a different manner.
- rewriteNdkLibs := func(list []string) ([]string, []string) {
- variantLibs := []string{}
- nonvariantLibs := []string{}
+ // The caller can then know to add the variantLibs dependencies differently from the
+ // nonvariantLibs
+ rewriteNdkLibs := func(list []string) (nonvariantLibs []string, variantLibs []string) {
+ variantLibs = []string{}
+ nonvariantLibs = []string{}
for _, entry := range list {
- if ctx.sdk() && inList(entry, ndkPrebuiltSharedLibraries) {
+ if ctx.useSdk() && inList(entry, ndkPrebuiltSharedLibraries) {
if !inList(entry, ndkMigratedLibs) {
nonvariantLibs = append(nonvariantLibs, entry+".ndk."+version)
} else {
variantLibs = append(variantLibs, entry+ndkLibrarySuffix)
}
- } else if ctx.vndk() && inList(entry, llndkLibraries) {
+ } else if ctx.useVndk() && inList(entry, llndkLibraries) {
nonvariantLibs = append(nonvariantLibs, entry+llndkLibrarySuffix)
} else {
nonvariantLibs = append(nonvariantLibs, entry)
@@ -892,117 +905,118 @@
return clang
}
+// Whether a module can link to another module, taking into
+// account NDK linking.
+func checkLinkType(ctx android.ModuleContext, from *Module, to *Module) {
+ if from.Target().Os != android.Android {
+ // Host code is not restricted
+ return
+ }
+ if from.Properties.UseVndk {
+ // Though vendor code is limited by the vendor mutator,
+ // each vendor-available module needs to check
+ // link-type for VNDK.
+ if from.vndkdep != nil {
+ from.vndkdep.vndkCheckLinkType(ctx, to)
+ }
+ return
+ }
+ if from.Properties.Sdk_version == "" {
+ // Platform code can link to anything
+ return
+ }
+ if _, ok := to.linker.(*toolchainLibraryDecorator); ok {
+ // These are always allowed
+ return
+ }
+ if _, ok := to.linker.(*ndkPrebuiltLibraryLinker); ok {
+ // These are allowed, but they don't set sdk_version
+ return
+ }
+ if _, ok := to.linker.(*ndkPrebuiltStlLinker); ok {
+ // These are allowed, but they don't set sdk_version
+ return
+ }
+ if _, ok := to.linker.(*stubDecorator); ok {
+ // These aren't real libraries, but are the stub shared libraries that are included in
+ // the NDK.
+ return
+ }
+ if to.Properties.Sdk_version == "" {
+ // NDK code linking to platform code is never okay.
+ ctx.ModuleErrorf("depends on non-NDK-built library %q",
+ ctx.OtherModuleName(to))
+ }
+
+ // At this point we know we have two NDK libraries, but we need to
+ // check that we're not linking against anything built against a higher
+ // API level, as it is only valid to link against older or equivalent
+ // APIs.
+
+ if from.Properties.Sdk_version == "current" {
+ // Current can link against anything.
+ return
+ } else if to.Properties.Sdk_version == "current" {
+ // Current can't be linked against by anything else.
+ ctx.ModuleErrorf("links %q built against newer API version %q",
+ ctx.OtherModuleName(to), "current")
+ }
+
+ fromApi, err := strconv.Atoi(from.Properties.Sdk_version)
+ if err != nil {
+ ctx.PropertyErrorf("sdk_version",
+ "Invalid sdk_version value (must be int): %q",
+ from.Properties.Sdk_version)
+ }
+ toApi, err := strconv.Atoi(to.Properties.Sdk_version)
+ if err != nil {
+ ctx.PropertyErrorf("sdk_version",
+ "Invalid sdk_version value (must be int): %q",
+ to.Properties.Sdk_version)
+ }
+
+ if toApi > fromApi {
+ ctx.ModuleErrorf("links %q built against newer API version %q",
+ ctx.OtherModuleName(to), to.Properties.Sdk_version)
+ }
+}
+
// Convert dependencies to paths. Returns a PathDeps containing paths
func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
var depPaths PathDeps
- // Whether a module can link to another module, taking into
- // account NDK linking.
- checkLinkType := func(from, to *Module) {
- if from.Target().Os != android.Android {
- // Host code is not restricted
- return
- }
- if from.Properties.UseVndk {
- // Though vendor code is limited by the vendor mutator,
- // each vendor-available module needs to check
- // link-type for VNDK.
- if from.vndkdep != nil {
- from.vndkdep.vndkCheckLinkType(ctx, to)
- }
- return
- }
- if from.Properties.Sdk_version == "" {
- // Platform code can link to anything
- return
- }
- if _, ok := to.linker.(*toolchainLibraryDecorator); ok {
- // These are always allowed
- return
- }
- if _, ok := to.linker.(*ndkPrebuiltLibraryLinker); ok {
- // These are allowed, but don't set sdk_version
- return
- }
- if _, ok := to.linker.(*ndkPrebuiltStlLinker); ok {
- // These are allowed, but don't set sdk_version
- return
- }
- if _, ok := to.linker.(*stubDecorator); ok {
- // These aren't real libraries, but are the stub shared libraries that are included in
- // the NDK.
- return
- }
- if to.Properties.Sdk_version == "" {
- // NDK code linking to platform code is never okay.
- ctx.ModuleErrorf("depends on non-NDK-built library %q",
- ctx.OtherModuleName(to))
- }
+ ctx.VisitDirectDeps(func(dep blueprint.Module) {
+ depName := ctx.OtherModuleName(dep)
+ depTag := ctx.OtherModuleDependencyTag(dep)
- // All this point we know we have two NDK libraries, but we need to
- // check that we're not linking against anything built against a higher
- // API level, as it is only valid to link against older or equivalent
- // APIs.
-
- if from.Properties.Sdk_version == "current" {
- // Current can link against anything.
- return
- } else if to.Properties.Sdk_version == "current" {
- // Current can't be linked against by anything else.
- ctx.ModuleErrorf("links %q built against newer API version %q",
- ctx.OtherModuleName(to), "current")
- }
-
- fromApi, err := strconv.Atoi(from.Properties.Sdk_version)
- if err != nil {
- ctx.PropertyErrorf("sdk_version",
- "Invalid sdk_version value (must be int): %q",
- from.Properties.Sdk_version)
- }
- toApi, err := strconv.Atoi(to.Properties.Sdk_version)
- if err != nil {
- ctx.PropertyErrorf("sdk_version",
- "Invalid sdk_version value (must be int): %q",
- to.Properties.Sdk_version)
- }
-
- if toApi > fromApi {
- ctx.ModuleErrorf("links %q built against newer API version %q",
- ctx.OtherModuleName(to), to.Properties.Sdk_version)
- }
- }
-
- ctx.VisitDirectDeps(func(m blueprint.Module) {
- name := ctx.OtherModuleName(m)
- tag := ctx.OtherModuleDependencyTag(m)
-
- a, _ := m.(android.Module)
- if a == nil {
- ctx.ModuleErrorf("module %q not an android module", name)
+ aDep, _ := dep.(android.Module)
+ if aDep == nil {
+ ctx.ModuleErrorf("module %q not an android module", depName)
return
}
- cc, _ := m.(*Module)
- if cc == nil {
- switch tag {
+ ccDep, _ := dep.(*Module)
+ if ccDep == nil {
+ // handling for a few module types that aren't cc Module but that are also supported
+ switch depTag {
case android.DefaultsDepTag, android.SourceDepTag:
// Nothing to do
case genSourceDepTag:
- if genRule, ok := m.(genrule.SourceFileGenerator); ok {
+ if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
depPaths.GeneratedSources = append(depPaths.GeneratedSources,
genRule.GeneratedSourceFiles()...)
} else {
- ctx.ModuleErrorf("module %q is not a gensrcs or genrule", name)
+ ctx.ModuleErrorf("module %q is not a gensrcs or genrule", depName)
}
// Support exported headers from a generated_sources dependency
fallthrough
case genHeaderDepTag, genHeaderExportDepTag:
- if genRule, ok := m.(genrule.SourceFileGenerator); ok {
+ if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders,
genRule.GeneratedSourceFiles()...)
flags := includeDirsToFlags(genRule.GeneratedHeaderDirs())
depPaths.Flags = append(depPaths.Flags, flags)
- if tag == genHeaderExportDepTag {
+ if depTag == genHeaderExportDepTag {
depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, flags)
depPaths.ReexportedFlagsDeps = append(depPaths.ReexportedFlagsDeps,
genRule.GeneratedSourceFiles()...)
@@ -1011,46 +1025,46 @@
}
} else {
- ctx.ModuleErrorf("module %q is not a genrule", name)
+ ctx.ModuleErrorf("module %q is not a genrule", depName)
}
case linkerScriptDepTag:
- if genRule, ok := m.(genrule.SourceFileGenerator); ok {
+ if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
files := genRule.GeneratedSourceFiles()
if len(files) == 1 {
depPaths.LinkerScript = android.OptionalPathForPath(files[0])
} else if len(files) > 1 {
- ctx.ModuleErrorf("module %q can only generate a single file if used for a linker script", name)
+ ctx.ModuleErrorf("module %q can only generate a single file if used for a linker script", depName)
}
} else {
- ctx.ModuleErrorf("module %q is not a genrule", name)
+ ctx.ModuleErrorf("module %q is not a genrule", depName)
}
default:
- ctx.ModuleErrorf("depends on non-cc module %q", name)
+ ctx.ModuleErrorf("depends on non-cc module %q", depName)
}
return
}
- if !a.Enabled() {
+ // some validation
+ if !aDep.Enabled() {
if ctx.AConfig().AllowMissingDependencies() {
- ctx.AddMissingDependencies([]string{name})
+ ctx.AddMissingDependencies([]string{depName})
} else {
- ctx.ModuleErrorf("depends on disabled module %q", name)
+ ctx.ModuleErrorf("depends on disabled module %q", depName)
}
return
}
-
- if a.Target().Os != ctx.Os() {
- ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), name)
+ if aDep.Target().Os != ctx.Os() {
+ ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
+ return
+ }
+ if aDep.Target().Arch.ArchType != ctx.Arch().ArchType {
+ ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
return
}
- if a.Target().Arch.ArchType != ctx.Arch().ArchType {
- ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), name)
- return
- }
-
- if tag == reuseObjTag {
- if l, ok := cc.compiler.(libraryInterface); ok {
+ // re-exporting flags
+ if depTag == reuseObjTag {
+ if l, ok := ccDep.compiler.(libraryInterface); ok {
objs, flags, deps := l.reuseObjs()
depPaths.Objs = depPaths.Objs.Append(objs)
depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, flags...)
@@ -1058,9 +1072,8 @@
return
}
}
-
- if t, ok := tag.(dependencyTag); ok && t.library {
- if i, ok := cc.linker.(exportedFlagsProducer); ok {
+ if t, ok := depTag.(dependencyTag); ok && t.library {
+ if i, ok := ccDep.linker.(exportedFlagsProducer); ok {
flags := i.exportedFlags()
deps := i.exportedFlagsDeps()
depPaths.Flags = append(depPaths.Flags, flags...)
@@ -1076,38 +1089,38 @@
}
}
- checkLinkType(c, cc)
+ checkLinkType(ctx, c, ccDep)
}
var ptr *android.Paths
var depPtr *android.Paths
- linkFile := cc.outputFile
+ linkFile := ccDep.outputFile
depFile := android.OptionalPath{}
- switch tag {
+ switch depTag {
case ndkStubDepTag, sharedDepTag, sharedExportDepTag:
ptr = &depPaths.SharedLibs
depPtr = &depPaths.SharedLibsDeps
- depFile = cc.linker.(libraryInterface).toc()
+ depFile = ccDep.linker.(libraryInterface).toc()
case lateSharedDepTag, ndkLateStubDepTag:
ptr = &depPaths.LateSharedLibs
depPtr = &depPaths.LateSharedLibsDeps
- depFile = cc.linker.(libraryInterface).toc()
+ depFile = ccDep.linker.(libraryInterface).toc()
case staticDepTag, staticExportDepTag:
ptr = &depPaths.StaticLibs
case lateStaticDepTag:
ptr = &depPaths.LateStaticLibs
case wholeStaticDepTag:
ptr = &depPaths.WholeStaticLibs
- staticLib, ok := cc.linker.(libraryInterface)
+ staticLib, ok := ccDep.linker.(libraryInterface)
if !ok || !staticLib.static() {
- ctx.ModuleErrorf("module %q not a static library", name)
+ ctx.ModuleErrorf("module %q not a static library", depName)
return
}
if missingDeps := staticLib.getWholeStaticMissingDeps(); missingDeps != nil {
- postfix := " (required by " + ctx.OtherModuleName(m) + ")"
+ postfix := " (required by " + ctx.OtherModuleName(dep) + ")"
for i := range missingDeps {
missingDeps[i] += postfix
}
@@ -1124,11 +1137,11 @@
depPaths.CrtEnd = linkFile
}
- switch tag {
+ switch depTag {
case staticDepTag, staticExportDepTag, lateStaticDepTag:
- staticLib, ok := cc.linker.(libraryInterface)
+ staticLib, ok := ccDep.linker.(libraryInterface)
if !ok || !staticLib.static() {
- ctx.ModuleErrorf("module %q not a static library", name)
+ ctx.ModuleErrorf("module %q not a static library", depName)
return
}
@@ -1139,11 +1152,12 @@
staticLib.objs().coverageFiles...)
depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles,
staticLib.objs().sAbiDumpFiles...)
+
}
if ptr != nil {
if !linkFile.Valid() {
- ctx.ModuleErrorf("module %q missing output file", name)
+ ctx.ModuleErrorf("module %q missing output file", depName)
return
}
*ptr = append(*ptr, linkFile.Path())
@@ -1157,24 +1171,24 @@
*depPtr = append(*depPtr, dep.Path())
}
- // Export the shared libs to the make world. In doing so, .vendor suffix
- // is added if the lib has both core and vendor variants and this module
- // is building against vndk. This is because the vendor variant will be
- // have .vendor suffix in its name in the make world. However, if the
- // lib is a vendor-only lib or this lib is not building against vndk,
- // then the suffix is not added.
- switch tag {
+ // Export the shared libs to Make.
+ switch depTag {
case sharedDepTag, sharedExportDepTag, lateSharedDepTag:
- libName := strings.TrimSuffix(name, llndkLibrarySuffix)
+ libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
libName = strings.TrimPrefix(libName, "prebuilt_")
isLLndk := inList(libName, llndkLibraries)
- if c.vndk() && (Bool(cc.VendorProperties.Vendor_available) || isLLndk) {
- libName += vendorSuffix
+ var makeLibName string
+ bothVendorAndCoreVariantsExist := ccDep.hasVendorVariant() || isLLndk
+ if c.useVndk() && bothVendorAndCoreVariantsExist {
+ // The vendor module in Make will have been renamed to not conflict with the core
+ // module, so update the dependency name here accordingly.
+ makeLibName = libName + vendorSuffix
+ } else {
+ makeLibName = libName
}
// Note: the order of libs in this list is not important because
- // they merely serve as dependencies in the make world and do not
- // affect this lib itself.
- c.Properties.AndroidMkSharedLibs = append(c.Properties.AndroidMkSharedLibs, libName)
+ // they merely serve as Make dependencies and do not affect this lib itself.
+ c.Properties.AndroidMkSharedLibs = append(c.Properties.AndroidMkSharedLibs, makeLibName)
}
})
@@ -1286,6 +1300,16 @@
vendorMode = "vendor"
)
+func squashVendorSrcs(m *Module) {
+ if lib, ok := m.compiler.(*libraryDecorator); ok {
+ lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
+ lib.baseCompiler.Properties.Target.Vendor.Srcs...)
+
+ lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
+ lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...)
+ }
+}
+
func vendorMutator(mctx android.BottomUpMutatorContext) {
if mctx.Os() != android.Android {
return
@@ -1297,7 +1321,7 @@
mctx.CreateVariations(coreMode)
} else if Bool(props.Vendor_available) {
mctx.CreateVariations(coreMode, vendorMode)
- } else if mctx.Vendor() {
+ } else if mctx.InstallOnVendorPartition() {
mctx.CreateVariations(vendorMode)
} else {
mctx.CreateVariations(coreMode)
@@ -1311,15 +1335,15 @@
}
// Sanity check
- if Bool(m.VendorProperties.Vendor_available) && mctx.Vendor() {
+ if m.VendorProperties.Vendor_available != nil && mctx.InstallOnVendorPartition() {
mctx.PropertyErrorf("vendor_available",
"doesn't make sense at the same time as `vendor: true` or `proprietary: true`")
return
}
if vndk := m.vndkdep; vndk != nil {
- if vndk.isVndk() && !Bool(m.VendorProperties.Vendor_available) {
+ if vndk.isVndk() && m.VendorProperties.Vendor_available == nil {
mctx.PropertyErrorf("vndk",
- "has to define `vendor_available: true` to enable vndk")
+ "vendor_available must be set to either true or false when `vndk: {enabled: true}`")
return
}
if !vndk.isVndk() && vndk.isVndkSp() {
@@ -1337,15 +1361,19 @@
// LL-NDK stubs only exist in the vendor variant, since the
// real libraries will be used in the core variant.
mctx.CreateVariations(vendorMode)
- } else if Bool(m.VendorProperties.Vendor_available) {
+ } else if m.hasVendorVariant() {
// This will be available in both /system and /vendor
// or a /system directory that is available to vendor.
mod := mctx.CreateVariations(coreMode, vendorMode)
- mod[1].(*Module).Properties.UseVndk = true
- } else if mctx.Vendor() && m.Properties.Sdk_version == "" {
+ vendor := mod[1].(*Module)
+ vendor.Properties.UseVndk = true
+ squashVendorSrcs(vendor)
+ } else if mctx.InstallOnVendorPartition() && m.Properties.Sdk_version == "" {
// This will be available in /vendor only
mod := mctx.CreateVariations(vendorMode)
- mod[0].(*Module).Properties.UseVndk = true
+ vendor := mod[0].(*Module)
+ vendor.Properties.UseVndk = true
+ squashVendorSrcs(vendor)
} else {
// This is either in /system (or similar: /data), or is a
// modules built with the NDK. Modules built with the NDK
@@ -1371,8 +1399,8 @@
return list[:k]
}
-// 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
+// lastUniqueElements returns all unique elements of a slice, keeping the last copy of each.
+// It modifies the slice contents in place, and returns a subslice of the original slice
func lastUniqueElements(list []string) []string {
totalSkip := 0
for i := len(list) - 1; i >= totalSkip; i-- {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 92120a5..94e3e66 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2,10 +2,136 @@
import (
"android/soong/android"
+ "io/ioutil"
+ "os"
"reflect"
"testing"
+
+ "github.com/google/blueprint/proptools"
)
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "soong_cc_test")
+ if err != nil {
+ panic(err)
+ }
+}
+
+func tearDown() {
+ os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+ run := func() int {
+ setUp()
+ defer tearDown()
+
+ return m.Run()
+ }
+
+ os.Exit(run())
+}
+
+func testCc(t *testing.T, bp string) *android.TestContext {
+ config := android.TestArchConfig(buildDir, nil)
+ config.ProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
+
+ ctx := android.NewTestArchContext()
+ ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(libraryFactory))
+ ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(toolchainLibraryFactory))
+ ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(llndkLibraryFactory))
+ ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("image", vendorMutator).Parallel()
+ ctx.BottomUp("link", linkageMutator).Parallel()
+ ctx.BottomUp("vndk", vndkMutator).Parallel()
+ })
+ ctx.Register()
+
+ ctx.MockFileSystem(map[string][]byte{
+ "Android.bp": []byte(bp),
+ "foo.c": nil,
+ "bar.c": nil,
+ })
+
+ _, errs := ctx.ParseBlueprintsFiles("Android.bp")
+ fail(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ fail(t, errs)
+
+ return ctx
+}
+
+func TestVendorSrc(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library {
+ name: "libTest",
+ srcs: ["foo.c"],
+ no_libgcc : true,
+ nocrt : true,
+ system_shared_libs : [],
+ vendor_available: true,
+ target: {
+ vendor: {
+ srcs: ["bar.c"],
+ },
+ },
+ }
+ toolchain_library {
+ name: "libatomic",
+ vendor_available: true,
+ }
+ toolchain_library {
+ name: "libcompiler_rt-extras",
+ vendor_available: true,
+ }
+ cc_library {
+ name: "libc",
+ no_libgcc : true,
+ nocrt : true,
+ system_shared_libs: [],
+ }
+ llndk_library {
+ name: "libc",
+ symbol_file: "",
+ }
+ cc_library {
+ name: "libm",
+ no_libgcc : true,
+ nocrt : true,
+ system_shared_libs: [],
+ }
+ llndk_library {
+ name: "libm",
+ symbol_file: "",
+ }
+ cc_library {
+ name: "libdl",
+ no_libgcc : true,
+ nocrt : true,
+ system_shared_libs: [],
+ }
+ llndk_library {
+ name: "libdl",
+ symbol_file: "",
+ }
+ `)
+
+ ld := ctx.ModuleForTests("libTest", "android_arm_armv7-a-neon_vendor_shared").Rule("ld")
+ var objs []string
+ for _, o := range ld.Inputs {
+ objs = append(objs, o.Base())
+ }
+ if len(objs) != 2 {
+ t.Errorf("inputs of libTest is expected to 2, but was %d.", len(objs))
+ }
+ if objs[0] != "foo.o" || objs[1] != "bar.o" {
+ t.Errorf("inputs of libTest must be []string{\"foo.o\", \"bar.o\"}, but was %#v.", objs)
+ }
+}
+
var firstUniqueElementsTestCases = []struct {
in []string
out []string
diff --git a/cc/compiler.go b/cc/compiler.go
index a65ddf8..102bc7a 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -236,7 +236,7 @@
flags.GlobalFlags = append(flags.GlobalFlags, "-I"+android.PathForModuleSrc(ctx).String())
flags.YasmFlags = append(flags.YasmFlags, "-I"+android.PathForModuleSrc(ctx).String())
- if !(ctx.sdk() || ctx.vndk()) || ctx.Host() {
+ if !(ctx.useSdk() || ctx.useVndk()) || ctx.Host() {
flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
"${config.CommonGlobalIncludes}",
tc.IncludeFlags(),
@@ -244,7 +244,7 @@
}
}
- if ctx.sdk() {
+ if ctx.useSdk() {
// 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
@@ -272,7 +272,7 @@
flags.SystemIncludeFlags = append(flags.SystemIncludeFlags, "-isystem "+legacyIncludes)
}
- if ctx.vndk() {
+ if ctx.useVndk() {
flags.GlobalFlags = append(flags.GlobalFlags,
"-D__ANDROID_API__=__ANDROID_API_FUTURE__", "-D__ANDROID_VNDK__")
}
@@ -366,7 +366,7 @@
flags.GlobalFlags = append(flags.GlobalFlags, tc.ToolchainCflags())
}
- if !ctx.sdk() {
+ if !ctx.useSdk() {
cStd := config.CStdVersion
if compiler.Properties.C_std == "experimental" {
cStd = config.ExperimentalCStdVersion
@@ -405,7 +405,7 @@
flags.CppFlags = append([]string{"-std=" + cppStd}, flags.CppFlags...)
}
- if ctx.vndk() {
+ if ctx.useVndk() {
flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Target.Vendor.Cflags)...)
}
@@ -478,7 +478,7 @@
var gnuToCReplacer = strings.NewReplacer("gnu", "c")
func ndkPathDeps(ctx ModuleContext) android.Paths {
- if ctx.sdk() {
+ if ctx.useSdk() {
// The NDK sysroot timestamp file depends on all the NDK sysroot files
// (headers and libraries).
return android.Paths{getNdkSysrootTimestampFile(ctx)}
@@ -490,14 +490,6 @@
pathDeps := deps.GeneratedHeaders
pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
- if ctx.vndk() {
- compiler.Properties.Srcs = append(compiler.Properties.Srcs,
- compiler.Properties.Target.Vendor.Srcs...)
-
- compiler.Properties.Exclude_srcs = append(compiler.Properties.Exclude_srcs,
- compiler.Properties.Target.Vendor.Exclude_srcs...)
- }
-
srcs := ctx.ExpandSources(compiler.Properties.Srcs, compiler.Properties.Exclude_srcs)
srcs = append(srcs, deps.GeneratedSources...)
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 0d22ed4..390936a 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -117,7 +117,7 @@
pctx.StaticVariable("Arm64Cflags", strings.Join(arm64Cflags, " "))
pctx.StaticVariable("Arm64Ldflags", strings.Join(arm64Ldflags, " "))
pctx.StaticVariable("Arm64Cppflags", strings.Join(arm64Cppflags, " "))
- pctx.StaticVariable("Arm64IncludeFlags", bionicHeaders("arm64", "arm64"))
+ pctx.StaticVariable("Arm64IncludeFlags", bionicHeaders("arm64"))
pctx.StaticVariable("Arm64ClangCflags", strings.Join(ClangFilterUnknownCflags(arm64Cflags), " "))
pctx.StaticVariable("Arm64ClangLdflags", strings.Join(ClangFilterUnknownCflags(arm64Ldflags), " "))
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index f093563..7110ccb 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -216,7 +216,7 @@
pctx.StaticVariable("ArmCflags", strings.Join(armCflags, " "))
pctx.StaticVariable("ArmLdflags", strings.Join(armLdflags, " "))
pctx.StaticVariable("ArmCppflags", strings.Join(armCppflags, " "))
- pctx.StaticVariable("ArmIncludeFlags", bionicHeaders("arm", "arm"))
+ pctx.StaticVariable("ArmIncludeFlags", bionicHeaders("arm"))
// Extended cflags
diff --git a/cc/config/global.go b/cc/config/global.go
index 82a44e6..e9f5473 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -180,9 +180,8 @@
var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
-func bionicHeaders(bionicArch, kernelArch string) string {
+func bionicHeaders(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,
diff --git a/cc/config/mips64_device.go b/cc/config/mips64_device.go
index 3a49e7b..e05dbf1 100644
--- a/cc/config/mips64_device.go
+++ b/cc/config/mips64_device.go
@@ -28,8 +28,6 @@
"-fomit-frame-pointer",
"-fno-strict-aliasing",
"-funswitch-loops",
- "-U__unix",
- "-U__unix__",
"-Umips",
"-ffunction-sections",
"-fdata-sections",
@@ -108,7 +106,7 @@
pctx.StaticVariable("Mips64Cflags", strings.Join(mips64Cflags, " "))
pctx.StaticVariable("Mips64Ldflags", strings.Join(mips64Ldflags, " "))
pctx.StaticVariable("Mips64Cppflags", strings.Join(mips64Cppflags, " "))
- pctx.StaticVariable("Mips64IncludeFlags", bionicHeaders("mips64", "mips"))
+ pctx.StaticVariable("Mips64IncludeFlags", bionicHeaders("mips"))
// Clang cflags
pctx.StaticVariable("Mips64ClangCflags", strings.Join(ClangFilterUnknownCflags(mips64ClangCflags), " "))
diff --git a/cc/config/mips_device.go b/cc/config/mips_device.go
index c135029..78e95b6 100644
--- a/cc/config/mips_device.go
+++ b/cc/config/mips_device.go
@@ -28,8 +28,6 @@
"-fomit-frame-pointer",
"-fno-strict-aliasing",
"-funswitch-loops",
- "-U__unix",
- "-U__unix__",
"-Umips",
"-ffunction-sections",
"-fdata-sections",
@@ -147,7 +145,7 @@
pctx.StaticVariable("MipsCflags", strings.Join(mipsCflags, " "))
pctx.StaticVariable("MipsLdflags", strings.Join(mipsLdflags, " "))
pctx.StaticVariable("MipsCppflags", strings.Join(mipsCppflags, " "))
- pctx.StaticVariable("MipsIncludeFlags", bionicHeaders("mips", "mips"))
+ pctx.StaticVariable("MipsIncludeFlags", bionicHeaders("mips"))
// Clang cflags
pctx.StaticVariable("MipsClangCflags", strings.Join(ClangFilterUnknownCflags(mipsClangCflags), " "))
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 2a6fe2a..a98001e 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -159,7 +159,7 @@
pctx.StaticVariable("X86_64Cflags", strings.Join(x86_64Cflags, " "))
pctx.StaticVariable("X86_64Ldflags", strings.Join(x86_64Ldflags, " "))
pctx.StaticVariable("X86_64Cppflags", strings.Join(x86_64Cppflags, " "))
- pctx.StaticVariable("X86_64IncludeFlags", bionicHeaders("x86_64", "x86"))
+ pctx.StaticVariable("X86_64IncludeFlags", bionicHeaders("x86"))
// Clang cflags
pctx.StaticVariable("X86_64ClangCflags", strings.Join(ClangFilterUnknownCflags(x86_64Cflags), " "))
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 3f079a4..6d361b5 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -159,6 +159,8 @@
strings.Join(ClangFilterUnknownCflags(darwinX8664Cflags), " "))
pctx.StaticVariable("DarwinX86ClangLdflags", strings.Join(darwinX86ClangLdflags, " "))
pctx.StaticVariable("DarwinX8664ClangLdflags", strings.Join(darwinX8664ClangLdflags, " "))
+ pctx.StaticVariable("DarwinX86YasmFlags", "-f macho -m x86")
+ pctx.StaticVariable("DarwinX8664YasmFlags", "-f macho -m amd64")
}
func xcrun(config android.Config, args ...string) (string, error) {
@@ -276,6 +278,14 @@
return "${config.DarwinClangLdflags} ${config.DarwinX8664ClangLdflags}"
}
+func (t *toolchainDarwinX86) YasmFlags() string {
+ return "${config.DarwinX86YasmFlags}"
+}
+
+func (t *toolchainDarwinX8664) YasmFlags() string {
+ return "${config.DarwinX8664YasmFlags}"
+}
+
func (t *toolchainDarwin) ShlibSuffix() string {
return ".dylib"
}
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 23518b6..53d2265 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -181,7 +181,7 @@
pctx.StaticVariable("X86Cflags", strings.Join(x86Cflags, " "))
pctx.StaticVariable("X86Ldflags", strings.Join(x86Ldflags, " "))
pctx.StaticVariable("X86Cppflags", strings.Join(x86Cppflags, " "))
- pctx.StaticVariable("X86IncludeFlags", bionicHeaders("x86", "x86"))
+ pctx.StaticVariable("X86IncludeFlags", bionicHeaders("x86"))
// Clang cflags
pctx.StaticVariable("X86ClangCflags", strings.Join(ClangFilterUnknownCflags(x86ClangCflags), " "))
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 093876d..277361b 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -78,7 +78,7 @@
pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " "))
pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " "))
- pctx.StaticVariable("LinuxBionicIncludeFlags", bionicHeaders("x86_64", "x86"))
+ pctx.StaticVariable("LinuxBionicIncludeFlags", bionicHeaders("x86"))
// Use the device gcc toolchain for now
pctx.StaticVariable("LinuxBionicGccRoot", "${X86_64GccRoot}")
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 75416bd..88bd514 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -159,6 +159,9 @@
pctx.StaticVariable("LinuxX8664ClangLdflags", strings.Join(linuxX8664ClangLdflags, " "))
pctx.StaticVariable("LinuxX86ClangCppflags", strings.Join(linuxX86ClangCppflags, " "))
pctx.StaticVariable("LinuxX8664ClangCppflags", strings.Join(linuxX8664ClangCppflags, " "))
+ // Yasm flags
+ pctx.StaticVariable("LinuxX86YasmFlags", "-f elf32 -m x86")
+ pctx.StaticVariable("LinuxX8664YasmFlags", "-f elf64 -m amd64")
}
type toolchainLinux struct {
@@ -251,6 +254,14 @@
return "${config.LinuxClangLdflags} ${config.LinuxX8664ClangLdflags}"
}
+func (t *toolchainLinuxX86) YasmFlags() string {
+ return "${config.LinuxX86YasmFlags}"
+}
+
+func (t *toolchainLinuxX8664) YasmFlags() string {
+ return "${config.LinuxX8664YasmFlags}"
+}
+
func (t *toolchainLinux) AvailableLibraries() []string {
return linuxAvailableLibraries
}
diff --git a/cc/installer.go b/cc/installer.go
index 027d191..92076e5 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -69,7 +69,7 @@
if !ctx.Host() && !ctx.Arch().Native {
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
- if installer.location == InstallInData && ctx.vndk() {
+ if installer.location == InstallInData && ctx.useVndk() {
dir = filepath.Join(dir, "vendor")
}
return android.PathForModuleInstall(ctx, dir, installer.subDir, installer.Properties.Relative_install_path, installer.relative)
diff --git a/cc/library.go b/cc/library.go
index f1681db..e963ecb 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -82,7 +82,8 @@
type FlagExporterProperties struct {
// list of directories relative to the Blueprints file that will
// be added to the include path (using -I) for this module and any module that links
- // against this module
+ // against this module. Directories listed in export_include_dirs do not need to be
+ // listed in local_include_dirs.
Export_include_dirs []string `android:"arch_variant"`
Target struct {
@@ -155,7 +156,7 @@
}
func (f *flagExporter) exportedIncludes(ctx ModuleContext) android.Paths {
- if ctx.vndk() && f.Properties.Target.Vendor.Export_include_dirs != nil {
+ if ctx.useVndk() && f.Properties.Target.Vendor.Export_include_dirs != nil {
return android.PathsForModuleSrc(ctx, f.Properties.Target.Vendor.Export_include_dirs)
} else {
return android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
@@ -434,7 +435,7 @@
deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
} else if library.shared() {
if ctx.toolchain().Bionic() && !Bool(library.baseLinker.Properties.Nocrt) {
- if !ctx.sdk() {
+ if !ctx.useSdk() {
deps.CrtBegin = "crtbegin_so"
deps.CrtEnd = "crtend_so"
} else {
@@ -697,7 +698,7 @@
func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
if library.shared() {
if ctx.Device() {
- if ctx.vndk() {
+ if ctx.useVndk() {
if ctx.isVndkSp() {
library.baseInstaller.subDir = "vndk-sp"
} else if ctx.isVndk() {
diff --git a/cc/linker.go b/cc/linker.go
index 02d3ba5..6ec5630 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -132,7 +132,7 @@
deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
deps.ReexportGeneratedHeaders = append(deps.ReexportGeneratedHeaders, linker.Properties.Export_generated_headers...)
- if ctx.vndk() {
+ if ctx.useVndk() {
deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs)
deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs)
}
@@ -174,7 +174,7 @@
}
deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
- } else if ctx.sdk() || ctx.vndk() {
+ } else if ctx.useSdk() || ctx.useVndk() {
deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl")
}
}
@@ -242,7 +242,7 @@
}
}
- if ctx.sdk() && (ctx.Arch().ArchType != android.Mips && ctx.Arch().ArchType != android.Mips64) {
+ if ctx.useSdk() && (ctx.Arch().ArchType != android.Mips && ctx.Arch().ArchType != android.Mips64) {
// The bionic linker now has support gnu style hashes (which are much faster!), but shipping
// to older devices requires the old style hash. Fortunately, we can build with both and
// it'll work anywhere.
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index c3d3462..30c4d4c 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -50,6 +50,11 @@
// Whether the system library uses symbol versions.
Unversioned bool
+
+ // whether this module can be directly depended upon by libs that are installed to /vendor.
+ // When set to false, this module can only be depended on by VNDK libraries, not vendor
+ // libraries. This effectively hides this module from vendors. Default value is true.
+ Vendor_available bool
}
type llndkStubDecorator struct {
@@ -149,6 +154,7 @@
stub := &llndkStubDecorator{
libraryDecorator: library,
}
+ stub.Properties.Vendor_available = true
module.compiler = stub
module.linker = stub
module.installer = nil
diff --git a/cc/makevars.go b/cc/makevars.go
index 2c6af70..295b4ac 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -62,6 +62,7 @@
ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(vndkCoreLibraries, " "))
ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(vndkSpLibraries, " "))
ctx.Strict("LLNDK_LIBRARIES", strings.Join(llndkLibraries, " "))
+ ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(vndkPrivateLibraries, " "))
ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(asanCflags, " "))
ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", strings.Join(asanLdflags, " "))
diff --git a/cc/object.go b/cc/object.go
index 59d523d..402b105 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -43,7 +43,7 @@
}
func (object *objectLinker) appendLdflags(flags []string) {
- panic(fmt.Errorf("appendLdflags on object Linker not supported"))
+ panic(fmt.Errorf("appendLdflags on objectLinker not supported"))
}
func (object *objectLinker) linkerProps() []interface{} {
diff --git a/cc/pgo.go b/cc/pgo.go
index a99cbad..ea23124 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -37,10 +37,11 @@
type PgoProperties struct {
Pgo struct {
- Instrumentation *bool
- Sampling *bool
- Profile_file *string `android:"arch_variant"`
- Benchmarks []string
+ Instrumentation *bool
+ Sampling *bool
+ Profile_file *string `android:"arch_variant"`
+ Benchmarks []string
+ Enable_profile_use *bool `android:"arch_variant"`
} `android:"arch_variant"`
PgoPresent bool `blueprint:"mutated"`
@@ -63,37 +64,60 @@
return []interface{}{&pgo.Properties}
}
-func (pgo *pgo) addProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
- if pgo.Properties.isInstrumentation() {
+func (props *PgoProperties) addProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
+ if props.isInstrumentation() {
flags.CFlags = append(flags.CFlags, profileInstrumentFlag)
// The profile runtime is added below in deps(). Add the below
// flag, which is the only other link-time action performed by
// the Clang driver during link.
flags.LdFlags = append(flags.LdFlags, "-u__llvm_profile_runtime")
}
- if pgo.Properties.isSampling() {
+ if props.isSampling() {
flags.CFlags = append(flags.CFlags, profileSamplingFlag)
flags.LdFlags = append(flags.LdFlags, profileSamplingFlag)
}
return flags
}
-func (pgo *pgo) profileUseFlag(ctx ModuleContext, file string) string {
- if pgo.Properties.isInstrumentation() {
+func (props *PgoProperties) profileUseFlag(ctx ModuleContext, file string) string {
+ if props.isInstrumentation() {
return fmt.Sprintf(profileUseInstrumentFormat, file)
}
- if pgo.Properties.isSampling() {
+ if props.isSampling() {
return fmt.Sprintf(profileUseSamplingFormat, file)
}
return ""
}
-func (pgo *pgo) profileUseFlags(ctx ModuleContext, file string) []string {
- flags := []string{pgo.profileUseFlag(ctx, file)}
+func (props *PgoProperties) profileUseFlags(ctx ModuleContext, file string) []string {
+ flags := []string{props.profileUseFlag(ctx, file)}
flags = append(flags, profileUseOtherFlags...)
return flags
}
+func (props *PgoProperties) addProfileUseFlags(ctx ModuleContext, flags Flags) Flags {
+ // Skip -fprofile-use if 'enable_profile_use' property is set
+ if props.Pgo.Enable_profile_use != nil && *props.Pgo.Enable_profile_use == false {
+ return flags
+ }
+
+ // If the PGO profiles project is found, and this module has PGO
+ // enabled, add flags to use the profile
+ if profilesDir := getPgoProfilesDir(ctx); props.PgoPresent && profilesDir.Valid() {
+ profileFile := android.PathForSource(ctx, profilesDir.String(), *props.Pgo.Profile_file)
+ profileUseFlags := props.profileUseFlags(ctx, profileFile.String())
+
+ flags.CFlags = append(flags.CFlags, profileUseFlags...)
+ flags.LdFlags = append(flags.LdFlags, profileUseFlags...)
+
+ // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
+ // if profileFile gets updated
+ flags.CFlagsDeps = append(flags.CFlagsDeps, profileFile)
+ flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFile)
+ }
+ return flags
+}
+
func (props *PgoProperties) isPGO(ctx BaseModuleContext) bool {
isInstrumentation := props.isInstrumentation()
isSampling := props.isSampling()
@@ -188,22 +212,11 @@
// Add flags to profile this module based on its profile_kind
if props.ShouldProfileModule {
- return pgo.addProfileGatherFlags(ctx, flags)
+ return props.addProfileGatherFlags(ctx, flags)
}
- // If the PGO profiles project is found, and this module has PGO
- // enabled, add flags to use the profile
- if profilesDir := getPgoProfilesDir(ctx); props.PgoPresent && profilesDir.Valid() {
- profileFile := android.PathForSource(ctx, profilesDir.String(), *(props.Pgo.Profile_file))
- profileUseFlags := pgo.profileUseFlags(ctx, profileFile.String())
-
- flags.CFlags = append(flags.CFlags, profileUseFlags...)
- flags.LdFlags = append(flags.LdFlags, profileUseFlags...)
-
- // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
- // if profileFile gets updated
- flags.CFlagsDeps = append(flags.CFlagsDeps, profileFile)
- flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFile)
+ if !ctx.AConfig().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") {
+ return props.addProfileUseFlags(ctx, flags)
}
return flags
diff --git a/cc/proto.go b/cc/proto.go
index a01951f..6e3cce7 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -60,14 +60,14 @@
switch proptools.String(p.Proto.Type) {
case "full":
- if ctx.sdk() {
+ if ctx.useSdk() {
lib = "libprotobuf-cpp-full-ndk"
static = true
} else {
lib = "libprotobuf-cpp-full"
}
case "lite", "":
- if ctx.sdk() {
+ if ctx.useSdk() {
lib = "libprotobuf-cpp-lite-ndk"
static = true
} else {
diff --git a/cc/relocation_packer.go b/cc/relocation_packer.go
index c9f82ba..d9b367c 100644
--- a/cc/relocation_packer.go
+++ b/cc/relocation_packer.go
@@ -56,7 +56,7 @@
if ctx.AConfig().Getenv("DISABLE_RELOCATION_PACKER") == "true" {
enabled = false
}
- if ctx.sdk() {
+ if ctx.useSdk() {
enabled = false
}
if p.Properties.Pack_relocations != nil &&
diff --git a/cc/rs.go b/cc/rs.go
index 976107e..e7eb3bb 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -82,7 +82,7 @@
func rsFlags(ctx ModuleContext, flags Flags, properties *BaseCompilerProperties) Flags {
targetApi := proptools.String(properties.Renderscript.Target_api)
- if targetApi == "" && ctx.sdk() {
+ if targetApi == "" && ctx.useSdk() {
switch ctx.sdkVersion() {
case "current", "system_current", "test_current":
// Nothing
diff --git a/cc/sabi.go b/cc/sabi.go
index e45b040..8086f5b 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -79,7 +79,7 @@
func sabiDepsMutator(mctx android.TopDownMutatorContext) {
if c, ok := mctx.Module().(*Module); ok &&
- ((c.isVndk() && c.vndk()) || inList(c.Name(), llndkLibraries) ||
+ ((c.isVndk() && c.useVndk()) || inList(c.Name(), llndkLibraries) ||
(c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) {
mctx.VisitDirectDeps(func(m blueprint.Module) {
tag := mctx.OtherModuleDependencyTag(m)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 090d490..b8b5ffa 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -128,7 +128,7 @@
s := &sanitize.Properties.Sanitize
// Don't apply sanitizers to NDK code.
- if ctx.sdk() {
+ if ctx.useSdk() {
s.Never = true
}
@@ -421,7 +421,7 @@
// When linking against VNDK, use the vendor variant of the runtime lib
sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary
- if ctx.vndk() {
+ if ctx.useVndk() {
sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + vendorSuffix
}
}
diff --git a/cc/stl.go b/cc/stl.go
index 17cde59..347db99 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -42,7 +42,7 @@
if stl.Properties.Stl != nil {
s = *stl.Properties.Stl
}
- if ctx.sdk() && ctx.Device() {
+ if ctx.useSdk() && ctx.Device() {
switch s {
case "":
return "ndk_system"
diff --git a/cc/test.go b/cc/test.go
index 12cc2ad..fa75f48 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -157,7 +157,7 @@
func (test *testDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
if test.gtest() {
- if ctx.sdk() && ctx.Device() {
+ if ctx.useSdk() && ctx.Device() {
switch ctx.selectedStl() {
case "ndk_libc++_shared", "ndk_libc++_static":
deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_libcxx", "libgtest_ndk_libcxx")
diff --git a/cc/test_data_test.go b/cc/test_data_test.go
index 962bde5..434edcd 100644
--- a/cc/test_data_test.go
+++ b/cc/test_data_test.go
@@ -117,7 +117,7 @@
}
defer os.RemoveAll(buildDir)
- config := android.TestConfig(buildDir)
+ config := android.TestConfig(buildDir, nil)
for _, test := range testDataTests {
t.Run(test.name, func(t *testing.T) {
diff --git a/cc/vndk.go b/cc/vndk.go
index 395069b..860678d 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -27,8 +27,8 @@
// declared as a VNDK or VNDK-SP module. The vendor variant
// will be installed in /system instead of /vendor partition.
//
- // `vendor_available: true` must set to together for VNDK
- // modules.
+ // `vendor_vailable` must be explicitly set to either true or
+ // false together with `vndk: {enabled: true}`.
Enabled *bool
// declared as a VNDK-SP module, which is a subset of VNDK.
@@ -81,6 +81,24 @@
if to.linker == nil {
return
}
+ if !vndk.isVndk() {
+ // Non-VNDK modules (those installed to /vendor) can't depend on modules marked with
+ // vendor_available: false.
+ violation := false
+ if lib, ok := to.linker.(*llndkStubDecorator); ok && !lib.Properties.Vendor_available {
+ violation = true
+ } else {
+ if _, ok := to.linker.(libraryInterface); ok && to.VendorProperties.Vendor_available != nil && !Bool(to.VendorProperties.Vendor_available) {
+ // Vendor_available == nil && !Bool(Vendor_available) should be okay since
+ // it means a vendor-only library which is a valid dependency for non-VNDK
+ // modules.
+ violation = true
+ }
+ }
+ if violation {
+ ctx.ModuleErrorf("Vendor module that is not VNDK should not link to %q which is marked as `vendor_available: false`", to.Name())
+ }
+ }
if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
// Check only shared libraries.
// Other (static and LL-NDK) libraries are allowed to link.
@@ -102,16 +120,17 @@
}
var (
- vndkCoreLibraries []string
- vndkSpLibraries []string
- llndkLibraries []string
- vndkLibrariesLock sync.Mutex
+ vndkCoreLibraries []string
+ vndkSpLibraries []string
+ llndkLibraries []string
+ vndkPrivateLibraries []string
+ vndkLibrariesLock sync.Mutex
)
// gather list of vndk-core, vndk-sp, and ll-ndk libs
func vndkMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*Module); ok {
- if _, ok := m.linker.(*llndkStubDecorator); ok {
+ if lib, ok := m.linker.(*llndkStubDecorator); ok {
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
@@ -119,22 +138,40 @@
llndkLibraries = append(llndkLibraries, name)
sort.Strings(llndkLibraries)
}
- } else if lib, ok := m.linker.(*libraryDecorator); ok && lib.shared() {
- if m.vndkdep.isVndk() {
- vndkLibrariesLock.Lock()
- defer vndkLibrariesLock.Unlock()
- if m.vndkdep.isVndkSp() {
- if !inList(m.Name(), vndkSpLibraries) {
- vndkSpLibraries = append(vndkSpLibraries, m.Name())
- sort.Strings(vndkSpLibraries)
+ if !lib.Properties.Vendor_available {
+ if !inList(name, vndkPrivateLibraries) {
+ vndkPrivateLibraries = append(vndkPrivateLibraries, name)
+ sort.Strings(vndkPrivateLibraries)
+ }
+ }
+ } else {
+ lib, is_lib := m.linker.(*libraryDecorator)
+ prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
+ if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
+ name := strings.TrimPrefix(m.Name(), "prebuilt_")
+ if m.vndkdep.isVndk() {
+ vndkLibrariesLock.Lock()
+ defer vndkLibrariesLock.Unlock()
+ if m.vndkdep.isVndkSp() {
+ if !inList(name, vndkSpLibraries) {
+ vndkSpLibraries = append(vndkSpLibraries, name)
+ sort.Strings(vndkSpLibraries)
+ }
+ } else {
+ if !inList(name, vndkCoreLibraries) {
+ vndkCoreLibraries = append(vndkCoreLibraries, name)
+ sort.Strings(vndkCoreLibraries)
+ }
}
- } else {
- if !inList(m.Name(), vndkCoreLibraries) {
- vndkCoreLibraries = append(vndkCoreLibraries, m.Name())
- sort.Strings(vndkCoreLibraries)
+ if !Bool(m.VendorProperties.Vendor_available) {
+ if !inList(name, vndkPrivateLibraries) {
+ vndkPrivateLibraries = append(vndkPrivateLibraries, name)
+ sort.Strings(vndkPrivateLibraries)
+ }
}
}
}
}
+
}
}
diff --git a/cmd/javac_wrapper/javac_wrapper.go b/cmd/javac_wrapper/javac_wrapper.go
index ab4d23f..4df4938 100644
--- a/cmd/javac_wrapper/javac_wrapper.go
+++ b/cmd/javac_wrapper/javac_wrapper.go
@@ -17,6 +17,11 @@
//
// It also hides the unhelpful and unhideable "warning there is a warning"
// messages.
+//
+// Each javac build statement has an order-only dependency on the
+// soong_javac_wrapper tool, which means the javac command will not be rerun
+// if soong_javac_wrapper changes. That means that soong_javac_wrapper must
+// not do anything that will affect the results of the build.
package main
import (
@@ -170,4 +175,5 @@
regexp.MustCompile(`Note: Recompile with -Xlint:deprecation for details.`),
regexp.MustCompile(`Note: (Some input files|.*\.java) uses? unchecked or unsafe operations.`),
regexp.MustCompile(`Note: Recompile with -Xlint:unchecked for details.`),
+ regexp.MustCompile(`bootstrap class path not set in conjunction with -source`),
}
diff --git a/cmd/javac_wrapper/javac_wrapper_test.go b/cmd/javac_wrapper/javac_wrapper_test.go
index c345479..d76793f 100644
--- a/cmd/javac_wrapper/javac_wrapper_test.go
+++ b/cmd/javac_wrapper/javac_wrapper_test.go
@@ -41,8 +41,8 @@
out: "\x1b[1mFile.java:398: \x1b[35mwarning:\x1b[0m\x1b[1m [RectIntersectReturnValueIgnored] Return value of com.blah.function() must be checked\x1b[0m\n",
},
{
- in: "warning: [options] bootstrap class path not set in conjunction with -source 1.7\n",
- out: "\x1b[1m\x1b[35mwarning:\x1b[0m\x1b[1m [options] bootstrap class path not set in conjunction with -source 1.7\x1b[0m\n",
+ in: "warning: [options] blah\n",
+ out: "\x1b[1m\x1b[35mwarning:\x1b[0m\x1b[1m [options] blah\x1b[0m\n",
},
{
in: " (see http://go/errorprone/bugpattern/RectIntersectReturnValueIgnored.md)\n",
@@ -56,6 +56,7 @@
Note: Recompile with -Xlint:unchecked for details.
Note: dir/file.java uses or overrides a deprecated API.
Note: dir/file.java uses unchecked or unsafe operations.
+warning: [options] bootstrap class path not set in conjunction with -source 1.7
`,
out: "\n",
},
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index e771c15..1c853d6 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -55,6 +55,8 @@
var buildVariant = flag.String("variant", "eng", "build variant to use")
+var skipProducts = flag.String("skip-products", "", "comma-separated list of products to skip (known failures, etc)")
+
const errorLeadingLines = 20
const errorTrailingLines = 20
@@ -221,12 +223,31 @@
trace.SetOutput(filepath.Join(config.OutDir(), "build.trace"))
}
- vars, err := build.DumpMakeVars(buildCtx, config, nil, nil, []string{"all_named_products"})
+ vars, err := build.DumpMakeVars(buildCtx, config, nil, []string{"all_named_products"})
if err != nil {
log.Fatal(err)
}
- products := strings.Fields(vars["all_named_products"])
- log.Verbose("Got product list:", products)
+ productsList := strings.Fields(vars["all_named_products"])
+
+ products := make([]string, 0, len(productsList))
+ skipList := strings.Split(*skipProducts, ",")
+ skipProduct := func(p string) bool {
+ for _, s := range skipList {
+ if p == s {
+ return true
+ }
+ }
+ return false
+ }
+ for _, product := range productsList {
+ if !skipProduct(product) {
+ products = append(products, product)
+ } else {
+ log.Verbose("Skipping: ", product)
+ }
+ }
+
+ log.Verbose("Got product list: ", products)
status.SetTotal(len(products))
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 8a26171..0619b5c 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -16,6 +16,8 @@
import (
"context"
+ "flag"
+ "fmt"
"os"
"path/filepath"
"strconv"
@@ -45,7 +47,10 @@
log := logger.New(os.Stderr)
defer log.Cleanup()
- if len(os.Args) < 2 || !inList("--make-mode", os.Args) {
+ if len(os.Args) < 2 || !(inList("--make-mode", os.Args) ||
+ os.Args[1] == "--dumpvars-mode" ||
+ os.Args[1] == "--dumpvar-mode") {
+
log.Fatalln("The `soong` native UI is not yet available.")
}
@@ -66,7 +71,12 @@
Tracer: trace,
StdioInterface: build.StdioImpl{},
}}
- config := build.NewConfig(buildCtx, os.Args[1:]...)
+ var config build.Config
+ if os.Args[1] == "--dumpvars-mode" || os.Args[1] == "--dumpvar-mode" {
+ config = build.NewConfig(buildCtx)
+ } else {
+ config = build.NewConfig(buildCtx, os.Args[1:]...)
+ }
log.SetVerbose(config.IsVerbose())
build.SetupOutDir(buildCtx, config)
@@ -99,5 +109,129 @@
defer f.Shutdown()
build.FindSources(buildCtx, config, f)
- build.Build(buildCtx, config, build.BuildAll)
+ if os.Args[1] == "--dumpvar-mode" {
+ dumpVar(buildCtx, config, os.Args[2:])
+ } else if os.Args[1] == "--dumpvars-mode" {
+ dumpVars(buildCtx, config, os.Args[2:])
+ } else {
+ build.Build(buildCtx, config, build.BuildAll)
+ }
+}
+
+func dumpVar(ctx build.Context, config build.Config, args []string) {
+ flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
+ flags.Usage = func() {
+ fmt.Fprintf(os.Stderr, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
+ fmt.Fprintln(os.Stderr, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
+ fmt.Fprintln(os.Stderr, "")
+
+ fmt.Fprintln(os.Stderr, "'report_config' is a special case that prints the human-readable config banner")
+ fmt.Fprintln(os.Stderr, "from the beginning of the build.")
+ fmt.Fprintln(os.Stderr, "")
+ flags.PrintDefaults()
+ }
+ abs := flags.Bool("abs", false, "Print the absolute path of the value")
+ flags.Parse(args)
+
+ if flags.NArg() != 1 {
+ flags.Usage()
+ os.Exit(1)
+ }
+
+ varName := flags.Arg(0)
+ if varName == "report_config" {
+ varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
+ if err != nil {
+ ctx.Fatal(err)
+ }
+
+ fmt.Println(build.Banner(varData))
+ } else {
+ varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
+ if err != nil {
+ ctx.Fatal(err)
+ }
+
+ if *abs {
+ var res []string
+ for _, path := range strings.Fields(varData[varName]) {
+ if abs, err := filepath.Abs(path); err == nil {
+ res = append(res, abs)
+ } else {
+ ctx.Fatalln("Failed to get absolute path of", path, err)
+ }
+ }
+ fmt.Println(strings.Join(res, " "))
+ } else {
+ fmt.Println(varData[varName])
+ }
+ }
+}
+
+func dumpVars(ctx build.Context, config build.Config, args []string) {
+ flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
+ flags.Usage = func() {
+ fmt.Fprintf(os.Stderr, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
+ fmt.Fprintln(os.Stderr, "In dumpvars mode, dump the values of one or more legacy make variables, in")
+ fmt.Fprintln(os.Stderr, "shell syntax. The resulting output may be sourced directly into a shell to")
+ fmt.Fprintln(os.Stderr, "set corresponding shell variables.")
+ fmt.Fprintln(os.Stderr, "")
+
+ fmt.Fprintln(os.Stderr, "'report_config' is a special case that dumps a variable containing the")
+ fmt.Fprintln(os.Stderr, "human-readable config banner from the beginning of the build.")
+ fmt.Fprintln(os.Stderr, "")
+ flags.PrintDefaults()
+ }
+
+ varsStr := flags.String("vars", "", "Space-separated list of variables to dump")
+ absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)")
+
+ varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping")
+ absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping")
+
+ flags.Parse(args)
+
+ if flags.NArg() != 0 {
+ flags.Usage()
+ os.Exit(1)
+ }
+
+ vars := strings.Fields(*varsStr)
+ absVars := strings.Fields(*absVarsStr)
+
+ allVars := append([]string{}, vars...)
+ allVars = append(allVars, absVars...)
+
+ if i := indexList("report_config", allVars); i != -1 {
+ allVars = append(allVars[:i], allVars[i+1:]...)
+ allVars = append(allVars, build.BannerVars...)
+ }
+
+ if len(allVars) == 0 {
+ return
+ }
+
+ varData, err := build.DumpMakeVars(ctx, config, nil, allVars)
+ if err != nil {
+ ctx.Fatal(err)
+ }
+
+ for _, name := range vars {
+ if name == "report_config" {
+ fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
+ } else {
+ fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
+ }
+ }
+ for _, name := range absVars {
+ var res []string
+ for _, path := range strings.Fields(varData[name]) {
+ abs, err := filepath.Abs(path)
+ if err != nil {
+ ctx.Fatalln("Failed to get absolute path of", path, err)
+ }
+ res = append(res, abs)
+ }
+ fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " "))
+ }
}
diff --git a/cmd/soong_zip/soong_zip.go b/cmd/soong_zip/soong_zip.go
index cb9df9a..2bcc9a5 100644
--- a/cmd/soong_zip/soong_zip.go
+++ b/cmd/soong_zip/soong_zip.go
@@ -62,12 +62,6 @@
io.Closer
}
-type fileArg struct {
- pathPrefixInZip, sourcePrefixToStrip string
- sourceFiles []string
- globDir string
-}
-
type pathMapping struct {
dest, src string
zipMethod uint16
@@ -89,8 +83,6 @@
return nil
}
-type fileArgs []fileArg
-
type file struct{}
type listFiles struct{}
@@ -106,10 +98,10 @@
return fmt.Errorf("must pass -C before -f")
}
- fArgs = append(fArgs, fileArg{
- pathPrefixInZip: filepath.Clean(*rootPrefix),
- sourcePrefixToStrip: filepath.Clean(*relativeRoot),
- sourceFiles: []string{s},
+ fArgs = append(fArgs, FileArg{
+ PathPrefixInZip: filepath.Clean(*rootPrefix),
+ SourcePrefixToStrip: filepath.Clean(*relativeRoot),
+ SourceFiles: []string{s},
})
return nil
@@ -129,10 +121,10 @@
return err
}
- fArgs = append(fArgs, fileArg{
- pathPrefixInZip: filepath.Clean(*rootPrefix),
- sourcePrefixToStrip: filepath.Clean(*relativeRoot),
- sourceFiles: strings.Split(string(list), "\n"),
+ fArgs = append(fArgs, FileArg{
+ PathPrefixInZip: filepath.Clean(*rootPrefix),
+ SourcePrefixToStrip: filepath.Clean(*relativeRoot),
+ SourceFiles: strings.Split(string(list), "\n"),
})
return nil
@@ -147,10 +139,10 @@
return fmt.Errorf("must pass -C before -D")
}
- fArgs = append(fArgs, fileArg{
- pathPrefixInZip: filepath.Clean(*rootPrefix),
- sourcePrefixToStrip: filepath.Clean(*relativeRoot),
- globDir: filepath.Clean(s),
+ fArgs = append(fArgs, FileArg{
+ PathPrefixInZip: filepath.Clean(*rootPrefix),
+ SourcePrefixToStrip: filepath.Clean(*relativeRoot),
+ GlobDir: filepath.Clean(s),
})
return nil
@@ -166,7 +158,7 @@
compLevel = flag.Int("L", 5, "deflate compression level (0-9)")
emulateJar = flag.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
- fArgs fileArgs
+ fArgs FileArgs
nonDeflatedFiles = make(uniqueSet)
cpuProfile = flag.String("cpuprofile", "", "write cpu profile to file")
@@ -186,7 +178,36 @@
os.Exit(2)
}
-type zipWriter struct {
+func main() {
+ flag.Parse()
+
+ err := Run(ZipArgs{
+ FileArgs: fArgs,
+ OutputFilePath: *out,
+ CpuProfileFilePath: *cpuProfile,
+ TraceFilePath: *traceFile,
+ EmulateJar: *emulateJar,
+ AddDirectoryEntriesToZip: *directories,
+ CompressionLevel: *compLevel,
+ ManifestSourcePath: *manifest,
+ NumParallelJobs: *parallelJobs,
+ NonDeflatedFiles: nonDeflatedFiles,
+ })
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+}
+
+type FileArg struct {
+ PathPrefixInZip, SourcePrefixToStrip string
+ SourceFiles []string
+ GlobDir string
+}
+
+type FileArgs []FileArg
+
+type ZipWriter struct {
time time.Time
createdFiles map[string]string
createdDirs map[string]string
@@ -213,11 +234,22 @@
allocatedSize int64
}
-func main() {
- flag.Parse()
+type ZipArgs struct {
+ FileArgs FileArgs
+ OutputFilePath string
+ CpuProfileFilePath string
+ TraceFilePath string
+ EmulateJar bool
+ AddDirectoryEntriesToZip bool
+ CompressionLevel int
+ ManifestSourcePath string
+ NumParallelJobs int
+ NonDeflatedFiles map[string]bool
+}
- if *cpuProfile != "" {
- f, err := os.Create(*cpuProfile)
+func Run(args ZipArgs) (err error) {
+ if args.CpuProfileFilePath != "" {
+ f, err := os.Create(args.CpuProfileFilePath)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
@@ -227,8 +259,8 @@
defer pprof.StopCPUProfile()
}
- if *traceFile != "" {
- f, err := os.Create(*traceFile)
+ if args.TraceFilePath != "" {
+ f, err := os.Create(args.TraceFilePath)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
@@ -242,46 +274,41 @@
defer trace.Stop()
}
- if *out == "" {
- fmt.Fprintf(os.Stderr, "error: -o is required\n")
- usage()
+ if args.OutputFilePath == "" {
+ return fmt.Errorf("output file path must be nonempty")
}
- if *emulateJar {
- *directories = true
+ if args.EmulateJar {
+ args.AddDirectoryEntriesToZip = true
}
- w := &zipWriter{
+ w := &ZipWriter{
time: jar.DefaultTime,
createdDirs: make(map[string]string),
createdFiles: make(map[string]string),
- directories: *directories,
- compLevel: *compLevel,
+ directories: args.AddDirectoryEntriesToZip,
+ compLevel: args.CompressionLevel,
}
-
pathMappings := []pathMapping{}
- for _, fa := range fArgs {
- srcs := fa.sourceFiles
- if fa.globDir != "" {
- srcs = append(srcs, recursiveGlobFiles(fa.globDir)...)
+ for _, fa := range args.FileArgs {
+ srcs := fa.SourceFiles
+ if fa.GlobDir != "" {
+ srcs = append(srcs, recursiveGlobFiles(fa.GlobDir)...)
}
for _, src := range srcs {
- if err := fillPathPairs(fa.pathPrefixInZip,
- fa.sourcePrefixToStrip, src, &pathMappings); err != nil {
+ if err := fillPathPairs(fa.PathPrefixInZip,
+ fa.SourcePrefixToStrip, src, &pathMappings, args.NonDeflatedFiles); err != nil {
log.Fatal(err)
}
}
}
- err := w.write(*out, pathMappings, *manifest)
- if err != nil {
- fmt.Fprintln(os.Stderr, err.Error())
- os.Exit(1)
- }
+ return w.write(args.OutputFilePath, pathMappings, args.ManifestSourcePath, args.EmulateJar, args.NumParallelJobs)
+
}
-func fillPathPairs(prefix, rel, src string, pathMappings *[]pathMapping) error {
+func fillPathPairs(prefix, rel, src string, pathMappings *[]pathMapping, nonDeflatedFiles map[string]bool) error {
src = strings.TrimSpace(src)
if src == "" {
return nil
@@ -317,7 +344,7 @@
io.Seeker
}
-func (z *zipWriter) write(out string, pathMappings []pathMapping, manifest string) error {
+func (z *ZipWriter) write(out string, pathMappings []pathMapping, manifest string, emulateJar bool, parallelJobs int) error {
f, err := os.Create(out)
if err != nil {
return err
@@ -346,18 +373,18 @@
// The RateLimit object will put the upper bounds on the number of
// parallel compressions and outstanding buffers.
z.writeOps = make(chan chan *zipEntry, 1000)
- z.cpuRateLimiter = NewCPURateLimiter(int64(*parallelJobs))
+ z.cpuRateLimiter = NewCPURateLimiter(int64(parallelJobs))
z.memoryRateLimiter = NewMemoryRateLimiter(0)
defer func() {
z.cpuRateLimiter.Stop()
z.memoryRateLimiter.Stop()
}()
- if manifest != "" && !*emulateJar {
+ if manifest != "" && !emulateJar {
return errors.New("must specify --jar when specifying a manifest via -m")
}
- if *emulateJar {
+ if emulateJar {
// manifest may be empty, in which case addManifest will fill in a default
pathMappings = append(pathMappings, pathMapping{jar.ManifestFile, manifest, zip.Deflate})
@@ -369,10 +396,10 @@
defer close(z.writeOps)
for _, ele := range pathMappings {
- if *emulateJar && ele.dest == jar.ManifestFile {
+ if emulateJar && ele.dest == jar.ManifestFile {
err = z.addManifest(ele.dest, ele.src, ele.zipMethod)
} else {
- err = z.addFile(ele.dest, ele.src, ele.zipMethod)
+ err = z.addFile(ele.dest, ele.src, ele.zipMethod, emulateJar)
}
if err != nil {
z.errors <- err
@@ -470,7 +497,7 @@
}
// imports (possibly with compression) <src> into the zip at sub-path <dest>
-func (z *zipWriter) addFile(dest, src string, method uint16) error {
+func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar bool) error {
var fileSize int64
var executable bool
@@ -478,11 +505,11 @@
return err
} else if s.IsDir() {
if z.directories {
- return z.writeDirectory(dest, src)
+ return z.writeDirectory(dest, src, emulateJar)
}
return nil
} else {
- if err := z.writeDirectory(filepath.Dir(dest), src); err != nil {
+ if err := z.writeDirectory(filepath.Dir(dest), src, emulateJar); err != nil {
return err
}
@@ -523,7 +550,7 @@
return z.writeFileContents(header, r)
}
-func (z *zipWriter) addManifest(dest string, src string, method uint16) error {
+func (z *ZipWriter) addManifest(dest string, src string, method uint16) error {
if prev, exists := z.createdDirs[dest]; exists {
return fmt.Errorf("destination %q is both a directory %q and a file %q", dest, prev, src)
}
@@ -531,7 +558,7 @@
return fmt.Errorf("destination %q has two files %q and %q", dest, prev, src)
}
- if err := z.writeDirectory(filepath.Dir(dest), src); err != nil {
+ if err := z.writeDirectory(filepath.Dir(dest), src, true); err != nil {
return err
}
@@ -545,7 +572,7 @@
return z.writeFileContents(fh, reader)
}
-func (z *zipWriter) writeFileContents(header *zip.FileHeader, r readerSeekerCloser) (err error) {
+func (z *ZipWriter) writeFileContents(header *zip.FileHeader, r readerSeekerCloser) (err error) {
header.SetModTime(z.time)
@@ -621,7 +648,7 @@
return nil
}
-func (z *zipWriter) crcFile(r io.Reader, ze *zipEntry, resultChan chan *zipEntry, wg *sync.WaitGroup) {
+func (z *ZipWriter) crcFile(r io.Reader, ze *zipEntry, resultChan chan *zipEntry, wg *sync.WaitGroup) {
defer wg.Done()
defer z.cpuRateLimiter.Finish()
@@ -637,7 +664,7 @@
close(resultChan)
}
-func (z *zipWriter) compressPartialFile(r io.Reader, dict []byte, last bool, resultChan chan io.Reader, wg *sync.WaitGroup) {
+func (z *ZipWriter) compressPartialFile(r io.Reader, dict []byte, last bool, resultChan chan io.Reader, wg *sync.WaitGroup) {
defer wg.Done()
result, err := z.compressBlock(r, dict, last)
@@ -651,7 +678,7 @@
resultChan <- result
}
-func (z *zipWriter) compressBlock(r io.Reader, dict []byte, last bool) (*bytes.Buffer, error) {
+func (z *ZipWriter) compressBlock(r io.Reader, dict []byte, last bool) (*bytes.Buffer, error) {
buf := new(bytes.Buffer)
var fw *flate.Writer
var err error
@@ -685,7 +712,7 @@
return buf, nil
}
-func (z *zipWriter) compressWholeFile(ze *zipEntry, r io.ReadSeeker, compressChan chan *zipEntry) {
+func (z *ZipWriter) compressWholeFile(ze *zipEntry, r io.ReadSeeker, compressChan chan *zipEntry) {
crc := crc32.NewIEEE()
_, err := io.Copy(crc, r)
@@ -758,7 +785,7 @@
// writeDirectory annotates that dir is a directory created for the src file or directory, and adds
// the directory entry to the zip file if directories are enabled.
-func (z *zipWriter) writeDirectory(dir, src string) error {
+func (z *ZipWriter) writeDirectory(dir string, src string, emulateJar bool) error {
// clean the input
dir = filepath.Clean(dir)
@@ -785,7 +812,7 @@
for _, cleanDir := range zipDirs {
var dirHeader *zip.FileHeader
- if *emulateJar && cleanDir+"/" == jar.MetaDir {
+ if emulateJar && cleanDir+"/" == jar.MetaDir {
dirHeader = jar.MetaDirFileHeader()
} else {
dirHeader = &zip.FileHeader{
@@ -808,7 +835,7 @@
return nil
}
-func (z *zipWriter) writeSymlink(rel, file string) error {
+func (z *ZipWriter) writeSymlink(rel, file string) error {
fileHeader := &zip.FileHeader{
Name: rel,
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 479e67a..4a734da 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -28,8 +28,8 @@
)
func init() {
- android.RegisterModuleType("gensrcs", genSrcsFactory)
- android.RegisterModuleType("genrule", genRuleFactory)
+ android.RegisterModuleType("gensrcs", GenSrcsFactory)
+ android.RegisterModuleType("genrule", GenRuleFactory)
}
var (
@@ -61,13 +61,13 @@
//
// Available variables for substitution:
//
- // $(location): the path to the first entry in tools or tool_files
- // $(location <label>): the path to the tool or tool_file with name <label>
- // $(in): one or more input files
- // $(out): a single output file
- // $(depfile): a file to which dependencies will be written, if the depfile property is set to true
- // $(genDir): the sandbox directory for this tool; contains $(out)
- // $$: a literal $
+ // $(location): the path to the first entry in tools or tool_files
+ // $(location <label>): the path to the tool or tool_file with name <label>
+ // $(in): one or more input files
+ // $(out): a single output file
+ // $(depfile): a file to which dependencies will be written, if the depfile property is set to true
+ // $(genDir): the sandbox directory for this tool; contains $(out)
+ // $$: a literal $
//
// All files used must be declared as inputs (to ensure proper up-to-date checks).
// Use "$(in)" directly in Cmd to ensure that all inputs used are declared.
@@ -331,7 +331,7 @@
return generatorFactory(tasks, properties)
}
-func genSrcsFactory() android.Module {
+func GenSrcsFactory() android.Module {
m := NewGenSrcs()
android.InitAndroidModule(m)
return m
@@ -361,7 +361,7 @@
return generatorFactory(tasks, properties)
}
-func genRuleFactory() android.Module {
+func GenRuleFactory() android.Module {
m := NewGenRule()
android.InitAndroidModule(m)
return m
diff --git a/java/androidmk.go b/java/androidmk.go
index 89d7d51..e349de4 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -19,6 +19,8 @@
"io"
"strings"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
)
@@ -38,6 +40,25 @@
fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", library.deviceProperties.Sdk_version)
},
},
+ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ android.WriteAndroidMkData(w, data)
+
+ if proptools.Bool(library.deviceProperties.Hostdex) && !library.Host() {
+ fmt.Fprintln(w, "include $(CLEAR_VARS)")
+ fmt.Fprintln(w, "LOCAL_MODULE := "+name+"-hostdex")
+ fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
+ fmt.Fprintln(w, "LOCAL_MODULE_CLASS := JAVA_LIBRARIES")
+ fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", library.classpathFile.String())
+ if library.properties.Installable != nil && *library.properties.Installable == false {
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ }
+ if library.dexJarFile != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", library.dexJarFile.String())
+ }
+ fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES := "+strings.Join(data.Required, " "))
+ fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
+ }
+ },
}
}
diff --git a/java/app.go b/java/app.go
index e40478a..42ae236 100644
--- a/java/app.go
+++ b/java/app.go
@@ -89,7 +89,7 @@
publicResourcesFile, proguardOptionsFile, aaptJavaFileList :=
CreateResourceJavaFiles(ctx, aaptRJavaFlags, aaptDeps)
a.aaptJavaFileList = aaptJavaFileList
- a.ExtraSrcLists = append(a.ExtraSrcLists, aaptJavaFileList)
+ // TODO(ccross): export aapt generated java files as a src jar
if a.appProperties.Export_package_resources {
aaptPackageFlags := append([]string(nil), aaptFlags...)
@@ -274,8 +274,6 @@
func AndroidAppFactory() android.Module {
module := &AndroidApp{}
- module.deviceProperties.Dex = true
-
module.AddProperties(
&module.Module.properties,
&module.Module.deviceProperties,
diff --git a/java/builder.go b/java/builder.go
index ca0d2c5..9086d51 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -39,22 +39,39 @@
javac = pctx.AndroidGomaStaticRule("javac",
blueprint.RuleParams{
Command: `rm -rf "$outDir" "$annoDir" && mkdir -p "$outDir" "$annoDir" && ` +
- `${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
- `$javacFlags $bootClasspath $classpath ` +
+ `${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
+ `$javacFlags $sourcepath $bootClasspath $classpath ` +
`-source $javaVersion -target $javaVersion ` +
`-d $outDir -s $annoDir @$out.rsp && ` +
`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
- CommandDeps: []string{"${config.JavacCmd}", "${config.SoongZipCmd}"},
- Rspfile: "$out.rsp",
- RspfileContent: "$in",
+ CommandDeps: []string{"${config.JavacCmd}", "${config.SoongZipCmd}"},
+ CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
},
- "javacFlags", "bootClasspath", "classpath", "outDir", "annoDir", "javaVersion")
+ "javacFlags", "sourcepath", "bootClasspath", "classpath", "outDir", "annoDir", "javaVersion")
+
+ kotlinc = pctx.AndroidGomaStaticRule("kotlinc",
+ blueprint.RuleParams{
+ // TODO(ccross): kotlinc doesn't support @ file for arguments, which will limit the
+ // maximum number of input files, especially on darwin.
+ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+ `${config.KotlincCmd} $classpath $kotlincFlags ` +
+ `-jvm-target $javaVersion -d $outDir $in && ` +
+ `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
+ CommandDeps: []string{
+ "${config.KotlincCmd}",
+ "${config.KotlinCompilerJar}",
+ "${config.SoongZipCmd}",
+ },
+ },
+ "kotlincFlags", "classpath", "outDir", "javaVersion")
errorprone = pctx.AndroidStaticRule("errorprone",
blueprint.RuleParams{
Command: `rm -rf "$outDir" "$annoDir" && mkdir -p "$outDir" "$annoDir" && ` +
- `${config.ErrorProneCmd} ` +
- `$javacFlags $bootClasspath $classpath ` +
+ `${config.SoongJavacWrapper} ${config.ErrorProneCmd} ` +
+ `$javacFlags $sourcepath $bootClasspath $classpath ` +
`-source $javaVersion -target $javaVersion ` +
`-d $outDir -s $annoDir @$out.rsp && ` +
`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
@@ -64,10 +81,11 @@
"${config.ErrorProneJar}",
"${config.SoongZipCmd}",
},
- Rspfile: "$out.rsp",
- RspfileContent: "$in",
+ CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
},
- "javacFlags", "bootClasspath", "classpath", "outDir", "annoDir", "javaVersion")
+ "javacFlags", "sourcepath", "bootClasspath", "classpath", "outDir", "annoDir", "javaVersion")
jar = pctx.AndroidStaticRule("jar",
blueprint.RuleParams{
@@ -126,95 +144,108 @@
dxFlags string
bootClasspath classpath
classpath classpath
+ systemModules classpath
desugarFlags string
aidlFlags string
javaVersion string
+ kotlincFlags string
+ kotlincClasspath classpath
+
protoFlags string
protoOutFlag string
}
-func TransformJavaToClasses(ctx android.ModuleContext, srcFiles, srcFileLists android.Paths,
- flags javaBuilderFlags, deps android.Paths) android.ModuleOutPath {
+func TransformKotlinToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
+ srcFiles android.Paths, srcJars classpath,
+ flags javaBuilderFlags) {
- classDir := android.PathForModuleOut(ctx, "classes")
- annoDir := android.PathForModuleOut(ctx, "anno")
- classJar := android.PathForModuleOut(ctx, "classes-compiled.jar")
+ classDir := android.PathForModuleOut(ctx, "classes-kt")
- javacFlags := flags.javacFlags
- if len(srcFileLists) > 0 {
- javacFlags += " " + android.JoinWithPrefix(srcFileLists.Strings(), "@")
- }
-
- deps = append(deps, srcFileLists...)
- deps = append(deps, flags.bootClasspath...)
- deps = append(deps, flags.classpath...)
+ inputs := append(android.Paths(nil), srcFiles...)
+ inputs = append(inputs, srcJars...)
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
- Rule: javac,
- Description: "javac",
- Output: classJar,
- Inputs: srcFiles,
- Implicits: deps,
+ Rule: kotlinc,
+ Description: "kotlinc",
+ Output: outputFile,
+ Inputs: inputs,
Args: map[string]string{
- "javacFlags": javacFlags,
- "bootClasspath": flags.bootClasspath.JavaBootClasspath(ctx.Device()),
- "classpath": flags.classpath.JavaClasspath(),
- "outDir": classDir.String(),
- "annoDir": annoDir.String(),
- "javaVersion": flags.javaVersion,
+ "classpath": flags.kotlincClasspath.JavaClasspath(),
+ "kotlincFlags": flags.kotlincFlags,
+ "outDir": classDir.String(),
+ "javaVersion": flags.javaVersion,
},
})
-
- return classJar
}
-func RunErrorProne(ctx android.ModuleContext, srcFiles, srcFileLists android.Paths,
- flags javaBuilderFlags) android.Path {
+func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
+ srcFiles android.Paths, srcJars classpath,
+ flags javaBuilderFlags, deps android.Paths) {
+
+ transformJavaToClasses(ctx, outputFile, srcFiles, srcJars, flags, deps,
+ "", "javac", javac)
+}
+
+func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath,
+ srcFiles android.Paths, srcJars classpath,
+ flags javaBuilderFlags) {
if config.ErrorProneJar == "" {
ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
- return nil
}
- classDir := android.PathForModuleOut(ctx, "classes-errorprone")
- annoDir := android.PathForModuleOut(ctx, "anno-errorprone")
- classFileList := android.PathForModuleOut(ctx, "classes-errorprone.list")
+ transformJavaToClasses(ctx, outputFile, srcFiles, srcJars, flags, nil,
+ "-errorprone", "errorprone", errorprone)
+}
- javacFlags := flags.javacFlags
- if len(srcFileLists) > 0 {
- javacFlags += " " + android.JoinWithPrefix(srcFileLists.Strings(), "@")
+// transformJavaToClasses takes source files and converts them to a jar containing .class files.
+// srcFiles is a list of paths to sources, srcJars is a list of paths to jar files that contain
+// sources. flags contains various command line flags to be passed to the compiler.
+//
+// This method may be used for different compilers, including javac and Error Prone. The rule
+// argument specifies which command line to use and desc sets the description of the rule that will
+// be printed at build time. The stem argument provides the file name of the output jar, and
+// suffix will be appended to various intermediate files and directories to avoid collisions when
+// this function is called twice in the same module directory.
+func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
+ srcFiles android.Paths, srcJars classpath,
+ flags javaBuilderFlags, deps android.Paths,
+ intermediatesSuffix, desc string, rule blueprint.Rule) {
+
+ deps = append(deps, srcJars...)
+
+ var bootClasspath string
+ if flags.javaVersion == "1.9" {
+ deps = append(deps, flags.systemModules...)
+ bootClasspath = flags.systemModules.JavaSystemModules(ctx.Device())
+ } else {
+ deps = append(deps, flags.bootClasspath...)
+ bootClasspath = flags.bootClasspath.JavaBootClasspath(ctx.Device())
}
- var deps android.Paths
-
- deps = append(deps, srcFileLists...)
- deps = append(deps, flags.bootClasspath...)
deps = append(deps, flags.classpath...)
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
- Rule: errorprone,
- Description: "errorprone",
- Output: classFileList,
+ Rule: rule,
+ Description: desc,
+ Output: outputFile,
Inputs: srcFiles,
Implicits: deps,
Args: map[string]string{
- "javacFlags": javacFlags,
- "bootClasspath": flags.bootClasspath.JavaBootClasspath(ctx.Device()),
+ "javacFlags": flags.javacFlags,
+ "bootClasspath": bootClasspath,
+ "sourcepath": srcJars.JavaSourcepath(),
"classpath": flags.classpath.JavaClasspath(),
- "outDir": classDir.String(),
- "annoDir": annoDir.String(),
+ "outDir": android.PathForModuleOut(ctx, "classes"+intermediatesSuffix).String(),
+ "annoDir": android.PathForModuleOut(ctx, "anno"+intermediatesSuffix).String(),
"javaVersion": flags.javaVersion,
},
})
-
- return classFileList
}
-func TransformResourcesToJar(ctx android.ModuleContext, jarArgs []string,
- deps android.Paths) android.Path {
-
- outputFile := android.PathForModuleOut(ctx, "res.jar")
+func TransformResourcesToJar(ctx android.ModuleContext, outputFile android.WritablePath,
+ jarArgs []string, deps android.Paths) {
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Rule: jar,
@@ -225,18 +256,10 @@
"jarArgs": strings.Join(jarArgs, " "),
},
})
-
- return outputFile
}
-func TransformJarsToJar(ctx android.ModuleContext, stem string, jars android.Paths,
- manifest android.OptionalPath, stripDirs bool) android.Path {
-
- outputFile := android.PathForModuleOut(ctx, stem)
-
- if len(jars) == 1 && !manifest.Valid() {
- return jars[0]
- }
+func TransformJarsToJar(ctx android.ModuleContext, outputFile android.WritablePath,
+ jars android.Paths, manifest android.OptionalPath, stripDirs bool) {
var deps android.Paths
@@ -260,18 +283,15 @@
"jarArgs": strings.Join(jarArgs, " "),
},
})
-
- return outputFile
}
-func TransformDesugar(ctx android.ModuleContext, classesJar android.Path,
- flags javaBuilderFlags) android.Path {
+func TransformDesugar(ctx android.ModuleContext, outputFile android.WritablePath,
+ classesJar android.Path, flags javaBuilderFlags) {
- outputFile := android.PathForModuleOut(ctx, "classes-desugar.jar")
dumpDir := android.PathForModuleOut(ctx, "desugar_dumped_classes")
javaFlags := ""
- if ctx.AConfig().Getenv("EXPERIMENTAL_USE_OPENJDK9") != "" {
+ if ctx.AConfig().UseOpenJDK9() {
javaFlags = "--add-opens java.base/java.lang.invoke=ALL-UNNAMED"
}
@@ -296,17 +316,14 @@
"desugarFlags": flags.desugarFlags,
},
})
-
- return outputFile
}
// Converts a classes.jar file to classes*.dex, then combines the dex files with any resources
// in the classes.jar file into a dex jar.
-func TransformClassesJarToDexJar(ctx android.ModuleContext, stem string, classesJar android.Path,
- flags javaBuilderFlags) android.Path {
+func TransformClassesJarToDexJar(ctx android.ModuleContext, outputFile android.WritablePath,
+ classesJar android.Path, flags javaBuilderFlags) {
outDir := android.PathForModuleOut(ctx, "dex")
- outputFile := android.PathForModuleOut(ctx, stem)
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Rule: dx,
@@ -318,12 +335,10 @@
"outDir": outDir.String(),
},
})
-
- return outputFile
}
-func TransformJarJar(ctx android.ModuleContext, classesJar android.Path, rulesFile android.Path) android.ModuleOutPath {
- outputFile := android.PathForModuleOut(ctx, "classes-jarjar.jar")
+func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath,
+ classesJar android.Path, rulesFile android.Path) {
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Rule: jarjar,
Description: "jarjar",
@@ -334,12 +349,20 @@
"rulesFile": rulesFile.String(),
},
})
-
- return outputFile
}
type classpath []android.Path
+// Returns a -sourcepath argument in the form javac expects. If the list is empty returns
+// -sourcepath "" to ensure javac does not fall back to searching the classpath for sources.
+func (x *classpath) JavaSourcepath() string {
+ if len(*x) > 0 {
+ return "-sourcepath " + strings.Join(x.Strings(), ":")
+ } else {
+ return `-sourcepath ""`
+ }
+}
+
// Returns a -classpath argument in the form java or javac expects
func (x *classpath) JavaClasspath() string {
if len(*x) > 0 {
@@ -371,6 +394,21 @@
}
}
+// Returns a --system argument in the form javac expects with -source 1.9. If forceEmpty is true,
+// returns --system=none if the list is empty to ensure javac does not fall back to the default
+// system modules.
+func (x *classpath) JavaSystemModules(forceEmpty bool) string {
+ if len(*x) > 1 {
+ panic("more than one system module")
+ } else if len(*x) == 1 {
+ return "--system=" + strings.TrimSuffix((*x)[0].String(), "lib/modules")
+ } else if forceEmpty {
+ return "--system=none"
+ } else {
+ return ""
+ }
+}
+
func (x *classpath) DesugarBootClasspath() []string {
if x == nil || *x == nil {
return nil
diff --git a/java/config/config.go b/java/config/config.go
index 4f74ef2..eb71ddb 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -15,7 +15,6 @@
package config
import (
- "path/filepath"
"strings"
_ "github.com/google/blueprint/bootstrap"
@@ -27,6 +26,7 @@
pctx = android.NewPackageContext("android/soong/java/config")
DefaultBootclasspathLibraries = []string{"core-oj", "core-libart"}
+ DefaultSystemModules = "core-system-modules"
DefaultLibraries = []string{"ext", "framework", "okhttp"}
)
@@ -47,14 +47,23 @@
// If a different javac is used the flag will be ignored and extra bridges will be inserted.
// The flag is implemented by https://android-review.googlesource.com/c/486427
`-XDskipDuplicateBridges=true`,
- }, " "))
- pctx.StaticVariable("DefaultJavaVersion", "1.8")
+ // b/65004097: prevent using java.lang.invoke.StringConcatFactory when using -target 1.9
+ `-XDstringConcat=inline`,
+ }, " "))
pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS)
- pctx.SourcePathVariableWithEnvOverride("JavaHome",
- "prebuilts/jdk/jdk8/${hostPrebuiltTag}", "OVERRIDE_ANDROID_JAVA_HOME")
+ pctx.VariableFunc("JavaHome", func(config interface{}) (string, error) {
+ if override := config.(android.Config).Getenv("OVERRIDE_ANDROID_JAVA_HOME"); override != "" {
+ return override, nil
+ }
+ if config.(android.Config).UseOpenJDK9() {
+ return "prebuilts/jdk/jdk9/${hostPrebuiltTag}", nil
+ }
+ return "prebuilts/jdk/jdk8/${hostPrebuiltTag}", nil
+ })
+
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
pctx.SourcePathVariableWithEnvOverride("JavacCmd",
"${JavaToolchain}/javac", "ALTERNATE_JAVAC")
@@ -63,14 +72,17 @@
pctx.SourcePathVariable("JavadocCmd", "${JavaToolchain}/javadoc")
pctx.SourcePathVariable("JlinkCmd", "${JavaToolchain}/jlink")
pctx.SourcePathVariable("JmodCmd", "${JavaToolchain}/jmod")
+ pctx.SourcePathVariable("JrtFsJar", "${JavaHome}/lib/jrt-fs.jar")
pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
- pctx.StaticVariable("SoongZipCmd", filepath.Join("${bootstrap.ToolDir}", "soong_zip"))
- pctx.StaticVariable("MergeZipsCmd", filepath.Join("${bootstrap.ToolDir}", "merge_zips"))
+ pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
+ pctx.HostBinToolVariable("MergeZipsCmd", "merge_zips")
pctx.HostBinToolVariable("DxCmd", "dx")
pctx.HostJavaToolVariable("JarjarCmd", "jarjar.jar")
pctx.HostJavaToolVariable("DesugarJar", "desugar.jar")
+ pctx.HostBinToolVariable("SoongJavacWrapper", "soong_javac_wrapper")
+
pctx.VariableFunc("JavacWrapper", func(config interface{}) (string, error) {
if override := config.(android.Config).Getenv("JAVAC_WRAPPER"); override != "" {
return override + " ", nil
@@ -78,17 +90,3 @@
return "", nil
})
}
-
-func StripJavac9Flags(flags []string) []string {
- var ret []string
- for _, f := range flags {
- switch {
- case strings.HasPrefix(f, "-J--add-modules="):
- // drop
- default:
- ret = append(ret, f)
- }
- }
-
- return ret
-}
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
new file mode 100644
index 0000000..35f9e9d
--- /dev/null
+++ b/java/config/kotlin.go
@@ -0,0 +1,25 @@
+// Copyright 2017 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 config
+
+var (
+ KotlinStdlibJar = "external/kotlinc/lib/kotlin-stdlib.jar"
+)
+
+func init() {
+ pctx.SourcePathVariable("KotlincCmd", "external/kotlinc/bin/kotlinc")
+ pctx.SourcePathVariable("KotlinCompilerJar", "external/kotlinc/lib/kotlin-compiler.jar")
+ pctx.SourcePathVariable("KotlinStdlibJar", KotlinStdlibJar)
+}
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 937d597..6b49592 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -27,8 +27,13 @@
func makeVarsProvider(ctx android.MakeVarsContext) {
ctx.Strict("TARGET_DEFAULT_JAVA_LIBRARIES", strings.Join(DefaultLibraries, " "))
ctx.Strict("TARGET_DEFAULT_BOOTCLASSPATH_LIBRARIES", strings.Join(DefaultBootclasspathLibraries, " "))
+ ctx.Strict("DEFAULT_SYSTEM_MODULES", DefaultSystemModules)
- ctx.Strict("DEFAULT_JAVA_LANGUAGE_VERSION", "${DefaultJavaVersion}")
+ if ctx.Config().TargetOpenJDK9() {
+ ctx.Strict("DEFAULT_JAVA_LANGUAGE_VERSION", "1.9")
+ } else {
+ ctx.Strict("DEFAULT_JAVA_LANGUAGE_VERSION", "1.8")
+ }
ctx.Strict("ANDROID_JAVA_HOME", "${JavaHome}")
ctx.Strict("ANDROID_JAVA_TOOLCHAIN", "${JavaToolchain}")
@@ -47,8 +52,10 @@
ctx.Strict("HOST_JAVAC", "${JavacCmd} ${CommonJdkFlags}")
}
- if ctx.Config().IsEnvTrue("EXPERIMENTAL_USE_OPENJDK9") {
+ if ctx.Config().UseOpenJDK9() {
ctx.Strict("JLINK", "${JlinkCmd}")
ctx.Strict("JMOD", "${JmodCmd}")
}
+
+ ctx.Strict("SOONG_JAVAC_WRAPPER", "${SoongJavacWrapper}")
}
diff --git a/java/gen.go b/java/gen.go
index e55be91..e12a71c 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -85,7 +85,7 @@
}
func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
- flags javaBuilderFlags) (android.Paths, android.Paths) {
+ flags javaBuilderFlags) (android.Paths, classpath) {
var protoFiles android.Paths
outSrcFiles := make(android.Paths, 0, len(srcFiles))
@@ -106,16 +106,17 @@
}
}
- var outSrcFileLists android.Paths
+ var outSrcJars classpath
if len(protoFiles) > 0 {
- protoFileList := genProto(ctx, protoFiles,
+ protoSrcJar := android.PathForModuleGen(ctx, "proto.src.jar")
+ genProto(ctx, protoSrcJar, protoFiles,
flags.protoFlags, flags.protoOutFlag, "")
- outSrcFileLists = append(outSrcFileLists, protoFileList)
+ outSrcJars = append(outSrcJars, protoSrcJar)
}
- return outSrcFiles, outSrcFileLists
+ return outSrcFiles, outSrcJars
}
func LogtagsSingleton() blueprint.Singleton {
diff --git a/java/java.go b/java/java.go
index 3726435..76e574e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -28,7 +28,6 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/genrule"
"android/soong/java/config"
)
@@ -101,7 +100,7 @@
Manifest *string
// if not blank, run jarjar using the specified rules file
- Jarjar_rules *string
+ Jarjar_rules *string `android:"arch_variant"`
// If not blank, set the java version passed to javac as -source and -target
Java_version *string
@@ -117,6 +116,14 @@
// List of classes to pass to javac to use as annotation processors
Annotation_processor_classes []string
+
+ Openjdk9 struct {
+ // List of source files that should only be used when passing -source 1.9
+ Srcs []string
+
+ // List of javac flags that should only be used when passing -source 1.9
+ Javacflags []string
+ }
}
type CompilerDeviceProperties struct {
@@ -126,16 +133,18 @@
// if not blank, set to the version of the sdk to compile against
Sdk_version string
- // Set for device java libraries, and for host versions of device java libraries
- // built for testing
- Dex bool `blueprint:"mutated"`
-
// directories to pass to aidl tool
Aidl_includes []string
// directories that should be added as include directories
// for any aidl sources of modules that depend on this module
Export_aidl_include_dirs []string
+
+ // If true, export a copy of the module as a -hostdex module for host testing.
+ Hostdex *bool
+
+ // When targeting 1.9, override the modules to use with --system
+ System_modules *string
}
// Module contains the properties and members used by all java module types
@@ -160,9 +169,9 @@
logtagsSrcs android.Paths
- // filelists of extra source files that should be included in the javac command line,
+ // jars containing source files that should be included in the javac command line,
// for example R.java generated by aapt for android apps
- ExtraSrcLists android.Paths
+ ExtraSrcJars android.Paths
// installed file for binary dependency
installFile android.Path
@@ -187,26 +196,40 @@
staticLibTag = dependencyTag{name: "staticlib"}
libTag = dependencyTag{name: "javalib"}
bootClasspathTag = dependencyTag{name: "bootclasspath"}
+ systemModulesTag = dependencyTag{name: "system modules"}
frameworkResTag = dependencyTag{name: "framework-res"}
+ kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
)
type sdkDep struct {
useModule, useFiles, useDefaultLibs, invalidVersion bool
- module string
- jar android.Path
- aidl android.Path
+ module string
+ systemModules string
+
+ jar android.Path
+ aidl android.Path
+}
+
+func sdkStringToNumber(ctx android.BaseContext, v string) int {
+ switch v {
+ case "", "current", "system_current", "test_current":
+ return 10000
+ default:
+ if i, err := strconv.Atoi(v); err != nil {
+ ctx.PropertyErrorf("sdk_version", "invalid sdk version")
+ return -1
+ } else {
+ return i
+ }
+ }
}
func decodeSdkDep(ctx android.BaseContext, v string) sdkDep {
- switch v {
- case "", "current", "system_current", "test_current":
- // OK
- default:
- if _, err := strconv.Atoi(v); err != nil {
- ctx.PropertyErrorf("sdk_version", "invalid sdk version")
- return sdkDep{}
- }
+ i := sdkStringToNumber(ctx, v)
+ if i == -1 {
+ // Invalid sdk version, error handled by sdkStringToNumber.
+ return sdkDep{}
}
toFile := func(v string) sdkDep {
@@ -242,8 +265,9 @@
toModule := func(m string) sdkDep {
return sdkDep{
- useModule: true,
- module: m,
+ useModule: true,
+ module: m,
+ systemModules: m + "_system_modules",
}
}
@@ -268,22 +292,31 @@
}
func (j *Module) deps(ctx android.BottomUpMutatorContext) {
- if !proptools.Bool(j.properties.No_standard_libs) {
- if ctx.Device() {
+ if ctx.Device() {
+ if !proptools.Bool(j.properties.No_standard_libs) {
sdkDep := decodeSdkDep(ctx, j.deviceProperties.Sdk_version)
if sdkDep.useDefaultLibs {
ctx.AddDependency(ctx.Module(), bootClasspathTag, config.DefaultBootclasspathLibraries...)
+ if ctx.AConfig().TargetOpenJDK9() {
+ ctx.AddDependency(ctx.Module(), systemModulesTag, config.DefaultSystemModules)
+ }
if !proptools.Bool(j.properties.No_framework_libs) {
ctx.AddDependency(ctx.Module(), libTag, config.DefaultLibraries...)
}
- }
- if sdkDep.useModule {
+ } else if sdkDep.useModule {
+ if ctx.AConfig().TargetOpenJDK9() {
+ ctx.AddDependency(ctx.Module(), systemModulesTag, sdkDep.systemModules)
+ }
ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.module)
}
- } else {
- // TODO(ccross): add hostdex support
+ } else if j.deviceProperties.System_modules == nil {
+ ctx.PropertyErrorf("no_standard_libs",
+ "system_modules is required to be set when no_standard_libs is true, did you mean no_framework_libs?")
+ } else if *j.deviceProperties.System_modules != "none" && ctx.AConfig().TargetOpenJDK9() {
+ ctx.AddDependency(ctx.Module(), systemModulesTag, *j.deviceProperties.System_modules)
}
}
+
ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
ctx.AddDependency(ctx.Module(), staticLibTag, j.properties.Static_libs...)
ctx.AddDependency(ctx.Module(), libTag, j.properties.Annotation_processors...)
@@ -294,6 +327,12 @@
if j.hasSrcExt(".proto") {
protoDeps(ctx, &j.protoProperties)
}
+
+ if j.hasSrcExt(".kt") {
+ // TODO(ccross): move this to a mutator pass that can tell if generated sources contain
+ // Kotlin files
+ ctx.AddDependency(ctx.Module(), kotlinStdlibTag, "kotlin-stdlib")
+ }
}
func hasSrcExt(srcs []string, ext string) bool {
@@ -338,8 +377,10 @@
staticJars android.Paths
staticJarResources android.Paths
aidlIncludeDirs android.Paths
- srcFileLists android.Paths
+ srcJars android.Paths
+ systemModules android.Path
aidlPreprocess android.OptionalPath
+ kotlinStdlib android.Paths
}
func (j *Module) collectDeps(ctx android.ModuleContext) deps {
@@ -362,6 +403,15 @@
switch tag {
case android.DefaultsDepTag, android.SourceDepTag:
// Nothing to do
+ case systemModulesTag:
+ if deps.systemModules != nil {
+ panic("Found two system module dependencies")
+ }
+ sm := module.(*SystemModules)
+ if sm.outputFile == nil {
+ panic("Missing directory for system module dependency")
+ }
+ deps.systemModules = sm.outputFile
default:
ctx.ModuleErrorf("depends on non-java module %q", otherName)
}
@@ -380,8 +430,10 @@
if ctx.ModuleName() == "framework" {
// framework.jar has a one-off dependency on the R.java and Manifest.java files
// generated by framework-res.apk
- deps.srcFileLists = append(deps.srcFileLists, module.(*AndroidApp).aaptJavaFileList)
+ // TODO(ccross): aapt java files should go in a src jar
}
+ case kotlinStdlibTag:
+ deps.kotlinStdlib = dep.ClasspathFiles()
default:
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
}
@@ -401,19 +453,29 @@
var flags javaBuilderFlags
javacFlags := j.properties.Javacflags
- if ctx.AConfig().Getenv("EXPERIMENTAL_USE_OPENJDK9") == "" {
- javacFlags = config.StripJavac9Flags(javacFlags)
+ if ctx.AConfig().TargetOpenJDK9() {
+ javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
+ j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...)
}
+ sdk := sdkStringToNumber(ctx, j.deviceProperties.Sdk_version)
if j.properties.Java_version != nil {
flags.javaVersion = *j.properties.Java_version
+ } else if ctx.Device() && sdk <= 23 {
+ flags.javaVersion = "1.7"
+ } else if ctx.Device() && sdk <= 26 || !ctx.AConfig().TargetOpenJDK9() {
+ flags.javaVersion = "1.8"
} else {
- flags.javaVersion = "${config.DefaultJavaVersion}"
+ flags.javaVersion = "1.9"
}
flags.bootClasspath.AddPaths(deps.bootClasspath)
flags.classpath.AddPaths(deps.classpath)
+ if deps.systemModules != nil {
+ flags.systemModules = append(flags.systemModules, deps.systemModules)
+ }
+
if len(javacFlags) > 0 {
ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
flags.javacFlags = "$javacFlags"
@@ -431,23 +493,42 @@
flags = protoFlags(ctx, &j.protoProperties, flags)
}
- var srcFileLists android.Paths
+ var srcJars classpath
+ srcFiles, srcJars = j.genSources(ctx, srcFiles, flags)
- srcFiles, srcFileLists = j.genSources(ctx, srcFiles, flags)
+ srcJars = append(srcJars, deps.srcJars...)
- srcFileLists = append(srcFileLists, deps.srcFileLists...)
-
- ctx.VisitDirectDeps(func(module blueprint.Module) {
- if gen, ok := module.(genrule.SourceFileGenerator); ok {
- srcFiles = append(srcFiles, gen.GeneratedSourceFiles()...)
- }
- })
-
- srcFileLists = append(srcFileLists, j.ExtraSrcLists...)
+ srcJars = append(srcJars, j.ExtraSrcJars...)
var jars android.Paths
- if len(srcFiles) > 0 {
+ if srcFiles.HasExt(".kt") {
+ // If there are kotlin files, compile them first but pass all the kotlin and java files
+ // kotlinc will use the java files to resolve types referenced by the kotlin files, but
+ // won't emit any classes for them.
+
+ flags.kotlincFlags = "-no-stdlib"
+ if ctx.Device() {
+ flags.kotlincFlags += " -no-jdk"
+ }
+
+ flags.kotlincClasspath = append(flags.kotlincClasspath, deps.kotlinStdlib...)
+ flags.kotlincClasspath = append(flags.kotlincClasspath, deps.classpath...)
+
+ kotlinJar := android.PathForModuleOut(ctx, "classes-kt.jar")
+ TransformKotlinToClasses(ctx, kotlinJar, srcFiles, srcJars, flags)
+ if ctx.Failed() {
+ return
+ }
+
+ // Make javac rule depend on the kotlinc rule
+ flags.classpath = append(flags.classpath, kotlinJar)
+ // Jar kotlin classes into the final jar after javac
+ jars = append(jars, kotlinJar)
+ jars = append(jars, deps.kotlinStdlib...)
+ }
+
+ if javaSrcFiles := srcFiles.FilterByExt(".java"); len(javaSrcFiles) > 0 {
var extraJarDeps android.Paths
if ctx.AConfig().IsEnvTrue("RUN_ERROR_PRONE") {
// If error-prone is enabled, add an additional rule to compile the java files into
@@ -455,12 +536,14 @@
// a rebuild when error-prone is turned off).
// TODO(ccross): Once we always compile with javac9 we may be able to conditionally
// enable error-prone without affecting the output class files.
- errorprone := RunErrorProne(ctx, srcFiles, srcFileLists, flags)
+ errorprone := android.PathForModuleOut(ctx, "classes-errorprone.list")
+ RunErrorProne(ctx, errorprone, javaSrcFiles, srcJars, flags)
extraJarDeps = append(extraJarDeps, errorprone)
}
// Compile java sources into .class files
- classes := TransformJavaToClasses(ctx, srcFiles, srcFileLists, flags, extraJarDeps)
+ classes := android.PathForModuleOut(ctx, "classes-compiled.jar")
+ TransformJavaToClasses(ctx, classes, javaSrcFiles, srcJars, flags, extraJarDeps)
if ctx.Failed() {
return
}
@@ -481,13 +564,14 @@
resDeps = append(resDeps, fileDeps...)
if proptools.Bool(j.properties.Include_srcs) {
- srcArgs, srcDeps := ResourceFilesToJarArgs(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+ srcArgs, srcDeps := SourceFilesToJarArgs(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
resArgs = append(resArgs, srcArgs...)
resDeps = append(resDeps, srcDeps...)
}
if len(resArgs) > 0 {
- resourceJar := TransformResourcesToJar(ctx, resArgs, resDeps)
+ resourceJar := android.PathForModuleOut(ctx, "res.jar")
+ TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps)
if ctx.Failed() {
return
}
@@ -502,12 +586,23 @@
// Combine the classes built from sources, any manifests, and any static libraries into
// classes.jar. If there is only one input jar this step will be skipped.
- outputFile := TransformJarsToJar(ctx, "classes.jar", jars, manifest, false)
+ var outputFile android.Path
+
+ if len(jars) == 1 && !manifest.Valid() {
+ // Optimization: skip the combine step if there is nothing to do
+ outputFile = jars[0]
+ } else {
+ combinedJar := android.PathForModuleOut(ctx, "classes.jar")
+ TransformJarsToJar(ctx, combinedJar, jars, manifest, false)
+ outputFile = combinedJar
+ }
if j.properties.Jarjar_rules != nil {
jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
// Transform classes.jar into classes-jarjar.jar
- outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
+ jarjarFile := android.PathForModuleOut(ctx, "classes-jarjar.jar")
+ TransformJarJar(ctx, jarjarFile, outputFile, jarjar_rules)
+ outputFile = jarjarFile
if ctx.Failed() {
return
}
@@ -515,7 +610,6 @@
j.classpathFile = outputFile
- // TODO(ccross): handle hostdex
if ctx.Device() && j.installable() {
dxFlags := j.deviceProperties.Dxflags
if false /* emma enabled */ {
@@ -564,13 +658,17 @@
flags.desugarFlags = strings.Join(desugarFlags, " ")
- desugarJar := TransformDesugar(ctx, outputFile, flags)
+ desugarJar := android.PathForModuleOut(ctx, "classes-desugar.jar")
+ TransformDesugar(ctx, desugarJar, outputFile, flags)
+ outputFile = desugarJar
if ctx.Failed() {
return
}
// Compile classes.jar into classes.dex and then javalib.jar
- outputFile = TransformClassesJarToDexJar(ctx, "javalib.jar", desugarJar, flags)
+ javalibJar := android.PathForModuleOut(ctx, "javalib.jar")
+ TransformClassesJarToDexJar(ctx, javalibJar, desugarJar, flags)
+ outputFile = javalibJar
if ctx.Failed() {
return
}
@@ -629,7 +727,6 @@
if !installable {
module.properties.Installable = proptools.BoolPtr(false)
}
- module.deviceProperties.Dex = true
module.AddProperties(
&module.Module.properties,
@@ -687,8 +784,6 @@
func BinaryFactory() android.Module {
module := &Binary{}
- module.deviceProperties.Dex = true
-
module.AddProperties(
&module.Module.properties,
&module.Module.deviceProperties,
@@ -748,7 +843,9 @@
func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.classpathFiles = android.PathsForModuleSrc(ctx, j.properties.Jars)
- j.combinedClasspathFile = TransformJarsToJar(ctx, "classes.jar", j.classpathFiles, android.OptionalPath{}, false)
+ outputFile := android.PathForModuleOut(ctx, "classes.jar")
+ TransformJarsToJar(ctx, outputFile, j.classpathFiles, android.OptionalPath{}, false)
+ j.combinedClasspathFile = outputFile
}
var _ Dependency = (*Import)(nil)
diff --git a/java/java_test.go b/java/java_test.go
index a4a3f52..d64688f 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -50,9 +50,12 @@
os.Exit(run())
}
-
func testJava(t *testing.T, bp string) *android.TestContext {
- config := android.TestArchConfig(buildDir)
+ return testJavaWithEnv(t, bp, nil)
+}
+
+func testJavaWithEnv(t *testing.T, bp string, env map[string]string) *android.TestContext {
+ config := android.TestArchConfig(buildDir, env)
ctx := android.NewTestArchContext()
ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory))
@@ -60,7 +63,9 @@
ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory))
ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory))
ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
+ ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(SystemModulesFactory))
ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
+ ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(genrule.GenRuleFactory))
ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
@@ -75,6 +80,7 @@
"android_stubs_current",
"android_system_stubs_current",
"android_test_stubs_current",
+ "kotlin-stdlib",
}
for _, extra := range extraModules {
@@ -83,15 +89,34 @@
name: "%s",
srcs: ["a.java"],
no_standard_libs: true,
+ system_modules: "core-system-modules",
}
`, extra)
}
+ if config.TargetOpenJDK9() {
+ systemModules := []string{
+ "core-system-modules",
+ "android_stubs_current_system_modules",
+ "android_system_stubs_current_system_modules",
+ "android_test_stubs_current_system_modules",
+ }
+
+ for _, extra := range systemModules {
+ bp += fmt.Sprintf(`
+ java_system_modules {
+ name: "%s",
+ }
+ `, extra)
+ }
+ }
+
ctx.MockFileSystem(map[string][]byte{
"Android.bp": []byte(bp),
"a.java": nil,
"b.java": nil,
"c.java": nil,
+ "b.kt": nil,
"a.jar": nil,
"b.jar": nil,
"res/a": nil,
@@ -189,17 +214,20 @@
host android.OsClass
properties string
bootclasspath []string
+ system string
classpath []string
}{
{
name: "default",
bootclasspath: []string{"core-oj", "core-libart"},
+ system: "core-system-modules",
classpath: []string{"ext", "framework", "okhttp"},
},
{
name: "blank sdk version",
properties: `sdk_version: "",`,
bootclasspath: []string{"core-oj", "core-libart"},
+ system: "core-system-modules",
classpath: []string{"ext", "framework", "okhttp"},
},
{
@@ -207,6 +235,7 @@
name: "sdk v14",
properties: `sdk_version: "14",`,
bootclasspath: []string{`""`},
+ system: "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
classpath: []string{"prebuilts/sdk/14/android.jar"},
},
{
@@ -214,6 +243,7 @@
name: "current",
properties: `sdk_version: "current",`,
bootclasspath: []string{"android_stubs_current"},
+ system: "android_stubs_current_system_modules",
classpath: []string{},
},
{
@@ -221,6 +251,7 @@
name: "system_current",
properties: `sdk_version: "system_current",`,
bootclasspath: []string{"android_system_stubs_current"},
+ system: "android_system_stubs_current_system_modules",
classpath: []string{},
},
{
@@ -228,12 +259,22 @@
name: "test_current",
properties: `sdk_version: "test_current",`,
bootclasspath: []string{"android_test_stubs_current"},
+ system: "android_test_stubs_current_system_modules",
classpath: []string{},
},
{
name: "nostdlib",
- properties: `no_standard_libs: true`,
+ properties: `no_standard_libs: true, system_modules: "none"`,
+ system: "none",
+ bootclasspath: []string{`""`},
+ classpath: []string{},
+ },
+ {
+
+ name: "nostdlib system_modules",
+ properties: `no_standard_libs: true, system_modules: "core-system-modules"`,
+ system: "core-system-modules",
bootclasspath: []string{`""`},
classpath: []string{},
},
@@ -262,7 +303,7 @@
{
name: "host supported nostdlib",
host: android.Host,
- properties: `host_supported: true, no_standard_libs: true`,
+ properties: `host_supported: true, no_standard_libs: true, system_modules: "none"`,
classpath: []string{},
},
}
@@ -274,12 +315,17 @@
if testcase.moduleType != "" {
moduleType = testcase.moduleType
}
- ctx := testJava(t, moduleType+` {
+
+ bp := moduleType + ` {
name: "foo",
srcs: ["a.java"],
- `+testcase.properties+`
+ ` + testcase.properties + `
+ }`
+
+ variant := "android_common"
+ if testcase.host == android.Host {
+ variant = android.BuildOs.String() + "_common"
}
- `)
convertModulesToPaths := func(cp []string) []string {
ret := make([]string, len(cp))
@@ -292,33 +338,63 @@
bootclasspath := convertModulesToPaths(testcase.bootclasspath)
classpath := convertModulesToPaths(testcase.classpath)
- variant := "android_common"
- if testcase.host == android.Host {
- variant = android.BuildOs.String() + "_common"
- }
- javac := ctx.ModuleForTests("foo", variant).Rule("javac")
-
- got := strings.TrimPrefix(javac.Args["bootClasspath"], "-bootclasspath ")
bc := strings.Join(bootclasspath, ":")
- if got != bc {
- t.Errorf("bootclasspath expected %q != got %q", bc, got)
+ if bc != "" {
+ bc = "-bootclasspath " + bc
}
- got = strings.TrimPrefix(javac.Args["classpath"], "-classpath ")
c := strings.Join(classpath, ":")
- if got != c {
- t.Errorf("classpath expected %q != got %q", c, got)
+ if c != "" {
+ c = "-classpath " + c
+ }
+ system := ""
+ if testcase.system == "none" {
+ system = "--system=none"
+ } else if testcase.system != "" {
+ system = "--system=" + filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system") + "/"
}
- var deps []string
- if len(bootclasspath) > 0 && bootclasspath[0] != `""` {
- deps = append(deps, bootclasspath...)
- }
- deps = append(deps, classpath...)
+ t.Run("1.8", func(t *testing.T) {
+ // Test default javac 1.8
+ ctx := testJava(t, bp)
- if !reflect.DeepEqual(javac.Implicits.Strings(), deps) {
- t.Errorf("implicits expected %q != got %q", deps, javac.Implicits.Strings())
- }
+ javac := ctx.ModuleForTests("foo", variant).Rule("javac")
+
+ got := javac.Args["bootClasspath"]
+ if got != bc {
+ t.Errorf("bootclasspath expected %q != got %q", bc, got)
+ }
+
+ got = javac.Args["classpath"]
+ if got != c {
+ t.Errorf("classpath expected %q != got %q", c, got)
+ }
+
+ var deps []string
+ if len(bootclasspath) > 0 && bootclasspath[0] != `""` {
+ deps = append(deps, bootclasspath...)
+ }
+ deps = append(deps, classpath...)
+
+ if !reflect.DeepEqual(javac.Implicits.Strings(), deps) {
+ t.Errorf("implicits expected %q != got %q", deps, javac.Implicits.Strings())
+ }
+ })
+
+ // Test again with javac 1.9
+ t.Run("1.9", func(t *testing.T) {
+ ctx := testJavaWithEnv(t, bp, map[string]string{"EXPERIMENTAL_USE_OPENJDK9": "true"})
+
+ javac := ctx.ModuleForTests("foo", variant).Rule("javac")
+ got := javac.Args["bootClasspath"]
+ expected := system
+ if testcase.system == "bootclasspath" {
+ expected = bc
+ }
+ if got != expected {
+ t.Errorf("bootclasspath expected %q != got %q", expected, got)
+ }
+ })
})
}
@@ -408,16 +484,16 @@
args string
}{
{
- // Test that a module with java_resource_dirs includes a file list file
+ // Test that a module with java_resource_dirs includes the files
name: "resource dirs",
prop: `java_resource_dirs: ["res"]`,
- args: "-C res -l ",
+ args: "-C res -f res/a -f res/b",
},
{
// Test that a module with java_resources includes the files
name: "resource files",
prop: `java_resources: ["res/a", "res/b"]`,
- args: "-C . -f res/a -C . -f res/b",
+ args: "-C . -f res/a -f res/b",
},
{
// Test that a module with a filegroup in java_resources includes the files with the
@@ -430,13 +506,13 @@
path: "res",
srcs: ["res/a", "res/b"],
}`,
- args: "-C res -f res/a -C res -f res/b",
+ args: "-C res -f res/a -f res/b",
},
{
// Test that a module with "include_srcs: true" includes its source files in the resources jar
name: "include sources",
prop: `include_srcs: true`,
- args: "-C . -f a.java -C . -f b.java -C . -f c.java",
+ args: "-C . -f a.java -f b.java -f c.java",
},
}
@@ -462,8 +538,8 @@
foo.Inputs.Strings(), fooRes.Output.String())
}
- if !strings.Contains(fooRes.Args["jarArgs"], test.args) {
- t.Errorf("foo resource jar args %q does not contain %q",
+ if fooRes.Args["jarArgs"] != test.args {
+ t.Errorf("foo resource jar args %q is not %q",
fooRes.Args["jarArgs"], test.args)
}
})
@@ -489,7 +565,7 @@
fooRes := ctx.ModuleForTests("foo", "android_common").Output("res.jar")
- expected := "-C res -l " + fooRes.Implicits[0].String()
+ expected := "-C res -f res/a -f res/b"
if fooRes.Args["jarArgs"] != expected {
t.Errorf("foo resource jar args %q is not %q",
fooRes.Args["jarArgs"], expected)
@@ -506,6 +582,71 @@
}
}
+func TestGeneratedSources(t *testing.T) {
+ ctx := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a*.java",
+ ":gen",
+ "b*.java",
+ ],
+ }
+
+ genrule {
+ name: "gen",
+ tool_files: ["res/a"],
+ out: ["gen.java"],
+ }
+ `)
+
+ javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+ genrule := ctx.ModuleForTests("gen", "").Rule("generator")
+
+ if len(genrule.Outputs) != 1 || filepath.Base(genrule.Outputs[0].String()) != "gen.java" {
+ t.Fatalf(`gen output file %v is not [".../gen.java"]`, genrule.Outputs.Strings())
+ }
+
+ if len(javac.Inputs) != 3 ||
+ javac.Inputs[0].String() != "a.java" ||
+ javac.Inputs[1].String() != genrule.Outputs[0].String() ||
+ javac.Inputs[2].String() != "b.java" {
+ t.Errorf(`foo inputs %v != ["a.java", ".../gen.java", "b.java"]`, javac.Inputs)
+ }
+}
+
+func TestKotlin(t *testing.T) {
+ ctx := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java", "b.kt"],
+ }
+ `)
+
+ kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
+ javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+ jar := ctx.ModuleForTests("foo", "android_common").Output("classes.jar")
+
+ if len(kotlinc.Inputs) != 2 || kotlinc.Inputs[0].String() != "a.java" ||
+ kotlinc.Inputs[1].String() != "b.kt" {
+ t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, kotlinc.Inputs)
+ }
+
+ if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
+ t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
+ }
+
+ if !strings.Contains(javac.Args["classpath"], kotlinc.Output.String()) {
+ t.Errorf("foo classpath %v does not contain %q",
+ javac.Args["classpath"], kotlinc.Output.String())
+ }
+
+ if !inList(kotlinc.Output.String(), jar.Inputs.Strings()) {
+ t.Errorf("foo jar inputs %v does not contain %q",
+ jar.Inputs.Strings(), kotlinc.Output.String())
+ }
+}
+
func fail(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
diff --git a/java/proto.go b/java/proto.go
index dd8cabd..fc259a5 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -30,20 +30,21 @@
blueprint.RuleParams{
Command: `rm -rf $outDir && mkdir -p $outDir && ` +
`$protocCmd $protoOut=$protoOutFlags:$outDir $protoFlags $in && ` +
- `find $outDir -name "*.java" > $out`,
- CommandDeps: []string{"$protocCmd"},
+ `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
+ CommandDeps: []string{
+ "$protocCmd",
+ "${config.SoongZipCmd}",
+ },
}, "protoFlags", "protoOut", "protoOutFlags", "outDir")
)
-func genProto(ctx android.ModuleContext, protoFiles android.Paths,
- protoFlags string, protoOut, protoOutFlags string) android.WritablePath {
-
- protoFileList := android.PathForModuleGen(ctx, "proto.filelist")
+func genProto(ctx android.ModuleContext, outputSrcJar android.WritablePath,
+ protoFiles android.Paths, protoFlags string, protoOut, protoOutFlags string) {
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Rule: proto,
Description: "protoc " + protoFiles[0].Rel(),
- Output: protoFileList,
+ Output: outputSrcJar,
Inputs: protoFiles,
Args: map[string]string{
"outDir": android.ProtoDir(ctx).String(),
@@ -52,8 +53,6 @@
"protoFlags": protoFlags,
},
})
-
- return protoFileList
}
func protoDeps(ctx android.BottomUpMutatorContext, p *android.ProtoProperties) {
diff --git a/java/resources.go b/java/resources.go
index 85ebd52..a596fd7 100644
--- a/java/resources.go
+++ b/java/resources.go
@@ -19,8 +19,6 @@
"path/filepath"
"strings"
- "github.com/google/blueprint/bootstrap"
-
"android/soong/android"
)
@@ -33,15 +31,6 @@
"**/*~",
}
-func isStringInSlice(str string, slice []string) bool {
- for _, s := range slice {
- if s == str {
- return true
- }
- }
- return false
-}
-
func ResourceDirsToJarArgs(ctx android.ModuleContext,
resourceDirs, excludeDirs []string) (args []string, deps android.Paths) {
var excludes []string
@@ -53,40 +42,64 @@
excludes = append(excludes, resourceExcludes...)
- for _, resourceDir := range resourceDirs {
- if isStringInSlice(resourceDir, excludeDirs) {
- continue
- }
- resourceDir := android.PathForModuleSrc(ctx, resourceDir)
- dirs := ctx.Glob(resourceDir.String(), nil)
- for _, dir := range dirs {
- fileListFile := android.ResPathWithName(ctx, dir, "resources.list")
- depFile := fileListFile.String() + ".d"
+ for _, dir := range resourceDirs {
+ dir := android.PathForModuleSrc(ctx, dir).String()
+ files := ctx.Glob(filepath.Join(dir, "**/*"), excludes)
- pattern := filepath.Join(dir.String(), "**/*")
- bootstrap.GlobFile(ctx, pattern, excludes, fileListFile.String(), depFile)
- args = append(args,
- "-C", dir.String(),
- "-l", fileListFile.String())
- deps = append(deps, fileListFile)
+ deps = append(deps, files...)
+
+ if len(files) > 0 {
+ args = append(args, "-C", dir)
+
+ for _, f := range files {
+ path := f.String()
+ if !strings.HasPrefix(path, dir) {
+ panic(fmt.Errorf("path %q does not start with %q", path, dir))
+ }
+ args = append(args, "-f", path)
+ }
}
}
return args, deps
}
+// Convert java_resources properties to arguments to soong_zip -jar, ignoring common patterns
+// that should not be treated as resources (including *.java).
func ResourceFilesToJarArgs(ctx android.ModuleContext,
res, exclude []string) (args []string, deps android.Paths) {
+
+ exclude = append([]string(nil), exclude...)
+ exclude = append(exclude, resourceExcludes...)
+ return resourceFilesToJarArgs(ctx, res, exclude)
+}
+
+// Convert java_resources properties to arguments to soong_zip -jar, keeping files that should
+// normally not used as resources like *.java
+func SourceFilesToJarArgs(ctx android.ModuleContext,
+ res, exclude []string) (args []string, deps android.Paths) {
+
+ return resourceFilesToJarArgs(ctx, res, exclude)
+}
+
+func resourceFilesToJarArgs(ctx android.ModuleContext,
+ res, exclude []string) (args []string, deps android.Paths) {
+
files := ctx.ExpandSources(res, exclude)
- for _, f := range files {
+ lastDir := ""
+ for i, f := range files {
rel := f.Rel()
path := f.String()
if !strings.HasSuffix(path, rel) {
panic(fmt.Errorf("path %q does not end with %q", path, rel))
}
- path = filepath.Clean(strings.TrimSuffix(path, rel))
- args = append(args, "-C", filepath.Clean(path), "-f", f.String())
+ dir := filepath.Clean(strings.TrimSuffix(path, rel))
+ if i == 0 || dir != lastDir {
+ args = append(args, "-C", dir)
+ }
+ args = append(args, "-f", path)
+ lastDir = dir
}
return args, files
diff --git a/java/system_modules.go b/java/system_modules.go
new file mode 100644
index 0000000..ddfc5cf
--- /dev/null
+++ b/java/system_modules.go
@@ -0,0 +1,144 @@
+// Copyright 2017 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 java
+
+import (
+ "fmt"
+ "io"
+ "strings"
+
+ "github.com/google/blueprint"
+
+ "android/soong/android"
+)
+
+// OpenJDK 9 introduces the concept of "system modules", which replace the bootclasspath. This
+// file will produce the rules necessary to convert each unique set of bootclasspath jars into
+// system modules in a runtime image using the jmod and jlink tools.
+
+func init() {
+ android.RegisterModuleType("java_system_modules", SystemModulesFactory)
+
+ pctx.SourcePathVariable("moduleInfoJavaPath", "build/soong/scripts/jars-to-module-info-java.sh")
+}
+
+var (
+ jarsTosystemModules = pctx.AndroidStaticRule("jarsTosystemModules", blueprint.RuleParams{
+ Command: `rm -rf ${outDir} ${workDir} && mkdir -p ${workDir}/jmod && ` +
+ `${moduleInfoJavaPath} ${moduleName} $in > ${workDir}/module-info.java && ` +
+ `${config.JavacCmd} --system=none --patch-module=java.base=${classpath} ${workDir}/module-info.java && ` +
+ `${config.SoongZipCmd} -jar -o ${workDir}/classes.jar -C ${workDir} -f ${workDir}/module-info.class && ` +
+ `${config.MergeZipsCmd} -j ${workDir}/module.jar ${workDir}/classes.jar $in && ` +
+ `${config.JmodCmd} create --module-version 9 --target-platform android ` +
+ ` --class-path ${workDir}/module.jar ${workDir}/jmod/${moduleName}.jmod && ` +
+ `${config.JlinkCmd} --module-path ${workDir}/jmod --add-modules ${moduleName} --output ${outDir} && ` +
+ `cp ${config.JrtFsJar} ${outDir}/lib/`,
+ CommandDeps: []string{
+ "${moduleInfoJavaPath}",
+ "${config.JavacCmd}",
+ "${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
+ "${config.JmodCmd}",
+ "${config.JlinkCmd}",
+ "${config.JrtFsJar}",
+ },
+ },
+ "moduleName", "classpath", "outDir", "workDir")
+)
+
+func TransformJarsToSystemModules(ctx android.ModuleContext, moduleName string, jars android.Paths) android.WritablePath {
+ outDir := android.PathForModuleOut(ctx, "system")
+ workDir := android.PathForModuleOut(ctx, "modules")
+ outputFile := android.PathForModuleOut(ctx, "system/lib/modules")
+ outputs := android.WritablePaths{
+ outputFile,
+ android.PathForModuleOut(ctx, "system/lib/jrt-fs.jar"),
+ android.PathForModuleOut(ctx, "system/release"),
+ }
+
+ ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+ Rule: jarsTosystemModules,
+ Description: "system modules",
+ Outputs: outputs,
+ Inputs: jars,
+ Args: map[string]string{
+ "moduleName": moduleName,
+ "classpath": strings.Join(jars.Strings(), ":"),
+ "workDir": workDir.String(),
+ "outDir": outDir.String(),
+ },
+ })
+
+ return outputFile
+}
+
+func SystemModulesFactory() android.Module {
+ module := &SystemModules{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
+ return module
+}
+
+type SystemModules struct {
+ android.ModuleBase
+
+ properties SystemModulesProperties
+
+ outputFile android.Path
+}
+
+type SystemModulesProperties struct {
+ // List of java library modules that should be included in the system modules
+ Libs []string
+
+ // List of prebuilt jars that should be included in the system modules
+ Jars []string
+
+ // Sdk version that should be included in the system modules
+ Sdk_version *string
+}
+
+func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var jars android.Paths
+
+ ctx.VisitDirectDeps(func(module blueprint.Module) {
+ if ctx.OtherModuleDependencyTag(module) == libTag {
+ dep, _ := module.(Dependency)
+ jars = append(jars, dep.ClasspathFiles()...)
+ }
+ })
+
+ jars = append(jars, android.PathsForModuleSrc(ctx, system.properties.Jars)...)
+
+ if ctx.AConfig().TargetOpenJDK9() {
+ system.outputFile = TransformJarsToSystemModules(ctx, "java.base", jars)
+ }
+}
+
+func (system *SystemModules) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), libTag, system.properties.Libs...)
+}
+
+func (system *SystemModules) AndroidMk() android.AndroidMkData {
+ return android.AndroidMkData{
+ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ if system.outputFile != nil {
+ makevar := "SOONG_SYSTEM_MODULES_" + name
+ fmt.Fprintln(w)
+ fmt.Fprintln(w, makevar, ":=", system.outputFile.String())
+ fmt.Fprintln(w, ".KATI_READONLY", ":=", makevar)
+ }
+ },
+ }
+}
diff --git a/python/python_test.go b/python/python_test.go
index 8737302..176c6ec 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -450,7 +450,7 @@
t.Fatal(err)
}
- config = android.TestConfig(buildDir)
+ config = android.TestConfig(buildDir, nil)
return
}
diff --git a/scripts/jars-to-module-info-java.sh b/scripts/jars-to-module-info-java.sh
new file mode 100755
index 0000000..44be549
--- /dev/null
+++ b/scripts/jars-to-module-info-java.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -e
+
+# Extracts the Java package names of all classes in the .jar files and writes a module-info.java
+# file to stdout that exports all of those packages.
+
+if [ -z "$1" ]; then
+ echo "usage: $0 <module name> <jar1> [<jar2> ...]" >&2
+ exit 1
+fi
+
+module_name=$1
+shift
+
+echo "module ${module_name} {"
+for j in "$@"; do zipinfo -1 $j ; done \
+ | grep -E '/[^/]*\.class$' \
+ | sed 's|\(.*\)/[^/]*\.class$| exports \1;|g' \
+ | sed 's|/|.|g' \
+ | sort -u
+echo "}"
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 34c21f7..d1b4943 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -27,11 +27,11 @@
"cleanbuild.go",
"config.go",
"context.go",
+ "dumpvars.go",
"environment.go",
"exec.go",
"finder.go",
"kati.go",
- "make.go",
"ninja.go",
"proc_sync.go",
"signal.go",
diff --git a/ui/build/build.go b/ui/build/build.go
index 45d18e0..0df22b3 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -104,7 +104,7 @@
func help(ctx Context, config Config, what int) {
cmd := Command(ctx, config, "help.sh", "build/make/help.sh")
- cmd.Sandbox = makeSandbox
+ cmd.Sandbox = dumpvarsSandbox
cmd.Stdout = ctx.Stdout()
cmd.Stderr = ctx.Stderr()
cmd.RunOrFatal()
diff --git a/ui/build/config.go b/ui/build/config.go
index 2b0da4d..191a102 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -154,7 +154,7 @@
c.verbose = true
} else if arg == "--skip-make" {
c.skipMake = true
- } else if arg[0] == '-' {
+ } else if len(arg) > 0 && arg[0] == '-' {
parseArgNum := func(def int) int {
if len(arg) > 2 {
p, err := strconv.ParseUint(arg[2:], 10, 31)
@@ -172,9 +172,9 @@
return def
}
- if arg[1] == 'j' {
+ if len(arg) > 1 && arg[1] == 'j' {
c.parallel = parseArgNum(c.parallel)
- } else if arg[1] == 'k' {
+ } else if len(arg) > 1 && arg[1] == 'k' {
c.keepGoing = parseArgNum(0)
} else {
ctx.Fatalln("Unknown option:", arg)
@@ -437,21 +437,13 @@
}
}
-func (c *configImpl) HostAsan() bool {
+func (c *configImpl) PrebuiltBuildTool(name string) string {
if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
if sanitize := strings.Fields(v); inList("address", sanitize) {
- return true
- }
- }
- return false
-}
-
-func (c *configImpl) PrebuiltBuildTool(name string) string {
- // (b/36182021) We're seeing rare ckati crashes, so always enable asan kati on the build servers.
- if c.HostAsan() || (c.Dist() && name == "ckati") {
- asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
- if _, err := os.Stat(asan); err == nil {
- return asan
+ asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
+ if _, err := os.Stat(asan); err == nil {
+ return asan
+ }
}
}
return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
diff --git a/ui/build/make.go b/ui/build/dumpvars.go
similarity index 62%
rename from ui/build/make.go
rename to ui/build/dumpvars.go
index edf6d96..fb20d63 100644
--- a/ui/build/make.go
+++ b/ui/build/dumpvars.go
@@ -15,8 +15,8 @@
package build
import (
+ "bytes"
"fmt"
- "path/filepath"
"strings"
)
@@ -28,27 +28,29 @@
// Make without actually building them. So all the variables based on
// MAKECMDGOALS can be read.
//
-// extra_targets adds real arguments to the make command, in case other targets
-// actually need to be run (like the Soong config generator).
-//
// vars is the list of variables to read. The values will be put in the
// returned map.
-func DumpMakeVars(ctx Context, config Config, goals, extra_targets, vars []string) (map[string]string, error) {
+func DumpMakeVars(ctx Context, config Config, goals, vars []string) (map[string]string, error) {
+ return dumpMakeVars(ctx, config, goals, vars, false)
+}
+
+func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool) (map[string]string, error) {
ctx.BeginTrace("dumpvars")
defer ctx.EndTrace()
- cmd := Command(ctx, config, "make",
- "make",
- "--no-print-directory",
- "-f", "build/core/config.mk",
+ cmd := Command(ctx, config, "dumpvars",
+ config.PrebuiltBuildTool("ckati"),
+ "-f", "build/make/core/config.mk",
+ "--color_warnings",
"dump-many-vars",
- "CALLED_FROM_SETUP=true",
- "BUILD_SYSTEM=build/core",
- "MAKECMDGOALS="+strings.Join(goals, " "),
- "DUMP_MANY_VARS="+strings.Join(vars, " "),
- "OUT_DIR="+config.OutDir())
- cmd.Args = append(cmd.Args, extra_targets...)
- cmd.Sandbox = makeSandbox
+ "MAKECMDGOALS="+strings.Join(goals, " "))
+ cmd.Environment.Set("CALLED_FROM_SETUP", "true")
+ cmd.Environment.Set("BUILD_SYSTEM", "build/make/core")
+ if write_soong_vars {
+ cmd.Environment.Set("WRITE_SOONG_VARIABLES", "true")
+ }
+ cmd.Environment.Set("DUMP_MANY_VARS", strings.Join(vars, " "))
+ cmd.Sandbox = dumpvarsSandbox
// TODO: error out when Stderr contains any content
cmd.Stderr = ctx.Stderr()
output, err := cmd.Output()
@@ -77,6 +79,49 @@
return ret, nil
}
+// Variables to print out in the top banner
+var BannerVars = []string{
+ "PLATFORM_VERSION_CODENAME",
+ "PLATFORM_VERSION",
+ "TARGET_PRODUCT",
+ "TARGET_BUILD_VARIANT",
+ "TARGET_BUILD_TYPE",
+ "TARGET_BUILD_APPS",
+ "TARGET_ARCH",
+ "TARGET_ARCH_VARIANT",
+ "TARGET_CPU_VARIANT",
+ "TARGET_2ND_ARCH",
+ "TARGET_2ND_ARCH_VARIANT",
+ "TARGET_2ND_CPU_VARIANT",
+ "HOST_ARCH",
+ "HOST_2ND_ARCH",
+ "HOST_OS",
+ "HOST_OS_EXTRA",
+ "HOST_CROSS_OS",
+ "HOST_CROSS_ARCH",
+ "HOST_CROSS_2ND_ARCH",
+ "HOST_BUILD_TYPE",
+ "BUILD_ID",
+ "OUT_DIR",
+ "AUX_OS_VARIANT_LIST",
+ "TARGET_BUILD_PDK",
+ "PDK_FUSION_PLATFORM_ZIP",
+}
+
+func Banner(make_vars map[string]string) string {
+ b := &bytes.Buffer{}
+
+ fmt.Fprintln(b, "============================================")
+ for _, name := range BannerVars {
+ if make_vars[name] != "" {
+ fmt.Fprintf(b, "%s=%s\n", name, make_vars[name])
+ }
+ }
+ fmt.Fprint(b, "============================================")
+
+ return b.String()
+}
+
func runMakeProductConfig(ctx Context, config Config) {
// Variables to export into the environment of Kati/Ninja
exportEnvVars := []string{
@@ -98,35 +143,6 @@
"CCACHE_CPP2",
}
- // Variables to print out in the top banner
- bannerVars := []string{
- "PLATFORM_VERSION_CODENAME",
- "PLATFORM_VERSION",
- "TARGET_PRODUCT",
- "TARGET_BUILD_VARIANT",
- "TARGET_BUILD_TYPE",
- "TARGET_BUILD_APPS",
- "TARGET_ARCH",
- "TARGET_ARCH_VARIANT",
- "TARGET_CPU_VARIANT",
- "TARGET_2ND_ARCH",
- "TARGET_2ND_ARCH_VARIANT",
- "TARGET_2ND_CPU_VARIANT",
- "HOST_ARCH",
- "HOST_2ND_ARCH",
- "HOST_OS",
- "HOST_OS_EXTRA",
- "HOST_CROSS_OS",
- "HOST_CROSS_ARCH",
- "HOST_CROSS_2ND_ARCH",
- "HOST_BUILD_TYPE",
- "BUILD_ID",
- "OUT_DIR",
- "AUX_OS_VARIANT_LIST",
- "TARGET_BUILD_PDK",
- "PDK_FUSION_PLATFORM_ZIP",
- }
-
allVars := append(append([]string{
// Used to execute Kati and Ninja
"NINJA_GOALS",
@@ -134,23 +150,15 @@
// To find target/product/<DEVICE>
"TARGET_DEVICE",
- }, exportEnvVars...), bannerVars...)
+ }, exportEnvVars...), BannerVars...)
- make_vars, err := DumpMakeVars(ctx, config, config.Arguments(), []string{
- filepath.Join(config.SoongOutDir(), "soong.variables"),
- }, allVars)
+ make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true)
if err != nil {
ctx.Fatalln("Error dumping make vars:", err)
}
// Print the banner like make does
- fmt.Fprintln(ctx.Stdout(), "============================================")
- for _, name := range bannerVars {
- if make_vars[name] != "" {
- fmt.Fprintf(ctx.Stdout(), "%s=%s\n", name, make_vars[name])
- }
- }
- fmt.Fprintln(ctx.Stdout(), "============================================")
+ fmt.Fprintln(ctx.Stdout(), Banner(make_vars))
// Populate the environment
env := config.Environment()
diff --git a/ui/build/kati.go b/ui/build/kati.go
index cc02c76..7bb721d 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -77,7 +77,8 @@
"--color_warnings",
"--gen_all_targets",
"--werror_find_emulator",
- "-f", "build/core/main.mk",
+ "--kati_stats",
+ "-f", "build/make/core/main.mk",
}
if !config.Environment().IsFalse("KATI_EMULATE_FIND") {
@@ -109,6 +110,7 @@
}
var katiIncludeRe = regexp.MustCompile(`^(\[\d+/\d+] )?including [^ ]+ ...$`)
+var katiLogRe = regexp.MustCompile(`^\*kati\*: `)
func katiRewriteOutput(ctx Context, pipe io.ReadCloser) {
haveBlankLine := true
@@ -119,6 +121,12 @@
line := scanner.Text()
verbose := katiIncludeRe.MatchString(line)
+ // Only put kati debug/stat lines in our verbose log
+ if katiLogRe.MatchString(line) {
+ ctx.Verbose(line)
+ continue
+ }
+
// For verbose lines, write them on the current line without a newline,
// then overwrite them if the next thing we're printing is another
// verbose line.
diff --git a/ui/build/sandbox_darwin.go b/ui/build/sandbox_darwin.go
index 60407d4..2cf6e20 100644
--- a/ui/build/sandbox_darwin.go
+++ b/ui/build/sandbox_darwin.go
@@ -24,7 +24,7 @@
const (
noSandbox = ""
globalSandbox = "build/soong/ui/build/sandbox/darwin/global.sb"
- makeSandbox = globalSandbox
+ dumpvarsSandbox = globalSandbox
soongSandbox = globalSandbox
katiSandbox = globalSandbox
katiCleanSpecSandbox = globalSandbox
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 6615d37..f2bfac2 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -19,7 +19,7 @@
const (
noSandbox = false
globalSandbox = false
- makeSandbox = false
+ dumpvarsSandbox = false
soongSandbox = false
katiSandbox = false
katiCleanSpecSandbox = false