fidry / makefile
用于解析 Makefile 并实现一些约定规则的实用工具。
1.0.2
2024-07-24 17:53 UTC
Requires
- php: ^8.1
- thecodingmachine/safe: ^2.0
Requires (Dev)
- bamarni/composer-bin-plugin: ^1.4
- ergebnis/composer-normalize: ^2.28
- infection/infection: ^0.26
- phpunit/phpunit: ^10.3
README
如果您不熟悉 Makefile,我建议您阅读这篇文章 这是一篇很好的介绍。
我是 Makefile 的大粉丝,在使用了几乎每一个我参与过的项目(无论是私人还是公共的,开源或非开源)多年后,我形成了一些关于如何编写 Makefile 的约定。
这个库旨在提供一些助手,以便进行一些约定检查,并提供一些内置的检查。
我可能会使用的最简单的 Makefile 看起来是这样的
# See https://tech.davis-hansson.com/p/make/ MAKEFLAGS += --warn-undefined-variables MAKEFLAGS += --no-builtin-rules .DEFAULT_GOAL := default # # Commands #--------------------------------------------------------------------------- # Provide a help command. In OSS projects where there is more contributors I tend to make this the # default as it's a better entry point for newcomers. # The command itself is a bit cryptic, but the result is simple: list all commands. See the following # command declarations to see how I do it. .PHONY: help help: @printf "\033[33mUsage:\033[0m\n make TARGET\n\n\033[32m#\n# Commands\n#---------------------------------------------------------------------------\033[0m\n" @fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//' | awk 'BEGIN {FS = ":"}; {printf "\033[33m%s:\033[0m%s\n", $$1, $$2}' # Technically this could be "inlined". I like to have it, but it's really up to you. When I do not # have it, I tend to have an "all" command that executes _every_ checks including CS fixing. .PHONY: default default: ## Runs the default task default: cs test # ... Declare your commands here. I often combine very specific commands with a few "meta" commands. # For example with the CS, you likely want a `php_cs_fixer` command, maybe you use `ergebnis/composer-normalize` # in which case you can have a `composer_normalize` command. Then, I have a meta command, e.g. "cs" # that executes them all. # # You can find another example bellow where I have two distinct test steps: the composer validate # and executing PHPUnit, and a final "test" meta command that does it all. # This is how a "documented" command is declared: # The first line is the PHONY target to make sure it will executed regardless of whether a file or # directory with that name does exist (here if the directory "test" exists, you likely want to # execute the _command_ test still. # The second line is the "comment" line, this is optional and when added it will include the command # in the "make help" output. # The third line is the actual rule declaration. .PHONY: test test: ## Executes all the tests test: composer_validate phpunit .PHONY: composer_validate composer_validate: ## Validates the composer.json composer_validate: composer validate --strict .PHONY: phpunit phpunit: ## Runs PHPUnit phpunit: $(PHPUNIT_BIN) vendor $(PHPUNIT) # # Rules #--------------------------------------------------------------------------- # Vendor does not depend on the composer.lock since the later is not tracked # or committed (this is not true if you have an application). vendor: composer.json $(COMPOSER) update --no-scripts touch -c $@ touch -c $(PHPUNIT_BIN) $(PHPUNIT_BIN): vendor touch -c $@
用法
在上述简单的 Makefile 中,仍然有几个东西可能会出错
- 声明命令的 2 或 3 行可能不一致
- 一个命令可能会被声明多次
- 帮助命令的输出对您很重要(例如,对您的贡献者),因此您希望确保它看起来很美观。
如果这对您很重要,那么您可以轻松创建以下测试
<?php declare(strict_types=1); namespace Acme; use Fidry\Makefile\Test\BaseMakefileTestCase; /** * @coversNothing */ class MakefileTest extends BaseMakefileTestCase { protected static function getMakefilePath(): string { return __DIR__.'/../Makefile'; } protected function getExpectedHelpOutput(): string { // It looks a bit ugly due to the coloring, but in practice still remains easy to update. // If you find it tedious to do it manually, I recommend to manually check the output // with `make help` and then copy it, e.g. via `make help | pbcopy` and then paste it here. return <<<'EOF' �[33mUsage:�[0m make TARGET �[32m# # Commands #---------------------------------------------------------------------------�[0m �[33mdefault:�[0m Runs the default task �[33mtest:�[0m Runs all the tests �[33mcomposer_validate:�[0m Validates the Composer package �[33mphpunit:�[0m Runs PHPUnit EOF; } }
进一步了解
在底层,这个包提供了一个简单的 Parser
,它将 Makefile 内容解析为一系列 Rule
(代表Makefile 规则)。
从这个结果中,很容易利用解析输出来实现更多针对您需求的定制检查。要了解更多细节,您可以查看 BaseMakefileTestCase
本身,它使用了它(没有魔法!)。