# ════════════════════════════════════════════════════════════════════════════ # GNU-free CMake build for portable OpenSSH (FenrirOS) # # Replaces OpenSSH's autotools GNU-make build with CMake + Ninja so the whole # pipeline stays GNU-free (driven by makeplus/ninja and the LLVM/musl toolchain). # # OpenSSH still needs its POSIX-sh ./configure run ONCE to probe the platform and # emit config.h (+ the openbsd-compat headers and the *_config man/config files). # configure is an autoconf-generated /bin/sh script — not GNU make — so running # it does not reintroduce a GNU build tool. build_openssh() in build-os.sh runs # ./configure before invoking cmake; this file then compiles and links every # target. The object lists below mirror OpenSSH 9.9p2 Makefile.in verbatim # (sources self-disable via config.h #ifdefs for --without-openssl/--without-pam). # ════════════════════════════════════════════════════════════════════════════ cmake_minimum_required(VERSION 3.13) project(openssh C) if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config.h") message(FATAL_ERROR "config.h not found in the OpenSSH source root.\n" "Run ./configure (build_openssh does this) before invoking cmake.") endif() # ── Install layout (mirrors OpenSSH bindir/sbindir/libexecdir) ─────────────── set(OPENSSH_SYSCONFDIR "/etc/ssh" CACHE STRING "ssh system config dir") set(OPENSSH_PRIVSEP_DIR "/var/empty" CACHE STRING "privilege-separation chroot") set(OPENSSH_PIDDIR "/var/run" CACHE STRING "pid file dir") set(_bindir "${CMAKE_INSTALL_PREFIX}/bin") set(_libexecdir "${CMAKE_INSTALL_PREFIX}/libexec") # musl sysroot (zlib lives here; its header was staged in by build_openssh). set(MUSL_SYSROOT "/usr/local/musl" CACHE PATH "musl sysroot prefix") # NB: openbsd-compat is intentionally NOT on the global include path. Upstream # only uses `-I. -I$(srcdir)`; the main sources reach the compat headers via the # explicit "openbsd-compat/..." prefix. Putting openbsd-compat on the search # path makes angle-bracket includes like resolve to the empty compat # stub instead of musl's real header (breaks scp.c's fnmatch, etc.). include_directories( "${CMAKE_CURRENT_SOURCE_DIR}" "${MUSL_SYSROOT}/include" ) link_directories("${MUSL_SYSROOT}/lib") # config.h carries the platform feature defines; the path macros below come from # the Makefile's CPPFLAGS PATHS block (resolved against the install prefix). add_compile_definitions( HAVE_CONFIG_H _XOPEN_SOURCE=600 _BSD_SOURCE _DEFAULT_SOURCE _GNU_SOURCE SSHDIR="${OPENSSH_SYSCONFDIR}" _PATH_SSH_PROGRAM="${_bindir}/ssh" _PATH_SSH_ASKPASS_DEFAULT="${_libexecdir}/ssh-askpass" _PATH_SFTP_SERVER="${_libexecdir}/sftp-server" _PATH_SSH_KEY_SIGN="${_libexecdir}/ssh-keysign" _PATH_SSHD_SESSION="${_libexecdir}/sshd-session" _PATH_SSH_PKCS11_HELPER="${_libexecdir}/ssh-pkcs11-helper" _PATH_SSH_SK_HELPER="${_libexecdir}/ssh-sk-helper" _PATH_SSH_PIDDIR="${OPENSSH_PIDDIR}" _PATH_PRIVSEP_CHROOT_DIR="${OPENSSH_PRIVSEP_DIR}" ) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") endif() add_compile_options( -O2 -fPIC -fno-strict-aliasing -Wno-pointer-sign -Wno-unused-parameter -Wno-unused-result ) # ── openbsd-compat → libopenbsd-compat.a (OPENBSD + COMPAT + PORTS) ────────── set(_compat_names arc4random arc4random_uniform base64 basename bcrypt_pbkdf bindresvport blowfish daemon dirname explicit_bzero fmt_scaled freezero fnmatch getcwd getgrouplist getopt_long getrrsetbyname glob inet_aton inet_ntoa inet_ntop md5 memmem mktemp pwcache readpassphrase reallocarray recallocarray rresvport setenv setproctitle sha1 sha2 sigact strcasestr strlcat strlcpy strmode strndup strnlen strptime strsep strtoll strtonum strtoull strtoul timingsafe_bcmp vis bsd-asprintf bsd-closefrom bsd-cygwin_util bsd-err bsd-flock bsd-getentropy bsd-getline bsd-getpagesize bsd-getpeereid bsd-malloc bsd-misc bsd-nextstep bsd-openpty bsd-poll bsd-pselect bsd-setres_id bsd-signal bsd-snprintf bsd-statvfs bsd-timegm bsd-waitpid fake-rfc2553 getrrsetbyname-ldns kludge-fd_set openssl-compat libressl-api-compat xcrypt port-aix port-irix port-linux port-prngd port-solaris port-net port-uw ) set(_compat_src "") foreach(_n ${_compat_names}) list(APPEND _compat_src "openbsd-compat/${_n}.c") endforeach() add_library(openbsd-compat STATIC ${_compat_src}) # Upstream compiles the compat objects from inside openbsd-compat/ (cd && make), # so their own ``/`` includes resolve to the local # stubs. Replicate that with a target-private include dir (kept off the global # path so the main sources still get musl's real headers). target_include_directories(openbsd-compat PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/openbsd-compat") # ── libssh.a (LIBOPENSSH_OBJS + XMSS + LIBSSH_OBJS) ───────────────────────── set(_libssh_names ssh_api ssherr sshbuf sshkey sshbuf-getput-basic sshbuf-misc sshbuf-getput-crypto krl bitmap ssh-xmss sshkey-xmss xmss_commons xmss_fast xmss_hash xmss_hash_address xmss_wots authfd authfile canohost channels cipher cipher-aes cipher-aesctr cleanup compat fatal hostfile log match moduli nchan packet readpass ttymodes xmalloc addr addrmatch atomicio dispatch mac misc utf8 monitor_fdpass rijndael ssh-dss ssh-ecdsa ssh-ecdsa-sk ssh-ed25519-sk ssh-rsa dh msg progressmeter dns entropy gss-genr umac umac128 ssh-pkcs11 smult_curve25519_ref poly1305 chacha cipher-chachapoly cipher-chachapoly-libcrypto ssh-ed25519 digest-openssl digest-libc hmac ed25519 hash kex kex-names kexdh kexgex kexecdh kexc25519 kexgexc kexgexs kexsntrup761x25519 kexmlkem768x25519 sntrup761 kexgen sftp-realpath platform-pledge platform-tracing platform-misc sshbuf-io ) set(_libssh_src "") foreach(_n ${_libssh_names}) list(APPEND _libssh_src "${_n}.c") endforeach() add_library(libssh STATIC ${_libssh_src}) set_target_properties(libssh PROPERTIES OUTPUT_NAME ssh) # libssh and openbsd-compat are mutually referential; rescan as a group so the # static-archive symbol resolution matches `-lssh -lopenbsd-compat -lssh ...`. set(SSH_LIBGROUP "$") set(SKOBJS ssh-sk-client.c) # ── Per-target object lists (Makefile.in) and install destinations ────────── # add_openssh_exe( ) function(add_openssh_exe _exe _dest _extralibs) add_executable(${_exe} ${ARGN}) target_link_libraries(${_exe} PRIVATE ${SSH_LIBGROUP} z ${_extralibs}) install(TARGETS ${_exe} RUNTIME DESTINATION ${_dest}) endfunction() add_openssh_exe(ssh bin "" ssh.c readconf.c clientloop.c sshtty.c sshconnect.c sshconnect2.c mux.c ${SKOBJS}) add_openssh_exe(sshd sbin "crypt" sshd.c platform-listen.c servconf.c sshpty.c srclimit.c groupaccess.c auth2-methods.c dns.c fatal.c compat.c utf8.c authfd.c canohost.c ${SKOBJS}) add_openssh_exe(sshd-session libexec "crypt" sshd-session.c auth-rhosts.c auth-passwd.c audit.c audit-bsm.c audit-linux.c platform.c sshpty.c sshlogin.c servconf.c serverloop.c auth.c auth2.c auth2-methods.c auth-options.c session.c auth2-chall.c groupaccess.c auth-bsdauth.c auth2-hostbased.c auth2-kbdint.c auth2-none.c auth2-passwd.c auth2-pubkey.c auth2-pubkeyfile.c monitor.c monitor_wrap.c auth-krb5.c auth2-gss.c gss-serv.c gss-serv-krb5.c loginrec.c auth-pam.c auth-shadow.c auth-sia.c sftp-server.c sftp-common.c sandbox-null.c sandbox-rlimit.c sandbox-systrace.c sandbox-darwin.c sandbox-seccomp-filter.c sandbox-capsicum.c sandbox-pledge.c sandbox-solaris.c uidswap.c ${SKOBJS}) add_openssh_exe(scp bin "" scp.c progressmeter.c sftp-common.c sftp-client.c sftp-glob.c) add_openssh_exe(ssh-add bin "" ssh-add.c ${SKOBJS}) add_openssh_exe(ssh-agent bin "" ssh-agent.c ssh-pkcs11-client.c ${SKOBJS}) add_openssh_exe(ssh-keygen bin "" ssh-keygen.c sshsig.c ${SKOBJS}) add_openssh_exe(ssh-keysign libexec "" ssh-keysign.c readconf.c uidswap.c ${SKOBJS}) add_openssh_exe(ssh-pkcs11-helper libexec "" ssh-pkcs11-helper.c ssh-pkcs11.c ${SKOBJS}) add_openssh_exe(ssh-sk-helper libexec "" ssh-sk-helper.c ssh-sk.c sk-usbhid.c) add_openssh_exe(ssh-keyscan bin "" ssh-keyscan.c ${SKOBJS}) add_openssh_exe(sftp-server libexec "" sftp-common.c sftp-server.c sftp-server-main.c) add_openssh_exe(sftp bin "" sftp.c sftp-usergroup.c progressmeter.c sftp-common.c sftp-client.c sftp-glob.c)