diff mbox series

config.mak.dev: specify -std=gnu99 for gcc/clang

Message ID YbEMnksMEuAz3Nt0@coredump.intra.peff.net (mailing list archive)
State Accepted
Commit 5f46385309b7a67d20a8471c27ccc1d5fdd09d53
Headers show
Series config.mak.dev: specify -std=gnu99 for gcc/clang | expand

Commit Message

Jeff King Dec. 8, 2021, 7:50 p.m. UTC
On Tue, Dec 07, 2021 at 08:13:43PM -0800, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> >> error: ISO C99 doesn't support unnamed structs/unions [-Werror=pedantic]
> >
> > Hmm. It's interesting that the regular DEVELOPER=1 doesn't catch this.
> > It's because we don't specify -std there, and newer gcc defaults to
> > gnu17 (unnamed unions appeared in c11, I think). I wonder if it would be
> > helpful to teach config.mak.dev to pass -std=c99.
> 
> FWIW, I use -std=gnu99 as our Makefile suggests.

I think the patch below would have detected this both locally for
Han-Wen, but also in C.

-- >8 --
Subject: [PATCH] config.mak.dev: specify -std=gnu99 for gcc/clang

The point of DEVELOPER=1 is to turn up the warnings so we can catch
portability or correctness mistakes at the compiler level. But since
modern compilers tend to default to modern standards like gnu17, we
might miss warnings about older standards, even though we expect Git to
build with compilers that use them.

So it's helpful for developer builds to set the -std argument to our
lowest-common denominator. Traditionally this was c89, but since we're
moving to assuming c99 in 7bc341e21b (git-compat-util: add a test
balloon for C99 support, 2021-12-01) that seems like a good spot to
land. And as explained in that commit, we want "gnu99" because we still
want to take advantage of some extensions when they're available.

The new argument kicks in only for clang and gcc (which we know to
support "-std=" and "gnu" standards). And only for compiler versions
which default to a newer standard. That will avoid accidentally
silencing any build problems that non-developers would run into on older
compilers that default to c89.

My digging found that the default switched to gnu11 in gcc 5.1.0.
Clang's documentation is less clear, but has done so since at least
clang-7. So that's what I put in the conditional here. It's OK to err on
the side of not-enabling this for older compilers. Most developers (as
well as CI) are using much more recent versions, so any warnings will
eventually surface.

A concrete example is anonymous unions, which became legal in c11.
Without this patch, "gcc -pedantic" will not complain about them, but
will if we add in "-std=gnu99".

Signed-off-by: Jeff King <peff@peff.net>
---
 config.mak.dev | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Ævar Arnfjörð Bjarmason Dec. 9, 2021, 12:05 p.m. UTC | #1
On Wed, Dec 08 2021, Jeff King wrote:

> On Tue, Dec 07, 2021 at 08:13:43PM -0800, Junio C Hamano wrote:
>
>> Jeff King <peff@peff.net> writes:
>> 
>> >> error: ISO C99 doesn't support unnamed structs/unions [-Werror=pedantic]
>> >
>> > Hmm. It's interesting that the regular DEVELOPER=1 doesn't catch this.
>> > It's because we don't specify -std there, and newer gcc defaults to
>> > gnu17 (unnamed unions appeared in c11, I think). I wonder if it would be
>> > helpful to teach config.mak.dev to pass -std=c99.
>> 
>> FWIW, I use -std=gnu99 as our Makefile suggests.
>
> I think the patch below would have detected this both locally for
> Han-Wen, but also in C.
>
> -- >8 --
> Subject: [PATCH] config.mak.dev: specify -std=gnu99 for gcc/clang
>
> The point of DEVELOPER=1 is to turn up the warnings so we can catch
> portability or correctness mistakes at the compiler level. But since
> modern compilers tend to default to modern standards like gnu17, we
> might miss warnings about older standards, even though we expect Git to
> build with compilers that use them.
>
> So it's helpful for developer builds to set the -std argument to our
> lowest-common denominator. Traditionally this was c89, but since we're
> moving to assuming c99 in 7bc341e21b (git-compat-util: add a test
> balloon for C99 support, 2021-12-01) that seems like a good spot to
> land. And as explained in that commit, we want "gnu99" because we still
> want to take advantage of some extensions when they're available.
>
> The new argument kicks in only for clang and gcc (which we know to
> support "-std=" and "gnu" standards). And only for compiler versions
> which default to a newer standard. That will avoid accidentally
> silencing any build problems that non-developers would run into on older
> compilers that default to c89.
>
> My digging found that the default switched to gnu11 in gcc 5.1.0.
> Clang's documentation is less clear, but has done so since at least
> clang-7. So that's what I put in the conditional here. It's OK to err on
> the side of not-enabling this for older compilers. Most developers (as
> well as CI) are using much more recent versions, so any warnings will
> eventually surface.
>
> A concrete example is anonymous unions, which became legal in c11.
> Without this patch, "gcc -pedantic" will not complain about them, but
> will if we add in "-std=gnu99".
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
>  config.mak.dev | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/config.mak.dev b/config.mak.dev
> index 7673fed114..d4afac6b51 100644
> --- a/config.mak.dev
> +++ b/config.mak.dev
> @@ -19,6 +19,11 @@ endif
>  endif
>  endif
>  endif
> +
> +ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),)
> +DEVELOPER_CFLAGS += -std=gnu99
> +endif
> +
>  DEVELOPER_CFLAGS += -Wdeclaration-after-statement
>  DEVELOPER_CFLAGS += -Wformat-security
>  DEVELOPER_CFLAGS += -Wold-style-definition

This approach looks good & the rationale make sense.

I mentioned in [1] that this might be a bad idea because:

    And as you note it's not only that older or non-gcc non-clang compilers
    may not understand this at all, but are we getting worse behavior on
    modern versions of those two because they're forced into some 20 year
    old C99 standard mode, instead of the current preferred default?

But from some short testing of GCC it will generate the exact same
<file>.s regardless of -std=* option, so I think this indeed only
impacts the warnings we'll emit. So pinning this seems to categorically
be a good thing.

A bad thing about this is that we'll explicitly avoid happy accidents
where we start relying on some newer C standard, and discover N releases
later that it was no big deal, and can thus just use that feature.

On the other hand having this means less back & forth churn of adding
such a dependency only to find it breaks on one of our platforms
etc. Overall I think this makes sense, just say'n.

I don't think this needs to change, but FWIW this would benefit from the
same sort of "let's just compile it" step as [2]. I.e. I think you'll
find that we could just check the exit code of:

    $(CC) -E -std=gnu99 - </dev/null

This works on GCC/Clang, and will die on xlc/suncc, and I assume any
other compiler that doesn't grok this. But I think it's better to avoid
a $(shell) here just for that, and any such change can wait until we
have some proper "compile this once and cache it" probing for
config.mak.dev.

1. https://lore.kernel.org/git/211116.86pmr0p82k.gmgdl@evledraar.gmail.com/
2. https://lore.kernel.org/git/211118.86lf1m5h1y.gmgdl@evledraar.gmail.com/
Jeff King Dec. 10, 2021, 8:56 a.m. UTC | #2
On Thu, Dec 09, 2021 at 01:05:44PM +0100, Ævar Arnfjörð Bjarmason wrote:

> > +
> > +ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),)
> > +DEVELOPER_CFLAGS += -std=gnu99
> > +endif
> [...]
> 
> This approach looks good & the rationale make sense.
> 
> I mentioned in [1] that this might be a bad idea because:
> 
>     And as you note it's not only that older or non-gcc non-clang compilers
>     may not understand this at all, but are we getting worse behavior on
>     modern versions of those two because they're forced into some 20 year
>     old C99 standard mode, instead of the current preferred default?
> 
> But from some short testing of GCC it will generate the exact same
> <file>.s regardless of -std=* option, so I think this indeed only
> impacts the warnings we'll emit. So pinning this seems to categorically
> be a good thing.

Thanks for looking into that. The thought crossed my mind, too, but I
didn't have any actual data. I think some of this is due to the standard
committee keeping backwards compatibility. I.e., it's unlikely for there
to be a case where the N standard says "you must do X", and N+1 says
"that's dumb, you can do Y instead". Usually it is about new features
that were syntactically invalid or created undefined behavior in version
N.

> A bad thing about this is that we'll explicitly avoid happy accidents
> where we start relying on some newer C standard, and discover N releases
> later that it was no big deal, and can thus just use that feature.
> 
> On the other hand having this means less back & forth churn of adding
> such a dependency only to find it breaks on one of our platforms
> etc. Overall I think this makes sense, just say'n.

Right. I think it forces us to be more deliberate, but that's probably
OK.

> I don't think this needs to change, but FWIW this would benefit from the
> same sort of "let's just compile it" step as [2]. I.e. I think you'll
> find that we could just check the exit code of:
> 
>     $(CC) -E -std=gnu99 - </dev/null
> 
> This works on GCC/Clang, and will die on xlc/suncc, and I assume any
> other compiler that doesn't grok this. But I think it's better to avoid
> a $(shell) here just for that, and any such change can wait until we
> have some proper "compile this once and cache it" probing for
> config.mak.dev.

You'd lose one property that the version-check has, which is that we
don't ever _upgrade_ to gnu99 from gnu89. I'm not sure how important
that is, though. It would have been bad if we took something like
brian's c99 patch, and developers and CI both failed to realize that it
was breaking the out-of-the-box build for older compilers (because
behind the scenes they were getting -std=gnu99 that non-developers do
not). But now that we've decided on that direction anyway, I'm not sure
there's anything left to be learned.

-Peff
brian m. carlson Jan. 14, 2022, 1:38 a.m. UTC | #3
On 2022-01-13 at 10:45:49, Ævar Arnfjörð Bjarmason wrote:
> [I'm aware that Jeff probably won't read this in his sabbatical, just
> replying to the relevant thread]
> 
> Something neither of us considered at the time, but which is pretty
> obvious in retrospect, is that this new -std=gnu99 dosen't only apply to
> our own code, but any system and library includes that we need.
> 
> Thus e.g. FreeBSD 13.0 which previously was happy to compile under
> DEVELOPER=1 will now die because its core libraries use C11-specific
> code:
>     
>     archive.c:337:35: error: '_Generic' is a C11 extension [-Werror,-Wc11-extensions]
>                     strbuf_addstr(&path_in_archive, basename(path));
>                                                     ^
>     /usr/include/libgen.h:61:21: note: expanded from macro 'basename'
>     #define basename(x)     __generic(x, const char *, __old_basename, basename)(x)
>                             ^
>     /usr/include/sys/cdefs.h:325:2: note: expanded from macro '__generic'
>             _Generic(expr, t: yes, default: no)
>             ^

I think we had this discussion about FreeBSD before and that's why I
specifically dropped that option from the main makefile.  We can either
drop that patch, or we can set it to -std=gnu11 and tell folks setting
DEVELOPER to use a system released in the last five years.  I think we
can be a little stricter with what we require in the case of DEVELOPER
than we might be otherwise.
Ævar Arnfjörð Bjarmason Jan. 14, 2022, 12:01 p.m. UTC | #4
On Fri, Jan 14 2022, brian m. carlson wrote:

> [[PGP Signed Part:Undecided]]
> On 2022-01-13 at 10:45:49, Ævar Arnfjörð Bjarmason wrote:
>> [I'm aware that Jeff probably won't read this in his sabbatical, just
>> replying to the relevant thread]
>> 
>> Something neither of us considered at the time, but which is pretty
>> obvious in retrospect, is that this new -std=gnu99 dosen't only apply to
>> our own code, but any system and library includes that we need.
>> 
>> Thus e.g. FreeBSD 13.0 which previously was happy to compile under
>> DEVELOPER=1 will now die because its core libraries use C11-specific
>> code:
>>     
>>     archive.c:337:35: error: '_Generic' is a C11 extension [-Werror,-Wc11-extensions]
>>                     strbuf_addstr(&path_in_archive, basename(path));
>>                                                     ^
>>     /usr/include/libgen.h:61:21: note: expanded from macro 'basename'
>>     #define basename(x)     __generic(x, const char *, __old_basename, basename)(x)
>>                             ^
>>     /usr/include/sys/cdefs.h:325:2: note: expanded from macro '__generic'
>>             _Generic(expr, t: yes, default: no)
>>             ^
>
> I think we had this discussion about FreeBSD before and that's why I
> specifically dropped that option from the main makefile.  We can either
> drop that patch, or we can set it to -std=gnu11 and tell folks setting
> DEVELOPER to use a system released in the last five years.  I think we
> can be a little stricter with what we require in the case of DEVELOPER
> than we might be otherwise.

