#1140755 clang-21: Uninstallable for cross builds

Package:
clang-21
Source:
clang-21
Description:
C, C++ and Objective-C compiler
Submitter:
Yavor Doganov
Date:
2026-06-27 15:47:02 UTC
Severity:
normal
Tags:
#1140755#5
Date:
2026-06-25 21:30:08 UTC
From:
To:
Packages that build-depend on clang cannot be cross built because
bin:clang from src:llvm-defaults depends on bin:clang-$MAJORVER which
in turn depends on binutils.  I used the attached patch to build
llvm-toolchain-21 on arm64/s390x.  Then I used the produced binary
packages and successfully cross built (on amd64 for arm64/s390x) a
bunch of packages that build-depend on clang, including the package
I'm interested in, libobjc2 (not yet in Debian).

We at the GNUstep team plan to package the GNUstep Objective-C runtime
which was specifically written for Clang, and to provide dual runtime
support on architectures where it will be available.  We've spent
considerable efforts to make the GNUstep stack cross-buildable during
the trixie release cycle and it would be a pity to lose that feature.

In case you consider applying the patch, the same should be done for
other (relevant) llvm-toolchain-* packages.  Thanks.

P.S.: I see that some packages (e.g., filament) build-depend on
clang:native, have a cross-specific make conditional in debian/rules
and pass --target accordingly.  This won't work in our case because
bin:gnustep-make must depend on clang and the :native annotation can
be used only for build-dependencies, IIRC.

#1140755#10
Date:
2026-06-26 11:07:47 UTC
From:
To:
Hi Yavor,

Thanks for addressing the wider audience for review.

I agree that there is a problem here, but the problem I see is a bit
bigger than what you describe.

Awesome. It's been a while that I ran into a GNUstep-related cross build
failure. Now I understand why.

It seems like your development packages declare a (runtime) dependency
on a clang package. This is unusual at best. Normally, libraries do not
depend on a toolchain. Can you give some background on why you think
this is needed?

You rightly indicate that your dependencies cannot use :native. Given
your patch, I expect that what you end up with is a host architecture
clang. This is not something you can actually run during a cross build.
While your dependencies may become satisfiable, your build fails upon
the first attempt to run the compiler. If it succeeds, you like
installed qemu-user-binfmt on the machine, but you cannot rely on that.

When clang links something, it runs /usr/bin/ld. This is not something
that binutils-for-host provides. Your patch breaks the very simple use
case of natively building and linking a hello world C source file using
clang. I would hope that clang's autopkgtests readily fail once your
patch is applied. Did you run them?

I am not sure where we want to go from here. clang is a multi-target
compiler, but it uses single-target binutils underneath. If you pass
-target, it calls out to prefixed binutils, so technically speaking we'd
need clang to depend on binutils-for-host for all architectures at the
same time (or use binutils-multiarch). Having clang depend on
binutils-multiarch may not be the worst of options. If we don't want
that, we likely need a clang-for-host package that can forward the
architecture constraint to the underlying binutils-for-host package.

If you look at cross build systems involving gcc, many of them have
learned that you can do a cross build by varying the compiler
executable. This approach would technically also work for clang as it
can parse its argv[0] and derive a target triplet from that. I'm not
sure that this is how many projects use clang. The other way is passing
a -target. How many projects reliably pass that? Which of these
approaches do we want to label the preferred approach?

I fear I'm adding more questions than answers.

Helmut

#1140755#17
Date:
2026-06-27 15:43:54 UTC
From:
To:
Helmut Grohne wrote:

I knew it was not that simple...

There's still #1094879; simpleagenda.app has exactly the same problem.
I recently fixed gnustep-sqlclient and edenmath.app (regression).

The most important reason is that occasionally we have to enforce a
non-default compiler for all GNUstep packages and it's easier to
control it from one package instead of doing sourceful uploads for ~60
packages.  TBH, the last time we did this was 15 years ago with GCC
4.7 and its libobjc transition.  But it's likely to occur much more
often with clang: libobjc2 supports only a subset of architectures
where clang is available, because one function is implemented in
assembly.  Adding support for more architectures is "simply" adding an
implementation in assembly for a new architecture.  So suppose all
GNUstep packages have this in their Build-Depends field:

  clang:native [amd64 arm64 armhf hurd-any i386 riscv64],
  libobjc2-dev [amd64 arm64 armhf hurd-any i386 riscv64],

If an implementation for loong64 is added, it would require correction
in debian/control for all packages and sourceful uploads in the right
order.  That's rather inconvenient.

Another reason is that a lot of users requested to make it easy to get
a capable development environment by installing just one package
(gnustep-devel or gnustep-core-devel).

That's indeed the case -- I had qemu-user-binfmt installed and that's
what confused me.  Removing it immediately shows the problem.  And I
can't explain why, but now I can reliably reproduce #1094879 which
would allow me to work on a fix that can be included upstream.

Of course you are right, that's so blatantly obvious.

Sadly, no; mea culpa.

Perhaps I'm misunderstanding something, but binutils-multiarch depends
on binutils, which would lead to the same problem we have now.

I guess all of these are questions for the LLVM maintainers.