simh-testsetgenerator/cmake/CMake-Maintainers.md
B. Scott Michel 06d41835fe CMake: Win XP (v141_xp) VS install script
Move the PowerShell code from .github/workflow/cmake-builds.yml into its
own script, cmake/github_v141_xp.ps1, to keep cmake-buils.yml readable.
The script also facilitates synchronizng with the Chocolatey installer's
Wait-VSIstallerProcesses function easier (from which this this code is
derived.)

cmake-builds.yml: Check the output from Get-VSSetupInstance and
Set-VSSetupInstance. Empty (or null) output indicates that the v141_xp
install did not complete successfully. Build process will bail when that
happens.

cmake/v141_xp_install.ps1: Unused and now unnecessary script.
2023-10-24 12:46:51 -04:00

35 KiB

Table of Contents

CMake Maintainer Walk-through

Introduction

This code walk-through is primarily intended for maintainers and developers interested in the CMake build and packaging environment internals.

The main idea is to make adding and compiling simulators easy for the simulator developers through a single CMake function, add_simulator. All a simulator developer should have to do is create a simulator CMakeLists.txt file, invokes the add_simulator function and update the cmake/simh-simulators.cmake file to include the new simulator sub-directory. That's it.

The remainder of this document explains the CMake infrastructure machinery that supports the add_simulator function.

CMake Basics

If you are not familiar with CMake, CMake is a meta-build platform that supports a wide cross section of operating systems and build systems. Typical CMake-based development has four phases:

  • Configure and generate: Search for headers, dependency libraries, adjust compiler flags, add defines and include paths, set up build targets (static, dynamic libraries and executables), setup test case support and packaging, then generate the build system's input (e.g., a makefile for make, solution hierarchy for Visual Studio, build.ninja for Ninja, project files for Mac OS X XCode, etc.)

  • Build: Invoke the build system (make, ninja, msbuild, ...) CMake's build mode is a wrapper around the underlying build system tool. It's perfectly acceptable to change to the build directory and invoke the build tool directly.

  • Test: Execute the test cases using the CTest driver and collect test status (success, failure, failure output logs.)

  • Package: Create installer packages using the CPack utility.

CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR

CMake has two variables that identify the top-level source directory, CMAKE_SOURCE_DIR, and the build artifact directory, CMAKE_BINARY_DIR. These two directories should be separate from each other -- you should not try to create build artifacts in the top-level source directory (this is enforced by the top-level CMakeLists.txt code.)

Top-level CMakeLists.txt

The top-level CMakeLists.txt file, located in CMAKE_SOURCE_DIR, drives the configure/generate phase. Each simulator sub-directory has its own CMakeLists.txt file included by top-level CMakeLists.txt. These per-simulator CMakeLists.txt files define one or more simulator executables along with each executable's simulator-specific defines, include paths and needed SIMH features (i.e., video support, 64-bit integer, 64-bit address support.)

Build Configurations

CMake understands multi-configuration build system tools, notably msbuild and XCode, versus single configuration build system tools, such as make and ninja. Multi-configuration build system tools require an explicit configuration at the build phase, e.g. --config Release or --config Debug to build optimized vs. debug simulators. Single configuration build system tools specify CMAKE_BUILD_TYPE at the configure/generate phase. If you need to change the build configuration for a single configuration tool, you have to reconfigure. Note that if you specify a configuration during the build phase for a single configuration build system tool, it will be silently ignored.

The SIMH CMake infrastructure has a strong preference for the Release and Debug build configurations. The MinSizeRel and RelDbgInfo configurations are weakly supported; their compile flags are not altered the way that the Release and Debug configurations are customized.

Code Roadmap