I guess, yeah.

As a practical matter the changes in this cycle have made DEVELOPER=1
much more fragile as a cross-platform facility. I test on various
platforms/OS's (across the GCC farm), and before this cycle only AIX and
Solaris were something I had to pay special attention to.

Now we've got things like this breaking (by default) non-obscure things
like FreeBSD.

Of course I can manually set -Wall etc. which is what I previously got
out of this, but before e.g. pedantic was opt-in, now an effective
C-version-a-pedantic is the default, and doesn't have a tweaking knob at
all.

Anyway, we'll see how much of a hassle it is, and it's not too painful
for me right now, so I don't think anything needs to be done in the RC
period.

But I wonder if the X-Y problem we're trying to solve is making sure we
don't move past C99 unintentionally whether this wouldn't be better
solved by dropping this -std=gnu99 approach in the Makefile, and instead
just do that in one of the CI jobs (whose OS includes would be known to
be C99-OK).
Junio C Hamano Jan. 14, 2022, 7:51 p.m. UTC | #5
"brian m. carlson" <sandals@crustytoothpaste.net> writes:

>> DEVELOPER=1 will now die because its core libraries use C11-specific
>> code:
>>     
>>     archive.c:337:35: error: '_Generic' is a C11 extension [-Werror,-Wc11-extensions]
>>                     strbuf_addstr(&path_in_archive, basename(path));
>>                                                     ^
>>     /usr/include/libgen.h:61:21: note: expanded from macro 'basename'
>>     #define basename(x)     __generic(x, const char *, __old_basename, basename)(x)
>>                             ^
>>     /usr/include/sys/cdefs.h:325:2: note: expanded from macro '__generic'
>>             _Generic(expr, t: yes, default: no)
>>             ^

Wow, that sounds horribly broken.

> I think we had this discussion about FreeBSD before and that's why I
> specifically dropped that option from the main makefile.  We can either
> drop that patch, or we can set it to -std=gnu11 and tell folks setting
> DEVELOPER to use a system released in the last five years.  I think we
> can be a little stricter with what we require in the case of DEVELOPER
> than we might be otherwise.

But that is not being stricter, but looser, no?  I thought that the
point of -std=gnu99 was to allow us to use C99 features while catching
use of language features newer than that, and use of -std=gnu11 will
defeat half the point, wouldn't it?
Ævar Arnfjörð Bjarmason Jan. 14, 2022, 8:41 p.m. UTC | #6
On Fri, Jan 14 2022, Junio C Hamano wrote:

> "brian m. carlson" <sandals@crustytoothpaste.net> writes:
>
>>> DEVELOPER=1 will now die because its core libraries use C11-specific
>>> code:
>>>     
>>>     archive.c:337:35: error: '_Generic' is a C11 extension [-Werror,-Wc11-extensions]
>>>                     strbuf_addstr(&path_in_archive, basename(path));
>>>                                                     ^
>>>     /usr/include/libgen.h:61:21: note: expanded from macro 'basename'
>>>     #define basename(x)     __generic(x, const char *, __old_basename, basename)(x)
>>>                             ^
>>>     /usr/include/sys/cdefs.h:325:2: note: expanded from macro '__generic'
>>>             _Generic(expr, t: yes, default: no)
>>>             ^
>
> Wow, that sounds horribly broken.

Yes, but it's also working as designed :) We're erroring because the C
library headers on the OS aren't C99-compliant. That it would apply to
only git.git's sources was only ever wishful thinking.

>> I think we had this discussion about FreeBSD before and that's why I
>> specifically dropped that option from the main makefile.  We can either
>> drop that patch, or we can set it to -std=gnu11 and tell folks setting
>> DEVELOPER to use a system released in the last five years.  I think we
>> can be a little stricter with what we require in the case of DEVELOPER
>> than we might be otherwise.
>
> But that is not being stricter, but looser, no?  I thought that the
> point of -std=gnu99 was to allow us to use C99 features while catching
> use of language features newer than that, and use of -std=gnu11 will
> defeat half the point, wouldn't it?

Indeed. But also as noted in my side-thread reply in
<220114.86a6fytte9.gmgdl@evledraar.gmail.com> I think that being able to
use it like this was always wishful thinking.

I.e. to brian's "tell folks setting DEVELOPER to use a system released
in the last five years". This is the exact opposite of that.

We are implicitly expecting that the OS will forever be using the
20+-year old C99 standard, and not trying out fetures in C11
standardized 10+ years ago. The FreeBSD 13.0 release is less than a year
old[1].

When I went looking I found that the change to use __generic in its
libgen.h just so happens to have been made in FreeBSD sources around 5
years ago: [2].

1. https://www.freebsd.org/releases/13.0R/announce/
2. https://github.com/freebsd/freebsd-src/commit/34168b28e99b0bb328c7bb49cd91cb942181056f
Junio C Hamano Jan. 14, 2022, 9:53 p.m. UTC | #7
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

>> Wow, that sounds horribly broken.
>
> Yes, but it's also working as designed :) We're erroring because the C
> library headers on the OS aren't C99-compliant. That it would apply to
> only git.git's sources was only ever wishful thinking.

No, C library supporting only C11 is perfectly fine.  On such a
system, the compiler shouldn't even support -std=gnu99.  That is
what I consider broken.
Junio C Hamano Jan. 14, 2022, 10:35 p.m. UTC | #8
Junio C Hamano <gitster@pobox.com> writes:

