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 from .c which uses $(CC) and $(CFLAGS), almost identical to yours, except that the built-in recipe also references CPPFLAGS. > 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. Programs should use CFLAGS, CPPFLAGS, LDFLAGS and LDLIBS if those are set on the make command line or in the environment. 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 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. 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.) 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. 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, 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).