使用cmake把代码移植到MinGW的总结

有一套嵌入式软件是基于gcc编译的,每次调试都要连接真机来运行,因为要升级文件,调试很不方便。既然都是c代码,为什么不能移植到pc上,在pc上进行调试呢,即使底层的寄存器是平台特有的,但完全可以做成一个硬件抽象层,由pc进行模拟,这样上层的逻辑就可以先在pc上实现,底层的部分才需要用真机来调试。
然而想是容易的,真正要实施还是要先评估一下吧。一开始的思路是采用VS2015,因为这边只有windows平台,如果用MacOS,或者Ubuntu理论上也可以行得通。
那么先尝试一下吧,整个项目大概有2000个c文件,这样要建立一个VS2015的项目。遇到的主要问题是gcc项目主要是采用Makefile来管理代码的依赖关系的,而VS则通过项目文件来做。在创建VS项目的过程中,经历了很多痛苦。首先是找不到头文件,原因是没有设置包含路径,600多个头文件,是按照子项目的形式分成了10多个目录来存放头文件的,这样就要分别把这些头文件的路径都一一添加到包含路径里,有一些h文件是没有放进include目录,而是与对应的c文件放在一起,但是别的c文件要引用这个h的话,就要把这个目录也包含进去。
就这样经过一番艰苦奋斗,终于解决包含的问题。
其实一开始也不是把所有文件都加到项目里,如这样做无异于制造一个errors的链式反应,所以一开始只是把一个c文件加进去,编译目标不能设置成EXE,而应该设置成lib,因为如果要产生EXE,则所有引用到的符号都必须具备,这样意味着只有等到所有文件都加进来才会成功生成,但lib则不同,它不需要提供它引用的外边符号就能生成,只有到链接的时候才会去检查是否存在相应的符号,这样可以把部分的文件先做成一个lib,把各个模块都做成lib之后,再把这些lib组合起来,就可以生成EXE了。
但是实际情况还是不妙,MSVC的编译器与GCC的编译器在某些细节上存在差异,某些代码在gcc上编译是没有问题的,但MSVC就会不通过,例如以下几种情况:
1. 不限定个数的宏参数的写法
“`#define printf_test(s…) \
do { psprintf(linebuf, ## s); io_write_wait_r(linebuf); } while (0)

这样的写法是gcc的标准写法,但MSVC就不行,要改成:
```#define printf_w(s,...) \
    do { psprintf(linebuf,s, ##__VA_ARGS__); io_write_wait(linebuf); } while (0)
  1. 不允许结构体里面定义长度为0的数组
  2. 不允许把未初始化的变量对结构体进行初始化
  3. 某些不定长的数组,需要在运行时申请内存,而不是预先分配
  4. 不允许宏的重复定义,包括枚举名的重复
  5. 在switch case语句里,不允许case A…C:这样的方式,必须把各种case单独列出
    以上种种情况,需要耗费的时间精力很大,有些地方都不知道要如何改造。最后只好放弃。
    由于一开始是想用SDL来做图像显示的模拟的,因为SDL在VS上的移植有很多参考资料,也有现成的例子。不过因为主代码很难移植到VS上,于是想到另一个思路,我不一定非要把代码移植到VS上,我只要让代码能在pc上运行,能跟SDL结合起来,起到模拟仿真的作用就可以达到目的了。于是开始了解MinGW,因为SDL也支持MinGW,它是支持gcc,我想同样是gcc编译器,对语法的差异应该会少一些吧。
    然后又发现一个问题,原有的Makefile不能用,总出现一个“此时不应该有dir”的错误,真不明白gcc不能把话说清楚一点吗?这到底算什么什么错误提示?
    好吧,既然Makefile不能用,我就不能自己写一个吗?后来了解到,原来现在大家都不手动写Makefile了,都是通过工具来生成Makefile,CMake就是这样的一个工具。
    CMake可以生成Makefile,但我们应该提供什么input给它呢?主要是一个叫CMakeLists的txt文件。对于一些大的工程,这个txt文件也会令人头晕,不过幸好CMake提供了一个入门的文档,tutorial,这样,从最basic的地方入门,就可以拿来使用了,毕竟我只想把事情做成,我并不是想实现什么花巧的算法。
    采用CMake+MinGW对代码进行移植的过程要比在VS上顺利一些,当然还是有些地方需要去进行改造,但有了之前的经验。把整个项目分解成若干个lib,这样就逐步地把大部分的代码都打包成lib了,毕竟我不可能把所有code都包含进行,底层的driver是与硬件相关的,不需要包含进来,到时候需要做一个假的实现函数去填充,这样就可以让代码在pc上跑起来了。
    当70% 的代码都变成lib之后,我开始尝试去测试一下,简单写了个main文件,在里面引用lib里的一个画图函数。简单,为了避免error的核爆炸,我必须把改动做得最小,但即使是这样,这么一个简单的动作,也引发了上百条错误,这是可以预期的,之前在VS平台上就经历过,大部分的问题是undefined reference错误,也就是缺失了外部的函数实现。于是,接下来的任务就是把必须的函数在pc上补回去,这样需要增加一些文件。
    整个工作目前就进行到这里。因为我又跳转到研究SDL的使用上了,因为要实现这一切,最简单的方式就是使用SDL,当然要实现GUI不一定要用SDL,可以用windows的MFC,GDI,也可以用QT,不过可能是因为先入为主的关系吧,我可不想浪费时间去研究这些东西,SDL之前是用过的,只要能达到目的,就可以了。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值