open-simh                            This is CMAKE_SOURCE_DIR
+-- .github/workflows
|   + build.yml                      GitHub CI/CD driver for push, pull request
|   |                                builds. Uses cmake-builds.yml for CMake builds.
|   + cmake-builds.yml               Reusable GitHub CI/CD workflow for CMake
|   |                                builds.
|   + release.yml                    GitHub CI/CD driver for packaging and publishing
|                                    releases. Uses cmake-builds.yml to create the
|                                    packaged artifacts (simulators and docs.)
|
+-- CMakeLists.txt                   Top-level CMake configure/generate driver.
+-- cmake                            CMake support code
|   +-- CMake-Walkthrough.md         Documentation. You're reading it.
|   +-- FindEDITLINE.cmake           find_package support for libeditline
|   +-- FindPCAP.cmake               find_package support for libpcap
|   +-- FindPCRE.cmake               find_package support for PCRE
|   +-- FindPCRE2.cmake              find_package support for PCRE2
|   +-- FindPTW.cmake                Platform thread support
|   +-- FindVDE.cmake                find_package support for VDE networking
|   +-- GitHub-release.md            Pre-built binary package install instructions
|   +-- add_simulator.cmake          The add_simulator function, SIMH core libraries
|   +-- build-*                      cmake-builder script output (CMAKE_BINARY_DIR)
|   |                                directories
|   +-- build_dep_matrix.cmake       Release and Debug build scaffolding for
|   |                                external dependency libraries
|   +-- cmake-builder.ps1            PowerShell builder script
|   +-- cmake-builder.sh             Bash builder script
|   +-- cpack-setup.cmake            CPack packaging setup code
|   +-- dep-link.cmake               CMake interface library configuration from
|   |                                previously located dependency libraries
|   +-- dep-locate.cmake             Dependency library location code, e.g., find
|   |                                PCRE, SDL2, SDL2_ttf, ...
|   +-- dependencies                 External dependency library installation
|   |   |                            hierarchy, if building dep. libraries
|   |   +-- Windows-10-MSVC-19.34    (Example 32-bit Windows 10 dependencies)
|   |   +-- Windows-10-MSVC-19.34-64 (Example 64-bit Windows 10 dependencies)
|   +-- file-link-copy.cmake         CMake script to symlink, hard link or copy a
|   |                                file
|   +-- fpintrin.cmake               Unused. Detects SSE, SSE2 and SSE3.
|   +-- generate.py                  Python script that generates the simulator
|   |                                CMakeLists.txt from the makefile
|   +-- git-commit-id.cmake          CMake script to update .git-commit-id and
|   |                                .git-commit-id.h
|   +-- github_v141_xp.ps1           Visual Studio "XP toolkit" installer PowerShell
|   |                                script
|   +-- installer-customizations     Installer-specific customization files
|   +-- os-features.cmake            Operating system feature probes, e.g., -lm
|   +-- patches                      Patches applied to external dependency libs
|   +-- platform-quirks.cmake        Platform quirks: compiler flags, HomeBrew
|   |                                includes, ...
|   +-- pthreads-dep.cmake           Detect platform thread support, configure the
|   |                                thread_lib interface library
|   +-- simgen                       generate.py script support
|   +-- simh-packaging.cmake         Simulator packaging, adds simulators to
|   |                                CPack components (simulator "families")
|   +-- simh-simulators.cmake        Simulator add_subdirectory includes, variable
|   |                                definitions
|   +-- vcpkg-setup.cmake            vcpkg package manager setup code

${CMAKE_SOURCE_DIR}/CMakeLists.txt

