#1094879 gnustep-gui FTCBFS: configures for the build architecture during dh_auto_clean

#1094879#5
Date:
2025-01-31 16:47:08 UTC
From:
To:
gnustep-gui fails to cross build from source, because it configures
during dh_auto_clean without passing --host but passing a cross CC. As a
result this configure invocation and the dh_auto_clean operation fails.
The configuration is also quite useless, because whatever is configured
is subsequently deleted. The configure step can be inhibited by touching
two files. I'm attaching a patch for doing so. Once dh_auto_clean
passes, the rest of the package cross builds just fine. Please consider
applying the patch and talking to upstream to figure out a way of
running make distlcean without invoking configure.

Helmut

#1094879#10
Date:
2025-01-31 22:11:36 UTC
From:
To:
Helmut Grohne wrote:

Thanks for the report.

I'm sorry but I cannot reproduce this; running "sbuild --host=armhf"
on an amd64 system results in a successful build.

While preparing for the gnustep-multiarch transition I tried to
cross-build the whole GNUstep stack and of course gnustep-gui is a
central part of it.  It hard codes pkg-config in configure.ac but
somehow still builds successfully, AFAICT.  There are no other issues
and I just retried a cross build to confirm (using git master but
there are no changes there that could affect cross building).

#1094879#15
Date:
2025-01-31 22:17:25 UTC
From:
To:
tags 1094879 = unreprodicble moreinfo
thanks

#1094879#22
Date:
2025-01-31 22:29:48 UTC
From:
To:
Hi Yavor,

Oh. That's surprising indeed. You can see an example failure at
https://crossqa.debian.net/src/gnustep-gui. Could it be that you pass
-nc or --no-pre-clean to dpkg-buildpackage somehow? When building with
sbuild, this likely makes sense as it slightly speeds up a build where
cleaning is not necessary. It's not the sbuild default however.

Thank you very much for having put in this effort. I was quite surprised
to that it just worked after fixing the cleaning and now I know why.

Helmut

#1094879#27
Date:
2025-01-31 22:53:24 UTC
From:
To:
Helmut Grohne wrote:

For me it's suprusing what I see at:

That's realy puzzling, I honestly can't figure out what's going on.

