跳到主要内容

KMPKG Portfile 内置变量全解析

KMPKG 会为每个端口的 portfile.cmake 自动注入一系列只读内置变量,用于适配不同编译目标、系统环境和路径规则,禁止端口代码修改这些变量。以下是按用途分类的完整解读(含实操示例)。

一、基础标识变量

1. PORT

  • 作用:当前正在构建的端口名称(与 ports/ 下的目录名一致)。
  • 使用场景:动态拼接路径、日志输出、目标命名等。
  • 示例
    # 输出当前构建的端口名
    message(STATUS "Building port: ${PORT}")
    # 拼接端口专属安装路径
    set(PORT_CONFIG_DIR "${CURRENT_INSTALLED_DIR}/share/${PORT}")

2. VERSION

  • 作用:当前端口的上游版本号(不含 port-version 修订号,如端口版本 1.0.0#2 时,VERSION1.0.0)。
  • 使用场景:源码下载、版本相关配置、文件名拼接。
  • 示例
    # 从自定义地址下载对应版本的源码包
    kmpkg_download_distfile(
    URL "https://example.com/${PORT}-${VERSION}.tar.gz"
    SHA512 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    )

3. TARGET_TRIPLET

  • 作用:当前编译目标的三元组名称(如 x64-uwparm64-linuxx86-mingw)。
  • 使用场景:区分不同编译目标的构建逻辑、路径适配。
  • 示例
    # 针对 UWP 三元组调整编译参数
    if(TARGET_TRIPLET STREQUAL "x64-uwp")
    kmpkg_cmake_configure(SOURCE_PATH ${SOURCE_PATH} OPTIONS "-DUWP_BUILD=ON")
    endif()

4. HOST_TRIPLET

  • 作用:构建机(宿主)对应的三元组名称(如 Windows 主机为 x64-windows,macOS 主机为 x64-osx)。
  • 使用场景:区分宿主/目标环境的工具链路径。
  • 示例
    # 从宿主安装目录获取构建工具
    set(HOST_TOOL "${CURRENT_HOST_INSTALLED_DIR}/bin/make${KMPKG_HOST_EXECUTABLE_SUFFIX}")

二、系统判定变量

1. 目标系统判定:KMPKG_TARGET_IS_<system>

  • 作用:判定编译目标系统(如 UWP、Linux、Android),匹配时值为 TRUE,否则未定义。
  • 支持的系统值
    变量匹配场景
    KMPKG_TARGET_IS_WINDOWSWindows(含 UWP、MinGW)
    KMPKG_TARGET_IS_UWP仅 UWP(Windows 运行时)
    KMPKG_TARGET_IS_MINGW仅 MinGW 环境
    KMPKG_TARGET_IS_LINUXLinux 系统
    KMPKG_TARGET_IS_OSXmacOS 系统
    KMPKG_TARGET_IS_IOSiOS 系统
    KMPKG_TARGET_IS_ANDROIDAndroid 系统
    KMPKG_TARGET_IS_FREEBSDFreeBSD 系统
    KMPKG_TARGET_IS_OPENBSDOpenBSD 系统
    KMPKG_TARGET_IS_EMSCRIPTENEmscripten(Wasm)环境
  • 示例
    # UWP 目标禁用动态库,强制静态编译
    if(KMPKG_TARGET_IS_UWP)
    set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
    endif()

    # Linux 目标链接 pthread 库
    if(KMPKG_TARGET_IS_LINUX)
    target_link_libraries(${PORT} PRIVATE pthread)
    endif()

2. 宿主系统判定:KMPKG_HOST_IS_<system>

  • 作用:判定构建机系统(宿主环境),匹配时值为 TRUE,否则未定义。
  • 支持的系统值WINDOWS/OSX/LINUX/FREEBSD/OPENBSD
  • 使用场景:适配宿主系统的工具链、路径分隔符、可执行文件后缀。
  • 示例
    # Windows 宿主使用批处理脚本,Linux/macOS 宿主使用 shell 脚本
    if(KMPKG_HOST_IS_WINDOWS)
    set(SCRIPT_PATH "${SOURCE_PATH}/build.bat")
    else()
    set(SCRIPT_PATH "${SOURCE_PATH}/build.sh")
    execute_process(COMMAND chmod +x ${SCRIPT_PATH})
    endif()

三、路径/可执行文件后缀变量

1. KMPKG_HOST_PATH_SEPARATOR

  • 作用:宿主系统的路径分隔符(Windows 为 ;,类 Unix 为 :)。
  • 注意:必须用引号包裹(避免分号被 CMake 解析为列表分隔符)。
  • 示例
    # 向环境变量追加路径
    set(ENV{PATH} "$ENV{PATH}${KMPKG_HOST_PATH_SEPARATOR}${SOURCE_PATH}/tools")

2. KMPKG_HOST_EXECUTABLE_SUFFIX

  • 作用:宿主系统的可执行文件后缀(Windows 为 .exe,类 Unix 为空字符串)。
  • 示例
    # 定位宿主的 cmake 可执行文件
    set(HOST_CMAKE "${CURRENT_HOST_INSTALLED_DIR}/bin/cmake${KMPKG_HOST_EXECUTABLE_SUFFIX}")

3. KMPKG_TARGET_EXECUTABLE_SUFFIX

  • 作用:目标系统的可执行文件后缀(KMPKG_TARGET_IS_WINDOWS.exe,否则为空)。
  • 示例
    # 安装可执行文件时适配目标后缀
    install(
    PROGRAMS "${SOURCE_PATH}/bin/app"
    RENAME "app${KMPKG_TARGET_EXECUTABLE_SUFFIX}"
    DESTINATION "${CURRENT_PACKAGES_DIR}/bin"
    )

4. KMPKG_HOST_BUNDLE_SUFFIX / KMPKG_TARGET_BUNDLE_SUFFIX

  • 作用:宿主/目标系统的「包后缀」(如 macOS 为 .bundle,其他系统为空)。
  • 示例
    # 安装 macOS 目标的 bundle 文件
    if(KMPKG_TARGET_IS_OSX)
    install(
    DIRECTORY "${SOURCE_PATH}/lib/mylib${KMPKG_TARGET_BUNDLE_SUFFIX}"
    DESTINATION "${CURRENT_PACKAGES_DIR}/lib"
    )
    endif()

四、库文件前缀/后缀变量

这类变量适配不同系统的库文件命名规则(如 Linux 静态库为 libxxx.a,Windows 为 xxx.lib),与 CMake 原生变量(如 CMAKE_STATIC_LIBRARY_PREFIX)等价,但为 KMPKG 标准化封装。

变量作用示例取值(Windows/Unix)
KMPKG_TARGET_STATIC_LIBRARY_PREFIX目标系统静态库前缀"" / "lib"
KMPKG_TARGET_STATIC_LIBRARY_SUFFIX目标系统静态库后缀".lib" / ".a"
KMPKG_TARGET_SHARED_LIBRARY_PREFIX目标系统动态库前缀"" / "lib"
KMPKG_TARGET_SHARED_LIBRARY_SUFFIX目标系统动态库后缀".dll" / ".so"
KMPKG_TARGET_IMPORT_LIBRARY_PREFIX目标系统导入库前缀(仅 Windows)"" / 无意义
KMPKG_TARGET_IMPORT_LIBRARY_SUFFIX目标系统导入库后缀(仅 Windows)".lib" / 无意义

示例:动态拼接库文件名

# 构造目标系统的静态库名称(如 Windows: foo.lib,Linux: libfoo.a)
set(STATIC_LIB_NAME "${KMPKG_TARGET_STATIC_LIBRARY_PREFIX}foo${KMPKG_TARGET_STATIC_LIBRARY_SUFFIX}")
# 验证库文件是否存在
if(NOT EXISTS "${CURRENT_INSTALLED_DIR}/lib/${STATIC_LIB_NAME}")
message(FATAL_ERROR "Static library ${STATIC_LIB_NAME} not found!")
endif()

5. KMPKG_FIND_LIBRARY_PREFIXES / KMPKG_FIND_LIBRARY_SUFFIXES

  • 作用find_library() 命令的默认前缀/后缀列表(适配目标系统)。
  • 示例
    # 查找目标系统的 foo 库(自动适配前缀/后缀)
    find_library(
    FOO_LIB
    NAMES foo
    PATHS "${CURRENT_INSTALLED_DIR}/lib"
    PREFIXES ${KMPKG_FIND_LIBRARY_PREFIXES}
    SUFFIXES ${KMPKG_FIND_LIBRARY_SUFFIXES}
    )

五、编译环境判定变量

KMPKG_CROSSCOMPILING

  • 作用:判定是否为「跨编译」(宿主三元组 ≠ 目标三元组),值为 TRUE/FALSE
  • 核心注意:跨编译时,端口不能执行编译生成的二进制文件(如 Android 目标无法在 Windows 主机运行)。
  • 示例
    # 非跨编译时,运行测试程序;跨编译时跳过
    if(NOT KMPKG_CROSSCOMPILING)
    execute_process(
    COMMAND "${CURRENT_BUILDDIR}/test${KMPKG_TARGET_EXECUTABLE_SUFFIX}"
    RESULT_VARIABLE TEST_RESULT
    )
    if(TEST_RESULT NOT EQUAL 0)
    message(FATAL_ERROR "Test failed!")
    endif()
    else()
    message(STATUS "Cross-compiling, skip test")
    endif()

六、安装目录变量

1. CURRENT_INSTALLED_DIR

  • 作用:目标三元组的端口安装根目录(绝对路径),即当前端口编译完成后要安装到的目录。
  • 示例
    # 查找目标系统的 CMake 配置文件
    find_package(
    foo CONFIG REQUIRED
    PATHS "${CURRENT_INSTALLED_DIR}/share/foo/cmake"
    )

2. CURRENT_HOST_INSTALLED_DIR

  • 作用:宿主三元组的端口安装根目录(绝对路径),用于获取宿主侧的构建工具/依赖。
  • 示例
    # 跨编译时,使用宿主的 pkg-config 工具
    if(KMPKG_CROSSCOMPILING)
    set(ENV{PKG_CONFIG_EXECUTABLE} "${CURRENT_HOST_INSTALLED_DIR}/bin/pkg-config${KMPKG_HOST_EXECUTABLE_SUFFIX}")
    endif()

核心使用原则

  1. 只读性:所有内置变量禁止修改,修改会导致 KMPKG 构建逻辑异常;
  2. 系统适配优先:优先使用 KMPKG_TARGET_IS_*/KMPKG_HOST_IS_* 判定系统,而非原生 CMake 变量(如 WIN32),适配性更强;
  3. 路径拼接规范:路径拼接必须使用 KMPKG_HOST_PATH_SEPARATOR,避免跨系统路径错误;
  4. 跨编译校验:涉及执行编译产物的逻辑,必须先判断 KMPKG_CROSSCOMPILING