\ 跳到主要內容

Compile behind-the-scene

習慣使用了具備強大功能的整合工具-- IDE(e.g Visual Studio),執行source code(e.g .cpp)僅需點下  建置(Build)  然後  ▷ ,有時是只點下  ▷  ,就完成了許多希望程式去做的事,很方便,但也因此缺乏對於幕後工程的認識。離開了IDE,使用terminal則可以透過下面的指令完成同樣的事情:

$ g++ main.cpp -o main.out #編譯
$ ./main.out #執行
helloworld

編譯透過以上一行簡單的指令,將我們寫的source code編譯成執行檔(在Linux上是.out,在Windows上則是.exe),然後可以直接被電腦執行。簡單的一句指令,過程則可以分為四個步驟,分別是1. 前編譯Preprocessing, 2. 編譯compilation, 3. 組譯assembly 以及 4. 連結linking。

GCC編譯過程分解


以下用一支比helloworld更簡單的程式來呈現:

  • main.cpp

#define N 81
int main(){
        return 0;//this is the end
}


1. Preprocessing: .cpp -> .ii,處理#,刪除註解(//, /**/),加以編號。

$ g++ -E main.cpp -o main.ii
  • main.ii:
# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"
int main(){
 return 0;
}


2. Compilation: .ii -> .s,將 .ii檔進行分析以及最佳化,將高階語言翻譯成assembly code。屬於程式建構過程最複雜的環節。

  • main.s

$ g++ -S main.ii -o main.s
        .file   "main.cpp"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
        .section        .note.GNU-stack,"",@progbits
        .section        .note.gnu.property,"a"
        .align 8
        .long    1f - 0f
        .long    4f - 1f
        .long    5
0:
        .string  "GNU"
1:
        .align 8
        .long    0xc0000002
        .long    3f - 2f
2:
        .long    0x3
3:
        .align 8
4:


3. Assembly: .s -> .o,將assembly code一一翻譯成machine code。

$ g++ -c main.s -o main.o 
^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^A^@>^@^A^@^@
^@^@^@^@^@^@^@^@^@^@X^B^@^@^@^@^@^@^@^@^@^
@@^@^@^@^@^@@^@^L^@^K^@ó^O^^úUH<89>å¸^@^@^
@^@]Ã^@GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1)
9.4.0^@^@^@^@^@^@^D^@^......


4. Linking: .o + static library -> .out,將.o檔連結static library(一大堆.o檔)形成.out檔。

$ ld -static (一大堆.o檔) 
^?ELF^B^A^A^@^@^@^@^C^@>^@^A^@^@^@À^P^@^@^
^@^@@^@^@^@^@^@^@^@è;^@^@^@^@^@^@^@^@^@^@@
^@8^@^M^@@^@^_^@^^^@^F^@^@^@^D^@^@^@@^@^@^
@^@^@^@^@@^@^@^@^@^@^@^@@^......

Reference: <<程式設計師的自我修養>>

留言

這個網誌中的熱門文章

Command Line 與 Makefile

在認識到Linux以前,我鮮少接觸到CLI(Command Line Interface),也花了些許時間去熟悉。一開始看它也許會感到有些震懾,但並沒有想像中的複雜,單純是將我們習慣使用的GUI(Graphical User Interface)改成CLI,滑鼠改成鍵盤,簡單做了轉換。 sudo apt-get install qt6-default //以superuser身份安裝qt6-default mkdir build/install -p //新增資料夾 cd build/install //切換目錄到build/install rm –rf build //remove文件, recursively. makefile make 以及 makefile讓我們得以自動化我們想執行的command line。比如說modmesh裡面中clean這個target,若是藉由一行一行的command line我們會需要輸入以下的指令, rm -f $(MODMESH_ROOT)/modmesh/_modmesh$(pyextsuffix) make -C $(BUILD_PATH) clean 但如果已經在Makefile中寫好了clean這個target,將一行行的command line寫成了shell script。 .PHONY: clean clean: rm -f $(MODMESH_ROOT)/modmesh/_modmesh$(pyextsuffix) make -C $(BUILD_PATH) clean 我們就可以去藉由make,直接輸入 make clean 去執行我們想要去執行的內容,不用逐步命令。 make clean

Python importation

In a well-organized C++ code base, the hpp files should always be included using the full path like: #include <modmesh/base.hpp> #include <modmesh/profile.hpp> #include <modmesh/buffer/buffer.hpp> Python import 的module 並不必然要用python撰寫,也可以藉由C++。然而我誤解了這番話的意思,進而混用了 header files 與 modules,以為以下的實驗會成功: import importation #succeed import layer1.importation #succeed import header #failed 以下是python importation 整理過後的資訊: 1. import modmesh 以 modmesh 作為例子 , import modmesh 我原先同樣是誤會 modmesh.hpp 才是被 python import的對象;但這個對象其實是library(or python package):$(MODMESH_ROOT)/modmesh。如果它已經被 built, 那麼目錄裡頭就會有 __init__.py 以及 .so 。 2. python importation python importation 的機制在於編輯 sys.path. e,g  del sys.path[0] sys.path儲存的是尋找python module的路徑。在這個動作之後,原先若是被import的對象被列在sys.path[0]所儲存的路徑之下,那麼import就會失敗。 3. Module written in C++ 如前所述,Python import 的module 並不必然要用python撰寫,e.g. C++, 它們是透過 import shared library(.so)來被python支援。 C++ and python 的連結可透過 swig, cython, pybind11 等等。在modmesh 中則是使用 py...