1. 程式人生 > >命令列編譯C++(Linux下、Windows下)

命令列編譯C++(Linux下、Windows下)

C++ 編譯過程

  一般而言,對於 C++ 程式編譯有以下4個階段:

  • 預處理(preprocessing)
    對源程式中的偽指令(以#開頭的指令)和特殊符號進行處理。偽指令包括巨集定義、條件編譯指令、標頭檔案包含指令等。
  • 編譯(compilation)
    將預處理後的檔案編譯生成字尾為 .s 的組合語言檔案,。編譯程式所要做的工作是通過記法分析和語法分析,在確認所有指令都符合語法規則後,將其翻譯成等價的中間程式碼或彙編程式碼。
  • 彙編(assembly)
    將彙編檔案彙編生成字尾為 .o 的目標檔案(二進位制)。彙編過程實際上是指把組合語言程式碼翻譯成目標機器指令的過程。
  • 連結(linking)
    將多個目標檔案和庫連線生成字尾為 .out 或 .exe 的可執行檔案。連結程式的主要工作就是將有關的目標檔案彼此相連線,即將在一個檔案中引用的符號現該符號在另外一個檔案中的定義連線起來,使得所有的這些目標檔案成為一個能夠被作業系統裝入執行的統一整體。
    連結處理分為兩種:
    • 靜態連結(static linking)
      簡單說,指連結器在連結時將庫(靜態庫)的內容拷貝到可執行程式中。
    • 動態連結(dynamic linking)
      簡單說,指程式執行時才將庫(動態連結庫)連線到程式中。

Linux系統

參考《An Introduction to GCC》

使用gcc(GNU編譯器套件)

  gcc 最開始的時候是 GNU C Compiler,就是一個 c 編譯器。但是後來因為這個專案裡邊集成了更多其他不同語言的編譯器, GCC 就代表 the GNU Compiler Collection,所以表示一堆編譯器的合集。g++ 則是GCC的 c++ 編譯器。
  現在呼叫 gcc 的時候,已經不是當初那個 c 語言編譯器了,更確切地說它是一個驅動程式,根據程式碼的字尾名來判斷呼叫 c 編譯器還是 c++ 編譯器(g++)。即程式碼字尾是 .c,則呼叫 c 編譯器和 linker 去連結 c 的 library,程式碼字尾是 .cpp,則呼叫 g++ 編譯器,但是這裡 gcc 不會自動

和 c++ 庫連結。

  • 基本引數
      shell 視窗中執行 gcc –help 列出基本引數:

    $ gcc --help
    
    # 省略一部分輸出
    
    -E                       Preprocess only; do not compile, assemble or link
    -S                       Compile only; do not assemble or link
    -c                       Compile and assemble, but do not link
    -o <file>                Place
    the output into <file>
    # 省略一部分輸出
  • $ cd ~/design-pattern/factory/
    $ ls
    Factory.cpp  Factory.h  main.cpp  Product.cpp  Product.h
    • 編譯
      如上所述,gcc 不會自動和 c++ 庫連結,所以這裡只編譯,否則會有一堆連結錯誤

      $ gcc *.cpp -c
      $ ls # 可以看到編譯生成 *.o 物件檔案(二進位制)
      Factory.cpp  Factory.o  main.o       Product.h
      Factory.h    main.cpp   Product.cpp  Product.o
    • 連結

      • 上面強調 gcc 不會自動連結 c++ 庫,這裡我們可以手動連結 c++ 庫
      $ gcc *.o -lstdc++
      $ ls
      a.out        Factory.h  main.cpp  Product.cpp  Product.o
      Factory.cpp  Factory.o  main.o    Product.h
      $ ./a.out
      Concrete Facotry
      Concrete Product...
      • 因 gcc 不會自動連結 c++ 庫,所以可直接用 g++ 連結 .o 檔案生成 .out 可執行檔案
      $ g++ *.o
      $ ls
      a.out        Factory.h  main.cpp  Product.cpp  Product.o
      Factory.cpp  Factory.o  main.o    Product.h
      $ ./a.out
      Concrete Facotry
      Concrete Product...
    • 綜上,可直接使用 g++ 編譯連結 c++ 程式生成可執行檔案

      $ g++ *.cpp
      $ ls
      a.out  Factory.cpp  Factory.h  main.cpp  Product.cpp  Product.h
      $ ./a.out
      Concrete Facotry
      Concrete Product...

include 包含檔案搜尋路徑

  include 包含檔案在編譯的時候使用,GCC 搜尋標頭檔案路徑的順序:

  1. 當前目錄(#include “” 方式會搜尋當前目錄,#include <> 方式不會搜尋當前目錄
  2. -I 選項指定的目錄
  3. gcc 環境變數 CPLUS_INCLUDE_PATH 指示的目錄(c 程式使用的是 C_INCLUDE_PATH
  4. gcc 的預設目錄

    /usr/local/include
    /usr/include
    /usr/lib/x86_64-linux-gnu/5.4.0/include

    gcc 的預設目錄,不是由 $PATH 環境變數指定的,而是由 g++ 的配置 prefix 指定。

lib 庫檔案搜尋路徑

  連結的時候使用,搜尋順序:

  • 靜態庫檔案

    1. -L 選項指定的路徑
    2. gcc 的環境變數 LIBRARY_PATH
    3. gcc 的預設目錄
    /lib
    /usr/local/lib
    /usr/lib
  • 動態庫檔案
    1. 編譯程式碼時指定的路徑(gcc 的引數 -Wl, -rpath 指定)
    2. 環境變數 LD_LIBRARY_PATH 指定的路徑(多個路徑用冒號 : 分隔)
    3. 配置檔案 /etc/ld.so.conf 指定的路徑
    4. 預設的動態庫路徑 /lib,/usr/lib

-I(大寫的i)、 -include、 -L、 -l(小寫的L) 引數說明

  • -I 擴充套件 gcc 在編譯時對包含檔案的搜尋路徑,即不使用 -I 引數時,只會在上述預設路徑下搜尋。

    $ cd ~/design-pattern/factory/
    $ ls
    Factory.cpp  Factory.h  main.cpp  Product.cpp  Product.h
    $ mv *.h ../
    $ gcc -c -I ../ *.cpp
    $ ls
    Factory.cpp  Factory.o  main.cpp  main.o  Product.cpp  Product.o
    $ gcc
  • -include 指定包含標頭檔案,很少用,因為一般標頭檔案都在原始碼中用 #include xxx實現了。
  • -L 擴充套件 gcc 在連結時對庫檔案的搜尋路徑,即不使用 -L 引數時,只會在上述預設路徑下搜尋。

    $ gcc *.cpp -I ../ -L /usr/lib/gcc/x86_64-linux-gnu/5.4.0 -lstdc++
    
    # or
    
    $ g++ *.cpp -I ../ -L /usr/lib/gcc/x86_64-linux-gnu/5.4.0
    $ ./a.out
    Concrete Facotry
    Concrete Product...
  • -l 緊接庫名,指定程式要連結的庫。
    這裡注意庫名庫檔名的區別,以檔案 ./usr/lib/gcc/x86_64-linux-gnu/5/libstdc++.so 為例,libstdc++.so 為庫檔名,而庫名則是 stdc++。如

    $ gcc *.cpp -I ../ -lstdc++
    $ ls
    a.out  Factory.cpp  Factory.o  main.cpp  main.o  Product.cpp  Product.o
    $ ./a.out
    Concrete Facotry
    Concrete Product...

-shared 引數說明

  用於編譯生成動態庫。

Windows系統

  cl.exe 和 link.exe 分別是 visual studio IDE 中的編譯器和連結器。

使用cl.exe編譯器

  • 用法

    usage: cl [ option... ] filename... [ /link linkoption... ]
  • 基本引數

    • -I: 指定第一個尋找標頭檔案的目錄(如果指定多個目錄,則使用多個-I)
    • -c: 只編譯不連結
    • -EHsc: 指示編譯器啟用 C++ 異常處理
  • 例:

  Windows下命令中使用路徑時,注意特殊字元要使用轉義字元”\”,如下路徑中包含\,空格和括號,前面均加轉義符”\”,或者將路徑用引號括起來。
  gitbash視窗:

    $ cl *.cpp -c -EHsc -I C:\\Program\ Files\ \(x86\)\\Microsoft\ Visual\ Studio\ 14.0\\VC\\include -I C:\\Program\ Files\ \(x86\)\\Windows\ Kits\\10\\Include\\10.0.10240.0\\ucrt
    # or
    $ cl *.cpp -c -EHsc -I "C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt" -I "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include"

使用link.exe連結器

  • 用法
usage: LINK [options] [files] [@commandfile]
  • 基本引數(以下引數在windows cmd視窗中執行有效,在bash中不過)
    • /LIBPATH: 指定要在環境庫路徑之前搜尋的路徑
    • /OUT: 指定輸出檔名
  • 例:

  windows cmd 視窗(bash下測試不過):

$ link *.obj /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib" /LIBPATH:"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib" /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86" /OUT:fac.exe

編譯器控制的LINK選項

  除非指定 -c 選項,否則 cl.exe 會自動呼叫 link.exe 。以下為 cl 中影響連結的常用功能(注意當引數有指定輸出檔案時,要帶冒號:):

  • /Fo: filename: 指定生成的 .obj 檔名
  • /Fe: filename: 傳遞 /OUT:filename 給 link.exe, 指定生成的 .exe 檔名

環境變數

  CL 和 LINK 用到的環境變數有:

  • cl.exe
    • INCLUDE: 指示 C/C++ 原始檔中使用 #include 包含的檔案,如標頭檔案等。標準 C/C++ 開發,會使用 Visual C++ 的安裝路徑下 vc\include 子目錄中的包含檔案, Windows API 開發,會使用Platform SDK 的安裝路徑下 vc\include 子目錄中的包含檔案。
    • LIBPATH: 指定用於搜尋使用 #using 引用的元資料檔案的目錄。
  • link.exe
    • LIB: 指定搜尋物件、庫或其他檔案的路徑。標準 C/C++ 開發,會使用 Visual C++ 的安裝路徑下 vc\lib 子目錄中的包含檔案, Windows API 開發,會使用Platform SDK 的安裝路徑下 vc\lib 子目錄中的包含檔案link.exe會從如下路徑搜尋物件檔案和庫檔案:
      • 當前路徑
      • 命令列上由 /BASE 指定的路徑
      • 使用 LIB環境變數中的路徑。
    • TMP: 連結時尋找 OMF 或 .res 檔案時,會從這個路徑中尋找。

我本機的系統環境變數設定指令碼

echo off

setx -m WIN_KIT "C:\Program Files (x86)\Windows Kits"
setx -m WIN_SDK "C:\Program Files (x86)\Microsoft SDKs"
setx -m VS_INSTALL_DIR "C:\Program Files (x86)\Microsoft Visual Studio 14.0"
setx -m Microsoft_SDK "C:\Program Files (x86)\Microsoft SDKs"

setx -m PATH "%VS_INSTALL_DIR%\VC\bin;%PATH%"

rem INCLUDE
rem -------
setx -m INCLUDE "%VS_INSTALL_DIR%\VC\INCLUDE;%VS_INSTALL_DIR%\VC\ATLMFC\INCLUDE;%WIN_KIT%\10\Include\10.0.10240.0\ucrt"

rem LIB
rem ---
setx -m LIB "%VS_INSTALL_DIR%\VC\lib;%VS_INSTALL_DIR%\VC\ATLMFC\LIB;%Microsoft_SDK%\Windows\v7.1A\Lib;%WIN_KIT%\10\Lib\10.0.10240.0\ucrt\x86;%WIN_KIT%\10\Lib\10.0.10240.0\ucrt\x64"

rem LIBPATH
rem -------
setx -m LIBPATH "%VS_INSTALL_DIR%\VC\lib;%VS_INSTALL_DIR%\VC\ATLMFC\LIB;%WIN_KIT%\10\Lib\10.0.10240.0\ucrt\x86;%Microsoft_SDK%\10\Lib\10.0.10240.0\ucrt\x86"

pause

使用 CL 生成可執行檔案

  環境變數設定好後,即可通過 cl 在命令列一步生成 C++ 的可執行檔案,例

$ cd /e/program/designPattern/Factory/Factory

$ ls *.cpp
Factory.cpp  main.cpp  Product.cpp

$ cl *.cpp -EHcs -Fe: fac
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

Factory.cpp
main.cpp
Product.cpp
Generating Code...
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:fac.exe
Factory.obj
main.obj
Product.obj

$ ls *.cpp *.obj *.exe
fac.exe*  Factory.cpp  Factory.obj  main.cpp  main.obj  Product.cpp  Product.obj

$ ./fac.exe
Concrete Facotry
Concrete Product...

相關推薦

命令編譯C++LinuxWindows

C++ 編譯過程   一般而言,對於 C++ 程式編譯有以下4個階段: 預處理(preprocessing) 對源程式中的偽指令(以#開頭的指令)和特殊符號進行處理。偽指令包括巨集定義、條件編譯指令、標頭檔案包含指令等。 編譯(compilation)

Windows 使用命令編譯C/C++檔案

對於一些比較小的測試程式來說,使用IDE編譯太費時間,這篇部落格簡單介紹一下如何在安裝了Visual Studio系列的Windows上使用原生的編譯工具來編譯C/C++。 Visual Studio自帶的用於編譯C/C++的工具是cl.exe,連結目標檔案使用link.e

Windows命令編譯C++程式

命令列編譯程式程式碼,因為編譯效率高、不用去研究開發工具,可以使初學者集中精力在程式碼理解上,因此(命令列+文字編輯器【推薦EditPlus】)非常適合程式設計學習。但往往由於命令列沒有像Visual Studio那麼友好的UI介面,加上需要記憶一堆引數,因而讓很多沒有人指

帶你玩轉Visual Studio——命令編譯C/C++程式

VS構建工具介紹 我們都知道C/C++原始碼要生成可執行的.exe程式,需要經過編譯、連結的過程。你在VS工具中只需要選擇選單Build或按一下F5可以編譯、連結、運行了,其實IDE幫我隱藏了好多的具體細節。 我先假設VS2010安裝在以下目錄中:

Hive命令常用操作資料庫操作,表操作

資料庫操作 檢視所有的資料庫 hive> show databases ; 使用資料庫default hive> use default; 檢視資料庫資訊 hive > describe data

實用VLC命令串流UDP到MMS,RTSP,HTTP

1.UDP-->MMS  vlc -vvv udp://@:9001 :sout=#std{acess=mms,mux=asfh,dst=:8080} (埠隨便改) 播放 mms://192.168.251.142:8080 2.UDP-->RTSP  vlc

修改雙系統Linux系統和Windows系統的啟動順序和等待時間

在安裝Linux和Windows雙系統的時候,往往需要先安裝Windows再安裝Linux。這是因為,Linux系統能夠識別Window系統,而Windows系統無法識別Linux系統。如果先安裝Linux系統,再安裝Windows系統,那麼後者的啟動程式就會覆蓋掉前者的啟

linux——命令建立c程式並編譯

gcc表示翻譯官、翻譯組織一、用命令列建c檔案1、vi 檔名.檔案格式   eg: vi a.c 回車//建立c檔案2.儲存退出(ESC,:wq)寫完內容後,按“ESC”,然後“:”,輸入“wq”儲存退出3、開啟檔案(gedit 檔名.檔案格式)gedit a.c  //進入

C++筆記】Windows通過命令編譯執行c程式 轉載

1.準備 一臺具備c開發環境的Windows。 驗證方式,命令列輸入gcc -v,檢視是否輸出版本資訊。 gcc -v 1 2.寫程式 在E盤建一個資料夾C,在裡面建立一個Hello.c檔案,副檔名是c,內容如下: #include <stdio.h>

linux 命令編譯打包war 包

--src --WebContent rm -rf build/* mkdir build/WEB-INF mkdir build/WEB-INF/classes find src -name *.java >javaFiles.txt javac -d buil

ubuntu使用javajavac命令編譯工程

一、java和javac命令列 (1)javac命令列 javac.exe用於編譯java原始檔,生成.class檔案 語法:javac  [option]  source 常用的[option]選項: A、-classpath  <路徑>(-cp縮寫):指定要

Linux命令編譯執行C/C++檔案

gcc是常用的Linux系統下的編譯工具,針對C/C++ 程式,首先將C檔案連結為目的碼x-object,即.o檔案,然後編譯成可執行檔案x-executable。 針對編寫好的C/C++檔案:test.c, 具體示例如下: $gcc -o test tes

ubuntu16.04使用命令編譯執行C++

使用vim或sublime編寫測試cpp檔案test.cpp例:#include<iostream> using namespace std; int main() { int a; cin>>a; cout<<a+

linux命令編譯 java的eclipse專案

由於jdk的版本問題導致在windows上編譯打包好的jar包放在linux伺服器上執行的時候出現一點小異常,所以決定在linux上進行一次專案編譯,這有兩個選擇 1.在相同的linux環境下安裝linux版的eclipse 進行編譯 2.在linux用javac命令列進行編譯 3.用maven,ant等專案

ubuntudlib編譯C++共享庫及使用,即cmake編譯dlib開原始檔的步驟和檔案結構,

一、cmake的工作機制         使用CMake很簡單。 構建過程是通過建立一個或多個CMakeLists檔案(實際上是CMakeLists.txt,但本指南將在大多數情況下脫離擴充套件)控制在專案的每個目錄中。

命令執行C++程式帶來的思考C++學習筆記 26

我的電腦是Win10 x64位,裝有編譯程式的軟體有CodeBlocks和Dev-C++。 我想用windows的cmd命令列來帶引數地進行編譯C++程式碼。但是網上說下載MinGw,但這個MinGw是幹什麼用的? 首先了解以下概念: IDE: 整合開發環境(IDE,Integr

Mac OS X 命令編譯錯誤: ld: library not found for -lcrt1.10.6.o

在 Mac OS X 的 10.8.3 的版本中,使用命令列執行 configure 時,生成下面的錯誤: WenBi-MacBook:tcpdump-4.4.0 wenbi$ ./configure checking build system type... x86

NDK環境變數的配置以及編譯方法linux環境

1、下載NDK 2 、配置NDK的環境變數 a 、sudo gedit .bashrc (這裡的bashrc檔案在不同電腦下所在的路徑不同) b 、export PATH=$PATH:/work/

使用javac命令編譯一個目錄的所有.java檔案?

使用javac命令列如何編譯一個目錄下的所有.java檔案? 參考這裡 使用javac -sourcepath src *.java不行!使用javac -sourcepath src src*.java可以!!! 總結一下! 方法一、進入原始檔夾進行編

windows用gcc命令編譯並執行oc程式

首先,我的GNUstep安裝在D盤的GNUstep資料夾下,oc程式放在E盤的oc資料夾下,這裡以程式WordLength.c為例說明。 編譯oc程式: 開啟dos,然後將路徑定位到E盤的oc路徑下 命令列的寫法:E:         &nbs