Add prebuilt_etc_xml
am: 5a8d1bee89
Change-Id: I8b54e220fc8c926ff809fae180249dbffd8969b5
This commit is contained in:
18
Android.bp
18
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
|
||||
//
|
||||
|
@@ -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) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
p.sourceFilePath = ctx.ExpandSource(p.properties.Srcs[0], "srcs")
|
||||
func (p *PrebuiltEtc) SourceFilePath(ctx ModuleContext) Path {
|
||||
return ctx.ExpandSource(String(p.properties.Src), "src")
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
136
xml/xml.go
Normal file
136
xml/xml.go
Normal file
@@ -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
|
||||
}
|
86
xml/xml_test.go
Normal file
86
xml/xml_test.go
Normal file
@@ -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)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user