Why my makefile fails, when I replace g++ with gcc? - c++

I am coding in OS X
Here is my Makefile:
#makefile for stack_5_1
# Yitong Zhou
stack_5 : main.o Stack.o LIFO_Stack.o Peekback_Stack.o
g++ -o stack_5 main.o Stack.o LIFO_Stack.o Peekback_Stack.o
main.o: main.cpp Stack.h LIFO_Stack.h Peekback_Stack.h
g++ -c main.cpp
Stack.o: Stack.cpp Stack.h
g++ -c Stack.cpp
LIFO_Stack.o: LIFO_Stack.cpp LIFO_Stack.h
g++ -c LIFO_Stack.cpp
Peekback_Stack.o: Peekback_Stack.cpp Peekback_Stack.h
g++ -c Peekback_Stack.cpp
clean:
rm -rf *.o stack_5
The error:
..... // very very long
Dwarf Exception Unwind Info (__eh_frame) in Stack.o
Dwarf Exception Unwind Info (__eh_frame) in LIFO_Stack.o
Dwarf Exception Unwind Info (__eh_frame) in Peekback_Stack.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
make: *** [stack_5] Error 1
What is the difference between gcc and g++? Why does my compile fail when I replace g++ with gcc?
By the way, how could I ensure that my makefile could be run correctly in Cygwin, linux, OS X and maybe other environment.

gcc is for compiling C by default
g++ is for compiling C++ by default
The primary difference is that g++ transparently adds the options -x c++ (use C++) and -lstdc++ (use C++ standard library).
Try this Makefile:
stack_5: main.o Stack.o LIFO_Stack.o Peekback_Stack.o
main.o: main.cpp Stack.h LIFO_Stack.h Peekback_Stack.h
Stack.o: Stack.cpp Stack.h
LIFO_Stack.o: LIFO_Stack.cpp LIFO_Stack.h
Peekback_Stack.o: Peekback_Stack.cpp Peekback_Stack.h
make will automatically fill in the sensible rules based on the file extensions.
Also take a look at the -MM gcc option. It will automatically generate the correct make dependencies (which header files) so you don't need to maintain this list manually. There is more in the make manual and gcc manual about how to use it.

gcc as a linker, IIRC, doesn't link in standard c++ libraries, like -lstdc++. Not sure if it's enough to make sure everything works on all systems, you may need to use autotools or similar.

gcc is meant to compile plain C while g++ accepts (compatible) C and C++ code.
That's probably the reason for your errors.

Related

2 Different LD errors when trying to link static library

