Forward bundle product_type to the compile_xcassets tool.

With Xcode 8, the actool command needs to know the product_type of the
bundle that will contain the Assets.car file. Add support for forwarding
the value to the actool invocation via the compile_xcassets tool.

BUG=634373

Review-Url: https://codereview.chromium.org/2239943002
Cr-Original-Commit-Position: refs/heads/master@{#411754}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 2eb03fab2b97643f80192ec8ffe947020982f445
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index 9d62a5e..7771965 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -624,7 +624,7 @@
 
 
 ```
-## **gn format [\--dump-tree] [\--in-place] [\--stdin] BUILD.gn**
+## **gn format [\--dump-tree] (\--stdin | <build_file>)**
 
 ```
   Formats .gn file to a standard format.
@@ -642,6 +642,7 @@
 ```
 
 ### **Arguments**
+
 ```
   --dry-run
       Does not change or output anything, but sets the process exit code
@@ -652,16 +653,12 @@
       - Exit code 2: successful format, but differs from on disk.
 
   --dump-tree
-      For debugging only, dumps the parse tree.
-
-  --in-place
-      Instead of writing the formatted file to stdout, replace the input
-      file with the formatted output. If no reformatting is required,
-      the input file will not be touched, and nothing printed.
+      For debugging, dumps the parse tree to stdout and does not update
+      the file or print formatted output.
 
   --stdin
-      Read input from stdin (and write to stdout). Not compatible with
-      --in-place of course.
+      Read input from stdin and write to stdout rather than update
+      a file in-place.
 
 ```
 
@@ -2563,10 +2560,12 @@
 ```
   The sources assignment filter is a list of patterns that remove files
   from the list implicitly whenever the "sources" variable is
-  assigned to. This is intended to be used to globally filter out files
-  with platform-specific naming schemes when they don't apply, for
-  example, you may want to filter out all "*_win.cc" files on non-
-  Windows platforms.
+  assigned to. This will do nothing for non-lists.
+
+  This is intended to be used to globally filter out files with
+  platform-specific naming schemes when they don't apply, for example
+  you may want to filter out all "*_win.cc" files on non-Windows
+  platforms.
 
   Typically this will be called once in the master build config script
   to set up the filter for the current platform. Subsequent calls will
@@ -3344,7 +3343,17 @@
   copied.
 
   The compile_xcassets tool will be called with one or more source (each
-  an asset catalog) that needs to be compiled to a single output.
+  an asset catalog) that needs to be compiled to a single output. The
+  following substitutions are avaiable:
+
+    {{inputs}}
+        Expands to the list of .xcassets to use as input to compile the
+        asset catalog.
+
+    {{bundle_product_type}}
+        Expands to the product_type of the bundle that will contain the
+        compiled asset catalog. Usually corresponds to the product_type
+        property of the corresponding create_bundle target.
 
 ```
 
@@ -3420,10 +3429,25 @@
     The tool() function call specifies the commands commands to run for
     a given step. See "gn help tool".
 
-  toolchain_args()
-    List of arguments to pass to the toolchain when invoking this
-    toolchain. This applies only to non-default toolchains. See
-    "gn help toolchain_args" for more.
+  toolchain_args
+    Overrides for build arguments to pass to the toolchain when invoking
+    it. This is a variable of type "scope" where the variable names
+    correspond to variables in declare_args() blocks.
+
+    When you specify a target using an alternate toolchain, the master
+    build configuration file is re-interpreted in the context of that
+    toolchain. toolchain_args allows you to control the arguments
+    passed into this alternate invocation of the build.
+
+    Any default system arguments or arguments passed in via "gn args"
+    will also be passed to the alternate invocation unless explicitly
+    overridden by toolchain_args.
+
+    The toolchain_args will be ignored when the toolchain being defined
+    is the default. In this case, it's expected you want the default
+    argument values.
+
+    See also "gn help buildargs" for an overview of these arguments.
 
   deps
     Dependencies of this toolchain. These dependencies will be resolved
@@ -3459,13 +3483,14 @@
       by the toolchain label).
    2. Re-runs the master build configuration file, applying the
       arguments specified by the toolchain_args section of the toolchain
-      definition (see "gn help toolchain_args").
+      definition.
    3. Loads the destination build file in the context of the
       configuration file in the previous step.
 
 ```
 
-### **Example**:
+### **Example**
+
 ```
   toolchain("plugin_toolchain") {
     tool("cc") {
@@ -3473,7 +3498,7 @@
       ...
     }
 
-    toolchain_args() {
+    toolchain_args = {
       is_plugin = true
       is_32bit = true
       is_64bit = false
@@ -3485,40 +3510,10 @@
 ## **toolchain_args**: Set build arguments for toolchain build setup.
 
 ```
-  Used inside a toolchain definition to pass arguments to an alternate
-  toolchain's invocation of the build.
+  DEPRECATED. Instead use:
+    toolchain_args = { ... }
 
-  When you specify a target using an alternate toolchain, the master
-  build configuration file is re-interpreted in the context of that
-  toolchain (see "gn help toolchain"). The toolchain_args function
-  allows you to control the arguments passed into this alternate
-  invocation of the build.
-
-  Any default system arguments or arguments passed in on the command-
-  line will also be passed to the alternate invocation unless explicitly
-  overridden by toolchain_args.
-
-  The toolchain_args will be ignored when the toolchain being defined
-  is the default. In this case, it's expected you want the default
-  argument values.
-
-  See also "gn help buildargs" for an overview of these arguments.
-
-```
-
-### **Example**:
-```
-  toolchain("my_weird_toolchain") {
-    ...
-    toolchain_args() {
-      # Override the system values for a generic Posix system.
-      is_win = false
-      is_posix = true
-
-      # Pass this new value for specific setup for my toolchain.
-      is_my_weird_system = true
-    }
-  }
+  See "gn help toolchain" for documentation.
 
 
 ```
@@ -4175,6 +4170,40 @@
 
 
 ```
+## **bundle_deps_filter**: [label list] A list of labels that are filtered out.
+
+```
+  A list of target labels.
+
+  This list contains target label patterns that should be filtered out
+  when creating the bundle. Any target matching one of those label will
+  be removed from the dependencies of the create_bundle target.
+
+  This is mostly useful when creating application extension bundle as
+  the application extension has access to runtime resources from the
+  application bundle and thus do not require a second copy.
+
+  See "gn help create_bundle" for more information.
+
+```
+
+### **Example**
+
+```
+  create_bundle("today_extension") {
+    deps = [
+      "//base"
+    ]
+    bundle_root_dir = "$root_out_dir/today_extension.appex"
+    bundle_deps_filter = [
+      # The extension uses //base but does not use any function calling
+      # into third_party/icu and thus does not need the icudtl.dat file.
+      "//third_party/icu:icudata",
+    ]
+  }
+
+
+```
 ## **bundle_executable_dir**: Expansion of {{bundle_executable_dir}} in create_bundle.
 
 ```
@@ -4830,40 +4859,6 @@
 
 
 ```
-## **bundle_deps_filter**: [label list] A list of labels that are filtered out.
-
-```
-  A list of target labels.
-
-  This list contains target label patterns that should be filtered out
-  when creating the bundle. Any target matching one of those label will
-  be removed from the dependencies of the create_bundle target.
-
-  This is mostly useful when creating application extension bundle as
-  the application extension has access to runtime resources from the
-  application bundle and thus do not require a second copy.
-
-  See "gn help create_bundle" for more information.
-
-```
-
-### **Example**
-
-```
-  create_bundle("today_extension") {
-    deps = [
-      "//base"
-    ]
-    bundle_root_dir = "$root_out_dir/today_extension.appex"
-    bundle_deps_filter = [
-      # The extension uses //base but does not use any function calling
-      # into third_party/icu and thus does not need the icudtl.dat file.
-      "//third_party/icu:icudata",
-    ]
-  }
-
-
-```
 ## **include_dirs**: Additional include directories.
 
 ```
@@ -5741,7 +5736,7 @@
   toolchain_args section of a toolchain definition. The use-case for
   this is that a toolchain may be building code for a different
   platform, and that it may want to always specify Posix, for example.
-  See "gn help toolchain_args" for more.
+  See "gn help toolchain" for more.
 
   If you specify an override for a build argument that never appears in
   a "declare_args" call, a nonfatal error will be displayed.
@@ -5871,7 +5866,7 @@
 
 
 ```
