Build make windows (#716)

* Refactor _env_prelude method to be public (589)

In an upcoming commit, the method will be used to set the PATH,
INCLUDE and LIB environment variables in Windows when building GNU
Make from source

* Build make from source on Windows (#589)

The built_tools_framework.bzl file was modified so that the PATH,
INCLUDE and LIB environment variables are set from the C++ toolchain,
e.g. MSVC.

The PATH environment variable is prepended with the path to the
toolchain's linker, otherwise the MSYS2 linker would be used instead
of MSVC (as they are both named link.exe).
This commit is contained in:
jheaff1 2021-07-12 07:17:18 -07:00 committed by GitHub
parent bb2f0ab0aa
commit 93d7c272cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 76 additions and 21 deletions

View File

@ -105,9 +105,7 @@ tasks:
- "-//cmake_hello_world_lib/..."
- "-//cmake_synthetic/..."
- "-//cmake_with_bazel_transitive/..."
- "-//cmake_working_dir/..."
- "-//configure_with_bazel_transitive/..."
- "-//make_simple/..."
- "-//ninja_simple/..."
build_targets: *windows_targets
test_targets: *windows_targets

View File

@ -1,8 +1,19 @@
BUILD_DIR=build-out
UNAME:=$(shell uname)
CXX_FLAGS :=
ifneq (,$(findstring NT, $(UNAME)))
# If Windows
CXX_FLAGS := /MD
else
CXX_FLAGS := -fPIC
endif
default all $(BUILD_DIR)/lib/liba.a: liba.cpp liba.h
rm -rf $(BUILD_DIR)/lib
mkdir -p $(BUILD_DIR)/lib
$(CLANG_WRAPPER) -fPIC -o $(BUILD_DIR)/lib/liba.o -c liba.cpp
$(CLANG_WRAPPER) $(CXX_FLAGS) -o $(BUILD_DIR)/lib/liba.o -c liba.cpp
ar rcs $(BUILD_DIR)/lib/liba.a $(BUILD_DIR)/lib/liba.o
install: $(BUILD_DIR)/lib/liba.a

View File

@ -1,3 +1,8 @@
#!/bin/bash -eu
exec clang "$@"
if [[ $(uname) == *"NT"* ]]; then
# If Windows
exec clang-cl "$@"
else
exec clang "$@"
fi

View File

@ -76,6 +76,7 @@ test_suite(
name = "windows_tests",
tags = ["manual"],
tests = [
# TODO: Add windows tests
"//curl:curl_build_test",
# TODO: Add more windows tests
],
)

View File

@ -1,27 +1,39 @@
""" Rule for building GNU Make from sources. """
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
load(
"//foreign_cc/built_tools/private:built_tools_framework.bzl",
"FOREIGN_CC_BUILT_TOOLS_ATTRS",
"FOREIGN_CC_BUILT_TOOLS_FRAGMENTS",
"FOREIGN_CC_BUILT_TOOLS_HOST_FRAGMENTS",
"built_tool_rule_impl",
)
load("//foreign_cc/private/framework:platform.bzl", "os_name")
def _make_tool_impl(ctx):
script = [
"./configure --disable-dependency-tracking --prefix=$$INSTALLDIR$$",
"./build.sh",
]
cc_toolchain = find_cpp_toolchain(ctx)
if "win" in os_name(ctx):
script.extend([
"./make.exe install",
])
build_str = "./build_w32.bat --without-guile"
dist_dir = None
if cc_toolchain.compiler == "mingw-gcc":
build_str += " gcc"
dist_dir = "GccRel"
else:
dist_dir = "WinRel"
script = [
build_str,
"mkdir -p $$INSTALLDIR$$/bin",
"cp -p ./{}/gnumake.exe $$INSTALLDIR$$/bin/make.exe".format(dist_dir),
]
else:
script.extend([
script = [
"./configure --disable-dependency-tracking --prefix=$$INSTALLDIR$$",
"./build.sh",
"./make install",
])
]
return built_tool_rule_impl(
ctx,
@ -34,6 +46,7 @@ make_tool = rule(
doc = "Rule for building Make. Invokes configure script and make install.",
attrs = FOREIGN_CC_BUILT_TOOLS_ATTRS,
host_fragments = FOREIGN_CC_BUILT_TOOLS_HOST_FRAGMENTS,
fragments = FOREIGN_CC_BUILT_TOOLS_FRAGMENTS,
output_to_genfiles = True,
implementation = _make_tool_impl,
toolchains = [

View File

@ -3,6 +3,7 @@
load(
"//foreign_cc/built_tools/private:built_tools_framework.bzl",
"FOREIGN_CC_BUILT_TOOLS_ATTRS",
"FOREIGN_CC_BUILT_TOOLS_FRAGMENTS",
"FOREIGN_CC_BUILT_TOOLS_HOST_FRAGMENTS",
"built_tool_rule_impl",
)
@ -28,6 +29,7 @@ ninja_tool = rule(
doc = "Rule for building Ninja. Invokes configure script.",
attrs = FOREIGN_CC_BUILT_TOOLS_ATTRS,
host_fragments = FOREIGN_CC_BUILT_TOOLS_HOST_FRAGMENTS,
fragments = FOREIGN_CC_BUILT_TOOLS_FRAGMENTS,
output_to_genfiles = True,
implementation = _ninja_tool_impl,
toolchains = [

View File

@ -1,12 +1,18 @@
"""A module defining a common framework for "built_tools" rules"""
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
load("//foreign_cc/private:detect_root.bzl", "detect_root")
load("//foreign_cc/private:framework.bzl", "wrap_outputs")
load("//foreign_cc/private:framework.bzl", "get_env_prelude", "wrap_outputs")
load("//foreign_cc/private/framework:helpers.bzl", "convert_shell_script", "shebang")
load("//foreign_cc/private/framework:platform.bzl", "os_name")
# Common attributes for all built_tool rules
FOREIGN_CC_BUILT_TOOLS_ATTRS = {
"env": attr.string_dict(
doc = "Environment variables to set during the build.",
default = {},
),
"srcs": attr.label(
doc = "The target containing the build tool's sources",
mandatory = True,
@ -21,6 +27,11 @@ FOREIGN_CC_BUILT_TOOLS_ATTRS = {
),
}
# Common fragments for all built_tool rules
FOREIGN_CC_BUILT_TOOLS_FRAGMENTS = [
"cpp",
]
# Common host fragments for all built_tool rules
FOREIGN_CC_BUILT_TOOLS_HOST_FRAGMENTS = [
"cpp",
@ -44,12 +55,29 @@ def built_tool_rule_impl(ctx, script_lines, out_dir, mnemonic):
"""
root = detect_root(ctx.attr.srcs)
lib_name = ctx.attr.name
env_prelude = get_env_prelude(ctx, lib_name, [], "")
script = [
cc_toolchain = find_cpp_toolchain(ctx)
path_prepend_cmd = ""
if "win" in os_name(ctx):
# Prepend PATH environment variable with the path to the toolchain linker, which prevents MSYS using its linker (/usr/bin/link.exe) rather than the MSVC linker (both are named "link.exe")
linker_path = paths.dirname(cc_toolchain.ld_executable)
# Change prefix of linker path from Windows style to Unix style, required by MSYS. E.g. change "C:" to "/c"
if linker_path[0].isalpha() and linker_path[1] == ":":
linker_path = linker_path.replace(linker_path[0:2], "/" + linker_path[0].lower())
# MSYS requires pahts containing whitespace to be wrapped in quotation marks
path_prepend_cmd = "export PATH=\"" + linker_path + "\":$PATH"
script = env_prelude + [
"##script_prelude##",
"export EXT_BUILD_ROOT=##pwd##",
"export INSTALLDIR=$$EXT_BUILD_ROOT$$/{}".format(out_dir.path),
"export BUILD_TMPDIR=$$INSTALLDIR$$.build_tmpdir",
path_prepend_cmd,
"##mkdirs## $$BUILD_TMPDIR$$",
"##copy_dir_contents_to_dir## ./{} $$BUILD_TMPDIR$$".format(root),
"cd $$BUILD_TMPDIR$$",
@ -65,10 +93,7 @@ def built_tool_rule_impl(ctx, script_lines, out_dir, mnemonic):
"",
])
lib_name = ctx.attr.name
wrapped_outputs = wrap_outputs(ctx, lib_name, mnemonic, script_text)
cc_toolchain = find_cpp_toolchain(ctx)
tools = depset(
[wrapped_outputs.wrapper_script_file, wrapped_outputs.script_file],

View File

@ -269,7 +269,7 @@ def _escape_dquote(text):
"""
return text.replace('"', r'\"\\\\\\"')
def _env_prelude(ctx, lib_name, data_dependencies, target_root):
def get_env_prelude(ctx, lib_name, data_dependencies, target_root):
"""Generate a bash snippet containing environment variable definitions
Args:
@ -379,7 +379,7 @@ def cc_external_rule_impl(ctx, attrs):
# Also add legacy dependencies while they're still available
data_dependencies += ctx.attr.tools_deps + ctx.attr.additional_tools
env_prelude = _env_prelude(ctx, lib_name, data_dependencies, target_root)
env_prelude = get_env_prelude(ctx, lib_name, data_dependencies, target_root)
postfix_script = [attrs.postfix_script]
if not attrs.postfix_script: