Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass toolchain and user env variables to make invocation #777

Merged
merged 3 commits into from
Nov 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions examples/make_simple/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ load("@rules_foreign_cc//foreign_cc:defs.bzl", "make")

make(
name = "make_lib",
build_data = ["//make_simple/code:clang_wrapper.sh"],
build_data = ["//make_simple/code:cxx_wrapper.sh"],
copts = [
"-DREQUIRED_DEFINE",
],
env = {
"CLANG_WRAPPER": "$(execpath //make_simple/code:clang_wrapper.sh)",
"CXX_WRAPPER": "$(execpath //make_simple/code:cxx_wrapper.sh)",
},
lib_source = "//make_simple/code:srcs",
out_static_libs = ["liba.a"],
Expand All @@ -16,6 +19,9 @@ cc_test(
srcs = [
"test_libb.cpp",
],
copts = [
"-std=c++11",
],
tags = ["windows"],
deps = [
":make_lib",
Expand Down
2 changes: 1 addition & 1 deletion examples/make_simple/code/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
exports_files(["clang_wrapper.sh"])
exports_files(["cxx_wrapper.sh"])

filegroup(
name = "srcs",
Expand Down
7 changes: 3 additions & 4 deletions examples/make_simple/code/Makefile
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
BUILD_DIR=build-out

UNAME:=$(shell uname)
CXX_FLAGS :=

ifneq (,$(findstring NT, $(UNAME)))
# If Windows
CXX_FLAGS := /MD
CXXFLAGS := $(CXXFLAGS) /MD
else
CXX_FLAGS := -fPIC
CXXFLAGS := $(CXXFLAGS) -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) $(CXX_FLAGS) -o $(BUILD_DIR)/lib/liba.o -c liba.cpp
$(CXX_WRAPPER) $(CXXFLAGS) -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ if [[ $(uname) == *"NT"* ]]; then
# If Windows
exec clang-cl "$@"
else
exec clang "$@"
exec "$CXX" "$@"
fi
16 changes: 15 additions & 1 deletion examples/make_simple/code/liba.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
#include "liba.h"

#include <math.h>

#ifndef REQUIRED_DEFINE
// '-DREQUIRED_DEFINE' is set via the copts attribute of the make rule.
#error "REQUIRED_DEFINE is not defined"
#endif

std::string hello_liba(void) {
return "Hello from LIBA!";
}
}

double hello_math(double a) {
// On Unix, this call requires linking to libm.so. The Bazel toolchain adds
// the required `-lm` linkopt automatically and rules_foreign_cc forwards
// this option to make invocation via the CXXFLAGS variable.
return acos(a);
}
3 changes: 2 additions & 1 deletion examples/make_simple/code/liba.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
#include <string>

std::string hello_liba(void);
double hello_math(double);

#endif
#endif
4 changes: 4 additions & 0 deletions examples/make_simple/test_libb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@ int main(int argc, char* argv[])
if (result != "Hello from LIBA!") {
throw std::runtime_error("Wrong result: " + result);
}
double math_result = hello_math(0.5);
if (math_result < 1.047 || math_result > 1.048) {
throw std::runtime_error("Wrong math_result: " + std::to_string(math_result));
}
std::cout << "Everything's fine!";
}
7 changes: 7 additions & 0 deletions foreign_cc/make.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ def _create_make_script(configureParameters):
for arg in ctx.attr.args
])

user_env = expand_locations(ctx, ctx.attr.env, data)

make_commands = []
prefix = "{} ".format(expand_locations(ctx, attrs.tool_prefix, data)) if attrs.tool_prefix else ""
for target in ctx.attr.targets:
Expand All @@ -65,8 +67,13 @@ def _create_make_script(configureParameters):
))

return create_make_script(
workspace_name = ctx.workspace_name,
tools = tools,
flags = flags,
root = root,
deps = ctx.attr.deps,
inputs = inputs,
env_vars = user_env,
make_commands = make_commands,
)

Expand Down
138 changes: 2 additions & 136 deletions foreign_cc/private/configure_script.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# buildifier: disable=module-docstring
load(":cc_toolchain_util.bzl", "absolutize_path_in_str")
load(":framework.bzl", "get_foreign_cc_dep")
load(":make_env_vars.bzl", "get_make_env_vars")
load(":make_script.bzl", "pkgconfig_script")