>> I think we had this discussion about FreeBSD before and that's why I
>> specifically dropped that option from the main makefile.  We can either
>> drop that patch, or we can set it to -std=gnu11 and tell folks setting
>> DEVELOPER to use a system released in the last five years.  I think we
>> can be a little stricter with what we require in the case of DEVELOPER
>> than we might be otherwise.
>
> But that is not being stricter, but looser, no?  I thought that the
> point of -std=gnu99 was to allow us to use C99 features while catching
> use of language features newer than that, and use of -std=gnu11 will
> defeat half the point, wouldn't it?

If FreeBSD (or any other platform) cannot do "reject features beyond
C99", I am perfectly OK to drop -std=gnu99 on such a place.

DEVELOPER=YesPlease ought to be a collection of settings that helps
the developers the most.  So on platforms that *can* do "reject
features beyond C99", I prefer to have it enabled when
DEVELOPER=YesPlease is given.

It seems that -std=gnu99 is only added conditionally even in today's
config.mak.dev, so it is fine if we dropped -std=gnu99 from there.
Which means that developers on FreeBSD cannot participate in vetting
use of features beyond C99, but there are developers on other
platforms who will, so it's not too bad, I would say.

As config.mak.dev is included after config.mak.uname, something like
this may be sufficient, perhaps?

 config.mak.dev | 5 +++++
 1 file changed, 5 insertions(+)

diff --git i/config.mak.dev w/config.mak.dev
index d4afac6b51..3deb076d5e 100644
--- i/config.mak.dev
+++ w/config.mak.dev
@@ -20,9 +20,14 @@ endif
 endif
 endif
 
+ifneq ($(uname_S),FreeBSD)
 ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),)
 DEVELOPER_CFLAGS += -std=gnu99
 endif
+else
+# FreeBSD cannot limit to C99 because its system headers unconditionally
+# rely on C11 features.
+endif
 
 DEVELOPER_CFLAGS += -Wdeclaration-after-statement
 DEVELOPER_CFLAGS += -Wformat-security
Ævar Arnfjörð Bjarmason Jan. 14, 2022, 11:56 p.m. UTC | #9
On Fri, Jan 14 2022, Junio C Hamano wrote:

> Junio C Hamano <gitster@pobox.com> writes:
>
>>> I think we had this discussion about FreeBSD before and that's why I
>>> specifically dropped that option from the main makefile.  We can either
>>> drop that patch, or we can set it to -std=gnu11 and tell folks setting
>>> DEVELOPER to use a system released in the last five years.  I think we
>>> can be a little stricter with what we require in the case of DEVELOPER
>>> than we might be otherwise.
>>
>> But that is not being stricter, but looser, no?  I thought that the
>> point of -std=gnu99 was to allow us to use C99 features while catching
>> use of language features newer than that, and use of -std=gnu11 will
>> defeat half the point, wouldn't it?
>
> If FreeBSD (or any other platform) cannot do "reject features beyond
> C99", I am perfectly OK to drop -std=gnu99 on such a place.
>
> DEVELOPER=YesPlease ought to be a collection of settings that helps
> the developers the most.  So on platforms that *can* do "reject
> features beyond C99", I prefer to have it enabled when
> DEVELOPER=YesPlease is given.
>
> It seems that -std=gnu99 is only added conditionally even in today's
> config.mak.dev, so it is fine if we dropped -std=gnu99 from there.
> Which means that developers on FreeBSD cannot participate in vetting
> use of features beyond C99, but there are developers on other
> platforms who will, so it's not too bad, I would say.
>
> As config.mak.dev is included after config.mak.uname, something like
> this may be sufficient, perhaps?

Wasn't the initial goal here to check whether we'd accidentally include
C99? Just checking on GCC/Clang somewhere seems sufficient enough,
I.e. something like:
    
    diff --git a/ci/lib.sh b/ci/lib.sh
    index 9d28ab50fb4..94d0d4127b9 100755
    --- a/ci/lib.sh
    +++ b/ci/lib.sh
    @@ -209,6 +209,9 @@ linux-leaks)
            export SANITIZE=leak
            export GIT_TEST_PASSING_SANITIZE_LEAK=true
            ;;
    +linux-gcc|linux-clang)
    +       MAKEFLAGS="$MAKEFLAGS CFLAGS=-std=gnu99"
    +       ;;
     esac
     
     MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}"
    diff --git a/config.mak.dev b/config.mak.dev
    index d4afac6b51f..216f92493fc 100644
    --- a/config.mak.dev
    +++ b/config.mak.dev
    @@ -20,10 +20,6 @@ endif
     endif
     endif
     
    -ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),)
    -DEVELOPER_CFLAGS += -std=gnu99
    -endif
    -
     DEVELOPER_CFLAGS += -Wdeclaration-after-statement
     DEVELOPER_CFLAGS += -Wformat-security
     DEVELOPER_CFLAGS += -Wold-style-definition
    
We're just starting to get into the whack-a-mole of hardcoding OS's and
compiler versions, it's not all versions of FreeBSD, probably not just
that OS etc.

I've also wondered why we can't just ship our own super-light version of
autoconf to run some real probes, and as a result eventually get rid of
configure.ac, ./detect-compiler, the version hardcoding in
config.mak.dev etc.

Just something as simple as extending this:
    
    diff --git a/Makefile b/Makefile
    index 5580859afdb..f197a07c100 100644
    --- a/Makefile
    +++ b/Makefile
    @@ -2557,6 +2557,15 @@ else
     $(OBJECTS): $(LIB_H) $(GENERATED_H)
     endif
     
    +ifdef DEVELOPER
    +probe/std.mak:
    +       @mkdir -p $(@D)
    +       $(QUIET_GEN)if $(CC) -E -std=gnu99 - </dev/null >/dev/null; then \
    +               echo 'DEVELOPER_CFLAGS += -std=gnu99'; \
    +       fi >$@
    +include probe/std.mak
    +endif
    +
     ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
     all:: compile_commands.json
     compile_commands.json:
Junio C Hamano Jan. 14, 2022, 11:57 p.m. UTC | #10
Junio C Hamano <gitster@pobox.com> writes:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>>> Wow, that sounds horribly broken.
>>
>> Yes, but it's also working as designed :) We're erroring because the C
>> library headers on the OS aren't C99-compliant. That it would apply to
>> only git.git's sources was only ever wishful thinking.
>
> No, C library supporting only C11 is perfectly fine.  On such a
> system, the compiler shouldn't even support -std=gnu99.  That is
> what I consider broken.

Or, the system headers should be arranged in such a way that
depending on __STDC_VERSION__, it should refrain from using features
of the language that is not supported.  So supporting -std=gnu99 in
their compilers may not be a bug---but in that case, their system
headers are buggy.

Anyway.  I think <xmqqzgny7xo7.fsf@gitster.g> shows a viable way
forward.
Junio C Hamano Jan. 15, 2022, 12:31 a.m. UTC | #11
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Wasn't the initial goal here to check whether we'd accidentally include
> C99? Just checking on GCC/Clang somewhere seems sufficient enough,

What do you mean by "accidentally include"?

The goal here is that developer build should give developer a set of
options that help the most---"not going beyond C99" is something we
want them to be checking, if able (and we have established that
users on FreeBSD are not capable).

Doesn't your "something like" limits the check to CI?  Developers
with compilers that _can_ help ensuring that we do not go beyond C99
should be able to do so by their local developer build.

> I.e. something like:
>     
>     diff --git a/ci/lib.sh b/ci/lib.sh
>     index 9d28ab50fb4..94d0d4127b9 100755
>     --- a/ci/lib.sh
>     +++ b/ci/lib.sh
>     @@ -209,6 +209,9 @@ linux-leaks)
>             export SANITIZE=leak
>             export GIT_TEST_PASSING_SANITIZE_LEAK=true
>             ;;
>     +linux-gcc|linux-clang)
>     +       MAKEFLAGS="$MAKEFLAGS CFLAGS=-std=gnu99"
>     +       ;;
>      esac
>      
>      MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}"
>     diff --git a/config.mak.dev b/config.mak.dev
>     index d4afac6b51f..216f92493fc 100644
>     --- a/config.mak.dev
>     +++ b/config.mak.dev
>     @@ -20,10 +20,6 @@ endif
>      endif
>      endif
>      
>     -ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),)
>     -DEVELOPER_CFLAGS += -std=gnu99
>     -endif
>     -
>      DEVELOPER_CFLAGS += -Wdeclaration-after-statement
>      DEVELOPER_CFLAGS += -Wformat-security
>      DEVELOPER_CFLAGS += -Wold-style-definition
Ævar Arnfjörð Bjarmason Jan. 15, 2022, 12:41 a.m. UTC | #12
On Fri, Jan 14 2022, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> Wasn't the initial goal here to check whether we'd accidentally include
>> C99? Just checking on GCC/Clang somewhere seems sufficient enough,
>
> What do you mean by "accidentally include"?
>
> The goal here is that developer build should give developer a set of
> options that help the most---"not going beyond C99" is something we
> want them to be checking, if able (and we have established that
> users on FreeBSD are not capable).

The reason we ended up with -std=gnu99 is because of this thread where
Han-Wen accidentally used an unnamed structs/unions:
https://lore.kernel.org/git/xmqqlf0w5bbc.fsf@gitster.g/

He then pointed out that it would be nice if CI caught this, which would
have been sufficient:
https://lore.kernel.org/git/CAFQ2z_NuOy+-pfSoNAYjJhS9jZCYOfoFue10=k=iyPVsPYrB3g@mail.gmail.com/

> Doesn't your "something like" limits the check to CI?  Developers
> with compilers that _can_ help ensuring that we do not go beyond C99
> should be able to do so by their local developer build.

Yes, I'm suggesting that what we're trying to catch here is rare enough
that that may be sufficient, and which would sidestep the issue of
wasting time on trying to make this portable everywhere.

The DEVELOPER=1 feature has recently gone from something I used on a
wide varity on of platforms and the worst I got was notices about
unknown -W flags in a couple of them, to something where recently due to
-fno-common and now more widely with -std=gnu99 I've ended up having to
manually blacklist it on a few boxes where it Just Worked.

So maybe you think we absolutely need to spend the effort to run less
portable checks like that locally if at all possible, with all the
config.mak.uname etc. work that entails, if so OK.

I'm just suggesting that perhaps a more practical solution is to
side-step those portability issues by checking this in CI, which I think
would be Good Enough on this case.
Junio C Hamano Jan. 15, 2022, 1:08 a.m. UTC | #13
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> I'm just suggesting that perhaps a more practical solution is to
> side-step those portability issues by checking this in CI, which I think
> would be Good Enough on this case.

Use of GitHub PR + GGG is required to take advantage of that, no?  I
do not think I want to see a change that makes it _more_ likely that
a patch I pick up from the list will have problems that my local
integration work will not catch (because DEVELOPER=YesPlease build
is castrated at the original contributor side, and also on my box)
and will only be caught after I push out 'seen'.
Johannes Schindelin Jan. 18, 2022, 12:32 p.m. UTC | #14
Hi Junio,

On Fri, 14 Jan 2022, Junio C Hamano wrote:

> Junio C Hamano <gitster@pobox.com> writes:
>
> >> I think we had this discussion about FreeBSD before and that's why I
> >> specifically dropped that option from the main makefile.  We can either
> >> drop that patch, or we can set it to -std=gnu11 and tell folks setting
> >> DEVELOPER to use a system released in the last five years.  I think we
> >> can be a little stricter with what we require in the case of DEVELOPER
> >> than we might be otherwise.
> >
> > But that is not being stricter, but looser, no?  I thought that the
> > point of -std=gnu99 was to allow us to use C99 features while catching
> > use of language features newer than that, and use of -std=gnu11 will
> > defeat half the point, wouldn't it?
>
> If FreeBSD (or any other platform) cannot do "reject features beyond
> C99", I am perfectly OK to drop -std=gnu99 on such a place.
>
> DEVELOPER=YesPlease ought to be a collection of settings that helps
> the developers the most.  So on platforms that *can* do "reject
> features beyond C99", I prefer to have it enabled when
> DEVELOPER=YesPlease is given.
>
> It seems that -std=gnu99 is only added conditionally even in today's
> config.mak.dev, so it is fine if we dropped -std=gnu99 from there.
> Which means that developers on FreeBSD cannot participate in vetting
> use of features beyond C99, but there are developers on other
> platforms who will, so it's not too bad, I would say.

