conda-forge.github.io icon indicating copy to clipboard operation
conda-forge.github.io copied to clipboard

ENH: minimally activated compilers

Open h-vetinari opened this issue 3 months ago • 29 comments

One unavoidable consequence of making compilers easily installable (whether as gcc_linux-64 or through the compilers metapackage), is that people and projects started using them, a lot.

This leads to friction because although we never promised to support use outside conda-forge, it is a de facto reality nowadays.

On top of that there are efforts to better handle build profiles (e.g. release/debug/etc.), c.f. conda-forge/ctng-compiler-activation-feedstock#157.

What I'm thinking about is that we should introduce a third level in the hierarchy between (currently):

  • ${<lang>_compiler}_<platform> (fully activated compiler, geared towards conda-forge)
  • ${<lang>_compiler}_impl_<platform> (complete dependencies, no activation)

into something like

  • ${<lang>_compiler}-cf_<platform> (fully activated compiler, geared towards conda-forge)
  • ${<lang>_compiler}_<platform> (minimally activated compiler, e.g. pointing to $PREFIX, but no extra flags)
  • ${<lang>_compiler}_impl_<platform> (complete dependencies, no activation)

That would allow external users of our compiler stack to avoid having to play around with stripping out flags, while conda-forge could keep all its default config (e.g. -O2 -DCMAKE_BUILD_TYPE=Release etc.) in the conda-forge-specific compiler flavours.

FYI @wolfv @ruben-arts @jaimergp @mgorny @rgommers CC @conda-forge/clang-compiler-activation @conda-forge/core

  • [x] https://github.com/conda-forge/clangdev-feedstock/pull/387
  • [x] https://github.com/conda-forge/clangdev-feedstock/pull/387
  • [x] https://github.com/conda-forge/openmp-feedstock/pull/193
  • [x] https://github.com/conda-forge/openmp-feedstock/pull/189
  • [x] https://github.com/conda-forge/cctools-and-ld64-feedstock/pull/91
  • [x] https://github.com/conda-forge/cctools-and-ld64-feedstock/pull/92
  • [x] https://github.com/conda-forge/cctools-and-ld64-feedstock/pull/93
  • [x] https://github.com/conda-forge/compiler-rt-feedstock/pull/159
  • [x] https://github.com/conda-forge/clangdev-feedstock/pull/390

h-vetinari avatar Sep 14 '25 17:09 h-vetinari

You can already use gcc, gxx, gfortran packages.

isuruf avatar Sep 14 '25 17:09 isuruf

Unfortunately the language platform format is baked into conda-build, so inserting cf_ into it will be non-trivial.

beckermr avatar Sep 14 '25 17:09 beckermr

You can already use gcc, gxx, gfortran packages.

I'm fine with making that the pattern, but it's not compatible with the way that clang / clangxx are currently set up on osx. I opened the issue here, because GCC is the most complicated compiler feedstock, but I'm talking about something across our entire compiler stack.

Unfortunately the language platform format is baked into conda-build, so inserting cf_ into it will be non-trivial.

We fully override this in the global pinning, so we could easily change the names of the compiler packages (assuming the respective outputs are installable). We could also introduce a separate name for the "minimal" compilers, but I liked the aspect that the <lang>-compilers metapackages would do the "more obvious thing", while we confine the cf-specific stuff into a package that the vast majority of people won't install by accident.

h-vetinari avatar Sep 14 '25 17:09 h-vetinari

This issue largely overlaps with https://github.com/conda-forge/conda-forge.github.io/issues/1998 and https://github.com/conda-forge/conda-forge.github.io/issues/2002, right?

rgommers avatar Sep 14 '25 18:09 rgommers

I already referenced the second issue (had forgotten about the first). To me at least, these two were more for discussing the issue(s), whereas this issue is a concrete proposal for how to solve this.

h-vetinari avatar Sep 14 '25 19:09 h-vetinari

To override in the pinnings we'd have to have compiler('c_cf') etc in recipes. That's not so much fun to me.

beckermr avatar Sep 14 '25 19:09 beckermr

To override in the pinnings we'd have to have compiler('c_cf') etc in recipes.

Not at all. It would suffice to do

 c_compiler:
