diff options
author | Yun Peng <pcloudy@google.com> | 2018-07-06 07:00:14 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-07-06 07:02:00 -0700 |
commit | 5947f474e152f7b1f447ef9c9392cd632c1fdd81 (patch) | |
tree | 4a48790ddb7cc5b5a11377d63af499cd463409b1 /tools/cpp | |
parent | e4809f2f8b6a3d2a71ffc64aca6ff43fb858cc87 (diff) |
Windows, CROSSTOOL: Remove MSVC wrapper scripts from Bazel completely
The only reason that those python wrapper scripts still exists is for
TensorFlow's Windows GPU build. As we will create a custom GPU CROSSTOOL
in TF repo, we can finally remove wrapper scripts from Bazel.
Closes #5526.
RELNOTES: Python wrapper scripts for MSVC are removed.
PiperOrigin-RevId: 203472223
Diffstat (limited to 'tools/cpp')
-rw-r--r-- | tools/cpp/BUILD.static.windows | 19 | ||||
-rw-r--r-- | tools/cpp/CROSSTOOL.tpl | 19 | ||||
-rw-r--r-- | tools/cpp/cc_configure.bzl | 5 | ||||
-rw-r--r-- | tools/cpp/windows_cc_configure.bzl | 124 | ||||
-rw-r--r-- | tools/cpp/wrapper/bin/call_python.bat.tpl | 25 | ||||
-rw-r--r-- | tools/cpp/wrapper/bin/msvc_cl.bat | 17 | ||||
-rw-r--r-- | tools/cpp/wrapper/bin/msvc_link.bat | 17 | ||||
-rw-r--r-- | tools/cpp/wrapper/bin/msvc_nop.bat | 17 | ||||
-rw-r--r-- | tools/cpp/wrapper/bin/pydir/msvc_cl.py | 113 | ||||
-rw-r--r-- | tools/cpp/wrapper/bin/pydir/msvc_link.py | 122 | ||||
-rw-r--r-- | tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl | 465 |
11 files changed, 2 insertions, 941 deletions
diff --git a/tools/cpp/BUILD.static.windows b/tools/cpp/BUILD.static.windows index dd3ce9fe00..b6af344738 100644 --- a/tools/cpp/BUILD.static.windows +++ b/tools/cpp/BUILD.static.windows @@ -100,8 +100,8 @@ toolchain( cc_toolchain( name = "cc-compiler-x64_windows", - all_files = ":every-file-x64_windows", - compiler_files = ":compile-x64_windows", + all_files = ":empty", + compiler_files = ":empty", cpu = "x64_windows", dwp_files = ":empty", dynamic_runtime_libs = [":empty"], @@ -153,21 +153,6 @@ toolchain( ) filegroup( - name = "every-file-x64_windows", - srcs = [ - ":compile-x64_windows", - ], -) - -filegroup( - name = "compile-x64_windows", - srcs = glob([ - "wrapper/bin/msvc_*", - "wrapper/bin/pydir/msvc*", - ]), -) - -filegroup( name = "link_dynamic_library", srcs = ["link_dynamic_library.sh"], ) diff --git a/tools/cpp/CROSSTOOL.tpl b/tools/cpp/CROSSTOOL.tpl index acc1d5fc72..fa6da1e342 100644 --- a/tools/cpp/CROSSTOOL.tpl +++ b/tools/cpp/CROSSTOOL.tpl @@ -396,7 +396,6 @@ toolchain { implies: 'linker_subsystem_flag' implies: 'linker_param_file' implies: 'msvc_env' - implies: 'use_linker' implies: 'no_stripping' } @@ -416,7 +415,6 @@ toolchain { implies: 'linker_subsystem_flag' implies: 'linker_param_file' implies: 'msvc_env' - implies: 'use_linker' implies: 'no_stripping' implies: 'has_configured_linker_path' implies: 'def_file' @@ -438,7 +436,6 @@ toolchain { implies: 'linker_subsystem_flag' implies: 'linker_param_file' implies: 'msvc_env' - implies: 'use_linker' implies: 'no_stripping' implies: 'has_configured_linker_path' implies: 'def_file' @@ -514,19 +511,6 @@ toolchain { } feature { - name: "use_linker" - env_set { - action: "c++-link-executable" - action: "c++-link-dynamic-library" - action: "c++-link-nodeps-dynamic-library" - env_entry { - key: "USE_LINKER" - value: "1" - } - } - } - - feature { name: 'include_paths' flag_set { action: "assemble" @@ -1093,7 +1077,4 @@ toolchain { } linking_mode_flags { mode: DYNAMIC } - -%{compilation_mode_content} - } diff --git a/tools/cpp/cc_configure.bzl b/tools/cpp/cc_configure.bzl index 57954f6f71..cf4c389bca 100644 --- a/tools/cpp/cc_configure.bzl +++ b/tools/cpp/cc_configure.bzl @@ -76,14 +76,9 @@ cc_autoconf = repository_rule( "CC_CONFIGURE_DEBUG", "CC_TOOLCHAIN_NAME", "CPLUS_INCLUDE_PATH", - "CUDA_COMPUTE_CAPABILITIES", - "CUDA_PATH", "GCOV", "HOMEBREW_RUBY_PATH", - "NO_WHOLE_ARCHIVE_OPTION", "SYSTEMROOT", - "USE_DYNAMIC_CRT", - "USE_MSVC_WRAPPER", "VS90COMNTOOLS", "VS100COMNTOOLS", "VS110COMNTOOLS", diff --git a/tools/cpp/windows_cc_configure.bzl b/tools/cpp/windows_cc_configure.bzl index 149eb3947b..a85ef5877e 100644 --- a/tools/cpp/windows_cc_configure.bzl +++ b/tools/cpp/windows_cc_configure.bzl @@ -80,27 +80,6 @@ def _get_system_root(repository_ctx): auto_configure_warning("SYSTEMROOT is not set, using default SYSTEMROOT=C:\\Windows") return "C:\\Windows" -def _find_cuda(repository_ctx): - """Find out if and where cuda is installed. Doesn't %-escape the result.""" - if "CUDA_PATH" in repository_ctx.os.environ: - return repository_ctx.os.environ["CUDA_PATH"] - nvcc = which(repository_ctx, "nvcc.exe") - if nvcc: - return nvcc[:-len("/bin/nvcc.exe")] - return None - -def _find_python(repository_ctx): - """Find where is python on Windows. Doesn't %-escape the result.""" - if "BAZEL_PYTHON" in repository_ctx.os.environ: - python_binary = repository_ctx.os.environ["BAZEL_PYTHON"] - if not python_binary.endswith(".exe"): - python_binary = python_binary + ".exe" - return python_binary - auto_configure_warning("'BAZEL_PYTHON' is not set, start looking for python in PATH.") - python_binary = which_cmd(repository_ctx, "python.exe") - auto_configure_warning("Python found at %s" % python_binary) - return python_binary - def _add_system_root(repository_ctx, env): """Running VCVARSALL.BAT and VCVARSQUERYREGISTRY.BAT need %SYSTEMROOT%\\\\system32 in PATH.""" if "PATH" not in env: @@ -269,62 +248,12 @@ def _find_missing_vc_tools(repository_ctx, vc_path): return missing_tools -def _is_support_whole_archive(repository_ctx, vc_path): - """Run MSVC linker alone to see if it supports /WHOLEARCHIVE.""" - env = repository_ctx.os.environ - if "NO_WHOLE_ARCHIVE_OPTION" in env and env["NO_WHOLE_ARCHIVE_OPTION"] == "1": - return False - linker = find_msvc_tool(repository_ctx, vc_path, "link.exe") - result = execute(repository_ctx, [linker], expect_failure = True) - return result.find("/WHOLEARCHIVE") != -1 - def _is_support_debug_fastlink(repository_ctx, vc_path): """Run MSVC linker alone to see if it supports /DEBUG:FASTLINK.""" linker = find_msvc_tool(repository_ctx, vc_path, "link.exe") result = execute(repository_ctx, [linker], expect_failure = True) return result.find("/DEBUG[:{FASTLINK|FULL|NONE}]") != -1 -def _is_use_msvc_wrapper(repository_ctx): - """Returns True if USE_MSVC_WRAPPER is set to 1.""" - env = repository_ctx.os.environ - return "USE_MSVC_WRAPPER" in env and env["USE_MSVC_WRAPPER"] == "1" - -def _get_compilation_mode_content(): - """Return the content for adding flags for different compilation modes when using MSVC wrapper.""" - return "\n".join([ - " compilation_mode_flags {", - " mode: DBG", - " compiler_flag: '-Xcompilation-mode=dbg'", - " linker_flag: '-Xcompilation-mode=dbg'", - " }", - " compilation_mode_flags {", - " mode: FASTBUILD", - " compiler_flag: '-Xcompilation-mode=fastbuild'", - " linker_flag: '-Xcompilation-mode=fastbuild'", - " }", - " compilation_mode_flags {", - " mode: OPT", - " compiler_flag: '-Xcompilation-mode=opt'", - " linker_flag: '-Xcompilation-mode=opt'", - " }", - ]) - -def _escaped_cuda_compute_capabilities(repository_ctx): - """Returns a %-escaped list of strings representing cuda compute capabilities.""" - - if "CUDA_COMPUTE_CAPABILITIES" not in repository_ctx.os.environ: - return ["3.5", "5.2"] - capabilities_str = escape_string(repository_ctx.os.environ["CUDA_COMPUTE_CAPABILITIES"]) - capabilities = capabilities_str.split(",") - for capability in capabilities: - # Workaround for Skylark's lack of support for regex. This check should - # be equivalent to checking: - # if re.match("[0-9]+.[0-9]+", capability) == None: - parts = capability.split(".") - if len(parts) != 2 or not parts[0].isdigit() or not parts[1].isdigit(): - auto_configure_fail("Invalid compute capability: %s" % capability) - return capabilities - def configure_windows_toolchain(repository_ctx): """Configure C++ toolchain on Windows.""" paths = resolve_labels(repository_ctx, [ @@ -332,8 +261,6 @@ def configure_windows_toolchain(repository_ctx): "@bazel_tools//tools/cpp:CROSSTOOL", "@bazel_tools//tools/cpp:CROSSTOOL.tpl", "@bazel_tools//tools/cpp:vc_installation_error.bat.tpl", - "@bazel_tools//tools/cpp:wrapper/bin/call_python.bat.tpl", - "@bazel_tools//tools/cpp:wrapper/bin/pydir/msvc_tools.py.tpl", ]) repository_ctx.symlink(paths["@bazel_tools//tools/cpp:BUILD.static.windows"], "BUILD") @@ -404,56 +331,6 @@ def configure_windows_toolchain(repository_ctx): msvc_link_path = find_msvc_tool(repository_ctx, vc_path, "link.exe").replace("\\", "/") msvc_lib_path = find_msvc_tool(repository_ctx, vc_path, "lib.exe").replace("\\", "/") escaped_cxx_include_directories = [] - compilation_mode_content = "" - - if _is_use_msvc_wrapper(repository_ctx): - if _is_support_whole_archive(repository_ctx, vc_path): - support_whole_archive = "True" - else: - support_whole_archive = "False" - nvcc_tmp_dir_name = escaped_tmp_dir + "\\\\nvcc_inter_files_tmp_dir" - - # Make sure nvcc.exe is in PATH - cuda_path = _find_cuda(repository_ctx) - if cuda_path: - escaped_paths = escape_string(cuda_path.replace("\\", "\\\\") + "/bin;") + escaped_paths - escaped_compute_capabilities = _escaped_cuda_compute_capabilities(repository_ctx) - repository_ctx.template( - "wrapper/bin/pydir/msvc_tools.py", - paths["@bazel_tools//tools/cpp:wrapper/bin/pydir/msvc_tools.py.tpl"], - { - "%{lib_tool}": escape_string(msvc_lib_path), - "%{support_whole_archive}": support_whole_archive, - "%{cuda_compute_capabilities}": ", ".join( - ["\"%s\"" % c for c in escaped_compute_capabilities], - ), - "%{nvcc_tmp_dir_name}": nvcc_tmp_dir_name, - }, - ) - - # nvcc will generate some source files under %{nvcc_tmp_dir_name} - # The generated files are guranteed to have unique name, so they can share the same tmp directory - escaped_cxx_include_directories += ["cxx_builtin_include_directory: \"%s\"" % nvcc_tmp_dir_name] - msvc_wrapper = repository_ctx.path( - paths["@bazel_tools//tools/cpp:CROSSTOOL"], - ).dirname.get_child( - "wrapper", - ).get_child("bin") - for f in ["msvc_cl.bat", "msvc_link.bat", "msvc_nop.bat"]: - repository_ctx.symlink(msvc_wrapper.get_child(f), "wrapper/bin/" + f) - msvc_wrapper = msvc_wrapper.get_child("pydir") - for f in ["msvc_cl.py", "msvc_link.py"]: - repository_ctx.symlink(msvc_wrapper.get_child(f), "wrapper/bin/pydir/" + f) - python_binary = _find_python(repository_ctx) - repository_ctx.template( - "wrapper/bin/call_python.bat", - paths["@bazel_tools//tools/cpp:wrapper/bin/call_python.bat.tpl"], - {"%{python_binary}": escape_string(python_binary)}, - ) - msvc_cl_path = "wrapper/bin/msvc_cl.bat" - msvc_link_path = "wrapper/bin/msvc_link.bat" - msvc_lib_path = "wrapper/bin/msvc_link.bat" - compilation_mode_content = _get_compilation_mode_content() for path in escaped_include_paths.split(";"): if path: @@ -478,7 +355,6 @@ def configure_windows_toolchain(repository_ctx): "%{msvc_lib_path}": msvc_lib_path, "%{dbg_mode_debug}": "/DEBUG:FULL" if support_debug_fastlink else "/DEBUG", "%{fastbuild_mode_debug}": "/DEBUG:FASTLINK" if support_debug_fastlink else "/DEBUG", - "%{compilation_mode_content}": compilation_mode_content, "%{content}": _get_escaped_windows_msys_crosstool_content(repository_ctx), "%{msys_x64_mingw_content}": _get_escaped_windows_msys_crosstool_content(repository_ctx, use_mingw = True), "%{opt_content}": "", diff --git a/tools/cpp/wrapper/bin/call_python.bat.tpl b/tools/cpp/wrapper/bin/call_python.bat.tpl deleted file mode 100644 index 1beb42698a..0000000000 --- a/tools/cpp/wrapper/bin/call_python.bat.tpl +++ /dev/null @@ -1,25 +0,0 @@ -:: Copyright 2016 The Bazel 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. - -:: Invoke the python script under pydir with the same basename -@echo OFF -set arg0=%~1 -for %%F in ("%arg0%") do set DRIVER_BIN=%%~dpF - -for /F "delims=" %%i in ("%arg0%") do set TOOLNAME=%%~ni - -set PYDIR=%DRIVER_BIN%pydir - -if not defined MSVCPYTHON set MSVCPYTHON="%{python_binary}" -%MSVCPYTHON% -B "%PYDIR%\%TOOLNAME%.py" %* diff --git a/tools/cpp/wrapper/bin/msvc_cl.bat b/tools/cpp/wrapper/bin/msvc_cl.bat deleted file mode 100644 index f32dd44871..0000000000 --- a/tools/cpp/wrapper/bin/msvc_cl.bat +++ /dev/null @@ -1,17 +0,0 @@ -:: Copyright 2016 The Bazel 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. - -:: Invoke the python script under pydir with the same basename -@echo OFF -external\local_config_cc\wrapper\bin\call_python.bat %0 %* diff --git a/tools/cpp/wrapper/bin/msvc_link.bat b/tools/cpp/wrapper/bin/msvc_link.bat deleted file mode 100644 index f32dd44871..0000000000 --- a/tools/cpp/wrapper/bin/msvc_link.bat +++ /dev/null @@ -1,17 +0,0 @@ -:: Copyright 2016 The Bazel 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. - -:: Invoke the python script under pydir with the same basename -@echo OFF -external\local_config_cc\wrapper\bin\call_python.bat %0 %* diff --git a/tools/cpp/wrapper/bin/msvc_nop.bat b/tools/cpp/wrapper/bin/msvc_nop.bat deleted file mode 100644 index b422585831..0000000000 --- a/tools/cpp/wrapper/bin/msvc_nop.bat +++ /dev/null @@ -1,17 +0,0 @@ -:: Copyright 2016 The Bazel 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. - -:: Invoke the python script under pydir with the same basename -@echo OFF -echo IGNORING: %0 %* diff --git a/tools/cpp/wrapper/bin/pydir/msvc_cl.py b/tools/cpp/wrapper/bin/pydir/msvc_cl.py deleted file mode 100644 index c148fdd220..0000000000 --- a/tools/cpp/wrapper/bin/pydir/msvc_cl.py +++ /dev/null @@ -1,113 +0,0 @@ -# pylint: disable=g-bad-file-header -# Copyright 2016 The Bazel 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. -"""Wrapper script for executing the Microsoft Compiler.""" -import os -import sys -import msvc_link -import msvc_tools - -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) -sys.path.append(SCRIPT_DIR) - -GCCPATTERNS = [ - ('-I(.+)', ['/I$0']), - ('-m(32|64)', ['$TARGET_ARCH']), - ('-Xcompilation-mode=(dbg|fastbuild|opt)', ['$COMPILATION_MODE']), - ('-msse', ['/arch:SSE']), - ('-msse2', ['/arch:SSE2']), - ('-D(.+)', ['/D$0']), - ('-U(.+)', ['/U$0']), - ('-E', ['/E']), - ('-O0', ['/Od']), - ('-Os', ['/O1']), - ('-O2', ['/O2']), - ('-g0', []), - ('-g', ['$DEBUG_RT']), - ('-fexceptions', ['/U_HAS_EXCEPTIONS', '/D_HAS_EXCEPTIONS=1', '/EHsc']), - ('-fomit-frame-pointer', ['/Oy']), - ('-fno-rtti', ['/GR-']), - ('-frtti', ['/GR']), - ('-fPIC', []), - - # This is unneeded for Windows. - (('-include', '(.+)'), ['/FI$PATH0']), - ('-w', ['/w']), - ('-Wall', ['/Wall']), - ('-Wsign-compare', ['/we4018']), - ('-Wno-sign-compare', ['/wd4018']), - ('-Wconversion', ['/we4244', '/we4267']), - ('-Wno-conversion', ['/wd4244', '/wd4267']), - ('-Wno-sign-conversion', []), - ('-Wno-implicit-fallthrough', []), - ('-Wno-implicit-function-declaration', ['/wd4013']), - ('-Wimplicit-function-declaration', ['/we4013']), - ('-Wcovered-switch-default', ['/we4062']), - ('-Wno-covered-switch-default', ['/wd4062']), - ('-Wno-error', []), - ('-Wno-invalid-offsetof', []), - ('-Wno-overloaded-virtual', []), - ('-Wno-reorder', []), - ('-Wno-string-plus-int', []), - ('-Wl,S', []), # Stripping is unnecessary since msvc uses pdb files. - ('-Wl,-rpath(.+)', []), - ('-B(.+)', []), - ('-static', []), - ('-shared', ['/DLL']), - ('-std=(.+)', []), -] - - -def _IsLink(): - """Determines whether we need to link rather than compile. - - Returns: - True if USE_LINKER is set to 1. - """ - return 'USE_LINKER' in os.environ and os.environ['USE_LINKER'] == '1' - - -class MsvcCompiler(msvc_tools.WindowsRunner): - """Driver for the Microsoft compiler.""" - - def Run(self, argv): - """Runs the compiler using the passed clang/gcc style argument list. - - Args: - argv: List of arguments - - Returns: - The return code of the compilation. - - Raises: - ValueError: if target architecture isn't specified - """ - parser = msvc_tools.ArgParser(self, argv, GCCPATTERNS) - - compiler = 'cl' - if parser.is_cuda_compilation: - compiler = 'nvcc' - return self.RunBinary(compiler, parser.options, parser) - - -def main(argv): - # If we are supposed to link create a static library. - if _IsLink(): - return msvc_link.main(argv) - else: - return MsvcCompiler().Run(argv[1:]) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) # need to skip the first argument diff --git a/tools/cpp/wrapper/bin/pydir/msvc_link.py b/tools/cpp/wrapper/bin/pydir/msvc_link.py deleted file mode 100644 index 28a58f727f..0000000000 --- a/tools/cpp/wrapper/bin/pydir/msvc_link.py +++ /dev/null @@ -1,122 +0,0 @@ -# pylint: disable=g-bad-file-header -# Copyright 2016 The Bazel 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. -"""Wrapper script for executing the Microsoft Linker.""" - -import os -import re -import sys -import msvc_tools - -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) - -sys.path.append(SCRIPT_DIR) - -LINKPATTERNS = [ - ('-m(32|64)', ['$TARGET_ARCH']), - ('-Xcompilation-mode=(dbg|fastbuild|opt)', ['$COMPILATION_MODE']), - (('rcs.*', '(.+)'), ['/OUT:"$PATH0"']), - (('-o', '(.+)'), ['/OUT:"$PATH0"']), - ('-B(.+)', []), - ('-lpthread', []), - ('-L(.+)', ['/LIBPATH:$PATH0']), - ('-static', []), - ('-shared', ['/DLL']), - ('-no-whole-archive', []), - ('-rdynamic', []), - (r'-Wl,(.+)\.lib', ['$0.lib']), - (r'-DEFAULTLIB:(.+)', ['/DEFAULTLIB:$0']), - ('-Wl,@(.+)', ['$LOAD_PARAMS0']), - ('@(.+)', ['$LOAD_PARAMS0']), - ('-Wl,-rpath(.+)', []), - ('-Wl,-S', []), # Debug symbols are in pdb files. - ('-Wl,/SUBSYSTEM:(WINDOWS|CONSOLE)', ['/SUBSYSTEM:$0']), - (r'/WHOLEARCHIVE:(.+)\.lib', ['$0.lib']), -] - - -class MsvcLinker(msvc_tools.WindowsRunner): - """Driver for the Microsoft linker.""" - - def Run(self, argv): - """Runs the linker using the passed clang/gcc style argument list. - - Args: - argv: List of arguments - - Returns: - The return code of the link. - - Raises: - ValueError: if target architecture or compile mode isn't specified - """ - # For now assume we are building a library. - tool = 'lib' - default_args = [] - - # Build argument list. - parser = msvc_tools.ArgParser(self, argv, LINKPATTERNS) - - # Preprocessing arguments for linking whole archive libraries - parser.WholeArchivePreprocess() - - # Find the output file name. - name = '' - for arg in parser.options: - if '/OUT:' in arg: - name = re.sub(r'^"|"$', '', arg[5:]) - if not name: - raise msvc_tools.Error('No output file name specified!') - # Check if the library is empty, which is what happens when we create header - # or intermediate link-only libraries. - if (len(parser.options) == 2 and parser.options[0].startswith('/OUT') and - parser.options[1].startswith('/M')): - # Just "touch" the library to create the file. - with open(name, 'w'): - os.utime(name, None) - else: - # If the output name ends in .lo, or .a, it is a library, otherwise - # we need to use link to create an executable. - if os.path.splitext(name)[1] not in ['.a', '.lo']: - tool = 'link' - - # If there is no .o on the command line, then we need to add the - # run-time library for the target. Without this the linker gives a - # LNK4001 error and cannot find an entry point. - for arg in parser.options: - if arg.endswith('.o'): - break - else: - if not parser.compilation_mode: - raise ValueError('Must specify compilation mode ' - '(-Xcompilation-mode={dbg,fastbuild,opt})') - - rtlib = 'libcmt%s.lib' - # attempt to choose the right runtime library if we can - for opt in reversed(parser.options): - if opt in ['/MT', '/MTd']: - rtlib = 'msvcrt%s.lib' - break - default_args.insert(0, rtlib % - ('d' if parser.compilation_mode == 'dbg' else '')) - - return self.RunBinary(tool, default_args + parser.options, parser) - - -def main(argv): - return MsvcLinker().Run(argv[1:]) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) # need to skip the first argument diff --git a/tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl b/tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl deleted file mode 100644 index 01b4bb6738..0000000000 --- a/tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl +++ /dev/null @@ -1,465 +0,0 @@ -# pylint: disable=g-bad-file-header -# pylint: disable=cell-var-from-loop -# Copyright 2016 The Bazel 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. -"""Tools for working with the Microsoft Visual C++ toolchain.""" - -from argparse import ArgumentParser -import ntpath -import os -import re -import subprocess -import sys - -MAX_PATH = 260 # The maximum number of characters in a Windows path. -MAX_OPTION_LENGTH = 10 # The maximum length of a compiler/linker option. -MAX_DRIVE_LENGTH = 3 # The maximum length of a drive. -MAX_PATH_ADJUSTED = MAX_PATH - MAX_OPTION_LENGTH - MAX_DRIVE_LENGTH -ASSEMBLY_AS_C_SOURCE = '/Tc' -LIB_SUFFIX = '.lib' -LIB_TOOL = "%{lib_tool}" -NVCC_TEMP_DIR = "%{nvcc_tmp_dir_name}" -supported_cuda_compute_capabilities = [ %{cuda_compute_capabilities} ] - -class Error(Exception): - """Base class for all script-specific errors.""" - pass - -def Log(s): - """Print log messages.""" - print('msvc_tools.py: {0}'.format(s)) - -class ArgParser(object): - """Class that parses gcc/clang-style options for a Windows. - - The particular substitutions that are needed are passed to the object. - """ - - def __init__(self, driver, argv, substitutions): - self.driver = driver - self.substitutions = substitutions - self.options = [] - self.leftover = [] - self.target_arch = None - self.compilation_mode = None - self.deps_file = None - self.output_file = None - self.params_file = None - self.support_whole_archive = %{support_whole_archive} - self.global_whole_archive = None - self.is_cuda_compilation = None - self.cuda_log = False - self.enforce_debug_rt = False - self._ParseArgs(argv) - - def ReplaceLibrary(self, arg): - """Do the actual replacement if necessary.""" - if arg == "/WHOLEARCHIVE": - return [] - if arg.startswith("/OUT:") or os.path.splitext(arg)[1] not in ['.a', '.lo']: - return [arg] - if self.global_whole_archive or arg.startswith("/WHOLEARCHIVE:"): - if arg.startswith("/WHOLEARCHIVE:"): - arg = arg[len("/WHOLEARCHIVE:"):] - output = subprocess.check_output([LIB_TOOL, "/list", arg]).decode("utf-8") - object_files = [] - for line in output.split("\n"): - line = line.strip() - if line.endswith(".o"): - object_files.append(line) - return object_files - return [arg] - - def WholeArchivePreprocess(self): - """Replace library file with object files if /WHOLEARCHIVE is not supported.""" - if self.support_whole_archive: - return - options = [] - self.global_whole_archive = "/WHOLEARCHIVE" in self.options - for arg in self.options: - options.extend(self.ReplaceLibrary(arg)) - self.options = options - - def IsCudaCompilation(self): - """Check if it's a cuda compilation.""" - parser = ArgumentParser() - parser.add_argument('-x', nargs=1) - parser.add_argument('--cuda_log', action='store_true') - args, leftover = parser.parse_known_args(self.leftover) - if args.x and args.x[0] == 'cuda': - if args.cuda_log: - Log('Using nvcc') - self.cuda_log = True - self.leftover = leftover - return True - return False - - def GetNvccOptions(self): - """Collect the -nvcc_options values from self.leftover. - - Returns: - The list of options that can be passed directly to nvcc. - """ - - parser = ArgumentParser() - parser.add_argument('-nvcc_options', nargs='*', action='append') - - args, leftover = parser.parse_known_args(self.leftover) - - if args.nvcc_options: - self.leftover = leftover - return ['--'+a for a in sum(args.nvcc_options, [])] - return [] - - def GetOptionValue(self, option): - """Extract the list of values for option from self.options. - - Args: - option: The option whose value to extract, without the leading '/'. - - Returns: - A list of values, either directly following the option, - (eg., /opt val1 val2) or values collected from multiple occurrences of - the option (eg., /opt val1 /opt val2). - """ - - parser = ArgumentParser(prefix_chars='/') - parser.add_argument('/' + option, nargs='*', action='append') - args, leftover = parser.parse_known_args(self.options) - if args and vars(args)[option]: - self.options = leftover - return sum(vars(args)[option], []) - return [] - - def GetOptionsForCudaCompilation(self): - """Get nvcc options with arguments assembled from self.options.""" - - src_files = [f for f in self.options if - re.search('\.cpp$|\.cc$|\.c$|\.cxx$|\.C$', f)] - if len(src_files) == 0: - raise Error('No source files found for cuda compilation.') - - out_file = [ f for f in self.options if f.startswith('/Fo') ] - if len(out_file) != 1: - raise Error('Please sepecify exactly one output file for cuda compilation.') - out = ['-o', out_file[0][len('/Fo'):]] - - nvcc_compiler_options = self.GetNvccOptions() - - opt_option = self.GetOptionValue('O') - opt = ['-g', '-G'] - if (len(opt_option) > 0 and opt_option[0] != 'd'): - opt = ['-O2'] - - include_options = self.GetOptionValue('I') - includes = ["-I " + include for include in include_options] - - defines = self.GetOptionValue('D') - defines = ['-D' + define for define in defines] - - undefines = self.GetOptionValue('U') - undefines = ['-U' + define for define in undefines] - - # The rest of the unrecongized options should be passed to host compiler - host_compiler_options = [option for option in self.options if option not in (src_files + out_file)] - - m_options = ["-m64"] - - nvccopts = ['-D_FORCE_INLINES'] - for capability in supported_cuda_compute_capabilities: - capability = capability.replace('.', '') - nvccopts += [r'-gencode=arch=compute_%s,"code=sm_%s,compute_%s"' % ( - capability, capability, capability)] - nvccopts += nvcc_compiler_options - nvccopts += undefines - nvccopts += defines - nvccopts += m_options - nvccopts += ['--compiler-options="' + " ".join(host_compiler_options) + '"'] - nvccopts += ['-x', 'cu'] + opt + includes + out + ['-c'] + src_files - # If we don't specify --keep-dir, nvcc will generate intermediate files under TEMP - # Put them under NVCC_TEMP_DIR instead, then Bazel can ignore files under NVCC_TEMP_DIR during dependency check - # http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#options-for-guiding-compiler-driver - # Different actions are sharing NVCC_TEMP_DIR, so we cannot remove it if the directory already exists. - if os.path.isfile(NVCC_TEMP_DIR): - os.remove(NVCC_TEMP_DIR) - if not os.path.exists(NVCC_TEMP_DIR): - os.makedirs(NVCC_TEMP_DIR) - nvccopts += ['--keep', '--keep-dir', NVCC_TEMP_DIR] - - if self.cuda_log: - Log("Running: " + " ".join(["nvcc"] + nvccopts)) - - self.options = nvccopts - - def _MatchOneArg(self, args): - """Finds a pattern which matches the beginning elements of args. - - Args: - args: A list of arguments to replace. - - Returns: - A tuple of (number of arguments parsed, action, match groups). - """ - for (regex, action) in self.substitutions: - if isinstance(regex, str): - regex = [regex] - j = 0 - matches = [] - for r in regex: - if j < len(args): - match = re.compile('^' + r + '$').match(args[j]) - else: - match = None - matches.append(match) - j += 1 - if None in matches: - continue - groups = [] - for m in matches: - groups.extend(m.groups()) - return (len(regex), action, groups) - return (0, '', []) - - def _ParseArgs(self, argv): - """Parses argv and replaces its elements using special tokens. - - The following is a list of supported tokens. The format is $TOKEN%d, where - %d is the 0-based group number from regex matches of the pattern. - $CREATE_PATH%d: Touches a file at the path in the matching token. - $LOAD_PARAMS%d: Loads an ld-style params file and appends all arguments to - the current argument list by recursively calling - _ParseArgs. - $%d : Numeric token that just replaces the match group with - the value specified in the match list. - $PATH%d : Replaces the match with a Windows-normalized version of - the match; assumes that the match is a path. - $PATH%d_NO_EXT: Same as $PATH but strips out any file extension. - $TARGET_ARCH : Set self.target_arch to 'x86' or 'x64' for '-m32' and - '-m64', respectively. - $DEBUG_RT : Enforce linkage to debug runtime. - $COMPILE_OUTPUT%d: Sets the output name of a compilation step. - $COMPILATION_MODE: Sets self.compilation_mode from the value of a - '-Xcompilation-mode=' flag. - $CREATE_PRECOMPILED_HEADER: Informs the system that we are generating a - precompiled header rather than an object file. - $GENERATE_DEPS%d: Generates a gcc-style .d file containing dependencies. - - Args: - argv: A list of arguments to replace. - - Returns: - A list of replaced arguments to pass to the target command. - - Raises: - Error: if wrong arguments found - """ - i = 0 - matched = [] - unmatched = [] - files = [] - while i < len(argv): - num_matched, action, groups = self._MatchOneArg(argv[i:]) - arg = argv[i] - if arg.startswith('/Fo') or arg.startswith('/Fa') or arg.startswith( - '/Fi'): - self.output_file = arg[3:] - if num_matched == 0: - # Strip out any .a's that have 0 size, they are header or intermediate - # dependency libraries and don't contain any code. 0-length files are - # considered corrupt by the linker (error LNK1136). - if (os.path.isfile(arg) and os.path.splitext(arg)[1] == '.a' and - os.path.getsize(arg) == 0): - i += 1 - continue - - # If the argument is an absolute path, then add it directly. - if arg[0] == '/': - self.AddOpt(arg) - elif os.path.isfile(arg): - path = self.NormPath(arg) - ext = os.path.splitext(arg)[1].lower() - if ext in ['.s']: - # Treat assembly files as C source files using a special option. - path = ASSEMBLY_AS_C_SOURCE + path - # If this is an actual file on disk then just pass it to the tool. - files.append(path) - elif not arg.endswith(LIB_SUFFIX): - # Ignore .lib files. - unmatched.append(arg) - i += 1 - continue - matched += argv[i:i + num_matched] - # Handle special options. - for entry in action: - if entry == '$TARGET_ARCH': - if arg == '-m32': - self.target_arch = 'x86' - elif arg == '-m64': - self.target_arch = 'x64' - else: - raise Error('Unknown target arch flag: %r' % arg) - continue - - if entry == '$COMPILATION_MODE': - empty, prefix, mode = arg.partition('-Xcompilation-mode=') - if empty or not prefix or mode not in ['dbg', 'fastbuild', 'opt']: - raise Error('Invalid compilation mode flag: %r' % arg) - self.compilation_mode = mode - continue - - if entry == '$DEBUG_RT': - self.enforce_debug_rt = True - continue - - if not groups: - self.options.append(entry) - else: - # Substitute special tokens. - for g in range(0, len(groups)): - value = groups[g] - - # Check for special tokens. - if entry == ('$CREATE_PATH%d' % g): - with open(value, 'a'): - os.utime(value, None) - continue - - if entry == ('$LOAD_PARAMS%d' % g): - try: - # The arguments in the params file need to be processed as - # regular command-line arguments. - params = [line.rstrip() for line in open(value, 'r')] - self._ParseArgs(params) - # Because we have no write permission to orginal params file, - # create a new params file with addtional suffix - self.params_file = value + '.msvc' - except (IOError, e): - print('Could not open', value, 'for reading:', str(e)) - exit(-1) - continue - - # Regular substitution. - patterns = { - '$%d' % g: value, - '$PATH%d_NO_EXT' % g: self.NormPath(os.path.splitext(value)[0]), - '$PATH%d' % g: self.NormPath(value), - } - pattern = re.compile('(%s)' % - '|'.join(map(re.escape, patterns.keys()))) - result = pattern.sub(lambda x: patterns[x.group(0)], entry) - self.options.append(result) - i += num_matched - self.leftover = unmatched - - # Add in any parsed files - self.options += files - - # Suppress all warning messages if /w is specified - is_warning_off = '/w' in self.options - if is_warning_off: - self.options = [option for option in self.options - if option not in ['/W2', '/W3', '/W4', '/Wall']] - - self.is_cuda_compilation = self.IsCudaCompilation() - if self.is_cuda_compilation: - self.GetOptionsForCudaCompilation() - - if self.leftover and not is_warning_off: - print('Warning: Unmatched arguments: ' + ' '.join(self.leftover)) - - def NormPath(self, path): - """Uses the current WindowsRunner to normalize the passed path. - - Args: - path: the path to normalize. - - Returns: - A normalized string representing a path suitable for Windows. - """ - return self.driver.NormPath(path) - - def AddOpt(self, option): - """Adds a single option. - - Args: - option: the option to add. - """ - self.options.append(option) - - -class WindowsRunner(object): - """Base class that encapsulates the details of running a binary.""" - - def NormPath(self, path): - """Normalizes an input unix style path to a < MAX_PATH char Windows format. - - Windows paths cannot be greater than MAX_PATH characters. - - Args: - path: A path in unix format. - - Returns: - An absolute path in Windows format, rooted from some - directory. - - Raises: - Error: if path is too long - """ - abspath = os.path.abspath(path) - # We must allow for the drive letter as well, which is three characters, and - # the length of any compiler option ahead of the path, - if len(abspath) >= MAX_PATH_ADJUSTED: - print( - 'Warning: path "%s" is >= %d characters (%d); programs may crash ' - 'with long arguments' - % (str(abspath), MAX_PATH_ADJUSTED, len(abspath))) - return abspath - - def RunBinary(self, binary, args, parser): - """Runs binary on Windows with the passed args. - - Args: - binary: The binary to run. - args: The arguments to pass to binary. - parser: An ArgParser that contains parsed arguments. - - Returns: - The return code from executing binary. - """ - - # Run the command. - if parser.params_file: - try: - # Using parameter file as input when linking static libraries. - params_file = open(parser.params_file, 'w') - for arg in args: - params_file.write(('"%s"' % arg) if os.path.isfile(arg) else arg) - params_file.write('\n') - params_file.close() - except (IOError, e): - print('Could not open', parser.params_file, 'for writing:', str(e)) - exit(-1) - cmd = [binary] + [('@' + os.path.normpath(parser.params_file))] - else: - cmd = [binary] + args - # Save stderr output to a temporary in case we need it. - # Unconmment the following line to see what exact command is executed. - # print("Running: " + " ".join(cmd)) - proc = subprocess.Popen(cmd, - stdout=sys.stdout, - stderr=sys.stderr, - env=os.environ.copy(), - shell=True) - proc.wait() - return proc.returncode |