http://wiki.jikexueyuan.com/project/learn-linux-step-by-step/images/16.bmp" alt="" />
前面提到過對于機器來說只能識別0,1,我們?nèi)绻寵C器運行必須輸入機器能夠識別的語言,可是機器語言不利于人們使用可理解,因此科學(xué)家就開發(fā)出人類能看的懂的程序語言,然后再創(chuàng)造出“編譯器”將程序語言轉(zhuǎn)換為機器語言。
C 語言就是我們能夠看懂的機器語言,gcc 就是 Linux 下編譯器。我們通常 C 語言寫的程序通過 gcc 編譯后,就能成為機器能夠識別的語言
如果 LINUX 系統(tǒng)中為安裝 GCC 編譯器,可以使用下面命令安裝
[root@bogon ~]# yum install gcc
語法:
gcc –c file.c
僅將源代碼編譯成目標文件。并不會進行鏈接以及生成可執(zhí)行文件
gcc –o 執(zhí)行文件名 源代碼文件
直接生成指定名稱的執(zhí)行文件。但不會生成目標文件
gcc –o 執(zhí)行文件名 目標文件
通過目標文件生成可執(zhí)行文件
gcc [其他編譯操作] –L庫文件路徑
查找?guī)煳募穆窂侥J是/usr/lib 與/ib
gcc [其他編譯操作] –I 包含文件路徑
查找包含文件的路徑默認是/usr/include
gcc [其他編譯操作] –Wall
更加嚴謹?shù)木幾g方式,會輸出很多警告信息
gcc -O [其他編譯操作]
編譯時依據(jù)操作環(huán)境優(yōu)化執(zhí)行速度
gcc [其他編譯操作] –l庫文件名稱
編譯時引入其他的庫文件,其中庫文件 lib 與擴展名不需要寫。如引入 libm.so 文件,可寫成-lm
[root@bogon code]# vim hello.c
#include <stdio.h>
int main(void)
{
printf("hello world!");
}
[root@bogon code]# gcc hello.c
[root@bogon code]# ll hello.c a.out
-rwxr-xr-x 1 root root 4947 04-05 16:07 a.out
-rw-r--r-- 1 root root 66 04-05 16:07 hello.c
說明:默認 gcc 編譯器編譯出來的執(zhí)行文件 a.out, 可以使用-o 來制定編譯后生產(chǎn)的執(zhí)行文件名稱
[root@bogon code]# gcc -o hello hello.c
[root@bogon code]# ll hello
-rwxr-xr-x 1 root root 4947 04-05 16:11 hello
[root@bogon code]# ./a.out
hello world!
[root@bogon code]# ./hello
hello world!
假設(shè)我們有 A.c ,B.c 兩個程序文件,并且他們之間存在函數(shù)調(diào)用,那么當(dāng)其中有一個文件更改了。是不是需要將這兩個文件都重新編譯?當(dāng)然不需要,這就需要引入目標文件
目標文件:編譯器編譯源代碼后生成的文件,目標文件從結(jié)構(gòu)上講,它是已經(jīng)編譯后的可執(zhí)行文件格式,只是沒有經(jīng)過鏈接的過程。
接著上面的說,當(dāng) B.c 文件更改時,我們執(zhí)行重新編譯 B 文件生產(chǎn)目標文件。再講整體鏈接即可
File:A.c
#include <stdio.h>
#include “B.c”
int main ()
{
printf("這是第一個文件\n");
method();
}
File:B.c
#include <stdio.h>
void method(void)
{
printf("這是第二個文件!\n";)
}
root@bogon code]# gcc -c A.c B.c -I./
[root@bogon code]# ll
-rw-r--r-- 1 root root 81 04-05 16:35 A.c
-rw-r--r-- 1 root root 912 04-05 16:35 A.o
-rw-r--r-- 1 root root 80 04-05 16:34 B.c
-rw-r--r-- 1 root root 860 04-05 16:35 B.o
[root@bogon code]# gcc -o result A.o B.o
[root@bogon code]# ./result
這是第一個文件
這是第二個文件!
#include <stdio.h>
void method(void)
{
printf("這是更改后第二個文件!\n";)
}
[root@bogon code]# gcc -c B.c =>只編譯了B這個文件
[root@bogon code]# gcc -o result A.o B.o
[root@bogon code]# ./result
這是第一個文件
這是更改后第二個文件!
#include<stdio.h>
#include<math.h>
int main ()
{
float val=sin(3.14);
printf("val值是:%f\n",val);
}
[root@bogon code]# gcc -o sinmath sinmath.c -lm
[root@bogon code]# ./sinmath
val值是:0.001593
函數(shù)庫介紹
函數(shù)庫依照是否編譯到程序內(nèi)部可分為
靜態(tài)函數(shù)庫:通常以.a 為擴展名,編譯時會整合到程序文件中
動態(tài)函數(shù)庫:通常以.so 為擴展名,編譯時會不會整合到程序文件中,只是在程序文件中存在一個指向的位置
因此程序執(zhí)行時是不需要靜態(tài)函數(shù)庫的,但是需要動態(tài)函數(shù)庫,使用動態(tài)函數(shù)庫的好處再在可以減少程序文件的大小
動態(tài)函數(shù)庫加載內(nèi)存
我們知道內(nèi)存的訪問速度是硬盤的好幾倍,如果先將動態(tài)函數(shù)庫加載到內(nèi)存中,那么在使用動態(tài)函數(shù)庫時就會,就會提高很多效率
語法:ldconfig[-f 需要緩存函數(shù)庫信息所在文件] [-C 已緩存函數(shù)庫信息所在文件]
ldconfig –p 列出已緩存函數(shù)庫信息
需要緩存函數(shù)庫信息所在文件:在這個文件中記錄所有需要緩存的的函數(shù)庫默認值是
/etc/ ld.so.conf
舉例:查看下我的系統(tǒng)下緩存的函數(shù)庫
[root@bogon etc]# vim ld.so.conf
include ld.so.conf.d/*.conf
[root@bogon etc]# cd ld.so.conf.d/
[root@bogon ld.so.conf.d]# ll
-rw-r--r-- 1 root root 15 2013-01-23 mysql-i386.conf
-rw-r--r-- 1 root root 17 2013-01-09 openais-athlon.conf
-rw-r--r-- 1 root root 20 2012-08-20 qt-i386.conf
-rw-r--r-- 1 root root 276 02-22 19:23 vmware-tools-libraries.conf
-rw-r--r-- 1 root root 19 2013-08-07 xulrunner-32.conf
[root@bogon ld.so.conf.d]# vim mysql-i386.conf
[root@bogon ld.so.conf.d]# ll /usr/lib/mysql
lrwxrwxrwx 1 root root 26 02-18 20:03 libmysqlclient_r.so.15 -> libmysqlclient_r.so.15.0.0
-rwxr-xr-x 1 root root 1460684 2013-01-23 libmysqlclient_r.so.15.0.0
lrwxrwxrwx 1 root root 24 02-18 20:03 libmysqlclient.so.15 -> libmysqlclient.so.15.0.0
-rwxr-xr-x 1 root root 1452764 2013-01-23 libmysqlclient.so.15.0.0
-rwxr-xr-x 1 root root 13220 2013-01-23 mysqlbug
-rwxr-xr-x 1 root root 6215 2013-01-23 mysql_config
已緩存函數(shù)庫信息所在文件:這個文件中記錄了已經(jīng)緩存的函數(shù)庫,默認文件為
/etc/ld.so.cache ,通過-p 查詢到的信息就是從這個文件讀取而來
舉例:查看所有已緩存的函數(shù)庫
[root@bogon ld.so.conf.d]# ldconfig -p|more
947 libs found in cache `/etc/ld.so.cache'
libz.so.1 (libc6) => /lib/libz.so.1
libz.so.1 (libc6) => /usr/lib/libz.so.1
libx11globalcomm.so.1 (libc6) => /usr/lib/libx11globalcomm.so.1
……..
查看程序所包含的動態(tài)函數(shù)庫
語法:ldd –v 文件名
-v:列出所有函數(shù)庫信息
舉例:
[root@bogon ld.so.conf.d]# ldd /usr/bin/passwd
linux-gate.so.1 => (0x00ddc000)
libuser.so.1 => /usr/lib/libuser.so.1 (0x007c5000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x05c74000)
……
如果一個程序中有很多文件,那么還像上面那樣講每個文件列出來在進行編譯就會很麻煩。因此這種時候就需要使用 make 工具了
Make 編譯好處
簡化編譯時所需的指令
若在編譯完成后,修改了某個源文件,只會針對修改的文件編譯
Make 使用方法
Make 是有個二進制文件,其會查找當(dāng)前目錄下的 Makefile 文件,根據(jù)其里面定義的內(nèi)容執(zhí)行操作。 Makefile 里面包含了若干目標與操作
其基本關(guān)于規(guī)則如下
目標: