aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Badour <bbadour@google.com>2021-03-19 19:35:42 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-03-19 19:35:42 +0000
commit6b4ddeb66c927507a191f2e8afde63d736a34de5 (patch)
tree8069784753ae22bdeec928c7d4b4fad0d7a37857
parent43743ee2ce573280c3f3413c7b2b057a5d967cc6 (diff)
parent58d85b87bc7ceba94701ee88e4bc66a757dad6f3 (diff)
downloadsoong-6b4ddeb66c927507a191f2e8afde63d736a34de5.tar.gz
Minimal license feature. am: 58d85b87bc
Original change: https://googleplex-android-review.googlesource.com/c/platform/build/soong/+/13929165 Change-Id: I49453a723ea46a2bda5d21655e569c212564c076
-rw-r--r--Android.bp4
-rw-r--r--android/license.go69
-rw-r--r--android/license_test.go150
-rw-r--r--android/module.go3
-rw-r--r--android/mutator.go1
-rw-r--r--android/package.go93
-rw-r--r--android/package_test.go110
7 files changed, 430 insertions, 0 deletions
diff --git a/Android.bp b/Android.bp
index 91a49814b..959cbf1ce 100644
--- a/Android.bp
+++ b/Android.bp
@@ -50,6 +50,7 @@ bootstrap_go_package {
"android/expand.go",
"android/filegroup.go",
"android/hooks.go",
+ "android/license.go",
"android/makevars.go",
"android/module.go",
"android/mutator.go",
@@ -58,6 +59,7 @@ bootstrap_go_package {
"android/notices.go",
"android/onceper.go",
"android/override_module.go",
+ "android/package.go",
"android/package_ctx.go",
"android/path_properties.go",
"android/paths.go",
@@ -81,10 +83,12 @@ bootstrap_go_package {
"android/arch_test.go",
"android/config_test.go",
"android/expand_test.go",
+ "android/license_test.go",
"android/namespace_test.go",
"android/neverallow_test.go",
"android/onceper_test.go",
"android/path_properties_test.go",
+ "android/package_test.go",
"android/paths_test.go",
"android/prebuilt_test.go",
"android/prebuilt_etc_test.go",
diff --git a/android/license.go b/android/license.go
new file mode 100644
index 000000000..6a7c31338
--- /dev/null
+++ b/android/license.go
@@ -0,0 +1,69 @@
+// Copyright 2020 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 (
+ "github.com/google/blueprint"
+)
+
+func init() {
+ RegisterModuleType("license", LicenseFactory)
+}
+
+type licenseProperties struct {
+ // Specifies the kinds of license that apply.
+ License_kinds []string
+ // Specifies a short copyright notice to use for the license.
+ Copyright_notice *string
+ // Specifies the path or label for the text of the license.
+ License_text []string `android:"path"`
+ // Specifies the package name to which the license applies.
+ Package_name *string
+ // Specifies where this license can be used
+ Visibility []string
+}
+
+type licenseModule struct {
+ ModuleBase
+ DefaultableModuleBase
+
+ properties licenseProperties
+}
+
+func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
+ // Do nothing.
+}
+
+func (m *licenseModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ // Nothing to do.
+}
+
+func (m *licenseModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
+ // Nothing to do.
+}
+
+func LicenseFactory() Module {
+ module := &licenseModule{}
+
+ base := module.base()
+ module.AddProperties(
+ &base.nameProperties,
+ &module.properties)
+
+ base.generalProperties = module.GetProperties()
+ base.customizableProperties = module.GetProperties()
+
+ return module
+}
diff --git a/android/license_test.go b/android/license_test.go
new file mode 100644
index 000000000..cd2cb64ff
--- /dev/null
+++ b/android/license_test.go
@@ -0,0 +1,150 @@
+package android
+
+import (
+ "io/ioutil"
+ "os"
+ "testing"
+)
+
+var licenseTests = []struct {
+ name string
+ fs map[string][]byte
+ expectedErrors []string
+}{
+ {
+ name: "license must not accept licenses property",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license {
+ name: "top_license",
+ visibility: ["//visibility:private"],
+ licenses: ["other_license"],
+
+ }`),
+ },
+ expectedErrors: []string{
+ `top/Blueprints:5:14: unrecognized property "licenses"`,
+ },
+ },
+ {
+ name: "public license",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license {
+ name: "top_proprietary",
+ license_kinds: ["top_by_exception_only"],
+ visibility: ["//visibility:public"],
+ }`),
+ "other/Blueprints": []byte(`
+ rule {
+ name: "arule",
+ licenses: ["top_proprietary"],
+
+ }`),
+ "yetmore/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["top_proprietary"],
+ }`),
+ },
+ },
+ {
+ name: "multiple licenses",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["top_proprietary"],
+ }
+ license {
+ name: "top_allowed_as_notice",
+ license_kinds: ["top_notice"],
+ }
+ license {
+ name: "top_proprietary",
+ license_kinds: ["top_by_exception_only"],
+ visibility: ["//visibility:public"],
+ }
+ rule {
+ name: "myrule",
+ licenses: ["top_allowed_as_notice", "top_proprietary"]
+ }`),
+ "other/Blueprints": []byte(`
+ rule {
+ name: "arule",
+ licenses: ["top_proprietary"],
+
+ }`),
+ "yetmore/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["top_proprietary"],
+ }`),
+ },
+ },
+}
+
+func TestLicense(t *testing.T) {
+ for _, test := range licenseTests {
+ t.Run(test.name, func(t *testing.T) {
+ _, errs := testLicense(test.fs)
+ expectedErrors := test.expectedErrors
+ if expectedErrors == nil {
+ FailIfErrored(t, errs)
+ } else {
+ for _, expectedError := range expectedErrors {
+ FailIfNoMatchingErrors(t, expectedError, errs)
+ }
+ if len(errs) > len(expectedErrors) {
+ t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
+ for i, expectedError := range expectedErrors {
+ t.Errorf("expectedErrors[%d] = %s", i, expectedError)
+ }
+ for i, err := range errs {
+ t.Errorf("errs[%d] = %s", i, err)
+ }
+ }
+ }
+ })
+ }
+}
+func testLicense(fs map[string][]byte) (*TestContext, []error) {
+ buildDir, err := ioutil.TempDir("", "license_test")
+ if err != nil {
+ return nil, []error{err}
+ }
+ defer os.RemoveAll(buildDir)
+
+ // Create a new config per test as visibility information is stored in the config.
+ env := make(map[string]string)
+ env["ANDROID_REQUIRE_LICENSES"] = "1"
+ config := TestArchConfig(buildDir, env)
+ ctx := NewTestArchContext()
+ ctx.MockFileSystem(fs)
+ ctx.RegisterModuleType("package", ModuleFactoryAdaptor(PackageFactory))
+ ctx.RegisterModuleType("license", ModuleFactoryAdaptor(LicenseFactory))
+ ctx.RegisterModuleType("rule", ModuleFactoryAdaptor(newMockRuleModule))
+ ctx.PreArchMutators(registerPackageRenamer)
+ ctx.Register()
+ _, errs := ctx.ParseBlueprintsFiles(".")
+ if len(errs) > 0 {
+ return ctx, errs
+ }
+ _, errs = ctx.PrepareBuildActions(config)
+ return ctx, errs
+}
+
+type mockRuleModule struct {
+ ModuleBase
+ DefaultableModuleBase
+}
+
+func newMockRuleModule() Module {
+ m := &mockRuleModule{}
+ InitAndroidModule(m)
+ InitDefaultableModule(m)
+ return m
+}
+
+func (p *mockRuleModule) GenerateAndroidBuildActions(ModuleContext) {
+}
+
+func (p *mockRuleModule) DepsMutator(BottomUpMutatorContext) {
+}
diff --git a/android/module.go b/android/module.go
index d34916fc4..7f4e30817 100644
--- a/android/module.go
+++ b/android/module.go
@@ -208,6 +208,9 @@ type commonProperties struct {
// emit build rules for this module
Enabled *bool `android:"arch_variant"`
+ // Names of the licenses that apply to this module.
+ Licenses []string
+
// control whether this module compiles for 32-bit, 64-bit, or both. Possible values
// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
diff --git a/android/mutator.go b/android/mutator.go
index e003f0bbe..68ba6f476 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -77,6 +77,7 @@ var preArch = []RegisterMutatorFunc{
ctx.TopDown("load_hooks", LoadHookMutator).Parallel()
},
RegisterNamespaceMutator,
+ registerPackageRenamer,
RegisterPrebuiltsPreArchMutators,
RegisterDefaultsPreArchMutators,
RegisterOverridePreArchMutators,
diff --git a/android/package.go b/android/package.go
new file mode 100644
index 000000000..6949c4e2d
--- /dev/null
+++ b/android/package.go
@@ -0,0 +1,93 @@
+// Copyright 2019 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"
+ "sync/atomic"
+
+ "github.com/google/blueprint"
+)
+
+func init() {
+ RegisterModuleType("package", PackageFactory)
+}
+
+type packageProperties struct {
+ // Specifies the default visibility for all modules defined in this package.
+ Default_visibility []string
+ // Specifies the names of the default licenses for all modules defined in this package.
+ Default_applicable_licenses []string
+}
+
+type packageModule struct {
+ ModuleBase
+
+ properties packageProperties
+ // The module dir
+ name string `blueprint:"mutated"`
+}
+
+func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) {
+ // Nothing to do.
+}
+
+func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
+ // Nothing to do.
+}
+
+func (p *packageModule) DepsMutator(ctx BottomUpMutatorContext) {
+ // Nothing to do.
+}
+
+func (p *packageModule) Name() string {
+ return p.name
+}
+
+func registerPackageRenamer(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("packages", packageRenamer).Parallel()
+}
+
+// packageRenamer ensures that every package gets named
+func packageRenamer(ctx BottomUpMutatorContext) {
+ if p, ok := ctx.Module().(*packageModule); ok {
+ p.name = "//" + ctx.ModuleDir()
+ ctx.Rename("//" + ctx.ModuleDir())
+ }
+}
+
+// Counter to ensure package modules are created with a unique name within whatever namespace they
+// belong.
+var packageCount uint32 = 0
+
+func PackageFactory() Module {
+ module := &packageModule{}
+
+ // Get a unique if for the package. Has to be done atomically as the creation of the modules are
+ // done in parallel.
+ id := atomic.AddUint32(&packageCount, 1)
+ module.name = fmt.Sprintf("soong_package_%d", id)
+
+ module.AddProperties(&module.properties)
+
+ // The name is the relative path from build root to the directory containing this
+ // module. Set that name at the earliest possible moment that information is available
+ // which is in a LoadHook.
+ AddLoadHook(module, func(ctx LoadHookContext) {
+ module.name = "//" + ctx.ModuleDir()
+ })
+
+ return module
+}
diff --git a/android/package_test.go b/android/package_test.go
new file mode 100644
index 000000000..c7e9c553f
--- /dev/null
+++ b/android/package_test.go
@@ -0,0 +1,110 @@
+package android
+
+import (
+ "io/ioutil"
+ "os"
+ "testing"
+)
+
+var packageTests = []struct {
+ name string
+ fs map[string][]byte
+ expectedErrors []string
+}{
+ // Package default_visibility handling is tested in visibility_test.go
+ {
+ name: "package must not accept visibility and name properties",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ name: "package",
+ visibility: ["//visibility:private"],
+ }`),
+ },
+ expectedErrors: []string{
+ `top/Blueprints:3:10: unrecognized property "name"`,
+ `top/Blueprints:4:16: unrecognized property "visibility"`,
+ },
+ },
+ {
+ name: "multiple packages in separate directories",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ }`),
+ "other/Blueprints": []byte(`
+ package {
+ }`),
+ "other/nested/Blueprints": []byte(`
+ package {
+ }`),
+ },
+ },
+ {
+ name: "package must not be specified more than once per package",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ default_visibility: ["//visibility:private"],
+ default_applicable_licenses: ["license"],
+ }
+
+ package {
+ }`),
+ },
+ expectedErrors: []string{
+ `"//top" conflicts with existing module`,
+ },
+ },
+}
+
+func TestPackage(t *testing.T) {
+ for _, test := range packageTests {
+ t.Run(test.name, func(t *testing.T) {
+ _, errs := testPackage(test.fs)
+
+ expectedErrors := test.expectedErrors
+ if expectedErrors == nil {
+ FailIfErrored(t, errs)
+ } else {
+ for _, expectedError := range expectedErrors {
+ FailIfNoMatchingErrors(t, expectedError, errs)
+ }
+ if len(errs) > len(expectedErrors) {
+ t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
+ for i, expectedError := range expectedErrors {
+ t.Errorf("expectedErrors[%d] = %s", i, expectedError)
+ }
+ for i, err := range errs {
+ t.Errorf("errs[%d] = %s", i, err)
+ }
+ }
+ }
+ })
+ }
+}
+
+func testPackage(fs map[string][]byte) (*TestContext, []error) {
+ buildDir, err := ioutil.TempDir("", "package_test")
+ if err != nil {
+ return nil, []error{err}
+ }
+ defer os.RemoveAll(buildDir)
+
+ // Create a new config per test as visibility information is stored in the config.
+ config := TestArchConfig(buildDir, nil)
+
+ ctx := NewTestArchContext()
+ ctx.MockFileSystem(fs)
+ ctx.RegisterModuleType("package", ModuleFactoryAdaptor(PackageFactory))
+ ctx.PreArchMutators(registerPackageRenamer)
+ ctx.Register()
+
+ _, errs := ctx.ParseBlueprintsFiles(".")
+ if len(errs) > 0 {
+ return ctx, errs
+ }
+
+ _, errs = ctx.PrepareBuildActions(config)
+ return ctx, errs
+}