Package: dpkg-dev
Version: 1.22.11
Severity: normal

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hi! I've just noted a strange behaviour of buildflags.mk. In short, including
the file seems to remove some level of string quoting from preprocessor flags
defined with DEB_CPPFLAGS_MAINT_APPEND, almost as if the value was passed to a
shell one too many times. It is simpler to explain this with an example.

Let's suppose the upstream software requires you to define a preprocessor
variable with a string value, like this one:

    $ cat main.c
    #include <stdio.h>
    int main(void) {
        puts(FOO);
        return 0;
    }

Let's also add a control and changelog file so that we can build the package:

    $ cat debian/control
    Source: testpackage
    Section: devel
    Priority: optional
    Maintainer: Andrea Pappacoda <and...@pappacoda.it>
    Build-Depends:
     debhelper-compat (= 13),
     dpkg-build-api (= 1),
    Standards-Version: 4.7.0
    X-Style: black

    Package: testpackage
    Architecture: any
    Multi-Arch: foreign
    Depends:
     ${misc:Depends},
     ${shlibs:Depends},
    Description: test package
     This is a test package

    $ cat debian/changelog
    testpackage (1.0-1) UNRELEASED; urgency=medium

      * Initial release. (Closes: #XXXXXX)

     -- Andrea Pappacoda <and...@pappacoda.it>  Fri, 23 Aug 2024 22:27:04 +0200

Finally, let's add a working rules file:

    $ cat debian/rules
    #!/usr/bin/make -f

    export DEB_CPPFLAGS_MAINT_APPEND = -DFOO='"string_value"'

    %:
        dh $@ --buildsystem=none

    override_dh_auto_build:
        $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o main main.c

    override_dh_auto_test:
        ./main

Let's now build the package with dpkg-buildpackage:

    $ dpkg-buildpackage
    dpkg-buildpackage: info: source package testpackage
    dpkg-buildpackage: info: source version 1.0-1
    dpkg-buildpackage: info: source distribution UNRELEASED
    dpkg-buildpackage: info: source changed by Andrea Pappacoda
<and...@pappacoda.it>
     dpkg-source --diff-ignore=true --tar-ignore=true --before-build .
    dpkg-buildpackage: info: host architecture amd64
     debian/rules clean
    dh clean --buildsystem=none
       dh_auto_clean -O--buildsystem=none
       dh_autoreconf_clean -O--buildsystem=none
       dh_clean -O--buildsystem=none
     dpkg-source --diff-ignore=true --tar-ignore=true -b .
    dpkg-source: warning: no source format specified in debian/source/format,
see dpkg-source(1)
    dpkg-source: warning: native package version may not have a revision
    dpkg-source: warning: source directory 'testpackage' is not
<sourcepackage>-<upstreamversion> 'testpackage-1.0'
    dpkg-source: info: using source format '1.0'
    dpkg-source: info: building testpackage in testpackage_1.0-1.tar.gz
    dpkg-source: info: building testpackage in testpackage_1.0-1.dsc
     debian/rules binary
    dh binary --buildsystem=none
       dh_update_autotools_config -O--buildsystem=none
       dh_autoreconf -O--buildsystem=none
       dh_auto_configure -O--buildsystem=none
       debian/rules override_dh_auto_build
    make[1]: Entering directory '/tmp/tmp.RvxkGPOuQf/testpackage'
    cc -Wdate-time -D_FORTIFY_SOURCE=2 -DFOO='"string_value"' -g -O2
- -Werror=implicit-function-declaration -ffile-prefix-
map=/tmp/tmp.RvxkGPOuQf/testpackage=. -fstack-protector-strong -fstack-clash-
protection -Wformat -Werror=format-security -fcf-protection -Wl,-z,relro -o
main main.c
    make[1]: Leaving directory '/tmp/tmp.RvxkGPOuQf/testpackage'
       debian/rules override_dh_auto_test
    make[1]: Entering directory '/tmp/tmp.RvxkGPOuQf/testpackage'
    ./main
    string_value
    make[1]: Leaving directory '/tmp/tmp.RvxkGPOuQf/testpackage'
       create-stamp debian/debhelper-build-stamp
       dh_testroot -O--buildsystem=none
       dh_prep -O--buildsystem=none
       dh_auto_install --destdir=debian/testpackage/ -O--buildsystem=none
       dh_installdocs -O--buildsystem=none
       dh_installchangelogs -O--buildsystem=none
       dh_installsystemduser -O--buildsystem=none
       dh_perl -O--buildsystem=none
       dh_link -O--buildsystem=none
       dh_strip_nondeterminism -O--buildsystem=none
       dh_compress -O--buildsystem=none
       dh_fixperms -O--buildsystem=none
       dh_missing -O--buildsystem=none
       dh_dwz -a -O--buildsystem=none
       dh_strip -a -O--buildsystem=none
       dh_makeshlibs -a -O--buildsystem=none
       dh_shlibdeps -a -O--buildsystem=none
       dh_installdeb -O--buildsystem=none
       dh_gencontrol -O--buildsystem=none
    dpkg-gencontrol: warning: Depends field of package testpackage:
substitution variable ${shlibs:Depends} used, but is not defined
       dh_md5sums -O--buildsystem=none
       dh_builddeb -O--buildsystem=none
    dpkg-deb: building package 'testpackage' in
'../testpackage_1.0-1_amd64.deb'.
     dpkg-genbuildinfo -O../testpackage_1.0-1_amd64.buildinfo
     dpkg-genchanges -O../testpackage_1.0-1_amd64.changes
    dpkg-genchanges: info: including full source code in upload
     dpkg-source --diff-ignore=true --tar-ignore=true --after-build .
    dpkg-buildpackage: warning: not signing UNRELEASED build; use --force-sign
to override
    dpkg-buildpackage: info: full upload; Debian-native package (full source is
included)

As you can see, the package builds and runs as expected, and the compiler is
invoked with -DFOO='"string_value"'. The issue presents when including
/usr/share/dpkg/buildflags.mk, just after the shebang line:

    $ dpkg-buildpackage
    dpkg-buildpackage: info: source package testpackage
    dpkg-buildpackage: info: source version 1.0-1
    dpkg-buildpackage: info: source distribution UNRELEASED
    dpkg-buildpackage: info: source changed by Andrea Pappacoda
<and...@pappacoda.it>
     dpkg-source --diff-ignore=true --tar-ignore=true --before-build .
    dpkg-buildpackage: info: host architecture amd64
     debian/rules clean
    dh clean --buildsystem=none
       dh_auto_clean -O--buildsystem=none
       dh_autoreconf_clean -O--buildsystem=none
       dh_clean -O--buildsystem=none
     dpkg-source --diff-ignore=true --tar-ignore=true -b .
    dpkg-source: warning: no source format specified in debian/source/format,
see dpkg-source(1)
    dpkg-source: warning: native package version may not have a revision
    dpkg-source: warning: source directory 'testpackage' is not
<sourcepackage>-<upstreamversion> 'testpackage-1.0'
    dpkg-source: info: using source format '1.0'
    dpkg-source: info: building testpackage in testpackage_1.0-1.tar.gz
    dpkg-source: info: building testpackage in testpackage_1.0-1.dsc
     debian/rules binary
    dh binary --buildsystem=none
       dh_update_autotools_config -O--buildsystem=none
       dh_autoreconf -O--buildsystem=none
       dh_auto_configure -O--buildsystem=none
       debian/rules override_dh_auto_build
    make[1]: Entering directory '/tmp/tmp.RvxkGPOuQf/testpackage'
    cc -Wdate-time -D_FORTIFY_SOURCE=2 -DFOO='string_value' -g -O2
- -Werror=implicit-function-declaration -ffile-prefix-
map=/tmp/tmp.RvxkGPOuQf/testpackage=. -fstack-protector-strong -fstack-clash-
protection -Wformat -Werror=format-security -fcf-protection -Wl,-z,relro -o
main main.c
    main.c: In function ‘main’:
    <command-line>: error: ‘string_value’ undeclared (first use in this
function)
    main.c:3:14: note: in expansion of macro ‘FOO’
        3 |         puts(FOO);
          |              ^~~
    <command-line>: note: each undeclared identifier is reported only once for
each function it appears in
    main.c:3:14: note: in expansion of macro ‘FOO’
        3 |         puts(FOO);
          |              ^~~
    make[1]: *** [debian/rules:11: override_dh_auto_build] Error 1
    make[1]: Leaving directory '/tmp/tmp.RvxkGPOuQf/testpackage'
    make: *** [debian/rules:8: binary] Error 2
    dpkg-buildpackage: error: debian/rules binary subprocess returned exit
status 2

As you can see, in the second run the compiler is invoked with
- -DFOO='string_value'. The double quotes get removed, even if surrounded with
single quotes; this of course leads to build failures.

It is worth noting that the issue presents also when invoking "debian/rules
binary" directly, without delegating to dpkg-buildpackage.

This seems to me like a bug in buildflags.mk, but I may be doing something
stupid I don't notice.

Please let me know. Thanks! Bye :)


