blob: 0b4493e9d45fd48bb940cc8052575173c2726640 [file] [log] [blame]
Ben Murdoch097c5b22016-05-18 11:27:45 +01001# 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
5import("//build/config/mac/base_rules.gni")
6
7# Generates Info.plist files for Mac apps and frameworks.
8#
9# Arguments
10#
11# info_plist:
12# string, the path to an plist file that will be included in the final
13# Info.plist generated.
14#
15# executable_name:
16# string, name of the generated target used for the product
17# and executable name as specified in the output Info.plist.
18#
19# extra_substitutions:
20# (optional) string array, 'key=value' pairs for extra fields which are
21# specified in a source Info.plist template.
22template("ios_info_plist") {
23 info_plist(target_name) {
24 format = "binary1"
25 extra_substitutions = []
26 if (defined(invoker.extra_substitutions)) {
27 extra_substitutions = invoker.extra_substitutions
28 }
29 extra_substitutions += [
30 "IOS_DEPLOYMENT_TARGET=$ios_deployment_target",
31 "IOS_PLATFORM_BUILD=$ios_platform_build",
32 "IOS_PLATFORM_NAME=$ios_sdk_name",
33 "IOS_PLATFORM_VERSION=$ios_sdk_version",
34 "IOS_SDK_BUILD=$ios_sdk_build",
35 "IOS_SDK_NAME=$ios_sdk_name$ios_sdk_version",
36 "IOS_SUPPORTED_PLATFORM=$ios_sdk_platform",
37 ]
38 plist_templates = [
39 "//build/config/ios/BuildInfo.plist",
40 invoker.info_plist,
41 ]
42 forward_variables_from(invoker,
43 [
44 "executable_name",
45 "visibility",
46 ])
47 }
48}
49
50# TODO(crbug.com/297668): refactor this template to extract common behaviour
51# between OS X and iOS bundle generation, then create a generic "app" template
52# that forward to "executable" on all platform except iOS/OS X.
53
54# Template to build an application bundle for iOS.
55#
56# This should be used instead of "executable" built-in target type on iOS.
57# As the template forward the generation of the application executable to
58# an "executable" target, all arguments supported by "executable" targets
59# are also supported by this template.
60#
61# Arguments
62#
63# output_name:
64# (optional) string, name of the generated application, if omitted,
65# defaults to the target_name.
66#
67# extra_substitutions:
68# (optional) list of string in "key=value" format, each value will
69# be used as an additional variable substitution rule when generating
70# the application Info.plist
71#
72# info_plist:
73# path to the template to use to generate the application Info.plist
74# by performing variable substitutions.
75#
76# For more information, see "gn help executable".
77template("ios_app_bundle") {
78 assert(defined(invoker.info_plist),
79 "info_plist must be specified for target $target_name")
80
81 _output_name = target_name
82 _target_name = target_name
83 if (defined(invoker.output_name)) {
84 _output_name = invoker.output_name
85 }
86
87 _generate_info_plist = target_name + "_generate_info_plist"
88 _bundle_data_info_plist = target_name + "_bundle_data_info_plist"
89
90 ios_info_plist(_generate_info_plist) {
91 executable_name = _output_name
92 forward_variables_from(invoker,
93 [
94 "extra_substitutions",
95 "info_plist",
96 ])
97 }
98
99 bundle_data(_bundle_data_info_plist) {
100 forward_variables_from(invoker, [ "testonly" ])
101 visibility = [ ":$_target_name" ]
102 sources = get_target_outputs(":$_generate_info_plist")
103 outputs = [
104 "{{bundle_root_dir}}/Info.plist",
105 ]
106 public_deps = [
107 ":$_generate_info_plist",
108 ]
109 }
110
111 _generate_executable = target_name + "_generate_executable"
112 _bundle_data_executable = target_name + "_bundle_data_executable"
113
114 executable(_generate_executable) {
115 visibility = [ ":$_bundle_data_executable" ]
116 forward_variables_from(invoker,
117 "*",
118 [
119 "assert_no_deps",
120 "code_signing_identity",
121 "data_deps",
122 "entitlements_path",
123 "info_plist",
124 "output_name",
125 "visibility",
126 ])
127
128 output_name = rebase_path("$target_gen_dir/$_output_name", root_out_dir)
129 if (!defined(libs)) {
130 libs = []
131 }
132 libs += [ "UIKit.framework" ]
133 }
134
135 bundle_data(_bundle_data_executable) {
136 forward_variables_from(invoker, [ "testonly" ])
137 visibility = [ ":$_target_name" ]
138 sources = [
139 "$target_gen_dir/$_output_name",
140 ]
141 outputs = [
142 "{{bundle_executable_dir}}/$_output_name",
143 ]
144 public_deps = [
145 ":$_generate_executable",
146 ]
147 }
148
149 create_bundle(target_name) {
150 forward_variables_from(invoker,
151 [
152 "data_deps",
153 "deps",
154 "public_deps",
155 "testonly",
156 "visibility",
157 ])
158
159 if (!defined(deps)) {
160 deps = []
161 }
162 deps += [
163 ":$_bundle_data_executable",
164 ":$_bundle_data_info_plist",
165 ]
166
167 if (use_ios_simulator) {
168 if (!defined(data_deps)) {
169 data_deps = []
170 }
171 data_deps += [ "//testing/iossim" ]
172 }
173
174 product_type = "com.apple.product-type.application"
175 bundle_root_dir = "$root_out_dir/$_output_name.app"
176 bundle_resources_dir = bundle_root_dir
177 bundle_executable_dir = bundle_root_dir
178 bundle_plugins_dir = "$bundle_root_dir/Plugins"
Ben Murdoch097c5b22016-05-18 11:27:45 +0100179 }
180
181 # TODO(crbug.com/297668):
182 # - add support for codesigning,
183 # - find a way to make "ninja -C out/Default base_unittests.app" work as
184 # an alias to "ninja -C out/Default base_unittests" (for convenience
185 # and compatibility with gyp),
186}
187
188# Compile a xib or storyboard file and add it to a bundle_data so that it is
189# available at runtime in the bundle.
190#
191# Arguments
192#
193# source:
194# string, path of the xib or storyboard to compile.
195#
196# Forwards all variables to the bundle_data target.
197template("bundle_data_xib") {
198 assert(defined(invoker.source), "source needs to be defined for $target_name")
199
200 _source_extension = get_path_info(invoker.source, "extension")
201 assert(_source_extension == "xib" || _source_extension == "storyboard",
202 "source must be a .xib or .storyboard for $target_name")
203
204 _target_name = target_name
205 _compile_xib = target_name + "_compile_xib"
206
207 compile_xibs(_compile_xib) {
208 sources = [
209 invoker.source,
210 ]
211 visibility = [ ":$_target_name" ]
212 ibtool_flags = [
213 "--minimum-deployment-target",
214 ios_deployment_target,
215 "--auto-activate-custom-fonts",
216 "--target-device",
217 "iphone",
218 "--target-device",
219 "ipad",
220 ]
221 }
222
223 bundle_data(_target_name) {
224 forward_variables_from(invoker, "*", [ "source" ])
225
226 if (!defined(public_deps)) {
227 public_deps = []
228 }
229 public_deps += [ ":$_compile_xib" ]
230
231 sources = get_target_outputs(":$_compile_xib")
232
233 outputs = [
234 "{{bundle_resources_dir}}/{{source_file_part}}",
235 ]
236 }
237}
238
239# Template to package a shared library into an iOS framework bundle.
240#
241# This template provides two targets to control whether the framework is
242# merely built when targets depend on it, or whether it is linked as well:
243# "$target_name" and "$target_name+link".
244#
245# See the //build/config/mac/base_rules.gni:framework_bundle for a discussion
246# and examples.
247#
248# Arguments
249#
250# output_name:
251# (optional) string, name of the generated framework without the
252# .framework suffix. If omitted, defaults to target_name.
253#
254# framework_version:
255# (optional) string, version of the framework. Typically this is a
256# single letter, like "A". If omitted, the Versions/ subdirectory
257# structure will not be created, and build output will go directly
258# into the framework subdirectory.
259#
260# public_headers:
261# (optional) list of paths to header file that needs to be copied
262# into the framework bundle Headers subdirectory. If omitted or
263# empty then the Headers subdirectory is not created.
264#
265# sources
266# (optional) list of files. Needs to be defined and non-empty if
267# public_headers is defined and non-empty.
268#
269# See "gn help shared_library" for more information on arguments supported
270# by shared library target.
271template("ios_framework_bundle") {
272 _target_name = target_name
273 _output_name = target_name
274 if (defined(invoker.output_name)) {
275 _output_name = invoker.output_name
276 }
277 _framework_target = _target_name
278
279 if (defined(invoker.public_headers) && invoker.public_headers != []) {
280 _public_headers = invoker.public_headers
281 _framework_name = _output_name + ".framework"
282 _framework_root = "$root_out_dir/$_framework_name"
283 _framework_target = target_name + "_internal"
284
285 _header_map_filename = "$target_gen_dir/$_output_name.headers.hmap"
286 _framework_headers_target = _target_name + "_framework_headers"
287
288 _compile_headers_map_target = _target_name + "_compile_headers_map"
289 action(_compile_headers_map_target) {
290 visibility = [ ":$_framework_headers_target" ]
291 script = "$root_out_dir/gyp-mac-tool"
292 outputs = [
293 _header_map_filename,
294 ]
295
296 # The header map generation only wants the list of headers, not all of
297 # sources, so filter any non-header source files from "sources". It is
298 # less error prone that having the developer duplicate the list of all
299 # headers in addition to "sources".
300 set_sources_assignment_filter([
301 "*.c",
302 "*.cc",
303 "*.cpp",
304 "*.m",
305 "*.mm",
306 ])
307 sources = invoker.sources
308 set_sources_assignment_filter([])
309
310 args = [
311 "compile-ios-framework-header-map",
312 rebase_path(_header_map_filename),
313 rebase_path(_framework_root, root_out_dir),
314 ] + rebase_path(sources, root_out_dir)
315 }
316
317 _create_module_map_target = _target_name + "_module_map"
318 action(_create_module_map_target) {
319 visibility = [ ":$_framework_headers_target" ]
320 script = "$root_out_dir/gyp-mac-tool"
321 outputs = [
322 "$_framework_root/Modules/module.modulemap",
323 ]
324 args = [
325 "package-ios-framework",
326 rebase_path("$_framework_root", root_out_dir),
327 ]
328 }
329
330 _copy_public_headers_target = _target_name + "_copy_public_headers"
331 copy(_copy_public_headers_target) {
332 visibility = [ ":$_framework_headers_target" ]
333 sources = _public_headers
334 outputs = [
335 "$_framework_root/Headers/{{source_file_part}}",
336 ]
337 }
338
339 _headers_map_config = _target_name + "_headers_map"
340 config(_headers_map_config) {
341 visibility = [ ":$_target_name" ]
342 include_dirs = [ _header_map_filename ]
343 ldflags = [
344 "-install_name",
345 "@rpath/$_framework_name/$_output_name",
346 ]
347 }
348
349 group(_framework_headers_target) {
350 deps = [
351 ":$_compile_headers_map_target",
352 ":$_copy_public_headers_target",
353 ":$_create_module_map_target",
354 ]
355 }
356 }
357
358 _framework_public_config = _target_name + "_ios_public_config"
359 config(_framework_public_config) {
360 visibility = [ ":$_framework_public_config" ]
361 if (defined(_public_headers)) {
362 common_flags = [ "-F" + rebase_path("$root_out_dir/.", root_out_dir) ]
363 cflags_objc = common_flags
364 cflags_objcc = common_flags
365 }
366
367 # The link settings are inherited from the framework_bundle config.
368 }
369
370 framework_bundle(_framework_target) {
371 forward_variables_from(invoker,
372 "*",
373 [
374 "output_name",
375 "public_headers",
376 "visibility",
377 ])
378 output_name = _output_name
379
380 if (!defined(public_configs)) {
381 public_configs = []
382 }
383 public_configs += [ ":$_framework_public_config" ]
384
385 if (defined(_public_headers)) {
386 visibility = [
387 ":$_target_name",
388 ":$_target_name+link",
389 ]
390 configs += [ ":$_headers_map_config" ]
391
392 if (!defined(deps)) {
393 deps = []
394 }
395 deps += [ ":$_framework_headers_target" ]
396 } else {
397 if (defined(invoker.visibility)) {
398 visibility = invoker.visibility
399 visibility += [ ":$_target_name+link" ]
400 }
401 }
402 }
403
404 if (defined(_public_headers)) {
405 group(_target_name) {
406 forward_variables_from(invoker,
407 [
408 "testonly",
409 "public_configs",
410 ])
411
412 if (defined(invoker.visibility)) {
413 visibility = invoker.visibility
414 visibility += [ ":$_target_name+link" ]
415 }
416
417 public_deps = [
418 ":$_framework_target",
419 ]
420 }
421
422 group(_target_name + "+link") {
423 forward_variables_from(invoker,
424 [
425 "testonly",
426 "visibility",
427 ])
428 public_deps = [
429 ":$_framework_target+link",
430 ]
431 }
432 }
433}