1. 程式人生 > >GCC中使用預編譯標頭檔案

GCC中使用預編譯標頭檔案

既使用過 Microsoft? Visual C++? 又使用過 GNU CC 的網友一定會感受到兩者編譯速度的差異,尤其是對於 wxWidgets 這樣標頭檔案內容多的軟體。Microsoft? Visual C++? 能夠有很高編譯效率的原因是其支援“預編譯標頭檔案” (Pre-Compiled Header, PCH)。當使用 Microsoft? Visual C++? 建立專案時,常常會建立檔案 StdAfx.cpp 和 StdAfx.h。其中 StdAfx.h 包含了專案中所有實質 C/C++ 原始檔所要用到的一些系統標頭檔案,而 StdAfx.cpp 只包含了 StdAfx.h。這兩個檔案便是用來建立預編譯標頭檔案“專案名.pch”的。預編譯標頭檔案是將一些專案中普遍使用的標頭檔案內容的詞法分析、語法分析等結 果快取在一個特定格式的二進位制檔案中;當然編譯實質 C/C++ 原始檔時,就不必從頭對這些標頭檔案進行詞法-語法分析,而只需要利用那些已經完成詞法-語法分析的結果就可以了。

事實上,GNU CC 從 3.4.x 版和 4.x 版開始,也支援了這種提高編譯效率的機制。只是由於 GNU CC 的手冊 中的《Using Precompiled Headers》一節對此介紹不多,也沒有簡單的自動專案管理工具支援這項功能,因而許多網友還不知道 GNU CC 的這項功能。

GNU CC 的手冊中建議使用 make 管理預編譯標頭檔案,還指出 C 語言的預編譯標頭檔案和 C++ 語言的預編譯標頭檔案是不一樣的

。這裡首先講述專案中只有 C 語言原始檔或只有 C++ 語言原始檔的情形,再講述專案中兩種語言的原始檔同時存在的情況。

專案中只有 C 或 C++ 一種語言的原始檔時,只需建立一個預編譯標頭檔案。

  1. 建立一個頭檔案,例如命名為 inc.h。該檔案供專案中所有的 C/C++ 原始檔使用。將整個專案所需要的標頭檔案都列在其中:
    /* $FreeBSD$ */
    #ifndef _INC_H_
    #define _INC_H_

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/uio.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>

    #endif /* ! _INC_H_ *
  2. 建立 Makefile,以維護預編譯標頭檔案。一方面要建立維護 GNU CC 的預編譯標頭檔案 inc.h.gch 的規則;另一方面,要在編譯每個 C/C++ 原始檔時檢查 inc.h.gch,即讓所有 .o 檔案依賴於 inc.h.gch。
    # $FreeBSD$

    CC = gcc
    CFLAGS = -g -Wall

    CXX = gcc
    CXXFLAGS = -g -Wall

    LD = gcc
    LDFLAGS = -g -Wall

    EXE = testapp
    PCH_H = inc.h
    PCH = inc.h.gch
    SRCS = testapp.c
    OBJS = testapp.o
    LIBS = # System Libraries

    ECHO = echo
    CP = cp -v
    RM = rm -f

    .SUFFIXES:
    .SUFFIXES: .o .c .cxx

    # The meaning of "$<":
    # BSD Pmake: the implied source
    # GNU make: the first prerequisite

    .c.o:
    $(CC) $(CFLAGS) -c $<
    .cxx.o:
    $(CXX) $(CXXFLAGS) -c $<

    all: $(EXE)

    # $> $^
    # BSD Pmake all sources not defined
    # GNU make not defined all prerequisites
    # Both interpret "[email protected]" as target

    $(EXE): $(OBJS) $(LIBBDD)
    $(LD) $(LDFLAGS) -o [email protected] $> $^ $(LIBS)

    # Pre-compiled header
    $(OBJS): $(PCH)

    $(PCH): $(PCH_H)
    $(CC) $(CFLAGS) $> $^

    clean:
    $(RM) $(PCH) $(OBJS)
    # For Both UNIX-like OS and Microsoft Windows (MinGW/Cygwin)
    $(RM) $(EXE) $(EXE).exe

