一、前言

我们在写应用程序的过程中,经常需要面对一个开发场景:编写跨平台的应用程序。

这种要求对于 Linux 系列的平台来说,还是比较好处理的,大部分情况下只需要换一个交叉编译工具链即可,涉及到硬件平台相关部分再嵌入几个内联汇编。

但是,对于 Windows 平台来说,就稍微麻烦一些。你可能会说,在 Windows 平台上用 cygwin, minGW 也可以统一编译啊,但是你能指望客户在安装你的程序时,还需要去部署兼容 Linux 的环境吗?最好的解决方式,还是使用微软自家的开发环境,比如VS等等。

这篇文章,我们以一个最简单的程序,来描述如何使用 cmake 这个构建工具,来组织一个跨平台的应用程序框架。

阅读这篇文章,您可以收获下面几个知识点:

> 1. cmake 在编译库文件、应用程序中的相关指令;

>

> 2. Windows 系统中的动态库导出、导入写法;

>

> 3. 如何利用宏定义来进行跨平台编程;

在公众号后台留言【430】,可以收到示例代码。在 Linux/Windows 系统中可以直接编译、执行,拿来即用。

二、示例代码说明

1. 功能描述

示例代码的主要目的,是用来描述如何组织一个跨平台的应用程序结构。它的功能比较简单,如下图所示:

2. 文件结构

> 1. Common:放置一些开源的第三方库,例如:网络处理,json 格式解析等等;

>

> 2. Application: 应用程序,使用 Utils生成的库;

>

> 3. Uitls:放置一些工具、助手函数,例如:文件处理、字符串处理、平台相关的助手函数等等,最后会编译得到库文件(动态库 libUtils.so、静态库 libUtils.a);

>

> 4. 如果扩展其他模块,可以按照 Utils 的文件结构复制一个即可。

3. cmake 构建步骤

在示例代码根目录下,有一个“总领” CMakeLists.txt 文件,主要用来设置编译器、编译选项,然后去 include 其他文件夹中的 CMakeLists.txt 文件,如下:

4. Utils 目录说明

这个目录的编译输出是库文件:

> Linux 系统:libUtils.so, libUtils.a;

>

> Windows 系统:libUtils.dll, libUtils.lib, libUtils.a;

其中的 CMakeLists.txt 文件内容如下:

目前,代码中只写了一个最简单的函数 getSystemTimestamp(),在可执行应用程序中,将会调用这个函数。

5. Application 目录说明

这个目录的编译输出是:一个可执行程序,其中调用了 libUtils 库中的函数。

CMakeLists.txt 文件内容如下:

三、Linux 系统下操作步骤

1. 创建构建目录 build

$ mkdir build

在一个独立的 build 目录中编译,生成的中间代码不会污染源代码,这样对于使用 git 等版本管控工具来说非常的方便,在提交的时候只需要 ignore build 目录即可,强烈推荐按照这样的方式来处理。

2. 执行 cmake,生成 Makefile

$ cd build
$ cmake ..

3. 编译 Utils 库

$ cd Utils/src
$ make

在 CMakeLists.txt 中的最后部分是安装指令,把产生的库文件和头文件,安装到源码中的 install 目录下。

$ make install

4. 编译可执行程序 Application

Application 使用到了 libUtils.so 库,因此需要手动把 libUtils.so 和头文件,复制到 Application 下面对应的 lib/linux 和 include 目录下。

当然,也可以把这个操作写在 Utils 的安装命令里。

$ cd build/Application/src
$ make

执行生成的可执行程序 main,即可看到输出结果。

四、Widnows 系统下操作步骤

1. 通过 cmake 指令生成 VS 工程

同样的道理,新建一个 build 目录,然后在其中执行 cmake .. 指令,生成 VS 解决方案,我使用的是 VS2019:

2. 编译 Utils 库文件

使用 VS2019 打开工程文件 DemoApp.sln,在右侧的解决方案中,可以看到:

在 libUtils_shared 单击右键,选择【生成】:

此时,在目录 build\Utils\src\Debug 下面,可以看到生成的文件:

3. 编译可执行程序 Application

因为Application需要使用 Utils 生成的库,因此,需要手动把库和头文件复制到 Application 下面的 lib/win32 和 include 目录下。

在 VS 解决方案窗口中,在 main 目标上,单击右键,选择【生成】:

此时,在目录 build\Application\src\Debug 下可以看到生成的可执行程序:

直接单击 main.exe 执行,报错:

需要把 libUtils.dll 动态库文件复制到 main.exe 所在的目录下,然后再执行,即可成功。

五、总结

这篇文章的操作过程主要以动态库为主,如果编译、使用静态库,执行过程是一样一样的。

如果操作过程有什么问题,欢迎留言、讨论,谢谢!

在公众号后台留言【430】,可以收到示例代码。在 Linux/Windows 系统中可以直接编译、执行,拿来即用。

祝您好运!

---------- End ----------


让知识流动起来,越分享,越幸运!


星标公众号,能更快找到我!

Hi~你好,我是道哥,一枚嵌入式开发老兵。

推荐阅读

1. C语言指针-从底层原理到花式技巧,用图文和代码帮你讲解透彻

2. 原来gdb的底层调试原理这么简单

3. 一步步分析-如何用C实现面向对象编程

4. 图文分析:如何利用Google的protobuf,来思考、设计、实现自己的RPC框架

