Add support for building .swift files

This CL allow listing .swift files in sources of compiler target
(source_set, executable, static_library, shared_library). Mixing
with other types of source files is disallowed due to complexity
of implementation (difficult to decide in which order the files
need to be built).

This adds a new "swift" tool that must always list a .swiftmodule
file as output but can generate additional outputs (.h, .o, ...).
To support whole module optimisation, the tool can have partial
outputs (i.e. have 1:1 mapping between source and output) or not.

The .swiftmodule are propagated both to direct and public deps
for generation of module search path (expanded by {{module_dirs}})
and to linkable target (expanded as {{modules}}) to embed the
module AST in the linked binary.

Based on the investigation at https://goto.google.com/swift-gn.

Bug: 121
Change-Id: If92b49f15e9ebb273feff7c935ca51698c27afa3
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/9180
Commit-Queue: Sylvain Defresne <sdefresne@chromium.org>
Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/build/gen.py b/build/gen.py
index e7a86ec..9353fb1 100755
--- a/build/gen.py
+++ b/build/gen.py
@@ -586,6 +586,9 @@
         'src/gn/substitution_pattern.cc',
         'src/gn/substitution_type.cc',
         'src/gn/substitution_writer.cc',
+        'src/gn/swift_values.cc',
+        'src/gn/swift_values_generator.cc',
+        'src/gn/swift_variables.cc',
         'src/gn/switches.cc',
         'src/gn/target.cc',
         'src/gn/target_generator.cc',
