What is the preferred way of distributing/vendoring a library that depends on my other packages?

xuanbao · · 463 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I have a library package that is supposed to be used by other Go developers. This library depends on several of my other (lower level) library packages, some of them depending on even other packages of me. The packages use major versions for API changes and I generally version all of my packages at once since I basically work on most of them at the same time. Using TravisCL I make sure that the master branch of all the packages compile together all the time.</p> <p>What would be the preferred way to distribute the libraries? Should I use a vendor folder with git submodules for each of my own libraries? Should I leave it as it is? Should I copy the dependencies into the vendor folder (ugh)?</p> <hr/>**评论:**<br/><br/>zeiko_is_back: <pre><p>You should not vendor the libraries at all! It is the responsibility of the root package which builds the final binary</p> <blockquote> <p>Vendoring should be used only for the dependencies of binaries, not for the dependencies of packages.</p> </blockquote> <p><a href="https://groups.google.com/forum/m/#!topic/golang-dev/nMWoEAG55v8" rel="nofollow">https://groups.google.com/forum/m/#!topic/golang-dev/nMWoEAG55v8</a></p></pre>tdewolff: <pre><p>Right, I think I should indeed avoid vendoring in the library. What about any cmd (in the cmd folder) in the library?</p> <p>How would I specify that v1 of the main lib works with v1 of a sublib, but that v2 of main works with v2 of sub? Or should I just mention that in the readme and people will use their vendoring solution to enforce that (ie. but the responsibility in their hands)?</p></pre>zeiko_is_back: <pre><p>Firstly I am not sure it is the best idea to have the command as a subdirectory in the library, it should be the other way round, the library should be a sub directory in the command folder. Secondly, if you make a breaking change, you should change the full package path similar to how gopkg.in handles things;</p></pre>natefinch: <pre><p>Exactly right. If you need both in the same repo, the root should be the command, the library should be a subdirectory. It is probably even better to have the library and command be separate repos, then it&#39;s more clear that you&#39;re maintaining the library for external reuse as well as for your own command... and the command can vendor everything it likes.</p></pre>karnd01: <pre><p>I have to say that although sometimes this is true, it can&#39;t be a hardened rule.</p> <p>For example I use some of @tdewolff&#39;s libraries inside of my library (which also has a command line component) to compress CSS and JavaScript and a program using my library doesn&#39;t use or know anything about the libraries it uses, and so in this case is my library needs to vendor to ensure the correct packages are used internally.</p> <p>Conversely I have an http router library which uses &#34;golang.org/x/net/websocket&#34; and &#34;golang.org/x/net/context&#34; but both are exposed (are passed or can be used) from withing the program using the router library and so is the root packages job to vendor the libraries.</p> <p>I wish there was a hard rule but ultimately I think it comes down to a case by case basis; all I can say is that when you need to vendor the packages should be checked in with your project.</p></pre>zeiko_is_back: <pre><p>I am not sure I understand why the root package cannot vendor your libraries dependencies in the first case.</p></pre>karnd01: <pre><p>If your library depends on dependency A version 1 which has method DoSomething()</p> <p>And in your root package you also use dependency A version 2 which no longer has method DoDomething , but now method DoSomethingElse()</p> <p>how is the root package supposed to know that the library needs a different version than itself because they have the same import?</p> <p>And that&#39;s just a simple example, many more versions could be at play.</p></pre>natefinch: <pre><p>This shouldn&#39;t ever happen if the dependencies change import paths for breaking changes, which it sounds like the OP is doing.</p></pre>karnd01: <pre><p>But that&#39;s the main reason vendoring exists, is so you don&#39;t have to change import paths, or have separate repo or branches for each version.. but to vendor(include) the code at the version that works.</p> <p>The above example doesn&#39;t really relate to @tdewolff as he is the maintainer of the libraries he wishes to vendor, but when you aren&#39;t... unless I&#39;m completely missing the point of vendoring, but if that&#39;s not why then people would have been including dependencies withing their repo under whatever folder and adjusting their import paths to be local, and the official vendor implementation would never have been needed.</p></pre>beeker1121: <pre><p>As @karnd01 pointed out, it really does depend.</p> <p>Personally I think you should try to decouple one library from the next as much as you possibly can. If you need to do URL normalization for instance, you could create a standalone library to do that which is then included locally into your project.</p> <p>For 3rd party libraries, the best option for stability and security seems to be saving and including them locally to your project. Ideally these libraries have very few dependencies, if any, outside of the standard lib.</p> <p>As you&#39;re looking to offer a library to other Go developers, again I think it would be ideal that the library is as self contained as possible. Would it be possible to just copy over the code from all sub-libraries into their own file/folder in the main library, making the imports direct?</p> <p>Otherwise, keeping a static version of each included library in the main seems the best option.</p></pre>karnd01: <pre><p>Hey @tdewolff, just realised I recently vendored some of your libraries in this project <a href="https://github.com/go-playground/assets" rel="nofollow">https://github.com/go-playground/assets</a></p> <p>Just wanted to day great work! And thanks!</p></pre>tdewolff: <pre><p>Thanks, great to see that it is useful to you!</p> <p>I see that you vendor all of the sub-dependencies avoiding nested dependencies, which sounds good to me. Also after reading <a href="https://blog.gopheracademy.com/advent-2015/vendor-folder/" rel="nofollow">https://blog.gopheracademy.com/advent-2015/vendor-folder/</a> and the Google groups discussion it seems that vendoring by library maintainers should be avoided.</p> <p>Perhaps I should move out the auxiliary cmd folder from the main library into its own package, then it can use vendoring and ensure non-breakable builds for the future. Unless I can put the vendor directory under github.com/username/package/cmd/cmd-name/vendor...</p></pre>karnd01: <pre><p>Putting vendor folder under the cmd.. Hmm interesting idea, I&#39;ve never tried that before.. might work.</p> <p>I agree it should be avoided, but that&#39;s not always the case.. I just had a project break because a dependency was updated with breaking changes and I neglected to vendor it and although anyone using my library before that and vendored it will continue to work fine...but anyone trying to use my library now, it&#39;s broken.</p> <p>I don&#39;t think it&#39;s such a big deal in your case because you maintain the dependencies your looking at vendoring, just there is no &#34;right&#34; or &#34;one&#34; way to vendor</p></pre>karnd01: <pre><p>First part depends on allot, but basically comes down to can your 100% trust that a program will always build when your updating your changed...if not then vendoring is probably a good idea.</p> <p>As for, should you check in dependencies in the vendor folder, the answer is yes you should; others may not agree but here is an article I wrote on why you should <a href="https://medium.com/@joeybloggs/go-vendoring-for-consistent-builds-e0dc8187606e#.t1zjxtgu0" rel="nofollow">https://medium.com/@joeybloggs/go-vendoring-for-consistent-builds-e0dc8187606e#.t1zjxtgu0</a></p></pre>

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

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