單個源檔案產生可執行程式
下面是一個儲存在檔案 helloworld.cpp 中一個簡單的 C++ 程式的代碼:
/* helloworld.cpp */
#include <iostream>
int main(int argc,char *argv[])
{
std::cout << "hello, world" << std::endl;
return(0);
}
程式使用定義在標頭檔 iostream 中的 cout,向標準輸出寫入一個簡單的字串。該代碼可用以下命令編譯為可執行檔:
$ g++ helloworld.cpp
編譯器 g++ 通過檢查命令列中指定的檔案的尾碼名可識別其為 C++ 原始碼檔案。編譯器預設的動作:編譯原始碼檔案產生對象檔案(object file),連結化物件檔案和 libstdc++ 庫中的函數得到可執行程式。然後刪除對象檔案。由於命令列中未指定可執行程式的檔案名稱,編譯器採用預設的 a.out。程式可以這樣來運行:
$ ./a.out
hello, world
更普遍的做法是通過 -o 選項指定可執行程式的檔案名稱。下面的命令將產生名為 helloworld 的可執行檔:
$ g++ helloworld.cpp -o helloworld
在命令列中輸入程式名可使之運行:
$ ./helloworld
hello, world
程式 g++ 是將 gcc 預設語言設為 C++ 的一個特殊的版本,連結時它自動使用 C++ 標準庫而不用 C 標準庫。通過遵循源碼的命名規範並指定對應庫的名字,用 gcc 來編譯連結 C++ 程式是可行的,如下例所示:
$ gcc helloworld.cpp -lstdc++ -o helloworld
選項 -l (ell) 通過添加首碼 lib 和尾碼 .a 將跟隨它的名字變換為庫的名字 libstdc++.a。而後它在標準庫路徑中尋找該庫。gcc 的編譯過程和輸出檔案與 g++ 是完全相同的。
在大多數系統中,GCC 安裝時會安裝一名為 c++ 的程式。如果被安裝,它和 g++ 是等同,如下例所示,用法也一致:
$ c++ helloworld.cpp -o helloworld
多個源檔案產生可執行程式
如果多於一個的源碼檔案在 g++ 命令中指定,它們都將被編譯並被連結成一個單一的可執行檔。下面是一個名為 speak.h 的標頭檔;它包含一個僅含有一個函數的類的定義:
/* speak.h */
#include <iostream>
class Speak
{
public:
void sayHello(const char *);
};
下面列出的是檔案 speak.cpp 的內容:包含 sayHello() 函數的函數體:
/* speak.cpp */
#include "speak.h"
void Speak::sayHello(const char *str)
{
std::cout << "Hello " << str << "\n";
}
檔案 hellospeak.cpp 內是一個使用 Speak 類的程式:
/* hellospeak.cpp */
#include "speak.h"
int main(int argc,char *argv[])
{
Speak speak;
speak.sayHello("world");
return(0);
}
下面這條命令將上述兩個源碼檔案編譯連結成一個單一的可執行程式:
$ g++ hellospeak.cpp speak.cpp -o hellospeak
PS:這裡說一下為什麼在命令中沒有提到“speak.h“該檔案(原因是:在“speak.cpp“中包含有”#include"speak.h"“這句代碼,它的意思是搜尋系統標頭檔目錄之前將先在目前的目錄中搜尋檔案“speak.h“。而”speak.h“正在該目錄中,不用再在命令中指定了)。
源檔案產生對象檔案
選項 -c 用來告訴編譯器編譯原始碼但不要執行連結,輸出結果為對象檔案。檔案預設名與源碼檔案名稱相同,只是將其尾碼變為 .o。例如,下面的命令將編譯源碼檔案 hellospeak.cpp 並產生對象檔案 hellospeak.o:
$ g++ -c hellospeak.cpp
命令 g++ 也能識別 .o 檔案並將其作為輸入檔案傳遞給連結器。下列命令將編譯源碼檔案為對象檔案並將其連結成單一的可執行程式:
$ g++ -c hellospeak.cpp
$ g++ -c speak.cpp
$ g++ hellospeak.o speak.o -o hellospeak
選項 -o 不僅僅能用來命名可執行檔。它也用來命名編譯器輸出的其他檔案。例如:除了中間的對象檔案有不同的名字外,下列命令生將產生和上面完全相同的可執行檔:
$ g++ -c hellospeak.cpp -o hspk1.o
$ g++ -c speak.cpp -o hspk2.o
$ g++ hspk1.o hspk2.o -o hellospeak
編譯預先處理
選項 -E 使 g++ 將原始碼用編譯前置處理器處理後不再執行其他動作。下面的命令預先處理源碼檔案 helloworld.cpp 並將結果顯示在標準輸出中:
$ g++ -E helloworld.cpp
本文前面所列出的 helloworld.cpp 的原始碼,僅僅有六行,而且該程式除了顯示一行文字外什麼都不做,但是,預先處理後的版本將超過 1200 行。這主要是因為標頭檔 iostream 被包含進來,而且它又包含了其他的標頭檔,除此之外,還有若干個處理輸入和輸出的類的定義。
預先處理過的檔案的 GCC 尾碼為 .ii,它可以通過 -o 選項來產生,例如:
$ gcc -E helloworld.cpp -o helloworld.ii
產生彙編代碼
選項 -S 指示編譯器將程式編譯成組合語言,輸出組合語言代碼而後結束。下面的命令將由 C++ 源碼檔案產生組合語言檔案 helloworld.s:
$ g++ -S helloworld.cpp
產生的組合語言依賴於編譯器的目標平台。
建立靜態庫
靜態庫是編譯器產生的一系列對象檔案的集合。連結一個程式時用庫中的對象檔案還是目錄中的對象檔案都是一樣的。庫中的成員包括普通函數,類定義,類的對象執行個體等等。靜態庫的另一個名字叫歸檔檔案(archive),管理這種歸檔檔案的工具叫 ar 。
在下面的例子中,我們先建立兩個對象模組,然後用其產生靜態庫。
標頭檔 say.h 包含函數 sayHello() 的原型和類 Say 的定義:
/* say.h */
#include <iostream>
void sayhello(void);
class Say {
private:
char *string;
public:
Say(char *str)
{
string = str;
}
void sayThis(const char *str)
{
std::cout << str << " from a static library\n";
}
void sayString(void);
};
下面是檔案 say.cpp 是我們要加入到靜態庫中的兩個對象檔案之一的源碼。它包含 Say 類中 sayString() 函數的定義體;類 Say 的一個執行個體 librarysay 的聲明也包含在內:
/* say.cpp */
#include "say.h"
void Say::sayString()
{
std::cout << string << "\n";
}
Say librarysay("Library instance of Say");源碼檔案 syshello.cpp 是我們要加入到靜態庫中的第二個對象檔案的源碼。它包含函數 sayhello() 的定義:
/* sayhello.cpp */
#include "say.h"
void sayhello()
{
std::cout << "hello from a static library\n";
}
下面的命令序列將源碼檔案編譯成對象檔案,命令 ar 將其存進庫中:
$ g++ -c sayhello.cpp
$ g++ -c say.cpp
$ ar -r libsay.a sayhello.o say.o
程式 ar 配合參數 -r 建立一個新庫 libsay.a 並將命令列中列出的對象檔案插入。採用這種方法,如果庫不存在的話,參數 -r 將建立一個新的庫,而如果庫存在的話,將用新的模組替換原來的模組。
下面是主程式 saymain.cpp,它調用庫 libsay.a 中的代碼:
/* saymain.cpp */
#include "say.h"
int main(int argc,char *argv[])
{
extern Say librarysay;
Say localsay = Say("Local instance of Say");
sayhello();
librarysay.sayThis("howdy");
librarysay.sayString();
localsay.sayString();
return(0);
}
該程式可以下面的命令來編譯和連結:
$ g++ saymain.cpp libsay.a -o saymain
程式運行時,產生以下輸出:
hello from a static library
howdy from a static library
Library instance of SayLocal instance of Say
原文:http://www.cnblogs.com/iloveyoucc/archive/2012/08/29/2661851.html