5. 都说软件架构要分层、分模块,具体应该怎么做(一)

6. 都说软件架构要分层、分模块,具体应该怎么做(二)

使用 cmake 来搭建跨平台的应用程序框架:C语言版本的更多相关文章

  1. 应用程序框架实战十七:DDD分层架构之值对象(层超类型篇)

    上一篇介绍了值对象的基本概念,得到了一些朋友的支持,另外也有一些朋友提出了不同意见.这其实是很自然的事情,设计本来就充满了各种可能性,没有绝对正确的做法,只有更好的实践.但是设计与实践的好与坏,对于不 ...

  2. 使用Nginx负载均衡搭建高性能.NETweb应用程序(转)

    一.遇到的问题 当我们用IIS服务器部署了一个web应用以后,当很多用户高并发访问的时候,客户端响应就会很慢,客户的体验就会很差,由于IIS接受到客户端请求的时候,就会创建一个线程,当线程达到几千个时 ...

  3. 一.1搭建跨平台的统一python开发环境

    搭建跨平台的统一python开发环境: 使用开发环境的好处: 可不用在服务器上直接修改源代码---写的代码首先得入版本库(放git或giitlab中),在本地写代码提交到git中.然后在服务器上git ...

  4. 基于ArcGIS Viewer for Flex开发的一款跨平台的应用程序

    特点: 1.基于ArcGIS Viewer for Flex开发的一款跨平台的应用程序: -(IBAction) showTOC:(id)sender { if (_tocViewController ...

  5. 使用Nginx负载均衡搭建高性能.NETweb应用程序二

    在文章<使用Nginx负载均衡搭建高性能.NETweb应用程序一>中,让我们对Nginx有了一个初步认识,下面我们将在windows平台下面使用Nginx演示集群部署我们的web应用. 一 ...

  6. [原创] 分享我们自己搭建的微信小程序开发框架——wframe及设计思想详解

    wframe不是控件库,也不是UI库,她是一个微信小程序面向对象编程框架,代码只有几百行.她的主要功能是规范小程序项目的文件结构.规范应用程序初始化.规范页面加载及授权管理的框架,当然,wframe也 ...

  7. 网络采集软件核心技术剖析系列(7)---如何使用C#语言搭建程序框架(经典Winform界面,顶部菜单栏,工具栏,左边树形列表,右边多Tab界面)

    一 本系列随笔概览及产生的背景 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受广大博客写作和阅读爱好者的喜爱.同时也不乏一些技术爱好者咨询我,这个软件里面各种实用的功能是如何实现的. 该软件 ...

  8. Cesium入门2 - Cesium环境搭建及第一个示例程序

    Cesium入门2 - Cesium环境搭建及第一个示例程序 Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 验 ...

  9. 跨平台的WebRTC客户端框架:OpenWebRTC

    Webrtc的ios框架编译 http://www.th7.cn/Program/IOS/201502/390418.shtml WebRTC in WebKit : http://www.webrt ...

随机推荐

  1. 11、pass,is,位运算的补充

    pass的补充 一般Python的代码是基于:和缩进来实现,Python中规定代码块中必须要有代码才算完整,在没有代码的情况下为了保证语法的完整性可以用pass代替 if 条件: pass else: ...

  2. Just a Joke HDU - 4969(物理+积分)

    题目链接:https://vjudge.net/problem/HDU-4969#author=0 题意:一个人在圆心以V2速度追赶一个以V1的速度进行圆周运动,问在圆心的人能否在不超过D的距离追上他 ...

  3. Co-prime HDU - 4135

    题目链接:https://vjudge.net/problem/HDU-4135#author=0 题意:求在区间[a,b]中有多少个数与n互质. 思路:先看数据范围很大,所以不能枚举.因为互质难求, ...

  4. 3、Spring教程之IOC创建对象方式

    1.通过无参构造方法来创建 1.User.java public class User { private String name; public User() { System.out.printl ...

  5. fork、exec 和 exit 对 IPC 对象的影响

    GitHub: https://github.com/storagezhang Emai: debugzhang@163.com 华为云社区: https://bbs.huaweicloud.com/ ...

  6. cordova app打包apk签名

    首先执行:ionic cordova build android --prod --release,执行完会在以下目录生成apk文件( --prod 用以压缩) 然后使用keytool生成keysto ...

  7. OO第四单元总结暨OO课程总结

    一.第四单元作业总结 本单元的主要任务是对 Uml 图元素进行管理和查询,测试一开始会输入一个静态图,之后会对图中相关内容进行查询. 第13,14次作业 第14次作业新增内容很少,故与第13次作业放在 ...

  8. JDK8中新日期时间API

    它们面临的问题是:可变性:像日期和时间这样的类应该是不可变的.偏移性:Date中的年份是从1900开始的,而月份都从0开始.格式化:格式化只对Date有用,Calendar则不行.此外,它们也不是线程 ...

  9. jQuery入门看这一篇就够了

    一.选择器 1.基本 名称 用法 描述 #id $("#myDiv"); 根据给定的ID匹配一个元素 element $("div"); 根据给定的元素标签名匹 ...

  10. Crackme_003

    功能: 拿到文件,先执行一下.功能如下: 1.nag窗口 会先出现如下nag窗口,持续几秒 2.注册窗口: 出现错误会提示:You Get Wrong  Try Again 破解: 1.查壳: 无壳, ...