The top-level CMakeLists.txt drives CMake's configure/generate phase, which has the following flow:

  • Initial sanity checks

    • Ensure CMake's version is greater or equal to version 3.14. CMake will terminate configuration if the minimum version is not met.
    • Check CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR, terminating with an error message if CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR are the same directory.
    • If CMake's version is below 3.21, emit a warning that creating installers will be unsuccessful. This doesn't prevent building simulators. This warning is only emitted once.
    • Emit a fatal error message and terminate if Windows XP compatibility was requested via -T v141_xp on the command line and the VCPKG_ROOT environment variable is set.
  • Set the SIMH version variables and call the project function to initiate project configuration.

  • Configure vcpkg.

  • Set GNUInstallDirs installation directory layout.

  • If the build system tool only supports a single configuration, such as make and ninja, default to a Release build configuration if CMAKE_BUILD_TYPE isn't set.

  • Generate a system identifier, SIMH_SYSTEM_ID.

    SIMH_SYSTEM_ID is used as a dependencies subdirectory name on platforms for which missing external dependency libraries need to be built (Windows, exclusively.)

  • Define and process options, specified on the command line with -DFOO=BAR arguments.

    • NO_DEP_BUILD_OPTVAL: This is the default value for NO_DEP_BUILD.
      • If NO_DEP_BUILD has a cached value already, leave it alone.
      • Initialize NO_DEP_BUILD_OPTVAL to False so that dependencies are never built.
      • When the detected system is Windows and NOT a MinGW variant and NOT using vcpkg, NO_DEP_BUILD_OPTVAL is set to True so that missing dependencies are built.
    • MAC_UNIVERSAL_OPTVAL: This is the default value for MAC_UNIVERSAL.
      • If MAC_UNIVERSAL has a cached value already, leave it alone.
      • Initialize MAC_UNIVERSAL_OPTVAL to False unless MAC_UNIVERSAL was specified as an option on the command line.
      • This is a placeholder for future work to support macOS universal binaries.
  • Set CMAKE_INSTALL_PREFIX to ${CMAKE_SOURCE_DIR}/SIMH-install as a default installation destination. Otherwise, a platform-specific prefix such as /usr/local might be used and cause unexpected surprises.

  • Set the default CMAKE_RUNTIME_OUTPUT_DIRECTORY value to SIMH_LEGACY_INSTALL. SIMH_LEGACY_INSTALL is set to ${CMAKE_SOURCE_DIR}/BIN, appending Win32 if on Windows, to emulate the SIMH makefile's executable output structure.

  • Tweak CMake's library and include search paths so that CMake can find the externally built dependency libraries, if needed.

  • Deal with platform-specific quirkiness, such as compiler flags, optimization levels, HomeBrew include and library directories on macOS.

  • Locate dependencies, create and populate the os_features, thread_lib, simh_regexp, simh_video and simh_network interface libraries.

    • CMake interface libraries encapsulate defines, include paths and dynamic/static link libraries as an integrated package.

    • add_simulator references the interface libraries via CMake's target_link_libraries function, which adds the interface libary's defines and include paths to the simulator compile flags.

      Note: If the interface library is empty, i.e., nothing was added to it because particular functionality wasn't found or undesired, the interface library adds nothing to the simulator's compile flags or link libraries. This permits consistency and simplicity in add_simulator's implementation.

    • os_features (os-features.cmake): Operating-system specific features, such testing whether -lrt contains the definitions for shm_open, tests for assorted system headers, adds the winmm and Windows socket libraries on Windows.

      Note: os-features.cmake could potentially fold itself into platform-quirks.cmake in the future. It is separate for the time being for functional clarity.

    • thread_lib (pthreads-dep.cmake): Platform threading support. Usually empty for Linux and macOS platforms, adds the PThreads4W external dependency for Windows native and XP platforms.

    • simh_regexp: Regular expression support, if the WITH_REGEX option is True. PCRE is effectively the only regular expression library that ends up in the simh_regexp interface library at the moment. There is support for PCRE2, but it requires changes to scp.c to actually make it useful.

    • simh_video: Graphics, input controller and sound support, based on SDL2, if the WITH_VIDEO option is True. Empty interface library if WITH_VIDEO is False. simh_video also pulls in libpng and SDL_ttf, along with their dependencies.

    • simh_network: This interface library collects defines and include paths for network support when VDE networking is enabled and used, as well as TUN network defines and includes.

  • Output a summary of dependencies and features.

  • If the NO_DEP_BUILD option is True (which is usually the case) and there are missing dependency libraries, print a fatal error message with the missing libraries, suggest to the user how they might fix this (.travis/deps.sh) and exit.

  • Initiate a "superbuild" if missing dependency libraries need to be built and NO_DEP_BUILD is False.

    • A superbuild is CMake's terminology for building external software and libraries (see CMake's ExternalProject module). When the superbuild successfully builds the external projects, it will re-execute the CMake configure/generate phase to re-detect them and continue building the SIMH simulators.
    • The superbuild normally happens only once. A superbuild can be reinitiated if the compiler's version changes or the dependencies subdirectory is cleaned.
  • Add the simulators (simh-simulators.cmake)

  • Configure packaging

    • cpack-setup.cmake: Per-packager configuration, i.e., customizations for the Nullsoft Scriptable Install System, macOS installer, Debian .deb packager.
    • simh-packaging.cmake: Define simulator package families (CPack components), add documentation to the default runtime support component.
  • End of file. Configuration is complete and CMake generates the build system's files appropriate to the specified generator, i.e., makefile for Unix Makefiles, build.ninja for the Ninja build system, etc.