diff --git a/docs/reference.md b/docs/reference.md
index 8fc86fd..168d64e 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -92,6 +92,7 @@
     *   [args: [string list] Arguments passed to an action.](#var_args)
     *   [asmflags: [string list] Flags passed to the assembler.](#var_asmflags)
     *   [assert_no_deps: [label pattern list] Ensure no deps on these targets.](#var_assert_no_deps)
+    *   [bridge_header: [string] Path to C/Objective-C compatibility header.](#var_bridge_header)
     *   [bundle_contents_dir: Expansion of {{bundle_contents_dir}} in create_bundle.](#var_bundle_contents_dir)
     *   [bundle_deps_filter: [label list] A list of labels that are filtered out.](#var_bundle_deps_filter)
     *   [bundle_executable_dir: Expansion of {{bundle_executable_dir}} in create_bundle](#var_bundle_executable_dir)
@@ -129,6 +130,7 @@
     *   [lib_dirs: [directory list] Additional library directories.](#var_lib_dirs)
     *   [libs: [string list] Additional libraries to link.](#var_libs)
     *   [metadata: [scope] Metadata of this target.](#var_metadata)
+    *   [module_name: [string] The name for the compiled module.](#var_module_name)
     *   [output_conversion: Data format for generated_file targets.](#var_output_conversion)
     *   [output_dir: [directory] Directory to put output file in.](#var_output_dir)
     *   [output_extension: [string] Value to use for the output's file extension.](#var_output_extension)
@@ -148,6 +150,7 @@
     *   [response_file_contents: [string list] Contents of .rsp file for actions.](#var_response_file_contents)
     *   [script: [file name] Script file for actions.](#var_script)
     *   [sources: [file list] Source files for a target.](#var_sources)
+    *   [swiftflags: [string list] Flags passed to the swift compiler.](#var_swiftflags)
     *   [testonly: [boolean] Declares a target must only be used for testing.](#var_testonly)
     *   [visibility: [label list] A list of labels that can depend on a target.](#var_visibility)
     *   [walk_keys: [string list] Key(s) for managing the metadata collection walk.](#var_walk_keys)
@@ -1676,7 +1679,7 @@
   Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
          asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
          libs, precompiled_header, precompiled_source, rustflags,
-         rustenv
+         rustenv, swiftflags
   Deps: data_deps, deps, public_deps
   Dependent configs: all_dependent_configs, public_configs
   General: check_includes, configs, data, friend, inputs, metadata,
@@ -1870,7 +1873,7 @@
   Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
          asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
          libs, precompiled_header, precompiled_source, rustflags,
-         rustenv
+         rustenv, swiftflags
   Deps: data_deps, deps, public_deps
   Dependent configs: all_dependent_configs, public_configs
   General: check_includes, configs, data, friend, inputs, metadata,
@@ -1902,7 +1905,7 @@
   Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
          asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
          libs, precompiled_header, precompiled_source, rustflags,
-         rustenv
+         rustenv, swiftflags
   Deps: data_deps, deps, public_deps
   Dependent configs: all_dependent_configs, public_configs
   General: check_includes, configs, data, friend, inputs, metadata,
@@ -1937,7 +1940,7 @@
   Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
          asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
          libs, precompiled_header, precompiled_source, rustflags,
-         rustenv
+         rustenv, swiftflags
   Deps: data_deps, deps, public_deps
   Dependent configs: all_dependent_configs, public_configs
   General: check_includes, configs, data, friend, inputs, metadata,
@@ -1971,7 +1974,7 @@
   Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
          asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
          libs, precompiled_header, precompiled_source, rustflags,
-         rustenv
+         rustenv, swiftflags
   Deps: data_deps, deps, public_deps
   Dependent configs: all_dependent_configs, public_configs
   General: check_includes, configs, data, friend, inputs, metadata,
@@ -2016,7 +2019,7 @@
   Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
          asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
          libs, precompiled_header, precompiled_source, rustflags,
-         rustenv
+         rustenv, swiftflags
   Deps: data_deps, deps, public_deps
   Dependent configs: all_dependent_configs, public_configs
   General: check_includes, configs, data, friend, inputs, metadata,
@@ -2040,7 +2043,7 @@
   Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
          asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
          libs, precompiled_header, precompiled_source, rustflags,
-         rustenv
+         rustenv, swiftflags
   Deps: data_deps, deps, public_deps
   Dependent configs: all_dependent_configs, public_configs
   General: check_includes, configs, data, friend, inputs, metadata,
@@ -2149,7 +2152,7 @@
   Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
          asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
          libs, precompiled_header, precompiled_source, rustflags,
-         rustenv
+         rustenv, swiftflags
   Nested configs: configs
 ```
 
@@ -3349,10 +3352,12 @@
     Compiler tools:
       "cc": C compiler
       "cxx": C++ compiler
+      "cxx_module": C++ compiler used for Clang .modulemap files
       "objc": Objective C compiler
       "objcxx": Objective C++ compiler
       "rc": Resource compiler (Windows .rc files)
       "asm": Assembler
+      "swift": Swift compiler driver
 
     Linker tools:
       "alink": Linker for static libraries (archives)
@@ -3497,6 +3502,19 @@
         would be:
           "-F. -framework UIKit -framework Foo -weak_framework MediaPlayer"
 
+    swiftmodule_switch [string, optional, link tools only]
+        Valid for: Linker tools except "alink"
+
+        The string will be prependend to the path to the .swiftmodule files
+        that are embedded in the linker output.
+
+        If you specified:
+          swiftmodule_swift = "-Wl,-add_ast_path,"
+        then the "{{swiftmodules}}" expansion for
+          [ "obj/foo/Foo.swiftmodule" ]
+        would be
+          "-Wl,-add_ast_path,obj/foo/Foo.swiftmodule"
+
     outputs  [list of strings with substitutions]
         Valid for: Linker and compiler tools (required)
 
@@ -3527,6 +3545,17 @@
             "{{output_dir}}/{{target_output_name}}.lib",
           ]
 
+    partial_outputs  [list of strings with substitutions]
+        Valid for: "swift" only
+
+        An array of names for the partial outputs the tool produces. These
+        are relative to the build output directory. The expansion will be
+        evaluated for each file listed in the "sources" of the target.
+
+        This is used to deal with whole module optimization, allowing to
+        list one object file per source file when whole module optimization
+        is disabled.
+
     pool [label, optional]
         Valid for: all tools (optional)
 
@@ -3776,6 +3805,13 @@
         {{frameworks}} and each item will be preceded by "-framework" or
         "-weak_framework".
 
+    {{swiftmodules}}
+        Swift .swiftmodule files that needs to be embedded into the binary.
+        This is necessary to correctly link with object generated by the
+        Swift compiler (the .swiftmodule file cannot be embedded in object
+        files directly). Those will be prefixed with "swiftmodule_switch"
+        value.
+
   The static library ("alink") tool allows {{arflags}} plus the common tool
   substitutions.
 
@@ -3813,6 +3849,21 @@
         Expands to the list of flags specified in corresponding
         create_bundle target.
 
+  The Swift tool has multiple input and outputs. It must have exactly one
+  output of .swiftmodule type, but can have one or more object file outputs,
+  in addition to other type of ouputs. The following expansions are available:
+
+    {{module_name}}
+        Expands to the string representing the module name of target under
+        compilation (see "module_name" variable).
+
+    {{module_dirs}}
+        Expands to the list of -I<path> for the target Swift module search
+        path computed from target dependencies.
+
+    {{swiftflags}}
+        Expands to the list of strings representing Swift compiler flags.
+
   Rust tools have the notion of a single input and a single output, along
   with a set of compiler-specific flags. The following expansions are
   available:
@@ -4668,6 +4719,14 @@
     ]
   }
 ```
+### <a name="var_bridge_header"></a>**bridge_header**: [string] Path to C/Objective-C compatibility header.
+
+```
+  Valid for binary targets that contain Swift sources.
+
+  Path to an header that includes C/Objective-C functions and types that
+  needs to be made available to the Swift module.
+```
 ### <a name="var_bundle_contents_dir"></a>**bundle_contents_dir**: Expansion of {{bundle_contents_dir}} in
 ```
                              create_bundle.
@@ -4778,7 +4837,8 @@
   versions of cflags* will be appended on the compiler command line after
   "cflags".
 
-  See also "asmflags" for flags for assembly-language files.
+  See also "asmflags" for flags for assembly-language files and "swiftflags"
+  for swift files.
 ```
 
 #### **Ordering of flags and values**
@@ -4811,7 +4871,8 @@
   versions of cflags* will be appended on the compiler command line after
   "cflags".
 
-  See also "asmflags" for flags for assembly-language files.
+  See also "asmflags" for flags for assembly-language files and "swiftflags"
+  for swift files.
 ```
 
 #### **Ordering of flags and values**
@@ -4844,7 +4905,8 @@
   versions of cflags* will be appended on the compiler command line after
   "cflags".
 
-  See also "asmflags" for flags for assembly-language files.
+  See also "asmflags" for flags for assembly-language files and "swiftflags"
+  for swift files.
 ```
 
 #### **Ordering of flags and values**
@@ -4877,7 +4939,8 @@
   versions of cflags* will be appended on the compiler command line after
   "cflags".
 
-  See also "asmflags" for flags for assembly-language files.
+  See also "asmflags" for flags for assembly-language files and "swiftflags"
+  for swift files.
 ```
 
 #### **Ordering of flags and values**
@@ -4910,7 +4973,8 @@
   versions of cflags* will be appended on the compiler command line after
   "cflags".
 
-  See also "asmflags" for flags for assembly-language files.
+  See also "asmflags" for flags for assembly-language files and "swiftflags"
+  for swift files.
 ```
 
 #### **Ordering of flags and values**
@@ -5753,6 +5817,13 @@
     }
   }
 ```
+### <a name="var_module_name"></a>**module_name**: [string] The name for the compiled module.
+
+```
+  Valid for binary targets that contain Swift sources.
+
+  If module_name is not set, then this rule will use the target name.
+```
 ### <a name="var_output_conversion"></a>**output_conversion**: Data format for generated_file targets.
 
 ```
@@ -6307,6 +6378,32 @@
   copy
     The source are the source files to copy.
 ```
+### <a name="var_swiftflags"></a>**swiftflags**: Flags passed to the swift compiler.
+
+```
+  A list of strings.
+
+  "swiftflags" are passed to any invocation of a tool that takes an .swift
+  file as input.
+```
+
+#### **Ordering of flags and values**
+
+```
+  1. Those set on the current target (not in a config).
+  2. Those set on the "configs" on the target in order that the
+     configs appear in the list.
+  3. Those set on the "all_dependent_configs" on the target in order
+     that the configs appear in the list.
+  4. Those set on the "public_configs" on the target in order that
+     those configs appear in the list.
+  5. all_dependent_configs pulled from dependencies, in the order of
+     the "deps" list. This is done recursively. If a config appears
+     more than once, only the first occurence will be used.
+  6. public_configs pulled from dependencies, in the order of the
+     "deps" list. If a dependency is public, they will be applied
+     recursively.
+```
 ### <a name="var_testonly"></a>**testonly**: Declares a target must only be used for testing.
 
 ```
diff --git a/src/gn/binary_target_generator.cc b/src/gn/binary_target_generator.cc
index 6c085e6..485884e 100644
--- a/src/gn/binary_target_generator.cc
+++ b/src/gn/binary_target_generator.cc
@@ -14,6 +14,7 @@
 #include "gn/rust_variables.h"
 #include "gn/scope.h"
 #include "gn/settings.h"
+#include "gn/swift_values_generator.h"
 #include "gn/value_extractors.h"
 #include "gn/variables.h"
 
@@ -73,6 +74,13 @@
       return;
   }
 
+  if (target_->source_types_used().SwiftSourceUsed()) {
+    SwiftValuesGenerator swiftgen(target_, scope_, err_);
+    swiftgen.Run();
+    if (err_->has_error())
+      return;
+  }
+
   // Config values (compiler flags, etc.) set directly on this target.
   ConfigValuesGenerator gen(&target_->config_values(), scope_,
                             scope_->GetSourceDir(), err_);
@@ -99,9 +107,11 @@
       case SourceFile::SOURCE_GO:
       case SourceFile::SOURCE_RS:
       case SourceFile::SOURCE_RC:
+      case SourceFile::SOURCE_SWIFT:
         // These are allowed.
         break;
       case SourceFile::SOURCE_UNKNOWN:
+      case SourceFile::SOURCE_SWIFTMODULE:
       case SourceFile::SOURCE_NUMTYPES:
         *err_ =
             Err(scope_->GetValue(variables::kSources, true)->list_value()[i],
diff --git a/src/gn/c_substitution_type.cc b/src/gn/c_substitution_type.cc
index b9b7eba..d0c04c8 100644
--- a/src/gn/c_substitution_type.cc
+++ b/src/gn/c_substitution_type.cc
@@ -10,18 +10,21 @@
 #include "gn/err.h"
 
 const SubstitutionTypes CSubstitutions = {
-    &CSubstitutionAsmFlags,     &CSubstitutionCFlags,
-    &CSubstitutionCFlagsC,      &CSubstitutionCFlagsCc,
-    &CSubstitutionCFlagsObjC,   &CSubstitutionCFlagsObjCc,
-    &CSubstitutionDefines,      &CSubstitutionFrameworkDirs,
-    &CSubstitutionIncludeDirs,
+    &CSubstitutionAsmFlags,        &CSubstitutionCFlags,
+    &CSubstitutionCFlagsC,         &CSubstitutionCFlagsCc,
+    &CSubstitutionCFlagsObjC,      &CSubstitutionCFlagsObjCc,
+    &CSubstitutionDefines,         &CSubstitutionFrameworkDirs,
+    &CSubstitutionIncludeDirs,     &CSubstitutionSwiftModules,
 
-    &CSubstitutionLinkerInputs, &CSubstitutionLinkerInputsNewline,
-    &CSubstitutionLdFlags,      &CSubstitutionLibs,
-    &CSubstitutionSoLibs,       &CSubstitutionFrameworks,
+    &CSubstitutionLinkerInputs,    &CSubstitutionLinkerInputsNewline,
+    &CSubstitutionLdFlags,         &CSubstitutionLibs,
+    &CSubstitutionSoLibs,          &CSubstitutionFrameworks,
     &CSubstitutionRlibs,
 
     &CSubstitutionArFlags,
+
+    &CSubstitutionSwiftModuleName, &CSubstitutionSwiftBridgeHeader,
+    &CSubstitutionSwiftModuleDirs, &CSubstitutionSwiftFlags,
 };
 
 // Valid for compiler tools.
@@ -47,10 +50,21 @@
 const Substitution CSubstitutionSoLibs = {"{{solibs}}", "solibs"};
 const Substitution CSubstitutionRlibs = {"{{rlibs}}", "rlibs"};
 const Substitution CSubstitutionFrameworks = {"{{frameworks}}", "frameworks"};
+const Substitution CSubstitutionSwiftModules = {"{{swiftmodules}}",
+                                                "swiftmodules"};
 
 // Valid for alink only.
 const Substitution CSubstitutionArFlags = {"{{arflags}}", "arflags"};
 
+// Valid for swift only.
+const Substitution CSubstitutionSwiftModuleName = {"{{module_name}}",
+                                                   "module_name"};
+const Substitution CSubstitutionSwiftBridgeHeader = {"{{bridge_header}}",
+                                                     "bridge_header"};
+const Substitution CSubstitutionSwiftModuleDirs = {"{{module_dirs}}",
+                                                   "module_dirs"};
+const Substitution CSubstitutionSwiftFlags = {"{{swiftflags}}", "swiftflags"};
+
 bool IsValidCompilerSubstitution(const Substitution* type) {
   return IsValidToolSubstitution(type) || IsValidSourceSubstitution(type) ||
          type == &SubstitutionSource || type == &CSubstitutionAsmFlags ||
@@ -67,6 +81,22 @@
          IsValidSourceSubstitution(type);
 }
 
+bool IsValidSwiftCompilerSubstitution(const Substitution* type) {
+  return IsValidToolSubstitution(type) ||
+         type == &CSubstitutionSwiftModuleName ||
+         type == &CSubstitutionLinkerInputs ||
+         type == &CSubstitutionIncludeDirs ||
+         type == &CSubstitutionSwiftBridgeHeader ||
+         type == &CSubstitutionSwiftModuleDirs ||
+         type == &CSubstitutionSwiftFlags || type == &CSubstitutionDefines;
+}
+
+bool IsValidSwiftCompilerOutputsSubstitution(const Substitution* type) {
+  return (IsValidSwiftCompilerSubstitution(type) &&
+          type != &SubstitutionOutput) ||
+         IsValidSourceSubstitution(type);
+}
+
 bool IsValidLinkerSubstitution(const Substitution* type) {
   return IsValidToolSubstitution(type) || type == &SubstitutionOutputDir ||
          type == &SubstitutionOutputExtension ||
@@ -74,7 +104,7 @@
          type == &CSubstitutionLinkerInputsNewline ||
          type == &CSubstitutionLdFlags || type == &CSubstitutionLibs ||
          type == &CSubstitutionSoLibs || type == &CSubstitutionFrameworks ||
-         type == &CSubstitutionRlibs;
+         type == &CSubstitutionRlibs || type == &CSubstitutionSwiftModules;
 }
 
 bool IsValidLinkerOutputsSubstitution(const Substitution* type) {
diff --git a/src/gn/c_substitution_type.h b/src/gn/c_substitution_type.h
index d4ba606..63eb627 100644
--- a/src/gn/c_substitution_type.h
+++ b/src/gn/c_substitution_type.h
@@ -32,13 +32,22 @@
 extern const Substitution CSubstitutionSoLibs;
 extern const Substitution CSubstitutionFrameworks;
 extern const Substitution CSubstitutionRlibs;
+extern const Substitution CSubstitutionSwiftModules;
 
 // Valid for alink only.
 extern const Substitution CSubstitutionArFlags;
 
+// Valid for swift only.
+extern const Substitution CSubstitutionSwiftModuleName;
+extern const Substitution CSubstitutionSwiftBridgeHeader;
+extern const Substitution CSubstitutionSwiftModuleDirs;
+extern const Substitution CSubstitutionSwiftFlags;
+
 // Both compiler and linker tools.
 bool IsValidCompilerSubstitution(const Substitution* type);
 bool IsValidCompilerOutputsSubstitution(const Substitution* type);
+bool IsValidSwiftCompilerSubstitution(const Substitution* type);
+bool IsValidSwiftCompilerOutputsSubstitution(const Substitution* type);
 bool IsValidLinkerSubstitution(const Substitution* type);
 bool IsValidLinkerOutputsSubstitution(const Substitution* type);
 bool IsValidALinkSubstitution(const Substitution* type);
diff --git a/src/gn/c_tool.cc b/src/gn/c_tool.cc
index dc391d1..767b324 100644
--- a/src/gn/c_tool.cc
+++ b/src/gn/c_tool.cc
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "gn/c_tool.h"
+
+#include "base/strings/stringprintf.h"
 #include "gn/c_substitution_type.h"
 #include "gn/target.h"
 
@@ -13,6 +15,7 @@
 const char* CTool::kCToolObjCxx = "objcxx";
 const char* CTool::kCToolRc = "rc";
 const char* CTool::kCToolAsm = "asm";
+const char* CTool::kCToolSwift = "swift";
 const char* CTool::kCToolAlink = "alink";
 const char* CTool::kCToolSolink = "solink";
 const char* CTool::kCToolSolinkModule = "solink_module";
@@ -41,8 +44,9 @@
 bool CTool::ValidateName(const char* name) const {
   return name == kCToolCc || name == kCToolCxx || name == kCToolCxxModule ||
          name == kCToolObjC || name == kCToolObjCxx || name == kCToolRc ||
-         name == kCToolAsm || name == kCToolAlink || name == kCToolSolink ||
-         name == kCToolSolinkModule || name == kCToolLink;
+         name == kCToolSwift || name == kCToolAsm || name == kCToolAlink ||
+         name == kCToolSolink || name == kCToolSolinkModule ||
+         name == kCToolLink;
 }
 
 void CTool::SetComplete() {
@@ -141,6 +145,7 @@
 
 bool CTool::ReadOutputsPatternList(Scope* scope,
                                    const char* var,
+                                   bool required,
                                    SubstitutionList* field,
                                    Err* err) {
   DCHECK(!complete_);
@@ -155,8 +160,10 @@
     return false;
 
   // Validate the right kinds of patterns are used.
-  if (list.list().empty()) {
-    *err = Err(defined_from(), "\"outputs\" must be specified for this tool.");
+  if (list.list().empty() && required) {
+    *err =
+        Err(defined_from(),
+            base::StringPrintf("\"%s\" must be specified for this tool.", var));
     return false;
   }
 
@@ -180,7 +187,8 @@
   }
 
   // All C tools should have outputs.
-  if (!ReadOutputsPatternList(scope, "outputs", &outputs_, err)) {
+  if (!ReadOutputsPatternList(scope, "outputs", /*required=*/true, &outputs_,
+                              err)) {
     return false;
   }
 
@@ -192,10 +200,19 @@
       !ReadString(scope, "lib_switch", &lib_switch_, err) ||
       !ReadString(scope, "lib_dir_switch", &lib_dir_switch_, err) ||
       !ReadPattern(scope, "link_output", &link_output_, err) ||
+      !ReadString(scope, "swiftmodule_switch", &swiftmodule_switch_, err) ||
       !ReadPattern(scope, "depend_output", &depend_output_, err)) {
     return false;
   }
 
+  // Swift tool can optionally specify partial_outputs.
+  if (name_ == kCToolSwift) {
+    if (!ReadOutputsPatternList(scope, "partial_outputs", /*required=*/false,
+                                &partial_outputs_, err)) {
+      return false;
+    }
+  }
+
   // Validate link_output and depend_output.
   if (!ValidateLinkAndDependOutput(link_output(), "link_output", err)) {
     return false;
@@ -222,6 +239,8 @@
       name_ == kCToolObjC || name_ == kCToolObjCxx || name_ == kCToolRc ||
       name_ == kCToolAsm)
     return IsValidCompilerSubstitution(sub_type);
+  if (name_ == kCToolSwift)
+    return IsValidSwiftCompilerSubstitution(sub_type);
   else if (name_ == kCToolAlink)
     return IsValidALinkSubstitution(sub_type);
   else if (name_ == kCToolSolink || name_ == kCToolSolinkModule ||
@@ -236,6 +255,8 @@
       name_ == kCToolObjC || name_ == kCToolObjCxx || name_ == kCToolRc ||
       name_ == kCToolAsm)
     return IsValidCompilerOutputsSubstitution(sub_type);
+  if (name_ == kCToolSwift)
+    return IsValidSwiftCompilerOutputsSubstitution(sub_type);
   // ALink uses the standard output file patterns as other linker tools.
   else if (name_ == kCToolAlink || name_ == kCToolSolink ||
            name_ == kCToolSolinkModule || name_ == kCToolLink)
diff --git a/src/gn/c_tool.h b/src/gn/c_tool.h
index 01b2431..fe32e53 100644
--- a/src/gn/c_tool.h
+++ b/src/gn/c_tool.h
@@ -27,6 +27,7 @@
   static const char* kCToolObjCxx;
   static const char* kCToolRc;
   static const char* kCToolAsm;
+  static const char* kCToolSwift;
 
   // C linker tools
   static const char* kCToolAlink;
@@ -108,6 +109,7 @@
                                    Err* err);
   bool ReadOutputsPatternList(Scope* scope,
                               const char* var,
+                              bool required,
                               SubstitutionList* field,
                               Err* err);
   bool ReadPrecompiledHeaderType(Scope* scope, Err* err);
diff --git a/src/gn/command_desc.cc b/src/gn/command_desc.cc
index cdb2e74..e36cf0b 100644
--- a/src/gn/command_desc.cc
+++ b/src/gn/command_desc.cc
@@ -16,12 +16,13 @@
 #include "gn/commands.h"
 #include "gn/config.h"
 #include "gn/desc_builder.h"
+#include "gn/rust_variables.h"
 #include "gn/setup.h"
 #include "gn/standard_out.h"
+#include "gn/swift_variables.h"
 #include "gn/switches.h"
 #include "gn/target.h"
 #include "gn/variables.h"
-#include "gn/rust_variables.h"
 
 namespace commands {
 
@@ -304,6 +305,8 @@
           {variables::kWriteOutputConversion, DefaultHandler},
           {variables::kRustCrateName, DefaultHandler},
           {variables::kRustCrateRoot, DefaultHandler},
+          {variables::kSwiftModuleName, DefaultHandler},
+          {variables::kSwiftBridgeHeader, DefaultHandler},
           {"runtime_deps", DefaultHandler}};
 }
 
@@ -354,6 +357,7 @@
   // Entries with DefaultHandler are present to enforce order
   HandleProperty("type", handler_map, v, dict);
   HandleProperty("toolchain", handler_map, v, dict);
+  HandleProperty(variables::kSwiftModuleName, handler_map, v, dict);
   HandleProperty(variables::kRustCrateName, handler_map, v, dict);
   HandleProperty(variables::kRustCrateRoot, handler_map, v, dict);
   HandleProperty(variables::kVisibility, handler_map, v, dict);
@@ -362,6 +366,7 @@
   HandleProperty(variables::kCheckIncludes, handler_map, v, dict);
   HandleProperty(variables::kAllowCircularIncludesFrom, handler_map, v, dict);
   HandleProperty(variables::kSources, handler_map, v, dict);
+  HandleProperty(variables::kSwiftBridgeHeader, handler_map, v, dict);
   HandleProperty(variables::kPublic, handler_map, v, dict);
   HandleProperty(variables::kInputs, handler_map, v, dict);
   HandleProperty(variables::kConfigs, handler_map, v, dict);
@@ -379,6 +384,7 @@
   HandleProperty(variables::kCflagsCC, handler_map, v, dict);
   HandleProperty(variables::kCflagsObjC, handler_map, v, dict);
   HandleProperty(variables::kCflagsObjCC, handler_map, v, dict);
+  HandleProperty(variables::kSwiftflags, handler_map, v, dict);
   HandleProperty(variables::kDefines, handler_map, v, dict);
   HandleProperty(variables::kFrameworkDirs, handler_map, v, dict);
   HandleProperty(variables::kFrameworks, handler_map, v, dict);
@@ -444,6 +450,7 @@
   HandleProperty(variables::kCflagsCC, handler_map, v, dict);
   HandleProperty(variables::kCflagsObjC, handler_map, v, dict);
   HandleProperty(variables::kCflagsObjCC, handler_map, v, dict);
+  HandleProperty(variables::kSwiftflags, handler_map, v, dict);
   HandleProperty(variables::kDefines, handler_map, v, dict);
   HandleProperty(variables::kFrameworkDirs, handler_map, v, dict);
   HandleProperty(variables::kFrameworks, handler_map, v, dict);
diff --git a/src/gn/config_values.cc b/src/gn/config_values.cc
index ba5ddf7..9bddf99 100644
--- a/src/gn/config_values.cc
+++ b/src/gn/config_values.cc
@@ -39,6 +39,7 @@
   VectorAppend(&libs_, append.libs_);
   VectorAppend(&rustflags_, append.rustflags_);
   VectorAppend(&rustenv_, append.rustenv_);
+  VectorAppend(&swiftflags_, append.swiftflags_);
 
   // Only append precompiled header if there isn't one. It might be nice to
   // throw an error if there are conflicting precompiled headers, but that
diff --git a/src/gn/config_values.h b/src/gn/config_values.h
index ef57b26..6361e78 100644
--- a/src/gn/config_values.h
+++ b/src/gn/config_values.h
@@ -50,6 +50,7 @@
   DIR_VALUES_ACCESSOR(lib_dirs)
   STRING_VALUES_ACCESSOR(rustflags)
   STRING_VALUES_ACCESSOR(rustenv)
+  STRING_VALUES_ACCESSOR(swiftflags)
   // =================================================================
   // IMPORTANT: If you add a new one, be sure to update AppendValues()
   //            and command_desc.cc.
@@ -96,6 +97,7 @@
   std::vector<LibFile> libs_;
   std::vector<std::string> rustflags_;
   std::vector<std::string> rustenv_;
+  std::vector<std::string> swiftflags_;
   std::vector<std::pair<std::string, LibFile>> externs_;
   // If you add a new one, be sure to update AppendValues().
 
diff --git a/src/gn/config_values_generator.cc b/src/gn/config_values_generator.cc
index c8070d2..fac03d7 100644
--- a/src/gn/config_values_generator.cc
+++ b/src/gn/config_values_generator.cc
@@ -106,6 +106,7 @@
   FILL_DIR_CONFIG_VALUE(lib_dirs)
   FILL_STRING_CONFIG_VALUE(rustflags)
   FILL_STRING_CONFIG_VALUE(rustenv)
+  FILL_STRING_CONFIG_VALUE(swiftflags)
 
 #undef FILL_STRING_CONFIG_VALUE
 #undef FILL_DIR_CONFIG_VALUE
diff --git a/src/gn/config_values_generator.h b/src/gn/config_values_generator.h
index b9740d1..b7b008c 100644
--- a/src/gn/config_values_generator.h
+++ b/src/gn/config_values_generator.h
@@ -41,6 +41,6 @@
   "  Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,\n"     \
   "         asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,\n" \
   "         libs, precompiled_header, precompiled_source, rustflags,\n"    \
-  "         rustenv\n"
+  "         rustenv, swiftflags\n"
 
 #endif  // TOOLS_GN_CONFIG_VALUES_GENERATOR_H_
diff --git a/src/gn/desc_builder.cc b/src/gn/desc_builder.cc
index 3865ac0..d8639b1 100644
--- a/src/gn/desc_builder.cc
+++ b/src/gn/desc_builder.cc
@@ -20,6 +20,7 @@
 #include "gn/settings.h"
 #include "gn/standard_out.h"
 #include "gn/substitution_writer.h"
+#include "gn/swift_variables.h"
 #include "gn/variables.h"
 
 // Example structure of Value for single target
@@ -276,6 +277,7 @@
     CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string)
     CONFIG_VALUE_ARRAY_HANDLER(lib_dirs, SourceDir)
     CONFIG_VALUE_ARRAY_HANDLER(libs, LibFile)
+    CONFIG_VALUE_ARRAY_HANDLER(swiftflags, std::string)
 
 #undef CONFIG_VALUE_ARRAY_HANDLER
 
@@ -340,6 +342,18 @@
       }
     }
 
+    if (target_->source_types_used().SwiftSourceUsed()) {
+      if (what(variables::kSwiftBridgeHeader)) {
+        res->SetWithoutPathExpansion(
+            variables::kSwiftBridgeHeader,
+            RenderValue(target_->swift_values().bridge_header()));
+      }
+      if (what(variables::kSwiftModuleName)) {
+        res->SetKey(variables::kSwiftModuleName,
+                    base::Value(target_->swift_values().module_name()));
+      }
+    }
+
     // General target meta variables.
 
     if (what(variables::kMetadata)) {
@@ -491,6 +505,7 @@
       CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir)
       CONFIG_VALUE_ARRAY_HANDLER(inputs, SourceFile)
       CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string)
+      CONFIG_VALUE_ARRAY_HANDLER(swiftflags, std::string)
 #undef CONFIG_VALUE_ARRAY_HANDLER
 
       // Libs and lib_dirs are handled specially below.
diff --git a/src/gn/function_toolchain.cc b/src/gn/function_toolchain.cc
index a6642d1..1288511 100644
--- a/src/gn/function_toolchain.cc
+++ b/src/gn/function_toolchain.cc
@@ -289,6 +289,7 @@
       "objcxx": Objective C++ compiler
       "rc": Resource compiler (Windows .rc files)
       "asm": Assembler
+      "swift": Swift compiler driver
 
     Linker tools:
       "alink": Linker for static libraries (archives)
@@ -431,6 +432,19 @@
         would be:
           "-F. -framework UIKit -framework Foo -weak_framework MediaPlayer"
 
+    swiftmodule_switch [string, optional, link tools only]
+        Valid for: Linker tools except "alink"
+
+        The string will be prependend to the path to the .swiftmodule files
+        that are embedded in the linker output.
+
+        If you specified:
+          swiftmodule_swift = "-Wl,-add_ast_path,"
+        then the "{{swiftmodules}}" expansion for
+          [ "obj/foo/Foo.swiftmodule" ]
+        would be
+          "-Wl,-add_ast_path,obj/foo/Foo.swiftmodule"
+
     outputs  [list of strings with substitutions]
         Valid for: Linker and compiler tools (required)
 
@@ -461,6 +475,17 @@
             "{{output_dir}}/{{target_output_name}}.lib",
           ]
 
+    partial_outputs  [list of strings with substitutions]
+        Valid for: "swift" only
+
+        An array of names for the partial outputs the tool produces. These
+        are relative to the build output directory. The expansion will be
+        evaluated for each file listed in the "sources" of the target.
+
+        This is used to deal with whole module optimization, allowing to
+        list one object file per source file when whole module optimization
+        is disabled.
+
     pool [label, optional]
         Valid for: all tools (optional)
 
@@ -709,6 +734,13 @@
         {{frameworks}} and each item will be preceded by "-framework" or
         "-weak_framework".
 
+    {{swiftmodules}}
+        Swift .swiftmodule files that needs to be embedded into the binary.
+        This is necessary to correctly link with object generated by the
+        Swift compiler (the .swiftmodule file cannot be embedded in object
+        files directly). Those will be prefixed with "swiftmodule_switch"
+        value.
+
 )"  // String break to prevent overflowing the 16K max VC string length.
     R"(  The static library ("alink") tool allows {{arflags}} plus the common tool
   substitutions.
@@ -747,6 +779,21 @@
         Expands to the list of flags specified in corresponding
         create_bundle target.
 
+  The Swift tool has multiple input and outputs. It must have exactly one
+  output of .swiftmodule type, but can have one or more object file outputs,
+  in addition to other type of ouputs. The following expansions are available:
+
+    {{module_name}}
+        Expands to the string representing the module name of target under
+        compilation (see "module_name" variable).
+
+    {{module_dirs}}
+        Expands to the list of -I<path> for the target Swift module search
+        path computed from target dependencies.
+
+    {{swiftflags}}
+        Expands to the list of strings representing Swift compiler flags.
+
   Rust tools have the notion of a single input and a single output, along
   with a set of compiler-specific flags. The following expansions are
   available:
diff --git a/src/gn/ninja_binary_target_writer.cc b/src/gn/ninja_binary_target_writer.cc
index 098a595..08e8c93 100644
--- a/src/gn/ninja_binary_target_writer.cc
+++ b/src/gn/ninja_binary_target_writer.cc
@@ -156,6 +156,9 @@
   // don't link at all.
   bool can_link_libs = target_->IsFinal();
 
+  if (can_link_libs && dep->swift_values().builds_module())
+    classified_deps->swiftmodule_deps.push_back(dep);
+
   if (dep->output_type() == Target::SOURCE_SET ||
       // If a complete static library depends on an incomplete static library,
       // manually link in the object files of the dependent library as if it
@@ -209,6 +212,25 @@
       obj_files->push_back(tool_outputs[0]);
   }
 
+  // Swift files may generate one object file per module or one per source file
+  // depending on how the compiler is invoked (whole module optimization).
+  if (source_set->source_types_used().SwiftSourceUsed()) {
+    const Tool* tool = source_set->toolchain()->GetToolForSourceTypeAsC(
+        SourceFile::SOURCE_SWIFT);
+
+    std::vector<OutputFile> outputs;
+    SubstitutionWriter::ApplyListToLinkerAsOutputFile(
+        source_set, tool, tool->outputs(), &outputs);
+
+    for (const OutputFile& output : outputs) {
+      SourceFile output_as_source =
+          output.AsSourceFile(source_set->settings()->build_settings());
+      if (output_as_source.type() == SourceFile::SOURCE_O) {
+        obj_files->push_back(output);
+      }
+    }
+  }
+
   // Add MSVC precompiled header object files. GCC .gch files are not object
   // files so they are omitted.
   if (source_set->config_values().has_precompiled_headers()) {
@@ -348,3 +370,19 @@
     weak_writer(all_weak_frameworks[i], out);
   }
 }
+
+void NinjaBinaryTargetWriter::WriteSwiftModules(
+    std::ostream& out,
+    const Tool* tool,
+    const std::vector<OutputFile>& swiftmodules) {
+  // Since we're passing these on the command line to the linker and not
+  // to Ninja, we need to do shell escaping.
+  PathOutput swiftmodule_path_output(
+      path_output_.current_dir(), settings_->build_settings()->root_path_utf8(),
+      ESCAPE_NINJA_COMMAND);
+
+  for (const OutputFile& swiftmodule : swiftmodules) {
+    out << " " << tool->swiftmodule_switch();
+    swiftmodule_path_output.WriteFile(out, swiftmodule);
+  }
+}
diff --git a/src/gn/ninja_binary_target_writer.h b/src/gn/ninja_binary_target_writer.h
index 142ca9e..76a8a4e 100644
--- a/src/gn/ninja_binary_target_writer.h
+++ b/src/gn/ninja_binary_target_writer.h
@@ -30,6 +30,7 @@
     UniqueVector<const Target*> linkable_deps;
     UniqueVector<const Target*> non_linkable_deps;
     UniqueVector<const Target*> framework_deps;
+    UniqueVector<const Target*> swiftmodule_deps;
   };
 
   // Writes to the output stream a stamp rule for inputs, and
@@ -70,6 +71,9 @@
                         const SourceFile* optional_def_file);
   void WriteLibs(std::ostream& out, const Tool* tool);
   void WriteFrameworks(std::ostream& out, const Tool* tool);
+  void WriteSwiftModules(std::ostream& out,
+                         const Tool* tool,
+                         const std::vector<OutputFile>& swiftmodules);
 
   void AddSourceSetFiles(const Target* source_set,
                          UniqueVector<OutputFile>* obj_files) const;
diff --git a/src/gn/ninja_c_binary_target_writer.cc b/src/gn/ninja_c_binary_target_writer.cc
index 80448a8..62edd4f 100644
--- a/src/gn/ninja_c_binary_target_writer.cc
+++ b/src/gn/ninja_c_binary_target_writer.cc
@@ -126,8 +126,12 @@
   //    object file list.
   std::vector<OutputFile> obj_files;
   std::vector<SourceFile> other_files;
-  WriteSources(*pch_files, input_deps, order_only_deps, &obj_files,
-               &other_files);
+  if (!target_->source_types_used().SwiftSourceUsed()) {
+    WriteSources(*pch_files, input_deps, order_only_deps, &obj_files,
+                 &other_files);
+  } else {
+    WriteSwiftSources(input_deps, order_only_deps, &obj_files);
+  }
 
   // Link all MSVC pch object files. The vector will be empty on GCC toolchains.
   obj_files.insert(obj_files.end(), pch_obj_files.begin(), pch_obj_files.end());
@@ -225,6 +229,44 @@
                  CTool::kCToolObjCxx, &ConfigValues::cflags_objcc, opts,
                  path_output_, out_);
   }
+  if (target_->source_types_used().SwiftSourceUsed()) {
+    if (subst.used.count(&CSubstitutionSwiftModuleName)) {
+      out_ << CSubstitutionSwiftModuleName.ninja_name << " = ";
+      EscapeStringToStream(out_, target_->swift_values().module_name(), opts);
+      out_ << std::endl;
+    }
+
+    if (subst.used.count(&CSubstitutionSwiftBridgeHeader)) {
+      out_ << CSubstitutionSwiftBridgeHeader.ninja_name << " = ";
+      if (!target_->swift_values().bridge_header().is_null()) {
+        path_output_.WriteFile(out_, target_->swift_values().bridge_header());
+      } else {
+        out_ << R"("")";
+      }
+      out_ << std::endl;
+    }
+
+    if (subst.used.count(&CSubstitutionSwiftModuleDirs)) {
+      // Uniquify the list of swiftmodule dirs (in case multiple swiftmodules
+      // are generated in the same directory).
+      UniqueVector<SourceDir> swiftmodule_dirs;
+      for (const Target* dep : target_->swift_values().modules())
+        swiftmodule_dirs.push_back(dep->swift_values().module_output_dir());
+
+      out_ << CSubstitutionSwiftModuleDirs.ninja_name << " =";
+      PathOutput swiftmodule_path_output(
+          path_output_.current_dir(),
+          settings_->build_settings()->root_path_utf8(), ESCAPE_NINJA_COMMAND);
+      IncludeWriter swiftmodule_path_writer(swiftmodule_path_output);
+      for (const SourceDir& swiftmodule_dir : swiftmodule_dirs) {
+        swiftmodule_path_writer(swiftmodule_dir, out_);
+      }
+      out_ << std::endl;
+    }
+
+    WriteOneFlag(target_, &CSubstitutionSwiftFlags, false, CTool::kCToolSwift,
+                 &ConfigValues::swiftflags, opts, path_output_, out_);
+  }
 
   WriteSharedVars(subst);
 }
@@ -387,11 +429,14 @@
     const std::vector<OutputFile>& order_only_deps,
     std::vector<OutputFile>* object_files,
     std::vector<SourceFile>* other_files) {
+  DCHECK(!target_->source_types_used().SwiftSourceUsed());
   object_files->reserve(object_files->size() + target_->sources().size());
 
   std::vector<OutputFile> tool_outputs;  // Prevent reallocation in loop.
   std::vector<OutputFile> deps;
   for (const auto& source : target_->sources()) {
+    DCHECK_NE(source.type(), SourceFile::SOURCE_SWIFT);
+
     // Clear the vector but maintain the max capacity to prevent reallocations.
     deps.resize(0);
     const char* tool_name = Tool::kToolNone;
@@ -441,6 +486,89 @@
     // output, but we'll only link to the first output.
     object_files->push_back(tool_outputs[0]);
   }
+
+  out_ << std::endl;
+}
+
+void NinjaCBinaryTargetWriter::WriteSwiftSources(
+    const std::vector<OutputFile>& input_deps,
+    const std::vector<OutputFile>& order_only_deps,
+    std::vector<OutputFile>* object_files) {
+  DCHECK(target_->source_types_used().SwiftSourceUsed());
+  object_files->reserve(object_files->size() + target_->sources().size());
+
+  // If the target contains .swift source files, they needs to be compiled as
+  // a single unit but still can produce more than one object file (if the
+  // whole module optimization is disabled).
+  if (target_->source_types_used().SwiftSourceUsed()) {
+    const Tool* tool =
+        target_->toolchain()->GetToolForSourceType(SourceFile::SOURCE_SWIFT);
+
+    const OutputFile swiftmodule_output_file =
+        target_->swift_values().module_output_file();
+
+    std::vector<OutputFile> additional_outputs;
+    SubstitutionWriter::ApplyListToLinkerAsOutputFile(
+        target_, tool, tool->outputs(), &additional_outputs);
+
+    additional_outputs.erase(
+        std::remove(additional_outputs.begin(), additional_outputs.end(),
+                    swiftmodule_output_file),
+        additional_outputs.end());
+
+    for (const OutputFile& output : additional_outputs) {
+      const SourceFile output_as_source =
+          output.AsSourceFile(target_->settings()->build_settings());
+
+      if (output_as_source.type() == SourceFile::SOURCE_O) {
+        object_files->push_back(output);
+      }
+    }
+
+    const SubstitutionList& partial_outputs_subst = tool->partial_outputs();
+    if (!partial_outputs_subst.list().empty()) {
+      // Avoid re-allocation during loop.
+      std::vector<OutputFile> partial_outputs;
+      for (const auto& source : target_->sources()) {
+        if (source.type() != SourceFile::SOURCE_SWIFT)
+          continue;
+
+        partial_outputs.resize(0);
+        SubstitutionWriter::ApplyListToCompilerAsOutputFile(
+            target_, source, partial_outputs_subst, &partial_outputs);
+
+        for (const OutputFile& output : partial_outputs) {
+          additional_outputs.push_back(output);
+          SourceFile output_as_source =
+              output.AsSourceFile(target_->settings()->build_settings());
+          if (output_as_source.type() == SourceFile::SOURCE_O) {
+            object_files->push_back(output);
+          }
+        }
+      }
+    }
+
+    UniqueVector<OutputFile> swift_order_only_deps;
+    swift_order_only_deps.reserve(order_only_deps.size());
+    swift_order_only_deps.Append(order_only_deps.begin(),
+                                 order_only_deps.end());
+
+    for (const Target* swiftmodule : target_->swift_values().modules())
+      swift_order_only_deps.push_back(swiftmodule->dependency_output_file());
+
+    WriteCompilerBuildLine(target_->sources(), input_deps,
+                           swift_order_only_deps.vector(), tool->name(),
+                           {swiftmodule_output_file});
+
+    if (!additional_outputs.empty()) {
+      out_ << std::endl;
+      WriteCompilerBuildLine(
+          {swiftmodule_output_file.AsSourceFile(settings_->build_settings())},
+          input_deps, swift_order_only_deps.vector(),
+          GeneralTool::kGeneralToolStamp, additional_outputs);
+    }
+  }
+
   out_ << std::endl;
 }
 
@@ -538,6 +666,19 @@
     }
   }
 
+  // Swift modules from dependencies (and possibly self).
+  std::vector<OutputFile> swiftmodules;
+  if (target_->IsFinal()) {
+    for (const Target* dep : classified_deps.swiftmodule_deps) {
+      swiftmodules.push_back(dep->swift_values().module_output_file());
+      implicit_deps.push_back(dep->swift_values().module_output_file());
+    }
+    if (target_->swift_values().builds_module()) {
+      swiftmodules.push_back(target_->swift_values().module_output_file());
+      implicit_deps.push_back(target_->swift_values().module_output_file());
+    }
+  }
+
   // Append implicit dependencies collected above.
   if (!implicit_deps.empty()) {
     out_ << " |";
@@ -575,6 +716,9 @@
     out_ << "  frameworks =";
     WriteFrameworks(out_, tool_);
     out_ << std::endl;
+    out_ << "  swiftmodules =";
+    WriteSwiftModules(out_, tool_, swiftmodules);
+    out_ << std::endl;
   } else if (target_->output_type() == Target::STATIC_LIBRARY) {
     out_ << "  arflags =";
     RecursiveTargetConfigStringsToStream(target_, &ConfigValues::arflags,
diff --git a/src/gn/ninja_c_binary_target_writer.h b/src/gn/ninja_c_binary_target_writer.h
index 1608af1..695c400 100644
--- a/src/gn/ninja_c_binary_target_writer.h
+++ b/src/gn/ninja_c_binary_target_writer.h
@@ -73,6 +73,9 @@
                     const std::vector<OutputFile>& order_only_deps,
                     std::vector<OutputFile>* object_files,
                     std::vector<SourceFile>* other_files);
+  void WriteSwiftSources(const std::vector<OutputFile>& input_deps,
+                         const std::vector<OutputFile>& order_only_deps,
+                         std::vector<OutputFile>* object_files);
 
   void WriteLinkerStuff(const std::vector<OutputFile>& object_files,
                         const std::vector<SourceFile>& other_files,
diff --git a/src/gn/ninja_c_binary_target_writer_unittest.cc b/src/gn/ninja_c_binary_target_writer_unittest.cc
index fbd6ff4..f650e44 100644
--- a/src/gn/ninja_c_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_c_binary_target_writer_unittest.cc
@@ -58,7 +58,7 @@
         "build obj/foo/bar.stamp: stamp obj/foo/bar.input1.o "
         "obj/foo/bar.input2.o ../../foo/input3.o ../../foo/input4.obj\n";
     std::string out_str = out.str();
-    EXPECT_EQ(expected, out_str);
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
   }
 
   // A shared library that depends on the source set.
@@ -90,10 +90,11 @@
         "  ldflags =\n"
         "  libs =\n"
         "  frameworks =\n"
+        "  swiftmodules =\n"
         "  output_extension = .so\n"
         "  output_dir = \n";
     std::string out_str = out.str();
-    EXPECT_EQ(expected, out_str);
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
   }
 
   // A static library that depends on the source set (should not link it).
@@ -123,7 +124,7 @@
         "  output_extension = \n"
         "  output_dir = \n";
     std::string out_str = out.str();
-    EXPECT_EQ(expected, out_str);
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
   }
 
   // Make the static library 'complete', which means it should be linked.
@@ -151,7 +152,7 @@
         "  output_extension = \n"
         "  output_dir = \n";
     std::string out_str = out.str();
-    EXPECT_EQ(expected, out_str);
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
   }
 }
 
@@ -209,7 +210,7 @@
       "  output_extension = \n"
       "  output_dir = \n";
   std::string out_str = out.str();
-  EXPECT_EQ(expected, out_str);
+  EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
 }
 
 TEST_F(NinjaCBinaryTargetWriterTest, CompleteStaticLibrary) {
@@ -256,7 +257,7 @@
         "  output_extension = \n"
         "  output_dir = \n";
     std::string out_str = out.str();
-    EXPECT_EQ(expected, out_str);
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
   }
 
   // Make the dependent static library complete.
@@ -285,7 +286,7 @@
         "  output_extension = \n"
         "  output_dir = \n";
     std::string out_str = out.str();
-    EXPECT_EQ(expected, out_str);
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
   }
 }
 
