注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Nihui's Blog

nihui的私人空间和日志

 
 
 

日志

 
 

Howto: 使用 gcc3 编译需要 gcc4 的代码的建议  

2008-12-06 22:24:00|  分类: 工作側記 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
MagicLinux 2.1 快要 final 的前夕,gcc 3.x 终于即将要被弃用的时候──在 gcc3 编译需要用 gcc4 编译的代码很多次之后,需要总结一下我所遇到的常见的编译问题,并罗列如下。gcc3 终究是应该被淘汰的,新版本的确已经广为接受,许多软件也标上了依赖 gcc4 编译的说明,已经不再需要继续兼容 gcc3。Howto: 使用 gcc3 编译需要 gcc4 的代码的建议 - nihui - Nihuis Blog

一年多的时间,我写了很多 gcc3 的编译补丁,为的仅仅是让 gcc4 的代码在 gcc3 下通过编译……而且无法保证代码质量。Howto: 使用 gcc3 编译需要 gcc4 的代码的建议 - nihui - Nihuis Blog
这些建议可能对 Mingw、MSVC 和 Mac Os X 的编译器同样适用。Howto: 使用 gcc3 编译需要 gcc4 的代码的建议 - nihui - Nihuis Blog



案例问题1:
phonon >= 4.2.71、kdelibs >= 4.1.3
错误消息:

xxxxx.cpp:xx:   instantiated from here
xxxx.h:xx: error: call of overloaded `function xxxxx' is ambiguous
xxxxx.h:xx:
candidates are: function xxxxx
xxxxx.h:xx: note:                 funtion xxxxx
解释:gcc3 对重载函数的 const 限定符 区别对待,而代码中两者参数恰好只相差一个 const。
nihui 的方案:一般而言,两个候选函数的实现部分是相同的,所以只要去掉一个,保留一个就可以通过编译。

示例:
phonon-4.2.80/phonon/experimental/abstractaudiodataoutput.cpp:39:   instantiated from here
/usr/lib/qt4/include/QtCore/qhash.h:854: error: call of overloaded `qHash(const Phonon::Experimental::AudioFormat&)' is ambiguous
phonon-4.2.80/phonon/experimental/audioformat.h:92: note: candidates are: uint qHash(const Phonon::Experimental::AudioFormat&)
phonon-4.2.80/phonon/experimental/audioformat.h:84: note:                 uint Phonon::Experimental::qHash(const Phonon::Experimental::AudioFormat&)

kdelibs-4.1.3/nepomuk/core/resourcefiltermodel.cpp:181:   instantiated from here
/usr/lib/qt4/include/QtCore/qhash.h:854: error: call of overloaded `qHash(const QUrl&)' is ambiguous
kdelibs-4.1.3/nepomuk/core/resourcefiltermodel.cpp:52: note: candidates are: uint qHash(const Soprano::Node&)
kdelibs-4.1.3/nepomuk/core/resourcefiltermodel.cpp:46: note:                 uint Soprano::qHash(const Soprano::Node&)


案例问题2:
phonon >= 4.2.71
错误消息:

In file included from xxxxx.cpp:xx:
xxxxx.h:xx: error: expected unqualified-id before "static_cast"
xxxxx.h:xx: error: expected `)' before "static_cast"

解释:gcc3 在判定 C/C++ 库函数作为函数名称的时候无法分辨是开发者定义的还是库当中的。
nihui 的方案:命名冲突,只需改动函数名称,并搜索源码包中所有调用该函数的地方,全部替换即可通过编译。

示例:
In file included from phonon-4.2.71/xine/sinknode.cpp:21:
phonon-4.2.71/xine/sinknode.h:44: error: expected unqualified-id before "static_cast"
phonon-4.2.71/xine/sinknode.h:44: error: expected `)' before "static_cast"
In file included from phonon-4.2.71/xine/sinknode.cpp:22:
phonon-4.2.71/xine/sourcenode.h:45: error: expected unqualified-id before "static_cast"
phonon-4.2.71/xine/sourcenode.h:45: error: expected `)' before "static_cast"


案例问题3:
kdelibs >= 4.1.3、kdebase-workspace 4.1RC2、kdebase-workspace 4.2beta1
错误消息:

xxxxx.cpp: In member function `function xxx':
xxxxx.h:xx: error: `function called xxx' is private/protected
xxxxx.cpp:xx: error: within this context

解释:此问题在 gcc < 4.1.2 的版本上都会出现,原因是这些版本的 gcc 没有正确遵守 C++ 标准中的 nested class 规范,无法调用
private/protected 的函数。
nihui 的方案:正确的办法是添加 friend class,如果还是不行,则应该将所有的 nested class 的 private 全部改为 ClassPrivate,移出 private/protected 的区域,并搜索源码包中所有调用该函数的地方进行替换
还有一种 dirty 的方式,就是直接把出错的函数移到 public 的地方即可。

