【轉】在linux下使用gcc/g++編譯多個.h文件


轉自:https://www.jianshu.com/p/e5c6a255076b

博主寫得很好

多個文件編譯在linux下編譯,下面有三個文件,分別是1.cpp 和 2.cpp 和myhead.h 文件。

1.cpp

#include <iostream> #include "myhead.h" using namespace std; int main(){ print(); cout<<"yes !"<<endl; return 0; } 

2.cpp

#include <iostream> #include "myhead.h" using namespace std; void print(){ std::cout<<" print "<<std::endl; cout<< } 

myhead.h

#ifndef __myhead_h #define __myhead_h void print(); #endif 

假如他們都在一個目錄下面,那么編譯流程:

g++ -c 2.cpp             #將2.cpp 編譯成2.o 文件
g++ 1.cpp -o a.out 2.o   #多個文件一起鏈接

or

g++ -c 2.cpp 
g++ -c 1.cpp 
g++ 1.o 2.o -o test

當然,沒有頭文件,兩個.c文件也是可以編譯的。如下:

1.cpp文件

#include <iostream> using namespace std; void fn(); int main(){ cout<<"123"<<endl; fn(); return 0; } 

2.cpp文件

#include <iostream> void fn(){ std::cout<<"fn"<<std::endl; } 

編譯:

g++ -c 1.cpp 
g++ -c 2.cpp 
g++ -o test 1.o 2.o

在稍微大一點的項目里面,一般都會包含多個文件。尤其是包含多個頭文件,各自頭文件的實現,和包含main函數的文件。這樣的好處就是更容易開發和維護。

舉一個簡單的例子,main.cpp 文件是包含main函數的文件,在myinclude的文件下,包含了myhead.h 和 myhead.cpp 文件。分別是頭文件的定義和實現。


 
文件樹

main.cpp :

#include <iostream> #include <myhead.h> using namespace std; int main(){ //fun_head(); cout<<"in main"<<endl; int x=100; int y=200; cout<<"sum : "<<sum(x,y); return 0; } 

myhead.h

#ifndef __myhead_h #define __muhead_h void print(); int sum(int a,int b); #endif 

myhead.cpp

#include "myhead.h" #include <iostream> using namespace std; void print(){ cout<<"in fun head"<<endl; } int sum(int a,int b){ return a+b; } 

下面開始編譯:
假如在當前目錄直接編譯的話:

zhaozheng@ubuntu:~/code/c++/test_compile/src$ g++ main.cpp -o main main.cpp:2:20: fatal error: myhead.h: No such file or directory compilation terminated. 

直接編譯的結果就是報錯了,錯誤的原因是 默認的include目錄下面沒有 myhead.h 頭文件。

如果不知道include的默認的頭文件,請看:
http://www.jianshu.com/p/3eb25114576e

那么通過 -I 選項 鏈接上去。重新編譯

zhaozheng@ubuntu:~/code/c++/test_compile/src$ g++ main.cpp -o main -I ../myinclude/ /tmp/ccH3BlLo.o: In function `main': main.cpp:(.text+0x3e): undefined reference to `sum(int, int)' collect2: error: ld returned 1 exit status 

有報錯,錯誤的原因是頭文件雖然找到了,但是沒有提示錯誤,沒有定義sum函數。sum函數是在myhead.cpp文件上面定義的。也就是需要把myhead.cpp文件編譯一下。

zhaozheng@ubuntu:~/code/c++/test_compile/myinclude$ g++ -c myhead.cpp -o myhead.o 

編譯通過:


 
image.png

最后,再一次的編譯:

zhaozheng@ubuntu:~/code/c++/test_compile/src$ g++ main.cpp -o main -I ../myinclude/ ../myinclude/myhead.o zhaozheng@ubuntu:~/code/c++/test_compile/src$ 
 
image.png

運行結果:


 
image.png

PS : 上面寫得是,如果編譯,鏈接多個文件,如果好奇編譯和鏈接的具體過程,請看 :
http://www.jianshu.com/writer#/notebooks/10152412/notes/9498296

PS:
gcc/g++ 里面的-c選項指的是,比如

gcc -c myhead.cpp -o myhead.o

將一個文件編譯,但是不鏈接。將代碼變成機器碼。

比如,

gcc -c main.cpp -o main.o

將main.cpp文件編譯為main.o 文件

那么鏈接器的作用是什么?

gcc -o main  main.o  ../myinclude/myhead.o 

這樣將兩個.o文件和依賴庫的文件鏈接起來,編程可執行的文件。

<br />
PPS:

  1. 以后再來寫,什么是編譯,什么是鏈接。
  2. 動態庫和靜態庫的區別

多個文件編譯的時候,可以順便理解一下static,extern兩個關鍵字的意思。

  • extern
    如下所示的代碼:

     
     

如果在2.cpp文件里面定義了一個變量,在1.cpp這個文件里面去訪問這個變量。在鏈接的時候,2.cpp里面的變量對1.cpp是可以的。1.cpp里面是可以訪問這個變量的,但是,需要使用extern聲明這個變量是賴在其他文件的。

編譯

g++ -c 1.cpp 
g++ -c 2.cpp
g++ 1.o 2.o -o test

但是,如果去掉extern的話,那么鏈接的時候,就會報一個錯誤


 
 

錯誤提示,連接的時候 兩個文件里面的value都是彼此可以的,所以,提示變量被定義了多次。

2.o:(.data+0x0): multiple definition of `value' 1.o:(.bss+0x0): first defined here collect2: error: ld returned 1 exit status 

改正這個錯誤,除了可以加上extern 之外,還可以加上static,改變變量的可見范圍。(加上static之后,變量只能在當前文件里面可見。)

 
 
  • static

static 聲明一個變量的時候,除了可以將變量的空間開辟在全局區。第二個就是改變變量的可見范圍,這個變量只能在文件內部可以。



作者:zhaozhengcoder
鏈接:https://www.jianshu.com/p/e5c6a255076b
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM