diff --git a/Cargo.lock b/Cargo.lock index 6e7bf5f0b..4f15e0c16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,6 +451,7 @@ name = "lix" version = "0.0.0" dependencies = [ "lix-doc", + "pkg-config", "regex", "rootcause", "rustyline", @@ -568,6 +569,12 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + [[package]] name = "proc-macro2" version = "1.0.106" diff --git a/Cargo.toml b/Cargo.toml index a73c15ba2..8f8a653ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ rustyline = "18" rustyline-derive = "0.12" syn = "2.0" zngur = "0.10" +pkg-config = "0.3.33" [profile.dev] opt-level = 1 diff --git a/justfile b/justfile index b456b6a85..70f81e92a 100644 --- a/justfile +++ b/justfile @@ -56,6 +56,12 @@ test-integration *OPTIONS: (test "--suite" "installcheck" OPTIONS) test-functional2 *OPTIONS: cd tests/functional2 && python -m pytest -v "$@" +# special target for cargo because meson cannot be convinced to not mangle cargo test output, +# and getting properly colored test output any other way also doesn't look all that possible. +[positional-arguments] +test-rs *OPTIONS: + meson test -C {{ builddir }} --interactive lix-rs-tests "$@" + # Lint with `clang-tidy` lint: ninja -C build clang-tidy diff --git a/lix/lix-rs/Cargo.toml b/lix/lix-rs/Cargo.toml index 2bd2ed0bf..4e656d9bb 100644 --- a/lix/lix-rs/Cargo.toml +++ b/lix/lix-rs/Cargo.toml @@ -19,3 +19,4 @@ rustyline-derive.workspace = true [build-dependencies] zngur.workspace = true +pkg-config.workspace = true diff --git a/lix/lix-rs/build.rs b/lix/lix-rs/build.rs index 9a96a3a22..d833793cf 100644 --- a/lix/lix-rs/build.rs +++ b/lix/lix-rs/build.rs @@ -13,4 +13,34 @@ fn main() { .expect("read main.zng.rs"), ) .expect("write generated.rs"); + + println!("cargo::rerun-if-env-changed=CXX_LINK_DIR_FOR_TEST"); + if let Some(dir) = env::var("CXX_LINK_DIR_FOR_TEST").ok() { + println!("cargo::rustc-link-search={}", dir); + println!("cargo::rustc-link-lib=static=lix_cpp_static"); + } + + // pull link args for each dependency we'll need to fully link. + println!("cargo::rerun-if-env-changed=CXX_LINK_LIBS_FOR_TEST"); + for dep in env::var("CXX_LINK_LIBS_FOR_TEST") + .ok() + .into_iter() + .flat_map(|s| s.split(':').map(|s| s.to_string()).collect::>()) + { + // meson has already checked that everything we need exists + let _ = pkg_config::probe_library(&dep); + } + + // explicitly pass sanitizer args. we can't use -Zsanitizer or -Zexternal-clangrt + // even with RUSTC_BOOTSTRAP because that will confuse the hell out of dependency + // crate tests when they're run. since we only need this for our own tests we can + // be quite careless about unnecessary dependencies, so just splat all arguments. + println!("cargo::rerun-if-env-changed=CXX_TEST_SANITIZERS"); + for arg in env::var("CXX_TEST_SANITIZERS") + .ok() + .iter() + .flat_map(|s| s.split(':')) + { + println!("cargo::rustc-link-arg={arg}"); + } } diff --git a/lix/meson.build b/lix/meson.build index 45689caba..a3f4ac10e 100644 --- a/lix/meson.build +++ b/lix/meson.build @@ -176,22 +176,6 @@ lixrs = custom_target( env : lixrs_cargo_env, ) -if meson.can_run_host_binaries() - test( - 'lix-rs-tests', - cargo, - args : [ - 'test', - '--all', '--all-targets', - '--no-fail-fast', - cargo_jobs_args, - ], - suite : 'check', - env : lixrs_cargo_env, - timeout : 300, - ) -endif - liblix_cpp_static = static_library( 'lix_cpp_static', liblix_sources, @@ -204,6 +188,34 @@ liblix_cpp_static = static_library( cpp_pch : cpp_pch, ) +if meson.can_run_host_binaries() + lixrs_test_deps = [] + foreach dep : dependencies.flatten() + lixrs_test_deps += dep.name() + endforeach + + test( + 'lix-rs-tests', + cargo, + args : [ + 'test', + '--all', '--all-targets', + '--no-fail-fast', + cargo_jobs_args, + ], + depends : [ + liblix_cpp_static, + ], + suite : 'check', + env : lixrs_cargo_env + { + 'CXX_LINK_DIR_FOR_TEST': meson.current_build_dir(), + 'CXX_LINK_LIBS_FOR_TEST': lixrs_test_deps, + 'CXX_TEST_SANITIZERS': cargo_sanitizer_args, + }, + timeout : 300, + ) +endif + if is_darwin lixrs_link_args = [ '-Wl,-force_load,lix/liblixrs.a' ] else diff --git a/meson.build b/meson.build index a5833eaaa..ce4d3422d 100644 --- a/meson.build +++ b/meson.build @@ -687,6 +687,9 @@ add_project_arguments( language : 'cpp', ) +sanitize_args = [] +cargo_sanitizer_args = [] + # 2024-03-24: jade benchmarked the default sanitize reporting in clang and got # a regression of about 10% on hackage-packages.nix with clang. So if the # signed-integer-overflow sanitizer is requested (our default), we trap instead. @@ -703,6 +706,11 @@ endif # GCC defaults to shared libsan so is fine. if cxx.get_id() == 'clang' and get_option('b_sanitize') != '' add_project_link_arguments('-shared-libsan', language : 'cpp') + cargo_sanitizer_args = [ + '-shared-libsan', + '-fsanitize=' + get_option('b_sanitize'), + sanitize_args, + ] endif # Clang gets grumpy about missing libasan symbols if -shared-libasan is not