我在makefile中有一些辅助目标,我想在makefile中限制内部或"私人"使用(仅限).也就是说,我希望能够在makefile中将这些目标指定为依赖项,但我想阻止将目标从命令行指定为构建目标.有点类似于privateOOP中的函数:目标是单独构建的有害(或根本没有意义).
我希望有一个特殊目标.HIDDEN或者.PRIVATE其他东西可以做到这一点,类似于.PHONY非文件目标,但我认为这不存在.该private关键字仅用于变量.
什么是保护目标仅供内部/私人使用的好/一般/优雅方式?
我能想出的最好的解决方法是检查$(MAKECMDGOALS)"不可接受的"目标,然后指出错误输出; 这似乎不优雅.我确信makefile可以被重写以避免这种情况 - 也许是一个更好的解决方案 - 但这在这里不实用.
在切割线下面......这是一个人为的例子.
虽然我正在寻找一般解决方案,但作为个人/主要目标有害的目标的一个示例是继承特定于目标的变量值:
override CFLAGS += -Wall
all : debug
%.o : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
debug : CFLAGS += -g3 -O0
release : CFLAGS += -O3
debug : CPPFLAGS += -DDEBUG
release : CPPFLAGS += -DRELEASE
debug release : foo.o bar.o main.o
$(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
clean:
-rm -f *.o debug release
.PHONY: all clean
Run Code Online (Sandbox Code Playgroud)
隐含规则重复(不必要)用于说明.随着目标debug或者release,foo.o和其他人将继承各自CFLAGS和CPPFLAGS-如果一个人make clean debug的所有对象将是一致的.但是,例如,如果有人foo.o单独构建,它将无法继承适当的标志; 例如,make clean foo.o debug你将foo.o使用默认构建CFLAGS; 然后在构建时不需要更新debug它,因此它将与具有不同优化或不同宏设置的其他对象链接.它可能适用于这种情况,但它不是预期的.将标记foo.o等标记为非法目标会阻止这种情况.
编辑:
很明显,我的例子(上图)对于我更普遍的问题来说不是一个好的选择:隐藏目标并不是解决我的例子问题的最佳方法.这是一个修改过的示例,说明了修改后的问题"如何强制执行特定于目标的值?" - 它建立在@Michael,@ Bed,@ Ross下面的评论的基础上,并允许冒充和回答这个更有限的场景.
如下面的前面的响应中所述,在这种情况下,更好的想法是创建在不同位置具有不同构建标志的对象.例如,
bin_debug/%.o : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
bin_release/%.o : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
OBJS = foo.o bar.o main.o # or $(SRCS:.o=.c)
DEBUG_OBJS = $(addprefix bin_debug/,$OBJS)
RELEASE_OBJS = $(addprefix bin_release/,$OBJS)
debug : $(DEBUG_OBJS)
release : $(RELEASE_OBJS)
debug release :
$(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
Run Code Online (Sandbox Code Playgroud)
模式规则重复的,因为我认为这是(多个"目标模式"( %)说服make所有目标都在一次建有一个配方,看到那么问题这个和这个).
所以现在,添加特定于目标的标志:
debug : CPPFLAGS += -DDEBUG
release : CPPFLAGS += -DRELEASE
Run Code Online (Sandbox Code Playgroud)
但这仍然受到影响:
make bin_debug/foo.o
Run Code Online (Sandbox Code Playgroud)
不会得到CPPFLAGS从debug.我已经接受了@ Michael的答案,因为它让我以更有帮助的方式思考问题,但也回答了我自己的一些修辞问题.
udo*_*dan 11
您可以通过使用两个连字符开始其名称来定义私有目标.
--private-target:
@echo private
public-target: --private-target
@echo public
Run Code Online (Sandbox Code Playgroud)
你可以打电话,make public-target但make --private-target会抱怨一个未知的选项:
$ make public-target
private
public
$ make --private-target
/Library/Developer/CommandLineTools/usr/bin/make: unrecognized option `--private-target'
Run Code Online (Sandbox Code Playgroud)
$ make --version
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i386-apple-darwin11.3.0
Run Code Online (Sandbox Code Playgroud)
Mic*_*ald 10
你试图解决的问题是合法的,但你正朝着解决它的更糟糕的道路前进.
当我们编写Makefile时,我们将根据目标,源和配方来描述编译工作.这项工作的进展由已经建立的一组目标来描述.现在你准确地观察了序列
make clean
make foo.o
make debug
Run Code Online (Sandbox Code Playgroud)
将生成格式不一致的对象,foo.o从而使您的构建目录处于不一致状态.但是推断出用户不应该foo.o明确构造是非常错误的.请考虑以下顺序:
make clean
# Wait for foo.o being compiles and
# interrupt the build job with a signal
make debug
Run Code Online (Sandbox Code Playgroud)
因为在使用不同的标志编译后续单元时make,foo.o它会恢复其所在的任务并保持foo.o不变,使构建目录与第一个场景中的状态相同.
因此,如果我们可以在Makefile中实现私有目标,那么这将是无效的并且可能传达错误的安全感,这甚至比不安全感本身更糟糕.您想象的解决方案也消除了使用Makefiles而不是shell脚本的最重要优势之一:Make可以轻松地继续执行中断任务.
我在回答"在Makefile中单独链接目标文件的目的是什么?"这一问题的答案中,记录了使用Makefiles的一些其他方面.
为了解决编译标志不一致的问题,我们可以安排将构建的目标存储到特殊目录中,具体取决于使用的编译标志.实现这一点可以解决问题,而不会迫使我们在恢复中断的编译工作时轻松辞职.
以下是实施路线图:
release和build.注意.在我看来,的BSD变体make有很多在一个特殊的目录写入目标更好的支持,请参阅我的回答这个问题:"如何编写使用目标和来源不同的目录中生成文件".一般来说,我喜欢的BSD变体make,因为它的文档很短,以点,它享有了很多有用的先进典型,因为操作系统的建立和港口在BSD世界建立该程序的编排.
| 归档时间: |
|
| 查看次数: |
5739 次 |
| 最近记录: |