Skip to content
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
46 changes: 46 additions & 0 deletions examples/meson_simple/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
load("@rules_cc//cc:defs.bzl", "cc_test")
load("@rules_foreign_cc//foreign_cc:defs.bzl", "meson")
load("@rules_shell//shell:sh_test.bzl", "sh_test")

meson(
name = "meson_lib",
build_data = ["//meson_simple/code:clang_wrapper.sh"],
env = select({
"//:windows": {
"CLANG_WRAPPER": "$(execpath //meson_simple/code:clang_wrapper.sh)",
"CXX_FLAGS": "/MD",
},
"//conditions:default": {
"CLANG_WRAPPER": "$(execpath //meson_simple/code:clang_wrapper.sh)",
"CXX_FLAGS": "-fPIC",
},
}),
lib_source = "//meson_simple/code:srcs",
out_static_libs = ["liba.a"],
)

cc_test(
name = "test_lib",
srcs = [
"test_libb.cpp",
],
deps = [
":meson_lib",
],
)

meson(
name = "meson_lib-introspect",
lib_source = "//meson_simple/code:srcs",
out_data_files = ["introspect.json"],
out_include_dir = "",
targets = ["introspect"],
)

sh_test(
name = "test_introspect",
srcs = ["test_introspect.sh"],
args = ["$(location meson_lib-introspect)"],
data = [":meson_lib-introspect"],
deps = ["@bazel_tools//tools/bash/runfiles"],
)
11 changes: 11 additions & 0 deletions examples/meson_simple/code/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
exports_files(["clang_wrapper.sh"])

filegroup(
name = "srcs",
srcs = [
"liba.cpp",
"liba.h",
"meson.build",
],
visibility = ["//meson_simple:__subpackages__"],
)
11 changes: 11 additions & 0 deletions examples/meson_simple/code/clang_wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash

set -o errexit
set -o nounset

if [[ $(uname) == *"NT"* ]]; then
# If Windows
exec clang-cl "$@"
else
exec clang "$@"
fi
3 changes: 3 additions & 0 deletions examples/meson_simple/code/liba.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "liba.h"

std::string hello_liba(void) { return "Hello from LIBA!"; }
10 changes: 10 additions & 0 deletions examples/meson_simple/code/liba.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef LIBA_H_
#define LIBA_H_ (1)

#include <stdio.h>

#include <string>

std::string hello_liba(void);

#endif
16 changes: 16 additions & 0 deletions examples/meson_simple/code/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
project('liba', 'cpp')

builddir = 'rules_foreign_cc_build'

cxx = meson.get_compiler('cpp')

liba = static_library(
'a',
'liba.cpp',
cpp_args: cxx.get_supported_arguments(),
include_directories: include_directories('.'),
install: true,
install_dir: join_paths(get_option('prefix'), 'lib'),
)

install_headers('liba.h', subdir: 'include')
30 changes: 30 additions & 0 deletions examples/meson_simple/test_introspect.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash

# --- begin runfiles.bash initialization ---
# The runfiles library itself defines rlocation which you would need to look
# up the library's runtime location, thus we have a chicken-and-egg problem.
#
# Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash).
set -euo pipefail
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
"$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
else
echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
exit 1
fi
# --- end runfiles.bash initialization ---

[[ -f $(rlocation $TEST_WORKSPACE/$1) ]] && exit 0
exit 1
13 changes: 13 additions & 0 deletions examples/meson_simple/test_libb.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <iostream>
#include <stdexcept>
#include <string>

#include "include/liba.h"

int main(int argc, char* argv[]) {
std::string result = hello_liba();
if (result != "Hello from LIBA!") {
throw std::runtime_error("Wrong result: " + result);
}
std::cout << "Everything's fine!";
}
140 changes: 100 additions & 40 deletions foreign_cc/meson.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -99,46 +99,98 @@ def _create_meson_script(configureParameters):
root = detect_root(ctx.attr.lib_source)
data = ctx.attr.data + ctx.attr.build_data

# Generate a list of arguments for meson
options_str = " ".join([
"-D{}=\"{}\"".format(key, ctx.attr.options[key])
for key in ctx.attr.options
])
if attrs.tool_prefix:
tool_prefix = "{} ".format(
expand_locations_and_make_variables(ctx, attrs.tool_prefix, "tool_prefix", data),
)
else:
tool_prefix = ""

meson_path = "{tool_prefix}{meson_path}".format(
tool_prefix = tool_prefix,
meson_path = attrs.meson_path,
)

prefix = "{} ".format(expand_locations_and_make_variables(ctx, attrs.tool_prefix, "tool_prefix", data)) if attrs.tool_prefix else ""
target_args = dict(ctx.attr.target_args)

setup_args_str = " ".join(expand_locations_and_make_variables(ctx, ctx.attr.setup_args, "setup_args", data))
# --- TODO: DEPRECATED, delete on a future release ------------------------
# Convert the deprecated arguments into the new target_args argument. Fail
# if there's a deprecated argument being used together with its new
# target_args (e.g. setup_args and a "setup" target_args).

