makefile第1 篇 gcc

makefile 篇 gcc

https://github.com/wrzfeijianshen/Courseware

課件在Courseware/csdn/裏面

makefile 是一個命令工具,可以自動化編譯,一般命名爲makefile或者Makefile.

現在咱針對c/c++語言進行對makefile的學習和認知

gcc 工作流程是編譯c和c++的基礎,有必要學習如何生成.o,可執行程序,以及靜態庫和動態庫,以及相關的知識等.

準備環境

  • ubuntu16.04 或其他linux系統
  • vscode

https://blog.csdn.net/wrzfeijianshen/article/details/102657549

重點: 顯示當前的tab 格式符號

“editor.insertSpaces”:false
“editor.detectIndentation”: false,
“editor.renderControlCharacters”: true,
“editor.renderWhitespace”: “all”,

遠程修改文件用 remote-ssh

gcc 工作流程

將.c編譯生成可執行程序.

hello.c -->預處理階段(gcc -E) 比如去掉註釋,頭文件展開,宏替換等 --> 彙編文件hello.s–>gcc -c 彙編器–>hello.o 二進制文件–>鏈接器 ld --> a.out

這樣一步步的進行生成,這隻有一個hello.c文件,通過生成.o文件,最終gcc 生成可執行程序

gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.s
gcc -c hello.s -o hello.o
gcc hello.o -o hello
- 01/01_01 :
源文件 hello.c
#include "stdio.h"
#define VERSION "1.0"
int main()
{
	// 打印輸出
	printf("hello %s ...\n",VERSION);
	return 0;
}

file 可執行程序名 查看當前程序是64位還是32等信息

ldd 可執行程序名,查看當前依賴哪些庫名

root@fjs:~/code/fjs/makefile/01/01_1# file hello
hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=9f25f325f85140831606a9f6eab2f0bde3711e3b, not stripped
root@fjs:~/code/fjs/makefile/01/01_1# ldd hello
        linux-vdso.so.1 (0x00007ffeac3c6000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3951941000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3951f34000)

gcc 常用參數
gcc -c 只編譯生成.o文件,稱爲目標文件
gcc -o 生成的目標文件的名字
gcc -I 指定頭文件路徑
gcc -L 指定庫文件所在的路徑
gcc -l 指定庫的名字
gcc -g 調試信息 debug
gcc -M 查看當前依賴哪些頭文件(系統頭文件)
gcc -MM 查看當前依賴哪些本地文件,不包含系統頭文件

hello.o依賴  hello.c 和stdio.h 等等

root@fjs:~/code/fjs/makefile/01/01_1# gcc -M hello.c
hello.o: hello.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
 /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/bits/long-double.h \
 /...
hello.c 僅僅依賴hello.c文件

root@fjs:~/code/fjs/makefile/01/01_1# gcc -MM hello.c
hello.o: hello.c
- 01/01_02
把宏名移動到.h頭文件中,gcc hello.c 自動會生成a.out可執行程序.

root@fjs:~/code/fjs/makefile/01/01_2# gcc hello.c
root@fjs:~/code/fjs/makefile/01/01_2# ls
a.out  hello.c  hello.h
root@fjs:~/code/fjs/makefile/01/01_2# ./a.out 
hello 1.0 ...


hello.c 依賴 hello.c hello.h 這兩個文件

root@fjs:~/code/fjs/makefile/01/01_2# gcc -MM hello.c
hello.o: hello.c hello.h

靜態庫和動態庫

靜態庫 static library : 一些目標目標代碼的集合,簡單講,就是一堆.o文件的集合,
在linux下一般是.a後綴名

靜態庫 一般供別人進行調用.
優點:函數庫最終被打包到應用程序中,運行速度快.移植方便,不依賴其他文件
缺點:更新發布帶來麻煩,耗費內存.

格式:

  • 前綴lib
  • 庫名字:test
  • 後綴:.a
    如libtest.a

生成步驟:

  • .c --> .o文件 格式: gcc -c xxx.c -o xxx.o

  • 打包工具ar,把.o文件打包爲.a文件, ar res(r更新,c創建,s建立索引)

    命令: ar rcs libxxx.a .o文件集合

靜態庫 使用: gcc hello.c -o hello.out -L./ -I./ -ltest

  • -L 指定鏈接的庫目錄
  • -l 指定需要鏈接的靜態庫.去前綴和後綴
  • -I 指定頭文件所在的路徑

動態庫(shared library )共享庫
程序在運行時纔會被載入.增量更新.以.so爲後綴
優點:

  • 節省內存
  • 升級更新方便,替換庫即可
    缺點:
  • 加載速度比靜態庫慢
  • 移植性差

組成: libtest.so

  • 前綴 lib
  • 庫名稱 :test
  • 後綴 .so

動態庫的生成:

  • 生成目標文件.o ,此時需要添加編譯選項 -fPIC
    (-fpic 創建與地址無關的編譯程序,目的是爲了能夠在多個應用程序之間共享)
  • 生成共享庫 -shared
    gcc -shared *.o列表

