rules.gni 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. # Copyright 2015 The Chromium Authors. All rights reserved.
  2. # Use of this source code is governed by a BSD-style license that can be
  3. # found in the LICENSE file.
  4. import("//build/apple/apple_info_plist.gni")
  5. import("//build/config/apple/symbols.gni")
  6. import("//build/config/mac/mac_sdk.gni")
  7. # Generates Info.plist files for Mac apps and frameworks.
  8. #
  9. # Arguments
  10. #
  11. # info_plist:
  12. # (optional) string, path to the Info.plist file that will be used for
  13. # the bundle.
  14. #
  15. # info_plist_target:
  16. # (optional) string, if the info_plist is generated from an action,
  17. # rather than a regular source file, specify the target name in lieu
  18. # of info_plist. The two arguments are mutually exclusive.
  19. #
  20. # executable_name:
  21. # string, name of the generated target used for the product
  22. # and executable name as specified in the output Info.plist.
  23. #
  24. # extra_substitutions:
  25. # (optional) string array, 'key=value' pairs for extra fields which are
  26. # specified in a source Info.plist template.
  27. template("mac_info_plist") {
  28. assert(defined(invoker.info_plist) != defined(invoker.info_plist_target),
  29. "Only one of info_plist or info_plist_target may be specified in " +
  30. target_name)
  31. if (defined(invoker.info_plist)) {
  32. _info_plist = invoker.info_plist
  33. } else {
  34. _info_plist_target_output = get_target_outputs(invoker.info_plist_target)
  35. _info_plist = _info_plist_target_output[0]
  36. }
  37. apple_info_plist(target_name) {
  38. format = "xml1"
  39. extra_substitutions = [
  40. "MAC_SDK_BUILD=$mac_sdk_version",
  41. "MAC_SDK_NAME=$mac_sdk_name$mac_sdk_version",
  42. "MACOSX_DEPLOYMENT_TARGET=$mac_deployment_target",
  43. "CHROMIUM_MIN_SYSTEM_VERSION=$mac_min_system_version",
  44. "XCODE_BUILD=$xcode_build",
  45. "XCODE_VERSION=$xcode_version",
  46. ]
  47. if (defined(invoker.extra_substitutions)) {
  48. extra_substitutions += invoker.extra_substitutions
  49. }
  50. plist_templates = [
  51. "//build/config/mac/BuildInfo.plist",
  52. _info_plist,
  53. ]
  54. if (defined(invoker.info_plist_target)) {
  55. deps = [ invoker.info_plist_target ]
  56. }
  57. forward_variables_from(invoker,
  58. [
  59. "testonly",
  60. "executable_name",
  61. ])
  62. }
  63. }
  64. # Template to package a shared library into a Mac framework bundle.
  65. #
  66. # By default, the bundle target this template generates does not link the
  67. # resulting framework into anything that depends on it. If a dependency wants
  68. # a link-time (as well as build-time) dependency on the framework bundle,
  69. # depend against "$target_name+link". If only the build-time dependency is
  70. # required (e.g., for copying into another bundle), then use "$target_name".
  71. #
  72. # Arguments
  73. #
  74. # framework_version:
  75. # string, version of the framework. Typically this is a
  76. # single letter, like "A".
  77. #
  78. # framework_contents:
  79. # list of string, top-level items in the framework. This is
  80. # the list of symlinks to create in the .framework directory that link
  81. # into Versions/Current/.
  82. #
  83. # info_plist:
  84. # (optional) string, path to the Info.plist file that will be used for
  85. # the bundle.
  86. #
  87. # info_plist_target:
  88. # (optional) string, if the info_plist is generated from an action,
  89. # rather than a regular source file, specify the target name in lieu
  90. # of info_plist. The two arguments are mutually exclusive.
  91. #
  92. # output_name:
  93. # (optional) string, name of the generated framework without the
  94. # .framework suffix. If omitted, defaults to target_name.
  95. #
  96. # extra_substitutions:
  97. # (optional) string array, 'key=value' pairs for extra fields which are
  98. # specified in a source Info.plist template.
  99. #
  100. # This template provides three targets for the resulting framework bundle. The
  101. # link-time behavior varies depending on which of the two targets below is
  102. # added as a dependency:
  103. # - $target_name only adds a build-time dependency. Targets that depend on
  104. # it will not link against the framework.
  105. # - $target_name+link adds a build-time and link-time dependency. Targets
  106. # that depend on it will link against the framework.
  107. # - $target_name+link_nested adds a build-time and link-time dependency, but
  108. # only on the shared library and not the fully-assembled framework bundle.
  109. # This should only be used for other nested binary components of the
  110. # framework bundle (e.g. Helpers) that themselves depend on the main shared
  111. # library of the framework bundle.
  112. #
  113. # The build-time-only dependency is used for when a target needs to use the
  114. # framework either only for resources, or because the target loads it at run-
  115. # time, via dlopen() or NSBundle. The link-time dependency will cause the
  116. # dependee to have the framework loaded by dyld at launch.
  117. #
  118. # Example of build-time only dependency:
  119. #
  120. # mac_framework_bundle("CoreTeleportation") {
  121. # sources = [ ... ]
  122. # }
  123. #
  124. # bundle_data("core_teleportation_bundle_data") {
  125. # deps = [ ":CoreTeleportation" ]
  126. # sources = [ "$root_out_dir/CoreTeleportation.framework" ]
  127. # outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ]
  128. # }
  129. #
  130. # app_bundle("GoatTeleporter") {
  131. # sources = [ ... ]
  132. # deps = [
  133. # ":core_teleportation_bundle_data",
  134. # ]
  135. # }
  136. #
  137. # The GoatTeleporter.app will not directly link against
  138. # CoreTeleportation.framework, but it will be included in the bundle's
  139. # Frameworks directory.
  140. #
  141. # Example of link-time dependency:
  142. #
  143. # mac_framework_bundle("CoreTeleportation") {
  144. # sources = [ ... ]
  145. # ldflags = [
  146. # "-install_name",
  147. # "@executable_path/../Frameworks/$target_name.framework"
  148. # ]
  149. # }
  150. #
  151. # bundle_data("core_teleportation_bundle_data") {
  152. # deps = [ ":CoreTeleportation+link" ]
  153. # sources = [ "$root_out_dir/CoreTeleportation.framework" ]
  154. # outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ]
  155. # }
  156. #
  157. # app_bundle("GoatTeleporter") {
  158. # sources = [ ... ]
  159. # deps = [
  160. # ":core_teleportation_bundle_data",
  161. # ]
  162. # }
  163. #
  164. # Note that the framework is still copied to the app's bundle, but dyld will
  165. # load this library when the app is launched because it uses the "+link"
  166. # target as a dependency. This also requires that the framework set its
  167. # install_name so that dyld can locate it.
  168. #
  169. # See "gn help shared_library" for more information on arguments supported
  170. # by shared library target.
  171. template("mac_framework_bundle") {
  172. assert(defined(invoker.deps) || defined(invoker.public_deps),
  173. "Dependencies must be specified for $target_name")
  174. assert(invoker.framework_version != "", "framework_version is required")
  175. assert(defined(invoker.framework_contents), "framework_contents is required")
  176. _info_plist_target = target_name + "_info_plist"
  177. mac_info_plist(_info_plist_target) {
  178. executable_name = target_name
  179. if (defined(invoker.output_name)) {
  180. executable_name = invoker.output_name
  181. }
  182. forward_variables_from(invoker,
  183. [
  184. "extra_substitutions",
  185. "info_plist",
  186. "info_plist_target",
  187. "testonly",
  188. ])
  189. }
  190. _info_plist_bundle_data = _info_plist_target + "_bundle_data"
  191. bundle_data(_info_plist_bundle_data) {
  192. forward_variables_from(invoker, [ "testonly" ])
  193. sources = get_target_outputs(":$_info_plist_target")
  194. outputs = [ "{{bundle_resources_dir}}/Info.plist" ]
  195. public_deps = [ ":$_info_plist_target" ]
  196. }
  197. _target_name = target_name
  198. _output_name = target_name
  199. if (defined(invoker.output_name)) {
  200. _output_name = invoker.output_name
  201. }
  202. # Create a file to track the build dependency on the framework_version and
  203. # framework_contents variables.
  204. _framework_toc = [
  205. "Version=" + invoker.framework_version,
  206. _output_name,
  207. ] + invoker.framework_contents
  208. _framework_contents = [ _output_name ] + invoker.framework_contents
  209. _framework_toc_file = "$target_out_dir/${target_name}.toc"
  210. write_file(_framework_toc_file, _framework_toc)
  211. # Create local variables for referencing different parts of the bundle.
  212. _framework_target = _target_name
  213. _framework_name = _output_name + ".framework"
  214. _framework_base_dir = "$root_out_dir/$_framework_name"
  215. _framework_root_dir =
  216. _framework_base_dir + "/Versions/${invoker.framework_version}"
  217. # Clean the entire framework if the framework_version changes.
  218. _version_file = "$target_out_dir/${target_name}_version"
  219. exec_script("//build/config/mac/prepare_framework_version.py",
  220. [
  221. rebase_path(_version_file),
  222. rebase_path(_framework_base_dir),
  223. invoker.framework_version,
  224. ])
  225. # Create the symlinks.
  226. _framework_package_target = target_name + "_package"
  227. action(_framework_package_target) {
  228. script = "//build/config/mac/package_framework.py"
  229. # The TOC file never needs to be read, since its contents are the values
  230. # of GN variables. It is only used to trigger this rule when the values
  231. # change.
  232. inputs = [ _framework_toc_file ]
  233. _stamp_file = "$target_out_dir/run_${_framework_package_target}.stamp"
  234. outputs = [ _stamp_file ]
  235. visibility = [ ":$_framework_target" ]
  236. args = [
  237. "--framework",
  238. rebase_path(_framework_base_dir, root_build_dir),
  239. "--stamp",
  240. rebase_path(_stamp_file, root_build_dir),
  241. "--version",
  242. invoker.framework_version,
  243. "--contents",
  244. ] + _framework_contents
  245. # It is not possible to list _framework_contents as outputs, since
  246. # ninja does not properly stat symbolic links.
  247. # https://github.com/ninja-build/ninja/issues/1186
  248. }
  249. _link_shared_library_target = target_name + "_shared_library"
  250. _shared_library_bundle_data = target_name + "_shared_library_bundle_data"
  251. shared_library(_link_shared_library_target) {
  252. forward_variables_from(invoker,
  253. "*",
  254. [
  255. "assert_no_deps",
  256. "bundle_deps",
  257. "code_signing_enabled",
  258. "data_deps",
  259. "info_plist",
  260. "info_plist_target",
  261. "output_name",
  262. "visibility",
  263. ])
  264. visibility = [
  265. ":$_shared_library_bundle_data",
  266. ":${_framework_target}+link_nested",
  267. ]
  268. output_name = _output_name
  269. output_prefix_override = true
  270. output_extension = ""
  271. output_dir = "$target_out_dir/$_link_shared_library_target"
  272. }
  273. bundle_data(_shared_library_bundle_data) {
  274. visibility = [ ":$_framework_target" ]
  275. forward_variables_from(invoker, [ "testonly" ])
  276. sources = [ "$target_out_dir/$_link_shared_library_target/$_output_name" ]
  277. outputs = [ "{{bundle_executable_dir}}/$_output_name" ]
  278. public_deps = [ ":$_link_shared_library_target" ]
  279. }
  280. _framework_public_config = _target_name + "_public_config"
  281. config(_framework_public_config) {
  282. visibility = [ ":$_framework_target+link" ]
  283. framework_dirs = [ root_out_dir ]
  284. frameworks = [ _framework_name ]
  285. }
  286. create_bundle(_framework_target) {
  287. forward_variables_from(invoker,
  288. [
  289. "data_deps",
  290. "deps",
  291. "public_deps",
  292. "testonly",
  293. ])
  294. if (defined(invoker.visibility)) {
  295. visibility = invoker.visibility
  296. visibility += [ ":$_target_name+link" ]
  297. }
  298. if (!defined(deps)) {
  299. deps = []
  300. }
  301. deps += [ ":$_info_plist_bundle_data" ]
  302. if (defined(invoker.bundle_deps)) {
  303. deps += invoker.bundle_deps
  304. }
  305. if (!defined(public_deps)) {
  306. public_deps = []
  307. }
  308. public_deps += [
  309. ":$_framework_package_target",
  310. ":$_shared_library_bundle_data",
  311. ]
  312. if (enable_dsyms) {
  313. data = [
  314. "$root_out_dir/$_output_name.dSYM/Contents/Info.plist",
  315. "$root_out_dir/$_output_name.dSYM/Contents/Resources/DWARF/$_output_name",
  316. ]
  317. }
  318. bundle_root_dir = _framework_base_dir
  319. bundle_contents_dir = _framework_root_dir
  320. bundle_resources_dir = "$bundle_contents_dir/Resources"
  321. bundle_executable_dir = bundle_contents_dir
  322. }
  323. group(_target_name + "+link") {
  324. forward_variables_from(invoker,
  325. [
  326. "public_configs",
  327. "testonly",
  328. "visibility",
  329. ])
  330. public_deps = [ ":$_target_name" ]
  331. if (!defined(public_configs)) {
  332. public_configs = []
  333. }
  334. public_configs += [ ":$_framework_public_config" ]
  335. }
  336. group(_target_name + "+link_nested") {
  337. forward_variables_from(invoker,
  338. [
  339. "public_configs",
  340. "testonly",
  341. "visibility",
  342. ])
  343. # Depend only on the shared library. Nested code will be a dependency of
  344. # the create_bundle target, which would be cyclic with depending on the
  345. # framework itself. This is sufficient to link; for loading, a proper
  346. # install_name should be set.
  347. public_deps = [ ":$_link_shared_library_target" ]
  348. }
  349. }
  350. set_defaults("mac_framework_bundle") {
  351. configs = default_shared_library_configs
  352. }
  353. # Template to create a Mac executable application bundle.
  354. #
  355. # Arguments
  356. #
  357. # package_type:
  358. # (optional) string, the product package type to create. Options are:
  359. # "app" to create a .app bundle (default)
  360. # "xpc" to create an .xpc service bundle
  361. #
  362. # info_plist:
  363. # (optional) string, path to the Info.plist file that will be used for
  364. # the bundle.
  365. #
  366. # info_plist_target:
  367. # (optional) string, if the info_plist is generated from an action,
  368. # rather than a regular source file, specify the target name in lieu
  369. # of info_plist. The two arguments are mutually exclusive.
  370. #
  371. # output_name:
  372. # (optional) string, name of the generated app without the
  373. # .app suffix. If omitted, defaults to target_name.
  374. #
  375. # extra_configs:
  376. # (optional) list of label, additional configs to apply to the
  377. # executable target.
  378. #
  379. # remove_configs:
  380. # (optional) list of label, default configs to remove from the target.
  381. #
  382. # extra_substitutions:
  383. # (optional) string array, 'key=value' pairs for extra fields which are
  384. # specified in a source Info.plist template.
  385. template("mac_app_bundle") {
  386. _target_name = target_name
  387. _output_name = target_name
  388. if (defined(invoker.output_name)) {
  389. _output_name = invoker.output_name
  390. }
  391. _package_type = "app"
  392. if (defined(invoker.package_type)) {
  393. _package_type = invoker.package_type
  394. }
  395. if (_package_type == "app") {
  396. _output_extension = "app"
  397. _product_type = "com.apple.product-type.application"
  398. _write_pkg_info = true
  399. } else if (_package_type == "xpc") {
  400. _output_extension = "xpc"
  401. _product_type = "com.apple.product-type.xpc-service"
  402. _write_pkg_info = false
  403. } else if (_package_type == "bundle") {
  404. _output_extension = "bundle"
  405. _product_type = "com.apple.product-type.bundle"
  406. _write_pkg_info = false
  407. } else {
  408. assert(false, "Unsupported packge_type: " + packge_type)
  409. }
  410. _executable_target = target_name + "_executable"
  411. _executable_bundle_data = _executable_target + "_bundle_data"
  412. _info_plist_target = target_name + "_info_plist"
  413. mac_info_plist(_info_plist_target) {
  414. executable_name = _output_name
  415. forward_variables_from(invoker,
  416. [
  417. "extra_substitutions",
  418. "info_plist",
  419. "info_plist_target",
  420. "testonly",
  421. ])
  422. }
  423. if (_write_pkg_info) {
  424. _pkg_info_target = target_name + "_pkg_info"
  425. action(_pkg_info_target) {
  426. forward_variables_from(invoker, [ "testonly" ])
  427. script = "//build/apple/write_pkg_info.py"
  428. inputs = [ "//build/apple/plist_util.py" ]
  429. sources = get_target_outputs(":$_info_plist_target")
  430. outputs = [ "$target_gen_dir/$_pkg_info_target" ]
  431. args = [ "--plist" ] + rebase_path(sources, root_build_dir) +
  432. [ "--output" ] + rebase_path(outputs, root_build_dir)
  433. deps = [ ":$_info_plist_target" ]
  434. }
  435. }
  436. executable(_executable_target) {
  437. visibility = [ ":$_executable_bundle_data" ]
  438. forward_variables_from(invoker,
  439. "*",
  440. [
  441. "assert_no_deps",
  442. "data_deps",
  443. "info_plist",
  444. "output_name",
  445. "visibility",
  446. ])
  447. if (defined(extra_configs)) {
  448. configs += extra_configs
  449. }
  450. if (defined(remove_configs)) {
  451. configs -= remove_configs
  452. }
  453. output_name = _output_name
  454. output_dir = "$target_out_dir/$_executable_target"
  455. }
  456. bundle_data(_executable_bundle_data) {
  457. visibility = [ ":$_target_name" ]
  458. forward_variables_from(invoker, [ "testonly" ])
  459. sources = [ "$target_out_dir/$_executable_target/$_output_name" ]
  460. outputs = [ "{{bundle_executable_dir}}/$_output_name" ]
  461. public_deps = [ ":$_executable_target" ]
  462. }
  463. _info_plist_bundle_data = _info_plist_target + "_bundle_data"
  464. bundle_data(_info_plist_bundle_data) {
  465. forward_variables_from(invoker, [ "testonly" ])
  466. visibility = [ ":$_target_name" ]
  467. sources = get_target_outputs(":$_info_plist_target")
  468. outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
  469. public_deps = [ ":$_info_plist_target" ]
  470. }
  471. if (_write_pkg_info) {
  472. _pkg_info_bundle_data = _pkg_info_target + "_bundle_data"
  473. bundle_data(_pkg_info_bundle_data) {
  474. forward_variables_from(invoker, [ "testonly" ])
  475. visibility = [ ":$_target_name" ]
  476. sources = get_target_outputs(":$_pkg_info_target")
  477. outputs = [ "{{bundle_contents_dir}}/PkgInfo" ]
  478. public_deps = [ ":$_pkg_info_target" ]
  479. }
  480. }
  481. create_bundle(_target_name) {
  482. forward_variables_from(invoker,
  483. [
  484. "data_deps",
  485. "deps",
  486. "public_deps",
  487. "testonly",
  488. ])
  489. if (!defined(deps)) {
  490. deps = []
  491. }
  492. deps += [
  493. ":$_executable_bundle_data",
  494. ":$_info_plist_bundle_data",
  495. ]
  496. if (_write_pkg_info) {
  497. deps += [ ":$_pkg_info_bundle_data" ]
  498. }
  499. if (enable_dsyms) {
  500. data = [
  501. "$root_out_dir/$_output_name.dSYM/Contents/Info.plist",
  502. "$root_out_dir/$_output_name.dSYM/Contents/Resources/DWARF/$_output_name",
  503. ]
  504. }
  505. product_type = _product_type
  506. bundle_root_dir = "$root_out_dir/${_output_name}.${_output_extension}"
  507. bundle_contents_dir = "$bundle_root_dir/Contents"
  508. bundle_resources_dir = "$bundle_contents_dir/Resources"
  509. bundle_executable_dir = "$bundle_contents_dir/MacOS"
  510. }
  511. }
  512. # Template to package a loadable_module into a .plugin bundle.
  513. #
  514. # This takes no extra arguments that differ from a loadable_module.
  515. template("mac_plugin_bundle") {
  516. assert(defined(invoker.deps),
  517. "Dependencies must be specified for $target_name")
  518. _target_name = target_name
  519. _loadable_module_target = _target_name + "_loadable_module"
  520. _loadable_module_bundle_data = _loadable_module_target + "_bundle_data"
  521. _output_name = _target_name
  522. if (defined(invoker.output_name)) {
  523. _output_name = invoker.output_name
  524. }
  525. loadable_module(_loadable_module_target) {
  526. visibility = [ ":$_loadable_module_bundle_data" ]
  527. forward_variables_from(invoker,
  528. "*",
  529. [
  530. "assert_no_deps",
  531. "data_deps",
  532. "output_name",
  533. "visibility",
  534. ])
  535. output_dir = "$target_out_dir"
  536. output_name = _output_name
  537. }
  538. bundle_data(_loadable_module_bundle_data) {
  539. forward_variables_from(invoker, [ "testonly" ])
  540. visibility = [ ":$_target_name" ]
  541. sources = [ "$target_out_dir/$_output_name.so" ]
  542. outputs = [ "{{bundle_executable_dir}}/$_output_name" ]
  543. public_deps = [ ":$_loadable_module_target" ]
  544. }
  545. create_bundle(_target_name) {
  546. forward_variables_from(invoker,
  547. [
  548. "data_deps",
  549. "deps",
  550. "public_deps",
  551. "testonly",
  552. "visibility",
  553. ])
  554. if (!defined(deps)) {
  555. deps = []
  556. }
  557. deps += [ ":$_loadable_module_bundle_data" ]
  558. if (enable_dsyms) {
  559. data = [
  560. "$root_out_dir/$_output_name.so.dSYM/Contents/Info.plist",
  561. "$root_out_dir/$_output_name.so.dSYM/Contents/Resources/DWARF/$_output_name.so",
  562. ]
  563. }
  564. bundle_root_dir = "$root_out_dir/$_output_name.plugin"
  565. bundle_contents_dir = "$bundle_root_dir/Contents"
  566. bundle_executable_dir = "$bundle_contents_dir/MacOS"
  567. }
  568. }