如何强制 makefile 重建目标?

发布于 2024-07-18 21:11:20 字数 1431 浏览 5 评论 0原文

我有一个生成文件,然后调用另一个生成文件。 由于这个 makefile 调用了更多的 makefile 来完成工作,所以它并没有真正改变。 因此,它一直认为该项目已建成并且是最新的。

dnetdev11 ~ # make
make: `release' is up to date.

如何强制 makefile 重建目标?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \


release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

注意:删除名称以保护无辜的

最终修复版本:

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \


.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib

I have a makefile that builds and then calls another makefile. Since this makefile calls more makefiles that does the work it doesn't really change. Thus it keeps thinking the project is built and up to date.

dnetdev11 ~ # make
make: `release' is up to date.

How do I force the makefile to rebuild the target?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \


release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

Note: Names removed to protect the innocent

Final Fixed version:

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \


.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

胡大本事 2024-07-25 21:11:21

make clean 删除所有已编译的目标文件。

make clean deletes all the already compiled object files.

瘫痪情歌 2024-07-25 21:11:21

如果我没记错的话,“make”使用时间戳(文件修改时间)来确定目标是否是最新的。 强制重新构建的常见方法是使用“touch”命令更新该时间戳。 您可以尝试在 makefile 中调用“touch”来更新目标之一(可能是那些子 makefile 之一)的时间戳,这可能会强制 Make 执行该命令。

If I recall correctly, 'make' uses timestamps (file modification time) to determine whether or not a target is up to date. A common way to force a re-build is to update that timestamp, using the 'touch' command. You could try invoking 'touch' in your makefile to update the timestamp of one of the targets (perhaps one of those sub-makefiles), which might force Make to execute that command.

随风而去 2024-07-25 21:11:21

我尝试了这个,它对我有用,

将这些行添加到 Makefile

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

保存,然后调用

make new 

,它将再次重新编译所有内容

发生了什么?

1)“新”叫干净。
'clean' do 'rm' 删除所有扩展名为 '.o' 的目标文件。

2)“新”调用“制造”。
“make”看到没有“.o”文件,因此它再次创建所有“.o”。 然后链接器将所有 .o 文件链接到一个可执行输出

祝你好运

I tried this and it worked for me

add these lines to Makefile

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

save and now call

make new 

and it will recompile everything again

What happened?

1) 'new' calls clean.
'clean' do 'rm' which removes all object files that have the extension of '.o'.

2) 'new' calls 'make'.
'make' see that there is no '.o' files, so it creates all the '.o' again. then the linker links all of the .o file int one executable output

Good luck

尴尬癌患者 2024-07-25 21:11:21

这个简单的技术将允许 makefile 在不需要强制时正常运行。 在 ma​​kefile 末尾创建一个名为 force 的新目标。 强制目标将触及默认目标所依赖的文件。 在下面的示例中,我添加了 touch myprogram.cpp。 我还添加了对 ma​​ke 的递归调用。 这将导致每次您键入 ma​​ke force 时都会创建默认目标。

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make

This simple technique will allow the makefile to function normally when forcing is not desired. Create a new target called force at the end of your makefile. The force target will touch a file that your default target depends on. In the example below, I have added touch myprogram.cpp. I also added a recursive call to make. This will cause the default target to get made every time you type make force.

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make
秋心╮凉 2024-07-25 21:11:21

正如 abernier 指出的,GNU make 手册中有一个推荐的解决方案,它使用“假”目标来强制重建目标:

clean: FORCE
        rm $(objects)
FORCE: ; 

这将干净地运行,而不管任何其他依赖项。

我在手册中的解决方案中添加了分号,否则需要空行。

As abernier pointed out, there is a recommended solution in the GNU make manual, which uses a 'fake' target to force rebuilding of a target:

clean: FORCE
        rm $(objects)
FORCE: ; 

This will run clean, regardless of any other dependencies.

I added the semicolon to the solution from the manual, otherwise an empty line is required.

我纯我任性 2024-07-25 21:11:21

根据 Miller 的 递归使人认为有害,您应该避免调用 $(制作)! 在您展示的情况下,它是无害的,因为这并不是真正的 makefile,只是一个包装脚本,也可能是用 Shell 编写的。 但是你说你在更深的递归级别上继续这样,所以你可能遇到了那篇令人大开眼界的文章中显示的问题。

