嵌入式大厂面经makefile常见面试题(持续更新中!)

这是一个嵌入式大厂面试题专栏,每天更新高频面试题。专栏将包含题目描述、详细解析、相关知识点扩展以及实际代码示例。内容涵盖操作系统、驱动开发、通信协议等核心领域,并结合实际项目经验进行分析。每道题目都会附带面试官可能的追问方向,帮助大家更好地准备面试!

Makefile常见面试题解析

Makefile是C/C++项目中常用的构建工具,在嵌入式开发和系统编程中尤为重要。以下是Makefile相关的常见面试题及详细解析:

1. Makefile基础概念

Q: 什么是Makefile?它的主要作用是什么?

:Makefile是一种用于自动化编译和构建软件的工具,它定义了一系列的规则来指定源文件如何被转换成目标文件。主要作用包括:

  1. 自动化构建:根据依赖关系自动编译需要更新的文件
  2. 管理依赖关系:跟踪源文件之间的依赖,确保正确的编译顺序
  3. 增量编译:只重新编译发生变化的文件,节省编译时间
  4. 定义构建流程:包括预处理、编译、链接等步骤
  5. 提供项目管理:支持多目标构建、条件编译等高级功能

2. Makefile基本语法

Q: Makefile的基本语法结构是什么?

:Makefile的基本语法结构包括:

  1. 规则(Rules):定义目标文件、依赖文件和命令
target: prerequisites
    command

  1. 变量(Variables):存储和重用值
CC = gcc
CFLAGS = -Wall -O2

  1. 注释(Comments):以#开头
# 这是一个注释

  1. 包含(Include):引入其他Makefile
include common.mk

  1. 条件语句:根据条件执行不同的操作
ifeq ($(DEBUG), yes)
    CFLAGS += -g
endif

  1. 函数(Functions):内置函数用于文本处理等
SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))

3. 自动变量

Q: Makefile中的自动变量有哪些?它们的作用是什么?

:Makefile中的常用自动变量包括:

  1. $@:表示当前规则的目标文件
  2. $<:表示当前规则的第一个依赖文件
  3. $^:表示当前规则的所有依赖文件,去除重复项
  4. $+:表示当前规则的所有依赖文件,保留重复项
  5. $*:表示当前规则中,目标文件的主文件名(不包括扩展名)
  6. $(@D):表示目标文件的目录部分
  7. $(@F):表示目标文件的文件名部分
  8. (<D)** 和 **(<F):分别表示第一个依赖文件的目录和文件名部分
# 自动变量使用示例
main.o: main.c defs.h
    $(CC) -c $< -o $@  # $< 表示main.c,$@表示main.o

4. 隐式规则

Q: 什么是Makefile的隐式规则?如何自定义隐式规则?

:隐式规则是Makefile预定义的一些规则,用于简化常见的编译操作。

  1. 常见的隐式规则:.c.o:从C源文件生成目标文件.cpp.o:从C++源文件生成目标文件.S.o:从汇编源文件生成目标文件
  2. 自定义隐式规则:使用模式规则(Pattern Rules)
# 自定义将.c文件编译为.o文件的规则
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

# 自定义将.md文件转换为.html文件的规则
%.html: %.md
    markdown $< > $@

  1. 隐式规则的变量: CC:C编译器命令CXX:C++编译器命令CFLAGS:C编译器选项CXXFLAGS:C++编译器选项LDFLAGS:链接器选项

5. 依赖管理

Q: Makefile如何处理文件依赖关系?如何自动生成依赖?

:Makefile通过依赖规则处理文件间的依赖关系,并可以自动生成依赖。

  1. 手动指定依赖
main.o: main.c defs.h utils.h

  1. 自动生成依赖:使用编译器的依赖生成功能
# 使用GCC的-MM选项生成依赖
%.d: %.c
    $(CC) -MM $< > $@

# 包含生成的依赖文件
-include $(SRC:.c=.d)

  1. 使用第三方工具:如makedepend或gcc -M
  2. 实际项目中的依赖生成示例:
# 定义源文件和目标文件
SRC = $(wildcard *.c)
OBJ = $(SRC:.c=.o)
DEP = $(SRC:.c=.d)

# 自动生成并包含依赖文件
%.d: %.c
    @set -e; rm -f $@; \
    $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
    rm -f $@.$$$$

# 包含所有依赖文件
-include $(DEP)

6. 变量与函数

Q: Makefile中变量的类型有哪些?常用的函数有哪些?

:Makefile中的变量类型和常用函数:

  1. 变量类型:简单变量(:=):立即展开递归变量(=):使用时才展开条件变量(?=):仅在变量未定义时赋值追加变量(+=):向已有变量追加值
  2. 常用函数:文件名处理:$(wildcard pattern):获取匹配模式的文件列表$(patsubst pattern,replacement,text):模式替换$(dir names):提取目录部分$(notdir names):提取文件名部分$(suffix names):提取文件扩展名$(basename names):提取不带扩展名的部分文本处理:$(subst from,to,text):字符串替换$(strip string):去除空格$(filter pattern,text):过滤出匹配模式的单词$(filter-out pattern,text):过滤出不匹配模式的单词$(sort list):排序控制函数:$(if condition,then-part,else-part):条件判断$(foreach var,list,text):循环处理$(call variable,param1,param2,...):调用自定义函数
