{"id":23470882,"url":"https://github.com/xanders/make-help","last_synced_at":"2025-04-14T17:22:08.865Z","repository":{"id":40433414,"uuid":"318333598","full_name":"Xanders/make-help","owner":"Xanders","description":"Just another one tool for simple and beautiful `make help` command","archived":false,"fork":false,"pushed_at":"2022-05-09T04:24:05.000Z","size":127,"stargazers_count":32,"open_issues_count":3,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-28T06:02:54.313Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Crystal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Xanders.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-03T22:14:13.000Z","updated_at":"2025-01-24T01:28:58.000Z","dependencies_parsed_at":"2022-08-09T20:20:28.739Z","dependency_job_id":null,"html_url":"https://github.com/Xanders/make-help","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xanders%2Fmake-help","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xanders%2Fmake-help/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xanders%2Fmake-help/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xanders%2Fmake-help/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Xanders","download_url":"https://codeload.github.com/Xanders/make-help/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248923854,"owners_count":21183983,"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":[],"created_at":"2024-12-24T16:17:11.429Z","updated_at":"2025-04-14T17:22:08.835Z","avatar_url":"https://github.com/Xanders.png","language":"Crystal","funding_links":[],"categories":[],"sub_categories":[],"readme":"# make-help\n\nIs it crazy enough to show the `Makefile` help via [Docker](https://www.docker.com)? This is exactly what I did. 😋\n\n## Why?\n\nI often use [`make`](https://www.gnu.org/software/make) as a uniform way to document tasks for cross-language projects.\nFor example, `make test` in any project will run tests, `make build` will always rebuild Docker images.\nIn any project, the first thing I do is go to the `Makefile` to remember how to work here.\n\nBut it will be much easier not to read the entire `Makefile`, but to run `make help` or even just `make` and see all the information I need.\n\nSo this project aims to provide a very simple way to achieve it.\n\n## How?\n\nJust add this to the top of the `Makefile`:\n\n```make\n# Show this help\nhelp:\n  @cat $(MAKEFILE_LIST) | docker run --rm -i xanders/make-help\n```\n\nThat's all. Now you can use both `make` and `make help` commands. No additional dependencies are required (with except for [Docker](https://www.docker.com), obviously).\n\nAdd comments to all public tasks. You can use multi-line comments as well as code examples in `` `backticks` ``.\nNo special syntax required, just use single `#` as usual.\n\nThanks to [@muuvmuuv](https://github.com/muuvmuuv) ([#1](https://github.com/Xanders/make-help/issues/1)), you can also add sections to a large `Makefile` like this:\n\n```make\n##\n## Section name (one line)\n##\n```\n\n**Please see the example in [this project `Makefile`](Makefile).**\n\n![Screenshot with this project help output](screenshot.png)\n\n*Screenshot from Windows Terminal, so this is a relatively platform-independent solution.*\n\n## What??\n\n`@` before `cat` means \"Do not show this line when I run the task\".\n\n`MAKEFILE_LIST` is a variable with current `Makefile` path. `$(...)` used to substitute variable name with it's value.\n\n`cat` with pipe (`|`) puts the file contents into the next command.\n\n`--rm` means \"Delete Docker container immediately after finishing\".\n\n`-i` means \"Allow to get information from Docker's standard input\".\n\n`xanders/make-help` is a name of [the image at Docker Hub](https://hub.docker.com/r/xanders/make-help).\n\nSo we grab current `Makefile` and push to the container with a program.\nIt processes the file and outputs usage help with the tasks comments.\n\nThe image [is built from scratch](https://docs.docker.com/develop/develop-images/baseimages/#create-a-simple-parent-image-using-scratch)\nand is as small as even possible in Docker: 932.34 **KB** compressed (two layers).\n\nI used [extra-fast](https://github.com/kostya/crystal-benchmarks-game) [Crystal programming language](https://crystal-lang.org) with [static linking](https://crystal-lang.org/reference/using_the_compiler/index.html#creating-a-statically-linked-executable) on [Alpine-based compiler](https://crystal-lang.org/2020/02/02/alpine-based-docker-images.html) at [build stage](https://docs.docker.com/develop/develop-images/multistage-build).\n\nSo it will be fast enough and also tiny on disk.\n\n## Alternatives\n\nThere is a lot of similar projects in different languages, for example:\n\n* A **lot** of [Bash solutions](https://gist.github.com/prwhite/8168133)\n* [Go](https://github.com/Songmu/make2help)\n* [JavaScript](https://github.com/ianstormtaylor/makefile-help)\n* [Python](https://github.com/mrdor44/MakeHelp)\n* [Perl](https://github.com/christianhujer/makehelp)\n\nYou even can use this one-line Ruby version:\n\n```make\n# Show this help\nhelp:\n  @cat $(MAKEFILE_LIST) | ruby -e \"input = ARGF.read; indent = input.scan(/^\\w[^:]*:/).map(\u0026:size).max + 1; puts \\\"\\nUsage: make \\033[32m\u003ccommand\u003e\\033[0m [ARGUMENT1=value1] [ARGUMENT2=value2]\\n\\nCommands:\\n\\\", input.scan(/((?:^# .+\\n)+)^([^:]+):/).map { |comments, command| \\\"\\n \\033[32m#{command.ljust indent}\\033[0m#{comments.lines.first.strip}#{comments.lines[1..-1].map { |comment| \\\"\\n \\\" + ' ' * indent + comment }.join}\\\".gsub(/\\`.+?\\`/) { |code| \\\"\\033[36m#{code}\\033[0m\\\" } }, ''\"\n```\n\nMost of them are 1) hard to read (Bash, Ruby one-liner), or 2) add dependencies to the project (language `X` libraries).\n\nDocker is de-facto standard tool for developers nowadays, so I don't think of it as of dependency.\n\nSo I think my solution may be useful in real-world. Feel free to use it in your projects! 🖖","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxanders%2Fmake-help","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxanders%2Fmake-help","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxanders%2Fmake-help/lists"}