当然,对于 GNU make 来说,避免这种情况很麻烦。 即使他们意识到这个问题,但这也是他们记录下来的做事方式。

OTOH,makepp 是作为这个问题的解决方案而创建的。 您可以在每个目录级别编写 makefile,但它们都会被组合在一起形成项目的完整视图。

但遗留的 makefile 是递归编写的。 因此,有一种解决方法,其中 $(MAKE) 不执行任何操作,只是将子请求引导回主 makepp 进程。 只有当您在子制作之间做了多余的事情,或者更糟糕的是,矛盾的事情时,您才必须请求 --traditional-recursive-make (这当然破坏了 makepp 的这一优势)。 我不知道你的其他 makefile,但如果它们写得很清楚,使用 makepp 应该会自动进行必要的重建,而不需要其他人在这里建议的任何 hack。

As per Miller's Recursive Make Considered Harmful you should avoid calling $(MAKE)! In the case you show, it's harmless, because this isn't really a makefile, just a wrapper script, that might just as well have been written in Shell. But you say you continue like that at deeper recursion levels, so you've probably encountered the problems shown in that eye-opening essay.

Of course with GNU make it's cumbersome to avoid. And even though they are aware of this problem, it's their documented way of doing things.

OTOH, makepp was created as a solution for this problem. You can write your makefiles on a per directory level, yet they all get drawn together into a full view of your project.

But legacy makefiles are written recursively. So there's a workaround where $(MAKE) does nothing but channel the subrequests back to the main makepp process. Only if you do redundant or, worse, contradictory things between your submakes, you must request --traditional-recursive-make (which of course breaks this advantage of makepp). I don't know your other makefiles, but if they're cleanly written, with makepp necessary rebuilds should happen automatically, without the need for any hacks suggested here by others.

笑看君怀她人 2024-07-25 21:11:21

已经提到过,但我想我可以添加使用 touch

如果您 touch 所有要编译的源文件,touch 命令会更改执行 touch 命令时文件到系统时间的时间戳。

源文件 timstamp 是 make 用来“知道”文件已更改并需要重新编译的文件。

例如:如果项目是 C++ 项目,则执行 touch *. cpp,然后再次运行 make,make 应该重新编译整个项目。

It was already mentioned, but thought I could add to using touch

If you touch all the source files to be compiled, the touch command changes the timestamps of a file to the system time the touch command was executed.

The source file timstamp is what make uses to "know" a file has changed, and needs to be re-compiled

For example: If the project was a c++ project, then do touch *.cpp, then run make again, and make should recompile the entire project.

陌上青苔 2024-07-25 21:11:21

如果您不需要保留任何已成功编译的输出,请

nmake /A 

重建所有

If you don't need to preserve any of the outputs you already successfully compiled

nmake /A 

rebuilds all

窝囊感情。 2024-07-25 21:11:21

这实际上取决于目标是什么。 如果它是一个虚假目标(即目标与文件无关),您应该将其声明为 .PHONY。

但是,如果目标不是虚假目标,但您只是想出于某种原因重建它(例如,当您使用 __TIME__ 预处理宏时),您应该使用此处答案中描述的 FORCE 方案。

It actually depends on what the target is. If it is a phony target (i.e. the target is NOT related to a file) you should declare it as .PHONY.

If however the target is not a phony target but you just want to rebuild it for some reason (an example is when you use the __TIME__ preprocessing macro), you should use the FORCE scheme described in answers here.

烟─花易冷 2024-07-25 21:11:21

在我的 Linux 系统 (Centos 6.2) 上,当规则实际创建与目标匹配的文件时,声明目标 .PHONY 和创建对 FORCE 的虚假依赖项之间存在显着差异。 当每次都必须重新生成文件时,它需要两者
文件上的假依赖项 FORCE,以及​​假依赖项的 .PHONY。

错误:

date > $@

正确:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE

On my Linux system (Centos 6.2), there is a significant difference between declaring the target .PHONY and creating a fake dependency on FORCE, when the rule actually does create a file matching the target. When the file must be regenerated every time, it required both
the fake dependency FORCE on the file, and .PHONY for the fake dependency.

