Skip to content

Commit

Permalink
System_cxx_toolchain improvements for MSVC support
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Jul 23, 2023
1 parent 0e46095 commit 3b73951
Show file tree
Hide file tree
Showing 6 changed files with 339 additions and 18 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,8 @@ jobs:
- name: Update buck2-prelude submodule
run: git submodule update --init --remote --no-fetch --depth 1 --single-branch tools/buck/prelude
- run: buck2 run demo
continue-on-error: ${{matrix.os == 'windows'}} # FIXME: cl.exe not found
- run: buck2 build ...
continue-on-error: ${{matrix.os == 'windows'}}
- run: buck2 test ...
continue-on-error: ${{matrix.os == 'windows'}}

reindeer:
name: Reindeer
Expand Down
33 changes: 18 additions & 15 deletions tools/buck/toolchains/cxx.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ load("@prelude//cxx:linker.bzl", "is_pdb_generated")
load("@prelude//linking:link_info.bzl", "LinkStyle")
load("@prelude//linking:lto.bzl", "LtoMode")
load("@prelude//utils:cmd_script.bzl", "ScriptOs", "cmd_script")
load("@toolchains//msvc:tools.bzl", "VisualStudio")

def _system_cxx_toolchain_impl(ctx):
archiver_args = ["ar", "rcs"]
Expand All @@ -34,9 +35,10 @@ def _system_cxx_toolchain_impl(ctx):
linker_type = "darwin"
pic_behavior = PicBehavior("always_enabled")
elif host_info().os.is_windows:
archiver_args = ["lib.exe"]
msvc_tools = ctx.attrs.msvc_tools[VisualStudio]
archiver_args = [msvc_tools.lib_exe]
archiver_type = "windows"
asm_compiler = "ml64.exe"
asm_compiler = msvc_tools.ml64_exe
asm_compiler_type = "windows_ml64"
compiler = _windows_compiler_wrapper(ctx)
cxx_compiler = compiler
Expand All @@ -47,9 +49,7 @@ def _system_cxx_toolchain_impl(ctx):
static_library_extension = "lib"
shared_library_name_format = "{}.dll"
shared_library_versioned_name_format = "{}.dll"
additional_linker_flags = [
"msvcrt.lib",
]
additional_linker_flags = ["msvcrt.lib"]
pic_behavior = PicBehavior("not_supported")
elif ctx.attrs.linker == "g++" or ctx.attrs.cxx_compiler == "g++":
pass
Expand Down Expand Up @@ -148,17 +148,19 @@ def _windows_linker_wrapper(ctx: AnalysisContext) -> cmd_args:
def _windows_compiler_wrapper(ctx: AnalysisContext) -> cmd_args:
# The wrapper is needed to dynamically find compiler location and
# Windows SDK to add necessary includes.
return cmd_script(
ctx = ctx,
name = "windows_compiler",
cmd = cmd_args(
ctx.attrs.windows_compiler_wrapper[RunInfo],
ctx.attrs.compiler,
),
os = ScriptOs("windows"),
)
if ctx.attrs.compiler == "cl.exe":
return cmd_script(
ctx = ctx,
name = "windows_compiler",
cmd = cmd_args(
ctx.attrs.windows_compiler_wrapper[RunInfo],
ctx.attrs.msvc_tools[VisualStudio].cl_exe,
),
os = ScriptOs("windows"),
)
else:
return cmd_args(ctx.attrs.compiler)

