这可能吗?
更新:我需要这个,因为我从动态和静态数据中创建了一个文件。
用例:我有一个测试目录。每个C文件都会生成一个测试可执行文件。带
SRCS = $(wildcard [a-z]*.c)
我可以根据需要添加新的测试并使其生效。我会找到新的测试,编译、运行并对其进行评估。我也用git。我希望.gitignore
包含可执行文件。
就这样。如何创建.gitignore
并包括静态数据,即我想要忽略的文件(*.o
和depend
(以及动态可执行文件?
另一个GNU Make解决方案。
您可以使用define
和export
命令执行此操作,如下所示:
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" >> $@
不过,您必须小心在define块内进行扩展(即$(x)
(。
是的,你可以。正如其他人所指出的,你可能不应该,但你可以。Ash的答案有一个涉及定义命令的解决方案,但这很复杂,可能会使变量扩展到正确的值变得很棘手。另一个技巧是使用.ONESHELL:
特殊目标。
有时,您更希望将配方中的所有行都传递给shell的单个调用。通常有两种情况下这是有用的:首先,它可以通过避免额外的过程来提高makefile中的性能,在makefile中,配方由许多命令行组成。其次,您可能希望在配方命令中包含换行符(例如,您使用的解释器与SHELL完全不同(。如果。ONESHELL特殊目标出现在makefile中的任何位置,然后每个目标的所有配方行都将提供给shell的单个调用。配方行之间的换行符将被保留。
几句警告:
- 这将影响Makefile中所有食谱的工作方式
- 用于抑制输出或忽略错误的行前缀运算符(如
-
或@
(仅适用于所有配方的第一行,并对后面的所有行生效 - 一些旧版本或GNU Make(例如在Travis的CI系统上默认运行的版本,甚至在新容器中(可能会忽略此指令,从而导致奇怪的错误和gotchas。确保您了解您的目标环境
有了这些,以下是生成降价文件的方式:
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!
GNU Makefile可以执行以下操作。这很丑陋,我不会说你应该这样做,但在某些情况下我会这样做。
.profile =
#!/bin/sh.exen
#n
# A MinGW equivalent for .bash_profile on Linux. In MinGW/MSYS, the filen
# is actually named .profile, not .bash_profile.n
#n
# Get the aliases and functionsn
#n
if [ -f $${HOME}/.bashrc ]n
thenn
. $${HOME}/.bashrcn
fin
n
export CVS_RSH="ssh"n
#
.profile:
echo -e "$($(@))" | sed -e 's/^[ ]//' >$(@)
如果不存在.profile文件,make .profile
将创建该文件。
该解决方案用于应用程序仅在POSIX shell环境中使用GNUMakefile的情况。该项目不是一个存在平台兼容性问题的开源项目。
目标是创建一个Makefile,以便于设置和使用特定类型的工作空间。Makefile带来了各种简单的资源,而不需要其他特殊的归档等。从某种意义上说,它是一个shell归档。然后,一个过程可以说,把这个Makefile放在要工作的文件夹中。设置你的工作空间,输入make workspace
,然后输入make blah
,等等。
最棘手的是弄清楚该引用什么。以上内容完成了这项工作,并且接近于在Makefile中指定here文档的想法。这是否是一个通用的好主意是另一个问题。
这取决于你的决心。最好假设它不会起作用。编写要启动的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的(make
,假设这里的文档不起作用。
如果您使用Gnu-Make,请使用"define"创建多行文本变量,并使用规则将其回显到文件中。参见6.8定义的多行变量https://www.gnu.org/software/make/manual/make.html#Appending
像这样:
define myvar
# line 1nline 2nline 3n#etcn
endef
myfile.txt:
/bin/echo -e "$(myvar)) >myfile.txt
要创建它,可以使用编辑器,创建您想要的文件,在每行的末尾附加"\n",然后将它们全部连接到一个字符串中。将其粘贴到生成文件中。
在linux上使用GNU Make 3.81进行测试。
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中。一切都安排好了。这很简单。
尽可能接近heredoc:
Makefile:
switch-version:
@printf "services:n
myservice:n
build:n
args:n
my_version: $(version)n
some_other_arg: foon
image: my_imagen
" > docker-compose.override.yml
结果:
$ make switch-version version=1.2.3
$ cat docker-compose.override.yml
services:
myservice:
build:
args:
my_version: 1.2.3
some_other_arg: foo
image: my_image
$
似乎无法在Makefile中创建here文档。但是,有一个可能的解决方法。使用echo发送此处的文档数据:
all:
echo "some text" | myScript.sh