我正在使用GNU make,并且在项目中包含第三方库,如果CFLAGS在调用环境时在环境中定义了构建系统,则该系统会变得狂暴.我喜欢CFLAGS在我的环境中定义其他原因.正在从另一个makefile调用库的构建,所以我说例如:
的3rdParty:
$(MAKE) -f Makefile.3rdparty
但是我想确保CFLAGS在第三方Makefile上调用make时没有设置.我能找到的最近的事情就是说:
CFLAGS:=
但是这仍然留CFLAGS在环境中,它只是一个空字符串.除了做一些可怕的事情,比如说:
的3rdParty:
bash -c "unset CFLAGS; $(MAKE) -f Makefile.3rdparty"
是否有一种简单的方法可以CFLAGS从我的主要makefile中"取消设置" 变量,以便在调用第三方库时环境中根本不存在该变量?
我正在开发一个中型项目,其中包含几个具有相互依赖性的库,我最近将其转换为使用非递归makefile构建.我的下一个目标是同时从同一源代码树中构建调试和发布版本(make debug; make release).我的第一步是制作包含正确构建标志的调试和释放目标.我使用目标特定变量做到了这一点,如下所示:CXXFLAGS = -Wall -Wextra -Werror -DLINUX
CXX_DEBUG_FLAGS=-g3 -DDEBUG_ALL
CXX_RELEASE_FLAGS=-O3
.PHONY: debug
debug: CXXFLAGS+=$(CXX_DEBUG_FLAGS)
debug: build
.PHONY: release
release: CXXFLAGS+=$(CXX_RELEASE_FLAGS)
release: build
Run Code Online (Sandbox Code Playgroud)
这工作正常,但您只能同时构建调试或发布,而不是两者.同时,我并不是说在同一个构建过程中,我的意思是在同一个源代码树中背靠背(make debug; make release).为了做到这一点,我需要将目标文件放在一个特定于调试/发布的目录中,这样它们就不会相互覆盖,我需要用'D'来修改调试目标二进制文件名.我虽然这很容易,因为我可以再次使用目标特定变量,如下所示:CXXFLAGS = -Wall -Wextra -Werror -DLINUX
CXX_DEBUG_FLAGS=-g3 -DDEBUG_ALL
CXX_RELEASE_FLAGS=-O3
.PHONY: debug
debug: CXXFLAGS+=$(CXX_DEBUG_FLAGS)
debug: MODULE_BLD_TYPE=D
debug: OUT_DIR=debug_obj
debug: build
.PHONY: release
release: CXXFLAGS+=$(CXX_RELEASE_FLAGS)
release: MODULE_BLD_TYPE:=
release: OUT_DIR=release_obj
release: build
.PHONY: build
build: TARGET_NAME=HelloWorld$(MODULE_BLD_TYPE)
build: TARGET_BUILD_DIR=$(PROJECT_ROOT_DIR)/$(OUT_DIR)
build: TARGET_BUILD_OBJS=$(addprefix $(TARGET_BUILD_DIR)/,$(SOURCES:.cpp=.o))
build: $(TARGET_NAME)
Run Code Online (Sandbox Code Playgroud)
你让专家读这个已经知道这不会起作用,因为你不能使用目标特定变量来创建实际目标.它们对我的CXXFLAGS var工作正常,因为该变量未在目标名称中使用.
是否有使用非递归makefile管理调试/发布版本的设计模式和/或最佳实践?具体来说,如何构建目标文件目录路径和目标名称(根据目标构建目标)?
我期待看到下面的makefile创建的文件foo1和foo3.但是只创建了一个文件foo3.对我而言,似乎罐头配方make-foo被make简单地忽略了.目标foo1和foo2(空配方)的调试结果是相同的.
# why canned recipe doesn't work ?
# http://www.gnu.org/software/make/manual/make.html#Canned-Recipes
define make-foo =
echo making $@
touch $@
endef
.PHONY: all
all: foo1 foo2 foo3
# foo1 is not created, but why ?
.PHONY: foo1
foo1:
$(make-foo)
# debug output similar to foo1
.PHONY: foo2
foo2:
# this works
.PHONY: foo3
foo3:
echo making $@
touch $@
Run Code Online (Sandbox Code Playgroud)
跑步:
xxxx@xxxx:/dev/shm$ make -dRr
GNU Make 3.81
Copyright (C) 2006 Free …Run Code Online (Sandbox Code Playgroud) 给定以冒号分隔的路径列表,使用GNU Make获取以空格分隔的列表非常简单:
CPATHS := /usr/bin/foo:/usr/bin/baz:/usr/bin/baz
SPATHS := $(subst :, ,$(CPATHS))
Run Code Online (Sandbox Code Playgroud)
但是,我找不到朝着相反方向前进的好方法.以下hack确实有效(至少在安装了sed的情况下)但是我很确定只有使用Make的内部函数才能有更好的解决方法.
SPATHS := /usr/bin/foo /usr/bin/baz /usr/bin/baz
CPATHS := $(shell echo $(SPATHS) > tmp; sed 's/ \+/:/g' tmp; rm tmp)
Run Code Online (Sandbox Code Playgroud) 什么设置适用于GNU在Windows上进行并行作业(-j)?
我已经尝试使用MinGW make 3.81将shell设置为cmd.exe,这适用于创建多个进程但是使用"等待作业"消息失败.
这可以工作,什么是最好的设置?(MinGW/Cygwin/???)有人能指出一个可以测试的工作示例吗?
我想写一些像正则表达式:
SRC:="a.dat.1 a.dat.2"
$(SRC): %.dat.%: (\\1).rlt.(\\2)
dat2rlt $^ $@
Run Code Online (Sandbox Code Playgroud)
这样a.dat.1和a.dat.2将给出a.rlt.1和a.rlt.2.
在GNU Make info页面中,它显示"%只能使用一次".
在GNU Make中有一些技巧可以实现吗?
鉴于此非常简单Makefile:
all:
@mkdir -pv test/{a,b}
Run Code Online (Sandbox Code Playgroud)
我在OS X 10.6.8和CentOS 5.5上得到了这个输出:
mkdir: created directory `test'
mkdir: created directory `test/a'
mkdir: created directory `test/b'
Run Code Online (Sandbox Code Playgroud)
但是在Ubuntu 11.04上我得到了这个:
mkdir: created directory `test'
mkdir: created directory `test/{a,b}'
Run Code Online (Sandbox Code Playgroud)
mkdir -pv test/{a,b}在所有平台上的shell中手动运行命令会产生预期的结果.
GNU Make的版本在所有平台上都是相同的:
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 is built for [PLATFORM]
Run Code Online (Sandbox Code Playgroud)
在Ubuntu下有什么不同,为什么shell扩展不在那里工作?
Makefile当我这样做时,有没有办法回应递归的每个目标所花费的(系统,用户,真实)时间make all?
我想以更细粒度的方式对项目的编译进行基准测试time make all.理想情况下,它会回显执行目标的树,每个树都有在其所有依赖项中花费的时间.如果它可以使用-j(并行制作)也会很棒.顺便说一下,我Makefile是非递归的(不会make为每个主要目标产生另一个实例).
谢谢!
好吧,我坚持这个,我不知道我做错了什么.在一个更复杂的makefile上,一切都很好,但突然之间我得到了"Missing separator"错误.我能够将它分离到一个非常简单的场景:
define push_dir
$(info ${1})
endef
define pop_dir
$(info ${1})
endef
define include_submake
$(call push_dir,${1})
$(call pop_dir,${1})
endef
Run Code Online (Sandbox Code Playgroud)
include test.mk
INITIAL_SUBMAKE:= includeme.mk
$(call include_submake,${INITIAL_SUBMAKE})
process:
@echo Processed...
Run Code Online (Sandbox Code Playgroud)
并输出:
C:\project>make -f Simple process
includeme.mk
includeme.mk
Simple:4: *** missing separator. Stop.
Run Code Online (Sandbox Code Playgroud)
includeme.mk实际上并不存在.我不知道这里出了什么问题我尝试了很多东西.如果我将include_submake的调用包围在这样的信息中:
$(info $(call include_submake,${INITIAL_SUBMAKE}))
Run Code Online (Sandbox Code Playgroud)
丢失的分隔符错误消失了.另外如果在include_submake定义中我只调用其中一个函数,它工作正常.另外,如果我直接调用函数而不是调用它,include_submake它也可以正常工作:
include test.mk
INITIAL_SUBMAKE:= includeme.mk
$(call push_dir,${INITIAL_SUBMAKE})
$(call pop_dir,${INITIAL_SUBMAKE})
process:
@echo Processed...
C:\project>make -f Simple process
includeme.mk
includeme.mk
Processed...
Run Code Online (Sandbox Code Playgroud)
我觉得我在这里忽略了一些基本的东西.谢谢你的帮助.
我想定义一个shell函数
#!/bin/sh
test ()
{
do_some_complicated_tests $1 $2;
if something; then
build_thisway $1 $2;
else
build_otherway $1 $2;
fi
}
Run Code Online (Sandbox Code Playgroud)
以这种方式,我可以在我的Makefile的每个规则中使用它,例如:
foo: bar
test foo baz
Run Code Online (Sandbox Code Playgroud)
要清楚,我希望shell函数成为Makefile的一部分.这样做最优雅的方法是什么?如果您可以在不递归调用make的情况下执行此操作,则可获得积分.
背景:我的实际问题是make -n产生一个非常长且不可读的输出.每个规则使用几乎相同的不可读shell命令序列,并且有许多规则.上述解决方案将使输出make -n更有用.