我正在Markdown写几本书。我的文件结构如下:
Description
writing/
Makefile 1. main Makefile (shown below)
book.template 2. pandoc template that uses TITLE
books/
current.txt 3. contains the current book name
book1/
meta.mk 4. sub-Makefile that defines TITLE
chapters/
01.md 5. actual text of book 1, chapter 1
02.md
...
book2/
meta.mk
chapters/
01.md
02.md
...
...
这是Makefile:
CURR_BOOK_NAME:=$(shell cat books/current.txt)
CURR_BOOK_DIR:=books/$(CURR_BOOK_NAME)/
CURR_CHAPTERS_DIR:=$(CURR_BOOK_DIR)chapters/
CURR_CHAPTERS:=$(wildcard $(CURR_CHAPTERS_DIR)*.pdf)
# suppose that each meta.mk defines the TITLE variable
include $(CURR_BOOK_DIR)/meta.mk
all: pdfs
...
pdfs: $(CURR_CHAPTERS)
%.pdf: %.md book.template
pandoc -o $@ $< ... \
--template=book.template \
--variable=title:$(TITLE)
我通常一次只能处理一本书。因此,使用当前书籍的名称创建文件current.txt
很方便。现在我只需输入make
即可将当前书籍编译为PDF,方法是在current.txt
中读取Makefile。请注意,PDF取决于特定于书籍meta.mk
中定义的变量。
偶尔,我想对另一本书做一个小改动。我应该如何修改Makefile,以便我不必更新current.txt
然后每次更改它?更确切地说,我想检测在命令行上传递给make
的参数是伪目标还是路径。例如,我希望这个过程看起来像:
$ cat books/current.txt
book1
$ ls books/*/chapters/*
books/book1/chapters/01.md books/book1/chapters/02.md
books/book2/chapters/01.md books/book2/chapters/02.md
$ make
pandoc -o books/book1/chapters/01.pdf ... --variable=title:One
pandoc -o books/book1/chapters/02.pdf ... --variable=title:One
$ ls books/*/chapters/*
books/book1/chapters/01.md books/book1/chapters/02.md
books/book1/chapters/01.pdf books/book1/chapters/02.pdf
books/book2/chapters/01.md books/book2/chapters/02.md
$ make books/book2/chapters/01.pdf
pandoc -o books/book2/chapters/01.pdf ... --variable=title:Two
$ ls books/*/chapters/*
books/book1/chapters/01.md books/book1/chapters/02.md
books/book1/chapters/01.pdf books/book1/chapters/02.pdf
books/book2/chapters/01.md books/book2/chapters/02.md
books/book2/chapters/01.pdf
建议在命令行上覆盖变量:
make CURR_BOOK_NAME=book2 books/book2/chapters/01.pdf
但是,我认为这太冗长和冗余,因为它需要重复两次书的名称,并输入一次内部变量CURR_BOOK_NAME
的名称。
这是一个简化的例子。请询问您是否要查看实际的Makefile。另外,请随意澄清问题标题。
答案 0 :(得分:1)
之前发布了以下有价值的答案,但在评论中对优缺点进行了简短讨论之后,回答者将其删除并留下了一个downvote,而没有选择评论。我在这里reproduce以防万一它可以帮助其他用户。我仍然在寻找一种“更复杂”的解决方案,它可以避免冗余并允许构建单独的章节。
一个简单的解决方案是将您的Makefile
复制到新文件,例如book.mak
并删除第一行CURR_BOOK_NAME:=$(shell cat books/current.txt)
。然后像这样创建新的Makefile:
CURR_BOOK_NAME:=$(shell cat books/current.txt)
current:
$(MAKE) -f book.mak CURR_BOOK_NAME="$(CURR_BOOK_NAME)"
book1:
$(MAKE) -f book.mak CURR_BOOK_NAME="book1"
book2:
$(MAKE) -f book.mak CURR_BOOK_NAME="book2"
然后当book2当前更改book1中的内容时,只需键入make book1
。 makefile将找出更改内容并更新它。
如果您真的希望能够输入make books/book2/chapters/01.pdf
,那么它会更复杂一些。
答案 1 :(得分:1)
我会对其进行重组,以便从每个项目的顶级目录中引用顶级Makefile。将其视为每个图书项目的支持库并相应地进行管理。
单个Makefile可以像
一样简单include /usr/local/share/lib/bookmaker/main.mk
...假设您调用库bookmaker
并将其安装在此路径中。 (它也可以存在于主目录下的某个树中。)
我认为这是对事实上的项目结构的规范化,而不仅仅是一种新的安排。您的个人书籍已经依赖于博彩公司Makefile,但强制它们存在于物理子目录中,这使得在实验克隆上工作变得更加困难(假设您将每本书作为单独的Git项目进行管理 - 如果没有,切换到此模型可能会使更有意义!)。您还可以摆脱现在显然不再需要的“当前”状态文件的轻微但令人讨厌的不便。