Wilhel

Wilhel

Metaprogramming

Build System#

make is one of the most commonly used build systems, and you will find that it is usually installed on almost all UNIX-based systems. make is not perfect, but it is good enough for small to medium-sized projects. When you execute make, it will refer to the file named Makefile in the current directory.

paper.pdf: paper.tex plot-data.png
	pdflatex paper.tex

plot-%.png: %.dat plot.py
	./plot.py -i $*.dat -o $@

The left side of the colon is the build target, and the right side is the dependencies required to build it. The indented part is a section of code that is needed to build the target from the dependencies. In make, the first instruction also specifies the purpose of the build. If you use make without any parameters, this will be our final build result. Alternatively, you can use the following command to build other targets: make plot-data.png.

$ cat paper.tex
\documentclass{article}
\usepackage{graphicx}
\begin{document}
\includegraphics[scale=0.65]{plot-data.png}
\end{document}
$ cat plot.py
#!/usr/bin/env python
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-i', type=argparse.FileType('r'))
parser.add_argument('-o')
args = parser.parse_args()

data = np.loadtxt(args.i)
plt.plot(data[:, 0], data[:, 1])
plt.savefig(args.o)
$ cat data.dat
1 1
2 2
3 3
4 4
5 8

Dependency Management#

Continuous Integration System#

Exercises#

Exercise Answers

  1. Most makefiles provide a build target called clean, which does not mean that we will generate a file named clean, but that we can use it to clean files and rebuild with make. You can think of its function as "undoing" all build steps. Implement a clean target for paper.pdf in the above makefile. You need to set the build target as phony. You may find the git ls-files subcommand useful. Other useful make build targets can be found here;

     paper.pdf: paper.tex plot-data.png
         pdflatex paper.tex
    
    plot-%.png: %.dat plot.py
         ./plot.py -i $*.dat -o $@
    
    .PHONY: clean
    clean:
         Rm *. Pdf *. Aux *. Log *. Png
         #git ls-files -o | xargs rm -f
    
    
    ~$ cat makefile
    paper.pdf: paper.tex plot-data.png
      pdflatex paper.tex
    
    plot-%.png: %.dat plot.py
      ./plot.py -i $*.dat -o $@
    
    .phony: clean
    clean:
      mkdir -p Untrack
      rm -f *~ .*~
      git ls-files -o | grep -v Untrack | xargs -r mv -u -t Untrack
    
    ~$ cat .gitignore
    Untrack
    # Set git to ignore this directory, used to place untracked files
    
    
  2. There are many ways to specify version requirements. Let's learn about dependency management in Rust's build system. Most package management repositories support similar syntax. For each syntax (caret, tilde, wildcard, comparison, multiplication), build a scenario that makes sense;

  3. Git can be used as a simple CI system. In the .git/hooks directory of any git repository, you can find some files (currently inactive) that act like scripts and can be automatically executed when certain events occur. Write a pre-commit hook that executes make paper.pdf before committing and rejects your commit if the build fails. This prevents commits with unbuildable versions from being created;

  4. Create a page that can be automatically published based on GitHub Pages. Add a GitHub Action to the repository to execute shellcheck on all shell files in the repository (one method);

  5. Build your own GitHub action to execute proselint or write-good on all .md files in the repository. Enable this feature in your repository and submit a file with errors to see if it works.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.