@@ -340,11 +341,12 @@
       "  ldflags =\n"
       "  libs =\n"
       "  frameworks =\n"
+      "  swiftmodules =\n"
       "  output_extension = .so.6\n"
       "  output_dir = foo\n";
 
   std::string out_str = out.str();
-  EXPECT_EQ(expected, out_str);
+  EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
 }
 
 TEST_F(NinjaCBinaryTargetWriterTest, NoHardDepsToNoPublicHeaderTarget) {
@@ -432,6 +434,7 @@
       "  ldflags =\n"
       "  libs =\n"
       "  frameworks =\n"
+      "  swiftmodules =\n"
       "  output_extension = .so\n"
       "  output_dir = foo\n";
 
@@ -470,6 +473,7 @@
       "  ldflags =\n"
       "  libs =\n"
       "  frameworks =\n"
+      "  swiftmodules =\n"
       "  output_extension = \n"
       "  output_dir = foo\n";
 
@@ -507,11 +511,12 @@
       "  ldflags = -L../../foo/bar\n"
       "  libs = ../../foo/lib1.a -lfoo\n"
       "  frameworks =\n"
+      "  swiftmodules =\n"
       "  output_extension = .so\n"
       "  output_dir = \n";
 
   std::string out_str = out.str();
-  EXPECT_EQ(expected, out_str);
+  EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
 }
 
 // Tests frameworks are applied.
