《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 可編程邏輯 > 業(yè)界動(dòng)態(tài) > 簡(jiǎn)要介紹編譯器工作過程的11步

簡(jiǎn)要介紹編譯器工作過程的11步

2015-09-18
關(guān)鍵詞: 編譯器

  源碼要運(yùn)行,必須先轉(zhuǎn)成二進(jìn)制的機(jī)器碼。這是編譯器的任務(wù)。
  比如,下面這段源碼(假定文件名叫做test.c)。
  #include <stdio.h>int main(void){
  fputs("Hello, world!\n", stdout);
  return 0;}
  要先用編譯器處理一下,才能運(yùn)行。
  $ gcc test.c
  $ ./a.out
  Hello, world!
  對(duì)于復(fù)雜的項(xiàng)目,編譯過程還必須分成三步。
  $ ./configure
  $ make
  $ make install
  這些命令到底在干什么?大多數(shù)的書籍和資料,都語焉不詳,只說這樣就可以編譯了,沒有進(jìn)一步的解釋。
  本文將介紹編譯器的工作過程,也就是上面這三個(gè)命令各自的任務(wù)。我主要參考了Alex Smith的文章《Building C Projects》。需要聲明的是,本文主要針對(duì)gcc編譯器,也就是針對(duì)C和C++,不一定適用于其他語言的編譯。
  編譯器的工作過程 - 第1張
  第一步 配置(configure)
  編譯器在開始工作之前,需要知道當(dāng)前的系統(tǒng)環(huán)境,比如標(biāo)準(zhǔn)庫在哪里、軟件的安裝位置在哪里、需要安裝哪些組件等等。這是因?yàn)椴煌?jì)算機(jī)的系統(tǒng)環(huán)境不一樣,通過指定編譯參數(shù),編譯器就可以靈活適應(yīng)環(huán)境,編譯出各種環(huán)境都能運(yùn)行的機(jī)器碼。這個(gè)確定編譯參數(shù)的步驟,就叫做"配置"(configure)。
  這些配置信息保存在一個(gè)配置文件之中,約定俗成是一個(gè)叫做configure的腳本文件。通常它是由autoconf工具生成的。編譯器通過運(yùn)行這個(gè)腳本,獲知編譯參數(shù)。
  configure腳本已經(jīng)盡量考慮到不同系統(tǒng)的差異,并且對(duì)各種編譯參數(shù)給出了默認(rèn)值。如果用戶的系統(tǒng)環(huán)境比較特別,或者有一些特定的需求,就需要手動(dòng)向configure腳本提供編譯參數(shù)。
  $ ./configure --prefix=/www --with-mysql
  上面代碼是php源碼的一種編譯配置,用戶指定安裝后的文件保存在www目錄,并且編譯時(shí)加入mysql模塊的支持。
  第二步 確定標(biāo)準(zhǔn)庫和頭文件的位置
  源碼肯定會(huì)用到標(biāo)準(zhǔn)庫函數(shù)(standard library)和頭文件(header)。它們可以存放在系統(tǒng)的任意目錄中,編譯器實(shí)際上沒辦法自動(dòng)檢測(cè)它們的位置,只有通過配置文件才能知道。
  編譯的第二步,就是從配置文件中知道標(biāo)準(zhǔn)庫和頭文件的位置。一般來說,配置文件會(huì)給出一個(gè)清單,列出幾個(gè)具體的目錄。等到編譯時(shí),編譯器就按順序到這幾個(gè)目錄中,尋找目標(biāo)。
  第三步 確定依賴關(guān)系
  對(duì)于大型項(xiàng)目來說,源碼文件之間往往存在依賴關(guān)系,編譯器需要確定編譯的先后順序。假定A文件依賴于B文件,編譯器應(yīng)該保證做到下面兩點(diǎn)。
  (1)只有在B文件編譯完成后,才開始編譯A文件。
  (2)當(dāng)B文件發(fā)生變化時(shí),A文件會(huì)被重新編譯。
  編譯順序保存在一個(gè)叫做makefile的文件中,里面列出哪個(gè)文件先編譯,哪個(gè)文件后編譯。而makefile文件由configure腳本運(yùn)行生成,這就是為什么編譯時(shí)configure必須首先運(yùn)行的原因。
  在確定依賴關(guān)系的同時(shí),編譯器也確定了,編譯時(shí)會(huì)用到哪些頭文件。
  第四步 頭文件的預(yù)編譯(precompilation)
  不同的源碼文件,可能引用同一個(gè)頭文件(比如stdio.h)。編譯的時(shí)候,頭文件也必須一起編譯。為了節(jié)省時(shí)間,編譯器會(huì)在編譯源碼之前,先編譯頭文件。這保證了頭文件只需編譯一次,不必每次用到的時(shí)候,都重新編譯了。
  不過,并不是頭文件的所有內(nèi)容,都會(huì)被預(yù)編譯。用來聲明宏的#define命令,就不會(huì)被預(yù)編譯。
  第五步 預(yù)處理(Preprocessing)
  預(yù)編譯完成后,編譯器就開始替換掉源碼中bash的頭文件和宏。以本文開頭的那段源碼為例,它包含頭文件stdio.h,替換后的樣子如下。
  extern int fputs(const char *, FILE *);extern FILE *stdout;int main(void){
  fputs("Hello, world!\n", stdout);
  return 0;}
  為了便于閱讀,上面代碼只截取了頭文件中與源碼相關(guān)的那部分,即fputs和FILE的聲明,省略了stdio.h的其他部分(因?yàn)樗鼈兎浅iL(zhǎng))。另外,上面代碼的頭文件沒有經(jīng)過預(yù)編譯,而實(shí)際上,插入源碼的是預(yù)編譯后的結(jié)果。編譯器在這一步還會(huì)移除注釋。
  這一步稱為"預(yù)處理"(Preprocessing),因?yàn)橥瓿芍螅鸵_始真正的處理了。
  第六步 編譯(Compilation)
  預(yù)處理之后,編譯器就開始生成機(jī)器碼。對(duì)于某些編譯器來說,還存在一個(gè)中間步驟,會(huì)先把源碼轉(zhuǎn)為匯編碼(assembly),然后再把匯編碼轉(zhuǎn)為機(jī)器碼。
  下面是本文開頭的那段源碼轉(zhuǎn)成的匯編碼。
  .file   "test.c"
  .section    .rodata.LC0:
  .string "Hello, world!\n"
  .text    .globl  main    .type   main, @functionmain:.LFB0:
  .cfi_startproc
  pushq   %rbp    .cfi_def_cfa_offset 16
  .cfi_offset 6, -16
  movq    %rsp, %rbp    .cfi_def_cfa_register 6
  movq    stdout(%rip), %rax
  movq    %rax, %rcx
  movl    $14, %edx
  movl    $1, %esi
  movl    $.LC0, %edi
  call    fwrite
  movl    $0, %eax
  popq    %rbp    .cfi_def_cfa 7, 8
  ret    .cfi_endproc.LFE0:
  .size   main, .-main    .ident  "GCC: (Debian 4.9.1-19) 4.9.1"
  .section    .note.GNU-stack,"",@progbits
  這種轉(zhuǎn)碼后的文件稱為對(duì)象文件(object file)。
  第七步 連接(Linking)
  對(duì)象文件還不能運(yùn)行,必須進(jìn)一步轉(zhuǎn)成可執(zhí)行文件。如果你仔細(xì)看上一步的轉(zhuǎn)碼結(jié)果,會(huì)發(fā)現(xiàn)其中引用了stdout函數(shù)和fwrite函數(shù)。也就是說,程序要正常運(yùn)行,除了上面的代碼以外,還必須有stdout和fwrite這兩個(gè)函數(shù)的代碼,它們是由C語言的標(biāo)準(zhǔn)庫提供的。
  編譯器的下一步工作,就是把外部函數(shù)的代碼(通常是后綴名為.lib和.a的文件),添加到可執(zhí)行文件中。這就叫做連接(linking)。這種通過拷貝,將外部函數(shù)庫添加到可執(zhí)行文件的方式,叫做靜態(tài)連接(static linking),后文會(huì)提到還有動(dòng)態(tài)連接(dynamic linking)。
  make命令的作用,就是從第四步頭文件預(yù)編譯開始,一直到做完這一步。
  第八步 安裝(Installation)
  上一步的連接是在內(nèi)存中進(jìn)行的,即編譯器在內(nèi)存中生成了可執(zhí)行文件。下一步,必須將可執(zhí)行文件保存到用戶事先指定的安裝目錄。
  表面上,這一步很簡(jiǎn)單,就是將可執(zhí)行文件(連帶相關(guān)的數(shù)據(jù)文件)拷貝過去就行了。但是實(shí)際上,這一步還必須完成創(chuàng)建目錄、保存文件、設(shè)置權(quán)限等步驟。這整個(gè)的保存過程就稱為"安裝"(Installation)。
  第九步 操作系統(tǒng)連接
  可執(zhí)行文件安裝后,必須以某種方式通知操作系統(tǒng),讓其知道可以使用這個(gè)程序了。比如,我們安裝了一個(gè)文本閱讀程序,往往希望雙擊txt文件,該程序就會(huì)自動(dòng)運(yùn)行。
  這就要求在操作系統(tǒng)中,登記這個(gè)程序的元數(shù)據(jù):文件名、文件描述、關(guān)聯(lián)后綴名等等。Linux系統(tǒng)中,這些信息通常保存在/usr/share/applications目錄下的.desktop文件中。另外,在Windows操作系統(tǒng)中,還需要在Start啟動(dòng)菜單中,建立一個(gè)快捷方式。
  這些事情就叫做"操作系統(tǒng)連接"。make install命令,就用來完成"安裝"和"操作系統(tǒng)連接"這兩步。
  第十步 生成安裝包
  寫到這里,源碼編譯的整個(gè)過程就基本完成了。但是只有很少一部分用戶,愿意耐著性子,從頭到尾做一遍這個(gè)過程。事實(shí)上,如果你只有源碼可以交給用戶,他們會(huì)認(rèn)定你是一個(gè)不友好的家伙。大部分用戶要的是一個(gè)二進(jìn)制的可執(zhí)行程序,立刻就能運(yùn)行。這就要求開發(fā)者,將上一步生成的可執(zhí)行文件,做成可以分發(fā)的安裝包。
  所以,編譯器還必須有生成安裝包的功能。通常是將可執(zhí)行文件(連帶相關(guān)的數(shù)據(jù)文件),以某種目錄結(jié)構(gòu),保存成壓縮文件包,交給用戶。
  第十一步 動(dòng)態(tài)連接(Dynamic linking)
  正常情況下,到這一步,程序已經(jīng)可以運(yùn)行了。至于運(yùn)行期間(runtime)發(fā)生的事情,與編譯器一概無關(guān)。但是,開發(fā)者可以在編譯階段選擇可執(zhí)行文件連接外部函數(shù)庫的方式,到底是靜態(tài)連接(編譯時(shí)連接),還是動(dòng)態(tài)連接(運(yùn)行時(shí)連接)。所以,最后還要提一下,什么叫做動(dòng)態(tài)連接。
  前面已經(jīng)說過,靜態(tài)連接就是把外部函數(shù)庫,拷貝到可執(zhí)行文件中。這樣做的好處是,適用范圍比較廣,不用擔(dān)心用戶機(jī)器缺少某個(gè)庫文件;缺點(diǎn)是安裝包會(huì)比較大,而且多個(gè)應(yīng)用程序之間,無法共享庫文件。動(dòng)態(tài)連接的做法正好相反,外部函數(shù)庫不進(jìn)入安裝包,只在運(yùn)行時(shí)動(dòng)態(tài)引用。好處是安裝包會(huì)比較小,多個(gè)應(yīng)用程序可以共享庫文件;缺點(diǎn)是用戶必須事先安裝好庫文件,而且版本和安裝位置都必須符合要求,否則就不能正常運(yùn)行。
  現(xiàn)實(shí)中,大部分軟件采用動(dòng)態(tài)連接,共享庫文件。這種動(dòng)態(tài)共享的庫文件,Linux平臺(tái)是后綴名為.so的文件,Windows平臺(tái)是.dll文件,Mac平臺(tái)是.dylib文件。

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認(rèn)版權(quán)者。如涉及作品內(nèi)容、版權(quán)和其它問題,請(qǐng)及時(shí)通過電子郵件或電話通知我們,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話:010-82306118;郵箱:aet@chinaaet.com。
亚洲一区二区欧美_亚洲丝袜一区_99re亚洲国产精品_日韩亚洲一区二区
亚洲欧洲99久久| 欧美福利视频在线观看| 亚洲精品一区二区三区在线观看| 亚洲欧美日韩综合| 亚洲永久在线| 亚洲午夜视频在线观看| 这里只有精品视频| 在线亚洲电影| 亚洲一区二区三区在线看| 亚洲图片欧美午夜| 亚洲天堂av综合网| 亚洲已满18点击进入久久| 这里只有精品视频| 亚洲欧美国产不卡| 亚洲欧美日本日韩| 欧美一区中文字幕| 久久精品国产在热久久 | 欧美一区二区免费| 欧美一级欧美一级在线播放| 亚欧成人在线| 久久久久久黄| 欧美 日韩 国产在线| 欧美韩日高清| 欧美三级在线视频| 国产精品视频观看| 国产欧美日韩综合精品二区| 国产亚洲欧美日韩日本| 精品51国产黑色丝袜高跟鞋| 亚洲成色最大综合在线| 亚洲黄色毛片| 中文在线资源观看网站视频免费不卡 | 国产欧美日韩激情| 国模一区二区三区| 亚洲电影第三页| 日韩一二三区视频| 亚洲尤物精选| 亚洲激情啪啪| 亚洲中午字幕| 久久精品99国产精品| 可以免费看不卡的av网站| 欧美精品一区三区在线观看| 欧美日韩在线精品| 国产亚洲综合精品| 亚洲日本无吗高清不卡| 亚洲影院在线观看| 亚洲精品黄色| 午夜精品久久久久久99热软件| 久久在线视频| 欧美日韩一视频区二区| 国内精品久久久久久久果冻传媒| 91久久黄色| 亚洲欧美中文日韩在线| 亚洲精品一区二区三区樱花| 亚洲欧美视频| 牛人盗摄一区二区三区视频| 国产精品久久| 136国产福利精品导航| 一区二区三区黄色| 亚洲国产欧美日韩| 亚洲欧美日韩国产一区| 久久综合精品国产一区二区三区| 欧美日韩一区二区欧美激情| 黄网站免费久久| 一区二区三区日韩精品| 亚洲电影免费| 亚洲一区高清| 欧美成人精品影院| 国产日韩欧美视频| 亚洲美女精品久久| 久久精品国产久精国产思思| 亚洲视频在线观看三级| 久久人体大胆视频| 国产精品久久久一区麻豆最新章节 | 久久伊人精品天天| 国产精品久久久久久久久久免费| 一区二区视频免费在线观看 | 国产亚洲一区二区精品| 一本大道久久a久久综合婷婷| 久久成人亚洲| 午夜亚洲一区| 欧美日韩黄色大片| 在线观看欧美亚洲| 欧美在线视频免费播放| 亚洲欧美日本日韩| 欧美日本在线视频| 尤物yw午夜国产精品视频| 亚洲女人天堂成人av在线| 一本色道久久综合亚洲精品按摩 | 欧美精品久久天天躁| 精久久久久久| 午夜亚洲精品| 性色av香蕉一区二区| 欧美日韩亚洲国产精品| 亚洲国产综合91精品麻豆| 久久av一区| 久久久国产精品一区| 国产乱码精品一区二区三| 在线亚洲一区| 中文国产一区| 欧美黄色免费| 亚洲高清不卡av| 亚洲国产你懂的| 乱中年女人伦av一区二区| 国产偷国产偷亚洲高清97cao| 亚洲制服av| 午夜亚洲精品| 国产精品爽爽ⅴa在线观看| 日韩亚洲成人av在线| 亚洲麻豆国产自偷在线| 欧美成人性生活| 怡红院av一区二区三区| 久久国产精品第一页| 午夜欧美精品久久久久久久| 国产精品久久午夜夜伦鲁鲁| 中日韩视频在线观看| 亚洲一区美女视频在线观看免费| 欧美日韩视频第一区| 99在线精品免费视频九九视| 一区二区三区欧美| 欧美人与性动交α欧美精品济南到| 亚洲精品1234| 在线视频欧美日韩| 欧美午夜宅男影院在线观看| 日韩一级二级三级| 亚洲影视在线| 国产精品视频xxx| 亚洲欧美视频在线| 久久九九免费| 激情久久中文字幕| 亚洲国产婷婷香蕉久久久久久99 | 欧美成人在线免费观看| 亚洲国产综合在线看不卡| 日韩亚洲视频在线| 欧美日韩在线视频一区| 99视频在线观看一区三区| 亚洲午夜电影| 国产伦精品一区二区三区四区免费| 亚洲男人的天堂在线| 久久久国产精品一区| 在线播放豆国产99亚洲| 亚洲精品乱码久久久久久黑人| 欧美日产国产成人免费图片| 一区二区三区四区五区在线| 欧美伊人久久久久久久久影院 | 亚洲人成在线观看| 亚洲网站在线播放| 国产精品免费一区豆花| 性感少妇一区| 美女黄色成人网| 亚洲精品一二三| 亚欧美中日韩视频| 激情综合色综合久久| 一本色道久久加勒比88综合| 国产精品v日韩精品| 小黄鸭视频精品导航| 欧美成人免费va影院高清| 一本色道久久综合狠狠躁篇怎么玩 | 免费中文日韩| 一区二区激情视频| 久久国产欧美| 亚洲欧洲日产国码二区| 午夜精品免费在线| 在线成人激情视频| 亚洲一区中文| 激情亚洲网站| 亚洲一区制服诱惑| 尤物在线观看一区| 亚洲曰本av电影| 狠久久av成人天堂| 亚洲一区www| 黄色小说综合网站| 亚洲一区二区在线播放| 激情国产一区二区| 亚洲视频在线一区观看| 黄色成人av网| 亚洲在线成人| 亚洲国产精品123| 欧美亚洲尤物久久| 亚洲精品1区2区| 久久精品伊人| 亚洲视频一二| 欧美黄色aa电影| 欧美在线电影| 国产精品二区三区四区| 最新国产乱人伦偷精品免费网站| 国产精品欧美激情| 日韩亚洲在线| 国内精品免费午夜毛片| 亚洲一区二区网站| 亚洲国产视频直播| 久久久av毛片精品| 亚洲视频在线观看一区| 欧美福利一区| 久久精品99国产精品| 国产精品免费福利| 一区二区激情| 亚洲夫妻自拍| 可以看av的网站久久看| 亚洲欧美综合一区| 国产精品女人毛片|