0

在阅读了关于非递归 makefile 的 Emile van Bergen 文章后,我试图从递归转向非递归,但似乎我做得不对。

更新:我终于做对了

这些文件是:

$ ls -R
.:
folder1  Makefile  test.c  topRules.mk

./folder1:
file.c  Rules.mk

测试.c

extern void sub_print();

void main()
{
    printf("Top Hello\r\n");
    sub_print();

}

生成文件

TARGET  = test.exe
.PHONY: all
all: $(TARGET)

include topRules.mk
dir = folder1
include folder1/Rules.mk

$(TARGET): test.o $(OBJS_folder1)
        $(LINK) 

顶级规则.mk

COMPILE = $(CC) $(CFLAGS) -o $@ -c $<
LINK = $(CC)  -o $@ $^ 

%.o:    %.c
    $(COMPILE)  

文件夹 1/Rules.mk

sp := $(sp).x
dirstack_$(sp) := $(d)
d := $(dir)

OBJS_$(d) := $(d)/file.o
$(d): $(OBJS_$(d))

文件夹 1/file.c

void sub_print()
{
    printf("Hello Sub World\r\n");
}
4

2 回答 2

1
  1. 从对象列表中生成源的替换列表是错误的。它没有剥离.o扩展:

     SRC_$(d) := $(OBJS_$(d):%.o=%.c))
                              ^^
    

    完全删除变量,考虑到下一点,您将不需要它。

  2. $(OBJS_$(d)): $((SRC_$(d))规则既多余又错误:

    1. 这是多余的,因为%.o: %.c模式规则适用并且做正确的事。
    2. 这是错误的,因为它创建了一个规则来进行所有编译,但是您需要分别编译每个源。即当您有两个文件时,它将扩展为:

      foo.o bar.o : foo.c bar.c
      

      但你想要两个单独的规则。

    完全删除该规则,不要添加任何其他规则。正确的规则就在那里。

    实际上,错误是由于两个规则相互作用不好造成的。文档说“如果规则从隐式规则中获得命令,$<则将是隐式规则添加的第一个先决条件”。由于隐式规则%.o: %.c首先出现,它提供了命令,但由于显式规则提供了先决条件,所以隐式规则添加 none 并$<扩展为无。明确的规则不应该在那里。隐含的将提供先决条件和命令,并且应该起作用。

  3. 由于不带参数的 make 会执行文件中的第一个目标,因此您应该将规则移到 include 之前,或者应该在开头附近$(TARGET): ...定义一个规则all: $(TAREGT)(不需要任何操作,但应该将规则标记为)。.phony

请注意,您实际上根本不需要进行替换,因为您也不需要使用它的规则。


有时会发生目录需要特殊标志的情况。在这种情况下,您仍然不会为该目录中的文件创建特殊的隐式规则,但您会创建特殊规则来为特定目标在本地设置变量。语法是:

$(OBJS_$(d)): %.o: %.c
    specific-command

或者

$(OBJS_$(d)): %.o: CFLAGS=specific-cflags

后者仍然从一般隐式规则中获取配方,但定义给定变量的目标特定值。我想这是无效$(OBJS_$(d)): $(SRC_$(d))规则所尝试的。

这在 GNU make 文档中称为静态模式规则。

于 2013-10-02T09:03:47.810 回答
0

包括之前如何设置$(sp)$(d)应该设置folder1/Rules.mk

你没有设置它们,所以它们是空的。

替换$(OBJS_$(d):%=%.c))可能也没有做你想要的。

尝试添加一些$(info Current value of d is $(d))行来显示您设置的变量。

另外,不main()应该返回。intvoid

于 2013-10-02T08:32:56.690 回答