如果專案既包含 C 語言原始檔,也包含 C++ 語言原始檔,就需要為兩種語言分別維護一個預編譯標頭檔案。

  1. 再建立一個頭檔案,例如命名為 inc.hpp。inc.h 供 C 語言原始檔使用,而 inc.hpp 供 C++ 語言檔案使用。假如 inc.hpp 的內容與 inc.h 的相同,只需要簡單的寫上:
    /* $FreeBSD$ */
    #ifndef _INC_HPP_
    #define _INC_HPP_

    #include "inc.h"

    #endif /* ! _INC_HPP_ */
  2. 在 Makefile 裡也要隨之增加對 inc.hpp 的維護。一是要增加產生 inc.hpp.gch 的規則,此時執行 GNU CC 時要增加引數“-x c++-header”;二是要在 clean 一節中刪除這個預編譯標頭檔案。
    # $FreeBSD$

    CC = gcc
    CFLAGS = -g -Wall

    CXX = gcc
    CXXFLAGS = -g -Wall

    LD = gcc
    LDFLAGS = -g -Wall

    EXE = testapp
    PCH_H = inc.h
    PCH = inc.h.gch
    PCH_X_H = inc.hpp
    PCH_X = inc.hpp.gch
    SRCS = testapp.c
    OBJS = testapp.o
    LIBS = # System Libraries

    ECHO = echo
    CP = cp -v
    RM = rm -f

    .SUFFIXES:
    .SUFFIXES: .o .c .cxx

    # The meaning of "$<":
    # BSD Pmake: the implied source
    # GNU make: the first prerequisite

    .c.o:
    $(CC) $(CFLAGS) -c $<
    .cxx.o:
    $(CXX) $(CXXFLAGS) -c $<

    all: $(EXE)

    # $> $^
    # BSD Pmake all sources not defined
    # GNU make not defined all prerequisites
    # Both interpret "[email protected]" as target

    $(EXE): $(OBJS) $(LIBBDD)
    $(LD) $(LDFLAGS) -o [email protected] $> $^ $(LIBS)

    # Pre-compiled header
    $(OBJS): $(PCH)

    $(PCH): $(PCH_H)
    $(CC) $(CFLAGS) $> $^

    $(PCH_X): $(PCH_X_H)
    $(CXX) $(CXXFLAGS) -x c++-header $> $^

    clean:
    $(RM) $(PCH) $(PCH_X) $(OBJS)
    # For Both UNIX-like OS and Microsoft Windows (MinGW/Cygwin)
    $(RM) $(EXE) $(EXE).exe

這是以上兩種 Makefile 的比較:

@@ -12,6 +12,8 @@
EXE = testapp
PCH_H = inc.h
PCH = inc.h.gch
+PCH_X_H = inc.hpp
+PCH_X = inc.hpp.gch
SRCS = testapp.c
OBJS = testapp.o
LIBS = # System Libraries
@@ -48,7 +50,10 @@
$(PCH): $(PCH_H)
$(CC) $(CFLAGS) $> $^

+$(PCH_X): $(PCH_X_H)
+ $(CXX) $(CXXFLAGS) -x c++-header $> $^
+
clean:
- $(RM) $(PCH) $(OBJS)
+ $(RM) $(PCH) $(PCH_X) $(OBJS)
# For Both UNIX-like OS and Microsoft Windows (MinGW/Cygwin)
$(RM) $(EXE) $(EXE).exe

轉自 http://zj880725.blog.163.com/blog/static/86190120200951781657881/




=========================
簡單嘗試

公司開發了一個自己的基礎類庫,有著龐大的標頭檔案。為了便於使用並提高編譯速度,嘗試了一下GCC的預編譯標頭檔案的功能:

1、先定義標頭檔案afl.h,內容如下:(afl意味a framework library)


#ifndef _AFL_H_
#define  _AFL_H_

