这篇文章给大家分享的是有关如何使用Cmake管理项目的跨平台C++应用程序的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
使用Cmake管理项目的跨平台C++应用程序
MSDN参考文档:https://docs.microsoft.com/zh-cn/cpp/build/cmake-projects-in-visual-studio?view=msvc-160
CMake对照VS参数修改总结:https://blog.csdn.net/xum2008/article/details/7268761?source=1
使用CMake管理项目,再使用标准C++作为开发语言,就可以创建完全跨平台的C++应用程序。
1)创建CMake项目
可以从IDE中创建一个新的cmake项目,也可以打开一个已经存在的cmake项目。
要打开存在的cmake项目,从【文件】【打开】【CMake】导入cmake配置:
新建cmake项目,从新建中选择cmake项目即可。从VS2019的项目解释可以看出,CMake是作为一个跨平台的管理工具存在,而不仅仅是Linux项目;
2)切换到CMake视图,这个很重要,因为默认为文件夹视图,不方便对子项目分别进行生成等操作:
切换到解决方案视图,找到这个按钮,单击一次:
出现选择视图,然后双击选中的视图类型,这里选择CMake目标视图,进入CMake开发视图:
这里就是CMake目标视图,右键单击项目,可以添加新的目标(即添加新的子项目),全部生成,清理等,同样单击某个项目也有类似的操作菜单:
这里解释下CMake缓存的意思:如果选择生成缓存,CMake会解析CMakeLists.txt文件,并生成CMake项目视图;必须这里有exe生成项目,也有dll生成项目,如果清除这些缓存,就只剩下CMakeLists.txt文件了。
需要注意的是,在输出栏需要选择不同的输出来源才能看到CMake过程,大多数默认都是生成输出来源,如果需要了解CMake的过程,可以切换到CMake来源。
3)添加一个名为Common的动态库项目:
//common.h #pragma once #ifdef _WIN32 #define COMMON_EXPORT _declspec(dllexport) #else #define COMMON_EXPORT #endif // _WIN32 namespace BGI { namespace Common { COMMON_EXPORT void add(int v1, int v2); } }
//common.cpp #include <iostream> #include <chrono> #include <thread> #include "Common.h" using namespace std; namespace BGI { namespace Common { static void threadproc(int* value) { for (int i = 0; i < 10; i++) { *value += 1; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } void add(int v1, int v2) { thread t1(threadproc, &v1); thread t2(threadproc, &v2); t1.join(); t2.join(); cout << "Value[0] = " << v1 << endl; cout << "Value[1] = " << v2 << endl; } } }
添加完成后选择生成试试。需要注意的是,如果要生成Windows下的动态库,还需要生成Common.lib文件,因此需要导出动态库接口:_declspec(dllexport);由于是跨平台项目,Linux项目无法设置导出接口,需要做宏限制。
注意!有时候当我们添加了宏来限制不同平台的宏输出,会发现在选择了Linux-GCC平台之后WIN32宏却被定义了。比如在common.h头文件中,WIN32显示已被定义,但是当你编译到Linux平台时却没有任何问题,甚至还可以调试,只是在某些地方代码和实际的可能对不上。那是因为IntelliSense(VS智能感知功能)没有被更新导致。简单说就是你的VS所在的Windows平台并没有得到最新的目标平台,也就是Linux平台的相关开发环境。找到【工具】【选项】【跨平台】,更新下设置的Linux远程电脑下的IntelliSense,重启一下VS即可。可打开【浏览】功能,找到VS从远程Linux同步过来的相关依赖文件。
4)在主项目上将Common子项目添加到引用,这一步会重新生成CMake缓存:
因为改变了主项目的CMakeLists.txt文件,增加了target_link_libraries(LinuxCmakeTest "Common")这一栏。这是CMake添加引用项目的方式。
5)完善cmake配置项
# CMakeList.txt: 顶层 CMake 项目文件,在此处执行全局配置 # 并包含子项目。 # #最低cmake版本要求 cmake_minimum_required (VERSION 3.8) #定义项目名称 project ("LinuxCmakeTest") #设置C++编译器选项(Linux系统才需要设置) IF (CMAKE_SYSTEM_NAME MATCHES "Linux") MESSAGE(STATUS "Current platform: Linux ") add_compile_options(-std=c++11) SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 ") ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Windows") MESSAGE(STATUS "Current platform: Windows") ELSE () MESSAGE(STATUS "Other platform: ${CMAKE_SYSTEM_NAME}") ENDIF() #根据编译类型指定不同的库输出路径 IF (CMAKE_BUILD_TYPE MATCHES "Release") add_definitions(-DRELEASE -DCPP) set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/release) ELSE() add_definitions(-DDEBUG -DCPP) set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/debug) ENDIF() #将程序输出指定到库输出路径 set(EXECUTABLE_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH}) #将链接库的搜寻目录设置为库输出目录 link_directories(${LIBRARY_OUTPUT_PATH}) #使用链接库相对路径(链接库寻找当前目录) set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TURE) set(CMAKE_INSTALL_RPATH "$ORIGIN") #添加当前目录为头文件包含目录(这里可以设置多个包含路径) include_directories(.) #添加子目录(自动加载目录下的子项目) add_subdirectory("Common") add_subdirectory ("LinuxCmakeTest") #配置安装选项(设置后才能使用【安装】菜单功能) install(TARGETS Common DESTINATION LinuxCmakeTest) install(TARGETS LinuxCmakeTest DESTINATION LinuxCmakeTest)
# CMakeList.txt: LinuxCmakeTest 的 CMake 项目,在此处包括源代码并定义 # 项目特定的逻辑。 # cmake_minimum_required (VERSION 3.8) # 将源代码添加到此项目的可执行文件。 add_executable (LinuxCmakeTest "LinuxCmakeTest.cpp" "LinuxCmakeTest.h") # 平台差异化设置 IF (CMAKE_SYSTEM_NAME MATCHES "Linux") # C++线程在Linux系统需要链接pthread库,使用动态库需要链接dl库 target_link_libraries(LinuxCmakeTest Common pthread dl) ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Windows") target_link_libraries(LinuxCmakeTest Common) ELSE () MESSAGE(STATUS "Other platform: ${CMAKE_SYSTEM_NAME}") ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
# CMakeList.txt: Common 的 CMake 项目,在此处包括源代码并定义 # 项目特定的逻辑。 # cmake_minimum_required (VERSION 3.8) add_library(Common SHARED "Common.cpp" "Common.h")
给debug和release指定不同的输出目录;
将dll和exe都输出到同一个目录下,以免exe找不到dll的情况;
将当前CMakeLists.txt文件所在目录设置为搜寻目录,就可以直接使用#include "Common/common.h";
使用add_definitions(-DRELEASE -DCPP)预先定义好需要的宏,就可以在IDE中直接得到宏定义(通过IntelliSense智能感知);
如果需要提供安装功能,添加install命令到CMakeLists.txt文件中,install安装后的文件少了.ink,.pdb,.exp等额外文件;
如果要满足多平台一套代码,免不了需要在cmake中对不同平台做不同的设置,跨平台不是简单说说那么容易!
每次修改CMakeLists.txt文件之后VS都会自动解析,如果该文件很大,解析需要花费的时间也会越长(体验不好!!!)
可以通过CMake设置页面重定向安装目录路径:
到此为止,这个程序已经可以在Windows平台编译并输出结果。但配置到Linux仍需要一些额外的配置才能正确运行。
6)新建Linux平台下的CMake配置
这里选择通用的Linux-GCC-Debug,如果是Release则选择Linux-GCC-Release:
设置远程调试Linux平台:
如果远程没有安装高版本cmake文件,VS会自动提示,可以点击【是】让VS自动帮忙安装一个符合要求的cmake版本:
这里需要注意的是,CentOS默认安装cmake2.8,很旧很旧的版本。使用VS开发Linux至少需要cmake3.8版本以上。
如果一切顺利,应该就可以make成功通过并生成到Linux平台,可以调试运行了。
7)调试代码
利用VS2019调试Linux平台下的Release版本代码没有成功,应该是不行。
Debug模式下设置程序启动参数:
点击【添加调试配置】,会打开一个名叫launch.vs.json的配置文件,在args中配置启动参数即可,可以写成一行,也可以写成多行:
如果Linux平台安装了gdbserver的话(参考文档一的相关说明),可以更改gdb调试方式:"debuggerConfiguration": "gdbserver"为gdbserver类型。
8)其他一些注意事项(专门填坑)
Linux平台设置最好使用root账号,否则可能会出现一些和cmake,gcc相关的报错;
Linux平台要安装最新的cmake和gcc,cmake至少要3.8以上,gcc最好是6.0以上,可以通过cmake --version和gcc/g++ --version命令查看;
WIN32宏或者其他宏显示不正确,通常重新刷新下IntelliSense就正常了;
如果使用【ln -f -s gcc新版 /usr/bin】配置重定向软链接的方式安装新版本g++,在编译时可能会出现“ GLIBCXX_3.4.20' not found ”的错误提示,那是因为使用了软链接重定向新版本gcc之后,相对应的lib/lib64库还未覆盖,仍然链接到了旧版本gcc中,参考下面的连接来处理https://my.oschina.net/u/3489228/blog/3082214 或者 https://blog.csdn.net/qingtingmeng/article/details/49863841
VS2019会将用户的平台配置写入到CMakeSettings.json文件中,可以直接修改这里的内容改变输出路径。参考MSDN上的说明:https://docs.microsoft.com/zh-cn/cpp/build/cmakesettings-reference?view=msvc-160
默认编译和安装的时候都会将原来的文件全部删除,如果不想这样做,尤其是安装了很多必要文件的时候,可以修改配置:将--delete --delete-excluded参数删除,只保留-t参数。
感谢各位的阅读!关于“如何使用Cmake管理项目的跨平台C++应用程序”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。