| # 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. |
| |
| 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 |
| write_file("$root_build_dir/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 = "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)" |
| } |
| } |
| } |