build: cargo entrypoint II
This is a second attempt at https://gerrit.lix.systems/c/lix/+/5516
instead of letting meson try to be cargo we'll just have cargo at home.
this requires some contortions to link everything together due to quite
a few meson deficiencies, but at the end we get to pretend that rust is
just c++ painted orange. we'll use cxx to bring real interop back soon.
also fixes #1230
also reverts 10845bfe63
co-authored-by: eldritch horrors <pennae@lix.systems>
Change-Id: Ib1fda843fa80d818705d5a65ec9054216a6a6964
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
[target.'cfg(true)']
|
||||
rustflags = [
|
||||
# rustc will pass `-nodefaultlibs` without this, but we need the C++ standard library.
|
||||
'-Cdefault-linker-libraries=yes',
|
||||
]
|
||||
|
||||
[target.'cfg(target_env = "musl")']
|
||||
rustflags = [
|
||||
'-Cdefault-linker-libraries=yes',
|
||||
# musl, at least in Nixpkgs, is not compiled with -fPIE.
|
||||
# XXX: nevermind? as of Nixpkgs 26.05??
|
||||
# Oh gods do we need to gate this??
|
||||
#'-Crelocation-model=static',
|
||||
]
|
||||
Generated
+7
@@ -30,6 +30,13 @@ version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "lix"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"lix-doc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lix-doc"
|
||||
version = "0.0.1"
|
||||
|
||||
+12
-1
@@ -1,6 +1,17 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["lix/lix-doc"]
|
||||
members = [
|
||||
"lix/lix-doc",
|
||||
"lix/lix-rs",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 1
|
||||
|
||||
[profile.release]
|
||||
debug = "full"
|
||||
debug-assertions = true
|
||||
overflow-checks = true
|
||||
|
||||
@@ -261,6 +261,7 @@ archive_setting_definitions = files(
|
||||
'archive-settings/use-case-hack.md',
|
||||
)
|
||||
liblix_generated_headers += custom_target(
|
||||
'archive-settings.gen.inc',
|
||||
command : [
|
||||
python.full_path(),
|
||||
'@SOURCE_ROOT@/lix/code-generation/build_settings.py',
|
||||
@@ -278,6 +279,7 @@ feature_setting_definitions = files(
|
||||
'feature-settings/experimental-features.md',
|
||||
)
|
||||
liblix_generated_headers += custom_target(
|
||||
'feature-settings.gen.inc',
|
||||
command : [
|
||||
python.full_path(),
|
||||
'@SOURCE_ROOT@/lix/code-generation/build_settings.py',
|
||||
@@ -299,6 +301,7 @@ logging_setting_definitions = files(
|
||||
# keep-sorted end
|
||||
)
|
||||
liblix_generated_headers += custom_target(
|
||||
'logging-settings.gen.inc',
|
||||
command : [
|
||||
python.full_path(),
|
||||
'@SOURCE_ROOT@/lix/code-generation/build_settings.py',
|
||||
|
||||
+1
-1
@@ -7,4 +7,4 @@ Description: Lix Package Manager (base include dir)
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: kj-async
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -lrust_monocrate
|
||||
Libs: -L${libdir}
|
||||
|
||||
+4
-35
@@ -1,36 +1,5 @@
|
||||
rnix = dependency('rnix-0.12-rs')
|
||||
rowan = dependency('rowan-0.15-rs')
|
||||
|
||||
rust = import('rust')
|
||||
|
||||
# This hack is required by the wombo combo of meson bugs:
|
||||
# Meson does not set the soname for us: https://github.com/mesonbuild/meson/issues/13537
|
||||
# Meson ignores link_args for Rust targets: https://github.com/mesonbuild/meson/issues/13538
|
||||
lix_doc_rust_args = [
|
||||
# link-arg=-soname has no effect when building a static lib,
|
||||
# since the linker is never actually invoked.
|
||||
'-C', f'link-arg=-Wl,@soname_arg@,liblix_doc.@dylib_suffix@',
|
||||
]
|
||||
|
||||
lix_doc = static_library(
|
||||
'lix_doc',
|
||||
sources : files('src/lib.rs'),
|
||||
dependencies : [
|
||||
rowan,
|
||||
rnix,
|
||||
],
|
||||
rust_args : [
|
||||
lix_doc_rust_args,
|
||||
],
|
||||
)
|
||||
|
||||
# NOTE: this dependency object is only used for `rust_monocrate`
|
||||
liblix_doc_internal = declare_dependency(
|
||||
link_with : lix_doc,
|
||||
)
|
||||
|
||||
rust.test(
|
||||
'lix_doc_test',
|
||||
lix_doc,
|
||||
suite : 'check'
|
||||
lix_rs_files += files(
|
||||
'Cargo.toml',
|
||||
'src/lib.rs',
|
||||
'src/pprint.rs',
|
||||
)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "lix"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "lixrs"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
lix-doc.path = "../lix-doc"
|
||||
@@ -0,0 +1,4 @@
|
||||
lix_rs_files += files(
|
||||
'Cargo.toml',
|
||||
'src/lib.rs',
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
extern crate lix_doc;
|
||||
+1
-1
@@ -9,4 +9,4 @@ Version: @PACKAGE_VERSION@
|
||||
Requires: lix-base kj-async @BOEHM_IF_FOUND@
|
||||
Requires.private: @AWS_SDK_IF_FOUND@ @BOEHM_IF_FOUND@ @CPUID_IF_FOUND@ @SECCOMP_IF_FOUND@ libeditline lowdown ncurses libbrotlidec libbrotlienc libarchive libcrypto capnp-rpc libcurl sqlite3
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -lrust_monocrate -llix
|
||||
Libs: -L${libdir} -llix
|
||||
|
||||
+99
-26
@@ -89,15 +89,15 @@ config_h = configure_file(
|
||||
|
||||
install_headers(config_h, subdir : 'lix')
|
||||
|
||||
lix_rs_files = files(
|
||||
'../Cargo.toml',
|
||||
'../Cargo.lock',
|
||||
)
|
||||
subdir('lix-rs')
|
||||
|
||||
# Subcomponents: these link into artifacts themselves, and have interdependencies.
|
||||
subdir('lix-doc')
|
||||
|
||||
subdir('rust-monocrate')
|
||||
|
||||
liblixutil_rs = declare_dependency(
|
||||
link_with : rust_monocrate,
|
||||
)
|
||||
|
||||
# we only collect sources and generated headers here. real headers are collected and
|
||||
# installed by each subdir due to how meson generates paths for headers it installs.
|
||||
liblix_sources = []
|
||||
@@ -150,36 +150,109 @@ dependencies = [
|
||||
seccomp,
|
||||
sqlite,
|
||||
toml11,
|
||||
# NOTE: this is secretly rust-monocrate in a trenchcoat.
|
||||
# See that directory's README for more details.
|
||||
liblixutil_rs,
|
||||
]
|
||||
|
||||
if host_machine.system() == 'freebsd'
|
||||
dependencies += [ libprocstat ]
|
||||
endif
|
||||
|
||||
liblix_all = library(
|
||||
'lix',
|
||||
liblix_sources,
|
||||
liblix_generated_headers,
|
||||
dependencies : dependencies,
|
||||
# `..` makes the `lix/` subtree of the repo available for includes,
|
||||
# mirroring our header directory structure once they are installed.
|
||||
include_directories : [ '..' ],
|
||||
cpp_args : cpp_args,
|
||||
cpp_pch : cpp_pch,
|
||||
install : true,
|
||||
# FIXME(Qyriad): is this right?
|
||||
install_rpath : libdir,
|
||||
lixrs = custom_target(
|
||||
'liblixrs',
|
||||
input : lix_rs_files,
|
||||
output : 'liblixrs.a',
|
||||
command : [
|
||||
cargo,
|
||||
'-Z', 'unstable-options',
|
||||
'build',
|
||||
'--artifact-dir=@0@'.format(meson.current_build_dir()),
|
||||
'-p',
|
||||
'lix',
|
||||
f'--target=@host_triple@',
|
||||
cargo_jobs_args,
|
||||
],
|
||||
console : true,
|
||||
env : {
|
||||
'MESON_BUILD_DIR': meson.project_build_root(),
|
||||
},
|
||||
)
|
||||
|
||||
liblix = declare_dependency(
|
||||
include_directories : include_directories('..'),
|
||||
dependencies : dependencies,
|
||||
link_with : liblix_all,
|
||||
if meson.can_run_host_binaries()
|
||||
test(
|
||||
'lix-rs-tests',
|
||||
cargo,
|
||||
args : [
|
||||
'test',
|
||||
'--all', '--all-targets',
|
||||
'--no-fail-fast',
|
||||
cargo_jobs_args,
|
||||
],
|
||||
suite : 'check',
|
||||
)
|
||||
endif
|
||||
|
||||
liblix_cpp_static = static_library(
|
||||
'lix_cpp_static',
|
||||
liblix_sources,
|
||||
liblix_generated_headers,
|
||||
dependencies : [
|
||||
dependencies,
|
||||
],
|
||||
include_directories : '..',
|
||||
cpp_args : cpp_args,
|
||||
cpp_pch : cpp_pch,
|
||||
)
|
||||
|
||||
if is_darwin
|
||||
lixrs_link_args = [ '-Wl,-force_load,lix/liblixrs.a' ]
|
||||
else
|
||||
lixrs_link_args = [ '-Wl,-L,lix,--whole-archive,-l,lixrs,--no-whole-archive' ]
|
||||
endif
|
||||
|
||||
if is_static
|
||||
liblix = declare_dependency(
|
||||
include_directories : include_directories('..'),
|
||||
dependencies : dependencies,
|
||||
link_whole : [ liblix_cpp_static ],
|
||||
link_args : lixrs_link_args,
|
||||
sources : [
|
||||
custom_target(
|
||||
input : [ lixrs ],
|
||||
output : 'lixrs-dep-propagator.gen.hh',
|
||||
command : [ 'bash', '-c', 'touch "$1"', 'touch', '@OUTPUT@' ],
|
||||
),
|
||||
],
|
||||
)
|
||||
else
|
||||
liblix_all_shared = shared_library(
|
||||
'lix',
|
||||
custom_target(
|
||||
input : [ lixrs ],
|
||||
output : 'lixrs-dep-propagator.gen.cc',
|
||||
command : [ 'bash', '-c', 'touch "$1"', 'touch', '@OUTPUT@' ],
|
||||
),
|
||||
dependencies : [
|
||||
dependencies,
|
||||
require_dylib_rtti,
|
||||
],
|
||||
link_whole : [ liblix_cpp_static ],
|
||||
link_args : lixrs_link_args,
|
||||
# `..` makes the `lix/` subtree of the repo available for includes,
|
||||
# mirroring our header directory structure once they are installed.
|
||||
include_directories : [ '..' ],
|
||||
cpp_args : cpp_args,
|
||||
cpp_pch : cpp_pch,
|
||||
install : true,
|
||||
# FIXME(Qyriad): is this right?
|
||||
install_rpath : libdir,
|
||||
)
|
||||
|
||||
liblix = declare_dependency(
|
||||
include_directories : include_directories('..'),
|
||||
dependencies : dependencies,
|
||||
link_with : [ liblix_all_shared ],
|
||||
)
|
||||
endif
|
||||
|
||||
meson.override_dependency('lix', liblix)
|
||||
|
||||
# The rest of the subdirectories aren't separate components,
|
||||
|
||||
+7
-36
@@ -155,9 +155,9 @@ nix_headers = files(
|
||||
# keep-sorted end
|
||||
)
|
||||
|
||||
# You know. The thing you link against with `-liblix`.
|
||||
iblix = library(
|
||||
'iblix',
|
||||
nix = executable(
|
||||
'nix',
|
||||
files('main.cc'),
|
||||
nix_sources,
|
||||
legacy_sources,
|
||||
nix_settings_headers,
|
||||
@@ -166,6 +166,9 @@ iblix = library(
|
||||
legacy_headers,
|
||||
legacy_generated_headers,
|
||||
include_directories : legacy_include_directories,
|
||||
cpp_pch : cpp_pch,
|
||||
install : true,
|
||||
install_rpath : libdir,
|
||||
dependencies : [
|
||||
liblix,
|
||||
boehm,
|
||||
@@ -173,41 +176,9 @@ iblix = library(
|
||||
nlohmann_json,
|
||||
kj,
|
||||
libatomic,
|
||||
],
|
||||
cpp_pch : cpp_pch,
|
||||
install : true,
|
||||
# FIXME(Qyriad): is this right?
|
||||
install_rpath : libdir,
|
||||
)
|
||||
|
||||
libiblix = declare_dependency(
|
||||
link_with : [iblix],
|
||||
dependencies : [
|
||||
liblix,
|
||||
],
|
||||
include_directories : [
|
||||
include_directories('.'),
|
||||
legacy_include_directories
|
||||
],
|
||||
sources : [
|
||||
nix_settings_headers,
|
||||
nix_generated_headers,
|
||||
nix_headers,
|
||||
legacy_headers,
|
||||
legacy_generated_headers,
|
||||
],
|
||||
)
|
||||
|
||||
nix = executable(
|
||||
'nix',
|
||||
'main.cc',
|
||||
cpp_pch : cpp_pch,
|
||||
install : true,
|
||||
install_rpath : libdir,
|
||||
dependencies : [
|
||||
libiblix,
|
||||
libasanoptions,
|
||||
],
|
||||
cpp_pch : cpp_pch,
|
||||
)
|
||||
|
||||
nix_symlinks = [
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# This may not actually build with Cargo, but exists to help Meson and to manage lockfiles.
|
||||
[package]
|
||||
name = "rust-monocrate"
|
||||
edition.workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
lix-doc = { path = "../lix-doc" }
|
||||
@@ -1,19 +0,0 @@
|
||||
# What the hell is this?
|
||||
|
||||
This is a cursed solution to the intersection of the following problems:
|
||||
|
||||
- Lix is separated into multiple libraries, which are intended to be buildable as dynamic/shared libraries *or* statlic libraries.
|
||||
- Those libraries are linked into the Lix executable binary.
|
||||
- Static libraries also statically link their library dependencies.
|
||||
- We want to be able to use Rust code in multiple places in the codebase.
|
||||
- Meson has poor support for Rust and non-Rust sources in the same target, with [internal errors](https://github.com/mesonbuild/meson/issues/15435) preventing mixed targets from linking against non-mixed targets.
|
||||
- Linking more than one Rust `crate-type = staticlib` is [unsupported](https://github.com/rust-lang/rust/issues/44322) with Rust's standard library.
|
||||
- Meson [does not support dynamically linking the Rust standard library for `crate-type = staticlib`](https://mesonbuild.com/Release-notes-for-1-9-0.html#new-experimental-option-rust_dynamic_std).
|
||||
- Meson [ignores `link_args` for Rust targets](https://github.com/mesonbuild/meson/issues/13538)
|
||||
- Meson [does not set soname of Rust cdylibs](https://github.com/mesonbuild/meson/issues/13537)
|
||||
|
||||
So! What do we do? For any Rust code that Lix wants to use, we always link to a single crate, which will reëxport Rust code from any crate (in-tree or out-of-tree) we wish to use.
|
||||
This "monocrate" is *always* built as a static library, and anything in Lix that depends on Rust code will statically link it in.
|
||||
When the Lix executable is linked against Lix libraries that are built statically, we do *not* `link_whole` them.
|
||||
As far as we::Qyriad can tell, this is sufficient to not break everything.
|
||||
But long-term, we should probably solve this problem by migrating to Rust code at top-level, and having Rustc do the final link.
|
||||
@@ -1,19 +0,0 @@
|
||||
# This crate is what ultimately links to Lix. All other Rust crates Lix uses must go through this.
|
||||
|
||||
rust_monocrate_sources = files(
|
||||
'src/lib.rs',
|
||||
)
|
||||
|
||||
rust_monocrate = static_library(
|
||||
'rust_monocrate',
|
||||
rust_abi : 'c',
|
||||
sources : rust_monocrate_sources,
|
||||
dependencies : [
|
||||
liblix_doc_internal,
|
||||
rnix,
|
||||
rowan,
|
||||
],
|
||||
# If any installed target links against a static library,
|
||||
# the static library must also be installed.
|
||||
install : true,
|
||||
)
|
||||
@@ -1,12 +0,0 @@
|
||||
//! This is a hack that forces Rust to link all the Lix libs as a single static
|
||||
//! library for usage when building Lix itself in static mode.
|
||||
//!
|
||||
//! The reason for this is that Rust does not support linking multiple
|
||||
//! staticlibs into one executable, as it will jam a libstd into every single
|
||||
//! one of them. This is ridiculously goofy because it would be trivially
|
||||
//! solved by linking libstd separately.
|
||||
//!
|
||||
//! https://github.com/rust-lang/rust/issues/44322
|
||||
//!
|
||||
//! It re-exports all the symbols that should be exported to C++.
|
||||
pub use lix_doc::*;
|
||||
+103
-33
@@ -102,6 +102,7 @@ enable_internal_api_docs = get_option('internal-api-docs')
|
||||
|
||||
doxygen = find_program('doxygen', required : enable_internal_api_docs, native : true)
|
||||
bash = find_program('bash', native : true)
|
||||
cargo = find_program('cargo')
|
||||
|
||||
rapidcheck_meson = dependency('rapidcheck', required : enable_internal_api_docs)
|
||||
|
||||
@@ -128,8 +129,99 @@ if get_option('tests-brief')
|
||||
tests_args += '--gtest_brief=1'
|
||||
endif
|
||||
|
||||
cargo_jobs = get_option('cargo-jobs')
|
||||
cargo_jobs_args = cargo_jobs != 0 ? [ f'-j@cargo_jobs@' ] : []
|
||||
|
||||
cxx = meson.get_compiler('cpp')
|
||||
rustc = meson.get_compiler('rust')
|
||||
rustc_for_build = meson.get_compiler('rust', native : true)
|
||||
|
||||
# NOT the same thing as is_static.
|
||||
# The default library can be static and this still be true.
|
||||
# But on musl, linking a shared library that uses C++ RTTI gives:
|
||||
# `relocation R_X86_64_32S against symbol `_ZTVN10__cxxabiv117__class_type_infoE'
|
||||
# can not be used when making a shared object; recompile with -fPIC`
|
||||
# We don't control Nixpkgs' Musl's position-independent-ness, so instead we just
|
||||
# disable shared libraries that use RTTI (like liblix) when this is the case.
|
||||
can_dylib_rtti = cxx.links('''
|
||||
#include <print>
|
||||
void foo() {
|
||||
std::println("");
|
||||
}
|
||||
''',
|
||||
args : '-shared',
|
||||
)
|
||||
require_dylib_rtti = declare_dependency(
|
||||
#'dylib-rtti-disabler',
|
||||
dependencies : can_dylib_rtti ? [] : disabler(),
|
||||
)
|
||||
summary('C++ RTTI in dylibs:', can_dylib_rtti, bool_yn : true)
|
||||
|
||||
|
||||
# HACK: Meson really does not tell us the build and host machine triples...
|
||||
# But we need these to provide Cargo configuration (lix/lix-rs/meson.build).
|
||||
# We can't even infer them from host_machine/build_machine.foo() methods!
|
||||
# Look! https://mesonbuild.com/Reference-manual_builtin_host_machine.html
|
||||
# In `<arch>-<vendor>-<os>-<abi>`, we can query Arch and OS, and vendor is w/e,
|
||||
# but we can't differentiate `-gnu` and `-musl`!
|
||||
# Okay okay, so we just ask our compilers. Meson does tell us those, and surely
|
||||
# the compilers know their own triples right?
|
||||
# Well...
|
||||
#
|
||||
# We can't use `cc -dumpmachine`, because that will also give us things like
|
||||
# `arm64-apple-darwin24.6.0`, which rustc won't accept for --target. Clang
|
||||
# does have `-print-effective-triple`, but that does exactly the same thing.
|
||||
# There aren't compiler builtin `#define`s that we can extract this information
|
||||
# from either, and there's also no `__MUSL__` macro:
|
||||
# https://wiki.musl-libc.org/faq#Q:-Why-is-there-no-%3Ccode%3E__MUSL__%3C/code%3E-macro?
|
||||
#
|
||||
# Okay...
|
||||
# rustc has `--print=host-tuple`, but that only prints the the triple for the
|
||||
# build machine.
|
||||
#
|
||||
# NOTE: Yes! Remember! Rust has only "host" and "target", which are what
|
||||
# everyone else (including Meson and Nixpkgs) calls the "build" and "host"
|
||||
# machines respectively.
|
||||
#
|
||||
# Anyway. There's no way to print the value of `--target`, since, well,
|
||||
# supposedly if you're passing it you already know it:
|
||||
# https://github.com/rust-lang/rust/issues/105588#issuecomment-1500285344
|
||||
#
|
||||
# So! Either we use `RUSTC_BOOTSTRAP=1` and use `--print=target-spec-json`:
|
||||
# https://github.com/rust-lang/rust/issues/38338
|
||||
#
|
||||
# ...or we string-parse the parse the arguments from `rustc.cmd_array()`.
|
||||
# That seems the least error-prone to me.
|
||||
#
|
||||
# FIXME: we can get rid of this whole thing when we have Meson 1.11:
|
||||
# https://mesonbuild.com/Rust-module.html#compiler_target
|
||||
host_triple = ''
|
||||
foreach i : range(rustc.cmd_array().length())
|
||||
arg = rustc.cmd_array()[i]
|
||||
if arg == '--target'
|
||||
host_triple = rustc.cmd_array()[i + 1]
|
||||
break
|
||||
endif
|
||||
if arg.startswith('--target=')
|
||||
host_triple = arg.split('=')[1]
|
||||
break
|
||||
endif
|
||||
unset_variable('arg')
|
||||
endforeach
|
||||
|
||||
# Thank GODS we can at least get this one reasonably.
|
||||
build_triple = run_command(
|
||||
# See the above comment about Rustc vs Meson/Nixpkgs terminology on host/build/target.
|
||||
rustc_for_build.cmd_array(), '--print=host-tuple',
|
||||
capture : true,
|
||||
check : true,
|
||||
).stdout().strip()
|
||||
# If there was no `--target` argument, assume it's the same as the "host tuple", ig.
|
||||
if host_triple == ''
|
||||
host_triple = build_triple
|
||||
endif
|
||||
summary('TRIPLE', host_triple)
|
||||
summary('TRIPLE_FOR_BUILD', build_triple)
|
||||
|
||||
# tag define to tell us we are compiling lix itself and can thus make
|
||||
# non-namespaced aliases of a utility defines visible. this spares us
|
||||
@@ -228,14 +320,6 @@ is_darwin = host_machine.system() == 'darwin'
|
||||
is_freebsd = host_machine.system() == 'freebsd'
|
||||
is_x64 = host_machine.cpu_family() == 'x86_64'
|
||||
|
||||
# Meson knows these, but won't tell us. We need them to hack around some linker shenanigans.
|
||||
# See the 'Rust Support' section below.
|
||||
if is_darwin
|
||||
dylib_suffix = 'dylib'
|
||||
elif is_linux
|
||||
dylib_suffix = 'so'
|
||||
endif
|
||||
|
||||
# Per-platform arguments that you should probably pass to shared_module() invocations.
|
||||
# Something like add_project_arguments() can't be scoped on only shared modules, so this
|
||||
# variable is here instead.
|
||||
@@ -254,30 +338,6 @@ elif is_linux
|
||||
endif
|
||||
configdata = configuration_data()
|
||||
|
||||
#
|
||||
# Rust Support
|
||||
#
|
||||
|
||||
if is_static
|
||||
rust_dynamic_args = []
|
||||
else
|
||||
rust_dynamic_args = ['-C', 'prefer-dynamic']
|
||||
endif
|
||||
|
||||
# This hack is required by the wombo combo of meson bugs:
|
||||
# Meson does not set the soname for us: https://github.com/mesonbuild/meson/issues/13537
|
||||
# Meson ignores link_args for Rust targets: https://github.com/mesonbuild/meson/issues/13538
|
||||
# Thus we have to, when the build is dynamic, pass these in rust_args to make it link properly.
|
||||
if cxx.get_linker_id().startswith('ld64')
|
||||
# Rust actually sets the -install_name if you pass -C rpath=yes on macOS targets (?!):
|
||||
# https://github.com/rust-lang/rust/blob/2a8af4f7c8262a90b886bc063fe0c271d2b51a45/compiler/rustc_codegen_ssa/src/back/linker.rs#L441-L445
|
||||
# https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/libstd.2C.20rpath.2C.20dylibs.20and.20packaging
|
||||
# This seems like a bug, so let's keep passing it deliberately.
|
||||
soname_arg = '-install_name'
|
||||
elif cxx.get_linker_id().startswith('ld')
|
||||
soname_arg = '-soname'
|
||||
endif
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
@@ -435,7 +495,6 @@ endif
|
||||
# Build-time tools
|
||||
#
|
||||
dot = find_program('dot', required : false, native : true)
|
||||
cbindgen = find_program('cbindgen', native : true)
|
||||
pymod = import('python')
|
||||
python = pymod.find_installation('python3')
|
||||
|
||||
@@ -659,6 +718,17 @@ if cxx.get_linker_id() in ['ld.bfd', 'ld.gold']
|
||||
add_project_link_arguments('-Wl,--no-copy-dt-needed-entries', language : 'cpp')
|
||||
endif
|
||||
|
||||
# musl + GNU ld has a complaint: "warning: arch_x86_64_setcontext.S.o:
|
||||
# missing .note.GNU-stack section implies executable stack. This behaviour
|
||||
# is deprecated and will be removed in a future version of the linker".
|
||||
# lld defaults to `-z noexecstack` in the first place:
|
||||
# https://github.com/llvm/llvm-project/issues/57009
|
||||
# So we can just add that to normalize the behavior.
|
||||
add_project_link_arguments(
|
||||
cxx.get_supported_link_arguments('-Wl,-z,noexecstack'),
|
||||
language : 'cpp',
|
||||
)
|
||||
|
||||
if is_freebsd
|
||||
# FreeBSD's `environ` is defined in `crt1.o`, not `libc.so`,
|
||||
# so the linker thinks it's undefined
|
||||
|
||||
@@ -108,3 +108,7 @@ option('disable-fibers', type : 'boolean', value : false,
|
||||
option('builtin-dep-closure', type : 'array',
|
||||
description : 'dependency closure used for builtin builder sandboxes. the install paths are included automatically.',
|
||||
)
|
||||
|
||||
option('cargo-jobs', type : 'integer', value : 0,
|
||||
description : 'Value to pass for Cargo -j. Use 0 to omit',
|
||||
)
|
||||
|
||||
@@ -24,6 +24,11 @@ def main():
|
||||
|
||||
targets = (
|
||||
[t for t in get_targets_of_rule(args.build_root, "CUSTOM_COMMAND") if t.endswith(".gen.hh")]
|
||||
+ [
|
||||
t
|
||||
for t in get_targets_of_rule(args.build_root, "CUSTOM_COMMAND")
|
||||
if t.endswith(".gen.cc")
|
||||
]
|
||||
+ [
|
||||
t
|
||||
for t in get_targets_of_rule(args.build_root, "CUSTOM_COMMAND_DEP")
|
||||
|
||||
+49
-3
@@ -54,8 +54,8 @@
|
||||
rapidcheck,
|
||||
removeReferencesTo,
|
||||
rustPlatform,
|
||||
rust-cbindgen,
|
||||
rustc,
|
||||
cargo,
|
||||
sqlite,
|
||||
systemtap-lix ? __forDefaults.systemtap-lix,
|
||||
toml11,
|
||||
@@ -289,6 +289,8 @@ let
|
||||
./subprojects/aws_sdk
|
||||
# Required for meson to generate Cargo wraps
|
||||
./Cargo.lock
|
||||
./Cargo.toml
|
||||
./.cargo/config.toml
|
||||
]);
|
||||
|
||||
functionalTestFiles = fileset.unions [
|
||||
@@ -303,6 +305,23 @@ let
|
||||
lldBintools = wrapBintoolsWith {
|
||||
bintools = llvmPackages.bintools;
|
||||
};
|
||||
|
||||
# Rustc will use `cc` as the linker by default, but we need to link the C++ standard library.
|
||||
# However the C++ compiler is not unprefixed `c++` in Nixpkgs when cross compiling.
|
||||
# This is a fair amount of logic to encode in a Cargo config.toml, so the most reasonable
|
||||
# options are to have meson `configure_file()` a config.toml,
|
||||
# or just use these environment variables.
|
||||
cxxLinkerFor = stdenv: lib.getExe' stdenv.cc "${stdenv.cc.targetPrefix}c++";
|
||||
hostCargoEnvVar = hostPlatform.rust.cargoEnvVarTarget;
|
||||
buildCargoEnvVar = buildPlatform.rust.cargoEnvVarTarget;
|
||||
|
||||
# Environment variables that set Cargo config values.
|
||||
cargoConfigEnv = {
|
||||
"CARGO_TARGET_${hostCargoEnvVar}_LINKER" = cxxLinkerFor stdenv;
|
||||
}
|
||||
// lib.optionalAttrs (hostCargoEnvVar != buildCargoEnvVar) {
|
||||
"CARGO_TARGET_${buildCargoEnvVar}_LINKER" = cxxLinkerFor buildPackages.clangStdenv;
|
||||
};
|
||||
in
|
||||
assert (lintInsteadOfBuild -> lix-clang-tidy != null);
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
@@ -427,13 +446,23 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
# We only include CMake so that Meson can locate toml11, which only ships CMake dependency metadata.
|
||||
dontUseCmakeConfigure = true;
|
||||
|
||||
# depsBuildBuild is put in PATH before nativeBuildInputs, but clangStdenv.cc's version
|
||||
# of clang-tidy doesn't seem to work. Thankfully, if we're linting, we don't need to
|
||||
# compile things for the build platform either.
|
||||
depsBuildBuild = lib.optionals (!lintInsteadOfBuild) [
|
||||
# clangStdenv is spliced but clangStdenv.cc is not:
|
||||
# https://github.com/NixOS/nixpkgs/issues/211340
|
||||
buildPackages.clangStdenv.cc
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
rustPlatform.cargoSetupHook
|
||||
finalAttrs.lixPythonForBuild
|
||||
meson
|
||||
ninja
|
||||
cmake
|
||||
rust-cbindgen
|
||||
rustc
|
||||
cargo
|
||||
capnproto
|
||||
# Required for libstd++ assertions that leaks inside of the final binary.
|
||||
removeReferencesTo
|
||||
@@ -572,6 +601,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
}
|
||||
# Putting these here means they'll also work in the dev shell.
|
||||
// cargoConfigEnv
|
||||
// lib.optionalAttrs (finalAttrs.buildTestEnv != null) {
|
||||
BUILD_TEST_ENV = finalAttrs.buildTestEnv;
|
||||
}
|
||||
@@ -590,7 +621,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
# what the correct `wrapCCWith`/`stdenv.cc.override` incantation is.
|
||||
# But just putting that libstdc++ in `-L` seems to make the driver find
|
||||
# the right things.
|
||||
NIX_CFLAGS_LINK = "-L${lib.makeLibraryPath [ pkgsStatic.gcc.cc ]}";
|
||||
NIX_CFLAGS_LINK = "-L${lib.getLib pkgsStatic.gcc.cc}/lib";
|
||||
};
|
||||
|
||||
cargoDeps = rustPlatform.importCargoLock { lockFile = ./Cargo.lock; };
|
||||
@@ -773,6 +804,21 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
# we make precompiled C++ stdlib conditional on using Clang.
|
||||
# https://git.lix.systems/lix-project/lix/issues/374
|
||||
++ [ (lib.mesonBool "enable-pch-std" stdenv.cc.isClang) ];
|
||||
depsBuildBuild = [
|
||||
# From a strict deps point-of-view, I'm pretty sure this is literally incorrect.
|
||||
# The clang-tidy from clang-tools is for checking source files that are compiled
|
||||
# for the host machine.
|
||||
# However, we need a clang-tools version of clang-tidy in PATH before
|
||||
# clangStdenv.cc, and it seems like all depsBuildBuild things come before
|
||||
# "packages" things.
|
||||
# I also tried just putting these in `packages` with the correct ordering,
|
||||
# but that did not work.
|
||||
# I guess the platform offsets really do matter here, even in the devshell.
|
||||
buildPackages.llvmPackages.clang-tools
|
||||
|
||||
# This *has* clang-tidy, but it doesn't (seem to?) work.
|
||||
buildPackages.clangStdenv.cc
|
||||
];
|
||||
|
||||
packages =
|
||||
lib.optional (stdenv.cc.isClang && hostPlatform == buildPlatform) llvmPackages.clang-tools
|
||||
|
||||
Reference in New Issue
Block a user