示例:
kde bug 162084
kdebase-workspace-4.0.73/libs/plasma/runnermanager.cpp: In member function `void plasma::RunnerManager::Private::loadAll()':
kdebase-workspace-4.0.73/libs/plasma/abstractrunner.h:192: error: 'Plasma::AbstractRunner::AbstractRunner(QObject*, const QString&)' is protected
kdebase-workspace-4.0.73/libs/plasma/runnermanager.cpp:256: error: within this context
kdebase-workspace-4.0.73/libs/plasma/dataengine.cpp: In member function `void Plasma::DataEngine::Private::internalUpdateSource(Plasma::DataContainer*)':
kdebase-workspace-4.0.73/libs/plasma/datacontainer.h:127: error: `uint Plasma::DataContainer::timeSinceLastUpdate() const' is protected
kdebase-workspace-4.0.73/libs/plasma/dataengine.cpp:444: error: within this context
kdebase-workspace-4.0.73/libs/plasma/datacontainer.h:137: error: `void Plasma::DataContainer::setNeedsUpdate(bool)' is protected
kdebase-workspace-4.0.73/libs/plasma/dataengine.cpp:450: error: within this context

kdelibs-4.1.3/kio/kio/kdirlister.cpp: In member function `void KDirListerCache::DirectoryData::moveListersWithoutCachedItemsJob()':
kdelibs-4.1.3/kio/kio/kdirlister.h:636: error: `KDirLister:rivate* const KDirLister::d' is private
kdelibs-4.1.3/kio/kio/kdirlister.cpp:2527: error: within this context


案例问题4:
google-gadgets-for-linux-0.10.2
错误消息:

xxxxx.h: In member function `function with template':
xxxx.cpp:xx:   instantiated from here
xxx.h:xx: error: `function called' is private/protected
xxxxx.h:xx: error: within this context
解释:
使用 C++ 函数模板,注意第二条消息的 cpp 文件,它说明调用函数的地方出错,而第三行就是错误来源。
原因是利用了两种不同的参数传递属性,比如 gcc3 区别对待的 const。

nihui 的方案:修改调用参数的属性以符合函数模板要求。另一种 dirty 的方法是直接删除相关的函数。

示例:
../ggadget/slot.h: In member function `ggadget::ResultVariant ggadget::DelegatedMethodSlot0<R, T, M, DelegateGetter>::Call(ggadget::ScriptableInterface*, int, const ggadget::Variant*) const [with R = const ggadget::ItemElement*, T = ggadget::ComboBoxElement, M = const ggadget::ItemElement*(ggadget::ListBoxElement::*)() const, DelegateGetter = const ggadget::ListBoxElement*(*)(ggadget::ComboBoxElement*)]':
combobox_element.cc:736:   instantiated from here
../ggadget/variant.h:330: error: `ggadget::Variant::Variant(const ggadget::ScriptableInterface*)' is private
../ggadget/slot.h:320: error: within this context


案例问题5:
google-gadgets-for-linux-0.10.2
错误消息:

xxxxx.cpp: In static member function `function':
xxxxx.cpp:xx: error: ISO C++ forbids casting between pointer-to-function and pointer-to-object

解释:错误消息写得比较明白了。函数指针转换为对象指针是不允许的。这只是 gcc3 的处理方式,而高版本 gcc 的处理方式有所放宽:依据 C++ DR195 标准建议,在不损害精度的情况下可以直接转换,然而高版本 gcc 仅对 reinterpret_cast 做了支持。所以这种编译错误通常都是来自于 reinterpret_cast 这个地方。
参考:http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195

nihui 的方案:导航到 cpp 文件出错的一行,reinterpret_cast<void*> 改成 (void*) 即可通过编译。

示例:
gadget_videosink.cc: In static member function `static void ggadget::gst::GadgetVideoSink::GetProperty(GObject*, guint, GValue*, GParamSpec*)':
gadget_videosink.cc:865: error: ISO C++ forbids casting between pointer-to-function and pointer-to-object


案例问题6:
NetworkManager-0.7-svn
错误消息:

In file included from xxxxx.h:xx,
                 from xxxxx.cpp:xx:
xxx.h:xx: warning: declaration of 'function' shadows a global declaration
/usr/include/xx.h:xx: warning: shadowed declaration is here
In file included from xxxxx.cpp:xx:
xx.h:xx: warning: declaration of 'function' shadows a global declaration
/usr/include/xx.h:xx: warning: shadowed declaration is here

解释:文件包含顺序问题。由于系统库中和源码包中有函数重名现象,gcc3 无法区别是调用哪一个函数,而高版本 gcc 有优先级区别。
nihui 的方案:导航到 cpp 文件头部,将 xxxxx.h 的包含语句移动到所有包含语句的最前,优先使用该头文件定义的函数即可通过编译。

示例:
In file included from /usr/include/nss3/pk11pub.h:44,
                 from crypto_nss.c:29:
/usr/include/nss3/certt.h:787: warning: declaration of 'time' shadows a global declaration
/usr/include/time.h:184: warning: shadowed declaration is here
In file included from crypto_nss.c:31:
/usr/include/nss3/cert.h:308: warning: declaration of 'time' shadows a global declaration
/usr/include/time.h:184: warning: shadowed declaration is here

  评论这张
 
阅读(2483)| 评论(1)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017