Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions test/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,19 @@ def test_kselftest_merge_runs_right_after_config_and_before_default(self, linux)
names = [t.name for t in build.targets]
assert names == ["config", "kselftest-merge", "default", "kernel"]

def test_nonfatal_continues_on_failure(self, linux, mocker):
b = Build(tree=linux, targets=["config"])
target = mocker.MagicMock()
target.name = "kselftest"
target.nonfatal = True
target.dependencies = []
target.preconditions = []
target.commands = [Command(["false"]), Command(["true"])]
mocker.patch.object(b, "run_cmd", side_effect=[False, True])
mocker.patch.object(b, "check_artifacts", return_value=True)
result = b.build(target)
assert result.passed


class TestHeaders:
def test_basics(self, linux):
Expand Down
12 changes: 12 additions & 0 deletions test/test_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,18 @@ def test_no_exclude_for_gcc(self, build):
kselftest = Kselftest("kselftest", build)
assert not getattr(kselftest, "exclude_build_makevars", set())

def test_kselftest_is_nonfatal(self, build):
kselftest = Kselftest("kselftest", build)
assert kselftest.nonfatal

def test_kselftest_bpf_is_nonfatal(self, build):
kselftest_bpf = Kselftest("kselftest-bpf", build)
assert kselftest_bpf.nonfatal

def test_config_is_not_nonfatal(self, build):
config = Target("config", build)
assert not config.nonfatal

def test_kdir_set_to_build_dir(self, build):
build.toolchain.name = "gcc-14"
kselftest = Kselftest("kselftest", build)
Expand Down
7 changes: 5 additions & 2 deletions tuxmake/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,8 +599,11 @@ def build(self, target):
interactive=cmd.interactive,
exclude_build_makevars=exclude_keys,
):
fail = True
break
if target.nonfatal:
self.log("W: command failed, continuing (nonfatal target)")
else:
fail = True
break

if not fail and not self.check_artifacts(target):
fail = True
Expand Down
1 change: 1 addition & 0 deletions tuxmake/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def __init_config__(self):
self.runs_after = self.config["target"].get("runs_after", "").split()
self.preconditions = self.__split_cmds__("target", "preconditions")
self.commands = self.__split_cmds__("target", "commands")
self.nonfatal = self.config["target"].get("nonfatal", "").lower() == "true"
self.kconfig_add = self.__split_kconfigs__()
try:
artifacts = dict(self.config["artifacts"])
Expand Down
4 changes: 3 additions & 1 deletion tuxmake/target/kselftest-bpf.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ description = "Kernel BPF selftest (kselftest)"
# config options are needed to run all BPF tests but not currently included
# by the kselftest-merge target.
dependencies = kernel headers
commands = {make} -C tools/testing/selftests/ install
nonfatal = true
Copy link
Copy Markdown
Member

@bhcopeland bhcopeland Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in favour of nonfatal by default. A partial tarball is better than nothing, but silently passing a degraded build pushes debugging down to the CI consumer, who now has to dig through logs to notice anything broke. I get a partial kselftest file, could be seen as better rather than not having one at all.

A --nonfatal= CLI option could address that, but it's not much better: every pipeline would need to adopt it, and it still hides failures once enabled.

Could we instead keep the two-step make all && make -o all install change, but surface nonfatal failures as a visible warning in the build status e.g. a PASS_WITH_WARNINGS state or similar to what went down? That way, the partial tarball is still produced, CI can detect the degradation, and nothing is hidden.

Thinking out loud through this comment :)

Copy link
Copy Markdown
Member

@bhcopeland bhcopeland Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave the patch a go and still ended up with an empty tarball. Looking at it, -o all applies to the outer make, but the Makefile invokes a fresh sub-make per subdir that has its own install: all, so the same partial-build failure repeats.

Put together this. Which seems to keep the install step happy and was able to get bpf tarball out of it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the PASS_WITH_WARNINGS make sense, but lets do that in a followup PR, this PR is just get the build to create a tarball. And lets see how we can get bpf to build or target kselftest-bpf and create a new PR for that too.

does that make sense?

commands = {make} -C tools/testing/selftests/ all
&& {make} -o all -C tools/testing/selftests/ install
&& {tar_caf} {build_dir}/kselftest-bpf.tar{z_ext} -C {build_dir}/kselftest_bpf_install .

[makevars]
Expand Down
4 changes: 3 additions & 1 deletion tuxmake/target/kselftest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
description = "Kernel selftest (kselftest)"
dependencies = config
runs_after = kselftest-merge
commands = {make} -C tools/testing/selftests install
nonfatal = true
commands = {make} -C tools/testing/selftests all
&& {make} -o all -C tools/testing/selftests install
&& {tar_caf} {build_dir}/kselftest.tar{z_ext} -C {build_dir}/kselftest_install .

[makevars]
Expand Down
Loading