1.makefile示例以及解析:
# 定义编译器和编译选项
CC=gcc
CFLAGS=-Wall -Wextra -pedantic -std=c99
LDFLAGS=-lm
# 定义项目目录和文件
SRCDIR=src
OBJDIR=obj
BINDIR=bin
INCDIR=include
LIBDIR=lib
# 查找源文件
SRCS=$(wildcard $(SRCDIR)/*.c)
OBJS=$(SRCS:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
# 定义目标可执行文件
TARGET=$(BINDIR)/myapp
# 编译和链接规则
all: $(TARGET)
$(OBJDIR)/%.o: $(SRCDIR)/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -I$(INCDIR) -c -o $@ $<
$(TARGET): $(OBJS)
@mkdir -p $(@D)
$(CC) $(OBJS) $(LDFLAGS) -o $@
# 清理规则
clean:
rm -rf $(OBJDIR) $(BINDIR)
# 安装规则
install: $(TARGET)
mkdir -p /usr/local/bin
cp $(TARGET) /usr/local/bin/
# 卸载规则
uninstall:
rm -f /usr/local/bin/$(notdir $(TARGET))
# 依赖库(假设)
LIB_NAME=mylib
LIB_SRC=$(wildcard $(LIBDIR)/*.c)
LIB_OBJ=$(LIB_SRC:$(LIBDIR)/%.c=$(OBJDIR)/lib/%.o)
$(OBJDIR)/lib/%.o: $(LIBDIR)/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -I$(INCDIR) -fPIC -c -o $@ $<
$(LIBDIR)/$(LIB_NAME).so: $(LIB_OBJ)
$(CC) -shared -o $@ $^
# 链接库到可执行文件(如果需要)
$(TARGET): $(OBJS) $(LIBDIR)/$(LIB_NAME).so
@mkdir -p $(@D)
$(CC) $(OBJS) -L$(LIBDIR) -l$(LIB_NAME) $(LDFLAGS) -o $@
# 伪目标,用于构建库
.PHONY: lib
lib: $(LIBDIR)/$(LIB_NAME).so
# 测试目标(假设有测试文件)
test: $(TARGET)
./$(TARGET) -t
# 依赖关系检查(可选)
.PHONY: check-deps
check-deps:
@echo "Checking dependencies..."
# 这里可以添加依赖检查命令
# 打印变量值(调试用)
.PHONY: print-vars
print-vars:
@echo "SRCS=$(SRCS)"
@echo "OBJS=$(OBJS)"
@echo "TARGET=$(TARGET)"
解析:
-
编译器和编译选项:定义了C编译器
CC
、编译选项CFLAGS
和链接选项LDFLAGS
。 -
目录和文件:定义了源代码目录
SRCDIR
、对象文件目录OBJDIR
、二进制文件目录BINDIR
、头文件目录INCDIR
和库文件目录LIBDIR
。 -
源文件和目标文件:使用
wildcard
函数查找所有.c
源文件,并计算对应的.o
对象文件路径。 -
编译和链接规则:
- 定义了如何从
.c
源文件生成.o
对象文件的规则。 - 定义了如何从对象文件生成最终的可执行文件
$(TARGET)
的规则。
- 定义了如何从
-
清理规则:定义了
clean
目标,用于删除所有生成的对象文件和二进制文件。 -
安装和卸载规则:定义了如何将可执行文件安装到系统路径,以及如何从系统路径中卸载它。
-
依赖库:
- 定义了库文件的构建规则,包括如何从
.c
源文件生成.o
对象文件,以及如何将对象文件链接成共享库文件。 - 修改了可执行文件的链接规则,以包含新构建的库。
- 定义了库文件的构建规则,包括如何从
-
伪目标:
lib
伪目标用于构建库文件。test
伪目标用于运行测试(假设有测试文件)。check-deps
和print-vars
伪目标用于依赖关系检查和打印变量值(调试用)。
2.makefile和cmake的区别:
1. 平台支持
-
CMake:是一个跨平台的构建工具,可以生成适用于多种操作系统和编译器的构建文件,如Makefile、Ninja构建文件、Visual Studio项目文件等。这使得CMake特别适合用于需要跨平台构建的项目。
-
Makefile:是一个基于文本的文件,它直接定义了构建过程的规则和命令。Makefile通常与GNU Make一起使用,但也需要针对不同的操作系统和编译器进行一定的设置或调整。
2. 依赖管理
-
CMake:能够自动管理源文件和库的依赖关系,从而简化构建过程。当源文件或依赖项发生变化时,CMake能够重新生成必要的构建文件,并确保按照正确的顺序进行构建。
-
Makefile:依赖关系需要手动管理。开发者需要在Makefile中明确指定每个目标文件所依赖的源文件或库,并在必要时更新这些依赖关系。
3. 配置文件
-
CMake:使用CMakeLists.txt文件来描述构建过程。这个文件包含了CMake命令和变量,用于定义项目名称、源文件列表、目标类型(如可执行文件或库)以及构建选项等。
-
Makefile:是一个简单的文本文件,包含了用于构建项目的规则和命令。Makefile的语法较为直接,但可能需要更多的手动配置和维护工作。
4. 可读性和维护性
-
CMake:通常被认为比Makefile更易于阅读和维护。CMakeLists.txt文件使用了更简洁的语法和更直观的结构,使得项目的构建过程更加清晰和可管理。
-
Makefile:虽然灵活且功能强大,但其语法相对复杂,且需要更多的手动配置。这可能会增加项目维护的难度和成本。
5. 执行效率
-
Makefile:由于它直接调用编译器进行编译,因此执行速度通常比CMake快。Makefile能够直接执行编译和链接等任务,而无需先生成中间文件。
-
CMake:需要先生成构建文件(如Makefile),然后再执行这些文件以完成编译过程。这个过程可能会比直接执行Makefile稍微慢一些,但CMake的跨平台特性和自动化依赖管理功能通常能够弥补这一不足。
6. 适用性
-
CMake:更适合大型项目和跨平台构建。CMake能够自动处理不同平台和编译器之间的差异,从而简化跨平台项目的构建过程。
-
Makefile:对于小型项目和单一平台构建来说,Makefile可能是一个更直接且高效的选择。Makefile的灵活性和直接性使得它能够在不需要复杂跨平台支持的情况下快速构建项目。
综上所述,CMake和Makefile各有其优势和适用场景。在选择构建工具时,应根据项目的具体需求和开发团队的偏好来进行决策。
标签:文件,CMake,makefile,Makefile,源文件,编译器,构建,相关 From: https://blog.csdn.net/yandong666/article/details/141107670