# buildifier: disable=function-docstring
Expand Down Expand Up @@ -72,7 +71,7 @@ def create_configure_script(

script.append("##mkdirs## $$BUILD_TMPDIR$$/$$INSTALL_PREFIX$$")
script.append("{env_vars} {prefix}\"{configure}\" --prefix=$$BUILD_TMPDIR$$/$$INSTALL_PREFIX$$ {user_options}".format(
env_vars = _get_env_vars(workspace_name, tools, flags, env_vars, deps, inputs),
env_vars = get_make_env_vars(workspace_name, tools, flags, env_vars, deps, inputs),
prefix = configure_prefix,
configure = configure_path,
user_options = " ".join(user_options),
Expand All @@ -92,136 +91,3 @@ def _get_autogen_env_vars(autogen_env_vars):
vars[key] = autogen_env_vars.get(key)
vars["NOCONFIGURE"] = "1"
return vars

# buildifier: disable=function-docstring
def _get_env_vars(
workspace_name,
tools,
flags,
user_vars,
deps,
inputs):
vars = _get_configure_variables(workspace_name, tools, flags, user_vars)
deps_flags = _define_deps_flags(deps, inputs)

if "LDFLAGS" in vars.keys():
vars["LDFLAGS"] = vars["LDFLAGS"] + deps_flags.libs
else:
vars["LDFLAGS"] = deps_flags.libs

# -I flags should be put into preprocessor flags, CPPFLAGS
# https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Preset-Output-Variables.html
vars["CPPFLAGS"] = deps_flags.flags

return " ".join(["{}=\"{}\""
.format(key, _join_flags_list(workspace_name, vars[key])) for key in vars])

def _define_deps_flags(deps, inputs):
# It is very important to keep the order for the linker => put them into list
lib_dirs = []

# Here go libraries built with Bazel
gen_dirs_set = {}
for lib in inputs.libs:
dir_ = lib.dirname
if not gen_dirs_set.get(dir_):
gen_dirs_set[dir_] = 1
lib_dirs.append("-L$$EXT_BUILD_ROOT$$/" + dir_)

include_dirs_set = {}
for include_dir in inputs.include_dirs:
include_dirs_set[include_dir] = "-I$$EXT_BUILD_ROOT$$/" + include_dir
for header in inputs.headers:
include_dir = header.dirname
if not include_dirs_set.get(include_dir):
include_dirs_set[include_dir] = "-I$$EXT_BUILD_ROOT$$/" + include_dir
include_dirs = include_dirs_set.values()

# For the external libraries, we need to refer to the places where
# we copied the dependencies ($EXT_BUILD_DEPS/<lib_name>), because
# we also want configure to find that same files with pkg-config
# -config or other mechanics.
# Since we need the names of include and lib directories under
# the $EXT_BUILD_DEPS/<lib_name>, we ask the provider.
gen_dirs_set = {}
for dep in deps:
external_deps = get_foreign_cc_dep(dep)
if external_deps:
for artifact in external_deps.artifacts.to_list():
if not gen_dirs_set.get(artifact.gen_dir):
gen_dirs_set[artifact.gen_dir] = 1

dir_name = artifact.gen_dir.basename
include_dirs.append("-I$$EXT_BUILD_DEPS$$/{}/{}".format(dir_name, artifact.include_dir_name))
lib_dirs.append("-L$$EXT_BUILD_DEPS$$/{}/{}".format(dir_name, artifact.lib_dir_name))

return struct(
libs = lib_dirs,
flags = include_dirs,
)

# See https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
_CONFIGURE_FLAGS = {
"ARFLAGS": "cxx_linker_static",
"ASFLAGS": "assemble",
"CFLAGS": "cc",
"CXXFLAGS": "cxx",
"LDFLAGS": "cxx_linker_executable",
# missing: cxx_linker_shared
}

_CONFIGURE_TOOLS = {
"AR": "cxx_linker_static",
"CC": "cc",
"CXX": "cxx",
# missing: cxx_linker_executable
}

def _get_configure_variables(workspace_name, tools, flags, user_env_vars):
vars = {}

for flag in _CONFIGURE_FLAGS:
flag_value = getattr(flags, _CONFIGURE_FLAGS[flag])
if flag_value:
vars[flag] = flag_value

# Merge flags lists
for user_var in user_env_vars:
toolchain_val = vars.get(user_var)
if toolchain_val:
vars[user_var] = toolchain_val + [user_env_vars[user_var]]

tools_dict = {}
for tool in _CONFIGURE_TOOLS:
tool_value = getattr(tools, _CONFIGURE_TOOLS[tool])
if tool_value:
# Force absolutize of tool paths, which may relative to the exec root (e.g. hermetic toolchains built from source)
tool_value_absolute = _absolutize(workspace_name, tool_value, True)

# If the tool path contains whitespaces (e.g. C:\Program Files\...),
# MSYS2 requires that the path is wrapped in double quotes
if " " in tool_value_absolute:
tool_value_absolute = "\\\"" + tool_value_absolute + "\\\""

tools_dict[tool] = [tool_value_absolute]

# Replace tools paths if user passed other values
for user_var in user_env_vars:
toolchain_val = tools_dict.get(user_var)
if toolchain_val:
tools_dict[user_var] = [user_env_vars[user_var]]

vars.update(tools_dict)

# Put all other environment variables, passed by the user
for user_var in user_env_vars:
if not vars.get(user_var):
vars[user_var] = [user_env_vars[user_var]]

return vars

def _absolutize(workspace_name, text, force = False):
return absolutize_path_in_str(workspace_name, "$$EXT_BUILD_ROOT$$/", text, force)

def _join_flags_list(workspace_name, flags):
return " ".join([_absolutize(workspace_name, flag) for flag in flags])
Loading