-## **GN build language grammar**
+## **Language and grammar for GN build files**
 
 ### **Tokens**
 
@@ -5951,6 +5946,13 @@
   To insert an arbitrary byte value, use $0xFF. For example, to
   insert a newline character: "Line one$0x0ALine two".
 
+  An expansion will evaluate the variable following the '$' and insert
+  a stringified version of it into the result. For example, to concat
+  two path components with a slash separating them:
+    "$var_one/$var_two"
+  Use the "${var_one}" format to be explicitly deliniate the variable
+  for otherwise-ambiguous cases.
+
 ```
 
 ### **Punctuation**
@@ -5973,19 +5975,20 @@
       File = StatementList .
 
       Statement     = Assignment | Call | Condition .
-      Assignment    = identifier AssignOp Expr .
+      LValue        = identifier | ArrayAccess | ScopeAccess .
+      Assignment    = LValue AssignOp Expr .
       Call          = identifier "(" [ ExprList ] ")" [ Block ] .
       Condition     = "if" "(" Expr ")" Block
                       [ "else" ( Condition | Block ) ] .
       Block         = "{" StatementList "}" .
       StatementList = { Statement } .
 
-      ArrayAccess = identifier "[" { identifier | integer } "]" .
+      ArrayAccess = identifier "[" Expr "]" .
       ScopeAccess = identifier "." identifier .
       Expr        = UnaryExpr | Expr BinaryOp Expr .
       UnaryExpr   = PrimaryExpr | UnaryOp UnaryExpr .
       PrimaryExpr = identifier | integer | string | Call
-                  | ArrayAccess | ScopeAccess
+                  | ArrayAccess | ScopeAccess | Block
                   | "(" Expr ")"
                   | "[" [ ExprList [ "," ] ] "]" .
       ExprList    = Expr { "," Expr } .
@@ -6000,6 +6003,103 @@
 
   All binary operators are left-associative.
 
+```
+
+### **Types**
+
+```
+  The GN language is dynamically typed. The following types are used:
+
+   - Boolean: Uses the keywords "true" and "false". There is no
+     implicit conversion between booleans and integers.
+
+   - Integers: All numbers in GN are signed 64-bit integers.
+
+   - Strings: Strings are 8-bit with no enforced encoding. When a string
+     is used to interact with other systems with particular encodings
+     (like the Windows and Mac filesystems) it is assumed to be UTF-8.
+     See "String literals" above for more.
+
+   - Lists: Lists are arbitrary-length ordered lists of values. See
+     "Lists" below for more.
+
+   - Scopes: Scopes are like dictionaries that use variable names for
+     keys. See "Scopes" below for more.
+
+```
+
+### **Lists**
+
+```
+  Lists are created with [] and using commas to separate items:
+
+       mylist = [ 0, 1, 2, "some string" ]
+
+  A comma after the last item is optional. Lists are dereferenced using
+  0-based indexing:
+
+       mylist[0] += 1
+       var = mylist[2]
+
+  Lists can be concatenated using the '+' and '+=' operators. Bare
+  values can not be concatenated with lists, to add a single item,
+  it must be put into a list of length one.
+
+  Items can be removed from lists using the '-' and '-=' operators.
+  This will remove all occurrences of every item in the right-hand list
+  from the left-hand list. It is an error to remove an item not in the
+  list. This is to prevent common typos and to detect dead code that
+  is removing things that no longer apply.
+
+  It is an error to use '=' to replace a nonempty list with another
+  nonempty list. This is to prevent accidentally overwriting data
+  when in most cases '+=' was intended. To overwrite a list on purpose,
+  first assign it to the empty list:
+
+    mylist = []
+    mylist = otherlist
+
+  When assigning to a list named 'sources' using '=' or '+=', list
+  items may be automatically filtered out.
+  See "gn help set_sources_assignment_filter" for more.
+
+```
+
+### **Scopes**
+
+```
+  All execution happens in the context of a scope which holds the
+  current state (like variables). With the exception of loops and
+  conditions, '{' introduces a new scope that has a parent reference to
+  the old scope.
+
+  Variable reads recursively search all nested scopes until the
+  variable is found or there are no more scopes. Variable writes always
+  go into the current scope. This means that after the closing '}'
+  (again excepting loops and conditions), all local variables will be
+  restored to the previous values. This also means that "foo = foo"
+  can do useful work by copying a variable into the current scope that
+  was defined in a containing scope.
+
+  Scopes can also be assigned to variables. Such scopes can be created
+  by functions like exec_script, when invoking a template (the template
+  code refers to the variables set by the invoking code by the
+  implicitly-created "invoker" scope), or explicitly like:
+
+    empty_scope = {}
+    myvalues = {
+      foo = 21
+      bar = "something"
+    }
+
+  Inside such a scope definition can be any GN code including
+  conditionals and function calls. After the close of the scope, it will
+  contain all variables explicitly set by the code contained inside it.
+  After this, the values can be read, modified, or added to:
+
+    myvalues.foo += 2
+    empty_scope.new_thing = [ 1, 2, 3 ]
+
 
 ```
 ## **input_conversion**: Specifies how to transform input to a variable.
diff --git a/tools/gn/function_toolchain.cc b/tools/gn/function_toolchain.cc
index 69ca961..0072e65 100644
--- a/tools/gn/function_toolchain.cc
+++ b/tools/gn/function_toolchain.cc
@@ -317,7 +317,7 @@
     "  toolchain_args\n"
     "    Overrides for build arguments to pass to the toolchain when invoking\n"
     "    it. This is a variable of type \"scope\" where the variable names\n"
-    "    correspond to varibles in declare_args() blocks.\n"
+    "    correspond to variables in declare_args() blocks.\n"
     "\n"
     "    When you specify a target using an alternate toolchain, the master\n"
     "    build configuration file is re-interpreted in the context of that\n"
@@ -858,7 +858,17 @@
     "  copied.\n"
     "\n"
     "  The compile_xcassets tool will be called with one or more source (each\n"
-    "  an asset catalog) that needs to be compiled to a single output.\n"
+    "  an asset catalog) that needs to be compiled to a single output. The\n"
+    "  following substitutions are avaiable:\n"
+    "\n"
+    "    {{inputs}}\n"
+    "        Expands to the list of .xcassets to use as input to compile the\n"
+    "        asset catalog.\n"
+    "\n"
+    "    {{bundle_product_type}}\n"
+    "        Expands to the product_type of the bundle that will contain the\n"
+    "        compiled asset catalog. Usually corresponds to the product_type\n"
+    "        property of the corresponding create_bundle target.\n"
     "\n"
     "Separate linking and dependencies for shared libraries\n"
     "\n"
diff --git a/tools/gn/ninja_create_bundle_target_writer.cc b/tools/gn/ninja_create_bundle_target_writer.cc
index 3b87129..77e05b2 100644
--- a/tools/gn/ninja_create_bundle_target_writer.cc
+++ b/tools/gn/ninja_create_bundle_target_writer.cc
@@ -164,6 +164,9 @@
   out_ << " | ";
   path_output_.WriteFile(out_, input_dep);
   out_ << std::endl;
+
+  out_ << "  product_type = " << target_->bundle_data().product_type()
+       << std::endl;
 }
 
 OutputFile
diff --git a/tools/gn/ninja_create_bundle_target_writer_unittest.cc b/tools/gn/ninja_create_bundle_target_writer_unittest.cc
index dee99c4..15885ba 100644
--- a/tools/gn/ninja_create_bundle_target_writer_unittest.cc
+++ b/tools/gn/ninja_create_bundle_target_writer_unittest.cc
@@ -95,6 +95,7 @@
   SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
   create_bundle.set_output_type(Target::CREATE_BUNDLE);
   create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
