本文面向需要构建可运行在OpenHarmony或 鸿蒙PC(arm64-ohos 等 triplet) 上的openssh命令行工具的开发者。通过使用vcpkg的方式构建。同时说明 OpenSSH 是什么为何用 vcpkg构建如何构建产物在哪、以及本 port 在适配过程中处理过的典型问题。


vcpkg (针对 C++ 库的包管理):虽然它最初是c/c++的包管理器,但它的 triplet 机制(如当前的 arm64-ohos)本质上也是一种轻量级的交叉编译配置框架

Qt 团队为鸿蒙做了 vcpkg 扩展,这套 fork 的改动刻意保持 小而聚焦,分支地址如下。

适配鸿蒙的vcpkg分支地址https://git.qt.io/jobor/vcpkg.git

关于vcpkg更详细的安装及使用,参见博文:
使用 vcpkg 为鸿蒙(HarmonyOS / OHOS)下载与安装三方库实践指南

1. OpenSSH 是什么

OpenSSH 是 OpenBSD 项目移植到多平台的 SSH 协议套件,提供安全远程登录、文件传输与密钥管理等功能。日常所说的「SSH 客户端」通常包括:

组件 作用
ssh 远程 shell、端口转发、跳板
scp / sftp 基于 SSH 的文件复制与交互式文件传输
ssh-keygen 生成与管理主机密钥、用户密钥
ssh-agent / ssh-add 代理私钥,减少重复输入口令
ssh-keyscan 批量采集主机公钥指纹
sshd SSH 服务端(守护进程)
sftp-server SFTP 子系统(常由 sshd 按需拉起)

Portable OpenSSHopenssh-portable)是面向 Linux、BSD 及各类类 Unix 环境的源码发行版,使用 GNU Autotoolsconfigure + make),与 Windows 上常见的 MSVC 工程形态不同。

openSSH的github仓https://github.com/openssh/openssh-portable

openSSH主页地址https://www.openssh.org/

2. 为什么在 OHOS 上用 vcpkg 构建 OpenSSH

因为简单。vcpkg上本来就支持上千个开源库,那么OpenSSH依赖的openssl和zlib库本来就有了。只需要新增加支持下OpenSSH的命令行即可。且移植符合通用的vcpkg的规范,熟悉cmake语法的移植起来也很简单了。

鸿蒙设备或 SDK 环境中,常见需求包括:

  • 开发机(多为 x86_64 Linux)交叉编译 arm64 目标;
  • OpenSSLzlib 等依赖版本 与工程其它库对齐
  • 同一套 vcpkg triplet / 工具链元数据 管理依赖与产物路径。

vcpkg 通过 portvcpkg.json + portfile.cmake)描述下载、配置、安装步骤;对 Autotools 项目通常走 vcpkg_configure_make / vcpkg_install_make,并与 ports/vcpkg-make 中的默认路径约定(例如把可执行文件安装到 tools/<port>/bin)集成。


3. 本仓库 openssh port 概要

仓库地址: https://gitcode.com/qq8864/vcpkg

