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 20 "github.com/google/blueprint" 21 "github.com/google/blueprint/proptools" 22) 23 24// prebuilt_etc_xml installs an xml file under <partition>/etc/<subdir>. 25// It also optionally validates the xml file against the schema. 26 27var ( 28 pctx = android.NewPackageContext("android/soong/xml") 29 30 xmllintDtd = pctx.AndroidStaticRule("xmllint-dtd", 31 blueprint.RuleParams{ 32 Command: `$XmlLintCmd --dtdvalid $dtd $in > /dev/null && touch -a $out`, 33 CommandDeps: []string{"$XmlLintCmd"}, 34 Restat: true, 35 }, 36 "dtd") 37 38 xmllintXsd = pctx.AndroidStaticRule("xmllint-xsd", 39 blueprint.RuleParams{ 40 Command: `$XmlLintCmd --schema $xsd $in > /dev/null && touch -a $out`, 41 CommandDeps: []string{"$XmlLintCmd"}, 42 Restat: true, 43 }, 44 "xsd") 45 46 xmllintMinimal = pctx.AndroidStaticRule("xmllint-minimal", 47 blueprint.RuleParams{ 48 Command: `$XmlLintCmd $in > /dev/null && touch -a $out`, 49 CommandDeps: []string{"$XmlLintCmd"}, 50 Restat: true, 51 }) 52) 53 54func init() { 55 android.RegisterModuleType("prebuilt_etc_xml", PrebuiltEtcXmlFactory) 56 pctx.HostBinToolVariable("XmlLintCmd", "xmllint") 57} 58 59type prebuiltEtcXmlProperties struct { 60 // Optional DTD that will be used to validate the xml file. 61 Schema *string `android:"path"` 62} 63 64type prebuiltEtcXml struct { 65 android.PrebuiltEtc 66 67 properties prebuiltEtcXmlProperties 68} 69 70func (p *prebuiltEtcXml) timestampFilePath(ctx android.ModuleContext) android.WritablePath { 71 return android.PathForModuleOut(ctx, p.PrebuiltEtc.SourceFilePath(ctx).Base()+"-timestamp") 72} 73 74func (p *prebuiltEtcXml) DepsMutator(ctx android.BottomUpMutatorContext) { 75 p.PrebuiltEtc.DepsMutator(ctx) 76} 77 78func (p *prebuiltEtcXml) GenerateAndroidBuildActions(ctx android.ModuleContext) { 79 p.PrebuiltEtc.GenerateAndroidBuildActions(ctx) 80 81 if p.properties.Schema != nil { 82 schema := android.PathForModuleSrc(ctx, proptools.String(p.properties.Schema)) 83 84 switch schema.Ext() { 85 case ".dtd": 86 ctx.Build(pctx, android.BuildParams{ 87 Rule: xmllintDtd, 88 Description: "xmllint-dtd", 89 Input: p.PrebuiltEtc.SourceFilePath(ctx), 90 Output: p.timestampFilePath(ctx), 91 Implicit: schema, 92 Args: map[string]string{ 93 "dtd": schema.String(), 94 }, 95 }) 96 break 97 case ".xsd": 98 ctx.Build(pctx, android.BuildParams{ 99 Rule: xmllintXsd, 100 Description: "xmllint-xsd", 101 Input: p.PrebuiltEtc.SourceFilePath(ctx), 102 Output: p.timestampFilePath(ctx), 103 Implicit: schema, 104 Args: map[string]string{ 105 "xsd": schema.String(), 106 }, 107 }) 108 break 109 default: 110 ctx.PropertyErrorf("schema", "not supported extension: %q", schema.Ext()) 111 } 112 } else { 113 // when schema is not specified, just check if the xml is well-formed 114 ctx.Build(pctx, android.BuildParams{ 115 Rule: xmllintMinimal, 116 Description: "xmllint-minimal", 117 Input: p.PrebuiltEtc.SourceFilePath(ctx), 118 Output: p.timestampFilePath(ctx), 119 }) 120 } 121 122 p.SetAdditionalDependencies([]android.Path{p.timestampFilePath(ctx)}) 123} 124 125func PrebuiltEtcXmlFactory() android.Module { 126 module := &prebuiltEtcXml{} 127 module.AddProperties(&module.properties) 128 129 android.InitPrebuiltEtcModule(&module.PrebuiltEtc) 130 // This module is device-only 131 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) 132 return module 133} 134