Genyleap/Docs
开发技术栈指南 · C++

现代 C++ 开发。

面向 production 的 C++26-first 环境:项目自有 modules、明确错误契约、RAII、target-based CMake、Ninja 与平台原生 toolchain。当所需 compiler 或 standard library 尚未支持所选 C++26 能力时,C++23 作为兼容路径。

Primary C++26 Compatibility C++23 开发 CMake 3.30+ · Ninja 1.11+ Targets Desktop · Mobile · Web

工程基线。

AreaDefaultRule
LanguageC++26优先使用当前语言路径;只有实际 toolchain 支持要求时才使用 C++23。
Project boundariesC++ modulesNew project-owned production boundaries use .cppm modules by default.
Standard libraryMinimal headersUse normal standard headers in the global module fragment; do not depend on experimental import std;.
错误std::expected将可恢复失败作为 API contract 的一部分,而不是隐藏在 sentinel values 后面。
Console outputstd::print / std::println新代码优先使用现代 formatted output,而不是 iostream insertion chain。
Build modelTarget-based CMake将 compile features、sources、definitions 与 dependencies 保持绑定到所属 target。
GeneratorNinja为每个 compiler、configuration 与 target 使用独立 build tree。

从 modules 开始,而不是 headers。

项目自有边界应直接表达职责。declarations 从 module interface 导出,非简单 implementation 放入 implementation unit,platform/third-party code 隔离在明确的 adapter 边界。

C++ module interfacesrc/greeting/greeting.cppm
module;

#include <expected>
#include <string>
#include <string_view>

export module genyleap.greeting;

export namespace genyleap::greeting {

enum class GreetingError {
    EmptyName
};

[[nodiscard]] auto makeGreeting(std::string_view name)
    -> std::expected<std::string, GreetingError>;

}
C++ implementation unitsrc/greeting/greeting.cpp
module;

#include <expected>
#include <format>
#include <string>
#include <string_view>

module genyleap.greeting;

namespace genyleap::greeting {

auto makeGreeting(std::string_view name)
    -> std::expected<std::string, GreetingError>
{
    if (name.empty()) {
        return std::unexpected {GreetingError::EmptyName};
    }

    return std::format("Hello, {}.", name);
}

}
Composition rootsrc/main.cpp
#include <print>

import genyleap.greeting;

int main()
{
    const auto greeting = genyleap::greeting::makeGreeting("Genyleap");

    if (!greeting) {
        std::println("Unable to create greeting.");
        return 1;
    }

    std::println("{}", *greeting);
    return 0;
}

支持 module scanning 的 target-based CMake。

将语言标准、module file set 与 dependency graph 保持在 target 上。不要退回 global compiler flags 或 project-wide include directory 来模拟传统 header 架构。

CMakeCMakeLists.txt
cmake_minimum_required(VERSION 3.30)

project(GenyleapHello
    VERSION 0.1.0
    LANGUAGES CXX
)

add_library(genyleap_greeting)

target_compile_features(genyleap_greeting
    PUBLIC
        cxx_std_26
)

target_sources(genyleap_greeting
    PUBLIC
        FILE_SET CXX_MODULES
        FILES
            src/greeting/greeting.cppm
    PRIVATE
        src/greeting/greeting.cpp
)

set_property(
    TARGET genyleap_greeting
    PROPERTY CXX_SCAN_FOR_MODULES ON
)

add_executable(genyleap_hello
    src/main.cpp
)

target_link_libraries(genyleap_hello
    PRIVATE
        genyleap_greeting
)

target_compile_features(genyleap_hello
    PRIVATE
        cxx_std_26
)
ShellConfigure · build · test
cmake -S . -B build/dev -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug

cmake --build build/dev --parallel

ctest --test-dir build/dev \
  --output-on-failure \
  --no-tests=error

平台 toolchain。

C++ 架构保持可移植;compiler、SDK、linker、packaging 与 runtime 作为明确的平台边界。切换 compiler 或 target SDK 后不要复用已 configure 的 CMake tree。

macOS.

为 Apple SDK 与平台工具安装完整 Xcode。Apple Clang 是默认 native compiler;需要更新 compiler feature 或 diagnostics 时可并行安装 upstream LLVM。

ShellInstall and verify
sudo xcode-select --switch /Applications/Xcode.app
sudo xcodebuild -license accept

brew install cmake ninja llvm

xcrun clang++ --version
cmake --version
ninja --version
xcrun --show-sdk-path
不要全局替换 Apple Clang。