# Use clang, since thats available everywhere and what we have tested with.
system_cxx_toolchain = rule(
impl = _system_cxx_toolchain_impl,
attrs = {
Expand All @@ -173,6 +175,7 @@ system_cxx_toolchain = rule(
"linker": attrs.string(default = "link.exe" if host_info().os.is_windows else "clang++"),
"linker_wrapper": attrs.default_only(attrs.dep(providers = [RunInfo], default = "prelude//cxx/tools:linker_wrapper")),
"make_comp_db": attrs.default_only(attrs.dep(providers = [RunInfo], default = "prelude//cxx/tools:make_comp_db")),
"msvc_tools": attrs.default_only(attrs.dep(providers = [VisualStudio], default = "toolchains//msvc:msvc_tools")),
"windows_compiler_wrapper": attrs.default_only(attrs.dep(providers = [RunInfo], default = "prelude//cxx/tools:windows_compiler_wrapper")),
},
is_toolchain_rule = True,
Expand Down
18 changes: 18 additions & 0 deletions tools/buck/toolchains/msvc/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
load(":tools.bzl", "find_msvc_tools")

python_bootstrap_binary(
name = "vswhere",
main = "vswhere.py",
visibility = [],
)

python_bootstrap_binary(
name = "run_msvc_tool",
main = "run_msvc_tool.py",
visibility = [],
)

find_msvc_tools(
name = "msvc_tools",
visibility = ["toolchains//..."],
)
40 changes: 40 additions & 0 deletions tools/buck/toolchains/msvc/run_msvc_tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python3

import json
import os
import subprocess
import sys
from typing import List, NamedTuple


class Tool(NamedTuple):
exe: str
libs: List[str]
paths: List[str]
includes: List[str]


def add_env(env, key, entries):
entries = ";".join(entries)
if key in env:
env[key] = entries + ";" + env[key]
else:
env[key] = entries


def main():
tool_json, arguments = sys.argv[1], sys.argv[2:]
with open(tool_json, encoding="utf-8") as f:
tool = Tool(**json.load(f))

env = os.environ.copy()
add_env(env, "LIB", tool.libs)
add_env(env, "PATH", tool.paths)
add_env(env, "INCLUDE", tool.includes)

completed_process = subprocess.run([tool.exe, *arguments], env=env)
sys.exit(completed_process.returncode)


if __name__ == "__main__":
main()
65 changes: 65 additions & 0 deletions tools/buck/toolchains/msvc/tools.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
load("@prelude//utils:cmd_script.bzl", "ScriptOs", "cmd_script")

VisualStudio = provider(fields = [
# Path to cl.exe
"cl_exe",
# Path to lib.exe
"lib_exe",
# Path to ml64.exe
"ml64_exe",
])

def _find_msvc_tools_impl(ctx: AnalysisContext) -> ["provider"]:
cl_exe_json = ctx.actions.declare_output("cl.exe.json")
lib_exe_json = ctx.actions.declare_output("lib.exe.json")
ml64_exe_json = ctx.actions.declare_output("ml64.exe.json")

cmd = [
ctx.attrs.vswhere[RunInfo],
cmd_args("--cl=", cl_exe_json.as_output(), delimiter = ""),
cmd_args("--lib=", lib_exe_json.as_output(), delimiter = ""),
cmd_args("--ml64=", ml64_exe_json.as_output(), delimiter = ""),
]

ctx.actions.run(
cmd,
category = "vswhere",
local_only = True,
)

run_msvc_tool = ctx.attrs.run_msvc_tool[RunInfo]
cl_exe_script = cmd_script(
ctx = ctx,
name = "cl",
cmd = cmd_args(run_msvc_tool, cl_exe_json),
os = ScriptOs("windows"),
)
lib_exe_script = cmd_script(
ctx = ctx,
name = "lib",
cmd = cmd_args(run_msvc_tool, lib_exe_json),
os = ScriptOs("windows"),
)
ml64_exe_script = cmd_script(
ctx = ctx,
name = "ml64",
cmd = cmd_args(run_msvc_tool, ml64_exe_json),
os = ScriptOs("windows"),
)

return [
DefaultInfo(),
VisualStudio(
cl_exe = cl_exe_script,
lib_exe = lib_exe_script,
ml64_exe = ml64_exe_script,
),
]

find_msvc_tools = rule(
impl = _find_msvc_tools_impl,
attrs = {
"run_msvc_tool": attrs.default_only(attrs.dep(providers = [RunInfo], default = "toolchains//msvc:run_msvc_tool")),
"vswhere": attrs.default_only(attrs.dep(providers = [RunInfo], default = "toolchains//msvc:vswhere")),
},
)
Loading

0 comments on commit 3b73951

Please sign in to comment.