I am new to C++ and I am having trouble understanding how Makefiles do their thing with the g++ compiler.
I have successfully installed armadillo library (via apt) and have a very simple c++ program test.cpp, like the one below:
#include <iostream>
#include <armadillo>
using namespace std;
int main()
{
arma::mat A;
A << -1 << 2 << arma::endr
<< 3 << 5;
cout << A << endl;
arma::fmat B;
B.randu(4,5);
cout << B;
return 0;
}
This works just fine if I compile manually like this:
g++ src/test.cpp -std=c++11 -Wall -o test -DARMA_DONT_USE_WRAPPER -lopenblas -llapack
I can manually run the program and it delivers the matrices as expected.
On the other hand, I have the Makefile template from the VSCode C/C++ Extension, which I have modifed slightly for including the LAPACK an BLAS Fortran libraries:
########################################################################
####################### Makefile Template ##############################
########################################################################
# Compiler settings - Can be customized.
CC = g++
CXXFLAGS = -std=c++11 -Wall
LDFLAGS = -DARMA_DONT_USE_WRAPPER -lopenblas -llapack
# Makefile settings - Can be customized.
APPNAME = test
EXT = .cpp
SRCDIR = src
OBJDIR = obj
############## Do not change anything from here downwards! #############
SRC = $(wildcard $(SRCDIR)/*$(EXT))
OBJ = $(SRC:$(SRCDIR)/%$(EXT)=$(OBJDIR)/%.o)
DEP = $(OBJ:$(OBJDIR)/%.o=%.d)
# UNIX-based OS variables & settings
RM = rm
DELOBJ = $(OBJ)
# Windows OS variables & settings
DEL = del
EXE = .exe
WDELOBJ = $(SRC:$(SRCDIR)/%$(EXT)=$(OBJDIR)\\%.o)
########################################################################
####################### Targets beginning here #########################
########################################################################
all: $(APPNAME)
# Builds the app
$(APPNAME): $(OBJ)
$(CC) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
# Creates the dependecy rules
%.d: $(SRCDIR)/%$(EXT)
#$(CPP) $(CFLAGS) $< -MM -MT $(#:%.d=$(OBJDIR)/%.o) >$#
# Includes all .h files
-include $(DEP)
# Building rule for .o files and its .c/.cpp in combination with all .h
$(OBJDIR)/%.o: $(SRCDIR)/%$(EXT)
$(CC) $(CXXFLAGS) -o $# -c $<
################### Cleaning rules for Unix-based OS ###################
# Cleans complete project
.PHONY: clean
clean:
$(RM) $(DELOBJ) $(DEP) $(APPNAME)
# Cleans only all files with the extension .d
.PHONY: cleandep
cleandep:
$(RM) $(DEP)
#################### Cleaning rules for Windows OS #####################
# Cleans complete project
.PHONY: cleanw
cleanw:
$(DEL) $(WDELOBJ) $(DEP) $(APPNAME)$(EXE)
# Cleans only all files with the extension .d
.PHONY: cleandepw
cleandepw:
$(DEL) $(DEP)
I have passed the needed libraries under LDFLAGS = -DARMA_DONT_USE_WRAPPER -lopenblas -llapack. Nevertheless, this solution does not work. It looks to me like the compiler is unable to find the armadillo library, so I must have linked it somehow wrongly. It delivers:
g++ -std=c++11 -Wall -o test obj/test.o -DARMA_DONT_USE_WRAPPER -lopenblas -llapack
/usr/bin/ld: obj/test.o: in function `TLS wrapper function for arma::arma_rng_cxx11_instance':
test.cpp:(.text._ZTWN4arma23arma_rng_cxx11_instanceE[_ZTWN4arma23arma_rng_cxx11_instanceE]+0x25): undefined reference to `arma::arma_rng_cxx11_instance'
collect2: error: ld returned 1 exit status
make: *** [Makefile:36: test] Error 1
So, aside from the obvious question (Why does this not work?), I would as well appreciate if someone could help me clarify as well the following aspects:
On the one hand, rom the message error it seems that the command run g++ -std=c++11 -Wall -o test obj/test.o -DARMA_DONT_USE_WRAPPER -lopenblas -llapack does not include the name of the cpp file I wrote (as opposed to in my manual compilation, in which it works). Nevertheless, if I do not use armadillo, the Makefile recipe above works just fine. I see the Makefile somehow looking for all cpp files in the source code folder SRC = $(wildcard $(SRCDIR)/*$(EXT)), but I cannot see where is this forwarded to the compiler. Can someone help me with that?
The other thing is that, in my manual compilation, it seems to make no difference to pass the LAPACK and BLAS libraries as CXXFLAGS or LDFLAGS, meaning both of the following commands:
g++ src/test.cpp -std=c++11 -Wall -DARMA_DONT_USE_WRAPPER -lopenblas -llapack -o test
and
g++ src/test.cpp -std=c++11 -Wall -o test -DARMA_DONT_USE_WRAPPER -lopenblas -llapack
work just fine. As far as I have been able to read, I understood the flags before -o are meant for the compiler, and those after are meant for the "linker" (whatever that is). Can someone explain me what are the main differences between the CXXFLAGS and LDFLAGS? Why both combinations work? And what is the linker?
Thank you very much for your help.
Best,
D.
The other answer is a good general introduction to compilation but if you want to know what is happening in your situation you need to first understand that answer and the difference between source files, object files, and executable files and the way that they work, then go deeper to figure out what's wrong.
As far as I have been able to read, I understood the flags before -o are meant for the compiler, and those after are meant for the "linker" (whatever that is)
No, that is not right.
Turning source files into an executable involves several steps each managed by a different tool. The compiler front-end (e.g., g++) manages the order of these. Each of these may use different options, and whenever the compiler front-end invokes one of these tools it will pass the appropriate flags from the command line for that tool. It's not the case that "only" flags before or after -o are passed to different tools; it doesn't matter where on the command line they live.
The tools involved with compilation, in the order in which they're invoked, are:
Preprocessor: this handles #include and #ifdef and #define, etc. (the lines that start with # in your source). The preprocessor takes the options -D, -I, and some others.
Compiler: this turns your source code (after preprocessing to handle all the included files etc.) into assembly code which is very low-level: basically machine code but in ASCII form. This does the bulk of the work including optimization etc. Flags like -O2, -g, and many others are used by this tool.
Assembler: this turns the assembly code into a binary format for your CPU and generates an object file (foo.o).
Linker: this takes one or more object files plus libraries and turns them into an executable. This tool uses options like -L and -l to find libraries.
There's a separate tool, the archiver (ar) which is not invoked by the compiler front-end, which is used to turn object files (foo.o) into static libraries (libfoo.a).
Note, the above is a "classical" view of building: newer compilers munge the above steps together sometimes to get either better error messages or better optimization or both.
Most of the time the first three steps are all done by a single invocation of the compiler front-end: it turns a source file into an object file. You do this once for each source file. Then at the end, another invocation of the compiler front-end takes those object files and builds an executable.
If you look at the output make prints you'll see these two steps. First you'll see the compilation step, which is controlled by this make rule:
$(OBJDIR)/%.o: $(SRCDIR)/%$(EXT)
$(CC) $(CXXFLAGS) -o $# -c $<
and runs this command:
g++ -std=c++11 -Wall -o obj/test.o -c src/test.cpp
The -c option here tells the compiler, "do all the steps up to and including the compile step, then stop and don't do the link step".
Then you will see your link command, which is controlled by this make rule:
$(APPNAME): $(OBJ)
$(CC) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
and runs this command:
g++ -std=c++11 -Wall -o test obj/test.o -DARMA_DONT_USE_WRAPPER -lopenblas -llapack
What do you notice about this? The -DARMA_DONT_USE_WRAPPER is a preprocessor option, but you're passing it to the link step and not passing it to the compile step. That means when the source is compiled, that option is not present and so whatever operation it was intended to suppress (using a wrapper apparently) is not being suppressed.
You need to put preprocessor options in a make variable that is sent to the compiler / preprocessor, so it should be this:
CXXFLAGS = -std=c++11 -Wall -DARMA_DONT_USE_WRAPPER
LDFLAGS = -lopenblas -llapack
Be sure to run clean before trying to build again.
One minor thing, but generally you should use CXX for your C++ compiler and CC for your C compiler (these are the usual conventions). If you do end up trying to compile C++ source with a C compiler you are likely to have problems. Less so the other way round.
So what it happening? Roughly speaking, you have two steps:
Compilation
Linking
When you compile a small exe, you can combine these into a single steps. Makefiles generally don't as two steps is more general.
For compilation the input has a .cpp suffix and you are passing the -c flag to tell the compiler to just compile. This will result in an object file (.o suffix).
For linking, there is no -c. The inputs are object files and the output is your application.
Other suffixes are possible (.cxx, .CC etc.).
There are 4 commonly used make variables
CPPFLAGS for preprocessor flags, can be used for C and C++ compilation
CFLAGS for flags specific to C compilation
CXXFLAGS for flags specific to C++ compilation
LDFLAGS for flags specific to linking
Historically, ld was the linker (and hence LDFLAGS), but it isn't smart enough to handle C++ linking well on its own. So now it is usually the C++ compiler that performs the task of "linker driver", that is g++ controls the linking that ld does.
Finally, your specific problem. You should add the armadillo library to LDFLAGS. The best way to do that is to just add -larmadillo. If armadillo is not installed in a 'standard' location like /usr/lib then you may need to additional arguments such as
-L/path//to/armadillo_lib -Wl,-rpath,/path//to/armadillo_lib
(the first one tells the linker where the library is, the second one puts that path into the executable so that is also knows where the library is).
I have a C++ project which uses multiple external static libraries and a huge code base.
If I put it all together like this:
g++ (ALL INCLUDE PATHS) (FLAGS) (ALL LIBRARIES) (ALL SOURCES) -o FILE
All at once in the same command, it works.
However I want to use a Makefile to generate file objects and speed up the compiling process.
I am able to generate a object file for each individual source file, but when trying to put them all together like this:
g++ -o FILE (ALL OBJECT FILES FOUND RECURSIVELY IN THE PATH)
I get the following errors, as if they had not been compiled with the static libraries
Linux_Release/.compilation_libs/linux.o: In function `WndProc(int, int, int)':
main_Linux.cpp:(.text+0xc6): undefined reference to `XRefreshKeyboardMapping'
main_Linux.cpp:(.text+0x18c): undefined reference to `XLookupKeysym'
main_Linux.cpp:(.text+0x20b): undefined reference to `Xutf8LookupString'
...
I've tried to put the includes/flags/libraries back into the command once again, but it doesn't make a difference.
Here are the flags I'm using for compiling each source file individually:
CFLAGS := -fmessage-length=0 -std=c++11 -Wno-sign-compare
-Wno-unused-local-typedefs -Wno-reorder -Wno-switch -fpermissive -static-libstdc++ -static-libgc
c -Wl,-rpath=.
And here are some of the libs included in the command above
LIBS := -lcurl -lz -lX11 -lXi -lGL -lGLU -lGLEW -lfreetype -lbass -lbass_fx -lOpenCL (and more...)
And the target for building each file object looks like this:
$(COMPILATION_LIBS_FOLDER)/%.o: %.cpp
mkdir -p '$(#D)'
g++ $(CFLAGS) $(FIXED_INCLUDES) $(LIBPATH) $(LIBS) -c $< -o $#
I'm just getting started using GLEW on Windows with MinGW. I can compile the program successfully (glew.h and libglew.a are in the proper place within MinGW), however executing my program throws the above error. glew32.dll is present in the same directory as the executable, and I've found and attempted various solutions to my problem. However, my problem seems to be different to others - the error message is complaining that glewInit cannot be found in the executable itself as opposed to glew32.dll. I haven't managed to find anything about this on Google.
Here's the error:
As you can see, it's not complaining about not being able to find the glew method in a DLL, but in the program file itself. I feel I am linking the executable incorrectly, but I have very little experience with fixing this kind of error.
Here's my Makefile:
EXEC = test1.exe
SRC_FILES = test1.cpp wavefront.cpp
CXX = g++
CC = $(CXX)
DEBUG_LEVEL = -g
EXTRA_CCFLAGS = -Wall
CXXFLAGS = $(DEBUG_LEVEL) $(EXTRA_CCFLAGS)
CCFLAGS = $(CXXFLAGS)
CPPFLAGS = -I.
LDFLAGS = -L"/cygdrive/c/MinGW/lib"
LDLIBS = -lsfml-graphics -lsfml-window -lsfml-system -lopengl32 -lglu32 -lglew32
O_FILES = $(SRC_FILES:.cpp=.o)
all: .FORCE
.FORCE: compile link
compile:
$(CXX) -c $(SRC_FILES)
link:
$(CXX) $(O_FILES) -o $(EXEC) $(LDFLAGS) $(LDLIBS)
clean:
$(RM) $(O_FILES) *.exe *.rpo
The error in your title and in your diagram are completely different. The first error, in your title is the decorated DLL export name and the second one is for a __stdcall function. For whatever reason, the import stub seems to be trying to resolve the function address from your application rather than the DLL.
Perhaps you did not properly define dllexport behavior when you built your DLL or dllimport when linking against it? GLEW uses the pre-processor definition: GLEW_BUILD for this purpose.
In any event, using the static linking glew library will definitely solve this issue, though I cannot say why it is happening for sure.
Link against glew32s and add -DGLEW_STATIC to your Makefile.
I have a project of multiple source and header files and I wrote my own Makefile by specifying the required external libraries and headers (the directory containing the OpenCV header files and the directory containing the OpenCV libraries).
When I start compiling the project, it is compiled without any errors. However when writing the code, Eclipse reports errors on some functions of OpenCV, as if it did not know these functions. Since I have listed all the required headers and libraries in the makefile (see below), why does this problem occur?
CXXFLAGS = -O3 -g -Wall -fmessage-length=0 -I./include -I/usr/local/include/opencv
LIBS = -L/usr/local/lib -lcv -lcvaux -lhighgui -lcxcore -limgproc
MAIN_PROG_OBJS = MainProgram.o src/Utilities.o src/ImageStream.o src/VideoStream.o
MAIN_PROG_TARGET = MainProgram
TEST_PROG_OBJS = TestProgram.o src/Utilities.o
TEST_PROG_TARGET = TestProgram
$(MAIN_PROG_TARGET): $(MAIN_PROG_OBJS)
$(CXX) -o $(MAIN_PROG_TARGET) $(MAIN_PROG_OBJS) $(LIBS)
$(TEST_PROG_TARGET): $(TEST_PROG_OBJS)
$(CXX) -o $(TEST_PROG_TARGET) $(TEST_PROG_OBJS) $(LIBS)
all: $(MAIN_PROG_TARGET) $(TEST_PROG_TARGET)
clean:
rm -f $(MAIN_PROG_OBJS) $(MAIN_PROG_TARGET) $(TEST_PROG_OBJS) $(TEST_PROG_TARGET)
Eclipse tries to find the errors quickly, but does not update all the time. Do not rely only on the error messages of Eclipse.
For example if you have just added a file to your project, Eclipse might still be telling you that it could not find the file while in fact it is there.
Use Project -> Clean to update the error checking of Eclipse.
I was writing an OpenGL program and it happens that I have a problem with linking with math3d.h.
I am using Ubuntu and g++.
The thing is that I didn't install the package for the math3d because I got the header file and a cpp file from the net with OpenGL superbible. So I just copied the header file and .cpp file to the local directory and did
#include "math3d.h"
But the thing is that I used to use switches to link the other header files like gl.h, glu.h ,glut.h by giving.
g++ test.cpp -lGL -lGLU -lglut.
But I don't know what to give for math3d. I get an error saying undefined reference to the functions. This error I used to get when I don't give -lGL etc. for the functions in those respective libraries.
I am totally stuck here and I don't know what to do and without this I cannot go forward.
You don't link header files. You include them, and then link the object files produced by the *.cpp files together.
Short answer
g++ test.cpp math3d.cpp -lGL -lGLU -lglut
... and it works.
Long Answer
What you are lacking is any kind of build system (read up on Makefile). You need to first build the math3d.cpp, then your test program.
Sample Makefile:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=-lGL -lGLU -lglut
SOURCES=test.cpp math3d.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=test
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Well, y'know, this one might even work :>
Need to compile math3d.cpp as well:
g++ test.cpp math3d.cpp -lGL -lGLU -lglut
There are a couple of problems with your question:
You don't link to header files - you include header files, you link object files or libraries
Besides including the appropriate header files you need to link in the library - you said you copied the .cpp file from the 'local directory' does this mean you added one of the .cpp files from the OpenGL project into your project? This can work if you make sure you get all the .cpp files you need (the functions you use that are declared in 'math3d.h' may be implemented across a number of .cpp files). However, it is MUCH better to build openGL as a library and link against that. You may want to consult the OpenGL documentation to see how to build it.