1# Copyright (c) 2013 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 5# ============================================================================= 6# PLATFORM SELECTION 7# ============================================================================= 8# 9# There are two main things to set: "os" and "cpu". The "toolchain" is the name 10# of the GN thing that encodes combinations of these things. 11# 12# Users typically only set the variables "target_os" and "target_cpu" in "gn 13# args", the rest are set up by our build and internal to GN. 14# 15# There are three different types of each of these things: The "host" 16# represents the computer doing the compile and never changes. The "target" 17# represents the main thing we're trying to build. The "current" represents 18# which configuration is currently being defined, which can be either the 19# host, the target, or something completely different (like nacl). GN will 20# run the same build file multiple times for the different required 21# configuration in the same build. 22# 23# This gives the following variables: 24# - host_os, host_cpu, host_toolchain 25# - target_os, target_cpu, default_toolchain 26# - current_os, current_cpu, current_toolchain. 27# 28# Note the default_toolchain isn't symmetrical (you would expect 29# target_toolchain). This is because the "default" toolchain is a GN built-in 30# concept, and "target" is something our build sets up that's symmetrical with 31# its GYP counterpart. Potentially the built-in default_toolchain variable 32# could be renamed in the future. 33# 34# When writing build files, to do something only for the host: 35# if (current_toolchain == host_toolchain) { ... 36 37if (target_os == "") { 38 target_os = host_os 39} 40 41if (target_cpu == "") { 42 if (target_os == "android") { 43 # If we're building for Android, we should assume that we want to 44 # build for ARM by default, not the host_cpu (which is likely x64). 45 # This allows us to not have to specify both target_os and target_cpu 46 # on the command line. 47 target_cpu = "arm" 48 } else { 49 target_cpu = host_cpu 50 } 51} 52 53if (current_cpu == "") { 54 current_cpu = target_cpu 55} 56if (current_os == "") { 57 current_os = target_os 58} 59 60# ============================================================================= 61# BUILD FLAGS 62# ============================================================================= 63# 64# This block lists input arguments to the build, along with their default 65# values. 66# 67# If a value is specified on the command line, it will overwrite the defaults 68# given in a declare_args block, otherwise the default will be used. 69# 70# YOU SHOULD ALMOST NEVER NEED TO ADD FLAGS TO THIS FILE. GN allows any file in 71# the build to declare build flags. If you need a flag for a single component, 72# you can just declare it in the corresponding BUILD.gn file. If you need a 73# flag in multiple components, there are a few options: 74# 75# - If your feature is a single target, say //components/foo, and the targets 76# depending on foo need to have some define set if foo is enabled: (1) Write 77# a declare_args block in foo's BUILD.gn file listing your enable_foo build 78# flag. (2) Write a config in that file listing the define, and list that 79# config in foo's public_configs. This will propagate that define to all the 80# targets depending on foo. (3) When foo is not enabled, just make it expand 81# to an empty group (or whatever's appropriate for the "off" state of your 82# feature. 83# 84# - If a semi-random set of targets need to know about a define: (1) In the 85# lowest level of the build that knows about this feature, add a declare_args 86# block in the build file for your enable flag. (2) Write a config that adds 87# a define conditionally based on that build flags. (3) Manually add that 88# config to the "configs" applying to the targets that need the define. 89# 90# - If a semi-random set of targets need to know about the build flag (to do 91# file inclusion or exclusion, more than just defines): (1) Write a .gni file 92# in the lowest-level directory that knows about the feature. (2) Put the 93# declare_args block with your build flag in that .gni file. (3) Import that 94# .gni file from the BUILD.gn files that need the flag. 95# 96# Other advice: 97# 98# - Use boolean values when possible. If you need a default value that expands 99# to some complex thing in the default case (like the location of the 100# compiler which would be computed by a script), use a default value of -1 or 101# the empty string. Outside of the declare_args block, conditionally expand 102# the default value as necessary. 103# 104# - Use a name like "use_foo" or "is_foo" (whatever is more appropriate for 105# your feature) rather than just "foo". 106# 107# - Write good comments directly above the declaration with no blank line. 108# These comments will appear as documentation in "gn args --list". 109# 110# - Don't call exec_script inside declare_args. This will execute the script 111# even if the value is overridden, which is wasteful. See first bullet. 112 113declare_args() { 114 # Component build. 115 is_component_build = false 116 117 # Debug build. 118 is_debug = true 119 120 # Whether we're a traditional desktop unix. 121 is_desktop_linux = current_os == "linux" 122 123 # Set to true when compiling with the Clang compiler. Typically this is used 124 # to configure warnings. 125 is_clang = current_os == "mac" || current_os == "ios" || 126 current_os == "linux" || current_os == "chromeos" 127 128 # Allows the path to a custom target toolchain to be injected as a single 129 # argument, and set as the default toolchain. 130 custom_toolchain = "" 131 132 # This should not normally be set as a build argument. It's here so that 133 # every toolchain can pass through the "global" value via toolchain_args(). 134 host_toolchain = "" 135 136 # DON'T ADD MORE FLAGS HERE. Read the comment above. 137} 138 139# ============================================================================== 140# TOOLCHAIN SETUP 141# ============================================================================== 142# 143# Here we set the default toolchain, as well as the variable host_toolchain 144# which will identify the toolchain corresponding to the local system when 145# doing cross-compiles. When not cross-compiling, this will be the same as the 146# default toolchain. 147# 148# We do this before anything else to make sure we complain about any 149# unsupported os/cpu combinations as early as possible. 150 151if (host_toolchain == "") { 152 # This should only happen in the top-level context. 153 # In a specific toolchain context, the toolchain_args() 154 # block should have propagated a value down. 155 # TODO(dpranke): Add some sort of assert here that verifies that 156 # no toolchain omitted host_toolchain from its toolchain_args(). 157 158 if (host_os == "linux") { 159 if (target_os != "linux") { 160 # TODO(dpranke) - is_clang normally applies only to the target 161 # build, and there is no way to indicate that you want to override 162 # it for both the target build *and* the host build. Do we need to 163 # support this? 164 host_toolchain = "//build/toolchain/linux:clang_$host_cpu" 165 } else if (is_clang) { 166 host_toolchain = "//build/toolchain/linux:clang_$host_cpu" 167 } else { 168 host_toolchain = "//build/toolchain/linux:$host_cpu" 169 } 170 } else if (host_os == "mac") { 171 host_toolchain = "//build/toolchain/mac:clang_$host_cpu" 172 } else if (host_os == "win") { 173 # TODO(crbug.com/467159): win cross-compiles don't actually work yet, so 174 # use the target_cpu instead of the host_cpu. 175 if (is_clang) { 176 host_toolchain = "//build/toolchain/win:clang_$target_cpu" 177 } else { 178 host_toolchain = "//build/toolchain/win:$target_cpu" 179 } 180 } else { 181 assert(false, "Unsupported host_os: $host_os") 182 } 183} 184 185_default_toolchain = "" 186 187if (target_os == "android") { 188 assert(host_os == "linux" || host_os == "mac", 189 "Android builds are only supported on Linux and Mac hosts.") 190 if (is_clang) { 191 _default_toolchain = "//build/toolchain/android:clang_$target_cpu" 192 } else { 193 _default_toolchain = "//build/toolchain/android:$target_cpu" 194 } 195} else if (target_os == "chromeos") { 196 # See comments in build/toolchain/cros/BUILD.gn about board compiles. 197 assert(host_os == "linux", 198 "ChromeOS builds are only supported on Linux hosts.") 199 if (is_clang) { 200 _default_toolchain = "//build/toolchain/cros:clang_target" 201 } else { 202 _default_toolchain = "//build/toolchain/cros:target" 203 } 204} else if (target_os == "ios") { 205 _default_toolchain = "//build/toolchain/mac:ios_clang_arm" 206} else if (target_os == "linux") { 207 if (is_clang) { 208 _default_toolchain = "//build/toolchain/linux:clang_$target_cpu" 209 } else { 210 _default_toolchain = "//build/toolchain/linux:$target_cpu" 211 } 212} else if (target_os == "mac") { 213 assert(host_os == "mac", "Mac cross-compiles are unsupported.") 214 _default_toolchain = host_toolchain 215} else if (target_os == "win") { 216 # On Windows we use the same toolchain for host and target by default. 217 assert(target_os == host_os, "Win cross-compiles only work on win hosts.") 218 if (is_clang) { 219 _default_toolchain = "//build/toolchain/win:clang_$target_cpu" 220 } else { 221 _default_toolchain = "//build/toolchain/win:$target_cpu" 222 } 223} else if (target_os == "winrt_81" || target_os == "winrt_81_phone" || 224 target_os == "winrt_10") { 225 _default_toolchain = "//build/toolchain/win:winrt_$target_cpu" 226} else { 227 assert(false, "Unsupported target_os: $target_os") 228} 229 230# If a custom toolchain has been set in the args, set it as default. Otherwise, 231# set the default toolchain for the platform (if any). 232if (custom_toolchain != "") { 233 set_default_toolchain(custom_toolchain) 234} else if (_default_toolchain != "") { 235 set_default_toolchain(_default_toolchain) 236} 237 238# ============================================================================= 239# OS DEFINITIONS 240# ============================================================================= 241# 242# We set these various is_FOO booleans for convenience in writing OS-based 243# conditions. 244# 245# - is_android, is_chromeos, is_ios, and is_win should be obvious. 246# - is_mac is set only for desktop Mac. It is not set on iOS. 247# - is_posix is true for mac and any Unix-like system (basically everything 248# except Windows). 249# - is_linux is true for desktop Linux and ChromeOS, but not Android (which is 250# generally too different despite being based on the Linux kernel). 251# 252# Do not add more is_* variants here for random lesser-used Unix systems like 253# aix or one of the BSDs. If you need to check these, just check the 254# current_os value directly. 255 256if (current_os == "win" || current_os == "winrt_81" || 257 current_os == "winrt_81_phone" || current_os == "winrt_10") { 258 is_android = false 259 is_chromeos = false 260 is_ios = false 261 is_linux = false 262 is_mac = false 263 is_nacl = false 264 is_posix = false 265 is_win = true 266} else if (current_os == "mac") { 267 is_android = false 268 is_chromeos = false 269 is_ios = false 270 is_linux = false 271 is_mac = true 272 is_nacl = false 273 is_posix = true 274 is_win = false 275} else if (current_os == "android") { 276 is_android = true 277 is_chromeos = false 278 is_ios = false 279 is_linux = false 280 is_mac = false 281 is_nacl = false 282 is_posix = true 283 is_win = false 284} else if (current_os == "chromeos") { 285 is_android = false 286 is_chromeos = true 287 is_ios = false 288 is_linux = true 289 is_mac = false 290 is_nacl = false 291 is_posix = true 292 is_win = false 293} else if (current_os == "nacl") { 294 # current_os == "nacl" will be passed by the nacl toolchain definition. 295 # It is not set by default or on the command line. We treat is as a 296 # Posix variant. 297 is_android = false 298 is_chromeos = false 299 is_ios = false 300 is_linux = false 301 is_mac = false 302 is_nacl = true 303 is_posix = true 304 is_win = false 305} else if (current_os == "ios") { 306 is_android = false 307 is_chromeos = false 308 is_ios = true 309 is_linux = false 310 is_mac = false 311 is_nacl = false 312 is_posix = true 313 is_win = false 314} else if (current_os == "linux") { 315 is_android = false 316 is_chromeos = false 317 is_ios = false 318 is_linux = true 319 is_mac = false 320 is_nacl = false 321 is_posix = true 322 is_win = false 323} 324 325# ============================================================================= 326# SOURCES FILTERS 327# ============================================================================= 328# 329# These patterns filter out platform-specific files when assigning to the 330# sources variable. The magic variable |sources_assignment_filter| is applied 331# to each assignment or appending to the sources variable and matches are 332# automatcally removed. 333# 334# Note that the patterns are NOT regular expressions. Only "*" and "\b" (path 335# boundary = end of string or slash) are supported, and the entire string 336# muct match the pattern (so you need "*.cc" to match all .cc files, for 337# example). 338 339# DO NOT ADD MORE PATTERNS TO THIS LIST, see set_sources_assignment_filter call 340# below. 341sources_assignment_filter = [] 342if (!is_posix) { 343 sources_assignment_filter += [ 344 "*_posix.h", 345 "*_posix.cc", 346 "*_posix_unittest.h", 347 "*_posix_unittest.cc", 348 "*\bposix/*", 349 ] 350} 351if (!is_win) { 352 sources_assignment_filter += [ 353 "*_win.cc", 354 "*_win.h", 355 "*_win_unittest.cc", 356 "*\bwin/*", 357 "*.def", 358 "*.rc", 359 ] 360} 361if (!is_mac) { 362 sources_assignment_filter += [ 363 "*_mac.h", 364 "*_mac.cc", 365 "*_mac.mm", 366 "*_mac_unittest.h", 367 "*_mac_unittest.cc", 368 "*_mac_unittest.mm", 369 "*\bmac/*", 370 "*_cocoa.h", 371 "*_cocoa.cc", 372 "*_cocoa.mm", 373 "*_cocoa_unittest.h", 374 "*_cocoa_unittest.cc", 375 "*_cocoa_unittest.mm", 376 "*\bcocoa/*", 377 ] 378} 379if (!is_ios) { 380 sources_assignment_filter += [ 381 "*_ios.h", 382 "*_ios.cc", 383 "*_ios.mm", 384 "*_ios_unittest.h", 385 "*_ios_unittest.cc", 386 "*_ios_unittest.mm", 387 "*\bios/*", 388 ] 389} 390if (!is_mac && !is_ios) { 391 sources_assignment_filter += [ "*.mm" ] 392} 393if (!is_linux) { 394 sources_assignment_filter += [ 395 "*_linux.h", 396 "*_linux.cc", 397 "*_linux_unittest.h", 398 "*_linux_unittest.cc", 399 "*\blinux/*", 400 ] 401} 402if (!is_android) { 403 sources_assignment_filter += [ 404 "*_android.h", 405 "*_android.cc", 406 "*_android_unittest.h", 407 "*_android_unittest.cc", 408 "*\bandroid/*", 409 ] 410} 411if (!is_chromeos) { 412 sources_assignment_filter += [ 413 "*_chromeos.h", 414 "*_chromeos.cc", 415 "*_chromeos_unittest.h", 416 "*_chromeos_unittest.cc", 417 "*\bchromeos/*", 418 ] 419} 420 421# DO NOT ADD MORE PATTERNS TO THIS LIST, see set_sources_assignment_filter call 422# below. 423 424# Actually save this list. 425# 426# These patterns are executed for every file in the source tree of every run. 427# Therefore, adding more patterns slows down the build for everybody. We should 428# only add automatic patterns for configurations affecting hundreds of files 429# across many projects in the tree. 430# 431# Therefore, we only add rules to this list corresponding to platforms on the 432# Chromium waterfall. This is not for non-officially-supported platforms 433# (FreeBSD, etc.) toolkits, (X11, GTK, etc.), or features. For these cases, 434# write a conditional in the target to remove the file(s) from the list when 435# your platform/toolkit/feature doesn't apply. 436set_sources_assignment_filter(sources_assignment_filter) 437 438# ============================================================================= 439# TARGET DEFAULTS 440# ============================================================================= 441# 442# Set up the default configuration for every build target of the given type. 443# The values configured here will be automatically set on the scope of the 444# corresponding target. Target definitions can add or remove to the settings 445# here as needed. 446 447# Holds all configs used for making native executables and libraries, to avoid 448# duplication in each target below. 449_native_compiler_configs = [ 450 "//build/config:feature_flags", 451 "//build/config/compiler:compiler", 452 "//build/config/compiler:clang_stackrealign", 453 "//build/config/compiler:compiler_arm_fpu", 454 "//build/config/compiler:chromium_code", 455 "//build/config/compiler:default_include_dirs", 456 "//build/config/compiler:default_optimization", 457 "//build/config/compiler:default_symbols", 458 "//build/config/compiler:no_rtti", 459 "//build/config/compiler:runtime_library", 460 "//build/config/sanitizers:default_sanitizer_flags", 461] 462if (is_win) { 463 _native_compiler_configs += [ 464 "//build/config/win:lean_and_mean", 465 "//build/config/win:nominmax", 466 "//build/config/win:unicode", 467 "//build/config/win:winver", 468 "//build/config/win:vs_code_analysis", 469 ] 470} 471if (current_os == "winrt_81" || current_os == "winrt_81_phone" || 472 current_os == "winrt_10") { 473 _native_compiler_configs += [ "//build/config/win:target_winrt" ] 474} 475if (is_posix) { 476 _native_compiler_configs += [ 477 "//build/config/gcc:no_exceptions", 478 "//build/config/gcc:symbol_visibility_hidden", 479 ] 480} 481 482if (is_android) { 483 _native_compiler_configs += 484 [ "//build/config/android:default_cygprofile_instrumentation" ] 485} 486 487if (is_clang && !is_nacl) { 488 _native_compiler_configs += [ 489 "//build/config/clang:find_bad_constructs", 490 "//build/config/clang:extra_warnings", 491 ] 492} 493 494# Debug/release-related defines. 495if (is_debug) { 496 _native_compiler_configs += [ "//build/config:debug" ] 497} else { 498 _native_compiler_configs += [ "//build/config:release" ] 499} 500 501if (is_win) { 502 # Many targets remove these configs, so they are not contained within 503 # //build/config:executable_config for easy removal. 504 _windows_linker_configs = [ 505 "//build/config/win:default_incremental_linking", 506 507 # Default to console-mode apps. Most of our targets are tests and such 508 # that shouldn't use the windows subsystem. 509 "//build/config/win:console", 510 ] 511} 512 513# Executable defaults. 514_executable_configs = _native_compiler_configs + [ 515 "//build/config:default_libs", 516 "//build/config:executable_config", 517 ] 518if (is_win) { 519 _executable_configs += _windows_linker_configs 520} 521set_defaults("executable") { 522 configs = _executable_configs 523} 524 525# Static library defaults. 526set_defaults("static_library") { 527 configs = _native_compiler_configs 528} 529 530# Shared library and loadable module defaults (also for components in component 531# mode). 532_shared_library_configs = _native_compiler_configs + [ 533 "//build/config:default_libs", 534 "//build/config:shared_library_config", 535 ] 536if (is_win) { 537 _shared_library_configs += _windows_linker_configs 538} else if (is_android) { 539 # Strip native JNI exports from shared libraries by default. Binaries that 540 # want this can remove this config. 541 _shared_library_configs += 542 [ "//build/config/android:hide_native_jni_exports" ] 543} 544set_defaults("shared_library") { 545 configs = _shared_library_configs 546} 547set_defaults("loadable_module") { 548 configs = _shared_library_configs 549} 550if (is_component_build) { 551 set_defaults("component") { 552 configs = _shared_library_configs 553 if (is_android) { 554 configs -= [ "//build/config/android:hide_native_jni_exports" ] 555 } 556 } 557} 558if (is_ios) { 559 set_defaults("ios_framework_bundle") { 560 configs = _shared_library_configs 561 } 562} 563if (is_mac) { 564 set_defaults("mac_framework_bundle") { 565 configs = _shared_library_configs 566 } 567} 568 569# Source set defaults (also for components in non-component mode). 570set_defaults("source_set") { 571 configs = _native_compiler_configs 572} 573if (!is_component_build) { 574 set_defaults("component") { 575 configs = _native_compiler_configs 576 } 577} 578 579# Test defaults. 580set_defaults("test") { 581 if (is_android) { 582 configs = _shared_library_configs 583 } else { 584 configs = _executable_configs 585 } 586} 587 588# ============================================================================== 589# COMPONENT SETUP 590# ============================================================================== 591 592# Defines a component, which equates to a shared_library when 593# is_component_build == true and a source_set / static_library otherwise. 594# 595# Arguments are the same as a normal library with this addition: 596# component_never_use_source_set: Whether to use static_library instead of 597# source_set for non-component builds. Some targets (e.g. //base) should 598# use static_library rather than source_set to avoid linking unused object 599# files. 600template("component") { 601 _never_use_source_set = defined(invoker.component_never_use_source_set) && 602 invoker.component_never_use_source_set 603 assert(_never_use_source_set || true) # Mark as used. 604 if (is_component_build) { 605 _component_mode = "shared_library" 606 } else if (_never_use_source_set) { 607 _component_mode = "static_library" 608 } else { 609 _component_mode = "source_set" 610 } 611 target(_component_mode, target_name) { 612 # Explicitly forward visibility, implicitly forward everything else. 613 # Forwarding "*" doesn't recurse into nested scopes (to avoid copying all 614 # globals into each template invocation), so won't pick up file-scoped 615 # variables. Normally this isn't too bad, but visibility is commonly 616 # defined at the file scope. Explicitly forwarding visibility and then 617 # excluding it from the "*" set works around this problem. 618 # See http://crbug.com/594610 619 forward_variables_from(invoker, [ "visibility" ]) 620 forward_variables_from(invoker, "*", [ "visibility" ]) 621 622 # All shared libraries must have the sanitizer deps to properly link in 623 # asan mode (this target will be empty in other cases). 624 if (!defined(deps)) { 625 deps = [] 626 } 627 deps += [ "//build/config/sanitizers:deps" ] 628 } 629} 630