I wrote a custom C++ library, which compiled correctly, and am trying to write a test program for some different accuracy checks.
When I compile it this way:
$ c++ -I./include/ -L./lib -lname test.cpp -c -o test.o
....[succeeds ]
$ c++ -I./include/ -L./lib -lname test.o -o test
I get:
ld: 1 duplicate symbol for... for the function I'm testing
But when I compile the test.o the same way & change the executable method:
c++ -I./include -L./lib test.o -o test
it returns: `ld: symbols() not found for ..." for the function I'm testing.
I am 100% sure about the way I compiled & built the library, so I don't understand exactly what I am doing wrong even after I've tried several different ways of compiling test.
Edits:
Fixed typo in test filename.
Removed -L & -l flags from step 1, and it compiled.
Removed -I from step 2, and it gave the error ld: library for -lname not found when compiled as:
c++ -L./lib -lname test.obj -o test

failing to link: ABI conflict between functions IN THE SAME FILE

I do not understand how this can happen. In g++ I am getting an error that there is an ABI conflict between two routines defined in the same file, at the same time, under the same ABI directives. For reasons unknown the linker is searching for the C++11 version of a function, in spite of me being very careful to tell it not to use the C++11 version of absolutely anything, in every last call to g++ in my makefile.
Here is the relevant chunk of makefile - using _D_GLIBCXX_USE_CXX11ABI=0 before anything is included. All the other .o files are built the same way.
project: chrome.o critter.o gene.o loc.o mask.o main.o octree.o rng.o save.o test.o utils.o
g++ -std=c++17 -D_GLIBCXX_USE_CXX11ABI=0 -D_DEFAULT_SOURCE -lstdc++ -lm -Wall -o project chrome.o critter.o gene.o loc.o mask.o main.o octree.o rng.o save.o test.o utils.o
main.o: main.cpp main.h save.h utils.h gene.h chrome.h critter.h
g++ -std=c++17 -D_GLIBCXX_USE_CXX11ABI=0 -D_DEFAULT_SOURCE -lstdc++ -c -Wall -o main.o main.cpp
Here is the relevant chunk of source code.
// the makesave method returns a string which is to be written to a savefile.
std::string rundata::makesave() const { // save all data
std::string parmsave = rparms.save2string();
std::string genesave = genes.makesave();
std::string chromesave = chromes.makesave();
std::string crittersave = critters.makesave();
return("<rundata> "+ parmsave + genesave + chromesave + crittersave + " </rundata>\n");
}
// the saveData method opens and writes the savefile.
void rundata::saveData(){
FILE *sav = fopen(rparms.savename(), "w");
if (sav == NULL) {fprintf(stderr, "Error opening save file to write.\n"); exit(1);}
std::string outstr = makesave();
fwrite(outstr.data(), 1, outstr.size(), sav);
fclose(sav);
}
And here's what happens when I run make:
albert#juno:~/src/nevermind$ make
g++ -std=c++17 -D_GLIBCXX_USE_CXX11ABI=0 -D_DEFAULT_SOURCE -lstdc++ -c -Wall -o main.o main.cpp 2>&1 | head -20
g++ -std=c++17 -D_GLIBCXX_USE_CXX11ABI=0 -D_DEFAULT_SOURCE -lstdc++ -lm -Wall -o nevermind chrome.o critter.o gene.o loc.o mask.o main.o octree.o rng.o save.o test.o utils.o 2>&1 | head -20
/usr/bin/ld: main.o: in function `rundata::saveData()':
main.cpp:(.text+0x2ac): undefined reference to `rundata::makesave[abi:cxx11]()'
collect2: error: ld returned 1 exit status
This isn't a call for a wrong-version library function caused by failure to use the macro before including libraries: This is a call to a function defined in the same file, compiled at the same time, with the same ABI directive in place. And I have an ABI conflict?!
How is this even possible?
When compiling c++ code with g++, you need to do three things to completely specify the language.
-std=c++17 tells you what the source code is allowed to look like, or means.
-D_GLIBCXX_USE_CXX11ABI=0 tells it not to call the library functions whose ABIs are compatible with the ABI that was current for this compiler as of C++11.
-fabi-version=14 tells it to use the most recent ABI for the machine code it's generating.
It is this last thing that I was missing. I was leaving it free to decide what binary ABI to use for its output, even though it was compiling with -std=c++17 for its input. And for some reason I still do not understand, it made a categorically wrong choice. But if I command it to use the most recent ABI, it is no longer free to make this choice.
I may never know why the compiler did what it did, but at least I know how to make sure it doesn't any more.

Igraph makevars will not link to static library, i can use data structures but cannot functions while importing igraph c++ library

I am trying to install my C++ igraph library from https://github.com/igraph/igraph to visual studio code using the following method this is my makefile made according to this link.
CXX = g++
CXX_FLAGS = -std=c++17 -O3 -march=native -DNDEBUG
LIB = -Llib
INC = -Iinclude
.PHONY: all
all: a.out
a.out: main.cpp
$(CXX) $(CXX_FLAGS) $(INC) $(LIB) -ligraph -lm -lstdc++ -lgomp -lpthread -o $# main.cpp
.PHONY: clean
clean:
rm a.out
The compiler will always return something like:
g++ -std=c++17 -O3 -march=native -DNDEBUG -Iinclude -Llib -ligraph -lm -lstdc++ -lgomp -lpthread -o a.out main.cpp
/usr/bin/ld: /tmp/ccqJLfvi.o: in function `main':
main.cpp:(.text.startup+0x9): undefined reference to `igraph_rng_default'
/usr/bin/ld: main.cpp:(.text.startup+0x16): undefined reference to `igraph_rng_seed'
collect2: error: ld returned 1 exit status
make: *** [Makefile:12: a.out] Error 1
If i only want to use data structures such as igraph_t graph* it will work, but if i try to call fucntion it will return error and will not generate a.out file. It would be incredablly good if someone would be able to explain why this happens cuz it really got on my nerve right now.
Please follow the instructions in the documentation to set up your package to link to igraph.
Instructions to install igraph: https://igraph.org/c/html/latest/igraph-Installation.html Note that you must both build and install the package. Make a note of the location you used to install it to (the value of CMAKE_INSTALL_PREFIX)
Instructions on compiling your first igraph program: https://igraph.org/c/html/latest/igraph-Tutorial.html Unless you are already comfortable with writing C programs and linking them to external libraries, I strongly recommend that you use CMake to set up your project, as described in the linked tutorial. CMake works the same way on all platforms (Windows/macOS/Linux) and will automatically figure out how to link your program to igraph correctly. When configuring your project, be sure to set CMAKE_PREFIX_PATH to the location where you installed igraph earlier.

