HPC NTCU
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Help
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
# 編譯、連結 library ## GCC預設的參數有什麼?代表什麼意思 ```bash gcc --help // 可以看到可用的參數與其解釋 ``` ### **gnu編譯過程** ![image](https://hackmd.io/_uploads/HJEjncrVa.png) ### 1. 預處理 將 include 、 macro 擴展成真正的內容,經過這一步驟後,檔案會變大許多。 使用 GCC 進行預處理的方式如下: ```bash gcc -E -I./src main.c -o main.i ``` - -E 會讓 gcc 僅對 c 程式做預處理 - -I 用來指定自定義標頭檔的優先搜尋目錄,若你定義的標頭檔與程式碼同目錄,就可以忽略該參數。 - -o 指定輸出檔案的檔名與格式 :::info ***巨集(Macro)*** 在編譯指令中宣告或是在程式碼中使用#define宣告 ``` bash // define gcc -D DEBUG -o main main.c // cancel defination gcc -U DEBUG -o main main.c ``` 可以使用巨集宣告定值、進行有條件編譯甚至是撰寫擬函式 ```c // 宣告定值 #define SIZE 10 // 撰寫擬函式 #define MAX(a, b) ((a) > (b) ? (a) : (b)) // 有條件編譯 #ifndef SOMETHING_H #define SOMETHING_H /* Declare some data types and public functions. */ #endif /* SOMETHING_H */ // 有條件編譯 #ifdef DEBUG fprintf(stderr, "Some message\n"); #endif ``` ::: ### 2. 編譯 將預處理過的程式碼編譯成組合語言,而組合語言又會因為不同的處理器架構出現差異。 使用 GCC 進行編譯的方法: ```bash gcc -S -I./src main.c -o main.s ``` - -S 僅輸出 C 程式對應的組合語言 :::info ***交叉編譯*** 假設要編譯出能在arm架構上執行的程式碼,通常因為效能和時間成本的關係不會直接在arm平台上編譯,而是可以先在x86先驗證程式碼(當然這邊是先編譯x86版本),接著再編譯出ARM(aarch64)的檔案部署到機器上整合測試 使用Toolchain內提供的交叉編譯器以及資料庫(Library),Toolchain提供了個階段的交叉編譯工具。無論你使用gcc或是Make或是CMaker,只要設定好路徑跟環境,整個交叉編譯的程序就可以直接在Host啟動 ![image](https://hackmd.io/_uploads/HkWBgJHVa.png) reference: https://allenshaing.wordpress.com/2021/08/21/cross-compiler-101/ ::: ### 3. 組譯 經過編譯後,我們會得到組合語言檔案,也就是 *.s 檔案。不過,若要讓電腦能夠執行我們的程式碼,我們仍需要將其轉換成機器碼。 ```bash gcc -c main.s -o main.o ``` - -c 僅編譯 C 程式,但不連結,即輸出對應的目標碼 ### 4. 連結 連結會將多個目標文件或是 library 連結成可執行檔。 ```bash gcc -o main main.o ``` 如果有多個機器碼最後會被連結成一個可執行檔案,也可以這麼做: ```bash gcc -o main a.o b.o c.o ``` 這樣一來,如果開發者更動了其中一個檔案,我們只需對有更動的檔案進行編譯再連結起來。可以大幅節省編譯的時間。 :::info **static linking** 靜態函式庫(static library)就是由一些物件檔案(object files)所構成的封裝檔,通常其檔案名稱都會以 lib 開頭,而副檔名則為 .a。 使用靜態連結函式庫的好處就是所有的程式都包裝在執行檔中,不會因為缺少函式庫的檔案而不能執行,不過缺點就是這樣的執行檔大小會比較大,而如果函式庫有更新的話,整個執行檔也要跟著重新編譯。 ```bash! gcc -o main main.c sum.c // static linking gcc -c -o sum.o sum.c ar -rcs libsum.a sum.o // linking 第一種寫法 gcc main.c -L. -lsum -o main_static // linking 第二種寫法 gcc -o main_static main.c libsum.a ``` ::: :::success **ar指令參數** - r => 把參數中所有的檔案插入 library 檔案中,若該檔案已存在於 library 中,覆蓋掉原本的內容 - c => 新增一個 library 檔案 - s => 在 library 中寫入 object file 的 index ::: :::info **shared library** 共享函式庫(shared library)是在程式實際開始執行時,才會被載入的函式庫,執行檔本身與共享函式庫是分離的,這樣可以讓執行檔的大小比較小,而且未來共享函式庫在更新之後,執行檔也不需要重新編譯,而缺點則是執行檔在執行時就會需要共享函式庫的檔案,如果缺少了共享函式庫的檔案,就會無法執行。 ```bash! gcc -shared -o libsum.so sum.o gcc -o main_dynamic main.c libsum.so LD_LIBRARY_PATH= . ./main_dynamic // LD_LIBRARY_PATH代表環境變數的設置 // '.'代表目前所在位置 ``` **底下以openssl為例子:** 使用shared library ![image](https://hackmd.io/_uploads/ryiEhoSVp.png) 使用static library ![image](https://hackmd.io/_uploads/SkQtToHE6.png) ```bash! du -sh openssl // 1.2M openssl => shared library // 7.5M openssl => static library ``` ::: :::info ***GNU Debugger*** 使用GDB進行除錯 ```bash gcc -Wall -g main main.c ``` - -Wall: 顯示所有警告信息 - -g: 使gcc要盡可能告知資訊給GDB幫助除錯 ::: ## 理解C++有不同標準版本:C++11, C++14, C++17, C++20。 - GCC如何指定不同版本?(不同版本可能在參數上不一樣) ```bash gcc -std=c11 -o main main.c ``` - 使用library前先閱讀最低版本需求,否則可能編譯失敗 ## GCC有哪些效能優化的參數,如果編譯指令有多個參數,會依照哪一個為準? :::warning 如果使用多個級別的優化選項,會以最後一個為準。 ::: ### **程式最佳化** **-O1** => 編譯器會在不做任何將編譯時間拉很長的優化的前提下,降低程式碼的大小與執行時間 -fdefer-pop -fmerge-constants -fthread-jumps -fif-conversion -fif-conversion2 -fdelayed-branch -fguess-branch-probability -fcprop-registers **-O2** => 不會做loop unrolling 或是 function inlining,並且相對於O1而言,增加了編譯的時間與生成出的組合語言的效能。 -fforce-mem -foptimize-sibling-calls -fstrength-reduce -fcse-follow-jumps -fcse-skip-blocks -frerun-cse-after-loop -frerun-loop-opt -fgcse -fgcse-lm -fgcse-sm -fgcse-las -fdelete-null-pointer-checks -fexpensive-optimizations -fregmove -fschedule-insns -fschedule-insns2 -fsched-interblock -fsched-spec -fcaller-saves -fpeephole2 -freorder-blocks -freorder-functions -fstrict-aliasing -funit-at-a-time -falign-functions -falign-jumps -falign-loops -falign-labels -fcrossjumping :::info ***loop unrolling: 一種犧牲程式的大小來加快程式執行速度的最佳化方法*** - 優點 - branch prediction的失敗次數減少。 - 如果循環結構內語句沒有data dependency,增加了平行執行的機會。 - 缺點 - 程式碼膨脹。 - 循環結構內若包含遞迴可能會降低循環展開的效益。 ```c for (i = 1; i <= 60; i++) a[i] = a[i] * b + c; ``` ```c for (i = 1; i <= 58; i+=3) { a[i] = a[i] * b + c; a[i+1] = a[i+1] * b + c; a[i+2] = a[i+2] * b + c; } ``` ::: :::info ***inline function*** 一般而言,當我們撰寫函數,並呼叫使用,電腦的機器語言指令會紀錄目前工作階段的記憶體位址,然後跳至函數的記憶體位置處理完程序後,並回到原先的位址上,而這樣來回會造成時間上的額外負擔。若開啟function inlining的功能,編譯時便會把函數中的程式直接展開。 ```c int pred(int x) { if (x == 0) return 0; else return x - 1; } ``` Before inlining: ```c int func(int y) { return pred(y) + pred(0) + pred(y+1); } ``` After inlining: ```c int func(int y) { int tmp; if (y == 0) tmp = 0; else tmp = y - 1; /* (1) */ if (0 == 0) tmp += 0; else tmp += 0 - 1; /* (2) */ if (y+1 == 0) tmp += 0; else tmp += (y + 1) - 1; /* (3) */ return tmp; } ``` ::: **-O3** => 相對於O2而言,增加了以下優化的選項 -finline-functions -fweb -frename-registesr -funswitch-loops reference: [1]https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Optimize-Options.html#Optimize-Options [2]https://en.wikipedia.org/wiki/Loop_unrolling [3]https://en.wikipedia.org/wiki/Inline_expansion ## 什麼是glibc?他和musl libc有什麼差別? glibc為GNU C Library,glibc於設計上有諸多不足之處,例如全靜態連結因NSS機制而有狀況、內部機制甚多而難以維護/移植、組語太多、pthread實做有bug......,因此Rich Felker重新設計出一個新的C Library - musl。 musl 被設計為更輕量級和高效的函式庫,特別適用於資源受限的環境,如嵌入式系統。musl傾向於嚴格遵循POSIX標準,這可能使得使用musl編譯的程式更容易在不同系統上實現二進制文件的可移植性。並且使用shared library的時候不支援lazy binding。 :::info **二進位可移植性** 將保證任何程式在符合標準的給定硬體平台上一旦編譯通過,可以在符合同樣標準的任何其他硬體平台上以編譯後的形式執行。 **lazy binding** 在library call 真正被呼叫時再去載入。 ::: reference: https://wiki.musl-libc.org/functional-differences-from-glibc.html#:~:text=glibc%20allows%20the%20usage%20of,in%20the%20regular%20symbol%20tables. ## 什麼CXXABI?他與GCC及glibc的版本有什麼關係? - Application Binary Interface(ABI) 當c語言程式碼編譯成組合語言後,透過ABI將組合語言轉換成機器語言 - CXXABI為c++的ABI,不同版本的GNU C Library支援不同的CXXABI - gcc -> glibc(GNU C Library) -> ABI ```bash! // 先找尋目前正在使用的GNU C Library版本 ll /usr/lib/x86_64-linux-gnu/libstdc* ``` ![截圖 2023-11-20 上午10.34.09](https://hackmd.io/_uploads/HkiarHuNT.png) ```bash! // 找可以支援的CXXABI strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6|grep CXXABI ``` ![image](https://hackmd.io/_uploads/ByCkIBd4p.png) :::warning 若出現 Error: /lib/libstdc++.so.6: version 'CXXABI_1.3.8' not found 類似的錯誤碼,可以考慮更換GNU C Library的版本,並使用ln指令更換新的連結 ::: reference: https://www.xdull.cn/cxxabi.html ## 一個Linux作業系統裡面可能有好幾個stdio.h,我該如何確認GCC會引用哪個stdio.h ![image](https://hackmd.io/_uploads/ByFXx8uNT.png) ```bash! gcc -H -c your_source.c ``` - -H => 顯示在編譯過程中每個header file的搜索路徑 ![image](https://hackmd.io/_uploads/Syk8gU_ET.png) ## 如果編譯過程中出現undefined reference該怎麼辦 1. 確定引用函數時的格式是否錯誤,或是該函數屬於的標頭檔是否有引入 2. 確定library是否有被正確連接上並檢查版本相容性 - 如果你在使用外部的library,確保被正確連接到編譯過程中,需要使用 -l 選項指定庫的名稱,並且 -L 選項指定庫的搜索路徑。 ```bash! // 這裡 -lmylibrary 指定了要使用的library,而 -L/path/to/library 指定了library的路徑。 gcc -o myprogram myprogram.c -lmylibrary -L/path/to/library ``` 3. 確定include file的路徑正確 - 如果你在標頭檔中聲明了某個函數或變數,確保其路徑正確。你可以使用 -I 選項指定標頭檔的路徑。 ```bash! gcc -o myprogram myprogram.c -I/path/to/headers ``` 4. 檢查編譯器和library的相容性: - 確保你使用的編譯器和library是相容的,有時不同版本的編譯器或library之間可能存在不同的ABI。 ## 如果我確定已經安裝某個library,但仍然編譯失敗,出現undefined reference,有哪些方法可以讓GCC找到我安裝的library 1. 檢查環境變數 LD_LIBRARY_PATH: 確保環境變數 LD_LIBRARY_PATH 包含了庫文件的搜索路徑。這個環境變數告訴運行時連接器(runtime linker)在哪裡找shared library。 ```bash! export LD_LIBRARY_PATH=/path/to/library:$LD_LIBRARY_PATH gcc -o myprogram myprogram.c -lmylibrary -L/path/to/library -Wl,-rpath=/path/to/library ``` ## 如果編譯過程中出現no such file "ooxx.h"該怎麼辦 1. 確認標頭檔的位置與權限: 2. 指定正確的標頭檔路徑 - 確定include file的路徑正確 - 如果你在標頭檔中聲明了某個函數或變數,確保其路徑正確。你可以使用 -I 選項指定標頭檔的路徑。 ```bash! gcc -o myprogram myprogram.c -I /path/to/headers ``` ## 使用apt或yum安裝library和我自己下載原始碼編譯有什麼不同 1. 安裝/卸載: 通過一條命令安裝套件及其相依項目,省去額外的步驟,包括解壓縮、配置、編譯、安裝與一些相依性問題。在卸載時也解決相依性的問題同時保持系統的整潔。 2. 版本管理: 不僅可以解決不同套件之間版本衝突的問題,通過一條指令可以將套件升級或退回到特定版本。 3. 系統整合: 安裝的套件其文件放置在系統預定的目錄中,並且可以被其他系統工具發現。

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully