I wrote the Makefile for an easier way to run the unit tests (the default target is test). The directories structure is as follows:
lib - google c++ test framework
src - source files
test - unit tests
In src I have the files a.h, a.cc, b.cc (which holds main) and I want to test class A() which is defined in a.h. All in all, because the order of linking is:
g++ -Wall -c -o obj/src/a.o src/a.cc
g++ -Wall -c -o obj/src/b.o src/b.cc
g++ -o all obj/src/a.o
I get the error:
(.text+0x18): undefined reference to main'
collect2: ld returned 1 exit status
make: *** [all] Error
even though I don't actually need a main() defined in src since I already have a main() defined in test which runs the unit tests.
I don't understand very well what you want to do, but if your main is in, say, test.o, you need to specify that in you linking line. For example:
g++ -o all obj/src/a.o test.o
When you say
g++ -o all obj/src/a.o
g++ thinks you've asked it to build a executable, and accordingly is looking for the entry point. Presumably you meant to ask it for something else (a library, maybe?).
Even though it doesn't solve your current problem, it might be helpful to know that you are re-engineering automake. You shouldn't be writing Makefiles for C or C++ projects by hand nowadays.
Related
I have the following C++ code in a file called helloworld.cpp:
#include<iostream>
int main()
{
std::cout << "Hello, World!\n";
}
I would like to compile this manually so I can really understand how the compilation steps work with gcc, namely:
Preprocessing
Compilation
Assembly
Linking
This article gives some useful information about how to break up the compilation steps. And so I came up with the following:
Preprocessing
cpp helloworld.cpp > helloworld.i
Compilation
g++ -S helloworld.i
Assembly as -o helloworld.o helloworld.s
Linking
ld -o helloworld helloworld.o
Everything seems to work except for the last step, as outlined by the article:
ld -o hello hello.o ...libraries...
The libraries argument above is a long list of libraries that you need to find out. I omitted the exact arguments because the list is really long and complicated, and depends on which libraries g++ is using on your system. If you are interested to find out, you can run the command g++ -Q -v -o hello hello.cpp and take a look at the last line where g++ invokes collect2
And so I tried running g++ -Q -v -o helloworld helloworld.cpp, but the result is extremely verbose.
I'm still unsure how to complete ld such that iostream can be available to the linker when I invoke it. How can I make sure iostream is available to the linker?
I'm still unsure how to complete ld such that iostream can be available to the linker when I invoke it.
You should never use ld to link any user-level programs, only when you are linking something esoteric, like an OS kernel or a boot loader.
Instead, (for user-level program) always use appropriate compiler driver (g++ here).
While you can find out how the compiler driver eventually invokes ld internally (e.g. using strace -fe execve -s 1024 g++ ...), note that that command may change from version to version, and depends on a multitude of flags (-pie vs. -no-pie, -shared, -static etc.) and you chances of continuing to use correct ld command after a few months are nil.
Based on the comments and posted answer I realized that the blog from which I was copying those commands makes things more complicated than they really need to be for my purposes. It's definitely possible to isolate every step of the compilation process using solely the g++ command. Here's a Makefile I came up with:
all: preprocess compile assemble link
# helloworld.i contains preprocessed source code
preprocess:
#echo "\nPREPROCESSING\n"; g++ -E -o helloworld.i helloworld.cpp
# compile preprocessed source code to assembly language.
# hello.s will contain assembly code
compile:
#echo "\nCOMPILATION\n"; g++ -S helloworld.i
# convert assembly to machine code
assemble:
#echo "\nASSEMBLY\n"; g++ -c helloworld.s
# links object code with the library code to produce an executable
# libraries need to be specified here
link:
#echo "\nLINKING\n"; g++ helloworld.o -o test
clean:
#find -type f ! -name "*.cpp" ! -name "*.h" ! -name "Makefile" -delete
Now I can compile my C++ programs in such a way that I can track whether the preprocessor, compiler, assembler or linker is generating the error.
Apologies for such a beginner question, but I have been stuck on making Makefile work on my c++ files for quite a while
My makefile contains two .cpp files and one .h files and are as follows
example.o: example.cpp example.h
g++ -c example.cpp
main.o: main.cpp example.h
g++ -c main.cpp
main: main.o example.o
g++ main.o example.o -o main
and it outputs the following error when I try to make main
Undefined symbols for architecture x86_64: *(with large pieces of code)*
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main] Error 1
However, it works perfectly fine when I just do a compilation of the program by using
g++ main.cpp example.cpp -o main
Is there any reason why Makefile doesn't work but just compiling works? Thanks a lot for any replies!
Please show the output of make including the compiler lines that were invoked, not just some of the error output. Also it would be helpful if you provided at least SOME of the symbols that were not found so we could get an idea of what is missing.
There is no reason from the info you've provided why this should happen, so the cause must be related to some detail that you haven't provided.
One difference between the command line and the makefile is that the makefile builds object files then turns them into an executable, while the command line simply compiles the sources directly into an executable.
Maybe you have some .o files lying around from a different compilation? If you use rm -f *.o before you run make do you still see the same errors?
Also, it's a little odd that you're invoking g++ but the error output says clang which is a completely different compiler. Are you trying to build on MacOS? You should always provide your operating system info. If you're building on MacOS you should just use clang directly, unless you've explicitly install GCC and want to use that.
I have a huge C/Pro*C project that I want to improve. I copied a piece of it, rewrote it in C++, and it compiles and works fine.
I now want to include it to my C project. In order to do that, I'd like to merge all my little obj files into one, then add it with the others obj files during the final linking.
However, I got errors, and I need help.
I tried ld -Ur file1.o file2.o -llib1 -llib2 -o feature.o but ld complains that it cannot find my libraries (none of them)
I tried ld -Ur file1.o file2.o -o feature.o but then ld complains that there is a huge ton of undefined references to various STL elements.
I tried g++ file1.o file2.o -llib1 -llib2 -o feature.o but it complains that it cannot find main() which is perfectly normal cause I did not want him to make an executable
I tried g++ file1.o file2.o main.o -llib1 -llib2 -o feature and it compiles perfectly good but that's not what I want...
I tried g++ -Xlinker -Ur file1.o file2.o -o feature.o so that g++ would give automagically the stl links to ld, but again, ld could not find the STL...
What should I do, please ?
EDIT:
The main makefile that I wish to change as little as possible contains a list of binaries and their associated obj files. I wish to add my obj file to one of these lists so that the final linking would be transparent.
EDIT2: I don't want to make a library. My new piece of code will replace the old one, and I'd like to use the same kind of process, module by module.
To merge object files into a static library you should use ar
I have been trying to compile a simple C++ program with the googletest libraries. I have gotten this to work using g++, however the project will soon become large and I want to be able to automate the compilation using make. I installed GNU make for windows which I have tested on another program and it works. However when I try and use make to compile my googletest project I get the following error:
ld.exe: cannot find -lgtest
Here is the contents of my makefile:
all: test.exe
test.exe: main.cpp
g++ -o test.exe .\main.cpp .\sample1.h .\sample1.cc .\sample1_unittest.cc -ID:\...\gtest\include -LD:\D...\gtest\lib\ -lgtest_main -lgtest -Wall
clean:
rm test.o test.exe
The weird thing is that if I run the same code from the command line, as follows, it works perfectly an I end up with my test.exe.
g++ -o test.exe .\main.cpp .\sample1.h .\sample1.cc .\sample1_unittest.cc -ID:\...\gtest\include -LD:\D...\gtest\lib\ -lgtest_main -lgtest -Wall
Does anyone know what this could be caused by and how to fix it?
Ok, I managed to find the problem! I'm still not sure why this is the case but apparently in make you have to specify paths like so:
-LD:\...\gtest\lib
And not like this (note the extra ):
-LD:\...\gtest\lib\
The error message makes sense since it must have been trying to search for the library in a path that looks something like this:
-LD:\...\gtest\lib\\
Which would obviously not work. I guess what threw me off was that the code worked when executed from the command line. It took me a while to see the inconstancy in my path specification and figure out that make doesn't want the extra '\'. Hopefully this will prevent someone else for wasting as much time as I did.
I came across this while trying to get an answer. But it seems like the poster had multiple files and they were not getting linked, and hence the error.
But, why do I get this error when using a single file?
g++ myClass.cpp
/usr/lib/gcc/i686-redhat-linux/4.6.3/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld returned 1 exit status
And why is main necessary here at compile time (from where does it find a mention of main in my code) ? main is the starting point of code execution, but why does the compiler assume i need a main here. I can have it defined in some other file and use gcc -o to make an executable?
Or maybe I am missing something else in the code which causes the error?
#include<iostream>
class myClass
{
public:
myClass()
{
std::cout<<"Constructor";
}
~myClass()
{
std::cout<<"Destructor";
}
};
main is not necessary to compile a source file. It is necessary to link a program into an executable [1], because the program has to start somewhere.
You need to tell the compiler that "this is not the whole of my program, just compile, but don't link", using the '-c' option, so
g++ -c myClass.cpp
which will produce a myClass.o file that you can then use later, e.g.
g++ -o myprog myClass.o myOtherClass.o something_that_has_main.o -lsomelib
(Obviously, substitute names with whatever you have in your project)
[1] Assuming you use the regular linker scrips that come with the compiler. There are "ways around that too", but I think that's beyond this answer.
You are trying to compile an executable, so a main function is expected. You should compile an object file by using the -c flag:
g++ -c myClass.cpp
While you are at it, I suggest adding warning flags -Wall -Wextra at the very least.
You are building your source as an application. Add -c option to produce only object file:
g++ -c myClass.cpp
Compile only?! use -c option
g++ -c file.cpp
otherwise the project needs a main.
You need to use the -c flag to compile and only tell the compiler to generate an object file. You're telling the compiler to make an executable.