惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Register - Security
The Register - Security
云风的 BLOG
云风的 BLOG
U
Unit 42
F
Fortinet All Blogs
The GitHub Blog
The GitHub Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
D
Docker
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
S
Secure Thoughts
Hacker News: Ask HN
Hacker News: Ask HN
Vercel News
Vercel News
S
Security @ Cisco Blogs
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
I
Intezer
MongoDB | Blog
MongoDB | Blog
AI
AI
MyScale Blog
MyScale Blog
Engineering at Meta
Engineering at Meta
Y
Y Combinator Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Proofpoint News Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
W
WeLiveSecurity
博客园 - 叶小钗
S
SegmentFault 最新的问题
N
News | PayPal Newsroom
WordPress大学
WordPress大学
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
D
DataBreaches.Net
小众软件
小众软件
Microsoft Azure Blog
Microsoft Azure Blog
Spread Privacy
Spread Privacy
H
Help Net Security
美团技术团队
博客园 - 司徒正美
T
Threat Research - Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
K
Kaspersky official blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
V
Vulnerabilities – Threatpost
TaoSecurity Blog
TaoSecurity Blog
N
Netflix TechBlog - Medium
L
Lohrmann on Cybersecurity
J
Java Code Geeks
量子位
Martin Fowler
Martin Fowler
博客园_首页

I'm OWenT

国产大模型(GLM 5.1、Kimi K2.6)真实场景效果和 Coding Plan 额度测试 新版本libatapp的连接管理——从etcd服务发现到拓扑驱动的自动重连 新版本libatbus的设计变更——从树形路由到拓扑驱动 Protobuf又一坑 - C++标准和ABI兼容性 AI真好用-给Blog主题统一加mermaid,chart.js,excalidraw,draw.io的多种引入方式支持 给内网部署Squid-通用HTTP下载缓存 UE使用CodeChecker和clang-tidy生成静态分析报告 找出UE的循环依赖 C++小协程栈和临时变量及作用域的栈溢出问题分析 游戏服务的可观测性能力建设(C++生态) 指标上报的多线程优化和多拉取源点优化 协程(libcopp)的Channel功能和CPU命中率优化 通用RPC代码生成器 实现strong_rc_ptr(比shared_ptr更快的引用计数智能指针) 手夯一个STL allocator和对象内存分析组件 std::condition_variable 的信号丢失问题 踩坑一处(GCC)STL std::async 实现BUG导致的crash问题 GCC 14的一个warning to error BUG 给xresloader(Excel导表工具)增强UE读表支持(包含蓝图,Blueprint) Opentelemetry社区在gRPC的几个链接问题(静态库和动态库混用,musl工具链,符号裁剪) Excel转表工具(xresloader)的新验证器(验证外部Excel和文本数据,唯一性和自定义规则) protobuf v22和gRPC v1.55版本升级的依赖变化和upb适配 关于protobuf近期版本(v20/v3.20+)和 gRPC v1.54版本在某些编译环境下的一些链接和编译问题 xresloader-Excel导表工具链的近期变更汇总 打通游戏服务端框架的C++20协程改造的最后一环 Opentelemetry-cpp的Logs模块标准更新(涉及近期版本:1.8-1.9的BREAK CHANGES) 给cmake-toolset和工具链(curl等)加HTTP/2和HTTP/3支持 又开新坑之 coredns 插件: nftables和filter 关于opentelemetry-cpp社区对于C++ Head Only组件单例和符号可见性的讨论小记 填个转表工具 xresloader 去年的坑(数组尾部裁剪) 集成 upb 和 lua binding 的踩坑小记 libcopp对C++20协程的接入和接口设计 再度优化GCC、LLVM、Clang、libc++、libc++abi等套件的构建脚本 游戏服务的分布式事务优化(二)- 事务管理 游戏服务的分布式事务优化(一)- Write Ahead Log(WAL) 模块 记录一些bazel适配用编译选项 测试现代化硬件C++浮点数性能和一致性 适配Boringssl和OpenSSL 3.0 C++20 Text Formatting/fmtlib 适配问题小记 再次重构LLVM+Clang+libcxx+libc++abi+其他相关工具的构建流程 重构基于CMake的构建工具链 新版GCC和LLVM+Clang终于Release啦 折腾一下nftables下的双拨 [C++20] Module partitions和符号交叉引用(声明和实现分离) [Rust] 实现一个线程安全且迭代器可以保存的链表 基于protobuf的代码生成 几个使用protobuf中C++接口的Arena的坑 Amazon Aurora DB存储引擎论文阅读小记 近期对libatapp的一些优化调整(增加服务发现和连接管理,支持yaml等) xresloader转表工具链增加了一些新功能(map,oneof支持,输出矩阵,基于模板引擎的加载代码生成等) 在游戏服务器中使用分布式事务 libcopp接入C++20 Coroutine和一些过渡期的设计 libatbus 的大幅优化 nftables初体验 容器配置开发环境小计 PALM Tree - 适合多核并发架构的B+树 - 论文阅读小记 跨平台协程库 - libcopp 简介 C++20 Coroutine 性能测试 (附带和libcopp/libco/libgo/goroutine/linux ucontext对比) 尝鲜Github Action 一些xresloader(转表工具)的改进 protobuf、flatbuffer、msgpack 针对小数据包的简单对比 协程框架(libcopp) 小幅优化 Excel转表工具(xresloader) 增加protobuf插件功能和集成 UnrealEngine 支持 Anna(支持任意扩展和超高性能的KV数据库系统)阅读笔记 C++20 Coroutine libcopp merge boost.context 1.69.0 Google去中心化分布式系统论文三件套(Percolator、Spanner、F1)读后感 Rust玩具-企业微信机器人通用服务 使用ELK辅助监控开发测试环境服务质量和问题定位 2018年的新通用伪随机数算法(xoshiro / xoroshiro)的C++(head only)实现 Webpack+vue+boostrap+ejs构建Web版GM工具 Rust的第二次接触-写个小服务器程序 理解和适配AEAD加密套件 atsf4g-co的进化:协程框架v2、对象路由系统和一些其他细节优化 协程框架(libcopp)v2优化、自适应栈池和同类库的Benchmark对比 可执行文件压缩 初识Rust 使用restructedtext编写xresloader文档 atframework的etcd模块化重构 C++的backtrace ECDH椭圆双曲线(比DH快10倍的密钥交换)算法简介和封装 protobuf-net的动态Message实现 pbc的proto3接入 atgateway内置协议流程优化-加密、算法协商和ECDH 整理一波软件源镜像同步工具+DevOps工具 Blog切换到Hugo libcopp v2的第一波优化完成 libcopp(v2) vs goroutine性能测试 libcopp的线程安全、栈池和merge boost.context 1.64.0 GCC 7和LLVM+Clang+libc++abi 4.0的构建脚本 libatbus的几个藏得很深的bug 用cmake交叉编译到iOS和Android 开源项目得一些小维护 atapp的c binding和c#适配 对象路由系统设计 2016年总结 近期的一个协程流程BUG 重写了llvm+clang+libc++和libc++abi的构建脚本 atsf4g完整游戏工程示例|I'm OWenT atframework基本框架已经完成|I'm OWenT
近期cmake-toolset的一些适配问题
owent · 2021-12-06 · via I'm OWenT

blog-website

前言

偷懒了好久没有写分享了,最近的时间也是花费了很多时间大量优化了之前游戏服务器框架和组件的很多细节。其中,相对独立且同时也被其他的项目使用的一个工具则是基于 cmakegit 且兼容 vcpkg 的构建系统 cmake-toolset 。之所以要写这么个构建工具主要是要提供比 vcpkg 更宽容的兼容性(没办法我们公司的编译环境比较古老),并且提供更进一步的定制化能力(包含但不限于功能开关和下载源,这些东西 vcpkg 也是很后期才有了个初步的支持)。那么先来记录一下构建系统适配过程中的一些问题吧。

增加 boringssl 支持,升级 openssl 到 3.0.0

之前 gRPC 的依赖使用的是 openssl 。其实官方默认的SSL库用的是 boringsslboringssl 裁剪掉了很多老的算法,阉割掉了很多低级接口。并且跨平台和跨编译器适配其实没有 openssl 做得好。不过所幸它也支持 cmake ,所以打个类似这样的patch就行了。

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 893bca753..56c90c637 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -117,7 +117,7 @@ endif()
 if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
   # Note clang-cl is odd and sets both CLANG and MSVC. We base our configuration
   # primarily on our normal Clang one.
-  set(C_CXX_FLAGS "-Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings -Wvla")
+  set(C_CXX_FLAGS "-Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings -Wvla")
   if(MSVC)
     # clang-cl sets different default warnings than clang. It also treats -Wall
     # as -Weverything, to match MSVC. Instead -W3 is the alias for -Wall.
