1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-04 16:10:59 +01:00

Merge pull request #14227 from NixOS/asan-hydra

packaging: Add buildWithSanitizers to hydraJobs
This commit is contained in:
John Ericson 2025-10-12 17:43:54 +00:00 committed by GitHub
commit a01df8de21
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 74 additions and 44 deletions

View file

@ -23,16 +23,6 @@ let
packages' = nixFlake.packages.${system}; packages' = nixFlake.packages.${system};
stdenv = (getStdenv pkgs); stdenv = (getStdenv pkgs);
enableSanitizersLayer = finalAttrs: prevAttrs: {
mesonFlags =
(prevAttrs.mesonFlags or [ ])
++ [ (lib.mesonOption "b_sanitize" "address,undefined") ]
++ (lib.optionals stdenv.cc.isClang [
# https://www.github.com/mesonbuild/meson/issues/764
(lib.mesonBool "b_lundef" false)
]);
};
collectCoverageLayer = finalAttrs: prevAttrs: { collectCoverageLayer = finalAttrs: prevAttrs: {
env = env =
let let
@ -55,14 +45,15 @@ let
''; '';
}; };
componentOverrides = componentOverrides = (lib.optional withCoverage collectCoverageLayer);
(lib.optional withSanitizers enableSanitizersLayer)
++ (lib.optional withCoverage collectCoverageLayer);
in in
rec { rec {
nixComponentsInstrumented = nixComponents.overrideScope ( nixComponentsInstrumented = nixComponents.overrideScope (
final: prev: { final: prev: {
withASan = withSanitizers;
withUBSan = withSanitizers;
nix-store-tests = prev.nix-store-tests.override { withBenchmarks = true; }; nix-store-tests = prev.nix-store-tests.override { withBenchmarks = true; };
# Boehm is incompatible with ASAN. # Boehm is incompatible with ASAN.
nix-expr = prev.nix-expr.override { enableGC = !withSanitizers; }; nix-expr = prev.nix-expr.override { enableGC = !withSanitizers; };

View file

@ -15,7 +15,6 @@ pymod = import('python')
python = pymod.find_installation('python3') python = pymod.find_installation('python3')
nix_env_for_docs = { nix_env_for_docs = {
'ASAN_OPTIONS' : 'abort_on_error=1:print_summary=1:detect_leaks=0',
'HOME' : '/dummy', 'HOME' : '/dummy',
'NIX_CONF_DIR' : '/dummy', 'NIX_CONF_DIR' : '/dummy',
'NIX_SSL_CERT_FILE' : '/dummy/no-ca-bundle.crt', 'NIX_SSL_CERT_FILE' : '/dummy/no-ca-bundle.crt',

View file

@ -0,0 +1,6 @@
extern "C" [[gnu::retain, gnu::weak]] const char * __asan_default_options()
{
// We leak a bunch of memory knowingly on purpose. It's not worthwhile to
// diagnose that memory being leaked for now.
return "abort_on_error=1:print_summary=1:detect_leaks=0:detect_odr_violation=0";
}

View file

@ -1,7 +1,3 @@
asan_test_options_env = {
'ASAN_OPTIONS' : 'abort_on_error=1:print_summary=1:detect_leaks=0',
}
# Clang gets grumpy about missing libasan symbols if -shared-libasan is not # Clang gets grumpy about missing libasan symbols if -shared-libasan is not
# passed when building shared libs, at least on Linux # passed when building shared libs, at least on Linux
if cxx.get_id() == 'clang' and ('address' in get_option('b_sanitize') or 'undefined' in get_option( if cxx.get_id() == 'clang' and ('address' in get_option('b_sanitize') or 'undefined' in get_option(
@ -10,3 +6,6 @@ if cxx.get_id() == 'clang' and ('address' in get_option('b_sanitize') or 'undefi
add_project_link_arguments('-shared-libasan', language : 'cpp') add_project_link_arguments('-shared-libasan', language : 'cpp')
endif endif
if 'address' in get_option('b_sanitize')
deps_other += declare_dependency(sources : 'asan-options.cc')
endif

View file

@ -204,6 +204,25 @@ let
mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or [ ]; mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or [ ];
}; };
enableSanitizersLayer =
finalAttrs: prevAttrs:
let
sanitizers = lib.optional scope.withASan "address" ++ lib.optional scope.withUBSan "undefined";
in
{
mesonFlags =
(prevAttrs.mesonFlags or [ ])
++ lib.optionals (lib.length sanitizers > 0) (
[
(lib.mesonOption "b_sanitize" (lib.concatStringsSep "," sanitizers))
]
++ (lib.optionals stdenv.cc.isClang [
# https://www.github.com/mesonbuild/meson/issues/764
(lib.mesonBool "b_lundef" false)
])
);
};
nixDefaultsLayer = finalAttrs: prevAttrs: { nixDefaultsLayer = finalAttrs: prevAttrs: {
strictDeps = prevAttrs.strictDeps or true; strictDeps = prevAttrs.strictDeps or true;
enableParallelBuilding = true; enableParallelBuilding = true;
@ -246,6 +265,16 @@ in
inherit filesetToSource; inherit filesetToSource;
/**
Whether meson components are built with [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html).
*/
withASan = false;
/**
Whether meson components are built with [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
*/
withUBSan = false;
/** /**
A user-provided extension function to apply to each component derivation. A user-provided extension function to apply to each component derivation.
*/ */
@ -332,6 +361,7 @@ in
setVersionLayer setVersionLayer
mesonLayer mesonLayer
fixupStaticLayer fixupStaticLayer
enableSanitizersLayer
scope.mesonComponentOverrides scope.mesonComponentOverrides
]; ];
mkMesonExecutable = mkPackageBuilder [ mkMesonExecutable = mkPackageBuilder [
@ -342,6 +372,7 @@ in
mesonLayer mesonLayer
mesonBuildLayer mesonBuildLayer
fixupStaticLayer fixupStaticLayer
enableSanitizersLayer
scope.mesonComponentOverrides scope.mesonComponentOverrides
]; ];
mkMesonLibrary = mkPackageBuilder [ mkMesonLibrary = mkPackageBuilder [
@ -353,6 +384,7 @@ in
mesonBuildLayer mesonBuildLayer
mesonLibraryLayer mesonLibraryLayer
fixupStaticLayer fixupStaticLayer
enableSanitizersLayer
scope.mesonComponentOverrides scope.mesonComponentOverrides
]; ];

View file

@ -158,6 +158,27 @@ in
in in
forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName}));
buildWithSanitizers =
let
components = forAllSystems (
system:
let
pkgs = nixpkgsFor.${system}.native;
in
pkgs.nixComponents2.overrideScope (
self: super: {
# Boost coroutines fail with ASAN on darwin.
withASan = !pkgs.stdenv.buildPlatform.isDarwin;
withUBSan = true;
nix-expr = super.nix-expr.override { enableGC = false; };
# Unclear how to make Perl bindings work with a dynamically linked ASAN.
nix-perl-bindings = null;
}
)
);
in
forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName}));
buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents2.nix-cli); buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents2.nix-cli);
# Toggles some settings for better coverage. Windows needs these # Toggles some settings for better coverage. Windows needs these

View file

@ -82,7 +82,7 @@ this_exe = executable(
test( test(
meson.project_name(), meson.project_name(),
this_exe, this_exe,
env : asan_test_options_env + { env : {
'_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data', '_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data',
}, },
protocol : 'gtest', protocol : 'gtest',

View file

@ -62,7 +62,6 @@ mkMesonExecutable (finalAttrs: {
mkdir -p "$HOME" mkdir -p "$HOME"
'' ''
+ '' + ''
export ASAN_OPTIONS=abort_on_error=1:print_summary=1:detect_leaks=0
export _NIX_TEST_UNIT_DATA=${resolvePath ./data} export _NIX_TEST_UNIT_DATA=${resolvePath ./data}
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
touch $out touch $out

View file

@ -63,7 +63,7 @@ this_exe = executable(
test( test(
meson.project_name(), meson.project_name(),
this_exe, this_exe,
env : asan_test_options_env + { env : {
'_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data', '_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data',
}, },
protocol : 'gtest', protocol : 'gtest',

View file

@ -61,7 +61,6 @@ mkMesonExecutable (finalAttrs: {
buildInputs = [ writableTmpDirAsHomeHook ]; buildInputs = [ writableTmpDirAsHomeHook ];
} }
'' ''
export ASAN_OPTIONS=abort_on_error=1:print_summary=1:detect_leaks=0
export _NIX_TEST_UNIT_DATA=${resolvePath ./data} export _NIX_TEST_UNIT_DATA=${resolvePath ./data}
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
touch $out touch $out

View file

@ -58,7 +58,7 @@ this_exe = executable(
test( test(
meson.project_name(), meson.project_name(),
this_exe, this_exe,
env : asan_test_options_env + { env : {
'_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data', '_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data',
'NIX_CONFIG' : 'extra-experimental-features = flakes', 'NIX_CONFIG' : 'extra-experimental-features = flakes',
'HOME' : meson.current_build_dir() / 'test-home', 'HOME' : meson.current_build_dir() / 'test-home',

View file

@ -59,7 +59,6 @@ mkMesonExecutable (finalAttrs: {
buildInputs = [ writableTmpDirAsHomeHook ]; buildInputs = [ writableTmpDirAsHomeHook ];
} }
('' (''
export ASAN_OPTIONS=abort_on_error=1:print_summary=1:detect_leaks=0
export _NIX_TEST_UNIT_DATA=${resolvePath ./data} export _NIX_TEST_UNIT_DATA=${resolvePath ./data}
export NIX_CONFIG="extra-experimental-features = flakes" export NIX_CONFIG="extra-experimental-features = flakes"
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}

View file

@ -104,7 +104,7 @@ this_exe = executable(
test( test(
meson.project_name(), meson.project_name(),
this_exe, this_exe,
env : asan_test_options_env + { env : {
'_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data', '_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data',
'HOME' : meson.current_build_dir() / 'test-home', 'HOME' : meson.current_build_dir() / 'test-home',
'NIX_REMOTE' : meson.current_build_dir() / 'test-home' / 'store', 'NIX_REMOTE' : meson.current_build_dir() / 'test-home' / 'store',
@ -138,7 +138,7 @@ if get_option('benchmarks')
benchmark( benchmark(
'nix-store-benchmarks', 'nix-store-benchmarks',
benchmark_exe, benchmark_exe,
env : asan_test_options_env + { env : {
'_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data', '_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data',
}, },
) )

View file

@ -83,7 +83,6 @@ mkMesonExecutable (finalAttrs: {
} }
( (
'' ''
export ASAN_OPTIONS=abort_on_error=1:print_summary=1:detect_leaks=0
export _NIX_TEST_UNIT_DATA=${data + "/src/libstore-tests/data"} export _NIX_TEST_UNIT_DATA=${data + "/src/libstore-tests/data"}
export NIX_REMOTE=$HOME/store export NIX_REMOTE=$HOME/store
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}

View file

@ -97,7 +97,7 @@ this_exe = executable(
test( test(
meson.project_name(), meson.project_name(),
this_exe, this_exe,
env : asan_test_options_env + { env : {
'_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data', '_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data',
}, },
protocol : 'gtest', protocol : 'gtest',

View file

@ -61,7 +61,6 @@ mkMesonExecutable (finalAttrs: {
mkdir -p "$HOME" mkdir -p "$HOME"
'' ''
+ '' + ''
export ASAN_OPTIONS=abort_on_error=1:print_summary=1:detect_leaks=0
export _NIX_TEST_UNIT_DATA=${./data} export _NIX_TEST_UNIT_DATA=${./data}
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
touch $out touch $out

View file

@ -1,6 +0,0 @@
extern "C" [[gnu::retain]] const char * __asan_default_options()
{
// We leak a bunch of memory knowingly on purpose. It's not worthwhile to
// diagnose that memory being leaked for now.
return "abort_on_error=1:print_summary=1:detect_leaks=0";
}

View file

@ -61,7 +61,6 @@ subdir('nix-meson-build-support/generate-header')
nix_sources = [ config_priv_h ] + files( nix_sources = [ config_priv_h ] + files(
'add-to-store.cc', 'add-to-store.cc',
'app.cc', 'app.cc',
'asan-options.cc',
'build.cc', 'build.cc',
'bundle.cc', 'bundle.cc',
'cat.cc', 'cat.cc',

View file

@ -5,13 +5,6 @@
using namespace nix; using namespace nix;
extern "C" [[gnu::retain]] const char * __asan_default_options()
{
// We leak a bunch of memory knowingly on purpose. It's not worthwhile to
// diagnose that memory being leaked for now.
return "abort_on_error=1:print_summary=1:detect_leaks=0";
}
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
try { try {

View file

@ -1,11 +1,12 @@
cxx = meson.get_compiler('cpp') cxx = meson.get_compiler('cpp')
deps_other = []
subdir('nix-meson-build-support/common/asan-options') subdir('nix-meson-build-support/common/asan-options')
libstoreconsumer_tester = executable( libstoreconsumer_tester = executable(
'test-libstoreconsumer', 'test-libstoreconsumer',
'main.cc', 'main.cc',
dependencies : [ dependencies : deps_other + [
dependency('nix-store'), dependency('nix-store'),
], ],
build_by_default : false, build_by_default : false,