+  create_bundle.bundle_data().product_type().assign("com.apple.product-type");
   create_bundle.SetToolchain(setup.toolchain());
   ASSERT_TRUE(create_bundle.OnResolved(&err));
 
@@ -105,6 +106,7 @@
   const char expected[] =
       "build bar.bundle/Contents/Resources/Assets.car: compile_xcassets "
           "../../foo/Foo.xcassets | obj/foo/data.stamp\n"
+      "  product_type = com.apple.product-type\n"
       "build obj/baz/bar.stamp: stamp "
           "bar.bundle/Contents/Resources/Assets.car\n"
       "build bar.bundle: phony obj/baz/bar.stamp\n";
@@ -210,6 +212,7 @@
   create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data1));
   create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data2));
   create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data3));
+  create_bundle.bundle_data().product_type().assign("com.apple.product-type");
   create_bundle.SetToolchain(setup.toolchain());
   ASSERT_TRUE(create_bundle.OnResolved(&err));
 
@@ -230,6 +233,7 @@
       "build bar.bundle/Contents/Resources/Assets.car: compile_xcassets "
           "../../foo/Foo.xcassets "
           "../../quz/Quz.xcassets | obj/baz/bar.xcassets.inputdeps.stamp\n"
+      "  product_type = com.apple.product-type\n"
       "build obj/baz/bar.stamp: stamp "
           "bar.bundle/Contents/Info.plist "
           "bar.bundle/Contents/Resources/input1.txt "
diff --git a/tools/gn/substitution_type.cc b/tools/gn/substitution_type.cc
index fcca19d..7730070 100644
--- a/tools/gn/substitution_type.cc
+++ b/tools/gn/substitution_type.cc
@@ -53,6 +53,7 @@
   "{{bundle_resources_dir}}",  // SUBSTITUTION_BUNDLE_RESOURCES_DIR
   "{{bundle_executable_dir}}",  // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR
   "{{bundle_plugins_dir}}",  // SUBSTITUTION_BUNDLE_PLUGINS_DIR
+  "{{bundle_product_type}}",  // SUBSTITUTION_BUNDLE_PRODUCT_TYPE
 
   "{{response_file_name}}",  // SUBSTITUTION_RSP_FILE_NAME
 };
@@ -104,6 +105,7 @@
     "bundle_resources_dir",   // SUBSTITUTION_BUNDLE_RESOURCES_DIR
     "bundle_executable_dir",  // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR
     "bundle_plugins_dir",     // SUBSTITUTION_BUNDLE_PLUGINS_DIR
+    "product_type",           // SUBSTITUTION_BUNDLE_PRODUCT_TYPE
 
     "rspfile",  // SUBSTITUTION_RSP_FILE_NAME
 };
@@ -227,7 +229,8 @@
 
 bool IsValidCompileXCassetsSubstitution(SubstitutionType type) {
   return IsValidToolSubstitution(type) ||
-         type == SUBSTITUTION_LINKER_INPUTS;
+         type == SUBSTITUTION_LINKER_INPUTS ||
+         type == SUBSTITUTION_BUNDLE_PRODUCT_TYPE;
 }
 
 bool EnsureValidSourcesSubstitutions(
diff --git a/tools/gn/substitution_type.h b/tools/gn/substitution_type.h
index e82ecd6..84524fb 100644
--- a/tools/gn/substitution_type.h
+++ b/tools/gn/substitution_type.h
@@ -69,6 +69,9 @@
   SUBSTITUTION_BUNDLE_EXECUTABLE_DIR,  // {{bundle_executable_dir}}
   SUBSTITUTION_BUNDLE_PLUGINS_DIR,  // {{bundle_plugins_dir}}
 
+  // Valid for compile_xcassets tool.
+  SUBSTITUTION_BUNDLE_PRODUCT_TYPE,  // {{bundle_product_type}}
+
   // Used only for the args of actions.
   SUBSTITUTION_RSP_FILE_NAME,  // {{response_file_name}}