﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Prayer-随笔分类-makefile</title><link>http://www.cppblog.com/prayer/category/11553.html</link><description>在一般中寻求卓越</description><language>zh-cn</language><lastBuildDate>Mon, 18 Mar 2019 13:19:43 GMT</lastBuildDate><pubDate>Mon, 18 Mar 2019 13:19:43 GMT</pubDate><ttl>60</ttl><item><title>理清gcc、libc、libstdc++的关系</title><link>http://www.cppblog.com/prayer/archive/2019/03/18/216301.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 18 Mar 2019 06:27:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/03/18/216301.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216301.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/03/18/216301.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216301.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216301.html</trackback:ping><description><![CDATA[<div><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">当你在linux下写C/C++代码的时候，是不是会遇到许多编译链接的问题？ 时不时报个glibc,gcc，g++等相关的错误？ 很多时候都无从下手，而且比较混乱。 这也是编译链接过程中经常出现的问题。</p><a id="more" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #555555; cursor: pointer; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; word-wrap: break-word; background-color: #ffffff; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #cccccc; line-height: 28px;"></a><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">这篇文章不是去介绍如何编译链接，而是理清编译链接过程中碰到的一些概念和出现的问题。尤其是，libc,glib,glibc,eglibc,libc++,libstdc++,gcc,g++。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">从libc说起。<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />libc是Linux下原来的标准C库，也就是当初写hello world时包含的头文件#include &lt; stdio.h&gt; 定义的地方。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">后来逐渐被glibc取代，也就是传说中的GNU C Library,在此之前除了有libc，还有klibc,uclibc。现在只要知道用的最多的是glibc就行了，主流的一些linux操作系统如 Debian, Ubuntu，Redhat等用的都是glibc（或者其变种，下面会说到).</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">那glibc都做了些什么呢？ glibc是<a href="https://www.baidu.com/s?wd=Linux%E7%B3%BB%E7%BB%9F&amp;tn=24004469_oem_dg&amp;rsv_dl=gh_pl_sl_csd" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">Linux系统</a>中最底层的API，几乎其它任何的运行库都要依赖glibc。 glibc最主要的功能就是对系统调用的封装，你想想看，你怎么能在C代码中直接用fopen函数就能打开文件？ 打开文件最终还是要触发系统中的sys_open系统调用，而这中间的处理过程都是glibc来完成的。<a href="http://www.chongh.wiki/blog/2016/04/08/linux-syscalls/" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #555555; text-decoration: none; cursor: pointer; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #cccccc;">这篇文章</a>详细介绍了glibc是如何与上层应用程序和系统调用交互的。除了封装系统调用，glibc自身也提供了一些上层应用函数必要的功能,如string,malloc,stdlib,linuxthreads,locale,signal等等。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">好了，那eglibc又是什么？ 这里的e是Embedded的意思，也就是前面说到的变种glibc。eglibc的主要特性是为了更好的支持嵌入式架构，可以支持不同的shell(包括嵌入式)，但它是二进制兼容glibc的，就是说如果你的代码之前依赖eglibc库，那么换成glibc后也不需要重新编译。<a href="https://www.baidu.com/s?wd=ubuntu%E7%B3%BB%E7%BB%9F&amp;tn=24004469_oem_dg&amp;rsv_dl=gh_pl_sl_csd" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">ubuntu系统</a>用的就是eglibc（而不是glibc）,不信，你执行 ldd &#8211;version 或者 /lib/i386-linux-gnu/libc.so.6<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />(64位系统运行/lib/x86_64-linux-gnu）看看，便会显示你系统中eglibc/glibc的版本信息。 这里提到了libc.so.6,这个文件就是eglibc/glibc编译后的生成库文件。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">还有一个glib看起来也很相似，那它又是什么呢？glib也是个c程序库，不过比较轻量级，glib将C语言中的数据类型统一封装成自己的数据类型，提供了C语言常用的数据结构的定义以及处理函数，有趣的宏以及可移植的封装等(注：glib是可移植的，说明你可以在linux下，也可以在windows下使用它）。那它跟glibc有什么关系吗？其实并没有，除非你的程序代码会用到glib库中的数据结构或者函数，glib库在ubuntu系统中并不会默认安装(可以通过apt-get install libglib2.0-dev手动安装)，著名的GTK+和Gnome底层用的都是glib库。想更详细了解glib？ 可以参考<a href="https://developer.gnome.org/glib/" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #555555; text-decoration: none; cursor: pointer; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #cccccc;">这里</a></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">看到这里，你应该知道这些库有多重要了吧？ 你写的C代码在编译的过程中有可能出现明明是这些库里面定义的变,却量还会出现&#8217;Undefined&#8217;, &#8216;Unreference&#8217;等错误，这时候你可能会怀疑是不是这些库出问题了？ 是不是该动手换个gilbc/eglibc了？ 这里强调一点，在你准备更换/升级这些库之前，你应该好好思考一下，你真的要更换/升级吗？你要知道你自己在做什么！你要时刻知道glibc/eglibc的影响有多大，不管你之前部署的什么程序，linux系统的ls,cd,mv,ps等等全都得依赖它，很多人在更换/升级都有过惨痛的教训，甚至让整个系统奔溃无法启动。所以，强烈不建议更换/升级这些库！</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">当然如果你写的是C++代码，还有两个库也要非常重视了，libc++/libstdc++,这两个库有关系吗？有。两个都是C++标准库。libc++是针对clang编译器特别重写的C++标准库，那libstdc++自然就是gcc的事儿了。libstdc++与gcc的关系就像clang与libc++. 其中的区别这里不作详细介绍了。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">再说说libstdc++，glibc的关系。 libstdc++与gcc是捆绑在一起的，也就是说安装gcc的时候会把libstdc++装上。 那为什么glibc和gcc没有捆绑在一起呢？<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />相比glibc，libstdc++虽然提供了c++程序的标准库，但它并不与内核打交道。对于系统级别的事件，libstdc++首先是会与glibc交互，才能和内核通信。相比glibc来说，libstdc++就显得没那么基础了。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">说完了这些库，这些库最终都是拿来干嘛的？当然是要将它们与你的程序链接在一起！ 这时候就不得不说说gcc了(当然还有前文提到的clang以及llvm等编译器，本文就不细说它们的区别了)。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">你写的C代码.c文件通过gcc首先转化为汇编.S文件，之后汇编器as将.S文件转化为机器代码.o文件，生成的.o文件再与其它.o文件，或者之前提到的libc.so.6库文件通过ld链接器链接在一块生成可执行文件。当然，在你编译代码使用gcc的时候，gcc命令已经帮你把这些细节全部做好了。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">那g++是做什么的? 慢慢说来，不要以为gcc只能编译C代码，g++只能编译c++代码。 后缀为.c的，gcc把它当作是C程序，而g++当作是c++程序；后缀为.cpp的，两者都会认为是c++程序，注意，虽然c++是c的超集，但是两者对语法的要求是有区别的。在编译阶段，g++会调用gcc,对于c++代码，两者是等价的，但是因为gcc命令不能自动和C++程序使用的库联接，需要这样，gcc -lstdc++, 所以如果你的Makefile文件并没有手动加上libstdc++库，一般就会提示错误，要求你安装g++编译器了。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">好了，就说到这，理清这些库与编译器之间的关系，相信会对你解决编译链接过程中遇到的错误起到一点帮助。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">如果你的编译器不支持一些新的C/C++特性，想升级gcc/g++, 这里也给出一个基于ubuntu系统的参考方法。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">添加ppa</p><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; font-family: consolas, Menlo, 'PingFang SC', 'Microsoft YaHei', monospace; white-space: pre-wrap; word-wrap: break-word; overflow: auto; font-size: 13px; line-height: 1.6; color: #4d4d4c; text-align: justify; background-color: #f7f7f7;"><code cs"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: consolas, Menlo, 'PingFang SC', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; color: #383a42; background-image: none; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; line-height: 22px; white-space: pre; word-wrap: break-word; font-size: 14px; background-position: initial initial; background-repeat: initial initial;">sudo <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word;">add</span>-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word;">get</span> update </code></pre><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">添加ppa，是因为你所用的ubuntu版本的更新源中可能并没有你想要的gcc/g++版本。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">安装新版gcc/g++</p><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; font-family: consolas, Menlo, 'PingFang SC', 'Microsoft YaHei', monospace; white-space: pre-wrap; word-wrap: break-word; overflow: auto; font-size: 13px; line-height: 1.6; color: #4d4d4c; text-align: justify; background-color: #f7f7f7;"><code sql"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: consolas, Menlo, 'PingFang SC', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; color: #383a42; background-image: none; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; line-height: 22px; white-space: pre; word-wrap: break-word; font-size: 14px; background-position: initial initial; background-repeat: initial initial;">sudo apt-get <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word;">install</span> gcc<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #986801; word-wrap: break-word;">-4.8</span> sudo apt-<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word;">get</span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word;">install</span> g++<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #986801; word-wrap: break-word;">-4.8</span> </code></pre><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">可以到/usr/bin/gcc查看新安装的gcc,g++</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">配置系统gcc/g++</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">使用update-alternatives,统一更新gcc/g++</p><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; font-family: consolas, Menlo, 'PingFang SC', 'Microsoft YaHei', monospace; white-space: pre-wrap; word-wrap: break-word; overflow: auto; font-size: 13px; line-height: 1.6; color: #4d4d4c; text-align: justify; background-color: #f7f7f7;"><code sql"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: consolas, Menlo, 'PingFang SC', 'Microsoft YaHei', monospace; display: block; overflow-x: auto; color: #383a42; background-image: none; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; line-height: 22px; white-space: pre; word-wrap: break-word; font-size: 14px; background-position: initial initial; background-repeat: initial initial;">sudo <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word;">update</span>-alternatives <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a0a1a7; font-style: italic; word-wrap: break-word;">--install /usr/bin/gcc gcc /usr/bin/gcc-4.6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.6</span> sudo <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word;">update</span>-alternatives <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a0a1a7; font-style: italic; word-wrap: break-word;">--install /usr/bin/gcc gcc /usr/bin/gcc-4.8 80 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8</span> sudo <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word;">update</span>-alternatives <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a0a1a7; font-style: italic; word-wrap: break-word;">--config gcc</span> </code></pre><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">数字优先级(如60，80)高的会被系统选择为默认的编译器,也可以执行第三条命令就是来手动配置系统的gcc,此处按照提示,选择4.8版本的即可。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Lato, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #555555; line-height: 28px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">转载：http://www.chongh.wiki/blog/2016/05/25/lib-compile-link/</p></div><img src ="http://www.cppblog.com/prayer/aggbug/216301.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-03-18 14:27 <a href="http://www.cppblog.com/prayer/archive/2019/03/18/216301.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux so 动态库中全局变量 被覆盖问题</title><link>http://www.cppblog.com/prayer/archive/2019/03/13/216294.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Wed, 13 Mar 2019 08:19:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/03/13/216294.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216294.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/03/13/216294.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216294.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216294.html</trackback:ping><description><![CDATA[<h2>问题描述</h2><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Helvetica, arial, freesans, clean, sans-serif; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; border: 0px;">回归正题，前段时间项目开发中，实现了一个动态库，封装了一些方法。然后基于这个动态库，实现了一个应用程序。应用程序中含有全局变量A，动态库中也含有全局变量A，当我调用动态库中函数后，发现应用程序的A发生了变化！！！O，My God！对于我这种还没在Linux下做过开发的人来说，一头雾水。。。。。。 于是我尝试着，将A中的变量名称改为B，这样问题也就没有了~~~</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Helvetica, arial, freesans, clean, sans-serif; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; border: 0px;"></p><h2><a name="t1" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(78, 161, 219); cursor: pointer; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;"></a>原因</h2><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Helvetica, arial, freesans, clean, sans-serif; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; border: 0px;">应用程序进行链接的时候，动态库中全局变量定义，将会被应用程序中同名的全局变量所覆盖。这样也就造成了，在动态库中修改A变量时，应用程序中的A也发生了变化。</p><h2><a name="t2" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: rgb(78, 161, 219); cursor: pointer; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;"></a>解决方法</h2><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Helvetica, arial, freesans, clean, sans-serif; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; border: 0px;">在创建动态链接库时，gcc/g++选项中添加编译选项</p><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; font-family: Consolas, Inconsolata, Courier, monospace; white-space: pre-wrap; word-wrap: break-word; overflow-x: auto; line-height: 22px; background-color: #ffffff;"><code hljs"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; display: block; overflow-x: auto; color: #abb2bf; background-color: #282c34; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; white-space: pre; word-wrap: break-word;">-Wl,-Bsymbolic.</code></pre><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: Helvetica, arial, freesans, clean, sans-serif; word-wrap: break-word; color: #333333; background-color: #ffffff;">其中</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: Helvetica, arial, freesans, clean, sans-serif; word-wrap: break-word; color: #333333; background-color: #ffffff; border-width: 0px;">Wl</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: Helvetica, arial, freesans, clean, sans-serif; word-wrap: break-word; color: #333333; background-color: #ffffff;">表示将紧跟其后的参数，传递给连接器</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: Helvetica, arial, freesans, clean, sans-serif; word-wrap: break-word; color: #333333; background-color: #ffffff; border-width: 0px;">ld<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word; border-width: 0px;">。</span>Bsymbolic</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: Helvetica, arial, freesans, clean, sans-serif; word-wrap: break-word; color: #333333; background-color: #ffffff;">表示强制采用本地的全局变量定义，这样就不会出现动态链接库的全局变量定义被应用程序的同名定义给覆盖了！</span><img src ="http://www.cppblog.com/prayer/aggbug/216294.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-03-13 16:19 <a href="http://www.cppblog.com/prayer/archive/2019/03/13/216294.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GCC的符号可见性——解决多个库同名符号冲突问题</title><link>http://www.cppblog.com/prayer/archive/2019/03/04/216284.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 04 Mar 2019 03:45:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/03/04/216284.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216284.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/03/04/216284.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216284.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216284.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 问题最近项目遇到一些问题，场景如下主程序依赖了两个库libA的funcA函数和libB的funcB函数。示意的代码(main.cpp)如下：#include &lt;cstdio&gt;  int funcA(int, int); int funcB(int, int);  int main() {     printf("%d,", funcA(2, 1));     printf("%d\n"...&nbsp;&nbsp;<a href='http://www.cppblog.com/prayer/archive/2019/03/04/216284.html'>阅读全文</a><img src ="http://www.cppblog.com/prayer/aggbug/216284.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-03-04 11:45 <a href="http://www.cppblog.com/prayer/archive/2019/03/04/216284.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>链接与自定义函数名同名的库函数</title><link>http://www.cppblog.com/prayer/archive/2019/03/04/216283.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 04 Mar 2019 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/03/04/216283.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216283.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/03/04/216283.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216283.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216283.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 遇到一个问题: 封装SQLite3成静态库，过程中发现SQLite3的源码的shell.c中有main函数：int SQLITE_CDECL main(int argc, char **argv){   char *zErrMsg = 0;   ShellState data;   const char *zInitFile = 0;   int i;   int rc = 0;   int wa...&nbsp;&nbsp;<a href='http://www.cppblog.com/prayer/archive/2019/03/04/216283.html'>阅读全文</a><img src ="http://www.cppblog.com/prayer/aggbug/216283.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-03-04 11:37 <a href="http://www.cppblog.com/prayer/archive/2019/03/04/216283.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>各unix平台动态连接库的编译与使用</title><link>http://www.cppblog.com/prayer/archive/2019/03/01/216276.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Fri, 01 Mar 2019 09:58:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/03/01/216276.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216276.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/03/01/216276.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216276.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216276.html</trackback:ping><description><![CDATA[<div>http://blog.itpub.net/283313/viewspace-2139257/<br /><br /><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">unix平台下，动态连接库的使用有两种方式，link方式和dlopen方式。需要设置LD_LIBRARY_PATH作为查找路径（低版本AIX使用LIBPATH）。link方式是程序启动时加载所有编译时连接的动态库，直到程序结束也不会关闭。dlopen方式是在运行中按照参数指定的方式加载动态库，并可以使用dlclose函数关闭，直到下次再使用dlopen重新加载。因此，link方式无法做到不重启应用程序而更新动态库版本，dlopen方式可以。</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">各平台动态连接库的编译参数如下。文件wel.c，编译成libwel.so（HPUX为libwel.sl）。</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"></p><div id="codeText" style="margin: 0px 0px 1.1em; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: Consolas, monospace; border: 1px solid #dddddd; width: 872.1875px; overflow: auto; word-break: break-all; background-color: #ffffff; font-size: 12px; line-height: normal; color: #444444;"><ol start="1" style="margin: 0px 1px 0px 0px; padding: 0px 0px 0px 40px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; list-style: disc; color: #5c5c5c; line-height: 1.3;"><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #000000;">#include&nbsp;<span style="color: #0000cc;">&lt;</span>stdio<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><br /></span></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">void welcome<span style="color: #0000cc;">(</span>void<span style="color: #0000cc;">)</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #0000cc;">{</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;puts<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"welcome,baby!"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #0000cc;">}</span></li></ol></div><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br />&nbsp;linux:<br />&nbsp;&nbsp;编译libwel.so:<br />&nbsp;&nbsp;&nbsp;gcc -fPIC -shared -o libwel.so wel.c -lc<br />&nbsp;&nbsp;&nbsp;&nbsp;-fPIC&nbsp;&nbsp;用相对地址定位<br />&nbsp;&nbsp;&nbsp;&nbsp;-shared&nbsp;&nbsp;生成动态连接库</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;sco unix open server:<br />&nbsp;&nbsp;编译libwel.so:<br />&nbsp;&nbsp;&nbsp;cc -K PIC -G -o libwel.so wel.c -lc<br />&nbsp;&nbsp;&nbsp;&nbsp;-K PIC&nbsp;&nbsp;用相对地址定位<br />&nbsp;&nbsp;&nbsp;&nbsp;-G&nbsp;&nbsp;生成动态连接库，包含了-b elf选项</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;AIX:<br />&nbsp;&nbsp;编译libwel.so:<br />&nbsp;&nbsp;&nbsp;xlc -G -bnoentry -o libwel.so wel.c -lc<br />&nbsp;&nbsp;&nbsp;&nbsp;-G&nbsp;&nbsp;指定生成动态连接库<br />&nbsp;&nbsp;&nbsp;&nbsp;-bnoentry&nbsp;动态库无需模块入口（低版本AIX需要此参数）</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;HP UX:<br />&nbsp;&nbsp;编译libwel.so:<br />&nbsp;&nbsp;&nbsp;cc +z -c wel.c<br />&nbsp;&nbsp;&nbsp;ld -b -o libwel.sl wel.o -lc<br />&nbsp;&nbsp;&nbsp;&nbsp;+z&nbsp;&nbsp;用相对地址定位<br />&nbsp;&nbsp;&nbsp;&nbsp;-b&nbsp;&nbsp;生成动态连接库</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;SUN OS: 很类似SCO，man帮助不全面<br />&nbsp;&nbsp;编译libwel.so:<br />&nbsp;&nbsp;&nbsp;cc -G -o libwel.so wel.c -lc<br />&nbsp;&nbsp;&nbsp;&nbsp;-G&nbsp;&nbsp;生成动态连接库</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">link方式使用动态连接库的编译参数如下。文件welcome.c，编译成welcome可执行程序。</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"></p><div id="codeText" style="margin: 0px 0px 1.1em; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: Consolas, monospace; border: 1px solid #dddddd; width: 872.1875px; overflow: auto; word-break: break-all; background-color: #ffffff; font-size: 12px; line-height: normal; color: #444444;"><ol start="1" style="margin: 0px 1px 0px 0px; padding: 0px 0px 0px 40px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; list-style: disc; color: #5c5c5c; line-height: 1.3;"><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #000000;">extern void welcome<span style="color: #0000cc;">(</span>void<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br /></span></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #ff0000;">int</span>&nbsp;main<span style="color: #0000cc;">(</span>void<span style="color: #0000cc;">)</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #0000cc;">{</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;welcome<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0<span style="color: #0000cc;">;</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #0000cc;">}</span></li></ol></div><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;linux:<br />&nbsp;&nbsp;&nbsp;gcc -rdynamic -o welcome welcome.c -L. -lwel<br />&nbsp;&nbsp;&nbsp;&nbsp;-rdynamic&nbsp;&nbsp;导出所有符号供动态使用</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;sco unix open server:<br />&nbsp;&nbsp;&nbsp;cc -b elf -o welcome welcome.c -L. -lwel<br />&nbsp;&nbsp;&nbsp;&nbsp;-b elf&nbsp;&nbsp;必须使用ELF的可执行文件格式</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;AIX:<br />&nbsp;&nbsp;&nbsp;xlc -bdynamic -brtl -o welcome welcome.c -L. -lwel<br />&nbsp;&nbsp;&nbsp;&nbsp;-bdynamic&nbsp;使用动态连接方式，系统默认为此方式<br />&nbsp;&nbsp;&nbsp;&nbsp;-brtl&nbsp;&nbsp;-l参数使用.so为库</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;HP UX:<br />&nbsp;&nbsp;&nbsp;cc -dynamic -o welcome welcome.c -L. -lwel<br />&nbsp;&nbsp;&nbsp;&nbsp;-dynamic&nbsp;使用动态连接方式，系统默认为此方式</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;SUN OS:<br />&nbsp;&nbsp;编译libwel.so:<br />&nbsp;&nbsp;&nbsp;cc -B dynamic -o welcome welcome.c -L. -lwel<br />&nbsp;&nbsp;&nbsp;&nbsp;-B dynamic&nbsp;使用动态连接方式</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">dlopen方式，其实就是把打开动态库和查找符号的动作放在程序中执行。因此编译可执行文件与普通的相同，只要连接libdl.so库即可。文件welcome.c，编译成welcome可执行程序。</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"></p><div id="codeText" style="margin: 0px 0px 1.1em; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: Consolas, monospace; border: 1px solid #dddddd; width: 872.1875px; overflow: auto; word-break: break-all; background-color: #ffffff; font-size: 12px; line-height: normal; color: #444444;"><ol start="1" style="margin: 0px 1px 0px 0px; padding: 0px 0px 0px 40px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; list-style: disc; color: #5c5c5c; line-height: 1.3;"><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #000000;">#include&nbsp;<span style="color: #0000cc;">&lt;</span>dlfcn<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><br /></span></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #ff0000;">int</span>&nbsp;main<span style="color: #0000cc;">(</span>void<span style="color: #0000cc;">)</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #0000cc;">{</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;<span style="color: #0000cc;">*</span>handle<span style="color: #0000cc;">;</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;<span style="color: #0000cc;">(</span><span style="color: #0000cc;">*</span>welcome<span style="color: #0000cc;">)</span><span style="color: #0000cc;">(</span>void<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;handle<span style="color: #0000cc;">=</span>dlopen<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"libwel.so"</span><span style="color: #0000cc;">,</span>RTLD_LAZY<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;welcome<span style="color: #0000cc;">=</span>dlsym<span style="color: #0000cc;">(</span>handle<span style="color: #0000cc;">,</span><span style="color: #ff00ff;">"welcome"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000cc;">(</span><span style="color: #0000cc;">*</span>welcome<span style="color: #0000cc;">)</span><span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;return 0<span style="color: #0000cc;">;</span><br /></li><li style="margin: 0px; padding: 0px 0px 0px 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span style="color: #0000cc;">}</span></li></ol></div><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br />&nbsp;linux:<br />&nbsp;&nbsp;&nbsp;gcc -rdynamic -o welcome welcome.c -ldl<br />&nbsp;&nbsp;&nbsp;&nbsp;-rdynamic&nbsp;导出所有符号供动态使用<br />&nbsp;&nbsp;&nbsp;&nbsp;-ldl&nbsp;&nbsp;用系统libdl.so库dlopen(),dlsym(),dlerror(),dlclose()</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;sco unix open server:<br />&nbsp;&nbsp;&nbsp;cc -b elf -o welcome welcome.c -lc<br />&nbsp;&nbsp;&nbsp;&nbsp;-b elf&nbsp;&nbsp;以elf格式，动态连接库必须</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;AIX:<br />&nbsp;&nbsp;&nbsp;xlc -bexpall -o welcome welcome.c -ldl -lc<br />&nbsp;&nbsp;&nbsp;&nbsp;-bexpall&nbsp;使主程序的符号可以被动态库使用</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;HP UX:<br />&nbsp;&nbsp;&nbsp;cc -o welcome welcome.c -ldl -lc</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">&nbsp;SUN OS:<br />&nbsp;&nbsp;&nbsp;cc -o welcome welcome.c -ldl -lc</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">------------------------------------------------------------------------------<br />参照的man手册：<br />&nbsp;cc, ld, ldd, dlopen, dlclose, dlerror, dlsym, CC</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;">另：AIX运行动态库时会加载系统内存统一管理，导致即使程序已退出，编译时仍然认为还在使用而无法覆盖。有两个办法，一是root用户执行slibclean，清理系统加载而无人使用的动态库，另一种是编译的库chmod go-rwx，使得组和其他人无权限，这种库系统会认为用户特有而不加载。</p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; line-height: 28px; font-size: 16px; color: #666666; text-align: justify; background-color: #ffffff;"><br /></p><p style="margin: 0px 0px 18px; padding: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; color: #666666; font-size: 16px; line-height: 28px; text-align: justify; background-color: #ffffff;">来自 &#8220; ITPUB博客 &#8221; ，链接：http://blog.itpub.net/283313/viewspace-2139257/，如需转载，请注明出处，否则将追究法律责任。</p></div><img src ="http://www.cppblog.com/prayer/aggbug/216276.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-03-01 17:58 <a href="http://www.cppblog.com/prayer/archive/2019/03/01/216276.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>shell脚本报错"[: =: unary operator expected"的解决方案</title><link>http://www.cppblog.com/prayer/archive/2019/03/01/216275.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Fri, 01 Mar 2019 07:20:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/03/01/216275.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216275.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/03/01/216275.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216275.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216275.html</trackback:ping><description><![CDATA[<p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">&nbsp; 在匹配字符串相等时，我用了类似这样的语句：</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">if [ $STATUS == "OK" ]; then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">echo "OK"</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">fi</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">&nbsp;&nbsp;&nbsp; 在运行时出现了&#8220; [: =: unary operator expected&#8221; 的错误，就一直找不到原因，尝试了删除等号两侧的空格和括号里的空格都不管用。最后<a href="https://www.baidu.com/s?wd=baidu&amp;tn=24004469_oem_dg&amp;rsv_dl=gh_pl_sl_csd" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">baidu</a>了一下，才找到原因，在条件表达式外再添加一层&#8220;[]&#8221;，就不会出错了，如下：</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">if [[ $STATUS = "OK" ]];&nbsp;</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">then &nbsp;</span>&nbsp;&nbsp;</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">echo "OK"</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">fi&nbsp;</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">&nbsp;&nbsp;&nbsp; 究其原因，是因为如果变量STATUS值为空，那么<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: Arial; word-wrap: break-word;">条件表达式</span>就成了 [ = "OK"] ，显然 [ 和 "OK" 不相等并且缺少了&nbsp;</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">[ 符号，所以报了这样的错误。当然不总是出错，如果变量STATUS值不为空，程序就正常了，所以这样的错误还是很隐蔽的。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">&nbsp;&nbsp;&nbsp; 或者，用下面的方法也能避免这种错误：</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">if [ "$STATUS"x == "OK"x ]; then&nbsp;&nbsp;&nbsp;</span>&nbsp;&nbsp;</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">echo</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">"OK"</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">fi。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">当然，x也可以是其他字符。顺便提一点，shell中有没有双引号在很多情况下是一致的。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: Arial; color: #333333; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; word-wrap: break-word;">转自：<a href="http://hi.baidu.com/vishare/blog/item/bd8ab9ee289753252cf53417.html" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #336699; text-decoration: none; cursor: pointer; word-wrap: break-word;">http://hi.baidu.com/vishare/blog/item/bd8ab9ee289753252cf53417.html</a></span></p><img src ="http://www.cppblog.com/prayer/aggbug/216275.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-03-01 15:20 <a href="http://www.cppblog.com/prayer/archive/2019/03/01/216275.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ "multiple definition of .. first defined here"</title><link>http://www.cppblog.com/prayer/archive/2019/02/26/216260.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Tue, 26 Feb 2019 08:02:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/02/26/216260.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216260.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/02/26/216260.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216260.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216260.html</trackback:ping><description><![CDATA[<div>https://www.cnblogs.com/zjutzz/p/4018816.html<br /><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;">在C++中，有时候需要在不同文件中使用同一个变量。对于这类变量如果处理不当，很容易出现&#8220;multiple definition of... first defined here&#8221;的错误。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;">例如，定义了如下3个文件：global.h, a.cpp, b.cpp</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code cpp"="" style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;"><span style="margin: 0px; padding: 0px; color: green;">//global.h:</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">ifndef</span> _GLOBAL_H_</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">define</span> _GLOBAL_H_</span>  <span style="margin: 0px; padding: 0px; color: #0000ff;">const</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">int</span> a=<span style="margin: 0px; padding: 0px;">1</span>; <span style="margin: 0px; padding: 0px; color: #0000ff;">int</span> b;  <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">endif</span></span></code></pre><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code cpp"="" style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;"><span style="margin: 0px; padding: 0px; color: green;">//a.cpp</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;iostream&gt;</span></span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;stdlib.h&gt;</span></span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">"global.h"</span></span>  <span style="margin: 0px; padding: 0px; color: #0000ff;">using</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">namespace</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">std</span>;  <span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #0000ff;">void</span> <span style="margin: 0px; padding: 0px; color: #a31515;">test1</span><span style="margin: 0px; padding: 0px;">()</span> </span>{      <span style="margin: 0px; padding: 0px; color: #0000ff;">cout</span>&lt;&lt;<span style="margin: 0px; padding: 0px; color: #a31515;">"test1"</span>&lt;&lt;<span style="margin: 0px; padding: 0px; color: #0000ff;">endl</span>; }</code></pre><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code cpp"="" style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;"><span style="margin: 0px; padding: 0px; color: green;">//b.cpp</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;iostream&gt;</span></span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;stdlib.h&gt;</span></span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">"global.h"</span></span>  <span style="margin: 0px; padding: 0px; color: #0000ff;">using</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">namespace</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">std</span>;  <span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #0000ff;">void</span> <span style="margin: 0px; padding: 0px; color: #a31515;">test2</span><span style="margin: 0px; padding: 0px;">()</span> </span>{     <span style="margin: 0px; padding: 0px; color: #0000ff;">cout</span>&lt;&lt;<span style="margin: 0px; padding: 0px; color: #a31515;">"test2"</span>&lt;&lt;<span style="margin: 0px; padding: 0px; color: #0000ff;">endl</span>; }  <span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #0000ff;">void</span> <span style="margin: 0px; padding: 0px; color: #a31515;">main</span><span style="margin: 0px; padding: 0px;">()</span> </span>{   <span style="margin: 0px; padding: 0px; color: #0000ff;">cout</span>&lt;&lt;<span style="margin: 0px; padding: 0px; color: #a31515;">"hello world"</span>&lt;&lt;<span style="margin: 0px; padding: 0px; color: #0000ff;">endl</span>; }</code></pre><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;">执行编译命令：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;">g++ -o main a.cpp b.cpp</code></pre><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;">提示错误为：</p><blockquote style="margin: 20px 0px; padding: 20px 50px; background-image: url(https://www.cnblogs.com/skins/iMetro/images/quote.png); background-color: #f0f0f0; border-top-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; color: #000000; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-position: -75px -20px; background-repeat: no-repeat no-repeat;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">[chris@zz jojo]g++ -o main a.cpp b.cpp<br style="margin: 0px; padding: 0px;" />/tmp/ccc7OcsO.o:(.bss+0x0): multiple definition of `b'<br style="margin: 0px; padding: 0px;" />/tmp/ccs7q2VA.o:(.bss+0x0)：第一次在此定义</p></blockquote><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">出错原因：a.cpp和b.cpp先分别被编译为.o格式的目标文件，两个目标文件再被链接器链接起来，这当中a.cpp和b.cpp分别进行了一次include，相当于global.h中的代码重复出现了一次。因为a是const类型，所以重新定义也没事；但是b只是普通变量，重复定义显然不行。</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;">显然，一个解决办法是<strong style="margin: 0px; padding: 0px;">把b定义为const int类型。或者，定义成static int类型</strong>也行。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;">还有一种解决方案，就是<strong style="margin: 0px; padding: 0px;">把global.h变为global.c文件，a.cpp和b.cpp中不再include它，但是编译的时候把global.c也编译进去</strong>，就可以了：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;">g++ -o main global.c  a.cpp b.cpp</code></pre><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;">再举一个class相关的例子。比如有Body和Mouth两个类，Body的greet方法会调用Mouth的say方法，而main函数中会调用全局变量body的greet方法。为了只是用一个body和一个mouth对象，可以这么写：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code cpp"="" style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;"><span style="margin: 0px; padding: 0px; color: green;">//body.h</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">ifndef</span> BODY_H</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">define</span> BODY_H</span>  <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;mouth.h&gt;</span></span>  <span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #0000ff;">class</span> <span style="margin: 0px; padding: 0px; color: #a31515;">Body</span> {</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">public</span>:     Body();     ~Body();     <span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #0000ff;">void</span> <span style="margin: 0px; padding: 0px; color: #a31515;">greet</span><span style="margin: 0px; padding: 0px;">()</span></span>; };  <span style="margin: 0px; padding: 0px; color: #0000ff;">extern</span> Body body;   <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">endif</span></span> </code></pre><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code cpp"="" style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;"><span style="margin: 0px; padding: 0px; color: green;">//body.cpp</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;body.h&gt;</span></span>  Body::Body(){}  Body::~Body() {}  <span style="margin: 0px; padding: 0px; color: #0000ff;">void</span> Body::greet() {     mouth.say(); } </code></pre><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code cpp"="" style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;"><span style="margin: 0px; padding: 0px; color: green;">//mouth.h</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">ifndef</span> MOUTH_H</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">define</span> MOUTH_H</span>  <span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #0000ff;">class</span> <span style="margin: 0px; padding: 0px; color: #a31515;">Mouth</span> {</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">public</span>:     Mouth();     ~Mouth();     <span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #0000ff;">void</span> <span style="margin: 0px; padding: 0px; color: #a31515;">say</span><span style="margin: 0px; padding: 0px;">()</span></span>; };  <span style="margin: 0px; padding: 0px; color: #0000ff;">extern</span> Mouth mouth;   <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">endif</span></span> </code></pre><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code cpp"="" style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;"><span style="margin: 0px; padding: 0px; color: green;">//mouth.cpp</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;mouth.h&gt;</span></span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;iostream&gt;</span></span>  <span style="margin: 0px; padding: 0px; color: #0000ff;">using</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">namespace</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">std</span>;  Mouth::Mouth() {}  Mouth::~Mouth() {}  <span style="margin: 0px; padding: 0px; color: #0000ff;">void</span> Mouth::say() {     <span style="margin: 0px; padding: 0px; color: #0000ff;">cout</span> &lt;&lt; <span style="margin: 0px; padding: 0px; color: #a31515;">"Have a Nice day!"</span> &lt;&lt; <span style="margin: 0px; padding: 0px; color: #0000ff;">endl</span>; } </code></pre><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code cpp"="" style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;"><span style="margin: 0px; padding: 0px; color: green;">//class.cpp</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;body.h&gt;</span></span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;mouth.h&gt;</span></span>   Body body; Mouth mouth; </code></pre><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code cpp"="" style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;"><span style="margin: 0px; padding: 0px; color: green;">//main.cpp</span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;iostream&gt;</span></span> <span style="margin: 0px; padding: 0px; color: #2b91af;">#<span style="margin: 0px; padding: 0px;">include</span> <span style="margin: 0px; padding: 0px;">&lt;body.h&gt;</span></span> <span style="margin: 0px; padding: 0px; color: #0000ff;">using</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">namespace</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">std</span>;  <span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #0000ff;">int</span> <span style="margin: 0px; padding: 0px; color: #a31515;">main</span><span style="margin: 0px; padding: 0px;">()</span> </span>{     body.greet(); } </code></pre><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;">上面代码中的include，虽然都是用的尖括号，但因为编译时可以通过指定include路径，不会出问题～<br style="margin: 0px; padding: 0px;" />编译命令：</p><pre style="margin-top: 10px; margin-bottom: 10px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;"><code style="margin: auto; vertical-align: middle; display: block; height: auto; overflow-x: auto; padding: 5px !important; line-height: 1.5 !important; font-family: 'Courier New', sans-serif !important; font-size: 12px !important; border: 1px solid #cccccc !important; border-top-left-radius: 3px !important; border-top-right-radius: 3px !important; border-bottom-right-radius: 3px !important; border-bottom-left-radius: 3px !important;">g++ -I ./ mouth.cpp body.cpp class.cpp main.cpp -o main</code></pre><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: 微软雅黑; font-size: 13.920000076293945px; line-height: 20px; background-color: #ffffff;">能够正常运行。</p></div><img src ="http://www.cppblog.com/prayer/aggbug/216260.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-02-26 16:02 <a href="http://www.cppblog.com/prayer/archive/2019/02/26/216260.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>g++: 错误： –fpermissive：没有那个文件或目录</title><link>http://www.cppblog.com/prayer/archive/2019/02/25/216258.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 25 Feb 2019 02:56:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/02/25/216258.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216258.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/02/25/216258.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216258.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216258.html</trackback:ping><description><![CDATA[<div>https://www.xuebuyuan.com/1611225.html<br /><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px;">错误：</p><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px;">host C++: libutils &lt;= frameworks/base/libs/utils/AssetDir.cpp</p><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px;">host C++: libutils &lt;= frameworks/base/libs/utils/Asset.cpp<br />g++: 错误： &#8211;fpermissive：没有那个文件或目录<br />make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/Asset.o] 错误 1<br />make: *** 正在等待未完成的任务....<br />g++: 错误： &#8211;fpermissive：没有那个文件或目录<br />make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/AssetDir.o] 错误 1</p><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px;">true</p><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px;"></p><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px;">是传递给g++的标志被误判成文件名了。用"make showcommands"编译，贴出完整的输出。</p><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px;">host C++: libutils &lt;= frameworks/base/libs/utils/AssetDir.cpp<br />g++&nbsp;&nbsp;-I external/zlib&nbsp;&nbsp; -I frameworks/base/libs/utils&nbsp;&nbsp; -I out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates&nbsp;&nbsp; -I dalvik/libnativehelper/include/nativehelper&nbsp;&nbsp; -I system/core/include&nbsp;&nbsp; -I hardware/libhardware/include&nbsp;&nbsp; -I hardware/libhardware_legacy/include&nbsp;&nbsp;<br />-I hardware/ril/include&nbsp;&nbsp; -I dalvik/libnativehelper/include&nbsp;&nbsp; -I frameworks/base/include&nbsp;&nbsp; -I frameworks/base/opengl/include&nbsp;&nbsp; -I frameworks/base/native/include&nbsp;&nbsp; -I external/skia/include&nbsp;&nbsp; -I tools/include&nbsp;&nbsp; -I out/host/linux-x86/obj/include&nbsp;&nbsp;-c&nbsp;&nbsp;-fno-exceptions<br />-Wno-multichar -m32 -fPIC -include system/core/include/arch/linux-x86/AndroidConfig.h -D_FORTIFY_SOURCE=0 -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -O2 -g -fno-strict-aliasing -DNDEBUG -UDEBUG -DANDROID -fmessage-length=0<br />-W -Wall -Wno-unused -Winit-self -Wpointer-arith -Wsign-promo -DNDEBUG -UDEBUG&nbsp;&nbsp; -DLIBUTILS_NATIVE=1&nbsp;&nbsp;&#8211;fpermissive&nbsp;&nbsp;&nbsp;&nbsp; -MD -o out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/AssetDir.o frameworks/base/libs/utils/AssetDir.cpp<br />g++: error: &#8211;fpermissive: No such file or directory<br />make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/AssetDir.o] Error 1</p><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px;"></p><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px; color: #ff0000;">问题解决方法是：</p><p style="margin: 0px 0px 10px; padding: 0px; border: 0px; font-size: 13px; background-color: #ffffff; font-family: 'Microsoft YaHei', 微软雅黑, Arial, 'Lucida Grande', Tahoma, sans-serif; line-height: 24px;"><span style="margin: 0px; padding: 0px; border: 0px; background-color: transparent; color: #ff0000;">因为&#8211;fpermissive 前边的－是带输入法的，改为不带输入法的 短线就可以了</span></p></div><img src ="http://www.cppblog.com/prayer/aggbug/216258.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-02-25 10:56 <a href="http://www.cppblog.com/prayer/archive/2019/02/25/216258.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>error: ‘memset’ was not declared in this scope</title><link>http://www.cppblog.com/prayer/archive/2019/02/25/216257.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 25 Feb 2019 02:53:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/02/25/216257.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216257.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/02/25/216257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216257.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216257.html</trackback:ping><description><![CDATA[<div>http://blog.sina.com.cn/s/blog_79d599dc0100r2vz.html<br /><br /><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">昨天一同事把代码准备重新全新布置到新的环境上去的时候，代码报错了，先开始报错如下：</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">&nbsp;<wbr>error: &#8216;memset&#8217; was not declared in this scope</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">&nbsp;<wbr>error: &#8216;strcat&#8217; was not declared in this scope</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">首先想到的肯定是头文件未包含进来。但不可能，因为这套代码已经在其它环境上编译过N次啦，不可能代码里面没有添加对头文件的包含啊。</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">于是想到是否是因为新环境里面include目录下没有对应的头文件呢？还或是include目录在这个环境下变了呢？不是/usr/include下面啦。</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">经过一查，上面两个都不是。</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">这个时候就有点郁闷啦。把环境按以前的都设置一遍，还是一样。没办法啦。只好放今天来重新查查啦。</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">今天早上来，可能时间也比较充足，所以慢慢来。既然报这个错误，那我把这个头文件再添加到.h代码里面呢？</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">然后发现添加一个，某个错误就能编译过去。看来还真是头文件的问题。</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;"></div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">但接下来还有其他几个警告，如下：</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">test.cpp:213: warning: ignoring return value of &#8216;int system(const char*)&#8217;, declared with attribute warn_unused_result</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">test.cpp: In member function &#8216;int test::load(std::string&amp;)&#8217;:</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">test.cpp:58: warning: deprecated conversion from string constant to &#8216;char*&#8217;</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">test.cpp:58: warning: deprecated conversion from string constant to &#8216;char*&#8217;</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">test.cpp:58: warning: deprecated conversion from string constant to &#8216;char*&#8217;</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">test.cpp:58: warning: deprecated conversion from string constant to &#8216;char*&#8217;</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">test.cpp:58: warning: deprecated conversion from string constant to &#8216;char*&#8217;</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">test.cpp:94: warning: suggest explicit braces to avoid ambiguous &#8216;else&#8217;</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">test.cpp:61: warning: ignoring return value of &#8216;int pipe(int*)&#8217;, declared with attribute warn_unused_result</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;"></div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">居然这些还报，一一为这些没有判断函数返回值的作了修改。编译通过。</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;"></div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">然后就想为什么这个系统要求这么严格呢？查一下GCC的版本，如下：</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">以前旧环境：</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">gcc 版本 4.1.2 20070626 (Red Hat 4.1.2-14)</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">现在的新环境：</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)&nbsp;<wbr></div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;"></div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">原来是GCC版本不同。所以想GCC新版本对代码的这些要求现在越来越严格啦。还有函数的一些检查项，还有编译时候MAKEFILE里面对库文件的引用。</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">具体是否是因为这个严格的原因，没有去详细查GCC的文档。但猜想是这样吧。</div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;"></div><div style="color: #494949; font-family: simsun; background-color: #c9f3e9;">以后如果代码里面对某个函数的头文件还是尽量包含进来吧，至少不是什么坏事。</div></div><img src ="http://www.cppblog.com/prayer/aggbug/216257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-02-25 10:53 <a href="http://www.cppblog.com/prayer/archive/2019/02/25/216257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LINUX下默认搜索头文件及库文件的路径</title><link>http://www.cppblog.com/prayer/archive/2019/02/21/216251.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Thu, 21 Feb 2019 07:38:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/02/21/216251.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216251.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/02/21/216251.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216251.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216251.html</trackback:ping><description><![CDATA[<div>https://www.jianshu.com/p/3eb25114576e 编写c/c++的代码的经常，经常#include 头文件。include有两种方式，一个是#include &#8220;头文件&#8221;，一个是#include &lt;头文件&gt;。区别在于：<div><div> <ol> <li>前者是从当前的目录来搜索</li> <li>后者是一般会先搜索 -I 选项后的路径（即用gcc编译时的-I选项），之后就是标准的系统头文件路径。</li> </ol> <p>通过cpp -v命令，可以查看标准系统头文件的路径。</p> <pre ruby"=""><code>zhaozheng@ubuntu:~$ cpp -v Using built-in specs. COLLECT_GCC=cpp Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.4' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)  COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=x86-64'  /usr/lib/gcc/x86_64-linux-gnu/5/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu - -mtune=generic -march=x86-64 -fstack-protector-strong -Wformat -Wformat-security ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/5/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include &lt;...&gt; search starts here:  /usr/lib/gcc/x86_64-linux-gnu/5/include  /usr/local/include  /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed  /usr/include/x86_64-linux-gnu  /usr/include End of search list. </code></pre> <p>所以基本上是三个目录：<br /> usr/include<br /> usr/lib/include<br /> usr/local/include</p> <blockquote> <p>注意：usr并不是user用户的缩写，而是unix system resource 的缩写。</p> </blockquote> <p>如果我们在给要编译的代码加上自己的头文件，应该怎么办？</p> <ol> <li><p>在path里面加上自己的目录</p></li> <li><p>gcc或g++ 编译的时候 ，加上 -I  选项, 比如这样</p></li> </ol> <pre undefined"=""><code>g++ -c ttcp_blocking.cc -I /home/zhaozheng/code/chensuo/code/muduo-master/ -o ttcp_blocking.o </code></pre> <p>这里把这个实际的例子写在这里</p></div><br /><br />作者：zhaozhengcoder<br />链接：https://www.jianshu.com/p/3eb25114576e<br />來源：简书<br />简书著作权归作者所有，任何形式的转载都请联系作者获得授权并注明出处。</div><br /><br /><br /></div><img src ="http://www.cppblog.com/prayer/aggbug/216251.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-02-21 15:38 <a href="http://www.cppblog.com/prayer/archive/2019/02/21/216251.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【错误总结】expected specifier-qualifier-list before sth</title><link>http://www.cppblog.com/prayer/archive/2019/02/21/216250.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Thu, 21 Feb 2019 06:51:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2019/02/21/216250.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216250.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2019/02/21/216250.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216250.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216250.html</trackback:ping><description><![CDATA[<div><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: KaiTi_GB2312; word-wrap: break-word; font-size: 18px;">转载于：http://www.cnblogs.com/lu-yang/archive/2011/11/24/2261282.html</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: KaiTi_GB2312; word-wrap: break-word; font-size: 18px;">在oc中经常会遇到expected specifier-qualifier-list before sth之类得编译错误，造成这种错误得主要原因就是使用了未被定义的变量。关于specifier-qualifier-list的定义：It's a list of specifiers and qualifiers :-) Specifiers are things like void, char, struct Foo, etc., and qualifiers are keywords like const and volatile. See this C grammar for the definition.如：</span></p><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; font-family: Consolas, Inconsolata, Courier, monospace; white-space: pre-wrap; word-wrap: break-word; overflow-x: auto; line-height: 22px; background-color: #ffffff;"><code hljs=""  objectivec"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; display: block; overflow-x: auto; color: #383a42; background-color: #fafafa; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; white-space: pre; word-wrap: break-word;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">typedef</span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">struct</span> { <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">char</span> *key; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">long</span> canTag; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">long</span> canSet; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">long</span> allowMultiple; confType *next; } confType;</code></pre><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><span style="color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">由于confType未被完全定义即在定义中使用，这样就会报错，常规得解决办法有：</span><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: KaiTi_GB2312; word-wrap: break-word; font-size: 18px;">1.</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-family: 'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"></p><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; font-family: Consolas, Inconsolata, Courier, monospace; white-space: pre-wrap; word-wrap: break-word; overflow-x: auto; line-height: 22px; background-color: #ffffff;"><code hljs=""  objectivec"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; display: block; overflow-x: auto; color: #383a42; background-color: #fafafa; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; white-space: pre; word-wrap: break-word;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: KaiTi_GB2312; word-wrap: break-word; font-size: 18px;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word; font-size: 14px;">typedef</span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word; font-size: 14px;">struct</span> confType { <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word; font-size: 14px;">char</span> *key; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word; font-size: 14px;">long</span> canTag; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word; font-size: 14px;">long</span> canSet; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word; font-size: 14px;">long</span> allowMultiple; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; color: #a626a4; word-wrap: break-word; font-size: 14px;">struct</span> confType*next; } confType;</span></code></pre><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; font-family: KaiTi_GB2312; word-wrap: break-word; color: #333333; background-color: #ffffff; font-size: 18px;">2.<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; font-family: Consolas, Inconsolata, Courier, monospace; white-space: pre-wrap; word-wrap: break-word; overflow-x: auto; line-height: 22px; background-color: #ffffff;"><code hljs=""  objectivec"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif; display: block; overflow-x: auto; color: #383a42; background-color: #fafafa; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; white-space: pre; word-wrap: break-word;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">typedef</span> structconfType confType;  <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">struct</span> confType { <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">char</span> *key; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">long</span> canTag; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">long</span> canSet; <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #a626a4; word-wrap: break-word;">long</span> allowMultiple; confType *next; };</code></pre><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><span style="color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">上述例子可参考</span><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><span style="color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">http://stackoverflow.com/questions/2894639/what-is-a-specifier-qualifier-list</span><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><span style="color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">http://stackoverflow.com/questions/3888569/expected-specifier-qualifier-list-before</span><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><span style="color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">在实际实验过程中会发现还会有一种方法可以解决此问题：</span><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;" /><span style="color: #333333; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">假如有一个ParserDemo工程，而其中有ParserDemoAppDelegate.h/ParserDemoAppDelegate.m和ParserDemoViewController.h/ParserDemoViewController.m. 有时候为了使用C++代码，经常会将后者改为.mm但忘记将前者修改，这样也会报类似的错误，解决办法很简单，就是将二者都改成.mm即可。</span></div><img src ="http://www.cppblog.com/prayer/aggbug/216250.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2019-02-21 14:51 <a href="http://www.cppblog.com/prayer/archive/2019/02/21/216250.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在linux中install命令和cp命令的区别</title><link>http://www.cppblog.com/prayer/archive/2018/11/28/216098.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Wed, 28 Nov 2018 09:03:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2018/11/28/216098.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216098.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2018/11/28/216098.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216098.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216098.html</trackback:ping><description><![CDATA[<div>https://blog.csdn.net/bugouyonggan/article/details/11962201<br /><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">转：http</span><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">://blog.yikuyiku.com/?p=2659</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">基本上，在Makefile里会用到install，其他地方会用cp命令。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">它们完成同样的任务&#8212;&#8212;拷贝文件，它们之间的区别主要如下：</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">1、最重要的一点，如果目标文件存在，cp会先清空文件后往里写入新文件，而install则会先删除掉原先的文件然后写入新文件。这是因为往正在 使用的文件中写入内容可能会导致一些问题，比如说写入正在执行的文件可能会失败，比如说往已经在持续写入的文件句柄中写入新文件会产生错误的文件。而使用 install先删除后写入（会生成新的文件句柄）的方式去安装就能避免这些问题了；</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">2、install命令会恰当地处理文件权限的问题。比如说，install -c会把目标文件的权限设置为rwxr-xr-x；</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">3、install命令可以打印出更多更合适的debug信息，还会自动处理SElinux上下文的问题。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">转：http://blog.csdn.net/stevenliyong/article/details/4663583</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">install&nbsp; - copy files and set attributes</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">install 在做拷贝的同时，设置attributes.</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">因此Makefile 中尽量使用install 命令。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">例如</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">@install&nbsp;-d /usr/bin</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">@install -p -D -m 0755 targets /usr/bin</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">相当于</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">@mkdir -p /usr/bin</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">@cp targets /usr/bin</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">@chmod 755 /usr/bin/targets</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">@touch /usr/bin/tagets&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;---- 更新文件时间戳</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">install 命令好强大啊。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">另外@前缀的意思是不在控制台输出结果。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; background-color: #ffffff;">转载:http://www.cnblogs.com/wwwsinagogogo/archive/2011/08/15/2139124.html</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; color: #4f4f4f; overflow-x: auto; word-wrap: break-word; font-family: 'black verdana';">&nbsp;</p><div id="cnblogs_post_body" style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; font-family: 'black verdana';"><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">【概述】</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">Install和cp类似，都可以将文件/目录拷贝到指定的地点。但是，install允许你控制目标文件的属性。install通常用于程序的makefile，使用它来将程序拷贝到目标（安装）目录。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">【语法】</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">install [OPTION]... [-T] SOURCE DEST</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">install [OPTION]... SOURCE... DIRECTORY</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">install [OPTION]... -t DIRECTORY SOURCE...</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">install [OPTION]... -d DIRECTORY...</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">*如果指定了两个文件名, `install' 将第一个文件拷贝到第二个</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">* 如果使用了 `--target-directory' (`-t') 选项，或者如果最后一个文件是一个目录并且没有使用`--no-target-directory' (`-T')选项， `install'将每一个源文件拷贝到指定的目录，目标文件名与SOURCE文件名相同。</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">* 如果使用了 `--directory' (`-d') 选项, `install' 将逐级创建缺失的目标目录</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">【常用选项】</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">-s:对待拷贝的可执行文件进行strip操作，取出文件中的符号表。（一般在做成nand rom时去除符号表，NFS时为了调试方便，一般不会使用此选项）</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">-d(--directory)：创建制定的目录结构（逐级创建）。如，指定安装位置为/usr/local/aaa/bbb，/usr/loacal已存在，install会帮助我们创建aaa和bbb目录，并把程序安装到指定位置</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff;"></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">If we hand write a&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">Makefile</code>, we should always stick to&nbsp;<a href="http://linux.die.net/man/1/install" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">install</a>&nbsp;instead of using&nbsp;<a href="http://linux.die.net/man/1/cp" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">cp</a>&nbsp;for the installation commands. Not only is it more convenient, but it does things right (cp does things&nbsp;<em style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">wrong</em>).</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">For example, if we attempt to update&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">/bin/bash</code>, which is currently running, with &#8220;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">cp ... /bin/bash</code>&#8221;, we get a &#8220;text busy&#8221; error. If we attempt to update&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">/lib/libc.so.6</code>&nbsp;with &#8220;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">cp ... /lib/libc.so.6</code>&#8221;, then we either get &#8220;text busy&#8221; (in ancient versions of Linux) or breaks each and every running program within a fraction of a second (in recent versions of Linux).&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">install</code>&nbsp;does the thing right in both situations.</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">The reason why&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">cp</code>&nbsp;fails is that it simply attempts to open the destination file in write-only mode and write the new contents. This causes problem because Linux (and all contemporary&nbsp;<a href="http://en.wikipedia.org/wiki/Unix-like" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">Unices</a>&nbsp;as well as Microsoft Windows) uses&nbsp;<a href="http://en.wikipedia.org/wiki/Memory-mapped_file" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">memory mapping</a>&nbsp;(mmap) to load executables and dynamic libraries.</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">The contents of an executable or dynamic library are mmap&#8217;d into the linear address space of relevant processes. Therefore, any change in the underlying file affects the mmap&#8217;d memory regions and can potentially break programs. (<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">MAP_PRIVATE</code>&nbsp;guarantees changes by processes to those memory regions are handled by&nbsp;<a href="http://en.wikipedia.org/wiki/Copy-on-write" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">COW</a>without affecting the underlying file. On the contrary,&nbsp;<a href="http://en.wikipedia.org/wiki/POSIX" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">POSIX</a>&nbsp;leaves to implementations whether COW should be used if the underlying file is modified. In fact, for purpose of efficiency, in Linux, such modifications are&nbsp;<em style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">visible</em>&nbsp;to processes even though&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">MAP_PRIVATE</code>&nbsp;may have be used.)</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">There is an option&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">MAP_DENWRITE</code>&nbsp;which disallows any modification to the underlying file, designed to avoid situations described above. Executables and dynamic libraries are all mmap&#8217;d with this option. Unfortunately, it turned out&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">MAP_DENYWRITE</code>&nbsp;became a source of&nbsp;<a href="http://en.wikipedia.org/wiki/Denial-of-service_attack" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">DoS attacks</a>, forcing Linux to ignore this option in recent versions.</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">Executables are mmap&#8217;d by the kernel (in the&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">execve</code>&nbsp;<a href="http://en.wikipedia.org/wiki/System_call" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">syscall</a>). For kernel codes,&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">MAP_DENYWRITE</code>&nbsp;still works, and therefore we get &#8220;text busy&#8221; errors if we attempt to modify the executable.</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">On the other hand, dynamic libraries are mmap&#8217;d by userspace codes (for example, by loaders like&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">/lib/ld-linux.so</code>). These codes still pass&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">MAP_DENYWRITE</code>&nbsp;to the kernel, but newer kernels silently ignores this option. The bad consequence is that you can break the whole system if you think you&#8217;re only upgrading the&nbsp;<a href="http://en.wikipedia.org/wiki/C_standard_library" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">C runtime library</a>.</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">Then, how does&nbsp;<code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; word-wrap: break-word;">install</code>&nbsp;solve this problem? Very simple &#8211;&nbsp;<a href="http://en.wikipedia.org/wiki/Unlink_(Unix)" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">unlinking</a>&nbsp;the file before writing the new one. Then the old file (no longer present in directory entries but still in disk until the last program referring to it exits) and the new file have different&nbsp;<a href="http://en.wikipedia.org/wiki/Inode" rel="nofollow" target="_blank" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #6795b5; text-decoration: none; cursor: pointer; word-wrap: break-word;">inodes</a>. Programs started before the upgrading (continuing using the old file) and those after the upgrading (using the new version) will both be happy.</span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 13px; color: #4f4f4f; line-height: 18px; overflow-x: auto; word-wrap: break-word; background-color: #ffffff; font-family: Verdana, Tahoma, 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word; font-family: Arial, Helvetica, simsun, u5b8bu4f53; font-size: 14px; line-height: 23px;">记得在大学的时候在编译LFS 6 的时候, 一直搞不懂 install 的命令 和 cp 以及和 chmod, chgrp 的区别?　</span></p><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">工作之后才明白一个Running 的进程不能随便进行 cp , 经常会提示 &nbsp;"text busy＂, 运维部的前辈们给的建议是采用mv 来替代 cp , 今天看起来前辈好像不知道install 这个命令啊.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">今天就简单介绍一下 install 命令.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />install copy 文件列表且同时能够设置文件的属性(包括 owner, group) , 通常用在 Makefiles 中 用来copy 程序到指定的目录. &nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">常见的用法有以下3中形式:　</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">1: &nbsp;install &nbsp;-d [option] &nbsp; DIRECTORY [DIRECTORY...] &nbsp;支持多个. 类似 mkdir -p &nbsp;支持递归.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">例如: &nbsp;install -d a/b/c e/f &nbsp;结果和 mkdir -p &nbsp;a/b/c &nbsp;e/f 一样. &nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">2: install [option] &nbsp;SOURCE DEST&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">复制 SOURCE &nbsp;文件(测试不能是目录) &nbsp; 到DEST file(文件) .&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">install &nbsp;a/e &nbsp; c &nbsp; 结果类似 &nbsp;cp &nbsp;a/e &nbsp;c &nbsp; # 注意c必须是文件.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">有用选项 -D</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">install -D x a/b/c &nbsp; &nbsp;# 效果类似 mkdir -p a/b &nbsp;&amp;&amp; cp &nbsp;x a/b/c &nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">3: install [option] &nbsp;SOURCE [SOURCE...] DIRECTORY</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">复制 &nbsp;多个SOURCE 文件到目的目录. &nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">install a/* &nbsp;d &nbsp; 其中 d 是目录.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">有用选项</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">&nbsp;-b ：自动备份.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">-m : 设置安装文件的权限</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">-p :保留文件的timestamps. 也就是说文件的timestaamps 和 source 文件一样. &nbsp;当我们想要利用安装文件的mtime来跟踪文件的build时间而不是 安装时间.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">-s :&nbsp;Strip the symbol tables from installed binary executables.</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">-S : 备份文件的后缀.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">install &nbsp;-S .bak new &nbsp;old &nbsp;#old 文件自动被 mv 为 old.bak.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">-v: verbose ,打印install 的文件的详细信息.&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">`-c'</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">&nbsp; &nbsp; &nbsp;Ignored; for compatibility with old Unix versions of `install'. &nbsp;#用来兼容旧版的unix.&nbsp;</span></div></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" /></span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">-C: (大写)&nbsp;</span></div><div style="box-sizing: border-box; outline: 0px; margin: 0px; word-wrap: break-word; color: #333333; background-color: #ffffff; line-height: 23px; font-family: Arial, Helvetica, simsun, u5b8bu4f53;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">安装文件, 但是如果目标文件和源文件一样( 判断方法需要看看代码确认) 就跳过, 这样的好处是 能够保持一样文件的mtime. &nbsp;</span></div><div><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><br /></span></div></div></div><img src ="http://www.cppblog.com/prayer/aggbug/216098.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2018-11-28 17:03 <a href="http://www.cppblog.com/prayer/archive/2018/11/28/216098.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Makefile中用宏定义进行条件编译</title><link>http://www.cppblog.com/prayer/archive/2018/11/28/216096.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Wed, 28 Nov 2018 07:55:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2018/11/28/216096.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216096.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2018/11/28/216096.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216096.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216096.html</trackback:ping><description><![CDATA[<div>https://blog.csdn.net/gdutliuyun827/article/details/17297513<br /><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">在源代码里面如果这样是定义的：&nbsp;<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />#ifdef&nbsp;&nbsp; MACRONAME&nbsp;<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />//可选代码&nbsp;<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />#endif</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">那在makefile里面&nbsp;<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />gcc&nbsp;&nbsp; -D&nbsp;&nbsp; MACRONAME=MACRODEF&nbsp;<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />或者&nbsp;<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />gcc&nbsp;&nbsp; -D&nbsp;&nbsp; MACRONAME</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">这样就定义了预处理宏，编译的时候可选代码就会被编译进去了。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">对于GCC编译器，有如下选项：&nbsp;<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -D macro=string，等价于在头文件中定义：#define&nbsp;&nbsp; macro&nbsp;&nbsp; string。例如：-D TRUE=true，等价于：#define&nbsp;&nbsp; TRUE&nbsp;&nbsp; true<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -D macro，等价于在头文件中定义：#define&nbsp;&nbsp; macro&nbsp;&nbsp; 1，实际上也达到了定义：#define&nbsp;&nbsp; macro的目的。例如：-D LINUX，等价于：#define&nbsp;&nbsp; LINUX&nbsp;&nbsp; 1（与#define&nbsp;&nbsp; LINUX作用类似）。<br style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --define-macro&nbsp;&nbsp; macro=string与-D macro=string作用相同。</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">如：</p><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; white-space: pre-wrap; word-wrap: break-word; overflow-x: auto; font-family: Consolas, Inconsolata, Courier, monospace; line-height: 22px; background-color: #ffffff;"><code hljs"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; display: block; overflow-x: auto; color: #abb2bf; background-color: #282c34; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; white-space: pre; word-wrap: break-word; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif;">TEST.C 文件   <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">include</span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #98c379; word-wrap: break-word;">&lt;stdio.h&gt;</span></span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">include</span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #98c379; word-wrap: break-word;">&lt;stdlib.h&gt;</span></span>  main() { <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">ifdef</span> p1</span>   <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #e6c07b; word-wrap: break-word;">printf</span>(<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #98c379; word-wrap: break-word;">"Hello p1"</span>); <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">else</span></span>   <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #e6c07b; word-wrap: break-word;">printf</span>(<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #98c379; word-wrap: break-word;">"Hello p2"</span>); <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">endif</span></span>    } </code></pre><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">1.</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">编译： gcc -o test test.c</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">运行： ./test</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">输出： Hello p2</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">2.</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">编译： gcc -o test test.c -D p1</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">运行： ./test</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">输出： Hello p1</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">&nbsp;</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">还有另外一种使用方式：</p><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">Makefile写法：</p><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; white-space: pre-wrap; word-wrap: break-word; overflow-x: auto; font-family: Consolas, Inconsolata, Courier, monospace; line-height: 22px; background-color: #ffffff;"><code style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; display: block; overflow-x: auto; white-space: pre; word-wrap: break-word; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif;">$(SERVER_NAME):$(SERVER_OBJ) $(COM_OBJS) 	$(CC) -Wall -pthread -D KRC_SERVER_NAME=$(SERVER_NAME)_FLAG</code></pre><p style="box-sizing: border-box; outline: 0px; margin: 0px 0px 16px; padding: 0px; font-size: 16px; color: #4f4f4f; line-height: 26px; overflow-x: auto; word-wrap: break-word; font-family: -apple-system, 'SF UI Text', Arial, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, SimHei, SimSun; background-color: #ffffff;">C代码中用法：</p><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; white-space: pre-wrap; word-wrap: break-word; overflow-x: auto; font-family: Consolas, Inconsolata, Courier, monospace; line-height: 22px; background-color: #ffffff;"><code hljs"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; display: block; overflow-x: auto; color: #abb2bf; background-color: #282c34; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; white-space: pre; word-wrap: break-word; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif;"><span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">if</span> KRC_SERVER_NAME == krc_search_FLAG</span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">elif</span> KRC_SERVER_NAME == krc_feedback_FLAG</span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">else</span></span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">endif</span></span>  注意：其中的两个参数为宏定义，不能使用常量定义，因为需要在预编译阶段就要确定其值！ <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">define</span> krc_search_FLAG     1</span> <span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; color: #61aeee; word-wrap: break-word;">#<span style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">define</span> krc_feedback_FLAG   2</span></code><div data-title="复制" style="box-sizing: border-box; outline: 0px; margin: 8px; padding: 2px 8px; position: absolute; right: 4px; top: 4px; font-size: 12px; color: #4d4d4d; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; cursor: pointer; box-shadow: rgba(0, 0, 0, 0.0470588) 0px 2px 4px, rgba(0, 0, 0, 0.0470588) 0px 2px 4px; word-wrap: break-word;"></div></pre><pre style="box-sizing: border-box; outline: 0px; margin-top: 0px; margin-bottom: 24px; padding: 8px; position: relative; white-space: pre-wrap; word-wrap: break-word; overflow-x: auto; font-family: Consolas, Inconsolata, Courier, monospace; line-height: 22px; background-color: #ffffff;"><code hljs"="" style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 8px; display: block; overflow-x: auto; color: #abb2bf; background-color: #282c34; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; white-space: pre; word-wrap: break-word; font-family: 'Source Code Pro', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Anonymous Pro', 'Droid Sans Mono', Menlo, Monaco, Consolas, Inconsolata, Courier, monospace, 'PingFang SC', 'Microsoft YaHei', sans-serif;">这种用法也能实现条件编译的作用，而且更好！</code></pre></div><img src ="http://www.cppblog.com/prayer/aggbug/216096.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2018-11-28 15:55 <a href="http://www.cppblog.com/prayer/archive/2018/11/28/216096.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>程序的静态链接，动态链接和装载</title><link>http://www.cppblog.com/prayer/archive/2018/11/28/216095.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Wed, 28 Nov 2018 07:53:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2018/11/28/216095.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216095.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2018/11/28/216095.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216095.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216095.html</trackback:ping><description><![CDATA[<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">参考自：<a href="http://www.xuebuyuan.com/1730287.html" target="_blank" style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom-width: 1px; border-bottom-style: dotted; border-bottom-color: #333333;">http://www.xuebuyuan.com/1730287.html</a></strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;"><strong style="margin: 0px; padding: 0px;">一、程序编译链接的整体流程</strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;"><strong style="margin: 0px; padding: 0px;">二、目标文件的样子（以linux下的elf文件格式为例）</strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;"><strong style="margin: 0px; padding: 0px;">三、静态链接</strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;"><strong style="margin: 0px; padding: 0px;">四、装载</strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;"><strong style="margin: 0px; padding: 0px;">五、动态链接</strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">一、程序编译链接的整体流程</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">通常我们使用gcc来生成可执行程序，命令为：gcc hello.c，默认生成可执行文件a.out</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">其实编译（包括链接）的命令：gcc hello.c 可分解为如下4个大的步骤：</p><ul style="margin: 0px 0px 0px 30px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><ul style="margin: 0px 0px 0px 30px; padding: 0px;"><li style="margin: 0px; padding: 0px; list-style: circle;"><strong style="margin: 0px; padding: 0px;">预处理</strong>(Preprocessing)</li><li style="margin: 0px; padding: 0px; list-style: circle;"><strong style="margin: 0px; padding: 0px;">编译</strong>(Compilation)</li><li style="margin: 0px; padding: 0px; list-style: circle;"><strong style="margin: 0px; padding: 0px;">汇编</strong>(Assembly)</li><li style="margin: 0px; padding: 0px; list-style: circle;"><strong style="margin: 0px; padding: 0px;">链接</strong>(Linking)</li></ul></ul><div id="attachment_354"  alignnone"="" style="margin: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><a href="http://smilejay.com/2012/01/c_compilation_stages/gcc_compilation_stages/" rel="attachment wp-att-354" style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom-width: 1px; border-bottom-style: dotted; border-bottom-color: #333333;"><img wp-image-354"="" title="gcc_compilation_stages" src="http://smilejay.b0.upaiyun.com/wp-content/uploads/2012/01/gcc_compilation_stages.jpg" alt="gcc compilation" width="554" height="267" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" /></a><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">gcc compilation</p></div><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong style="margin: 0px; padding: 0px;">预处理(Preproceessing)</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">预处理的过程主要处理包括以下过程：</strong></p><ul style="margin: 0px 0px 0px 30px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><li style="margin: 0px; padding: 0px; list-style: disc;">将所有的#define删除，并且<strong style="margin: 0px; padding: 0px;">展开所有的宏定义</strong></li><li style="margin: 0px; padding: 0px; list-style: disc;"><strong style="margin: 0px; padding: 0px;">处理</strong>所有的<strong style="margin: 0px; padding: 0px;">条件预编译指令</strong>，比如#if #ifdef #elif #else #endif等</li><li style="margin: 0px; padding: 0px; list-style: disc;"><strong style="margin: 0px; padding: 0px;">处理#include</strong>&nbsp;预编译指令，将被包含的文件插入到该预编译指令的位置。</li><li style="margin: 0px; padding: 0px; list-style: disc;"><strong style="margin: 0px; padding: 0px;">删除所有注释&nbsp;</strong>&#8220;//&#8221;和&#8221;/* */&#8221;.</li><li style="margin: 0px; padding: 0px; list-style: disc;"><strong style="margin: 0px; padding: 0px;">添加行号和文件标识</strong>，以便编译时产生调试用的行号及编译错误警告行号。</li><li style="margin: 0px; padding: 0px; list-style: disc;">保留所有的<strong style="margin: 0px; padding: 0px;">#pragma</strong><strong style="margin: 0px; padding: 0px;">编译器指令</strong>，因为编译器需要使用它们</li></ul><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">通常使用以下命令来进行预处理：</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">gcc -E hello.c -o hello.i</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">参数<strong style="margin: 0px; padding: 0px;">-E</strong>表示只进行预处理 或者也可以使用以下指令完成预处理过程</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">cpp hello.c &gt; hello.i &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* &nbsp;cpp &#8211; The C Preprocessor&nbsp; */</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">直接cat hello.i 你就可以看到预处理后的代码</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong style="margin: 0px; padding: 0px;">编译(Compilation)</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">编译过程就是把预处理完的文件进行一系列的词法分析，语法分析，语义分析及优化后生成相应的汇编代码。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">$gcc &#8211;S hello.i &#8211;o hello.s</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">或者</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">$ /usr/lib/gcc/i486-linux-gnu/4.4/cc1 hello.c</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">注：现在版本的GCC把预处理和编译两个步骤合成一个步骤，用cc1工具来完成。gcc其实是后台程序的一些包装，根据不同参数去调用其他的实际处理程序，比如：预编译编译程序cc1、汇编器as、连接器ld</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong style="margin: 0px; padding: 0px;">汇编(Assembly)</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">汇编器是将汇编代码转变成机器可以执行的命令，每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单，根据汇编指令和机器指令的对照表一一翻译即可。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">$ gcc &#8211;c hello.c &#8211;o hello.o</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">或者</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">$ as hello.s &#8211;o hello.co</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">由于hello.o的内容为机器码，不能以普通文本形式的查看（vi 打开看到的是乱码）。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong style="margin: 0px; padding: 0px;">链接(Linking)</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">通过调用链接器ld来链接程序运行需要的一大堆目标文件，以及所依赖的其它库文件，最后生成可执行文件。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">ld -static crt1.o crti.o crtbeginT.o hello.o -start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o (省略了文件的路径名)。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">helloworld的大体编译和链接过程就是这样了，那么编译器和链接器到底做了什么呢？</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">编译过程可分为6</strong><strong style="margin: 0px; padding: 0px;">步：扫描（词法分析）、语法分析、语义分析、源代码优化、代码生成、目标代码优化。</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">词法分析：扫描器（Scanner）将源代的字符序列分割成一系列的记号（Token）。lex工具可实现词法扫描。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">语法分析：语法分析器将记号（Token）产生语法树（Syntax Tree）。yacc工具可实现语法分析(yacc: Yet Another Compiler Compiler)。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">语义分析：静态语义（在编译器可以确定的语义）、动态语义（只能在运行期才能确定的语义）。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">源代码优化：源代码优化器(Source Code Optimizer)，将整个语法书转化为中间代码（Intermediate Code）（中间代码是与目标机器和运行环境无关的）。中间代码使得编译器被分为前端和后端。编译器前端负责产生机器无关的中间代码；编译器后端将中间代码转化为目标机器代码。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">目标代码生成：代码生成器(Code Generator).</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">目标代码优化：目标代码优化器(Target Code Optimizer)。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">链接的主要内容是把各个模块之间相互引用的部分处理好，使得各个模块之间能够正确地衔接。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">链接的主要过程包括：地址和空间分配（Address and Storage Allocation），符号决议（Symbol Resolution），重定位（Relocation）等。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">链接分为静态链接和动态链接。</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">静态链接</strong>是指在编译阶段直接把静态库加入到可执行文件中去，这样可执行文件会比较大。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">而<strong style="margin: 0px; padding: 0px;">动态链接</strong>则是指链接阶段仅仅只加入一些描述信息，而程序执行时再从系统中把相应动态库加载到内存中去。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">静态链接的大致过程如下图所示：</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><a href="http://smilejay.com/2012/01/c_compilation_stages/linking/" rel="attachment wp-att-355" style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom-width: 1px; border-bottom-style: dotted; border-bottom-color: #333333;"><img wp-image-355"="" title="static linking" src="http://smilejay.b0.upaiyun.com/wp-content/uploads/2012/01/linking.jpg" alt="static linking" width="467" height="675" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" /></a></p><div style="margin: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><dl id="attachment_355"  alignnone"="" style="margin: 0px; padding: 0px;"><dd style="margin: 0px; padding: 0px;">static linking</dd></dl></div><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><br style="margin: 0px; padding: 0px;" /></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">二、目标文件的样子（以linux下的elf文件格式为例）</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><div id="embody" style="margin: 0px -20px; padding: 10px; border-bottom-style: solid; border-bottom-width: 1px; border-bottom-color: #ededed; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><div id="lib" style="margin: 0px 10px 0px 0px; font-size: 12px; display: inline-block;">&nbsp;</div></div><div id="article_content" style="margin: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><img src="http://img.my.csdn.net/uploads/201302/02/1359777256_5685.jpg" alt="" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" /></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">夹在<strong style="margin: 0px; padding: 0px;">ELF头</strong>和<strong style="margin: 0px; padding: 0px;">节头部表</strong>之间的都是节。一个典型的ELF可重定位目标文件包含下面几个节：</p><ul style="margin: 0px 0px 0px 30px; padding: 0px;"><li style="margin: 0px; padding: 0px; list-style: disc;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;"><strong style="margin: 0px; padding: 0px;">.text</strong></span>：已编译程序的机器代码。</li><li style="margin: 0px; padding: 0px; list-style: disc;"><strong style="margin: 0px; padding: 0px;">.rodata</strong>：只读数据，比如printf语句中的格式串和开关（switch）语句的跳转表。</li><li style="margin: 0px; padding: 0px; list-style: disc;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;"><strong style="margin: 0px; padding: 0px;">.data</strong></span>：已初始化的全局C变量。局部C变量在运行时被保存在栈中，既不出现在.data中，也不出现在.bss节中。</li><li style="margin: 0px; padding: 0px; list-style: disc;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;"><strong style="margin: 0px; padding: 0px;">.bss</strong></span>：未初始化的全局C变量。在目标文件中这个节不占据实际的空间，它仅仅是一个占位符。目标文件格式区分<strong style="margin: 0px; padding: 0px;">初始化</strong>和<strong style="margin: 0px; padding: 0px;">未初始化</strong>变量是为了空间效率在：在目标文件中，未初始化变量不需要占据任何实际的磁盘空间。</li><li style="margin: 0px; padding: 0px; list-style: disc;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;"><strong style="margin: 0px; padding: 0px;">.symtab</strong>：<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #333300;">一个符号表（symbol table），它存放在程序中被<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">定义</span>和<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">引用</span>的<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">函数和全局变量（包括引用到的外部变量和函数，不含有局部变量）</span>的信息。一些程序员错误地认为必须通过-g选项来编译一个程序，得到符号表信息。实际上，每个可重定位目标文件在.symtab中都有一张符号表。然而，和编译器中的符号表不同，.symtab符号表不包含局部变量的表目。</span></span></li><li style="margin: 0px; padding: 0px; list-style: disc;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;"><strong style="margin: 0px; padding: 0px;">.rel.text</strong></span>：当链接噐把这个目标文件和其他文件结合时，.text节中的许多位置都需要修改。一般而言，<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">任何调用外部函数或者引用全局变量（包括本目标文件内的全局变量，因为在链接时要多个目标文件的相同段合并，这样数据的地址就会改变，所以要重定位）的指令都需要修改</span>。另一方面调用本地函数的指令则不需要修改。注意，可执行目标文件中并不需要重定位信息，因此通常省略，除非使用者显式地指示链接器包含这些信息。</li><li style="margin: 0px; padding: 0px; list-style: disc;"><strong style="margin: 0px; padding: 0px;">.rel.data</strong>：被模块定义或引用的任何全局变量的信息。一般而言，任何已初始化全局变量的初始值是全局变量或者外部定义函数的地址都需要被修改。</li><li style="margin: 0px; padding: 0px; list-style: disc;"><strong style="margin: 0px; padding: 0px;">.debug</strong>：一个调试符号表，其有些表目是程序中定义的局部变量和类型定义，有些表目是程序中定义和引用的全局变量，有些是原始的C源文件。只有以-g选项调用编译驱动程序时，才会得到这张表。</li><li style="margin: 0px; padding: 0px; list-style: disc;"><strong style="margin: 0px; padding: 0px;">.line</strong>：原始C源程序中的行号和.text节中机器指令之间的映射。只有以-g选项调用编译驱动程序时，才会得到这张表。</li><li style="margin: 0px; padding: 0px; list-style: disc;"><strong style="margin: 0px; padding: 0px;">.strtab</strong>：一个字符串表，其内容包括.symtab和.debug节中的符号表，以及节头部中的节名字。字符串表就是以null结尾的字符串序列。</li></ul><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">旁注：为什么未初始化的数据称为.bss?</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用术语.bss来表示未初始化的数据是很普遍的。它起始于IBM 704汇编语言（大约在1957年）中&#8221;块存储开始（Block Storage Start）&#8220;指令的首字母缩写，并沿用至今。一个记住区分.data和.bss节的简单方法是把&#8220;bss&#8221;看成是&#8220;更好地节省空间（Better Save Space）！&#8220;的缩写。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><strong style="margin: 0px; padding: 0px;">三、静态链接</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">虚拟存储器是建立在主存--辅存物理结构基础上，有附加的硬件装置及操作系统存储管理软件组成的一种存储体系。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><img src="http://hi.csdn.net/attachment/201011/28/0_1290943844z9zN.gif" alt="" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" />&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">顾名思义，虚拟存储器是虚拟的存储器，它其实是不存在的，而仅仅是由一些硬件和软件管理的一种&#8220;系统&#8221;。他提供了三个重要的能力：1，它将主存看成一个存储在磁盘上的地址空间的高速缓存，在主存中只保存活动区域，并根据需要在磁盘和主存之间来回传送数据（这里存在&#8220;交换空间&#8221;以及&#8220;页面调度&#8221;等概念），通过这种方式，高效地利用主存；2，它为每个进程提供了统一的地址空间（以虚拟地址编址），从而简化了存储器管理；3，操作系统会为每个进程提供独立的地址空间，从而保护了每个进程的地址空间不被其他进程破坏。&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">虚拟存储器与虚拟地址空间是两个不同的概念：虚拟存储器是假想的存储器，而虚拟存储空间是假想的内存。它们之间的关系应该与主存储器与内存空间之间的关系类似。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">链接部分：</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">链接就是将不同部分的<span style="margin: 0px; padding: 0px; line-height: 1.8;"><a title="代码" href="http://www.xuebuyuan.com/" target="_blank" style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom-width: 1px; border-bottom-style: dotted; border-bottom-color: #333333;">代码</a>和数据收集和组合成一个单一文件的过程，也就是把不同目标文件合并成最终可执行文件的过程。当然，务必知道：这个过程不涉及内存。链接可以分为三种情形：1，编译时链接，也就是我们常说的静态链接；2，装载时链接；3，运行时链接。装载时链接和运行时链接合称为动态链接。在此，我们的链接部分将主要讲述静态链接，而装载时链接我们放在装载部分讲，运行时链接忽略。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">1、什么是静态链接？</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">静态链接就是将多个目标文件组合在一起形成一个可执行文件，如将a.o 和 b.o 链接在一起形成 可执行文件ab。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">2、静态链接的过程包括哪几个部分？</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 静态链接包括两个大部分：一是空间和地址的分配；二是符号解析和重定位</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">（1）空间和地址的分配</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">编译器在将a.o 和 b.o 是如何合并在一起的？？</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">第二种方法就是 相似段合并：顾名思义 就是把不同目标文件的相同名字的段合并成一个段，如下图：</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><img src="https://images2015.cnblogs.com/blog/376860/201608/376860-20160806114729590-1085295555.png" alt="" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" /></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">　　　　　　　　　　　　　　　　　　　　　　图1</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><strong style="margin: 0px; padding: 0px;">这是编译器实际进行合并目标文件的策略。</strong></p><div style="margin: 5px 0px; color: #000000; font-size: 12px !important;"><div style="margin: 5px 0px 0px;"><span style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.8;"><a title="复制代码" style="margin: 0px; padding: 0px; border: none !important;"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 900px; height: auto; border: none !important;" /></a></span></div><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;">/*a.c*/<br style="margin: 0px; padding: 0px;" />extern</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;">int</span><span style="margin: 0px; padding: 0px; line-height: 1.8;"> shared; </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;">int</span><span style="margin: 0px; padding: 0px; line-height: 1.8;"> main() { </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;">int</span> a = <span style="margin: 0px; padding: 0px; line-height: 1.8; color: #800080;">100</span><span style="margin: 0px; padding: 0px; line-height: 1.8;">; swap(</span>&amp;a,&amp;<span style="margin: 0px; padding: 0px; line-height: 1.8;">shared); }</span></pre><div style="margin: 5px 0px 0px;"><span style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.8;"><a title="复制代码" style="margin: 0px; padding: 0px; border: none !important;"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 900px; height: auto; border: none !important;" /></a></span></div></div><div style="margin: 5px 0px; color: #000000; font-size: 12px !important;"><div style="margin: 5px 0px 0px;"><span style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.8;"><a title="复制代码" style="margin: 0px; padding: 0px; border: none !important;"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 900px; height: auto; border: none !important;" /></a></span></div><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;">/*b.c*/<br style="margin: 0px; padding: 0px;" />int</span> shared = <span style="margin: 0px; padding: 0px; line-height: 1.8; color: #800080;">1</span><span style="margin: 0px; padding: 0px; line-height: 1.8;">; </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;">void</span> swap(<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;">int</span> *a,<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;">int</span> *<span style="margin: 0px; padding: 0px; line-height: 1.8;">b) {    </span>*a ^= *b ^= *a ^= *<span style="margin: 0px; padding: 0px; line-height: 1.8;">b; }  </span></pre><div style="margin: 5px 0px 0px;"><span style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.8;"><a title="复制代码" style="margin: 0px; padding: 0px; border: none !important;"><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 900px; height: auto; border: none !important;" /></a></span></div></div><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">编译这两个文件得到&#8220;a.o&#8221;和&#8220;b.o&#8221;两个目标文件</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&#167;gcc&nbsp;-c&nbsp;a.c&nbsp;b.c</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">从代码中可以看到三个符号：share，swap和main。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">静态链接的整个过程分为两步:<br style="margin: 0px; padding: 0px;" />&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">第一步：空间和地址分配。扫描所有的输入目标文件，获得他们的各个段的长度、属性和位置，并且将输入目标文件中的符号表中所有的符号定义和符号引用收集起来，统一放到一个全局符号表。这样，连接器将能够获得所有输入目标文件的段长度，并且将它们合并，计算出输出文件中各个段合并后的长度与位置，并建立映射关系。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">这里可能会有一个问题：建立了什么样的映射关系。如上面的图1，你可能就会有所了解。映射关系就是指可执行文件与进程虚拟地址空间之间的映射。那么，这里程序还没有执行，更不会出现进程，哪里来的进程地址空间呢？此时虚拟存储器便发挥了很大的作用：虽然此时没有进程，但是每个进程的虚拟地址空间的格式都是一致的。所以，为可执行文件的每个段甚至每个符号符号分配地址也就不会有什么错了。注意：在链接之前，目标文件中的所有段的虚拟地址都是0，因为虚拟空间还没有被分配，默认都为0.等到链接之后，可执行文件中的各个段已经都被分配到了相应的虚拟地址</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">第二步：符号解析与重定位</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">首先，符号解析。解析符号就是将每个符号引用与它输入的可重定位目标文件中的符号表中的一个确定的符号定义联系起来。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">若找不到，则出现编译时错误。&nbsp;&nbsp;&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">其次是重定位；</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">不同的处理器指令对于地址的格式和方式都不一样。我们这里采用的是32位的x86处理器，介绍两种寻址方式。</p><table border="1" style="margin: 0px; padding: 0px; border-style: solid; border-color: silver; border-collapse: collapse; word-break: break-word;"><tbody style="margin: 0px; padding: 0px;"><tr style="margin: 0px; padding: 0px;"><td colspan="3" valign="top" width="573" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">X86基本重定位类型</p></td></tr><tr style="margin: 0px; padding: 0px;"><td valign="top" width="191" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">宏定义</p></td><td valign="top" width="191" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">值</p></td><td valign="top" width="191" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">重定位修正方法</p></td></tr><tr style="margin: 0px; padding: 0px;"><td valign="top" width="191" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">R_386_32</p></td><td valign="top" width="191" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">1</p></td><td valign="top" width="191" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">绝对寻址修正S&nbsp;+&nbsp;A</p></td></tr><tr style="margin: 0px; padding: 0px;"><td valign="top" width="191" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">R_386_PC32</p></td><td valign="top" width="191" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">2</p></td><td valign="top" width="191" style="margin: 0px; padding: 8px 14px; border-style: solid; border-color: silver; border-collapse: collapse;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">相对寻址修正S&nbsp;+&nbsp;A&nbsp;-&nbsp;P</p></td></tr></tbody></table><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">注：</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">A：保存在被修正位置的值，对于32位cpu的话，采用<br style="margin: 0px; padding: 0px;" />R_386_PC32寻址的话<br style="margin: 0px; padding: 0px;" />它应该为0xFFFFFFFC即-4，它是代表地址的四个字节；而采用<br style="margin: 0px; padding: 0px;" />R_386_32寻址，它应该为0.</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">P：被修正的位置。考虑以下程序</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">...</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">1023:&nbsp;11&nbsp;11&nbsp;11</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">1026:e8&nbsp;<br style="margin: 0px; padding: 0px;" />fc<br style="margin: 0px; padding: 0px;" />&nbsp;ff&nbsp;ff&nbsp;ff</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">102b:&nbsp;11&nbsp;11&nbsp;11</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">...</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">上述蓝色fc标记处即是被修正的位置，即0x1027.</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">S：符号的实际地址。也就是第一步中空间和地址分配时得到的符号虚拟地址。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">举例来说吧！链接成的可执行文件中，假设main函数的虚拟地址为0x1000，swap函数的虚拟地址为0x2000；shared变量的虚拟地址为0x3000;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">绝对地址修正：对shared变量的地址修正。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">l&nbsp;<br style="margin: 0px; padding: 0px;" />S：shared的实际地址为0x3000；</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">l&nbsp;<br style="margin: 0px; padding: 0px;" />A：被修正位置的值，即0.</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">所以最后这个重定位修正地址为：0x3000，不变！</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">相对寻址修正：对符号&#8220;swap&#8221;进行修正。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">l&nbsp;<br style="margin: 0px; padding: 0px;" />S：符号swap的实际地址，即0x2000；</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">l&nbsp;<br style="margin: 0px; padding: 0px;" />A：被修正位置的值，即0xFFFFFFFC（-4）；</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">l&nbsp;<br style="margin: 0px; padding: 0px;" />P：被修正位置，及0x1027</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">最后的重定位修正地址为：S&nbsp;+&nbsp;A&nbsp;-P&nbsp;=&nbsp;0x2000&nbsp;+（-4）-&nbsp;0x1027&nbsp;=&nbsp;0xFD5.即修正后的程序为：</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">...</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">1023:&nbsp;11&nbsp;11&nbsp;11</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">1026:e8&nbsp;<br style="margin: 0px; padding: 0px;" />d5&nbsp;0f&nbsp;00&nbsp;00</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">102b:&nbsp;11&nbsp;11&nbsp;11</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">...</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">发现熟悉的规则了吗？下一条指令（PC）的地址为0x102b，加上这个修正值正好等于0x2000，</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">0x102b&nbsp;+&nbsp;0xFD5&nbsp;=&nbsp;0x2000，刚好是swap函数的地址。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;<img src="http://hi.csdn.net/attachment/201011/28/0_1290945325g9vI.gif" alt="" width="277" height="239" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" /></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">以上内容没有涉及到c标准库，仅仅是自己实现的两个<span style="margin: 0px; padding: 0px; line-height: 1.8;"><a title="c语言" href="http://www.xuebuyuan.com/zt/17447.html%E2%80%8E" target="_blank" style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom-width: 1px; border-bottom-style: dotted; border-bottom-color: #333333;">c语言</a>程序之间的链接状况，也就是&#8220;程序里面的printf怎么处理&#8221;没有说明。这里，我们就要提及&#8220;静态库&#8221;的概念。其实一个静态库可以简单地看成一组目标文件的集合，即很多目标文件经过压缩打包后形成的一个文件。与静态库链接的过程是这样的：ld链接器自动查找全局符号表，找到那些为决议的符号，然后查出它们所在的目标文件，将这些目标文件从静态库中&#8220;解压&#8221;出来，最终将它们链接在一起成为一个可执行文件。也就是说只有少数几个库和目标文件被链接入了最终的可执行文件，而非所有的库一股脑地被链接进了可执行文件。<br style="margin: 0px; padding: 0px;" /></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.8;">四、装载：</span></strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">以Linux内核装载ELF为例简述一下装载过程。当我们在Linux系统的bash下输入一个命令执行某个ELF程序时，在用户层面，bash进程会调用fork()系统调用创建一个新的进程，然后新的进程调用execve()来执行指定的ELF文件，原先的bash进程继续返回等待刚才启动时新进程结束，然后继续等待用户输入命令。这里需注意，随着一个新进程的出现，操作系统会为它创建一个独立的虚拟地址空间。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">【创建虚拟地址空间】我们知道一个虚拟空间由一组映射函数将虚拟空间的各个页映射到相应的物理空间，那么创建一个虚拟空间实际上并不是创建空间而是创建映射函数所需要的数据结构。举例来说，在x86的Linux下创建虚拟地址空间实际上只是分配一个页目录（页表）就可以了，甚至不设置页映射关系，这些映射关系等到后面程序发生&#8220;缺页&#8221;时在进行设置。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">在进入execve()系统调用之后，Linux内核就开始进行真正的装载工作。在内核中，execve()系统调用相应的入口是sys_execve(),作用：参数的检查复制；调用do_execve(),流程：查找被执行的文件，读取文件的前128个字节以判断文件的格式是elf还是其它；调用search_binary_handle(),流程：通过判断文件头部的魔数确定文件的格式，并且调用相应的装载处理程序。ELF可执行文件的装载处理过程叫load_elf_binary(),它的主要步骤如下：</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">1，检查ELF可执行文件格式的有效性，比如魔数、程序头表中段的数量。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">2，寻找动态链接的&#8220;.interp&#8221;段，找到动态链接器的路径，以便于后面动态链接时会用上。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">3，读取可执行文件的程序头，并且创建虚拟空间与可执行文件的映射关系。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">【读取可执行文件的<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">程序头（存储了哪些部分被映射）</span>，<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">并且创建虚拟空间与可执行文件的映射关系</span>】创建虚拟空间时的页映射关系函数是虚拟空间到物理内存的映射关系，而这一步所做的事虚拟空间与可执行文件的映射关系。我们知道，当程序发生缺页是，操作系统会为物理内存分配一个物理页，然后将该缺页从磁盘中读取到内存，在设置缺页的虚拟页与物理页之间的映射关系，这样程序才可以得以正常运行。但是明显的一点是，当操作系统捕获到缺页错误时，他应当知道程序当前需要的页在可执行文件中的哪一个位置。而这就是虚拟存储与可执行文件之间的映射关系。实际上，这种映射关系仅仅是保存在操作系统内部的一个数据结构。当发生缺页错误是，CPU将控制权交给操作系统，操作系统利用专门的缺页处理例程来查询这个数据结构（映射关系），然后找到所需页所在的虚拟内存区域，以及在可执行文件的偏移，然后把该页加载进物理内存，同时将该虚拟页与物理页之间建立映射关系，最后把控制权还给进程，进程从刚才缺页位置重新开始执行。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">4，初始化ELF进程环境。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">5，将系统调用的返回地址修改成ELF可执行文件的入口点，这个入口点取决于程序的链接方式，对于静态链接的ELF可执行文件，它就是ELF文件的文件头中e_entry所指的地址；对于动态链接的ELF可执行文件，程序入口点就是动态链接器。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">【将CPU指令寄存器设置成可执行文件的入口，启动运行】对动态链接来讲，此时就启动了动态链接器。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">当load_elf_binary()执行完毕，返回至do_execve()在返回至sys_execve()时，系统调用的返回地址已经被改写成了被装载的ELF程序的入口地址了。所以，当sys_execve()系统调用从内核态返回到用户态时，EIP寄存器直接跳转到ELF程序的入口地址。此时，ELF可执行文件装载完成。接下来就是动态链接器对程序进行动态链接了。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">进程的虚拟空间：</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><img src="https://images2015.cnblogs.com/blog/376860/201608/376860-20160806161516825-542579710.png" alt="" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" /></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><strong style="margin: 0px; padding: 0px;">五、动态链接</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">动态链接ELF文件的生成过程</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><img src="https://images2015.cnblogs.com/blog/376860/201608/376860-20160806163246840-1854978573.png" alt="" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" /></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">主要原因有两个：第一，考虑内存和磁盘空间。静态链接极大地浪费内存空间。因为在静态链接的情况下，假设有两个程序共享一个模块，那么在静态链接后输出的两个可执行文件中各有一个共享模块的副本。如果同时运行这两个可执行文件，那么这个共享模块将在磁盘和内存中都有两个副本，对磁盘和内存造成极大地浪费；第二，程序的更新。一旦程序中的一个模块被修改，那么整个程序都要重新链接、发布给用户。如果这个程序相当的大，那么后果就会更加严重！</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;对于一个共享对象（linux下共享的模块），<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">要实现被其他程序之间的共享，就要使其代码和数据分开，每个程序都会有该模块的数据部分的副本，代码部分是共享的。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">共享模块被映射的虚拟地址空间就在上面进程虚拟空间中的 （Memery Mapping部分）</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">共享模块被映射的模样是</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;"><img src="https://images2015.cnblogs.com/blog/376860/201608/376860-20160806164350590-605002435.png" alt="" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px; height: auto;" /></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">动态链接做了什么？</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">务必知道，动态链接是相对于共享对象而言的。动态链接器将程序所需要的所有共享库装载到进程的地址空间，并且将程序汇总所有为决议的符号绑定到相应的动态链接库（共享库）中，并进行重定位工作。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">对于共享模块来说，要实现共享，那么其代码对数据的访问必须是地址无关（就是代码中的地址是固定的，当然这是用的相对地址喽）的，如何做到地址无关，编译器是这么干的，每一个共享模块，都会在其代码段有一个GOT(global offset table)段，如上图所示，<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">Got是一个指针数组，用来存储外部变量的地址</span>，而代码相对于Got的距离是固定的，当对<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">外部模块变量数据和函数</span>进行访问时，就去访问变量在GOT中的位置。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">共享模块对于数据的访问方式：</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">本模块的全局变量和函数------相对地址</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">外模块的全局变量和函数-------GOT段</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #0000ff;">动态链接重定位时修改GOT中的值就实现了对变量的正确访问。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">动态链接的ELF文件启动过程</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">动态链接基本分为三步：先是启动动态链接器本身，然后装载所有需要的共享对象，最后重定位和初始化。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">1，动态链接器自举</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">就我们所知道的，对普通的共享对象文件来说，它的重定位工作是由动态链接器来完成；它也可以依赖于其他共享对象，其中被依赖的共享对象由动态链接器负责链接和装载。那么，对于动态链接器本身呢，它也是一个共享对象，它的重定位工作由谁完成？它是否可以依赖于其他的共享对象文件？</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">动态链接器有其自身的特殊性：首先，动态链接器本身不可以依赖其他任何共享对象（人为控制）；其次动态链接器本身所需要的全局和静态变量的重定位工作由它自身完成（自举代码）。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">我们知道，在Linux下，动态链接器ld.so实际上也是一个共享对象，操作系统同样通过映射的方式将它加载到进程的地址空间中。操作系统在加载完动态链接器之后，就将控制权交给动态链接器。动态链接器入口地址即是自举代码的入口。动态链接器启动后，它的自举代码即开始执行。自举代码首先会找到它自己的GOT(全局偏移表，记录每个段的偏移位置）。而GOT的第一个入口保存的就是&#8220;.dynamic&#8221;段的偏移地址，由此找到动态链接器本身的&#8220;.dynamic&#8221;段。通过&#8220;.dynamic&#8221;段中的信息，自举代码便可以获得动态链接器本身的重定位表和符号表等，从而得到动态链接器本身的重定位入口，然后将它们重定位。完成自举后，就可以自由地调用各种函数和全局变量。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">2，装载共享对象</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">完成自举后，<span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">动态链接器将可执行文件和链接器本身的符号表都合并到一个符号表当中</span>，称之为&#8220;全局符号表&#8221;。然后链接器开始寻找可执行文件所依赖的共享对象：从&#8220;.dynamic&#8221;段中找到DT_NEEDED类型，它所指出的就是可执行文件所依赖的共享对象。由此，动态链接器可以列出可执行文件所依赖的所有共享对象，并将这些共享对象的名字放入到一个装载集合中。然后链接器开始从集合中取出一个所需要的共享对象的名字，找到相应的文件后打开该文件，读取相应的ELF文件头和&#8220;.dynamic&#8221;，然后将它相应的代码段和数据段映射到进程空间中。如果这个ELF共享对象还依赖于其他共享对象，那么将依赖的共享对象的名字放到装载集合中。如此循环，直到所有依赖的共享对象都被装载完成为止。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 1.8; color: #ff0000;">当一个新的共享对象被装载进来的时候，它的符号表会被合并到全局符号表中</span>。所以当所有的共享对象都被装载进来的时候，全局符号表里面将包含动态链接器所需要的所有符号。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">3，重定位和初始化</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">当上述两步完成以后，动态链接器开始重新遍历可执行文件和每个共享对象的重定位表，将表中每个需要重定位的位置进行修正，原理同前。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">重定位完成以后，如果某个共享对象有&#8220;.init&#8221;段，那么动态链接器会执行&#8220;.init&#8221;段中的代码，用以实现共享对象特有的初始化过程。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">此时，所有的共享对象都已经装载并链接完成了，动态链接器的任务也到此结束。同时装载链接部分也将告一段落！接下来便是程序的执行了。。。</p></div><img src ="http://www.cppblog.com/prayer/aggbug/216095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2018-11-28 15:53 <a href="http://www.cppblog.com/prayer/archive/2018/11/28/216095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅谈LINUX与AIX的动态库编译过程 </title><link>http://www.cppblog.com/prayer/archive/2018/11/28/216089.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Wed, 28 Nov 2018 06:35:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2018/11/28/216089.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/216089.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2018/11/28/216089.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/216089.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/216089.html</trackback:ping><description><![CDATA[<div><div>http://blog.sina.com.cn/s/blog_5e4b74040102x19u.html</div><div></div><div>由于单位的项目需要，要把Linux和AIX环境下的静态库编译为动态库，现总结一下整个编译的过程及重点注意事项。</div><div>linux下的静态库文件编译makefile如下：</div><div>INCLUDE= \</div><div>-I/libpath/hdf5-1.8.9/include/ -I/libpath/include -I/libpath/hdf5</div><div>all: libname.a</div><div>libname.a: zhdf.o</div><div>ar -r libname.a zhdf.o</div><div>zhdf.o: ../zhdf.cpp</div><div>g++ $(INCLUDE) -Wall -g -c -lm ../zhdf.cpp -o zhdf.o</div><div>.PHONY: clean</div><div>clean:</div><div>rm -rf *.o libname.a</div><div>linux下的动态库文件编译makefile如下：</div><div>INCLUDE= \</div><div>-I/libpath/hdf5-1.8.9/include/ -I/libpath/include -I/libpath/hdf5</div><div>all: libname.so</div><div>libname.so: zhdf.o</div><div>g++ -shared zhdf.o -o libname.so&nbsp;</div><div>zhdf.o: ../zhdf.cpp</div><div>g++ $(INCLUDE) -Wall -g -c -fPIC -lm ../zhdf.cpp -o zhdf.o</div><div>.PHONY: clean</div><div>clean:</div><div>rm -rf *.o libname.so</div><div></div><div>区别主要是动态库编译时makefile需要-shared和-fPIC选项，另外，动态库编译成功后，需要进入使用该库的用户/home/user路径下，vi .bashrc文件，用export指令将动态库的路径加入环境变量，如export LD_LIBRARY_PATH=yourlibpath，然后source .bashrc进行环境变量修改的保存，保存后可用env查看环境变量是否修改成功。以上，LINUX环境下动态库的编译就算完成啦！</div><div></div><div>AIX下的静态库文件编译makefile如下：</div><div>INCLUDE= \</div><div>-I/libpath/hdf5-1.8.9/include/ -I/libpath/include -I/libpath/hdf5/ \</div><div>all: libname.a</div><div>libname.a: zhdf.o</div><div>ar -X64 -r libname.a zhdf.o</div><div>zhdf.o: ../zhdf.cpp</div><div>xlC $(INCLUDE) -q64 -qinfo -g -c -lm ../zhdf.cpp -o zhdf.o</div><div>.PHONY: clean</div><div>clean:</div><div>rm -rf *.o libname.a</div><div>AIX下的动态库文件编译makefile如下：</div><div>INCLUDE= \</div><div>-I/libpath/hdf5-1.8.9/include/ -I/libpath/include -I/libpath/hdf5/ \</div><div>all: libname.so</div><div>llibname.so: zhdf.o</div><div>xlC $(INCLUDE) -q64 -bnoentry -qmkshrobj -blazy -G -o libname.so ../zhdf.cpp -lc</div><div>zhdf.o: ../zhdf.cpp</div><div>xlC $(INCLUDE) -q64 -c -lm ../zhdf.cpp -o zhdf.o</div><div>.PHONY: clean</div><div>clean:</div><div>rm -rf *.o libname.so</div><div>AIX环境下动态库和静态库的编译主要区别是动态库使用-qmkshrobj进行动态库的编译，对应Linux环境下的-shared选项，动态库编译成功后，需要进入使用该库的用户/home/user路径下，vi .profile文件，用export指令将动态库的路径加入环境变量，如export LIBPATH=yourlibpath，然后用. .profile完成对环境变量修改的保存，保存后可通过echo $LIBPATH查看是否添加成功。最后，由于AIX环境下动态库的编译机制问题，应用程序查找动态库时，会去查找一个同名的.a文件。所以，很多人动态库编译成功，应用程序编译时却无法找到该动态库。解决办法是，在动态库的路径下，创建一个同名.a的连接，如ln -s libname.so libname.a。以上，AIX环境下动态库的编译也完成啦！</div><div></div></div><img src ="http://www.cppblog.com/prayer/aggbug/216089.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2018-11-28 14:35 <a href="http://www.cppblog.com/prayer/archive/2018/11/28/216089.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GNU Makefile 之 (概要)</title><link>http://www.cppblog.com/prayer/archive/2012/03/30/169494.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Fri, 30 Mar 2012 02:51:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2012/03/30/169494.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/169494.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2012/03/30/169494.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/169494.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/169494.html</trackback:ping><description><![CDATA[<div style="word-wrap: break-word">
<p><span>1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">GNU</span><span style="font-family: 微软雅黑">的make工作时的执行<strong><span style="color: red">步骤</span></strong>入下： </span></p>
<blockquote>
<p><span style="font-family: 微软雅黑">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">读入所有的Makefile。 </span></p>
<p><span style="font-family: 微软雅黑">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">读入被include的其它Makefile。 </span></p>
<p><span style="font-family: 微软雅黑">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">初始化文件中的变量。 </span></p>
<p><span>4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">推导隐晦规则，并分析所有规则。 </span></p>
<p><span>5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">为所有的目标文件创建依赖关系链。 </span></p>
<p><span>6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">根据依赖关系，决定哪些目标要重新生成。 </span></p>
<p><span>7.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">执行生成命令。</span></p></blockquote>
<p><span style="font-family: 微软雅黑"></span>&nbsp;</p>
<p><span>2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>.PHONY 指明后面为伪目标</p>
<p style="margin-left: 18pt">.SILENT 相当于make的<span>-s参数</span>，在执行前不显示要执行的命令</p>
<p style="margin-left: 18pt">.IGNORE 相当于make的<span>-i参数</span>，当检测到错误，继续执行其他命令</p>
<p style="margin-left: 18pt">make &#8211;n 参数，读取规则并显示，但是不执行</p>
<p style="margin-left: 18pt">gcc &#8211;M <span style="font-family: 微软雅黑">由编译器自动<span style="color: blue">生成依赖关系</span></span></p>
<p style="margin-left: 18pt"><span style="font-family: 微软雅黑"></span>&nbsp;</p>
<p><span style="font-family: 微软雅黑">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">判断：ifeq/ ifneq/ ifdef/ ifndef</span></p>
<p style="text-indent: 18pt"><span style="font-family: 微软雅黑">ifeq&nbsp;($(CC),gcc) </span></p>
<p><span style="font-family: 微软雅黑">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-o&nbsp;foo&nbsp;$(objects)&nbsp;$(libs_for_gcc) </span></p>
<p><span style="font-family: 微软雅黑">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else </span></p>
<p><span style="font-family: 微软雅黑">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-o&nbsp;foo&nbsp;$(objects)&nbsp;$(normal_libs) </span></p>
<p><span style="font-family: 微软雅黑">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; endif</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 微软雅黑">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">可识别的后缀指的是特殊目标&#8220;<span style="color: red">.SUFFIXES</span>&#8221;的所有依赖的名字。通过给特殊目标&#8220;SUFFIXES&#8221;添加依赖来增加一个可被识别的后缀：</span></p>
<blockquote>
<p><span style="color: blue; font-family: 微软雅黑">&nbsp;.SUFFIXES: .hack .win</span></p></blockquote>
<p style="margin-left: 20.95pt"><span style="font-family: 微软雅黑">它所实现的功能是把后缀&#8220;.hack&#8221;和&#8220;.win&#8221;加入到可识别后缀列表的末尾。</span></p>
<p style="margin-left: 20.95pt"><span style="font-family: 微软雅黑">如果需要重设默认所有的可识别后缀，可以这样来实现：</span></p>
<p style="margin-left: 38.95pt"><span style="font-family: 微软雅黑">.SUFFIXES:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #</span><span style="font-family: 微软雅黑">删除所有已定义的可识别后缀</span></p>
<p style="margin-left: 38.95pt"><span style="font-family: 微软雅黑">.SUFFIXES: .c .o .h&nbsp;&nbsp; #</span><span style="font-family: 微软雅黑">重新定义</span></p>
<p style="margin-left: 38.95pt"><span style="font-family: 微软雅黑"></span>&nbsp;</p>
<p><span style="font-family: 微软雅黑">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑"><strong>-</strong>include filename</span><span style="font-family: 微软雅黑">，包含文件</span></p>
<p><span style="font-family: 微软雅黑"></span>&nbsp;</p>
<p><span style="font-family: 微软雅黑">6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 微软雅黑">-<a name="baidusnap2"></a>M </span><span style="font-family: 微软雅黑">生成文件的关联的信息，这样就可以知道源代码文件里面关联了哪些它所依赖的头文件。</span></p>
<p style="margin-left: 18pt"><span style="color: blue; font-family: 微软雅黑">-MD </span><span style="font-family: 微软雅黑">跟-<strong>M</strong>相当，但是<span style="color: blue">输出导入到.d文件中</span>，如gcc -MD test.c，刚输出的依赖关系存放在</span><span style="font-family: 微软雅黑">test.d</span><span style="font-family: 微软雅黑">文件里。</span></p>
<p style="margin-left: 18pt"><span style="font-family: 微软雅黑"></span>&nbsp;</p>
<p><span style="color: red; font-family: 微软雅黑">7.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong>$@</strong> 代表规则中的目标文件名</p>
<p style="margin-left: 18pt"><strong>$&lt; </strong>规则的第一个依赖文件名。如果是隐含规则，则它代表通过目标指定的第一个依赖文件。</p>
<p style="margin-left: 18pt"><strong>$^</strong> 规则的所有依赖文件列表，使用空格分隔。</p>
<p style="margin-left: 18pt">&nbsp;</p>
<p><span>8.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>我们可以使用最终万用规则来实现。例如：在调试<span>Makefile时</span>（可能一些源文件还没有完成），我们所关心的是<span>Makefile中规则的正确执行，而不关心源文件的内容。</span></p>
<p style="margin-left: 20.95pt">&nbsp;<strong>%::</strong></p>
<p style="margin-left: 20.95pt"><strong>&nbsp;&nbsp;&nbsp; touch $@</strong></p>
<p style="margin-left: 20.95pt"><strong><em></em></strong>&nbsp;</p>
<p><span>9.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>列出当前目录下所有符合模式&#8220;<span>PATTERN&#8221;格式的文件名。</span></p>
<p style="margin-left: 20.95pt">返回值：空格分割的、存在当前目录下的所有符合模式&#8220;<span>PATTERN&#8221;的文件名。</span></p>
<p style="margin-left: 20.95pt">&nbsp;<strong>$(</strong><strong>wildcard</strong><strong> *.c)</strong></p>
<p style="margin-left: 20.95pt">&nbsp;返回值为当前目录下所有<span>.c源文件列表。</span></p>
<p style="margin-left: 20.95pt">&nbsp;</p>
<p><span>10.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span>目标总会被认为是最新的。就是说：这个规则一旦被执行，<span>make就认为它的目标已经被更新过&nbsp;</span></p>
<p style="margin-left: 20.95pt"><strong>clean: </strong><strong>FORCE</strong></p>
<p style="margin-left: 20.95pt"><strong>rm $(objects)</strong></p>
<p style="margin-left: 20.95pt"><strong>FORCE:</strong></p>
<p style="margin-left: 20.95pt"><strong><em></em></strong>&nbsp;</p>
<p><span>11.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><strong>subsystem:</strong></p>
<p style="margin-left: 9pt"><strong>&nbsp;&nbsp;&nbsp;&nbsp; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cd subdir &amp;&amp; $(MAKE)</span></strong></p>
<p style="margin-left: 18pt">&nbsp;其等价于规则：</p>
<p style="margin-left: 18pt">&nbsp;<strong>subsystem:</strong></p>
<p style="margin-left: 18pt"><strong>&nbsp;&nbsp;&nbsp;&nbsp; $(MAKE) -C subdir</strong></p>
<p style="margin-left: 18pt">规则中&#8220;$(MAKE)&#8221;是对变量&#8220;<span>MAKE" 的引用。第一个规则命令的意思是：进入子目录，然后在子目录下执行make。第二个规则时用了make的</span>&#8220;<span>-C&#8221;选项</span>，同样是首先进入子目录而后再执行<span>make。</span></p>
<p style="margin-left: 18pt">&nbsp;</p>
<p><a name="_gnu_make_5.6.4"><span>12.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span>-w</a><span>选项</span></p>
<p style="margin-left: 21pt">在多级<span>make递归调用过程中，选项&#8220;-w&#8221;或者&#8220;--print-directory&#8221;可以让make在开始编译一个目录之前和完成此目录的编译之后给出相应的提示信息</span></p>
<p style="margin-left: 21pt">&nbsp;</p>
<p style="margin-left: 21pt">以下是自己写的一个<span>Makefile，目录结构为模块目录下存在inc、src、obj三个目录。由于用到了隐式规则，存在目录的一些限制，当前巴该Makefile放到子目录obj下：</span></p>
<p style="margin-left: 21pt">====================================================</p>
<p style="margin-left: 36pt">vpath %.c ../src</p>
<p style="margin-left: 36pt">INCLUDE=../inc</p>
<p style="margin-left: 36pt">&nbsp;</p>
<p style="margin-left: 36pt">CC=gcc</p>
<p style="margin-left: 36pt">CFLAGS=-g -I$(INCLUDE)</p>
<p style="margin-left: 36pt">TARGET=lib.a</p>
<p style="margin-left: 36pt">DEPENDFILE=depend.dep</p>
<p style="margin-left: 36pt">&nbsp;</p>
<p style="margin-left: 36pt">SRC_DIR=$(wildcard ../src/*.c)</p>
<p style="margin-left: 36pt">OBJS=$(patsubst %.c,%.o,$(notdir $(SRC_DIR)))</p>
<p style="margin-left: 36pt">&nbsp;</p>
<p style="margin-left: 36pt">all:$(TARGET)</p>
<p style="margin-left: 36pt">&nbsp;</p>
<p style="margin-left: 36pt">$(TARGET):$(DEPENDFILE) $(OBJS)</p>
<p style="margin-left: 36pt">&nbsp;ar -crv $@ $(OBJS)</p>
<p style="margin-left: 36pt">&nbsp;</p>
<p style="margin-left: 36pt">$(DEPENDFILE):</p>
<p style="margin-left: 36pt">&nbsp;$(CC) -M -I$(INCLUDE) $(SRC_DIR) &gt; $@</p>
<p style="margin-left: 36pt">&nbsp;</p>
<p style="margin-left: 36pt">.PHONY:clean</p>
<p style="margin-left: 36pt">clean:</p>
<p style="margin-left: 36pt">&nbsp;rm -rf $(TARGET) *.o $(DEPENDFILE)</p>
<p style="margin-left: 36pt">&nbsp;</p>
<p style="margin-left: 36pt">-include depend.*</p>
<p style="margin-left: 21pt">====================================================</p></div><img src ="http://www.cppblog.com/prayer/aggbug/169494.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2012-03-30 10:51 <a href="http://www.cppblog.com/prayer/archive/2012/03/30/169494.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Unix环境下嵌入式C程序编译 </title><link>http://www.cppblog.com/prayer/archive/2012/03/21/168489.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Wed, 21 Mar 2012 05:45:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2012/03/21/168489.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/168489.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2012/03/21/168489.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/168489.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/168489.html</trackback:ping><description><![CDATA[<div class="blog_content" id="blog_content">A.预编译部分 <br />1.预编译DB2篇 <br />1.1 什么是DB2预编译 <br />&nbsp; 在我们用C语言编写访问DB2的程序过程中,需要用到嵌入式SQL,其作用是将DB2 SQL混入一般C程序中, DB2预编译器可以将SQL语法直接转换为DB2行时服务应用程序编程接口（API）调用。 <br />1.2 什么是bind <br />&nbsp; 这是DB2 prep要做的事情，即把SQC中的SQL语句变为DB2数据库可认的API。bind的作用主要是根据你SQC中的SQL语句使用的表和操作指定一个访问时DB要使用的策略，是一种优化作用，加快数据访问的速度；当然也可以不bind，那样，访问的过程策略是在访问时才有的，速度会受很大的影响，特别是并发访问。 <br /><br />2.预编译命令 <br />&nbsp; 2.1 db2 prep .sqc文件 bindfile 其中bindfile参数作用是生成和sqc文件同名的.bnd文件 <br />例: db2 prep /export/home/shwhome/sqc/CON_DB2.sqc bindfile 如果编译正常完成,则在.sqc文件同目录下会生成CON_DB2.c和CON_DB2.bnd文件 <br />2.2 bind .bnd文件 <br />&nbsp; 例: db2 bind /export/home/shwhome/sqc/CON_DB2.bnd <br />因为是DB2的预编译命令,使用的是DB2的预编译器,所以以上两条命令需要在连接DB2数据库的情况下才可以使用 <br /><br />B.嵌入式部分 <br />1.嵌入式C程序的编译 <br />我们采用GCC来编译C程序,GCC的一般编译命令请参考文档中的相关说明,这里具体说明在目前环境下编译C程序的注意点。 <br />1.1 编译C程序 <br />gcc -m64 -c -I/export/home/shwhome/inc -o /export/home/shwhome/obj/testdb.o /export/home/shwhome/src/testdb.c <br />参数说明 <br />-m64: 在64位服务器上编译时采用,这里为了将所有的编译后的目标文件统一,所以都加上-m64,如果再之后引用目标文件没有采用-m64编译则在最后编译时会出现ELF CLASS32(或ELF CLASS64)错误. -C: 只编译并生成目标文件,不做链接。 <br />1.2 编译SQC文件生成的.C文件 <br />gcc -m64 -c -I/export/home/shwhome/inc -I/export/home/aix/sqllib/include -L/usr/include/lib -o /export/home/shwhome/obj/CON_DB2.o /export/home/shwhome/sqc/CON_DB2.c <br />参数说明 <br />-I/export/home/aix/sqllib/include: 这个目录下主要使用到2个头文件:sqladef.h和sqlca.h,这个是DB2预编译包含的都文件,可以查看你用prep编译出来的与.sqc同名的.C文件,其中就包含这两个头文件。其中aix是DB2Instance用户,DB2安装后会将include路径复制到instance用户的环境变量中,再次创建instance后只要复制过来就可以,因为Instance用户还包含其他的环境设定,所以不要直接引用-I/opt/IBM/db2/V9.5/include/这个DB2的安装路径 <br />-L/usr/include/lib: 这个目录是系统包含函数的库文件,是编写应用程序的时候使用的相当于API,也就是应用编程接口。 <br />&#8251; -I/usr/include和-L/usr/include/lib是将usr/include下的函数作为头文件包括进来,并且将程序链接到库文件,这个例子中没有用到,但是如果保险的话,在编译时最好加上这两个选项。 <br />1.3 将两个目标文件(主体C程序和嵌入式SQL)编译成可执行程序 <br />gcc -m64 -ldb2 -lc -o /export/home/shwhome/bin/testdb /export/home/shwhome/obj/CON_DB2.o /export/home/shwhome/obj/testdb.o <br />参数说明 <br />-ldb2: 链接DB2库文件。在SQC程序编译时必须链接libdb2.so库,其路径是/usr/lib/krb5/libdb2.so,之所以写成-ldb2,是在使用-l时,将库名的lib和后缀都去除,即库名是db2。以上命令是引用/export/home/shwhome/obj/CON_DB2.o /export/home/shwhome/obj/testdb.o这两个目标文件,编译后生成testdb,放在路径/export/home/shwhome/bin下。 </div><img src ="http://www.cppblog.com/prayer/aggbug/168489.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2012-03-21 13:45 <a href="http://www.cppblog.com/prayer/archive/2012/03/21/168489.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Makefile", line 1: make: Dependency line needs colon or double colon operator.</title><link>http://www.cppblog.com/prayer/archive/2012/02/24/166419.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Fri, 24 Feb 2012 05:13:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2012/02/24/166419.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/166419.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2012/02/24/166419.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/166419.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/166419.html</trackback:ping><description><![CDATA[<p>&nbsp; 问题描述：从CVS上下载一个Makefile文件，上传AIX测试服务器上，通过make进行C++代码的编译和打包，出现下列的错误：</p>
<p>&nbsp;</p>
<p>Makefile", line 1: make: Dependency line needs colon or double colon operator.<br />"Makefile", line 7: make: Dependency line needs colon or double colon operator.<br />", line 0: make: Cannot open /gboss/anta32/stdmake/stdenv<br />"Makefile", line 10: make: Dependency line needs colon or double colon operator.<br />"Makefile", line 13: make: Dependency line needs colon or double colon operator.<br />"Makefile", line 14: make: Dependency line needs colon or double colon operator.<br />"Makefile", line 18: make: Dependency line needs colon or double colon operator.<br />"Makefile", line 21: make: Dependency line needs colon or double colon operator.<br />"Makefile", line 24: make: Dependency line needs colon or double colon operator.<br />"Makefile", line 28: make: Dependency line needs colon or double colon operator</p>
<p>......</p>
<p>&nbsp;</p>
<p>原来是上传文件时的编码没有设置好，要用asc进行编码。重新上传后，正常。</p><img src ="http://www.cppblog.com/prayer/aggbug/166419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2012-02-24 13:13 <a href="http://www.cppblog.com/prayer/archive/2012/02/24/166419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>老式风格的"后缀规则" </title><link>http://www.cppblog.com/prayer/archive/2010/02/08/107476.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 08 Feb 2010 02:43:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2010/02/08/107476.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/107476.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2010/02/08/107476.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/107476.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/107476.html</trackback:ping><description><![CDATA[后缀规则是一个比较老式的定义隐含规则的方法。后缀规则会被模式规则逐步地取代。因为模式规则更强更清晰。为了和老版本的Makefile兼容，GNU&nbsp;make同样兼容于这些东西。后缀规则有两种方式："双后缀"和"单后缀"。 <br><br>双后缀规则定义了一对后缀：目标文件的后缀和依赖目标（源文件）的后缀。如".c.o"相当于"%o&nbsp;:&nbsp;%c"。单后缀规则只定义一个后缀，也就是源文件的后缀。如".c"相当于"%&nbsp;:&nbsp;%.c"。 <br><br>后缀规则中所定义的后缀应该是make所认识的，如果一个后缀是make所认识的，那么这个规则就是单后缀规则，而如果两个连在一起的后缀都被make所认识，那就是双后缀规则。例如：".c"和".o"都是make所知道。因而，如果你定义了一个规则是".c.o"那么其就是双后缀规则，意义就是".c"是源文件的后缀，".o"是目标文件的后缀。如下示例： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;.c.o: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-c&nbsp;$(CFLAGS)&nbsp;$(CPPFLAGS)&nbsp;-o&nbsp;$@&nbsp;$&lt; <br><br>后缀规则不允许任何的依赖文件，如果有依赖文件的话，那就不是后缀规则，那些后缀统统被认为是文件名，如： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;.c.o:&nbsp;foo.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-c&nbsp;$(CFLAGS)&nbsp;$(CPPFLAGS)&nbsp;-o&nbsp;$@&nbsp;$&lt; <br><br>这个例子，就是说，文件".c.o"依赖于文件"foo.h"，而不是我们想要的这样： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;%.o:&nbsp;%.c&nbsp;foo.h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-c&nbsp;$(CFLAGS)&nbsp;$(CPPFLAGS)&nbsp;-o&nbsp;$@&nbsp;$&lt; <br><br>后缀规则中，如果没有命令，那是毫无意义的。因为他也不会移去内建的隐含规则。 <br><br>而要让make知道一些特定的后缀，我们可以使用伪目标".SUFFIXES"来定义或是删除，如： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;.SUFFIXES:&nbsp;.hack&nbsp;.win <br><br>把后缀.hack和.win加入后缀列表中的末尾。 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;.SUFFIXES:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;删除默认的后缀 <br>&nbsp;&nbsp;&nbsp;&nbsp;.SUFFIXES:&nbsp;.c&nbsp;.o&nbsp;.h&nbsp;&nbsp;&nbsp;#&nbsp;定义自己的后缀 <br><br>先清楚默认后缀，后定义自己的后缀列表。 <br><br>make的参数"-r"或"-no-builtin-rules"也会使用得默认的后缀列表为空。而变量"SUFFIXE"被用来定义默认的后缀列表，你可以用".SUFFIXES"来改变后缀列表，但请不要改变变量"SUFFIXE"的值。 <br>
<img src ="http://www.cppblog.com/prayer/aggbug/107476.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2010-02-08 10:43 <a href="http://www.cppblog.com/prayer/archive/2010/02/08/107476.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GNU make 的主要预定义变量 </title><link>http://www.cppblog.com/prayer/archive/2010/01/22/106227.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Fri, 22 Jan 2010 07:45:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2010/01/22/106227.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/106227.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2010/01/22/106227.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/106227.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/106227.html</trackback:ping><description><![CDATA[表 13-2 GNU make 的主要预定义变量 <br>　　预定义变量 <br>　　含义 <br>　　$* <br>　　不包含扩展名的目标文件名称。 <br>　　$+ <br>　　所有的依赖文件，以空格分开，并以出现的先后为序，可能包含重复的依赖文件。 <br>　　$&lt; <br>　　第一个依赖文件的名称。 <br>　　$? <br>　　所有的依赖文件，以空格分开，这些依赖文件的修改日期比目标的创建日期晚。 <br>　　$@ <br>　　目标的完整名称。 <br>　　$^ <br>　　所有的依赖文件，以空格分开，不包含重复的依赖文件。 <br>　　$% <br>　　如果目标是归档成员，则该变量表示目标的归档成员名称。例如，如果目标名称为 <br>　　mytarget.so(image.o)，则 $@ 为 mytarget.so，而 $% 为 image.o。 <br>　　AR <br>　　归档维护程序的名称，默认值为 ar。 <br>　　ARFLAGS <br>　　归档维护程序的选项。 <br>　　AS <br>　　汇编程序的名称，默认值为 as。 <br>　　ASFLAGS <br>　　汇编程序的选项。 <br>　　CC <br>　　C 编译器的名称，默认值为 cc。 <br>　　CFLAGS <br>　　C 编译器的选项。 <br>　　CPP <br>　　C 预编译器的名称，默认值为 $(CC) -E。 <br>　　CPPFLAGS <br>　　C 预编译的选项。 <br>　　CXX <br>　　C++ 编译器的名称，默认值为 g++。 <br>　　CXXFLAGS <br>　　C++ 编译器的选项。 <br>　　FC <br>　　FORTRAN 编译器的名称，默认值为 f77。 <br>　　FFLAGS <br>　　FORTRAN 编译器的选项。<br>
<img src ="http://www.cppblog.com/prayer/aggbug/106227.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2010-01-22 15:45 <a href="http://www.cppblog.com/prayer/archive/2010/01/22/106227.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正确的makefile</title><link>http://www.cppblog.com/prayer/archive/2010/01/22/106226.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Fri, 22 Jan 2010 07:38:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2010/01/22/106226.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/106226.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2010/01/22/106226.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/106226.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/106226.html</trackback:ping><description><![CDATA[<p>DB2&nbsp;&nbsp;&nbsp; = db2<br>CC&nbsp;&nbsp;&nbsp;&nbsp; = cc<br>CFLAGS = -O</p>
<p>IP1&nbsp;&nbsp; = /ZDZ_UAT/usr/sqllib/include<br>LP1&nbsp;&nbsp; = /ZDZ_UAT/usr/sqllib/lib<br>LIB1&nbsp; = db2</p>
<p>DATABASE = mydb<br>USER = 1111<br>PASSWD = 1111</p>
<p>EXE = myfirst</p>
<p>SQC = myfirst.sqc<br>CFILE = myfirst.c<br>BND = myfirst.bnd<br>OBJ = myfirst.o</p>
<p>all : $(EXE)</p>
<p>$(EXE) : $(OBJ)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(CC) $(CFLAGS) -L$(LP1) $(OBJ) -o $@ -l$(LIB1);</p>
<p>$(OBJ) : $(CFILE)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(CC) -g -c $(CFLAGS) -I$(IP1) $(CFILE)</p>
<p>$(CFILE) $(BND) : $(SQC)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(DB2) connect to $(DATABASE) user $(USER) using $(PASSWD) ;\<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(DB2) prep $(SQC) bindfile ;\<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(DB2) bind $(BND); \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(DB2) connect reset<br>clean :<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rm $(CFILE) $(BND) $(OBJ) $(EXE)</p>
<img src ="http://www.cppblog.com/prayer/aggbug/106226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2010-01-22 15:38 <a href="http://www.cppblog.com/prayer/archive/2010/01/22/106226.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用AutoMake轻松生成Makefile</title><link>http://www.cppblog.com/prayer/archive/2010/01/22/106225.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Fri, 22 Jan 2010 07:02:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2010/01/22/106225.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/106225.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2010/01/22/106225.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/106225.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/106225.html</trackback:ping><description><![CDATA[在 Unix 上写过程序的人一般都遇到过 Makefile，尤其是用 C 来开发程序的人。用 make 来开发和编译程序的确很方便，可是要写出一个MakeFile就不那么简单了。偏偏介紹 Makefile 的文件不多，GNU Make 那份印出来要几百页的文件，光看完 Overview 自己就快要先Over了，难怪许多人闻 Unix色变。本文将介绍如何利用 GNU Autoconf 及 Automake 这两套软件来帮助『自动』产生 Makefile 文件，并且让开发出来的的软件可以象 Apache, MySQL 和常見的 GNU 软件一样，只要会 ``./configure', ``make', ``make install' 就可以把程序安裝到系统中。如果您有心开发 Open Source 的软件，或只是想在 Unix 系統下写写程序。希望这份介绍文件能帮助您轻松的进入 Unix Programming 的殿堂。 <br><br>　 <br><br>　 <br><br>1. 简介 <br>Makefile 基本上就是『目标』(target), 『关联』(dependencies) 和『动作』三者所组成的一系列规则。而 make 就会根据 Makefile 的规则来決定如何编译 (compile) 和连接 (link) 程式。实际上，make 可做的不只是编译和连接程序，例如 FreeBSD 的 port collection 中，Makefile还可以做到自动下载远程程序，解压缩 (extract) ， 打补丁 (patch)，设定，然后编译，安装到系统中。 <span class=Sqx657></span><br><br>Makefile 基本结构虽然很简单，但是妥善运用这些规则就可以变换出许多不同的花样。却也因为这样，许多刚刚开始学习写Makefile 时会觉得没有规范可以遵循，每个人写出来的Makefile都不大一样，不知道从哪里下手，而且常常会受到自己的开发环境的限制，只要环境参数不同或者路径更改，可能 Makefile 就得跟着修改修改。虽然有 GNU Makefile Conventions (GNU Makefile惯例例)订出一些使用 GNU 程式设计时撰写 Makefile 的一些标准和规范，但是内容很长而且很复杂，并且经常作一些调整，为了减轻程序开发人员维护Makefile 的负担，因此出现了Automake。 <br><br>程序设计者只需要写一些预先定义好的宏 (macro)，提交给Automake处理后会产生一个可以供 Autoconf 使用的 Makefile.in文件。再配合利用 Autoconf产生的自动培植设置文件 configure 即可产生一份符合符合 GNU Makefile 惯例的 Makeifle 了。 <br><br>　 <br><br>2. 上路之前 <br>在开始使用 Automake 之前，首先确认你的系统安装有如下软件： <br><br>　 <br><br>1. <br>GNU Automake <br>2. <br>GNU Autoconf <br>3. <br>GNU m4 <br>4. <br>perl <br>5. <br>GNU Libtool (如果你需要产生 shared library) <br>建议最好也使用 GNU C/C 编译器 、GNU Make 以及其它 GNU 的工具程序来作为开发的环境，这些工具都是属于 Open Source Software 不但免费而且功能强大。如果你是使用 Red Hat Linux 可以找到所有上述软件的 rpm 文件，FreeBSD 也有现成的 package 可以直接安装，或也可以自行下载这些软件的源代码回来安装。下面的示例是在Red Hat Linux 5.2 CLE2 的环境下所完成的。
<div class=Sqx657></div>
<br><br>　 <br><br>3. 一个简单的例子 <br>Automake 所产生的 Makefile 除了可以做到程式的编译和连接，也已经把如何产生程序文件 (如 manual page, info 文件及 dvi 文件) 的动作，还有把源码文件包装起来以供发布都考虑进去了，所以程序源代码所存放的目录结构最好符合GNU 的标准惯例，接下来就用一个hello.c 來做为例子。 <br><br>在工作目录下建立一个新的子目录"devel"'，再在 devel 下建立一个"hello"' 的子目录，这个目录将作为存放 hello这个程序及其相关文件的地方： <br><br>% mkdir devel <br>% cd devel <br>% mkdir hello <br>% cd hello <br>用编辑器写一个hello.c文件， <br><br><br>#include <stdio.h><br>int main(int argc, char** argv) { <br>printf(``Hello, GNU!n'); <br>return 0; <br>} <br>接下来就要用 Autoconf 及 Automake 來产生 Makefile 文件了， <br><br>1. <br>用 autoscan 产生一个 configure.in 的原型，执行autoscan 后会产生一个configure.scan 的文件，可以用它作为 configure.in文件的蓝本。 <br>　 <br>% autoscan <br>% ls <br>configure.scan hello.c <br>2. <br>编辑 configure.scan文件，如下所示，並且改名为configure.in <br>dnl Process this file with autoconf to produce a configure script. AC_INIT(hello.c) AM_INIT_AUTOMAKE(hello, 1.0) <br>dnl Checks for programs. <br>AC_PROG_CC <br>dnl Checks for libraries. <br>dnl Checks for header files. <br>dnl Checks for typedefs, structures, and compiler characteristics. <br>dnl Checks for library functions. <br>AC_OUTPUT(Makefile) <br>3. <br>执行 aclocal 和 autoconf ，分別会产生 aclocal.m4 及 configure 两个文件 <br>% aclocal <br>% autoconf <br>% ls <br>aclocal.m4 configure configure.in hello.c <br>4. <br>编辑 Makefile.am 文件，內容如下 <br>AUTOMAKE_OPTIONS= foreign
<div class=Cos786></div>
<br>bin_PROGRAMS= hello <br>hello_SOURCES= hello.c <br>5. <br>执行 automake --add-missing ，Automake 会根据Makefile.am 文件产生一些文件，包含最重要的 Makefile.in <br>% automake --add-missing automake: configure.in: installing `./install-sh' automake: configure.in: installing `./mkinstalldirs' automake: configure.in: installing `./missing' <br>6. <br>最后执行 ./configure ， <br>% ./configure creating cache ./config.cache checking for a BSD compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking whether make sets ${MAKE}... yes checking for working aclocal... found checking for working autoconf... found checking for working automake... found checking for working autoheader... found checking for working makeinfo... found checking for gcc... gcc checking whether the C compiler (gcc ) works... yes checking whether the C compiler (gcc ) is a cross-compiler... no checking whether we are using GNU C... yes checking whether gcc accepts -g... yes updating cache ./config.cache creating ./config.status creating Makefile
<p class=Cos786>软件开发网</p>
<br>現在你的目录下已经产生了一个 Makefile 檔，下個 ``make' 指令就可以開始編譯 hello.c 成執行檔，執行 ./hello 和 GNU 打聲招呼吧！ <br><br>% make gcc -DPACKAGE="hello" -DVERSION="1.0" -I. -I. -g -O2 -c hello.c gcc -g -O2 -o hello hello.o % ./hello Hello! GNU! <br>你還可以試試 ``make clean'，'make install'，'make dist' 看看會有什麼結果。你也可以把產生出來的 Makefile 秀給你的老闆，讓他從此對你刮目相看 :-) <br><br>4. 追根问底 <br>上述产生Makefile 的过程和以往自行编写的方式非常不一樣，舍弃传统自定义make 的规则，使用 Automake 只需用到一些已经定义好的宏就可以了。我们把宏及目标 (target)写在Makefile.am 文件内，Automake 读入 Makefile.am 文件后会把这一串已经定义好的宏展开并产生相对应的 Makefile.in 文件，然后再由 configure这个 shell script 根据 Makefile.in 产生合适的Makefile。 <br><br><br>[Figure 1:利用 autoconf 及 automake产生Makefile 的流程] <br><br>上图表示在上一范例中要使用的文件档案及产生出来的文件，有星号 (*) 者代表可执行文件。在此示例中可由 Autoconf 及 Automake 工具所产生的额外文件有 configure.scan、aclocal.m4、configure、Makefile.in，需要自行加入设置的有configure.in 及 Makefile.am。 <br><br>4.1 编辑 configure.in 文件 <br>Autoconf 是用来产生 'configure'文件的工具。'configure' 是一个 shell script，它可以自动设定原始程序以符合各种不同平台上Unix 系统的特性，并且根据系统参数及环境产生合适的Makefile文件或C 的头文件(header file)，让原始程式可以很方便地在不同的平台上进行编译。Autoconf会读取 configure.in 文件然后产生'configure' 这个 shell script。 <br><br>configure.in 文件内容是一系列GNU m4 的宏，这些宏经autoconf处理后会变成检查系统特性的shell scripts。 configure.in 内宏的顺序并没有特别的规定，但是每一个configure.in 文件必須在所有宏前加入 AC_INIT 宏，然后在所有宏的最后加上 AC_OUTPUT宏。可先用 autoscan 扫描原始文件以产生一个 configure.scan 文件，再对 configure.scan 做些修改成 configure.in 文件。在范例中所用到的宏如下： <br><br>dnl <br>这个宏后面的字不会被处理，可以视为注释 <br>AC_INIT(FILE) <br>该宏用来检查源代码所在路径，autoscan 会自动产生，一般无须修改它。 <br>AM_INIT_AUTOMAKE(PACKAGE,VERSION) <br>这个是使用 Automake 所必备的宏，PACKAGE 是所要产生软件套件的名称，VERSION 是版本编号。 <br>AC_PROG_CC <font color=#ffffff></font><br>检查系统可用的C编译器，若源代码是用C写的就需要这个宏。 <br>AC_OUTPUT(FILE) <br>设置 configure 所要产生的文件，若是Makefile ，configure 便会把它检查出来的结果带入 Makefile.in 文件后产生合适的 Makefile。 <br>实际上，这里使用 Automake 时，还需要一些其他的宏，这些额外的宏我们用 aclocal来帮助产生。執行 aclocal会产生aclocal.m4 文件，如果无特别的用途，可以不需要修改它，用 aclocal 所产生的宏会告诉 Automake如何动作。 <br><br>有了 configure.in 及 aclocal.m4两个文件以后，便可以执行 autoconf来产生 configure 文件了。 <br><br>4.2 编辑Makefile.am 文件 <br>接下来要编辑Makefile.am 文件，Automake 会根据 configure.in 中的宏把Makefile.am 转成 Makefile.in 文件。 Makefile.am 文件定义所要产生的目标： <br><br>AUTOMAKE_OPTIONS <br>设置 automake 的选项。Automake 主要是帮助开发 GNU 软件的人员来维护软件，所以在执行 automake 时，会检查目录下是否存在标准 GNU 软件中应具备的文件，例如 'NEWS'、'AUTHOR'、'ChangeLog' 等文件。设置 foreign 时，automake 会改用一般软件的标准来检查。 <br>bin_PROGRAMS <br>定义要产生的执行文件名。如果要产生多个执行文件，每个文件名用空白符隔开。 <font color=#ffffff></font><br>hello_SOURCES <br>定义 'hello' 这个执行程序所需要的原始文件。如果 'hello'这个程序是由多个原始文件所产生，必須把它所用到的所有原始文件都列出来，以空白符隔开。假设 'hello' 还需要 'hello.c'、'main.c'、'hello.h' 三个文件的话，则定义 <br>hello_SOURCES= hello.c main.c hello.h <br>如果定义多个执行文件，则对每个执行程序都要定义相对的filename_SOURCES。 <br><br>编辑好 Makefile.am 文件，就可以用 automake --add-missing来产生 Makefile.in。加上 --add-missing 选项来告诉 automake顺便假如包装一个软件所必须的文件。Automake产生生出來的 Makefile.in 文件是完全符合 GNU Makefile 的惯例，只要执行 configure这个shell script 便可以产生合适的 Makefile 文件了。 <br><br>4.3 使用 Makefile <br>利用 configure 所产生的 Makefile文件有几个预先设定的目标可供使用，这里只用几个简述如下： <br><br>make all <br>产生设定的目标，既次范例中的执行文件。只敲入make 也可以，此时会开始编译源代码，然后连接并产生执行文件。 <br>make clean <br>清除之前所编译的执行文件及目标文件(object file, *.o)。 <br>make distclean <br>除了清除执行文件和目的文件以外，也把 configure 所产生的 Makefile 清除掉。 <br><br>make install <br>將程序安装到系统中，若源码编译成功，且执行结果正确，便可以把程序安装到系统预先设定的执行文件存放路径中，若用 bin_PROGRAMS 宏的话，程序会被安装到 /usr/local/bin下。 <br>make dist <br>將程序和相关的文档包装为一个压缩文档以供发布 (distribution) 。执行完在目录下会产生一个以PACKAGE-VERSION.tar.gz 为名称的文件。PACKAGE 和 VERSION 这两个参数是根据 configure.in 文件中 AM_INIT_AUTOMAKE(PACKAGE, VERSION) 的定义。在此范例中会产生 'hello-1.0.tar.gz' 的文件。 <br>make distcheck <br>和 make dist 类似，但是加入检查包装以后的压缩文件是否正常，这个目标除了把程序和相关文档包装成 tar.gz 文件外，还会自动把这个压缩文件解开，执行 configure，并执行 make all ，确认编译无错误以后，户显示这个 tar.gz 文件已经准备好可以发布了。这个检查非常有用，检查过关的套件，基本上可以给任何具备 GNU 开发环境的人去重新编译成功。就 hello-1.tar.gz 这个范例而言，除了在Red Hat Linux 上，在 FreeBSD 2.2.x 也可以正确编译。 <br>要注意的是，利用 Autoconf 及 Automake 所产生出來的软件套件是可以在没有安装 Autoconf 及 Automake 的环境使用的，因为 configure 是一个 shell script，它己被设计为可以在一般 Unix 的 sh 这个 shell 下执行。但是如果要修改 configure.in 及 Makefile.am 文件再产生新的 configure 及 Makefile.in 文件时就一定要有 Autoconf 及 Automake 了。 <font color=#ffffff>软件开发网</font> <br><br>5. 相关资料 <br>Autoconf 和 Automake 功能十分强大，可以从它们附带的 info 稳当4中找到详细的使用方法说明。你也可以从许多现有的GNU 软件或 Open Source 软件中找到相关的 configure.in 或 Makefile.am 文件，他们是学习 Autoconf 及 Automake 更多技巧的最佳范例。 <br><br>这个简介只用到了 Autoconf 及 Automake 的皮毛罢了，如果你有心加入 Open Source 软件开发的行列，希望这篇文章可以帮助你对产生 Makefile 有个简单的了解。其它有关开发 GNU 程式或 C 程序设计及 Makefile 的详细运用及技巧，建议从 GNU Coding Standards (GNU 编码规定) 读起，里面包含了 GNU Makefile 惯例，及开发 GNU 软件的标准程序和惯例。这些 GNU 软件的在线说明文件可以在 http://www.gnu.org/ 上找到。 <br><br>6. 结束语 <br>利用 Autoconf 及 Automake，产生一个 Makefile 似乎不再象以前那么困难了，而使用 Autoconf 也使得我们在不同平台上或各家 Unix 之间发布及便宜程序变的简单，这对于在Unix 系统上程序开发员来说减轻了许多负担。妥善运用这些 GNU 的工具软件，可以帮助我们更容易的去开发程序，而且更容易维护源代码。 </font><br>
<img src ="http://www.cppblog.com/prayer/aggbug/106225.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2010-01-22 15:02 <a href="http://www.cppblog.com/prayer/archive/2010/01/22/106225.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>错误的makefile</title><link>http://www.cppblog.com/prayer/archive/2010/01/21/106193.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Thu, 21 Jan 2010 15:22:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2010/01/21/106193.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/106193.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2010/01/21/106193.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/106193.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/106193.html</trackback:ping><description><![CDATA[<p>DB2&nbsp;&nbsp;&nbsp; = db2<br>CC&nbsp;&nbsp;&nbsp;&nbsp; = cc<br>CFLAGS = -O</p>
<p>IP1&nbsp;&nbsp; = /home/ppqf_sd/sqllib/include<br>LP1&nbsp;&nbsp; = /home/ppqf_sd/sqllib/lib<br>LIB1&nbsp; = db2</p>
<p>DATABASE = mydb<br>USER = ppqf_sd<br>PASSWD = ppqf_sd</p>
<p>EXE = myfirst</p>
<p>SQC = myfirst.sqc<br>C&nbsp;&nbsp; = myfirst.c<br>BND = myfirst.bnd<br>OBJ = myfirst.o</p>
<p>all : $(EXE)</p>
<p>$(EXE) : $(OBJ)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(CC) $(CFLAGS) -L$(LP1) $(OBJ) -o $@ -l$(LIB1);</p>
<p>$(OBJ) : $(C)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(CC) -g -c $(CFLAGS) -I$(IP1) $(C)</p>
<p>$(C) $(BND) : $(SQC)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(DB2) connect to $(DATABASE) user $(USER) using $(PASSWD) ;/<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(DB2) prep $(SQC) target cplusplus bindfile using $(BND) ;/<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(DB2) bind $(BND); /<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(DB2) connect reset<br>clean :<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rm $(C) $(BND) $(OBJ) $(EXE)</p>
<img src ="http://www.cppblog.com/prayer/aggbug/106193.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2010-01-21 23:22 <a href="http://www.cppblog.com/prayer/archive/2010/01/21/106193.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DB2下嵌入C(sqC) 的编译，连接，环境，路径，make file 的问题 </title><link>http://www.cppblog.com/prayer/archive/2010/01/21/106192.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Thu, 21 Jan 2010 15:19:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2010/01/21/106192.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/106192.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2010/01/21/106192.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/106192.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/106192.html</trackback:ping><description><![CDATA[<br>GCC=gcc<br>CC=gcc<br><br><br><br>DB2PATH=/&#215;&#215;&#215;&#215;/&#215;&#215;&#215;&#215;/sqllib<br>CCFLAGS=-g<br><br>CFLAGS=&nbsp;&nbsp;-I$(DB2PATH)/include<br><br>LIBS= -L $(DB2PATH)/lib&nbsp; &nbsp;-ldb2<br>UID=XXXX<br>PWD=XXX<br>DB=XXX<br><br>BILLHOME=.<br>BILLBIN=.<br>BILLSRC=$(BILLHOME)<br>BILLOBJ=$(BILLHOME)<br>BILLLIB=../lib<br><br>INCLUDE=-I. -I$(BILLHOME)/src -I$(BILLLIB) \<br>&nbsp; &nbsp;&nbsp; &nbsp; -I$(DB2PATH)/include \<br>&nbsp; &nbsp;&nbsp; &nbsp; -I/usr/lib -I/usr/local/include \<br>&nbsp; &nbsp;&nbsp; &nbsp; -I/usr/include<br><br><br>TARGET1 = $(BILLBIN)/test<br>all(TARGET1)<br><br>.sqc.o:<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;db2 connect to $(DB) user $(UID) using $(PWD);\<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;db2 prep $*.sqc bindfile;\<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;db2 bind $*.bnd;\<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;db2 connect reset;\<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$(CC) $(INCLUDE) -o&nbsp;&nbsp;$*.o -c&nbsp;&nbsp;$(CCFLAGS) $(CFLAGS) $(DEFS)&nbsp;&nbsp;$*.c ;<br><br>.c.o:<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$(CC) $ (INCLUDE) -o&nbsp;&nbsp;$*.o -c&nbsp;&nbsp;$(CCFLAGS) $(CFLAGS) $(LIBS) $(DEFS) $*.c --def \standard.def<br><br><br>PICK_OBJS1= $(BILLSRC)/test.o<br><br>$(BILLBIN)/test:&nbsp; &nbsp; $(PICK_OBJS1)<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$(CC) $(CFLAGS) -o $(TARGET1)&nbsp;&nbsp;$(PICK_OBJS1)&nbsp;&nbsp;$(ORACLE_LIB)$(LINKFLAG) $(LIBS)<br><br>clean:<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;rm -f *.o $(TARGET1) test.c test.o test.bnd
<img src ="http://www.cppblog.com/prayer/aggbug/106192.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2010-01-21 23:19 <a href="http://www.cppblog.com/prayer/archive/2010/01/21/106192.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>制作和使用静态库</title><link>http://www.cppblog.com/prayer/archive/2009/12/15/103280.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Tue, 15 Dec 2009 13:35:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2009/12/15/103280.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/103280.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2009/12/15/103280.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/103280.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/103280.html</trackback:ping><description><![CDATA[<div class=tit>AIX使用CC工具生成静态库（by Capcom）</div>
<div class=date>2009-01-07 11:25</div>
<table style="TABLE-LAYOUT: fixed; WIDTH: 100%">
    <tbody>
        <tr>
            <td>
            <div class=cnt id=blog_text>
            <p>以前在linux和unix solaris平台上，使用GCC编写过动态库（.so），编写和使用动态库文档有时间再整理到博客</p>
            <p>本次我想记录和共享一下AIX上使用CC工具如何生成静态库（.a）</p>
            <p>首先有一台aix操作系统的服务器</p>
            <p>编码中心思想：</p>
            <p>1、我们写的普通C程序都有函数，我们先养成好的习惯，头文件和实现分开</p>
            <p>2、一个.c文件通过cc -c 命令生成了.o</p>
            <p>3、现在只要将.o合并成.a文件即可，无需专门的导出头文件之类VC和GCC的动态库编译的东东</p>
            <p>4、可以将很多.o合并在一个.a中，使用ar -rv 命令</p>
            <p>如： ar -rv all.a 1.o 2.o 3.o</p>
            <p>简单不，然后这个.a别人就可以使用了</p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<div class=date>2009-01-07 16:23</div>
<table style="TABLE-LAYOUT: fixed; WIDTH: 100%">
    <tbody>
        <tr>
            <td>
            <div class=cnt id=blog_text>
            <p>怎么说呢，太简单了，但是还是写一下</p>
            <p>直接说了，使用动态库的程序需要静态库的头文件（和windows很像）</p>
            <p>编译命令如下</p>
            <p>cc -o run a.o b.o A.a B.a</p>
            <p>不知道怎么说，只能说静态库比动态库简单太多，将.o文件打包而已</p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/prayer/aggbug/103280.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2009-12-15 21:35 <a href="http://www.cppblog.com/prayer/archive/2009/12/15/103280.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ar命令和nm命令</title><link>http://www.cppblog.com/prayer/archive/2009/09/14/96090.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 14 Sep 2009 02:03:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2009/09/14/96090.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/96090.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2009/09/14/96090.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/96090.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/96090.html</trackback:ping><description><![CDATA[<div class=cnt id=blog_text>ar-create,modify and extract from archive<br>nm-list symbol from obj files -可以查看动态库中都有些什么函数<br>当我们的程序中有经常使用的模块，而且这种模块在其他程序中也会用到，这时按照软件重用的思想，我们应该将它们生成库，使得以后编程可以减少开发代码量。这里介绍两个命令ar和nm，用来对库操作。<br><br>1、ar基本用法<br><br>ar命令可以用来创建、修改库，也可以从库中提出单个模块。库是一单独的文件，里面包含了按照特定的结构组织起来的其它的一些文件（称做此库文件的member）。原始文件的内容、模式、时间戳、属主、组等属性都保留在库文件中。<br><br>下面是ar命令的格式：<br><br>ar[-][abcfilNoPsSuvV][membername][count]archivefiles...<br><br>例如我们可以用ar rvl ibtest.a hello.o hello1.o来生成一个库，库名字是test，链接时可以用-ltest链接。该库中存放了两个模块hello.o和hello1.o。选项前可以有 &#8216;-&#8217;字符，也可以没有。下面我们来看看命令的操作选项和任选项。现在我们把部分称为操作选项，而[abcfilNoPsSuvV]部分称为任选项。<br><br>中的操作选项在命令中只能并且必须使用其中一个，它们的含义如下：<br><br>d：从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块。<br><br>m：该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义)，则成员的位置顺序很重要。如果没有指定任选项，任何指定的成员将移到库的最后。也可以使用&#8217;a&#8217;，&#8217;b&#8217;，或&#8217;I&#8217;任选项移动到指定的位置。<br><br>p：显示库中指定的成员到标准输出。如果指定任选项v，则在输出成员的内容前，将显示成员的名字。如果没有指定成员的名字，所有库中的文件将显示出来。<br><br>q：快速追加。增加新模块到库的结尾处。并不检查是否需要替换。&#8217;a&#8217;，&#8217;b&#8217;，或&#8217;I&#8217;任选项对此操作没有影响，模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。这时，库的符号表没有更新，可以用&#8217;ars&#8217;或ranlib来更新库的符号表索引。<br><br>r：在库中插入模块(替换)。当插入的模块名已经在库中存在，则替换同名的模块。如果若干模块中有一个模块在库中不存在，ar显示一个错误消息，并不替换其他同名模块。默认的情况下，新的成员增加在库的结尾处，可以使用其他任选项来改变增加的位置。<br><br>t：显示库的模块表清单。一般只显示模块名。<br><br>x：从库中提取一个成员。如果不指定要提取的模块，则提取库中所有的模块。<br><br>下面在看看可与操作选项结合使用的任选项：<br><br>a：在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a，则应该为命令行中membername参数指定一个已经存在的成员名。<br><br>b：在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b，则应该为命令行中membername参数指定一个已经存在的成员名。<br><br>c：创建一个库。不管库是否存在，都将创建。<br><br>f：在库中截短指定的名字。缺省情况下，文件名的长度是不受限制的，可以使用此参数将文件名截短，以保证与其它系统的兼容。<br><br>i：在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项i，则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。<br><br>l：暂未使用<br><br>N：与count参数一起使用，在库中有多个相同的文件名时指定提取或输出的个数。<br><br>o：当提取成员时，保留成员的原始数据。如果不指定该任选项，则提取出的模块的时间将标为提取出的时间。<br><br>P：进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名（这样的库文件不符合POSIX标准），但是有些工具可以。<br><br>s：写入一个目标文件索引到库中，或者更新一个存在的目标文件索引。甚至对于没有任何变化的库也作该动作。对一个库做ars等同于对该库做ranlib。<br><br>S：不创建目标文件索引，这在创建较大的库时能加快时间。<br><br>u：一般说来，命令arr&#8230;插入所有列出的文件到库中，如果你只想插入列出文件中那些比库中同名文件新的文件，就可以使用该任选项。该任选项只用于r操作选项。<br><br>v：该选项用来显示执行操作选项的附加信息。<br><br>V：显示ar的版本。<br><br>2、nm基本用法命令<br><br>nm用来列出目标文件的符号清单。下面是nm命令的格式：<br><br>nm[-a|--debug-syms][-g|--extern-only][-B]<br><br>[-C|--demangle][-D|--dynamic][-s|--print-armap]<br><br><font color=#993300>[-o|--print-file-name][-n|--numeric-sort]</font>&nbsp;&nbsp; 输出符号所对应的库的名字，在查找符号在那个库中被定义时比较有用<br><br>[-p|--no-sort][-r|--reverse-sort][--size-sort]<br><br>[-u|--undefined-only][-l|--line-numbers][--help]<br><br>[--version][-tradix|--radix=radix]<br><br>[-P|--portability][-fformat|--format=format]<br><br>[--target=bfdname][objfile...]<br><br>如果没有为nm命令指出目标文件，则nm假定目标文件是a.out。下面列出该命令的任选项，大部分支持&#8220;-&#8221;开头的短格式和&#8220;-&#8220;开头的长格式。<br><br>-A、-o或--print-file-name：在找到的各个符号的名字前加上文件名，而不是在此文件的所有符号前只出现文件名一次。<br><br>例如nmlibtest.a的输出如下：<br><br>CPThread.o:<br><br>00000068TMain__8CPThreadPv<br><br>00000038TStart__8CPThread<br><br>00000014T_._8CPThread<br><br>00000000T__8CPThread<br><br>00000000?__FRAME_BEGIN__<br><br>&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br><br>则nm-A的输出如下：<br><br>libtest.a:CPThread.o:00000068TMain__8CPThreadPv<br><br>libtest.a:CPThread.o:00000038TStart__8CPThread<br><br>libtest.a:CPThread.o:00000014T_._8CPThread<br><br>libtest.a:CPThread.o:00000000T__8CPThread<br><br>libtest.a:CPThread.o:00000000?__FRAME_BEGIN__<br><br>&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;..<br><br>-a或--debug-syms：显示调试符号。<br><br>-B：等同于--format=bsd，用来兼容MIPS的nm。<br><br>-C或--demangle：将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。<br><br>-D或--dynamic：显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。<br><br>-fformat：使用format格式输出。format可以选取bsd、sysv或posix，该选项在GNU的nm中有用。默认为bsd。<br><br>-g或--extern-only：仅显示外部符号。<br><br>-n、-v或--numeric-sort：按符号对应地址的顺序排序，而非按符号名的字符顺序。<br><br>-p或--no-sort：按目标文件中遇到的符号顺序显示，不排序。<br><br>-P或--portability：使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项-fposix。<br><br>-s或--print-armap：当列出库中成员的符号时，包含索引。索引的内容包含：哪些模块包含哪些名字的映射。<br><br>-r或--reverse-sort：反转排序的顺序(例如，升序变为降序)。<br><br>--size-sort：按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。<br><br>-tradix或--radix=radix：使用radix进制显示符号值。radix只能为&#8220;d&#8221;表示十进制、&#8220;o&#8221;表示八进制或&#8220;x&#8221;表示十六进制。<br><br>--target=bfdname：指定一个目标代码的格式，而非使用系统的默认格式。<br><br>-u或--undefined-only：仅显示没有定义的符号(那些外部符号)。<br><br>-l或--line-numbers：对每个符号，使用调试信息来试图找到文件名和行号。对于已定义的符号，查找符号地址的行号。对于未定义符号，查找指向符号重定位入口的行号。如果可以找到行号信息，显示在符号信息之后。<br><br>-V或--version：显示nm的版本号。<br><br>--help：显示nm的任选项。<br><br>ar cs libmy.a//创建一个库<br><br>ar rs libmy.a 1.o//增加一个模块<br><br>ar t libmy.a//显示库里的模块<br><br>ar d libmy.a 1.o//删除一个模块<br><br>nm命令的输出：<br>关于符号的类型，这里我们再多讨论一下。符号的类型是以一个字母的形式显示的，小写字母表示这个符号是本地（local）的，而大写字母则表示这个符号是 全局的（global,externel）。一般来说，类型有一下几种：T、D、B、U、W。各自的含义如下：T表示在代码段中定义的一般变量符号；D表 示时初始化过的数据段；B表示初始化的数据段；U表示没有定义的，在这个库里面使用了，但是在其他库中定义的符号；W，weak的缩写，表示如果其他函数 库中也有对这个符号的定义，则其他符号的定义可以覆盖这个定义。</div>
<br>
<img src ="http://www.cppblog.com/prayer/aggbug/96090.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2009-09-14 10:03 <a href="http://www.cppblog.com/prayer/archive/2009/09/14/96090.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>makefile里的$&lt;的符号的问题</title><link>http://www.cppblog.com/prayer/archive/2009/08/24/94333.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 24 Aug 2009 15:58:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2009/08/24/94333.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/94333.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2009/08/24/94333.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/94333.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/94333.html</trackback:ping><description><![CDATA[$&lt;,$@是自动化变量，$&lt;表示所有的依赖目标集，$@表示目标集。<br>&nbsp;&nbsp;比如：<br><!--<!--[quote]<br />
%o : %c<br />
$(CC) -c $(CFLAGS) $&lt; -o $@ <br />
行如：<br />
foo.o : foo.c<br />
$(CC) -c $(CFLAGS) foo.c -o foo.o<br />
[/quote]-->--&gt;<br>&nbsp;&nbsp;你那个编译不通过，估计是上面没有对依赖目标进行定义
<img src ="http://www.cppblog.com/prayer/aggbug/94333.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2009-08-24 23:58 <a href="http://www.cppblog.com/prayer/archive/2009/08/24/94333.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>makefile 中的符号 </title><link>http://www.cppblog.com/prayer/archive/2009/08/24/94332.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 24 Aug 2009 15:57:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2009/08/24/94332.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/94332.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2009/08/24/94332.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/94332.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/94332.html</trackback:ping><description><![CDATA[Makefile使用的符号<br>make 支持3各通配符："*","?","..."<br>支持特别符号："%"：匹配零或多个字符，如&nbsp;&nbsp;％.c 表示所有以 .c 结尾的文件<br>$ 表示执行一个Makefile函数<br>$@ 表示目标集合，相当于从一个数组中依次取出目标<br><br>
<img src ="http://www.cppblog.com/prayer/aggbug/94332.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2009-08-24 23:57 <a href="http://www.cppblog.com/prayer/archive/2009/08/24/94332.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自动生成依赖性</title><link>http://www.cppblog.com/prayer/archive/2009/08/24/94331.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 24 Aug 2009 15:52:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2009/08/24/94331.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/94331.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2009/08/24/94331.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/94331.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/94331.html</trackback:ping><description><![CDATA[在Makefile中，我们的依赖关系可能会需要包含一系列的头文件，比如，如果我们的main.c中有一句&#8220;#include&nbsp;"defs.h"&#8221;，那么我们的依赖关系应该是： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;main.o&nbsp;:&nbsp;main.c&nbsp;defs.h <br><br>但是，如果是一个比较大型的工程，你必需清楚哪些C文件包含了哪些头文件，并且，你在加入或删除头文件时，也需要小心地修改Makefile，这是一个很没有维护性的工作。为了避免这种繁重而又容易出错的事情，我们可以使用C/C++编译的一个功能。<strong>大多数的C/C++编译器都支持一个&#8220;-M&#8221;的选项，即自动找寻源文件中包含的头文件，并生成一个依赖关系。例如，如果我们执行下面的命令： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;cc&nbsp;-M&nbsp;main.c <br></strong><br>其输出是： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;main.o&nbsp;:&nbsp;main.c&nbsp;defs.h <br><br>于是由编译器自动生成的依赖关系，这样一来，你就不必再手动书写若干文件的依赖关系，而由编译器自动生成了。需要提醒一句的是，如果你使用GNU的C/C++编译器，你得用&#8220;-MM&#8221;参数，不然，&#8220;-M&#8221;参数会把一些标准库的头文件也包含进来。 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;gcc&nbsp;-M&nbsp;main.c的输出是： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;main.o:&nbsp;main.c&nbsp;defs.h&nbsp;/usr/include/stdio.h&nbsp;/usr/include/features.h&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/usr/include/sys/cdefs.h&nbsp;/usr/include/gnu/stubs.h&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stddef.h&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/usr/include/bits/types.h&nbsp;/usr/include/bits/pthreadtypes.h&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/usr/include/bits/sched.h&nbsp;/usr/include/libio.h&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/usr/include/_G_config.h&nbsp;/usr/include/wchar.h&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/usr/include/bits/wchar.h&nbsp;/usr/include/gconv.h&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stdarg.h&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/usr/include/bits/stdio_lim.h <br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;gcc&nbsp;-MM&nbsp;main.c的输出则是： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;main.o:&nbsp;main.c&nbsp;defs.h <br><br>那么，编译器的这个功能如何与我们的Makefile联系在一起呢。因为这样一来，我们的Makefile也要根据这些源文件重新生成，让Makefile自已依赖于源文件？这个功能并不现实，不过我们可以有其它手段来迂回地实现这一功能。GNU组织建议把编译器为每一个源文件的自动生成的依赖关系放到一个文件中，为每一个&#8220;name.c&#8221;的文件都生成一个&#8220;name.d&#8221;的Makefile文件，[.d]文件中就存放对应[.c]文件的依赖关系。 <br><br>于是，我们可以写出[.c]文件和[.d]文件的依赖关系，并让make自动更新或自成[.d]文件，并把其包含在我们的主Makefile中，这样，我们就可以自动化地生成每个文件的依赖关系了。 <br><br>这里，我们给出了一个模式规则来产生[.d]文件： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;%.d:&nbsp;%.c <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@set&nbsp;-e;&nbsp;rm&nbsp;-f&nbsp;$@;&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-M&nbsp;$(CPPFLAGS)&nbsp;$&lt;&nbsp;&gt;;&nbsp;$@.$$$$;&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sed&nbsp;'s,\($*\)\.o[&nbsp;:]*,\1.o&nbsp;$@&nbsp;:&nbsp;,g'&nbsp;&lt;&nbsp;$@.$$$$&nbsp;&gt;;&nbsp;$@;&nbsp;\ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;-f&nbsp;$@.$$$$ <br><br><br>这个规则的意思是，所有的[.d]文件依赖于[.c]文件，&#8220;rm&nbsp;-f&nbsp;$@&#8221;的意思是删除所有的目标，也就是[.d]文件，第二行的意思是，为每个依赖文件&#8220;$&lt;&#8221;，也就是[.c]文件生成依赖文件，&#8220;$@&#8221;表示模式&#8220;%.d&#8221;文件，如果有一个C文件是name.c，那么&#8220;%&#8221;就是&#8220;name&#8221;，&#8220;$$$$&#8221;意为一个随机编号，第二行生成的文件有可能是&#8220;name.d.12345&#8221;，第三行使用sed命令做了一个替换，关于sed命令的用法请参看相关的使用文档。第四行就是删除临时文件。 <br><br>总而言之，这个模式要做的事就是在编译器生成的依赖关系中加入[.d]文件的依赖，即把依赖关系： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;main.o&nbsp;:&nbsp;main.c&nbsp;defs.h <br><br>转成： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;main.o&nbsp;main.d&nbsp;:&nbsp;main.c&nbsp;defs.h <br><br>于是，我们的[.d]文件也会自动更新了，并会自动生成了，当然，你还可以在这个[.d]文件中加入的不只是依赖关系，包括生成的命令也可一并加入，让每个[.d]文件都包含一个完赖的规则。一旦我们完成这个工作，接下来，我们就要把这些自动生成的规则放进我们的主Makefile中。我们可以使用Makefile的&#8220;include&#8221;命令，来引入别的Makefile文件（前面讲过），例如： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;sources&nbsp;=&nbsp;foo.c&nbsp;bar.c <br><br>&nbsp;&nbsp;&nbsp;&nbsp;include&nbsp;$(sources:.c=.d) <br><br>上述语句中的&#8220;$(sources:.c=.d)&#8221;中的&#8220;.c=.d&#8221;的意思是做一个替换，把变量$(sources)所有[.c]的字串都替换成[.d]，关于这个&#8220;替换&#8221;的内容，在后面我会有更为详细的讲述。当然，你得注意次序，因为include是按次来载入文件，最先载入的[.d]文件中的目标会成为默认目标。<br>
<img src ="http://www.cppblog.com/prayer/aggbug/94331.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2009-08-24 23:52 <a href="http://www.cppblog.com/prayer/archive/2009/08/24/94331.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自动化变量</title><link>http://www.cppblog.com/prayer/archive/2009/08/24/94329.html</link><dc:creator>Prayer</dc:creator><author>Prayer</author><pubDate>Mon, 24 Aug 2009 15:47:00 GMT</pubDate><guid>http://www.cppblog.com/prayer/archive/2009/08/24/94329.html</guid><wfw:comment>http://www.cppblog.com/prayer/comments/94329.html</wfw:comment><comments>http://www.cppblog.com/prayer/archive/2009/08/24/94329.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/prayer/comments/commentRss/94329.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/prayer/services/trackbacks/94329.html</trackback:ping><description><![CDATA[看一个例子： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;objects&nbsp;=&nbsp;foo.o&nbsp;bar.o <br><br>&nbsp;&nbsp;&nbsp;&nbsp;all:&nbsp;$(objects) <br><br>&nbsp;&nbsp;&nbsp;&nbsp;$(objects):&nbsp;%.o:&nbsp;%.c <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-c&nbsp;$(CFLAGS)&nbsp;$&lt;&nbsp;-o&nbsp;$@ <br><br><br>上面的例子中，指明了我们的目标从$object中获取，&#8220;%.o&#8221;表明要所有以&#8220;.o&#8221;结尾的目标，也就是&#8220;foo.o&nbsp;bar.o&#8221;，也就是变量$object集合的模式，而依赖模式&#8220;%.c&#8221;则取模式&#8220;%.o&#8221;的&#8220;%&#8221;，也就是&#8220;foo&nbsp;bar&#8221;，并为其加下&#8220;.c&#8221;的后缀，于是，我们的依赖目标就是&#8220;foo.c&nbsp;bar.c&#8221;。而命令中的&#8220;$&lt;&#8221;和&#8220;$@&#8221;则是自动化变量，&#8220;$&lt;&#8221;表示所有的依赖目标集（也就是&#8220;foo.c&nbsp;bar.c&#8221;），&#8220;$@&#8221;表示目标集（也就是&#8220;foo.o&nbsp;bar.o&#8221;）。于是，上面的规则展开后等价于下面的规则： <br><br>&nbsp;&nbsp;&nbsp;&nbsp;foo.o&nbsp;:&nbsp;foo.c <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-c&nbsp;$(CFLAGS)&nbsp;foo.c&nbsp;-o&nbsp;foo.o <br>&nbsp;&nbsp;&nbsp;&nbsp;bar.o&nbsp;:&nbsp;bar.c <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-c&nbsp;$(CFLAGS)&nbsp;bar.c&nbsp;-o&nbsp;bar.o <br><br>试想，如果我们的&#8220;%.o&#8221;有几百个，那种我们只要用这种很简单的&#8220;静态模式规则&#8221;就可以写完一堆规则，实在是太有效率了。&#8220;静态模式规则&#8221;的用法很灵活，如果用得好，那会一个很强大的功能。再看一个例子： <br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;files&nbsp;=&nbsp;foo.elc&nbsp;bar.o&nbsp;lose.o <br><br>&nbsp;&nbsp;&nbsp;&nbsp;$(filter&nbsp;%.o,$(files)):&nbsp;%.o:&nbsp;%.c <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(CC)&nbsp;-c&nbsp;$(CFLAGS)&nbsp;$&lt;&nbsp;-o&nbsp;$@ <br>&nbsp;&nbsp;&nbsp;&nbsp;$(filter&nbsp;%.elc,$(files)):&nbsp;%.elc:&nbsp;%.el <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;emacs&nbsp;-f&nbsp;batch-byte-compile&nbsp;$&lt; <br><br><br>$(filter&nbsp;%.o,$(files))表示调用Makefile的filter函数，过滤&#8220;$filter&#8221;集，只要其中模式为&#8220;%.o&#8221;的内容。其的它内容，我就不用多说了吧。这个例字展示了Makefile中更大的弹性。 <br><br>
<img src ="http://www.cppblog.com/prayer/aggbug/94329.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/prayer/" target="_blank">Prayer</a> 2009-08-24 23:47 <a href="http://www.cppblog.com/prayer/archive/2009/08/24/94329.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>