Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a8d1bee authored by Jiyong Park's avatar Jiyong Park
Browse files

Add prebuilt_etc_xml

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
parent aac4b84c
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -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
//
+37 −25
Original line number Diff line number Diff line
@@ -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
	additionalDependencies *Paths
}

func (p *prebuiltEtc) Prebuilt() *Prebuilt {
	return &p.prebuilt
func (p *PrebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) {
	if p.properties.Src == nil {
		ctx.PropertyErrorf("src", "missing prebuilt source file")
	}

func (p *prebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) {
	if len(p.properties.Srcs) == 0 {
		ctx.PropertyErrorf("srcs", "missing prebuilt source file")
	// To support ":modulename" in src
	ExtractSourceDeps(ctx, p.properties.Src)
}

	if len(p.properties.Srcs) > 1 {
		ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
func (p *PrebuiltEtc) SourceFilePath(ctx ModuleContext) Path {
	return ctx.ExpandSource(String(p.properties.Src), "src")
}

	// To support ":modulename" in src
	ExtractSourceDeps(ctx, &(p.properties.Srcs)[0])
// 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(p.properties.Srcs[0], "srcs")
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
}
+1 −1
Original line number Diff line number Diff line
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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)

xml/xml.go

0 → 100644
+136 −0
Original line number Diff line number Diff line
// 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
}
Loading