No, I don't do that.  I only pass --no-clean if the build-depends are
not available on my system, and in such cases I pass --extra-package=
(as long as they're necessary).  I performed the test above with no
extra arguments, and my sbuild configuration file is bare.

#1094879#32
Date:
2025-02-01 06:55:32 UTC
From:
To:
Would you mind sharing a successful build log of yours for me to look
into? Diffing build logs is a powerful tool.

Helmut

#1094879#37
Date:
2025-02-01 07:35:22 UTC
From:
To:
Helmut Grohne wrote:

Sure; please find it attached (gzipped).

#1094879#42
Date:
2025-02-01 08:54:44 UTC
From:
To:
Being puzzled goes on. The log did not reveal much to me. A few
observations:
 * It actually does not use -nc (as you said) and really does run make
   distclean (as does the failing one).
 * make distclean does not run configure (unlike the failing one).

I added --debug=a to a local test build and this is what I get:

| dh_auto_clean -- --debug=a
|         make -j8 distclean --debug=a
| GNU Make 4.4.1
| Built for x86_64-pc-linux-gnu
| Copyright (C) 1988-2023 Free Software Foundation, Inc.
| License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
| This is free software: you are free to change and redistribute it.
| There is NO WARRANTY, to the extent permitted by law.
| Reading makefiles...
| Reading makefile 'GNUmakefile'...
| Reading makefile '/usr/share/GNUstep/Makefiles/common.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/config-noarch.make' (search path) (no ~ expansion)...
| Reading makefile '/etc/GNUstep/GNUstep.conf' (search path) (don't care) (no ~ expansion)...
| Reading makefile '/build/reproducible-path/gnustep-gui-0.31.1/debian/.debhelper/generated/_source/home/.GNUstep.conf' (search path) (don't care) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/names.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/config.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/library-combo.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/messages.make' (search path) (no ~ expansion)...
| Reading makefile 'gui.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/Additional/base.make' (search path) (don't care) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/target.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/filesystem.make' (search path) (no ~ expansion)...
| make[2]: Entering directory '/build/reproducible-path/gnustep-gui-0.31.1'
| This is gnustep-make 2.9.2. Type 'make print-gnustep-make-help' for help.
| Running in gnustep-make version 2 strict mode.
| Reading makefile 'Version' (search path) (no ~ expansion)...
| Reading makefile 'GNUmakefile.preamble' (search path) (don't care) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/aggregate.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/Master/serial-subdirectories.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/rules.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/Master/rules.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/Master/source-distribution.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/Master/rpm.make' (search path) (no ~ expansion)...
| Reading makefile '/usr/share/GNUstep/Makefiles/Master/deb.make' (search path) (no ~ expansion)...
| Reading makefile 'GNUmakefile.postamble' (search path) (no ~ expansion)...
| Using jobserver controller fifo:/tmp/GMfifo269
| Updating makefiles....
|  Considering target file 'GNUmakefile'.
|   Looking for an implicit rule for 'GNUmakefile'.
|    Trying pattern rule '%: %.m' with stem 'GNUmakefile'.
|    Trying implicit prerequisite 'GNUmakefile.m'.
|    Not found 'GNUmakefile.m'.
|    Trying harder.
|    Trying pattern rule '%: %.m' with stem 'GNUmakefile'.
|    Trying implicit prerequisite 'GNUmakefile.m'.
|    Looking for a rule with intermediate file 'GNUmakefile.m'.
|     Avoiding implicit rule recursion for rule '%: %.m'.
|    No implicit rule found for 'GNUmakefile.m'.
|    Rejecting rule '%: %.m' due to impossible prerequisite 'GNUmakefile.m'.
|   No implicit rule found for 'GNUmakefile'.
|  Finished prerequisites of target file 'GNUmakefile'.
|  No need to remake target 'GNUmakefile'.
|  Considering target file '/usr/share/GNUstep/Makefiles/common.make'.
|  Finished prerequisites of target file '/usr/share/GNUstep/Makefiles/common.make'.
|  No need to remake target '/usr/share/GNUstep/Makefiles/common.make'.
|  Considering target file '/usr/share/GNUstep/Makefiles/config-noarch.make'.
|  Finished prerequisites of target file '/usr/share/GNUstep/Makefiles/config-noarch.make'.
|  No need to remake target '/usr/share/GNUstep/Makefiles/config-noarch.make'.
|  Considering target file '/etc/GNUstep/GNUstep.conf'.
|  Finished prerequisites of target file '/etc/GNUstep/GNUstep.conf'.
|  No need to remake target '/etc/GNUstep/GNUstep.conf'.
|  Considering target file '/build/reproducible-path/gnustep-gui-0.31.1/debian/.debhelper/generated/_source/home/.GNUstep.conf'.
|   File '/build/reproducible-path/gnustep-gui-0.31.1/debian/.debhelper/generated/_source/home/.GNUstep.conf' does not exist.
|  Finished prerequisites of target file '/build/reproducible-path/gnustep-gui-0.31.1/debian/.debhelper/generated/_source/home/.GNUstep.conf'.
|  Must remake target '/build/reproducible-path/gnustep-gui-0.31.1/debian/.debhelper/generated/_source/home/.GNUstep.conf'.
|  Successfully remade target file '/build/reproducible-path/gnustep-gui-0.31.1/debian/.debhelper/generated/_source/home/.GNUstep.conf'.
|  Considering target file '/usr/share/GNUstep/Makefiles/names.make'.
|  Finished prerequisites of target file '/usr/share/GNUstep/Makefiles/names.make'.
|  No need to remake target '/usr/share/GNUstep/Makefiles/names.make'.
|  Considering target file '/usr/share/GNUstep/Makefiles/config.make'.
|  Finished prerequisites of target file '/usr/share/GNUstep/Makefiles/config.make'.
|  No need to remake target '/usr/share/GNUstep/Makefiles/config.make'.
|  Considering target file '/usr/share/GNUstep/Makefiles/library-combo.make'.
|  Finished prerequisites of target file '/usr/share/GNUstep/Makefiles/library-combo.make'.
|  No need to remake target '/usr/share/GNUstep/Makefiles/library-combo.make'.
|  Considering target file '/usr/share/GNUstep/Makefiles/messages.make'.
|  Finished prerequisites of target file '/usr/share/GNUstep/Makefiles/messages.make'.
|  No need to remake target '/usr/share/GNUstep/Makefiles/messages.make'.
|  Considering target file 'gui.make'.
|   File 'gui.make' does not exist.
|   Considering target file 'gui.make.in'.
|    Looking for an implicit rule for 'gui.make.in'.
|     Trying pattern rule '%: %.m' with stem 'gui.make.in'.
|     Trying implicit prerequisite 'gui.make.in.m'.
|     Not found 'gui.make.in.m'.
|     Trying harder.
|     Trying pattern rule '%: %.m' with stem 'gui.make.in'.
|     Trying implicit prerequisite 'gui.make.in.m'.
|     Looking for a rule with intermediate file 'gui.make.in.m'.
|      Avoiding implicit rule recursion for rule '%: %.m'.
|     No implicit rule found for 'gui.make.in.m'.
|     Rejecting rule '%: %.m' due to impossible prerequisite 'gui.make.in.m'.
|    No implicit rule found for 'gui.make.in'.
|   Finished prerequisites of target file 'gui.make.in'.
|   No need to remake target 'gui.make.in'.
|   Considering target file 'Version'.
|    Looking for an implicit rule for 'Version'.
|     Trying pattern rule '%: %.m' with stem 'Version'.
|     Trying implicit prerequisite 'Version.m'.
|     Not found 'Version.m'.
|     Trying harder.
|     Trying pattern rule '%: %.m' with stem 'Version'.
|     Trying implicit prerequisite 'Version.m'.
|     Looking for a rule with intermediate file 'Version.m'.
|      Avoiding implicit rule recursion for rule '%: %.m'.
|     No implicit rule found for 'Version.m'.
|     Rejecting rule '%: %.m' due to impossible prerequisite 'Version.m'.
|    No implicit rule found for 'Version'.
|   Finished prerequisites of target file 'Version'.
|   No need to remake target 'Version'.
|   Considering target file 'configure'.
|    Looking for an implicit rule for 'configure'.
|     Trying pattern rule '%: %.m' with stem 'configure'.
|     Trying implicit prerequisite 'configure.m'.
|     Not found 'configure.m'.
|     Trying harder.
|     Trying pattern rule '%: %.m' with stem 'configure'.
|     Trying implicit prerequisite 'configure.m'.
|     Looking for a rule with intermediate file 'configure.m'.
|      Avoiding implicit rule recursion for rule '%: %.m'.
|     No implicit rule found for 'configure.m'.
|     Rejecting rule '%: %.m' due to impossible prerequisite 'configure.m'.
|    No implicit rule found for 'configure'.
|   Finished prerequisites of target file 'configure'.
|   No need to remake target 'configure'.
|  Finished prerequisites of target file 'gui.make'.
|  Must remake target 'gui.make'.
| Need a job token; we don't have children
| GNUmakefile.postamble:81: update target 'gui.make' due to: target does not exist
| if [ -x config.status ]; then \
|   ./config.status --recheck && ./config.status; \
| else \
|   ./configure; \
| fi

Once configure is invoked, things go bad.

From what I see, GNUmakefile sets:

| GNUSTEP_LOCAL_ADDITIONAL_MAKEFILES=gui.make

and then does

| include $(GNUSTEP_MAKEFILES)/common.make

which comes from gnustep-make and does

| ifneq ($(GNUSTEP_LOCAL_ADDITIONAL_MAKEFILES),)
| include $(GNUSTEP_LOCAL_ADDITIONAL_MAKEFILES)
| endif

which is combined with GNUmakefile.postamble as included via

| include GNUmakefile.postamble

and contains

| gui.make: gui.make.in Version configure
|         if [ -x config.status ]; then \
|           ./config.status --recheck && ./config.status; \
|         else \
|           ./configure; \
|         fi

and thus remakes gui.make as it does not exist.

Would you happen to see where this chain of logic fails for your build
and why it ends up not remaking gui.make? Consider adding --debug=a to
your make distclean invocation and comparing (or giving me the output to
compare).

Thanks for bearing with me.

Helmut

#1094879#47
Date:
2025-02-01 17:47:18 UTC
From:
To:
Helmut Grohne wrote:

Running configure without arguments is the culprit, yes.

Here is the problem but I don't understand why it happens.  From my
log at the end of this prerequisite check:

| Finished prerequisites of target file 'gui.make'.
|   Prerequisite 'gui.make.in' is older than target 'gui.make'.
|   Prerequisite 'Version' is older than target 'gui.make'.
|   Prerequisite 'configure' is older than target 'gui.make'.

How it happens that the gui.make target needs to be rebuilt in your
case?  I attach my build log with --debug=a entirely as I'm afraid of
making a mistake while cutting stuff you're not interested in.  I'll
just make another try with the official package in unstable, obtained
with apt-get source.

Definitely.

Please, I'm grateful for all of your efforts in different areas and
I'm probably the most interested person on this planet to get
gnustep-gui cross-built on the official infrastructure.  I am also
curious about this problem, although life has thought me that in such
cases it's something innocent and obvious but you just can't spot it
initially.

#1094879#52
Date:
2025-02-02 15:43:26 UTC
From:
To:
Yavor Doganov wrote:
build.  I'm not attaching the log as it's basically the same.

#1094879#57
Date:
2025-02-01 21:14:55 UTC
From:
To:
I fear I am not seeing the cause yet. From reading the log, it very much
seems to me that your source package would contain a gui.make. In your
log, it says

|  Considering target file 'gui.make'.
|   Considering target file 'gui.make.in'.

whereas in my log it says

|  Considering target file 'gui.make'.
|   File 'gui.make' does not exist.

and this leads me to conclude that gui.make initially exists in your
build for some reason while it does not exist in the uploaded Debian
source package. Incidentally, what my proposed patch does is creating it
before running make distclean.

Your log also shows that make distclean ends up removing gui.make (as
also happens for me). Unfortunately, the second make distclean that also
passes doc=yes is not run with --debug=a, so we do not see how it
evaluates gui.make, but as it is not running configure, it probably
works the same way as the first make distclean. I therefore conclude
that I am missing an important detail here.

Would you disclose what type of filesystem your build environment uses
for storing the build tree? In my case (and crossqa.d.n) it is tmpfs.

While I find the failure quite plausible now, I am lacking an
explanation for the behaviour I see in your log. Clearly, the first
distclean does remove gui.make and equally clearly, the second distclean
does not run configure. As the first distclean finds a gui.make, a very
plausible explanation would be that gui.make actually does exist when
running the second distclean, but what would create it or prevent it
from being deleted?

I'm running out of ideas on how to debug this.

Helmut

#1094879#62
Date:
2025-02-05 16:13:27 UTC
From:
To:
That's basically exactly the same bug as agenda.app #1094007.  But the
agenda.app bug is 100% reproducible with debuild, sbuild or pbuilder
while this one is not.  The fact that agenda.app sets local.make and
config.h as prerequisites of the "before-all" target shouldn't matter
because dh_auto_clean builds the "distclean" target.  JFTR, I still
cannot reproduce this bug if I add gui.make and config.make as
prerequisites of "before-all" in gnustep-gui's GNUmakefile.postamble.

At least I understood why all of this happens -- it's because of
changes in GNU make 4.4 and 4.4.1, properly documented in NEWS.

Since your patch doesn't do any harm I'll apply it after the
gnustep-multiarch transition (there are still some sourceful uploads
of rdeps pending so I don't want to disrupt things with another
gnustep-gui upload now).

Answers to your questions below:

On Sat, 01 Feb 2025 23:14:55 +0200, Helmut Grohne wrote:

That's definitely not the case.  It doesn't exist in the .orig.tar.gz
and in my tree.  Only configure can create it but it's not being run.
I think GNU make's messages are confusing, they are the same on
bookworm which makes me think that in your environment GNU make is
taking a different decision when parsing makefiles and deciding which
targets must be rebuilt.  Why it happens is a mystery to me.

Yes, that's a rule in GNUmakefile.postamble:

| after-distclean::
|         rm -f config.status config.log config.cache TAGS config.make gui.make

Yes, I can confirm it works the same way.  I forgot to add it, sorry.

It's the default, ext4.

What happens if you do a native build in your environment?  Logic
dictates that it would run configure in the clean target, just like it
does for a cross build.  But this doesn't happen on the official
buildds.  (It also doesn't happen for agenda.app which was uploaded in
October while the new GNU make release was uploaded in December.)

Likewise.  I am very curious to find the cause because I hate leaving
questions unanswered, they are like worms eating my brain constantly.

#1094879#69
Date:
2025-02-05 17:43:06 UTC
From:
To:
Now it gets even more mysterious to me. The native build succeeds in my
sbuild/unshare environment whereas the cross build fails. Starting with
the dpkg-buildpackage invocation, the builds look exactly the same
(except for dpkg-buildpackage printing a different host architecture)
until they reach this:

| dh_auto_clean -- doc=yes
|         make -j8 distclean doc=yes
| make[2]: Entering directory '/build/reproducible-path/gnustep-gui-0.31.1'
| This is gnustep-make 2.9.2. Type 'make print-gnustep-make-help' for help.
| Running in gnustep-make version 2 strict mode.

The native build proceeds:

| rm -rf ./*~ ./obj
| Making clean in Source ...
| rm -rf ./*~ ./obj
| rm -f libgnustep-gui.def
| ...

Whereas the cross build fails:

| if [ -x config.status ]; then \
|   ./config.status --recheck && ./config.status; \
| else \
|   ./configure; \
| fi

I tried a few host architectures to see whether it would depend on the
precise architecture, but it seems to be a general cross/native
difference.

Would you mind deferring this issue? Prioritizing the gnustep-multiarch
transition seems more urgent to me as well and if you figure out the
similar case where it is reproducible right now, maybe this one is
solved as well?

Helmut

#1094879#74
Date:
2025-02-06 17:59:54 UTC
From:
To:
Helmut Grohne wrote:

That's actually a good outcome because it presumably will help you
find the real cause -- something in your cross environment setup makes
GNU make behave differently.  I anticipate it won't be easy to find
out what it is and unfortunately I can't help you in this quest.

FTR, I'm not using the new sbuild "unshare" feature as it slows down
builds for me on my most powerful marchine (which is not so powerful).
I don't know if it helps you but might give you a clue.  TTBOMK the
official buildds already switched to "unshare" so this is perhaps an
unimportant detail, irrelevant to this bug.

Sure, I was going to suggest the same.

#1094879#81
Date:
2026-06-29 08:39:53 UTC
From:
To:
We believe that the bug you reported is fixed in the latest version of
gnustep-gui, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 1094879@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Yavor Doganov <yavor@gnu.org> (supplier of updated gnustep-gui package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@ftp-master.debian.org)
Format: 1.8
Date: Sat, 27 Jun 2026 22:09:59 +0300
Source: gnustep-gui
Architecture: source
Version: 0.32.0-5
Distribution: unstable
Urgency: medium
Maintainer: Debian GNUstep maintainers <pkg-gnustep-maintainers@lists.alioth.debian.org>
Changed-By: Yavor Doganov <yavor@gnu.org>
Closes: 1094879
Changes:
 gnustep-gui (0.32.0-5) unstable; urgency=medium
 .
   * debian/patches/cross.patch: New; fix FTCBFS (Closes: #1094879).
   * debian/salsa-ci.yml: New file; extend the standard recipe to test the
     cross, nocheck and nodoc build profiles.
   * debian/templates/control.m4 (Build-Depends): Switch to debhelper
     compat level 14.
     (Depends): Remove ${misc:Depends} and ${shlibs:Depends}.
     (Priority): Remove; redundant.
     (Standards-Version): Claim compliance with 4.7.4.
   * debian/control: Regenerate.
   * debian/copyright: Update copyright years.
Checksums-Sha1:
 8f84cf25a77fe0c1a964fdf5ee4f18cc9b279212 3098 gnustep-gui_0.32.0-5.dsc
 663f9a80715cd26f6cf9429048236437db25462a 22752 gnustep-gui_0.32.0-5.debian.tar.xz
 9aeadcbffaa48fa2942f76f894a42b34de64a9d0 13460 gnustep-gui_0.32.0-5_source.buildinfo
Checksums-Sha256:
 89443bf8bf1f8ae16a95352e66dcb3586818ff7b3befa529215b9f6d7a2dd51e 3098 gnustep-gui_0.32.0-5.dsc
 f8d7b869d46cb7489f9f79270723c4d9abbf0740a184ec36300755f212893355 22752 gnustep-gui_0.32.0-5.debian.tar.xz
 912934ed89c7eb8d45d504e715f41af2c50ea9f6395979e0d204c3c983675ed2 13460 gnustep-gui_0.32.0-5_source.buildinfo
Files:
 3025a23382fc4220cba9aa99ae82d945 3098 gnustep optional gnustep-gui_0.32.0-5.dsc
 8eb9142f7b66e499b57977a42b7958f2 22752 gnustep optional gnustep-gui_0.32.0-5.debian.tar.xz
 c0076ece96a71c2a54dd86bd6b5ac2af 13460 gnustep optional gnustep-gui_0.32.0-5_source.buildinfo
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEtgob82PcExn/Co6JEWhSvN91FcAFAmpCJIgACgkQEWhSvN91
FcD4Zg/9HUhxvfs7s6DpDyT8WV9OE0RmQldX2NihH3XZEx2sZ03BwFA8PV9j44EJ
VbPonIvD3aZl9dRSucuc7ieDoNTEApMZwIEuCPAFvgzVm9UwBjmSyh2Yag0yBdCB
xhs2U7uUG6ibww+oNSpOp3a8GGuSY5IYfsdOZderfKa5wsRqHjHAI3hiQ7ns+KZY
9LlKACzythJEJtk8rvvxv865dFlUkTHfEbdid/rRt71sjQw4YPwHjU1B7Zawu/Qp
1EF26HNLzJDXn1OKmv2A0umrJt9kaHAOb5isYtV0GDDog6G+UwW3iEFg4tMLZP1c
x4INQjzjOumNgCMRp5bpme44V9/aXWasndgzJb2j2aQNgO5iGnDAMaK2oKqe7jgt
Z+1RxYknjWrKKlXJRftnYwbO8+yagBYai58JsQQiCVmnEhs9iLm1bHGhPO5qJoR/
lx4yclZtRxEDJYS2+IRitZK2vc5899DdNTijtC9JK3BiiVhdGVQHxMy28v2jrIW8
JGMOqVp9Fs46onAwAkNGtkF3CX2USe5aFqyKNJ1s/vYRR/pfF7MPP2aP+n7Fl2ux
/vN5L/cW+0JGrEB369DTRaacQUE+TPv7ohkrMz6P9zi5EKxJATNbpp9abBYeApX6
2Vpvv/H/J3jovSyeshaJpLDfH5FUM28ir2Mxeoj2l54W6JBWvd8=
=h3PG
-----END PGP SIGNATURE-----