Browse Source
Despite meson officially "supporting" Rust it does support working with Cargo (Rust package manager and build system) so we need to have a bit of custom system for using it. `cargo-output.py` to build and copy the output files (static archive and depfile) to the expected location by meson. And `cargo-rustc-static-libs.py` to get the common linker args for a bar-bone std rust program (ie without dependencies). Those two scripts would potentially be removed if meson and/or cargo became more flexible and/or intelligent.pull/169/head
committed by
Steve Lhomme
5 changed files with 334 additions and 0 deletions
@ -0,0 +1,80 @@ |
|||
#!/usr/bin/env python3 |
|||
# SPDX-License-Identifier: LGPL-2.1-or-later |
|||
# Copyright (C) 2022 Loïc Branstett <loic@videolabs.io> |
|||
# |
|||
# This program is free software; you can redistribute it and/or modify it |
|||
# under the terms of the GNU Lesser General Public License as published by |
|||
# the Free Software Foundation; either version 2.1 of the License, or |
|||
# (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Lesser General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Lesser General Public License |
|||
# along with this program; if not, write to the Free Software Foundation, |
|||
# Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
|||
|
|||
|
|||
# This is a wrapper/interceptor script for Cargo (the Rust package manager) that adds |
|||
# the ability to specify an output directory for the final compiler artifact |
|||
# (archive lib, depfile). |
|||
# |
|||
# Usage: ./buildsystem/cargo-output.py --output=out/ --depfile NORMAL_CARGO_INVOCATION |
|||
# Usage: ./buildsystem/cargo-output.py --output=out/ --depfile /usr/bin/cargo |
|||
# --target=x86_64-unknown-linux-gnu rustc --crate-type=staticlib |
|||
# |
|||
# The resulting static library will be put in the output directory as well as its depfile |
|||
# if asked (--depfile) and available |
|||
|
|||
import os, sys, json, pathlib, shutil, subprocess, argparse |
|||
|
|||
def dir_path(string): |
|||
if os.path.isdir(string): |
|||
return string |
|||
else: |
|||
raise NotADirectoryError(string) |
|||
|
|||
parser = argparse.ArgumentParser() |
|||
|
|||
parser.add_argument("--depfile", action="store_true") |
|||
parser.add_argument("-o", "--output", type=dir_path) |
|||
parser.add_argument("cargo_cmds", nargs=argparse.REMAINDER) |
|||
|
|||
args = parser.parse_args() |
|||
|
|||
cargo_argv = args.cargo_cmds |
|||
|
|||
# Insert Cargo argument `--message-format=json-render-diagnostics` |
|||
# before a `--` (if there are any) to still be in Cargo arguments |
|||
# and not in the inner thing (rustc, ...) |
|||
cargo_argv.insert( |
|||
cargo_argv.index('--') if '--' in cargo_argv else len(cargo_argv), |
|||
"--message-format=json-render-diagnostics" |
|||
) |
|||
|
|||
# Execute the cargo build and redirect stdout (and not stderr) |
|||
cargo_r = subprocess.run(cargo_argv, stdout=subprocess.PIPE) |
|||
|
|||
# We don't use `check=True` in the above `run` method call because it |
|||
# raise an execption and outputing a python traceback isn't useful at all |
|||
if cargo_r.returncode != 0: |
|||
sys.exit(cargo_r.returncode) |
|||
|
|||
# Get the jsons output |
|||
cargo_stdout = cargo_r.stdout.decode('utf-8') |
|||
cargo_jsons = [json.loads(line) for line in cargo_stdout.splitlines()] |
|||
|
|||
# We are only interrested in the final artifact (ie the output, not it's deps) |
|||
last_compiler_artifact = next( |
|||
j for j in reversed(cargo_jsons) if j["reason"] == "compiler-artifact") |
|||
|
|||
# We only take the first one, because the other one are just aliases and thus |
|||
# are not relevant for us |
|||
first_compiler_artifact_filename = last_compiler_artifact["filenames"][0] |
|||
|
|||
for filename in [first_compiler_artifact_filename]: |
|||
shutil.copy2(filename, args.output) |
|||
if args.depfile: |
|||
shutil.copy2(pathlib.Path(filename).with_suffix(".d"), args.output) |
|||
@ -0,0 +1,83 @@ |
|||
#!/usr/bin/env python3 |
|||
# SPDX-License-Identifier: LGPL-2.1-or-later |
|||
# Copyright (C) 2022 Loïc Branstett <loic@videolabs.io> |
|||
# |
|||
# This program is free software; you can redistribute it and/or modify it |
|||
# under the terms of the GNU Lesser General Public License as published by |
|||
# the Free Software Foundation; either version 2.1 of the License, or |
|||
# (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Lesser General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Lesser General Public License |
|||
# along with this program; if not, write to the Free Software Foundation, |
|||
# Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
|||
|
|||
|
|||
# This script is meant to find the required native libs of an empty Rust crate |
|||
# compiled as a static lib. |
|||
# |
|||
# Usage: ./buildsystem/cargo-rustc-static-libs.py /usr/bin/cargo |
|||
# Usage: ./buildsystem/cargo-rustc-static-libs.py /usr/bin/cargo --target=x86_64-unknown-linux-gnu |
|||
# |
|||
# The result is then printed to the standard output. |
|||
|
|||
import os, sys, json, subprocess, tempfile, argparse |
|||
|
|||
NATIVE_STATIC_LIBS="native-static-libs" |
|||
|
|||
parser = argparse.ArgumentParser() |
|||
parser.add_argument("cargo_cmds", nargs=argparse.REMAINDER) |
|||
|
|||
args = parser.parse_args() |
|||
|
|||
cargo_argv = args.cargo_cmds |
|||
cargo_argv.append("rustc") |
|||
cargo_argv.append("--message-format=json") |
|||
cargo_argv.append("--crate-type=staticlib") |
|||
cargo_argv.append("--quiet") |
|||
cargo_argv.append("--") |
|||
cargo_argv.append("--print=native-static-libs") |
|||
|
|||
with tempfile.TemporaryDirectory() as tmpdir: |
|||
os.chdir(tmpdir) |
|||
|
|||
with open("Cargo.toml", "w") as cargo_toml: |
|||
cargo_toml.write(""" |
|||
[package] |
|||
name = "native-static-libs" |
|||
version = "0.0.0" |
|||
|
|||
[lib] |
|||
path = "lib.rs" |
|||
""") |
|||
|
|||
with open("lib.rs", "w") as lib_rs: |
|||
lib_rs.write("#![allow(dead_code)] fn main(){}") |
|||
|
|||
# Execute the cargo build and redirect stdout (and not stderr) |
|||
cargo_r = subprocess.run(cargo_argv, stdout=subprocess.PIPE) |
|||
|
|||
# We don't use `check=True in run because it raise an execption |
|||
# and outputing a python traceback isn't useful at all. |
|||
# |
|||
# We also exit here so that the output o tmp dir is not cleared when |
|||
# there is an error. |
|||
if cargo_r.returncode != 0: |
|||
print("command: {cargo_argv}", file=sys.stderr) |
|||
print("cwd: {tmpdir}", file=sys.stderr) |
|||
sys.exit(cargo_r.returncode) |
|||
|
|||
# Get the jsons output |
|||
cargo_stdout = cargo_r.stdout.decode('utf-8') |
|||
cargo_jsons = [json.loads(line) for line in cargo_stdout.splitlines()] |
|||
|
|||
# Print the last message with a `NATIVE_STATIC_LIBS` message |
|||
for j in reversed(cargo_jsons): |
|||
if j["reason"] == "compiler-message": |
|||
msg = j["message"]["message"] |
|||
if msg.startswith(NATIVE_STATIC_LIBS): |
|||
print(msg[len(NATIVE_STATIC_LIBS + ": "):]) |
|||
Loading…
Reference in new issue