@@ -238,8 +238,8 @@ elseif(MSVC)
                             ${MSVC_DISABLED_WARNINGS_LIST})
   string(REPLACE "C" " -w4" MSVC_LEVEL4_WARNINGS_STR
                             ${MSVC_LEVEL4_WARNINGS_LIST})
-  set(CMAKE_C_FLAGS   "-utf-8 -Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
-  set(CMAKE_CXX_FLAGS "-utf-8 -Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
+  set(CMAKE_C_FLAGS   "-utf-8 -Wall ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
+  set(CMAKE_CXX_FLAGS "-utf-8 -Wall ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
 endif()
 
 if(WIN32)
@@ -562,7 +562,7 @@ endif()
 
 # Add minimal googletest targets. The provided one has many side-effects, and
 # googletest has a very straightforward build.
-add_library(boringssl_gtest third_party/googletest/src/gtest-all.cc)
+add_library(boringssl_gtest STATIC third_party/googletest/src/gtest-all.cc)
 target_include_directories(boringssl_gtest PRIVATE third_party/googletest)
 
 include_directories(third_party/googletest/include)
@@ -649,3 +649,12 @@ add_custom_target(
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
     DEPENDS all_tests bssl_shim handshaker fips_specific_tests_if_any
     USES_TERMINAL)
+
+include(GNUInstallDirs)
+install(TARGETS bssl crypto ssl
+  RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+  LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+  ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
+
+install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
+
diff --git a/crypto/pkcs8/pkcs12_test.cc b/crypto/pkcs8/pkcs12_test.cc
index e67630d62..1641a6c6d 100644
--- a/crypto/pkcs8/pkcs12_test.cc
+++ b/crypto/pkcs8/pkcs12_test.cc
@@ -34,7 +34,7 @@ std::string GetTestData(const char *path);
 static const char kPassword[] = "foo";
 
 // kUnicodePassword is the password for unicode_password.p12
-static const char kUnicodePassword[] = u8"Hello, 世界";
+static const char* kUnicodePassword = reinterpret_cast<const char*>(u8"Hello, 世界");
 
 static bssl::Span<const uint8_t> StringToBytes(const std::string &str) {
   return bssl::MakeConstSpan(reinterpret_cast<const uint8_t *>(str.data()),
@@ -391,7 +391,7 @@ TEST(PKCS12Test, RoundTrip) {
                 {bssl::Span<const uint8_t>(kTestCert2)}, 0, 0, 0, 0);
 
   // Test some Unicode.
-  TestRoundTrip(kPassword, u8"Hello, 世界!",
+  TestRoundTrip(kPassword, reinterpret_cast<const char*>(u8"Hello, 世界!"),
                 bssl::Span<const uint8_t>(kTestKey),
                 bssl::Span<const uint8_t>(kTestCert),
                 {bssl::Span<const uint8_t>(kTestCert2)}, 0, 0, 0, 0);
diff --git a/crypto/x509v3/internal.h b/crypto/x509v3/internal.h
index e510b4092..bd004847f 100644
--- a/crypto/x509v3/internal.h
+++ b/crypto/x509v3/internal.h
@@ -58,7 +58,7 @@ int x509v3_cache_extensions(X509 *x);
 // it decodes an IPv4 address, it writes the result to the first four bytes of
 // |ipout| and returns four. If it decodes an IPv6 address, it writes the result
 // to all 16 bytes of |ipout| and returns 16. Otherwise, it returns zero.
-int x509v3_a2i_ipadd(unsigned char ipout[16], const char *ipasc);
+int x509v3_a2i_ipadd(unsigned char* ipout, const char *ipasc);
 
 
 #if defined(__cplusplus)
diff --git a/decrepit/ripemd/ripemd_test.cc b/decrepit/ripemd/ripemd_test.cc
index 0700baee0..2eeb38210 100644
--- a/decrepit/ripemd/ripemd_test.cc
+++ b/decrepit/ripemd/ripemd_test.cc
@@ -109,7 +109,7 @@ TEST(RIPEMDTest, RunTest) {
       0x37, 0xf9, 0x7f, 0x68, 0xf0, 0x83, 0x25, 0xdc, 0x15, 0x28};
 
   if (OPENSSL_memcmp(digest, kMillionADigest, sizeof(digest)) != 0) {
-    fprintf(stderr, u8"Digest incorrect for “million a's” test: ");
+    fprintf(stderr, "%s", reinterpret_cast<const char*>(u8"Digest incorrect for “million a's” test: "));
     hexdump(stderr, "", digest, sizeof(digest));
     ok = 0;
   }

当然 boringssl 的支持和升级 openssl 还涉及我们开发框架的基础库 atframe_utils 的适配。后面 专门写一篇总结吧。

protobufstd::to_string 的使用和交叉编译适配

protobuf 从 v3.14.0 版本开始依赖 C++11,直接使用了。其中有个比较特别的地方是使用了 std::to_string 这个API。为什么说这个API特别呢?是因为Clang从3.3版本开始就宣传支持C++11的全部特性了(详见: https://clang.llvm.org/cxx_status.html),但是其实它带的 libc++ 对C++11库的支持还不完整。在我的测试中 Clang 6.0 版本(对应AppleClang 版本10.0)带的 libc++ 才开始能够正常使用这个接口。所以在这些老的编译器下需要降级到 v3.13.0 。

另一个问题是现在的 protobuf 已经支持了 cmake 的config模式的导出库。然后install完以后,会有一个 protobuf-module.cmake 文件用于兼容老的模式提供的函数和变量,可以通过 find_package(Protobuf) 设置 set(protobuf_MODULE_COMPATIBLE TRUE) 选项来开启。在交叉编译时,我们其实是不需要编译 protoc 的,但是这个模块没有考虑到我们可能关闭某些模块的情况。所以需要打一些Patch。

diff --git a/cmake/protobuf-module.cmake.in b/cmake/protobuf-module.cmake.in
index 09b9d29..8787d65 100644
--- a/cmake/protobuf-module.cmake.in
+++ b/cmake/protobuf-module.cmake.in
@@ -134,6 +134,7 @@ get_target_property(Protobuf_INCLUDE_DIRS protobuf::libprotobuf
   INTERFACE_INCLUDE_DIRECTORIES)
 
 # Set the protoc Executable
+if (NOT Protobuf_PROTOC_EXECUTABLE AND TARGET protobuf::protoc)
 get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
   IMPORTED_LOCATION_RELEASE)
 if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
@@ -152,6 +153,7 @@ if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
   get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
     IMPORTED_LOCATION_NOCONFIG)
 endif()
+endif()
 
 # Version info variable
 set(Protobuf_VERSION "@protobuf_VERSION@")

另外,因为我们需要兼容到 GCC 4.8。所使用的 protobuf v3.13.0 里对关闭 protoc 和单元测试以后,开启 libprotoc 也没有支持,所以也需要Patch一下。

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 9ca31ac..a789e29 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -44,6 +44,7 @@ option(protobuf_BUILD_TESTS "Build tests" ON)
 option(protobuf_BUILD_CONFORMANCE "Build conformance tests" OFF)
 option(protobuf_BUILD_EXAMPLES "Build examples" OFF)
 option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" ON)
+option(protobuf_BUILD_LIBPROTOC "Build libprotoc" OFF)
 if (BUILD_SHARED_LIBS)
   set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON)
 else (BUILD_SHARED_LIBS)
@@ -64,8 +65,6 @@ include(protobuf-options.cmake)
 # Overrides for option dependencies
 if (protobuf_BUILD_PROTOC_BINARIES OR protobuf_BUILD_TESTS)
   set(protobuf_BUILD_LIBPROTOC ON)
-else()
-  set(protobuf_BUILD_LIBPROTOC OFF)
 endif ()
 # Path to main configure script
 set(protobuf_CONFIGURE_SCRIPT "../configure.ac")

交叉编译 gRPC 和对 abseil-cpp 的适配

abseil-cpp 是 Google 的STL扩展库,用来提前体验一些新版本的STL的功能。我们的基础框架倒是不依赖它,但是 gRPCopentelemetry-cpp 都依赖它。 abseil-cpp 的问题仍然是在一些编译器适配上,特别是它其实对编译器版本要求比较高。而且比较坑的是 gRPC 申明支持的编译器版本比 abseil-cpp 声明支持的版本要老,然而 abseil-cpp 却是 gRPC 的依赖项之一,所以我们也得按实际的测试来看支持性。

新增对 gRPC 交叉编译的支持并不是说原来的版本不支持。而是原来的版本里 cmake-toolset 在交叉编译的场景下只编译库,不编译宿主平台的 gRPC 代码生成插件。这主要是因为 gRPC 的依赖特别多。所以这次大规模重构了编译依赖库的变量继承部分:把很多原先默认继承的选项分离成了默认继承的 CMAKE_XXX 和默认不继承的 CMAKE_HOST_XXX ;并且交叉编译的可执行程序搜索目录加入了host平台的二进制目录,并且共享交叉编译时host平台和非交叉编译时target平台的默认输出目录。这样可以最大限度地共享已有的编译缓存;另外优化了一些重置cmake会用到的环境变量的脚本。因为有些构建流程会通过设置环境变量来影响构建选项。

gRPC 对新版本的编译器适配也有一些问题。比如 gRPC 里使用了 std::string_view::string_view(nullptr) 。而这个接口在C++23里被移除了(详见: https://en.cppreference.com/w/cpp/string/basic_string_view/basic_string_view )。 那么在一些新式的编译器开启 C++23的时候,比如 (Visual Studio 2022里带的MSVC v14.30)就会编译不过,这里也是打个Patch就好了。

GCC/Clang STL BUG

在适配 gRPC 的过程中,我还碰到了一个GCC和Clang的BUG。我只在GCC上碰到了,但是按 stackoverflow 上的相关问题的说法Clang也是有问题的。我本地的Clang版本都比较高,在高版本的Clang上是没有这个问题的。相关的链接在此: https://stackoverflow.com/questions/53408962/try-to-understand-compiler-error-message-default-member-initializer-required-be 。

触发的代码是 gRPC v1.42.0 版本的 src/core/ext/xds/xds_api.h 文件(老版本没有这个问题,因为实现不一样)。相关代码是:

struct Duration {
  int64_t seconds = 0;
  int32_t nanos = 0;
  bool operator==(const Duration& other) const {
    return seconds == other.seconds && nanos == other.nanos;
  }
  std::string ToString() const {
    return absl::StrFormat("Duration seconds: %ld, nanos %d", seconds, nanos);
  }
};

和下面的 absl::variant<UnknownAction, RouteAction, NonForwardingAction> action;

在这种语法中,默认生成的构造函数应该是能够初始化 secondsnanos 的。后面这一行会报 /usr/include/c++/9/type_traits:883:12: error: default member initializer for ‘grpc_core::XdsApi::Duration::seconds’ required before the end of its enclosing class 这个错误。

abseil-cpp 会在自带的STL支持的时候使用STL版本的标准库,否则才是使用 abseil-cpp 内的版本。

虽然这是编译器的问题,但是我们也不得不打Patch绕开他。

支持 Android NDK r23

Android NDK r23 是当前最新的LTS版本,里面的 android.toolchain.cmake 锁提供的信息和NDK的目录结构和之前的版本有比较大的变化,所以这里适配了一下。详情就不列举了,大致上就是一些平台相关的变量和新的NDK没有platform目录了。这个目录以前是放不同版本的的一些基础库文件的。

macOS宿主机编译的适配

这里碰到的问题是默认情况下,macOS使用的是xcode环境(默认编译器是 /Applications/Xcode_12.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc/Applications/Xcode_12.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ )。其实我们需要命令行工具环境 ( /usr/bin/clang/usr/bin/clang++ )。因为有些包会链接 -framework CoreFoundation 在xcode环境中不设置 SYSROOT 是找不到的。而我们在交叉编译到iOS和iPhoneSimulator的时候其实是会重置掉SYSROOT让编译器从默认默认目录里找,就会编译不过。所以我的解决方案是直接找到并使用命令行工具版本的 clang 。

libuv 和MinGW

最后一个问题是和 libuv 还有MinGW相关。最新版本的MinGW更新了一些头文件,导致即便是当前最新版本的 libuv ( v1.42.0 ) 仍然是编译不过。这个问题在 https://github.com/libuv/libuv/commit/3e90bc76b036124c2a94f9bf006af527755271cf 里修复了,但是还未发布。所以 cmake-toolset 不得不把 libuv 指向打了patch的版本。

另外就是 libuvv1.42.0 版本开始有了cmake config的官方导出支持。但是有点问题,uv_a 未导出。我给提交了一个 PR: https://github.com/libuv/libuv/pull/3373 。不知道是否能够合入,也不知道啥时候能合入。目前在 cmake-toolset 里也有一份这个Patch。

总结

近期对 cmake-toolset 的改造主要就上面这些了。对一些依赖库的升级过程中,碰到的不是特别典型的问题我就不一一列举了。目前CI测试的平台增加了 Android NDK,iOS,iPhoneSimulator。我自己测试过的平台已经扩大到了 Visual Studio 2022 (MSVC v143) ,Android NDK r23,GCC 11,LLVM/Clang 13 这些非常高版本的编译环境,且测试过开启部分 C++23 特性时的兼容性。后面可能陆陆续续也会碰到更多问题,欢迎大家一起交流改进。