如何在没有空格的Makefile中跨多行中断变量定义?

时间:2014-01-19 23:07:47

标签: makefile

考虑以下Makefile

CP = .:${HADOOP_HOME}/share/hadoop/common/lib/hadoop-auth-2.2.0.jar:\
${HADOOP_HOME}/share/hadoop/hdfs/hadoop-hdfs-2.2.0.jar:\
${HADOOP_HOME}/share/hadoop/common/hadoop-common-2.2.0.jar:\
${HADOOP_HOME}/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.2.0.jar:\
${HADOOP_HOME}/share/hadoop/mapreduce/lib/hadoop-annotations-2.2.0.jar\

all:
    echo $(CP)

正在运行make的输出是

.:/home/hduser/Hadoop/hadoop-2.2.0/share/hadoop/common/lib/hadoop-auth-2.2.0.jar: /home/hduser/Hadoop/hadoop-2.2.0/share/hadoop/hdfs/hadoop-hdfs-2.2.0.jar: /home/hduser/Hadoop/hadoop-2.2.0/share/hadoop/common/hadoop-common-2.2.0.jar: /home/hduser/Hadoop/hadoop-2.2.0/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.2.0.jar: /home/hduser/Hadoop/hadoop-2.2.0/share/hadoop/mapreduce/lib/hadoop-annotations-2.2.0.jar

观察每个:后面有空格。

有没有办法用换行符定义变量CP,但没有多余的空格替换每一个换行符?

5 个答案:

答案 0 :(得分:4)

不是真的;反斜杠 - 换行符组合定义为生成空格。但是,如果您使用的是GNU Make,则只需$(subst : ,:,$(CP))

答案 1 :(得分:2)

很抱歉这一点,但我 这会给你你想要的东西:

CP = .:${HADOOP_HOME}/share/hadoop/common/lib/hadoop-auth-2.2.0.jar:
CP:=$(CP)${HADOOP_HOME}/share/hadoop/hdfs/hadoop-hdfs-2.2.0.jar:
CP:=$(CP)${HADOOP_HOME}/share/hadoop/common/hadoop-common-2.2.0.jar:
CP:=$(CP)${HADOOP_HOME}/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.2.0.jar:
CP:=$(CP)${HADOOP_HOME}/share/hadoop/mapreduce/lib/hadoop-annotations-2.2.0.jar

这应该将下一行附加到CP的值上,与“+ =”略有不同,这会增加一个空格。

答案 2 :(得分:2)

阻止反斜杠 - 换行符不可能成为一个空格,并且之后尝试删除空格是笨拙且容易出错的(如果应该有空格怎么办?),但是你可以删除每个产生的。这具有在任何地方工作的显着优势,甚至内部函数调用。诀窍是将表达式中生成的空间嵌入到无任何内容中。

具有空/未定义$(call foo)

foo可以工作,但我们可以做得更好:变量名称可以在(GNU)Make中包含空格。分配给他们很难,但我们不想反正。那么我们可以将其缩短为$(a b)甚至$(a );在查找之前,反斜杠换行符将变为空格。但即使是一个空间也可以工作:

foo=bar$(\
)baz

最后,对于单字符变量名称,可省略括号:

foo=bar$\
baz

...最终看起来我们(完全)逃避换行而不是以某种方式使用它。只要没有人分配给“”(这甚至比使用更疯狂!),无论如何。

答案 3 :(得分:2)

最简单的解决方案是使用$\<newline>分割线。使用 为了简洁起见,遵循假路径:

CP = one$\
     two$\
     three$\
     four

all:
    echo $(CP)

输出将是&#34; onetwothreefour&#34;没有空格。这是因为GNU Make 将用一个空格替换反斜杠 - 换行符 - 空格,制作 分配给CP等同于:

CP = one$ two$ three$ four

https://www.gnu.org/software/make/manual/html_node/Reference.html#Reference:&#34; A 美元符号后跟一个美元符号以外的字符,开括号 或者open-brace将该单个字符视为变量名称。&#34; 所以$<space>对是名称为单个变量的扩展 空间特征。由于默认情况下未定义此变量,因此它将展开 到空字符串。

请注意,变量CP仍会包含$<space>对 扩大了。大多数情况下,这并不重要,但如果你的makefile 取决于使用$(value CP)来处理基础(未扩展)值, 上述技术可能会提供令人惊讶的结果。

另一种技术是清除CP的值。这需要GNU Make 3.80或以上,因为它依赖于$(value)$(eval)。它使 使用一些变量和函数进行洗涤过程。

首先,将变量empty定义为空字符串和变量 spacenewline分别包含文字空格和换行符:

empty :=

space := $(empty) $(empty)

define newline


endef

接下来,使用$(eval)以编程方式创建递归扩展变量 具有给定值:

# Define recursively expanded variable $1 with value $2.
defineVar = $(eval define $1$(newline)$2$(newline)endef)

并定义函数resubst以重复替换一个字符串 另一:

# Replace $1 with $2 in $3 until no more changes are made.
resubst = $\
  $(if $(findstring $1,$3),$\
       $(call resubst,$\
              $1,$\
              $2,$\
              $(subst $1,$2,$3)),$\
       $3)

这些足以用任意方式二维定义函数 换行和缩进。一般方法包括三个步骤:

  1. 在函数体前添加换行符;
  2. 用换行符重复替换换行符空格对;
  3. 删除所有换行符。
  4. 函数def删除换行符/空白行 来自递归扩展的$(value)的延续 通过define / endef

    定义的变量
    # $1 - name of function to redefine as a normalized single-line function.
    def = $\
      $(call defineVar,$\
             $1,$\
             $(subst $(newline),$\
                     $(empty),$\
                     $(call resubst,$\
                            $(newline)$(space),$\
                            $(newline),$\
                            $(newline)$(value $1))))
    

    现在def可用于后处理递归扩展变量。对于 例如:

    define CP
      one
      two
      three
      four
    endef
    $(call def,CP)
    

    现在,$(value CP)将返回所需的onetwothreefour

    以上是我的文章&#34; GNU Make line continuation&#34;的精华: http://drmikehenry.com/gnu-make-line-continuations/

答案 4 :(得分:0)

我使它类似于@ goodguy5

CP:=${HADOOP_HOME}/share/hadoop/common/lib/hadoop-auth-2.2.0.jar
CP+=$(CP)${HADOOP_HOME}/share/hadoop/hdfs/hadoop-hdfs-2.2.0.jar
CP+=$(CP)${HADOOP_HOME}/share/hadoop/common/hadoop-common-2.2.0.jar
CP+=$(CP)${HADOOP_HOME}/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.2.0.jar
CP+=$(CP)${HADOOP_HOME}/share/hadoop/mapreduce/lib/hadoop-annotations-2.2.0.jar