How to use GCC's I-flag to include multiple folders? - gcc

Normally I use GCC's I-flag to include folders in this way:
gcc main.c -IfolderA -IfolderB
Well I need to reorganize my makefiels structure and I'm thinking about to have an environment variable which is defined as this:
INCLUDES="folderA folderB"
How could I use GCC's I-flag to include both folders?
I thought about something (but it does not work) like this:
gcc main.c -I($(INCLUDES))

You need to add the -I flag to all the "elements" of your INCLUDES variable. Perhaps through something like this:
gcc main.c $(foreach dir,$(INCLUDES),-I$(dir))
The foreach function.

You could also use the addprefix function -- although it's designed to work on filenames, it can still be used here:
gcc main.c $(addprefix -I,$(INCLUDES))

Related

Module specific includes, CXXFLAGS in non-recursive makefile

I am implementing Non-Recursive Make, using John Graham Cummings example here.
I would like to be able to specify specific includes or specific compilation flags, depending on which module I'm compiling.
For instance, say I have directories(and therefore separate Makefiles in) src/lib1 and src/executable. Say I would like to use -std=c++11 for the src/lib1 Makefile compilation, and (for some reason) -std=gnu99 for the src/executable Makefile.
Another example, say I need to include different paths for these directories.
What is the standard way to do this in non-recursive make?
What I have tried so far is something like...
$(MODULE_NAME)_CXXFLAGS:=-std=c++11
$(MODULE_NAME)_INCLUDES:=--I/.
But then the following printit just echos nothing.
printit:
#echo $($(MODULE_NAME)_INCLUDES)

pass variable to make file

I read documents about CPPFLAGS. Shortly, I understand that CPPFLAGS used for pass parameter to compiler. Sample usage CPPFLAGS in makefile is below.
gcc $(CPPFLAGS) main.c -o main.o
Execute make
make CPPFLAGS=-I../header
What is special CPPFLAGS text? It can be interchangable any other text like "FOO". What is the differences between FOO variable and CPPFLAGS variable? Replace all CPPFLAGS text with FOO text build is success again, nothing changes.
Main problem that actually need to solve. There are lots of makefiles. There is no include CPPFLAGS variable in these makefiles. Is there a way to pass compiler options without change makefiles.
Thanks.
What is special CPPFLAGS text? It can be interchangable any other text like "FOO"
Three things are special about CPPFLAGS:
It is a convention that many tools follow. Most notably GNU autoconf/automake.
GNU Make provides implicit rules to build many target types. These implicit rules use CPPFLAGS variable when compiling .o from C and C++ sources. These rules can be replaced with one's own rules if necessary.
When you use CPPFLAGS for preprocessor flags you follow the principle of least astonishment.
There is no include CPPFLAGS variable in these makefiles
If you meant that there are no occurrences of CPPFLAGS in the makefiles that may be because the implicit rules are used which I mentioned above.

makefile question

