TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

An opinionated approach to GNU Make

414 点作者 DarkCrusader2超过 5 年前

28 条评论

jgrahamc超过 5 年前
For one-line recipes you can use semicolon<p><pre><code> foo.o: foo.c ; $(CC) $&lt; </code></pre> If you find $(@D) hard to remember then do $(dir $@) instead.<p>I wrote a book about GNU Make stuff (<a href="https:&#x2F;&#x2F;nostarch.com&#x2F;gnumake" rel="nofollow">https:&#x2F;&#x2F;nostarch.com&#x2F;gnumake</a>). If (and only if) you&#x27;ve read the GNU Make Manual from the FSF my book may help you. It&#x27;s not for newbies. Don&#x27;t want the book? All the articles are here: <a href="https:&#x2F;&#x2F;blog.jgc.org&#x2F;2013&#x2F;02&#x2F;updated-list-of-my-gnu-make-articles.html" rel="nofollow">https:&#x2F;&#x2F;blog.jgc.org&#x2F;2013&#x2F;02&#x2F;updated-list-of-my-gnu-make-art...</a>
评论 #21814572 未加载
评论 #21813065 未加载
cies超过 5 年前
Learned some good tricks here. There&#x27;s one that I use but did not find in the article. This one:<p><pre><code> # Borrowed from https:&#x2F;&#x2F;marmelab.com&#x2F;blog&#x2F;2016&#x2F;02&#x2F;29&#x2F;auto-documented-makefile.html .PHONY: help help: ## Display this help section @awk &#x27;BEGIN {FS = &quot;:.*?## &quot;} &#x2F;^[a-zA-Z0-9_-]+:.*?## &#x2F; {printf &quot;\033[36m%-38s\033[0m %s\n&quot;, $$1, $$2}&#x27; $(MAKEFILE_LIST) .DEFAULT_GOAL := help .PHONY: load-terraform-output load-terraform-output: ## Request the output JSON from Terraform some commands some more </code></pre> It makes Makefiles a little more self documenting.<p>Now I issue a `make` (or `make help`) to get a listing of the documented tasks. Very helpful.
评论 #21817505 未加载
评论 #21819894 未加载
评论 #21814002 未加载
评论 #21820658 未加载
评论 #21836440 未加载
评论 #21813675 未加载
sirn超过 5 年前
If you&#x27;re using GNU-specific Make features, please, please consider naming the file GNUmakefile instead of Makefile and use $(MAKE) for recursion. GNU make will happily pick up GNUmakefile before Makefile, and using $(MAKE) will remove a lot of headaches when people try to build your project outside of author&#x27;s $PREFERRED_PLATFORM.
评论 #21813499 未加载
评论 #21813509 未加载
calpaterson超过 5 年前
Terrible clickbaity title that he walks back throughout the entire post - &quot;this is not dogma&quot;. There are a couple of valid remedial notes in here (like using files as targets) but the part about changing the default shell and inserting hacks that allow you to use spaces will just baffle anyone else and probably make your Makefiles non-portable (eg macs don&#x27;t have a recent bash).
评论 #21813743 未加载
评论 #21812828 未加载
评论 #21815374 未加载
评论 #21813392 未加载
评论 #21817828 未加载
majewsky超过 5 年前
&gt; And you will never again pull your hair out because some editor swapped a tab for four spaces and made Make do insane things.<p><i>steps up to you and whispers in your ear</i><p>Or you could, you know... use a real text editor.
评论 #21812890 未加载
评论 #21815269 未加载
评论 #21819829 未加载
clarry超过 5 年前
Ok, since we&#x27;re sharing controversial opinions...<p>If you&#x27;re going to rely on a fancy shell anyway, why not just throw make out of the loop altogether? That is, unless you&#x27;re working on a big project where incremental builds really make a difference. (But IME, with a few exceptions, these are the projects that usually outgrow and abandon make anyway)<p>You can run cc via shell via make, or you can just run cc via shell. In the latter case, there&#x27;s one less program (with quirks) to fight with, and more flexibility to do stuff that you can&#x27;t easily bend make to do.
评论 #21812889 未加载
评论 #21814023 未加载
评论 #21813821 未加载
评论 #21813541 未加载
评论 #21822524 未加载
bogwog超过 5 年前
This is a good list, but I have to disagree on the tab thing.<p>&gt; And you will never again pull your hair out because some editor swapped a tab for four spaces<p>How many editors out there in 2019 will automatically replace tabs with spaces by default? Unless you&#x27;re editing makefiles in Microsoft Word or something, I don&#x27;t see why a <i>working</i> code editor will do something you didn&#x27;t tell it to do.<p>Vim, Emacs, Nano, Sublime Text, Kate&#x2F;Kdevelop, Visual Studio&#x2F;Code, Atom, Brackets, Text Mate, Scintilla&#x2F;SciTE&#x2F;Geany&#x2F;etc, Programmers Notepad, CodeBlocks, Eclipse, and JetBrains all know not to mess with your tabs.<p>Rather than switch away from tabs so you can keep using a broken editor, the correct solution is to switch an editor that works. And if you configured your editor to replace tabs with spaces, and it doesn&#x27;t give you an option to handle Makefiles differently, then that&#x27;s a broken editor.
评论 #21815741 未加载
wyldfire超过 5 年前
&gt; MAKEFLAGS += --no-builtin-rules<p>&gt; This disables the bewildering array of built in rules ...<p>Oh, wow, I totally disagree. It&#x27;s good to be opinionated -- that is, unless you&#x27;re wrong. ;)<p>In all seriousness I find it terribly useful to quickly create simple Makefiles and follow idioms like CFLAGS&#x2F;CXXFLAGS&#x2F;LDFLAGS&#x2F;LDLIBS&#x2F;etc.
评论 #21818561 未加载
评论 #21815198 未加载
rwmj超过 5 年前
I wonder if anyone has ever generalized &quot;make&quot; so that it can operate on general dependencies and tactics rather than always on files? The sort of thing I mean is that you&#x27;d be able to write:<p><pre><code> url_exists(http:&#x2F;&#x2F;example.com&#x2F;file): file rsync file example.com:&#x2F;html </code></pre> I&#x27;ve had a few attempts at this (most recently in 2013: <a href="https:&#x2F;&#x2F;people.redhat.com&#x2F;~rjones&#x2F;goaljobs&#x2F;" rel="nofollow">https:&#x2F;&#x2F;people.redhat.com&#x2F;~rjones&#x2F;goaljobs&#x2F;</a>) but never really arrived at anything satisfactory.
评论 #21813299 未加载
评论 #21813171 未加载
评论 #21813157 未加载
评论 #21814085 未加载
bilekas超过 5 年前
$(CXX) -MM $(CPPFLAGS) $&lt; | sed &#x27;s,\($<i>\)\.o[ :]</i>,\1.o $@ : ,g&#x27; &gt; $@<p>My makefiles are beautiful... To me<p>And they&#x27;re sure as sh!t not wrong, or they wouldn&#x27;t work! :)
评论 #21812749 未加载
评论 #21813457 未加载
评论 #21812748 未加载
mvaliente2001超过 5 年前
Another trick, create a `help` target:<p><pre><code> help: ## Show this help @fgrep -h &quot;##&quot; $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e &#x27;s&#x2F;\\$$&#x2F;&#x2F;&#x27; | sed -e &#x27;s&#x2F;##&#x2F;&#x2F;&#x27; foo: ## foo help # make help will print the names of the targets with # the help message following ## </code></pre> I don&#x27;t remember the source, I think I saw it in a stackoverflow question.
anon9001超过 5 年前
Experimental, but this exists: <a href="https:&#x2F;&#x2F;github.com&#x2F;mrtazz&#x2F;checkmake" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;mrtazz&#x2F;checkmake</a>
KerrickStaley超过 5 年前
My 2c on GNU Make is that you should not use it for new projects. There are better build systems, like Bazel, that are faster and produce consistent, reproducible results.<p>Make&#x27;s lack of hermeticity means that it&#x27;s easy to accidentally craft a Makefile where there are dependencies between targets that are not explicitly listed in the Makefile. When this happens, you can&#x27;t be sure that when you change an input file and run `make`, all the dependent targets will be rebuilt. This means you often have to `make clean; make` to make sure that things get correctly rebuilt.<p>Bazel also supports things like caching of artifacts so that when you build, switch branches, build, switch back, and build, it can re-use built artifacts from build #1 so that build #3 becomes a no-op. With remote caching, this can happen across computers and users; when user 1 builds at SHA 123, and then user 2 later checks out SHA 123 and does a build, user 2&#x27;s build will simply copy the cached artifacts over the network and do no local work. (There is some operational overhead to maintaining this shared cache however).<p>That said, guides like this are really helpful for maintaining and extending existing make-based build systems!
评论 #21819877 未加载
评论 #21821242 未加载
morelisp超过 5 年前
&quot;Opinionated&quot; sure is right.<p>I love make, but a lot of this advice is targeted at being able to write &quot;better&quot; shell scripts in make. I don&#x27;t recommend it. If you find yourself writing a shell for loop, you probably want instead to build a list of targets. If you find yourself wanting complex shell variable preparation, you probably instead want target-specific variables. ONESHELL is a good way to accidentally build some invisible dependencies into a recipe, and make it difficult to use custom functions or canned recipes.<p>If you do find yourself really wanting a shell, you&#x27;ll probably also want &quot;advanced&quot; features like error traps, and you&#x27;ll probably want to work with tools like shellcheck (imo critical for any shell script longer than one pipeline). Both are thwarted by baking the invocations into your make recipe. And the recipe still looks great - probably better! - if you extract any logic into a separate script (which then also opens up further possibilities, like including that tool itself in a shell pipeline in a make recipe).
schnable超过 5 年前
I liked Make due to my perceived simplicity of it. Thanks to this article, I think I&#x27;ll just use Rake next time.
评论 #21815490 未加载
评论 #21813565 未加载
anticristi超过 5 年前
I hope I&#x27;m not carried away by the example, but I would definitely not build Docker images using make. A multi-stage Dockerfile can take care of building, testing, packing, etc. source code a lot more predictably than any amount of make, by using known images of the tools involved (e.g., node, webpack, etc.).<p>Moreover, Docker&#x27;s caching implicitly allows to declare dependencies with a lot fewer headaches than make. On the downside, it is all to easy to write something that busts Docker&#x27;s cache early in the build process, rendering `docker build` super-expensive.<p>So my opinionated tooling: docker, git (to extract project versions and inject them into the image), bash (to glue everything together). Everything else belongs <i>inside</i> the Docker build.
评论 #21817528 未加载
bobbyi_settv超过 5 年前
The problem with this:<p><pre><code> out&#x2F;image-id: $(shell find src -type f) </code></pre> is that if you delete a file from src (without also modifying or adding a file), make won&#x27;t consider image-id to need rebuilding
评论 #21819705 未加载
chrismorgan超过 5 年前
Concerning creating directories:<p><pre><code> out&#x2F;foo: &gt; mkdir -p $(@D) &gt; … </code></pre> I prefer to use this pattern, which lets you have many fewer `mkdir -p …` lines in the make output when you use it a bunch of times:<p><pre><code> out&#x2F;foo: | out &gt; … out: &gt; mkdir &quot;$@&quot; </code></pre> (Here using the &gt; recipe prefix from the article, though you won’t find me doing that in real life—I like my tabs.)
评论 #21813233 未加载
knorker超过 5 年前
So force GNU make and bash as shell?<p>No thanks.
Tyr42超过 5 年前
I 120% recommend MAKEFLAGS += --no-builtin-rules<p>If I could rewrite history, I would make those builtin rules nicely, explicitly, importable. No magic when I&#x27;m trying to teach make, please.
Porthos9K超过 5 年前
I&#x27;m glad the author specified that this is mainly for GNU make, because I suspect that if I tried most of these using OpenBSD make I would have a bad time.
einpoklum超过 5 年前
To be honest - I don&#x27;t believe I&#x27;ve had to write a single Makefile since I started using CMake.<p>At most I&#x27;ve had to tinker with existing ones - in which case I wasn&#x27;t motivated to make them more elegant, as opposed to replacing them with CMake generation.
dima55超过 5 年前
FYI, there&#x27;s a patched Make providing (among other things) an interactive debugger:<p><a href="https:&#x2F;&#x2F;github.com&#x2F;rocky&#x2F;remake" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;rocky&#x2F;remake</a>
评论 #21820786 未加载
donpdonp超过 5 年前
.ONESHELL is a huge help, and replacing the recipe tab is very interesting. Great post!
juped超过 5 年前
More derangements to undo when you want it to build on a different system.
jrockway超过 5 年前
I think I have decided that I&#x27;m done with Makefiles. They are very tempting, because they follow naturally from interactive exploration. You see yourself writing a command a lot, and think &quot;I&#x27;ll just paste that into a Makefile&quot;. Now you don&#x27;t have to remember the command anymore.<p>But the problem is that building software is a lot more than just running a bunch of commands. The commands represent solutions to problems, but if the solutions aren&#x27;t good enough, you just make more problems for yourself.<p>The biggest problems I&#x27;ve had with Makefile-based builds are getting everyone using the repository the right version of dependencies, and incrementality. A project I did at work involved protos, and it was great when I was the only person working on it. I had a Makefile that generated them for Go and Typescript (gRPC-Web) and usually an incremental edit to a proto file and a re-run of the Makefile resulted in an incremental update to the generated protos. Perfect. Then other people started working on the project, and sometimes a simple proto change would regenerate the entire proto. Sometimes the protos would compile, but not actually work. The problem was that there is a hidden dependency of the proto compiler, protoc-gen-(go|ts), and the language-specific proto API version that controls the output of the proto compilation process. Make has no real way to say &quot;when I say protoc, I mean protoc from this .tar.gz file with SHA256:abc123def456...&quot; You just kind of yolo it. Yolo-ing it works fine for one person; even if your dev machine gets destroyed, you&#x27;ll probably get it working again in a day or two. As soon as you have four people working on it, every hidden dependency destroys a day of productivity. I just don&#x27;t think it&#x27;s a good idea.<p>Meanwhile, you can see how well automated dependency management systems work. Things like npm and go modules pretty much always deliver the right version of dependencies to you. With go, the compiler even updates the project definition for you, so you don&#x27;t even have to manage files. It just works. This is what we should be aiming for for everything.<p>I have also not had much luck with incremental builds in make. Some projects have a really good set of Makefiles that usually results in an edit resulting in a changed binary. Some don&#x27;t! You make a change, try out your binary, and see that it decided to cache something that isn&#x27;t cacheable. How do you debug it? Blow away the cache and wait 20 minutes for a full build. Correctness or speed, choose any 1. I had this problem all the time when I worked on a buildroot project, probably because I never understood what the build system was doing. &quot;Oh yeah, just clean out those dep files.&quot; What even are the dep files? I never understood how to make it work for me, even after asking questions and getting little pieces of wisdom that seemed a lot like cargo-culting or religion. Nobody could ever point to &quot;here&#x27;s the function that computes the dependency graph&quot; and &quot;here&#x27;s the function that schedules commands to use all your CPUs&quot;. The reason is... because it lives in many different modules that don&#x27;t know about each other. (Some in make itself, some in makefiles, some in the jobs make runs... it&#x27;s a mess.)<p>Meanwhile, I&#x27;ve also worked on projects that use a full build system that tracks every dependency required to build every input. You start it up, and it uses 300M of RAM to build a full graph. When it&#x27;s done it maxes out all your CPUs until you have a binary. You change one file, and 100% of the time, it just builds what depended on that file. You run it in your CI environment and it builds and the tests pass, the first time.<p>I am really tired of not having that. I started using Bazel for all my personal projects that involve protocol buffers or have files in more than one language. The setup is intense, watching your CPU stress the neighborhood power grid as it builds the proto compiler from scratch is surprising, but once it starts working, it keeps working. There are no magic incantations. The SHA256 of everything you depend on is versioned in the repository. It works with traditional go tools like goimports and gopls. Someone can join your project and contribute code by only installing one piece of software and cloning your repository. It&#x27;s the way of the future. Makefiles got us far, but I&#x27;m done. I am tired of debugging builds. I am tired of helping people install software. &quot;bazel build ...&quot; and get your work done.
Annatar超过 5 年前
This is chalk full of bad advice like &quot;use GNU make and bash&quot; that it&#x27;s obvious to me it was written by someone who only knows GNU&#x2F;Linux and doesn&#x27;t know UNIX (or much else). Blind leading the blind again. Don&#x27;t write GNU-specific constructs unless you have no other choice; use ksh instead of bash, it&#x27;s portable and a standard and has been long before the GNU&#x2F;Linux abomination. What nonsense I get to read...
评论 #21830097 未加载
floor_超过 5 年前
If you&#x27;re doing anything other than a unity build (single compilation unit) you&#x27;re doing it wrong.