2
0
Fork 0
mirror of https://github.com/bazel-contrib/rules_foreign_cc synced 2024-12-03 02:52:58 +00:00
rules_foreign_cc/tools/build_defs/configure_script.bzl
James Sharpe 9a4435ecab
Attempt to catch shell script errors proactively with 'set -euo pipef… (#500)
* Attempt to catch shell script errors proactively with 'set -euo pipefail'

* Fix up uninitialised variable use

* Fix osx shell function

* Fix to unbound variable in windows commands
2021-02-16 11:55:48 -08:00

239 lines
7.9 KiB
Python

# buildifier: disable=module-docstring
load(":cc_toolchain_util.bzl", "absolutize_path_in_str")
load(":framework.bzl", "get_foreign_cc_dep")
def _pkgconfig_script(ext_build_dirs):
"""Create a script fragment to configure pkg-config"""
script = []
for ext_dir in ext_build_dirs:
script.append("##increment_pkg_config_path## $$EXT_BUILD_DEPS$$/" + ext_dir.basename)
script.append("echo \"PKG_CONFIG_PATH=$${PKG_CONFIG_PATH:-}$$\"")
script.append("##define_absolute_paths## $$EXT_BUILD_DEPS$$ $$EXT_BUILD_DEPS$$")
return script
# buildifier: disable=function-docstring
def create_configure_script(
workspace_name,
target_os,
tools,
flags,
root,
user_options,
user_vars,
is_debug,
configure_command,
deps,
inputs,
configure_in_place,
autoconf,
autoconf_options,
autoconf_env_vars,
autoreconf,
autoreconf_options,
autoreconf_env_vars,
autogen,
autogen_command,
autogen_options,
autogen_env_vars):
env_vars_string = get_env_vars(workspace_name, tools, flags, user_vars, deps, inputs)
ext_build_dirs = inputs.ext_build_dirs
script = _pkgconfig_script(ext_build_dirs)
root_path = "$$EXT_BUILD_ROOT$$/{}".format(root)
configure_path = "{}/{}".format(root_path, configure_command)
if configure_in_place:
script.append("##symlink_contents_to_dir## $$EXT_BUILD_ROOT$$/{} $$BUILD_TMPDIR$$".format(root))
root_path = "$$BUILD_TMPDIR$$"
configure_path = "{}/{}".format(root_path, configure_command)
if autogen and configure_in_place:
# NOCONFIGURE is pseudo standard and tells the script to not invoke configure.
# We explicitly invoke configure later.
autogen_env_vars = _get_autogen_env_vars(autogen_env_vars)
script.append("{} \"{}/{}\" {}".format(
" ".join(["{}=\"{}\"".format(key, autogen_env_vars[key]) for key in autogen_env_vars]),
root_path,
autogen_command,
" ".join(autogen_options),
).lstrip())
if autoconf and configure_in_place:
script.append("{} autoconf {}".format(
" ".join(["{}=\"{}\"".format(key, autoconf_env_vars[key]) for key in autoconf_env_vars]),
" ".join(autoconf_options),
).lstrip())
if autoreconf and configure_in_place:
script.append("{} autoreconf {}".format(
" ".join(["{}=\"{}\"".format(key, autoreconf_env_vars[key]) for key in autoreconf_env_vars]),
" ".join(autoreconf_options),
).lstrip())
script.append("{env_vars} \"{configure}\" --prefix=$$BUILD_TMPDIR$$/$$INSTALL_PREFIX$$ {user_options}".format(
env_vars = env_vars_string,
configure = configure_path,
user_options = " ".join(user_options),
))
return "\n".join(script)
# buildifier: disable=function-docstring
def create_make_script(
workspace_name,
tools,
flags,
root,
user_vars,
deps,
inputs,
make_commands,
prefix):
env_vars_string = get_env_vars(workspace_name, tools, flags, user_vars, deps, inputs)
ext_build_dirs = inputs.ext_build_dirs
script = _pkgconfig_script(ext_build_dirs)
script.append("##symlink_contents_to_dir## $$EXT_BUILD_ROOT$$/{} $$BUILD_TMPDIR$$".format(root))
script.append("" + " && ".join(make_commands))
return "\n".join(script)
# buildifier: disable=function-docstring
def get_env_vars(
workspace_name,
tools,
flags,
user_vars,
deps,
inputs):
vars = _get_configure_variables(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 _get_autogen_env_vars(autogen_env_vars):
# Make a copy if necessary so we can set NOCONFIGURE.
if autogen_env_vars.get("NOCONFIGURE"):
return autogen_env_vars
vars = {}
for key in autogen_env_vars:
vars[key] = autogen_env_vars.get(key)
vars["NOCONFIGURE"] = "1"
return 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(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:
tools_dict[tool] = [tool_value]
# 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):
return absolutize_path_in_str(workspace_name, "$$EXT_BUILD_ROOT$$/", text)
def _join_flags_list(workspace_name, flags):
return " ".join([_absolutize(workspace_name, flag) for flag in flags])