I have a makefile that can be reduced to this:
OBJS = obj1.o obj2.o
FLAGS = -Wall -Wextra -Werror -pedantic-errors -fno-rtti -std=c++0x
DEBUG_FLAGS = -ggdb -O0 -fstack-protector-all -D_GLIBCXX_DEBUG
RELEASE_FLAGS = -O3
release: $(OBJS)
g++ $(FLAGS) $(RELEASE_FLAGS) $(OBJS)
debug: $(OBJS)
g++ $(FLAGS) $(DEBUG_FLAGS) $(OBJS)
obj1.o: obj1.cpp
g++ -c $(FLAGS) obj1.cpp
obj2.o: obj2.cpp
g++ -c $(FLAGS) obj2.cpp
The problem is that all or none of the files must be built with the -D_GLIBCXX_DEBUG flag. I don't know how to do this without writing two entries for every compilation unit, like
obj1_release.o: obj1.cpp
g++ -c $(FLAGS) $(RELEASE_FLAGS) obj1.cpp
obj1_debug.o: obj1.cpp
g++ -c $(FLAGS) $(DEBUG_FLAGS) obj1.cpp
How can I make the -D_GLIBCXX_DEBUG flag (and the other debug flags) take effect for all compilation units only when the user types make debug without writing two entries for every CU? (And vice versa; the release flags need to take effect on all CUs when the user types make release.)
I apologise if this is the basics of writing Makefiles, I don't know much about them.
You are looking for pattern rules: something like this should do what you want. Note that this cannot be made to work correctly unless the debug and release versions of the program are given different names.
OBJS := obj1 obj2 obj3
R_OBJS := $(OBJS:=_r.o)
D_OBJS := $(OBJS:=_d.o)
all: prog_r prog_d
release: prog_r
debug: prog_d
prog_r: $(R_OBJS)
$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) $(LDFLAGS) $^ $(LIBS) -o $#
prog_d: $(D_OBJS)
$(CXX) $(CXXFLAGS) $(DEBUG_FLAGS) $(LDFLAGS) $^ $(LIBS) -o $#
%_r.o: %.cc
$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) -c $< -o $#
%_d.o: %.cc
$(CXX) $(CXXFLAGS) $(DEBUG_FLAGS) -c $< -o $#
# header files
obj1_d.o obj1_r.o: foo.h bar.h
obj2_d.o obj2_r.o: quux.h
# ... etc ...
There is a pretty straightforward way to select compilation flags based on the type of the build in Makefiles.
In addition to that you may like to ensure that debug build only links debug object files and same for release (i.e. no mixing debug and release object files). To achieve that compile object into different directories depending on the build type.
This might help : http://sunsite.ualberta.ca/Documentation/Gnu/make-3.79/html_chapter/make_7.html
You could check the first argument (debug/release) and set the CFLAGS accordingly.
HTH.
Related
I have multiple source files in a directory, which some are responsible for a main executable, and some are responsible for a shared library, which then in turn is needed for the main executable. Thus I wrote the makefile in the following way:
CC=gcc
CXX=g++
CFLAGS=-I$(DIR) -fPIC -c -fopenmp
CXXLFLAGS=-I$(DIR) -fopenmp -O3 -g -march=native -std=gnu++17 -fPIC -c
CXXFLAGS=-I$(DIR) -fopenmp -O3 -g -march=native -std=gnu++17 -c
LDFLAGS=-lfftw3 -lgomp -lm -larmadillo -lpthread -lX11 -lboost_system -lboost_program_options -L/opt/intel/mkl/lib/intel64 -lmkl_rt
LDMAINFLAGS=-lfftw3 -lgomp -lm -larmadillo -lpthread -lX11 -lboost_system -lboost_program_options -L/opt/intel/mkl/lib/intel64 -lmkl_rt -lpulse_propagation
LIBSOURCES=source/image_processing.cpp source/pulse_propagation.cpp
LIBOBJECTS=source/image_processing.o source/pulse_propagation.o
MAINSOURCES=source/fftw.cpp source/fftw++.cc
MAINOBJECTS=source/fftw.o source/fftw++.o
EXECUTABLE=fftw
LIBRARY=libpulse_propagation.so
.PHONY: default all clean
default: all
all: $(LIBRARY) main
main: $(LIBRARY) $(MAINOBJECTS)
$(CXX) $(LDFLAGS) $(MAINOBJECTS) -o $(EXECUTABLE)
$(LIBRARY): $(LIBOBJECTS)
$(CXX) $(LDFLAGS) -shared $^ -o $#
$(LIBOBJECTS): $(LIBSOURCES)
$(CXX) $(CXXLFLAGS) $^ -o $#
$(MAINOBJECTS): $(MAINSOURCES)
$(CXX) $(CXXFLAGS) $^ -o $#
clean_compile:
rm -f source/*.o
clean:
rm -f source/*.o $(EXECUTABLE) $(LIBRARY)
with everything labeled with a MAIN belonging to the main executable and everything else to the library. I would like to loop over the files in LIBSOURCES/MAINSOURCES and compile each of them. I would prefer if I do not have to use the .cpp.o:-macro, after there are different flags depending if it is a library file or a main file. I tried using $<, which executed the compilation twice (ok), but always used the first value from the variable list. When using $^ instead, both files are used at once, also resulting in an error. How could I else do that?
Your source/fftw++.cc instead of source/fftw++.cpp makes everything uselessly complex. If you can rename it, then the following should do what you want:
$(LIBOBJECTS): CXXFLAGS := $(CXXLFLAGS)
$(LIBOBJECTS) $(MAINOBJECTS): %.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
The first line defines the value of variable CXXFLAGS for the $(LIBOBJECTS) targets. The following rule is a static pattern rule that translates into as many rules with one target and one prerequisite only. It is completely different from your rules that declares all source files of one kind as prerequisites of all corresponding object files. Not what you want normally.
If you cannot rename source/fftw++.cc you can split your sources and objects lists:
MAINCPPSOURCES=source/fftw.cpp
MAINCCSOURCES=source/fftw++.cc
MAINCPPOBJECTS=source/fftw.o
MAINCCOBJECTS=source/fftw++.o
$(LIBOBJECTS): CXXFLAGS := $(CXXLFLAGS)
$(LIBOBJECTS) $(MAINCPPOBJECTS): %.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
$(MAINCCOBJECTS): %.o: %.cc
$(CXX) $(CXXFLAGS) $< -o $#
Finally, it would probably be better (easier to maintain) if you were computing what can be, instead of hard-wiring it in your Makefile:
MAINCPPOBJECTS = $(patsubst %.cpp,%.o,$(MAINCPPSOURCES))
MAINCCOBJECTS = $(patsubst %.cc,%.o,$(MAINCCSOURCES))
...
CC=g++
CFLAGS=-I
GCCCOMPFLAGS=-Wall -Wextra -O -ansi -pedantic -fpic -shared -c
GCCLINKFLAGS=-shared
DEPS = ./src/a.h ./src/b.h
OBJ = a.o b.o
CPPOBJ = mycpp.cpp
%.o: ./src/%.cpp $(DEPS)
$(CC) -DTARGET_OS_LINUX $(GCCCOMPFLAGS) -o $# $<
final: $(OBJ)
$(CC) -DTARGET_OS_LINUX $(GCCLINKFLAGS) -o ./src/$#.so $^
<newtarget>:
$(CC) -std=gnu++0x ..... -o mycpp.o mycpp.cpp
How to compile mycpp.cpp with different gcc option and add it to "final" linking target
Now I want compile a new file "mycpp.cpp" with different GCC options and add it to the final target to link together.
%.o: ./src/%.cpp $(DEPS)
$(CC) -DTARGET_OS_LINUX $(GCCCOMPFLAGS) -o $# $<
final: $(OBJ) mycpp.o
$(CC) -DTARGET_OS_LINUX $(GCCLINKFLAGS) -o ./src/$#.so $^
mycpp.o:
compile ...
This will make mycpp getting handled by the wild card %.o
How do we separate this build targets ?
Target-specific variables are fully explained in the GNU make documentation, which you should consult for additional information. In the Makefile:
mycpp.o: VARIABLE=X
This sets a variable within the scope of a single target only. Using this you can override CPPFLAGS, or any other variables, when building a specific target only.
Finally, for situations where more than just a variable needs to be overridden, you can always specify an explicit rule:
mycpp.o: ./src/mycpp.cpp
[ build instructions ]
that will override the default rule for building .o from .cpp.
I want to use a single make file to generate a project in multiple modes, and then each mode in a "normal" and "debug" mode, ie:
I have the following files (ofc more in reality, but this will serve to show my point):
kernel/core/main.cpp
kernel/processor/Processor.cpp
kernel/processor/x86/Processor.cpp
kernel/processor/x86_common/Processor.cpp
kernel/processor/x64/Processor.cpp
And i want to be able to use my makefile in the following ways:
make x86
(compiles all files except "kernel/processor/x64/Processor.cpp")
(enables the pre-processor directives X86 & X86_COMMON)
And,
make x86debug
(compiles all files except "kernel/processor/x64/Processor.cpp")
(enables the pre-processor directives X86 & X86_COMMON & DEBUG)
(puts "-g -ggdb" infront of all gcc/g++/as arguments)
And so on.
Currently i have the following makefile, which while it works, only lets me compile in x86-debug mode and now that i am porting my software to other platforms I wish to be able to specify what mode to build in.
CC = i586-elf-g++
CFLAGS = -g -ggdb -ffreestanding -Wall -Wextra -fno-exceptions -fno-rtti -std=gnu++11 -Isrc/system/include -DX86 -DX86_COMMON
LD = i586-elf-gcc
LDFLAGS = -g -ggdb -ffreestanding -O2 -nostdlib -lgcc
AS = i586-elf-as
ASFLAGS = -g -ggdb
OBJECTS = src/system/kernel/core/main.o
ALL_OBJECTS = $(OBJECTS) $(X86_OBJECTS)
X86COMMON_OBJECTS = src/system/kernel/core/processor/x86_common/Processor.o
X86_OBJECTS = $(X86COMMON_OBJECTS) src/system/kernel/core/processor/x86/boot.o
X86_LINKER = src/system/kernel/core/processor/x86/link.ld
X86_OUTPUT = bin/kernel_x86.bin
.PHONY: clean
clean: $(ALL_OBJECTS)
rm $(ALL_OBJECTS)
.PHONY: all
all: $(X86_OUTPUT)
$(X86_OUTPUT): $(X86_LINKER) $(OBJECTS) $(X86_OBJECTS)
$(LD) $(LDFLAGS) -T $(X86_LINKER) $^ -o $#
%.o: %.cpp
$(CC) $(CFLAGS) -c $< -o $#
%.o: %.asm
$(AS) $(ASFLAGS) $< -o $#
As you can probably tell, im not an expert with make so any help/ideas would be appreciated.
Remove -g from CFLAGS and LDFLAGS, and add the following PHONY:
.PHONY: x86_debug
x86_debug: CFLAGS += -g
x86_debug: LDFLAGS += -g
x86_debug: $(X86_OUTPUT)
To compile in normal mode: make.
To compile in debug mode: make x86_debug
It may not do exactly what you're expecting, but it's easy to modify
can compiler options be applied selectively on my files?
I want some files to be covered by some option but not the other files.
Guessing that you might be using Make files:
This should get you started: Note how -fopenmp gets added just for source2.c
CC=gcc
SRC=source1.c source2.c
OBJ=$(patsubst %.c,%.o,$(SRC))
EXE=source1.exe
FLAGS= -g -O2
source2.o: FLAGS+=-fopenmp
all: $(EXE)
$(EXE): $(OBJ)
$(CC) -o $# $^ $(FLAGS)
%.o: %.c
$(CC) -c -o $# $^ $(FLAGS)
clean:
rm $(EXE)$
Output of make -Bsn:
gcc -o source1.o source1.c -g -O2
gcc -o source2.o source2.c -g -O2 -fopenmp
gcc -o source1 source1.o source2.o -g -O2
Of course. You invoke the compiler, and you can tell it what you want.
Some tools may add some restrictions; Visual Studio, as far as I know, only allows specifying options at the project level. But that's an artificial restriction of the tool (and I'm sure there are ways around it—I just don't know them).
I have the following file from the PARSEC opensource benchmarks, and I want to be able to profile it using gcc. yet as u know i need to raise the -pg flags. yet i am having difficulties doing so. i tried to use a regular g++ -pg -o files.cpp yet it didnt work. i also tried to modify the makefile that infront of the -o i placed a -pg yet it also gave huge errors. So now i am stuck, either I did something wrong or the -pg flags require something special...yet the makefile when executed alone gave me an output which i tested by running and it was successfull! so i am sure the source code is accepted by my compiler
# Makefile for parallel simulated annealer
PREFIX=${PARSECDIR}/pkgs/kernels/canneal/inst/${PARSECPLAT}
TARGET=canneal
LIBS:=$(LIBS) -lm
ifdef version
ifeq "$(version)" "pthreads"
CXXFLAGS+=-DENABLE_THREADS -pthread
endif
endif
all:
$(CXX) $(CXXFLAGS) annealer_thread.cpp -c -o annealer_thread.o
$(CXX) $(CXXFLAGS) rng.cpp -c -o rng.o
$(CXX) $(CXXFLAGS) netlist.cpp -c -o netlist.o
$(CXX) $(CXXFLAGS) main.cpp -c -o main.o
$(CXX) $(CXXFLAGS) netlist_elem.cpp -c -o netlist_elem.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) *.o $(LIBS) -o $(TARGET)
clean:
rm -f *.o $(TARGET)
install:
mkdir -p $(PREFIX)/bin
cp -f $(TARGET) $(PREFIX)/bin/$(TARGET)
Try adding this near the top of the file:
CXXFLAGS+= -pg