The cmake sub-directory

add_simulator.cmake

add_simulator is the centerpiece around which the rest of the CMake-based infrastructure revolves. The basic principle is to make simulator compiles very straightforward with a simple CMake function. The function's full documentation for usage and options are in README-CMake.md.

add_simulator.cmake decomposes into eight (8) sections:

  • Update ${CMAKE_SOURCE_DIR}/.git-commit-id and ${CMAKE_SOURCE_DIR}/.git-commit-id.h with the current Git hash identifier, if it has changed. These files are only rewritten if the hash identifier has changed, i.e., there has been a new commit.

  • build_simcore function: This is the workhorse function that compiles the six (6) simulator core libraries: simhcore, simhi64, simhz64 and their _video counterparts. Network support is always included in the core libraries. Networking is enabled by default, and must be explicitly disabled.

    Each core library includes the simh_network, simh_regexp, os_features and thread_lib interface libraries, which causes the core library to inherit the interface libraries' command line defines, include directories and link libraries. Consequently, a core library is a single target_link_library unit from CMake's perspective and simplifies add_simulator.

    build_simcore also adds a ${core_libray}_cppcheck, e.g., simhcore_cppcheck, to execute cppcheck static analysis on the library's source. cppcheck rules are only added if the ENABLE_CPPCHECK option is True (CMake configuration option) and the cppcheck executable is available.

  • simh_executable_template: Common code used by the add_simulator and add_unit_test functions to compile an executable. The basic flow is:

    • add_executable to create the simulator's executable target in the build system, add the simulator's sources to get executable target.
    • Set the C dialect to C99, which causes the generator to add the necessary flags to the compile command line to request the C99 dialect. Note that some compilers can ignore the request.
    • Set ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} to ${SIMH_LEGACY_INSTALL} to mimic the SIMH makefile's binary output structure.
    • Add extra target compiler flags and linker flags; these flags are usually set or modified in platform_quirks.cmake.
    • MINGW and MSVC: Set the console subsystem linker option.
    • Add simulator-specific defines and includes, define USE_DISPLAY on the command line if video support requested.
    • Add the appropriate SIMH core library to executable's target link library list, i.e., select one of the six core librarys.
  • add_simulator: The simulator developer's "compile this simulator" function.

    • Call simh_executable_template to create the simulator executable target.
    • Add the simulator executable target to the CPack installed executables list. If using CMake 3.21 or later, also add the imported runtime artifacts. These are primarily Windows DLLs, but could also include macOS shared libraries.
    • CTest simulator test setup. Each simulator always executes RegisterSanityCheck. If the TEST option is passed to add_simulator and the simulator's tests subdirectory and test script exist, the test script will execute after RegisterSanityCheck.
    • Create a simulator cppcheck static analysis target if the ENABLE_CPPCHECK option is True and the cppcheck executable exists.
    • Add the DONT_USE_INTERNAL_ROM to the executable's command line if the DONT_USE_ROMS option is True. (Probably could move this earlier to after the call to simh_executable_template.)
  • add_unit_test: This function is intended for future use to execute non-simulator C-code unit tests, to potentially subsume SIMH's testlib command. It is not currently used. These non-simulator unit tests are supposed to utilize the Unity test framework, written in "pure" C.

  • Add the SIMH core support libraries targets the build_simcore function.

  • Add the BuildROMs executable, add the ROM header files as outputs from BuildROMs. Future FIXME: Add the ROM header files as build targets that depend on their respective ROM binary files so that they're automagically rebuilt. However, there is no corresponding rule or set of rules in the SIMH makefile, which is why this is a FIXME.

  • Add the frontpaneltest executable. frontpaneltest provides its own main function, which prevents it from being linked directly with a SIMH core library, e.g., simhcore. It has to be its own special executable target.

