help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: CFLAGS and other flag variables


From: Alejandro Colomar
Subject: Re: CFLAGS and other flag variables
Date: Wed, 17 Jul 2024 11:11:01 +0200

Hi Kaz,

On Tue, Jul 16, 2024 at 05:10:00PM GMT, Kaz Kylheku wrote:
> On 2024-07-16 06:37, Alejandro Colomar wrote:
> > Hi Paul!
> > 
> > Usual compilation in a makefile is something like
> > 
> >     foo.o: foo.c; $(CC) $(CFLAGS) $< -o $@
> 
> You should only need:
> 
>   foo.o: foo.c
> 
> because there is a built-in recipe for making .o files

Except that I do:

        MAKEFLAGS += --no-builtin-rules
        MAKEFLAGS += --no-builtin-variables
        MAKEFLAGS += --warn-undefined-variables

Sorry for not mentioning that.

> from .c which uses $(CC) and $(CFLAGS), almost identical
> to yours, except that the built-in recipe also
> references CPPFLAGS.

Yep, my actual recipe also uses CPPFLAGS.  I wrote it like that to keep
it short.

> 
> > If a project needs some CFLAGS, I guess it would do the following
> > 
> >     CFLAGS ?= $(shell pkgconf --cflags somedep)
> 
> The problem with this that you're saying "if CFLAGS
> isn't set, then define it with the options for a needed
> dependency".
> 
> You should only conditionally define CFLAGS to set
> some basic options that are not strictly necessary.
> 
>   CFLAGS ?= -O2   # Optimize, unless told otherwise
> 
> You should never be clobbering the CFLAGS. CFLAGS belongs
> to the user building the program, which could be an entire
> distro.
> 
> Distros set certain things with CFLAGS, like tuning for
> a particular CPU and whatnot.

Thanks.  I assumed that, although I didn't know the exact semantics when
a user specifies CFLAGS.

> 
> Programs should use CFLAGS, CPPFLAGS, LDFLAGS and LDLIBS if those
> are set on the make command line or in the environment.

Hmmmm, for the time being, I won't be able to use them from the
environment, because that conflicts with

        MAKEFLAGS += --no-builtin-variables

I'll need the next release of make(1) to be able to use an empty default

        CFLAGS ?=

> If you want to use built-in recipes, and your code needs
> certain cflags (like for instance C dialect selection), then
> you can add that to CFLAGS:
> 
>    CFLAGS += -std=c17 -Wmy-favorite-warning-option

There's a problem with that.  My selection would have preference over
the user, since it's specified later in the command line.  It should be
the user that has preference, so I need a way to prepend to CFLAGS, not
append.  I want this:

        CFLAGS  ?=
        CFLAGS_ := -Wmy-fav-warn-opt $(CFLAGS)

and then use CFLAGS_ instead of CFLAGS in recipes.

> If you want your users to tweak some of your own flags without
> having to edit your Makefile, you can use your own variables.
> 
>    FOO_LANG_FLAGS := -std=c17
>    FOO_DIAG_FLAGS := -Wall -W
> 
>    CFLAGS += $(FOO_LANG_FLAGS) $(FOO_DIAG_FLAGS)
> 
> Now the user can use "make FOO_DIAG_FLAGS=..." to add a diagnostic
> option, without having to mess with CFLAGS.

Since appending a different -std= or -Wno- overrides my selection, they
should only need to append it to the command line, without using my
internal variable names.

> For instance, the user could be running a build recipe from a distro,
> which specifies CFLAGS, so having to get between the distro and
> the programs' build system to adjust CFLAGS is inconvenient.
> 
> (If you ever have to do that, it's a good thing that GNU Make
> supports the += syntax on the command line.)

Not so good in this case, because of the need for prepending.  In fact,
I seldom use +=.  Only in conditionals.

        $ find GNUmakefile share/mk/ -type f \
        | grep '\.mk$' \
        | xargs grep += \
        | wc -l;
        4

> 
> There are two variables LDFLAGS and LDLIBS because linker flags
> like -Wl,-L/path/to/dir and library options like -lfoo are
> separated on the compiler command line; the libraries come last.
> 
> If you write your own recipe for linking an executable or shared
> object, you should pull in $(LDFLAGS) and $(LDLIBS) in the
> right places.
> 
> Distros sometimes use both of these!
> 
> CPPFLAGS is for C preprocessor flags that are independent of
> language. In GNU Make, built-in recipes for different languages
> bring in CPPFLAGS.
> 
> CPPFLAGS could be used for something like passing a -DFOO=BAR
> option everywhere the preprocessor is used, whether for C, or
> Fortran or whatever.
> 
> GNU CPP has some -W diagnostic options that make sense in CPPFLAGS.
> For instance -Wundef: warn if an undefined identifier is
> referenced in an #if directive, where it is treated as zero.
> 
> In summary, a C project should use all of these if they are defined:
> 
> CFLAGS, CPPFLAGS, LDFLAGS, LDLIBS.

Yup, I use all of these.  Thanks!

> 
> The project should only add to these variables, never taken them over.
> 
> Never do things like CFLAGS ?= --badly-needed-option  where your program
> breaks at build time or run time without --badly-needed-option.
> Use this only to set up some some minimal optimization.
> 
> If CFLAGS exist,

The bad part is that CFLAGS _always_ exists (unless you remove it on the
command line with -R, which is kind of nonsensical, because whoever runs
make(1) already can override it by specifying a different value
explicitly).

Thankfully, the next version of make(1) will fix that historical bug.

> assume that the user/distro is using that to
> control optimization and possibly other code generation options.
> You can disable optimization by adding -O0 after $(CFLAGS).

That would be overriding the user's choice, which I don't think is a
good idea.

Thanks!

Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es/>

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]