blob: b628d269816fd6eb143ccc4e3f48016283833dc6 [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"
179 assert(
180 product_type != "",
181 "workaround to allow generation with version of gn that don't support product_type property for create_bundle target => remove once gn has rolled this change")
182 }
183
184 # TODO(crbug.com/297668):
185 # - add support for codesigning,
186 # - find a way to make "ninja -C out/Default base_unittests.app" work as
187 # an alias to "ninja -C out/Default base_unittests" (for convenience
188 # and compatibility with gyp),
189}
190
191# Compile a xib or storyboard file and add it to a bundle_data so that it is
192# available at runtime in the bundle.
193#
194# Arguments
195#
196# source:
197# string, path of the xib or storyboard to compile.
198#
199# Forwards all variables to the bundle_data target.
200template("bundle_data_xib") {
201 assert(defined(invoker.source), "source needs to be defined for $target_name")
202
203 _source_extension = get_path_info(invoker.source, "extension")
204 assert(_source_extension == "xib" || _source_extension == "storyboard",
205 "source must be a .xib or .storyboard for $target_name")
206
207 _target_name = target_name
208 _compile_xib = target_name + "_compile_xib"
209
210 compile_xibs(_compile_xib) {
211 sources = [
212 invoker.source,
213 ]
214 visibility = [ ":$_target_name" ]
215 ibtool_flags = [
216 "--minimum-deployment-target",
217 ios_deployment_target,
218 "--auto-activate-custom-fonts",
219 "--target-device",
220 "iphone",
221 "--target-device",
222 "ipad",
223 ]
224 }
225
226 bundle_data(_target_name) {
227 forward_variables_from(invoker, "*", [ "source" ])
228
229 if (!defined(public_deps)) {
230 public_deps = []
231 }
232 public_deps += [ ":$_compile_xib" ]
233
234 sources = get_target_outputs(":$_compile_xib")
235
236 outputs = [
237 "{{bundle_resources_dir}}/{{source_file_part}}",
238 ]
239 }
240}
241
242# Template to package a shared library into an iOS framework bundle.
243#
244# This template provides two targets to control whether the framework is
245# merely built when targets depend on it, or whether it is linked as well:
246# "$target_name" and "$target_name+link".
247#
248# See the //build/config/mac/base_rules.gni:framework_bundle for a discussion
249# and examples.
250#
251# Arguments
252#
253# output_name:
254# (optional) string, name of the generated framework without the
255# .framework suffix. If omitted, defaults to target_name.
256#
257# framework_version:
258# (optional) string, version of the framework. Typically this is a
259# single letter, like "A". If omitted, the Versions/ subdirectory
260# structure will not be created, and build output will go directly
261# into the framework subdirectory.
262#
263# public_headers:
264# (optional) list of paths to header file that needs to be copied
265# into the framework bundle Headers subdirectory. If omitted or
266# empty then the Headers subdirectory is not created.
267#
268# sources
269# (optional) list of files. Needs to be defined and non-empty if
270# public_headers is defined and non-empty.
271#
272# See "gn help shared_library" for more information on arguments supported
273# by shared library target.
274template("ios_framework_bundle") {
275 _target_name = target_name
276 _output_name = target_name
277 if (defined(invoker.output_name)) {
278 _output_name = invoker.output_name
279 }
280 _framework_target = _target_name
281
282 if (defined(invoker.public_headers) && invoker.public_headers != []) {
283 _public_headers = invoker.public_headers
284 _framework_name = _output_name + ".framework"
285 _framework_root = "$root_out_dir/$_framework_name"
286 _framework_target = target_name + "_internal"
287
288 _header_map_filename = "$target_gen_dir/$_output_name.headers.hmap"
289 _framework_headers_target = _target_name + "_framework_headers"
290
291 _compile_headers_map_target = _target_name + "_compile_headers_map"
292 action(_compile_headers_map_target) {
293 visibility = [ ":$_framework_headers_target" ]
294 script = "$root_out_dir/gyp-mac-tool"
295 outputs = [
296 _header_map_filename,
297 ]
298
299 # The header map generation only wants the list of headers, not all of
300 # sources, so filter any non-header source files from "sources". It is
301 # less error prone that having the developer duplicate the list of all
302 # headers in addition to "sources".
303 set_sources_assignment_filter([
304 "*.c",
305 "*.cc",
306 "*.cpp",
307 "*.m",
308 "*.mm",
309 ])
310 sources = invoker.sources
311 set_sources_assignment_filter([])
312
313 args = [
314 "compile-ios-framework-header-map",
315 rebase_path(_header_map_filename),
316 rebase_path(_framework_root, root_out_dir),
317 ] + rebase_path(sources, root_out_dir)
318 }
319
320 _create_module_map_target = _target_name + "_module_map"
321 action(_create_module_map_target) {
322 visibility = [ ":$_framework_headers_target" ]
323 script = "$root_out_dir/gyp-mac-tool"
324 outputs = [
325 "$_framework_root/Modules/module.modulemap",
326 ]
327 args = [
328 "package-ios-framework",
329 rebase_path("$_framework_root", root_out_dir),
330 ]
331 }
332
333 _copy_public_headers_target = _target_name + "_copy_public_headers"
334 copy(_copy_public_headers_target) {
335 visibility = [ ":$_framework_headers_target" ]
336 sources = _public_headers
337 outputs = [
338 "$_framework_root/Headers/{{source_file_part}}",
339 ]
340 }
341
342 _headers_map_config = _target_name + "_headers_map"
343 config(_headers_map_config) {
344 visibility = [ ":$_target_name" ]
345 include_dirs = [ _header_map_filename ]
346 ldflags = [
347 "-install_name",
348 "@rpath/$_framework_name/$_output_name",
349 ]
350 }
351
352 group(_framework_headers_target) {
353 deps = [
354 ":$_compile_headers_map_target",
355 ":$_copy_public_headers_target",
356 ":$_create_module_map_target",
357 ]
358 }
359 }
360
361 _framework_public_config = _target_name + "_ios_public_config"
362 config(_framework_public_config) {
363 visibility = [ ":$_framework_public_config" ]
364 if (defined(_public_headers)) {
365 common_flags = [ "-F" + rebase_path("$root_out_dir/.", root_out_dir) ]
366 cflags_objc = common_flags
367 cflags_objcc = common_flags
368 }
369
370 # The link settings are inherited from the framework_bundle config.
371 }
372
373 framework_bundle(_framework_target) {
374 forward_variables_from(invoker,
375 "*",
376 [
377 "output_name",
378 "public_headers",
379 "visibility",
380 ])
381 output_name = _output_name
382
383 if (!defined(public_configs)) {
384 public_configs = []
385 }
386 public_configs += [ ":$_framework_public_config" ]
387
388 if (defined(_public_headers)) {
389 visibility = [
390 ":$_target_name",
391 ":$_target_name+link",
392 ]
393 configs += [ ":$_headers_map_config" ]
394
395 if (!defined(deps)) {
396 deps = []
397 }
398 deps += [ ":$_framework_headers_target" ]
399 } else {
400 if (defined(invoker.visibility)) {
401 visibility = invoker.visibility
402 visibility += [ ":$_target_name+link" ]
403 }
404 }
405 }
406
407 if (defined(_public_headers)) {
408 group(_target_name) {
409 forward_variables_from(invoker,
410 [
411 "testonly",
412 "public_configs",
413 ])
414
415 if (defined(invoker.visibility)) {
416 visibility = invoker.visibility
417 visibility += [ ":$_target_name+link" ]
418 }
419
420 public_deps = [
421 ":$_framework_target",
422 ]
423 }
424
425 group(_target_name + "+link") {
426 forward_variables_from(invoker,
427 [
428 "testonly",
429 "visibility",
430 ])
431 public_deps = [
432 ":$_framework_target+link",
433 ]
434 }
435 }
436}