@@ -562,11 +567,12 @@
       "  libs =\n"
       "  frameworks = -framework System -framework Bar "
       "-weak_framework Whizbang\n"
+      "  swiftmodules =\n"
       "  output_extension = .so\n"
       "  output_dir = \n";
 
   std::string out_str = out.str();
-  EXPECT_EQ(expected, out_str);
+  EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
 }
 
 TEST_F(NinjaCBinaryTargetWriterTest, EmptyOutputExtension) {
@@ -608,11 +614,12 @@
       "  ldflags =\n"
       "  libs =\n"
       "  frameworks =\n"
+      "  swiftmodules =\n"
       "  output_extension = \n"
       "  output_dir = \n";
 
   std::string out_str = out.str();
-  EXPECT_EQ(expected, out_str);
+  EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
 }
 
 TEST_F(NinjaCBinaryTargetWriterTest, SourceSetDataDeps) {
@@ -693,6 +700,7 @@
       "  ldflags =\n"
       "  libs =\n"
       "  frameworks =\n"
+      "  swiftmodules =\n"
       "  output_extension = \n"
       "  output_dir = \n";
   EXPECT_EQ(final_expected, final_out.str());
@@ -730,6 +738,7 @@
       "  ldflags = /DEF:../../foo/bar.def\n"
       "  libs =\n"
       "  frameworks =\n"
+      "  swiftmodules =\n"
       "  output_extension = .so\n"
       "  output_dir = \n";
   EXPECT_EQ(expected, out.str());
@@ -766,6 +775,7 @@
       "  ldflags =\n"
       "  libs =\n"
       "  frameworks =\n"
+      "  swiftmodules =\n"
       "  output_extension = .so\n"
       "  output_dir = \n";
   EXPECT_EQ(loadable_expected, out.str());
@@ -800,6 +810,7 @@
       "  ldflags =\n"
       "  libs =\n"
       "  frameworks =\n"
+      "  swiftmodules =\n"
       "  output_extension = \n"
       "  output_dir = \n";
   EXPECT_EQ(final_expected, final_out.str());
@@ -1157,6 +1168,7 @@
         "  ldflags =\n"
         "  libs =\n"
         "  frameworks =\n"
+        "  swiftmodules =\n"
         "  output_extension = .so\n"
         "  output_dir = \n";
 
@@ -1297,6 +1309,7 @@
         "  ldflags =\n"
         "  libs =\n"
         "  frameworks =\n"
+        "  swiftmodules =\n"
         "  output_extension = \n"
         "  output_dir = \n";
 
@@ -1409,6 +1422,7 @@
         "  ldflags =\n"
         "  libs =\n"
         "  frameworks =\n"
+        "  swiftmodules =\n"
         "  output_extension = \n"
         "  output_dir = \n"
         "  rlibs = obj/quux/lib4.rlib obj/qux/lib2.rlib\n";
@@ -1470,6 +1484,7 @@
         "  ldflags =\n"
         "  libs =\n"
         "  frameworks =\n"
+        "  swiftmodules =\n"
         "  output_extension = \n"
         "  output_dir = \n";
 
@@ -1511,5 +1526,167 @@
       "  output_extension = \n"
       "  output_dir = \n";
   std::string out_str = out.str();
-  EXPECT_EQ(expected, out_str);
+  EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
+}
+
+// Test linking of targets containing Swift modules.
+TEST_F(NinjaCBinaryTargetWriterTest, SwiftModule) {
+  Err err;
+  TestWithScope setup;
+
+  // A single Swift module.
+  Target foo_target(setup.settings(), Label(SourceDir("//foo/"), "foo"));
+  foo_target.set_output_type(Target::SOURCE_SET);
+  foo_target.visibility().SetPublic();
+  foo_target.sources().push_back(SourceFile("//foo/file1.swift"));
+  foo_target.sources().push_back(SourceFile("//foo/file2.swift"));
+  foo_target.source_types_used().Set(SourceFile::SOURCE_SWIFT);
+  foo_target.swift_values().module_name() = "Foo";
+  foo_target.SetToolchain(setup.toolchain());
+  ASSERT_TRUE(foo_target.OnResolved(&err));
+
+  {
+    std::ostringstream out;
+    NinjaCBinaryTargetWriter writer(&foo_target, out);
+    writer.Run();
+
+    const char expected[] =
+        "defines =\n"
+        "include_dirs =\n"
+        "module_name = Foo\n"
+        "module_dirs =\n"
+        "root_out_dir = .\n"
+        "target_out_dir = obj/foo\n"
+        "target_output_name = foo\n"
+        "\n"
+        "build obj/foo/Foo.swiftmodule: swift"
+        " ../../foo/file1.swift ../../foo/file2.swift\n"
+        "\n"
+        "build obj/foo/file1.o obj/foo/file2.o: stamp obj/foo/Foo.swiftmodule\n"
+        "\n"
+        "build obj/foo/foo.stamp: stamp"
+        " obj/foo/file1.o obj/foo/file2.o\n";
+
+    const std::string out_str = out.str();
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
+  }
+
+  // Swift module_dirs correctly set if dependency between Swift modules.
+  {
+    Target bar_target(setup.settings(), Label(SourceDir("//bar/"), "bar"));
+    bar_target.set_output_type(Target::SOURCE_SET);
+    bar_target.visibility().SetPublic();
+    bar_target.sources().push_back(SourceFile("//bar/bar.swift"));
+    bar_target.source_types_used().Set(SourceFile::SOURCE_SWIFT);
+    bar_target.swift_values().module_name() = "Bar";
+    bar_target.private_deps().push_back(LabelTargetPair(&foo_target));
+    bar_target.SetToolchain(setup.toolchain());
+    ASSERT_TRUE(bar_target.OnResolved(&err));
+
+    std::ostringstream out;
+    NinjaCBinaryTargetWriter writer(&bar_target, out);
+    writer.Run();
+
+    const char expected[] =
+        "defines =\n"
+        "include_dirs =\n"
+        "module_name = Bar\n"
+        "module_dirs = -Iobj/foo\n"
+        "root_out_dir = .\n"
+        "target_out_dir = obj/bar\n"
+        "target_output_name = bar\n"
+        "\n"
+        "build obj/bar/Bar.swiftmodule: swift ../../bar/bar.swift"
+        " || obj/foo/foo.stamp\n"
+        "\n"
+        "build obj/bar/bar.o: stamp obj/bar/Bar.swiftmodule"
+        " || obj/foo/foo.stamp\n"
+        "\n"
+        "build obj/bar/bar.stamp: stamp obj/bar/bar.o "
+        "|| obj/foo/foo.stamp\n";
+
+    const std::string out_str = out.str();
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
+  }
+
+  // Swift module_dirs correctly set if dependency between Swift modules,
+  // even if the dependency is indirect (via public_deps).
+  {
+    Target group(setup.settings(), Label(SourceDir("//bar/"), "group"));
+    group.set_output_type(Target::GROUP);
+    group.visibility().SetPublic();
+    group.public_deps().push_back(LabelTargetPair(&foo_target));
+    group.SetToolchain(setup.toolchain());
+    ASSERT_TRUE(group.OnResolved(&err));
+
+    Target bar_target(setup.settings(), Label(SourceDir("//bar/"), "bar"));
+    bar_target.set_output_type(Target::SOURCE_SET);
+    bar_target.visibility().SetPublic();
+    bar_target.sources().push_back(SourceFile("//bar/bar.swift"));
+    bar_target.source_types_used().Set(SourceFile::SOURCE_SWIFT);
+    bar_target.swift_values().module_name() = "Bar";
+    bar_target.private_deps().push_back(LabelTargetPair(&group));
+    bar_target.SetToolchain(setup.toolchain());
+    ASSERT_TRUE(bar_target.OnResolved(&err));
+
+    std::ostringstream out;
+    NinjaCBinaryTargetWriter writer(&bar_target, out);
+    writer.Run();
+
+    const char expected[] =
+        "defines =\n"
+        "include_dirs =\n"
+        "module_name = Bar\n"
+        "module_dirs = -Iobj/foo\n"
+        "root_out_dir = .\n"
+        "target_out_dir = obj/bar\n"
+        "target_output_name = bar\n"
+        "\n"
+        "build obj/bar/Bar.swiftmodule: swift ../../bar/bar.swift"
+        " || obj/foo/foo.stamp\n"
+        "\n"
+        "build obj/bar/bar.o: stamp obj/bar/Bar.swiftmodule"
+        " || obj/foo/foo.stamp\n"
+        "\n"
+        "build obj/bar/bar.stamp: stamp obj/bar/bar.o "
+        "|| obj/bar/group.stamp obj/foo/foo.stamp\n";
+
+    const std::string out_str = out.str();
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
+  }
+
+  // C target links with module.
+  {
+    Target bar_target(setup.settings(), Label(SourceDir("//bar/"), "bar"));
+    bar_target.set_output_type(Target::EXECUTABLE);
+    bar_target.visibility().SetPublic();
+    bar_target.private_deps().push_back(LabelTargetPair(&foo_target));
+    bar_target.SetToolchain(setup.toolchain());
+    ASSERT_TRUE(bar_target.OnResolved(&err));
+
+    std::ostringstream out;
+    NinjaCBinaryTargetWriter writer(&bar_target, out);
+    writer.Run();
+
+    const char expected[] =
+        "defines =\n"
+        "include_dirs =\n"
+        "root_out_dir = .\n"
+        "target_out_dir = obj/bar\n"
+        "target_output_name = bar\n"
+        "\n"
+        "\n"
+        "build ./bar: link obj/foo/file1.o obj/foo/file2.o "
+        "| obj/foo/Foo.swiftmodule "
+        "|| obj/foo/foo.stamp\n"
+        "  ldflags =\n"
+        "  libs =\n"
+        "  frameworks =\n"
+        "  swiftmodules = obj/foo/Foo.swiftmodule\n"
+        "  output_extension = \n"
+        "  output_dir = \n";
+
+    const std::string out_str = out.str();
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
+  }
 }