项目 说明
上游版本 OpenSSH 9.9p2(portable tarball)
清单版本字段 使用 version-string9.9p2p,非 semver)
主要依赖 opensslzlib;可选 feature fido2libfido2
平台表达式 supports 支持 Linux/macOS/MinGW 等;并显式支持 ohos(`
构建系统 Autotools(无 CMake 顶层工程)

鸿蒙相关适配要点(均在 portfile.cmake 与补丁中体现):

  1. config.sub 不认识 linux-ohos
    通过补丁 ohos-config-sub.patchconfig.sub 中增加对 ohos / linux-ohos* 的识别(与 triplet aarch64-unknown-linux-ohos 一类配置一致)。

  2. 交叉工具链需要显式 --target
    VCPKG_TARGET_IS_OHOS 时通过 vcpkg_cmake_get_vars 读取 VCPKG_DETECTED_CMAKE_C_COMPILER_TARGET 等,并追加到 VCPKG_C_FLAGS / VCPKG_CXX_FLAGS,与 openssllibpng 等 port 在 OHOS 上的思路一致。

  3. --sysconfdir 须为绝对路径
    OpenSSH 的 configure 不接受相对 --sysconfdir,使用 ${CURRENT_PACKAGES_DIR}/etc/ssh

  4. Shadow / getspnam
    OHOS 类环境可能出现 shadow 头文件但无可用 getspnam 的情况,对 OHOS 使用 --without-shadow(定义 DISABLE_SHADOW)。

  5. loginrec.cutmpx 笔误
    上游在 #else 分支误写 &ut 应为 &utx,补丁 fix-loginrec-utmpx-typo.patch

  6. 安装阶段 strip / check-config
    交叉编译时宿主 strip 无法处理目标 ELF;默认 make install 会跑 check-config(执行 sshd -t),不适合交叉环境。采用 install-nokeys 跳过 check-config / host-key,并在 VCPKG_CROSSCOMPILING 时加 --disable-strip

  7. vcpkg_copy_tools 路径
    Autotools 默认把二进制装到 tools/openssh/bintools/openssh/sbin(经 DESTDIR 整理后),与 vcpkg_copy_tools 默认查找的 packages/.../bin 不一致;port 中按实际目录 vcpkg_copy_tool_dependencies,必要时用 SEARCH_DIR 从扁平 bin/ 迁出。

  8. 仅工具、无头文件
    portfile.cmake 开头 设置 VCPKG_POLICY_EMPTY_INCLUDE_FOLDER,避免 post-build 对空 include 误报。


4. 环境准备

4.1 必备条件

  • 已克隆并引导好的 vcpkg(能执行 ./vcpkg install)。
  • 针对 OHOSCMake toolchain / triplet(例如 arm64-ohos),且 opensslzlib 等依赖能在同一 triplet 下成功安装。
  • 若使用 OHOS SDK 的 Clang,通常需设置 OHOS_SDK_ROOT 等(与 triplet、文档一致;具体以你方工程为准)。

4.2 依赖端口(由 vcpkg.json 声明)

  • opensslzlib:始终需要。
  • vcpkg-cmake-get-varshost: trueplatform: "ohos"):仅在配置 OHOS 目标时参与,用于读取编译器 --target 等变量。

4.3 移植步骤

默认的vcpkg仓库中只有libssh或libssh2等相关的库,并没有openssh。因为openssh是一组命令行工具(ssh、scp、sftp等),而vcpkg主要是用来构建库和提供c/c++的包管理。但是它也可以用来构建二进制可执行程序。

1.clone下来vcpkg的仓库后,在ports文件夹下新建openssh的目录。

在这里插入图片描述
2.开始编写移植openssh相关的文件:
vcpkg.json

{
  "name": "openssh",
  "version-string": "9.9p2",
  "description": "OpenSSH suite: ssh(1), scp(1), sftp(1), ssh-keygen(1), ssh-agent(1), sshd(8), and related tools (portable release).",
  "homepage": "https://www.openssh.com/",
  "license": null,
  "supports": "(!uwp & !android & !ios & !emscripten & (!windows | mingw)) | ohos",
  "dependencies": [
    "openssl",
    "zlib",
    {
      "name": "vcpkg-cmake-get-vars",
      "host": true,
      "platform": "ohos"
    }
  ],
  "features": {
    "fido2": {
      "description": "Link against libfido2 for built-in U2F/FIDO security key support in ssh/sftp tools.",
      "dependencies": [
        "libfido2"
      ]
    }
  }
}

portfile.cmake文件

# Tools-only port; no public headers to install.
set(VCPKG_POLICY_EMPTY_INCLUDE_FOLDER enabled)

vcpkg_download_distfile(
    ARCHIVE
    URLS
        "https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${VERSION}.tar.gz"
        "https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${VERSION}.tar.gz"
    FILENAME "openssh-${VERSION}.tar.gz"
    SHA512 4c6d839aa3189cd5254c745f2bd51cd3f468b02f8e427b8d7a16b9ad017888a41178d2746dc51fb2d3fec5be00e54b9ab7c32c472ca7dec57a1dea4fc9840278
)

vcpkg_extract_source_archive(
    SOURCE_PATH
    ARCHIVE "${ARCHIVE}"
    PATCHES
        ohos-config-sub.patch
        fix-loginrec-utmpx-typo.patch
)

if(VCPKG_HOST_IS_WINDOWS)
    vcpkg_find_acquire_program(PERL)
    get_filename_component(PERL_EXE_PATH "${PERL}" DIRECTORY)
    vcpkg_add_to_path("${PERL_EXE_PATH}")
endif()

vcpkg_find_acquire_program(PKGCONFIG)
get_filename_component(PKGCONFIG_DIR "${PKGCONFIG}" DIRECTORY)
vcpkg_add_to_path("${PKGCONFIG_DIR}")

# OHOS: OpenHarmony toolchains often require an explicit Clang --target so
# configure-time compile/link probes resolve sysroot headers and libs
# correctly (same approach as ports/openssl/unix and ports/libpng).
if(VCPKG_TARGET_IS_OHOS)
    vcpkg_cmake_get_vars(cmake_vars_file)
    include("${cmake_vars_file}")
    string(APPEND VCPKG_C_FLAGS " --target=${VCPKG_DETECTED_CMAKE_C_COMPILER_TARGET}")
    string(APPEND VCPKG_CXX_FLAGS " --target=${VCPKG_DETECTED_CMAKE_CXX_COMPILER_TARGET}")
    # OpenSSL 3.0 deprecations in upstream portable sources (noise only).
    string(APPEND VCPKG_C_FLAGS " -Wno-deprecated-declarations")
endif()

# OpenSSH's configure rejects a relative --sysconfdir; it must be absolute.
vcpkg_list(SET configure_opts
    "--with-ssl-dir=${CURRENT_INSTALLED_DIR}"
    "--with-zlib=${CURRENT_INSTALLED_DIR}"
    "--without-openssl-header-check"
    "--sysconfdir=${CURRENT_PACKAGES_DIR}/etc/ssh"
)

# OpenHarmony sysroot may expose shadow-style headers without a usable getspnam;
# --without-shadow defines DISABLE_SHADOW (see configure.ac).
if(VCPKG_TARGET_IS_OHOS)
    vcpkg_list(APPEND configure_opts "--without-shadow")
endif()

if("fido2" IN_LIST FEATURES)
    vcpkg_list(APPEND configure_opts "--with-security-key-builtin=yes")
endif()

# Cross builds: GNU install -s invokes the host strip(1), which cannot handle
# target ELFs (e.g. arm64-ohos built on x86_64 Linux).
if(VCPKG_CROSSCOMPILING)
    vcpkg_list(APPEND configure_opts "--disable-strip")
endif()

set(extra_make_opts "")
if(VCPKG_TARGET_IS_WINDOWS)
    list(APPEND extra_make_opts
        DETERMINE_BUILD_TRIPLET
        USE_WRAPPERS
    )
endif()

vcpkg_configure_make(
    SOURCE_PATH "${SOURCE_PATH}"
    ${extra_make_opts}
    OPTIONS
        ${configure_opts}
)

# install-nokeys: install-files + install-sysconf, but not host-key / check-config.
# check-config runs $(DESTDIR)$(sbindir)/sshd -t under DESTDIR staging; that is
# wrong for cross-compiles (host cannot execute the target sshd, and paths may
# concatenate badly when bindir/sbindir are absolute).
vcpkg_install_make(INSTALL_TARGET install-nokeys)

# vcpkg_configure_make defaults bindir/sbindir to ${prefix}/tools/<port>/{bin,sbin}
# (see ports/vcpkg-make/vcpkg_make_common.cmake). After DESTDIR flatten, binaries
# are under tools/<port>/..., not packages/<port>/bin — vcpkg_copy_tools must use SEARCH_DIR.
set(_openssh_bindir "${CURRENT_PACKAGES_DIR}/tools/${PORT}/bin")
set(_openssh_sbindir "${CURRENT_PACKAGES_DIR}/tools/${PORT}/sbin")
if(NOT EXISTS "${_openssh_bindir}/ssh${VCPKG_TARGET_EXECUTABLE_SUFFIX}")
    set(_openssh_bindir "${CURRENT_PACKAGES_DIR}/bin")
    set(_openssh_sbindir "${CURRENT_PACKAGES_DIR}/sbin")
endif()

set(openssh_bin_tools
    ssh
    scp
    sftp
    ssh-add
    ssh-agent
    ssh-keygen
    ssh-keyscan
    ssh-pkcs11-helper
    ssh-sk-helper
)
set(openssh_sbin_tools
    sshd
    sshd-session
)

set(_openssh_dest_bin "${CURRENT_PACKAGES_DIR}/tools/${PORT}/bin")
set(_openssh_dest_sbin "${CURRENT_PACKAGES_DIR}/tools/${PORT}/sbin")
if("${_openssh_bindir}" STREQUAL "${_openssh_dest_bin}" AND "${_openssh_sbindir}" STREQUAL "${_openssh_dest_sbin}")
    # vcpkg autotools defaults already install into tools/<port>/{bin,sbin}.
    vcpkg_copy_tool_dependencies("${_openssh_dest_bin}")
    vcpkg_copy_tool_dependencies("${_openssh_dest_sbin}")
else()
    vcpkg_copy_tools(
        TOOL_NAMES ${openssh_bin_tools}
        SEARCH_DIR "${_openssh_bindir}"
        DESTINATION "${_openssh_dest_bin}"
        AUTO_CLEAN
    )
    vcpkg_copy_tools(
        TOOL_NAMES ${openssh_sbin_tools}
        SEARCH_DIR "${_openssh_sbindir}"
        DESTINATION "${_openssh_dest_sbin}"
        AUTO_CLEAN
    )
    vcpkg_copy_tool_dependencies("${_openssh_dest_bin}")
    vcpkg_copy_tool_dependencies("${_openssh_dest_sbin}")
endif()

# ssh-keysign and sftp-server install to ${prefix}/libexec; already under the
# package root after DESTDIR flatten — only pull in shared-library deps.
if(EXISTS "${CURRENT_PACKAGES_DIR}/libexec")
    vcpkg_copy_tool_dependencies("${CURRENT_PACKAGES_DIR}/libexec")
endif()

file(REMOVE_RECURSE
    "${CURRENT_PACKAGES_DIR}/debug/share"
    "${CURRENT_PACKAGES_DIR}/share/man"
    "${CURRENT_PACKAGES_DIR}/debug/share/man"
    "${CURRENT_PACKAGES_DIR}/lib"
    "${CURRENT_PACKAGES_DIR}/debug/lib"
    "${CURRENT_PACKAGES_DIR}/include"
    "${CURRENT_PACKAGES_DIR}/debug/include"
)

vcpkg_copy_pdbs()

file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENCE")


5. 构建步骤

在 vcpkg 根目录执行(示例 triplet 为 arm64-ohos):

./vcpkg install openssh:arm64-ohos

可选功能(若 triplet 上 libfido2 可用):

./vcpkg install 'openssh[fido2]:arm64-ohos'

首次或排错时可加 --clean-after-build 清理中间树。

成功时日志末尾会出现类似:

All requested installations completed successfully

如果要删除重新构建,可以:

export OHOS_SDK_ROOT=/root/ohos-sdk/linux/

rm -rf /root/vcpkg/buildtrees/openssh
./vcpkg remove openssh:arm64-ohos
./vcpkg install openssh:arm64-ohos

6. 安装产物路径说明

安装完成后,在 installed/<triplet>/ 下可重点关注:

路径 内容
tools/openssh/bin/ sshscpsftpssh-keygenssh-agentssh-addssh-keyscanssh-pkcs11-helperssh-sk-helper
tools/openssh/sbin/ sshdsshd-session
libexec/(triplet 根下) ssh-keysignsftp-server(Autotools 默认 libexecdir
etc/ssh/(若保留) ssh_configsshd_configmoduli 等模板(由 install-nokeys 中的 install-sysconf 安装)

说明:install-nokeys 不会在 DESTDIR 安装阶段执行 ssh-keygen -A 生成主机密钥;部署到设备时需按运维规范自行生成 /etc/ssh/ssh_host_* 等。


7. 与「完全成功」相关的校验信息

  • 安装成功:以 vcpkg 输出 All requested installations completed successfully 为准。
  • SPDX 提示:若 vcpkg.json 未写 SPDX license,vcpkg 可能提示查看各包的 copyright;OpenSSH 使用上游 LICENCE 文件,已通过 vcpkg_install_copyright 安装到 share/openssh/copyright
  • include 警告:工具型 port 无公共头文件属正常;应使用 VCPKG_POLICY_EMPTY_INCLUDE_FOLDER(变量名须正确),否则 post-build 仍会提示 include 为空

在这里插入图片描述


8. 常见问题(FAQ)

8.1 config.sub 报错 OS 'ohos' not recognized

已通过 ohos-config-sub.patch 扩展 config.sub;请确认 vcpkg_extract_source_archivePATCHES 中包含该补丁且为最新 port。

8.2 getspnam / xcrypt.c 编译失败

在 OHOS 上使用 --without-shadow;若你自行去掉该选项,需保证 sysroot 中 shadow API 完整且与探测一致

8.3 strip 无法识别 ELF / install-files 失败

交叉编译时启用 --disable-strip,并避免使用默认 make install 中的 check-config(本 port 使用 install-nokeys)。

8.4 vcpkg_copy_tools 找不到 ssh

Autotools 在 vcpkg 下默认安装到 tools/openssh/bin,不是 bin/;port 已按实际路径处理 vcpkg_copy_tool_dependencies 与可选 vcpkg_copy_tools

8.5 为何不用 MSVC 的 x64-windows

上游 portableAutotools + POSIX 为主;x64-windows(MSVC) 通常不在本 port 的 supports 范围内;在 Windows 上可考虑 MinGW triplet 或系统自带的 OpenSSH 分发渠道。


9. 真机验证

在鸿蒙PC的容器环境中验证方法:
低成本搭建鸿蒙PC运行环境:基于 Docker 的 x86_64 服务器

在这里插入图片描述
因为在我的测试阶段,库(so文件)和程序(bin)都在同一个文件夹下,为了使二进制可执行程序能够顺利找到库,需要使用一下指令配置下临时环境:

export LD_LIBRARY_PATH=$(pwd)

当运行 ssh 这种程序时,它需要加载 libcrypto.so(OpenSSL)和 libz.so(zlib)库。如果系统里有就直接去系统里找了。默认只会去系统的固定的“公家仓库”(如 /lib 或 /usr/lib)找。 正式发布产品时,通常不需要这么麻烦。如果鸿蒙PC环境已经有了OpenSSL的库,是可以直接运行的。

或者使用 RPATH(嵌入式最常用),在编译阶段,直接把库的路径“刻”进程序里。做法:在编译参数里加上 -Wl,-rpath,' O R I G I N / . . / l i b ′ 。程序运行时会自己找身边的库。 ORIGIN/../lib'。程序运行时会自己找身边的库。 ORIGIN/../lib。程序运行时会自己找身边的库。ORIGIN 就代表程序自己所在的目录,不管你把程序装到哪,它都能定位到附近的库。

或者把 .so 文件放入系统标准目录,直接拷贝到板子的 /usr/lib 或 /lib 下。这是最省事的,系统启动时会自动扫描这些地方,程序拿起来就能跑。
在这里插入图片描述
使用SSH命令远程登录一下后台的服务器试试:
在这里插入图片描述
测试成功!


10. 小结

  • OpenSSH 是工业界事实标准的 SSH 套件portable 版本适合 类 Unix / OHOSAutotools 构建链。
  • 使用 vcpkg 可在 统一 triplet 下安装 openssh,并与 opensslzlib 等依赖版本对齐。

最后,欢迎加入开源鸿蒙开发者社区交流:https://harmonypc.csdn.net/

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