make与makefile
make命令
make是linux系统中的一个编译源码的命令。
通常在执行后,会成功生成一个elf的可执行文件。
make
是一个构建管理工具,主要用于自动化编译程序和其他文件。它通过读取一个名为 Makefile
的文件来执行任务。Makefile
是一个包含规则和命令的文本文件,描述了如何编译和链接一个程序或者执行其他类型的任务。在 Makefile
中,你可以定义目标(target)、依赖关系(dependencies)和操作命令(commands),make
工具根据 Makefile
中定义的规则来决定需要重新编译哪些文件,以确保所有的文件都是最新的。
如何编写makefile
编写 Makefile
可以帮助你自动化编译和管理项目的过程,以下是编写 Makefile
的基本步骤和语法说明:
基本语法
目标(Targets):
- 目标是
Makefile
中的主要部分,它们指定了要执行的操作。
- 目标是
依赖关系(Dependencies):
- 每个目标可以有零个或多个依赖项,这些依赖项是目标执行所必需的文件或其他目标。
命令(Commands):
- 每个目标可以有一个或多个命令,用于执行特定操作。命令必须以 Tab 键开始。
示例 Makefile
假设有一个简单的 C 语言项目,包含两个源文件 main.c
和 helper.c
,以及它们对应的头文件 helper.h
。我们可以编写一个 Makefile
来编译这个项目:
1 |
|
解释和说明
- CC: 定义了编译器为
gcc
。 - CFLAGS: 定义了编译选项,这里包括
-Wall
(显示所有警告)和-g
(生成调试信息)。 - default: 这是一个伪目标,定义了默认的目标,这里是
myprogram
。 - myprogram: 目标
myprogram
的依赖是main.o
和helper.o
,执行命令是将它们链接为可执行文件myprogram
。 - main.o 和 helper.o: 分别是
main.c
和helper.c
的编译目标,每个都有对应的依赖和编译命令。 - clean: 清理目标,用于删除编译生成的
.o
文件和可执行文件myprogram
。
使用方法
在命令行中,你可以运行 make
命令来执行 Makefile
中定义的目标。比如:
make
:执行默认目标myprogram
,编译整个项目。make clean
:执行清理目标,删除所有编译生成的文件。
注意事项
- 目标和依赖关系中的文件名区分大小写。
- 命令必须以 Tab 键开始,而不是空格。
- 可以在
Makefile
中使用变量来简化和参数化编译过程。 Makefile
是根据目标和依赖关系来判断是否需要重新编译文件,从而提高了项目的编译效率。
编写 Makefile
可以根据具体项目的需要灵活调整,例如添加更多目标来执行测试、文档生成等其他任务。
案例
1 |
|
这个 Makefile
文件定义了一些规则和目标,用来构建一个名为 mythic-cli
的命令行工具。
变量定义:
BINARY_NAME=mythic-cli
:定义生成的可执行文件的名称为mythic-cli
。LOCAL_PATH=$(shell pwd)
:获取当前工作目录的路径,并存储在LOCAL_PATH
变量中。BUILDER_IMAGE=ghcr.io/its-a-feature/mythic_cli:v0.0.3.53
:定义了用于构建的 Docker 镜像名称和版本。
默认目标及依赖:
.PHONY: default
:声明default
是一个伪目标,即不对应实际文件。default: build_linux ;
:默认目标是build_linux
,即执行make
命令时默认会执行build_linux
目标。
包含外部文件:
-include ../build.env
:尝试包含上级目录的build.env
文件。-include ../.env
:尝试包含上级目录的.env
文件。
目标规则:
copy_binary_linux
和copy_binary_macos
:这两个目标使用 Docker 容器来复制生成的 Linux 和 macOS 版本的mythic-cli
可执行文件,并将其重命名为mythic-cli
。然后将其移动到当前目录下,并赋予执行权限。build_local
:在src
目录下使用 Go 编译器编译源代码,生成mythic-cli
可执行文件,并将其移动到上一级目录。build_linux_docker
和build_macos_docker
:这两个目标使用 Docker 容器来构建 Linux 和 macOS 版本的mythic-cli
可执行文件。它们分别构建一个临时的mythic-cli-builder
容器,从中复制生成的可执行文件,并进行后续的文件操作。
依赖关系:
build_linux
和build_macos
:这两个目标分别依赖于copy_binary_linux
和copy_binary_macos
目标,因此执行make build_linux
或make build_macos
时,会先执行相应的复制操作,然后才完成构建。
这个 Makefile
使用了 Docker 来隔离和执行编译任务,确保了构建过程的环境一致性和可重复性。
用Docker 来隔离和执行编译任务
使用 Docker 来隔离和执行编译任务在现代软件开发中非常常见。以下是一些使用 Docker 来执行编译任务的常见优点和场景:
环境一致性:Docker 可以确保在不同的开发环境中具有一致的编译和构建环境,避免了因环境差异而导致的构建失败或不一致的问题。
依赖管理:通过将所有依赖项(如编译器、库文件)封装在 Docker 镜像中,可以简化项目的依赖管理,减少了安装和配置软件所需的手动步骤。
隔离性:使用 Docker 可以将编译过程隔离在容器中,防止其影响主机系统的其他部分,同时也减少了与操作系统版本和配置相关的问题。
跨平台:Docker 镜像可以在不同的操作系统上运行,从而使得开发团队可以在不同的操作系统上使用相同的构建环境。
持续集成和持续部署(CI/CD):Docker 可以集成到 CI/CD 流水线中,用于自动化构建、测试和部署流程,提高了开发团队的生产力和发布的可靠性。
因此,使用 Docker 来隔离和执行编译任务已经成为许多现代软件项目的标准实践,特别是对于需要跨平台开发、复杂依赖关系或需要确保环境一致性的项目。