28

这有可能吗?怎么做?

更新:我需要这个,因为我从动态和静态数据创建了一个文件。

用例:我有一个测试目录。每个 C 文件都会生成一个测试可执行文件。和

SRCS = $(wildcard [a-z]*.c)

我可以根据需要添加新的测试,make 会找到新的测试、编译、运行和 valgrind。我也使用 git。我想.gitignore包括可执行文件。

所以在那里。如何创建.gitignore和包含静态数据,即我想被忽略的文件(*.odepend)以及动态的可执行文件?

4

7 回答 7

31

另一个 GNU Make 解决方案。

您可以使用defineandexport命令执行此操作,如下所示:

define GITIGNOREDS
*.o
depend
endef

SRCS = $(wildcard [a-z]*.c)
EXES = $(SRCS:.c=)


export GITIGNOREDS
.gitignore: $(SRCS)
    echo $(EXES) | sed 's/ /\n/g' > $@
    echo "$$GITIGNOREDS" >> $@

不过,您必须小心$(x)在定义块内进行扩展(即)。

于 2011-09-11T10:08:34.230 回答
26

是的你可以。正如其他人所说,您可能不应该这样做,但您可以。Ash 的答案有一个涉及定义命令的解决方案,但这很麻烦,并且可能难以将变量扩展为正确的值。另一个技巧是使用.ONESHELL:特殊目标

有时您希望将配方中的所有行都传递给 shell 的单个调用。通常在两种情况下这很有用:首先,它可以通过避免额外的进程来提高配方包含许多命令行的 makefile 的性能。其次,您可能希望在您的配方命令中包含换行符(例如,您可能正在使用一个非常不同的解释器作为您的 SHELL)。如果 .ONESHELL 特殊目标出现在 makefile 中的任何位置,则每个目标的所有配方行都将提供给 shell 的单个调用。配方行之间的换行符将被保留。

几句警告:

  • 这将影响Makefile 中所有配方的工作方式。
  • 行前缀运算符,例如-@抑制输出或忽略错误,仅适用于所有配方的第一行,并对后面的所有行生效。
  • 一些旧版本或 GNU Make(例如在 Travis 的 CI 系统上默认运行的版本,甚至在新容器中)可能会忽略该指令,从而导致奇怪的错误和陷阱。确保您了解您的目标环境。

有了这个,下面是生成降价文件的样子:

SHELL = bash
.ONESHELL:
MYVAR = "Some Title"

file.md:
    cat <<- EOF > $@
        $(MYVAR)
        ========

        This stuff will all be written to the target file. Be sure
        to escape dollar-signs and backslashes as Make will be scanning
        this text for variable replacements before bash scans it for its
        own strings.

        Otherwise formatting is just as in any other bash heredoc. Note
        I used the <<- operator which allows for indentation. This markdown
        file will not have whitespace at the start of lines.

        Here is a programmatic way to generate a markdwon list all PDF files
        in the current directory:

        `find -maxdepth 1 -name '*.pdf' -exec echo " + {}" \;`
    EOF

请注意,另一个问题是 Make 会跳过空行。如果在heredoc 的内容中有一个空白行很重要,您需要确保使用适当级别的空格缩进该行以匹配heredoc,否则Make 会吃掉它,甚至不会将它传递给cat!

于 2016-03-22T07:41:26.457 回答
7

GNU Makefile 可以做以下事情。这很丑陋,我不会说你应该这样做,但我在某些情况下会这样做。

.profile = \
\#!/bin/sh.exe\n\
\#\n\
\# A MinGW equivalent for .bash_profile on Linux.  In MinGW/MSYS, the file\n\
\# is actually named .profile, not .bash_profile.\n\
\#\n\
\# Get the aliases and functions\n\
\#\n\
if [ -f \$${HOME}/.bashrc ]\n\
then\n\
  . \$${HOME}/.bashrc\n\
fi\n\
\n\
export CVS_RSH="ssh"\n  
#
.profile:
        echo -e "$($(@))" | sed -e 's/^[ ]//' >$(@)

make .profile如果不存在,则创建一个 .profile 文件。

此解决方案用于应用程序仅在 POSIX shell 环境中使用 GNU Makefile 的情况。该项目不是平台兼容性问题的开源项目。

目标是创建一个便于设置和使用特定类型工作空间的 Makefile。Makefile 带来了各种简单的资源,而不需要其他特殊存档等。从某种意义上说,它是一个 shell 存档。然后,程序可以说将这个 Makefile 放到要工作的文件夹中。设置您的工作区 enter make workspace,然后执行 blah 、 entermake blah等。

可能会变得棘手的是弄清楚要引用什么。以上完成了这项工作,并且接近在 Makefile 中指定 here 文档的想法。对于一般用途来说,这是否是一个好主意是另一个问题。

于 2011-07-21T20:28:41.543 回答
5

这取决于你的决心。最好假设它不起作用。编写一个要启动的 shell 脚本,而不是 makefile 中的 here 文档。

失败 1

heredoc:
    cat - <<!
    This is the heredoc.
    !

这会产生:

cat - <<!
This is the heredoc.
make: This: No such file or directory
make: *** [heredoc] Error 1

每行单独执行 - 哎呀。

失败 2

heredoc:
    cat - <<! \
    This is the heredoc.\
    !

这产生了:

cat: This: No such file or directory
cat: is: No such file or directory
cat: the: No such file or directory
cat: heredoc.!: No such file or directory
make: *** [heredoc] Error 1

可能有一些方法使用特定版本的 make(例如,GNU make 可以在单个子 shell 中执行所有命令以执行某个操作,我相信),但是您必须指定您的可移植性要求。对于常规(比如 POSIX-compliant)make,假设这里的文档不起作用。

于 2011-05-03T17:08:59.977 回答
4

如果您使用 Gnu Make,请使用“定义”来创建多行文本变量,并使用规则将其回显到文件中。参见https://www.gnu.org/software/make/manual/make.html#Appending的 6.8 定义多行变量

像这样:

  define myvar
  # line 1\nline 2\nline 3\n#etc\n
  endef

  myfile.txt:
         /bin/echo -e "$(myvar)) >myfile.txt

要创建它,使用编辑器会有所帮助,创建您想要的文件,将“\n”附加到每一行的末尾,然后将它们全部连接成一个字符串。将其粘贴到您的 makefile 中。

在 Linux 上使用 GNU Make 3.81 进行测试。

于 2014-11-10T18:41:28.937 回答
0
SRCS = (wildcard [a-z]*.c)
EXES = $(SRCS:.c=)
GITIGNOREDS = *.o depend

.gitignore: $(SRCS)
        echo $(EXES) | sed 's/ /\n/g' > $@
        echo $(GITIGNOREDS) | sed 's/ /\n/g' > $@

重要的是GITIGNOREDS线路。我会更喜欢heredoc

GITIGNOREDS = <<EOT
*.o
depend
EOT

但我也很高兴有一个文件列表,由空格分隔,以及一个将空格转换为换行符的 sed 脚本。

按照 Ryan V. Bissell 的建议进行编辑:使用添加到 gitignore 的单独测试子目录。一切都到位了。这很简单。

于 2011-05-05T11:39:37.040 回答
0

似乎没有办法在 Makefile 中做一个 here-document。但是,有一个可能的解决方法。使用 echo 发送 here-document 数据:

all:
    echo "some text" | myScript.sh
于 2017-05-09T16:19:00.460 回答