【问题标题】:makefile "strip" function not workingmakefile“剥离”功能不起作用
【发布时间】:2014-05-13 16:46:40
【问题描述】:

我想在 makefile 中定义一个变量,它应该是项目中所有文件依赖项的列表,用一个空格分隔。我这样做:

DEP_LIST = $(shell g++ -M $(SRC_FILES) $(INC_DIRS))

输出我所有的项目依赖,例如:

main.o: src/main.cpp /usr/include/stdc-predef.h   /usr/include/c++/4.8/iostream   /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h ...

我用

过滤掉 xxx.o:
DEP_LIST_FILTERED = $(filter-out %.o:, $(DEP_LIST))

现在输出

src/main.cpp /usr/include/stdc-predef.h  /usr/include/c++/4.8/iostream  /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h ...

到目前为止看起来不错,现在我只需要使用以下方法去除双空格:

DEP_LIST_STRIPPED = $(strip $(DEP_LIST_FILTERED))

但是这没有效果,输出和之前一样。大概这与我的 shell(bash)如何处理空格有关,但我找不到任何关于它的信息。有任何想法吗?

编辑:如果它是相关的,我需要删除双空格的原因是我想以表格的形式将列表传递给 ctags

ctags $(DEP_LIST_STRIPPED) -{options}

但在当前的形式中它抱怨:

ctags: Warning: cannot open source file " /usr/include/c++/4.8/iostream" : No such file or directory

【问题讨论】:

  • 您使用的是哪个版本的makemake --version。使用 GNU make 3.81,我看到 filter-out 删除了额外的空格,甚至不需要 strip
  • 嘿,不幸的是,如果我尝试将双空格版本传递给 ctags(这是我想要的),它会说 ctags: Warning: cannot open source file " /usr/include/c++/4.8/iostream" : No such file or directory :P
  • $ make --version GNU Make 3.81
  • 我认为问题不在于您的想法。除非你的 shell、你的系统或你的 make 版本有什么特别奇怪的地方,否则还有一些你没有向我们展示的东西。请剪切并粘贴调用ctags 的makefile 部分到您的问题中,并剪切并粘贴在该错误之前进行打印的输出(向我们展示ctags 命令行)。在这一点上,我最好的猜测是该字符不是真正的空格:它是一些 i18n 字符,打印起来像空格,但不是 ASCII 空格、制表符或换行符。
  • @MadScientist 来自 gcc 文档 "如果包含的文件很多,则使用'\'-newline 将规则分成几行"

标签: bash makefile


【解决方案1】:

问题似乎是g++generates with the -M option

如果包含的文件很多,则使用'\'-newline 将规则分成几行

似乎makes $(shell ) 函数删除了换行符,但\ 字符保留在原处,从而有效地转义了一些额外的空格。如果你添加这样的规则:

echo:
    echo "$(DEP_LIST_FILTERED)"

然后make echo,您应该会看到一个列表,如下所示:

src.c /usr/include/c++/4.6/iostream \ /usr/include/c++/4.6/x86_64-linux-gnu/./bits/c++config.h \ /usr/include/c++/ 4.6/x86_64-linux-gnu/./bits/os_defines.h ...

所以我认为这里可能的解决方法就是过滤掉\ 字符串:

DEP_LIST_FILTERED1 = $(filter-out \ , $(DEP_LIST_FILTERED))

echo1:
    echo "$(DEP_LIST_FILTERED1)"

然后make echo1 显示我认为你想要什么。

【讨论】:

  • 哎呀,你说得对。我没有发现这一点的原因:我只是使用echo $(DEP_LIST_STRIPPED) 来打印我的输出,没有引号,它不会在bash 中打印退格。谢谢!
  • @JohnnyLyco 是的,shell 和 make 都有不同的引用陷阱 - 您必须在 makefile 配方中仔细考虑两者。
  • Make 将打印将要调用的命令(如果您没有在命令前添加@)。如果你看它,你会看到 shell 所看到的。如果您尝试使用 shell 的 echo 或其他方式自己打印命令行,那么您必须担心 shell 引用等问题。
  • @MadScientist $(filter-out \ :, $(DEP_LIST_FILTERED)) 对我来说有点丑陋/骇人听闻。我很乐意接受任何比这更干净的修复建议。
  • 不需要冒号顺便说一句,我之前过滤了冒号。最后完整的过程是DEP_LIST1 = $(shell g++ -M $(SRC_FILES) $(INC_DIRS))DEP_LIST2 = $(filter-out %.o:, $(DEP_LIST1))DEP_LIST3 = $(filter-out \, $(DEP_LIST2))DEP_LIST = $(strip $(DEP_LIST3)) - 我敢肯定它可以更简洁但它有效!
猜你喜欢
  • 2017-04-12
  • 2015-08-22
  • 2018-08-25
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多