find_package support

find_package is CMake's functionality to find a package and set variables for compile defines, includes and link libraries, when found. CMake has a collection of find_package modules for well known, commonly used packages. CMake searches ${CMAKE_MODULE_PATH} for modules outside of its packaged collection; SIMH adds ${CMAKE_SOURCE_DIR}/cmake to ${CMAKE_MODULE_PATH}.

The Find<Package>.cmake modules used by SIMH and provided by CMake include:

  • ZLIB: The zlib compression library
  • Freetype: The Freetype font library
  • PNG: The PNG graphics library

SIMH includes six find_package scripts:

  • FindEDITLINE.cmake: Locates libeditline, adds termcap to the linker's library list. Applicable to non-Windows systems to provide command line history.

  • FindPCAP.cmake: Locates the packet capture library's headers. SIMH does not need the libpcap packet capture library; libpcap and it's Win32 equivalent are dynamically loaded at run time. The headers are only needed for libpcap's function prototypes.

  • FindPCRE.cmake, FindPCRE2.cmake: Locate PCRE and PCRE2 libraries and headers. SIMH does not support PCRE2 yet, however, finding the PCRE2 headers and library are included to make PCRE2 support easier at some point in the future.

  • FindPTW.cmake: "PTW" is shorthand for the Windows PThreads4w POSIX threads compatibility library.

  • FindVDE.cmake: Locates the VDE networking headers and library if the WITH_VDE option is True.

In addition to Find<Package>.cmake modules, packages can also supply CMake configuration modules. SDL2 and SDL2-ttf generate and install CMake cofiguration files that are used in lieu of a find_package module.

platform-quirks.cmake: Platform-specific settings/tweaks

platform_quirks.cmake is the code container for managing platform-specific compiler and linker settings. Specific "quirks":

  • Set CMake's libary architecture variables (CMAKE_C_LIBRARY_ARCHITECTURE, CMAKE_LIBRARY_ARCHITECTURE) on Linux.

  • Windows compiler-specific quirks:

    • Ensure that SIMH links with the correct multi-threaded Visual C runtime.
    • Ensure that SIMH's source compiles with single byte character sets.
    • Increase warning verbosity if the DEBUG_WALL configuration option is True.
    • Make warnings fatal if the WARNINGS_FATAL configuration option is True.
  • There are no specific quirks for Linux.

  • Adjust the GNU and Clang compilers' Release build configuration flags, such as link-time optimization (LTO) and -O2 optimization, fatal warnings, ...

  • Construct the macOS HomeBrew and MacPorts header and library search paths so that find_package succeeds.

vcpkg.cmake: vcpkg package installer/maintainer

Setting the VCPKG_ROOT environment variable enables vcpkg support in SIMH. vcpkg is a package management system designed primarily for Windows Visual C/C++ software development with integrated CMake support. vcpkg also supports MinGW-w64, Linux and macOS. The GitHub CI/CD pipeline does not use vcpkg for either the Linux or macOS builds. MinGW-w64 is a SIMH CMake-supported platform, but is not normally targeted in a CI/CD pipeline. Also, MinGW-w64 uses the Pacman package manager, which makes vcpkg redundant.

vcpkg does not support producing Windows XP binaries. CMake will emit a fatal error message if VCPKG_ROOT is present and the CMake configure/generate command line specified the Windows XP-compatible toolset -T vc141_xp.

CMakeLists.txt sets the globally visible variable USING_VCPKG. This makes better shorthand than having to use DEFINED VCPKG_ROOT in conditionals and makes those tests more readable.