Plus, we have CI runs that do help us, thanks to setting `DEVELOPER=1`
(see https://github.com/git/git/blob/v2.35.0-rc1/ci/lib.sh#L154).

> As config.mak.dev is included after config.mak.uname, something like
> this may be sufficient, perhaps?
>
>  config.mak.dev | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git i/config.mak.dev w/config.mak.dev
> index d4afac6b51..3deb076d5e 100644
> --- i/config.mak.dev
> +++ w/config.mak.dev
> @@ -20,9 +20,14 @@ endif
>  endif
>  endif
>
> +ifneq ($(uname_S),FreeBSD)
>  ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),)
>  DEVELOPER_CFLAGS += -std=gnu99
>  endif
> +else
> +# FreeBSD cannot limit to C99 because its system headers unconditionally
> +# rely on C11 features.
> +endif
>
>  DEVELOPER_CFLAGS += -Wdeclaration-after-statement
>  DEVELOPER_CFLAGS += -Wformat-security
>

I applied this patch on top of the current tip of `seen`, opened a PR at
https://github.com/gitgitgadget/git/pull/1116. The corresponding FreeBSD
run is here: https://cirrus-ci.com/task/5867558132776960, and it
succeeded.

In addition, I concur that this is the best we can do, and I really would
like to have that patch as soon as possible because it confuses new
contributors when their PR builds fail out of no mistake of their own.

Please count this as a vote for including this patch in -rc2.

Thank you,
Dscho
Ævar Arnfjörð Bjarmason Jan. 18, 2022, 3:17 p.m. UTC | #15
On Tue, Jan 18 2022, Johannes Schindelin wrote:

> Hi Junio,
>
> On Fri, 14 Jan 2022, Junio C Hamano wrote:
>
>> Junio C Hamano <gitster@pobox.com> writes:
>>
>> >> I think we had this discussion about FreeBSD before and that's why I
>> >> specifically dropped that option from the main makefile.  We can either
>> >> drop that patch, or we can set it to -std=gnu11 and tell folks setting
>> >> DEVELOPER to use a system released in the last five years.  I think we
>> >> can be a little stricter with what we require in the case of DEVELOPER
>> >> than we might be otherwise.
>> >
>> > But that is not being stricter, but looser, no?  I thought that the
>> > point of -std=gnu99 was to allow us to use C99 features while catching
>> > use of language features newer than that, and use of -std=gnu11 will
>> > defeat half the point, wouldn't it?
>>
>> If FreeBSD (or any other platform) cannot do "reject features beyond
>> C99", I am perfectly OK to drop -std=gnu99 on such a place.
>>
>> DEVELOPER=YesPlease ought to be a collection of settings that helps
>> the developers the most.  So on platforms that *can* do "reject
>> features beyond C99", I prefer to have it enabled when
>> DEVELOPER=YesPlease is given.
>>
>> It seems that -std=gnu99 is only added conditionally even in today's
>> config.mak.dev, so it is fine if we dropped -std=gnu99 from there.
>> Which means that developers on FreeBSD cannot participate in vetting
>> use of features beyond C99, but there are developers on other
>> platforms who will, so it's not too bad, I would say.
>
> Plus, we have CI runs that do help us, thanks to setting `DEVELOPER=1`
> (see https://github.com/git/git/blob/v2.35.0-rc1/ci/lib.sh#L154).
>
>> As config.mak.dev is included after config.mak.uname, something like
>> this may be sufficient, perhaps?
>>
>>  config.mak.dev | 5 +++++
>>  1 file changed, 5 insertions(+)
>>
>> diff --git i/config.mak.dev w/config.mak.dev
>> index d4afac6b51..3deb076d5e 100644
>> --- i/config.mak.dev
>> +++ w/config.mak.dev
>> @@ -20,9 +20,14 @@ endif
>>  endif
>>  endif
>>
>> +ifneq ($(uname_S),FreeBSD)
>>  ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),)
>>  DEVELOPER_CFLAGS += -std=gnu99
>>  endif
>> +else
>> +# FreeBSD cannot limit to C99 because its system headers unconditionally
>> +# rely on C11 features.
>> +endif
>>
>>  DEVELOPER_CFLAGS += -Wdeclaration-after-statement
>>  DEVELOPER_CFLAGS += -Wformat-security
>>
>
> I applied this patch on top of the current tip of `seen`, opened a PR at
> https://github.com/gitgitgadget/git/pull/1116. The corresponding FreeBSD
> run is here: https://cirrus-ci.com/task/5867558132776960, and it
> succeeded.
>
> In addition, I concur that this is the best we can do, and I really would
> like to have that patch as soon as possible because it confuses new
> contributors when their PR builds fail out of no mistake of their own.

I just submitted a more narrow fix in the side-thread[1]. I've tested it
on the FreeBSD 13.0 box I have access to, but perhaps you'd like to test
it too?

> Please count this as a vote for including this patch in -rc2.

I'd like to have it too, but for context needing to add NO_UNCOMPRESS2=Y
(which Junio's punted on for the final[2]) is a much more widespread
issue of needing new post-install build tweaking than this issue that
only affects developer builds on FreeBSD.

What makes that FreeBSD run a part of the GGG CI? Another and more
narrow workaround for that in particular is to have whatever's driving
it add -Wno-c11-extensions to the CFLAGS.

1. https://lore.kernel.org/git/patch-1.1-06cc12be94d-20220118T151234Z-avarab@gmail.com/
2. https://lore.kernel.org/git/patch-1.1-9cea01a1395-20220117T170457Z-avarab@gmail.com/
Junio C Hamano Jan. 18, 2022, 8:15 p.m. UTC | #16
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> I'd like to have it too, but for context needing to add NO_UNCOMPRESS2=Y
> (which Junio's punted on for the final[2]) is a much more widespread
> issue of needing new post-install build tweaking than this issue that
> only affects developer builds on FreeBSD.

I hate it when people misrepresent what I said, even in an attempt
to spite me.  For the "check ZLIB_VERSION_NUM" topic, I gave you
specific things that needs to be different from the version posted
with reasons, fully expecting that a better version of the patch to
materialize soon (knowing how proliferate you can be when you want
to) to give us enough time to assess the potential damage.

I wouldn't call that "punted".

For this one, config.mak.dev patch WOULD only affect developer
builds, which is a much better solution than overriding what their
system headers want to do and force compiling with C99 mode.  With
the status quo with today's code, with or without the patch Dscho
wants in this thread, means ANYBODY will be stopped when they
attempt to build with -std=gnu99 on FreeBSD, which is a GOOD thing.

The reason why it is a much better solution to PUNT on using C99
mode on FreeBSD is because this episode makes it very clear that
nobody tested building anything that use basename(), dirname(),
etc. with C99 mode on the platform.  I do not trust such a build,
even if we could work around the system header breakage.

This time we got lucky and wereq stopped by a compilation error, but
I have a strong suspicion that C99-only mode of compiler on this
platform is not as well battle tested as their standard mode of
compilation that allows C11.  I simply do not think we want to waste
developer's time with C99-only mode on this platform which may end
up debugging the platform and not our program.  Next bug that will
hit us may not be so friendly to clearly break compilation.
Instead, the symptom may be a subtle runtime breakage that wastes
people's time.

After developers who work on FreeBSD (not Git developers who uses
FreeBSD) ships an updated system headers so that more programs, not
just us, are built and testsd with C99-only mode, perhaps it becomes
usable as a platform to catch use of language features beyond C99,
like everybody else.  But with such a clearly broken system headers,
I do not think today's FreeBSD is ready for that.  I do trust their
default settings that allows C11, a lot more than C99-only
compilation with the "their libgen is broken, so here is a user side
workaround" patch.
Ævar Arnfjörð Bjarmason Jan. 19, 2022, 12:29 a.m. UTC | #17
On Tue, Jan 18 2022, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> I'd like to have it too, but for context needing to add NO_UNCOMPRESS2=Y
>> (which Junio's punted on for the final[2]) is a much more widespread
>> issue of needing new post-install build tweaking than this issue that
>> only affects developer builds on FreeBSD.
>
> I hate it when people misrepresent what I said, even in an attempt
> to spite me.

Let's assume some mutual good faith here. I'm just trying to help debug
last-minute issues in this release to help get it out the door.

If I've misrepresented your views that's clearly true if you're the one
claiming it, but it's not intentional.

I was trying to read the tea leaves here in terms of helping patch
triage along. My assessment of that NO_UNCOMPRESS2=Y issue from the
boxes I've tested on is that it's a much more widespread problem new in
this release (this is purely from testing on the GCC farm, however
representative that is). It'll impact multiple OS's, linux distros &
versions.

Whereas the C11 warning is "just" recent FreeBSD && DEVELOPER=1.

So I assumed if you weren't interested in the former before the final
you probably wouldn't be in the latter, but wanted to provide a more
narrow fix in case you were.

> For the "check ZLIB_VERSION_NUM" topic, I gave you
> specific things that needs to be different from the version posted
> with reasons, fully expecting that a better version of the patch to
> materialize soon (knowing how proliferate you can be when you want
> to) to give us enough time to assess the potential damage.

I can re-roll it sooner than later if you'd like, but figured per your
"I like the basic idea of the patch, but I am afraid that it is way too
late in the cycle"[1] that the resulting on-list distraction wouldn't be
worth it at this point, if it wasn't being considered for being applied
in the release window.

Aside from "I can re-roll it". I also think that the point of making
that change mostly (but not entirely) disappears if it isn't included in
v2.35.0.

I.e. the point of doing it is to avoid the one-time pain of anyone
building new releases of git on $OLD_OS/$OLD_DISTRO not having to run
into the compilation error that's fixed with NO_UNCOMPRESS2=Y.

So if we put out a release without it anyone who's compiling git
releases will need to adjust their build system for that anyway (or
they're using autoconf, where it'll Just Work).

If we then get this into v2.36.0 there'll be someone somewhere that
benefits, but I'd think the ship has sailed for most of those who'd
avoid the needless flag twiddling (git-packagers@ et al).

So I don't know if it's even worth it to pursue that patch in that
case...

> I wouldn't call that "punted".

I don't think I've used or heard that word outside of this ML. FWIW I'm
using it in the sense of "kicking the can down the road" or "deferred
it".

Maybe that's incorrect, and I certainly stand corrected if I implied
something that wasn't true about our views by using that word.

> For this one, config.mak.dev patch WOULD only affect developer
> builds, which is a much better solution than overriding what their
> system headers want to do and force compiling with C99 mode.  With
> the status quo with today's code, with or without the patch Dscho
> wants in this thread, means ANYBODY will be stopped when they
> attempt to build with -std=gnu99 on FreeBSD, which is a GOOD thing.
>
> The reason why it is a much better solution to PUNT on using C99
> mode on FreeBSD is because this episode makes it very clear that
> nobody tested building anything that use basename(), dirname(),
> etc. with C99 mode on the platform.  I do not trust such a build,
> even if we could work around the system header breakage.

Aside from anything else I think you're assuming a lot about warning
hygiene in a typical C project. Git's use of even optional -Werror is
fairly unusual.

If you Google search that error you'll find numerous past reports of it,
it just hasn't been solved.

I also think we discussed around the -std=gnu99 change that the "C99
mode" in compilers we tested isn't impacting generated code (although of
course it will if it's conditional on __STDC_VERSION___). Otherwise the
generated objects are the same, it's just what warnings/errors you get
that changes.

In this case the fallback case already existed without my __generic
hack, so forcing that codepath for libgen.h isn't new.

> This time we got lucky and wereq stopped by a compilation error, but
> I have a strong suspicion that C99-only mode of compiler on this
> platform is not as well battle tested as their standard mode of
> compilation that allows C11.  I simply do not think we want to waste
> developer's time with C99-only mode on this platform which may end
> up debugging the platform and not our program.  Next bug that will
> hit us may not be so friendly to clearly break compilation.
> Instead, the symptom may be a subtle runtime breakage that wastes
> people's time.

I'd share that opinion if this was aCC on HP/UX or xlc on AIX or
whatever. But in this case it's just vanilla clang, not some scary
platform-specific compiler. Its "C99-only mode" isn't anything different
on FreeBSD than Linux.

We're just talking about one specific and avoidable warning in
/usr/include/libgen.h on that OS, once we're past that its "C99-mode"
works just fine.

> After developers who work on FreeBSD (not Git developers who uses
> FreeBSD) ships an updated system headers so that more programs, not
> just us, are built and testsd with C99-only mode, perhaps it becomes
> usable as a platform to catch use of language features beyond C99,
> like everybody else.  But with such a clearly broken system headers,
> I do not think today's FreeBSD is ready for that.  I do trust their
> default settings that allows C11, a lot more than C99-only
> compilation with the "their libgen is broken, so here is a user side
> workaround" patch.

Fair enough. I'm happy for us to get past this one way or the other,
whether it's with your patch or mine.

I took your previous reservations about my suggestions to just do this
C99 checking in CI-only to mean that you'd like to keep -std=gnu99 on
DEVELOPER=1 if at all possible, which my approach does.

1. https://lore.kernel.org/git/xmqq7dayw732.fsf@gitster.g/
Junio C Hamano Jan. 19, 2022, 1:02 a.m. UTC | #18
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Whereas the C11 warning is "just" recent FreeBSD && DEVELOPER=1.
>
> So I assumed if you weren't interested in the former before the final
> you probably wouldn't be in the latter, but wanted to provide a more
> narrow fix in case you were.

If we muck with the inclusion of libgen.h, it then becomes a problem
for everybody who builds on FreeBSD, not just the developer builds.
IOW, it is not even narrower to begin with.  Giving the same
potential breakage to everybody will make it easier to diagnose it,
but because I do not trust -std=gnu99 on today's FreeBSD, I think it
is a problem we do not even have to solve.

> I.e. the point of doing it is to avoid the one-time pain of anyone
> building new releases of git on $OLD_OS/$OLD_DISTRO not having to run
> into the compilation error that's fixed with NO_UNCOMPRESS2=Y.
> ...
> If we then get this into v2.36.0 there'll be someone somewhere that
> benefits, but I'd think the ship has sailed for most of those who'd
> avoid the needless flag twiddling (git-packagers@ et al).

I actually think it is a good thing.  It is what they brought onto
themselves.  They can follow David's example next time.
Ævar Arnfjörð Bjarmason Jan. 19, 2022, 1:05 a.m. UTC | #19
On Tue, Jan 18 2022, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> Whereas the C11 warning is "just" recent FreeBSD && DEVELOPER=1.
>>
>> So I assumed if you weren't interested in the former before the final
>> you probably wouldn't be in the latter, but wanted to provide a more
>> narrow fix in case you were.
>
> If we muck with the inclusion of libgen.h, it then becomes a problem
> for everybody who builds on FreeBSD, not just the developer builds.
> IOW, it is not even narrower to begin with.  Giving the same
> potential breakage to everybody will make it easier to diagnose it,
> but because I do not trust -std=gnu99 on today's FreeBSD, I think it
> is a problem we do not even have to solve.

The patch I submitted could trivially have an additional "#ifdef
DEVELOPER" or equivalent, which would narrow it down even further.

The reason it doesn't is because we provide -std=gnu99 in
config.mak.dev, but that doesn't mean that we don't have to deal with
e.g. a user-supplied -std=gnu99.

Except of course if we declare that we're not going to generally support
such a thing, and you should only provide such flags via
DEVELOPER/DEVOPTS, not manually in CFLAGS, which is fair enough.

>> I.e. the point of doing it is to avoid the one-time pain of anyone
>> building new releases of git on $OLD_OS/$OLD_DISTRO not having to run
>> into the compilation error that's fixed with NO_UNCOMPRESS2=Y.
>> ...
>> If we then get this into v2.36.0 there'll be someone somewhere that
>> benefits, but I'd think the ship has sailed for most of those who'd
>> avoid the needless flag twiddling (git-packagers@ et al).
>
> I actually think it is a good thing.  It is what they brought onto
> themselves.  They can follow David's example next time.

Do you mean David Aguilar's addition of "NO_UNCOMPRESS2 = YesPlease" in
[1]? Isn't that mutually exclusive with pursuing my change to
auto-detect it[2] instead?

As noted I'm a bit "meh" on my own patch if it's not in the release. I'm
just trying to see where you stand, since you seemed to want a re-roll
of it post-release....

1. https://lore.kernel.org/git/20220116020520.26895-1-davvid@gmail.com/
2. https://lore.kernel.org/git/patch-1.1-9cea01a1395-20220117T170457Z-avarab@gmail.com/
Junio C Hamano Jan. 19, 2022, 1:19 a.m. UTC | #20
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> As noted I'm a bit "meh" on my own patch if it's not in the release. I'm
> just trying to see where you stand, since you seemed to want a re-roll
> of it post-release....

I was hoping to see a quick reroll that would be in time for the
release, but it seems it was overly optimistic back when I gave my
initial review.  I do not see it happening given that I'd be tagging
the -rc2 tomorrow.

I do think in the longer term, we should aim to retire the current
mechanism and depend more on ZLIB_VERSION_NUM.  I am not optimistic
that we can have a reasonable version before the final.
diff mbox series

Patch

diff --git a/config.mak.dev b/config.mak.dev
index 7673fed114..d4afac6b51 100644
--- a/config.mak.dev
+++ b/config.mak.dev
@@ -19,6 +19,11 @@  endif
 endif
 endif
 endif
+
+ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),)
+DEVELOPER_CFLAGS += -std=gnu99
+endif
+
 DEVELOPER_CFLAGS += -Wdeclaration-after-statement
 DEVELOPER_CFLAGS += -Wformat-security
 DEVELOPER_CFLAGS += -Wold-style-definition