在linux下使用gcc/g++編譯多個(gè).h .c 文件

多個(gè)文件編譯在linux下編譯,下面有三個(gè)文件,分別是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è)目錄下面,那么編譯流程:

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

or

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

當(dāng)然,沒(méi)有頭文件,兩個(gè).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

在稍微大一點(diǎn)的項(xiàng)目里面,一般都會(huì)包含多個(gè)文件。尤其是包含多個(gè)頭文件,各自頭文件的實(shí)現(xiàn),和包含main函數(shù)的文件。這樣的好處就是更容易開(kāi)發(fā)和維護(hù)。

舉一個(gè)簡(jiǎn)單的例子,main.cpp 文件是包含main函數(shù)的文件,在myinclude的文件下,包含了myhead.h 和 myhead.cpp 文件。分別是頭文件的定義和實(shí)現(xiàn)。


文件樹(shù)

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;
}

下面開(kāi)始編譯:
假如在當(dāng)前目錄直接編譯的話:

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.

直接編譯的結(jié)果就是報(bào)錯(cuò)了,錯(cuò)誤的原因是 默認(rèn)的include目錄下面沒(méi)有 myhead.h 頭文件。

如果不知道include的默認(rèn)的頭文件,請(qǐng)看:
http://www.itdecent.cn/p/3eb25114576e

那么通過(guò) -I 選項(xiàng) 鏈接上去。重新編譯

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

有報(bào)錯(cuò),錯(cuò)誤的原因是頭文件雖然找到了,但是沒(méi)有提示錯(cuò)誤,沒(méi)有定義sum函數(shù)。sum函數(shù)是在myhead.cpp文件上面定義的。也就是需要把myhead.cpp文件編譯一下。

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

編譯通過(guò):


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

運(yùn)行結(jié)果:


image.png

PS : 上面寫(xiě)得是,如果編譯,鏈接多個(gè)文件,如果好奇編譯和鏈接的具體過(guò)程,請(qǐng)看 :
http://www.itdecent.cn/writer#/notebooks/10152412/notes/9498296

PS:
gcc/g++ 里面的-c選項(xiàng)指的是,比如

gcc -c myhead.cpp -o myhead.o

將一個(gè)文件編譯,但是不鏈接。將代碼變成機(jī)器碼。

比如,

gcc -c main.cpp -o main.o

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

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

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

這樣將兩個(gè).o文件和依賴庫(kù)的文件鏈接起來(lái),編程可執(zhí)行的文件。

<br />
PPS:

  1. 以后再來(lái)寫(xiě),什么是編譯,什么是鏈接。
  2. 動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)的區(qū)別

多個(gè)文件編譯的時(shí)候,可以順便理解一下static,extern兩個(gè)關(guān)鍵字的意思。

  • extern
    如下所示的代碼:

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

編譯

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

但是,如果去掉extern的話,那么鏈接的時(shí)候,就會(huì)報(bào)一個(gè)錯(cuò)誤


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

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

改正這個(gè)錯(cuò)誤,除了可以加上extern 之外,還可以加上static,改變變量的可見(jiàn)范圍。(加上static之后,變量只能在當(dāng)前文件里面可見(jiàn)。)

  • static

static 聲明一個(gè)變量的時(shí)候,除了可以將變量的空間開(kāi)辟在全局區(qū)。第二個(gè)就是改變變量的可見(jiàn)范圍,這個(gè)變量只能在文件內(nèi)部可以。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容