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 xsdc 16 17import ( 18 "android/soong/android" 19 "android/soong/java" 20 "path/filepath" 21 "strings" 22 23 "github.com/google/blueprint" 24 "github.com/google/blueprint/proptools" 25) 26 27func init() { 28 pctx.Import("android/soong/java/config") 29 android.RegisterModuleType("xsd_config", xsdConfigFactory) 30 31 android.PreArchMutators(func(ctx android.RegisterMutatorsContext) { 32 ctx.TopDown("xsd_config", xsdConfigMutator).Parallel() 33 }) 34} 35 36var ( 37 pctx = android.NewPackageContext("android/xsdc") 38 39 xsdc = pctx.HostBinToolVariable("xsdcCmd", "xsdc") 40 xsdcJavaRule = pctx.StaticRule("xsdcJavaRule", blueprint.RuleParams{ 41 Command: `rm -rf "${out}.temp" && mkdir -p "${out}.temp" && ` + 42 `${xsdcCmd} $in -p $pkgName -o ${out}.temp -j $args && ` + 43 `${config.SoongZipCmd} -jar -o ${out} -C ${out}.temp -D ${out}.temp && ` + 44 `rm -rf ${out}.temp`, 45 CommandDeps: []string{"${xsdcCmd}", "${config.SoongZipCmd}"}, 46 Description: "xsdc Java ${in} => ${out}", 47 }, "pkgName", "args") 48 49 xsdcCppRule = pctx.StaticRule("xsdcCppRule", blueprint.RuleParams{ 50 Command: `rm -rf "${outDir}" && ` + 51 `${xsdcCmd} $in -p $pkgName -o ${outDir} -c $args`, 52 CommandDeps: []string{"${xsdcCmd}", "${config.SoongZipCmd}"}, 53 Description: "xsdc C++ ${in} => ${out}", 54 }, "pkgName", "outDir", "args") 55 56 xsdConfigRule = pctx.StaticRule("xsdConfigRule", blueprint.RuleParams{ 57 Command: "cp -f ${in} ${output}", 58 Description: "copy the xsd file: ${in} => ${output}", 59 }, "output") 60) 61 62type xsdConfigProperties struct { 63 Srcs []string 64 Package_name *string 65 Api_dir *string 66 Gen_writer *bool 67 Nullability *bool 68 69 // Whether has{element or atrribute} methods are set to public. 70 // It is not applied to C++, because these methods are always 71 // generated to public for C++. 72 Gen_has *bool 73 // Only generate code for enum converters. Applies to C++ only. 74 // This is useful for memory footprint reduction since it avoids 75 // depending on libxml2. 76 Enums_only *bool 77 // Only generate complementary code for XML parser. Applies to C++ only. 78 // The code being generated depends on the enum converters module. 79 Parser_only *bool 80 // Whether getter name of boolean element or attribute is getX or isX. 81 // Default value is false. If the property is true, getter name is isX. 82 Boolean_getter *bool 83} 84 85type xsdConfig struct { 86 android.ModuleBase 87 88 properties xsdConfigProperties 89 90 genOutputDir android.Path 91 genOutputs_j android.WritablePath 92 genOutputs_c android.WritablePaths 93 genOutputs_h android.WritablePaths 94 95 docsPath android.Path 96 97 xsdConfigPath android.OptionalPath 98 genOutputs android.Paths 99} 100 101var _ android.SourceFileProducer = (*xsdConfig)(nil) 102 103type ApiToCheck struct { 104 Api_file *string 105 Removed_api_file *string 106 Args *string 107} 108 109type CheckApi struct { 110 Last_released ApiToCheck 111 Current ApiToCheck 112} 113type DroidstubsProperties struct { 114 Name *string 115 Installable *bool 116 Srcs []string 117 Sdk_version *string 118 Args *string 119 Api_filename *string 120 Removed_api_filename *string 121 Check_api CheckApi 122} 123 124func (module *xsdConfig) GeneratedSourceFiles() android.Paths { 125 return module.genOutputs_c.Paths() 126} 127 128func (module *xsdConfig) Srcs() android.Paths { 129 return append(module.genOutputs, module.genOutputs_j) 130} 131 132func (module *xsdConfig) GeneratedDeps() android.Paths { 133 return module.genOutputs_h.Paths() 134} 135 136func (module *xsdConfig) GeneratedHeaderDirs() android.Paths { 137 return android.Paths{module.genOutputDir} 138} 139 140func (module *xsdConfig) DepsMutator(ctx android.BottomUpMutatorContext) { 141 android.ExtractSourcesDeps(ctx, module.properties.Srcs) 142} 143 144func (module *xsdConfig) generateXsdConfig(ctx android.ModuleContext) { 145 if !module.xsdConfigPath.Valid() { 146 return 147 } 148 149 output := android.PathForModuleGen(ctx, module.Name()+".xsd") 150 module.genOutputs = append(module.genOutputs, output) 151 152 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 153 Rule: xsdConfigRule, 154 Input: module.xsdConfigPath.Path(), 155 Output: output, 156 Args: map[string]string{ 157 "output": output.String(), 158 }, 159 }) 160} 161 162func (module *xsdConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { 163 if len(module.properties.Srcs) != 1 { 164 ctx.PropertyErrorf("srcs", "xsd_config must be one src") 165 } 166 167 ctx.VisitDirectDeps(func(to android.Module) { 168 if doc, ok := to.(java.ApiFilePath); ok { 169 module.docsPath = doc.ApiFilePath() 170 } 171 }) 172 173 srcFiles := ctx.ExpandSources(module.properties.Srcs, nil) 174 xsdFile := srcFiles[0] 175 176 pkgName := *module.properties.Package_name 177 filenameStem := strings.Replace(pkgName, ".", "_", -1) 178 179 args := "" 180 if proptools.Bool(module.properties.Gen_writer) { 181 args = "-w" 182 } 183 184 if proptools.Bool(module.properties.Nullability) { 185 args = args + " -n " 186 } 187 188 if proptools.Bool(module.properties.Gen_has) { 189 args = args + " -g " 190 } 191 192 if proptools.Bool(module.properties.Enums_only) { 193 args = args + " -e " 194 } 195 196 if proptools.Bool(module.properties.Parser_only) { 197 args = args + " -x " 198 } 199 200 if proptools.Bool(module.properties.Boolean_getter) { 201 args = args + " -b " 202 } 203 204 module.genOutputs_j = android.PathForModuleGen(ctx, "java", filenameStem+"_xsdcgen.srcjar") 205 206 ctx.Build(pctx, android.BuildParams{ 207 Rule: xsdcJavaRule, 208 Description: "xsdc " + xsdFile.String(), 209 Input: xsdFile, 210 Implicit: module.docsPath, 211 Output: module.genOutputs_j, 212 Args: map[string]string{ 213 "pkgName": pkgName, 214 "args": args, 215 }, 216 }) 217 218 if proptools.Bool(module.properties.Enums_only) { 219 module.genOutputs_c = android.WritablePaths{ 220 android.PathForModuleGen(ctx, "cpp", filenameStem+"_enums.cpp")} 221 module.genOutputs_h = android.WritablePaths{ 222 android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+"_enums.h")} 223 } else if proptools.Bool(module.properties.Parser_only) { 224 module.genOutputs_c = android.WritablePaths{ 225 android.PathForModuleGen(ctx, "cpp", filenameStem+".cpp")} 226 module.genOutputs_h = android.WritablePaths{ 227 android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+".h")} 228 } else { 229 module.genOutputs_c = android.WritablePaths{ 230 android.PathForModuleGen(ctx, "cpp", filenameStem+".cpp"), 231 android.PathForModuleGen(ctx, "cpp", filenameStem+"_enums.cpp")} 232 module.genOutputs_h = android.WritablePaths{ 233 android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+".h"), 234 android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+"_enums.h")} 235 } 236 module.genOutputDir = android.PathForModuleGen(ctx, "cpp", "include") 237 238 ctx.Build(pctx, android.BuildParams{ 239 Rule: xsdcCppRule, 240 Description: "xsdc " + xsdFile.String(), 241 Input: xsdFile, 242 Implicit: module.docsPath, 243 Outputs: module.genOutputs_c, 244 ImplicitOutputs: module.genOutputs_h, 245 Args: map[string]string{ 246 "pkgName": pkgName, 247 "outDir": android.PathForModuleGen(ctx, "cpp").String(), 248 "args": args, 249 }, 250 }) 251 module.xsdConfigPath = android.ExistentPathForSource(ctx, xsdFile.String()) 252 module.generateXsdConfig(ctx) 253} 254 255func xsdConfigMutator(mctx android.TopDownMutatorContext) { 256 if module, ok := mctx.Module().(*xsdConfig); ok { 257 name := module.BaseModuleName() 258 259 args := " --stub-packages " + *module.properties.Package_name + 260 " --hide MissingPermission --hide BroadcastBehavior" + 261 " --hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol" + 262 " --hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo" 263 264 api_dir := proptools.StringDefault(module.properties.Api_dir, "api") 265 266 currentApiFileName := filepath.Join(api_dir, "current.txt") 267 removedApiFileName := filepath.Join(api_dir, "removed.txt") 268 269 check_api := CheckApi{} 270 271 check_api.Current.Api_file = proptools.StringPtr(currentApiFileName) 272 check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName) 273 274 check_api.Last_released.Api_file = proptools.StringPtr( 275 filepath.Join(api_dir, "last_current.txt")) 276 check_api.Last_released.Removed_api_file = proptools.StringPtr( 277 filepath.Join(api_dir, "last_removed.txt")) 278 279 mctx.CreateModule(java.DroidstubsFactory, &DroidstubsProperties{ 280 Name: proptools.StringPtr(name + ".docs"), 281 Srcs: []string{":" + name}, 282 Args: proptools.StringPtr(args), 283 Api_filename: proptools.StringPtr(currentApiFileName), 284 Removed_api_filename: proptools.StringPtr(removedApiFileName), 285 Check_api: check_api, 286 Installable: proptools.BoolPtr(false), 287 Sdk_version: proptools.StringPtr("core_platform"), 288 }) 289 } 290} 291 292func xsdConfigFactory() android.Module { 293 module := &xsdConfig{} 294 module.AddProperties(&module.properties) 295 android.InitAndroidModule(module) 296 297 return module 298} 299