bazel-contrib / rules_foreign_cc

Build rules for interfacing with "foreign" (non-Bazel) build systems (CMake, configure-make, GNU Make, boost, ninja, Meson)
https://bazel-contrib.github.io/rules_foreign_cc
Apache License 2.0
668 stars 246 forks source link

`configure_make()` and `meson()` don't work with hermetic toolchain #1296

Open mering opened 3 weeks ago

mering commented 3 weeks ago

See #1295 for a reproduction example.

Both configure() and meson() don't seem to detect the hermetic toolchain and fail with errors like C compiler cannot create executables.

untimtam commented 3 weeks ago

Relevant for meson: https://github.com/bazel-contrib/rules_foreign_cc/issues/1222

filmil commented 2 weeks ago

Seeing similar issues (apparently) at https://github.com/filmil/bazel_delib

voxeljorge commented 1 week ago

Not all configure based applications fail, I'm able to build some. FFmpeg is an unusual example because they've explicitly decided to ignore CC CFLAGS etc, which is how foreign_cc sets these parameters.

For meson I've found that my issue shows errors like this in the log:

Sanity check compile stderr:
ld.lld: error: cannot open Scrt1.o: No such file or directory
ld.lld: error: cannot open crti.o: No such file or directory
ld.lld: error: unable to find library -lm
ld.lld: error: unable to find library -lpthread
ld.lld: error: unable to find library -ldl
ld.lld: error: unable to find library -lc
ld.lld: error: cannot open crtn.o: No such file or directory
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I have an llvm toolchain configured with a sysroot, and my best guess is that because my sysroot is being passed with a relative path (instead of absolute) meson commands fail to find it. Here's an example command:

/home/jorge/.cache/bazel/_bazel_jorge/576ee54cf2522471c5c073f98825487b/sandbox/linux-sandbox/22/execroot/_main/external/toolchains_llvm~~llvm~llvm_toolchain/bin/cc_wrapper.sh'
    sanitycheckc.c
    -o
    sanitycheckc.exe
    '--sysroot=/home/jorge/.cache/bazel/_bazel_jorge/576ee54cf2522471c5c073f98825487b/sandbox/linux-sandbox/22/execroot/_main/external/_main~_repo_rules~ubuntu_20_04_sysroot'
    -D_FILE_OFFSET_BITS=64
    -Wl,-S
    --target=x86_64-unknown-linux-gnu
    -lm
    -no-canonical-prefixes
    -fuse-ld=lld
    -Wl,--build-id=md5
    -Wl,--hash-style=gnu
    -Wl,-z,relro,-z,now
    -l:libc++.a
    -l:libc++abi.a
    -l:libunwind.a
    -lpthread
    -ldl
    -rtlib=compiler-rt
    '--sysroot=external/_main~_repo_rules~ubuntu_20_04_sysroot/

I tried hardcoding an absolute sysroot with a CFLAGS env but unfortunately the parameters are not ordered correctly and the relative one takes precedence.

voxeljorge commented 1 week ago

I can confirm that at least in my case the issue comes from having a relative sysroot, the following patch resolves my build issue:

diff --git a/foreign_cc/meson.bzl b/foreign_cc/meson.bzl
index 9d4179a..e39886a 100644
--- a/foreign_cc/meson.bzl
+++ b/foreign_cc/meson.bzl
@@ -54,6 +54,15 @@ def _meson_impl(ctx):
     )
     return cc_external_rule_impl(ctx, attrs)

+def _absolutize_sysroot_flag(workspace_name, flags):
+    fixed_flags = []
+    for flag in flags:
+        if not flag.startswith("--sysroot="):
+            fixed_flags.append(flag)
+            continue
+        fixed_flags.append("--sysroot="+_absolutize(workspace_name, flag.lstrip("--sysroot=")))
+    return fixed_flags
+
 def _create_meson_script(configureParameters):
     """Creates the bash commands for invoking commands to build meson projects

@@ -86,6 +95,9 @@ def _create_meson_script(configureParameters):
     copts = (ctx.fragments.cpp.copts + ctx.fragments.cpp.conlyopts + getattr(ctx.attr, "copts", [])) or []
     cxxopts = (ctx.fragments.cpp.copts + ctx.fragments.cpp.cxxopts + getattr(ctx.attr, "copts", [])) or []

+    copts = _absolutize_sysroot_flag(ctx.workspace_name, copts)
+    cxxopts = _absolutize_sysroot_flag(ctx.workspace_name, cxxopts)
+
     if copts:
         script.append("##export_var## CFLAGS \"{} ${{CFLAGS:-}}\"".format(" ".join(copts).replace("\"", "'")))
     if cxxopts:
@@ -93,7 +105,8 @@ def _create_meson_script(configureParameters):

     flags = get_flags_info(ctx)
     if flags.cxx_linker_executable:
-        script.append("##export_var## LDFLAGS \"{} ${{LDFLAGS:-}}\"".format(" ".join(flags.cxx_linker_executable).replace("\"", "'")))
+        ldflags = _absolutize_sysroot_flag(ctx.workspace_name, flags.cxx_linker_executable)
+        script.append("##export_var## LDFLAGS \"{} ${{LDFLAGS:-}}\"".format(" ".join(ldflags).replace("\"", "'")))

     script.append("##export_var## CMAKE {}".format(attrs.cmake_path))
     script.append("##export_var## NINJA {}".format(attrs.ninja_path))
mering commented 1 week ago

@voxeljorge I created #1303 to solve the issue with the relative sysroot similar to what is done for other foreign tools.

voxeljorge commented 6 days ago

@mering I can confirm that your PR fixes my build as well. I am not partial to the fix but I definitely would like to see one merged in