非递归Makefile编译问题

时间:2013-10-02 07:54:49

标签: c makefile gnu-make

在阅读关于非递归makefile的Emile van Bergen文章后,我试图从递归到非递归,但似乎我没有做对。

更新:我终于做对了

文件是:

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

./folder1:
file.c  Rules.mk

test.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) 

topRules.mk

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

%.o:    %.c
    $(COMPILE)  

的folder1 / Rules.mk

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

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

的folder1 / file.c

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

2 个答案:

答案 0 :(得分: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
      

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

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

      实际上,错误是由于两个规则相互影响很严重。文档说&#34;如果规则从隐式规则获得它的命令,$<将是隐式规则添加的第一个先决条件&#34;。由于隐式规则%.o: %.c首先出现,它提供了命令,但由于显式规则提供了先决条件,因此隐式规则不添加任何内容,$<扩展为空。明确的规则不应该存在。比隐式的提供先决条件和命令都应该有效。

    4. 由于make without argument会执行文件中的第一个目标,您应该在include之前移动$(TARGET): ...规则,或者应该定义规则all: $(TAREGT)(不需要任何操作,但规则应该在开头附近标记.phony

    5. 请注意,您根本不需要进行替换,因为您不需要使用该规则。


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

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

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

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

      这在GNU make documentation中称为static pattern rules

答案 1 :(得分:0)

$(sp)被包含之前,如何设置$(d)folder1/Rules.mk

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

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

尝试添加一些$(info Current value of d is $(d))行以显示您已将变量设置为的内容。

此外,main()应该返回int而不是void