Bug 197847

Summary: [objtool] make failure due to change in make handling of # characters
Product: Other Reporter: zibeon
Component: ConfigurationAssignee: other_configuration (other_configuration)
Status: NEW ---    
Severity: blocking CC: pmenzel+bugzilla.kernel.org, rdunlap, tomenglund26
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: all Subsystem:
Regression: Yes Bisected commit-id:
Attachments: tools/build/Build.include: fix # escaping in .cmd files for future Make

Description zibeon 2017-11-11 15:25:05 UTC
Hi,

In 2016 make made a backwards incompatible change to the way '#' characters
were handled in Makefiles when used inside functions or macros:

http://git.savannah.gnu.org/cgit/make.git/commit/?id=c6966b323811c37acedff05b57

Due to this change, when attempting to run `make prepare' I get a spurious make
syntax error:

    /home/earnest/linux/tools/objtool/.fixdep.o.cmd:1: *** missing separator.  Stop.

When inspecting `.fixdep.o.cmd' it includes two lines which use unescaped
comment characters at the top:

    \# cannot find fixdep (/home/earnest/linux/tools/objtool//fixdep)
    \# using basic dep data

This is because `tools/build/Build.include' prints these '\#' characters:

    printf '\# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \
    printf '\# using basic dep data\n\n' >> $(dot-target).cmd;           \


Another issue this causes is the test used for libelf determining elfshdr
causes it to fail due to the escaped '#' being passed to gcc:

    elfshdr := $(shell echo '\#include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | grep elf_getshdr)

When run this would produce the wrong output which results in
`-DLIBELF_USE_DEPRECATED' being added to the CLFAGS:

    CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)

Because of this the following #ifdef causes us to link against the deprecated
symbols:

    #ifdef LIBELF_USE_DEPRECATED
    # define elf_getshdrnum    elf_getshnum
    # define elf_getshdrstrndx elf_getshstrndx
    #endif

This causes build errors due to -Werror:

    elf.c:144:2: error: ‘elf_getshnum’ is deprecated [-Werror=deprecated-declarations]
    elf.c:149:2: error: ‘elf_getshstrndx’ is deprecated [-Werror=deprecated-declarations]

The workaround I'm using is the following patch which simply removes the escape
characters:

    --- tools/objtool/Makefile	2017-11-11 14:55:08.243236243 +0000
    +++ tools/objtool/Makefile.new	2017-11-11 14:56:52.322443760 +0000
    @@ -29,7 +29,7 @@
     LDFLAGS  += -lelf $(LIBSUBCMD)

     # Allow old libelf to be used:
    -elfshdr := $(shell echo '\#include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | grep elf_getshdr)
    +elfshdr := $(shell echo '#include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | grep elf_getshdr)
     CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)

     AWK = awk

    --- tools/build/Build.include	2017-11-11 14:57:12.862287367 +0000
    +++ tools/build/Build.include.new	2017-11-11 14:56:37.232558659 +0000
    @@ -62,8 +62,8 @@
                $(fixdep) $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;           \
                rm -f $(depfile);                                                    \
                mv -f $(dot-target).tmp $(dot-target).cmd,                           \
    -           printf '# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd;  \
    -           printf '# using basic dep data\n\n' >> $(dot-target).cmd;            \
    +           printf '\# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \
    +           printf '\# using basic dep data\n\n' >> $(dot-target).cmd;           \
                cat $(depfile) >> $(dot-target).cmd;                                 \
                printf '\n%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)

Clearly this won't work in a portable manner, so I'm reporting this bug for
others to figure out a better way of handling it.
Comment 1 Tom Englund 2017-11-18 16:55:29 UTC
same issue happening here aswell, and it will probably affect quite a lot more once make gets a new release. which brings in the relevant commit.
Comment 2 Randy Dunlap 2018-04-09 18:45:40 UTC
Patch is merged into linux-kbuild git tree (2018-APR-09).
Comment 3 Paul Menzel 2018-06-05 16:05:52 UTC
Randy, it’d be great, if this was applied to the stable series too.
Comment 4 Paul Menzel 2018-06-05 16:58:33 UTC
Rasmus’ commit 9564a8cf (Kbuild: fix # escaping in .cmd files for future Make) [1][2] is incomplete.

The printf’s in the hunk below need to be updated too.

```
dep-cmd = $(if $(wildcard $(fixdep)),                                           \
           $(fixdep) $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;           \
           rm -f $(depfile);                                                    \
           mv -f $(dot-target).tmp $(dot-target).cmd,                           \
           printf '\# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \
           printf '\# using basic dep data\n\n' >> $(dot-target).cmd;           \
           cat $(depfile) >> $(dot-target).cmd;                                 \
           printf '\n%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
```

[1] https://patchwork.kernel.org/patch/10328633/
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9564a8cf422d7b58f6e857e3546d346fa970191e
Comment 5 Paul Menzel 2018-06-05 17:15:37 UTC
Created attachment 276327 [details]
tools/build/Build.include: fix # escaping in .cmd files for future Make

Here is the fix.