// from here to include all head files
#include  < Log.h >
#include 
< DebugUtil.h >

#endif

2、預編譯這個標頭檔案:
g++ -o afl.h.gch -x c++-header -c afl.h -g -Wall -I"libpath..."
   使用-x c++-header來說明這個檔案作為C++的預編譯標頭檔案。注意:C和C++的處理方式不一樣,C要使用-x c-header選項。
3、經過上一步,alf.h.gch的這個預編譯的標頭檔案已經產生了。下面是程式碼中的引用方式:

// test.cpp
#include  " alf.h "

int  main()
{
    LOG(
" test " );
    
return 1 ;
}

    注意:所有的需要庫的地方,都引用alf.h就可以了。
4、編譯這個檔案:
g++ -o test.o -c test.cpp -g -Wall
  呵呵,發現編譯的時候相當快,而且不用指定庫的標頭檔案路徑。

轉自 http://blog.csdn.net/ah__fu/archive/2008/04/08/2260330.aspx

相關推薦

GCC編譯檔案的嘗試

    公司開發了一個自己的基礎類庫,有著龐大的標頭檔案。為了便於使用並提高編譯速度,嘗試了一下GCC的預編譯標頭檔案的功能:1、先定義標頭檔案afl.h,內容如下:(afl意味a framework library) #ifndef _AFL_H_#define _AFL_

GCC使用編譯檔案

既使用過 Microsoft? Visual C++? 又使用過 GNU CC 的網友一定會感受到兩者編譯速度的差異,尤其是對於 wxWidgets 這樣標頭檔案內容多

c++編譯檔案問題

環境:VS2008 語言:C++      下午出了一個非常可惡的問題,我的一個基於MFC 對話方塊的程式因為預編譯標頭檔案stdafx.h的原因始終無法編譯通過。 由於程式整體是需要預編譯標頭檔案的。因此工程內所有cpp檔案通通都包括了#include stdafx.h。      我自己寫的檔案放在工程

VSc++檔案呼叫c 函式 ,fatal error C1853 編譯檔案來自編譯器的早期版本,或者編譯為 C++ 而在 C 使用它(或相反)

出現錯誤:error C1853: “Debug\ConsoleApplication1.pch”預編譯標頭檔案來自編譯器的早期版本,或者預編譯頭為 C++ 而在 C 中使用它(或相反) 相關資料:

fatal error C1853 編譯檔案來自編譯器的早期版本,或者編譯為 C++ 而在 C 使用它(或相反)

當 Visual C++ 專案啟用了預編譯頭 (Precompiled header) 功能時,如果專案中同時混合有 .c 和 .cpp 原始檔,則可能收到 C1853 編譯器錯誤:fatal error C1853: 'pjtname.pch' precompiled header file is fro

VS關於編譯檔案的介紹

預編譯標頭檔案的原理: 在DXUT.cpp裡include一次DXUT.h,生成一次pch,pdb檔案,其他地方實際上直接用這個編譯的結果,從而減少編譯時間,提高編譯效率。一般,我們把常用的不變的庫標頭檔案放裡面,如,atlbase.h,atlcore.h,window

gcc如何生成編譯檔案(.gch)

1 建立comm.h 2 main.c中包含comm.h : #include "comm.h" 3 gcc -o comm.h.gch comm.h(低版本gcc會有bug) 4 gcc main.

錯誤:fatal error C1083: 無法開啟編譯檔案:“Debug/DistanceMeasure.pch”: No such file or directory

錯誤:fatal error C1083: 無法開啟預編譯標頭檔案:“Debug/DistanceMeasure.pch”: No such file or  directory  這種錯誤是不存在預編譯的.pch檔案,即沒有建立。 網上各種方法都是不使用預編譯,其實這樣

gcc和交叉編譯檔案包含問題

eclipse開發環境下,同一個工程,使用gcc成功編譯,但是使用交叉編譯,提示找不到標頭檔案,這是因為兩者預設的標頭檔案包含路徑不一樣。 在LINUX程式設計當中,經常會遇到標頭檔案包含的問題,那麼這些標頭檔案到底在哪個路徑下?具體的標頭檔案路徑依賴於程

