我想知道是否有一种方法可以trap在GNU中实现make,类似于内置的BASH?
如果用户按下CTRL-C,或者make自身失败(非零退出),我想调用特定目标或宏.
从这里开始,这是一个问题的延续.问题是有一条规则从单个输入生成多个输出,并且命令很耗时,所以我们宁愿避免重新计算.现在还有一个额外的转折,我们希望保持文件不被删除为中间文件,规则涉及通配符以允许参数.
建议的解决方案是我们设置以下规则:
file-a.out: program file.in
./program file.in file-a.out file-b.out file-c.out
file-b.out: file-a.out
@
file-c.out: file-b.out
@
Run Code Online (Sandbox Code Playgroud)
然后,调用make file-c.out创建两者,我们避免make与-jswitch 并行运行的问题.到目前为止都很好.
问题如下.因为上述解决方案在DAG中建立了一个链,所以make考虑它不同; 文件file-a.out和file-b.out被视为中间文件,它们在默认情况下得到尽快删除不必要的file-c.out准备.
这里提到了一种避免这种情况的方法,它包括添加file-a.out和file-b.out作为目标的依赖关系.SECONDARY,这使它们不被删除.不幸的是,这并不能解决我的问题,因为我的规则使用了通配符模式; 具体来说,我的规则看起来更像是这样:
file-a-%.out: program file.in
./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out
file-b-%.out: file-a-%.out
@
file-c-%.out: file-b-%.out
@
Run Code Online (Sandbox Code Playgroud)
这样就可以传递一个包含在文件名中的参数,例如通过运行
make file-c-12.out
Run Code Online (Sandbox Code Playgroud)
make文档建议的解决方案是将这些作为隐式规则添加到依赖项列表中.PRECIOUS,从而防止删除这些文件.
有效的解决方案.PRECIOUS,但它也可以防止在规则失败和文件不完整时删除这些文件.有没有其他方法可以使这项工作?
解决这个问题的方法是定义一个.SECONDARY没有先决条件的目标,即:
.SECONDARY:
Run Code Online (Sandbox Code Playgroud)
通知make所有文件都应被视为辅助文件,因此不会被删除,除非make被中断或规则失败.不幸的是,这不允许选择带有通配符的规则子集以这种方式工作,所以我认为这只是一个黑客(即使它很有用).
在makefile中,我想定义一个变量,指定当前的redhat-release是否大于5.3.(此变量将作为#define传递给gcc)
到目前为止,我想出了:
# Find out which version of Red-Hat we're running
RH_VER_NUM = $(shell /bin/grep -o [0-9].[0-9] /etc/redhat-release)
RH_GT_5_3 = $RH_VER_NUM > '5.3'
Run Code Online (Sandbox Code Playgroud)
定义RH_GT_5_3的正确方法是什么?
以下是一个非常简单的makefile,似乎无法正常工作.
TEST=ON
buildbegin:
ifeq ($(TEST),ON)
@echo TEST PASSED
else
@echo TEST FAILED
endif
Run Code Online (Sandbox Code Playgroud)
无论我将TEST变量设置为什么,我的ifeq语句都会通过.我总是看到TEST PASSED.谁知道我在这里做错了什么?
编辑:
好.我的例子并不准确.我实际拥有的是:
SHELL = /bin/sh
DEFAULT_TARGS:= all all_debug
DEBUG_TARGS:= all_debug
ALL_TARGS:= $(DEFAULT_TARGS) $(DEBUG_TARGS)
.PHONY: $(ALL_TARGS)
.PHONY: buildbegin
$(ALL_TARGS): buildbegin
TEST=ON
$(DEBUG_TARGS): TEST=OFF
buildbegin:
@echo $(TEST)
ifeq ($(TEST),ON)
@echo PASSED
else
@echo FAILED
endif
Run Code Online (Sandbox Code Playgroud)
运行make all或make all_debug将导致打印"PASSED".如果我在条件之前回显$(TEST),看起来我的规则正在改变变量,但ifeq只能看到默认值.
我有一个第三方makefile,我希望在第一个构建自定义目标(T2)之前不会构建其中一个目标(T1).通常,这可以通过使T2成为T1的先决条件来实现.但是,T1在其中一个规则中使用了$ ^ ..因此,通过添加先决条件,我最终打破了构建......我所拥有的是:
T1: x y z T2
$(MAKE) -j $^;
# fails because T2 should not be passed to the make!!!
.PHONY: T2
T2:
#do some linking and prep for T1
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以确保T2在T1之前运行?(注意:上面的例子实际上有点简化.T1实际上是Linux内核makefile中的vmlinux目标,因此重写它不仅困难,而且使代码不可移植.而且,我之前无法运行T2由于某些其他依赖项而在内核上调用make).
(GNU)make使用了几个变量,如:
CC - 默认情况下为C编译器 ccCFLAGS - C编译器的标志,默认为空我想在我的中指定一些我自己的默认值Makefile.在下面的示例中,我使用条件赋值运算符?=在运行时能够覆盖我的默认值make:
CFLAGS ?= CFLAGS_my_default
CC ?= CC_my_default
print:
echo CC=$(CC) CFLAGS=$(CFLAGS)
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不会改变CC变量的值,因为原始默认值保持不变.CFLAGS由我的赋值设置,因为变量最初是空的:
$ make print
echo CC=cc CFLAGS=CFLAGS_my_default
CC=cc CFLAGS=CFLAGS_my_default
Run Code Online (Sandbox Code Playgroud)
从环境变量覆盖按预期工作:
$ CC=CC_from_env CFLAGS=CFLAGS_from_env make print
echo CC=CC_from_env CFLAGS=CFLAGS_from_env
CC=CC_from_env CFLAGS=CFLAGS_from_env
Run Code Online (Sandbox Code Playgroud)
如何更改变量的默认值,并且仍然可以在调用时覆盖它们make?
在makefile中,转义换行\允许在多个源行中拆分单行长字符串内容.但是,新线被替换为空格.源中是否存在透明换行符,不会影响字符串内容?
VAR=w\
o\
r\
d
all:
echo $(VAR)
Run Code Online (Sandbox Code Playgroud)
期望的输出是'word',但实际输出是'wor d'.
有没有办法让gmake永远不会从一组并行运行两个目标?
我不想使用.NOTPARALLEL,因为它强制整个Makefile按顺序运行,而不仅仅是所需的部分.
我还可以添加依赖项,以便一个依赖于另一个,但是然后(除了uglu)我需要构建所有它们以构建最后一个,这是不必要的.
我需要这个的原因是我的Makefile的一部分(只有一部分)调用ghc --make,它自己处理它的依赖.并且不可能在两个不同的目标上并行运行它,因为如果两个目标共享一些依赖关系,它们可以重写彼此的.o文件.(但ghc顺序调用很好.)
更新:举一个具体的例子.假设我需要在Makefile中编译两个程序:
prog1取决于prog1.hs和mylib.hs;prog2取决于prog2.hs和mylib.hs.现在,如果我调用ghc --make prog1.hs,它会检查它的依赖,既编译prog1.hs并mylib.hs到各自的目标和接口文件和链接prog1.我打电话时也是如此ghc --make prog2.hs.因此,如果两个命令并行运行,则会覆盖mylib.o另一个命令,从而导致其严重失败.
但是,我需要它既不prog1依赖prog2也不反过来,因为它们应该单独编译.(实际上它们非常庞大,有很多模块,需要编译它们都会大大减慢开发速度.)
我最近遇到了几个关于改善CMake启用C++项目周转时间的具体方面的问题(比如"我应该在什么级别分配我的构建过程?"或"cmake rebuild_cache 只是一个子目录?"),我是想知道是否有更一般的指导利用CMake提供的特定可能性.如果可能没有跨平台编译时优化,我主要对Visual Studio或基于GNU toochain的方法感兴趣.
我已经意识到并投资了一般推荐的领域来加速C++构建:
更改/优化/微调工具链
优化您的代码库/软件架构(例如,通过减少依赖关系并使用明确定义的子项目 - 单元测试)
投资更好的硬件(SSD,CPU,内存)
喜欢在这里,这里或这里推荐.所以我在这个问题上的重点是第一点.
另外我知道在CMake的Wiki中可以找到的建议:
前者只处理基础(并行make),后者主要处理如何加速解析CMake文件.
为了使这更具体一点,如果我从这里使用MSYS/GNU的100个库获取我的CMake示例,我得到了以下time测量结果:
$ cmake --version
cmake version 3.5.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
$ time -p cmake -G "MSYS Makefiles" ..
-- The CXX compiler identification is GNU 4.8.1
...
-- Configuring done
-- Generating done
-- Build files have been written to: [...]
real 27.03
user …Run Code Online (Sandbox Code Playgroud) 我有以下规则
define compile_c
$(ECHO) "CC $<"
$(Q)$(CC) $(CFLAGS) -c -MD -o $@ $<
@# The following fixes the dependency file.
@# See http://make.paulandlesley.org/autodep.html for details.
@# Regex adjusted from the above to play better with Windows paths, etc.
@$(CP) $(@:.o=.d) $(@:.o=.P); \
$(SED) -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \
$(RM) -f $(@:.o=.d)
endef
vpath %.c . $(TOP)
$(BUILD)/%.o: %.c $(BUILD)/%.pp
$(call compile_c)
vpath %.c . $(TOP) …Run Code Online (Sandbox Code Playgroud)