linker - Why does the compiler only generate object files .o only from .cpp files -


as title says : why compiler generate object files .o .cpp files not header files ? , how linker knows how link object files if implementation in .h files ?

why compiler generate object files .o .cpp files not header files

for concreteness, i'll assume compiler gcc's c++ compiler.

the compiler compile header file object file, if make clear that's want.

header.h

#ifndef header_h #define header_h  #include <iostream>  inline void hw() {     std::cout << "hello world" << std::endl; }  #endif 

if do:

$ g++ header.h 

then won't generate object file, because assumes .h extension don't want to. instead, generate precompiled header file, header.h.gch.

this reasonable assumption because don't want compile header file directly object file. usually, don't want compile header file directly @ all, , if do, want pre-compiled header file.

but if want header.h compiled header.o, can insist on this:

$ g++ -c -x c++ header.h 

which says: compile, without linking, header.h, treating c++ source file. , output header.o.

this header.o pretty useless, however. not, instance, export solitary function hw linker, because function inlined. if @ symbols in object file:

$ objdump -c -t header.o  header.o:     file format elf64-x86-64  symbol table: 0000000000000000 l    df *abs*  0000000000000000 header.h 0000000000000000 l    d  .text  0000000000000000 .text 0000000000000000 l    d  .data  0000000000000000 .data 0000000000000000 l    d  .bss   0000000000000000 .bss 0000000000000000 l     o .bss   0000000000000001 std::__ioinit 0000000000000000 l     f .text  000000000000003e __static_initialization_and_destruction_0(int, int) 000000000000003e l     f .text  0000000000000015 _global__sub_i_header.h 0000000000000000 l    d  .init_array    0000000000000000 .init_array 0000000000000000 l    d  .note.gnu-stack    0000000000000000 .note.gnu-stack 0000000000000000 l    d  .eh_frame  0000000000000000 .eh_frame 0000000000000000 l    d  .comment   0000000000000000 .comment 0000000000000000         *und*  0000000000000000 std::ios_base::init::init() 0000000000000000         *und*  0000000000000000 .hidden __dso_handle 0000000000000000         *und*  0000000000000000 std::ios_base::init::~init() 0000000000000000         *und*  0000000000000000 __cxa_atexit 

we see there's nothing there boilerplate , things pulled in #include <iostream>.

we could make header.h serviceable linkage deleting keyword inline. if recompile before , have look:

$ objdump -c -t header.o | grep hw 0000000000000061 l     f .text  0000000000000015 _global__sub_i__z2hwv 0000000000000000 g     f .text  0000000000000023 hw()  

we've exported hw()! can link header.o in program!

main.cpp

extern void hw();  int main() {     hw();     return 0; } 

compile that:

$ g++ -c main.cpp 

link:

$ g++ -o prog main.o header.o 

run:

$ ./prog hello world 

but there's snag. we've defined hw() in header.h linker can see it, we can't use header.h in way header files used more, i.e. can't #include "header.h" in more 1 .cpp file compiled , linked in same program:

main1.cpp

extern void foo(); extern void bar();  int main() {   foo();   bar();   return 0; } 

foo.cpp

#include "header.h"  void foo(){     hw(); }; 

bar.cpp

#include "header.h"  void bar(){     hw(); }; 

compile them all:

$ g++ -c main1.cpp foo.cpp bar.cpp 

all good. link:

% g++ -o prog main1.o foo.o bar.o bar.o: in function `hw()': bar.cpp:(.text+0x0): multiple definition of `hw()' foo.o:foo.cpp:(.text+0x0): first defined here collect2: error: ld returned 1 exit status 

no good, because hw() defined twice, once in foo.o , again in bar.o, , that's linkage error: linker can't pick 1 definition rather other.

so see compiler willing , able compile .h file c++ source file if insist; it's able , willing compile .blahblah file c++ source if insist, assumimg there legal c++ in .blahblah file. header file compiled object file of little or no use us.

the distinction between .h file , .cpp file conventional distinction how intend file used. if give .h extension saying: all c++ in file can safely included in multiple translation units (.cpp files) compiled , linked together. if give .cpp extension saying: at least of c++ in file can compiled , linked once in same linkage.

the header.h started was proper header file, according convention. header.h deleted inline no longer header file according convention. should have renamed .cpp, if don't confusing people.

how linker knows how link object files if implementation in .h files

the linker links nothing object files , libraries. doesn't know .cpp files or .h files: might not exist far linker concerned. there 3 ways "implementation" in header file can linker.

1) unconventional way discussed: compiling header file object file, linked. you've seen, there no technical problem in doing that, though in practice it's never done.

2) usual way, #include-ing header file in .cpp file.

hello.h

#ifndef hello_h #define hello_h  static char const * hw = "hello world";  #endif 

hello.cpp

#include "hello.h" char const * hello = hw; 

in case, compiler preprocesses hello.cpp before starts generate object code, , can see compiler sees after preprocessor finished telling compiler preprocessing , nothing else:

$ g++ -p -e hello.cpp static char const * hw = "hello world"; char const * hello = hw; 

the output of command translation unit compiled hello.o, , see, code in hello.h copied translation unit in place of #include "hello.h".

so time compiler starts generate hello.o, header hello.h irrelevant: might not exist.

3) compiling header.h file pre-compiled header.h.gch. header.h.gch "semi-compiled" form of header.h #include-ed, if exists, whenever #include "header.h" or #include <header.h> appears in code. difference semi-compiled header.h.gch can processed faster header.h: (3) faster version of (2) (and has limitation compiler accept 1 precompiled header per compilation.)

whether gets there (1),(2) or (3), linkage of code .h file no different linkage of code .cpp file. code compiled compiler. compiler doesn't care whether code originates in .h file or .cpp file. compiler generates object files, , linker links object files.


Comments

Popular posts from this blog

java - Run spring boot application error: Cannot instantiate interface org.springframework.context.ApplicationListener -

reactjs - React router and this.props.children - how to pass state to this.props.children -

Excel VBA "Microsoft Windows Common Controls 6.0 (SP6)" Location Changes -