dumpvars.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 build
  15. import (
  16. "bytes"
  17. "fmt"
  18. "io/ioutil"
  19. "os"
  20. "strings"
  21. "android/soong/ui/metrics"
  22. "android/soong/ui/status"
  23. )
  24. // DumpMakeVars can be used to extract the values of Make variables after the
  25. // product configurations are loaded. This is roughly equivalent to the
  26. // `get_build_var` bash function.
  27. //
  28. // goals can be used to set MAKECMDGOALS, which emulates passing arguments to
  29. // Make without actually building them. So all the variables based on
  30. // MAKECMDGOALS can be read.
  31. //
  32. // vars is the list of variables to read. The values will be put in the
  33. // returned map.
  34. //
  35. // variables controlled by soong_ui directly are now returned without needing
  36. // to call into make, to retain compatibility.
  37. func DumpMakeVars(ctx Context, config Config, goals, vars []string) (map[string]string, error) {
  38. soongUiVars := map[string]func() string{
  39. "OUT_DIR": func() string { return config.OutDir() },
  40. "DIST_DIR": func() string { return config.DistDir() },
  41. "TMPDIR": func() string { return absPath(ctx, config.TempDir()) },
  42. }
  43. makeVars := make([]string, 0, len(vars))
  44. for _, v := range vars {
  45. if _, ok := soongUiVars[v]; !ok {
  46. makeVars = append(makeVars, v)
  47. }
  48. }
  49. var ret map[string]string
  50. if len(makeVars) > 0 {
  51. // It's not safe to use the same TMPDIR as the build, as that can be removed.
  52. tmpDir, err := ioutil.TempDir("", "dumpvars")
  53. if err != nil {
  54. return nil, err
  55. }
  56. defer os.RemoveAll(tmpDir)
  57. SetupLitePath(ctx, config, tmpDir)
  58. ret, err = dumpMakeVars(ctx, config, goals, makeVars, false, tmpDir)
  59. if err != nil {
  60. return ret, err
  61. }
  62. } else {
  63. ret = make(map[string]string)
  64. }
  65. for _, v := range vars {
  66. if f, ok := soongUiVars[v]; ok {
  67. ret[v] = f()
  68. }
  69. }
  70. return ret, nil
  71. }
  72. func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool, tmpDir string) (map[string]string, error) {
  73. ctx.BeginTrace(metrics.RunKati, "dumpvars")
  74. defer ctx.EndTrace()
  75. tool := ctx.Status.StartTool()
  76. if write_soong_vars {
  77. // only print this when write_soong_vars is true so that it's not printed when using
  78. // the get_build_var command.
  79. tool.Status("Running product configuration...")
  80. }
  81. defer tool.Finish()
  82. cmd := Command(ctx, config, "dumpvars",
  83. config.PrebuiltBuildTool("ckati"),
  84. "-f", "build/make/core/config.mk",
  85. "--color_warnings",
  86. "--kati_stats",
  87. "dump-many-vars",
  88. "MAKECMDGOALS="+strings.Join(goals, " "))
  89. cmd.Environment.Set("CALLED_FROM_SETUP", "true")
  90. if write_soong_vars {
  91. cmd.Environment.Set("WRITE_SOONG_VARIABLES", "true")
  92. }
  93. cmd.Environment.Set("DUMP_MANY_VARS", strings.Join(vars, " "))
  94. if tmpDir != "" {
  95. cmd.Environment.Set("TMPDIR", tmpDir)
  96. }
  97. cmd.Sandbox = dumpvarsSandbox
  98. output := bytes.Buffer{}
  99. cmd.Stdout = &output
  100. pipe, err := cmd.StderrPipe()
  101. if err != nil {
  102. ctx.Fatalln("Error getting output pipe for ckati:", err)
  103. }
  104. cmd.StartOrFatal()
  105. // TODO: error out when Stderr contains any content
  106. status.KatiReader(tool, pipe)
  107. cmd.WaitOrFatal()
  108. ret := make(map[string]string, len(vars))
  109. for _, line := range strings.Split(output.String(), "\n") {
  110. if len(line) == 0 {
  111. continue
  112. }
  113. if key, value, ok := decodeKeyValue(line); ok {
  114. if value, ok = singleUnquote(value); ok {
  115. ret[key] = value
  116. ctx.Verboseln(key, value)
  117. } else {
  118. return nil, fmt.Errorf("Failed to parse make line: %q", line)
  119. }
  120. } else {
  121. return nil, fmt.Errorf("Failed to parse make line: %q", line)
  122. }
  123. }
  124. if ctx.Metrics != nil {
  125. ctx.Metrics.SetMetadataMetrics(ret)
  126. }
  127. return ret, nil
  128. }
  129. // Variables to print out in the top banner
  130. var BannerVars = []string{
  131. "PLATFORM_VERSION_CODENAME",
  132. "PLATFORM_VERSION",
  133. "PRODUCT_INCLUDE_TAGS",
  134. "PRODUCT_SOURCE_ROOT_DIRS",
  135. "TARGET_PRODUCT",
  136. "TARGET_BUILD_VARIANT",
  137. "TARGET_BUILD_APPS",
  138. "TARGET_BUILD_UNBUNDLED",
  139. "TARGET_ARCH",
  140. "TARGET_ARCH_VARIANT",
  141. "TARGET_CPU_VARIANT",
  142. "TARGET_2ND_ARCH",
  143. "TARGET_2ND_ARCH_VARIANT",
  144. "TARGET_2ND_CPU_VARIANT",
  145. "HOST_OS",
  146. "HOST_OS_EXTRA",
  147. "HOST_CROSS_OS",
  148. "BUILD_ID",
  149. "OUT_DIR",
  150. "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE",
  151. }
  152. func Banner(make_vars map[string]string) string {
  153. b := &bytes.Buffer{}
  154. fmt.Fprintln(b, "============================================")
  155. for _, name := range BannerVars {
  156. if make_vars[name] != "" {
  157. fmt.Fprintf(b, "%s=%s\n", name, make_vars[name])
  158. }
  159. }
  160. fmt.Fprint(b, "============================================")
  161. return b.String()
  162. }
  163. func runMakeProductConfig(ctx Context, config Config) {
  164. // Variables to export into the environment of Kati/Ninja
  165. exportEnvVars := []string{
  166. // So that we can use the correct TARGET_PRODUCT if it's been
  167. // modified by a buildspec.mk
  168. "TARGET_PRODUCT",
  169. "TARGET_BUILD_VARIANT",
  170. "TARGET_BUILD_APPS",
  171. "TARGET_BUILD_UNBUNDLED",
  172. // compiler wrappers set up by make
  173. "CC_WRAPPER",
  174. "CXX_WRAPPER",
  175. "RBE_WRAPPER",
  176. "JAVAC_WRAPPER",
  177. "R8_WRAPPER",
  178. "D8_WRAPPER",
  179. // ccache settings
  180. "CCACHE_COMPILERCHECK",
  181. "CCACHE_SLOPPINESS",
  182. "CCACHE_BASEDIR",
  183. "CCACHE_CPP2",
  184. // LLVM compiler wrapper options
  185. "TOOLCHAIN_RUSAGE_OUTPUT",
  186. }
  187. allVars := append(append([]string{
  188. // Used to execute Kati and Ninja
  189. "NINJA_GOALS",
  190. "KATI_GOALS",
  191. // To find target/product/<DEVICE>
  192. "TARGET_DEVICE",
  193. // So that later Kati runs can find BoardConfig.mk faster
  194. "TARGET_DEVICE_DIR",
  195. // Whether --werror_overriding_commands will work
  196. "BUILD_BROKEN_DUP_RULES",
  197. // Whether to enable the network during the build
  198. "BUILD_BROKEN_USES_NETWORK",
  199. // Extra environment variables to be exported to ninja
  200. "BUILD_BROKEN_NINJA_USES_ENV_VARS",
  201. // Used to restrict write access to source tree
  202. "BUILD_BROKEN_SRC_DIR_IS_WRITABLE",
  203. "BUILD_BROKEN_SRC_DIR_RW_ALLOWLIST",
  204. // Not used, but useful to be in the soong.log
  205. "BOARD_VNDK_VERSION",
  206. "TARGET_BUILD_TYPE",
  207. "HOST_ARCH",
  208. "HOST_2ND_ARCH",
  209. "HOST_CROSS_ARCH",
  210. "HOST_CROSS_2ND_ARCH",
  211. "HOST_BUILD_TYPE",
  212. "PRODUCT_SOONG_NAMESPACES",
  213. "DEFAULT_WARNING_BUILD_MODULE_TYPES",
  214. "DEFAULT_ERROR_BUILD_MODULE_TYPES",
  215. "BUILD_BROKEN_PREBUILT_ELF_FILES",
  216. "BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW",
  217. "BUILD_BROKEN_USES_BUILD_COPY_HEADERS",
  218. "BUILD_BROKEN_USES_BUILD_EXECUTABLE",
  219. "BUILD_BROKEN_USES_BUILD_FUZZ_TEST",
  220. "BUILD_BROKEN_USES_BUILD_HEADER_LIBRARY",
  221. "BUILD_BROKEN_USES_BUILD_HOST_EXECUTABLE",
  222. "BUILD_BROKEN_USES_BUILD_HOST_JAVA_LIBRARY",
  223. "BUILD_BROKEN_USES_BUILD_HOST_PREBUILT",
  224. "BUILD_BROKEN_USES_BUILD_HOST_SHARED_LIBRARY",
  225. "BUILD_BROKEN_USES_BUILD_HOST_STATIC_LIBRARY",
  226. "BUILD_BROKEN_USES_BUILD_JAVA_LIBRARY",
  227. "BUILD_BROKEN_USES_BUILD_MULTI_PREBUILT",
  228. "BUILD_BROKEN_USES_BUILD_NATIVE_TEST",
  229. "BUILD_BROKEN_USES_BUILD_NOTICE_FILE",
  230. "BUILD_BROKEN_USES_BUILD_PACKAGE",
  231. "BUILD_BROKEN_USES_BUILD_PHONY_PACKAGE",
  232. "BUILD_BROKEN_USES_BUILD_PREBUILT",
  233. "BUILD_BROKEN_USES_BUILD_RRO_PACKAGE",
  234. "BUILD_BROKEN_USES_BUILD_SHARED_LIBRARY",
  235. "BUILD_BROKEN_USES_BUILD_STATIC_JAVA_LIBRARY",
  236. "BUILD_BROKEN_USES_BUILD_STATIC_LIBRARY",
  237. }, exportEnvVars...), BannerVars...)
  238. makeVars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
  239. if err != nil {
  240. ctx.Fatalln("Error dumping make vars:", err)
  241. }
  242. env := config.Environment()
  243. // Print the banner like make does
  244. if !env.IsEnvTrue("ANDROID_QUIET_BUILD") {
  245. fmt.Fprintln(ctx.Writer, Banner(makeVars))
  246. }
  247. // Populate the environment
  248. for _, name := range exportEnvVars {
  249. if makeVars[name] == "" {
  250. env.Unset(name)
  251. } else {
  252. env.Set(name, makeVars[name])
  253. }
  254. }
  255. config.SetKatiArgs(strings.Fields(makeVars["KATI_GOALS"]))
  256. config.SetNinjaArgs(strings.Fields(makeVars["NINJA_GOALS"]))
  257. config.SetTargetDevice(makeVars["TARGET_DEVICE"])
  258. config.SetTargetDeviceDir(makeVars["TARGET_DEVICE_DIR"])
  259. config.sandboxConfig.SetSrcDirIsRO(makeVars["BUILD_BROKEN_SRC_DIR_IS_WRITABLE"] == "false")
  260. config.sandboxConfig.SetSrcDirRWAllowlist(strings.Fields(makeVars["BUILD_BROKEN_SRC_DIR_RW_ALLOWLIST"]))
  261. config.SetBuildBrokenDupRules(makeVars["BUILD_BROKEN_DUP_RULES"] == "true")
  262. config.SetBuildBrokenUsesNetwork(makeVars["BUILD_BROKEN_USES_NETWORK"] == "true")
  263. config.SetBuildBrokenNinjaUsesEnvVars(strings.Fields(makeVars["BUILD_BROKEN_NINJA_USES_ENV_VARS"]))
  264. config.SetIncludeTags(strings.Fields(makeVars["PRODUCT_INCLUDE_TAGS"]))
  265. config.SetSourceRootDirs(strings.Fields(makeVars["PRODUCT_SOURCE_ROOT_DIRS"]))
  266. }