diff options
| -rw-r--r-- | Android.bp | 4 | ||||
| -rw-r--r-- | android/config.go | 12 | ||||
| -rw-r--r-- | android/filegroup.go (renamed from genrule/filegroup.go) | 33 | ||||
| -rw-r--r-- | android/module.go | 17 | ||||
| -rw-r--r-- | android/paths.go | 12 | ||||
| -rw-r--r-- | android/paths_test.go | 5 | ||||
| -rw-r--r-- | android/prebuilt.go | 19 | ||||
| -rw-r--r-- | android/prebuilt_etc.go | 91 | ||||
| -rw-r--r-- | android/prebuilt_test.go | 14 | ||||
| -rw-r--r-- | android/variable.go | 1 | ||||
| -rw-r--r-- | cc/builder.go | 2 | ||||
| -rw-r--r-- | cc/cc_test.go | 3 | ||||
| -rw-r--r-- | cc/config/global.go | 2 | ||||
| -rw-r--r-- | cc/config/x86_darwin_host.go | 15 | ||||
| -rw-r--r-- | cc/config/x86_linux_bionic_host.go | 6 | ||||
| -rw-r--r-- | cc/config/x86_linux_host.go | 15 | ||||
| -rw-r--r-- | cc/config/x86_windows_host.go | 14 | ||||
| -rw-r--r-- | cc/linker.go | 2 | ||||
| -rw-r--r-- | cc/test_data_test.go | 3 | ||||
| -rw-r--r-- | java/aar.go | 20 | ||||
| -rw-r--r-- | java/androidmk.go | 4 | ||||
| -rw-r--r-- | java/app.go | 22 | ||||
| -rw-r--r-- | java/app_test.go | 95 | ||||
| -rw-r--r-- | java/droiddoc.go | 14 | ||||
| -rw-r--r-- | java/java.go | 40 | ||||
| -rw-r--r-- | java/java_test.go | 90 | ||||
| -rw-r--r-- | java/sdk_library.go | 425 |
27 files changed, 882 insertions, 98 deletions
diff --git a/Android.bp b/Android.bp index ad2ad4782..5396664be 100644 --- a/Android.bp +++ b/Android.bp @@ -46,6 +46,7 @@ bootstrap_go_package { "android/defaults.go", "android/defs.go", "android/expand.go", + "android/filegroup.go", "android/hooks.go", "android/makevars.go", "android/module.go", @@ -56,6 +57,7 @@ bootstrap_go_package { "android/package_ctx.go", "android/paths.go", "android/prebuilt.go", + "android/prebuilt_etc.go", "android/proto.go", "android/register.go", "android/singleton.go", @@ -186,7 +188,6 @@ bootstrap_go_package { "soong-shared", ], srcs: [ - "genrule/filegroup.go", "genrule/genrule.go", ], pluginFor: ["soong_build"], @@ -232,6 +233,7 @@ bootstrap_go_package { "java/java.go", "java/java_resources.go", "java/proto.go", + "java/sdk_library.go", "java/system_modules.go", ], testSrcs: [ diff --git a/android/config.go b/android/config.go index 7122f489e..40ba8c177 100644 --- a/android/config.go +++ b/android/config.go @@ -476,6 +476,10 @@ func (c *config) PlatformSdkVersion() string { return strconv.Itoa(c.PlatformSdkVersionInt()) } +func (c *config) PlatformSdkCodename() string { + return String(c.productVariables.Platform_sdk_codename) +} + func (c *config) MinSupportedSdkVersion() int { return 14 } @@ -488,6 +492,14 @@ func (c *config) DefaultAppTargetSdkInt() int { } } +func (c *config) DefaultAppTargetSdk() string { + if Bool(c.productVariables.Platform_sdk_final) { + return c.PlatformSdkVersion() + } else { + return c.PlatformSdkCodename() + } +} + func (c *config) AppsDefaultVersionName() string { return String(c.productVariables.AppsDefaultVersionName) } diff --git a/genrule/filegroup.go b/android/filegroup.go index 2cff5fee8..b284ce027 100644 --- a/genrule/filegroup.go +++ b/android/filegroup.go @@ -12,17 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -package genrule +package android import ( - "android/soong/android" "io" "strings" "text/template" ) func init() { - android.RegisterModuleType("filegroup", FileGroupFactory) + RegisterModuleType("filegroup", FileGroupFactory) } type fileGroupProperties struct { @@ -43,34 +42,34 @@ type fileGroupProperties struct { } type fileGroup struct { - android.ModuleBase + ModuleBase properties fileGroupProperties - srcs android.Paths + srcs Paths } -var _ android.SourceFileProducer = (*fileGroup)(nil) +var _ SourceFileProducer = (*fileGroup)(nil) // filegroup modules contain a list of files, and can be used to export files across package // boundaries. filegroups (and genrules) can be referenced from srcs properties of other modules // using the syntax ":module". -func FileGroupFactory() android.Module { +func FileGroupFactory() Module { module := &fileGroup{} module.AddProperties(&module.properties) - android.InitAndroidModule(module) + InitAndroidModule(module) return module } -func (fg *fileGroup) DepsMutator(ctx android.BottomUpMutatorContext) { - android.ExtractSourcesDeps(ctx, fg.properties.Srcs) - android.ExtractSourcesDeps(ctx, fg.properties.Exclude_srcs) +func (fg *fileGroup) DepsMutator(ctx BottomUpMutatorContext) { + ExtractSourcesDeps(ctx, fg.properties.Srcs) + ExtractSourcesDeps(ctx, fg.properties.Exclude_srcs) } -func (fg *fileGroup) GenerateAndroidBuildActions(ctx android.ModuleContext) { +func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) { fg.srcs = ctx.ExpandSourcesSubDir(fg.properties.Srcs, fg.properties.Exclude_srcs, String(fg.properties.Path)) } -func (fg *fileGroup) Srcs() android.Paths { - return append(android.Paths{}, fg.srcs...) +func (fg *fileGroup) Srcs() Paths { + return append(Paths{}, fg.srcs...) } var androidMkTemplate = template.Must(template.New("filegroup").Parse(` @@ -81,9 +80,9 @@ endif .KATI_READONLY := {{.makeVar}} `)) -func (fg *fileGroup) AndroidMk() android.AndroidMkData { - return android.AndroidMkData{ - Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { +func (fg *fileGroup) AndroidMk() AndroidMkData { + return AndroidMkData{ + Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) { if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" { androidMkTemplate.Execute(w, map[string]string{ "makeVar": makeVar, diff --git a/android/module.go b/android/module.go index a011f5717..552d16517 100644 --- a/android/module.go +++ b/android/module.go @@ -323,6 +323,7 @@ func InitAndroidModule(m Module) { &base.nameProperties, &base.commonProperties, &base.variableProperties) + base.customizableProperties = m.GetProperties() } func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) { @@ -500,6 +501,22 @@ func (a *ModuleBase) DeviceSupported() bool { *a.hostAndDeviceProperties.Device_supported) } +func (a *ModuleBase) Platform() bool { + return !a.DeviceSpecific() && !a.SocSpecific() && !a.ProductSpecific() +} + +func (a *ModuleBase) DeviceSpecific() bool { + return Bool(a.commonProperties.Device_specific) +} + +func (a *ModuleBase) SocSpecific() bool { + return Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific) +} + +func (a *ModuleBase) ProductSpecific() bool { + return Bool(a.commonProperties.Product_specific) +} + func (a *ModuleBase) Enabled() bool { if a.commonProperties.Enabled == nil { return !a.Os().DefaultDisabled diff --git a/android/paths.go b/android/paths.go index 87efe5340..91dd9a6d2 100644 --- a/android/paths.go +++ b/android/paths.go @@ -308,6 +308,18 @@ func LastUniquePaths(list Paths) Paths { return list[totalSkip:] } +// ReversePaths returns a copy of a Paths in reverse order. +func ReversePaths(list Paths) Paths { + if list == nil { + return nil + } + ret := make(Paths, len(list)) + for i := range list { + ret[i] = list[len(list)-1-i] + } + return ret +} + func indexPathList(s Path, list []Path) int { for i, l := range list { if l == s { diff --git a/android/paths_test.go b/android/paths_test.go index 00757985b..cd9fbfd54 100644 --- a/android/paths_test.go +++ b/android/paths_test.go @@ -474,10 +474,7 @@ func TestDirectorySortedPaths(t *testing.T) { } paths := makePaths() - reversePaths := make(Paths, len(paths)) - for i, v := range paths { - reversePaths[len(paths)-i-1] = v - } + reversePaths := ReversePaths(paths) sortedPaths := PathsToDirectorySortedPaths(paths) reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths) diff --git a/android/prebuilt.go b/android/prebuilt.go index 9356aabb9..47c5cf531 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -59,7 +59,9 @@ func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { return nil } - return PathForModuleSrc(ctx, (*p.srcs)[0]) + // Return the singleton source after expanding any filegroup in the + // sources. + return ctx.ExpandSource((*p.srcs)[0], "") } func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { @@ -79,7 +81,7 @@ func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) { func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) { ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel() - ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel() + ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel() } // prebuiltMutator ensures that there is always a module with an undecorated name, and marks @@ -119,10 +121,12 @@ func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) { } } -// PrebuiltReplaceMutator replaces dependencies on the source module with dependencies on the -// prebuilt when both modules exist and the prebuilt should be used. When the prebuilt should not -// be used, disable installing it. -func PrebuiltReplaceMutator(ctx BottomUpMutatorContext) { +// PrebuiltPostDepsMutator does two operations. It replace dependencies on the +// source module with dependencies on the prebuilt when both modules exist and +// the prebuilt should be used. When the prebuilt should not be used, disable +// installing it. Secondly, it also adds a sourcegroup to any filegroups found +// in the prebuilt's 'Srcs' property. +func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { p := m.Prebuilt() name := m.base().BaseModuleName() @@ -133,6 +137,9 @@ func PrebuiltReplaceMutator(ctx BottomUpMutatorContext) { } else { m.SkipInstall() } + if len(*p.srcs) > 0 { + ExtractSourceDeps(ctx, &(*p.srcs)[0]) + } } } diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go new file mode 100644 index 000000000..fee2c4949 --- /dev/null +++ b/android/prebuilt_etc.go @@ -0,0 +1,91 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "fmt" + "io" +) + +// prebuilt_etc is for prebuilts that will be installed to +// <partition>/etc/<subdir> + +func init() { + RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory) +} + +type prebuiltEtcProperties struct { + // Source file of this prebuilt. + Srcs []string `android:"arch_variant"` + + // optional subdirectory under which this file is installed into + Sub_dir *string `android:"arch_variant"` +} + +type prebuiltEtc struct { + ModuleBase + prebuilt Prebuilt + + properties prebuiltEtcProperties + + sourceFilePath Path + installDirPath OutputPath +} + +func (p *prebuiltEtc) Prebuilt() *Prebuilt { + return &p.prebuilt +} + +func (p *prebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) { + if len(p.properties.Srcs) == 0 { + ctx.PropertyErrorf("srcs", "missing prebuilt source file") + } + + if len(p.properties.Srcs) > 1 { + ctx.PropertyErrorf("srcs", "multiple prebuilt source files") + } + + // To support ":modulename" in src + ExtractSourceDeps(ctx, &(p.properties.Srcs)[0]) +} + +func (p *prebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) { + p.sourceFilePath = ctx.ExpandSource(p.properties.Srcs[0], "srcs") + p.installDirPath = PathForModuleInstall(ctx, "etc", String(p.properties.Sub_dir)) +} + +func (p *prebuiltEtc) AndroidMk() AndroidMkData { + return AndroidMkData{ + Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) { + fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") + fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) + fmt.Fprintln(w, "LOCAL_MODULE :=", name) + fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") + fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional") + fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.sourceFilePath.String()) + fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString()) + fmt.Fprintln(w, "include $(BUILD_PREBUILT)") + }, + } +} + +func PrebuiltEtcFactory() Module { + module := &prebuiltEtc{} + module.AddProperties(&module.properties) + + InitPrebuiltModule(module, &(module.properties.Srcs)) + InitAndroidModule(module) + return module +} diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index 69ce16a3c..cd1ffae12 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -109,6 +109,19 @@ var prebuiltsTests = []struct { }`, prebuilt: false, }, + { + name: "prebuilt file from filegroup preferred", + modules: ` + filegroup { + name: "fg", + } + prebuilt { + name: "bar", + prefer: true, + srcs: [":fg"], + }`, + prebuilt: true, + }, } func TestPrebuilts(t *testing.T) { @@ -125,6 +138,7 @@ func TestPrebuilts(t *testing.T) { ctx := NewTestContext() ctx.PreArchMutators(RegisterPrebuiltsPreArchMutators) ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators) + ctx.RegisterModuleType("filegroup", ModuleFactoryAdaptor(FileGroupFactory)) ctx.RegisterModuleType("prebuilt", ModuleFactoryAdaptor(newPrebuiltModule)) ctx.RegisterModuleType("source", ModuleFactoryAdaptor(newSourceModule)) ctx.Register() diff --git a/android/variable.go b/android/variable.go index 3eee9887e..205790333 100644 --- a/android/variable.go +++ b/android/variable.go @@ -110,6 +110,7 @@ type productVariables struct { DateFromFile *string `json:",omitempty"` Platform_sdk_version *int `json:",omitempty"` + Platform_sdk_codename *string `json:",omitempty"` Platform_sdk_final *bool `json:",omitempty"` Platform_version_active_codenames []string `json:",omitempty"` Platform_version_future_codenames []string `json:",omitempty"` diff --git a/cc/builder.go b/cc/builder.go index cec005646..cb09d0909 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -203,7 +203,7 @@ var ( commandStr := "($sAbiDiffer $allowFlags -lib $libName -arch $arch -check-all-apis -o ${out} -new $in -old $referenceDump)" distAbiDiffDir := android.PathForDist(ctx, "abidiffs") - commandStr += "|| (echo ' ---- Please update abi references by running platform/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l ${libName} ----'" + commandStr += "|| (echo ' ---- Please update abi references by running $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l ${libName} ----'" if distAbiDiffDir.Valid() { commandStr += " && (mkdir -p " + distAbiDiffDir.String() + " && cp ${out} " + distAbiDiffDir.String() + ")" } diff --git a/cc/cc_test.go b/cc/cc_test.go index 10c1aba7f..9b4cc0fa1 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -16,7 +16,6 @@ package cc import ( "android/soong/android" - "android/soong/genrule" "fmt" "io/ioutil" @@ -62,7 +61,7 @@ func createTestContext(t *testing.T, config android.Config, bp string) *android. ctx.RegisterModuleType("llndk_headers", android.ModuleFactoryAdaptor(llndkHeadersFactory)) ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory)) ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory)) - ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory)) + ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory)) ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("image", vendorMutator).Parallel() ctx.BottomUp("link", linkageMutator).Parallel() diff --git a/cc/config/global.go b/cc/config/global.go index 051eba546..d998ca2d9 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -99,7 +99,7 @@ var ( hostGlobalLdflags = []string{} - hostGlobalLldflags = []string{} + hostGlobalLldflags = []string{"-fuse-ld=lld"} commonGlobalCppflags = []string{ "-Wsign-promo", diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go index 4aa8242d8..4ec2b3190 100644 --- a/cc/config/x86_darwin_host.go +++ b/cc/config/x86_darwin_host.go @@ -73,10 +73,16 @@ var ( darwinClangLdflags = ClangFilterUnknownCflags(darwinLdflags) + darwinClangLldflags = ClangFilterUnknownLldflags(darwinClangLdflags) + darwinX86ClangLdflags = ClangFilterUnknownCflags(darwinX86Ldflags) + darwinX86ClangLldflags = ClangFilterUnknownLldflags(darwinX86ClangLdflags) + darwinX8664ClangLdflags = ClangFilterUnknownCflags(darwinX8664Ldflags) + darwinX8664ClangLldflags = ClangFilterUnknownLldflags(darwinX8664ClangLdflags) + darwinSupportedSdkVersions = []string{ "10.10", "10.11", @@ -141,6 +147,7 @@ func init() { pctx.StaticVariable("DarwinClangCflags", strings.Join(darwinClangCflags, " ")) pctx.StaticVariable("DarwinClangLdflags", strings.Join(darwinClangLdflags, " ")) + pctx.StaticVariable("DarwinClangLldflags", strings.Join(darwinClangLldflags, " ")) // Extended cflags pctx.StaticVariable("DarwinX86Cflags", strings.Join(darwinX86Cflags, " ")) @@ -152,7 +159,9 @@ func init() { pctx.StaticVariable("DarwinX8664ClangCflags", strings.Join(ClangFilterUnknownCflags(darwinX8664Cflags), " ")) pctx.StaticVariable("DarwinX86ClangLdflags", strings.Join(darwinX86ClangLdflags, " ")) + pctx.StaticVariable("DarwinX86ClangLldflags", strings.Join(darwinX86ClangLldflags, " ")) pctx.StaticVariable("DarwinX8664ClangLdflags", strings.Join(darwinX8664ClangLdflags, " ")) + pctx.StaticVariable("DarwinX8664ClangLldflags", strings.Join(darwinX8664ClangLldflags, " ")) pctx.StaticVariable("DarwinX86YasmFlags", "-f macho -m x86") pctx.StaticVariable("DarwinX8664YasmFlags", "-f macho -m amd64") } @@ -274,8 +283,7 @@ func (t *toolchainDarwinX86) ClangLdflags() string { } func (t *toolchainDarwinX86) ClangLldflags() string { - // TODO: define and use Darwin*ClangLldflags - return "${config.DarwinClangLdflags} ${config.DarwinX86ClangLdflags}" + return "${config.DarwinClangLldflags} ${config.DarwinX86ClangLldflags}" } func (t *toolchainDarwinX8664) ClangLdflags() string { @@ -283,8 +291,7 @@ func (t *toolchainDarwinX8664) ClangLdflags() string { } func (t *toolchainDarwinX8664) ClangLldflags() string { - // TODO: define and use Darwin*ClangLldflags - return "${config.DarwinClangLdflags} ${config.DarwinX8664ClangLdflags}" + return "${config.DarwinClangLldflags} ${config.DarwinX8664ClangLldflags}" } func (t *toolchainDarwinX86) YasmFlags() string { diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go index 057e905d9..a9fb1f661 100644 --- a/cc/config/x86_linux_bionic_host.go +++ b/cc/config/x86_linux_bionic_host.go @@ -61,11 +61,14 @@ var ( // Use the device gcc toolchain "--gcc-toolchain=${LinuxBionicGccRoot}", }) + + linuxBionicLldflags = ClangFilterUnknownLldflags(linuxBionicLdflags) ) func init() { pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " ")) pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " ")) + pctx.StaticVariable("LinuxBionicLldflags", strings.Join(linuxBionicLldflags, " ")) pctx.StaticVariable("LinuxBionicIncludeFlags", bionicHeaders("x86")) @@ -127,8 +130,7 @@ func (t *toolchainLinuxBionic) ClangLdflags() string { } func (t *toolchainLinuxBionic) ClangLldflags() string { - // TODO: define and use LinuxBionicLldflags - return "${config.LinuxBionicLdflags}" + return "${config.LinuxBionicLldflags}" } func (t *toolchainLinuxBionic) ToolchainClangCflags() string { diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go index 6144fc2ae..354500eb0 100644 --- a/cc/config/x86_linux_host.go +++ b/cc/config/x86_linux_host.go @@ -78,18 +78,24 @@ var ( "--sysroot ${LinuxGccRoot}/sysroot", }...) + linuxClangLldflags = ClangFilterUnknownLldflags(linuxClangLdflags) + linuxX86ClangLdflags = append(ClangFilterUnknownCflags(linuxX86Ldflags), []string{ "-B${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}/32", "-L${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}/32", "-L${LinuxGccRoot}/${LinuxGccTriple}/lib32", }...) + linuxX86ClangLldflags = ClangFilterUnknownLldflags(linuxX86ClangLdflags) + linuxX8664ClangLdflags = append(ClangFilterUnknownCflags(linuxX8664Ldflags), []string{ "-B${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}", "-L${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}", "-L${LinuxGccRoot}/${LinuxGccTriple}/lib64", }...) + linuxX8664ClangLldflags = ClangFilterUnknownLldflags(linuxX8664ClangLdflags) + linuxClangCppflags = []string{ "-isystem ${LinuxGccRoot}/${LinuxGccTriple}/include/c++/${LinuxGccVersion}", "-isystem ${LinuxGccRoot}/${LinuxGccTriple}/include/c++/${LinuxGccVersion}/backward", @@ -134,6 +140,7 @@ func init() { pctx.StaticVariable("LinuxClangCflags", strings.Join(linuxClangCflags, " ")) pctx.StaticVariable("LinuxClangLdflags", strings.Join(linuxClangLdflags, " ")) + pctx.StaticVariable("LinuxClangLldflags", strings.Join(linuxClangLldflags, " ")) pctx.StaticVariable("LinuxClangCppflags", strings.Join(linuxClangCppflags, " ")) // Extended cflags @@ -147,7 +154,9 @@ func init() { pctx.StaticVariable("LinuxX8664ClangCflags", strings.Join(ClangFilterUnknownCflags(linuxX8664Cflags), " ")) pctx.StaticVariable("LinuxX86ClangLdflags", strings.Join(linuxX86ClangLdflags, " ")) + pctx.StaticVariable("LinuxX86ClangLldflags", strings.Join(linuxX86ClangLldflags, " ")) pctx.StaticVariable("LinuxX8664ClangLdflags", strings.Join(linuxX8664ClangLdflags, " ")) + pctx.StaticVariable("LinuxX8664ClangLldflags", strings.Join(linuxX8664ClangLldflags, " ")) pctx.StaticVariable("LinuxX86ClangCppflags", strings.Join(linuxX86ClangCppflags, " ")) pctx.StaticVariable("LinuxX8664ClangCppflags", strings.Join(linuxX8664ClangCppflags, " ")) // Yasm flags @@ -242,8 +251,7 @@ func (t *toolchainLinuxX86) ClangLdflags() string { } func (t *toolchainLinuxX86) ClangLldflags() string { - // TODO: define and use Linux*ClangLldflags - return "${config.LinuxClangLdflags} ${config.LinuxX86ClangLdflags}" + return "${config.LinuxClangLldflags} ${config.LinuxX86ClangLldflags}" } func (t *toolchainLinuxX8664) ClangLdflags() string { @@ -251,8 +259,7 @@ func (t *toolchainLinuxX8664) ClangLdflags() string { } func (t *toolchainLinuxX8664) ClangLldflags() string { - // TODO: define and use Linux*ClangLldflags - return "${config.LinuxClangLdflags} ${config.LinuxX8664ClangLdflags}" + return "${config.LinuxClangLldflags} ${config.LinuxX8664ClangLldflags}" } func (t *toolchainLinuxX86) YasmFlags() string { diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go index fea629109..6fbff9f19 100644 --- a/cc/config/x86_windows_host.go +++ b/cc/config/x86_windows_host.go @@ -64,7 +64,8 @@ var ( windowsLdflags = []string{ "--enable-stdcall-fixup", } - windowsClangLdflags = append(ClangFilterUnknownCflags(windowsLdflags), []string{}...) + windowsClangLdflags = append(ClangFilterUnknownCflags(windowsLdflags), []string{}...) + windowsClangLldflags = ClangFilterUnknownLldflags(windowsClangLdflags) windowsX86Cflags = []string{ "-m32", @@ -84,6 +85,7 @@ var ( "-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32", "-B${WindowsGccRoot}/${WindowsGccTriple}/lib32", }...) + windowsX86ClangLldflags = ClangFilterUnknownLldflags(windowsX86ClangLdflags) windowsX8664Ldflags = []string{ "-m64", @@ -94,6 +96,7 @@ var ( "-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3", "-B${WindowsGccRoot}/${WindowsGccTriple}/lib64", }...) + windowsX8664ClangLldflags = ClangFilterUnknownLldflags(windowsX8664ClangLdflags) windowsAvailableLibraries = addPrefix([]string{ "gdi32", @@ -128,6 +131,7 @@ func init() { pctx.StaticVariable("WindowsClangCflags", strings.Join(windowsClangCflags, " ")) pctx.StaticVariable("WindowsClangLdflags", strings.Join(windowsClangLdflags, " ")) + pctx.StaticVariable("WindowsClangLldflags", strings.Join(windowsClangLldflags, " ")) pctx.StaticVariable("WindowsClangCppflags", strings.Join(windowsClangCppflags, " ")) pctx.StaticVariable("WindowsX86Cflags", strings.Join(windowsX86Cflags, " ")) @@ -140,7 +144,9 @@ func init() { pctx.StaticVariable("WindowsX8664ClangCflags", strings.Join(ClangFilterUnknownCflags(windowsX8664Cflags), " ")) pctx.StaticVariable("WindowsX86ClangLdflags", strings.Join(windowsX86ClangLdflags, " ")) + pctx.StaticVariable("WindowsX86ClangLldflags", strings.Join(windowsX86ClangLldflags, " ")) pctx.StaticVariable("WindowsX8664ClangLdflags", strings.Join(windowsX8664ClangLdflags, " ")) + pctx.StaticVariable("WindowsX8664ClangLldflags", strings.Join(windowsX8664ClangLldflags, " ")) pctx.StaticVariable("WindowsX86ClangCppflags", strings.Join(windowsX86ClangCppflags, " ")) pctx.StaticVariable("WindowsX8664ClangCppflags", strings.Join(windowsX8664ClangCppflags, " ")) @@ -246,8 +252,7 @@ func (t *toolchainWindowsX86) ClangLdflags() string { } func (t *toolchainWindowsX86) ClangLldflags() string { - // TODO: define and use Windows*ClangLldflags - return "${config.WindowsClangLdflags} ${config.WindowsX86ClangLdflags}" + return "${config.WindowsClangLldflags} ${config.WindowsX86ClangLldflags}" } func (t *toolchainWindowsX8664) ClangLdflags() string { @@ -255,8 +260,7 @@ func (t *toolchainWindowsX8664) ClangLdflags() string { } func (t *toolchainWindowsX8664) ClangLldflags() string { - // TODO: define and use Windows*ClangLldflags - return "${config.WindowsClangLdflags} ${config.WindowsX8664ClangLdflags}" + return "${config.WindowsClangLldflags} ${config.WindowsX8664ClangLldflags}" } func (t *toolchainWindows) ShlibSuffix() string { diff --git a/cc/linker.go b/cc/linker.go index 217630633..d9da404ad 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -59,7 +59,7 @@ type BaseLinkerProperties struct { No_libgcc *bool // Use clang lld instead of gnu ld. - Use_clang_lld *bool + Use_clang_lld *bool `android:"arch_variant"` // -l arguments to pass to linker for host-provided shared libraries Host_ldlibs []string `android:"arch_variant"` diff --git a/cc/test_data_test.go b/cc/test_data_test.go index 4a7b0f756..56c3e38ca 100644 --- a/cc/test_data_test.go +++ b/cc/test_data_test.go @@ -22,7 +22,6 @@ import ( "testing" "android/soong/android" - "android/soong/genrule" ) type dataFile struct { @@ -129,7 +128,7 @@ func TestDataTests(t *testing.T) { "dir/bar/baz": nil, }) ctx.RegisterModuleType("filegroup", - android.ModuleFactoryAdaptor(genrule.FileGroupFactory)) + android.ModuleFactoryAdaptor(android.FileGroupFactory)) ctx.RegisterModuleType("test", android.ModuleFactoryAdaptor(newTest)) ctx.Register() diff --git a/java/aar.go b/java/aar.go index 57c752c6e..13c536940 100644 --- a/java/aar.go +++ b/java/aar.go @@ -76,14 +76,11 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkVersion string) (flags [ hasVersionCode := false hasVersionName := false - hasProduct := false for _, f := range a.aaptProperties.Aaptflags { if strings.HasPrefix(f, "--version-code") { hasVersionCode = true } else if strings.HasPrefix(f, "--version-name") { hasVersionName = true - } else if strings.HasPrefix(f, "--product") { - hasProduct = true } } @@ -134,27 +131,12 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkVersion string) (flags [ // SDK version flags switch sdkVersion { case "", "current", "system_current", "test_current": - sdkVersion = proptools.NinjaEscape([]string{ctx.Config().AppsDefaultVersionName()})[0] + sdkVersion = proptools.NinjaEscape([]string{ctx.Config().DefaultAppTargetSdk()})[0] } linkFlags = append(linkFlags, "--min-sdk-version "+sdkVersion) linkFlags = append(linkFlags, "--target-sdk-version "+sdkVersion) - // Product characteristics - if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 { - linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics()) - } - - // Product AAPT config - for _, aaptConfig := range ctx.Config().ProductAAPTConfig() { - linkFlags = append(linkFlags, "-c", aaptConfig) - } - - // Product AAPT preferred config - if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 { - linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig()) - } - // Version code if !hasVersionCode { linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion()) diff --git a/java/androidmk.go b/java/androidmk.go index dfbe7fa75..8bde716bb 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -206,7 +206,9 @@ func (app *AndroidApp) AndroidMk() android.AndroidMkData { } if len(app.rroDirs) > 0 { - fmt.Fprintln(w, "LOCAL_SOONG_RRO_DIRS :=", strings.Join(app.rroDirs.Strings(), " ")) + // Reverse the order, Soong stores rroDirs in aapt2 order (low to high priority), but Make + // expects it in LOCAL_RESOURCE_DIRS order (high to low priority). + fmt.Fprintln(w, "LOCAL_SOONG_RRO_DIRS :=", strings.Join(android.ReversePaths(app.rroDirs).Strings(), " ")) } if Bool(app.appProperties.Export_package_resources) { diff --git a/java/app.go b/java/app.go index 3e24ebc89..dd83a0a77 100644 --- a/java/app.go +++ b/java/app.go @@ -86,6 +86,28 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.properties.Instrument = true } + hasProduct := false + for _, f := range a.aaptProperties.Aaptflags { + if strings.HasPrefix(f, "--product") { + hasProduct = true + } + } + + // Product characteristics + if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 { + linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics()) + } + + // Product AAPT config + for _, aaptConfig := range ctx.Config().ProductAAPTConfig() { + linkFlags = append(linkFlags, "-c", aaptConfig) + } + + // Product AAPT preferred config + if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 { + linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig()) + } + // TODO: LOCAL_PACKAGE_OVERRIDES // $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \ diff --git a/java/app_test.go b/java/app_test.go index 7a6177138..6770119ef 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -16,8 +16,10 @@ package java import ( "android/soong/android" + "fmt" "reflect" "sort" + "strings" "testing" ) @@ -240,3 +242,96 @@ func TestEnforceRRO(t *testing.T) { }) } } + +func TestAppSdkVersion(t *testing.T) { + testCases := []struct { + name string + sdkVersion string + platformSdkInt int + platformSdkCodename string + platformSdkFinal bool + expectedMinSdkVersion string + }{ + { + name: "current final SDK", + sdkVersion: "current", + platformSdkInt: 27, + platformSdkCodename: "REL", + platformSdkFinal: true, + expectedMinSdkVersion: "27", + }, + { + name: "current non-final SDK", + sdkVersion: "current", + platformSdkInt: 27, + platformSdkCodename: "OMR1", + platformSdkFinal: false, + expectedMinSdkVersion: "OMR1", + }, + { + name: "default final SDK", + sdkVersion: "", + platformSdkInt: 27, + platformSdkCodename: "REL", + platformSdkFinal: true, + expectedMinSdkVersion: "27", + }, + { + name: "default non-final SDK", + sdkVersion: "", + platformSdkInt: 27, + platformSdkCodename: "OMR1", + platformSdkFinal: false, + expectedMinSdkVersion: "OMR1", + }, + { + name: "14", + sdkVersion: "14", + expectedMinSdkVersion: "14", + }, + } + + for _, moduleType := range []string{"android_app", "android_library"} { + for _, test := range testCases { + t.Run(moduleType+" "+test.name, func(t *testing.T) { + bp := fmt.Sprintf(`%s { + name: "foo", + srcs: ["a.java"], + sdk_version: "%s", + }`, moduleType, test.sdkVersion) + + config := testConfig(nil) + config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt + config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename + config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal + + ctx := testAppContext(config, bp, nil) + + run(t, ctx, config) + + foo := ctx.ModuleForTests("foo", "android_common") + link := foo.Output("package-res.apk") + linkFlags := strings.Split(link.Args["flags"], " ") + min := android.IndexList("--min-sdk-version", linkFlags) + target := android.IndexList("--target-sdk-version", linkFlags) + + if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 { + t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags) + } + + gotMinSdkVersion := linkFlags[min+1] + gotTargetSdkVersion := linkFlags[target+1] + + if gotMinSdkVersion != test.expectedMinSdkVersion { + t.Errorf("incorrect --min-sdk-version, expected %q got %q", + test.expectedMinSdkVersion, gotMinSdkVersion) + } + + if gotTargetSdkVersion != test.expectedMinSdkVersion { + t.Errorf("incorrect --target-sdk-version, expected %q got %q", + test.expectedMinSdkVersion, gotTargetSdkVersion) + } + }) + } + } +} diff --git a/java/droiddoc.go b/java/droiddoc.go index 0224da5ae..07004873e 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -306,6 +306,20 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { default: panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName())) } + case SdkLibraryDependency: + switch tag { + case libTag: + sdkVersion := String(j.properties.Sdk_version) + linkType := javaSdk + if strings.HasPrefix(sdkVersion, "system_") || strings.HasPrefix(sdkVersion, "test_") { + linkType = javaSystem + } else if sdkVersion == "" { + linkType = javaPlatform + } + deps.classpath = append(deps.classpath, dep.HeaderJars(linkType)...) + default: + ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName) + } case android.SourceFileProducer: switch tag { case libTag: diff --git a/java/java.go b/java/java.go index bc58df3ad..8c2312476 100644 --- a/java/java.go +++ b/java/java.go @@ -292,6 +292,10 @@ type Dependency interface { AidlIncludeDirs() android.Paths } +type SdkLibraryDependency interface { + HeaderJars(linkType linkType) android.Paths +} + type SrcDependency interface { CompiledSrcs() android.Paths CompiledSrcJars() android.Paths @@ -387,24 +391,29 @@ func decodeSdkDep(ctx android.BaseContext, v string) sdkDep { } } - toFile := func(v string) sdkDep { - isCore := strings.HasPrefix(v, "core_") - if isCore { - v = strings.TrimPrefix(v, "core_") + toPrebuilt := func(sdk string) sdkDep { + var api, v string + if strings.Contains(sdk, "_") { + t := strings.Split(sdk, "_") + api = t[0] + v = t[1] + } else { + api = "public" + v = sdk } - dir := filepath.Join("prebuilts/sdk", v) + dir := filepath.Join("prebuilts", "sdk", v, api) jar := filepath.Join(dir, "android.jar") - if isCore { - jar = filepath.Join(dir, "core.jar") - } - aidl := filepath.Join(dir, "framework.aidl") + // There's no aidl for other SDKs yet. + // TODO(77525052): Add aidl files for other SDKs too. + public_dir := filepath.Join("prebuilts", "sdk", v, "public") + aidl := filepath.Join(public_dir, "framework.aidl") jarPath := android.ExistentPathForSource(ctx, jar) aidlPath := android.ExistentPathForSource(ctx, aidl) if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() { return sdkDep{ invalidVersion: true, - module: "sdk_v" + v, + module: fmt.Sprintf("sdk_%s_%s_android", api, v), } } @@ -439,7 +448,7 @@ func decodeSdkDep(ctx android.BaseContext, v string) sdkDep { } if ctx.Config().UnbundledBuild() && v != "" { - return toFile(v) + return toPrebuilt(v) } switch v { @@ -457,7 +466,7 @@ func decodeSdkDep(ctx android.BaseContext, v string) sdkDep { case "core_current": return toModule("core.current.stubs", "") default: - return toFile(v) + return toPrebuilt(v) } } @@ -724,6 +733,13 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { } deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...) + case SdkLibraryDependency: + switch tag { + case libTag: + deps.classpath = append(deps.classpath, dep.HeaderJars(getLinkType(j, ctx.ModuleName()))...) + default: + ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName) + } case android.SourceFileProducer: switch tag { case libTag: diff --git a/java/java_test.go b/java/java_test.go index 0e7bb18b2..de514e048 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -78,14 +78,18 @@ func testContext(config android.Config, bp string, ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory)) ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(SystemModulesFactory)) ctx.RegisterModuleType("java_genrule", android.ModuleFactoryAdaptor(genRuleFactory)) - ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory)) + ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory)) ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(genrule.GenRuleFactory)) ctx.RegisterModuleType("droiddoc", android.ModuleFactoryAdaptor(DroiddocFactory)) ctx.RegisterModuleType("droiddoc_host", android.ModuleFactoryAdaptor(DroiddocHostFactory)) ctx.RegisterModuleType("droiddoc_template", android.ModuleFactoryAdaptor(DroiddocTemplateFactory)) + ctx.RegisterModuleType("java_sdk_library", android.ModuleFactoryAdaptor(sdkLibraryFactory)) ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators) ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) + ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) { + ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel() + }) ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory)) ctx.Register() @@ -151,17 +155,14 @@ func testContext(config android.Config, bp string, "java-fg/b.java": nil, "java-fg/c.java": nil, - "prebuilts/sdk/14/android.jar": nil, - "prebuilts/sdk/14/framework.aidl": nil, - "prebuilts/sdk/current/android.jar": nil, - "prebuilts/sdk/current/framework.aidl": nil, - "prebuilts/sdk/current/core.jar": nil, - "prebuilts/sdk/system_current/android.jar": nil, - "prebuilts/sdk/system_current/framework.aidl": nil, - "prebuilts/sdk/system_14/android.jar": nil, - "prebuilts/sdk/system_14/framework.aidl": nil, - "prebuilts/sdk/test_current/android.jar": nil, - "prebuilts/sdk/test_current/framework.aidl": nil, + "prebuilts/sdk/14/public/android.jar": nil, + "prebuilts/sdk/14/public/framework.aidl": nil, + "prebuilts/sdk/14/system/android.jar": nil, + "prebuilts/sdk/current/public/android.jar": nil, + "prebuilts/sdk/current/public/framework.aidl": nil, + "prebuilts/sdk/current/public/core.jar": nil, + "prebuilts/sdk/current/system/android.jar": nil, + "prebuilts/sdk/current/test/android.jar": nil, // For framework-res, which is an implicit dependency for framework "AndroidManifest.xml": nil, @@ -340,7 +341,7 @@ var classpathTestcases = []struct { 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"}, + classpath: []string{"prebuilts/sdk/14/public/android.jar"}, }, { @@ -362,7 +363,7 @@ var classpathTestcases = []struct { properties: `sdk_version: "system_14",`, bootclasspath: []string{`""`}, system: "bootclasspath", // special value to tell 1.9 test to expect bootclasspath - classpath: []string{"prebuilts/sdk/system_14/android.jar"}, + classpath: []string{"prebuilts/sdk/14/system/android.jar"}, }, { @@ -864,9 +865,9 @@ func TestTurbine(t *testing.T) { if len(barTurbineCombined.Inputs) != 2 || barTurbineCombined.Inputs[1].String() != fooHeaderJar { t.Errorf("bar turbine combineJar inputs %v does not contain %q", barTurbineCombined.Inputs, fooHeaderJar) } - if !strings.Contains(bazJavac.Args["classpath"], "prebuilts/sdk/14/android.jar") { + if !strings.Contains(bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar") { t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"], - "prebuilts/sdk/14/android.jar") + "prebuilts/sdk/14/public/android.jar") } } @@ -1001,3 +1002,60 @@ func TestExcludeFileGroupInSrcs(t *testing.T) { t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs) } } + +func TestJavaSdkLibrary(t *testing.T) { + ctx := testJava(t, ` + droiddoc_template { + name: "droiddoc-templates-sdk", + path: ".", + } + java_library { + name: "conscrypt", + } + java_library { + name: "bouncycastle", + } + java_sdk_library { + name: "foo", + srcs: ["a.java", "b.java"], + api_packages: ["foo"], + } + java_sdk_library { + name: "bar", + srcs: ["a.java", "b.java"], + api_packages: ["bar"], + } + java_library { + name: "baz", + srcs: ["c.java"], + libs: ["foo", "bar"], + sdk_version: "system_current", + } + `) + + // check the existence of the internal modules + ctx.ModuleForTests("foo", "android_common") + ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix, "android_common") + ctx.ModuleForTests("foo"+sdkStubsLibrarySuffix+sdkSystemApiSuffix, "android_common") + ctx.ModuleForTests("foo"+sdkDocsSuffix, "android_common") + ctx.ModuleForTests("foo"+sdkDocsSuffix+sdkSystemApiSuffix, "android_common") + ctx.ModuleForTests("foo"+sdkImplLibrarySuffix, "android_common") + ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "") + + bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac") + // tests if baz is actually linked to the stubs lib + if !strings.Contains(bazJavac.Args["classpath"], "foo.stubs.system.jar") { + t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"], + "foo.stubs.system.jar") + } + // ... and not to the impl lib + if strings.Contains(bazJavac.Args["classpath"], "foo.impl.jar") { + t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"], + "foo.impl.jar") + } + // test if baz is not linked to the system variant of foo + if strings.Contains(bazJavac.Args["classpath"], "foo.stubs.jar") { + t.Errorf("baz javac classpath %v should not contain %q", bazJavac.Args["classpath"], + "foo.stubs.jar") + } +} diff --git a/java/sdk_library.go b/java/sdk_library.go new file mode 100644 index 000000000..301ec6120 --- /dev/null +++ b/java/sdk_library.go @@ -0,0 +1,425 @@ +// Copyright 2018 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 ( + "android/soong/android" + "android/soong/genrule" + "fmt" + "path" + "strings" + + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" +) + +var ( + sdkStubsLibrarySuffix = ".stubs" + sdkSystemApiSuffix = ".system" + sdkDocsSuffix = ".docs" + sdkImplLibrarySuffix = ".impl" + sdkXmlFileSuffix = ".xml" +) + +type stubsLibraryDependencyTag struct { + blueprint.BaseDependencyTag + name string +} + +var ( + publicApiStubsTag = dependencyTag{name: "public"} + systemApiStubsTag = dependencyTag{name: "system"} +) + +// java_sdk_library is to make a Java library that implements optional platform APIs to apps. +// It is actually a wrapper of several modules: 1) stubs library that clients are linked against +// to, 2) droiddoc module that internally generates API stubs source files, 3) the real runtime +// shared library that implements the APIs, and 4) XML file for adding the runtime lib to the +// classpath at runtime if requested via <uses-library>. +// +// TODO: these are big features that are currently missing +// 1) check for API consistency +// 2) install stubs libs as the dist artifacts +// 3) ensuring that apps have appropriate <uses-library> tag +// 4) disallowing linking to the runtime shared lib +// 5) HTML generation + +func init() { + android.RegisterModuleType("java_sdk_library", sdkLibraryFactory) + + android.PreArchMutators(func(ctx android.RegisterMutatorsContext) { + ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel() + }) +} + +type sdkLibraryProperties struct { + // list of source files used to compile the Java module. May be .java, .logtags, .proto, + // or .aidl files. + Srcs []string `android:"arch_variant"` + + // list of of java libraries that will be in the classpath + Libs []string `android:"arch_variant"` + + // list of java libraries that will be compiled into the resulting runtime jar. + // These libraries are not compiled into the stubs jar. + Static_libs []string `android:"arch_variant"` + + // list of package names that will be documented and publicized as API + Api_packages []string + + // TODO: determines whether to create HTML doc or not + //Html_doc *bool +} + +type sdkLibrary struct { + android.ModuleBase + android.DefaultableModuleBase + + properties sdkLibraryProperties + + publicApiStubsPath android.Paths + systemApiStubsPath android.Paths +} + +func (module *sdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { + // Add dependencies to the stubs library + ctx.AddDependency(ctx.Module(), publicApiStubsTag, module.stubsName(false)) + ctx.AddDependency(ctx.Module(), systemApiStubsTag, module.stubsName(true)) +} + +func (module *sdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Record the paths to the header jars of the stubs library. + // When this java_sdk_library is dependened from others via "libs" property, + // the recorded paths will be returned depending on the link type of the caller. + ctx.VisitDirectDeps(func(to android.Module) { + otherName := ctx.OtherModuleName(to) + tag := ctx.OtherModuleDependencyTag(to) + + if stubs, ok := to.(Dependency); ok { + switch tag { + case publicApiStubsTag: + module.publicApiStubsPath = stubs.HeaderJars() + case systemApiStubsTag: + module.systemApiStubsPath = stubs.HeaderJars() + default: + ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag) + } + } + }) +} + +// Module name of the stubs library +func (module *sdkLibrary) stubsName(forSystemApi bool) string { + stubsName := module.BaseModuleName() + sdkStubsLibrarySuffix + if forSystemApi { + stubsName = stubsName + sdkSystemApiSuffix + } + return stubsName +} + +// Module name of the docs +func (module *sdkLibrary) docsName(forSystemApi bool) string { + docsName := module.BaseModuleName() + sdkDocsSuffix + if forSystemApi { + docsName = docsName + sdkSystemApiSuffix + } + return docsName +} + +// Module name of the runtime implementation library +func (module *sdkLibrary) implName() string { + return module.BaseModuleName() + sdkImplLibrarySuffix +} + +// File path to the runtime implementation library +func (module *sdkLibrary) implPath() string { + partition := "system" + if module.SocSpecific() { + partition = "vendor" + } else if module.DeviceSpecific() { + partition = "odm" + } else if module.ProductSpecific() { + partition = "product" + } + return "/" + partition + "/framework/" + module.implName() + ".jar" +} + +// Module name of the XML file for the lib +func (module *sdkLibrary) xmlFileName() string { + return module.BaseModuleName() + sdkXmlFileSuffix +} + +// SDK version that the stubs library is built against. Note that this is always +// *current. Older stubs library built with a numberd SDK version is created from +// the prebuilt jar. +func (module *sdkLibrary) sdkVersion(forSystemApi bool) string { + if forSystemApi { + return "system_current" + } else { + return "current" + } +} + +// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated +// api file for the current source +// TODO: remove this when apicheck is done in soong +func (module *sdkLibrary) apiTagName(forSystemApi bool) string { + apiTagName := strings.Replace(strings.ToUpper(module.BaseModuleName()), ".", "_", -1) + if forSystemApi { + apiTagName = apiTagName + "_SYSTEM" + } + return apiTagName +} + +// returns the path (relative to this module) to the API txt file. Files are located +// ./<api_dir>/<api_level>.txt where <api_level> is either current, system-current, removed, +// or system-removed. +func (module *sdkLibrary) apiFilePath(apiLevel string, forSystemApi bool) string { + apiDir := "api" + apiFile := apiLevel + if forSystemApi { + apiFile = "system-" + apiFile + } + apiFile = apiFile + ".txt" + + return path.Join(apiDir, apiFile) +} + +// Creates a static java library that has API stubs +func (module *sdkLibrary) createStubsLibrary(mctx android.TopDownMutatorContext, forSystemApi bool) { + props := struct { + Name *string + Srcs []string + Sdk_version *string + Soc_specific *bool + Device_specific *bool + Product_specific *bool + Product_variables struct { + Unbundled_build struct { + Enabled *bool + } + } + }{} + + props.Name = proptools.StringPtr(module.stubsName(forSystemApi)) + // sources are generated from the droiddoc + props.Srcs = []string{":" + module.docsName(forSystemApi)} + props.Sdk_version = proptools.StringPtr(module.sdkVersion(forSystemApi)) + // Unbundled apps will use the prebult one from /prebuilts/sdk + props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false) + + if module.SocSpecific() { + props.Soc_specific = proptools.BoolPtr(true) + } else if module.DeviceSpecific() { + props.Device_specific = proptools.BoolPtr(true) + } else if module.ProductSpecific() { + props.Product_specific = proptools.BoolPtr(true) + } + + mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory(false)), &props) +} + +// Creates a droiddoc module that creates stubs source files from the given full source +// files +func (module *sdkLibrary) createDocs(mctx android.TopDownMutatorContext, forSystemApi bool) { + props := struct { + Name *string + Srcs []string + Custom_template *string + Installable *bool + Srcs_lib *string + Srcs_lib_whitelist_dirs []string + Srcs_lib_whitelist_pkgs []string + Libs []string + Args *string + Api_tag_name *string + Api_filename *string + Removed_api_filename *string + }{} + + props.Name = proptools.StringPtr(module.docsName(forSystemApi)) + props.Srcs = module.properties.Srcs + props.Custom_template = proptools.StringPtr("droiddoc-templates-sdk") + props.Installable = proptools.BoolPtr(false) + props.Libs = module.properties.Libs + + droiddocArgs := " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128" + + " -stubpackages " + strings.Join(module.properties.Api_packages, ":") + + " -nodocs" + if forSystemApi { + droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi" + } + props.Args = proptools.StringPtr(droiddocArgs) + + // List of APIs identified from the provided source files are created. They are later + // compared against to the not-yet-released (a.k.a current) list of APIs and to the + // last-released (a.k.a numbered) list of API. + // TODO: If any incompatible change is detected, break the build + currentApiFileName := "current.txt" + removedApiFileName := "removed.txt" + if forSystemApi { + currentApiFileName = "system-" + currentApiFileName + removedApiFileName = "system-" + removedApiFileName + } + currentApiFileName = path.Join("api", currentApiFileName) + removedApiFileName = path.Join("api", removedApiFileName) + props.Api_tag_name = proptools.StringPtr(module.apiTagName(forSystemApi)) + // Note: the exact names of these two are not important because they are always + // referenced by the make variable $(INTERNAL_PLATFORM_<TAG_NAME>_API_FILE) + props.Api_filename = proptools.StringPtr(currentApiFileName) + props.Removed_api_filename = proptools.StringPtr(removedApiFileName) + + // Includes the main framework source to ensure that doclava has access to the + // visibility information for the base classes of the mock classes. Without it + // otherwise hidden methods could be visible. + // TODO: remove the need for this + props.Srcs_lib = proptools.StringPtr("framework") + props.Srcs_lib_whitelist_dirs = []string{"core/java"} + props.Srcs_lib_whitelist_pkgs = []string{"android"} + // These libs are required by doclava to parse the sources from framework. + // If we don't add them to the classpath, errors messages are generated by doclava, + // though they don't break the build. + props.Libs = append(props.Libs, "conscrypt", "bouncycastle", "okhttp") + + mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props) +} + +// Creates the runtime library. This is not directly linkable from other modules. +func (module *sdkLibrary) createImplLibrary(mctx android.TopDownMutatorContext) { + props := struct { + Name *string + Srcs []string + Libs []string + Static_libs []string + Soc_specific *bool + Device_specific *bool + Product_specific *bool + Required []string + }{} + + props.Name = proptools.StringPtr(module.implName()) + props.Srcs = module.properties.Srcs + props.Libs = module.properties.Libs + props.Static_libs = module.properties.Static_libs + // XML file is installed along with the impl lib + props.Required = []string{module.xmlFileName()} + + if module.SocSpecific() { + props.Soc_specific = proptools.BoolPtr(true) + } else if module.DeviceSpecific() { + props.Device_specific = proptools.BoolPtr(true) + } else if module.ProductSpecific() { + props.Product_specific = proptools.BoolPtr(true) + } + + mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory(true)), &props) +} + +// Creates the xml file that publicizes the runtime library +func (module *sdkLibrary) createXmlFile(mctx android.TopDownMutatorContext) { + template := ` +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<permissions> + <library name="%s" file="%s"/> +</permissions> +` + // genrule to generate the xml file content from the template above + // TODO: preserve newlines in the generate xml file. Newlines are being squashed + // in the ninja file. Do we need to have an external tool for this? + xmlContent := fmt.Sprintf(template, module.BaseModuleName(), module.implPath()) + genruleProps := struct { + Name *string + Cmd *string + Out []string + }{} + genruleProps.Name = proptools.StringPtr(module.xmlFileName() + "-gen") + genruleProps.Cmd = proptools.StringPtr("echo '" + xmlContent + "' > $(out)") + genruleProps.Out = []string{module.xmlFileName()} + mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProps) + + // creates a prebuilt_etc module to actually place the xml file under + // <partition>/etc/permissions + etcProps := struct { + Name *string + Srcs []string + Sub_dir *string + Soc_specific *bool + Device_specific *bool + Product_specific *bool + }{} + etcProps.Name = proptools.StringPtr(module.xmlFileName()) + etcProps.Srcs = []string{":" + module.xmlFileName() + "-gen"} + etcProps.Sub_dir = proptools.StringPtr("permissions") + if module.SocSpecific() { + etcProps.Soc_specific = proptools.BoolPtr(true) + } else if module.DeviceSpecific() { + etcProps.Device_specific = proptools.BoolPtr(true) + } else if module.ProductSpecific() { + etcProps.Product_specific = proptools.BoolPtr(true) + } + mctx.CreateModule(android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory), &etcProps) +} + +// to satisfy SdkLibraryDependency interface +func (module *sdkLibrary) HeaderJars(linkType linkType) android.Paths { + // This module is just a wrapper for the stubs. + if linkType == javaSystem || linkType == javaPlatform { + return module.systemApiStubsPath + } else { + return module.publicApiStubsPath + } +} + +// For a java_sdk_library module, create internal modules for stubs, docs, +// runtime libs and xml file. If requested, the stubs and docs are created twice +// once for public API level and once for system API level +func sdkLibraryMutator(mctx android.TopDownMutatorContext) { + if module, ok := mctx.Module().(*sdkLibrary); ok { + // for public API stubs + module.createStubsLibrary(mctx, false) + module.createDocs(mctx, false) + + // for system API stubs + module.createStubsLibrary(mctx, true) + module.createDocs(mctx, true) + + // for runtime + module.createXmlFile(mctx) + module.createImplLibrary(mctx) + } +} + +func sdkLibraryFactory() android.Module { + module := &sdkLibrary{} + module.AddProperties(&module.properties) + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} |