CMakeLists.txt学习记录三
背景
以一个实例,来整体使用一下之前学习的技巧
以做过的一个项目为例
编写magazine/test/CMakeLists.txt
test目录下,是对代码增加的单元测试模块
目的:magazine/test/CMakeLists.txt将所有的测试代码整合编译,生成一个执行文件。(现在是每个test下的子目录各自生成一个可执行文件)
因此,magazine/test/CMakeLists.txt内容如下:
1 | # 旧的写法 |
以一个实例,来整体使用一下之前学习的技巧
编写magazine/test/CMakeLists.txt
test目录下,是对代码增加的单元测试模块
目的:magazine/test/CMakeLists.txt将所有的测试代码整合编译,生成一个执行文件。(现在是每个test下的子目录各自生成一个可执行文件)
因此,magazine/test/CMakeLists.txt内容如下:
1 | # 旧的写法 |
单实例设计模式,是指让一个类只创建一个对象,为了保证这一点,将不会对外暴露new出来的接口对象,只提供一个实例供外部访问。
1 | class SignalModel |
将SignalModel()构造函数设为私有,可以阻止外部new出来实例;
为了让外部可以访问类的public接口,所以类暴露出来一个访问自身的接口GetInstance(),并将其声明为静态成员函数;
完整代码已放在github上,地址:https://github.com/TreeAndFlower/singleModel.git
单实例模式声明了一个静态成员变量,那么,什么时候需要释放这个变量申请的空间呢?经过我自己目前经历的项目分析来看,是不需要释放,因为是静态对象,随着进程开始的时候被定义,然后当进程结束后,会自动释放空间;
理论上,项目被设计为单例模式的时候,在进程没有结束以前,是不会希望释放这个实例空间的,所以不用特意纠结在哪里释放实例指针;
打算将自己学习到的设计模式一个个做个系统的总结,也算是自己的学习总结,这将会是一个系列,也是对我的知识体系的一个梳理过程,如有描述不当之处,还请大家指正。
安利《大话设计模式》,讲解的非常有趣而且易懂
对CMake常用命令的一个系统性的学习和记录。
1 | cmake_minimum_required(VERSION 2.8) |
这行命令是可选的,我们可以不写这句话,但在有些情况下,如果 CMakeLists.txt 文件中使用了一些高版本 cmake 特有的一些命令的时候,就需要加上这样一行,提醒用户升级到该版本之后再执行cmake。
1 | project(exampleProject) |
这个命令不是强制性的,但最好都加上。它会引入两个变量 exampleProject_BINARY_DIR 和 exampleProject_SOURCE_DIR,同时,cmake 自动定义了两个等价的变量 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR。还会创建PROJECT_NAME
${PROJECT_SOURCE_DIR}:本CMakeLists.txt所在的文件夹路径
${PROJECT_NAME}:本CMakeLists.txt的project名称
1 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") |
1 | add_definitions(编译选项) |
比如,如果想要生成的可执行文件拥有符号表,可以gdb调试,就直接加上这句
1 | add_definitions("-Wall -g") |
如果需要fpermissive选项
1 | ADD_DEFINITIONS("-fpermissive") |
1 | 给文件名/路径名或其他字符串起别名,用${变量}获取变量内容 |
1 | set(SRC_LIST main.cpp) |
1 | message(消息) |
1 | add_subdirectory(子文件夹名称) |
1 | aux_source_directory(路径 变量) |
1 | include_directories(路径) |
1 | link_directories(路径) |
1 | 生成可执行文件 |
1 | target_link_libraries(库文件名称/可执行文件名称 链接的库文件名称) |
1 | 将生成的执行程序/库文件/头文件等,安装到指定路径下 |
1 | aux_source_directory(dir VAR) |
1 | file(GLOB SRC_LIST "*.cpp" "protocol/*.cpp") |
1 | find_library(VAR name path)查找到指定的预编译库,并将它的路径存储在变量中。 |
1 | 逻辑判断和比较: |
1 | while(condition) |
1 | foreach(loop_var RANGE start stop [step]) |
1 | PROJECT_SOURCE_DIR:工程的根目录 |
1 | 使用环境变量 |
1 | CMAKE_MAJOR_VERSION:cmake 主版本号,比如 3.4.1 中的 3 |
1 | BUILD_SHARED_LIBS:这个开关用来控制默认的库编译方式,如果不进行设置,使用 add_library 又没有指定库类型的情况下,默认编译生成的库都是静态库。如果 set(BUILD_SHARED_LIBS ON) 后,默认生成的为动态库 |
https://blog.csdn.net/AgingMoon/article/details/123307248
//几乎全部摘抄自此链接
有时候可能会需要交叉编译,所以需要知道平台上编译出来的版本到底是64位还是32位
如图:file libcurl.so 查看当前编译的libcurl.so是32位还是64位的
如图:objdump -a libtest.a 查看当前编译的静态库libtest.a是32位还是64位的
如图:readelf -h libssl.so 查看编译的动态库lib
Class字段显示当前库是32位or64位
Machine字段显示当前库运行的目标机器系统
在编译一个程序demo的时候,需要继承一个第三方库libexample.so,第三方库用到了cjson,本身这个程序也用到了cjson,由于两者用的cjson的版本不一致,导致json解析失败……
第三方库libexample.so使用的旧版本的cjson,cjson-types截图如下:
程序demo使用的是新版本的cjson,cjson-types截图如下:
用旧版本的cJSON源码编译到自己的代码里,编译出libexample.so库;
程序demo已经使用过新版本的cJSON源码,但是又连接了上面编译出来的libexample.so的库,再次进行json解析,会发现libexample.so里面解析cJSON_Number类型的节点的值会失败;
然后重新用新版本的cJSON源码编译出libexample.so库,再集成到上面的demo里面,即可解析成功。
可以从上面两个不同版本的cjson源码截图的cjosn-types看出来:
这两个版本的cJSON Types的值不一样,比如cJSON_Number类型节点的值,旧版本的值是3, 新版本的值是8,
所以用旧版本编译的libexample.so库,集成到demo里的时候,解析到cJSON_Number节点的时候,错误的使用值8而不是3,所以导致解析失败
代码里一定要保持一个版本的cjson;
版本混乱很容易造成奇怪的问题,而且这种问题往往还不容易排查!
由于有时候,想把某一类功能的函数,存在一个map里,所以写了一个demo
源码如下(已本地运行通过):
1 | // |
//PS: map的第二个参数为什么用了long型,而不是int型
//由于在XCode编译报错 Cast from pointer to smaller type ‘int’ loses information
//报错原因是:由于使用了强转将void转为int,而在XCode上使用的为x64的编译,X64下的void地址为8字节,而int为4字节,强转时会导致越界,故出现此错误。
源码运行后到结果如下:
注意类型强制转换到时候,可能会有越界报错
源码已同步到github上:https://github.com/TreeAndFlower/map_func_ptr
由于是统一API的前提下,做成了不同实现了这些API功能的动态链接库,然后根据需要,动态的做出选择去加载这些动态库,并且是在windows下,所以最终用Kernel32.lib库
头文件如下:(要注意将接口导出)
1 | #include <string> |
主要代码如下
1 | short loadLibDemo::realLoadLib(const string& libPath) |
完整代码已经放在了https://github.com/TreeAndFlower/loadlibdemo-windows
要记得导出API接口!
1 | 如果没有导出接口,可能会报错,报错信息如下: |
windows下用Kernel32.lib库,头文件是Windows.h;
PS:
另外,linux版本的blog在这里:https://treeandflower.github.io/2019/09/01/linux下使用dl库,统一API/
如有描述不对之处,欢迎大家指正
使用mqtt-c库,创建mqtt连接的时候报错,错误码是-8
根据头文件来看
1 | #define MQTTASYNC_BAD_STRUCTURE -8 |
错误码是-8的时候,表示创建连接的mqtt的结构体是错误的
经过排查之后,发现,是mqtt的库版本不对。
因为系统里同时安装了两个版本的mqtt的库,一个是最新的,一个是原本用的旧版本的,在编译的时候,用了最新的mqtt的版本编译。
但是把程序给别人的时候,别人用的是旧版本的mqtt的动态库,所以当程序执行的时候,当创建连接时,会报错-8
在多个人使用同一个第三方库的时候,一定一定要注意,版本的问题;要保证大家使用的是统一的版本号编译的第三方动态库!
版本差异导致报错,这种问题真的很坑……
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true