-  - gcc                        # [linux]
-  - clang                      # [osx]
-  - vs2022                     # [win]
+  - gcc-cf                     # [linux]
+  - clang-cf                   # [osx]
+  - vs2022-cf                  # [win]

in the pinning, and so on for cxx_compiler and fortran_compiler, with no changes to individual recipes.

h-vetinari avatar Sep 14 '25 19:09 h-vetinari

Since there's already gcc, gxx, gfortran in this feedstock that does the minimal thing, I don't see the need to add another output here. So, I suggest you raise this in the clang-compiler-activation-feedstock

isuruf avatar Sep 14 '25 21:09 isuruf

Or in the conda-forge.github.io repo where you can talk about the entire compiler stack.

isuruf avatar Sep 14 '25 21:09 isuruf

Or in the conda-forge.github.io repo where you can talk about the entire compiler stack.

Transferred

h-vetinari avatar Sep 15 '25 06:09 h-vetinari

IMO, relying on activation scripts is the wrong solution for letting our compilers be used by users outside of conda-build. This is because we want the compilers to work in all sorts of build-systems and make it robust enough that users can't tell the difference between our compilers and the ones they usually see on their system. A solution should take into account that some build systems override CFLAGS, some don't really use CFLAGS or LDFLAGS and that g++ hello.cpp should work out of the box, etc.

