In my C++ project, I have a convention where whenever the macro DEBUG is defined, debugging printf-esque statements are compiled into the executable.
To indicate whether or not I want these compiled into the executable, I normally would pass the macro name to gcc with the -Dmacro option. So, in the Makefile I (currently) have:
CXXFLAGS += -g -I ../ -Wall -Werror -DDEBUG
However, this is not very flexible; if I didn't want debug statements in my final program, I'd have to modify the Makefile to remove the -DDEBUG.
Is there a way to modify the Makefile such that I can conditionally select whether to compile with -D in the CXXFLAGS at compile time by passing in, say, another target name or a commandline switch? Not sure how'd I go about doing that.
You can conditionally define other variables based on the target in the makefile.
all: target
debug: target
debug: DEBUG=PLOP
target:
#echo "HI $(DEBUG)"
So now:
> make
HI
>
> make debug
HI PLOP
>
Append another variable that you can set from the CLI or environment
$ cat Makefile
CXXFLAGS += $(CLIFLAGS)
maintarget:
echo $(CXXFLAGS)
$ make CLIFLAGS=-DDEBUG
echo -DDEBUG
-DDEBUG
$
Consider this one:
http://users.softlab.ece.ntua.gr/~ttsiod/makefile.html
After meditating upon the make documentation, I tried putting this in my Makefile:
ifneq(,$(findstring d,$(MAKEFLAGS)))
CXXFLAGS += <... all normal options ...> -DDEBUG
else
CXXFLAGS += <... all normal options ...>
endif
Then, when you run make -d, -DDEBUG is set.
Now, mind you, it works, but I had to use a normal flag that make usually accepts (you can't make up your own). Using -d also spews (harmless) verbose make-level debugging statements to the screen. Which I really don't want; it obscures compile errors. But it does work.
I hope someone can come up with a better idea.
Related
I have a Makefile.in file that generate a Makefile.am by configure. After that with automake the Makefile.am create the Makefile.
Now i want to add a define in the geneated Makefile. The problem is that in the generated Makefile i found a list of flags in variable CPPFLAGS, but in the definition of CPPFLAGS in the Makefile.in i found only a line that is write in the following way:
CPPFLAGS = #CPPFLAGS#
What does it means #CPPFLAGS# ? And how i can set a new flag in the generated Makefile?
CPPFLAGS stands for C Pre Processor flags.
You can set it as an environmental variable or via the commandline:
CPPFLAGS="-g -Wall -O0" automake
or
CPPFLAGS="-g -Wall -O0" make
From the gnu Make manual:
CPPFLAGS
Extra flags to give to the C preprocessor and programs that use it (the C and Fortran compilers).
The string #CPPFLAGS# is expanded by the configure script to be the value of CPPFLAGS at the time configure is executed. In other words, if you run configure CPPFLAGS=foo, then #CPPFLAGS# will be expanded to the string foo.
Automake was run long before configure is invoked. All automake did was add the string #CPPFLAGS# to Makefile.in when it built that file.
As the project maintainer, you should not edit these values. This is the mechanism by which the user is able to add flags to the build at configure time.
If you want to add flags, you should assign to AM_CPPFLAGS in Makefile.am. But chances are you don't really want to do that. It's hard to say, and will depend on what flags you think you want to add.
I would like to compile and run my program in two different environments. The libraries in both environments are installed on slightly different places, resulting in different makefile-lines:
In makefile A:
CXXFLAGS=-I$(DIR) -flto -fopenmp -O3 -g -march=native -std=gnu++17 -c -I/opt/interp2d/include -std=c++17 -I/opt/splinter/include -I/usr/include/eigen3
In makefile B:
CXXFLAGS=-I$(DIR) -nostindc++ -I~/local_opt/eigen/include/eigen3/ -I~/local_opt/boost/include -I~/local_opt/armadillo/include -flto -fopenmp -O3 -g -march=native -std=gnu++17 -c -I~/local_opt/interp2d/include -std=c++17 -I~/local_opt/splinterp/include -I/usr/include/eigen3
My problem now is that I am developing the program on the first machine, using makefile A, but also deploying it on the second machine. The deployment is done using git.
Every time I do a git pull on the second machine, I have to fix all the paths in the makefile in order to compile the program properly. Nevertheless I still would like to include the makefile in the git repository in order to keep both makefiles at the same level regarding compiling flags and linked libraries.
Thus, is there an easier way to still sync the makefile via git, while using different paths for the libraries and includes?
I think you could solve your problem by conditionally setting the variable CXXFLAGS in a common file (e.g.: config.mk) and by including that file in your makefiles.
The value used for setting the CXXFLAGS variable could, for example, depend on the value of the environment variable HOST:
ifeq ($(HOST),A)
CXXFLAGS = ... # for machine A
else # B
CXXFLAGS = ... # for machine B
endif
Then, include this config.mk makefile in both makefileA and makefileB:
include config.mk
I like this answer, however, I thought I'd mention this for completeness: If you have a lot of different hosts you can do something to the effect of:
include HostConfig_$(HOST).mk
And then create HostConfig_A.mk and HostConfig_B.mk which set host specific flags (Be it directories, etc). This is useful if you are managing a large project with lots of different host-specific variables.
As well, (for smaller projects), you could do something to the effect of:
CXX_INCLUDES_A = ...
CXX_INCLUDES_B = ...
CXX_FLAGS := -I$(DIR) -flto -fopenmp -O3 -g -march=native -std=gnu++17
CXX_FLAGS += $(CXX_INCLUDES_$(HOST))
The traditional answer to this problem is a configure script (see automake, autoconf for widely used framework). After checking out the source you run ./configure --with-eigen=~/local_opt/eigen/include/eigen3/ and it will adjust your Makefiles accordingly (usually generates Makefile from Makefile.in and only Makefile.in is in git).
Note: Properly done you only need to run configure on the first checkout, not on updates. make can generate Makefile again automatially as needed.
I am trying to enable and disable compile flags for gcov in C++ on Linux. I do not want to have the gcov flags set at all times. I only want them set when I am testing the software. The environment variable I am checking is called TESTENABLED.
In my configure.ac file I have the following line:
AM_CONDITIONAL([ENABLEGCOV],[test x$TESTENABLED = xtrue])
In my Makefile.am file I have the following lines:
if ENABLEGCOV
AM_CXXFLAGS = -Wall -fPIC -fprofile-arcs -ftest-coverage
else
AM_CXXFLAGS = -Wall
endif
However when I build my program I notice that it is not setting AM_CXXFLAGS correctly. So none of my gcov .gcno/.gcda files are being generated. Does anyone see what I am doing wrong?
Do you have your environment variable set to true, or probably to some other truish-value (e.g. 1)?
In any case, the usual way would be add a flag to configure that turns on a certain feature. The following configure.ac snippet adds a --enable-gcov flag to configure; it will also do a printout whether it has enabled gcov or not:
AC_ARG_ENABLE(gcov,[AS_HELP_STRING([--enable-gcov], [enable coverage test])])
AC_MSG_CHECKING([whether to enable gcov])
AS_IF([test "x${enable_gcov}" = "xyes" ], AC_MSG_RESULT([yes]), AC_MSG_RESULT([no]))
AM_CONDITIONAL([ENABLEGCOV],[test "x${enable_gcov}" = "xyes"])
I also find Makefile.am more easy to read by just adding flags to CXXFLAGS if a certain condition is met:
AM_CXXFLAGS = -Wall -fPIC
if ENABLEGCOV
AM_CXXFLAGS += -fprofile-arcs -ftest-coverage
endif
I just recently switched back to Linux from windows and VC, but I never done any special coding using g++ compiler.
Currently my libraries (boost and others) are scattered all over the hard drive and I need to learn how to setup my compiler and linker so that all the compiler settings..
(includes, libs, flags) etc.. will be held in one single file or place, so that it becomes easy to manage, because I don't want to type these things every time I launch the compiler on command line.
Also note that I'm using a vim as my code editor and do not want to use IDE.
What is the best way to achieve that goal?
You need to use some of Building tools. It's allow you type small command (in vim you need just type :make) which launch build process with predetermined parameters (includes, libs, etc).
For C++ in Linux the most common tools are:
- make;
- automake;
- CMake.
If you use Qt also qmake is available.
I've had experience with all of them and my suggestion is use plain make for small projects and CMake for others and don't use autotools while you don't have to do it.
Note: All hight-level tools just help generate appropriate files (Makefile) for plain make (CMake generate Makefile based on CMakeLists.txt, automake based on Makefile.am, qmake based on *.pro).
because I don't want to type these things every time I launch the
compiler on command line.
I don't like to type either. All I want to do for small builds is issue:
(1) a short alias (2) the name of the file to compile, and (3) an output file.
Then I want my tool to take care of all common options, and if necessary, include the paths to any extra -I include directories, -L library directories and form the command line for me.
I have a short script that can handle the drudgery. Separating your projects into separate directories and including a 'bldflags' file with specific options allows the scripts to load any project specific options you may require. It is flexible enough to take any additional options specified on the command line. Alias the script in your .bashrc, and all that is required for quick builds is:
g+ filename.cpp outname
Now this is a very basic script and is not intented to replace proper build tools for your projects, but for quick compilations, it, or something like it, will sure cut down on the typing required. Here is the short script:
#!/bin/bash
## validate input
test -n "$1" && test -n "$2"|| { echo "insufficient input. usage: ${0//*\//} source.cpp out [options]"; exit 1; }
## set standard build flags and test if exists/source ./bldflags
stdclfags="-Wall" # add any standard flags you use.
test -r ./bldflags && bldflags="`<./bldflags`"
## show build command and call g++
echo -e "building $1 with:\n g++ $stdclfags -o $2 $1 $bldflags ${#:3}"
g++ $stdclfags -o "$2" "$1" $bldflags ${#:3}
exit 0
Make the script executable and include a simple alias in your .bashrc giving it any name you like:
alias g+='/home/david/scr/utl/bgc++.sh'
Examples of basic use: (basic without additional flags or a ./bldflags file)
$ g+ input.cpp output
building input.cpp with:
g++ -Wall -o output input.cpp
With a few extra options added on the command line:
$ g+ input.cpp output -Wunused -fno-default-inline
building input.cpp with:
g++ -Wall -o output input.cpp -Wunused -fno-default-inline
Including project specific options in ./bldflags (e.g: -I/home/david/inc -L/home/david/lib -Wl,-rpath=/home/david/lib
g+ input.cpp output -Wunused -fno-default-inline
building input.cpp with:
g++ -Wall -o output input.cpp -I/home/david/inc -L/home/david/lib -Wl,-rpath=/home/david/lib -Wunused -fno-default-inline
So to address the I don't want to type these things every time I launch the
compiler on command line, this is a very quick and easy way I've found to cut the typing down to a minimum for quick/repetitive builds where a full Makefile isn't needed.
How can I make GNU Make use a different compiler without manually editing the makefile?
You should be able to do something like this:
make CC=my_compiler
This is assuming whoever wrote the Makefile used the variable CC.
You can set the environment variables CC and CXX, which are used for compiling C and C++ files respectively. By default they use the values cc and g++
If the makefile is written like most makefiles, then it uses $(CC) when it wishes to invoke the C compiler. That's what the built-in rules do, anyway. If you specify a different value for that variable, then Make will use that instead. You can provide a new value on the command line:
make CC=/usr/bin/special-cc
You can also specify that when you run configure:
./configure CC=/usr/bin/special-cc
The configuration script will incorporate the new CC value into the makefile that it generates, so you don't need to manually edit it, and you can just run make by itself thereafter (instead of giving the custom CC value on the command line every time).
Many makefiles use 'CC' to define the compiler. If yours does, you can override that variable with
make CC='/usr/bin/gcc'
Use variables for the compiler program name.
Either pass the new definition to the make utility or set them in the environment before building.
See Using Variables in Make
Makefile:
#!MAKE
suf=$(suffix $(src))
ifeq ($(suf), .c)
cc=gcc
else
ifeq ($(suf), .cpp)
cc=g++
endif
endif
all:
$(cc) $(src) -o $(src:$(suf)=.exe)
clean:
rm *.exe
.PHONY: all clean
Terminal:
$ make src=main.c