android.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. // Copyright 2017 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. package androidmk
  15. import (
  16. mkparser "android/soong/androidmk/parser"
  17. "fmt"
  18. "sort"
  19. "strings"
  20. bpparser "github.com/google/blueprint/parser"
  21. )
  22. const (
  23. clear_vars = "__android_mk_clear_vars"
  24. include_ignored = "__android_mk_include_ignored"
  25. )
  26. type bpVariable struct {
  27. name string
  28. variableType bpparser.Type
  29. }
  30. type variableAssignmentContext struct {
  31. file *bpFile
  32. prefix string
  33. mkvalue *mkparser.MakeString
  34. append bool
  35. }
  36. var rewriteProperties = map[string](func(variableAssignmentContext) error){
  37. // custom functions
  38. "LOCAL_32_BIT_ONLY": local32BitOnly,
  39. "LOCAL_AIDL_INCLUDES": localAidlIncludes,
  40. "LOCAL_ASSET_DIR": localizePathList("asset_dirs"),
  41. "LOCAL_C_INCLUDES": localIncludeDirs,
  42. "LOCAL_EXPORT_C_INCLUDE_DIRS": exportIncludeDirs,
  43. "LOCAL_JARJAR_RULES": localizePath("jarjar_rules"),
  44. "LOCAL_LDFLAGS": ldflags,
  45. "LOCAL_MODULE_CLASS": prebuiltClass,
  46. "LOCAL_MODULE_STEM": stem,
  47. "LOCAL_MODULE_HOST_OS": hostOs,
  48. "LOCAL_RESOURCE_DIR": localizePathList("resource_dirs"),
  49. "LOCAL_SANITIZE": sanitize(""),
  50. "LOCAL_SANITIZE_DIAG": sanitize("diag."),
  51. "LOCAL_STRIP_MODULE": strip(),
  52. "LOCAL_CFLAGS": cflags,
  53. "LOCAL_UNINSTALLABLE_MODULE": invert("installable"),
  54. "LOCAL_PROGUARD_ENABLED": proguardEnabled,
  55. "LOCAL_MODULE_PATH": prebuiltModulePath,
  56. // composite functions
  57. "LOCAL_MODULE_TAGS": includeVariableIf(bpVariable{"tags", bpparser.ListType}, not(valueDumpEquals("optional"))),
  58. // skip functions
  59. "LOCAL_ADDITIONAL_DEPENDENCIES": skip, // TODO: check for only .mk files?
  60. "LOCAL_CPP_EXTENSION": skip,
  61. "LOCAL_MODULE_SUFFIX": skip, // TODO
  62. "LOCAL_PATH": skip, // Nothing to do, except maybe avoid the "./" in paths?
  63. "LOCAL_PRELINK_MODULE": skip, // Already phased out
  64. "LOCAL_BUILT_MODULE_STEM": skip,
  65. "LOCAL_USE_AAPT2": skip, // Always enabled in Soong
  66. "LOCAL_JAR_EXCLUDE_FILES": skip, // Soong never excludes files from jars
  67. "LOCAL_ANNOTATION_PROCESSOR_CLASSES": skip, // Soong gets the processor classes from the plugin
  68. "LOCAL_CTS_TEST_PACKAGE": skip, // Obsolete
  69. "LOCAL_JACK_ENABLED": skip, // Obselete
  70. "LOCAL_JACK_FLAGS": skip, // Obselete
  71. }
  72. // adds a group of properties all having the same type
  73. func addStandardProperties(propertyType bpparser.Type, properties map[string]string) {
  74. for key, val := range properties {
  75. rewriteProperties[key] = includeVariable(bpVariable{val, propertyType})
  76. }
  77. }
  78. func init() {
  79. addStandardProperties(bpparser.StringType,
  80. map[string]string{
  81. "LOCAL_MODULE": "name",
  82. "LOCAL_CXX_STL": "stl",
  83. "LOCAL_MULTILIB": "compile_multilib",
  84. "LOCAL_ARM_MODE_HACK": "instruction_set",
  85. "LOCAL_SDK_VERSION": "sdk_version",
  86. "LOCAL_MIN_SDK_VERSION": "min_sdk_version",
  87. "LOCAL_NDK_STL_VARIANT": "stl",
  88. "LOCAL_JAR_MANIFEST": "manifest",
  89. "LOCAL_CERTIFICATE": "certificate",
  90. "LOCAL_PACKAGE_NAME": "name",
  91. "LOCAL_MODULE_RELATIVE_PATH": "relative_install_path",
  92. "LOCAL_PROTOC_OPTIMIZE_TYPE": "proto.type",
  93. "LOCAL_MODULE_OWNER": "owner",
  94. "LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api",
  95. "LOCAL_NOTICE_FILE": "notice",
  96. "LOCAL_JAVA_LANGUAGE_VERSION": "java_version",
  97. "LOCAL_INSTRUMENTATION_FOR": "instrumentation_for",
  98. "LOCAL_MANIFEST_FILE": "manifest",
  99. "LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING": "dex_preopt.profile",
  100. "LOCAL_TEST_CONFIG": "test_config",
  101. })
  102. addStandardProperties(bpparser.ListType,
  103. map[string]string{
  104. "LOCAL_SRC_FILES": "srcs",
  105. "LOCAL_SRC_FILES_EXCLUDE": "exclude_srcs",
  106. "LOCAL_HEADER_LIBRARIES": "header_libs",
  107. "LOCAL_SHARED_LIBRARIES": "shared_libs",
  108. "LOCAL_STATIC_LIBRARIES": "static_libs",
  109. "LOCAL_WHOLE_STATIC_LIBRARIES": "whole_static_libs",
  110. "LOCAL_SYSTEM_SHARED_LIBRARIES": "system_shared_libs",
  111. "LOCAL_ASFLAGS": "asflags",
  112. "LOCAL_CLANG_ASFLAGS": "clang_asflags",
  113. "LOCAL_COMPATIBILITY_SUPPORT_FILES": "data",
  114. "LOCAL_CONLYFLAGS": "conlyflags",
  115. "LOCAL_CPPFLAGS": "cppflags",
  116. "LOCAL_REQUIRED_MODULES": "required",
  117. "LOCAL_HOST_REQUIRED_MODULES": "host_required",
  118. "LOCAL_TARGET_REQUIRED_MODULES": "target_required",
  119. "LOCAL_OVERRIDES_MODULES": "overrides",
  120. "LOCAL_LDLIBS": "host_ldlibs",
  121. "LOCAL_CLANG_CFLAGS": "clang_cflags",
  122. "LOCAL_YACCFLAGS": "yacc.flags",
  123. "LOCAL_SANITIZE_RECOVER": "sanitize.recover",
  124. "LOCAL_LOGTAGS_FILES": "logtags",
  125. "LOCAL_EXPORT_HEADER_LIBRARY_HEADERS": "export_header_lib_headers",
  126. "LOCAL_EXPORT_SHARED_LIBRARY_HEADERS": "export_shared_lib_headers",
  127. "LOCAL_EXPORT_STATIC_LIBRARY_HEADERS": "export_static_lib_headers",
  128. "LOCAL_INIT_RC": "init_rc",
  129. "LOCAL_VINTF_FRAGMENTS": "vintf_fragments",
  130. "LOCAL_TIDY_FLAGS": "tidy_flags",
  131. // TODO: This is comma-separated, not space-separated
  132. "LOCAL_TIDY_CHECKS": "tidy_checks",
  133. "LOCAL_RENDERSCRIPT_INCLUDES": "renderscript.include_dirs",
  134. "LOCAL_RENDERSCRIPT_FLAGS": "renderscript.flags",
  135. "LOCAL_JAVA_RESOURCE_DIRS": "java_resource_dirs",
  136. "LOCAL_JAVA_RESOURCE_FILES": "java_resources",
  137. "LOCAL_JAVACFLAGS": "javacflags",
  138. "LOCAL_ERROR_PRONE_FLAGS": "errorprone.javacflags",
  139. "LOCAL_DX_FLAGS": "dxflags",
  140. "LOCAL_JAVA_LIBRARIES": "libs",
  141. "LOCAL_STATIC_JAVA_LIBRARIES": "static_libs",
  142. "LOCAL_JNI_SHARED_LIBRARIES": "jni_libs",
  143. "LOCAL_AAPT_FLAGS": "aaptflags",
  144. "LOCAL_PACKAGE_SPLITS": "package_splits",
  145. "LOCAL_COMPATIBILITY_SUITE": "test_suites",
  146. "LOCAL_OVERRIDES_PACKAGES": "overrides",
  147. "LOCAL_ANNOTATION_PROCESSORS": "plugins",
  148. "LOCAL_PROGUARD_FLAGS": "optimize.proguard_flags",
  149. "LOCAL_PROGUARD_FLAG_FILES": "optimize.proguard_flags_files",
  150. // These will be rewritten to libs/static_libs by bpfix, after their presence is used to convert
  151. // java_library_static to android_library.
  152. "LOCAL_SHARED_ANDROID_LIBRARIES": "android_libs",
  153. "LOCAL_STATIC_ANDROID_LIBRARIES": "android_static_libs",
  154. "LOCAL_ADDITIONAL_CERTIFICATES": "additional_certificates",
  155. // Jacoco filters:
  156. "LOCAL_JACK_COVERAGE_INCLUDE_FILTER": "jacoco.include_filter",
  157. "LOCAL_JACK_COVERAGE_EXCLUDE_FILTER": "jacoco.exclude_filter",
  158. "LOCAL_FULL_LIBS_MANIFEST_FILES": "additional_manifests",
  159. })
  160. addStandardProperties(bpparser.BoolType,
  161. map[string]string{
  162. // Bool properties
  163. "LOCAL_IS_HOST_MODULE": "host",
  164. "LOCAL_CLANG": "clang",
  165. "LOCAL_FORCE_STATIC_EXECUTABLE": "static_executable",
  166. "LOCAL_NATIVE_COVERAGE": "native_coverage",
  167. "LOCAL_NO_CRT": "nocrt",
  168. "LOCAL_ALLOW_UNDEFINED_SYMBOLS": "allow_undefined_symbols",
  169. "LOCAL_RTTI_FLAG": "rtti",
  170. "LOCAL_PACK_MODULE_RELOCATIONS": "pack_relocations",
  171. "LOCAL_TIDY": "tidy",
  172. "LOCAL_USE_CLANG_LLD": "use_clang_lld",
  173. "LOCAL_PROPRIETARY_MODULE": "proprietary",
  174. "LOCAL_VENDOR_MODULE": "vendor",
  175. "LOCAL_ODM_MODULE": "device_specific",
  176. "LOCAL_PRODUCT_MODULE": "product_specific",
  177. "LOCAL_SYSTEM_EXT_MODULE": "system_ext_specific",
  178. "LOCAL_EXPORT_PACKAGE_RESOURCES": "export_package_resources",
  179. "LOCAL_PRIVILEGED_MODULE": "privileged",
  180. "LOCAL_AAPT_INCLUDE_ALL_RESOURCES": "aapt_include_all_resources",
  181. "LOCAL_DONT_MERGE_MANIFESTS": "dont_merge_manifests",
  182. "LOCAL_USE_EMBEDDED_NATIVE_LIBS": "use_embedded_native_libs",
  183. "LOCAL_USE_EMBEDDED_DEX": "use_embedded_dex",
  184. "LOCAL_DEX_PREOPT": "dex_preopt.enabled",
  185. "LOCAL_DEX_PREOPT_APP_IMAGE": "dex_preopt.app_image",
  186. "LOCAL_DEX_PREOPT_GENERATE_PROFILE": "dex_preopt.profile_guided",
  187. "LOCAL_PRIVATE_PLATFORM_APIS": "platform_apis",
  188. "LOCAL_JETIFIER_ENABLED": "jetifier",
  189. })
  190. }
  191. type listSplitFunc func(bpparser.Expression) (string, bpparser.Expression, error)
  192. func emptyList(value bpparser.Expression) bool {
  193. if list, ok := value.(*bpparser.List); ok {
  194. return len(list.Values) == 0
  195. }
  196. return false
  197. }
  198. func splitBpList(val bpparser.Expression, keyFunc listSplitFunc) (lists map[string]bpparser.Expression, err error) {
  199. lists = make(map[string]bpparser.Expression)
  200. switch val := val.(type) {
  201. case *bpparser.Operator:
  202. listsA, err := splitBpList(val.Args[0], keyFunc)
  203. if err != nil {
  204. return nil, err
  205. }
  206. listsB, err := splitBpList(val.Args[1], keyFunc)
  207. if err != nil {
  208. return nil, err
  209. }
  210. for k, v := range listsA {
  211. if !emptyList(v) {
  212. lists[k] = v
  213. }
  214. }
  215. for k, vB := range listsB {
  216. if emptyList(vB) {
  217. continue
  218. }
  219. if vA, ok := lists[k]; ok {
  220. expression := val.Copy().(*bpparser.Operator)
  221. expression.Args = [2]bpparser.Expression{vA, vB}
  222. lists[k] = expression
  223. } else {
  224. lists[k] = vB
  225. }
  226. }
  227. case *bpparser.Variable:
  228. key, value, err := keyFunc(val)
  229. if err != nil {
  230. return nil, err
  231. }
  232. if value.Type() == bpparser.ListType {
  233. lists[key] = value
  234. } else {
  235. lists[key] = &bpparser.List{
  236. Values: []bpparser.Expression{value},
  237. }
  238. }
  239. case *bpparser.List:
  240. for _, v := range val.Values {
  241. key, value, err := keyFunc(v)
  242. if err != nil {
  243. return nil, err
  244. }
  245. l := lists[key]
  246. if l == nil {
  247. l = &bpparser.List{}
  248. }
  249. l.(*bpparser.List).Values = append(l.(*bpparser.List).Values, value)
  250. lists[key] = l
  251. }
  252. default:
  253. panic(fmt.Errorf("unexpected type %t", val))
  254. }
  255. return lists, nil
  256. }
  257. // classifyLocalOrGlobalPath tells whether a file path should be interpreted relative to the current module (local)
  258. // or relative to the root of the source checkout (global)
  259. func classifyLocalOrGlobalPath(value bpparser.Expression) (string, bpparser.Expression, error) {
  260. switch v := value.(type) {
  261. case *bpparser.Variable:
  262. if v.Name == "LOCAL_PATH" {
  263. return "local", &bpparser.String{
  264. Value: ".",
  265. }, nil
  266. } else {
  267. // TODO: Should we split variables?
  268. return "global", value, nil
  269. }
  270. case *bpparser.Operator:
  271. if v.Type() != bpparser.StringType {
  272. return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", v.Type())
  273. }
  274. if v.Operator != '+' {
  275. return "global", value, nil
  276. }
  277. firstOperand := v.Args[0]
  278. secondOperand := v.Args[1]
  279. if firstOperand.Type() != bpparser.StringType {
  280. return "global", value, nil
  281. }
  282. if _, ok := firstOperand.(*bpparser.Operator); ok {
  283. return "global", value, nil
  284. }
  285. if variable, ok := firstOperand.(*bpparser.Variable); !ok || variable.Name != "LOCAL_PATH" {
  286. return "global", value, nil
  287. }
  288. local := secondOperand
  289. if s, ok := secondOperand.(*bpparser.String); ok {
  290. if strings.HasPrefix(s.Value, "/") {
  291. s.Value = s.Value[1:]
  292. }
  293. }
  294. return "local", local, nil
  295. case *bpparser.String:
  296. return "global", value, nil
  297. default:
  298. return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", v.Type())
  299. }
  300. }
  301. // splitAndAssign splits a Make list into components and then
  302. // creates the corresponding variable assignments.
  303. func splitAndAssign(ctx variableAssignmentContext, splitFunc listSplitFunc, namesByClassification map[string]string) error {
  304. val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
  305. if err != nil {
  306. return err
  307. }
  308. lists, err := splitBpList(val, splitFunc)
  309. if err != nil {
  310. return err
  311. }
  312. var classifications []string
  313. for classification := range namesByClassification {
  314. classifications = append(classifications, classification)
  315. }
  316. sort.Strings(classifications)
  317. for _, nameClassification := range classifications {
  318. name := namesByClassification[nameClassification]
  319. if component, ok := lists[nameClassification]; ok && !emptyList(component) {
  320. err = setVariable(ctx.file, ctx.append, ctx.prefix, name, component, true)
  321. if err != nil {
  322. return err
  323. }
  324. }
  325. }
  326. return nil
  327. }
  328. func localIncludeDirs(ctx variableAssignmentContext) error {
  329. return splitAndAssign(ctx, classifyLocalOrGlobalPath, map[string]string{"global": "include_dirs", "local": "local_include_dirs"})
  330. }
  331. func exportIncludeDirs(ctx variableAssignmentContext) error {
  332. // Add any paths that could not be converted to local relative paths to export_include_dirs
  333. // anyways, they will cause an error if they don't exist and can be fixed manually.
  334. return splitAndAssign(ctx, classifyLocalOrGlobalPath, map[string]string{"global": "export_include_dirs", "local": "export_include_dirs"})
  335. }
  336. func local32BitOnly(ctx variableAssignmentContext) error {
  337. val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.BoolType)
  338. if err != nil {
  339. return err
  340. }
  341. boolValue, ok := val.(*bpparser.Bool)
  342. if !ok {
  343. return fmt.Errorf("value should evaluate to boolean literal")
  344. }
  345. if boolValue.Value {
  346. thirtyTwo := &bpparser.String{
  347. Value: "32",
  348. }
  349. return setVariable(ctx.file, false, ctx.prefix, "compile_multilib", thirtyTwo, true)
  350. }
  351. return nil
  352. }
  353. func localAidlIncludes(ctx variableAssignmentContext) error {
  354. return splitAndAssign(ctx, classifyLocalOrGlobalPath, map[string]string{"global": "aidl.include_dirs", "local": "aidl.local_include_dirs"})
  355. }
  356. func localizePathList(attribute string) func(ctx variableAssignmentContext) error {
  357. return func(ctx variableAssignmentContext) error {
  358. paths, err := localizePaths(ctx)
  359. if err == nil {
  360. err = setVariable(ctx.file, ctx.append, ctx.prefix, attribute, paths, true)
  361. }
  362. return err
  363. }
  364. }
  365. func localizePath(attribute string) func(ctx variableAssignmentContext) error {
  366. return func(ctx variableAssignmentContext) error {
  367. paths, err := localizePaths(ctx)
  368. if err == nil {
  369. pathList, ok := paths.(*bpparser.List)
  370. if !ok {
  371. panic("Expected list")
  372. }
  373. switch len(pathList.Values) {
  374. case 0:
  375. err = setVariable(ctx.file, ctx.append, ctx.prefix, attribute, &bpparser.List{}, true)
  376. case 1:
  377. err = setVariable(ctx.file, ctx.append, ctx.prefix, attribute, pathList.Values[0], true)
  378. default:
  379. err = fmt.Errorf("Expected single value for %s", attribute)
  380. }
  381. }
  382. return err
  383. }
  384. }
  385. // Convert the "full" paths (that is, from the top of the source tree) to the relative one
  386. // (from the directory containing the blueprint file) and set given attribute to it.
  387. // This is needed for some of makefile variables (e.g., LOCAL_RESOURCE_DIR).
  388. // At the moment only the paths of the `$(LOCAL_PATH)/foo/bar` format can be converted
  389. // (to `foo/bar` in this case) as we cannot convert a literal path without
  390. // knowing makefiles's location in the source tree. We just issue a warning in the latter case.
  391. func localizePaths(ctx variableAssignmentContext) (bpparser.Expression, error) {
  392. bpvalue, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
  393. var result bpparser.Expression
  394. if err != nil {
  395. return result, err
  396. }
  397. classifiedPaths, err := splitBpList(bpvalue, classifyLocalOrGlobalPath)
  398. if err != nil {
  399. return result, err
  400. }
  401. for pathClass, path := range classifiedPaths {
  402. switch pathClass {
  403. case "local":
  404. result = path
  405. default:
  406. err = fmt.Errorf("Only $(LOCAL_PATH)/.. values are allowed")
  407. }
  408. }
  409. return result, err
  410. }
  411. func stem(ctx variableAssignmentContext) error {
  412. val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.StringType)
  413. if err != nil {
  414. return err
  415. }
  416. varName := "stem"
  417. if exp, ok := val.(*bpparser.Operator); ok && exp.Operator == '+' {
  418. if variable, ok := exp.Args[0].(*bpparser.Variable); ok && variable.Name == "LOCAL_MODULE" {
  419. varName = "suffix"
  420. val = exp.Args[1]
  421. }
  422. }
  423. return setVariable(ctx.file, ctx.append, ctx.prefix, varName, val, true)
  424. }
  425. func hostOs(ctx variableAssignmentContext) error {
  426. val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
  427. if err != nil {
  428. return err
  429. }
  430. inList := func(s string) bool {
  431. for _, v := range val.(*bpparser.List).Values {
  432. if v.(*bpparser.String).Value == s {
  433. return true
  434. }
  435. }
  436. return false
  437. }
  438. falseValue := &bpparser.Bool{
  439. Value: false,
  440. }
  441. trueValue := &bpparser.Bool{
  442. Value: true,
  443. }
  444. if inList("windows") {
  445. err = setVariable(ctx.file, ctx.append, "target.windows", "enabled", trueValue, true)
  446. }
  447. if !inList("linux") && err == nil {
  448. err = setVariable(ctx.file, ctx.append, "target.linux_glibc", "enabled", falseValue, true)
  449. }
  450. if !inList("darwin") && err == nil {
  451. err = setVariable(ctx.file, ctx.append, "target.darwin", "enabled", falseValue, true)
  452. }
  453. return err
  454. }
  455. func sanitize(sub string) func(ctx variableAssignmentContext) error {
  456. return func(ctx variableAssignmentContext) error {
  457. val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
  458. if err != nil {
  459. return err
  460. }
  461. if _, ok := val.(*bpparser.List); !ok {
  462. return fmt.Errorf("unsupported sanitize expression")
  463. }
  464. misc := &bpparser.List{}
  465. for _, v := range val.(*bpparser.List).Values {
  466. switch v := v.(type) {
  467. case *bpparser.Variable, *bpparser.Operator:
  468. ctx.file.errorf(ctx.mkvalue, "unsupported sanitize expression")
  469. case *bpparser.String:
  470. switch v.Value {
  471. case "never", "address", "fuzzer", "thread", "undefined", "cfi":
  472. bpTrue := &bpparser.Bool{
  473. Value: true,
  474. }
  475. err = setVariable(ctx.file, false, ctx.prefix, "sanitize."+sub+v.Value, bpTrue, true)
  476. if err != nil {
  477. return err
  478. }
  479. default:
  480. misc.Values = append(misc.Values, v)
  481. }
  482. default:
  483. return fmt.Errorf("sanitize expected a string, got %s", v.Type())
  484. }
  485. }
  486. if len(misc.Values) > 0 {
  487. err = setVariable(ctx.file, false, ctx.prefix, "sanitize."+sub+"misc_undefined", misc, true)
  488. if err != nil {
  489. return err
  490. }
  491. }
  492. return err
  493. }
  494. }
  495. func strip() func(ctx variableAssignmentContext) error {
  496. return func(ctx variableAssignmentContext) error {
  497. val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.StringType)
  498. if err != nil {
  499. return err
  500. }
  501. if _, ok := val.(*bpparser.String); !ok {
  502. return fmt.Errorf("unsupported strip expression")
  503. }
  504. bpTrue := &bpparser.Bool{
  505. Value: true,
  506. }
  507. v := val.(*bpparser.String).Value
  508. sub := (map[string]string{"false": "none", "true": "all", "keep_symbols": "keep_symbols"})[v]
  509. if sub == "" {
  510. return fmt.Errorf("unexpected strip option: %s", v)
  511. }
  512. return setVariable(ctx.file, false, ctx.prefix, "strip."+sub, bpTrue, true)
  513. }
  514. }
  515. func prebuiltClass(ctx variableAssignmentContext) error {
  516. class := ctx.mkvalue.Value(ctx.file.scope)
  517. if _, ok := prebuiltTypes[class]; ok {
  518. ctx.file.scope.Set("BUILD_PREBUILT", class)
  519. } else {
  520. // reset to default
  521. ctx.file.scope.Set("BUILD_PREBUILT", "prebuilt")
  522. }
  523. return nil
  524. }
  525. func makeBlueprintStringAssignment(file *bpFile, prefix string, suffix string, value string) error {
  526. val, err := makeVariableToBlueprint(file, mkparser.SimpleMakeString(value, mkparser.NoPos), bpparser.StringType)
  527. if err == nil {
  528. err = setVariable(file, false, prefix, suffix, val, true)
  529. }
  530. return err
  531. }
  532. // If variable is a literal variable name, return the name, otherwise return ""
  533. func varLiteralName(variable mkparser.Variable) string {
  534. if len(variable.Name.Variables) == 0 {
  535. return variable.Name.Strings[0]
  536. }
  537. return ""
  538. }
  539. func prebuiltModulePath(ctx variableAssignmentContext) error {
  540. // Cannot handle appending
  541. if ctx.append {
  542. return fmt.Errorf("Cannot handle appending to LOCAL_MODULE_PATH")
  543. }
  544. // Analyze value in order to set the correct values for the 'device_specific',
  545. // 'product_specific', 'system_ext_specific' 'vendor'/'soc_specific',
  546. // 'system_ext_specific' attribute. Two cases are allowed:
  547. // $(VAR)/<literal-value>
  548. // $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/<literal-value>
  549. // The last case is equivalent to $(TARGET_OUT_VENDOR)/<literal-value>
  550. // Map the variable name if present to `local_module_path_var`
  551. // Map literal-path to local_module_path_fixed
  552. varname := ""
  553. fixed := ""
  554. val := ctx.mkvalue
  555. if len(val.Variables) == 1 && varLiteralName(val.Variables[0]) != "" && len(val.Strings) == 2 && val.Strings[0] == "" {
  556. fixed = val.Strings[1]
  557. varname = val.Variables[0].Name.Strings[0]
  558. } else if len(val.Variables) == 2 && varLiteralName(val.Variables[0]) == "PRODUCT_OUT" && varLiteralName(val.Variables[1]) == "TARGET_COPY_OUT_VENDOR" &&
  559. len(val.Strings) == 3 && val.Strings[0] == "" && val.Strings[1] == "/" {
  560. fixed = val.Strings[2]
  561. varname = "TARGET_OUT_VENDOR"
  562. } else {
  563. return fmt.Errorf("LOCAL_MODULE_PATH value should start with $(<some-varaible>)/ or $(PRODUCT_OUT)/$(TARGET_COPY_VENDOR)/")
  564. }
  565. err := makeBlueprintStringAssignment(ctx.file, "local_module_path", "var", varname)
  566. if err == nil && fixed != "" {
  567. err = makeBlueprintStringAssignment(ctx.file, "local_module_path", "fixed", fixed)
  568. }
  569. return err
  570. }
  571. func ldflags(ctx variableAssignmentContext) error {
  572. val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
  573. if err != nil {
  574. return err
  575. }
  576. lists, err := splitBpList(val, func(value bpparser.Expression) (string, bpparser.Expression, error) {
  577. // Anything other than "-Wl,--version_script," + LOCAL_PATH + "<path>" matches ldflags
  578. exp1, ok := value.(*bpparser.Operator)
  579. if !ok {
  580. return "ldflags", value, nil
  581. }
  582. exp2, ok := exp1.Args[0].(*bpparser.Operator)
  583. if !ok {
  584. return "ldflags", value, nil
  585. }
  586. if s, ok := exp2.Args[0].(*bpparser.String); !ok || s.Value != "-Wl,--version-script," {
  587. return "ldflags", value, nil
  588. }
  589. if v, ok := exp2.Args[1].(*bpparser.Variable); !ok || v.Name != "LOCAL_PATH" {
  590. ctx.file.errorf(ctx.mkvalue, "Unrecognized version-script")
  591. return "ldflags", value, nil
  592. }
  593. s, ok := exp1.Args[1].(*bpparser.String)
  594. if !ok {
  595. ctx.file.errorf(ctx.mkvalue, "Unrecognized version-script")
  596. return "ldflags", value, nil
  597. }
  598. s.Value = strings.TrimPrefix(s.Value, "/")
  599. return "version", s, nil
  600. })
  601. if err != nil {
  602. return err
  603. }
  604. if ldflags, ok := lists["ldflags"]; ok && !emptyList(ldflags) {
  605. err = setVariable(ctx.file, ctx.append, ctx.prefix, "ldflags", ldflags, true)
  606. if err != nil {
  607. return err
  608. }
  609. }
  610. if version_script, ok := lists["version"]; ok && !emptyList(version_script) {
  611. if len(version_script.(*bpparser.List).Values) > 1 {
  612. ctx.file.errorf(ctx.mkvalue, "multiple version scripts found?")
  613. }
  614. err = setVariable(ctx.file, false, ctx.prefix, "version_script", version_script.(*bpparser.List).Values[0], true)
  615. if err != nil {
  616. return err
  617. }
  618. }
  619. return nil
  620. }
  621. func cflags(ctx variableAssignmentContext) error {
  622. // The Soong replacement for CFLAGS doesn't need the same extra escaped quotes that were present in Make
  623. ctx.mkvalue = ctx.mkvalue.Clone()
  624. ctx.mkvalue.ReplaceLiteral(`\"`, `"`)
  625. return includeVariableNow(bpVariable{"cflags", bpparser.ListType}, ctx)
  626. }
  627. func proguardEnabled(ctx variableAssignmentContext) error {
  628. val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
  629. if err != nil {
  630. return err
  631. }
  632. list, ok := val.(*bpparser.List)
  633. if !ok {
  634. return fmt.Errorf("unsupported proguard expression")
  635. }
  636. set := func(prop string, value bool) {
  637. bpValue := &bpparser.Bool{
  638. Value: value,
  639. }
  640. setVariable(ctx.file, false, ctx.prefix, prop, bpValue, true)
  641. }
  642. enable := false
  643. for _, v := range list.Values {
  644. s, ok := v.(*bpparser.String)
  645. if !ok {
  646. return fmt.Errorf("unsupported proguard expression")
  647. }
  648. switch s.Value {
  649. case "disabled":
  650. set("optimize.enabled", false)
  651. case "obfuscation":
  652. enable = true
  653. set("optimize.obfuscate", true)
  654. case "optimization":
  655. enable = true
  656. set("optimize.optimize", true)
  657. case "full":
  658. enable = true
  659. case "custom":
  660. set("optimize.no_aapt_flags", true)
  661. enable = true
  662. default:
  663. return fmt.Errorf("unsupported proguard value %q", s)
  664. }
  665. }
  666. if enable {
  667. // This is only necessary for libraries which default to false, but we can't
  668. // tell the difference between a library and an app here.
  669. set("optimize.enabled", true)
  670. }
  671. return nil
  672. }
  673. func invert(name string) func(ctx variableAssignmentContext) error {
  674. return func(ctx variableAssignmentContext) error {
  675. val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.BoolType)
  676. if err != nil {
  677. return err
  678. }
  679. val.(*bpparser.Bool).Value = !val.(*bpparser.Bool).Value
  680. return setVariable(ctx.file, ctx.append, ctx.prefix, name, val, true)
  681. }
  682. }
  683. // given a conditional, returns a function that will insert a variable assignment or not, based on the conditional
  684. func includeVariableIf(bpVar bpVariable, conditional func(ctx variableAssignmentContext) bool) func(ctx variableAssignmentContext) error {
  685. return func(ctx variableAssignmentContext) error {
  686. var err error
  687. if conditional(ctx) {
  688. err = includeVariableNow(bpVar, ctx)
  689. }
  690. return err
  691. }
  692. }
  693. // given a variable, returns a function that will always insert a variable assignment
  694. func includeVariable(bpVar bpVariable) func(ctx variableAssignmentContext) error {
  695. return includeVariableIf(bpVar, always)
  696. }
  697. func includeVariableNow(bpVar bpVariable, ctx variableAssignmentContext) error {
  698. var val bpparser.Expression
  699. var err error
  700. val, err = makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpVar.variableType)
  701. if err == nil {
  702. err = setVariable(ctx.file, ctx.append, ctx.prefix, bpVar.name, val, true)
  703. }
  704. return err
  705. }
  706. // given a function that returns a bool, returns a function that returns the opposite
  707. func not(conditional func(ctx variableAssignmentContext) bool) func(ctx variableAssignmentContext) bool {
  708. return func(ctx variableAssignmentContext) bool {
  709. return !conditional(ctx)
  710. }
  711. }
  712. // returns a function that tells whether mkvalue.Dump equals the given query string
  713. func valueDumpEquals(textToMatch string) func(ctx variableAssignmentContext) bool {
  714. return func(ctx variableAssignmentContext) bool {
  715. return (ctx.mkvalue.Dump() == textToMatch)
  716. }
  717. }
  718. func always(ctx variableAssignmentContext) bool {
  719. return true
  720. }
  721. func skip(ctx variableAssignmentContext) error {
  722. return nil
  723. }
  724. // Shorter suffixes of other suffixes must be at the end of the list
  725. var propertyPrefixes = []struct{ mk, bp string }{
  726. {"arm", "arch.arm"},
  727. {"arm64", "arch.arm64"},
  728. {"x86", "arch.x86"},
  729. {"x86_64", "arch.x86_64"},
  730. {"32", "multilib.lib32"},
  731. // 64 must be after x86_64
  732. {"64", "multilib.lib64"},
  733. {"darwin", "target.darwin"},
  734. {"linux", "target.linux_glibc"},
  735. {"windows", "target.windows"},
  736. }
  737. var conditionalTranslations = map[string]map[bool]string{
  738. "($(HOST_OS),darwin)": {
  739. true: "target.darwin",
  740. false: "target.not_darwin"},
  741. "($(HOST_OS), darwin)": {
  742. true: "target.darwin",
  743. false: "target.not_darwin"},
  744. "($(HOST_OS),windows)": {
  745. true: "target.windows",
  746. false: "target.not_windows"},
  747. "($(HOST_OS), windows)": {
  748. true: "target.windows",
  749. false: "target.not_windows"},
  750. "($(HOST_OS),linux)": {
  751. true: "target.linux_glibc",
  752. false: "target.not_linux_glibc"},
  753. "($(HOST_OS), linux)": {
  754. true: "target.linux_glibc",
  755. false: "target.not_linux_glibc"},
  756. "($(BUILD_OS),darwin)": {
  757. true: "target.darwin",
  758. false: "target.not_darwin"},
  759. "($(BUILD_OS), darwin)": {
  760. true: "target.darwin",
  761. false: "target.not_darwin"},
  762. "($(BUILD_OS),linux)": {
  763. true: "target.linux_glibc",
  764. false: "target.not_linux_glibc"},
  765. "($(BUILD_OS), linux)": {
  766. true: "target.linux_glibc",
  767. false: "target.not_linux_glibc"},
  768. "(,$(TARGET_BUILD_APPS))": {
  769. false: "product_variables.unbundled_build"},
  770. "($(TARGET_BUILD_APPS),)": {
  771. false: "product_variables.unbundled_build"},
  772. "($(TARGET_BUILD_PDK),true)": {
  773. true: "product_variables.pdk"},
  774. "($(TARGET_BUILD_PDK), true)": {
  775. true: "product_variables.pdk"},
  776. }
  777. func mydir(args []string) []string {
  778. return []string{"."}
  779. }
  780. func allFilesUnder(wildcard string) func(args []string) []string {
  781. return func(args []string) []string {
  782. dirs := []string{""}
  783. if len(args) > 0 {
  784. dirs = strings.Fields(args[0])
  785. }
  786. paths := make([]string, len(dirs))
  787. for i := range paths {
  788. paths[i] = fmt.Sprintf("%s/**/"+wildcard, dirs[i])
  789. }
  790. return paths
  791. }
  792. }
  793. func allSubdirJavaFiles(args []string) []string {
  794. return []string{"**/*.java"}
  795. }
  796. func includeIgnored(args []string) []string {
  797. return []string{include_ignored}
  798. }
  799. var moduleTypes = map[string]string{
  800. "BUILD_SHARED_LIBRARY": "cc_library_shared",
  801. "BUILD_STATIC_LIBRARY": "cc_library_static",
  802. "BUILD_HOST_SHARED_LIBRARY": "cc_library_host_shared",
  803. "BUILD_HOST_STATIC_LIBRARY": "cc_library_host_static",
  804. "BUILD_HEADER_LIBRARY": "cc_library_headers",
  805. "BUILD_EXECUTABLE": "cc_binary",
  806. "BUILD_HOST_EXECUTABLE": "cc_binary_host",
  807. "BUILD_NATIVE_TEST": "cc_test",
  808. "BUILD_HOST_NATIVE_TEST": "cc_test_host",
  809. "BUILD_NATIVE_BENCHMARK": "cc_benchmark",
  810. "BUILD_HOST_NATIVE_BENCHMARK": "cc_benchmark_host",
  811. "BUILD_JAVA_LIBRARY": "java_library_installable", // will be rewritten to java_library by bpfix
  812. "BUILD_STATIC_JAVA_LIBRARY": "java_library",
  813. "BUILD_HOST_JAVA_LIBRARY": "java_library_host",
  814. "BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik",
  815. "BUILD_PACKAGE": "android_app",
  816. "BUILD_CTS_EXECUTABLE": "cc_binary", // will be further massaged by bpfix depending on the output path
  817. "BUILD_CTS_SUPPORT_PACKAGE": "cts_support_package", // will be rewritten to android_test by bpfix
  818. "BUILD_CTS_PACKAGE": "cts_package", // will be rewritten to android_test by bpfix
  819. "BUILD_CTS_TARGET_JAVA_LIBRARY": "cts_target_java_library", // will be rewritten to java_library by bpfix
  820. "BUILD_CTS_HOST_JAVA_LIBRARY": "cts_host_java_library", // will be rewritten to java_library_host by bpfix
  821. }
  822. var prebuiltTypes = map[string]string{
  823. "SHARED_LIBRARIES": "cc_prebuilt_library_shared",
  824. "STATIC_LIBRARIES": "cc_prebuilt_library_static",
  825. "EXECUTABLES": "cc_prebuilt_binary",
  826. "JAVA_LIBRARIES": "java_import",
  827. "APPS": "android_app_import",
  828. "ETC": "prebuilt_etc",
  829. }
  830. var soongModuleTypes = map[string]bool{}
  831. var includePathToModule = map[string]string{
  832. "test/vts/tools/build/Android.host_config.mk": "vts_config",
  833. // The rest will be populated dynamically in androidScope below
  834. }
  835. func mapIncludePath(path string) (string, bool) {
  836. if path == clear_vars || path == include_ignored {
  837. return path, true
  838. }
  839. module, ok := includePathToModule[path]
  840. return module, ok
  841. }
  842. func androidScope() mkparser.Scope {
  843. globalScope := mkparser.NewScope(nil)
  844. globalScope.Set("CLEAR_VARS", clear_vars)
  845. globalScope.SetFunc("my-dir", mydir)
  846. globalScope.SetFunc("all-java-files-under", allFilesUnder("*.java"))
  847. globalScope.SetFunc("all-proto-files-under", allFilesUnder("*.proto"))
  848. globalScope.SetFunc("all-aidl-files-under", allFilesUnder("*.aidl"))
  849. globalScope.SetFunc("all-Iaidl-files-under", allFilesUnder("I*.aidl"))
  850. globalScope.SetFunc("all-logtags-files-under", allFilesUnder("*.logtags"))
  851. globalScope.SetFunc("all-subdir-java-files", allSubdirJavaFiles)
  852. globalScope.SetFunc("all-makefiles-under", includeIgnored)
  853. globalScope.SetFunc("first-makefiles-under", includeIgnored)
  854. globalScope.SetFunc("all-named-subdir-makefiles", includeIgnored)
  855. globalScope.SetFunc("all-subdir-makefiles", includeIgnored)
  856. // The scope maps each known variable to a path, and then includePathToModule maps a path
  857. // to a module. We don't care what the actual path value is so long as the value in scope
  858. // is mapped, so we might as well use variable name as key, too.
  859. for varName, moduleName := range moduleTypes {
  860. path := varName
  861. globalScope.Set(varName, path)
  862. includePathToModule[path] = moduleName
  863. }
  864. for varName, moduleName := range prebuiltTypes {
  865. includePathToModule[varName] = moduleName
  866. }
  867. return globalScope
  868. }