aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiyong Park <jiyong@google.com>2018-04-25 22:57:34 +0900
committerJiyong Park <jiyong@google.com>2018-04-28 00:13:00 +0900
commit5a8d1bee89af690ea9383252e7b509fa7a06665d (patch)
tree29c461f6ef3a62d5121cd89210b228797c51a526
parentaac4b84ce5d72c37cd892f1713fcfceab5ee96bb (diff)
downloadbuild_soong-5a8d1bee89af690ea9383252e7b509fa7a06665d.tar.gz
build_soong-5a8d1bee89af690ea9383252e7b509fa7a06665d.tar.bz2
build_soong-5a8d1bee89af690ea9383252e7b509fa7a06665d.zip
prebuilt_etc_xml installs an xml file to <partition>/etc[/<subdir>] and validates the xml file against the given DTD file before installing it. This change also includes some fixes for prebuilt_etc which is the super module of prebuilt_etc_xml: 1) The module is changed to arch-specific module as the prebuilts are only for devices (installed under the etc dir), but not for hosts. 2) Dependency to android.Prebuilt is removed because android.Prebuilt is intended to be used for the case when a module can exist as prebuilts, source or both. These prebuilt_etc_* modules are prebuilt only. 3) srcs property which accepts a list of source files is changed to src that only accepts single source file, which makes more sense for prebuilts. Bug: 65686190 Test: m -j (xml_test.go) Change-Id: I40484f3f6615b99f6b8d43176db0c40c5bfd838e
-rw-r--r--Android.bp18
-rw-r--r--android/prebuilt_etc.go62
-rw-r--r--java/java_test.go2
-rw-r--r--java/sdk_library.go4
-rw-r--r--xml/xml.go136
-rw-r--r--xml/xml_test.go86
6 files changed, 280 insertions, 28 deletions
diff --git a/Android.bp b/Android.bp
index aa652096..4a06a113 100644
--- a/Android.bp
+++ b/Android.bp
@@ -291,6 +291,24 @@ bootstrap_go_package {
],
}
+bootstrap_go_package {
+ name: "soong-xml",
+ pkgPath: "android/soong/xml",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "soong",
+ "soong-android",
+ ],
+ srcs: [
+ "xml/xml.go",
+ ],
+ testSrcs: [
+ "xml/xml_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
+
//
// Defaults to enable various configurations of host bionic
//
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index fee2c494..55a72a6a 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -28,45 +28,47 @@ func init() {
type prebuiltEtcProperties struct {
// Source file of this prebuilt.
- Srcs []string `android:"arch_variant"`
+ Src *string `android:"arch_variant"`
// optional subdirectory under which this file is installed into
Sub_dir *string `android:"arch_variant"`
}
-type prebuiltEtc struct {
+type PrebuiltEtc struct {
ModuleBase
- prebuilt Prebuilt
properties prebuiltEtcProperties
- sourceFilePath Path
- installDirPath OutputPath
+ sourceFilePath Path
+ installDirPath OutputPath
+ additionalDependencies *Paths
}
-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")
+func (p *PrebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) {
+ if p.properties.Src == nil {
+ ctx.PropertyErrorf("src", "missing prebuilt source file")
}
// To support ":modulename" in src
- ExtractSourceDeps(ctx, &(p.properties.Srcs)[0])
+ ExtractSourceDeps(ctx, p.properties.Src)
+}
+
+func (p *PrebuiltEtc) SourceFilePath(ctx ModuleContext) Path {
+ return ctx.ExpandSource(String(p.properties.Src), "src")
}
-func (p *prebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
- p.sourceFilePath = ctx.ExpandSource(p.properties.Srcs[0], "srcs")
+// This allows other derivative modules (e.g. prebuilt_etc_xml) to perform
+// additional steps (like validating the src) before the file is installed.
+func (p *PrebuiltEtc) SetAdditionalDependencies(paths Paths) {
+ p.additionalDependencies = &paths
+}
+
+func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
+ p.sourceFilePath = ctx.ExpandSource(String(p.properties.Src), "src")
p.installDirPath = PathForModuleInstall(ctx, "etc", String(p.properties.Sub_dir))
}
-func (p *prebuiltEtc) AndroidMk() AndroidMkData {
+func (p *PrebuiltEtc) AndroidMk() AndroidMkData {
return AndroidMkData{
Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
@@ -76,16 +78,26 @@ func (p *prebuiltEtc) AndroidMk() AndroidMkData {
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())
+ if p.additionalDependencies != nil {
+ fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
+ for _, path := range *p.additionalDependencies {
+ fmt.Fprint(w, " "+path.String())
+ }
+ fmt.Fprintln(w, "")
+ }
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
},
}
}
-func PrebuiltEtcFactory() Module {
- module := &prebuiltEtc{}
- module.AddProperties(&module.properties)
+func InitPrebuiltEtcModule(p *PrebuiltEtc) {
+ p.AddProperties(&p.properties)
+}
- InitPrebuiltModule(module, &(module.properties.Srcs))
- InitAndroidModule(module)
+func PrebuiltEtcFactory() Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module)
+ // This module is device-only
+ InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
return module
}
diff --git a/java/java_test.go b/java/java_test.go
index de514e04..ea524962 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1040,7 +1040,7 @@ func TestJavaSdkLibrary(t *testing.T) {
ctx.ModuleForTests("foo"+sdkDocsSuffix, "android_common")
ctx.ModuleForTests("foo"+sdkDocsSuffix+sdkSystemApiSuffix, "android_common")
ctx.ModuleForTests("foo"+sdkImplLibrarySuffix, "android_common")
- ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "")
+ ctx.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common")
bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
// tests if baz is actually linked to the stubs lib
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 13a9275c..2396467f 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -407,14 +407,14 @@ func (module *sdkLibrary) createXmlFile(mctx android.TopDownMutatorContext) {
// <partition>/etc/permissions
etcProps := struct {
Name *string
- Srcs []string
+ Src *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.Src = proptools.StringPtr(":" + module.xmlFileName() + "-gen")
etcProps.Sub_dir = proptools.StringPtr("permissions")
if module.SocSpecific() {
etcProps.Soc_specific = proptools.BoolPtr(true)
diff --git a/xml/xml.go b/xml/xml.go
new file mode 100644
index 00000000..218d73ce
--- /dev/null
+++ b/xml/xml.go
@@ -0,0 +1,136 @@
+// 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 xml
+
+import (
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+// prebuilt_etc_xml installs an xml file under <partition>/etc/<subdir>.
+// It also optionally validates the xml file against the schema.
+
+var (
+ pctx = android.NewPackageContext("android/soong/xml")
+
+ xmllintDtd = pctx.AndroidStaticRule("xmllint-dtd",
+ blueprint.RuleParams{
+ Command: `$XmlLintCmd --dtdvalid $dtd $in > /dev/null && touch -a $out`,
+ CommandDeps: []string{"$XmlLintCmd"},
+ Restat: true,
+ },
+ "dtd")
+
+ xmllintXsd = pctx.AndroidStaticRule("xmllint-xsd",
+ blueprint.RuleParams{
+ Command: `$XmlLintCmd --schema $xsd $in > /dev/null && touch -a $out`,
+ CommandDeps: []string{"$XmlLintCmd"},
+ Restat: true,
+ },
+ "xsd")
+
+ xmllintMinimal = pctx.AndroidStaticRule("xmllint-minimal",
+ blueprint.RuleParams{
+ Command: `$XmlLintCmd $in > /dev/null && touch -a $out`,
+ CommandDeps: []string{"$XmlLintCmd"},
+ Restat: true,
+ })
+)
+
+func init() {
+ android.RegisterModuleType("prebuilt_etc_xml", PrebuiltEtcXmlFactory)
+ pctx.HostBinToolVariable("XmlLintCmd", "xmllint")
+}
+
+type prebuiltEtcXmlProperties struct {
+ // Optional DTD that will be used to validate the xml file.
+ Schema *string
+}
+
+type prebuiltEtcXml struct {
+ android.PrebuiltEtc
+
+ properties prebuiltEtcXmlProperties
+}
+
+func (p *prebuiltEtcXml) timestampFilePath(ctx android.ModuleContext) android.WritablePath {
+ return android.PathForModuleOut(ctx, p.PrebuiltEtc.SourceFilePath(ctx).Base()+"-timestamp")
+}
+
+func (p *prebuiltEtcXml) DepsMutator(ctx android.BottomUpMutatorContext) {
+ p.PrebuiltEtc.DepsMutator(ctx)
+
+ // To support ":modulename" in schema
+ android.ExtractSourceDeps(ctx, p.properties.Schema)
+}
+
+func (p *prebuiltEtcXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ p.PrebuiltEtc.GenerateAndroidBuildActions(ctx)
+
+ if p.properties.Schema != nil {
+ schema := ctx.ExpandSource(proptools.String(p.properties.Schema), "schema")
+
+ switch schema.Ext() {
+ case ".dtd":
+ ctx.Build(pctx, android.BuildParams{
+ Rule: xmllintDtd,
+ Description: "xmllint-dtd",
+ Input: p.PrebuiltEtc.SourceFilePath(ctx),
+ Output: p.timestampFilePath(ctx),
+ Implicit: schema,
+ Args: map[string]string{
+ "dtd": schema.String(),
+ },
+ })
+ break
+ case ".xsd":
+ ctx.Build(pctx, android.BuildParams{
+ Rule: xmllintXsd,
+ Description: "xmllint-xsd",
+ Input: p.PrebuiltEtc.SourceFilePath(ctx),
+ Output: p.timestampFilePath(ctx),
+ Implicit: schema,
+ Args: map[string]string{
+ "xsd": schema.String(),
+ },
+ })
+ break
+ default:
+ ctx.PropertyErrorf("schema", "not supported extension: %q", schema.Ext())
+ }
+ } else {
+ // when schema is not specified, just check if the xml is well-formed
+ ctx.Build(pctx, android.BuildParams{
+ Rule: xmllintMinimal,
+ Description: "xmllint-minimal",
+ Input: p.PrebuiltEtc.SourceFilePath(ctx),
+ Output: p.timestampFilePath(ctx),
+ })
+ }
+
+ p.SetAdditionalDependencies([]android.Path{p.timestampFilePath(ctx)})
+}
+
+func PrebuiltEtcXmlFactory() android.Module {
+ module := &prebuiltEtcXml{}
+ module.AddProperties(&module.properties)
+
+ android.InitPrebuiltEtcModule(&module.PrebuiltEtc)
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
diff --git a/xml/xml_test.go b/xml/xml_test.go
new file mode 100644
index 00000000..e8fa49c2
--- /dev/null
+++ b/xml/xml_test.go
@@ -0,0 +1,86 @@
+// 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 xml
+
+import (
+ "android/soong/android"
+ "io/ioutil"
+ "os"
+ "testing"
+)
+
+func testXml(t *testing.T, bp string) *android.TestContext {
+ config, buildDir := setup(t)
+ defer teardown(buildDir)
+ ctx := android.NewTestArchContext()
+ ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
+ ctx.RegisterModuleType("prebuilt_etc_xml", android.ModuleFactoryAdaptor(PrebuiltEtcXmlFactory))
+ ctx.Register()
+ mockFiles := map[string][]byte{
+ "Android.bp": []byte(bp),
+ "foo.xml": nil,
+ "foo.dtd": nil,
+ "bar.xml": nil,
+ "bar.xsd": nil,
+ }
+ ctx.MockFileSystem(mockFiles)
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ return ctx
+}
+
+func setup(t *testing.T) (config android.Config, buildDir string) {
+ buildDir, err := ioutil.TempDir("", "soong_xml_test")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ config = android.TestArchConfig(buildDir, nil)
+
+ return
+}
+
+func teardown(buildDir string) {
+ os.RemoveAll(buildDir)
+}
+
+// Minimal test
+func TestPrebuiltEtcXml(t *testing.T) {
+ ctx := testXml(t, `
+ prebuilt_etc_xml {
+ name: "foo.xml",
+ src: "foo.xml",
+ schema: "foo.dtd",
+ }
+ prebuilt_etc_xml {
+ name: "bar.xml",
+ src: "bar.xml",
+ schema: "bar.xsd",
+ }
+ `)
+
+ xmllint := ctx.ModuleForTests("foo.xml", "android_common").Rule("xmllint")
+ input := xmllint.Input.String()
+ if input != "foo.xml" {
+ t.Errorf("input expected %q != got %q", "foo.xml", input)
+ }
+ schema := xmllint.Args["dtd"]
+ if schema != "foo.dtd" {
+ t.Errorf("dtd expected %q != got %q", "foo.dtdl", schema)
+ }
+}