Page MenuHomeFreeBSD

Support "variant" kernel configs, aka FOO-BAR
Needs ReviewPublic

Authored by cperciva on Jul 28 2025, 7:56 PM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Oct 3, 1:38 AM
Unknown Object (File)
Thu, Oct 2, 10:26 AM
Unknown Object (File)
Thu, Oct 2, 5:31 AM
Unknown Object (File)
Sat, Sep 20, 6:33 AM
Unknown Object (File)
Thu, Sep 18, 2:41 AM
Unknown Object (File)
Tue, Sep 16, 6:37 AM
Unknown Object (File)
Sep 4 2025, 7:00 PM
Unknown Object (File)
Sep 3 2025, 7:19 PM

Details

Reviewers
jhb
kevans
Summary

If KERNCONF=FOO-BAR is requested but there is no FOO-BAR configuration
file, construct one automatically:
include FOO
include "std.bar"
ident FOO-BAR

This also works recursively (KERNCONF=FOO-BAR-BAZ) given appropriate
sys/conf/std.* files.

Future commits will remove several sys/*/conf/*-* files and add some
additional sys/conf/std.* files.

Discussed with: kevans, jhb

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 65815
Build 62698: arc lint + arc unit

Event Timeline

Makefile.inc1
1758

This logic can't be here any more but the equivalent is in the kernconffile target now.

1796

This could change to taste, but personally I think the existing std.debug / std.nodebug files provide a good pattern to follow.

1824

Changes here are to create the /usr/obj/.../sys/KERNCONF directory first and then copy or construct a kernel configuration file inside that directory. I figured that was easier than dealing with "sometimes we're constructing a kernel configuration file and sometimes we're using an existing one intact".

Makefile.inc1
1796

I think @jhb had a good point in IRC, we should consider renaming std.debug/std.nodebug to uppercase suffix to draw the connection a little better, then drop :tl.

while we're at it, can we drop DEFAULT? it was not an inherently bad idea but the way it's actually used makes no sense, and it's extremely surprising if you don't know about it (which is quite likely as it's completely undocumented)

I'd support dropping DEFAULTS. It's a really bad way to accomplish things. It could be std.defaults in $MACHINE and we can drop that at the start of GENERIC and MINIMAL

But for 16 I'd like to replace config(8) finally.

I think @jhb had a good point in IRC, we should consider renaming std.debug/std.nodebug to uppercase suffix to draw the connection a little better, then drop :tl.

Ok, do we want std.NODEBUG, inc.NODEBUG, NODEBUG.inc, or some other spelling?

I think @jhb had a good point in IRC, we should consider renaming std.debug/std.nodebug to uppercase suffix to draw the connection a little better, then drop :tl.

Ok, do we want std.NODEBUG, inc.NODEBUG, NODEBUG.inc, or some other spelling?

i'd vote for std.NODEBUG, personally. We have some precedence for std.foo being config(5) format already, but *.inc is kind of all over the place. Alternatively, slapping a config- prefix on them, maybe (config-NODEBUG), but I don't really have strong feelings here.

I think @jhb had a good point in IRC, we should consider renaming std.debug/std.nodebug to uppercase suffix to draw the connection a little better, then drop :tl.

Ok, do we want std.NODEBUG, inc.NODEBUG, NODEBUG.inc, or some other spelling?

i'd vote for std.NODEBUG, personally. We have some precedence for std.foo being config(5) format already, but *.inc is kind of all over the place. Alternatively, slapping a config- prefix on them, maybe (config-NODEBUG), but I don't really have strong feelings here.

I guess the other question is, does changing the spelling help enough to justify potentially breaking users' existing (custom) kernel config files?

I think @jhb had a good point in IRC, we should consider renaming std.debug/std.nodebug to uppercase suffix to draw the connection a little better, then drop :tl.

Ok, do we want std.NODEBUG, inc.NODEBUG, NODEBUG.inc, or some other spelling?

i'd vote for std.NODEBUG, personally. We have some precedence for std.foo being config(5) format already, but *.inc is kind of all over the place. Alternatively, slapping a config- prefix on them, maybe (config-NODEBUG), but I don't really have strong feelings here.

I guess the other question is, does changing the spelling help enough to justify potentially breaking users' existing (custom) kernel config files?

I'm still fuzzy why it needs to be changed at all... and I've read through this. I don't think it's a good idea at all to rename here. I don't agree with john that this is a good way to make the connection (or that this is even a good feature). I'm not sure this has enough value to be worth it. We shouldn't be polishing the turd of 4.3BSD config anymore. we should be replacing it entirely. I won't oppose, but we keep laying new hacks that aren't quite consistent with the old hacks and maintain weird compat in some ways, but wantonly break it in others.

And let's not use .inc. We don't use that anywhere else. All std.* files are config syntax already. It's a weird convention, but we're kinda stuck with it.

tl;dr: Seems silly do to this for a set of one.

In D51602#1178876, @imp wrote:

tl;dr: Seems silly do to this for a set of one.

I would agree if it was just GENERIC-NODEBUG which we were talking about. But @markj tripped over this wanting GENERIC-SYSKALLER; I (and my GSoC students) have wanted GENERIC-TSLOG; and it would also apply to GENERIC-K[ACM]SAN configurations. Once we make use of this feature we'd be looking at something like a net reduction of 400 lines of code from the tree while simultaneously increasing the number of kernel configurations available.

But these are really niche speacial cases that will resort toba lot of proliferation of speacial case std.* files. There's notvone for TSLOG. And many of the profrered cases are not a good cross section of desired options, most of which are just an option. If anything it's showing just how creaky config(8) has become as different people try to shore it up in increasingly incompatible ways. Are you going to support doing multiple of these std files? NODEBUG and TSLOG seem like they would go together, for example.

Amd we still can't convey the difference between implied options, required options and some parts on only if other options are present very well...

In D51602#1178915, @imp wrote:

Are you going to support doing multiple of these std files? NODEBUG and TSLOG seem like they would go together, for example.

As I wrote in the commit message: "This also works recursively (KERNCONF=FOO-BAR-BAZ) given appropriate sys/conf/std.* files."

I was thinking specifically of GENERIC-NODEBUG-TSLOG when I wrote that.

So I only object to this if it is undocumented. Please add the appropriate documentation to build(7) and note it won't work with the old-school config(8) usage we still support. The biggest problem with redoing config is all the undocumented warts we've grown in it over the years... the second biggest is a tie between the documented warts and the not sufficiently expressive dependency language.

In D51602#1179421, @imp wrote:

Please add the appropriate documentation to build(7)

Will do. I'll also mention it in make.conf(5).

We have various other std.foo functions (especially in sys/arm/conf and sys/arm64/conf) and I think it might be surprising for GENERIC-APPLE to suddenly be a thing on arm64, especially given that GENERIC already includes std.apple. That is why I think you want a separate namespace (FOO.inc or the like) to clearly distinguish config files intended to be joined with other things, and ones that aren't. The case mismatch is also really odd and non-intuitive IMO, nor is it clear how "std" (standard?) maps to some notion of header/inc file. We already use .inc in other places (Makefiles in particular) for this sort of thing, hence why I think it is a more intuitive naming for general developers and new developers who haven't been hacking on kernel configs for embedded systems in the past.

Also, the GENERIC-FOO-BAZ idea of more than one suffix is not that crazy. We have this in CheriBSD now sadly:

GENERIC-MORELLO
GENERIC-MORELLO-MFS-ROOT
GENERIC-MORELLO-NOCAPREVOKE
GENERIC-MORELLO-NOCAPREVOKE-NODEBUG
GENERIC-MORELLO-NODEBUG
GENERIC-MORELLO-PURECAP
GENERIC-MORELLO-PURECAP-BENCHMARK
GENERIC-MORELLO-PURECAP-BENCHMARK-MFS-ROOT
GENERIC-MORELLO-PURECAP-BENCHMARK-NOCAPREVOKE
GENERIC-MORELLO-PURECAP-BENCHMARK-NOCAPREVOKE-NODEBUG
GENERIC-MORELLO-PURECAP-BENCHMARK-NODEBUG
GENERIC-MORELLO-PURECAP-BENCHMARK-NOSUBOBJECT
GENERIC-MORELLO-PURECAP-BENCHMARK-NOSUBOBJECT-NODEBUG
GENERIC-MORELLO-PURECAP-MFS-ROOT
GENERIC-MORELLO-PURECAP-NOCAPREVOKE
GENERIC-MORELLO-PURECAP-NOCAPREVOKE-NODEBUG
GENERIC-MORELLO-PURECAP-NODEBUG
GENERIC-MORELLO-PURECAP-NOSUBOBJECT
GENERIC-MORELLO-PURECAP-NOSUBOBJECT-NODEBUG
GENERIC-MORELLO-PURECAP-SUBOBJECT-STATS
GENERIC-MORELLO-PURECAP-SYZKALLER
GENERIC-MORELLO-PURECAP-SYZKALLER-NODEBUG

Where most of these are simple permutations. I don't really know how you'd implement it. I think you'd have to keep chopping off suffixes until you find a base config file to use?

In D51602#1179756, @jhb wrote:

We have various other std.foo functions (especially in sys/arm/conf and sys/arm64/conf) and I think it might be surprising for GENERIC-APPLE to suddenly be a thing on arm64, especially given that GENERIC already includes std.apple.

Good point, I had forgotten about the std.foo blobs in sys/*/conf. I'll rework this.

We have std.* files scattered through the tree too. It's in sys/arm/$VENDOR/std.$vendor and sys/arm/$VENDOR/std.$board as well. None of those files, thankfully, should be part of this. Constructing those config files is more complex because std.board will often include std.vendor. And it's mostly on arm only, so that's OK.

And if we must, please, let's not use .inc. That's already used for makefiles (mostly) and some assembler. It's too overloaded. We don't use it for config stuff currently in the tree. We should use something like .kcfg for this, imho, if we wanted to enumerate these things.

But also, let's not go nuts. Let's not have a scsi.kcfg, net.kcfg, etc. config(8) isn't expressive enough to handle the cross product of those with busses, etc. It can't tell the difference between the requires, implies and needs concepts (requires X -- fail if X isn't present, implies X -- set X option too, needs X -- only include if X is also included) that other systems can do.

So I've been noodling on this at the back of my head. After seeing jhb's cheri list, I think I have figured out one of the things that is nagging at me: This is Magic. Dashes in the filename sometimes are a file and sometimes not. And if we ever shipped a GENERIC-FOO that's more than just a simple include, all of a sudden the user's use of GENERIC-FOO changes. Also, there's no way in the pattern to unambiguously specify removing an option. Is 'nova' the negation of the 'va' option, or is it the inclusion of the 'nova' option. And no, we're not modifying config(8) so you can ask..

Let's take a step back. The problem we're trying to solve is that it's a bit of a pain to stitch together config files from parts. I'd prefer that we take the approach we've taken elsewhere of being explicit. 'make buildwork KERNCONF=IMP KERNGEN="GENERIC noip.kcfg fred.kcfg"' (this option iterates over its args doing include for each, with an ident $KERNCONF at the end) is more generic and easy to explain. If we really wanted to make it generic, we could also have KERNCONF_APPEND="options fred; nooptions va; device nonplussed" which would add the lines

options fred
nooptions va
device nonplussed

to the end of the config. We get a way from the magic of GENERIC-DEBUG name (though we could keep a smaller number of these around that would get heavy use like the instant example) It's more modular, can handle any number of situations and still wouldn't need the proliferation of .kcfg files to unambiguously specify a single option. This would allow full config file construction without the magic naming thing that's really eaten at me. Plus it would take a simplar number of lines to implement. Though perhaps this wouldn't work well with multiple KERNCONFs (though maybe it doesn't have to).