【问题标题】:Compile and link when dependent header file changed in other directory依赖头文件在其他目录发生变化时编译链接
【发布时间】:2023-04-04 10:42:01
【问题描述】:

我有 3 个关于以更少 步骤编译和链接我的项目的问题...

首先,我的项目如下:(我使用 Watcom C 编译//链接我的项目)

目录“MyProject”包含不同模块和一些文件的 3 个子目录:

  • 目录“A”(包括 a.h 和 a.c)
  • 目录“B”(包括 b.h 和 b.c)
  • 目录“C”(包括 c.h 和 c.c)
  • my.c 和 my.h
  • 我的.lnk
  • 制作文件

并且在每个子目录中都有一个对应的makefile...

[Q1]假设我更新目录A中的a.h,并且a.h被目录B中的b.c引用,那么我原来的步骤是:

  1. 在目录 A 中编译(生成 obj 和 lib...)
  2. 在目录 B 中编译(生成 obj 和 lib...)
  3. 回到目录 MyProject 然后编译链接

我可以迈出一步来覆盖上面吗?

[Q2]如果我想忽略所有现有的 obj/lib 并全部重建,该怎么做?

  • 我知道这需要时间,但有时“杀戮和重建”会更好...

[Q3]如果 my.h 被更新并且被 a.c、b.c 和 c.c 引用...

我可以迈出一步来覆盖上面吗?

[我在 sub 目录中的 makefile 看起来像]

INCLUDE1 = -ic:\watcom\h
OBJECTS1 = a.obj
CFLAGS   = -zq -mf -oxsbl $(INCLUDE1)
DEST     = a.exe
COMPILER = wpp386

.erase # special cmd, tell wmake to "erase" target if make is not successful
.cpp.obj: .AUTODEPEND
      $(COMPILER) $(CFLAGS) $<

$(DEST) : $(OBJECTS1) makefile

[我在 ma​​in 目录中的 makefile 看起来像]

INCLUDE1 = -i=c:\myproj\my -i=c:\watcom\h 
OBJECTS1 = my.obj
CFLAGS   = -zq -fp6 -mf -6r -s -oxsbl $(INCLUDE1)
DEST     = my.exe
COMPILER = wpp386
LINKER   = wlink
LNK_FILE = my.lnk

.erase # special cmd, tell wmake to "erase" target if make is not successful

.cpp.obj: .AUTODEPEND
      $(COMPILER) $(CFLAGS) $<


$(DEST) : $(OBJECTS1) makefile my.lnk
      $(LINKER) @$(LNK_FILE)

[更新 1]

我使用 wpp386 作为编译器,它是 watcom c++ 工具。

为了构建目标,我使用一个批处理文件来编译 cpp 文件:

@echo off
del a1.lib
del *.err
wmake -h
wlib -q a1.lib + a.obj

del *.obj
  • 我可以成功编译cpp文件,一切正常。
  • 在B目录下,我用同样的方式(批处理文件+makefile)编译b.cpp

总结一下我的项目工作,我问的原因是如果我只是更新一些头文件,就可以找到“更快的编译/链接序列”......

我尝试将命令ehco hello 添加到规则$(DEST) 中,发现没问题。然后使用echo $(MAKE) 得到:

...
echo C:\WATCOM\BINW\WMAKE.EXE
C:\WATCOM\BINW\WMAKE.EXE
...

谢谢!

【问题讨论】:

  • 一个好的 makefile 应该完全符合您的要求。你的makefile是什么样子的?
  • 致 Matthias,我在上面列出了我的 makefile。
  • 主 Makefile 必须命令子目录中的 Makefile。你更喜欢include他们,还是调用他们($(MAKE) A/makefile)?
  • 到Beta:我在主makefile中添加了( $(MAKE) A/makefile )并在子目录A中更新了a.h(用于测试)。然后在主目录中执行wmake -h并发现:A 中的 lib 文件“未”重新构建...我错过了什么吗?

标签: batch-file makefile project-management dos


【解决方案1】:

我不熟悉你的编译器,所以我看不出这些 makefile 是如何工作的,所以我们必须一步一步来。

1) 当您进入子目录A 时,您使用什么命令来构建目标?它有效吗?在子目录B怎么样?

2) 在主 makefile 中,您可以在 $(DEST) 规则中添加一个命令,例如 echo hello 吗?如果可行,请尝试echo $(MAKE)

编辑:

非 GNU 版本的 Make 很麻烦,但我们会看看我们能做什么。

尝试在 subdir A 中编辑 makefile:

INCLUDE1 = -ic:\watcom\h
OBJECTS1 = a.obj
CFLAGS   = -zq -mf -oxsbl $(INCLUDE1)
DEST     = a1.lib # NOTE THIS CHANGE
COMPILER = wpp386

.erase # special cmd, tell wmake to "erase" target if make is not successful
.cpp.obj: .AUTODEPEND
      $(COMPILER) $(CFLAGS) $<

$(DEST) : $(OBJECTS1) makefile
      wlib -q $@ + $(OBJECTS1)
      del $(OBJECTS1)

只运行make -h 而不是批处理文件。这应该重建库(如果库需要重建)。如果可行,请尝试升级到 MyProject 并运行 make -h -C A。这应该在A 中执行makefile 并在那里重建库(除非WMAKE 有其他语法)。

如果 有效,请尝试在 B 中进行相同的更改,然后在主 makefile 中编辑 $(DEST) 规则:

$(DEST) : $(OBJECTS1) makefile my.lnk
    $(MAKE) -h -C A
    $(MAKE) -h -C B
    $(LINKER) @$(LNK_FILE)

交叉手指并运行make -h。这应该重建两个库、编译、链接和解决 Q1...

【讨论】:

  • 我试过了,请检查上面我的问题中的 [Update 1],谢谢!
  • 我在目录 A 中的 makefile 中发现了 2 个差异。第一个是 a.lib,第二个是为目标添加的 2 prerequisites。我不知道为什么a.exe被改为a.lib,但我可以理解第二个,因为Prerequisites need to be updated first, before the target on the left hand side can be updated。对于我的Q2,我发现使用wmake -a 可以重建所有目标,我正确吗?
  • 不知道wmake,所以不知道wmake -a是否满足Q2。而且我不知道.AUTODEPEND,所以我不知道它是否满足Q3(如果不满足,为什么要有它?)。
  • wmake -a 表示 make all targs(忽略时间戳),.AUTODEPEND 表示使用 wmake 和 Open Watcom 编译器,使用自动依赖检查很简单。用户需要做的就是使用适当的规则指定 .AUTODEPEND 指令。 C/C++ 编译器以及 Windows 和 OS/2 资源编译器会自动在目标文件中发出依赖信息,wmake 将从其中读取它。不需要额外的文件或编译器开关。我会检查他们两个......!