Use both -isystem and -I for the same path with CMake - c++11

Is there a way to use both -isystem and -I on the same path in CMake? I am currently doing something like the following:
add_library(lib SHARED libSource.cpp)
target_include_directories(lib PUBLIC pathA)
target_include_directories(lib SYSTEM PUBLIC pathA)
When I run make VERBOSE=1, the build flags for lib only include -isystem pathA, where I need both -isystem pathA and -IpathA.

CMake allows generator expressions, which you could use, for example:
Output Expressions:
These expressions generate output, in some cases depending on an input. These expressions may be combined with other expressions for information or logical comparison:
-I$<JOIN:$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>, -I>
Generates a string of the entries in the INCLUDE_DIRECTORIES target property with each entry preceded by -I. Note that a more-complete use in this situation would require first checking if the INCLUDE_DIRECTORIES property is non-empty:
$<$<BOOL:${prop}>:-I$<JOIN:${prop}, -I>>
Where ${prop} refers to a helper variable:
set(prop "$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>")
↳ CMake Generator Expressions

Related

How to modify implicit GNUMake rules to compile files?

GNUMake has implicit rules to compile certain file types, for instance, in my directory if I have a file 1.cpp, and I write on terminal make 1, the following command gets executed:
g++ 1.cpp -o 1
All this happens without any Makefile in the directory, due to implicit Make rules. However, I am unable to figure out how to modify these rules for my benefit. For instance, if I need to compile my file like this:
g++ -std=c++14 -O2 -g -w -o 1 1.cpp
and for doing this, I want to run the command: make 1, it should do it. Also, it should be generic for any file, for instance I now create a file 2.cpp and write make 2, it should compile it and produce the executable, even if there is no rule for 2 in my Makefile.
Also, if I now go to another directory where this explicit rule has not been mentioned, it should compile according to the default implicit rules only. How to I achieve this?
One way is to set the variables used by the implicit rules in your environment
set CXXFLAGS="-std=c++14 -O2 -g -w"
If you only want this to apply to a single directory, then place a Makefile in the directory with the following
CXXFLAGS := -std=c++14 -O2 -g -w

automake: the ordering of compiler options hinders make

I am new to automake tools. In "src/Makefile.am", I use "AM_LDFLAGS = -L... -l...".
Then, I run "autoreconf --force --install ; ./configure ; make"
In the last command,
$ g++ -O2 -L... -l... -o target_name [some *.o files]
the compiler complains "undefined reference to ...".
But if I copy it and move "-L... -l..." to the end, and run it independently it is fine (below).
$ g++ -O2 -o target_name [some *.o files] -L... -l...
So the order of options does matter? Anyway, how to smooth it?
Thanks a lot.
For the "-L" options, try using the LDADD or target_name_LDADD variable instead (where target_name is replaced with the actual target name). This places these flags at the end of the linking command.
The order of "-l" and "-L" does make a difference. From http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html:
-l library
Search the library named library when linking. ... It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded. ... The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined.
So libraries should appear after object files/other libraries that depend upon them.

How to customize the meaning of the "-l" flag for GCC?

I have problems with GCC and I would like to use the -l flags in a customized way.
I would like to specify the search path for the correspondant libfoo specified by -lfoo , I also would like to override any internal search path in GCC, i don't want GCC to use any random lib that can solve the symbols, I only want GCC to compile with a really specific lib when -l is specified.
I know that there are utils such as pkg-config but my problem is more gcc-centric because i'm focusing on having more control on the compilation steps.
There is an undocumented syntax for specifying an absolute lib path to gcc:
$ gcc -o test test.c -l:/usr/lib/libfoo.so #(note the colon)
See here: https://code.ros.org/lurker/message/20130119.001059.fad11362.de.html
A more standard way to do this would simply be:
$ gcc -o test test.c /usr/lib/libfoo.so
Really, the only reason to use the -l: syntax is if you have a conflicting library of the same name in your search path and you can't change the search path.

what's the difference between DLDFLAGS and LDFLAGS

A quick question. I found both "DLDFLAGS" and "LDFLAGS" in a sample Makefile. The compiler used is gcc. It looks like they are both used for linkers. I'm wondering what's the difference between them.
LDFLAGS is normally set to contain options that are passed through to the linker (so may include required libraries). Together with CFLAGS, these are often set as part of a developers environment variables and make will know about them so will actively look to see if they're set and pass them through to the compiler.
For example, if I set CFLAGS in my environment to -O2 -Wall, then if I type make hello with no Makefile, make will automatically invoke the compiler as gcc -O2 -Wall hello.c -o hello.o. Then it'll invoke the linker in a similar way, adding the flags in LDFLAGS to the command line.
Makefiles can explicitly override both LDFLAGS and CFLAGS.
DLDFLAGS on the other hand is not a well known/defined variable, so it's likely to be specific to that particular Makefile. You'd have to read the Makefile to find out how it's used. It may, for example, define linker flags to use if LDFLAGS is set - read the Makefile to find out for sure.
Isn't DLDFLAGS just a precompiler flag that defines macro named "LDFLAGS"?
From gcc manual:
-D name
Predefine name as a macro, with definition 1

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