Makefile的简单示例

一、Makefile介绍

Makefile是一套用于自动化构建的脚本工具,定义了源文件的依赖关系,如何编译和链接程序

二、简单的Makefile模板

.PHONY: clean all

CC ?= gcc
CFLAGS := -Wall -g -O2 -I./
LDFLAGS := -L./
LIBS := 
targets := hello
sources := main.c xx.c
objects := main.o xx.o

all: ${targets}
  @echo "all done"

${targets}: ${objects}
  ${CC} ${LDFLAGS} $^ ${LIBS} -o $@

${objects}: ${sources}
  ${CC} ${CFLAGS} -c $< -o $@

clean:
  rm -rf *.o ${targets}

三、语法介绍

  1. .PHONY指定伪目标,例如make cleanmake all
  2. 变量,?=没有定义则定义,:=定义的时候直接展开
  3. 命令前加@可以不打印命令本身
  4. $(变量)引用变量,等价于${}
  5. *.o匹配所有的o文件
  6. 编译时使用CFLAGS指定选项,链接时使用LDFLAGS指定链接目录,使用LIBS指定链接库
  7. make和一些选项,f指定文件,n打印执行命令但是不执行,-C指定目录
  8. $<表示第一个依赖,$^表示所有依赖,$@表示目标文件
  9. -I指定头文件目录,-L指定库文件目录,-l指定动态库文件

四、驱动程序的Makefile模板

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
KERNEL_DIR = /home/uisrc/zynq-lab/kernel

all:
  make -C ${KERNEL_DIR} M=`pwd` modules

clean:
  make -C ${KERNEL_DIR} M=`pwd` module clean
  rm -rf modules.order

obj-m += my_driver.o

五、驱动程序模板的解释

  1. C选项表示make命令切换到内核源码目录进行编译
  2. M选项指令了模块源码的路径
  3. obj-m表示需要增加一个编译成模块的驱动

六、Makefile生成静态库和动态库

AR ?= ar
ARFLAGS := rcs
LIBNAMES := libmlist.a

${LIBNAMES}: m_list.o
  ${AR} ${ARFLAGS} $@ $<
CC ?= gcc
CFLAGS := -Wall -g -O2
SHARED_FLASG := -shared -fPIC
DYNAMIC_LIB := libmlist.so

${DYNAMIC_LIB}: m_list.shared.o
  ${CC} ${SHARED_FLAGS} -Wl,-soname,${DYNAMIC_LIB} -o $@ $^

m_list.shared.o: m_list.c
  ${CC} ${CFLAGS} -fPIC -c $< -o $@

七、语法解释

  1. 静态库是o文件的归档集合,链接时会被复制到最终文件中
  2. 工具是ar,选项rcs表示创建并替换现有文件并创建索引
  3. 静态库一般libxxx.a,并在链接是使用-l指定库(去掉lib和.a)
  4. 创建静态库的依赖文件是对应的o文件,可以是多个,$<可以替换为$^
  5. 创建动态库需要将先将.c文件生成.o文件,需要加入-fPIC选项
  6. 工具gcc,选项-shared、-fPIC、并使用-Wl,-soname,指定动态库名称
  7. 根据观察linux的动态库一般有xx.so,xx.so.1,xx.so.1.0,应该使用ln -sf source target建立符号链接
  8. -shared告诉工具链生成动态库,-fPIC生成位置无关代码,-Wl,-soname,指定动态库名称

八、其他注意事项

  1. Makefile中引用变量的时候,使用$()和${}是等价的,但是在CMake中变量引用的时候使用的是${},shell中也是${}
posted @ 2025-08-11 10:47  gramming  阅读(13)  评论(0)    收藏  举报