- -- Package-specific info:

- -- System Information:
Debian Release: trixie/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 6.10.4-amd64 (SMP w/4 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_WARN, TAINT_OOT_MODULE, 
TAINT_UNSIGNED_MODULE
Locale: LANG=it_IT.UTF-8, LC_CTYPE=it_IT.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages dpkg-dev depends on:
ii  binutils      2.43-2
ii  bzip2         1.0.8-5.1
ii  libdpkg-perl  1.22.11
ii  make          4.3-4.1
ii  patch         2.7.6-7
ii  perl          5.38.2-5
ii  tar           1.35+dfsg-3
ii  xz-utils      5.6.2-2

Versions of packages dpkg-dev recommends:
ii  build-essential          12.10
ii  clang-16 [c-compiler]    1:16.0.6-27+b1
ii  clang-17 [c-compiler]    1:17.0.6-15
ii  fakeroot                 1.36-1
ii  gcc [c-compiler]         4:14.1.0-2
ii  gcc-10 [c-compiler]      10.5.0-4
ii  gcc-11 [c-compiler]      11.5.0-1
ii  gcc-12 [c-compiler]      12.4.0-2
ii  gcc-13 [c-compiler]      13.3.0-5
ii  gcc-14 [c-compiler]      14.2.0-1
ii  gnupg                    2.2.43-8
ii  gpgv                     2.2.43-8
ii  libalgorithm-merge-perl  0.08-5
ii  sqop                     0.35.0-5

Versions of packages dpkg-dev suggests:
ii  debian-keyring  2024.06.24

- -- no debconf information

-----BEGIN PGP SIGNATURE-----

iIoEARYIADIWIQS6VuNIvZRFHt7JcAdKkgiiRVB3pwUCZsj26xQcYW5kcmVhQHBh
cHBhY29kYS5pdAAKCRBKkgiiRVB3p4B/AQC/lMFd+8zlHWPgscs7ii0DIx9qAlhV
h6djBzfdnNhUiAEAz45LCyb+E1vAXTH5hbNM9VEwhzIwaWvLJhEzjdL5JgA=
=mBWO
-----END PGP SIGNATURE-----

Reply via email to