Makefiles are a mystery to me

blov · · 912 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m a CS student finishing up my degree, Go has been a small hobby of mine on the side. I really love using Vim with all it&#39;s plugins, and I&#39;ve used Makefiles (very simple ones) for my C++ school projects. </p> <p>Every example of a Go Makefile I&#39;ve ever seen looks like an impenetrable mess that I really don&#39;t understand and it&#39;s the only thing inhibiting me from not using Atom or GoLand anymore and going back to my sweet, beloved Vim. </p> <p>Can anyone here give me a complete idiot&#39;s guide to creating a Go Makefile? Thanks!</p> <hr/>**评论:**<br/><br/>eduncan911: <pre><p>While you don&#39;t need make for Go, it is however useful for those small edge casts for advance Go development.</p> <p>For example: </p> <p>What if you are publishing your binary cross-compiled for 5 systems? Who wants to remember all of those params and typos when you can have it all in a single make target that will loop though all 5 targets and build for each system.</p> <p>What about controlling C.I. servers like Jenkins? Who wants to become a Jenkins expert, having to grant everyone on the team direct access to modify the Jenkins runners for the slight build change - when instead you just have it run a make target. Then you can control what Jenkins runs, tests, builds and deploys all from Makefiles and batch files.</p> <p>Another is often devs don&#39;t read the README to know they need to first run go generate before go build to update any Go files before you build. You can put this in a make target.</p> <p>Another I often use is for testing: instead of teach dozens of people across different teams on how to run unit tests separately for your project than you integration tests, you could instead just have Make targets for each (tests that include Intergation or not, tests with -s short flag, etc).</p> <p>In summary, while you mostly don&#39;t need them, Makefiles can be used for slightly more complex projects requiring a few addition build steps, where you don&#39;t have to teach every single person what those build steps are, how they changed, what they adapt to as it progresses and so on.</p> <p>Instead, you just tell everyone and support <code>make build test deploy</code> and be done with it.</p> <p>The basic rules I follow is: if it is anything other than <code>go build</code>, create a Makefiles and direct everyone to run that instead. If anyone has a question as to what steps to follow, they can just open the Makefiles and see the additional steps.</p></pre>tealeg: <pre><p>99.9% of the time you don&#39;t need a makefile for go. </p></pre>MinnieAppleEater: <pre><p>the vim plugins youcompleteme and ycm-generator require it</p></pre>VirmundiUndead: <pre><p>Why not look into VSCode + Go plugin?</p></pre>MinnieAppleEater: <pre><p>ew.</p></pre>ChristophBerger: <pre><p>VSCode + Go plugin + <strong>Vim plugin</strong> then!</p></pre>MinnieAppleEater: <pre><p>I strongly dislike visual studio. </p></pre>feddasch: <pre><p>Visual Studio Code is not Visual Studio (Microsoft sucks at naming things)</p> <p>EDIT: Or you can use nvim + vim-go + nvim-completion-manager and avoid all the YCM bs</p></pre>HankDanger: <pre><p>Asking for help is a hell of a time to be an elitist.</p></pre>MinnieAppleEater: <pre><p>It was a joke, get over yourself. </p></pre>HankDanger: <pre><p>Oh okay good one.</p></pre>icholy: <pre><p>No they don&#39;t, that&#39;s just for the clang completer. You need to install gocode though.</p></pre>tealeg: <pre><p>As an emacs user, I&#39;m not even going to comment. ;-)</p></pre>MinnieAppleEater: <pre><p><a href="https://78.media.tumblr.com/dc942338a5c819cbf57c450d6daa6dd7/tumblr_o91ea0KOJP1rjmvbeo1_1280.jpg" rel="nofollow">MFW an emacs user shows up</a></p></pre>tealeg: <pre><p><a href="https://media.giphy.com/media/QKEFDjlKEuXLy/giphy.gif" rel="nofollow">MFW when I get that reaction</a></p></pre>mcandre: <pre><p>I try to structure my Makefile’s as minimally as possible, basically just a place to store oft used tasks like running gox, linters, and other extras. I think all Go projects should “just compile” and install with the standard go command line utility. If you like, here is how I currently structure Makefile’s for my Go projects:</p> <p><a href="https://github.com/mcandre/toys/tree/master/go/hello" rel="nofollow">https://github.com/mcandre/toys/tree/master/go/hello</a></p> <p>Ultimately, make falls short of being a complete command line solution for organizing builds, simply because of its dependency on low level shell details. It’s actually quite painful to write a Makefile that can delete artifacts for both UNIX and Windows developer machines. I started on a project to do that, called “meme”, but I think it’s best to use a build system that comes with crossplatform features, basic things like deleting files, getting the path to the user’s home directory and so on, so that the build tool users don’t have to rediscover and test this logic themselves. Gradle does a half decent job of this for JVM projects, and Gulp/Grunt can get by for JavaScript projects. I think in Go land, the thing to do is mage, which unfortunately requires a compilation step, but does at least hooks in fairly naturally to the Go standard library, which contains a crossplatform API for file system, shell, and path query operations.</p></pre>Justinsaccount: <pre><p>Makefile for building any go project:</p> <pre><code>all: go build </code></pre></pre>JustinCampbell: <pre><p>For those unfamiliar with make, <code>all</code> is not a special keyword, Make just uses the first target as the default, so running <code>make</code> would run <code>make all</code> in this instance. It could be called <code>foobar:</code> and would work the same way.</p></pre>dilap: <pre><p>Yeah, like other people have mentioned, usually you don&#39;t use a makefile with go, since a build-system is built into the go command (and how you build go code is defined by the directory structure, so no need for a makefile).</p> <p>What&#39;s the specific thing you&#39;re trying to do?</p></pre>raff99: <pre><p>First rule of makefiles: Never create a makefile from scratch. Always copy and modify!</p> <p>Second rule: why do I have to use tabs ?</p> <p>Joking, but actually when I was first introduced to makefiles (many, many, many, many years ago) and I asked where to start, I was told to never start from scratch, until you know what you are doing :)</p></pre>hell_0n_wheel: <pre><blockquote> <p>Always copy and modify!</p> </blockquote> <p>If you can&#39;t understand make well enough to write a Makefile, how would you know if your copypasta&#39;s any better?</p></pre>touristtam: <pre><p>Experiment with someone else&#39;s code. And don&#39;t try to re-invent the wheel. ;)</p> <p>But I agree that you need some sort of understanding of how things works to be able to use the code proficiently. </p></pre>epiris: <pre><p>The best resource is the one-page <a href="https://www.gnu.org/software/make/manual/make.html" rel="nofollow">make manual</a> here. Just control + F for any identifier you&#39;re unclear about. If it&#39;s not found than it is probably an environment variable or defined in the Makefile. I personally think Makefile&#39;s are really useful and use them in all my projects to build my docker containers and binaries.</p> <p>Although many people use it to just execute commands, the purpose of make is to map targets to a dependency graph and set of commands to <em>make</em> the target. Knowing this there is only 3 things to be confused about, what are the targets? what does a target depend on? what commands are needed to make a target? Some useful flags to answer these questions:</p> <ul> <li>Flag -r to remove all the implicit rules which makes the next flags less noisy</li> <li>Flag -d to add debug information, this will show how make is determining if targets need rebuilt.</li> <li>Flag -n to just print the commands but don&#39;t execute them, a dry run</li> <li>Flag -p provides a nice dump of makes internal state, this is useful for example to figure out the origin of a variable. Things that come from the environment will have a comment the line above them of &#34;environment&#34; where as macros will have &#34;makefile&#34;.</li> </ul> <p>If you show some examples of ones that you don&#39;t understand than people could help explain what they are doing. Knowing the above though- when you want to discover those meanings on your own you may simply:</p> <pre><code># What the heck is this? $(ACME_VAR) # control + f &#34;ACME_VAR&#34; on makefile docs, not found so lets check make -np $ make -np | grep -B1 &#39;^ACME_VAR&#39; &gt; # environment &gt; ACME_VAR = acmeval # ^ It&#39;s an environment variable # What about $(targets), it&#39;s not in docs! $ make -np | grep -B1 &#39;^targets&#39; &gt; # makefile (from &#39;Makefile&#39;, line 1) &gt; targets := acme_file1 acme_file2 # ^ It&#39;s a regular variable containing a list of space separated files # What about $(call ACME_BUILD), docs say call means execute a # function, but ACME_BUILD is not in docs or in my environment? $ make -np | grep -B1 &#39;^ACME_BUILD&#39; &gt; # makefile (from &#39;Makefile&#39;, line 24) &gt; ACME_BUILD = test -f .$(1).image || { ... shell cmds ... } # Interesting, what other functions are defined? $ make -np | grep -A1 &#39;^# makefile&#39; &gt; # makefile (from &#39;Makefile&#39;, line 1) &gt; targets := .acme.image .acme2.image &gt; -- &gt; # makefile (from &#39;Makefile&#39;, line 12) &gt; ACME_LOG = test -f .$(1).image || { ... cmds ... } &gt; -- &gt; # makefile (from &#39;Makefile&#39;, line 24) &gt; ACME_BUILD = test -f .$(1).image || { ... shell cmds ... } &gt; ... # Why is this building the entire project .. EVERY TIME! $ make -dr &gt; &lt;will print dependency resolution decisions&gt; &gt; Prerequisite ACME_FILE is older than ACME_PART. &gt; Must remake target ACME_FILE # Your makefile needs improved, make sure you can type # make ACME_FILE without rebuilds before running a # top-level target as more distance in your dependency # graph makes troubleshooting harder. </code></pre> <p>You can write horrible make files just like you can write horrible shell scripts, but well put together makefiles are pretty easy to follow after a while if you take the time to learn.</p></pre>PaluMacil: <pre><p>As someone who writes Go, I&#39;ve never seen a Go Makefile, but since you&#39;re looking for a VIM experience, I recommend using VS Code with VIM keymappings. A friend of mine uses that setup, and I don&#39;t believe he uses Make for anything. Make isn&#39;t bad, but it just isn&#39;t common in Go projects. That said, the suggestion for the one linego build make file works.</p></pre>wjkohnen: <pre><p>Go&#39;s project layout is a mess which will hopefully be fixed with Go 1.11. I cry a little whenever I have to set up a CI pipeline for a Go project. Why GoLand does not support <code>go install</code> is beyond me. But I&#39;ll probably never write an actual Makefile for Go.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

912 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传