# 变量使用示例
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC))

# 函数使用示例
dirs := $(sort $(dir $(SRC)))
files := $(notdir $(SRC))
bases := $(basename $(files))

7. 条件语句和循环

Q: 如何在Makefile中使用条件语句和循环?

:Makefile中的条件语句和循环:

  1. 条件语句
# if-else条件
ifeq ($(DEBUG), yes)
    CFLAGS += -g -DDEBUG
else
    CFLAGS += -O2
endif

# 检查变量是否定义
ifdef DEBUG
    CFLAGS += -g
endif

# 检查变量是否为空
ifneq ($(MAKECMDGOALS),clean)
    include $(DEPS)
endif

  1. 循环:使用foreach函数
# 为每个源文件生成编译命令
dirs := src lib utils
files :=
define get-files
    files += $(wildcard $(dir)/*.c)
endef
$(foreach dir,$(dirs),$(eval $(call get-files)))

# 创建多个目录
DIRS = obj bin lib
$(foreach dir,$(DIRS),$(shell mkdir -p $(dir)))

8. 多目标构建

Q: 如何在Makefile中实现多目标构建?

:Makefile中实现多目标构建的方法:

  1. 定义多个目标
# 定义多个目标
all: prog1 prog2 prog3

prog1: prog1.o utils.o
    $(CC) $^ -o $@

prog2: prog2.o utils.o
    $(CC) $^ -o $@

prog3: prog3.o
    $(CC) $^ -o $@

  1. 使用模式规则
# 使用模式规则构建多个目标
PROGS = prog1 prog2 prog3
all: $(PROGS)

# 每个程序依赖同名的.o文件
$(PROGS): %: %.o
    $(CC) $< -o $@

  1. 使用变量和函数
# 使用变量和函数定义多目标
PROGS = prog1 prog2 prog3
SRCS = $(addsuffix .c, $(PROGS))
OBJS = $(SRCS:.c=.o)

all: $(PROGS)

# 链接规则
$(PROGS): %: %.o
    $(CC) $^ $(LDFLAGS) -o $@

# 编译规则
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

9. 递归Make

Q: 什么是递归Make?如何实现?有什么优缺点?

:递归Make是指在Makefile中调用子目录中的Makefile的技术。

  1. 实现方法
# 定义子目录
SUBDIRS = lib src utils

# 递归调用子目录的Makefile
all:
    for dir in $(SUBDIRS); do \
        $(MAKE) -C $$dir all; \
    done

clean:
    for dir in $(SUBDIRS); do \
       

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

嵌入式面试八股文全集 文章被收录于专栏

这是一个全面的嵌入式面试专栏。主要内容将包括:操作系统(进程管理、内存管理、文件系统等)、嵌入式系统(启动流程、驱动开发、中断管理等)、网络通信(TCP/IP协议栈、Socket编程等)、开发工具(交叉编译、调试工具等)以及实际项目经验分享。专栏将采用理论结合实践的方式,每个知识点都会附带相关的面试真题和答案解析。

全部评论

相关推荐

04-05 14:01
已编辑
香港中文大学(深圳) C++
特斯拉毁约警告2024年四月毁约全体应届生&nbsp;2025年又毁实习oc一面&nbsp;hr照着八股题库提问+谈人生二面&nbsp;小组普通员工面:谈项目+判断二叉树是否相似三面&nbsp;小组leader面:&nbsp;谈项目+实现有过期时间,优先级的LRU当晚oc&nbsp;第二天发准备入职材料邮件下午&nbsp;发消息需要加面四面&nbsp;其他组的员工面:谈项目+场景题:音乐播放器的下载功能五面&nbsp;貌似是部门大佬:qt的几种connect方式+cmake用法+莫名其妙的优化问题+手写shared_ptr五面还是清明节假期面的。莫名其妙的优化问题:在有一个函数A(),函数B中&nbsp;return&nbsp;A(),&nbsp;无法修改函数A与&nbsp;B的return语句,如何计算A函数的cpu调用时间,不能在其他地方调用A与B。手写shared_ptr:正常写出来了,&nbsp;提问&nbsp;如何实现功能&nbsp;根据raw指针来构造有其他智能指针时能使用其他指向它的智能指针的引用计数&nbsp;。因为没用过shared_from_this&nbsp;我说可以写一个map来存指针地址和计数&nbsp;。&nbsp;后续面试官说可以用std::enable_shared_from_this主要就是四面面的莫名其妙,让其他方向&nbsp;其他组的员工来面这个方向的,场景题出了一个音频下载问题同时又没有详细描述,做完才告诉一个音乐是分好几个块来下载的。五面反问&nbsp;为什么会加面,更看重候选人的什么品质?&nbsp;答:这么多轮面试很正常,更看重候选人的基础能力(鸡掰五轮面试,只用第一轮hr来照着题库问专业问题,回答与题库答案不一样&nbsp;说题库没这么写。其他几轮一点基础没问,二面更是谈项目只是单方面输出,毫无反问)。问hr面评:&nbsp;前三轮没问题,第四轮场景题没思路,第五轮不知道。&nbsp;前三轮没问题&nbsp;那加个毛线。讲这么详细感觉要被hr开盒了。#特斯拉#
查看10道真题和解析
点赞 评论 收藏
分享
评论
点赞
3
分享

创作者周榜

更多
牛客网
牛客企业服务