Functional flow:

  • If USING_VCPKG is False, return from vcpkg-setup.cmake immediately.

  • Construct the vcpkg "(architecture)-(platform)-(runtime)" triplet

    • Use the user's desired triplet if VCPKG_DEFAULT_TRIPLET exists as an environment variable.
    • Windows: Always choose a statically linked, static runtime triple for MS Visual C/C++ or Clang -- "(x64|x86|arm|arm64)-windows-static".
    • MinGW-w64: Triplets are "(x64|x86)-mingw-dynamic". Note: Waiting for a new community triplet that supports the statically linked runtime.
  • Set VCPKG_CRT_LINKAGE to "static" if the triplet ends in "-static". If not, set VCPKG_CRT_LINKAGE to "dynamic".

  • Execute the vcpkg CMake toolchain initialization. This installs the packages listed as dependencies in vcpkg.json:

    • pthreads
    • pcre
    • libpng
    • sdl2
    • sdl2-ttf

dep-locate.cmake is the consolidated code container for locating SIMH's dependency libraries: PCRE/PCRE2 regular expressions; libpng graphics for screen captures; SDL2, SDL2-ttf, freetype video support, VDE network support, the zlib compression needed by libpng and PCRE/PCRE2, etc. It is divided into two sections:

  • Locate packages: First try find_package to locate required packages, falling back to pkgconfig if pkgconfig is available. dep-locate.cmake also understands how to use vcpkg-based packages, since some of the package names differ from what would normally be expected. PCRE, in particular, is named unofficial-pcre vs. PCRE.

  • Superbuild setup: dep-locate.cmake constructs the external project builds for missing dependency libraries in preparation for the superbuild. Currently, this only applies to Windows. There is a list of source URL variables that immediately follows include (ExternalProject) that specify where the superbuild's external projects download the dependency's source code.

    • The source URL list needs to be periodically reviewed to bump library version numbers as new library versions are released.
    • sourceforce.net mirrors' SSL responses are very quirky and requires multiple mirror URLs to succeed.

    Future FIXME: The superbuild would be entirely unnecessary if SIMH didn't have to support Windows XP binaries. vcpkg should be the future dependency library package manager for Windows, but it does not support the XP toolkit and likely never will.

dep-link.cmake is the consolidated code container that populates the simh_regexp, simh_video and simh_network interface libraries. Note that the order in which dependency libraries are added to these interface libraries is important: SDL2-ttf must precede freetype and SDL2, for example. This reverse ordering is standard library linking practice, given that linkers only make a single pass through each library to resolve symbols.

simh-simulators.cmake

simh-simulators.cmake is the list of SIMH simulator subdirectories added as CMake subprojects. Each simulator subdirectory has its own CMakeLists.txt file that contains calls to add_simulator. Subprojects are a CMake idiom and maps well to build system generators, such as Visual Studio and XCode, which assume a subdirectory-subproject organization.

This file is currently autogenerated by the generate.py Python script, although, this may not the the case in the future.

generate.py: Automagic makefile → CMake infrastructure

The SIMH makefile is still considered the authoritative source for simulator compiler command lines and source code. generate.py was built to scrape the makefile's all and exp rules, gather simulator source code lists, simulator-specific defines, and emit the simulator subdirectory CMakeLists.txt and the simh-simulators.cmake files. To synchronize the SIMH CMake infrastructure with the SIMH makefile when new simulators are added to the makefile, when compiler command lines change or new simulator source code is added:

$ cd cmake; python3 -m generate