關於Visual Studio的編譯檔案

使用Visual Studio很久了,關於這個細節今天終於算弄清楚了,記錄一下。使用Visual Studio或其他IDE學習C++時,即便是最簡單的hello world的控制檯程式,首先也要新建一個工程,而不能直接用記事本新建個字尾為cpp的文字檔案,然後一條命令(比如c

編譯 #include"編譯檔案"為何要放在第一句

vs2010 預編譯頭 jiese1990 預編譯頭原理 你有兩個檔案a.cpp和b.cpp,都包含了同一個標頭檔案c.h。那麼正常的流程是:將c.h和a.cpp合併,編譯成a.obj;將c.h和b

【C++】 編譯檔案

許多初學 VC 的朋友也許都為那麼一個問題困擾過:     為什麼所有的 cpp 都必須 #include "stdafx.h"     也許請教了別的高手之後,他們會告訴你,這是預編譯頭,必須包含。可是,這到底 是為什麼呢?預編譯頭有什麼用呢?     這得從標頭檔案的

Xcode-工程新增編譯檔案Prefix.pch

人生苦短,道阻且艱;修行不易,且行且努力。 【專業擅長領域】:iOS開發,遊戲開發,圖形學 【擅長平臺】:iOS平臺,Unity --------------------------------------------------------- 【個人主頁】:信厚

編譯檔案的作用和使用方法介紹

預編譯頭的概念: 所謂的預編譯頭就是把一個工程中的那一部分程式碼,預先編譯好放在一個檔案裡(通常是以.pch為副檔名的),這個檔案就稱為預編譯標頭檔案這些預先編譯好的程式碼可以是任何的C/C++程式碼--------甚至是inline的函式,但是必須是穩定的,在工程開發的過

無法寫入編譯檔案,由於 IO 裝置錯誤,無法執行此項請求的錯誤的解決

作者:朱金燦        早上檢視伺服器每日構建的情況,發現出現一個詭異的錯誤: fatal error C1085: 無法寫入預編譯標頭檔案:“E:\workspace\MyApp\Intdir\D

無法開啟編譯檔案的解決方法及編譯原理[ZZ]

1。用VC.NET編輯程式,按Ctrl+F7,出現下列錯誤: fatal error C1083: 無法開啟預編譯標頭檔案:“Debug/UGFace.pch”: No such file or  directory   解決方法:修改:專案->屬性->C/C

fatal error C1083: 無法開啟編譯檔案 的解決方法

在VS中移植工程,尤其是含有StdAfx.h和StdAfx.cpp這兩個檔案的工程,重新編譯時常發生“fatal error C1083: 無法開啟預編譯標頭檔案”的錯誤。如何解決呢?下面以VS2010為例說明解決步驟 1. 在解決方案資源管理器中,工程名上點右鍵,選擇“屬

編譯檔案PCH

一、預編譯標頭檔案使用經驗: 如果預編譯標頭檔案被正確使用時,它確實大大提高我們程式設計的效率(你工作中,有多少時間是在等編譯完成?很多吧,這個時候一般都很無聊,無奈,浪費時間)。但是他太容易用錯了. 下面是幾種常見的錯誤用法. 1) 在預編譯標頭檔案裡include自己的

C++編譯檔案

許多初學 VC 的朋友也許都為那麼一個問題困擾過:    為什麼所有的 cpp 都必須 #include "stdafx.h"    也許請教了別的高手之後,他們會告訴你,這是預編譯頭,必須包含。可是,這到底是為什麼呢?預編譯頭有什麼用呢?    這得從標頭檔案的編譯原理講起

error無法開啟編譯檔案的解決方法及編譯原理

1。用VC.NET編輯程式,按Ctrl+F7,出現下列錯誤: fatal error C1083: 無法開啟預編譯標頭檔案:“Debug/UGFace.pch”: No such file or directory 解決方法:修改:專案->屬性->C/C++