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:
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 commandg++ -Q -v -o hello hello.cpp
and take a look at the last line whereg++
invokescollect2
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?
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.