2013-03-15 88 views
0

我有一个Makefile文件,看起来像:定义变量

gator: LIB=-lm 
gatorgpu : GPU=-DG 

.... 
STATIC= 
ifdef STATIC 
    $(info CPU static)  
endif 

不过,我想有这样的:

gator: LIB=-lm 
gatorgpu : GPU=-DG 

.... 
STATIC= 
ifdef STATIC 
    ifdef GPU 
    $(info GPU static) 
    else 
    $(info CPU static) 
    endif 
endif 

所以,当有人类型$make gatorgpu STATIC=1$make gator STATIC=1然后它将根据目标(在此情况下为CPU或GPU)与静态库进行编译。不幸的是,STATIC被读取,但是GPU变量不是,所以它总是去CPU static。有没有一种优雅的方式来做到这一点?

+0

你缺少的东西是特定于目标的变量只有在生效时才会构建target_。因此,在''ifdef''这样的全局范围内测试'GPU'将不起作用,因为直到稍后make开始构建'gatorgpu'目标时才会定义它。 – MadScientist 2013-03-16 13:50:14

+0

@MadScientist我发现问题,目标特定变量不能用于此目的。但我能做些什么呢?我如何根据目标定义一个变量? – Manolete 2013-03-16 18:31:49

+0

那么,您的问题对我们来说太抽象了,无法为您提供有效的建议。创建makefile的缩减版本是很好的,但是你必须小心,不要把它切得太远,以至于所有的上下文都会丢失。大概你想做_something_,除了运行'$(info ...)',这取决于GPU的类型。如果不了解更多关于什么是什么的问题,我们不能就最佳方式给你提供建议,除非通过猜测解决方案,直到有效。干杯! – MadScientist 2013-03-16 22:44:55

回答

1

目标特定变量仅在相应的配方中可用。不同的目标可以为其配方使用不同版本的相同变量。

但如果你决定使用目标特定变量来实现任何你tyring做,这会工作:

gator: export LIB := -lm 
gatorgpu : export GPU := -DG 
STATIC ?= 0 
ACTUAL ?= 0 

export STATIC 

ifeq ($(ACTUAL),1) 
ifeq ($(STATIC), 1) 
    ifneq ($(GPU),) 
     $(info GPU static) 
    else 
     $(info CPU static) 
    endif 
endif 
endif 

.gator: 
    @echo LIB=$(LIB) GPU=$(GPU) 

.gatorgpu: 
    @echo LIB=$(LIB) GPU=$(GPU) 

gator: 
    @$(MAKE) .gator ACTUAL=1 

gatorgpu: 
    @$(MAKE) .gatorgpu ACTUAL=1 

PHONY: .gator .gatorgpu gator gatorgpu 
  • 这有调用额外的化妆(每个目标)的开销正确的一组导出变量。
  • 导出可确保为从make运行的任何子流程设置变量。

这是结果,我看到:

$ make gatorgpu 
make[1]: Entering directory `/home/ash/.scratch/make-test' 
LIB= GPU=-DG 
make[1]: Leaving directory `/home/ash/.scratch/make-test' 

$ make gator 
make[1]: Entering directory `/home/ash/.scratch/make-test' 
LIB=-lm GPU= 
make[1]: Leaving directory `/home/ash/.scratch/make-test' 

$ make gatorgpu STATIC=1 
GPU static 
make[1]: Entering directory `/home/ash/.scratch/make-test' 
LIB= GPU=-DG 
make[1]: Leaving directory `/home/ash/.scratch/make-test' 

$ make gator STATIC=1 
CPU static 
make[1]: Entering directory `/home/ash/.scratch/make-test' 
LIB=-lm GPU= 
make[1]: Leaving directory `/home/ash/.scratch/make-test' 

几个较小的修正,虽然它并不影响结果了:

  • ?=(被称为conditional variable assignment operator)执行仅当变量未分配时才分配。因此,当您运行make mytarget STATIC=1时,变量STATIC不会被分配0
  • ifeqifneq更加坚固检查相比ifdef,你可以对你有兴趣在一个特定的值进行比较的变量。
  • :=应在定期=是首选,以避免进行不必要的放缓,除非你真的需要recursively expanded variables

一个更好的办法是重构你的Makefile,你只是基于对STATIC

ifeq ($(STATIC), 1) 
gator: LIB := -lm 
gatorgpu : GPU := -DG 
else 
gator: LIB := <SOMETHING_ELSE_HERE> 
gatorgpu : GPU := <SOMETHING_ELSE_HERE> 
endif 

值定义不同的特定目标变量或规则,这样也有一个不所谓推荐的方法,包括检查$(MAKECMDGOALS)的值,其中包含调用make的目标。

ifeq ($(MAKECMDGOALS),gatorgpu) 
    GPU := -DG 
endif 
+0

@ Tuxdude我已经尝试了你的建议,但GPU变量仍然没有在Makefile到达'ifeq'部分的时候被定义... – Manolete 2013-03-16 16:36:41

+0

@Manolete - 已经更新了答案,第一次问题并不清楚:) – Tuxdude 2013-03-16 19:57:13

+0

@ Tuxdude我喜欢'$(MAKECMDGOALS)'方法。你为什么认为它不被推荐? – Manolete 2013-03-18 12:17:58

1

从你的描述,我会说下面的方法可以用来:

ifdef STATIC 
gator: LIB:=-static -lstaticlib 
gatorgpu: GPU:=-DSTATICDEF 
else 
gator: LIB:=-lm 
gatorgpu: GPU:=-DG 
endif 

你还没有确切地指出你想什么办法使用或在情况变化时STATIC定义与当它不定义,所以我已经提出了一些示例值。