wrong:

date > $@

right:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE
嘿哥们儿 2024-07-25 21:11:20

make 的 -B 开关,其长形式为 --always-make,告诉 make 忽略时间戳并生成指定的目标。 这可能会违背使用 make 的目的,但它可能正是您所需要的。

The -B switch to make, whose long form is --always-make, tells make to disregard timestamps and make the specified targets. This may defeat the purpose of using make, but it may be what you need.

表情可笑 2024-07-25 21:11:20

您可以将一个或多个目标声明为虚假

虚假目标并不是真正的文件名; 而是它
只是当您显式执行时要执行的配方的名称
要求。 使用虚假目标有两个原因:
与同名文件冲突,并提高性能。

...

虚假目标不应成为真实目标文件的先决条件; 如果
是的,每次 make 更新它时都会运行它的配方
文件。 只要虚假目标永远不是真实目标的先决条件
目标,仅当虚假目标配方时才会执行虚假目标配方
target是指定的目标

You could declare one or more of your targets to be phony.

A phony target is one that is not really the name of a file; rather it
is just a name for a recipe to be executed when you make an explicit
request. There are two reasons to use a phony target: to avoid a
conflict with a file of the same name, and to improve performance.

...

A phony target should not be a prerequisite of a real target file; if
it is, its recipe will be run every time make goes to update that
file. As long as a phony target is never a prerequisite of a real
target, the phony target recipe will be executed only when the phony
target is a specified goal

浅沫记忆 2024-07-25 21:11:20

Sun 的 make 手册中曾经记录过一个技巧,即使用(不存在的)目标“.FORCE”。 您可以通过创建一个文件 force.mk 来完成此操作,其中包含:

.FORCE:
$(FORCE_DEPS): .FORCE

然后,假设您现有的 makefile 名为 makefile,您可以运行:

make FORCE_DEPS=release -f force.mk -f makefile release

由于 .FORCE 不存在,任何依赖于它的东西都会过时并被重建。

所有这些都适用于任何版本的 make; 在 Linux 上,您有 GNU Make,因此可以使用所讨论的 .PHONY 目标。

还值得考虑为什么 make 认为发布是最新的。 这可能是因为您执行的命令中有一个 touch release 命令; 这可能是因为存在一个名为“release”的文件或目录,并且没有依赖项,因此是最新的。 那么,真正的原因就...

One trick that used to be documented in a Sun manual for make is to use a (non-existent) target '.FORCE'. You could do this by creating a file, force.mk, that contains:

.FORCE:
$(FORCE_DEPS): .FORCE

Then, assuming your existing makefile is called makefile, you could run:

make FORCE_DEPS=release -f force.mk -f makefile release

Since .FORCE does not exist, anything that depends on it will be out of date and rebuilt.

All this will work with any version of make; on Linux, you have GNU Make and can therefore use the .PHONY target as discussed.

It is also worth considering why make considers release to be up to date. This could be because you have a touch release command in amongst the commands executed; it could be because there is a file or directory called 'release' that exists and has no dependencies and so is up to date. Then there's the actual reason...

北方的巷 2024-07-25 21:11:20

其他人建议使用 .PHONY,这绝对是正确的。 .PHONY 应用于输入和输出之间的日期比较无效的任何规则。 由于您没有任何 output: input 形式的目标,因此您应该对所有目标使用 .PHONY!

话虽如此,您可能应该在 makefile 的顶部为各种文件名定义一些变量,并定义具有输入和输出部分的真正 make 规则,以便您可以利用 make 的好处,即您只需实际编译合作所必需的事情!

编辑:添加示例。 未经测试,但这就是你的做法。PHONY

.PHONY: clean    
clean:
    $(clean)

Someone else suggested .PHONY which is definitely correct. .PHONY should be used for any rule for which a date comparison between the input and the output is invalid. Since you don't have any targets of the form output: input you should use .PHONY for ALL of them!

All that said, you probably should define some variables at the top of your makefile for the various filenames, and define real make rules that have both input and output sections so you can use the benefits of make, namely that you'll only actually compile things that are necessary to copmile!

Edit: added example. Untested, but this is how you do .PHONY

.PHONY: clean    
clean:
    $(clean)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文