日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一个适用各类场合的Makefile模板

發布時間:2023/12/20 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个适用各类场合的Makefile模板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.寫在前面

對于Windows下開發,很多IDE都集成了編譯器,如Visual Studio,提供了“一鍵編譯”,編碼完成后只需一個操作即可完成編譯、鏈接、生成目標文件。Linux開發與Windows不同,Linux下一般用的的gcc/g++編譯器,如果是開發ARM下的Linux程序,還需用到arm-linux-gcc/arm-linux-g++交叉編譯器。Linux下也可以實現“一鍵編譯”功能,此時需要一個編譯腳本“Makefile”,Makefile可以手動編寫,也可以借助自動化構建工具(如scons、CMake)生成。手動編寫Makefile是Linux和Windows程序員的區別之一,一般地一個通用的Makefile能夠適合大部分Linux項目程序。

2.通用Makefile模板

2.1 編譯可執行文件Makefile

VERSION??=1.00 CC???=gcc DEBUG???=-DUSE_DEBUG CFLAGS??=-Wall SOURCES???=$(wildcard?./source/*.c) INCLUDES???=-I./include LIB_NAMES??=-lfun_a?-lfun_so LIB_PATH??=-L./lib OBJ???=$(patsubst?%.c,?%.o,?$(SOURCES)) TARGET??=app#links $(TARGET):$(OBJ)@mkdir?-p?output$(CC)?$(OBJ)?$(LIB_PATH)?$(LIB_NAMES)?-o?output/$(TARGET)$(VERSION)@rm?-rf?$(OBJ)#compile %.o:?%.c$(CC)?$(INCLUDES)?$(DEBUG)?-c?$(CFLAGS)?$<?-o?$@.PHONY:clean clean:@echo?"Remove?linked?and?compiled?files......"rm?-rf?$(OBJ)?$(TARGET)?output

【要點說明】

【1】程序版本 開發調試過程可能產生多個程序版本,可以在目標文件后(前)增加版本號標識。

VERSION?=?1.00 $(CC)?$(OBJ)?$(LIB_PATH)?$(LIB_NAMES)?-o?output/$(TARGET)$(VERSION)

【2】編譯器選擇 Linux下為gcc/g++;arm下為arm-linux-gcc;不同CPU廠商提供的定制交叉編譯器名稱可能不同,如Hisilicon“arm-hisiv300-linux-gcc”。

CC?=?gcc

【3】宏定義 開發過程,特殊代碼一般增加宏條件來選擇是否編譯,如調試打印輸出代碼。-D是標識,后面接著的是“宏”。

DEBUG?=-DUSE_DEBUG

【4】編譯選項 可以指定編譯條件,如顯示警告(-Wall),優化等級(-O)。

CFLAGS?=-Wall?-O

【5】源文件 指定源文件目的路徑,利用“wildcard”獲取路徑下所有依賴源文件。

SOURCES?=$(wildcard?./source/*.c)

【6】頭文件 包含依賴的頭文件,包括源碼文件和庫文件的頭文件。

INCLUDES?=-I./include

【7】庫文件名稱 指定庫文件名稱,庫文件有固定格式,靜態庫為libxxx.a;動態庫為libxxx.so,指定庫文件名稱只需寫“xxx”部分,

LIB_NAMES?=-lfun_a?-lfun_so

【8】庫文件路徑 指定依賴庫文件的存放路徑。注意如果引用的是動態庫,動態庫也許拷貝到“/lib”或者“/usr/lib”目錄下,執行應用程序時,系統默認在該文件下索引動態庫。

LIB_PATH?=-L./lib

【9】目標文件 調用“patsubst”將源文件(.c)編譯為目標文件(.o)。

OBJ?=$(patsubst?%.c,?%.o,?$(SOURCES))

【10】執行文件 執行文件名稱

TARGET?=app

【11】編譯

%.o:?%.c$(CC)?$(INCLUDES)?$(DEBUG)?$(CFLAGS)?$<?-o?$@

【12】鏈接 可創建一個“output”文件夾存放目標執行文件。鏈接完輸出目標執行文件,可以刪除編譯產生的臨時文件(.o)。

$(TARGET):$(OBJ)@mkdir?-p?output$(CC)?$(OBJ)?$(LIB_PATH)?$(LIB_NAMES)?-o?output/$(TARGET).$(VERSION)@rm?-rf?$(OBJ)

【13】清除編譯信息 執行“make clean”清除編譯產生的臨時文件。

.PHONY:clean clean:@echo?"Remove?linked?and?compiled?files......"rm?-rf?$(OBJ)?$(TARGET)?output

2.2 編譯靜態庫Makefile

VERSION?????= CC??????????=gcc DEBUG???= CFLAGS??=-Wall AR???=ar ARFLAGS?????=rv SOURCES???=$(wildcard?*.c) INCLUDES????=-I. LIB_NAMES???= LIB_PATH??= OBJ?????????=$(patsubst?%.c,?%.o,?$(SOURCES)) TARGET??????=libfun_a#link $(TARGET):$(OBJ)@mkdir?-p?output$(AR)?$(ARFLAGS)?output/$(TARGET)$(VERSION).a?$(OBJ)@rm?-rf?$(OBJ)#compile %.o:?%.c$(CC)?$(INCLUDES)?$(DEBUG)?-c?$(CFLAGS)?$<?-o?$@.PHONY:clean clean:@echo?"Remove?linked?and?compiled?files......"rm?-rf?$(OBJ)?$(TARGET)?output

【要點說明】 基本格式與“編譯可執行Makefile”一致,不同點包括以下。

【1】使用到“ar”命令將目標文件(.o)鏈接成靜態庫文件(.a)。靜態庫文件固定命名格式為:libxxx.a。

2.3 編譯動態庫Makefile

VERSION???= CC????????=gcc DEBUG?????= CFLAGS????=-fPIC?-shared? LFLAGS???=-fPIC?-shared? SOURCES???=$(wildcard?*.c) INCLUDES??=-I. LIB_NAMES?= LIB_PATH??= OBJ???????=$(patsubst?%.c,?%.o,?$(SOURCES)) TARGET????=libfun_so#link $(TARGET):$(OBJ)@mkdir?-p?output$(CC)?$(OBJ)?$(LIB_PATH)?$(LIB_NAMES)?$(LFLAGS)?-o?output/$(TARGET)$(VERSION).so@rm?-rf?$(OBJ)#compile %.o:?%.c$(CC)?$(INCLUDES)?$(DEBUG)?-c?$(CFLAGS)?$<?-o?$@.PHONY:clean clean:@echo?"Remove?linked?and?compiled?files......"rm?-rf?$(OBJ)?$(TARGET)?output

【要點說明】 基本格式與“編譯可執行Makefile”一致,不同點包括以下。

【1】編譯選項和鏈接選項增加“-fPIC -shared ”選項。動態庫文件固定命名格式為libxxx.so。

3.Demo

3.1 應用程序

編寫測試例程,文件存放目錄結構如下,頭文件存放在“include”目錄,庫文件存放在“lib”目錄,源文件存放在“source”目錄,Makefile在當前目錄下。

源碼1

/*頭文件*/ #ifndef?_FUN0_H_ #define?_FUN0_H_ #endifextern?void?fun0_printf(void); extern?void?fun1_printf(void);/*源文件*/ #include?<stdio.h> #include?"fun0.h"void?fun0_printf(void) {printf("Call?\'fun0\'.?\r\n"); }

源碼2

/*頭文件*/ #ifndef?_FUN1_H_ #define?_FUN1_H_ #endifextern?void?fun1_printf(void);/*源文件*/ #include?<stdio.h> #include?"fun1.h"void?fun1_printf(void) {printf("Call?\'fun1\'.\r\n"); }

主函數源碼

/*源文件*/ #include?<stdio.h> #include?"fun0.h" #include?"fun1.h" #include?"fun_lib_a.h" #include?"fun_lib_so.h"int?main(void) {#ifdef?USE_DEBUGprintf("Debug?Application?startup.\r\n");#endiffun0_printf();fun1_printf();fun_lib_a_printf();fun_lib_so_printf();return?0; }

庫文件,“./lib”目錄下存放兩個庫文件,一個靜態庫libfun_a.a,一個動態庫libfun_so.so。

Makefile文件即為“2.1節”的Makefile模板。

測試運行:

【如果執行文件提示無“libfun_so.so”,則需拷貝“libfun_so.so”到根目錄下的“/lib”或者“/usr/lib”目錄下,因為系統執行程序,默認從該路徑引腳動態庫】

3. 2 生成靜態庫

編寫測試例程,生產的庫文件即為“3.1節”調用的庫文件(libfun_a.a)。文件存放目錄結構如下

源文件

/*頭文件*/ #ifndef?_FUN_LIB_A_H_ #define?_FUN_LIB_A_H_ #endifextern?void?fun_lib_a_printf(void);/*源文件*/ #include?<stdio.h> #include?"fun_lib_a.h"void?fun_lib_a_printf(void) {printf("Call?\'fun_lib_a\'.\r\n"); }

Makefile文件即為“2.2節”的Makefile模板。

編譯生成靜態庫

3. 3 生成靜態庫

編寫測試例程,生產的庫文件即為“3.1節”調用的庫文件(libfun_so.so)。文件存放目錄結構如下

源文件

/*頭文件*/ #ifndef?_FUN_LIB_SO_H_ #define?_FUN_LIB_SO_H_ #endifextern?void?fun_lib_so_printf(void);/*頭文件*/#include?<stdio.h> #include?"fun_lib_so.h"void?fun_lib_so_printf(void) {printf("Call?\'fun_lib_so\'.\r\n"); }

編譯生成動態庫

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的一个适用各类场合的Makefile模板的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。