{"id":16768504,"url":"https://github.com/theofidry/makefile","last_synced_at":"2025-03-17T02:31:26.464Z","repository":{"id":63867748,"uuid":"570324854","full_name":"theofidry/makefile","owner":"theofidry","description":"Utility to parse a Makefile and implement some convention rules.","archived":false,"fork":false,"pushed_at":"2025-03-08T11:37:31.000Z","size":182,"stargazers_count":10,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-08T12:16:33.542Z","etag":null,"topics":["makefile","testing"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theofidry.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["theofidry"]}},"created_at":"2022-11-24T22:43:05.000Z","updated_at":"2025-03-08T11:36:55.000Z","dependencies_parsed_at":"2024-10-27T11:53:26.024Z","dependency_job_id":"cd4f1b68-2a0b-48ca-bd9d-21961e1b0b6b","html_url":"https://github.com/theofidry/makefile","commit_stats":{"total_commits":28,"total_committers":3,"mean_commits":9.333333333333334,"dds":0.1071428571428571,"last_synced_commit":"c2d56513b5a20581c50995e58057452348aaab96"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theofidry%2Fmakefile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theofidry%2Fmakefile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theofidry%2Fmakefile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theofidry%2Fmakefile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theofidry","download_url":"https://codeload.github.com/theofidry/makefile/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243837011,"owners_count":20355813,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["makefile","testing"],"created_at":"2024-10-13T06:11:46.413Z","updated_at":"2025-03-17T02:31:26.124Z","avatar_url":"https://github.com/theofidry.png","language":"PHP","funding_links":["https://github.com/sponsors/theofidry"],"categories":[],"sub_categories":[],"readme":"# Makefile\n\nIf you are not familiar with Makefiles, I recommend you [this blog article] which\nis a nice introduction.\n\nI am a big fan of Makefiles and after using it for years in almost every project\nI had my hand in, private or public, OSS or not, I adopted some conventions on\nhow to write a Makefile.\n\nThis library is about providing some helpers as to build some convetion checks\nas well as provide a few built-in ones.\n\nA bare-bone Makefile that I may use will look like this:\n\n```Makefile\n# See https://tech.davis-hansson.com/p/make/\nMAKEFLAGS += --warn-undefined-variables\nMAKEFLAGS += --no-builtin-rules\n\n.DEFAULT_GOAL := default\n\n\n#\n# Commands\n#---------------------------------------------------------------------------\n\n# Provide a help command. In OSS projects where there is more contributors I tend to make this the\n# default as it's a better entry point for newcomers.\n# The command itself is a bit cryptic, but the result is simple: list all commands. See the following\n# command declarations to see how I do it.\n.PHONY: help\nhelp:\n\t@printf \"\\033[33mUsage:\\033[0m\\n  make TARGET\\n\\n\\033[32m#\\n# Commands\\n#---------------------------------------------------------------------------\\033[0m\\n\"\n\t@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}'\n\n# Technically this could be \"inlined\". I like to have it, but it's really up to you. When I do not\n# have it, I tend to have an \"all\" command that executes _every_ checks including CS fixing.\n.PHONY: default\ndefault:   ## Runs the default task\ndefault: cs test\n\n# ... Declare your commands here. I often combine very specific commands with a few \"meta\" commands.\n# For example with the CS, you likely want a `php_cs_fixer` command, maybe you use `ergebnis/composer-normalize`\n# in which case you can have a `composer_normalize` command. Then, I have a meta command, e.g. \"cs\"\n# that executes them all.\n#\n# You can find another example bellow where I have two distinct test steps: the composer validate\n# and executing PHPUnit, and a final \"test\" meta command that does it all.\n\n# This is how a \"documented\" command is declared:\n# The first line is the PHONY target to make sure it will executed regardless of whether a file or\n#   directory with that name does exist (here if the directory \"test\" exists, you likely want to\n#   execute the _command_ test still.\n# The second line is the \"comment\" line, this is optional and when added it will include the command\n#   in the \"make help\" output.\n# The third line is the actual rule declaration.\n.PHONY: test\ntest:   ## Executes all the tests\ntest: composer_validate phpunit\n\n.PHONY: composer_validate\ncomposer_validate:  ## Validates the composer.json\ncomposer_validate:\n\tcomposer validate --strict\n\n.PHONY: phpunit\nphpunit:   ## Runs PHPUnit\nphpunit: $(PHPUNIT_BIN) vendor\n\t$(PHPUNIT)\n\n#\n# Rules\n#---------------------------------------------------------------------------\n\n# Vendor does not depend on the composer.lock since the later is not tracked\n# or committed (this is not true if you have an application).\nvendor: composer.json\n\t$(COMPOSER) update --no-scripts\n\ttouch -c $@\n\ttouch -c $(PHPUNIT_BIN)\n\n$(PHPUNIT_BIN): vendor\n\ttouch -c $@\n\n```\n\n\n## Usage\n\nWith the simple Makefile above, there is a few things that can easily go wrong\nstill:\n\n- The 2 or 3 lines to declare a command may not be in sync\n- A command may be declared more than once\n- The output of the help command matters to you (e.g. for your contributors) so\n  you want to make sure it looks nice.\n\nIf this is of matter to you, then you can easily create the following test:\n\n```php\n\n\u003c?php declare(strict_types=1);\n\nnamespace Acme;\n\nuse Fidry\\Makefile\\Test\\BaseMakefileTestCase;\n\n/**\n * @coversNothing\n */\nclass MakefileTest extends BaseMakefileTestCase\n{\n    protected static function getMakefilePath(): string\n    {\n        return __DIR__.'/../Makefile';\n    }\n\n    protected function getExpectedHelpOutput(): string\n    {\n        // It looks a bit ugly due to the coloring, but in practice still remains easy to update.\n        // If you find it tedious to do it manually, I recommend to manually check the output\n        // with `make help` and then copy it, e.g. via `make help | pbcopy` and then paste it here.\n        return \u003c\u003c\u003c'EOF'\n            \u001b[33mUsage:\u001b[0m\n              make TARGET\n            \n            \u001b[32m#\n            # Commands\n            #---------------------------------------------------------------------------\u001b[0m\n            \u001b[33mdefault:\u001b[0m Runs the default task\n            \u001b[33mtest:\u001b[0m\t  Runs all the tests\n            \u001b[33mcomposer_validate:\u001b[0m  Validates the Composer package\n            \u001b[33mphpunit:\u001b[0m    Runs PHPUnit\n\n            EOF;\n    }\n}\n```\n\n## Going further\n\nUnder the hood this package provides a simple [`Parser`] which parses the Makefile\ncontent into a list of `Rule`s (which represent a [Makefile rule]).\n\nFrom this it is easy to leverage the parsed output to implement some more custom\nchecks tailored to your needs. To check in more details, you can check the\n[`BaseMakefileTestCase`] itself which makes use of it (there is no magic!).\n\n\n[`BaseMakefileTestCase`]: src/Test/BaseMakefileTestCase.php\n[Makefile rule]: https://www.gnu.org/software/make/manual/html_node/Rules.html\n[`Parser`]: src/Parser.php\n[this blog article]: https://localheinz.com/articles/2018/01/24/makefile-for-lazy-developers/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheofidry%2Fmakefile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheofidry%2Fmakefile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheofidry%2Fmakefile/lists"}