C++ file compiling: -L and -I arguments don't work for boost library

There are similar questions but their answers did not work for my issue.
I have a c++ program with #include <boost/test/unit_test.hpp> on top (among other includes).
To compile correctly, if I understood, I should do the command:
g++ -g -L/path_to_boost_lib -lboost_lib myprog.cpp -o myprog.exe
If i do a locate, I get /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.
Hence I edited my call to g++ by doing:
g++ -g -L/usr/lib/x86_64-linux-gnu -lboost_unit_test_framework myprog.cpp -o myprog.exe
But I still get errors of the type undefined reference to boost::unit_test.
I also tried the option -I/usr/include/ which contains the boost folder, without success.
It's because of the order. The GCC linker goes through the artifacts left-to-right, and every unknown symbol it encounters in an object file must be resolved by an artifact occurring afterwards.
The right command is thus:
g++ -g myprog.cpp -L/usr/lib/x86_64-linux-gnu -lboost_unit_test_framework -o myprog.exe
See this answer for a more thorough explanation.
I suggest using a build tool like CMake that takes care of such low-level details for you.

gsl undefined symbol: gsl_multifit_nlinear_trs_lmaccel

I'm having some troubles with the GNU Scientific Lbrary (GSL).
After having intalled it, I tested it with the example here and it works when compiling with:
gcc -Wall -c main.cpp ; gcc -L/usr/local/lib main.o -lgsl -lgslcblas -lm -libtemt
Next, I tried to compile that with no change in the source code nor the compiling command. But here is the problem, when I try to run the result, I get :
./a.out: symbol lookup error: ./a.out: undefined symbol: gsl_multifit nlinear_trs_lmaccel
I tried to comment it out, but it's making other issues. I found that variable in the fulle doc, but I can't find where it's defined.
As the first example is working, I think GSL was installed successfully, and as the same variableis used in different codes, I think it's a global variable, defined in th library.
Does anyone have an idea why I can't access it?
Thank's a lot!
Well, after a lot of tears (no, it's a joke) I found a sort of answer:
I copy and paste libgsl.a and libgslcblas.a in my directory, i wrote that makefile:
CC=gcc
CXXFLAGS=-W -Wall -ansi -pedantic
LIBS=libgsl.a libgslcblas.a -lm
main:main.o
$(CC) -o main main.o $(LDFLAGS) $(LIBS)
main.o: main.cpp
$(CC) -o main.o -c main.cpp $(CXXFLAGS)
I'm happy with that answer even if there is 2 weaknesses:
1) I don't know how to use shared library (at this moment)
2) I don't know how to make it by command line
Hope it will help someone