bazelbuild / bazel

a fast, scalable, multi-language and extensible build system
https://bazel.build
Apache License 2.0
23.23k stars 4.07k forks source link

Custom compilation modes #24092

Open ansonos opened 3 weeks ago

ansonos commented 3 weeks ago

Description of the feature request:

It would be beneficial if users would be able to add their own "modes". Currently there are three hardcoded modes --compilation_mode (fastbuild|opt|dbg) (-c). That these modes come with default flags, which do not map well to all projects is a minor issue. The bigger issue is that probjects with more flag sets and configurations have no good way to specify a different output directory:

Bazel uses a different output directory for each different compilation mode, so you can switch between modes without needing to do a full rebuild every time.

Really the concept of compilation_modes is quite nice, but limited by being hardcoded.

Which category does this issue belong to?

Configurability, Core

What underlying problem are you trying to solve with this feature?

Different output dictionaries per user flag set.

Which operating system are you running Bazel on?

Linux

What is the output of bazel info release?

release 7.4.0

If bazel info release returns development version or (@non-git), tell us how you built Bazel.

No response

What's the output of git remote get-url origin; git rev-parse HEAD ?

-

Have you found anything relevant by searching the web?

https://bazel.build/docs/user-manual#compilation-mode

The --compilation_mode option (often shortened to -c, especially -c opt) takes an argument of fastbuild, dbg or opt, and affects various C/C++ code-generation options, such as the level of optimization and the completeness of debug tables. Bazel uses a different output directory for each different compilation mode, so you can switch between modes without needing to do a full rebuild every time.

  • fastbuild means build as fast as possible: generate minimal debugging information (-gmlt -Wl,-S), and don't optimize. This is the default. Note: -DNDEBUG will not be set.
  • dbg means build with debugging enabled (-g), so that you can use gdb (or another debugger).
  • opt means build with optimization enabled and with assert() calls disabled (-O2 -DNDEBUG). Debugging information will not be generated in opt mode unless you also pass --copt -g.

https://bazel.build/docs/user-manual#platform-suffix

Adds a suffix to the configuration short name, which is used to determine the output directory. Setting this option to different values puts the files into different directories, for example to improve cache hit rates for builds that otherwise clobber each others output files, or to keep the output files around for comparisons.

Could be used as a way around this issue, but is rather clunky (and flags x platfrom x configuration matrix explosive) as long as there is a better way.

Any other information, logs, or outputs that you want to share?

No response

benjaminp commented 3 weeks ago

788

ansonos commented 2 weeks ago

Somehow I didn't see that one, or it slipped my mind sorry about that.

I still think that this/#788 is a valid request. That it's not an easy change is really by side the point - if it's something that should be done.

gregestren commented 2 days ago

What problem are you trying to solve? I realize your core request is different output directories per "user flag set". But I assume the underlying problem is some kind of performance issue.

As noted at https://github.com/bazelbuild/bazel/issues/788#issuecomment-554145728, setting different output directories has mixed performance impact. It can help with local rebuilds with changing flags. But it can hurt remote cache efficiency, reduce caching prewarming, etc. depending on what the flags are and how they change the actions. If we set unique output paths for every possible flag combination, I think most users would see pretty bad performance loss.

--platform_suffix Could be used as a way around this issue, but is rather clunky (and flags x platfrom x configuration matrix explosive)

What makes this worse? Isn't is pretty much the same: instead of --compilation_mode=foo adding foo to output paths you have --config=foo adding foo to output paths? https://github.com/bazelbuild/bazel/issues/788#issuecomment-172937446 shows a complication. Are there others?

Also curious: what kind of project flag sets do you mean?

ansonos commented 1 day ago

Thanks for looking into my request :+1:

We have code that is compiled for debug, release and llvm (which differs more than just in flags). These flagsets differ in a few global flags that are applied to all files. We also have to multiply these sets by the platform/version that we're targeting, which again change/add to the global flags for all files. There is no way around these different flagset, but they are also not unbound. I think our upper limit is ~10 and usually ~3 distinctly uniquely unions of sets. From these unique unions >95% of the devs will build debug for a platform.

I want to prevent that the cache is destroyed for most of the developers if a few use the different flags (they'll not get cache hits but that's "fine"). (Maybe I do not understand how the cache works. We are trying to migrate to bazel right now and I have not seen any performance issues as we're not there yet, to see them.) I also want to be able to preserve the outputs from the builds, so that developers don't have to rebuild the output when switching back and forth between the configurations (maybe that's a no-issue with the bazel cache). On a similar note; developers should be able to read from the path how the output was created.

What makes --compilation_mode more compelling than just --config is that bazel is aware of the compilation modes and can select on them (maybe I'm wrong, but I think I saw examples). To do the same with configs I have to create a new setting, named awfully similar to compilation_mode, and add that to a config and in that config I then also have to set the platform suffix (which hopefully will not overwrite the platform dir/suffix/`experimental_platform_in_output_dir). And I would have to do that for every combination, because only the last suffix wins. An alternative might be to leverage platform flags(?), but I haven't looked into them yet.

At the end of the day it's not convenient or apparent how to solve multiple configurations/flag sets and I find it curious that not more projects have these type of issues.