Select upstream LLVM per build when needed; Apple SDK integration and upstream language experimentation are separate concerns.

Linux.

当 portability 重要时同时保留 GCC 与 Clang。为每个 compiler 使用独立 build directory,并用真实的 CMake/compiler/generator 组合验证 module support,而不是仅凭版本号推断。

ShellUbuntu / Debian baseline
sudo apt update
sudo apt install -y \
  build-essential \
  clang \
  lld \
  cmake \
  ninja-build \
  gdb
ShellSeparate compiler builds
cmake -S . -B build/gcc -G Ninja \
  -DCMAKE_CXX_COMPILER=g++

cmake -S . -B build/clang -G Ninja \
  -DCMAKE_CXX_COMPILER=clang++

Windows.

Use Visual Studio Build Tools with the C++ workload for the Windows SDK and MSVC ABI. Add LLVM when you want clang-cl diagnostics while retaining MSVC-compatible platform integration.

PowerShellInstall toolchains
winget install --id Microsoft.VisualStudio.2022.BuildTools `
  --override "--wait --passive --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"

winget install --id Kitware.CMake
winget install --id Ninja-build.Ninja
winget install --id LLVM.LLVM
使用 Developer PowerShell。

在 configure CMake 前必须初始化 MSVC compiler、linker 与 Windows SDK 环境。

Android.

Use the Android NDK's Clang toolchain and CMake toolchain file rather than treating Android as a normal Linux desktop build. For projects that also use the current Qt baseline, the compatibility manifest currently resolves NDK r27c (27.2.12479018).

CMakeNative Android shape
cmake -S . -B build/android-arm64 -G Ninja \
  -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \
  -DANDROID_ABI=arm64-v8a \
  -DANDROID_PLATFORM=android-28

cmake --build build/android-arm64 --parallel

将 Android 特定 JNI、lifecycle、storage 与 permission code 放在 adapter 后面,让 domain/application modules 保持普通 C++。

iOS.

Use Xcode 16 or newer for the current Qt compatibility profile, and treat Apple frameworks, entitlements, signing and bundle resources as platform boundaries. Device and simulator builds are distinct targets even when they share application modules.

ShellInspect active Apple SDKs
xcodebuild -version
xcrun --sdk iphoneos --show-sdk-path
xcrun --sdk iphonesimulator --show-sdk-path
xcrun --sdk iphoneos clang++ --version

WebAssembly.

Use Emscripten when the target runtime is the browser. For the current Qt compatibility profile, Emscripten 5.0.5 is pinned automatically from upstream Qt documentation; a standalone C++/WASM project may intentionally choose a newer SDK after its own verification.

POSIX shellPin an emsdk toolchain
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk

./emsdk install 5.0.5./emsdk activate 5.0.5
source ./emsdk_env.sh
em++ --version
PowerShellWindows activation
git clone https://github.com/emscripten-core/emsdk.git
Set-Location emsdk

.\emsdk.bat install 5.0.5.\emsdk.bat activate 5.0.5
.\emsdk_env.ps1
em++ --version

浏览器 threading、SIMD、filesystem access 与 network behavior 是 runtime 约束,不只是 compiler switch。将其建模为 target capability,并在实际发布的 browser configuration 中验证。

Diagnostics 是开发环境的一部分。

compile-time correctness 只是一层。应从一开始就准备 sanitizer 与 static-analysis build,而不是等到出现难以复现的问题后再添加。

工具用途Recommendation
ASanMemory safety failuresDebug and CI where supported
UBSanUndefined behaviorPair with ASan in a dedicated diagnostic build
TSanData racesSeparate build because instrumentation changes runtime behavior
clang-tidyStatic analysis and modernizationEditor plus CI on changed production surfaces
CMakeTarget-local sanitizer example
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
    target_compile_options(genyleap_greeting PRIVATE
        -fsanitize=address,undefined
        -fno-omit-frame-pointer
    )

    target_link_options(genyleap_greeting PRIVATE
        -fsanitize=address,undefined
    )
endif()

Boost is part of the native foundation.

Use the C++ standard library first when it cleanly provides the required facility, then use Boost for capabilities that remain stronger or broader there. Keep Boost dependencies target-local, architecture-specific when compiled, and visible through modern CMake imported targets.

面向用户的应用:有意识地采用 Qt。

对于新的 Genyleap 风格图形应用,默认界面栈是构建在 module-based C++ application/domain code 之上的 Qt Quick、QML 与 Qt Quick Controls。UI 是 adapter,不拥有重复的 business logic。