在windows安裝軟件是極其簡單的事,無非就是下載,然后一路點擊“下一步”即可。而在linux裝軟件就沒那么簡單了,尤其是對于新手而言,往往會手足無措,覺得linux很不好用。可一旦習慣了,就會驚嘆于linux的強大,安裝軟件可以簡單地用一句命令行解決從下載到安裝的整個流程,比windows下的一鍵安裝還要輕爽。也可以自己到官網下載源碼,自己編譯,甚至修改源碼,真正自定義安裝軟件。
本系列文章主要講解通過源碼安裝軟件的原理以及方法。
我們知道,不管是windows,還是linux,最終能執行的都是二進制文件,而我們的代碼是用編程語言寫的文本文件,要轉換成操作系統能識別的二進制碼就需要編譯器。
以下用實例演示編譯源碼的操作流程
編譯單一文件
新建c語言文件:hello.c
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
}
[senlong@linux ~]$ gcc hello.c
[senlong@linux ~]$ ll hello.c a.out
-rwxrwxr-x 1 senlong senlong 8512 7月 27 08:44 a.out
-rw-rw-r-- 1 senlong senlong 67 7月 27 08:44 hello.c
[senlong@linux ~]$ ./a.out
Hello World
以上實例演示了hello.c
源碼文件經由gcc
命令編譯生成a.out
可執行文件
相關術語解釋:
- 源碼文件:即程序員寫的源代碼文件(hello.c)
- 編譯器:將便于人編寫,閱讀,維護的高級計算機語言所寫作的源碼程序,翻譯為計算機能解讀、運行的低階機器語言的程序(gcc)
- 可執行文件:操作系統能直接識別,可直接執行的二進制文件(a.out)
可執行文件與普通文本文件可通過file
指令識別:
[senlong@linux ~]$ file hello.c
hello.c: C source, ASCII text # 普通文本文件
[senlong@linux ~]$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=29c4c64ff2985490bb17a37ef188574a0009b3da, not stripped # 可執行的二進制文件
編譯多個文件
默認情況下,使用gcc編譯輸出的二進制文件是a.out
, 我們可以將gcc的編譯行為拆分成兩個步驟:
-
gcc -c filename.c
生成目標文件(object file) -
gcc -o filename.o
生成可執行文件
[senlong@linux ~]$ gcc -c hello.c
[senlong@linux ~]$ ll hello*
-rw-rw-r-- 1 senlong senlong 67 7月 27 08:44 hello.c
-rw-rw-r-- 1 senlong senlong 1496 7月 27 08:53 hello.o # object file
[senlong@linux ~]$ gcc -o hello hello.o
[senlong@linux ~]$ ll hello*
-rwxrwxr-x 1 senlong senlong 8512 7月 27 08:54 hello # 二進制文件
-rw-rw-r-- 1 senlong senlong 67 7月 27 08:44 hello.c
-rw-rw-r-- 1 senlong senlong 1496 7月 27 08:53 hello.o
[senlong@linux ~]$ ./hello
Hello World
那么問題來了,既然可以一步到位用一個命令生成可執行文件,為什么還要拆分成兩步呢?
繼續以下實例:
thanks.c
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
thanks_2();
}
thanks_2.c
#include <stdio.h>
void thanks_2(void)
{
printf("Thank you!\n");
}
[senlong@linux ~]$ gcc -c thanks.c thanks_2.c
[senlong@linux ~]$ ll thanks*
-rw-rw-r-- 1 senlong senlong 71 7月 27 08:57 thanks_2.c
-rw-rw-r-- 1 senlong senlong 1504 7月 27 09:04 thanks_2.o
-rw-rw-r-- 1 senlong senlong 83 7月 27 08:56 thanks.c
-rw-rw-r-- 1 senlong senlong 1560 7月 27 09:04 thanks.o
[senlong@linux ~]$ gcc -o thanks thanks.o thanks_2.o
[senlong@linux ~]$ ll thanks*
-rwxrwxr-x 1 senlong senlong 8584 7月 27 09:05 thanks
-rw-rw-r-- 1 senlong senlong 71 7月 27 08:57 thanks_2.c
-rw-rw-r-- 1 senlong senlong 1504 7月 27 09:04 thanks_2.o
-rw-rw-r-- 1 senlong senlong 83 7月 27 08:56 thanks.c
-rw-rw-r-- 1 senlong senlong 1560 7月 27 09:04 thanks.o
[senlong@linux ~]$ ./thanks
Hello World
Thank you!
此時我們再來更改thanks_2.c
文件:
#include <stdio.h>
void thanks_2(void)
{
printf("Thank you very much!\n");
}
現在我們只需要單獨編譯thanks_2.c
文件,再將兩個目標文件聯結重新生成可執行文件。不需要再去編譯thanks.c
[senlong@linux ~]$ gcc -c thanks_2.c
[senlong@linux ~]$ gcc -o thanks thanks.o thanks_2.o
[senlong@linux ~]$ ./thanks
Hello World
Thank you very much!
之所以要生成目標文件,是因為源碼文件很多時候不是單一文件,如果其中有一個文件變化了,只需要重新編譯此文件,而不用全部文件再次編譯
引用外部函數庫
函數庫指封裝好的實現一定功能的程序。可以在別的程序直接引用,如以下實例:計算sina值,調用了sin()
函數
sina.c
#include <stdio.h>
#include <math.h>
int main(void)
{
float value;
value = sin ( 3.14 / 2 );
printf("%f\n",value);
}
[senlong@linux ~]$ gcc sina.c
[senlong@linux ~]$ ./a.out
1.000000
以上介紹了編譯源碼的基本流程,可以很明顯地看出,當我們的文件量大時,如有幾百個、幾千個文件時,如果還是按照以上這種手工編譯的方式,那linux就不好玩了。下篇文章將介紹快速編譯的方式。
敬請關注我的賬號。
本文借鑒于鳥哥linux