使用make,如何使用汇编项目中的.c文件防止此行为?

Eva*_*oll 2 c assembly makefile gnu-make

我正在制作一个超级简单的NASM x86_64装配程序 mytest.asm

BITS 64
GLOBAL _start

SECTION .text
    _start:
        mov  rax, 60   ; 'exit' system call
        mov  rdi, 42   ; exit with error code 42
        syscall
Run Code Online (Sandbox Code Playgroud)

所有这个程序都以状态42退出.我为它做了一个非常简单的Makefile,

AS=nasm
ASFLAGS=-f elf64

.PHONY: all

all: mytest

%.o : %.asm
    $(AS) $(ASFLAGS) -o "$@" "$<"

% : %.o
    $(LD) $(LDFLAGS) -o "$@" "$<"
Run Code Online (Sandbox Code Playgroud)

执行时,这很好,

nasm -f elf64 -o "mytest.o" "mytest.asm"
ld -m elf_x86_64 -o "mytest" "mytest.o"
rm mytest.o
Run Code Online (Sandbox Code Playgroud)

除非有相同名称的文件.c,例如此处mytest.c

// exits with status 66
int main () {
  __asm__ (
    "mov $60, %%rax\n\t"
    "mov $66, %%rdi\n\t"
    "syscall\n\t"
    ::: "%rax", "%rdi"
  );
}
Run Code Online (Sandbox Code Playgroud)

如果我运行make以下文件,C代码实际上被编译到mytest.

并且笨拙地,$(LDARGS)被送到$(CC)而不是被送到$(LD).这对我来说似乎不安全,任何具有这种非常典型的人都Makefile可以通过插入.c具有相同名称的文件从代码名称生成可执行文件?

这种行为是否由GNU Make记录?

GNU Make 4.1
Built for x86_64-pc-linux-gnu
Run Code Online (Sandbox Code Playgroud)

理想情况下,.c文件的存在不会影响程序集构建流.

Ste*_*itt 6

这来自Make的内置规则.Make知道如何从C文件构建可执行文件,所以当你要求它构建时mytest(这是make因为你有一个all目标要求mytest),它会建立它的依赖树并注意到:

  • 它可以建立mytestmytest.c继其内置的规则;
  • 它可以建立mytestmytest.o,下面您所指定的规则;
  • 它可以建立mytest.omytest.c继其内置的规则;
  • 它可以建立mytest.omytest.asm,下面您所指定的规则.

第一条规则获胜(我不确定优先级是什么),这就是它的作用.

您可以使用以下-r选项禁用此功能:

make -r mytest
Run Code Online (Sandbox Code Playgroud)

将始终使用您的规则来构建程序.

您也可以取消内置规则要么

  • 通过重新定义它们来单独:

    % : %.c
    
    Run Code Online (Sandbox Code Playgroud)

    在你的结尾Makefile将禁用该内置规则并导致你所追求的行为;

  • 通过MAKEFLAGS += -r在Makefile中指定全局.

  • 实际上我所做的就是"MAKEFLAGS + = --no-builtin-rules" (2认同)
  • @EvanCarroll:内置规则在很多时候非常方便.另外,为了避免目标文件之间的名称冲突,通常不建议同时使用`foo.asm`和`foo.c`.这意味着你不能同时使用`gcc -c foo.c`和`nasm -felf64 foo.asm`.因此,不这样做是正常的,这也是为什么你必须与`make`作斗争以使其发挥作用的部分原因. (2认同)
  • @PeterCordes我理解这个问题是关于使构建具有弹性 - 如何确保构建正确的工件,即使存在不需要的,冲突的工件. (2认同)