diff --git a/src/gn/ninja_toolchain_writer.cc b/src/gn/ninja_toolchain_writer.cc
index 3793ab0..7be7719 100644
--- a/src/gn/ninja_toolchain_writer.cc
+++ b/src/gn/ninja_toolchain_writer.cc
@@ -83,7 +83,8 @@
   EscapeOptions options;
   options.mode = ESCAPE_NINJA_PREFORMATTED_COMMAND;
 
-  WriteCommandRulePattern("command", tool->command_launcher(), tool->command(), options);
+  WriteCommandRulePattern("command", tool->command_launcher(), tool->command(),
+                          options);
 
   WriteRulePattern("description", tool->description(), options);
   WriteRulePattern("rspfile", tool->rspfile(), options);
@@ -92,7 +93,7 @@
   if (CTool* c_tool = tool->AsC()) {
     if (c_tool->depsformat() == CTool::DEPS_GCC) {
       // GCC-style deps require a depfile.
-      if (!tool->depfile().empty()) {
+      if (!c_tool->depfile().empty()) {
         WriteRulePattern("depfile", tool->depfile(), options);
         out_ << kIndent << "deps = gcc" << std::endl;
       }
diff --git a/src/gn/source_file.cc b/src/gn/source_file.cc
index 0b0e8e5..89c8cf0 100644
--- a/src/gn/source_file.cc
+++ b/src/gn/source_file.cc
@@ -49,6 +49,10 @@
     return SourceFile::SOURCE_RS;
   if (extension == "go")
     return SourceFile::SOURCE_GO;
+  if (extension == "swift")
+    return SourceFile::SOURCE_SWIFT;
+  if (extension == "swiftmodule")
+    return SourceFile::SOURCE_SWIFTMODULE;
 
   return SourceFile::SOURCE_UNKNOWN;
 }
@@ -123,8 +127,13 @@
   return Get(SourceFile::SOURCE_GO);
 }
 
+bool SourceFileTypeSet::SwiftSourceUsed() const {
+  return Get(SourceFile::SOURCE_SWIFT);
+}
+
 bool SourceFileTypeSet::MixedSourceUsed() const {
   return (1 << static_cast<int>(CSourceUsed())
             << static_cast<int>(RustSourceUsed())
-            << static_cast<int>(GoSourceUsed())) > 2;
+            << static_cast<int>(GoSourceUsed())
+            << static_cast<int>(SwiftSourceUsed())) > 2;
 }
