Chakarat Skawratananond (chakarat@us.ibm.com) , 技術顧問, IBM Nam Keung (namkeung@us.ibm.com) , 高級程序員, IBM Calvin Sze (calvins@us.ibm.com) , Linux 顧問 , IBM
2005 年 01 月 本文旨在幫助研究基于IBM® POWER™ 處理器的系統的 Linux™ 開發人員快速從 GNU gcc 和 gcc-c++ 編譯器(稱為 GCC)遷移到 IBMXL C/C++ Advanced Edition V7.0。本文是對 2003 年 7 月首次出版的“How to Use IBM VisualAge C++ Version 6.0 for Linux on IBM pSeries and iSeries”一文的更新。 簡介 XLC/C++ Advanced Edition for Linux 是基于標準的命令行編譯器,用于在基于 POWER 處理器的系統上運行的Linux。它是 VisualAge® C++ V6.0 for Linux 的后續版本。XL C/C++ 不僅使用 IBMPOWER、POWER3™ 和 POWER4™ 的功能,而且還添加了對新的 POWER5™ 和 POWER 970 處理器的支持。本文介紹了XL C/C++ V7.0 for Linux 編譯器中添加的新功能并著重講述了 GCC 和 XL C/C++ 之間的各種區別。 在本文中,我們用 XL C/C++ 表示 IBM XL C/C++ V7.0 for Linux。術語 Linux on POWER 是指在基于 IBM POWER 處理器的系統上運行的 Linux 操作系統。 本文要說明的主題包括: - 版本 7.0 中的新功能。
- 如何設置 XL C/C++ 的編譯環境。
- 優化選項。
- 檢查對 GNU gcc 和 gcc-c++ 擴展的依賴。
- 32/64 位編譯器模式。
- 模板實例化。
- 運行時鏈接。
- XL C/C++ 支持的 GCC 功能。
- 可重新分布的庫。
- 鏈接順序。
- 對運行時錯誤的診斷。
XL C/C++ 提供了大量為 POWER Architecture量身定做的優化選項,其中包括POWER5 和 POWER 970 處理器。在許多情況下,對于 POWER 基于處理器的系統,使用 XLC/C++ 構建的應用程序顯示了比使用 GCC on Linux 構建的那些應用程序更顯著的性能提高。如果您想充分利用 POWERArchitecture 的潛能,我們建議您使用 XL C/C++。 XL C/C++ for Linux 現在可以在 SUSE LinuxEnterprise Server 9 for POWER (SLES 9) 和 Red Hat Enterprise Linux AS V3(RHEL 3) Update 3 上使用。在 IBM XL C/C++ Advanced Edition for Linux 站點中,可以發現更多信息。 XL C/C++ 概述 XLC/C++ 是 Linux on POWER 的優化的、基于標準的命令行編譯器??梢詫?XL C/C++ 用作后綴為 .c(小寫 c)的文件的C 編譯器,或用作后綴為 .C(大寫 C)、.cc、.cpp 或 .cxx 的文件的 C++ 編譯器。XL C/C++ 支持 C 的兩種ISO 編程語言規范:C89 和 C99。該編譯器還支持兩種 C++ 標準:Standard C++ 和C++98。另外,編譯器還支持許多語言擴展,包括 GNU gcc 和 gcc-c++ 語言擴展的子集。 XL C/C++ 創建二進制或對象文件,這些文件與由 GCC生成的文件相兼容。為了獲得這種兼容性,在同一系統上,使用 XL C/C++ 編譯的程序與 GCC 使用的那些程序包含相同的頭文件。XLC/C++ 使用 GNU gcc 和 gcc-c++ 頭文件,生成的應用程序與通過 GCC 提供的 C 和 C++運行時庫鏈接。因此,應用程序的一部分可以使用 XL C/C++ 構建獲得優化,然后將其與使用 GCC構建的那部分組合來生成應用程序,該應用程序運行性能就好像是由 GCC 或 XL C/C++ 單獨構建的。Linux on POWER 的 XLC/C++ 和 GCC 之間的關系可以概括如下: - 編譯使用 Linux 分布的 GNU gcc 和 gcc-c++ 頭文件。
- 編譯使用 GUN 匯編程序。
- 鏈接使用 GUN 鏈接程序。
- 編譯的程序使用 GNU gcc 和 gcc-c++ 運行時庫。
- 調試使用 GNU 編譯器,gdb。
- POWER 處理器的 IBM 內置功能與 GNU gcc/gcc-c++ 內置功能共存。
版本 7 中的新功能 這一節將重點介紹 XL C/C++ for Linux 新增功能中的一小部分。有關新功能的完整列表,請參閱安裝 XL C/C++ 時提供的 Getting Started with XL C/C++。 性能與優化
- 對選項
-qarch 和 -qtune 的優化。把對 POWER5 和 POWER 970 架構的支持添加到選項 -qarch 和 -qtune 中。
例如:
-qarch=pwr5, -qarch=ppc970, -qtune=pwr5, -qtune=ppc970
|
- 通過
–qaltivec (僅 POWER 970)和 –qenablevmx 支持 Vector Multimedia Extensions (VMX)。 - 隨編譯器提供了 IBM Mathematics Acceleration Subsystem (MASS) 向量庫。向量庫是線程安全的,通過相應的 libm 例程提供改善的性能。
符合行業標準
- 對于 C、C++ 和 Fortran,XL C/C++ 支持 OpenMP API V2.0。
- 在版本 7 中,用 XL C/C++ 實現了更多的 GNU gcc 和 gcc++ 擴展。(有關的完整列表,請參見 Getting Started with XL C/C++ 中的表。)
- 增強的 Unicode 和 NLS 支持。添加了新數據類型以支持 UTF-16 和 UTF-32。
新功能
- gxlc 和 gxlc++ Utilities。它們是一些調用方法,將 GNU gcc 或 gcc-c++ 調用命令轉換為相應 xlc 或 xlc++ 命令以調用 XL C/C++ 編譯器。
要使用 gcc –ansi 選項來編譯 Hello World 程序的 C 版本,可以使用:
其轉換為:
然后使用此命令來調用 XL C 編譯器。 gxlc 和 gxlc++ 有助于最大程度地減少對使用 GNU編譯器構建的現有應用程序的 makefile 的更改。它們支持 GCC 選項的主要部分,配置文件 gxlc.cfg控制它們的操作。對于未轉換的輸入選項,gxlc 和 gxlc++ 將返回警告。雖然 gxlc 和 gxlc++ 方便了到 XL C/C++的轉換,從而可以充分使用 XL C/C++ 的功能,但我們建議您使用 XL C/C++ 調用方法及其相關選項。 - XL C/C++ 將版本信息添加到創建的模板注冊文件中。編譯器在內部使用這條信息來跟蹤應該使用的模板注冊文件格式的版本。
- 為編譯器調用命令和每個命令行實用程序都提供了手冊頁。
編譯器模式 XL C/C++ 的默認位置是 /opt/ibmcmp。XL C/C++ 包含各種調用命令。每個命令都有相應的線程安全版本。構建多線程應用程序時,要使用線程安全版本(除了 gxlc 和 gxlc++ )。下表顯示了可用調用命令。 表 1. 可用調用命令
調用命令 | 線程安全變量 | 描述 | xlC 或 xlc++ | xlC_r 或 xlc++_r | 源文件作為 C++ 代碼進行編譯 | xlc | xlc_r | 源文件作為 C 代碼進行編譯。該模式包含下列編譯器選項:-qlanglvl=extc89 、-qalias=ansi 、-qcpluscmt 、-qkeyword=inline | c89 | c89_r | 編譯器執行 ISO C89 標準。此調用包含下列編譯器選項:-qlanglvl=stdc89 , -qalias=ansi 、-qstrict_induction 、-qnolonglong 、-D_ANSI_C_SOURCE 、-D__STRICT_ANSI__ | c99 | c99_r | 編譯器執行 ISO C99 標準。此調用包含下列編譯器選項:-qlanglvl=stdc99 、-qalias=ansi 、-qstrict_induction 、-D_ANSI_C_SOURCE 、-D_ISOC99_SOURCE 、-D__STRICT_ANSI__ | cc | cc_r | 用于不需要遵守 C89 和 C99 的遺留 C 代碼。此調用包含下列編譯器選項:-qlanglvl=extended 、-qnoro 、-qnoroconst | xlCcore 或 xlc++core | XlCcore_r 或 xlc++core_r | 與 xlC 和 xlc++ 相同,但是編譯器將僅鏈接到運行時庫的內核。如果想將應用程序鏈接到其他運行時庫,而不是鏈接到隨 XL C/C++ 一起提供的運行時庫,那么可以使用這個調用 | gxlc 或 gxlc++ |
| 轉換方法,該方法將 GNU gcc 或 gcc-c++ 調用命令轉換為相應 xlC 或 xlc++ 命令并調用 XL C/C++ 編譯器 |
在大多數情況下,應該使用 xlC 命令來編譯 C++ 源文件,使用 xlc 命令來編譯 C 源文件。如果既擁有 C 文件又擁有 C++ 對象文件,那么可以使用 xlC 進行鏈接。注意,在 VisualAge V6.0 中,調用 xlc 意味著使用的是選項 -qlanglvl=stdc89 ,而不是在 XL C/C++ V7.0 中的 -qlanglvl=extc89 。 XL C/C++ 文檔 安裝 XL C/C++ 時提供下列 PDF 文檔: - XL C/C++ for Linux Getting Started (getstart.pdf)。
- XL C/C++ for Linux Installation Guide (install.pdf) 包含有關安裝編譯器和啟用手冊頁的說明。
- XL C/C++ for Linux C/C++ Language Reference (language.pdf) 包含關于 IBM 支持的 C 和 C++ 語言的信息。
- XL C/C++ for Linux Compiler Reference (compiler.pdf) 包含關于各種編譯器選項、編譯指令、宏和內置函數信息,這些信息包括那些用于并行處理的信息。
- XL C/C++ for Linux Programming Guide (proguide.pdf) 包含其他出版物中尚未涉及的關于使用 XL C/C++ 編程的信息。
在下列位置可以找到這些文檔: - 安裝 CD 的 /docs/LANG/pdf 目錄,其中 LANG 表示語言和位置代碼。
- 安裝編譯器后的 /opt/ibmcmp/vacpp/7.0/doc/LANG/pdf 目錄。
產品文檔的 HTML 版本安裝在 /opt/ibmcmp/vacpp/7.0/doc/LANG/html 目錄。在這個目錄中打開 index.html 文件可以查看 HTML 文件。 安裝和配置 XL C/C++ 為了獲得與 GNU gcc 和 gcc-c++ 編譯器的二進制兼容,必須首先安裝下列包: 表 2. RHEL3
GCC 先決條件 | 版本要求 | gcc | 3.2.3 | gcc-c++ | 3.2.3 | glibc-devel(32 和 64 位) | 2.3.2 | libstdc++-devel(32 和 64 位) | 3.2.3 |
表 3. SLES 9
GCC 先決條件 | 版本要求 | gcc | 3.3.3 | gcc-c++ | 3.3.3 | gcc-64bit | 9 | glibc-devel-64 bit | 9 | libstdc++-devel-64 bit) | 9 |
SLES 9 還需要 java2 和 java2-jre 包版本 1.3.1。 有關安裝編譯器的詳細信息,請參閱 XL C/C++ for Linux Installation Guide。 安裝 XL C/C++ 后,我們建議您在開始使用編譯器之前,先運行名為 new_install 的工具(默認情況下,這個工具位于 /opt/ibmcmp/vac/7.0/bin)。然后,這個工具會執行 vac_configure 腳本并創建適當的配置文件。 配置文件保存 XL C/C++ 應該使用的 32 位和 64 位 GCC 編譯器的位置。該文件是必需的,因為系統中可能會安裝多個 GCC,XL C/C++ 需要知道應該使用哪個 GCC。XL C/C++ 提供名為 vac_configure 的實用程序(默認情況下,該程序位于 /opt/ibmcmp/vac/7.0/bin),幫助創建和更新配置文件。默認配置文件是 /etc/opt/ibmcmp/vac/7.0/vac.cfg。XL C/C++ Compiler Reference 文檔中有 vac_configure 的語法。 還可以使用下列編譯器選項指定標準包含路徑: 表 4. 編譯器選項
選項名稱 | 描述 | -qgcc_c_stdinc= | 指定 GNU gcc 頭文件的新目錄搜索路徑 | -qgcc_cpp_stdinc= | 指定 GNU gcc-c++ 頭文件的新目錄搜索路徑 | -qc_stdinc= | 指定 IBM C 頭文件的新目錄搜索路徑 | -qcpp_stdinc= | 指定 IBM C++ 頭文件的新目錄搜索路徑 |
XL C/C++ 中的優化選項 XLC/C++ 提供了適合 IBM 硬件的優化選項組合。在許多情況下,對于 Linux on POWER,使用 XL C/C++編譯的應用程序顯示了比那些使用 GCC編譯的應用程序更顯著的性能提高。應該注意的是,對于所有應用程序,并不是所有優化都是有利的。通常必須在編譯器進行的優化與編譯時間增加(伴隨著調試能力減低)的程度之間進行平衡。 優化級別 優化級別由編譯器選項指定。下表匯總了每一優化級別上的編譯器行為。 表 5. 編譯器行為
選項 | 行為 | -qnoopt | 快速編譯,完全調試支持 | -O2(與 -O 相同) | 執行編譯器開發人員認為是編譯速度和運行時性能最佳組合的優化。如果沒有使用 -qnostrict_induction 或 -qnostrict 明確否定,那么這個設置中將包含 -qstrict 和 –qstrict_induction | -O3 | 執行內存占用大、編譯時間長或兩者都有的其他優化。當運行時改善比最大程度地減少編譯資源使用重要時,建議使用這些優化 | -O4 和 -O5 | 執行過程間優化、循環優化和自動計算機調整 |
特定處理器架構的優化 目標計算機選項是指示編譯器為給定微處理器或架構系列上的最佳執行生成代碼的那些選項。您可以通過優化,來滿足目標處理器、給定處理器架構系列內的一系列處理器或特定處理器的最大范圍的可能選擇。下列選項將控制影響目標計算機的單獨某些方面的優化。 表 6. 優化選項
選項 | 行為 | -qarch | 選擇應該為其生成指令代碼的處理器架構系列。默認值是 -qarch=ppc64grsq 。還可以使用以下子選項:auto 、pwr3 、pwr4 、pwr5 、ppc970 、ppc64 、ppcgr 、rs64b 、rs64c | -qtune | 偏向于對給定微處理器上的執行操作進行優化,但這并不意味著將與指令集合架構有關的任何操作作為目標。Linux 上的默認值是 -qtune=pwr3 ??捎玫淖舆x項包括:auto 、pwr3 、pwr4 、pwr5 、ppc970 、rs64b 、rs64c | -qcache | 定義特定緩存或內存幾何。如果使用了 –qcache ,則將 -qhot 或 -qsmp 與其一起使用 | -qhot | High-Order Transformations:該優化可以通過諸如交換、合并及展開等方法特別地提高循環性能。指定 -qhot 時,默認值為選項 -qhot=vector 。嘗試將 -qhot 與 -O2 和 -O3 一起使用。如果不可能存在轉換,該選項的影響是中性的。 | -qsmp | 生成共享內存并行處理所需的線程代碼。指定 -qsmp 時,默認值為選項 -qsmp=auto 。如果在 OpenMP 程序中編譯且不想進行自動并行化,則使用 -qsmp=omp:noauto 。使用 -qsmp 時,總是使用 _r 編譯器調用 |
為了最有效地使用目標計算機選項,應該嘗試使用 –qarch 指定可能的最小計算機系列,它將很好地運行代碼。嘗試使用 –qtune 為實際上指定性能最好的地方。例如,如果僅 POWER5 系統中支持應用程序,則使用 -O3 -qarch=pwr5 -qtune=pwr5 。當系統具有可配置的 L2 或 L3 緩存選項時,或者當執行模式減少了緩存的共享級別的有效大小時(例如,POWER5 中的單片雙核的 SMP 執行),修改緩存配置可能會有用。 POWER 平臺支持其他平臺上無法使用的機器指令。XL C/C++ 提供了一組內置函數,直接映射到特定 POWER 指令。通過使用這些函數,可以消除函數調用返回成本、參數傳遞、堆棧調整及所有與函數調用相關的其他成本。有關支持的內置函數的完整列表,請參閱 XL C/C++ C++ for Linux on pSeries Compiler Reference 文檔。 檢查對 GNU gcc 和 gcc-c++ 語言擴展的依賴 嚴格遵從 ISO 語言規范的應用程序將具有最大程度的可移植性。IBM XL C/C++ 支持一部分 GNU gcc 和 gcc-c++ 到 C 和 C++ 的擴展??赡苄枰匦驴匆幌乱蕾嚥皇苤С值臄U展的代碼。如果使用了任何擴展,GCC 選項 –pedantic 會將引導它打印警告消息。http://gcc.gnu.org 中有 GNU gcc/gcc-c++ 擴展的完整列表。 在 32 位和 64 位編譯器模式之間切換 通過指定編譯器選項 -q32 或 -q64 ,或通過設置環境變量 OBJECT_MODE ,可以設置 XL C/C++ 生成 32 位或 64 位對象。-q32 和 -q64 選項會覆蓋 OBJECT_MODE 變量設置的值。如果沒有指定 -q32 和 -q64 ,并且沒有設置 OBJECT_MODE ,那么編譯器的默認模式為 32 位輸出模式。在 64 位模式中,定義了 __64BIT__ 預處理器宏。 32 位和 64 位對象不能綁定在一起,所以需要確保全部在同一模式中編譯所有對象。鏈接選項還必須反映要鏈接到的對象類型。如果具有 64 位對象,必須使用 64 位模式鏈接這些對象。 模板實例化 模板實例化是到 C++ 語言的擴展之一,GCC 和 XL C/C++ 對其進行不同處理。編譯器和鏈接程序需要確保每個模板實例在可執行程序中確實僅出現一次。這一節先討論 GCC 如何處理模板實例化,然后討論 XL C/C++ 中的可用選項。 GCC 3.2 不支持模板儲存庫的概念,模板儲存庫是存儲模板實例的自動維護的位置。然而,GCC 3.2 提供了下列選項: -frepo 如果使用此選項,那么對于將模板實例化了的每個 .cc 文件,編譯器將生成擴展名為 .rpo 的文件。這個 .rpo 文件包含相應對象文件中使用的模板實例化的清單。鏈接時,一些對象文件可能會重新編譯和重新鏈接,以避免符號重復。 -fno-implicit-templates 使用這個選項,開發人員可以確定必須對哪些實例進行實例化。還有其他幾個選項,如 -fexternal-templates 和 -falt-external-templates ,但是 GCC 3.2 中不支持這些選項。
XL C/C++ 中可以使用下列編譯器選項: -qtempinc 使用這個選項,XL C/C++ 可以確定要實例化的模板代碼,作為編譯和鏈接過程的最后一步。這樣做可以防止在最終的可執行程序或庫中有重復的模板實例。 該選項要求以特定方式組織源代碼。也就是說,模板的聲明和定義必須在單獨的文件中。模板定義需要位于與頭文件相同的目錄中,并且擁有相同名稱,但是具有 .cc(小寫字母 c)后綴。否則,頭文件必須使用 #pragma implementation("...") 語句來標識相應的定義文件。例如,模板類 List 的聲明和定義文件分別為 List.h 和 List.cc 。在 List.h 文件中,必須包含語句 #pragma implementation("List.cc") 。 如果沒有使用 -qtempinc 指定目錄,那么編譯器將在當前目錄中創建名為 tempinc 的目錄,用它來保存將在模板中生成的信息??梢詾檫@個目錄選擇自己的名稱和位置,這樣,當創建包含在不同目錄中編譯的對象文件的可執行程序時,可以使用相同目錄。 例如: xlC -c foo.cc -qtempinc=../mytemplates cd .. xlC -o app app.cc src/foo.o qtempinc=mytemplates
|
因為模板代碼實際由編譯器在鏈接時創建,所以當使用具有共享庫的模板時(其中沒有鏈接發生),就會出現問題。在 XL C/C++ Version 5 中,引入了選項 -qmkshrobj ,當創建使用模板的共享對象時,該選項應該與 -qtempinc 一起使用。不使用 makeC++SharedLib 而使用這些選項的優點是:編譯器將自動包含并編譯 tempinc 目錄中的模板實例化。 如果 XL C/C++ 檢測到上述代碼布局結構,那么它會自動啟用 -qtempinc 選項。如果想阻止這項操作,自己手工對模板進行實例化,那么可以使用選項 -qnotempinc 。還可以使用 #pragma define 指令強制執行實例化。例如,#pragma define(List); -qtemplateregistry 如果不想更改代碼布局或不想在頭文件中添加 #pragma implementation指令,那么可以使用此選項。它依賴于算法的先到先得類型。在編譯單元對新的實例第一次進行實例化時,編譯器將創建在個實例,并將記錄保存在注冊表文件中??梢栽谠撨x項中指定這個注冊表文件的名稱。默認情況下,在當前目錄中創建名為 templreg的文件。當另一編譯單元引用上一編譯單元中相同的實例化或使用相同的注冊表文件時,不再需要對該實例進行實例化。因此,只需為整個程序生成一個副本即可。
-qtemplateregistry 和 -qtempinc 選項是互斥的。指定 -qtempinc 則意味著 -qnotemplateregistry 。然而,指定 -qnotempinc 并不意味著 -qtemplateregistry 。
如果更改源代碼,并且僅重新編譯受影響的部分,那么 -qtemplaterecompile 選項將參考模板注冊表,來確定是否對源文件進行更改需要重新編譯其他編譯單元。當將源文件更改為不再引用給定實例化及以前包含該實例化的相應對象文件時,需要執行這項操作。如果是這樣,那么受影響的編譯單元將自動重新編譯。 如果需要的話,可以使用選項 -qnotemplaterecompile 禁用依賴單元的自動重新編譯。從原始子目錄移動對象文件的自動化構建過程就是這樣的例子。 示例代碼 下列示例代碼說明了在 XL C/C++ 中如何處理 C++ 模板。 清單 1. 文件布局
-app/ | main.cc |--- bar/ |--- bar.cc |--- foo/ |--- foo.cc |--- stack/ |--- stack.cc |--- stack.h
|
清單 2. stack.h
stack.h -------- #ifndef STACK_H #define STACK_H
#ifdef TEMPINC //This is needed when building with -qtempinc #pragma implementation("stack.cc") #endif
template class stack { private: T* array ; int top ; int sz ; public: stack( int ) ; ~stack() ; void push( T ) ; T pop( ); };
#endif
|
清單 3. stack.cc
#include "stack.h" #include
template stack::stack(int s) { array = new T[sz = s]; top = 0; } template stack::~stack() { delete [] array; } template void stack::push( T a ) { if ( top >= sz ) { printf( "Out of stack range, push failed "); } else { array[top++] = a ; } } template T stack::pop() { if ( top <= 0 ) { printf( "out of stack range, pop failed "); return 0; } else { T ret = array[--top]; return ret; } }
|
清單 4. bar.cc
#include "../stack/stack.h" #include
#ifdef REGISTRY #include "../stack/stack.cc" #endif
stack barstack( 2 ) ;
void bar () { barstack.push( 5 ); barstack.push( 6 ); int p = barstack.pop(); printf("Pop from barstack is %d ", p); }
|
清單 5. foo.cc
#include "../stack/stack.h" #include
#ifdef REGISTRY #include "../stack/stack.cc" #endif
stack foostack( 2 );
void foo () { foostack.push ( 11 ); foostack.push ( 12 ); int p = foostack.pop(); printf("Pop from foostack is %d ", p); }
|
清單 6. main.cc
extern void foo(void); extern void bar(void);
main(){ foo(); bar(); }
|
下面是使用選項 -qtempinc 構建 main 的過程: cd stack/ xlC -c stack.cc cd ../bar xlC -c bar.cc -DTEMPINC -qtempinc=../mytemp cd ../foo xlC -c foo.cc -DTEMPINC -qtempinc=../mytemp cd .. xlC -o main main.cc -qtempinc=mytemp stack/stack.o bar/bar.o foo/foo.o
注意,bar.cc 、foo.cc 和 main.cc 共享了名為 mytemp 的相同 "tempinc" 目錄。因此,只需創建一個 stack 實例即可。在 mytemp 目錄下,有兩個文件:stack.C 和 stack.o。stack.C 的內容如下所示: 清單 7. stack.c
/*1053113184*/#include "/home/chakarat/Template_va/foo/../stack/stack.h" /*0000000000*/#include "/home/chakarat/Template_va/stack/stack.cc" /*1053113184*/#include "/home/chakarat/Template_va/bar/../stack/stack.h" template stack::stack(int); template stack::~stack(); template void stack::push(int); template int stack::pop();
|
如果不想在 stack.h 中添加 #pragma implementation("stack.cc") ,那么可以使用選項 -qtemplateregistry 。下面說明了如何使用這個選項: cd stack/ xlC -c stack.cc cd ../bar xlC -c bar.cc -DREGISTRY -qtemplateregistry=../registry cd ../foo xlC -c foo.cc -DREGISTRY -qtemplateregistry=../registry cd .. xlC -o main main.cc -qtemplateregistry=registry stack/stack.o bar/bar.o foo/foo.o
有關 XL C/C++ 中的 C++ 模板的詳細信息,請參閱 XL C/C++ for Linux Programming Guide。 運行時鏈接 運行時鏈接是在已經開始執行程序之后分析尚未定義并且還沒有延時的符號的能力。下面是用來構建名為 test 的可執行程序的 GCC 命令的順序示例,這個可執行程序擁有共享庫 libfoo.so 和 libbar.so。所有這些命令都能夠用于運行時鏈接。 gcc -c foo.c gcc -c bar.c gcc -o libfoo.so foo.o -shared gcc -o libbar.so bar.o -shared gcc -o test test.c -L. -lfoo -lbar
|
要執行 test,那么環境變量 LD_LIBRARY_PATH 必須包含 libfoo.so 和 libbar.so 所在的目錄。也可以使用選項 -Wl,-rpath ,而不用向 LD_LIBRARY_PATH 添加搜索位置。 在本例中,使用
gcc -o test test.c -L. -lfoo -lbar -Wl,-rpath=/home/app
|
其中 /home/app 是 libfoo.so 和 libbar.so 的位置。 對于 XL C/C++,必須用選項 -qmkshrobj 替代選項 -shared ,如下所示:
xlc -c foo.c xlc -c bar.c xlc -o libfoo.so foo.o -qmkshrobj xlc -o libbar.so bar.o -qmkshrobj xlc -o test test.c -L. -lfoo -lbar
|
與 XL C/C++ on AIX 不同,使用 XL C/C++ on Linux 構建啟用了運行時鏈接的可執行程序時,不需要選項 -brtl 。這是因為 XL C/C++ on Linux 使用 GNU 鏈接程序,因此,還可以在 XL C/C++ on Linux 中使用選項 -Wl,-rpath 。與 GCC 相似,要執行應用程序,必須設置環境變量 LD_LIBRARY_PATH 。 XL C/C++ 支持的 GCC 功能 對于 Linux on POWER,從 GCC 移至 XL C/C++ 通常很簡單。為了幫助執行此任務,XL C/C++ 提供了選項 -qinfo=por ,幫助篩選發出的診斷消息,從而只顯示與可移植問題有關的那些消息。另外,XL C/C++ 還支持 GNU 到 gcc 和 gcc-c++ 的一部分擴展。有關受支持的功能以及被接受的但忽略語義的那些功能的完整列表,請參閱 XL C/C++ C++ for Linux on pSeries Compiler Reference。 要與 C 代碼一起使用受支持的功能,則需要指定 -qlanglvl=extended 或 -qlanglvl=extc89 。默認情況下,C++ 中所有受支持的 GNU gcc/gcc-c++ 功能都能被接受。 如本文“版本 7 中的新功能”一節所述,gxlc 和 gxlc++ 有助于最大程度地減少對使用 GNU 編譯器構建的現有應用程序的 makefile 的更改。 可重新發布的庫 XL C/C++ 提供下列可重新發布的庫。根據應用程序,可能需要隨應用程序一起提供這些庫中的一個或多個。 libibmc++.so 僅由 C++ 程序使用。libxlsmp.so 、libxlsmp_ser.so 、libxlsmpdebug.so 當 -qsmp 或 -qsmp=omp 選項有效時,需要使用這個庫。
鏈接順序 XL C/C++ 按下列順序鏈接庫: - User .o 文件和庫
- XL C/C++ C++ for Linux 庫
- C++ 標準庫
- C 標準庫
在 XL C/C++ 的手冊中,有關于鏈接順序的詳細信息。 運行時錯誤診斷 也許能夠成功地編譯和鏈接程序,但在執行過程中卻生成意想不到的結果。這一節將描述了一些普遍錯誤、如何檢測和更正這些錯誤。 未初始化變量 對象未隱式初始化,因此其初始值不確定。如果未設置就使用 auto 變量,那么它可能每次都產生不同的結果。-qinfo=gen 指示編譯器將所有自動變量初始化為指定的值。 運行時檢查
–qcheck 的子選項指定檢查空指針、超出數組范圍的下標以及與零相除。建議只使用 –qcheck 選項進行調試,因為它會降低應用程序的運行時性能。 ANSI 別名 ANSI 別名規則表明指針只能解除對相同類型或可兼容類型的對象的引用。將指針轉換為不兼容的類型,然后解除對該類型的引用的這種通用編碼習慣違反了這條規則。設置 –qalias=noansi 可以更正程序行為。但是這樣做會減少編譯器優化應用程序的機會。建議更改程序,使之符合 ANSI 別名規則。 #pragma option_override 有時只在進行優化時才出現錯誤。這時可以關閉對已知會有特定編程錯誤的函數的優化,同時允許優化程序的其余部分。這條指令允許為特定函數指定備用優化選項。通過有選擇地關閉復雜程序中每個函數的優化,它還可以用于確定引起問題的函數。 編譯器選項 下表對 GCC 和 XL C/C++ 中常常用到的編譯器選項進行了比較: 表 7. 常常用到的編譯器選項
GCC | XL C/C++ C/C++ | 描述 | -v | -v、-V、-# | 開啟詳細模式 | -p/-profile | -p | 設置編譯器生成的對象文件進行概要分析 | n/a | -q32、-q64 或設置 OBJECT_MODE 環境變量 | 創建 32 位或 64 位對象。GCC 64 位編譯器位于 /opt/cross/bin 中 | -fsyntax-only | -qsyntaxonly | 執行語法檢查,不生成對象文件 | -fpic | -qpic=small | 生成共享庫中使用的 Position-Independent Code。在 XL C/C++ 中,Global Offset Table 的大小不超過 64 Kb。如果指定 –qpic ,而無任何子選項,則假設 -qpic=small 。如果指定了 -qmkshrobj 編譯器選項,則啟用 –qpic 選項 | -fPIC | -qpic=large | 允許 Global Offset Table 大于 64 Kb | -pthread | -qthreaded 或 _r 調用模式 | 創建在多線程環境中運行的程序 | -fno-rtti | -qnortti | 對于異常處理和 typeid 和 dynamic_cast 操作符的使用,禁止生成運行時類型 –qrtti 識別(RTTI)。在 XL C/C++ 中,默認值為 -qnortti | -static | -qstaticlink | 使用這個選項生成的對象將無法與共享庫進行鏈接 | -static-libgcc | -qstaticlink=libgcc | 指示編譯器與 libgcc 的靜態版本鏈接 | -shared | -mkshrobj Instruct | 編譯器生成共享對象 | -shared-libgcc | -qnostaticlink=libgcc | 指示編譯器與 libgcc 的共享版本鏈接 | -Wl、-rpath | -Wl、-rpath 或 –R | 傳遞用冒號分隔的目錄列表,用它來指定運行時鏈接程序搜索的目錄 | -fno-implicit-templates、-frepo | -qtempinc、-qtemplateregistry、-qtemplaterecompile | 模板實例化 | -w | -w | 取消警告消息 |
| -warn64 | 允許對長型到整型的截斷舍位(long-to-integer truncation)進行檢查 |
| -qinfo=<…> | 生成信息消息 | -fpack-struct | -qalign=bit_packed | 使用 bit_packed 排列規則 |
| -qalign=linuxppc | 使用默認 GCC 排列規則來維護與 GCC 對象的兼容性。這個值是默認值 |
|
|
| -O、-O2、-O3 | -O、-O2、-O3、-O4、-O5 | 優化級別 |
| -qarch、-qtune、-qcache | 特定處理器的優化選項 |
結束語 為了編譯使用 XL C/C++ 為 GCC 編寫的應用程序,有多種幫助促進遷移的方法。在編譯階段出現錯誤時,可以檢查應用程序使用的任何 GCC擴展,并使用前面介紹的運行時診斷技術解決運行時錯誤。另外,使用 XL C/C++ 提供的優化功能時,會提高應用程序的性能。 詞匯
- GNU Compiler Collection (GCC)開源 GNU Compiler Set,其中包括 gcc、GNU C Compiler、gcc-c++、GNU C++ 編譯器和 g77、GNU Fortran77 編譯器。
- i5 或 iSeries 運行 OS/400 和 Linux 的 IBM 集成服務器。
- Linux on POWER在 POWER 系統上運行的 Linux 操作系統。在本文中可以假設這個操作系統是指 IBM eServer pSeries(包括eServer p5);eServer iSeries(包括 eServer i5);eServer OpenPower 和 eServerBladeCenter JS20 服務器。
- OpenMPOpenMP是一種行業標準,它描述了包括 UNIX 和 Windows NT 平臺在內的所有架構中,C、C++ 和 Fortran 中的對稱多處理(SMP) 編程的 API 的通用集合。有關 XL C/C++ 如何支持 OpenMP 規范的詳細信息,請參閱 XL C/C++ for Linux Compiler Reference。
- POWER由 IBM、Motorola 和 Apple 合作生成的基于 RISC 的芯片技術?;?POWER 架構的 IBM 處理器示例包括 RS64 IV、POWER3、POWER4、POWER 970 和 POWER5。
- p5 或 pSeries運行 AIX 和/或 Linux 的 IBM 基于 UNIX 的服務器。
- Red Hat Enterprise Linux AS 3 (RHEL 3)Red Hat Enterprise Linux AS version 3。這是 Red Hat 最新的企業 Linux 產品。在本文中,RHEL 3 是指 RHEL 3 for POWER 架構。
- SUSE LINUX Enterprise Server 9(SLES 9)SUSE LINUX Enterprise Server version 9。這是 SUSE LINUX 最新的企業 Linux 產品。在本文中,SLES 9 是指 SLES 9 for POWER 架構。
感謝 作者對 Steve Dibbell、Linda Kinnunen 和 Linux Solutions Enablement 團隊的幫助不勝感謝。 參考資料 - 您可以參閱本文在 developerWorks 全球站點上的 英文原文。
- 閱讀“AIX Linking and Loading Mechanisms”,以了解鏈接和加載機制的不同方面,它們對于在 PowerPC 架構中開發 AIX 應用程序非常重要(developerWorks,2001)。
- 查看 GCC online manual。
- 閱讀“Application Development on Linux Power”,了解如何在基于 IBM POWER 的服務器上的 Linux 中開發和部署應用程序(developerWorks,2003)。
- 有關 Linux on POWER 的解決方案啟用、市場營銷和銷售軟件的其他信息,請參閱 Linux on POWER ISV Resource Center。
- 對于想了解 Power 架構的 Linux 開發人員,Linux on POWER Architecture developer’s corner 中有許多文章和參考資料。
作者簡介 ChakaratSkawratananond 是 IBM eServer Solutions Enablement 組織的一名技術顧問,在那里,他幫助 ISV在 IBM pSeries 平臺上使用他們用于 AIX 5L 和 Linux的應用程序。他擁有得克薩斯大學奧斯汀分校電子和計算機工程的博士學位。您可以通過 chakarat@us.ibm.com 與 Chakarat聯系。 | Nam Keung 是一名高級程序員,他曾致力于 AIX 通信開發、AIX多媒體、SOM/DSOM 開發和 Java 性能方面的工作。他目前的工作包括幫助 ISV 進行應用程序設計、應用程序部署、性能調整和關于IBM pSeries 平臺的教育。他從 1989 年起就是 IBM 的一名程序員。您可以通過 namkeung@us.ibm.com 與Nam 聯系。
| Calvin Sze 是 IBM eServer SolutionsEnablement 組織的一名 Linux 顧問。他在得克薩斯州的奧斯汀市工作。Calvin的主要職責是幫助解決方案開發人員將他們的應用程序引入 Linux on POWER。Calvin 致力于 Linux 和 AIX平臺上的軟件開發和系統集成已經 10 多年了。您可以通過 calvins@us.ibm.com 與 Calvin 聯系。
|
|