1// Copyright 2018 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package xml 16 17import ( 18 "android/soong/android" 19 "android/soong/etc" 20 21 "github.com/google/blueprint" 22 "github.com/google/blueprint/proptools" 23) 24 25// prebuilt_etc_xml installs an xml file under <partition>/etc/<subdir>. 26// It also optionally validates the xml file against the schema. 27 28var ( 29 pctx = android.NewPackageContext("android/soong/xml") 30 31 xmllintDtd = pctx.AndroidStaticRule("xmllint-dtd", 32 blueprint.RuleParams{ 33 Command: `$XmlLintCmd --dtdvalid $dtd $in > /dev/null && touch -a $out`, 34 CommandDeps: []string{"$XmlLintCmd"}, 35 Restat: true, 36 }, 37 "dtd") 38 39 xmllintXsd = pctx.AndroidStaticRule("xmllint-xsd", 40 blueprint.RuleParams{ 41 Command: `$XmlLintCmd --schema $xsd $in > /dev/null && touch -a $out`, 42 CommandDeps: []string{"$XmlLintCmd"}, 43 Restat: true, 44 }, 45 "xsd") 46 47 xmllintMinimal = pctx.AndroidStaticRule("xmllint-minimal", 48 blueprint.RuleParams{ 49 Command: `$XmlLintCmd $in > /dev/null && touch -a $out`, 50 CommandDeps: []string{"$XmlLintCmd"}, 51 Restat: true, 52 }) 53) 54 55func init() { 56 registerXmlBuildComponents(android.InitRegistrationContext) 57 pctx.HostBinToolVariable("XmlLintCmd", "xmllint") 58} 59 60func registerXmlBuildComponents(ctx android.RegistrationContext) { 61 ctx.RegisterModuleType("prebuilt_etc_xml", PrebuiltEtcXmlFactory) 62} 63 64type prebuiltEtcXmlProperties struct { 65 // Optional DTD that will be used to validate the xml file. 66 Schema *string `android:"path"` 67} 68 69type prebuiltEtcXml struct { 70 etc.PrebuiltEtc 71 72 properties prebuiltEtcXmlProperties 73} 74 75func (p *prebuiltEtcXml) timestampFilePath(ctx android.ModuleContext) android.WritablePath { 76 return android.PathForModuleOut(ctx, p.PrebuiltEtc.SourceFilePath(ctx).Base()+"-timestamp") 77} 78 79func (p *prebuiltEtcXml) GenerateAndroidBuildActions(ctx android.ModuleContext) { 80 p.PrebuiltEtc.GenerateAndroidBuildActions(ctx) 81 82 if p.properties.Schema != nil { 83 schema := android.PathForModuleSrc(ctx, proptools.String(p.properties.Schema)) 84 85 switch schema.Ext() { 86 case ".dtd": 87 ctx.Build(pctx, android.BuildParams{ 88 Rule: xmllintDtd, 89 Description: "xmllint-dtd", 90 Input: p.PrebuiltEtc.SourceFilePath(ctx), 91 Output: p.timestampFilePath(ctx), 92 Implicit: schema, 93 Args: map[string]string{ 94 "dtd": schema.String(), 95 }, 96 }) 97 break 98 case ".xsd": 99 ctx.Build(pctx, android.BuildParams{ 100 Rule: xmllintXsd, 101 Description: "xmllint-xsd", 102 Input: p.PrebuiltEtc.SourceFilePath(ctx), 103 Output: p.timestampFilePath(ctx), 104 Implicit: schema, 105 Args: map[string]string{ 106 "xsd": schema.String(), 107 }, 108 }) 109 break 110 default: 111 ctx.PropertyErrorf("schema", "not supported extension: %q", schema.Ext()) 112 } 113 } else { 114 // when schema is not specified, just check if the xml is well-formed 115 ctx.Build(pctx, android.BuildParams{ 116 Rule: xmllintMinimal, 117 Description: "xmllint-minimal", 118 Input: p.PrebuiltEtc.SourceFilePath(ctx), 119 Output: p.timestampFilePath(ctx), 120 }) 121 } 122 123 p.SetAdditionalDependencies([]android.Path{p.timestampFilePath(ctx)}) 124} 125 126func PrebuiltEtcXmlFactory() android.Module { 127 module := &prebuiltEtcXml{} 128 module.AddProperties(&module.properties) 129 etc.InitPrebuiltEtcModule(&module.PrebuiltEtc, "etc") 130 // This module is device-only 131 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 132 return module 133} 134