> but would fail hard if you intend to support multiple release versions of an app, which happens often in the embedded world with multiple hardware targets, or self-hosted, large enterprise apps that require qualification sign-offs.
I don't have experience in this world, indeed.
But isn't "multiple release versions of an app" just "one application, with multiple different configurations"? The application code is the same (same version), the configuration (which is external to the application) is different.
Your build system takes your application code and the configuration as input, and outputs artifacts for that specific combination of inputs.
> But isn't "multiple release versions of an app" just "one application, with multiple different configurations"?
That would be nice (and evergreen), but that's not always the case. It's common to have different versions of the app released simultaneously, with different features and bugfixes shipped.
Think of Microsoft simultaneously supporting Windows 10 and 11, while still releasing patches for XP: they are all individual OSes that share some common code, but can't be detangled at build times[1]
The customer will be reluctant to upgrade major versions due to licensing costs and risk if breakage (your code, or their integrations), but still expect bugfixes (and only bugfixes) on their deployed versions, which you're contracted to provide. Using the evergreen approach.
I'm not convinced using build flags to manage which code is shipped is superior to release branches, I fall on the side of release branches because using bisect is invaluable.
1. I suppose as long as the build system is turing complete, one could hypothetically build Windows XP, 7, 8, 10 and 11 off the same codebase using flags. I would not envy that person.
I don't have experience in this world, indeed.
But isn't "multiple release versions of an app" just "one application, with multiple different configurations"? The application code is the same (same version), the configuration (which is external to the application) is different.
Your build system takes your application code and the configuration as input, and outputs artifacts for that specific combination of inputs.