script.append("{prefix}{meson} setup --prefix={install_dir} {setup_args} {options} {source_dir}".format(
prefix = prefix,
meson = attrs.meson_path,
install_dir = "$$INSTALLDIR$$",
setup_args = setup_args_str,
options = options_str,
source_dir = "$$EXT_BUILD_ROOT$$/" + root,
))
deprecated = [
("setup", ctx.attr.setup_args),
("compile", ctx.attr.build_args),
("install", ctx.attr.install_args),
]

for target_name, args_ in deprecated:
if args_ and target_name in target_args:
fail("Please migrate '{t}_args' to 'target_args[\"{t}\"]'".format(t = target_name))

target_args[target_name] = args_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from my testing, this will override any values I currently have set in target_args

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created #1444

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right the code is wrong, but see my comments in the PR.


# --- TODO: DEPRECATED, delete on a future release ------------------------

build_args = [] + ctx.attr.build_args
build_args_str = " ".join([
ctx.expand_location(arg, data)
for arg in build_args
])
# Expand target args
for target_name, args_ in target_args.items():
if target_name == "setup":
args = expand_locations_and_make_variables(ctx, args_, "setup_args", data)
else:
args = [ctx.expand_location(arg, data) for arg in args_]

script.append("{prefix}{meson} compile {args}".format(
prefix = prefix,
meson = attrs.meson_path,
args = build_args_str,
target_args[target_name] = args

script.append("{meson} setup --prefix={install_dir} {setup_args} {options} {source_dir}".format(
meson = meson_path,
install_dir = "$$INSTALLDIR$$",
setup_args = " ".join(target_args.get("setup", [])),
options = " ".join([
"-D{}=\"{}\"".format(key, ctx.attr.options[key])
for key in ctx.attr.options
]),
source_dir = "$$EXT_BUILD_ROOT$$/" + root,
))

if ctx.attr.install:
install_args = " ".join([
ctx.expand_location(arg, data)
for arg in ctx.attr.install_args
])
script.append("{prefix}{meson} install {args}".format(
prefix = prefix,
meson = attrs.meson_path,
args = install_args,
targets = ctx.attr.targets

# --- TODO: DEPRECATED, delete on a future release ------------------------
targets = [
t
for t in targets
if t != "install" or ctx.attr.install
]
# --- TODO: DEPRECATED, delete on a future release ------------------------

# NOTE:
# introspect has an "old API" and doesn't work like other commands.
# It requires a builddir argument and it doesn't have a flag to output to a
# file, so it requires a redirect. And, most probably, it will remain like
# this for the foreseable future (see
# https://github.com/mesonbuild/meson/issues/8182#issuecomment-758183324).
#
# To keep things simple, we provide a basic API: users must supply the
# introspection JSON file in `out_data_files`, and we offer a sensible
# default for the introspect command that users can override if needed.
if "introspect" in targets:
if len(ctx.attr.out_data_files) != 1:
msg = "Meson introspect expects a single JSON filename via "
msg += "out_data_files; only one filename should be provided."
fail(msg)

introspect_file = ctx.attr.out_data_files[0]

introspect_args = ["$$BUILD_TMPDIR$$"]
introspect_args += target_args.get("introspect", ["--all", "--indent"])
introspect_args += [">", "$$INSTALLDIR$$/{}".format(introspect_file)]

target_args["introspect"] = introspect_args

for target_name in targets:
script.append("{meson} {target} {args}".format(
meson = meson_path,
target = target_name,
args = " ".join(target_args.get(target_name, [])),
))

return script
Expand All @@ -153,26 +205,34 @@ def _attrs():

attrs.update({
"build_args": attr.string_list(
doc = "Arguments for the Meson build command",
doc = "__deprecated__: please use `target_args` with `'build'` target key.",
mandatory = False,
),
"install": attr.bool(
doc = "If True, the `meson install` comand will be performed after a build",
doc = "__deprecated__: please use `targets` if you want to skip install.",
default = True,
),
"install_args": attr.string_list(
doc = "Arguments for the meson install command",
doc = "__deprecated__: please use `target_args` with `'install'` target key.",
mandatory = False,
),
"options": attr.string_dict(
doc = (
"Meson option entries to initialize (they will be passed with `-Dkey=value`)"
),
doc = "Meson `setup` options (converted to `-Dkey=value`)",
mandatory = False,
default = {},
),
"setup_args": attr.string_list(
doc = "Arguments for the Meson setup command",
doc = "__deprecated__: please use `target_args` with `'setup'` target key.",
mandatory = False,
),
"target_args": attr.string_list_dict(
doc = "Dict of arguments for each of the Meson targets. The " +
"target name is the key and the list of args is the value.",
mandatory = False,
),
"targets": attr.string_list(
doc = "A list of targets to run. Defaults to ['compile', 'install']",
default = ["compile", "install"],
mandatory = False,
),
})
Expand Down
Loading