CGO: Why do I need to link when building a static lib?

agolangf · · 403 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>If I have a dependency between files first.c and second.c, I can still build a static library first.a, which is just a packaged form of first.o. </p> <p>But if I try to then build a go library that uses first.a I get a linker error for the missing symbols of second.</p> <p>eg. go install -buildmode=c-archive uses_first.go </p> <p>Now, were I building a executable, it would make perfect sense to reject this on the basis of unresolved symbols. But I&#39;m not building an executable, I&#39;m building another static lib. AFAIK there should be no reason to complain about unresolved dependencies on a lib.</p> <p>At the end of the day I&#39;m looking to link everything together, but I can&#39;t get past this intermediate step.</p> <hr/>**评论:**<br/><br/>mdempsky: <pre><p>I believe your question can be summarized as why doesn&#39;t this file build:</p> <pre><code>package p // extern int foo(); import &#34;C&#34; var x = C.foo() </code></pre> <p>The short answer is during package compilation, cgo links the object files into a stub executable so that it can analyze the executable. If <code>foo</code> is not defined, then this stub link will fail. The expected use case is that packages should provide <code>#cgo LDFLAGS</code> directives that link in any necessary dependencies so that the stub executable links okay.</p> <p>It looks like we could perhaps prevent this failure (e.g., link the stub executable with something like <code>--unresolved-symbols=ignore-all</code>), but I would expect that will just delay the linker errors until later in the build process.</p> <p>Do you have a need for packages that utilize undefined symbols?</p></pre>Ahhmyface: <pre><p>Temporarily, yes. Because I have a cyclical dependency. If I include the LDFLAGS then it presumes that lib has been built, despite the fact that I have no need for it. The headers can be generated independently. I&#39;m trying to avoid the linking until the final call.</p> <p>I would like to be able to build like so: gcc bar.o -L-lfoo -lc_archive -o bar</p> <p>c-archive depends on foo, foo depends on bar, bar depends on c-archive</p> <p>Is my only option to break the cycle?</p></pre>mdempsky: <pre><p>I think the only supported way is to break the cycle. I would suggest that as the ideal solution.</p> <p>You may be able to workaround it with weak symbols. For example, changing the <code>import &#34;C&#34;</code> directive above to:</p> <pre><code>// extern int foo(); // #pragma weak foo import &#34;C&#34; </code></pre> <p>That at least works around the package link failure.</p></pre>Ahhmyface: <pre><p>I&#39;ve examined breaking the cycle somewhat, but it strikes me as counterproductive. I have a program written in C that I thought could benefit from some Go. But either I can call it and it can&#39;t make any useful changes to state, or I can&#39;t call it at all. </p> <p>The circular dependency is actually really what makes it useful.</p></pre>mdempsky: <pre><p>Can you provide a representative standalone example of your cyclic dependency?</p></pre>Ahhmyface: <pre><p>Sure. something like this</p> <p>foo.c:</p> <pre><code>int test = 0; int main() { GoIncrementTest(); return test; } </code></pre> <p>foo.go:</p> <pre><code>/* #cgo extern int test; */ //export GoIncrementTest func GoIncrementTest() { test+=1 } </code></pre></pre>

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

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