简介
现在讲述如何写 makefile 的文章很多,从几页的简易版到几十页、几百页的详细版都有。Makefile 有自己的书写格式、关键字、函数、隐含规则,像C语言一样灵活多变、功能强大。在Makefile中还可以使用系统shell所提供的任何命令来完成想要的工作,这又涉及shell编程知识。一般算法工程师也不会花太多时间去琢磨makefile和shell的语法细节,再加上gcc编译选项的复杂性,总而言之,makefile+shell+gcc用好了也能写出简洁的Makefile脚本完成复杂的编译任务。当遇到用不好的情况,要去解决makefile错误信息简直就是一个灾难。
因此,针对常见的使用场景(1、当前目录下多个测试代码片段的demo程序。2、当前目录是算法代码,需要生成库和测试程序),编写了2个万能脚本,再增加代码文件也基本不用修改makefile脚本文件。通过这2个脚本能熟练掌握makefile的基础知识,即使不用,也可以用作查找问题时的一个参考模板。构建万能makefile五部曲结构:设置编译器、指定代码-输出目标、all完成编译过程、clean清除生成文件、dist发布版本。
代码下载地址:
https://gitcode.net/openliu/devtools/-/tree/master/Makefile
A. makefile for demos
# # Makefile for building demos # Copyright by 'Audio Algorithm & Engineering Practice'. # Usage: # make # make CROSS_COMPILE=armv7a-linux-androideabi28 # make CROSS_COMPILE=aarch64-linux-android28 # make CROSS_COMPILE=arm-linux-gnueabihf # make CROSS_COMPILE=aarch64-linux-gnu # make CROSS_COMPILE=none $(info =============Start==============) ifeq ($(CROSS_COMPILE), ) CROSS_COMPILE=armv7a-linux-androideabi28 endif ifeq ($(CROSS_COMPILE), armv7a-linux-androideabi28) CC = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi28-clang AR = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar CFLAGS += -DARM_MATH_NEON endif ifeq ($(CROSS_COMPILE), aarch64-linux-android28) CC = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android28-clang AR = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar CFLAGS += -DARM_MATH_NEON -static endif ifeq ($(CROSS_COMPILE), arm-linux-gnueabihf) CC = ~/gcc-linaro-12.2.1-2023.04-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc AR = ~/gcc-linaro-12.2.1-2023.04-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-ar CFLAGS += -DARM_MATH_NEON -mfpu=neon -static endif ifeq ($(CROSS_COMPILE), aarch64-linux-gnu) CC = ~/gcc-linaro-12.2.1-2023.01-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc AR = ~/gcc-linaro-12.2.1-2023.01-x86_64_aarch64-linux-gnu/bin/arch64-linux-gnu-ar CFLAGS += -DARM_MATH_NEON -static endif ifeq ($(CROSS_COMPILE), none) CC = gcc AR = ar endif CFLAGS += -O3 -Wall -I./ CXXFLAGS += -O3 -Wall -I./ LDFLAGS += -lstdc++ -ldl -lpthread -lm -L./ #**************************************************************************** SOURCES = $(wildcard *.c) Targets = $(patsubst %.c, %, $(SOURCES)) #**************************************************************************** .PHONY:all clean all: $(Targets) $(info =============End==============) $(Targets): %: %.c $(info target: $@) @mkdir -p bin $(CC) $(CFLAGS) -o bin/$@ $< clean: rm bin -rf
编译命令:
make clean;make
make clean;make CROSS_COMPILE=armv7a-linux-androideabi28
make clean;make CROSS_COMPILE=aarch64-linux-android28
make clean;make CROSS_COMPILE=arm-linux-gnueabihf
make clean;make CROSS_COMPILE=aarch64-linux-gnu
上述模板的缺点是不能分别指定不同的编译器或者编译选项,这时不用上述模板,直接把gcc编译命令写在makefile1文件即可,编译命令:make -f makefile1
arm-android-clang = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi28-clang arm-android-ar = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar arch64-android-clang = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android28-clang arch64-android-ar = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar arm-linaro-gcc = ~/gcc-linaro-12.2.1-2023.04-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc arm-linaro-ar = ~/gcc-linaro-12.2.1-2023.04-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-ar arch64-linaro-gcc = ~/gcc-linaro-12.2.1-2023.01-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc arch64-linaro-ar = ~/gcc-linaro-12.2.1-2023.01-x86_64_aarch64-linux-gnu/bin/arch64-linux-gnu-ar CC = gcc AR = ar .PHONY:all clean all: arm armv8 matmul dotprod arm:%:%.c $(info target: $@) @mkdir -p bin $(arm-android-clang) -O3 -o bin/$@ $< armv8:%:%.c $(info target: $@) $(arm-linaro-gcc) -O3 -static -o bin/$@ $< matmul:%:%.c $(info target: $@) $(arm-linaro-gcc) -O3 -mfpu=neon -static -DARM_MATH_NEON -o bin/$@ $< dotprod:%:%.cx $(info target: $@) $(arch64-android-clang) -xc -O3 -march=armv8.2-a+dotprod -I./ -o bin/$@ $< $(arch64-linaro-gcc) -xc -O3 -march=armv8.2-a+dotprod -S $< -o bin/$@.s $(arch64-linaro-gcc) -xc -O3 -march=armv8.2-a+dotprod $< -o bin/$@1 $(arch64-linaro-gcc) -xc -O3 -static -march=armv8.2-a+dotprod -I./ -o bin/$@2 $< clean: rm bin -rf
B.makefile for library
# # Makefile for building library # Copyright by 'Audio Algorithm & Engineering Practice'. # Usage: # make # make CROSS_COMPILE=armv7a-linux-androideabi28 # make CROSS_COMPILE=aarch64-linux-android28 # make CROSS_COMPILE=arm-linux-gnueabihf # make CROSS_COMPILE=aarch64-linux-gnu # make CROSS_COMPILE=none $(info =============Start==============) ifeq ($(CROSS_COMPILE), ) CROSS_COMPILE=armv7a-linux-androideabi28 endif ifeq ($(CROSS_COMPILE), armv7a-linux-androideabi28) CC = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi28-clang AR = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar CFLAGS += -DARM_MATH_NEON CFLAGSEXE = endif ifeq ($(CROSS_COMPILE), aarch64-linux-android28) CC = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android28-clang AR = ~/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar CFLAGS += -DARM_MATH_NEON CFLAGSEXE = -static endif ifeq ($(CROSS_COMPILE), arm-linux-gnueabihf) CC = ~/gcc-linaro-12.2.1-2023.04-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc AR = ~/gcc-linaro-12.2.1-2023.04-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-ar CFLAGS += -DARM_MATH_NEON -mfpu=neon CFLAGSEXE = -static endif ifeq ($(CROSS_COMPILE), aarch64-linux-gnu) CC = ~/gcc-linaro-12.2.1-2023.01-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc AR = ~/gcc-linaro-12.2.1-2023.01-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ar CFLAGS += -DARM_MATH_NEON CFLAGSEXE = -static endif ifeq ($(CROSS_COMPILE), none) CC = gcc AR = ar endif CFLAGS += -fPIC -O3 -Wall -I./ CXXFLAGS += -O3 -Wall -I./ #LDFLAGS += -Wl,-soname=libalg.so -Wl,--no-whole-archive LDFLAGS += -lstdc++ -ldl -lm -L./lib #**************************************************************************** SOURCES = $(filter-out test.c, $(wildcard *.c)) OBJS = $(patsubst %.c, ./obj/%.o, $(SOURCES)) LIB_STATIC = ./lib/libalg.a LIB_DYNAMIC = ./lib/libalg.so TestSOURCES = test.c TestOBJS = ./obj/test.o #**************************************************************************** .PHONY:all clean dist all:alglibrary test test_so $(info =============End==============) alglibrary:$(LIB_STATIC) $(LIB_DYNAMIC) $(LIB_STATIC):$(OBJS) @mkdir -p lib $(AR) rc $(LIB_STATIC) $(OBJS) $(LIB_DYNAMIC):$(OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $(LIB_DYNAMIC) $(OBJS) $(OBJS):./obj/%.o:%.c $(info =============Obj==============) $(info dbg: $(SOURCES) $(OBJS)) $(info dbg: $@ $<) @mkdir -p obj $(CC) $(CFLAGS) -c $< -o $@ test:$(TestOBJS) $(LIB_STATIC) $(info target: $@ $^) $(CC) $(CFLAGSEXE) -o $@ $^ #./test test_so:$(TestOBJS) $(info target: $@ $^) $(CC) -o $@ $^ -L./lib -lalg #./test_so $(TestOBJS):$(TestSOURCES) $(info dbg: $@ $<) $(CC) $(CFLAGS) -c $< -o $@ clean: $(info =============make clean==============) rm -rf lib obj release test test_so release.tar.gz dist: @mkdir -p release cp ./lib/* release/ -rf cp ./*.h release/ -rf cp $(TestSOURCES) release/ -rf tar -czvf release.tar.gz release/
编译命令:
make clean;make
make clean;make CROSS_COMPILE=armv7a-linux-androideabi28
make clean;make CROSS_COMPILE=aarch64-linux-android28
make clean;make CROSS_COMPILE=arm-linux-gnueabihf
make clean;make CROSS_COMPILE=aarch64-linux-gnu
make clean;make CROSS_COMPILE=none
C.开发&测试环境
编译环境信息:
audio@ubuntu:~/$ getconf LONG_BIT
64
audio@ubuntu:~/$ uname -a
Linux ubuntu 5.4.0-122-generic #138~18.04.1-Ubuntu SMP Fri Jun 24 21:14:03 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
运行环境信息:
console:/ # getconf LONG_BIT
32
console:/ # uname -a
Linux localhost 5.4.225-gc4839768cf9b-dirty #1 SMP PREEMPT Thu May 19 21:34:52 UTC 2023 armv8l
微信扫一扫,关注公众号“音频算法与工程实践”