I'm looking to modify a makefile to include a local directory of headers. However, most of the makefile compilation happens outside my current makefile limiting what I can do. Here's the current makefile:
TARGET = final
LIBS = -lsimple -lcheck -lsuif -luseful
OBJS = doproc.o main.o
all: $(TARGET)
install-bin: install-prog
include $(SUIFHOME)/Makefile.std
The directory of headers (boost) I wish to use of is in the same directory as this makefile and doproc.cc/main.cc. I tried modifying the makefile to this
TARGET = final
INC= -I/boost
LIBS = -lsimple -lcheck -lsuif -luseful
OBJS = doproc.o main.o
all: $(TARGET) $(INC)
install-bin: install-prog
include $(SUIFHOME)/Makefile.std
but to no effect. I have an account on this machine but no root access and I can't change Makefile.std. If this is trivial, I apologize. I'm not used to using makefiles.
Thanks in advance
EDIT:
The suggestions so far are helpful for getting me the right directory. But It's still not making the directory be included in the compilation
Okay, it's really hard to discern all details without knowing the internals of Makefile.std. However, let's assume that $(INC) is not somehow magically consumed inside Makefile.std (it's at least not one of the default macros, see make -p for those), in this case you would have to append your include folders to CXXFLAGS (for C++) or CFLAGS (for C) like so:
CXXFLAGS+=$(CXXFLAGS) -I$(MAKEDIR)/boost
Side-note: There are variations on this, but from where I stand
all: $(TARGET) $(INC)
doesn't make too much sense for a value of -I/boost or even the corrected -I$(MAKEDIR)/boost. The reason is that it is no variable assignment (which is possible instead of dependencies) and thus would be considered as a file dependency (unless declared .PHONY).
I should add that I'm assuming the usual default rules that come with GNU make. Otherwise you'd have to show us the actual rules %.o: %.cpp etc ...
Use this - Your current INC specifies /boost not ./boost:
INC= -I$(PWD)/boost
/ is filesystem root; ./ is current directory.
Did you mean -I./boost? -Iboost works too.
Remove the leading / in front of boost. You're telling the compiler to look in /boost under the root folder.

Compiling with different flags in Makefile?

I have a single program used to interact with a joystick. It uses conditional compilation to specify a specific joystick. We do this right now by just hard coding the correct flag into the Makefile.
I'd like to make it so it uses a different flag based on the command given to the Makefile. So for example, I currently have this:
.PHONY: saitek
saitek: $(SOURCES)
$(COMPILE) -DSAITEK
.PHONY: logitech
logitech: $(SOURCES)
$(COMPILE) -DLOGITECH
I want only one of these commands to ever be run, and I want them all to make the same executable. But if I rerun 'make' it will compile the program again. I'd like it to recognize that it's already built the program.
Is there anyway to do this with a Makefile?
If you're using GNUMake, this will do what you're asking. It uses a different flag based on the command given to Make, and it doesn't rebuild the program unnecessarily.
.PHONY: saitek logitech
saitek: JOYSTICK=SAITEK
logitech: JOYSTICK=LOGITECH
# Suppose the actual name of your executable is "program"
saitek logitech: program
program: $(SOURCES)
$(COMPILE) -D$(JOYSTICK)
GNU make inherits variables from its environment, so if you specify
$ JOYSICK=LOGITECH
in your shell, and use
CFLAGS+=-D$(JOYSTICK)
in your makefile.
I question the necessity of this. You could just call make as something like make CFLAGS=-DSAITEK or use autoconf and substitute in the correct defines.
That said, how about something like this:
saitek logitech: program
.PHONY: saitek logitech
ifeq ($(MAKECMDGOALS),saitek)
CFLAGS += -DSAITEK
endif
ifeq ($(MAKECMDGOALS),logitech)
CFLAGS += -DLOGITECH
endif
program: $(OBJS)
# Whatever

CFLAGS vs CPPFLAGS

I understand that CFLAGS (or CXXFLAGS for C++) are for the compiler, whereas CPPFLAGS is used by the preprocessor.
But I still don't understand the difference.
I need to specify an include path for a header file that is included with #include -- because #include is a preprocessor directive, is the preprocessor (CPPFLAGS) the only thing I care about?
Under what circumstances do I need to give the compiler an extra include path?
In general, if the preprocessor finds and includes needed header files, why does it ever need to be told about extra include directories? What use is CFLAGS at all?
(In my case, I actually found that BOTH of these allow me to compile my program, which adds to the confusion... I can use CFLAGS OR CPPFLAGS to accomplish my goal (in autoconf context at least). What gives?)
The implicit make rule for compiling a C program is
%.o:%.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
where the $() syntax expands the variables. As both CPPFLAGS and CFLAGS are used in the compiler call, which you use to define include paths is a matter of personal taste. For instance if foo.c is a file in the current directory
make foo.o CPPFLAGS="-I/usr/include"
make foo.o CFLAGS="-I/usr/include"
will both call your compiler in exactly the same way, namely
gcc -I/usr/include -c -o foo.o foo.c
The difference between the two comes into play when you have multiple languages which need the same include path, for instance if you have bar.cpp then try
make bar.o CPPFLAGS="-I/usr/include"
make bar.o CFLAGS="-I/usr/include"
then the compilations will be
g++ -I/usr/include -c -o bar.o bar.cpp
g++ -c -o bar.o bar.cpp
as the C++ implicit rule also uses the CPPFLAGS variable.
This difference gives you a good guide for which to use - if you want the flag to be used for all languages put it in CPPFLAGS, if it's for a specific language put it in CFLAGS, CXXFLAGS etc. Examples of the latter type include standard compliance or warning flags - you wouldn't want to pass -std=c99 to your C++ compiler!
You might then end up with something like this in your makefile
CPPFLAGS=-I/usr/include
CFLAGS=-std=c99
CXXFLAGS=-Weffc++
The CPPFLAGS macro is the one to use to specify #include directories.
Both CPPFLAGS and CFLAGS work in your case because the make(1) rule combines both preprocessing and compiling in one command (so both macros are used in the command).
You don't need to specify . as an include-directory if you use the form #include "...". You also don't need to specify the standard compiler include directory. You do need to specify all other include-directories.
You are after implicit make rules.
To add to those who have mentioned the implicit rules, it's best to see what make has defined implicitly and for your env using:
make -p
For instance:
%.o: %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
which expands
COMPILE.c = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
This will also print # environment data. Here, you will find GCC's include path among other useful info.
C_INCLUDE_PATH=/usr/include
In make, when it comes to search, the paths are many, the light is one... or something to that effect.
C_INCLUDE_PATH is system-wide, set it in your shell's *.rc.
$(CPPFLAGS) is for the preprocessor include path.
If you need to add a general search path for make, use:
VPATH = my_dir_to_search
... or even more specific
vpath %.c src
vpath %.h include
make uses VPATH as a general search path so use cautiously. If a file exists in more than one location listed in VPATH, make will take the first occurrence in the list.
I installed httpd on Ubuntu 18.04 using the CPPFLAGS variable for the -DLINUX flag. When run, CPPFLAGS scans the code from top to bottom, file by file, looking for directives before compiling, and will not be extended by other meaningful things like size optimization, flags that do not increase the size of the output file; under the type of processor; to reduce the size of the code and speed up the program; disable all variables except case. The only difference between CPPFLAGS and CFLAGS is that CFLAGS can be set to specify additional switches to be passed to the compiler. That is, the CFLAGS environment variable creates a directory in the installation path (eg CFLAGS=-i/opt/include) to add debugging information to the executable target's path: include general alarm messages; turning off alarm information; independent location generation; display compiler driver, preprocessor, compiler version number.
Standard way to set CPPFLAGS:
sudo ./configure --enable-unixd=DLINUX #for example
list of some known variables:
CPPFLAGS - is the variable name for flags to the C preprocessor.
CXXFLAGS - is the standard variable name for flags to the C++ compiler.
CFLAGS is - the standard name for a variable with compilation flags.
LDFLAGS - should be used for search flags/paths (-L) - i.e. -L/usr/lib (/usr/lib are library binaries).
LDLIBS - for linking libraries.
CPPFLAGS seems to be an invention of GNU Make, referenced in some of its built-in recipes.
If your program is built by some Free software distributions, you may find that some of them require packages to interpolate this variable, using CPPFLAGS for passing down options like -D_WHATEVER=1 for passing down a macro definition.
This separation is a poor idea and completely unnecessary in the GNU environment because:
There is a way to run gcc to do preprocessing only (while ignoring compiler options unrelated to preprocessing).
The stand-alone GNU cpp is tolerant to compiler options, such as -W warnings that do not pertain to preprocessing and even code generation options like -fstrict-aliasing and the linker-pass through like -Wl,--whatever.
So generally speaking, build systems that need to call the stand-alone preprocessor for whatever reason can just pass it $(CFLAGS).
As an application developer writing a Makefile, you cannot rely on the existence of CPPFLAGS. Users who are not insider experts in open source building won't know about CPPFLAGS, and will do things like make CFLAGS=-Dfoo=bar when building your program. If that doesn't work, they will be annoyed.
As a distro maintainer, you cannot rely on programs to pull in CPPFLAGS; even otherwise well-behaved ones that pull in CFLAGS, LDFLAGS and LDLIBS.
It's easy enough for the application developers to write GNU Make code to separate preprocessor flags out of $(CFLAGS):
cpp_only_flags := $(foreach arg, \
$(CFLAGS), \
$(or $(filter -D%,$(arg)), \
$(filter -U%,$(arg)), \
$(filter -I%,$(arg)), \
$(filter -iquote%,$(arg)), \
$(filter -W%,$(arg)), \
$(filter -M%,$(arg)))) \
$(CPPFLAGS) # also pull this in
all:
#echo cpp_only_flags == $(cpp_only_flags)
Demo:
$ make CFLAGS="-Wall -I/path/to/include -W -UMAC -DFOO=bar -o foo.o -lm"
cpp_only_flags == -Wall -I/path/to/include -W -UMAC -DFOO=bar
In the case of the GNU compiler and preprocessor, this is probably unnnecessary; but it illustrates a technique that could be used for non-GNU compilers and preprocessors, in a build system based on GNU Make.

Resources