关于cmake和开源项目发布的那些事(PF)
本来是打算写一篇年终总结,随便和以往一样提一提自己的开源项目(长不大的plain framework)的一些进度,不过最近这一年对于这个项目实在是维护不多,实在难以用它作为醒目的标题。而最近由于使用了VS2022,微软居然自动识别了项目中的cmake(看来我是很久没有使用这个工具了),于是在想方设法将这个项目做到可以在windows平台上尽快提供编译支持,其中遇到了许多有关的技术问题,我觉得可以在这里为大家提供一定的借鉴,特别是自己想要拥有快速编写项目的技巧。分享虽然微不足道,但是也希望大家在此能够有所收获。
2022的新春就要到了,新的一年(手动狗头,这是指旧历),祝福大家能够平安喜乐!
1、项目地址
https://github.com/viticm/plain
每次将地址放出来,感觉像是为自己的孩子做宣传,真的是可怜天下父母心。虽然这个孩子看起来实在太平庸了,可是我想说的是它还是有一定潜力的,至少在大多数的网络应用中都能够很好地发挥其作用。核心的框架并没有过多依赖,只需要依赖于标准的C/C++库即可,目前支持的语法为C++11。
核心的模块:基础(basic)、网络(net)、文件(file)、系统(system)、数据库(database)、脚本(script)
具体的我不再这里描述了,我之前对这个项目写过一些较为详细的介绍(估计也不够详细大家将就看吧)。
2、windows下的cmake
接下来开始上主菜,一切都源于这张图:
如果没有更改VS中默认的设置,那么它在打开文件夹时会自动识别目录下的CMakelist.txt,然后你就会发现这个页面了。它的目的是为提醒我们进行cmake相关的设置,有点像是游戏里面的引导功能,在IDE里微软的VS还是很注重用户体验的。虽然它出现了这个页面,但在跨平台开发的时候我仍然习惯于直接到相应的系统下直接开发,者或许是因为还没有真正体验到一个IDE跨平台开发的乐趣吧。但为了更好的开发编译,最近半个月时间几乎对于项目的维护都在了CMake这里,可以看到提交最多的注释为Update cmake。
plain下面的CMakelist(根目录cmake/CMakelist.txt)
# Copyright 2017 Viticm. All rights reserved.
#
# Licensed under the MIT License(the "License");
# you may not use this file except in compliance with the License.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 2.8.12) set(PROJECT_NAME PlainFramework)
set(PF_VERSION 1.1.0)
set(PROJECT_DESC "Plain framework, based on c++ for net applictions") if (CMAKE_VERSION VERSION_LESS 3.0)
project(PlainFramework CXX C)
else()
cmake_policy(SET CMP0048 NEW)
cmake_policy(SET CMP0037 NEW)
project(PlainFramework VERSION ${PF_VERSION} LANGUAGES CXX C)
endif() # Call fplutil to get locations of dependencies and set common build settings.
include("inc/find_fplutil.cmake")
include("inc/common.cmake")
include("inc/internal_utils.cmake") if (NOT dependencies_gtest_dir)
set(dependencies_gtest_dir ${root_dir}/dependencies/googletest/googletest)
endif() if (NOT has_output_path) # This is the directory into which the executables are built.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${root_dir}/plain/bin) # This is the directory into which the librarys are built.
set(LIBRARY_OUTPUT_PATH ${root_dir}/plain/lib) set(has_output_path 1) endif() #For utf8 no boom.
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4819")
endif() # Options that control the build configuration.
# To configure PlainFramework flags per build target, see the
# plainframework_configure_flags() function.
option(plainframework_build_tests "Build PlainFramework unit tests." ON) # Build plain framework plugins.
option(plainframework_build_plugins "Build PlainFramework plugins" ON) file(GLOB_RECURSE PLAINFRAMEWORK_HEADERS ${CMAKE_CURRENT_LIST_DIR}/framework/core/include *.h) set(VERSION_RC ${root_dir}/cmake/inc/version.rc.in) add_subdir(${plainframework_dir}/cmake plainframework plainframework) # Plugins.
if (plainframework_build_plugins)
add_subdir(${root_dir}/plain/plugins/cmake plugins plainframework)
endif() if(plainframework_build_tests)
add_subdir(${root_dir}/framework/unit_tests/cmake
${root_dir}/framework/unit_tests/cmake/build
plainframework)
if (NOT plainframework_no_app)
add_subdir(${root_dir}/plain/app/cmake
${root_dir}/plain/app/cmake/build
plainframework)
endif()
endif()
root_dir(根目录)
这个变量是当前项目的绝对路径,在PF项目中这个绝对路径是相对于CMakelist而言,也就是在子项目所在的根目录,这样是为了每个项目设置可以独立进行设置。
这个变量在inc/common.cmake中,每个项目都这样设置:
set(root_dir ${CMAKE_CURRENT_LIST_DIR}/../.. CACHE INTERNAL "plainframework root directory")
设置的路径为inc目录的上两级目录,PF项目中的cmake结构如下:
如图inc的上两级目录就是plain,这样就获取到了项目所在的根目录,但这样的设置因人而异,或许大家能够想到更好的方式。
让VS编译的时候不提示编码的警告(由于项目大胆的使用了google,因此整体的警告等级为最高4,而且所有警告都视为错误)
作为纯粹的开发者,no boom的utf8文件才是可选的,由于历史原因微软各种自己使用的utf8文件都是加上了boom标记。
#For utf8 no boom.
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4819")
endif()
has_output_path(是否指定输出目录)
这个变量的目的为控制每个项目的输出路径,在VS中有生成后事件,也可以将生成的文件拷贝到自己想要的目录,但我自认为不太方便,直接就编译到指定目录才是王道。
设置运行文件生成目录
# This is the directory into which the executables are built.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${root_dir}/plain/bin)
在windows下这个目录输出工程的exe和dll等文件,在linux下输出的是可执行文件和so动态库。
设置库文件生成目录
# This is the directory into which the librarys are built.
set(LIBRARY_OUTPUT_PATH ${root_dir}/plain/lib)
在windows下这个目录输出工程的lib和exp等文件,在linux下输出的是.a文件。
add_dir(添加目录)
在PF中为了保证每个子目录或者项目的根目录被正确设置,因此自己封装了这个添加目录的函数用以替换直接使用add_subdirectory。
# Safe add_subdirectory.
function(add_subdir target target_build project)
set_compiler_flags_for_external_libraries()
set(saved_root_dir${project} ${root_dir} CACHE INTERNAL "root dir cache")
add_subdirectory(${target} ${target_build})
set(root_dir ${saved_root_dir${project}} CACHE INTERNAL "root dir recover")
restore_compiler_flags()
endfunction(add_subdir)
其目的保证当前的root_dir在子目录添加后不被更改,保证当前的编译变量在添加之后和之前一样(这里或许有些问题),个人认为这样暂时足够使用而且还挺方便的。
下面的命令即是添加框架的所在目录:
add_subdir(${plainframework_dir}/cmake plainframework plainframework)
在windows上使用cmake进行编译(是一个动图)
运行测试(这个测试是自从编写db模块时才加入的,因此不会太多,在后续大版本中会坚持每一个接口增加):
关于测试遇到的问题
我这里要说的这个问题是windows上的,以前没有写测试用例的时候根本没有关注这个问题,其罪魁元首我先直接贴在最前面(internal_utils.cmake):
if (NOT BUILD_SHARED_LIBS AND NOT pf_force_shared_crt)
# When Plain Framework is built as a shared library, it should also use
# shared runtime libraries. Otherwise, it may end up with multiple
# copies of runtime library data in different modules, resulting in
# hard-to-find crashes. When it is built as a static library, it is
# preferable to use CRT as static libraries, as we don't have to rely
# on CRT DLLs being available. CMake always defaults to using shared
# CRT libraries, so we override that default here.
string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
endif()
这段代码是谷歌的,我之前一直连接的时候都是使用谷歌的静态库,其实都是为了方便。作为第三方的gtest,我直接将它作为自己的子模块,而且不能修改的子模块,用静态库我就不用在生成的时候去特意拷贝到自己的运行目录了(windows)。可是最后发现,运行测试的时候直接产生了一个异常断点,提示的是acrt_first_block==header。说实话对windows开发还缺少经验的我来说,遇到这个问题第一时间只能搜索查找资料,但是你会发现与此相关的都是内存泄漏。但转念我想到过,对于内存问题,PF是经过一段优化的,因此还是心存怀疑,于是使用vs进行调试这次提示的是内存访问冲突。
最后让我怀疑是动态库的原因,是看到了一篇文章,这是无意发现的,这也许是经过了几天摸不着头脑,老天可怜的缘故吧。于是我仔细检查了所有的cmake编译脚本文件,很快就定位到了上述怀疑的地方。想不到当初为了偷懒,到头来却为自己带来了几天的麻烦,关于windows的内存分配可以搜索HeapAlloc关键字,里面有详细关于dll的内存分配。为了节省时间,加上本身不愿意再去做修改,因此加上了下面的编译脚本(当初只是为了不做这一步)。
# Copy gtest libraries.
if (MSVC AND pf_build_shared AND BUILD_SHARED_LIBS)
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
add_custom_command(TARGET core_tests
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/bin/gtestd.dll ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)
else()
add_custom_command(TARGET core_tests
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/bin/gtest.dll ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)
endif()
endif()
上面的目的很简单,在不同的类型下拷贝不同的gtest动态库。
默认示例
如果你使用PF进行开发,那么可以先从这个简单的示例开始(这里有点跑题,不过目前在cmake中遇到的问题已经差不多讲完了,那么就说说相关的题外话)。
配置的细节就不用说了,新建一个cpp文件就可以快速开始使用PF了,如下面动图的开始那样(是不是很简单?)。
3、1.1.0
在我编写这篇有关发布文章的时候,其实自己也在准备PF第一个版本的发布,以前没有正经的做过发布,这次发布出来是为了能够同大家一起研究和学习,不足之处还请指正。开源项目位于github,不过这个网站这两年很不稳定,还希望大家多一点耐心等待,要么就是用一下科学的工具吧。
plain项目(提供了框架库和简单的示例)
plain-simple(框架稍微详细的示例,里面包含了一个目前上线应用的例子)
写在最后
在这里再次祝福大家新年快乐,希望所有困扰我们的通通都消散,希望全世界和平美好!
如果有需要可以加入我们的QQ群(348477824),这是一个潜水专用群,群主基本上已经是潜水几年了,但是如果你需要进行技术交流,那么可以到群里来闲聊。
关于cmake和开源项目发布的那些事(PF)的更多相关文章
- 如何把开源项目发布到Jcenter
转载自:https://www.jianshu.com/p/f66972f0607a 首先我们应该注册一个JFrog Bintray的账号 Jfrog Bintray官网 这里我们可以注意到那个绿色的 ...
- YourSQLDba开源项目发布到codeplex网站了
今天登录YourSQLDba的官方网站http://yoursqldba.grics.ca/index_en.shtml,发现YourSQLDba项目已经发布到开源网站http://www.codep ...
- AndroidStudio怎么将开源项目发布到jcenter
前言 自己在网上搜了一大堆,大体就两种方法,而我选择的是其中代码少的的方法,不过他们或多或少留下了少许的坑,(按他们的方法我是上传成功,但不能发布到jCenter上去,也可能是我自己的问题o(≧v≦) ...
- [转]使用Gradle发布Android开源项目到JCenter
转自:http://blog.csdn.net/maosidiaoxian/article/details/43148643 使用Gradle发布Android开源项目到JCenter 分类: G ...
- 使用Gradle发布Android开源项目到JCenter
喜欢做些开源项目的朋友,相信有不少人都希望能把自己的项目发布到公共的中央仓库,如maven中央仓库,以供别人方便地集成使用.而使用了Android Studio的同学,应该也对gradle和jcent ...
- 百度DMLC分布式深度机器学习开源项目(简称“深盟”)上线了如xgboost(速度快效果好的Boosting模型)、CXXNET(极致的C++深度学习库)、Minerva(高效灵活的并行深度学习引擎)以及Parameter Server(一小时训练600T数据)等产品,在语音识别、OCR识别、人脸识别以及计算效率提升上发布了多个成熟产品。
百度为何开源深度机器学习平台? 有一系列领先优势的百度却选择开源其深度机器学习平台,为何交底自己的核心技术?深思之下,却是在面对业界无奈时的远见之举. 5月20日,百度在github上开源了其 ...
- 发布开源项目到Jcenter
前言 为了将阿里云短信开箱即用发布到Jcenter仓库,前前后后花费了1天半的时间,把端午节都搭进去了.终于今天收到了Jcenter的消息,自己发布的包被添加到了Jcenter仓库,也算给开源社区做了 ...
- 有趣的开源项目集结完毕,HelloGitHub 月刊第 63 期发布啦!
兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这里有实战项目.入门教程.黑科技.开源书籍.大厂开源项目等,涵盖多种编程语言 Pyt ...
- 一大波开发者福利来了,一份微软官方Github上发布的开源项目清单等你签收
目录 微软Github开源项目入口 微软开源项目受欢迎程度排名 Visual Studio Code TypeScript RxJS .NET Core 基础类库 CNTK Microsoft cal ...
随机推荐
- 在执行java代码时,设置了断点,然后莫名的没执行完方法内的代码就结束了,此刻一般在出错处代码用try,catch包括起来
在执行java代码时,设置了断点,然后莫名的没执行完方法内的代码就结束了,此刻一般在出错处代码用try,catch包括起来就能看到是什么异常了,记住try,catch语句的作用
- [react]react创建app,路由,mobx 全教程
1.创建app, npx create-react-app my-app Cmd Copy 2.进入项目目录 cd my-app Cmd Copy 3.启用配置文件(默认是不开启配置文件的) ya ...
- python 安装模块报错 response.py", line 302, in _error_catcher
python 安装模块报错 Exception:Traceback (most recent call last): File "/usr/share/python-wheels/urlli ...
- Linux(Centos)部署Jenkins,并配置Git生成Jar包进行发布部署
需要先安装jdk.maven.git环境 jdk安装:https://www.cnblogs.com/pxblog/p/10512886.html maven安装:https://www.cnblog ...
- 【LeetCode】896. Monotonic Array 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- C. Hongcow Builds A Nation
C. Hongcow Builds A Nation time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- A. Points on Line
A. Points on Line time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- 1067 - Combinations
1067 - Combinations PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Giv ...
- 【操作系统】编程模拟FIFO,LRU,NUR,OPT页面置换算法
#include<stdio.h> #include<stdlib.h> #include<time.h> #define random(x) (rand()%x) ...
- Reflection 基础知识(二)
Proxy 定义 Proxy用于修改对象的某些行为,获取值,设置值等 let p = new Proxy(target, handler); target 用Proxy包装的目标对象(可以是任何类型的 ...