Internally, generate.py has three principal classes defined in the cmake/simgen subdirectory: CMakeBuildSystem (cmake_container.py), SimCollection (sim_collection.py) and SIMHBasicSimulator (basic_simulator.py).

  • CMakeBuildSystem: The top-level container for the entire SIMH simulator collection scraped from the makefile. It's a container that maps a SimCollection simulator group to a subdirectory. The CMakeBuildSystem.extract method interprets the makefile's parsed contents, and builds up the per-subdirectory SimCollection simulator groups.

  • SimCollection: A group of simulators, e.g., all of the VAX or PDP-11 simulators, or the PDP-8 simulator. It also maps simulator source macro names to source lists that become CMake variables to make the emitted CMakeLists.txt files more readable. The SimCollection.write_simulators method emits the simulator subdirectory CMakeLists.txt file.

  • SIMHBasicSimulator: An individual SIMH simulator stored inside a SimCollection. This class keeps track of the simulator's sources, simulator-specific defines and include paths, as well as detects when the simulator requires 64-bit address and 64-bit data, when the simulator requires video support. The SIMHBasicSimulator.write_section method emits the individual simulator's add_simulator function call to the CMakeLists.txt file stream passed by the parent SimCollection.

    SIMHBasicSimulator has several subclasses that specialize the write_section method. For example, the BESM6 simulator requires a Cyrillic font, which requires additional CMake code to search for an available font from a list of known Cyrillic-supporting fonts. The VAXSimulator class injects CMake code to symlink, hard link or copy the vax executable to microvax3900. The SimCollection.special_simulators dictionary maps simulator names to specialized SIMHBasicSimulator subclasses. If the simulator's name is not present in the special_simulators dictionary, SIMHBasicSimulator is used.

CPack configuration

CPack is the CMake utility for packaging SIMH's pre-built binaries. Like CMake, CPack has its own generators that support different packaging systems. Some packaging systems only support a single, all-in-one package, like Debian .deb packages. Other packaging systems support a finer grained approach with individually selectable package components, like the NullSoft Installation System (NSIS) and macOS' "productbuild" packagers.

cpack-setup.cmake imports the CPack module and customizes CPack variables and generator settings. Principally, cpack-setup.cmake sets the output name for the package, which is simh-major.minor-suffix. The suffix defaults to the system's name, ${CMAKE_SYSTEM_NAME} for non-Windows operating systems, and (win64|win32)-(Debug|Release)-(vs2022|vs2019|vs2017|vs2015)[-xp] for Windows systems. The -xp suffix is only appended when building Windows XP-compatible binaries. Setting the SIMH_PACKAGE_SUFFIX environment variable overrides the default suffix.

Platform and generator-specific settings in cpack-setup.cmake include:

  • Runtime installation exclusions: A list of files that should be excluded from the resulting installation package. For Windows, CPack should not install well known DLLs or anything from the system32 directory. Linux and macOS do not currently have a runtime exclusion list. If that changes, edit the pre_runtime_exclusions and post_runtime_exclusions variables' regular expressions.

  • NullSoft Installation System (NSIS): Arrange to use the installer-customizations/NSIS.template.in script timeplate (see below.) NSIS also uses "SIMH-major.minor" (e.g., "SIMH-4.0") as the installation directory's name and defaults to installing SIMH in the user's `$LocalAppData\Programs".

  • WIX Windows Installer: Sets the WIX GUID for SIMH. This GUID was entirely fabricated by a GUID generator.

  • Debian: Adds Debian package dependencies for libsd2, libsd2-ttf, libpcap, libvdeplug2 and libedit2. This dependency list needs to be periodically revisited when dependencies change.

simh-packaging.cmake defines package components and basic runtime support installation common to all simulators. Package components are groups of SIMH simulator "families" -- there is a strong correlation between a simulator family and the SIMH simulator subdirectories. For example, all of the VAX simulators belong to the vax_family component. simh-packaging.cmake creates the vax_family CPack component and add_simulator adds a simulator to its package family via its PKG_FAMILY <family> option.

The experimental_family is the exception to the simulator family-subdirectory rule, serving as the package family for the currently experimental simulators.

The runtime_support family is intended for executables and documentation common to all simulators. Currently, only the simh.doc SIMH documentation is part of this family. Future FIXME: populate this family with additional, non-simulator-specific documentation.

The cmake/installer-customizations subdirectory is where CPack-specific generator customizations should be kept. The NSIS installer template was altered so that the resulting SIMH installer executable only required user privileges to installer; the default escalates to "admin" privileges, which are unnecessary for SIMH.