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
679 stars 249 forks source link

Meson lacks support for cross compilation #1222

Open allsey87 opened 4 months ago

allsey87 commented 4 months ago

Meson support was merged in #986, but appears to not have support for cross compilation. I am concluding this from a use case where I am trying to cross compile using the Emscripten compiler. For this to work, a cross file should be provided to meson setup, however there is no logic for passing cross file as can be seen here:

https://github.com/bazelbuild/rules_foreign_cc/blob/9d5727d5e51bf1be8423dff7996bdb4d847b47e6/foreign_cc/meson.bzl#L113-L119

I think this should be solved by generating a cross file for Meson mirroring what is done for the CMake toolchain file here:

https://github.com/bazelbuild/rules_foreign_cc/blob/9d5727d5e51bf1be8423dff7996bdb4d847b47e6/foreign_cc/private/cmake_script.bzl#L197-L230

What do you think @jheaff1, @jsharpe, and @edison-moreland?

jsharpe commented 4 months ago

Very happy to accept a PR that adds support for cross-compilation for meson.

allsey87 commented 4 months ago

If we can move quickly, I can look into that but let's start with #1223

bbatliner-ocient commented 3 months ago

Chiming in with the bare minimum cross-compilation support that appeared to work for me:

diff --git a/foreign_cc/meson.bzl b/foreign_cc/meson.bzl
index 9d4179a..ea25bf2 100644
--- a/foreign_cc/meson.bzl
+++ b/foreign_cc/meson.bzl
@@ -68,8 +68,17 @@ def _create_meson_script(configureParameters):
     inputs = configureParameters.inputs

     tools = get_tools_info(ctx)
+    flags = get_flags_info(ctx)
     script = pkgconfig_script(inputs.ext_build_dirs)

+    # write cross file
+    script.append("cat > crosstool_bazel.txt << EOF")
+    script.append("[binaries]")
+    script.append("c = '{}'".format(_absolutize(ctx.workspace_name, tools.cc)))
+    script.append("cpp = '{}'".format(_absolutize(ctx.workspace_name, tools.cxx)))
+    script.append("EOF")
+    script.append("")
+
     # CFLAGS and CXXFLAGS are also set in foreign_cc/private/cmake_script.bzl, so that meson
     # can use the intended tools.
     # However, they are split by meson on whitespace. For Windows it's common to have spaces in path
@@ -91,7 +100,6 @@ def _create_meson_script(configureParameters):
     if cxxopts:
         script.append("##export_var## CXXFLAGS \"{} ${{CXXFLAGS:-}}\"".format(" ".join(cxxopts).replace("\"", "'")))

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

@@ -112,7 +120,7 @@ def _create_meson_script(configureParameters):

     setup_args_str = " ".join(expand_locations_and_make_variables(ctx, ctx.attr.setup_args, "setup_args", data))

-    script.append("{prefix}{meson} setup --prefix={install_dir} {setup_args} {options} {source_dir}".format(
+    script.append("{prefix}{meson} setup --cross-file crosstool_bazel.txt --prefix={install_dir} {setup_args} {options} {source_dir}".format(
         prefix = prefix,
         meson = attrs.meson_path,
         install_dir = "$$INSTALLDIR$$",

Unconditionally writing this file and passing --cross-file with either a native c and cpp binary, or a cross-compiling c and cpp binary, appeared to be everything Meson needed to build with various --platforms.

I recognize that this has some ways to go before claiming support, but wanted to get discussion going.


Following up, that patch worked for me to compile one library, but failed on a different library. It's evidently not a complete solution.

allsey87 commented 3 months ago

I am using Meson for cross compilation to WebAssembly via Emscripten and it seems to work pretty well for most things now. I am just passing a hardcoded --cross-file via setup_args for the moment which I took from the NumPy project:

[binaries]
exe_wrapper = 'node' # run webassembly inside of node
pkg-config = 'pkg-config'

[properties]
needs_exe_wrapper = true
skip_sanity_check = true
longdouble_format = 'IEEE_QUAD_LE' # for numpy

[host_machine]
system = 'emscripten'
cpu_family = 'wasm32'
cpu = 'wasm'
endian = 'little'

Notably, I do not set c or cpp under binaries. I am using platforms and a custom toolchain which I believe sets the CC and CXX environment variables which Meson picks up automatically.

Disclaimer: I have only been using Bazel for a couple months

mering commented 1 month ago

@bbatliner-ocient you might want to include the ar and strip tools in your patch.

For ar you can use:

script.append("ar = '{}'".format(_absolutize(ctx.workspace_name, tools.cxx_linker_static)))

For strip one actually has to add the following into CxxToolsInfo in cc_toolchain_util.bzl:

strip = cc_common.get_tool_for_action(
    feature_configuration = feature_configuration,
    action_name = ACTION_NAMES.strip,
),

Note: meson also support using the same file as --native-file, so it might be acceptable to always generate this file and just change the flag how this file is passed to meson.