<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>链接 on ZRJ | 学习笔记</title>
        <link>https://blog.zrj.me/tags/%E9%93%BE%E6%8E%A5/</link>
        <description>Recent content in 链接 on ZRJ | 学习笔记</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-CN</language>
        <lastBuildDate>Fri, 14 Mar 2014 20:10:56 +0800</lastBuildDate><atom:link href="https://blog.zrj.me/tags/%E9%93%BE%E6%8E%A5/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>gcc 链接时动态库和静态库的优先选择</title>
        <link>https://blog.zrj.me/posts/2014-03-14-gcc-%E9%93%BE%E6%8E%A5%E6%97%B6%E5%8A%A8%E6%80%81%E5%BA%93%E5%92%8C%E9%9D%99%E6%80%81%E5%BA%93%E7%9A%84%E4%BC%98%E5%85%88%E9%80%89%E6%8B%A9/</link>
        <pubDate>Fri, 14 Mar 2014 20:10:56 +0800</pubDate>
        
        <guid>https://blog.zrj.me/posts/2014-03-14-gcc-%E9%93%BE%E6%8E%A5%E6%97%B6%E5%8A%A8%E6%80%81%E5%BA%93%E5%92%8C%E9%9D%99%E6%80%81%E5%BA%93%E7%9A%84%E4%BC%98%E5%85%88%E9%80%89%E6%8B%A9/</guid>
        <description>&lt;p&gt;老话题了，不过还是记一笔&lt;/p&gt;
&lt;p&gt;先看文件&lt;/p&gt;
&lt;p&gt;ModuleA.cpp&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ModuleB.cpp&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;minus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Main.cpp&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;minus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%d&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%d&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;minus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Makefile&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;all:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC Main.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC ModuleA.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC ModuleB.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -shared ModuleA.o ModuleB.o -o libmodule.so
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -o Run Main.o -L./ -lmodule
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;clean:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	rm *.o *.so Run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;记得指定动态库路径&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;./:&lt;span class=&#34;nv&#34;&gt;$LD_LIBRARY_PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ldd 确认一下&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ldd Run 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/&lt;span class=&#34;nv&#34;&gt;$LIB&lt;/span&gt;/libonion.so &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libonion.so &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b98dea29000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libmodule.so &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; ./libmodule.so &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b98deb39000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libstdc++.so.6 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /usr/lib64/libstdc++.so.6 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b98dec4d000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libm.so.6 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libm.so.6 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b98dee4c000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libgcc_s.so.1 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libgcc_s.so.1 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b98defa1000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libc.so.6 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libc.so.6 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b98df0ae000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libdl.so.2 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libdl.so.2 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b98df2ef000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/lib64/ld-linux-x86-64.so.2 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b98de90d000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;跑起来&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ./Run 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再来看静态的方式，修改后的 Makefile&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;all:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC Main.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC ModuleA.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC ModuleB.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	ar -r libmodule.a ModuleA.o ModuleB.o
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -o Run Main.o -L./ -lmodule
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;clean:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	rm *.o *.a Run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;编译出来的已经不依赖动态库了（废话）&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ldd Run 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/&lt;span class=&#34;nv&#34;&gt;$LIB&lt;/span&gt;/libonion.so &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libonion.so &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002ad9ce948000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libstdc++.so.6 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /usr/lib64/libstdc++.so.6 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002ad9cea58000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libm.so.6 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libm.so.6 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002ad9cec56000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libgcc_s.so.1 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libgcc_s.so.1 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002ad9cedac000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libc.so.6 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libc.so.6 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002ad9ceeb9000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libdl.so.2 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libdl.so.2 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002ad9cf0f9000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/lib64/ld-linux-x86-64.so.2 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002ad9ce82c000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;静态版本的 Run 是 9850 字节，动态是 9954 字节，这。。&lt;/p&gt;
&lt;p&gt;下面问题来了，如果静态动态都有，链接器要哪个呢&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;all:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC Main.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC ModuleA.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC ModuleB.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	ar -r libmodule.a ModuleA.o ModuleB.o
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -shared ModuleA.o ModuleB.o -o libmodule.so
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -o Run Main.o -L./ -lmodule
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;clean:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	rm *.o *.a *.so Run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;答案是动态库&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ldd Run 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/&lt;span class=&#34;nv&#34;&gt;$LIB&lt;/span&gt;/libonion.so &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libonion.so &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b2243070000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libmodule.so &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; ./libmodule.so &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b2243180000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libstdc++.so.6 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /usr/lib64/libstdc++.so.6 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b2243294000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libm.so.6 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libm.so.6 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b2243493000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libgcc_s.so.1 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libgcc_s.so.1 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b22435e8000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libc.so.6 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libc.so.6 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b22436f5000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libdl.so.2 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;gt; /lib64/libdl.so.2 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b2243936000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/lib64/ld-linux-x86-64.so.2 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0x00002b2242f54000&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以这样来强制链接静态库&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;all:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC Main.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC ModuleA.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -c -fPIC ModuleB.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	ar -r libmodule.a ModuleA.o ModuleB.o
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -shared ModuleA.o ModuleB.o -o libmodule.so
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	g++ -o Run Main.o libmodule.a
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;clean:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	rm *.o *.a *.so Run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;历史评论&#34;&gt;历史评论
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Joanie Lucien&lt;/strong&gt; (2018-06-07 20:57:09):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nice bro!&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        <item>
        <title>gcc 编译时动态静态库的问题</title>
        <link>https://blog.zrj.me/posts/2014-01-14-gcc-%E7%BC%96%E8%AF%91%E6%97%B6%E5%8A%A8%E6%80%81%E9%9D%99%E6%80%81%E5%BA%93%E7%9A%84%E9%97%AE%E9%A2%98/</link>
        <pubDate>Tue, 14 Jan 2014 10:08:41 +0800</pubDate>
        
        <guid>https://blog.zrj.me/posts/2014-01-14-gcc-%E7%BC%96%E8%AF%91%E6%97%B6%E5%8A%A8%E6%80%81%E9%9D%99%E6%80%81%E5%BA%93%E7%9A%84%E9%97%AE%E9%A2%98/</guid>
        <description>&lt;p&gt;一般来说，动态静态库的问题，可以参考这个文章，&lt;a class=&#34;link&#34; href=&#34;http://blog.csdn.net/ast_224/article/details/3988244&#34;  title=&#34;http://blog.csdn.net/ast_224/article/details/3988244&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://blog.csdn.net/ast_224/article/details/3988244&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;gcc生成静态库和动态库&lt;/p&gt;
