blob: 01c3ebbdcf696f8030f37b702b84dfb3e0e832c3 [file] [log] [blame]
# Copyright 2021 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
assert(use_cobalt_customizations)
import("//build/toolchain/cc_wrapper.gni")
import("//build/toolchain/toolchain.gni")
tool_wrapper_path = rebase_path("tool_wrapper.py", root_build_dir)
template("msvc_toolchain") {
# Write the environment variables file in the out directory.
required_environment_variables = [
"SYSTEMROOT",
"TEMP",
"TMP",
]
optional_environment_variables = [
"INCLUDE",
"LIB",
"PATH",
"PATHEXT",
"XEDK", # TODO: What does this do?
"IS_DOCKER", # needed for ninja to invoke docker-specific logic
"IS_CI", # needed for ninja to exclude some logic on GKE
# The remaining variables should be explicitly enumerated.
# "cell_.*",
# "sn_.*",
# "sce_.*",
]
environment_key_value_pairs = []
foreach(key, required_environment_variables) {
value = getenv(key)
assert(value != "", "Envionment variable $key is required to be set.")
environment_key_value_pairs += [ "$key=$value" ]
}
foreach(key, optional_environment_variables) {
value = getenv(key)
if (value != "") {
environment_key_value_pairs += [ "$key=$value" ]
}
}
nul = "$0x00"
env_block = string_join(nul, environment_key_value_pairs) + nul
# If the default toolchain shares its name with another toolchain,
# there could be a deadlock where both toolchains try to write to the same environment file.
# See b/297227714 for more context.
write_file("$root_build_dir/$target_name/environment.$target_cpu", env_block)
toolchain(target_name) {
# When invoking this toolchain not as the default one, these args will be
# passed to the build. They are ignored when this is the default toolchain.
assert(defined(invoker.toolchain_args))
toolchain_args = {
if (defined(invoker.toolchain_args)) {
forward_variables_from(invoker.toolchain_args, "*")
}
}
# Make these apply to all tools below.
lib_switch = ""
lib_dir_switch = "/LIBPATH:"
# Object files go in this directory.
object_subdir = "{{target_out_dir}}/{{label_name}}"
env = "$target_name/environment.$target_cpu"
cl = invoker.cl
lib = invoker.lib
link = invoker.link
asm = invoker.asm
env_wrapper = "ninja -t msvc -e $env -- " # Note trailing space.
# TODO(https://crbug.com/gn/273): Always use sccache for cc and cxx tools.
if (cc_wrapper != "") {
cl_prefix = "${cc_wrapper} " # Note trailing space.
} else {
cl_prefix = env_wrapper
}
sys_include_flags = ""
tool("cc") {
precompiled_header_type = "msvc"
pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
# Label names may have spaces in them so the pdbname must be quoted. The
# source and output don't need to be quoted because GN knows they're a
# full file name and will quote automatically when necessary.
depsformat = "msvc"
description = "CC {{output}}"
outputs = [ "$object_subdir/{{source_name_part}}.obj" ]
command = "$cl_prefix\"$cl\" /nologo /showIncludes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
}
tool("cxx") {
precompiled_header_type = "msvc"
# The PDB name needs to be different between C and C++ compiled files.
pdbname = "{{target_out_dir}}/{{label_name}}_cc.pdb"
# See comment in CC tool about quoting.
depsformat = "msvc"
description = "CXX {{output}}"
outputs = [ "$object_subdir/{{source_name_part}}.obj" ]
command = "$cl_prefix\"$cl\" /nologo /showIncludes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
}
tool("asm") {
description = "ASM {{output}}"
outputs = [ "$object_subdir/{{source_name_part}}.obj" ]
command = "$env_wrapper$asm /nologo /Fo{{output}} /c {{defines}} {{include_dirs}} {{asmflags}} {{source}}"
}
sys_lib_flags = "${invoker.sys_lib_flags} " # Note trailing space.
tool("alink") {
rspfile = "{{output}}.rsp"
command = "$env_wrapper$lib /ignore:4221 /OUT:{{output}} /nologo ${sys_lib_flags}{{arflags}} @$rspfile"
description = "LIB {{output}}"
outputs = [
# Ignore {{output_extension}} and always use .lib, there's no reason to
# allow targets to override this extension on Windows.
"{{output_dir}}/{{target_output_name}}.lib",
]
default_output_extension = ".lib"
default_output_dir = "{{target_out_dir}}"
# The use of inputs_newline is to work around a fixed per-line buffer
# size in the linker.
rspfile_content = "{{inputs_newline}}"
}
# TODO(b/217794556): All following linker tools should list the PDB file in
# their outputs. It has been removed as it is not always generated, and
# ninja will treat the missing file as a dirty edge.
tool("solink") {
# E.g. "foo.dll":
dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
libname = "${dllname}.lib" # e.g. foo.dll.lib
pdbname = "${dllname}.pdb"
rspfile = "${dllname}.rsp"
pool = "//build/toolchain:link_pool($default_toolchain)"
command = "$env_wrapper$link /OUT:$dllname /nologo ${sys_lib_flags}/IMPLIB:$libname /DLL /PDB:$pdbname @$rspfile"
default_output_extension = ".dll"
default_output_dir = "{{root_out_dir}}"
description = "LINK(DLL) {{output}}"
outputs = [
dllname,
libname,
]
link_output = libname
depend_output = libname
runtime_outputs = [ dllname ]
# Since the above commands only updates the .lib file when it changes, ask
# Ninja to check if the timestamp actually changed to know if downstream
# dependencies should be recompiled.
restat = true
# The use of inputs_newline is to work around a fixed per-line buffer
# size in the linker.
rspfile_content = "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}}"
}
tool("solink_module") {
# E.g. "foo.dll":
dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
pdbname = "${dllname}.pdb"
rspfile = "${dllname}.rsp"
pool = "//build/toolchain:link_pool($default_toolchain)"
command = "$env_wrapper$link /OUT:$dllname /nologo ${sys_lib_flags}/DLL /PDB:$pdbname @$rspfile"
default_output_extension = ".dll"
default_output_dir = "{{root_out_dir}}"
description = "LINK_MODULE(DLL) {{output}}"
outputs = [ dllname ]
runtime_outputs = outputs
# The use of inputs_newline is to work around a fixed per-line buffer
# size in the linker.
rspfile_content = "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}}"
}
tool("link") {
exename = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
pdbname = "$exename.pdb"
rspfile = "$exename.rsp"
pool = "//build/toolchain:link_pool($default_toolchain)"
command = "$env_wrapper$link /OUT:$exename /nologo ${sys_lib_flags} /PDB:$pdbname @$rspfile"
default_output_extension = ".exe"
default_output_dir = "{{root_out_dir}}"
description = "LINK {{output}}"
outputs = [ exename ]
runtime_outputs = outputs
# The use of inputs_newline is to work around a fixed per-line buffer
# size in the linker.
rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}"
}
# These two are really entirely generic, but have to be repeated in
# each toolchain because GN doesn't allow a template to be used here.
# See //build/toolchain/toolchain.gni for details.
tool("stamp") {
command = stamp_command
description = stamp_description
pool = "//build/toolchain:action_pool($default_toolchain)"
}
tool("copy") {
command = copy_command
description = copy_description
pool = "//build/toolchain:action_pool($default_toolchain)"
}
tool("action") {
pool = "//build/toolchain:action_pool($default_toolchain)"
}
}
}