代码之家  ›  专栏  ›  技术社区  ›  KPexEA

不同输出目录的gcc依赖项生成

  •  21
  • KPexEA  · 技术社区  · 16 年前

    我使用gcc生成一个依赖文件,但是我的构建规则将输出放到一个子目录中。有没有办法告诉GCC把我的子目录前缀放在它为我生成的依赖文件中?

    gcc $(INCLUDES) -E -MM $(CFLAGS) $(SRC) >>$(DEP)
    
    7 回复  |  直到 16 年前
        1
  •  18
  •   LogicStuff    9 年前

    答案在 GCC manual 使用 -MT 旗帜。

    -MT target

    更改由依赖项生成发出的规则的目标。默认情况下,cpp采用主输入文件的名称,删除任何目录组件和任何文件后缀,例如 .c ,并附加平台的常规对象后缀。结果就是目标。

    -MT 选项将目标设置为您指定的字符串。如果需要多个目标,可以将其指定为 -MT 或使用多个 -MT 选项。

    例如, -MT '$(objpfx)foo.o' 可能给

    $(objpfx)foo.o: foo.c
    
        2
  •  38
  •   Don McCaughey    15 年前

    我假设您使用的是GNU make和GCC。首先添加一个变量来保存依赖文件列表。假设您已经有一个列出了我们所有的来源:

    SRCS = \
            main.c \
            foo.c \
            stuff/bar.c
    
    DEPS = $(SRCS:.c=.d)
    

    然后在makefile中包含生成的依赖项:

    include $(DEPS)
    

    然后添加此模式规则:

    # automatically generate dependency rules
    
    %.d : %.c
            $(CC) $(CCFLAGS) -MF"$@" -MG -MM -MP -MT"$@" -MT"$(<:.c=.o)" "$<"
    
    # -MF  write the generated dependency rule to a file
    # -MG  assume missing headers will be generated and don't stop with an error
    # -MM  generate dependency rule for prerequisite, skipping system headers
    # -MP  add phony target for each header to prevent errors when header is missing
    # -MT  add a target to the generated dependency
    

    “$@”是目标(位于:)左侧的内容,“$<”是前提条件(位于:)右侧的内容)。表达式“$(<:.c=.o)”将.c扩展名替换为.o。

    这里的诀窍是通过两次添加-mt来生成具有两个目标的规则;这使得.o文件和.d文件都依赖于源文件及其头文件;这样,每当任何相应的.c或.h文件发生更改时,依赖文件都会自动重新生成。

    -mg和-mp选项可以防止make在缺少头文件时出错。

        3
  •  10
  •   Steve Pitchers D V Santhosh Kiran    11 年前

    你可能会喜欢这个简短版本的唐·麦考奇的回答:

    SRCS = \
        main.c \
        foo.c \
        stuff/bar.c
    

    DEPS = $(SRCS:.c=.d)

    添加 -include $(DEPS) 注意 - 前缀,如果 .d 文件尚不存在。

    不需要单独的模式规则来生成依赖文件。简单添加 -MD -MMD 到您的正常编译行, D 在编译源文件的同时生成文件。例如:

    %.o: %.c
         gcc $(INCLUDE) -MMD -c $< -o $@
    
    # -MD can be used to generate a dependency output file as a side-effect of the compilation process.
    
        4
  •  3
  •   rsp1984    10 年前

    详细介绍了德根蒂的答案,这对我来说很有效:

    .depend: $(SOURCES)
        $(CC) $(CFLAGS) -MM $(SOURCES) | sed 's|[a-zA-Z0-9_-]*\.o|$(OBJDIR)/&|' > ./.depend
    

    这也适用于只有一个依赖文件包含所有源文件的依赖规则的情况。

        5
  •  1
  •   Emile    16 年前

    好的,只是为了确保我的问题是正确的:我假设您有test.c,其中包括test.h,并且您希望生成subdir/test.d(while 生成subdir/test.o),其中subdir/test.d包含

    subdir/test.o: test.c test.h
    

    而不是

    test.o: test.c test.h
    

    这就是你现在得到的。对吗?

    我想不出一个简单的方法来做你想要的。但是,看看 http://www.gnu.org/software/gcc/news/dependencies.html ,如果要在生成.o文件时创建.d文件,可以使用

    GCC$(包括)-MMD$(cflags)$(src)-O$(subdir)/$(obj)

    (给定src=test.c,subdir=subdir,obj=test.o)这将创建subdir/test.o和subdir/test.d,其中subdir/test.d包含上述所需的输出。希望有帮助。

        6
  •  0
  •   DGentry    16 年前

    如果GCC有理由这么做,我不知道这是什么。最后,我们通过sed传递依赖项输出,将所有出现的.o重写为$objdir/.o。

        7
  •  0
  •   florin    16 年前
    1. 如果不将输出放在当前目录中,make会生气。您真正应该做的是从build目录运行make,并使用vpath make变量定位源代码。如果你对编译器撒谎,迟早会报仇的。

    2. 如果您坚持在其他目录中生成对象和依赖项,则需要使用emile所回答的-o参数。