C/C++编译问题之-Makefile

一、Makefile基本语法

Makefile是一种用于自动化构建和管理项目的工具,它使用一种特定的语法来描述目标(target)和依赖关系(dependencies)。下面是Makefile的基本语法:

  1. 目标规则(Target Rules):

    target: dependencies
        commands
    
    • target:表示要生成的目标文件或执行的目标操作的名称。
    • dependencies:表示生成目标所需要的依赖文件或其他目标。
    • commands:表示生成目标时要执行的命令。
  2. 变量(Variables):

    variable_name = value
    
    • variable_name:变量名。
    • value:变量的值。

    在Makefile中,你可以定义自己的变量,并在规则中使用它们。例如:

    CC = gcc
    CFLAGS = -Wall -O2
    
    target: dependencies
        $(CC) $(CFLAGS) -o target dependencies
    
  3. 通配符(Wildcards):

    *.c
    

    在Makefile中,你可以使用通配符来匹配文件。例如,*.c表示匹配所有以.c为扩展名的文件。

  4. 隐式规则(Implicit Rules):

    .c.o:
        $(CC) $(CFLAGS) -c $<
    

    隐式规则定义了如何将一种类型的文件转换为另一种类型的文件。上述示例中,.c.o表示将.c文件转换为.o目标文件的规则,$<表示依赖文件的名称。

  5. 伪目标(Phony Targets):

    .PHONY: target
    

    伪目标是指不对应实际文件的目标,而是表示某个操作或动作。在Makefile中,你可以声明一个目标为伪目标,以告诉Make工具该目标不对应任何实际文件。例如:

    .PHONY: clean
    
    clean:
        rm -f *.o
    

这些是Makefile的基本语法。通过灵活运用这些规则、变量和命令,你可以构建复杂的自动化构建系统来管理项目。

二、实战常见用法

1. ifeq

ifneq 是 Makefile 中的条件判断语句,用于判断两个值是否不相等。它的语法如下:

ifneq (arg1, arg2)
    # 条件满足时执行的命令
else
    # 条件不满足时执行的命令
endif

其中,arg1arg2 是需要进行比较的值。如果它们不相等,则执行 ifneq 语句块中的命令;否则,执行 else 语句块中的命令(可选)。最后使用 endif 结束整个条件判断块。

以下是一个示例,演示了如何在 Makefile 中使用 ifneq 条件判断语句:

ARCH_TYPE := x86

ifeq ($(ARCH_TYPE), x86)
    CC := gcc
else
    CC := arm-linux-gcc
endif

target:
    $(CC) -o target source.c

在这个示例中,根据 ARCH_TYPE 变量的值来选择不同的编译器。如果 ARCH_TYPE 的值是 “x86”,则将 CC 变量设置为 “gcc”;否则,将 CC 变量设置为 “arm-linux-gcc”。最后,在 target 目标中使用 $(CC) 变量来编译源代码。

通过使用 ifneq 条件判断语句,可以根据不同的条件执行不同的操作,增强了 Makefile 的灵活性和可定制性。

2.Object rules的vpath %.c thirdparty_special

在 Makefile 中,vpath %.c thirdparty_special 是一个 vpath 指令,用于指定 Make 在查找源文件(.c 文件)时的搜索路径。

具体来说,vpath 指令的作用是将指定的文件模式(这里是 %.c)与指定的搜索路径(这里是 thirdparty_special)关联起来。这意味着当 Make 在构建目标时需要查找以 .c 结尾的源文件时,它会首先在 thirdparty_special 目录下进行搜索。

这个特性的作用在于,当项目中的源文件分布在多个目录中时,我们可以通过 vpath 指令告诉 Make 在哪些目录下查找特定类型的文件。这样可以使 Make 能够更智能地定位和使用源文件,而无需在每个规则中都指定完整的路径。

总的来说,vpath %.c thirdparty_special 这个指令可以让 Make 在查找 .c 源文件时自动去 thirdparty_special 目录下寻找,提高了 Makefile 的灵活性和可维护性。

三、常用手段

1. 脚本修改文件名

例1:将含"ab_"、"ab_cde_“的文件名替换为"aaa_”

使用 find 命令找到当前目录下所有含有 “ab_” 或 “ab_cde_” 的文件,并使用 sed 命令来进行替换。下面是一个简单的 Shell 脚本示例,实现了这一功能:

#!/bin/bash

# 查找当前目录下所有含有"gc_"或"gc_hal_"文件名的文件,并循环处理
find . -type f -name 'ab_cde_*' -o -name 'ab_*' | while read filename; do
    # 将文件名中的"ab_cde_"和"ab_"替换为"aaa_"
    newname=$(echo $filename | sed -e 's/ab_cde_/aaa_/' -e 's/ab_/aaa_/')
    # 执行重命名操作
    mv "$filename" "$newname"
    echo "Renamed $filename to $newname"
done

将上述代码保存到一个文件(比如 rename_files.sh),然后给予执行权限:

chmod +x rename_files.sh

接着在当前目录下执行该脚本即可:

./rename_files.sh

这个脚本会遍历当前目录以及子目录中的所有文件,将文件名中的 “ab_cde_” 和 “ab_” 替换为 “aaa_”。注意转换先后顺序,此处需先将"ab_cde_"转换,否则先产生的"aaa_de"无法达到转换目的。
请注意,在运行脚本之前,请务必做好必要的备份工作,以免意外情况造成文件损坏。

2. 脚本修改文件内容

例1:将含"ab_"、"ab_cde_“的文件内容替换为"aaa_”

上述例请1修改了文件名,则调用处的文件内容也需修改。
使用 sed 命令来修改文件内容中的特定词汇。下面是一个简单的 Shell 脚本示例,实现了将当前目录下所有文件中的 “ab_def_” 和 “ab_” 替换为 “aaa_”:

#!/bin/bash

# 查找当前目录下的所有文件,并循环处理
find . -type f -exec sed -i 's/ab_cde_/aaa_/g; s/ab_/aaa_/g' {} \;

将上述代码保存到一个文件(比如 modify_files.sh),然后给予执行权限:

chmod +x modify_files.sh

接着在当前目录下执行该脚本即可:

./modify_files.sh

这个脚本会遍历当前目录以及子目录中的所有文件,将文件内容中的 “ab_cde_” 和 “ab_” 替换为 “aaa_”。使用 -i 参数可以直接修改文件内容,而不需要输出到标准输出或者创建新文件。若替换的字符串中含有路径如"abstract/main",需添加转义字符"abstract/main"。

请注意,在运行脚本之前,请务必做好必要的备份工作,以免意外情况造成文件内容丢失或损坏。

3. 打印变量值

在 Makefile 中,你可以使用 $(info ...) 函数来打印变量的值。

以下是使用 $(info ...) 函数打印变量值的示例:

VAR := Hello, World!

all:
    @echo $(VAR)
    $(info Variable VAR is $(VAR))

在这个示例中,我们定义了一个名为 VAR 的变量,并将其赋值为 “Hello, World!”。然后,在 all 目标中,我们使用 echo 命令来打印变量 VAR 的值,以验证其内容是否正确。接着,在 $(info ...) 函数中,我们打印了变量 VAR 的值,并加上了一些额外的文本信息。

当你执行 make 命令时,Makefile 将会输出以下内容:

Hello, World!
Variable VAR is Hello, World!

通过使用 $(info ...) 函数,你可以在 Makefile 中打印出变量的值,方便调试和确认变量的内容。

4. 使用shell命令

在 Makefile 中,你可以使用 $(shell ...) 函数来执行任意的 Shell 命令,并将其输出作为变量的值。

因此,如果你想在 Makefile 中获取当前工作目录的绝对路径,可以使用 Shell 命令 pwd 并将其输出赋值给一个变量。以下是一个示例:

CUR_DIR := $(shell pwd)

all:
    @echo Current directory is $(CUR_DIR)

在这个示例中,我们使用 $(shell ...) 函数调用了 Shell 命令 pwd,并将其输出赋值给 CUR_DIR 变量。然后在 all 目标中,我们使用 echo 命令将 CUR_DIR 变量的值打印出来。

当你执行 make 命令时,Makefile 将会输出以下内容:

Current directory is /path/to/current/directory

总之,你可以使用 $(shell ...) 函数在 Makefile 中执行任意的 Shell 命令,并将其输出作为变量的值,从而实现获取当前工作目录的绝对路径等操作。

你可能感兴趣的:(c语言,c++)