生成可執行程序:同靜態庫
使用: gcc hello.c -o hello.out -L./ -I./ -ltest

  • -L 指定鏈接的庫目錄
  • -l 指定需要鏈接的靜態庫.去前綴和後綴
  • -I 指定頭文件所在的路徑

執行時找不到該庫: ldd file

如何讓程序找到共享庫:

  • 把.so文件 拷貝到/lib 或者/usr/lib

例子1:生成靜態庫

正常編譯文件步驟

第1步: 把每個.c文件生成.o文件
gcc -c test1.c -o test1.o
gcc -c main.c -o main.o
第2步: 生成可執行程序hello
gcc -o hello main.o test1.o

- 01/01_03: 例子,先正常編譯,test1裏面有void GetTest1Version() 函數,
咱們在main中調用GetTest1Version函數的示例

root@fjs:~/code/fjs/makefile/01/01_03# ls
main.c  test1.c  test1.h
root@fjs:~/code/fjs/makefile/01/01_03# gcc -c test1.c -o test1.o
root@fjs:~/code/fjs/makefile/01/01_03# ls
main.c  test1.c  test1.h  test1.o
root@fjs:~/code/fjs/makefile/01/01_03# gcc -c main.c -o main.o
root@fjs:~/code/fjs/makefile/01/01_03# ls
main.c  main.o  test1.c  test1.h  test1.o
root@fjs:~/code/fjs/makefile/01/01_03# gcc -o hello main.o test1.o
root@fjs:~/code/fjs/makefile/01/01_03# ls
hello  main.c  main.o  test1.c  test1.h  test1.o
root@fjs:~/code/fjs/makefile/01/01_03# ./hello 
當前test1 版本號[1.1]
main run end 

上面的例子,生成.a文件

咱們把test1.h和test1.c 生成的.o文件 封裝成靜態庫.然後供main函數進行調用

第1步: 把每個.c文件生成.o文件
gcc -c test1.c -o test1.o
gcc -c main.c -o main.o

第2步: 生成靜態庫libtest1.a
ar rcs libtest1.a test1.o

第3步: 生成可執行程序hello
gcc main.o -o hello  -L./ -I./ -ltest1
 
01_04 :操作如下

root@fjs:~/code/fjs/makefile/01/01_04# ls
main.c  test1.c  test1.h
root@fjs:~/code/fjs/makefile/01/01_04# gcc -c test1.c -o test1.o
root@fjs:~/code/fjs/makefile/01/01_04# gcc -c main.c -o main.o
root@fjs:~/code/fjs/makefile/01/01_04# ls
main.c  main.o  test1.c  test1.h  test1.o
root@fjs:~/code/fjs/makefile/01/01_04# ar rcs libtest1.a test1.o
root@fjs:~/code/fjs/makefile/01/01_04# ls
libtest1.a  main.c  main.o  test1.c  test1.h  test1.o
root@fjs:~/code/fjs/makefile/01/01_04# gcc main.o -o hello  -L./ -I./ -ltest1
root@fjs:~/code/fjs/makefile/01/01_04# ls
hello  libtest1.a  main.c  main.o  test1.c  test1.h  test1.o
root@fjs:~/code/fjs/makefile/01/01_04# ./hello 
當前test1 版本號[1.1]
main run end 

例子2:生成動態庫

同樣是上面的三個文件
編譯流程:
gcc -fpic -c *.c
gcc -shared *.o -o libxxx.so
gcc main.c -I./ -L./ -lxxxx -o hello

第1步: 編譯出庫.o
gcc -fpic -c test1.c -o test1.o
第2步: 生成.so文件
gcc -shared test1.o -o libtest1.so
第3步: 生成其他.o
gcc -c main.c -o main.o
第4步:生成可執行程序
gcc main.o -I./ -L./ -ltest1 -o hello

ldd hello

01/01_05

root@fjs:~/code/fjs/makefile/01/01_05# gcc -fpic -c test1.c -o test1.o
root@fjs:~/code/fjs/makefile/01/01_05# gcc -shared test1.o -o libtest1.so
root@fjs:~/code/fjs/makefile/01/01_05# gcc -c main.c -o main.o
root@fjs:~/code/fjs/makefile/01/01_05# ls
libtest1.so  main.c  main.o  test1.c  test1.h  test1.o
root@fjs:~/code/fjs/makefile/01/01_05# gcc main.o -I./ -L./ -ltest1 -o hello
root@fjs:~/code/fjs/makefile/01/01_05# ls
hello  libtest1.so  main.c  main.o  test1.c  test1.h  test1.o
root@fjs:~/code/fjs/makefile/01/01_05# ldd hello 
        linux-vdso.so.1 (0x00007ffd22791000)
        libtest1.so (0x00007fefde37b000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fefddf8a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fefde77f000)
root@fjs:~/code/fjs/makefile/01/01_05# ./hello 
當前test1 版本號[1.2]
main run end 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章