linux環境下編譯C++ 程式

GCC(GNU Compiler Collection)是Linux下最主要的編譯工具,GCC不僅功能非常強大,結構也異常靈活。它可以通過不同的前端模組來支持各種語言,如:Java、Fortran、Pascal、Modula-3和Ada。

安裝Gcc和g++:

yum -y install gcc automake autoconf libtool make

安裝g++:

yum install gcc gcc-c++

g++是GCC中的一個工具,專門來編譯C++語言的。
GCC的參數有:( 也是分步實現)

  • -E 讓GCC在預處理結束後停止編譯。
    g++ -E hello.cpp  -o  hello.i
    
  • -chello.i編譯成目標代碼
    g++  -c  hello.i  -o  hello.o
    
    將目標檔連接成可執行檔
    g++ hell.o   -o   hello
    
    可以一步實現
    g++  hello.cpp  -o  hello
    

假如有兩個以上原始檔案應該一下編譯

一步就實現:

g++   foo1.cpp   foo2.cpp   -o   foo

也可以分步實現:

g++   -c   foo1.cpp  -o   foo1.o
g++   -c    foo2.cpp  -o   foo2.o
g++   foo1.o  foo2.o    -o    foo

GCC一些常用選項

1、產生警告資訊的選項大多數以-W開頭 其中有-Wall

g++  -Wall  hello.cpp   -o   hello

2、將所有的警告當成錯誤的選項-Werror

g++ -Werror  hello.cpp  -o  hello

3、尋找頭檔選項

  • -I (linux默認路徑:頭檔在/usr/include/下),不在這個路徑下就要用-I指定。
    gcc  foo.cpp  -I/home/include   -o  foo
    
    4、 庫依賴選項
  • -L (linux默認路徑:庫檔在/usr/lib/下),不在這個路徑下就要用-L指定。
    g++  foo.cpp  -L/home/lib  -lfoo  -o   foo
    

庫就是將原始檔案編譯之後生成的目標檔的集合。庫命名以lib開頭。庫有靜態庫(通常以.a結尾)和動態庫(通常以.so結尾)默認情況下,g++以動態庫形式連接。如果要靜態庫連接則要用-static指定(g++ foo.cpp -L/home/lib -static -lfoo -o foo)

單個原始檔案生成可執行程式

下麵是一個保存在檔 helloworld.cpp 中一個簡單的 C++ 程式的代碼: 單個原始檔案生成可執行程式。

/* helloworld.cpp */
#include <iostream>
int main(int argc,char *argv[])
{
    std::cout << "hello, world" << std::endl;
    return(0);
}

程式使用定義在頭檔 iostream 中的 cout,向標準輸出寫入一個簡單的字串。該代碼可用以下命令編譯為可執行檔:

[root@localhost cpp]# g++ helloworld.cpp
[root@localhost cpp]# ll
total 16
-rwxr-xr-x. 1 root   root   9136 Mar  8 03:31 a.out
-rw-rw-r--. 1 zaixian zaixian  138 Mar  8 03:24 helloworld.cpp
[root@localhost cpp]#

編譯器 g++ 通過檢查命令行中指定的檔的尾碼名可識別其為 C++ 源代碼檔。
編譯器默認的動作: 編譯源代碼檔生成對象檔(object file),鏈接對象檔和 libstd c++ 庫中的函數得到可執行程式。然後刪除對象檔。由於命令行中未指定可執行程式的檔案名,編譯器採用默認的a.out。程式可以這樣來運行:

[zaixian@localhost cpp]$ ./a.out
hello, world
[zaixian@localhost cpp]$

更普遍的做法是通過 -o 選項指定可執行程式的檔案名。下麵的命令將產生名為 helloworld 的可執行檔:

[zaixian@localhost cpp]$  g++ helloworld.cpp -o helloworld
[zaixian@localhost cpp]$ ll
total 28
-rwxr-xr-x. 1 root   root   9136 Mar  8 03:31 a.out
-rwxrwxr-x. 1 zaixian zaixian 9136 Mar  8 03:32 helloworld
-rw-rw-r--. 1 zaixian zaixian  138 Mar  8 03:24 helloworld.cpp
[zaixian@localhost cpp]$

在命令行中輸入程式名可使之運行:

[zaixian@localhost cpp]$  ./helloworld
hello, world
[zaixian@localhost cpp]$

程式 g++ 是將 gcc 默認語言設為 C++ 的一個特殊的版本,鏈接時它自動使用 C++ 標準庫而不用 C 標準庫。通過遵循源碼的命名規範並指定對應庫的名字,用 gcc 來編譯鏈接 C++ 程式是可行的,如下例所示:

[zaixian@localhost cpp]$ gcc helloworld.cpp -lstdc++ -o helloworld

選項 -l (ell)通過添加首碼 lib 和尾碼 .a 將跟隨它的名字變換為庫的名字libstdc++.a。而後它在標準庫路徑中查找該庫。gcc 的編譯過程和輸出檔與 g++ 是完全相同的。

在大多數系統中,GCC 安裝時會安裝一名為 c++ 的程式。如果被安裝,它和 g++ 是等同,如下例所示,用法也一致:

[zaixian@localhost cpp]$ 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

提示: 這裏說一下為什麼在命令中沒有提到“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/ucas/p/5778664.html


上一篇: C++開發環境的安裝 下一篇: C++第一個程式