diff --git a/src/gn/source_file.h b/src/gn/source_file.h
index 1e156fe..5ad8f62 100644
--- a/src/gn/source_file.h
+++ b/src/gn/source_file.h
@@ -41,6 +41,8 @@
 
     SOURCE_RS,
     SOURCE_GO,
+    SOURCE_SWIFT,
+    SOURCE_SWIFTMODULE,
 
     // Must be last.
     SOURCE_NUMTYPES,
@@ -158,6 +160,7 @@
   bool CSourceUsed() const;
   bool RustSourceUsed() const;
   bool GoSourceUsed() const;
+  bool SwiftSourceUsed() const;
 
   bool MixedSourceUsed() const;
 
diff --git a/src/gn/substitution_writer.cc b/src/gn/substitution_writer.cc
index 199faa3..6fe83ce 100644
--- a/src/gn/substitution_writer.cc
+++ b/src/gn/substitution_writer.cc
@@ -576,6 +576,8 @@
   } else if (type == &kRustSubstitutionCrateName) {
     // Only include the toolchain for non-default toolchains.
     return target->rust_values().crate_name();
+  } else if (type == &CSubstitutionSwiftModuleName) {
+    return target->swift_values().module_name();
   } else {
     NOTREACHED();
     return std::string();
diff --git a/src/gn/swift_values.cc b/src/gn/swift_values.cc
new file mode 100644
index 0000000..c15e319
--- /dev/null
+++ b/src/gn/swift_values.cc
@@ -0,0 +1,70 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gn/swift_values.h"
+
+#include "gn/deps_iterator.h"
+#include "gn/err.h"
+#include "gn/settings.h"
+#include "gn/substitution_writer.h"
+#include "gn/target.h"
+
+SwiftValues::SwiftValues() = default;
+
+SwiftValues::~SwiftValues() = default;
+
+bool SwiftValues::OnTargetResolved(const Target* target, Err* err) {
+  if (!FillModuleOuputFile(target, err))
+    return false;
+
+  FillModuleDependencies(target);
+  return true;
+}
+
+void SwiftValues::FillModuleDependencies(const Target* target) {
+  for (const auto& pair : target->GetDeps(Target::DEPS_LINKED)) {
+    if (pair.ptr->toolchain() == target->toolchain() ||
+        pair.ptr->toolchain()->propagates_configs()) {
+      modules_.Append(pair.ptr->swift_values().public_modules().begin(),
+                      pair.ptr->swift_values().public_modules().end());
+    }
+  }
+
+  for (const auto& pair : target->public_deps()) {
+    if (pair.ptr->toolchain() == target->toolchain() ||
+        pair.ptr->toolchain()->propagates_configs())
+      public_modules_.Append(pair.ptr->swift_values().public_modules().begin(),
+                             pair.ptr->swift_values().public_modules().end());
+  }
+
+  if (builds_module())
+    public_modules_.push_back(target);
+}
+
+bool SwiftValues::FillModuleOuputFile(const Target* target, Err* err) {
+  if (!target->IsBinary() || !target->source_types_used().SwiftSourceUsed())
+    return true;
+
+  const Tool* tool =
+      target->toolchain()->GetToolForSourceType(SourceFile::SOURCE_SWIFT);
+  CHECK(tool->outputs().list().size() >= 1);
+
+  OutputFile module_output_file =
+      SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
+          target, tool, tool->outputs().list()[0]);
+
+  const SourceFile module_output_file_as_source =
+      module_output_file.AsSourceFile(target->settings()->build_settings());
+  if (module_output_file_as_source.type() != SourceFile::SOURCE_SWIFTMODULE) {
+    *err = Err(tool->defined_from(), "Incorrect outputs for tool",
+               "The first output of tool " + std::string(tool->name()) +
+                   " must be a .swiftmodule file.");
+    return false;
+  }
+
+  module_output_file_ = std::move(module_output_file);
+  module_output_dir_ = module_output_file_as_source.GetDir();
+
+  return true;
+}
diff --git a/src/gn/swift_values.h b/src/gn/swift_values.h
new file mode 100644
index 0000000..c529738
--- /dev/null
+++ b/src/gn/swift_values.h
@@ -0,0 +1,91 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SWIFT_TARGET_VALUES_H_
+#define TOOLS_GN_SWIFT_TARGET_VALUES_H_
+
+#include <string>
+
+#include "gn/output_file.h"
+#include "gn/source_dir.h"
+#include "gn/source_file.h"
+#include "gn/unique_vector.h"
+
+class Err;
+class Target;
+
+// Holds values specific to target that compile .swift files.
+class SwiftValues {
+ public:
+  SwiftValues();
+  ~SwiftValues();
+
+  SwiftValues(const SwiftValues&) = delete;
+  SwiftValues& operator=(const SwiftValues&) = delete;
+
+  // Called when the target is resolved.
+  bool OnTargetResolved(const Target* target, Err* err);
+
+  // Path of the bridging header.
+  SourceFile& bridge_header() { return bridge_header_; }
+  const SourceFile& bridge_header() const { return bridge_header_; }
+
+  // Name of the module.
+  std::string& module_name() { return module_name_; }
+  const std::string module_name() const { return module_name_; }
+
+  // Returns whether the target generates a .swiftmodule.
+  bool builds_module() const { return module_output_file_ != OutputFile(); }
+
+  // Name of the generated .swiftmodule file. Computed when the target
+  // is resolved.
+  const OutputFile& module_output_file() const { return module_output_file_; }
+
+  // Path of the directory containing the generated .swiftmodule file.
+  // Computed when the target is resolved.
+  const SourceDir& module_output_dir() const { return module_output_dir_; }
+
+  // List of dependent target that generate a .swiftmodule. The current target
+  // is assumed to depend on those modules, and will add them to the module
+  // search path.
+  const UniqueVector<const Target*>& modules() const { return modules_; }
+
+  // List of dependent target that generate a .swiftmodule that are publicly
+  // exported by the current target. This will include the current target if
+  // it generates a .swiftmodule.
+  const UniqueVector<const Target*>& public_modules() const {
+    return public_modules_;
+  }
+
+ private:
+  // Fill informations about .swiftmodule generated by this target.
+  bool FillModuleOuputFile(const Target* target, Err* err);
+
+  // Fill dependencies information on other target generating .swiftmodules.
+  void FillModuleDependencies(const Target* target);
+
+  // Name of the optional bridge header used to import Objective-C classes.
+  // Filled from the target, may be empty even if the target include .swift
+  // source files.
+  SourceFile bridge_header_;
+
+  // Name of the generate module for use by substitution.
+  std::string module_name_;
+
+  // Path to the .swiftmodule generated by this target. Will be empty if the
+  // target does not include .swift sources.
+  OutputFile module_output_file_;
+
+  // Path of the directory containing the .swiftmodule generated by this
+  // target. Will be null if the target does not include .swift sources.
+  SourceDir module_output_dir_;
+
+  // For modules() and public_modules() function. Will be filled when the
+  // target is resolved (can be non-empty even if the target does not build
+  // .swift sources due to transitive dependencies).
+  UniqueVector<const Target*> modules_;
+  UniqueVector<const Target*> public_modules_;
+};
+
+#endif  // TOOLS_GN_SWIFT_TARGET_VALUES_H_
diff --git a/src/gn/swift_values_generator.cc b/src/gn/swift_values_generator.cc
new file mode 100644
index 0000000..ba56e28
--- /dev/null
+++ b/src/gn/swift_values_generator.cc
@@ -0,0 +1,60 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gn/swift_values_generator.h"
+
+#include "gn/label.h"
+#include "gn/scope.h"
+#include "gn/settings.h"
+#include "gn/swift_values.h"
+#include "gn/swift_variables.h"
+#include "gn/target.h"
+#include "gn/value_extractors.h"
+
+SwiftValuesGenerator::SwiftValuesGenerator(Target* target,
+                                           Scope* scope,
+                                           Err* err)
+    : target_(target), scope_(scope), err_(err) {}
+
+SwiftValuesGenerator::~SwiftValuesGenerator() = default;
+
+void SwiftValuesGenerator::Run() {
+  if (!FillBridgeHeader())
+    return;
+
+  if (!FillModuleName())
+    return;
+}
+
+bool SwiftValuesGenerator::FillBridgeHeader() {
+  const Value* value = scope_->GetValue(variables::kSwiftBridgeHeader, true);
+  if (!value)
+    return true;
+
+  if (!value->VerifyTypeIs(Value::STRING, err_))
+    return false;
+
+  SourceFile dest;
+  if (!ExtractRelativeFile(scope_->settings()->build_settings(), *value,
+                           scope_->GetSourceDir(), &dest, err_))
+    return false;
+
+  target_->swift_values().bridge_header() = std::move(dest);
+  return true;
+}
+
+bool SwiftValuesGenerator::FillModuleName() {
+  const Value* value = scope_->GetValue(variables::kSwiftModuleName, true);
+  if (!value) {
+    // The target name will be used.
+    target_->swift_values().module_name() = target_->label().name();
+    return true;
+  }
+
+  if (!value->VerifyTypeIs(Value::STRING, err_))
+    return false;
+
+  target_->swift_values().module_name() = std::move(value->string_value());
+  return true;
+}
diff --git a/src/gn/swift_values_generator.h b/src/gn/swift_values_generator.h
new file mode 100644
index 0000000..211c059
--- /dev/null
+++ b/src/gn/swift_values_generator.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SWIFT_TARGET_VALUES_GENERATOR_H_
+#define TOOLS_GN_SWIFT_TARGET_VALUES_GENERATOR_H_
+
+#include <string>
+
+class Err;
+class FunctionCallNode;
+class Scope;
+class Target;
+
+class SwiftValuesGenerator {
+ public:
+  SwiftValuesGenerator(Target* target, Scope* scope, Err* err);
+  ~SwiftValuesGenerator();
+
+  SwiftValuesGenerator(const SwiftValuesGenerator&) = delete;
+  SwiftValuesGenerator& operator=(const SwiftValuesGenerator&) = delete;
+
+  void Run();
+
+ private:
+  bool FillBridgeHeader();
+  bool FillModuleName();
+
+  Target* target_;
+  Scope* scope_;
+  Err* err_;
+};
+
+#endif  // TOOLS_GN_SWIFT_TARGET_VALUES_GENERATOR_H_
diff --git a/src/gn/swift_variables.cc b/src/gn/swift_variables.cc
new file mode 100644
index 0000000..cf9d3d4
--- /dev/null
+++ b/src/gn/swift_variables.cc
@@ -0,0 +1,44 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gn/swift_variables.h"
+
+namespace variables {
+
+// Swift target vars -----------------------------------------------------
+
+const char kSwiftBridgeHeader[] = "bridge_header";
+const char kSwiftBridgeHeader_HelpShort[] =
+    "bridge_header: [string] Path to C/Objective-C compatibility header.";
+const char kSwiftBridgeHeader_Help[] =
+    R"(bridge_header: [string] Path to C/Objective-C compatibility header.
+
+  Valid for binary targets that contain Swift sources.
+
+  Path to an header that includes C/Objective-C functions and types that
+  needs to be made available to the Swift module.
+)";
+
+const char kSwiftModuleName[] = "module_name";
+const char kSwiftModuleName_HelpShort[] =
+    "module_name: [string] The name for the compiled module.";
+const char kSwiftModuleName_Help[] =
+    R"(module_name: [string] The name for the compiled module.
+
+  Valid for binary targets that contain Swift sources.
+
+  If module_name is not set, then this rule will use the target name.
+)";
+
+void InsertSwiftVariables(VariableInfoMap* info_map) {
+  info_map->insert(std::make_pair(
+      kSwiftBridgeHeader,
+      VariableInfo(kSwiftBridgeHeader_HelpShort, kSwiftBridgeHeader_Help)));
+
+  info_map->insert(std::make_pair(
+      kSwiftModuleName,
+      VariableInfo(kSwiftModuleName_HelpShort, kSwiftModuleName_Help)));
+}
+
+}  // namespace variables
diff --git a/src/gn/swift_variables.h b/src/gn/swift_variables.h
new file mode 100644
index 0000000..c430468
--- /dev/null
+++ b/src/gn/swift_variables.h
@@ -0,0 +1,26 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SWIFT_TARGET_VARIABLES_H_
+#define TOOLS_GN_SWIFT_TARGET_VARIABLES_H_
+
+#include "gn/variables.h"
+
+namespace variables {
+
+// Swift target vars -----------------------------------------------------
+
+extern const char kSwiftBridgeHeader[];
+extern const char kSwiftBridgeHeader_HelpShort[];
+extern const char kSwiftBridgeHeader_Help[];
+
+extern const char kSwiftModuleName[];
+extern const char kSwiftModuleName_HelpShort[];
+extern const char kSwiftModuleName_Help[];
+
+void InsertSwiftVariables(VariableInfoMap* info_map);
+
+}  // namespace variables
+
+#endif  // TOOLS_GN_SWIFT_TARGET_VARIABLES_H_
diff --git a/src/gn/target.cc b/src/gn/target.cc
index 97e3d37..39bf492 100644
--- a/src/gn/target.cc
+++ b/src/gn/target.cc
@@ -388,6 +388,9 @@
   if (!FillOutputFiles(err))
     return false;
 
