Skip to content

Commit

Permalink
configure_make: support autotools cross-compilation
Browse files Browse the repository at this point in the history
This teaches the autotools-based configure script to pass --host when
cross-compilation is detected. This fixes at least part of #1082. This
functionality is off by default (because configure_make can be used for
non-autotools builds) and can be enabled by passing configure_xcompile
to configure_make.

This functionality is also extended to the built_tools that use autoconf
(pkg-config and make).

It also does a bit of generalization to make it easier to support more
platforms in the future, and adds s390x to the detected arches.
  • Loading branch information
novas0x2a committed Aug 9, 2024
1 parent 122d83c commit 920c1d6
Show file tree
Hide file tree
Showing 9 changed files with 247 additions and 28 deletions.
25 changes: 22 additions & 3 deletions foreign_cc/built_tools/make_build.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ load(
"get_flags_info",
"get_tools_info",
)
load("//foreign_cc/private:detect_xcompile.bzl", "detect_xcompile")
load("//foreign_cc/private/framework:platform.bzl", "os_name")

def _make_tool_impl(ctx):
Expand Down Expand Up @@ -74,6 +75,25 @@ def _make_tool_impl(ctx):
if os_name(ctx) == "macos":
non_sysroot_ldflags += ["-undefined", "error"]

configure_options = [
"--without-guile",
"--with-guile=no",
"--disable-dependency-tracking",
"--prefix=$$INSTALLDIR$$",
]

install_cmd = ["./make install"]

xcompile_options = detect_xcompile(ctx)
if xcompile_options:
configure_options.extend(xcompile_options)

# We can't use make to install make when cross-compiling
install_cmd = [
"mkdir -p $$INSTALLDIR$$/bin",
"cp -p make $$INSTALLDIR$$/bin/make",
]