&lt;p&gt;一、库文件简介&lt;/p&gt;
&lt;p&gt;简单地说，库（Library）就是一组已经写好了的函数和变量、经过编译代码，是为了能够提高开发效率和运行效率而设计的。库分为静态库（Static Library）和共享库（Shared library）两类。静态库文件的扩展名是.a，共享库文件的扩展名是.so（在CYGWIN环境下，分别叫做.o和.dll）。共享库现在常常被叫做动态库，是由于很多人借用了MS Windows的DLL（Dynamic Linked Library）这个词。 （1）静态库 静态是指每个用到该库的应用程序都拥有一份自己的库拷贝；应用程序运行的时候，即使将库删除也没有问题，因为应用程序自己已经有了自己的拷贝。 （2）共享库 一个共享库有可能被多个所有应用程序共享。因此，对每个应用程序来说，即使不再使用某个共享库，也不应将其删除。此外，应用程序需要正确的环境变量设置（LD_LIBRARY_PATH），从而找到共享库所在的位置，否则，应用程序运行时会报告找不到这个库。&lt;/p&gt;
&lt;p&gt;二、关于使用库的问题&lt;/p&gt;
&lt;p&gt;如果库是已经编译好的，那么如何在开发、运行应用程序时使用呢？头文件和库文件所在的路径，必须通过适当的方式通知给编译器、链接器和相关的应用程序。 对于静态库来说，主要涉及开发工具，如gcc。例如，用gcc编译、链接时，需要通过适当的路径找到头文件和静态库文件；实现的方法有两种： gcc的命令行参数（-I, -L） shell的环境变量（C_INCLUDE_PATH, LIBRARY_PATH 对于共享库来说，程序在运行时，如果用到了动态库，也需要找到对应的动态库文件；实现的方法： shell的环境变量（LD_LIBRARY_PATH） 1） gcc命令行参数（-I, -L） 默认情况下，gcc会自动搜索下面的路径： 对头文件： /usr/local/include/ /usr/include/ 对库文件： /usr/local/lib/ /usr/lib/ 但是由于系统管理员对系统安装路径有不同的配置，或者对于如64位系统等情况，上述路径对于一台具体的计算机来说可能不同。如果开发者还有自己工程所需的头文件和库文件，就要用gcc的-I和-L来指定对应的路径。如果需要链接库，还要用-l选项。 例如：如果工程涉及到GDBM（GNU DataBase Management）包，需要libgdbm库，而系统中安装GDBM的路径是： 头文件：/opt/gdbm-1.8.3/include 库文件：/opt/gdbm-1.8.3/lib/ 那么，gcc的命令参数是： $gcc … -I/opt/gdbm-1.8.3/include -L/opt/gdbm-1.8.3/lib –lgdbm 注意：为保证兼容性，必须坚决杜绝在C/C++源文件的#include语句中或者其他相关语句中使用上述路径。 2） shell环境变量（Environmental Variable） 除了用命令行参数，还可以用环境变量来指示gcc搜索适当的路径。而由于Shell的不同，环境变量的设置方法也不同。常用的Shell有Bash, Csh和Tcsh。 （1）Bash 对于Bash来说，除了由系统管理员配置的内容以外，每个用户的用户目录（$HOME）下，有个.bash_profile文件。可在该文件内，增加下面的两个语句来设置GDBM头文件路径的环境变量： C_INCLUDE_PATH=/opt/gdbm-1.8.3/include export C_INCLUDE_PATH 类似地，在该文件内用下面的两个语句来设置库文件路径的环境变量： LIBRARY_PATH=/opt/gdbm-1.8.3/lib export LIBRARY_PATH 在.bash_profile中有了上述语句以后，就不用再使用-I和-L来搜索特定包的路径了。但是链接库的时候，还是要用-l选项。 $gcc … –lgdbm 在Bash下，要检查有什么样的环境变量，可用env命令。 $env （2）Csh和Tcsh 如果是Csh或Tcsh，对环境变量的设置方法就不同了。在用户的（$HOME）目录下，相关的一些文件如下： .cshrc 每次进入Csh时的启动(Startup)文件 .tcshrc 每次进入Tcsh时的启动(Startup)文件（在Tcsh下，如果没有这个文件，系统会用.cshrc文件代替） .login 每次登录Shell时的启动(Startup)文件 在Csh和Tcsh下，分为Shell变量和环境变量；前者是用来设置Shell本身的，而后者则是供其他程序使用的。一般习惯是：Shell变量在.cshrc中定义，而环境变量则在.login文件中定义。 定义Shell变量的方法是在.cshrc或.tcshrc中用set语句： set history = 20 定义环境变量的方法是在.login文件中用setenv语句。对于上面关于GDBM的例子： setenv C_INCLUDE_PATH /opt/gdbm-1.8.3/include setenv LIBRARY_PATH /opt/gdbm-1.8.3/lib 在Csh和Tcsh下，可以用setenv命令来查看设置了哪些环境变量（如果要看Shell变量，要用set命令）。 注意： - 设置Shell变量时要用“=”号； - 设置环境变量时，变量名与实际值（这里是真实路径）之间没有“=”号; - 不需要export。 3） 使用共享库 使用共享库的应用程序，要通过环境变量LD_LIBRARY_PATH找到对应的共享库文件。与其他环境变量一样，对LD_LIBRARY_PATH也要根据shell的种类和库文件的实际路径进行设置。但是，必须注意的是，与一般的环境变量不同，LD_LIBRARY_PATH的值，是已经安装了的所有共享库的路径，因此，在Bash下，不能简单地用下面的办法： LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib 错误！ export LD_LIBRARY_PATH 而必须用： LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH 这样，就把其他共享库的路径也一起加入进来了。同样地，在Csh和Tcsh下， setenv LD_LIBRARY_PATH /opt/gdbm-1.8.3/lib:$LD_LIBRARY_PATH&lt;/p&gt;
&lt;p&gt;三、关于库生成的问题 我们通常把一些公用函数制作成函数库，供其它程序使用。函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中，程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中，而是在程序运行是才被载入，因此在程序运行时还需要动态库存在。&lt;/p&gt;
&lt;p&gt;（1）静态库 简单地说，静态库是一个目标文件的简单集合。因此，首先要解决目标文件。 第一步：将各函数代码所在的源文件编译成目录文件。 例如，对于myfunc.c, myproc.c gcc -c myfunc.c myproc.c 将得到myfunc.o和myproc.o。 第二步：由ar（archive，归档的意思）把多个目标文件集合起来。 $ar -r libmyjob.a myfunc.o myproc.o 通常，静态库的命名方式应遵守libXXXXX.a格式。应用程序在使用静态库的时候，通常只需要把命名中的XXXXX部分传递给gcc即可。例如： $gcc –o mywork –lmyjob … 意为让gcc（实际上是gcc调用ld）去连接一个名字为libmyjob.a（或者libmyjob.so）的库。如果库的命名不遵循libXXXXX.a的格式就找不到相应文件。 例子：创建静态库 hello.h为该函数库的头文件。hello.c是函数库的源程序，其中包含公用函数hello，该函数将在屏幕上输出&amp;quot; hello XXX!&amp;quot;。main.c为测试库文件的主程序，在主程序中调用了公用函数hello。 程序1： //hello.h #ifndef HELLO_H #define HELLO_H void hello(const char *name); #endif 程序2： //hello.c #include void hello(const char *name) { printf(&amp;ldquo;hello %s! /n&amp;rdquo;,name); } 程序3： //main.c #include &amp;ldquo;hello.h&amp;rdquo; int main() { hello(&amp;ldquo;everyone&amp;rdquo;); return 0; }&lt;/p&gt;
&lt;p&gt;实现步骤： 第一步：必须将源程序hello.c通过gcc先编译成.o文件，生成hello.o（静态库/动态库，都是由.o文件创建的）； 第二步：由.o文件创建静态库,生成libmyhello.a（静态库文件名的命名规范是以lib为前缀，紧接着跟静态库名，扩展名为.a）创建静态库用ar命令； 第三步：在程序中使用静态库；（只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明，然后在用gcc命令生成目标文件时指明静态库名，gcc将会从静态库中将公用函数连接到目标文件中。注意，gcc会在静态库名前加上前缀lib，然后追加扩展名.a得到的静态库文件名来查找静态库文件） 第四步：删除静态库文件，程序照常运行，静态库中的公用函数hello已经连接到目标文件main中了。 运行： [root@localhost moduletest]# ls hello.c hello.h main.c [root@localhost moduletest]# gcc -c hello.c [root@localhost moduletest]# ls hello.c hello.h hello.o main.c [root@localhost moduletest]# ar crv libmyhello.a hello.o a - hello.o [root@localhost moduletest]# ls hello.c hello.h hello.o libmyhello.a main.c [root@localhost moduletest]# gcc main.c libmyhello.a -o main [root@localhost moduletest]# ./main hello everyone! [root@localhost moduletest]# rm -f libmyhello.a [root@localhost moduletest]# ls hello.c hello.h hello.o main main.c [root@localhost moduletest]# ./main hello everyone! [root@localhost moduletest]#&lt;/p&gt;
&lt;p&gt;（2）共享库 共享库的构造复杂一些，通常是一个ELF格式的文件。可以有三种方法生成： $ld -G $gcc -shared $libtool 用ld最复杂，用gcc -share就简单的多，但是-share并非在任何平台都可以使用。GNU提供了一个更好的工具libtool，专门用来在各种平台上生成各种库。 用gcc的-shared参数： gcc –shared –o libmyjob.so myjob.o 这样，就通过myjob.o生成了共享库文件libmyjob.so。 特别地，在CYGWIN环境下，仍需要输出符合Windows命名的共享库（动态库），即libXXXXX.dll。如： gcc –shared –o libmyjob.dll myjob.o&lt;/p&gt;
&lt;p&gt;例子：创建动态库（延用上面的程序1，2，3） 实现步骤： 第五步：由.o文件创建动态库文件（命令：gcc -shared -fPCI -o libmyhello.so hello.o）； 第六步：在程序中使用动态库；（在程序中使用动态库和使用静态库完全一样，也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明，然后在用gcc命令生成目标文件时指明动态库名进行编译。程序在运行时，会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到，则载入动态库，否则将提示错误信息而终止程序运行。要将文件libmyhello.so复制到目录/usr/lib中） 运行： [root@localhost moduletest]# ls hello.c hello.h hello.o main.c [root@localhost moduletest]# gcc -shared -fPIC -o libmyhello.so hello.o [root@localhost moduletest]# ls hello.c hello.h hello.o libmyhello.so main.c [root@localhost moduletest]# gcc main.c libmyhello.so -o main [root@localhost moduletest]# ls hello.c hello.h hello.o libmyhello.so main main.c [root@localhost moduletest]# ./main ./main: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory [root@localhost moduletest]# mv libmyhello.so /usr/lib 可以： [root@localhost moduletest]# ls hello.c hello.h hello.o main main.c [root@localhost moduletest]# ./main hello everyone! [root@localhost moduletest]# 或者： [root@localhost moduletest]# rm -f main [root@localhost moduletest]# ls hello.c hello.h hello.o main.c [root@localhost moduletest]# gcc -Wall -g main.c -lmyhello -o main [root@localhost moduletest]# ls hello.c hello.h hello.o main main.c [root@localhost moduletest]# ./main hello everyone! [root@localhost moduletest]# 注意： 当静态库和动态库同名时， gcc命令将优先使用动态库。&lt;/p&gt;
&lt;p&gt;（3）库生成以后的配置 如果要把自己开发的库文件安装到操作系统中，需要有管理员权限： (a) 把库文件复制到适当的目录： 可以把自己开发的动态连接库放到/usr/local/lib（或者/usr/lib），或放到其他目录，但不论放在那里，都必须与LIBRARY_PATH的值、LD_LIBRARY_PATH的值相一致。 (b) 修改相关的系统配置文件： 修改/etc/ld.so.conf，然后利用/sbin/ldconfig来完成。&lt;/p&gt;
&lt;p&gt;Note: 编译参数解析 最主要的是GCC命令行的一个选项: -shared 该选项指定生成动态连接库（让连接器生成T类型的导出符号表，有时候也生成弱连接W类型的导出符号），不用该标志外部程序无法连接。相当于一个可执行文件 l -fPIC：表示编译为位置独立的代码，不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要，而不能达到真正代码段共享的目的。 l -L.：表示要连接的库在当前目录中 l -ltest：编译器查找动态连接库时有隐含的命名规则，即在给出的名字前面加上lib，后面加上.so来确定库的名称 l LD_LIBRARY_PATH：这个环境变量指示动态连接器可以装载动态库的路径。 l 当然如果有root权限的话，可以修改/etc/ld.so.conf文件，然后调用 /sbin/ldconfig来达到同样的目的，不过如果没有root权限，那么只能采用输出LD_LIBRARY_PATH的方法了。 调用动态库的时候有几个问题会经常碰到，有时，明明已经将库的头文件所在目录 通过 “-I” include进来了，库所在文件通过 “-L”参数引导，并指定了“-l”的库名，但通过ldd命令察看时，就是死活找不到你指定链接的so文件，这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;但是，奇葩的事情总是有的，我们现在面临的问题是，主程序是一个框架类型的可执行，这个框架跑起来之后，会用 dlopen 的方式，打开一个 so，业务逻辑在这个 so 里面，那么，自然的，这个 so 就是要用动态的方式来编译了，但是，这个 so 又依赖于 google pb，在部署的时候，环境并不保证有 pb，或者 pb 的版本并不保证匹配，那么，我们希望，把这个 pb 的库，静态的链接进来，也就是这个文章说道的，&lt;a class=&#34;link&#34; href=&#34;http://www.cnblogs.com/nobugtodebug/archive/2012/11/07/e6cd72c67b3dd843f40d7ce919f7336a.html&#34;  title=&#34;http://www.cnblogs.com/nobugtodebug/archive/2012/11/07/e6cd72c67b3dd843f40d7ce919f7336a.html&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://www.cnblogs.com/nobugtodebug/archive/2012/11/07/e6cd72c67b3dd843f40d7ce919f7336a.html&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;动态库(.so)链接静态库(.a)的情况总结 一般来说在链接时想要使用静态库有三种方法： 1、link时加上 -static 选项；当加上 -static选项后，gcc会把所有用到的库都做静态连接。 2、link时直接指定想要静态连接的.a文件的绝对路径。优点是除非.a文件不存在，否则肯定有效；缺点也是很明显，拿到其他机器上编译时，.a文件也必须在相同的路径下存放。 3、在要静态连接的库前指定-Bstatic ，在要动态连接的库前指定-Bdynamic选项。连接器在看到-Bstatic时会优于去找静态库，如果找不到再去找动态库。 -Bdynamic也是同样的情况。（可是我实验的结果是这两个选项根本不起作用，我的环境是centos 6.2 gcc4.7.2, 仔细看了gcc 文档，这两个选项是针对VxWorks平台的，所以不起作用。） 当我们要编译一个so提供给外部使用，这个so本身依赖一些第三方库。但是我们却希望so的使用者不用关心该so对其他库的依赖。很自然的是会想到在编译so的时候把依赖到的第三方库静态链接进来。 我在这样做的时候碰到了问题：指定-static选项时，link失败，错误提示说要用到的object文件应该用-fPIC选项重新编译才行（也就是说，只有用-fPIC选项编译的object文件能被link到.so里）；当直接给出.a的绝对路径的时候link成功，但是.so里却并没有直正包含所用到的符合连接。针对碰到的问题，我做了一些实验。实验如下： static.c&lt;/p&gt;
&lt;p&gt;#include const char* sz_static = &amp;ldquo;i&amp;rsquo;m a static str.&amp;rdquo;; void print_niuzai_said() { printf(&amp;ldquo;in static lib, niu zai said, i&amp;rsquo;m happy!\n&amp;rdquo;); } dynamic.c #include #include &amp;ldquo;static.h&amp;rdquo; void print_papa_said() { print_niuzai_said(); printf(&amp;ldquo;in dynamic lib, papa said, niu zai is wonderful!\n&amp;rdquo;); } main.c #include #include &amp;ldquo;dynamic.h&amp;rdquo; int main(int argc, char** argv) { print_papa_said(); return 0; } 分别用两组命令编译出了两个.a 文件 1、gcc -o static.o -c static.c ar -r libstatic.a static.o 2、gcc -o static_shared.o -shared -fPIC -c static.c ar -r libstatic_shared.a static_shared.o 然后用此命令 &amp;ldquo;gcc -o dynamic.o -c dynamic.c&amp;rdquo; 编译出dynamic.o文件 接下来就是本文的主题了，链接生成libdynamic.so.此时有这么几种情况： 1、使用 &amp;ldquo;gcc -o libdynamic.so -shared -fPIC -L. -lstatic dynamic.o &amp;ldquo;，连接成功，但.so里实际上没有static.o里的内容。 2、使用&amp;quot;gcc -o libdynamic.so dynamic.o -shared -fPIC -L. -lstatic&amp;rdquo;,连接失败 3、使用 &amp;ldquo;gcc -o libdynamic.so -shared -fPIC -L. -lstatic_shared dynamic.o&amp;rdquo;，连接成功，但.so里实际上没有static.o里还是没有的内容。 4、使用 &amp;ldquo;gcc -o libdynamic.so dynamic.o -shared -fPIC -L. -lstatic_shared&amp;rdquo;,连接成功，.a的内容被连接到了.so里面。 另外，链接静态生成可执行程序时，静态库是不是用 &amp;ldquo;-shared -fPIC&amp;rdquo; 选项编译产生的没有影响。都能正常生成可执行程序。 综合以上情况，总结如下： 1、动态连接库中用到的object文件必须是用 &amp;ldquo;-shared -fPIC&amp;quot;选项编译产生的，否则连接时要么报错，要么被忽略。 2、静态库中的object文件最好也用&amp;rdquo;-shared -fPIC&amp;quot;选项编译，这样静态库就可以同时被连接到.so 或者可执行性文件中。 3、动态库只能连接用&amp;rdquo;-shared -fPIC&amp;quot;选项编译出来的静态库（和第1点是同一件事） 4、连接选项的顺序对连接器的行为有重要影响！ 静态库使用-shared -fPIC 连接命令 连接执行结果 动态库结果 最终结果 否 gcc -o libdynamic.so -shared -fPIC -L. -lstatic dynamic.o 成功 静态库内容没有被连接 失败 否 gcc -o libdynamic.so dynamic.o -shared -fPIC -L. -lstatic 失败 失败 是 gcc -o libdynamic.so -shared -fPIC -L. -lstatic_shared dynamic.o 成功 静态库内容没有被连接 失败 是 gcc -o libdynamic.so dynamic.o -shared -fPIC -L. -lstatic_shared 成功 静态库内容被连接 成功&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;直接链接 lib.a 的文件，会报错，要求 fPIC，看到这个文章，&lt;a class=&#34;link&#34; href=&#34;http://hi.baidu.com/88908775/item/4c147df59c218d1fa62988c6&#34;  title=&#34;http://hi.baidu.com/88908775/item/4c147df59c218d1fa62988c6&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://hi.baidu.com/88908775/item/4c147df59c218d1fa62988c6&lt;/a&gt;，里面提供了两种方式，一个改 configure，一个是改 Makefile，改 Makefile 在我这个尝试了不行，改 configure 可以&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;环境： gcc (GCC) 4.1.2 20070115 (prerelease) (SUSE Linux) 64位&lt;/p&gt;
&lt;p&gt;google protobuf 2.4.1&lt;/p&gt;
&lt;p&gt;问题： 在使用libprotobuf.a文件时，编译错误 libprotobuf.a(common.o): relocation R_X86_64_32S against `std::basic_string, std::allocator &amp;gt;::_Rep::_S_empty_rep_storage&amp;rsquo; can not be used when making a shared object; recompile with -fPIC&lt;/p&gt;
&lt;p&gt;原因： -fPIC 是个神马东东呢？ 选项 -fPIC PIC是Position-Independent-Code的缩写。在计算机系统中，PIC和PIE(Position-IndependentExecutable)是可以在主存中不同位置执行的目标代码。PIC经常被用在共享库中，这样就能将相同的库代码为每个程序映射到一个位置，不用担心覆盖掉其他程序或共享库。&lt;/p&gt;
&lt;p&gt;因为so动态库编译的时候加上了 -fPIC，但是连接的 libprotobuf.a文件并不是 -fPIC生成的，所以就报错了。 那就是说连接的 libprotobuf.aa 文件，也需要加上 -fPIC 选项进行编译了。&lt;/p&gt;
&lt;p&gt;解决方法：&lt;/p&gt;
&lt;p&gt;以文本形式打开google buff代码目录下的configure文件，在把第2575至2578行修改为如下： if test &amp;ldquo;x${ac_cv_env_CFLAGS_set}&amp;rdquo; = &amp;ldquo;x&amp;rdquo;; then : CFLAGS=&amp;quot;-fPIC&amp;quot; fi if test &amp;ldquo;x${ac_cv_env_CXXFLAGS_set}&amp;rdquo; = &amp;ldquo;x&amp;rdquo;; then : CXXFLAGS=&amp;quot;-fPIC&amp;quot; 再次执行configure： configrue &amp;ndash;disable-shared make make install 编译完成后,使用libprotobuf.a文件，以上问题解决。&lt;/p&gt;
&lt;p&gt;或者修改 google protobuf的 Makefile文件， 加上 -fPIC 选项，重新编译生成 libprotobuf.a文件&lt;/p&gt;
&lt;p&gt;参考资料：&lt;/p&gt;
&lt;p&gt;详细说明-fPIC的工作原理： &lt;a class=&#34;link&#34; href=&#34;http://blog.csdn.net/chrisniu1984/article/details/6620665&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://blog.csdn.net/chrisniu1984/article/details/6620665&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;-DPIC 是一个宏定义预处理标识 &lt;a class=&#34;link&#34; href=&#34;http://gcc.gnu.org/ml/gcc-help/2006-10/msg00147.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://gcc.gnu.org/ml/gcc-help/2006-10/msg00147.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;http://www.lingcc.com/2009/11/20/10065/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://www.lingcc.com/2009/11/20/10065/&lt;/a&gt; &lt;a class=&#34;link&#34; href=&#34;http://canlynet.blog.163.com/blog/static/25501365201191145113156/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://canlynet.blog.163.com/blog/static/25501365201191145113156/&lt;/a&gt; 编译动态库时遇到如下错误： &amp;hellip; &amp;hellip; relocation R_X86_64_32 against `a local symbol&amp;rsquo; can not be used when making a shared object; recompile with -fPIC &amp;hellip; could not read symbols: Bad value&lt;/p&gt;
&lt;p&gt;解决办法编译器已经提示了：recompile with -fPIC 但是我们应该重新编译谁带上这个参数呢？经过我几番折腾，发现如下情况： 1、编译.o文件的时候，没有加参数-fPIC，这问题个在gcc version 3.4.6版本没有发生，可能那个编译器默认都给加上吧。 2、当前程序中有用到某个静态库，那个静态库编译.o文件的时候没有加上-fPIC（静态库其实就是.o文件打包）。补充一点：我发现手写Makefile时即使不加-fPIC也没有这个问题，这一点很郁闷，这个只在用automake工具编译出.a文件时才出现过。 知道原因了，解决办法自然有了，保证你编译.o文件的时候，都加上-fPIC，这样你才能编译出动态库来。&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;http://bbs.chinaunix.net/thread-1035042-1-1.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://bbs.chinaunix.net/thread-1035042-1-1.html&lt;/a&gt; 从GCC来看，shared应该是包含fPIC选项的，但似乎不是所以系统都支持，所以最好显式加上fPIC选项。参见如下&lt;/p&gt;
&lt;p&gt;`-shared&amp;rsquo; Produce a shared object which can then be linked with other objects to form an executable. Not all systems support this option. For predictable results, you must also specify the same set of options that were used to generate code (`-fpic&amp;rsquo;, `-fPIC&amp;rsquo;, or model suboptions) when you specify this option.(1)&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        <item>
        <title>gcc 查看链接库路径</title>
        <link>https://blog.zrj.me/posts/2013-12-04-gcc-%E6%9F%A5%E7%9C%8B%E9%93%BE%E6%8E%A5%E5%BA%93%E8%B7%AF%E5%BE%84/</link>
        <pubDate>Wed, 04 Dec 2013 13:01:14 +0800</pubDate>
        
        <guid>https://blog.zrj.me/posts/2013-12-04-gcc-%E6%9F%A5%E7%9C%8B%E9%93%BE%E6%8E%A5%E5%BA%93%E8%B7%AF%E5%BE%84/</guid>
        <description>&lt;p&gt;当我们想知道 gcc 在链接的时候使用了什么库的时候，可以使用这样的命令&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ gcc --print-file-name&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;librt.so 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/librt.so
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;之前用过一次，今天再用的时候差点又忘了，简单记一下&lt;/p&gt;
</description>
        </item>
        <item>
        <title>printf 一定需要 stdio.h 吗</title>
        <link>https://blog.zrj.me/posts/2012-09-30-printf-%E4%B8%80%E5%AE%9A%E9%9C%80%E8%A6%81-stdio-h-%E5%90%97/</link>
        <pubDate>Sun, 30 Sep 2012 09:01:32 +0800</pubDate>
        
        <guid>https://blog.zrj.me/posts/2012-09-30-printf-%E4%B8%80%E5%AE%9A%E9%9C%80%E8%A6%81-stdio-h-%E5%90%97/</guid>
        <description>&lt;p&gt;刚刚看到一个范例代码，调用了 printf 函数，但是却没有包含 stdio.h 的头文件，这种写法第一反应就应该是不对的啊，本着动手实验的原则，试了一下&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;zrj@vm:~/c/test$ cat test.c
int main() {
    printf(&amp;#34;hello worldn&amp;#34;);
    return 0;
}
zrj@vm:~/c/test$ gcc -o test test.c
test.c: 在函数‘main’中:
test.c:2:5: 警告： 隐式声明与内建函数‘printf’不兼容 [默认启用]
zrj@vm:~/c/test$ ./test
hello world
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;发现确实是可以的，gcc 在编译的时候给了一个警告，但是能够正常的生成可执行文件，而且也能正常的运行出结果，找了一下，在这里，&lt;a class=&#34;link&#34; href=&#34;http://wiki.ubuntu.org.cn/Gcchowto&#34;  title=&#34;http://wiki.ubuntu.org.cn/Gcchowto&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://wiki.ubuntu.org.cn/Gcchowto&lt;/a&gt;，找到解释&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;链接外部库 库是预编译的目标文件(object files)的集合，它们可被链接进程序。静态库以后缀为‘.a’的特殊的存档文件(archive file)存储。&lt;/p&gt;
&lt;p&gt;标准系统库可在目录 /usr/lib 与 /lib 中找到。比如，在类 Unix 系统中 C 语言的数学库一般存储为文件 /usr/lib/libm.a。该库中函数的原型声明在头文件 /usr/include/math.h 中。C 标准库本身存储为 /usr/lib/libc.a，它包含 ANSI/ISO C 标准指定的函数，比如‘printf’。对每一个 C 程序来说，libc.a 都默认被链接。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;============================================&lt;/p&gt;
&lt;p&gt;2012-10-05 14:27:11 update 在这里，&lt;a class=&#34;link&#34; href=&#34;http://zhidao.baidu.com/question/341065125.html?seed=0&#34;  title=&#34;http://zhidao.baidu.com/question/341065125.html?seed=0&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://zhidao.baidu.com/question/341065125.html?seed=0&lt;/a&gt;，有更好的解释&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;由于编译器在处理函数调用代码时没有找到函数原型，只好根据函数调用代码做隐式声明. 为什么编译器在处理函数调用代码时需要有函数原型？因为必须知道参数的类型和个数以及返回值的类型才知道生成什么样的指令。为什么隐式声明靠不住呢？因为隐式声明是从函数调用代码推导而来的，而事实上函数定义的形参类型可能跟函数调用代码传的实参类型并不一致，如果函数定义带有可变参数（例如printf），那么从函数调用代码也看不出来这个函数带有可变参数，另外，从函数调用代码也看不出来返回值应该是什么类型，所以隐式声明只能规定返回值都是int型的。既然隐式声明靠不住，那编译器为什么不自己去找函数定义，而非要让我们在调用之前写函数原型呢？因为编译器往往不知道去哪里找函数定义.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        
    </channel>
</rss>
