gst-plugins-rs/cargo_wrapper.py
Nirbheek Chauhan a3d405f670 meson: Add options for all plugins
Required a slight rework of the build file, and how options are passed
to cargo_wrapper.py

Necessitated a bump of the required gstreamer version to 1.20, which
should be fine for the meson build since its primary function is to be
built as part of the gstreamer monorepo build to get a dev env.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1028>
2022-12-28 22:30:11 +05:30

168 lines
5.9 KiB
Python

#!/usr/bin/env python3
import hashlib
import re
import glob
import os
import shutil
import subprocess
import sys
from argparse import ArgumentParser
from pathlib import Path as P
PARSER = ArgumentParser()
PARSER.add_argument('command', choices=['build', 'test'])
PARSER.add_argument('build_dir', type=P)
PARSER.add_argument('src_dir', type=P)
PARSER.add_argument('root_dir', type=P)
PARSER.add_argument('target', choices=['release', 'debug'])
PARSER.add_argument('prefix', type=P)
PARSER.add_argument('libdir', type=P)
PARSER.add_argument('--version', default=None)
PARSER.add_argument('--bin', default=None, type=P)
PARSER.add_argument('--packages', nargs="+", default=[])
PARSER.add_argument('--lib-suffixes', nargs="+", default=[])
PARSER.add_argument('--exe-suffix')
PARSER.add_argument('--depfile')
PARSER.add_argument('--disable-doc', action="store_true", default=False)
def generate_depfile_for(fpath):
file_stem = fpath.parent / fpath.stem
depfile_content = ""
with open(f"{file_stem}.d", 'r') as depfile:
for l in depfile.readlines():
if l.startswith(str(file_stem)):
# We can't blindly split on `:` because on Windows that's part
# of the drive letter. Lucky for us, the format of the dep file
# is one of:
#
# /path/to/output: /path/to/src1 /path/to/src2
# /path/to/output:
#
# So we parse these two cases specifically
if l.endswith(':'):
output = l[:-1]
srcs = ''
else:
output, srcs = l.split(": ", maxsplit=2)
all_deps = []
for src in srcs.split(" "):
all_deps.append(src)
src = P(src)
if src.name == 'lib.rs':
# `rustc` doesn't take `Cargo.toml` into account
# but we need to
cargo_toml = src.parent.parent / 'Cargo.toml'
if cargo_toml.exists():
all_deps.append(str(cargo_toml))
depfile_content += f"{output}: {' '.join(all_deps)}\n"
return depfile_content
if __name__ == "__main__":
opts = PARSER.parse_args()
logfile = open(opts.root_dir / 'meson-logs' /
f'{opts.src_dir.name}-cargo-wrapper.log', 'w')
print(opts, file=logfile)
cargo_target_dir = opts.build_dir / 'target'
env = os.environ.copy()
if 'PKG_CONFIG_PATH' in env:
pkg_config_path = env['PKG_CONFIG_PATH'].split(os.pathsep)
else:
pkg_config_path = []
pkg_config_path.append(str(opts.root_dir / 'meson-uninstalled'))
env['PKG_CONFIG_PATH'] = os.pathsep.join(pkg_config_path)
if opts.command == 'build':
cargo_cmd = ['cargo']
if opts.bin:
cargo_cmd += ['build']
else:
cargo_cmd += ['cbuild']
if not opts.disable_doc:
cargo_cmd += ['--features', "doc"]
if opts.target == 'release':
cargo_cmd.append('--release')
elif opts.command == 'test':
# cargo test
cargo_cmd = ['cargo', 'ctest', '--no-fail-fast', '--color=always']
else:
print("Unknown command:", opts.command, file=logfile)
sys.exit(1)
cwd = None
cargo_cmd += ['--target-dir', cargo_target_dir]
if not opts.bin:
cargo_cmd.extend(['--manifest-path', opts.src_dir / 'Cargo.toml'])
cargo_cmd.extend(['--prefix', opts.prefix, '--libdir',
opts.prefix / opts.libdir])
for p in opts.packages:
cargo_cmd.extend(['-p', p])
else:
cargo_cmd.extend(['--bin', opts.bin.name])
cwd = opts.src_dir
def run(cargo_cmd, env, cwd=cwd):
try:
subprocess.run(cargo_cmd, env=env, check=True, cwd=cwd)
except subprocess.SubprocessError:
sys.exit(1)
run(cargo_cmd, env, cwd)
if opts.command == 'build':
target_dir = cargo_target_dir / '**' / opts.target
if opts.bin:
exe = glob.glob(str(target_dir / opts.bin) + opts.exe_suffix, recursive=True)[0]
shutil.copy2(exe, opts.build_dir)
depfile_content = generate_depfile_for(P(exe))
else:
# Copy so files to build dir
depfile_content = ""
for suffix in opts.lib_suffixes:
for f in glob.glob(str(target_dir / f'*.{suffix}'), recursive=True):
libfile = P(f)
depfile_content += generate_depfile_for(libfile)
copied_file = (opts.build_dir / libfile.name)
try:
if copied_file.stat().st_mtime == libfile.stat().st_mtime:
print(f"{copied_file} has not changed.", file=logfile)
continue
except FileNotFoundError:
pass
print(f"Copying {copied_file}", file=logfile)
shutil.copy2(f, opts.build_dir)
with open(opts.depfile, 'w') as depfile:
depfile.write(depfile_content)
# Copy generated pkg-config files
for f in glob.glob(str(target_dir / '*.pc'), recursive=True):
shutil.copy(f, opts.build_dir)
# Move -uninstalled.pc to meson-uninstalled
uninstalled = opts.build_dir / 'meson-uninstalled'
os.makedirs(uninstalled, exist_ok=True)
for f in opts.build_dir.glob('*-uninstalled.pc'):
# move() does not allow us to update the file so remove it if it already exists
dest = uninstalled / P(f).name
if dest.exists():
dest.unlink()
# move() takes paths from Python3.9 on
if ((sys.version_info.major >= 3) and (sys.version_info.minor >= 9)):
shutil.move(f, uninstalled)
else:
shutil.move(str(f), str(uninstalled))