env.update({
"AR": absolute_ar,
"ARFLAGS": _join_flags_list(ctx.workspace_name, arflags),
Expand All @@ -85,11 +105,10 @@ def _make_tool_impl(ctx):

configure_env = " ".join(["%s=\"%s\"" % (key, value) for key, value in env.items()])
script = [
"%s ./configure --without-guile --with-guile=no --disable-dependency-tracking --prefix=$$INSTALLDIR$$" % configure_env,
"%s ./configure %s" % (configure_env, " ".join(configure_options)),
"cat build.cfg",
"./build.sh",
"./make install",
]
] + install_cmd

return built_tool_rule_impl(
ctx,
Expand Down
12 changes: 11 additions & 1 deletion foreign_cc/built_tools/pkgconfig_build.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ load(
"get_flags_info",
"get_tools_info",
)
load("//foreign_cc/private:detect_xcompile.bzl", "detect_xcompile")
load("//foreign_cc/private/framework:platform.bzl", "os_name")
load("//toolchains/native_tools:tool_access.bzl", "get_make_data")

Expand Down Expand Up @@ -61,6 +62,15 @@ def _pkgconfig_tool_impl(ctx):

make_data = get_make_data(ctx)

configure_options = [
"--with-internal-glib",
"--prefix=$$INSTALLDIR$$",
]

xcompile_options = detect_xcompile(ctx)
if xcompile_options:
configure_options.extend(xcompile_options)

env.update({
"AR": absolute_ar,
"ARFLAGS": _join_flags_list(ctx.workspace_name, arflags),
Expand All @@ -73,7 +83,7 @@ def _pkgconfig_tool_impl(ctx):

configure_env = " ".join(["%s=\"%s\"" % (key, value) for key, value in env.items()])
script = [
"%s ./configure --with-internal-glib --prefix=$$INSTALLDIR$$" % configure_env,
"%s ./configure %s" % (configure_env, " ".join(configure_options)),
"%s" % make_data.path,
"%s install" % make_data.path,
]
Expand Down
10 changes: 10 additions & 0 deletions foreign_cc/built_tools/private/built_tools_framework.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ load("//foreign_cc/private:cc_toolchain_util.bzl", "absolutize_path_in_str")
load("//foreign_cc/private:detect_root.bzl", "detect_root")
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", "PLATFORM_CONSTRAINTS_RULE_ATTRIBUTES")

# Common attributes for all built_tool rules
FOREIGN_CC_BUILT_TOOLS_ATTRS = {
"configure_xcompile": attr.bool(
doc = (
"If this is set and an xcompile scenario is detected, pass the necessary autotools flags. (Only applies if autotools is used)"
),
default = False,
),
"env": attr.string_dict(
doc = "Environment variables to set during the build. This attribute is subject to make variable substitution.",
default = {},
Expand All @@ -26,6 +33,9 @@ FOREIGN_CC_BUILT_TOOLS_ATTRS = {
),
}

# this would be cleaner as x | y, but that's not supported in bazel 5.4.0
FOREIGN_CC_BUILT_TOOLS_ATTRS.update(PLATFORM_CONSTRAINTS_RULE_ATTRIBUTES)

# Common fragments for all built_tool rules
FOREIGN_CC_BUILT_TOOLS_FRAGMENTS = [
"apple",
Expand Down
11 changes: 11 additions & 0 deletions foreign_cc/configure.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ load(
)
load("//foreign_cc/private:configure_script.bzl", "create_configure_script")
load("//foreign_cc/private:detect_root.bzl", "detect_root")
load("//foreign_cc/private:detect_xcompile.bzl", "detect_xcompile")
load(
"//foreign_cc/private:framework.bzl",
"CC_EXTERNAL_RULE_ATTRIBUTES",
Expand Down Expand Up @@ -78,6 +79,10 @@ def _create_configure_script(configureParameters):
configure_prefix = "{} ".format(expand_locations_and_make_variables(ctx, ctx.attr.configure_prefix, "configure_prefix", data)) if ctx.attr.configure_prefix else ""
configure_options = [expand_locations_and_make_variables(ctx, option, "configure_option", data) for option in ctx.attr.configure_options] if ctx.attr.configure_options else []

xcompile_options = detect_xcompile(ctx)
if xcompile_options:
configure_options.extend(xcompile_options)

for target in ctx.attr.targets:
# Configure will have generated sources into `$BUILD_TMPDIR` so make sure we `cd` there
make_commands.append("{prefix}{make} {target} {args}".format(
Expand Down Expand Up @@ -187,6 +192,12 @@ def _attrs():
"configure_prefix": attr.string(
doc = "A prefix for the call to the `configure_command`.",
),
"configure_xcompile": attr.bool(
doc = (
"If this is set and an xcompile scenario is detected, pass the necessary autotools flags."
),
default = False,
),
"install_prefix": attr.string(
doc = (
"Install prefix, i.e. relative path to where to install the result of the build. " +
Expand Down
2 changes: 2 additions & 0 deletions foreign_cc/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ bzl_library(
deps = [
":cc_toolchain_util",
":detect_root",
":detect_xcompile.bzl",
":run_shell_file_utils",
"//foreign_cc:providers",
"//foreign_cc/private/framework:helpers",
"//foreign_cc/private/framework:platform",
"@bazel_skylib//lib:collections",
"@bazel_skylib//lib:paths",
"@bazel_tools//tools/cpp:toolchain_utils.bzl",
Expand Down
8 changes: 7 additions & 1 deletion foreign_cc/private/cmake_script.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ _TARGET_ARCH_PARAMS = {
"aarch64": {
"CMAKE_SYSTEM_PROCESSOR": "aarch64",
},
"s390x": {
"CMAKE_SYSTEM_PROCESSOR": "s390x",
},
"x86_64": {
"CMAKE_SYSTEM_PROCESSOR": "x86_64",
},
Expand Down Expand Up @@ -120,7 +123,10 @@ def create_cmake_script(
# by setting CMAKE_SYSTEM_NAME and CMAKE_SYSTEM_PROCESSOR,
# see https://github.com/bazelbuild/rules_foreign_cc/issues/289,
# and https://github.com/bazelbuild/rules_foreign_cc/pull/1062
if target_os != host_os and target_os != "unknown":
if target_os == "unknown":
# buildifier: disable=print
print("target_os is unknown; please update foreign_cc/private/framework/platform.bzl and foreign_cc/private/cmake_script.bzl")
elif target_os != host_os:
params.cache.update(_TARGET_OS_PARAMS.get(target_os, {}))
params.cache.update(_TARGET_ARCH_PARAMS.get(target_arch, {}))

Expand Down
61 changes: 61 additions & 0 deletions foreign_cc/private/detect_xcompile.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# buildifier: disable=module-docstring
load(
"//foreign_cc/private/framework:platform.bzl",
"arch_name",
"os_name",
"target_arch_name",
"target_os_name",
"triplet_name",
)

def detect_xcompile(ctx):
"""A helper function for detecting and setting autoconf-style xcompile flags
Args:
ctx (ctx): The current rule's context object
Returns:
list(str): The flags to set, or None if xcompiling is disabled
"""

if not ctx.attr.configure_xcompile:
return None

host_triplet = triplet_name(
os_name(ctx),
arch_name(ctx),
)

if host_triplet == "unknown":
# buildifier: disable=print
print("host is unknown; please update foreign_cc/private/framework/platform.bzl")
return None

target_triplet = triplet_name(
target_os_name(ctx),
target_arch_name(ctx),
)

if target_triplet == "unknown":
# buildifier: disable=print
print("target is unknown; please update foreign_cc/private/framework/platform.bzl")
return None

if target_triplet == host_triplet:
return None

# We pass both --host and --build here, even though we technically only
# need to pass --host. This is because autotools compares them (without
# normalization) to determine if a build is a cross-compile
#
# If we don't pass --build, autotools will populate it itself, and it might
# be normalized such that autotools thinks it's a cross-compile, but it
# shouldn't be.
#
# An example of this is if we pass --host=x86_64-pc-linux-gnu but the
# target compiler thinks it's for x86_64-unknown-linux-gnu; if we don't
# pass --build, that will incorrectly be considered a cross-compile.
#
# Also, no, this isn't backwards. --host means target
# https://www.gnu.org/software/automake/manual/html_node/Cross_002dCompilation.html
return ["--host=" + target_triplet, "--build=" + host_triplet]
8 changes: 4 additions & 4 deletions foreign_cc/private/framework.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ load(
"script_extension",
"shebang",
)
load("//foreign_cc/private/framework:platform.bzl", "PLATFORM_CONSTRAINTS_RULE_ATTRIBUTES")
load(
":cc_toolchain_util.bzl",
"LibrariesToLinkInfo",
Expand Down Expand Up @@ -209,8 +210,6 @@ CC_EXTERNAL_RULE_ATTRIBUTES = {
cfg = "exec",
default = [],
),
"_aarch64_constraint": attr.label(default = Label("@platforms//cpu:aarch64")),
"_android_constraint": attr.label(default = Label("@platforms//os:android")),
# we need to declare this attribute to access cc_toolchain
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
Expand All @@ -220,10 +219,11 @@ CC_EXTERNAL_RULE_ATTRIBUTES = {
cfg = "exec",
default = Label("@rules_foreign_cc//foreign_cc/private/framework:platform_info"),
),
"_linux_constraint": attr.label(default = Label("@platforms//os:linux")),
"_x86_64_constraint": attr.label(default = Label("@platforms//cpu:x86_64")),
}

# this would be cleaner as x | y, but that's not supported in bazel 5.4.0
CC_EXTERNAL_RULE_ATTRIBUTES.update(PLATFORM_CONSTRAINTS_RULE_ATTRIBUTES)

# A list of common fragments required by rules using this framework
CC_EXTERNAL_RULE_FRAGMENTS = [
"apple",
Expand Down
Loading

0 comments on commit 920c1d6

Please sign in to comment.