您的位置:首页 > 编程语言 > C语言/C++

如何编写跨平台的C/C++代码

2015-03-01 20:17 204 查看
怎样才能实现一套C/C++代码跨平台编译呢?应该注意哪些问题,下面对其进行总结。
平台包括: windows7(32bit and 64bit), windows 8.1(32bit and 64bit, desktop, app store, metro ),windows phone, Mac(32bit and 64bit), iOS(32bit and 64bit, x86, x64, armv6,armv7-a, arm64), Linux(32bit and 64bit, x86, x64, mips, armv8-a), Android(32bitand 64bit, x86, x64, armv6, armv7-a, armv8-a).
遇到的问题包括:
(1).数据类型在不同平台有可能长度不一致;
(2).重定义问题,在有些平台某个功能有多种语言实现,如C++,SIMD,汇编等;
(3).在有些平台,库的前后位置放置不正确,如Linux, Mac链接时与库位置有关;
(4).对于intel SIMD指令,在Linux/Mac和windows下,有些包含的头文件名字不一致,如在windows下用"intrin.h",在linux下用"x86intrin.h",而在mac下用"nmmintrin.h";
(5). 在特定系统中有些与性能相关的实现需要关闭,如SIMD在中标麒麟或湖南麒麟Linux下是不支持的;
(6). SIMD个别用法不一致不能使用统一方法导致编译出错,如__m128i在linux下不能直接提取子元素,而在windows下是可以的;
(7). 在有些平台只有函数声明没有实现,有时会报编译错误;
(8). 在用命令行编译和链接时,要保证编译和链接的配置参数保持完全一致;
(9). 有些平台缺少必要的软件或插件导致编译错误;
(10). 对于SIMD,有些机子配置偏低,支持SIMD指令有限;
(11). 在移动平台,对armv6, armv7-a, armv8-a,它们支持的参数是不一致的,要区别对待,如-msoft-float参数,在armv6和armv7-a下是支持的,在armv8-a下是不支持的;
(12).在有些平台,自动获取CPU架构及位数有误。
下面是从网上汇总的一些关于跨平台开发时的一些注意事项:
以下内容参考(http://loopjump.com/ten_rules_for_cross_platform_cpp/http://www.cppblog.com/johndragon/archive/2007/04/18/22204.html?opt=admin):
(1).不要先开发后移植:当增加了一个功能或者修复了某个bug,开始就需要考虑所有的目标平台,并使得代码能够在所有的平台上正常工作。
(2).将GUI代码作为不可复用代码
(3).使用标准C/C++类型,不要使用特定于平台的类型。
(4).只使用内置的 #ifdef 编译标志,不要自己发明轮子。
(5).开发一个简单的可重用的跨平台的基础库,来隐藏每个平台的代码。
(6).在所有的API中都使用Unicode(特别是UTF-8)。现在,Unicode在各个平台所有应用上都是100%支持的,UTF-8的一个好的性质是它向后兼容ASCII码。
(7).不要使用第三方应用程序框架或者运行时环境来使你的代码跨平台。
(8).程序中不要硬性编码与平台相关的任何常量,比如行分隔符、文件分隔符、路径分隔符等。
(9).不同的操作系统,不同的机器,系统支持的颜色和屏幕的大小和分辨率都不同,要注意。
(10).注意内存对齐。
(11).注意文件名的大小写。
(12).保证每个代码文件(.cpp, .h)的结尾都有单独的没有任何内容的一行,这在CC/GCC/G++编译器下能减少很多警告。
(13).#include 包含头文件的时候一定要注意文件名的大小写。
(14).头文件的路径分隔推荐使用”/”,而不是windows下常用的”\”,前者基本可以在所有系统上使用,后者似乎是windows独家支持的。
(15).尽量使用标准C++的原子数据类型,避免使用被重新定义过的类型。或者自己重新重定义一套。
(16).避免使用与编译器相关的一些特性。尽量所有代码都按照c++标准来编写。
(17).尽量把操作系统相关的东西都封装成统一的调用接口,这样在移植代码的时候,可以做到重新编译即可运行。
(18).尽量不要使用内嵌汇编。
(19).在编译时尽量打开所有的警告选项,这样编译器可以尽可能多的发现平台相关的语句,并给出警告
以下内容摘自《C++跨平台开发技术指南》 :
(1).把所有的平台都放在同样重要的位置:必须在产品开发和发布的每一个阶段,都要在所有支持的平台上完全达到功能和质量的要求。
(2).使用公共的代码:能被不同平台共享的代码越多,跨平台的项目就越容易成功。所有平台上公用的功能应该被标识出来避免它们在平台相关的代码里重复出现。并且它们的编译、测试和部署应该贯穿在整个产品生命期中。如果代码不能公用的话,应该把它隐藏到一个统一的API抽象之中去。这些封装平台相关功能的API对使用它的应用程序来说应该是透明的。
(3).要求开发人员用不同的编译器编译代码:它可以帮助你避免编译器相关的特性、标志和宏。它把对C/C++标准不同解读的影响减到最小,并帮助你避免使用未经证明的语言特性。每种编译器都会产生不同的错误和警告,这会帮助你编写更强壮的代码,让开发过程变得简单。不同的编译器会生成不同的代码,这可以帮助你发现一些很难发现的问题。
(4).要求开发人员在不同的平台上编译代码
(5).测试所有的平台
(6).关注编译警告
(7).使用最适合平台的编译器
(8).尽量使用本地IDE。
(9).在Windows上安装和使用Cygwin:Cygwin是一个”windows 上的Linux环境”。
(10).使用跨平台的Make系统。
(11).使用跨平台的bug报告和跟踪系统:跨平台工具包里非常重要的一个组件就是bug报告和跟踪系统(bug系统)。工程师和测试人员利用bug系统来报告软件开发测试中遇到的缺陷和问题。通常一个bug系统应该允许报告的人描述遇到的问题,界定发现bug时系统的环境和状态,以及重现bug的步骤。它还必须允许跟踪所有包含的问题。
(12).设置Tinderbox:Tinderbox最初由Netscape开发,现在则作为一个开源软件由Mozilla项目负责维护。Tinderbox是设计用来管理在开发过程中,特别是涉及大量身处不同地方的开发人员的大型跨平台软件开发中的复杂性。Tinderbox的目标非常明确:在源码仓库发生任何修改时,以集中的方式立刻通知整个团队。通过持续地在每个所支持的平台上编译代码来告知目前源码仓库的“健康状况”。对于每个编译循环,每一次通过或失败都会报告到一个集中的地方。这让开发人员能够决定什么时候应该更新他们的本地代码树,从而避免获取到不能正确编译(或运行)的代码。结合以上两点,Tinderbox可以知晓是谁或者什么修改影响了代码树的“健康”,这些信息可以帮助我们尽可能迅速准确地解决问题。
(13).用CVS或Subversion来管理源代码。
(14).使用patch
(15).为本地安装程序提供支持。
(16).使用标准API。
(17).考虑使用NSPR这样的平台抽象库:NSPR为一些常见的移植性问题提供了解决方案。
(18).慎用浮点数:对于浮点数来说,硬件、编译器和编写代码的方式都可以影响结果的精确性。
(19).显示地注明char类型的符号:不用char类型变量而用int类型变量来存放整型值。如果开始时值是以char保存的话,根据需要将它赋值给一个有符号或者无符号的整型变量。即使如果一定要用char类型变量来存放整数,也不要放任不管。
(20).避免序列化二进制数据:在跨平台的应用程序里,数据序列化(就是把应用程序数据写到可持久保存的地方)需要额外的考量,主要是因为在一个平台上的程序所写下的数据要能在其他平台的程序的实例上被识别读取。
(21).避免类型长度和组织带来的问题:整型是非常依赖于CPU和编译器的。
(22).从Model里把用户界面分离出来:跨平台开发里最困难的地方之一就是应用程序的GUI部分。平台之间的外观、行为和创建UI所用的工具都非常的不同。
(23). 开发一个跨平台用户界面的策略:两个最流行的跨平台桌面GUI工具包:wxWidgets和Qt。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: