I have created a small library (around 600 lines) in C++ in Codeblocks and I'm using OMP and O3 optimization to build it. When I try to build the same code through the terminal with a Makefile with exactly the same options (-fopenmp -O3) it runs around 3 times slower. I need to build it in various machines so I need to do the process through a terminal and not through Codeblocks. Why is this happening?
This is my Makefile if you're interested:
CC=g++
CFLAGS=
LDFLAGS= -fopenmp -O3 -std=c++11
SOURCES=main.cpp CNNFunctions.cpp
OBJECTS=$(SOURCES:.cpp=.o) EXECUTABLE=cnn
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Your Makefile is wrong. The optimization flags are relevant mostly at compile time. Try at least:
CXX=g++
CXXFLAGS= -Wall -fopenmp -O3 -std=c++11 -mtune=native
LDFLAGS= -fopenmp
SOURCES=main.cpp CNNFunctions.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=cnn
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(LINK.cpp) $(OBJECTS) -o $#
Optimization might matter at link time for Link-Time Optimization, for that use CXX=g++ -flto and LDFLAGS=$(CXXFLAGS)
Because, contrary to your claim, you're not building it with the exact same options.
Your CFLAGS are empty, and those are the flags you're using for the compilation. You cannot resolve that by the time you get to the linking step.
Related
I have installed SDL through homebrew, and it works perfectly with my test program if I enter the following command directly in the terminal:
g++ -O3 -g -Wall -Wextra -std=c++1y hello.cpp hello_main.cpp `sdl2-config --cflags --libs` -o hello
but unfortunately my attempts to write a makefile (I will definitely need one) have yielded unsuccessful/unexplained results.
I am following this, but my configuration is different/I am not specifying Cocoa (I don't need to) so I expect that the issues I am encountering are probably due in part to my different requirements:
Compiling SDL on OS X with makefile
Example:
CC=g++
CFLAGS=-c -Wall
SDLFLAGS=`sdl-config --cflags --libs` -framework Cocoa
SOURCES=main.cpp Game.cpp IO.cpp Board.cpp Pieces.cpp Piece.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=tetris
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) $(SDLFLAGS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf *.o $(EXECUTABLE)
My makefile so far:
CXX = g++
CXXFLAGS = -c -O3 -g -Wall -Wextra -std=c++1y
SDLFLAGS = `sdl2-config --cflags --libs`
SOURCES = hello_main.cpp hello.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXECNAME = hello
all: $(SOURCES) $(EXECNAME)
$(EXECUTABLE): $(OBJECTS)
$(CXX) $ (OBJECTS) $(SDLFLAGS) -o $#
.cpp.o:
$(CXX) $(CXXFLAGS) $< -o $#
clean :
-rm -f *.o *.core $(EXECNAME)
In my .hpp header file if I #include <SDL.h> and run the one-liner command, everything is successful. If I try my makefile above, cannot be found, but if I then change the directive into #include <SDL2/SDL.h> the library is discovered. Yet the console output is the following:
g++ -c -O3 -g -Wall -Wextra -std=c++1y hello.cpp -o hello
which is odd.
Running ./hello yields a "permission denied" error, which confirms that the linking and compilation were not successful.
Everyone's system is a little bit different and the questions I've found so far don't help in this case.
I am very close to having this working (but then again, how would I start using this in an IDE? I suppose that as long as I can import the fixed makefile or build from the terminal/edit only from the IDE, I am fine.)
What changes in the makefile do I need to make?
Thank you.
EDIT:
Variation 1:
CXX = g++
CXXFLAGS = -O3 -g -Wall -Wextra -std=c++1y -c
SDLCFLAGS = `sdl2-config --cflags`
SDLLIBFLAGS = `sdl2-config --libs`
SOURCES = hello_main.cpp hello.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXECNAME = hello
all: $(SOURCES) $(EXECNAME)
$(EXECUTABLE): $(OBJECTS)
$(CXX) $ (OBJECTS) $(SDLLIBFLAGS) -o $#
.cpp.o:
$(CXX) $(CXXFLAGS) $(SDLCFLAGS) $< -o $#
clean :
-rm -f *.o *.core $(EXECNAME)
I chatted with a friend and figured what was wrong: a bunch of typos and rule oddities. The following works, for anyone out there who needs a basic makefile:
CXX = g++
CXXFLAGS = -O3 -g -Wall -Wextra -std=c++1y
#LDFLAGS = -lSDL2_image
SDLCFLAGS = $(shell sdl2-config --cflags)
SDLLIBFLAGS = $(shell sdl2-config --libs)
SOURCES = hello_main.cpp hello.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXECNAME = hello
all: $(EXECNAME)
$(EXECNAME): $(OBJECTS)
$(CXX) $(OBJECTS) $(SDLLIBFLAGS) $(LDFLAGS) -o $#
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $(SDLCFLAGS) $< -o $#
clean :
-rm -f *.o *.core $(EXECNAME)
You should split your sdl2-config into two - as there are two steps. sdl2-config --cflags should go in the compiler step - thats is the .cpp:.o line in your example. The linking step should be sdl2-config --libs then. The second one seems fine for your case, the additional --cflags there does no harm but is not required.
In my Makefile I am using the -DDEBUG Flag for debugging which works fine (compiles and right output) in the following minimal example:
# Makefile
all : debug
CXX = g++
CXXFLAGS = -std=c++11 -Werror -Wall -Wextra -Wno-unused-value
SOURCES = main.cpp vector.cpp
OBJECTS = $(subst .cpp,.o, $(SOURCES))
debug: $(OBJECTS)
$(CXX) $(CXXFLAGS) -DDEBUG -o Program $(OBJECTS)
./Program
clean:
rm *.o Program
.PHONY: clean debug
But when i copy all project-files into the Folder the Debug-Flag wont be set (tested with #ifdef DEBUG and cout). I am adding the following files:
ind.hpp ind.cpp debug.hpp debug.cpp
I first thought debug.* could be the problem, but ".PHONY: clean debug" didn't help.
In the Makefile change this:
debug: $(OBJECTS)
$(CXX) $(CXXFLAGS) -DDEBUG -o Program $(OBJECTS)
to:
debug: $(SOURCES)
$(CXX) $(CXXFLAGS) -DDEBUG -o Program $(SOURCES)
The reason being that in the rule to build debug target you are just linking the object files and not compiling with -DDEBUG. With this change you should be able to compile with -DDEBUG flag.
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 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.