In Linux with our gcc package the way things work is the following

  1. gcc_impl_linux-64 has all executables prefixed with x86_64-conda-linux-gnu- and no activation flags The compiler's default spec file has been customized to use a conda.specs file if it exists, but it doesn't exist in this package.
  2. gcc_linux-64 depends on gcc_impl_linux-64 only and adds CC, CFLAGS, LDFLAGS env variables.
  3. conda-gcc-specs - this package adds a conda.specs file that adds -isystem $CONDA_PREFIX/include to compile flags and -L $$CONDA_PREFIX/lib -Wl,-rpath,$CONDA_PREFIX/lib when linking.
  4. gcc depends on conda-gcc-specs (there's a variant that doesn't, but it's not default and not relevant to this conversation) and also has cc, gcc, cpp symlinks into the prefixed executables.

What this means is that if a user does g++ hello.cpp from an activated environment or /path/to/g++ hello.cpp from a not activated environment or an environment where the user has some values for CFLAGS, LDFLAGS, all of them will do the same thing. Also the user will not have to do g++ $CXXFLAGS hello.cpp $LDFLAGS and can just do g++ hello.cpp. Technically even without conda-gcc-specs the user can do g++ hello.cpp, but running the executable will sometimes fail because the dynamic loader will be able to load the system libstdc++.so.6, but that maybe old.

TLDR; in Linux g++ hello.cpp with just conda install gxx works perfectly without needing to activate the environment or use environment variables. On macOS, this is not the case since clang doesn't have a concept of spec files. (clang configuration files are not useful for this scenario). We can make macOS work like Linux too with a little bit of work.

isuruf avatar Sep 16 '25 15:09 isuruf

IMO, relying on activation scripts is the wrong solution for letting our compilers be used by users outside of conda-build.

I think the "unactivated" use of our compilers is a nice-to-have, but less of a priority to support (than our so-far-explicit lack thereof for any of our compilers) from my POV. Anyone using compilers is already happily using the compilers in activated environments.

But since GCC offers a mechanism to do this without activation scripts, that's great to use it IMO! However, we should also switch the compilers meta-package to depend on gcc / gxx / gfortran IMO.

We can make macOS work like Linux too with a little bit of work.

How do you envision that? I don't mind following this path, but we'd have to come up with some alternate output naming (or rename the existing clang / clangxx, which are just the binaries, not the symlinks with your mechanism).

Also, I'm guessing we won't be able to avoid activation on windows anyway...?

h-vetinari avatar Sep 16 '25 16:09 h-vetinari

I think this is a nice idea, and the proposed implementation sounds like a good compromise. And it will definitely make it easier for us to adjust the defaults for conda-forge builds in the future without affecting third parties.

mgorny avatar Sep 16 '25 16:09 mgorny

I think this is a nice idea, and the proposed implementation sounds like a good compromise.

@mgorny thank you for your input. Which idea in particular are you talking about here?

or rename the existing clang / clangxx, which are just the binaries, not the symlinks with your mechanism

clang, clangxx packages are already symlinks to clang-<major> executable in clang-<major> package.

How do you envision that? I don't mind following this path, but we'd have to come up with some alternate output naming (or rename the existing clang / clangxx, which are just the binaries, not the symlinks with your mechanism).

We can add support to clang to load a configuration file conda-clang.cfg that appends options in addition to the configuration file that prepends. Also add a conda-clang-cfg similar to conda-gcc-specs

Then we can downprioritize the clang * default_* variant and add a new clang * user_* variant that depends on conda-clang-cfg, clang-<major>, compiler-rt and other helper packages and also adds the symlinks.

isuruf avatar Sep 16 '25 16:09 isuruf

I think this is a nice idea, and the proposed implementation sounds like a good compromise.

@mgorny thank you for your input. Which idea in particular are you talking about here?

I was talking about the original idea from #c0, i.e. splitting off conda-forge specific activation. Even if we long term don't want people relying on activation scripts, they already are, and the split will permit us to change things without breaking them.

How do you envision that? I don't mind following this path, but we'd have to come up with some alternate output naming (or rename the existing clang / clangxx, which are just the binaries, not the symlinks with your mechanism).

We can add support to clang to load a configuration file conda-clang.cfg that appends options in addition to the configuration file that prepends. Also add a conda-clang-cfg similar to conda-gcc-specs

Then we can downprioritize the clang * default_* variant and add a new clang * user_* variant that depends on conda-clang-cfg, clang-<major>, compiler-rt and other helper packages and also adds the symlinks.

Well, config files is something Gentoo extensively uses in Clang (I helped implement them), but before you go down that rabbit hole, you should probably note that you may end up using a lot of them. Just FYI:

Scary
$ tree /etc/clang/
/etc/clang/
├── 20
│   ├── gentoo-linker.cfg
│   ├── gentoo-plugins.cfg
│   ├── gentoo-rtlib.cfg
│   ├── gentoo-runtimes.cfg
│   ├── gentoo-stdlib.cfg
│   ├── gentoo-unwindlib.cfg
│   ├── i386-gentoo-linux-gnu-clang++.cfg -> i386-pc-linux-gnu-clang++.cfg
│   ├── i386-gentoo-linux-gnu-clang.cfg -> i386-pc-linux-gnu-clang.cfg
│   ├── i386-gentoo-linux-gnu-clang-cpp.cfg -> i386-pc-linux-gnu-clang-cpp.cfg
│   ├── i386-pc-linux-gnu-clang++.cfg
│   ├── i386-pc-linux-gnu-clang.cfg
│   ├── i386-pc-linux-gnu-clang-cpp.cfg
│   ├── i386-unknown-linux-gnu-clang++.cfg -> i386-pc-linux-gnu-clang++.cfg
│   ├── i386-unknown-linux-gnu-clang.cfg -> i386-pc-linux-gnu-clang.cfg
│   ├── i386-unknown-linux-gnu-clang-cpp.cfg -> i386-pc-linux-gnu-clang-cpp.cfg
│   ├── i686-gentoo-linux-gnu-clang++.cfg -> i686-pc-linux-gnu-clang++.cfg
│   ├── i686-gentoo-linux-gnu-clang.cfg -> i686-pc-linux-gnu-clang.cfg
│   ├── i686-gentoo-linux-gnu-clang-cpp.cfg -> i686-pc-linux-gnu-clang-cpp.cfg
│   ├── i686-pc-linux-gnu-clang++.cfg
│   ├── i686-pc-linux-gnu-clang.cfg
│   ├── i686-pc-linux-gnu-clang-cpp.cfg
│   ├── i686-unknown-linux-gnu-clang++.cfg -> i686-pc-linux-gnu-clang++.cfg
│   ├── i686-unknown-linux-gnu-clang.cfg -> i686-pc-linux-gnu-clang.cfg
│   ├── i686-unknown-linux-gnu-clang-cpp.cfg -> i686-pc-linux-gnu-clang-cpp.cfg
│   ├── x86_64-gentoo-linux-gnu-clang++.cfg -> x86_64-pc-linux-gnu-clang++.cfg
│   ├── x86_64-gentoo-linux-gnu-clang.cfg -> x86_64-pc-linux-gnu-clang.cfg
│   ├── x86_64-gentoo-linux-gnu-clang-cpp.cfg -> x86_64-pc-linux-gnu-clang-cpp.cfg
│   ├── x86_64-gentoo-linux-gnux32-clang++.cfg -> x86_64-pc-linux-gnux32-clang++.cfg
│   ├── x86_64-gentoo-linux-gnux32-clang.cfg -> x86_64-pc-linux-gnux32-clang.cfg
│   ├── x86_64-gentoo-linux-gnux32-clang-cpp.cfg -> x86_64-pc-linux-gnux32-clang-cpp.cfg
│   ├── x86_64-pc-linux-gnu-clang++.cfg
│   ├── x86_64-pc-linux-gnu-clang.cfg
│   ├── x86_64-pc-linux-gnu-clang-cpp.cfg
│   ├── x86_64-pc-linux-gnux32-clang++.cfg
│   ├── x86_64-pc-linux-gnux32-clang.cfg
│   ├── x86_64-pc-linux-gnux32-clang-cpp.cfg
│   ├── x86_64-unknown-linux-gnu-clang++.cfg -> x86_64-pc-linux-gnu-clang++.cfg
│   ├── x86_64-unknown-linux-gnu-clang.cfg -> x86_64-pc-linux-gnu-clang.cfg
│   ├── x86_64-unknown-linux-gnu-clang-cpp.cfg -> x86_64-pc-linux-gnu-clang-cpp.cfg
│   ├── x86_64-unknown-linux-gnux32-clang++.cfg -> x86_64-pc-linux-gnux32-clang++.cfg
│   ├── x86_64-unknown-linux-gnux32-clang.cfg -> x86_64-pc-linux-gnux32-clang.cfg
│   └── x86_64-unknown-linux-gnux32-clang-cpp.cfg -> x86_64-pc-linux-gnux32-clang-cpp.cfg
├── 21
│   ├── gentoo-linker.cfg
│   ├── gentoo-plugins.cfg
│   ├── gentoo-rtlib.cfg
│   ├── gentoo-runtimes.cfg
│   ├── i386-gentoo-linux-gnu-clang++.cfg -> i386-pc-linux-gnu-clang++.cfg
│   ├── i386-gentoo-linux-gnu-clang.cfg -> i386-pc-linux-gnu-clang.cfg
│   ├── i386-gentoo-linux-gnu-clang-cpp.cfg -> i386-pc-linux-gnu-clang-cpp.cfg
│   ├── i386-pc-linux-gnu-clang++.cfg
│   ├── i386-pc-linux-gnu-clang.cfg
│   ├── i386-pc-linux-gnu-clang-cpp.cfg
│   ├── i386-unknown-linux-gnu-clang++.cfg -> i386-pc-linux-gnu-clang++.cfg
│   ├── i386-unknown-linux-gnu-clang.cfg -> i386-pc-linux-gnu-clang.cfg
│   ├── i386-unknown-linux-gnu-clang-cpp.cfg -> i386-pc-linux-gnu-clang-cpp.cfg
│   ├── i686-gentoo-linux-gnu-clang++.cfg -> i686-pc-linux-gnu-clang++.cfg
│   ├── i686-gentoo-linux-gnu-clang.cfg -> i686-pc-linux-gnu-clang.cfg
│   ├── i686-gentoo-linux-gnu-clang-cpp.cfg -> i686-pc-linux-gnu-clang-cpp.cfg
│   ├── i686-pc-linux-gnu-clang++.cfg
│   ├── i686-pc-linux-gnu-clang.cfg
│   ├── i686-pc-linux-gnu-clang-cpp.cfg
│   ├── i686-unknown-linux-gnu-clang++.cfg -> i686-pc-linux-gnu-clang++.cfg
│   ├── i686-unknown-linux-gnu-clang.cfg -> i686-pc-linux-gnu-clang.cfg
│   ├── i686-unknown-linux-gnu-clang-cpp.cfg -> i686-pc-linux-gnu-clang-cpp.cfg
│   ├── x86_64-gentoo-linux-gnu-clang++.cfg -> x86_64-pc-linux-gnu-clang++.cfg
│   ├── x86_64-gentoo-linux-gnu-clang.cfg -> x86_64-pc-linux-gnu-clang.cfg
│   ├── x86_64-gentoo-linux-gnu-clang-cpp.cfg -> x86_64-pc-linux-gnu-clang-cpp.cfg
│   ├── x86_64-gentoo-linux-gnux32-clang++.cfg -> x86_64-pc-linux-gnux32-clang++.cfg
│   ├── x86_64-gentoo-linux-gnux32-clang.cfg -> x86_64-pc-linux-gnux32-clang.cfg
│   ├── x86_64-gentoo-linux-gnux32-clang-cpp.cfg -> x86_64-pc-linux-gnux32-clang-cpp.cfg
│   ├── x86_64-pc-linux-gnu-clang++.cfg
│   ├── x86_64-pc-linux-gnu-clang.cfg
│   ├── x86_64-pc-linux-gnu-clang-cpp.cfg
│   ├── x86_64-pc-linux-gnux32-clang++.cfg
│   ├── x86_64-pc-linux-gnux32-clang.cfg
│   ├── x86_64-pc-linux-gnux32-clang-cpp.cfg
│   ├── x86_64-unknown-linux-gnu-clang++.cfg -> x86_64-pc-linux-gnu-clang++.cfg
│   ├── x86_64-unknown-linux-gnu-clang.cfg -> x86_64-pc-linux-gnu-clang.cfg
│   ├── x86_64-unknown-linux-gnu-clang-cpp.cfg -> x86_64-pc-linux-gnu-clang-cpp.cfg
│   ├── x86_64-unknown-linux-gnux32-clang++.cfg -> x86_64-pc-linux-gnux32-clang++.cfg
│   ├── x86_64-unknown-linux-gnux32-clang.cfg -> x86_64-pc-linux-gnux32-clang.cfg
│   └── x86_64-unknown-linux-gnux32-clang-cpp.cfg -> x86_64-pc-linux-gnux32-clang-cpp.cfg
├── gentoo-cet.cfg
├── gentoo-common.cfg
├── gentoo-common-ld.cfg
├── gentoo-gcc-install.cfg
├── gentoo-hardened.cfg
├── gentoo-hardened-ld.cfg
├── gentoo-runtimes.cfg
├── i386-gentoo-linux-gnu-clang++.cfg -> i386-pc-linux-gnu-clang++.cfg
├── i386-gentoo-linux-gnu-clang.cfg -> i386-pc-linux-gnu-clang.cfg
├── i386-gentoo-linux-gnu-clang-cpp.cfg -> i386-pc-linux-gnu-clang-cpp.cfg
├── i386-pc-linux-gnu-clang++.cfg
├── i386-pc-linux-gnu-clang.cfg
├── i386-pc-linux-gnu-clang-cpp.cfg
├── i386-unknown-linux-gnu-clang++.cfg -> i386-pc-linux-gnu-clang++.cfg
├── i386-unknown-linux-gnu-clang.cfg -> i386-pc-linux-gnu-clang.cfg
├── i386-unknown-linux-gnu-clang-cpp.cfg -> i386-pc-linux-gnu-clang-cpp.cfg
├── i686-gentoo-linux-gnu-clang++.cfg -> i686-pc-linux-gnu-clang++.cfg
├── i686-gentoo-linux-gnu-clang.cfg -> i686-pc-linux-gnu-clang.cfg
├── i686-gentoo-linux-gnu-clang-cpp.cfg -> i686-pc-linux-gnu-clang-cpp.cfg
├── i686-pc-linux-gnu-clang++.cfg
├── i686-pc-linux-gnu-clang.cfg
├── i686-pc-linux-gnu-clang-cpp.cfg
├── i686-unknown-linux-gnu-clang++.cfg -> i686-pc-linux-gnu-clang++.cfg
├── i686-unknown-linux-gnu-clang.cfg -> i686-pc-linux-gnu-clang.cfg
├── i686-unknown-linux-gnu-clang-cpp.cfg -> i686-pc-linux-gnu-clang-cpp.cfg
├── x86_64-gentoo-linux-gnu-clang++.cfg -> x86_64-pc-linux-gnu-clang++.cfg
├── x86_64-gentoo-linux-gnu-clang.cfg -> x86_64-pc-linux-gnu-clang.cfg
├── x86_64-gentoo-linux-gnu-clang-cpp.cfg -> x86_64-pc-linux-gnu-clang-cpp.cfg
├── x86_64-gentoo-linux-gnux32-clang++.cfg -> x86_64-pc-linux-gnux32-clang++.cfg
├── x86_64-gentoo-linux-gnux32-clang.cfg -> x86_64-pc-linux-gnux32-clang.cfg
├── x86_64-gentoo-linux-gnux32-clang-cpp.cfg -> x86_64-pc-linux-gnux32-clang-cpp.cfg
├── x86_64-pc-linux-gnu-clang++.cfg
├── x86_64-pc-linux-gnu-clang.cfg
├── x86_64-pc-linux-gnu-clang-cpp.cfg
├── x86_64-pc-linux-gnux32-clang++.cfg
├── x86_64-pc-linux-gnux32-clang.cfg
├── x86_64-pc-linux-gnux32-clang-cpp.cfg
├── x86_64-unknown-linux-gnu-clang++.cfg -> x86_64-pc-linux-gnu-clang++.cfg
├── x86_64-unknown-linux-gnu-clang.cfg -> x86_64-pc-linux-gnu-clang.cfg
├── x86_64-unknown-linux-gnu-clang-cpp.cfg -> x86_64-pc-linux-gnu-clang-cpp.cfg
├── x86_64-unknown-linux-gnux32-clang++.cfg -> x86_64-pc-linux-gnux32-clang++.cfg
├── x86_64-unknown-linux-gnux32-clang.cfg -> x86_64-pc-linux-gnux32-clang.cfg
└── x86_64-unknown-linux-gnux32-clang-cpp.cfg -> x86_64-pc-linux-gnux32-clang-cpp.cfg

3 directories, 125 files

Admittedly, some of that complexity is Gentoo-specific. We have made the mistake of originally using a single config directory for all Clang versions (we're in process of finally removing that). The split runtime files are used for bootstrap. It roughly goes like this:

$ clang-21 --version
clang version 21.1.1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm/21/bin
Build config: +assertions
Configuration file: /etc/clang/21/x86_64-pc-linux-gnu-clang.cfg
$ cat /etc/clang/21/x86_64-pc-linux-gnu-clang.cfg
# This configuration file is used by x86_64-pc-linux-gnu-clang driver.
@../x86_64-pc-linux-gnu-clang.cfg
@gentoo-plugins.cfg
@gentoo-runtimes.cfg
$ cat /etc/clang/x86_64-pc-linux-gnu-clang.cfg
# This configuration file is used by x86_64-pc-linux-gnu-clang driver.
@gentoo-common.cfg
@gentoo-common-ld.cfg
@gentoo-cet.cfg
$ cat /etc/clang/gentoo-common.cfg 
# This file contains flags common to clang, clang++ and clang-cpp.
@gentoo-gcc-install.cfg
@gentoo-hardened.cfg
# bug #870001
-include "/usr/include/gentoo/maybe-stddefs.h"
...

mgorny avatar Sep 16 '25 18:09 mgorny

To override in the pinnings we'd have to have compiler('c_cf') etc in recipes.

Not at all. It would suffice to do

c_compiler:

    • gcc # [linux]
    • clang # [osx]
    • vs2022 # [win]
    • gcc-cf # [linux]
    • clang-cf # [osx]
    • vs2022-cf # [win]

in the pinning, and so on for cxx_compiler and fortran_compiler, with no changes to individual recipes.

It just occurred to me but I guess we'll also need to change the recipes that override the compiler in their conda_build_config.yaml, and probably these that use {{ compiler('clang') }} explicitly (not 100% sure of that, I only recently learned that such a thing works :-)).

mgorny avatar Sep 30 '25 12:09 mgorny

I was talking about the original idea from #c0, i.e. splitting off conda-forge specific activation. Even if we long term don't want people relying on activation scripts, they already are, and the split will permit us to change things without breaking them.

It doesn't have to be long term. We can just work on removing reliance on activation scripts in cxx-compiler package etc.

isuruf avatar Sep 30 '25 16:09 isuruf

As a quick update, @isuruf did some great work towards this goal in https://github.com/conda-forge/clangdev-feedstock/pull/405 & https://github.com/conda-forge/clangdev-feedstock/pull/407

Now it looks like we're (partially) recreating a pattern of how this was implemented in gcc (with so-called spec files). As of the current state of https://github.com/conda-forge/clangdev-feedstock/pull/407, this would look like

GCC Clang
configuration files conda-gcc-specs handled via build strings
convenience output for bare compiler gcc-no-conda-specs clang-no-conda-cfg?

I'm not a big fan of the conda- moving around between the positive/negative variant, especially since this is an ouput that's related to conda-forge('s compilers), not conda. To unify these patterns, I suggested to repeat the pattern from gcc (e.g. a separate output for the .cfg files that configure clang), and to avoid the specific configuration file name (specs & cfg) for the outputs, instead using a neutral & common name for both:

GCC Clang
configuration files conda-forge-gcc-config conda-forge-clang-config
convenience output for bare compiler gcc-minimal clang-minimal

I wanted to make this part of the conversation a bit more visible. Would be happy to hear what other people think.

PS. Obviously there's many other colours in which to paint this bikeshed. I decided to put conda-forge first in the above, but I could similarly imagine {clang,gcc}-config-conda-forge or {clang,gcc}-config-cf

h-vetinari avatar Dec 19 '25 05:12 h-vetinari

The convenience output is something that is needed rarely, so I don't want to bikeshed on the name and spend a lot of time on this.

isuruf avatar Dec 19 '25 15:12 isuruf

The convenience output is something that is needed rarely

There's quite a bit of interest in this from various parties. I don't want to miss the opportunity to design this coherently and then have to live with it ~forever.

I don't want to bikeshed on the name and spend a lot of time on this.

Great, so you accept my above proposal for naming the outputs? Or do you have a better suggestion that I can quickly agree to?

FWIW, I think {gcc,clang}-minimal would hit the nail on the head in terms of expressiveness and ease of use. It's similar in spirit to other recent convenience outputs like python-freethreading. I care less about how we name the config file output, but I think we should have one for clang too, and come up with a consistent name (e.g. one of the several suggestions above).

I don't know why we'd be under time pressure on this, but I've got a PR ready to go, we just need to switch on the allowed outputs once we agree on their names.

h-vetinari avatar Dec 19 '25 20:12 h-vetinari

There's quite a bit of interest in this from various parties.

No, the interest is to use the ones with the cfg or specs files. There's very little interest in using the nocfg output. gcc-minimal would imply that the package is for minimally activated compilers which is not the case at all.

I like the original name gcc-no-conda-specs because it's very specific and technical and would be understood by power users only and these packages are for power users only. 99% of people would not need them and would be happy with just gcc and clang.

isuruf avatar Dec 19 '25 21:12 isuruf

gcc-minimal would imply that the package is for minimally activated compilers which is not the case at all.

That's a good point. It would be more minimal than what people actually want when we talk about "minimally activated" here. Fair enough that disabling the spec/cfg file is not relevant for most users. Even so, can we please spend a few minutes on designing this? Below are three choices, I'm hoping one of those would be fine for you.

The first is a previous suggestion, based on wanting to to unify this (and better reflecting "conda" -> "conda-forge"):

GCC Clang
configuration files conda-forge-gcc-specs conda-forge-clang-cfg
convenience output for bare compiler gcc-no-specs clang-no-cfg

That keeps the "power-user-only" aspect of reflecting the technical realities, but at least it'd be internally consistent. This had been leaning on naming the output for the configuration files after its content. But if we decide to lean on on the fact that the output pins the compiler itself, we could also keep the compiler name as first component

GCC Clang
configuration files gcc-specs clang-cfg
convenience output for bare compiler gcc-no-specs clang-no-cfg

Or, if we want to be verbose:

GCC Clang
configuration files gcc-conda-forge-specs clang-conda-forge-cfg
convenience output for bare compiler gcc-no-conda-forge-specs clang-no-conda-forge-cfg

I've excluded the variants with only "conda", because I think that is more misleading than either "conda-forge" or its absence.

h-vetinari avatar Dec 19 '25 22:12 h-vetinari

1 & 2: gcc-no-specs this is misleading because there's already a spec file and the conda spec file is additional.

3: conda-forge is bad since there's a defaults::conda-gcc-specs and having divergent names are bad.

My suggestion:

GCC Clang
configuration files conda-gcc-specs no need
convenience output for bare compiler gcc-no-conda-specs clang-no-conda-cfg

isuruf avatar Dec 19 '25 22:12 isuruf

Edited my suggestion

isuruf avatar Dec 19 '25 22:12 isuruf

Those arguments make sense to me. If it's shared across c-f & defaults, "conda" is accurate. I liked it better before the edit though; gcc-conda-specs & gcc-no-conda-specs is definitely more consistent than conda-gcc-specs & gcc-no-conda-specs.

conda-forge is bad since there's a defaults::conda-gcc-specs and having divergent names are bad.

Of course, any rename of existing outputs runs into this. OTOH, defaults just inherited https://github.com/conda-forge/ctng-compilers-feedstock/pull/91 and the other compiler work 1:1 (see here). And since we know how to do package renames (e.g. add new output with run_constrained: on the old one), this would resolve itself naturally once defaults picks up those changes.

Don't get me wrong, I can see the argument that a rename is not worth the effort, and that your suggestion minimises the amount of work we have to do now. It's just a bit of a hodgepodge in terms of naming & patterns, which makes me sad about cementing this for the long term.

no need

Even if we don't need it, wouldn't it make sense to use the same pattern (e.g. an output for the compiler configuration) between GCC & clang? Some divergences are unavoidable, but where we can avoid them, the less the better. So then

GCC Clang
configuration files gcc-conda-specs clang-conda-cfg
convenience output for bare compiler gcc-no-conda-specs clang-no-conda-cfg

would only need to rename a single output for GCC, and would otherwise not cause undue extra work.

h-vetinari avatar Dec 19 '25 22:12 h-vetinari

For clang, we'd need clang-conda-cfg_linux-64 etc and it won't be the same.

The issue with the name gcc-conda-specs and gcc-no-conda-specs is that it feels like they are opposites of each other. It feels like first one is gcc with the conda specs and the second one is gcc without the conda specs, but this is not the case. However conda-gcc-specs is clear that it is just conda specific gcc specs file.

isuruf avatar Dec 19 '25 22:12 isuruf

The issue with the name gcc-conda-specs and gcc-no-conda-specs is that it feels like they are opposites of each other.

Isn't that the case though? Since the specs output pins gcc_impl_<tgt>, and gcc is really just the sum of impl+specs (in other words, equivalent to a convenience wrapper around the specs package by default), that would be a valid interpretation.

I think that kind of consistency in naming would be a huge plus, even if we don't have an explicit cfg output for clang

h-vetinari avatar Dec 19 '25 23:12 h-vetinari

No, conda-gcc-specs doesn't include the unprefixed gcc.

isuruf avatar Dec 20 '25 00:12 isuruf

No, conda-gcc-specs doesn't include the unprefixed gcc.

I didn't say that it did. I said that the spec output is the same in terms of dependencies as gcc. The only difference is that gcc contains bin/gcc etc. symlinks, but those could just as well live in gcc-conda-specs if we wanted[^1], and then the result of installing either would be fully equivalent in the spec-ful case; spec-less gcc would keep the symlinks obviously.

That would give gcc-{,no-}conda-specs for an explicit choice of with/without specs, and gcc as the universal option that's compatible with either, defaulting to spec-ful.

[^1]: I understand if this is not the most appealing option from a purist's view about what content belongs in which output, but it would IMO lead to a more cohesive overall story on the usage side.

h-vetinari avatar Dec 20 '25 01:12 h-vetinari

I really don't like that suggestion. The symlinks should stay in gcc. It would be too confusing if it was any other way.

isuruf avatar Dec 22 '25 17:12 isuruf