Search code examples
c++gcccompilationlinkeriostream

How can I make sure `iostream` is available to the linker?


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:

  1. Preprocessing
  2. Compilation
  3. Assembly
  4. Linking

This article gives some useful information about how to break up the compilation steps. And so I came up with the following:

  1. Preprocessing cpp helloworld.cpp > helloworld.i

  2. Compilation g++ -S helloworld.i

  3. Assembly as -o helloworld.o helloworld.s

  4. 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?


Solution

  • 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.