+  if (!swift_values_.OnTargetResolved(this, err))
+    return false;
+
   if (!CheckSourceSetLanguages(err))
     return false;
   if (!CheckVisibility(err))
@@ -598,9 +601,19 @@
     if (!tool)
       return false;  // Tool does not apply for this toolchain.file.
 
+    // Swift may generate on a module or source level.
+    if (file_type == SourceFile::SOURCE_SWIFT) {
+      if (tool->partial_outputs().list().empty())
+        return false;
+    }
+
+    const SubstitutionList& substitution_list =
+        file_type == SourceFile::SOURCE_SWIFT ? tool->partial_outputs()
+                                              : tool->outputs();
+
     // Figure out what output(s) this compiler produces.
     SubstitutionWriter::ApplyListToCompilerAsOutputFile(
-        this, source, tool->outputs(), outputs);
+        this, source, substitution_list, outputs);
   }
   return !outputs->empty();
 }
@@ -727,9 +740,12 @@
 
     // If |pair.ptr| is binary target and |pair.ptr| has no public header,
     // |this| target does not need to have |pair.ptr|'s hard_deps as its
-    // hard_deps to start compiles earlier.
+    // hard_deps to start compiles earlier. Unless the target compiles a
+    // Swift module (since they also generate a header that can be used
+    // by the current target).
     if (pair.ptr->IsBinary() && !pair.ptr->all_headers_public() &&
-        pair.ptr->public_headers().empty()) {
+        pair.ptr->public_headers().empty() &&
+        !pair.ptr->swift_values().builds_module()) {
       continue;
     }
 
diff --git a/src/gn/target.h b/src/gn/target.h
index 6332880..336c20c 100644
--- a/src/gn/target.h
+++ b/src/gn/target.h
@@ -25,6 +25,7 @@
 #include "gn/output_file.h"
 #include "gn/rust_values.h"
 #include "gn/source_file.h"
+#include "gn/swift_values.h"
 #include "gn/toolchain.h"
 #include "gn/unique_vector.h"
 
@@ -210,7 +211,8 @@
   bool hard_dep() const {
     return output_type_ == ACTION || output_type_ == ACTION_FOREACH ||
            output_type_ == COPY_FILES || output_type_ == CREATE_BUNDLE ||
-           output_type_ == BUNDLE_DATA || output_type_ == GENERATED_FILE;
+           output_type_ == BUNDLE_DATA || output_type_ == GENERATED_FILE ||
+           (IsBinary() && swift_values().builds_module());
   }
 
   // Returns the iterator range which can be used in range-based for loops
@@ -271,6 +273,9 @@
   ActionValues& action_values() { return action_values_; }
   const ActionValues& action_values() const { return action_values_; }
 
+  SwiftValues& swift_values() { return swift_values_; }
+  const SwiftValues& swift_values() const { return swift_values_; }
+
   RustValues& rust_values() { return rust_values_; }
   const RustValues& rust_values() const { return rust_values_; }
 
@@ -474,6 +479,9 @@
   // Used for Rust targets.
   RustValues rust_values_;
 
+  // User for Swift targets.
+  SwiftValues swift_values_;
+
   // Toolchain used by this target. Null until target is resolved.
   const Toolchain* toolchain_ = nullptr;
 
diff --git a/src/gn/test_with_scope.cc b/src/gn/test_with_scope.cc
index ae9c939..583eebb 100644
--- a/src/gn/test_with_scope.cc
+++ b/src/gn/test_with_scope.cc
@@ -231,6 +231,17 @@
       "{{root_out_dir}}/{{crate_name}}{{output_extension}}"));
   toolchain->SetTool(std::move(rustc_tool));
 
+  // SWIFT
+  std::unique_ptr<Tool> swift_tool = Tool::CreateTool(CTool::kCToolSwift);
+  SetCommandForTool(
+      "swiftc --module-name {{module_name}} {{module_dirs}} {{inputs}}",
+      swift_tool.get());
+  swift_tool->set_outputs(SubstitutionList::MakeForTest(
+      "{{target_out_dir}}/{{module_name}}.swiftmodule"));
+  swift_tool->set_partial_outputs(SubstitutionList::MakeForTest(
+      "{{target_out_dir}}/{{source_name_part}}.o"));
+  toolchain->SetTool(std::move(swift_tool));
+
   // CDYLIB
   std::unique_ptr<Tool> cdylib_tool = Tool::CreateTool(RustTool::kRsToolCDylib);
   SetCommandForTool(
diff --git a/src/gn/tool.cc b/src/gn/tool.cc
index 9fc10ce..5e4186d 100644
--- a/src/gn/tool.cc
+++ b/src/gn/tool.cc
@@ -26,6 +26,7 @@
   outputs_.FillRequiredTypes(&substitution_bits_);
   rspfile_.FillRequiredTypes(&substitution_bits_);
   rspfile_content_.FillRequiredTypes(&substitution_bits_);
+  partial_outputs_.FillRequiredTypes(&substitution_bits_);
 }
 
 GeneralTool* Tool::AsGeneral() {
@@ -263,6 +264,8 @@
     return std::make_unique<CTool>(CTool::kCToolRc);
   else if (name == CTool::kCToolAsm)
     return std::make_unique<CTool>(CTool::kCToolAsm);
+  else if (name == CTool::kCToolSwift)
+    return std::make_unique<CTool>(CTool::kCToolSwift);
   else if (name == CTool::kCToolAlink)
     return std::make_unique<CTool>(CTool::kCToolAlink);
   else if (name == CTool::kCToolSolink)
@@ -323,6 +326,8 @@
       return CTool::kCToolRc;
     case SourceFile::SOURCE_RS:
       return RustTool::kRsToolBin;
+    case SourceFile::SOURCE_SWIFT:
+      return CTool::kCToolSwift;
     case SourceFile::SOURCE_UNKNOWN:
     case SourceFile::SOURCE_H:
     case SourceFile::SOURCE_O:
diff --git a/src/gn/tool.h b/src/gn/tool.h
index 7fe6ed5..e64935f 100644
--- a/src/gn/tool.h
+++ b/src/gn/tool.h
@@ -157,6 +157,12 @@
     lib_dir_switch_ = std::move(s);
   }
 
+  const std::string& swiftmodule_switch() const { return swiftmodule_switch_; }
+  void set_swiftmodule_switch(std::string s) {
+    DCHECK(!complete_);
+    swiftmodule_switch_ = std::move(s);
+  }
+
   const std::string& linker_arg() const { return linker_arg_; }
   void set_linker_arg(std::string s) {
     DCHECK(!complete_);
@@ -169,6 +175,12 @@
     outputs_ = std::move(out);
   }
 
+  const SubstitutionList& partial_outputs() const { return partial_outputs_; }
+  void set_partial_outputs(SubstitutionList partial_out) {
+    DCHECK(!complete_);
+    partial_outputs_ = std::move(partial_out);
+  }
+
   const SubstitutionList& runtime_outputs() const { return runtime_outputs_; }
   void set_runtime_outputs(SubstitutionList run_out) {
     DCHECK(!complete_);
@@ -271,8 +283,10 @@
   std::string framework_dir_switch_;
   std::string lib_switch_;
   std::string lib_dir_switch_;
+  std::string swiftmodule_switch_;
   std::string linker_arg_;
   SubstitutionList outputs_;
+  SubstitutionList partial_outputs_;
   SubstitutionList runtime_outputs_;
   std::string output_prefix_;
   bool restat_ = false;
diff --git a/src/gn/variables.cc b/src/gn/variables.cc
index b543dd2..d575a14 100644
--- a/src/gn/variables.cc
+++ b/src/gn/variables.cc
@@ -5,6 +5,7 @@
 #include "gn/variables.h"
 
 #include "gn/rust_variables.h"
+#include "gn/swift_variables.h"
 
 namespace variables {
 
@@ -727,7 +728,8 @@
   versions of cflags* will be appended on the compiler command line after
   "cflags".
 
-  See also "asmflags" for flags for assembly-language files.
+  See also "asmflags" for flags for assembly-language files and "swiftflags"
+  for swift files.
 )" COMMON_ORDERING_HELP;
 const char* kCflags_Help = kCommonCflagsHelp;
 
@@ -2017,6 +2019,18 @@
     The source are the source files to copy.
 )";
 
+const char kSwiftflags[] = "swiftflags";
+const char kSwiftflags_HelpShort[] =
+    "swiftflags: [string list] Flags passed to the swift compiler.";
+const char* kSwiftflags_Help =
+    R"(swiftflags: Flags passed to the swift compiler.
+
+  A list of strings.
+
+  "swiftflags" are passed to any invocation of a tool that takes an .swift
+  file as input.
+)" COMMON_ORDERING_HELP;
+
 const char kXcodeTestApplicationName[] = "xcode_test_application_name";
 const char kXcodeTestApplicationName_HelpShort[] =
     "xcode_test_application_name: [string] Name for Xcode test target.";
@@ -2307,6 +2321,7 @@
     INSERT_VARIABLE(ResponseFileContents)
     INSERT_VARIABLE(Script)
     INSERT_VARIABLE(Sources)
+    INSERT_VARIABLE(Swiftflags)
     INSERT_VARIABLE(XcodeTestApplicationName)
     INSERT_VARIABLE(Testonly)
     INSERT_VARIABLE(Visibility)
@@ -2317,6 +2332,7 @@
     INSERT_VARIABLE(WriteRuntimeDeps)
     INSERT_VARIABLE(XcodeExtraAttributes)
     InsertRustVariables(&info_map);
+    InsertSwiftVariables(&info_map);
   }
   return info_map;
 }
diff --git a/src/gn/variables.h b/src/gn/variables.h
index acd78af..f5794d1 100644
--- a/src/gn/variables.h
+++ b/src/gn/variables.h
@@ -314,6 +314,10 @@
 extern const char kSources_HelpShort[];
 extern const char kSources_Help[];
 
+extern const char kSwiftflags[];
+extern const char kSwiftflags_HelpShort[];
+extern const char* kSwiftflags_Help;
+
 extern const char kXcodeTestApplicationName[];
 extern const char kXcodeTestApplicationName_HelpShort[];
 extern const char kXcodeTestApplicationName_Help[];