From 40a64324b71b28cd76669457f0bd1bcc15f1b775 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 12 Mar 2024 12:35:07 -0400 Subject: [PATCH] SCP: Added support for CMAKE. --- B5500/CMakeLists.txt | 34 + CMakeLists.txt | 532 +++++++++ I7000/CMakeLists.txt | 151 +++ IBM360/CMakeLists.txt | 39 + ICL1900/CMakeLists.txt | 37 + PDP10/CMakeLists.txt | 204 ++++ SEL32/CMakeLists.txt | 42 + cmake/CMake-Maintainers.md | 582 ++++++++++ cmake/FindEDITLINE.cmake | 142 +++ cmake/FindPCAP.cmake | 76 ++ cmake/FindPCRE.cmake | 102 ++ cmake/FindPCRE2.cmake | 97 ++ cmake/FindPTW.cmake | 75 ++ cmake/FindVDE.cmake | 64 ++ cmake/GitHub-release.md | 41 + cmake/__pycache__/generate.cpython-310.pyc | Bin 0 -> 5308 bytes cmake/add_simulator.cmake | 427 +++++++ cmake/build_dep_matrix.cmake | 85 ++ cmake/cmake-builder.ps1 | 584 ++++++++++ cmake/cmake-builder.sh | 426 +++++++ cmake/cpack-setup.cmake | 139 +++ cmake/dep-link.cmake | 367 ++++++ cmake/dep-locate.cmake | 361 ++++++ cmake/diff-master.ps1 | 14 + cmake/file-link-copy.cmake | 50 + cmake/fpintrin.cmake | 79 ++ cmake/generate.py | 193 ++++ cmake/git-commit-id.cmake | 89 ++ cmake/github_v141_xp.ps1 | 153 +++ .../CPackSimhCustom.cmake.in | 3 + .../installer-customizations/NSIS.template.in | 1018 +++++++++++++++++ .../NSIS/FileLinks.nsh | 198 ++++ cmake/os-features.cmake | 207 ++++ cmake/patches/SDL_ttf/fix-pkgconfig.patch | 22 + ...id-inclusions-when-HAVE_-is-set-to-0.patch | 53 + .../zlib/0002-skip-building-examples.patch | 17 + ...0003-build-static-or-shared-not-both.patch | 53 + .../zlib/0004-android-and-mingw-fixes.patch | 31 + cmake/platform-quirks.cmake | 266 +++++ cmake/pthreads-dep.cmake | 76 ++ .../basic_simulator.cpython-310.pyc | Bin 0 -> 12221 bytes .../cmake_container.cpython-310.pyc | Bin 0 -> 12586 bytes .../__pycache__/packaging.cpython-310.pyc | Bin 0 -> 7513 bytes .../parse_makefile.cpython-310.pyc | Bin 0 -> 4065 bytes .../sim_collection.cpython-310.pyc | Bin 0 -> 5598 bytes .../__pycache__/text_file.cpython-310.pyc | Bin 0 -> 8422 bytes .../simgen/__pycache__/utils.cpython-310.pyc | Bin 0 -> 416 bytes .../vax_simulators.cpython-310.pyc | Bin 0 -> 2501 bytes cmake/simgen/basic_simulator.py | 337 ++++++ cmake/simgen/cmake_container.py | 411 +++++++ cmake/simgen/packaging.py | 253 ++++ cmake/simgen/parse_makefile.py | 185 +++ cmake/simgen/sim_collection.py | 158 +++ cmake/simgen/simulators.py | 75 ++ cmake/simgen/text_file.py | 286 +++++ cmake/simgen/utils.py | 9 + cmake/simgen/vax_simulators.py | 51 + cmake/simh-packaging.cmake | 34 + cmake/simh-simulators.cmake | 48 + cmake/vcpkg-setup.cmake | 88 ++ slirp/CMakeLists.txt | 56 + 61 files changed, 9120 insertions(+) create mode 100644 B5500/CMakeLists.txt create mode 100644 CMakeLists.txt create mode 100644 I7000/CMakeLists.txt create mode 100644 IBM360/CMakeLists.txt create mode 100644 ICL1900/CMakeLists.txt create mode 100644 PDP10/CMakeLists.txt create mode 100644 SEL32/CMakeLists.txt create mode 100644 cmake/CMake-Maintainers.md create mode 100644 cmake/FindEDITLINE.cmake create mode 100644 cmake/FindPCAP.cmake create mode 100644 cmake/FindPCRE.cmake create mode 100644 cmake/FindPCRE2.cmake create mode 100644 cmake/FindPTW.cmake create mode 100644 cmake/FindVDE.cmake create mode 100644 cmake/GitHub-release.md create mode 100644 cmake/__pycache__/generate.cpython-310.pyc create mode 100644 cmake/add_simulator.cmake create mode 100644 cmake/build_dep_matrix.cmake create mode 100644 cmake/cmake-builder.ps1 create mode 100755 cmake/cmake-builder.sh create mode 100644 cmake/cpack-setup.cmake create mode 100644 cmake/dep-link.cmake create mode 100644 cmake/dep-locate.cmake create mode 100644 cmake/diff-master.ps1 create mode 100644 cmake/file-link-copy.cmake create mode 100644 cmake/fpintrin.cmake create mode 100644 cmake/generate.py create mode 100644 cmake/git-commit-id.cmake create mode 100644 cmake/github_v141_xp.ps1 create mode 100644 cmake/installer-customizations/CPackSimhCustom.cmake.in create mode 100644 cmake/installer-customizations/NSIS.template.in create mode 100644 cmake/installer-customizations/NSIS/FileLinks.nsh create mode 100644 cmake/os-features.cmake create mode 100644 cmake/patches/SDL_ttf/fix-pkgconfig.patch create mode 100644 cmake/patches/zlib/0001-Prevent-invalid-inclusions-when-HAVE_-is-set-to-0.patch create mode 100644 cmake/patches/zlib/0002-skip-building-examples.patch create mode 100644 cmake/patches/zlib/0003-build-static-or-shared-not-both.patch create mode 100644 cmake/patches/zlib/0004-android-and-mingw-fixes.patch create mode 100644 cmake/platform-quirks.cmake create mode 100644 cmake/pthreads-dep.cmake create mode 100644 cmake/simgen/__pycache__/basic_simulator.cpython-310.pyc create mode 100644 cmake/simgen/__pycache__/cmake_container.cpython-310.pyc create mode 100644 cmake/simgen/__pycache__/packaging.cpython-310.pyc create mode 100644 cmake/simgen/__pycache__/parse_makefile.cpython-310.pyc create mode 100644 cmake/simgen/__pycache__/sim_collection.cpython-310.pyc create mode 100644 cmake/simgen/__pycache__/text_file.cpython-310.pyc create mode 100644 cmake/simgen/__pycache__/utils.cpython-310.pyc create mode 100644 cmake/simgen/__pycache__/vax_simulators.cpython-310.pyc create mode 100644 cmake/simgen/basic_simulator.py create mode 100644 cmake/simgen/cmake_container.py create mode 100644 cmake/simgen/packaging.py create mode 100644 cmake/simgen/parse_makefile.py create mode 100644 cmake/simgen/sim_collection.py create mode 100644 cmake/simgen/simulators.py create mode 100644 cmake/simgen/text_file.py create mode 100644 cmake/simgen/utils.py create mode 100644 cmake/simgen/vax_simulators.py create mode 100644 cmake/simh-packaging.cmake create mode 100644 cmake/simh-simulators.cmake create mode 100644 cmake/vcpkg-setup.cmake create mode 100644 slirp/CMakeLists.txt diff --git a/B5500/CMakeLists.txt b/B5500/CMakeLists.txt new file mode 100644 index 00000000..047a5cb7 --- /dev/null +++ b/B5500/CMakeLists.txt @@ -0,0 +1,34 @@ +## B5500 simulator +## +## This is an automagically generated file. Do NOT EDIT. +## Any changes you make will be overwritten!! +## +## Make changes to the SIMH top-level makefile and then run the +## "cmake/generate.py" script to regenerate these files. +## +## cd cmake; python -m generate --help +## +## ------------------------------------------------------------ + +if (HAVE_UNITY_FRAMEWORK AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/CMakeLists.txt") + add_subdirectory(unit-tests) +endif () + +add_simulator(b5500 + SOURCES + b5500_cpu.c + b5500_io.c + b5500_sys.c + b5500_dk.c + b5500_mt.c + b5500_urec.c + b5500_dr.c + b5500_dtc.c + INCLUDES + .. + DEFINES + B5500 + FEATURE_INT64 + LABEL B5500 + PKG_FAMILY b5500_family + TEST b5500) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..a715f9a6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,532 @@ +## Note: pthreads4w requires 3.14 or better. +cmake_minimum_required(VERSION 3.14) + +if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) + message(FATAL_ERROR + "" + "!!! DO NOT BUILD CMake artifacts in the SIMH source directory !!!\n" + "" + "Create a subdirectory and build in that subdirectory, e.g.:" + "\n" + " $ mkdir cmake-build\n" + " $ cd cmake-build\n" + " $ cmake -G \"your generator here\" ..\n" + "" + "Preventing in-tree source build.") +endif () + +if (CMAKE_VERSION VERSION_LESS "3.21" AND NOT DEFINED SIMH_INSTALLER_WARNING) + message(WARNING "!!! DO NOT CREATE INSTALLERS WITH THIS VERSION OF CMAKE (${CMAKE_VERSION}) !!!" + "\n" + "Do not create a release or installers with this version of CMake. It does not have " + "the required install(RUNTIME_DEPENDENCY_SET) or install(IMPORTED_RUNTIME_ARTIFACTS) " + "functionality to collect runtime executable dependencies as part of the installation" + " packages, such as Mac OS bundles or Windows DLLs." + "\n" + "Minimum version for creating installers with CPack is 3.21." + ) + set(SIMH_INSTALLER_WARNING TRUE CACHE BOOL "Installer/CPack warning issued when CMAKE_VERSION < 3.21" FORCE) +endif () + +## SIMH Version variables: +set(SIMH_VERSION_MAJOR 4) +set(SIMH_VERSION_MINOR 1) +set(SIMH_VERSION_PATCH 0) +set(SIMH_VERSION "${SIMH_VERSION_MAJOR}.${SIMH_VERSION_MINOR}.${SIMH_VERSION_PATCH}" + CACHE PATH "Open-Simh version string.") + +# Places to look for CMake modules/includes +set(SIMH_INCLUDE_PATH_LIST + ${CMAKE_SOURCE_DIR}/cmake + ${CMAKE_SOURCE_DIR}/cmake/installer-customizations) +list(APPEND CMAKE_MODULE_PATH ${SIMH_INCLUDE_PATH_LIST}) +message(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}") + +## vcpkg sanity checking: Cannot use vcpkg and XP toolkit together. If this is +## a XP build, disable vcpkg: +set(USING_VCPKG FALSE) +if (DEFINED ENV{VCPKG_ROOT}) + if (CMAKE_GENERATOR_TOOLSET MATCHES "v[0-9][0-9][0-9]_xp") + message(FATAL_ERROR + "Configuration conflict: Cannot build XP binaries with vcpkg. Either " + "unset VCPKG_ROOT in your environment or remove the '-T' toolkit option." + "\n" + "Also remove CMakeCache.txt and recursively remove the CMakeFiles " + "subdirectory in your build folder before reconfiguring.") + endif () + + set(USING_VCPKG TRUE) + + ## Defer loading the CMAKE_TOOLCHAIN_FILE: + set(SIMH_CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake") + if(DEFINED CMAKE_TOOLCHAIN_FILE) + ## Use the user's provided toolchain file, but load it later. + message(STATUS "Deferring CMAKE_TOOLCHAIN_FILE load.") + set(SIMH_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}") + unset(CMAKE_TOOLCHAIN_FILE) + unset(CMAKE_TOOLCHAIN_FILE CACHE) + endif() + + file(TO_CMAKE_PATH "${SIMH_CMAKE_TOOLCHAIN_FILE}" SIMH_CMAKE_TOOLCHAIN_FILE) + message(STATUS "SIMH_CMAKE_TOOLCHAIN_FILE is ${SIMH_CMAKE_TOOLCHAIN_FILE}") +endif () + +## Respect MSVC_RUNTIME_LIBRARY's setting. the policy has to be set before +## project(), otherwise it'd have been put into platform-quirks. +## +## Note: See cmake\build_dep_matrix.cmake to see how this is propagated down +## into the dependency libraries. +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.15) + cmake_policy(SET CMP0091 NEW) +endif() + +project(simh VERSION "${SIMH_VERSION}" LANGUAGES C CXX) + +include(vcpkg-setup) +include(GNUInstallDirs) + +## Provide a default CMAKE_BUILD_TYPE if CMAKE_CONFIGURATION_TYPES is empty or not defined. +if (NOT CMAKE_CONFIGURATION_TYPES) + if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") + message(STATUS "CMAKE_BUILD_TYPE defaulted to ${CMAKE_BUILD_TYPE}") + else (NOT CMAKE_BUILD_TYPE) + message(STATUS "CMAKE_BUILD_TYPE is ${CMAKE_BUILD_TYPE}") + endif (NOT CMAKE_BUILD_TYPE) +endif () + +# SIMH_SYSTEM_ID: Roughly analogous to the autoconf system triple. Used (almost exclusively) +# as part of the depedencies' top-level directory name. +set(SIMH_SYSTEM_ID ${CMAKE_SYSTEM_NAME}) +string(REPLACE "." ";" version_list ${CMAKE_SYSTEM_VERSION}) +list(GET version_list 0 version_major) +string(APPEND SIMH_SYSTEM_ID "-" ${version_major}) + +if (CMAKE_C_LIBRARY_ARCHITECTURE) + string(APPEND SIMH_SYSTEM_ID -${CMAKE_C_LIBRARY_ARCHITECTURE}) +endif (CMAKE_C_LIBRARY_ARCHITECTURE) +string(APPEND SIMH_SYSTEM_ID -${CMAKE_C_COMPILER_ID}) +string(REPLACE "." ";" version_list ${CMAKE_C_COMPILER_VERSION}) +list(GET version_list 0 version_major) +list(GET version_list 1 version_minor) +if (NOT version_minor) + set(version_minor 0) +endif () +string(APPEND SIMH_SYSTEM_ID "-${version_major}.${version_minor}") +if (CMAKE_SIZEOF_VOID_P EQUAL 8) + string(APPEND SIMH_SYSTEM_ID "-64") +else () + string(APPEND SIMH_SYSTEM_ID "-32") +endif () +if (CMAKE_GENERATOR MATCHES "Visual Studio .*" AND CMAKE_GENERATOR_TOOLSET MATCHES "v[0-9][0-9][0-9]_xp") + string(APPEND SIMH_SYSTEM_ID "-XP") +endif () + +# SIMH_DEP_TOPDIR: This is the top-level directory where dependencies live. It's cached so that +# scripts (e.g., cmake-builder.ps1) can update PATH to find shared objects and DLLs. +# +# Only add to search paths if NO_DEP_BUILD is False +set(SIMH_DEP_TOPDIR + ${CMAKE_SOURCE_DIR}/cmake/dependencies/${SIMH_SYSTEM_ID} + CACHE PATH "Top-level directory for SIMH library dependencies") + +# SIMH_DEP_PATCHES: This is where various external package patches live. Also cached just in case +# it's needed by a script. +set(SIMH_DEP_PATCHES ${CMAKE_SOURCE_DIR}/cmake/patches + CACHE PATH "Top-level directory for external dependency patches") + +##-- Options --## +set(NO_DEP_BUILD_OPTVAL FALSE) +if (NOT DEFINED NO_DEP_BUILD) + ## For Windows, always build dependencies + if (WIN32 AND NOT DEFINED ENV{MSYSTEM} AND NOT USING_VCPKG) + message(STATUS "Setting NO_DEP_BUILD to FALSE, will BUILD missing dependencies") + set(NO_DEP_BUILD_OPTVAL FALSE) + else () + message(STATUS "Setting NO_DEP_BUILD to TRUE, will NOT BUILD missing dependencies") + set(NO_DEP_BUILD_OPTVAL TRUE) + endif () +else () + set(NO_DEP_BUILD_OPTVAL ${NO_DEP_BUILD}) + if (NO_DEP_BUILD_OPTVAL) + message(STATUS "Missing dependencies WILL NOT BE BUILT.") + else () + message(STATUS "Missing dependencies WILL BE BUILT.") + endif () +endif () + +set(MAC_UNIVERSAL_OPTVAL FALSE) +if (NOT DEFINED MAC_UNIVERSAL) + if (APPLE) + message("macOS universal binaries WILL NOT BE BUILT") + endif () +else () + set(MAC_UNIVERSAL_OPTVAL ${MAC_UNIVERSAL}) + if (MAC_UNIVERSAL_OPTVAL) + message(STATUS "macOS unversal binaries WILL BE BUILT.") + else () + message(STATUS "macOS unversal binaries NOT WILL BE BUILT.") + endif () +endif () + +option(NO_DEP_BUILD + "Enable (=1)/disable (=0) Dependency library builds (def: enabled)" + ${NO_DEP_BUILD_OPTVAL}) +option(BUILD_SHARED_DEPS + "Enable (=1)/disable (=0) building dependencies as shared libraries/DLLs (def: disabled)" + FALSE) +option(WITH_ASYNC + "Enable (=1)/disable (=0) Asynchronous I/O and threading." + TRUE) +option(WITH_REGEX + "Enable (=1)/disable (=0) PCRE/PCRE2 regular expression support (def: enabled)" + TRUE) +option(PREFER_PCRE + "Prefer (=1)/ignore (=0) Prefer PCRE over PCRE2 (def: ignore)" + TRUE) +option(WITH_NETWORK + "Enable (=1)/disable (=0) simulator networking support. (def: enabled)" + TRUE) +option(WITH_PCAP + "Enable (=1)/disable (=0) libpcap (packet capture) support. (def: enabled)" + TRUE) +option(WITH_SLIRP + "Enable (=1)/disable (=0) SLIRP network support. (def: enabled)" + TRUE) +option(WITH_VDE + "Enable (=1)/disable (=0) VDE2/VDE4 network support. (def: enabled)" + TRUE) +option(WITH_TAP + "Enable (=1)/disable (=0) TAP/TUN device network support. (def: enabled)" + TRUE) +option(WITH_VIDEO + "Enable (=1)/disable (=0) simulator display and graphics support (def: enabled)" + TRUE) +option(PANDA_LIGHTS + "Enable (=1)/disable (=0) KA-10/KI-11 simulator's Panda display. (def: disabled)" + FALSE) +option(DONT_USE_ROMS + "Enable (=1)/disable (=0) building support ROMs. (def: disabled)" + FALSE) +option(ENABLE_CPPCHECK + "Enable (=1)/disable (=0) 'cppcheck' static code analysis. (def: disabled.)" + FALSE) +option(WINAPI_DEPRECATION + "Show (=1)/mute (=0) Various WinAPI deprecation warning (def: mute.)" + FALSE) +option(WARNINGS_FATAL + "Compile-time warnings are errors (e.g., \"-Werror\" on GCC)" + FALSE) +option(RELEASE_LTO + "Use Link Time Optimization (LTO) in Release builds." + FALSE) +option(DEBUG_WALL + "Turn on maximal compiler warnings in Debug builds (e.g., \"-Wall\" or \"/W4\")" + FALSE) +option(SIMH_PACKAGE_SUFFIX + "The packaging suffix for CPack artifacts, e.g. simh-SIMH_VERSION-SIMH_PACKAGE_SUFFIX." + "") +option(MAC_UNIVERSAL + "macOS universal binary flag: TRUE -> build universal binaries, FALSE -> don't." + ${MAC_UNIVERSAL_OPTVAL}) + +# Places where CMake should look for dependent package configuration fragments and artifacts: +set(SIMH_PREFIX_PATH_LIST) +if (NOT (USING_VCPKG OR NO_DEP_BUILD)) + list(APPEND CMAKE_INCLUDE_PATH ${SIMH_DEP_TOPDIR}) + list(APPEND SIMH_PREFIX_PATH_LIST ${SIMH_DEP_TOPDIR}) + list(APPEND CMAKE_PREFIX_PATH ${SIMH_PREFIX_PATH_LIST}) +endif () + +## libpcap, if not found, will put its headers in $CMAKE_BINARY_DIR/include. +## Make sure we can find them. +list(APPEND CMAKE_INCLUDE_PATH "${CMAKE_BINARY_DIR}/include") + +## Additional command line arguments for dependencies. Need this because Powershell will report +## an error if anything is sent to stderr and $ErrorDefaultAction is set to "Stop". +set(DEP_CMAKE_ARGS "-Wno-dev" "--no-warn-unused-cli") + +## build-stage directory hierarchy for dependency installs: +if (NOT (USING_VCPKG OR NO_DEP_BUILD) AND NOT EXISTS ${SIMH_DEP_TOPDIR}) + message(STATUS "Creating dependency library directory hierarchy") + execute_process( + COMMAND ${CMAKE_COMMAND} -E make_directory ${SIMH_DEP_TOPDIR} ${SIMH_DEP_TOPDIR}/include ${SIMH_DEP_TOPDIR}/lib + ${SIMH_DEP_TOPDIR}/bin + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) +endif () + +## Default install location is ${CMAKE_SOURCE_DIR}/SIMH-install if not otherwise set +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/SIMH-install" CACHE PATH "${CMAKE_SOURCE_DIR}/SIMH-install default install prefix" FORCE) +endif() + +## The default runtime output directory is the BIN subdirectory in the source tree's top +set(SIMH_LEGACY_INSTALL "${CMAKE_SOURCE_DIR}/BIN") +if (WIN32) + string(APPEND SIMH_LEGACY_INSTALL "/Win32") +endif() +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${SIMH_LEGACY_INSTALL}) + +## Source directory is always on the global include path. +include_directories(${CMAKE_SOURCE_DIR}) + +if (NOT USING_VCPKG AND NOT NO_DEP_BUILD) + # Make sure we can include and link from the dependency directory + list(APPEND CMAKE_LIBRARY_PATH ${SIMH_DEP_TOPDIR}/lib) + link_directories(${SIMH_DEP_TOPDIR}/lib) + list(APPEND CMAKE_INCLUDE_PATH ${SIMH_DEP_TOPDIR}/include) + include_directories(${SIMH_DEP_TOPDIR}/include) +endif () + +## CMake policy tweaks + +if (CMAKE_VERSION GREATER_EQUAL 3.24) + ## Until I figure out a way to add DOWNLOAD_EXTRACT_TIMESTAMP to the call to + ## ExternalProject_Add cleanly.. + cmake_policy(SET CMP0135 NEW) +endif() + +## "Standard" includes +include(CheckCSourceCompiles) +include(CheckIncludeFile) +include(CheckSymbolExists) +include(CheckTypeSize) +include(CheckCCompilerFlag) +include(FindPackageHandleStandardArgs) + +## Deal with platform quirkiness +include(platform-quirks) + +# Find packages, arrange for dependency download/compile/install: +# +# SIMH_BUILD_DEPS is the list of the dependecies' names, for pretty-printing. +# SIMH_DEP_TARGETS is the list of dependency targets' names that we'll actually build. + +set(SIMH_BUILD_DEPS) +set(SIMH_DEP_TARGETS) + +set(THREADING_PKG_STATUS "unknown") +set(ZLIB_PKG_STATUS "unknown") +set(PCRE_PKG_STATUS "unknown") +set(VIDEO_PKG_STATUS) +set(NETWORK_PKG_STATUS) + +# if (USING_VCPKG) +# ## Sanity checking output: Ensure that vcpkg picked up the correct triplet +# message(STATUS "VCPKG sanity check:\n" +# " .. VCPKG target triplet is ${VCPKG_TARGET_TRIPLET}\n" +# " .. VCPKG_CRT_LINKAGE is ${VCPKG_CRT_LINKAGE}" +# ## " .. CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}\n" +# ## " .. CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH} +# ) +# endif () + +# SIMH local packages: +include(build_dep_matrix) +include(os-features) +include(dep-locate) +include(dep-link) + +if (VIDEO_PKG_STATUS) + string(REPLACE ";" ", " VIDEO_PKG_STATUS "${VIDEO_PKG_STATUS}") +else (VIDEO_PKG_STATUS) + set(VIDEO_PKG_STATUS "unknown") +endif (VIDEO_PKG_STATUS) + +if (NETWORK_PKG_STATUS) + string(REPLACE ";" ", " NETWORK_PKG_STATUS "${NETWORK_PKG_STATUS}") +else (NETWORK_PKG_STATUS) + set(NETWORK_PKG_STATUS "unknown") +endif (NETWORK_PKG_STATUS) + +set(CPPCHECK_STATUS "disabled.") + +if (ENABLE_CPPCHECK) + find_program(cppcheck_cmd NAMES cppcheck) + if (cppcheck_cmd) + list(APPEND cppcheck_cmd + "--language=c" + "--enable=warning,style,performance,portability,information,missingInclude" + "--suppress=missingIncludeSystem" + "--inline-suppr" + "--std=c99" + "--force") + set(CPPCHECK_STATUS "found and enabled.") + if (WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND cppcheck_cmd + "--platform=win64") + set(CPPCHECK_STATUS "found, Win64 platform.") + else () + list(APPEND cppcheck_cmd + "--platform=win32A") + set(CPPCHECK_STATUS "found, Win32 ASCII platform.") + endif () + endif () + else (cppcheck_cmd) + set(CPPCHECK_STATUS "'cppcheck' not installed.") + endif () +endif () + +set(_feature_text "Libraries and features:\n") +string(APPEND _feature_text "\n * Build with video/graphics support. ${BUILD_WITH_VIDEO}") +string(APPEND _feature_text "\n * Build with networking support .... ${BUILD_WITH_NETWORK}") +string(APPEND _feature_text "\n * Build internal ROMS .............. ") +if (DONT_SET_ROMS) + string(APPEND _feature_text "No") +else () + string(APPEND _feature_text "Yes") +endif () +string(APPEND _feature_text "\n * Thread support ................... ${THREADING_PKG_STATUS}") +string(APPEND _feature_text "\n * zlib ............................. ${ZLIB_PKG_STATUS}") +string(APPEND _feature_text "\n * Perl-Compatible RegExps........... ${PCRE_PKG_STATUS}") +string(APPEND _feature_text "\n * PNG, Freetype, SDL2, SDL2_ttf .... ${VIDEO_PKG_STATUS}") +string(APPEND _feature_text "\n * Network support .................. ${NETWORK_PKG_STATUS}") + +get_target_property(OS_FEATURE_DEFS os_features INTERFACE_COMPILE_DEFINITIONS) +list(LENGTH OS_FEATURE_DEFS len_os_features) +string(APPEND _feature_text "\n * OS Feature definitions") +if (OS_FEATURE_DEFS) + string(APPEND _feature_text ":") + foreach (feature ${OS_FEATURE_DEFS}) + string(APPEND _feature_text "\n .. ${feature}") + endforeach() +else () + string(APPEND _feature_text " ........... None defined.") +endif () + +get_target_property(OS_FEATURE_LIBS os_features INTERFACE_LINK_LIBRARIES) +list(LENGTH OS_FEATURE_LIBS len_os_features) +string(APPEND _feature_text "\n * OS Feature libraries") +if (OS_FEATURE_LIBS) + string(APPEND _feature_text ":") + foreach (feature ${OS_FEATURE_LIBS}) + string(APPEND _feature_text "\n .. ${feature}") + endforeach () +else () + string(APPEND _feature_text " ............. None required.") +endif () + +string(APPEND _feature_text "\n * 'cppcheck' ....................... ${CPPCHECK_STATUS}") +string(APPEND _feature_text "\n") + +message(STATUS ${_feature_text}) +unset(_feature_text) + +unset(ROM_STATUS) + +if (NO_DEP_BUILD AND SIMH_BUILD_DEPS) + ## Don't build dependencies. Just wail about them. + message("") + message("Missing SIMH dependencies:") + foreach (dep ${SIMH_BUILD_DEPS}) + message(STATUS " ${dep}") + endforeach() + message("") + message("Please install the above dependencies via your platform package management or") + message("software installation system and reconfigure.") + message("") + message("Also see the .travis/deps.h file for Brew and apt packages installed during") + message("github.com workflow actions.") + message(FATAL_ERROR "Missing dependencies, cannot continue.") + + ## TODO: Assume that these dependencies are optional? +endif () + +if (NOT DEFINED DO_DEPENDENCY_BUILD OR SIMH_BUILD_DEPS) + if (DEFINED DO_DEPENDENCY_BUILD AND NOT DO_DEPENDENCY_BUILD AND SIMH_BUILD_DEPS) + message(FATAL_ERROR "Dependency libraries did not build successfully!!??") + endif() + + if (SIMH_BUILD_DEPS) + message(STATUS "Building dependency libraries as a superbuild") + set(DO_DEPENDENCY_BUILD ON CACHE BOOL "Superbuild flag" FORCE) + else () + set(DO_DEPENDENCY_BUILD OFF CACHE BOOL "Superbuild flag" FORCE) + endif () +else () + set(DO_DEPENDENCY_BUILD ${DO_DEPENDENCY_BUILD} CACHE BOOL "Superbuild flag" FORCE) +endif () + +if (NOT DO_DEPENDENCY_BUILD) + include (add_simulator) + if (WITH_SLIRP) + add_subdirectory(slirp) + endif (WITH_SLIRP) + +## Don't delete yet ## set(Python_ADDITIONAL_VERSIONS 3) +## Don't delete yet ## include(FindPythonInterp) +## Don't delete yet ## if (PYTHONINTERP_FOUND AND PYTHON_VERSION_MAJOR GREATER_EQUAL 3) +## Don't delete yet ## add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/cmake/simh-simulators.cmake +## Don't delete yet ## COMMAND ${PYTHON_EXECUTABLE} "-m" generate "--srcdir" "${CMAKE_SOURCE_DIR}" +## Don't delete yet ## MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/makefile +## Don't delete yet ## COMMENT "Updating cmake/simh-simulators.cmake" +## Don't delete yet ## WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/cmake +## Don't delete yet ## COMMAND_EXPAND_LISTS) +## Don't delete yet ## message(STATUS "Added makefile update rule.") +## Don't delete yet ## endif (PYTHONINTERP_FOUND AND PYTHON_VERSION_MAJOR GREATER_EQUAL 3) +## Don't delete yet ## +## Don't delete yet ## if (${CMAKE_SOURCE_DIR}/makefile IS_NEWER_THAN ${CMAKE_SOURCE_DIR}/cmake/simh-simulators.cmake) +## Don't delete yet ## if (NOT PYTHONINTERP_FOUND OR PYTHON_VERSION_MAJOR LESS 3) +## Don't delete yet ## if (NOT PYTHONINTERP_FOUND) +## Don't delete yet ## message("!! Python not found") +## Don't delete yet ## elseif (PYTHON_VERSION_MAJOR LESS 3) +## Don't delete yet ## message("!! Python is not python3") +## Don't delete yet ## endif (NOT PYTHONINTERP_FOUND) +## Don't delete yet ## +## Don't delete yet ## message("!!") +## Don't delete yet ## message("!! Cannot update cmake/simh-simulators.cmake, using older version.") +## Don't delete yet ## message("!! Proceed with caution: This build might not succeed.") +## Don't delete yet ## message("!!") +## Don't delete yet ## message(STATUS "Keeping existing cmake/simh-simulators.cmake") +## Don't delete yet ## else (NOT PYTHONINTERP_FOUND OR PYTHON_VERSION_MAJOR LESS 3) +## Don't delete yet ## message(STATUS "Updating cmake/simh-simulators.cmake") +## Don't delete yet ## execute_process(COMMAND ${PYTHON_EXECUTABLE} "-m" generate "--srcdir" "${CMAKE_SOURCE_DIR}" +## Don't delete yet ## WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/cmake) +## Don't delete yet ## endif (NOT PYTHONINTERP_FOUND OR PYTHON_VERSION_MAJOR LESS 3) +## Don't delete yet ## endif () + + message(STATUS "Adding simulators") + include(simh-simulators) + + include(cpack-setup) + include(simh-packaging) +else () + message(STATUS "") + message(STATUS "Building the following dependency libraries:") + message(STATUS "") + foreach(dep ${SIMH_BUILD_DEPS}) + message(STATUS " ${dep}") + endforeach () + message(STATUS "") + + ExternalProject_Add (simh_superbuild + DEPENDS + ${SIMH_DEP_TARGETS} + SOURCE_DIR + ${CMAKE_SOURCE_DIR} + CMAKE_ARGS + -DDO_DEPENDENCY_BUILD:BOOL=OFF + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + INSTALL_COMMAND "" + BINARY_DIR + ${CMAKE_BINARY_DIR} + USES_TERMINAL_CONFIGURE TRUE + USES_TERMINAL_BUILD TRUE + ) + + ## Ensure that the next build rechecks the dependency + ## libraries that were just built and finds them. + unset(Freetype_FOUND CACHE) + unset(PCAP_FOUND CACHE) + unset(PCRE_FOUND CACHE) + unset(PCRE2_FOUND CACHE) + unset(PNG_FOUND CACHE) + unset(PTW_FOUND CACHE) + unset(SDL2_FOUND CACHE) + unset(SDL2_ttf_FOUND CACHE) + unset(ZLIB_FOUND CACHE) +endif () diff --git a/I7000/CMakeLists.txt b/I7000/CMakeLists.txt new file mode 100644 index 00000000..a4f781b6 --- /dev/null +++ b/I7000/CMakeLists.txt @@ -0,0 +1,151 @@ +## I7000 simulators +## +## This is an automagically generated file. Do NOT EDIT. +## Any changes you make will be overwritten!! +## +## Make changes to the SIMH top-level makefile and then run the +## "cmake/generate.py" script to regenerate these files. +## +## cd cmake; python -m generate --help +## +## ------------------------------------------------------------ + +if (HAVE_UNITY_FRAMEWORK AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/CMakeLists.txt") + add_subdirectory(unit-tests) +endif () + +add_simulator(i701 + SOURCES + ${I7000D}/i701_cpu.c + ${I7000D}/i701_sys.c + ${I7000D}/i701_chan.c + ${I7000D}/i7090_cdr.c + ${I7000D}/i7090_cdp.c + ${I7000D}/i7090_lpr.c + ${I7000D}/i7000_mt.c + ${I7000D}/i7090_drum.c + ${I7000D}/i7000_chan.c + INCLUDES + ${I7000D} + DEFINES + I701 + FEATURE_INT64 + LABEL I7000 + PKG_FAMILY ibm_family + TEST i701) + +add_simulator(i7010 + SOURCES + ${I7000D}/i7010_cpu.c + ${I7000D}/i7010_sys.c + ${I7000D}/i7010_chan.c + ${I7000D}/i7000_cdp.c + ${I7000D}/i7000_cdr.c + ${I7000D}/i7000_con.c + ${I7000D}/i7000_chan.c + ${I7000D}/i7000_lpr.c + ${I7000D}/i7000_mt.c + ${I7000D}/i7000_chron.c + ${I7000D}/i7000_dsk.c + ${I7000D}/i7000_com.c + ${I7000D}/i7000_ht.c + INCLUDES + ${CMAKE_CURRENT_SOURCE_DIR} + DEFINES + I7010 + LABEL I7000 + PKG_FAMILY ibm_family + TEST i7010) + +add_simulator(i704 + SOURCES + ${I7000D}/i7090_cpu.c + ${I7000D}/i7090_sys.c + ${I7000D}/i7090_chan.c + ${I7000D}/i7090_cdr.c + ${I7000D}/i7090_cdp.c + ${I7000D}/i7090_lpr.c + ${I7000D}/i7000_mt.c + ${I7000D}/i7090_drum.c + ${I7000D}/i7000_chan.c + INCLUDES + ${I7000D} + DEFINES + I704 + FEATURE_INT64 + LABEL I7000 + PKG_FAMILY ibm_family + TEST i704) + +add_simulator(i7070 + SOURCES + ${I7000D}/i7070_cpu.c + ${I7000D}/i7070_sys.c + ${I7000D}/i7070_chan.c + ${I7000D}/i7000_cdp.c + ${I7000D}/i7000_cdr.c + ${I7000D}/i7000_con.c + ${I7000D}/i7000_chan.c + ${I7000D}/i7000_lpr.c + ${I7000D}/i7000_mt.c + ${I7000D}/i7000_chron.c + ${I7000D}/i7000_dsk.c + ${I7000D}/i7000_com.c + ${I7000D}/i7000_ht.c + INCLUDES + ${I7000D} + DEFINES + I7070 + FEATURE_INT64 + LABEL I7000 + PKG_FAMILY ibm_family + TEST i7070) + +add_simulator(i7080 + SOURCES + ${I7000D}/i7080_cpu.c + ${I7000D}/i7080_sys.c + ${I7000D}/i7080_chan.c + ${I7000D}/i7080_drum.c + ${I7000D}/i7000_cdp.c + ${I7000D}/i7000_cdr.c + ${I7000D}/i7000_con.c + ${I7000D}/i7000_chan.c + ${I7000D}/i7000_lpr.c + ${I7000D}/i7000_mt.c + ${I7000D}/i7000_chron.c + ${I7000D}/i7000_dsk.c + ${I7000D}/i7000_com.c + ${I7000D}/i7000_ht.c + INCLUDES + ${I7000D} + DEFINES + I7080 + LABEL I7000 + PKG_FAMILY ibm_family + TEST i7080) + +add_simulator(i7090 + SOURCES + i7090_cpu.c + i7090_sys.c + i7090_chan.c + i7090_cdr.c + i7090_cdp.c + i7090_lpr.c + i7000_chan.c + i7000_mt.c + i7090_drum.c + i7090_hdrum.c + i7000_chron.c + i7000_dsk.c + i7000_com.c + i7000_ht.c + INCLUDES + ${CMAKE_CURRENT_SOURCE_DIR} + DEFINES + I7090 + FEATURE_INT64 + LABEL I7000 + PKG_FAMILY ibm_family + TEST i7090) diff --git a/IBM360/CMakeLists.txt b/IBM360/CMakeLists.txt new file mode 100644 index 00000000..ec084621 --- /dev/null +++ b/IBM360/CMakeLists.txt @@ -0,0 +1,39 @@ +## IBM360 simulator +## +## This is an automagically generated file. Do NOT EDIT. +## Any changes you make will be overwritten!! +## +## Make changes to the SIMH top-level makefile and then run the +## "cmake/generate.py" script to regenerate these files. +## +## cd cmake; python -m generate --help +## +## ------------------------------------------------------------ + +if (HAVE_UNITY_FRAMEWORK AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/CMakeLists.txt") + add_subdirectory(unit-tests) +endif () + +add_simulator(ibm360 + SOURCES + ibm360_cpu.c + ibm360_sys.c + ibm360_con.c + ibm360_chan.c + ibm360_cdr.c + ibm360_cdp.c + ibm360_mt.c + ibm360_lpr.c + ibm360_dasd.c + ibm360_com.c + ibm360_scom.c + ibm360_scon.c + ibm360_vma.c + INCLUDES + ${CMAKE_CURRENT_SOURCE_DIR} + DEFINES + IBM360 + FEATURE_INT64 + LABEL IBM360 + PKG_FAMILY ibm_family + TEST ibm360) diff --git a/ICL1900/CMakeLists.txt b/ICL1900/CMakeLists.txt new file mode 100644 index 00000000..f84f7354 --- /dev/null +++ b/ICL1900/CMakeLists.txt @@ -0,0 +1,37 @@ +## ICL1900 simulator +## +## This is an automagically generated file. Do NOT EDIT. +## Any changes you make will be overwritten!! +## +## Make changes to the SIMH top-level makefile and then run the +## "cmake/generate.py" script to regenerate these files. +## +## cd cmake; python -m generate --help +## +## ------------------------------------------------------------ + +if (HAVE_UNITY_FRAMEWORK AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/CMakeLists.txt") + add_subdirectory(unit-tests) +endif () + +add_simulator(icl1900 + SOURCES + icl1900_cpu.c + icl1900_sys.c + icl1900_stdio.c + icl1900_cty.c + icl1900_tr.c + icl1900_tp.c + icl1900_cr.c + icl1900_cp.c + icl1900_lp.c + icl1900_mta.c + icl1900_mt.c + icl1900_eds8.c + INCLUDES + ${CMAKE_CURRENT_SOURCE_DIR} + DEFINES + ICL1900 + LABEL ICL1900 + PKG_FAMILY icl_family + TEST icl1900) diff --git a/PDP10/CMakeLists.txt b/PDP10/CMakeLists.txt new file mode 100644 index 00000000..f755cf63 --- /dev/null +++ b/PDP10/CMakeLists.txt @@ -0,0 +1,204 @@ +## PDP10 simulators +## +## This is an automagically generated file. Do NOT EDIT. +## Any changes you make will be overwritten!! +## +## Make changes to the SIMH top-level makefile and then run the +## "cmake/generate.py" script to regenerate these files. +## +## cd cmake; python -m generate --help +## +## ------------------------------------------------------------ + +if (HAVE_UNITY_FRAMEWORK AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/CMakeLists.txt") + add_subdirectory(unit-tests) +endif () + +add_simulator(pdp10-ka + SOURCES + ${KA10D}/kx10_cpu.c + ${KA10D}/kx10_sys.c + ${KA10D}/kx10_df.c + ${KA10D}/kx10_dp.c + ${KA10D}/kx10_mt.c + ${KA10D}/kx10_cty.c + ${KA10D}/kx10_lp.c + ${KA10D}/kx10_pt.c + ${KA10D}/kx10_dc.c + ${KA10D}/kx10_rp.c + ${KA10D}/kx10_rc.c + ${KA10D}/kx10_dt.c + ${KA10D}/kx10_dk.c + ${KA10D}/kx10_cr.c + ${KA10D}/kx10_cp.c + ${KA10D}/kx10_tu.c + ${KA10D}/kx10_rs.c + ${KA10D}/ka10_pd.c + ${KA10D}/kx10_rh.c + ${KA10D}/kx10_imp.c + ${KA10D}/ka10_tk10.c + ${KA10D}/ka10_mty.c + ${KA10D}/ka10_imx.c + ${KA10D}/ka10_ch10.c + ${KA10D}/ka10_stk.c + ${KA10D}/ka10_ten11.c + ${KA10D}/ka10_auxcpu.c + ${KA10D}/ka10_pmp.c + ${KA10D}/ka10_dkb.c + ${KA10D}/pdp6_dct.c + ${KA10D}/pdp6_dtc.c + ${KA10D}/pdp6_mtc.c + ${KA10D}/pdp6_dsk.c + ${KA10D}/pdp6_dcs.c + ${KA10D}/ka10_dpk.c + ${KA10D}/kx10_dpy.c + ka10_ai.c + ${KA10D}/ka10_iii.c + ${KA10D}/kx10_disk.c + ka10_pclk.c + ka10_tv.c + ${KA10D}/kx10_ddc.c + ka10_dd.c + ${DISPLAY340} + INCLUDES + ${KA10D} + DEFINES + KA=1 + FEATURE_INT64 + FEATURE_VIDEO + FEATURE_DISPLAY + LABEL PDP10 + PKG_FAMILY pdp10_family + TEST ka10) + +if (PANDA_LIGHTS) + target_sources(pdp10-ka PUBLIC ${PDP10D}/ka10_lights.c) + target_compile_definitions(pdp10-ka PUBLIC PANDA_LIGHTS) + target_link_libraries(pdp10-ka PUBLIC usb-1.0) +endif (PANDA_LIGHTS) + +add_simulator(pdp10-ki + SOURCES + ${KI10D}/kx10_cpu.c + ${KI10D}/kx10_sys.c + ${KI10D}/kx10_df.c + ${KI10D}/kx10_dp.c + ${KI10D}/kx10_mt.c + ${KI10D}/kx10_cty.c + ${KI10D}/kx10_lp.c + ${KI10D}/kx10_pt.c + ${KI10D}/kx10_dc.c + ${KI10D}/kx10_rh.c + ${KI10D}/kx10_rp.c + ${KI10D}/kx10_rc.c + ${KI10D}/kx10_dt.c + ${KI10D}/kx10_dk.c + ${KI10D}/kx10_cr.c + ${KI10D}/kx10_cp.c + ${KI10D}/kx10_tu.c + ${KI10D}/kx10_rs.c + ${KI10D}/kx10_imp.c + ${KI10D}/kx10_dpy.c + ${KI10D}/kx10_disk.c + ${KI10D}/kx10_ddc.c + ${KI10D}/kx10_tym.c + ${DISPLAY340} + INCLUDES + ${KI10D} + DEFINES + KI=1 + FEATURE_INT64 + FEATURE_VIDEO + FEATURE_DISPLAY + LABEL PDP10 + PKG_FAMILY pdp10_family + TEST ki10) + +add_simulator(pdp10-kl + SOURCES + ${KL10D}/kx10_cpu.c + ${KL10D}/kx10_sys.c + ${KL10D}/kx10_df.c + ${KA10D}/kx10_dp.c + ${KA10D}/kx10_mt.c + ${KA10D}/kx10_lp.c + ${KA10D}/kx10_pt.c + ${KA10D}/kx10_dc.c + ${KL10D}/kx10_rh.c + ${KA10D}/kx10_dt.c + ${KA10D}/kx10_cr.c + ${KA10D}/kx10_cp.c + ${KL10D}/kx10_rp.c + ${KL10D}/kx10_tu.c + ${KL10D}/kx10_rs.c + ${KL10D}/kx10_imp.c + ${KL10D}/kl10_fe.c + ${KL10D}/ka10_pd.c + ${KL10D}/ka10_ch10.c + ${KL10D}/kl10_nia.c + ${KL10D}/kx10_disk.c + ${KL10D}/kl10_dn.c + INCLUDES + ${KL10D} + DEFINES + KL=1 + FEATURE_INT64 + LABEL PDP10 + PKG_FAMILY pdp10_family + TEST kl10) + +add_simulator(pdp10-ks + SOURCES + ${KS10D}/kx10_cpu.c + ${KS10D}/kx10_sys.c + ${KS10D}/kx10_disk.c + ${KS10D}/ks10_cty.c + ${KS10D}/ks10_uba.c + ${KS10D}/kx10_rh.c + ${KS10D}/kx10_rp.c + ${KS10D}/kx10_tu.c + ${KS10D}/ks10_dz.c + ${KS10D}/ks10_tcu.c + ${KS10D}/ks10_lp.c + ${KS10D}/ks10_ch11.c + ${KS10D}/ks10_kmc.c + ${KS10D}/ks10_dup.c + ${KS10D}/kx10_imp.c + INCLUDES + ${KS10D} + DEFINES + KS=1 + FEATURE_INT64 + LABEL PDP10 + PKG_FAMILY pdp10_family + TEST ks10) + +add_simulator(pdp6 + SOURCES + ${PDP6D}/kx10_cpu.c + ${PDP6D}/kx10_sys.c + ${PDP6D}/kx10_cty.c + ${PDP6D}/kx10_lp.c + ${PDP6D}/kx10_pt.c + ${PDP6D}/kx10_cr.c + ${PDP6D}/kx10_cp.c + ${PDP6D}/pdp6_dct.c + ${PDP6D}/pdp6_dtc.c + ${PDP6D}/pdp6_mtc.c + ${PDP6D}/pdp6_dsk.c + ${PDP6D}/pdp6_dcs.c + ${PDP6D}/kx10_dpy.c + ${PDP6D}/pdp6_slave.c + ${PDP6D}/pdp6_ge.c + ${DISPLAY340} + INCLUDES + ${PDP6D} + DEFINES + PDP6=1 + FEATURE_INT64 + FEATURE_VIDEO + FEATURE_DISPLAY + USES_AIO + LABEL PDP10 + PKG_FAMILY decpdp_family + TEST pdp6) diff --git a/SEL32/CMakeLists.txt b/SEL32/CMakeLists.txt new file mode 100644 index 00000000..41b72dec --- /dev/null +++ b/SEL32/CMakeLists.txt @@ -0,0 +1,42 @@ +## SEL32 simulator +## +## This is an automagically generated file. Do NOT EDIT. +## Any changes you make will be overwritten!! +## +## Make changes to the SIMH top-level makefile and then run the +## "cmake/generate.py" script to regenerate these files. +## +## cd cmake; python -m generate --help +## +## ------------------------------------------------------------ + +if (HAVE_UNITY_FRAMEWORK AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/CMakeLists.txt") + add_subdirectory(unit-tests) +endif () + +add_simulator(sel32 + SOURCES + sel32_cpu.c + sel32_sys.c + sel32_chan.c + sel32_iop.c + sel32_com.c + sel32_con.c + sel32_clk.c + sel32_mt.c + sel32_lpr.c + sel32_scfi.c + sel32_fltpt.c + sel32_disk.c + sel32_hsdp.c + sel32_mfp.c + sel32_scsi.c + sel32_ec.c + sel32_ipu.c + INCLUDES + ${CMAKE_CURRENT_SOURCE_DIR} + DEFINES + SEL32 + LABEL SEL32 + PKG_FAMILY gould_family + TEST sel32) diff --git a/cmake/CMake-Maintainers.md b/cmake/CMake-Maintainers.md new file mode 100644 index 00000000..ce44d196 --- /dev/null +++ b/cmake/CMake-Maintainers.md @@ -0,0 +1,582 @@ + +**Table of Contents** + +- [CMake Maintainer Walk-through](#cmake-maintainer-walk-through) + - [Introduction](#introduction) + - [*CMake* Basics](#cmake-basics) + - [`CMAKE_SOURCE_DIR` and `CMAKE_BINARY_DIR`](#cmake_source_dir-and-cmake_binary_dir) + - [Top-level `CMakeLists.txt`](#top-level-cmakeliststxt) + - [Build Configurations](#build-configurations) + - [Code Roadmap](#code-roadmap) + - [`${CMAKE_SOURCE_DIR}/CMakeLists.txt`](#cmake_source_dircmakeliststxt) + - [The `cmake` sub-directory](#the-cmake-sub-directory) + - [`add_simulator.cmake`](#add_simulatorcmake) + - [`find_package` support](#find_package-support) + - [`platform-quirks.cmake`: Platform-specific settings/tweaks](#platform-quirkscmake-platform-specific-settingstweaks) + - [`vcpkg.cmake`: vcpkg package installer/maintainer](#vcpkgcmake-vcpkg-package-installermaintainer) + - [`dep-locate.cmake`, `dep-link.cmake`: Dependency libraries](#dep-locatecmake-dep-linkcmake-dependency-libraries) + - [`simh-simulators.cmake`](#simh-simulatorscmake) + - [`generate.py`: Automagic `makefile` → CMake infrastructure](#generatepy-automagic-makefile--cmake-infrastructure) + - [CPack configuration](#cpack-configuration) + + + +# CMake Maintainer Walk-through + +## Introduction + +This code walk-through is primarily intended for maintainers and developers interested in the +[CMake][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`](#vcpkgcmake-vcpkg-package-installermaintainer). + +- Set [GNUInstallDirs][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](#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](#platform-quirkscmake-platform-specific-settingstweaks), 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][libsdl2], 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][external_project]). 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][nullsoft], 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][cmake_readme]. + +`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][unity_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`][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][cmake_modules] 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.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.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][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][mingw-w64], Linux and macOS. The GitHub CI/CD pipeline does not +use _vcpkg_ for either the Linux or macOS builds. [MinGW-w64][mingw-w64] is a SIMH CMake-supported +platform, but is not normally targeted in a CI/CD pipeline. Also, [MinGW-w64][mingw-w64] uses the +[Pacman][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`, `dep-link.cmake`: Dependency libraries + +`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: + +``` shell +$ 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*][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 ` 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. + + +[cmake]: https://cmake.org +[cmake_modules]: https://gitlab.kitware.com/cmake/cmake/-/tree/master/Modules +[cmake_readme]: ../README-CMake.md +[cpack]: https://cmake.org/cmake/help/latest/module/CPack.html +[cpack_generators]: https://cmake.org/cmake/help/latest/manual/cpack-generators.7.html#manual:cpack-generators(7) +[external_project]: https://cmake.org/cmake/help/latest/module/ExternalProject.html +[find_package]: https://cmake.org/cmake/help/latest/command/find_package.html +[gnuinstalldirs]: https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html +[libsdl2]: https://github.com/libsdl-org/SDL +[mingw-w64]: https://www.mingw-w64.org/ +[nullsoft]: https://sourceforge.net/projects/nsis/ +[pacman]: https://archlinux.org/pacman/ +[unity_framework]: http://www.throwtheswitch.org/unity +[vcpkg]: https://vcpkg.io +[vde_network]: https://wiki.virtualsquare.org/#!index.md + + diff --git a/cmake/FindEDITLINE.cmake b/cmake/FindEDITLINE.cmake new file mode 100644 index 00000000..2ab7b5c3 --- /dev/null +++ b/cmake/FindEDITLINE.cmake @@ -0,0 +1,142 @@ +# +# This module is designed to find/handle editline library +# +# Requirements: +# - CMake >= 2.8.3 (for new version of find_package_handle_standard_args) +# +# The following variables will be defined for your use: +# - EDITLINE_INCLUDE_DIRS : editline include directory +# - EDITLINE_LIBRARIES : editline libraries +# - EDITLINE_VERSION : complete version of editline (x.y) +# - EDITLINE_MAJOR_VERSION : major version of editline +# - EDITLINE_MINOR_VERSION : minor version of editline +# +# How to use: +# 1) Copy this file in the root of your project source directory +# 2) Then, tell CMake to search this non-standard module in your project directory by adding to your CMakeLists.txt: +# set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}) +# 3) Finally call find_package(EditLine) once +# +# Here is a complete sample to build an executable: +# +# set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}) +# +# find_package(EditLine REQUIRED) # Note: name is case sensitive +# +# include_directories(${EDITLINE_INCLUDE_DIRS}) +# add_executable(myapp myapp.c) +# target_link_libraries(myapp ${EDITLINE_LIBRARIES}) +# + + +#============================================================================= +# Copyright (c) 2014, julp +# +# Distributed under the OSI-approved BSD License +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +#============================================================================= + +########## Private ########## +if(NOT DEFINED EDITLINE_PUBLIC_VAR_NS) + set(EDITLINE_PUBLIC_VAR_NS "EDITLINE") +endif(NOT DEFINED EDITLINE_PUBLIC_VAR_NS) +if(NOT DEFINED EDITLINE_PRIVATE_VAR_NS) + set(EDITLINE_PRIVATE_VAR_NS "_${EDITLINE_PUBLIC_VAR_NS}") +endif(NOT DEFINED EDITLINE_PRIVATE_VAR_NS) + +function(editline_debug _VARNAME) + if(${EDITLINE_PUBLIC_VAR_NS}_DEBUG) + if(DEFINED ${EDITLINE_PUBLIC_VAR_NS}_${_VARNAME}) + message("${EDITLINE_PUBLIC_VAR_NS}_${_VARNAME} = ${${EDITLINE_PUBLIC_VAR_NS}_${_VARNAME}}") + else(DEFINED ${EDITLINE_PUBLIC_VAR_NS}_${_VARNAME}) + message("${EDITLINE_PUBLIC_VAR_NS}_${_VARNAME} = ") + endif() + endif() +endfunction() + +# Alias all EditLine_FIND_X variables to EDITLINE_FIND_X +# Workaround for find_package: no way to force case of variable's names it creates (I don't want to change MY coding standard) +# --- +# NOTE: only prefix is considered, not full name of the variables to minimize conflicts with string(TOUPPER) for example +# EditLine_foo becomes EDITLINE_foo not EditLine_FOO as this is two different variables +set(${EDITLINE_PRIVATE_VAR_NS}_FIND_PKG_PREFIX "EditLine") +get_directory_property(${EDITLINE_PRIVATE_VAR_NS}_CURRENT_VARIABLES VARIABLES) +foreach(${EDITLINE_PRIVATE_VAR_NS}_VARNAME ${${EDITLINE_PRIVATE_VAR_NS}_CURRENT_VARIABLES}) + if(${EDITLINE_PRIVATE_VAR_NS}_VARNAME MATCHES "^${${EDITLINE_PRIVATE_VAR_NS}_FIND_PKG_PREFIX}") + string(REGEX REPLACE "^${${EDITLINE_PRIVATE_VAR_NS}_FIND_PKG_PREFIX}" "${EDITLINE_PUBLIC_VAR_NS}" ${EDITLINE_PRIVATE_VAR_NS}_NORMALIZED_VARNAME ${${EDITLINE_PRIVATE_VAR_NS}_VARNAME}) + set(${${EDITLINE_PRIVATE_VAR_NS}_NORMALIZED_VARNAME} ${${${EDITLINE_PRIVATE_VAR_NS}_VARNAME}}) + endif() +endforeach() + +########## Public ########## +find_path( + ${EDITLINE_PUBLIC_VAR_NS}_INCLUDE_DIRS + NAMES histedit.h +) + +if(${EDITLINE_PUBLIC_VAR_NS}_INCLUDE_DIRS) + + find_library( + ${EDITLINE_PUBLIC_VAR_NS}_LIBRARIES + NAMES edit + ) + + find_library( + ${EDITLINE_PUBLIC_VAR_NS}_TERMCAP + NAMES termcap + ) + +# file(READ "${${EDITLINE_PUBLIC_VAR_NS}_INCLUDE_DIRS}/histedit.h" ${EDITLINE_PRIVATE_VAR_NS}_H_CONTENT) +# string(REGEX REPLACE ".*# *define +LIBEDIT_MAJOR +([0-9]+).*" "\\1" ${EDITLINE_PUBLIC_VAR_NS}_MAJOR_VERSION ${${EDITLINE_PRIVATE_VAR_NS}_H_CONTENT}) +# string(REGEX REPLACE ".*# *define +LIBEDIT_MINOR +([0-9]+).*" "\\1" ${EDITLINE_PUBLIC_VAR_NS}_MINOR_VERSION ${${EDITLINE_PRIVATE_VAR_NS}_H_CONTENT}) +# set(${EDITLINE_PUBLIC_VAR_NS}_VERSION "${${EDITLINE_PUBLIC_VAR_NS}_MAJOR_VERSION}.${${EDITLINE_PUBLIC_VAR_NS}_MINOR_VERSION}") + + include(FindPackageHandleStandardArgs) + if(${EDITLINE_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${EDITLINE_PUBLIC_VAR_NS}_FIND_QUIETLY) + find_package_handle_standard_args( + ${EDITLINE_PUBLIC_VAR_NS} + REQUIRED_VARS ${EDITLINE_PUBLIC_VAR_NS}_LIBRARIES ${EDITLINE_PUBLIC_VAR_NS}_INCLUDE_DIRS +# VERSION_VAR ${EDITLINE_PUBLIC_VAR_NS}_VERSION + ) + else(${EDITLINE_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${EDITLINE_PUBLIC_VAR_NS}_FIND_QUIETLY) + find_package_handle_standard_args(${EDITLINE_PUBLIC_VAR_NS} "editline not found" ${EDITLINE_PUBLIC_VAR_NS}_LIBRARIES ${EDITLINE_PUBLIC_VAR_NS}_INCLUDE_DIRS) + endif() + +else() + + if(${EDITLINE_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${EDITLINE_PUBLIC_VAR_NS}_FIND_QUIETLY) + message(FATAL_ERROR "Could not find editline include directory") + endif(${EDITLINE_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${EDITLINE_PUBLIC_VAR_NS}_FIND_QUIETLY) + +endif() + +mark_as_advanced( + ${EDITLINE_PUBLIC_VAR_NS}_INCLUDE_DIRS + ${EDITLINE_PUBLIC_VAR_NS}_LIBRARIES +) + +if (${EDITLINE_PUBLIC_VAR_NS}_FOUND) + add_library(Editline::Editline UNKNOWN IMPORTED) + set_target_properties(Editline::Editline PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${${EDITLINE_PUBLIC_VAR_NS}_INCLUDE_DIRS}" + INTERFACE_COMPILE_DEFINITIONS "HAVE_EDITLINE" + INTERFACE_LINK_LIBRARIES "$<$:${${EDITLINE_PUBLIC_VAR_NS}_TERMCAP}>") + set_property(TARGET Editline::Editline APPEND PROPERTY + IMPORTED_LOCATION "${${EDITLINE_PUBLIC_VAR_NS}_LIBRARIES}") +endif () + +# IN (args) +editline_debug("FIND_REQUIRED") +editline_debug("FIND_QUIETLY") +editline_debug("FIND_VERSION") +# OUT +# Linking +editline_debug("INCLUDE_DIRS") +editline_debug("LIBRARIES") +editline_debug("TERMCAP") +# Version +# editline_debug("MAJOR_VERSION") +# editline_debug("MINOR_VERSION") +# editline_debug("VERSION") diff --git a/cmake/FindPCAP.cmake b/cmake/FindPCAP.cmake new file mode 100644 index 00000000..c3250046 --- /dev/null +++ b/cmake/FindPCAP.cmake @@ -0,0 +1,76 @@ +# Locate the PCAP library +# +# This module defines: +# +# :: +# +# PCAP_LIBRARIES, the name of the library to link against +# PCAP_INCLUDE_DIRS, where to find the headers +# PCAP_FOUND, if false, do not try to link against +# PCAP_VERSION_STRING - human-readable string containing the version of SDL_ttf +# +# Tweaks: +# 1. PCAP_PATH: A list of directories in which to search +# 2. PCAP_DIR: An environment variable to the directory where you've unpacked or installed PCAP. +# +# "scooter me fecit" + +find_path(PCAP_INCLUDE_DIR + NAMES + pcap.h + HINTS + ENV PCAP_DIR + PATHS + pcap + PCAP + ${PCAP_PATH} + ) + +# if (CMAKE_SIZEOF_VOID_P EQUAL 8) +# set(LIB_PATH_SUFFIXES lib64 x64 amd64 x86_64-linux-gnu aarch64-linux-gnu lib) +# else () +# set(LIB_PATH_SUFFIXES x86) +# endif () + +# find_library(PCAP_LIBRARY +# NAMES +# pcap pcap_static libpcap libpcap_static +# HINTS +# ENV PCAP_DIR +# PATH_SUFFIXES +# ${LIB_PATH_SUFFIXES} +# PATHS +# ${PCAP_PATH} +# ) +# ## message(STATUS "LIB_PATH_SUFFIXES ${LIB_PATH_SUFFIXES}") +# ## message(STATUS "PCAP_LIBRARY is ${PCAP_LIBRARY}") + +# if (WIN32 AND PCAP_LIBRARY) +# ## Only worry about the packet library on Windows. +# find_library(PACKET_LIBRARY +# NAMES +# packet Packet +# HINTS +# ENV PCAP_DIR +# PATH_SUFFIXES +# ${LIB_PATH_SUFFIXES} +# PATHS +# ${PCAP_PATH} +# ) +# else (WIN32 AND PCAP_LIBRARY) +# set(PACKET_LIBRARY) +# endif (WIN32 AND PCAP_LIBRARY) +# ## message(STATUS "PACKET_LIBRARY is ${PACKET_LIBRARY}") + +# set(PCAP_LIBRARIES ${PCAP_LIBRARY} ${PACKET_LIBRARY}) +set(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR}) +unset(PCAP_LIBRARY) +unset(PCAP_INCLUDE_DIR) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + PCAP + REQUIRED_VARS + ## PCAP_LIBRARIES + PCAP_INCLUDE_DIRS +) diff --git a/cmake/FindPCRE.cmake b/cmake/FindPCRE.cmake new file mode 100644 index 00000000..fa9c1a23 --- /dev/null +++ b/cmake/FindPCRE.cmake @@ -0,0 +1,102 @@ +# Locate the PCRE library +# +# This module defines: +# +# :: +# +# PCRE_LIBRARIES, the name of the library to link against +# PCRE_INCLUDE_DIRS, where to find the headers +# PCRE_FOUND, if false, do not try to link against +# +# Tweaks: +# 1. PCRE_PATH: A list of directories in which to search +# 2. PCRE_DIR: An environment variable to the directory where you've unpacked or installed PCRE. +# +# "scooter me fecit" + +function(findpcre_debug _VARNAME) + if(FINDPCRE_DEBUG) + if(DEFINED PCRE_${_VARNAME}) + message("PCRE_${_VARNAME} = ${PCRE_${_VARNAME}}") + else(DEFINED PCRE_${_VARNAME}) + message("PCRE_${_VARNAME} = ") + endif(DEFINED PCRE_${_VARNAME}) + endif() +endfunction(findpcre_debug) + +## Normal path to find the PCRE header and library: +find_path(PCRE_INCLUDE_DIR pcre.h + HINTS + ${PC_PCRE_INCLUDEDIR} + ${PC_PCRE_INCLUDE_DIRS} + ENV PCRE_DIR + # path suffixes to search inside ENV{PCRE_DIR} + PATHS ${PCRE_PATH} + PATH_SUFFIXES + pcre + PCRE + ) + +find_library(PCRE_LIBRARY_RELEASE + NAMES + pcre + libpcre + HINTS + ${PC_PCRE_LIBDIR} + ${PC_PCRE_LIBRARY_DIRS} + ENV PCRE_DIR + PATH_SUFFIXES + ${LIB_PATH_SUFFIXES} + PATHS + ${PCRE_PATH} +) + +find_library(PCRE_LIBRARY_DEBUG + NAMES + pcred + libpcred + HINTS + ENV PCRE_DIR + PATH_SUFFIXES + ${LIB_PATH_SUFFIXES} + PATHS + ${PCRE_PATH} +) + +if (PCRE_INCLUDE_DIR) + if (EXISTS "${PCRE_INCLUDE_DIR}/pcre.h") + file(STRINGS "${PCRE_INCLUDE_DIR}/pcre.h" PCRE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+PCRE_MAJOR[ \t]+[0-9]+$") + file(STRINGS "${PCRE_INCLUDE_DIR}/pcre.h" PCRE_VERSION_MINOR_LINE REGEX "^#define[ \t]+PCRE_MINOR[ \t]+[0-9]+$") + endif () + + string(REGEX REPLACE "^#define[ \t]+PCRE?_MAJOR[ \t]+([0-9]+)$" "\\1" PCRE_VERSION_MAJOR "${PCRE_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+PCRE?_MINOR[ \t]+([0-9]+)$" "\\1" PCRE_VERSION_MINOR "${PCRE_VERSION_MINOR_LINE}") + + set(PCRE_VERSION_STRING "${PCRE_VERSION_MAJOR}.${PCRE_VERSION_MINOR}") + unset(PCRE_VERSION_MAJOR_LINE) + unset(PCRE_VERSION_MINOR_LINE) + unset(PCRE_VERSION_MAJOR) + unset(PCRE_VERSION_MINOR) +endif () + +include(SelectLibraryConfigurations) +select_library_configurations(PCRE) + +set(PCRE_LIBRARIES ${PCRE_LIBRARY}) +set(PCRE_INCLUDE_DIRS ${PCRE_INCLUDE_DIR}) + +findpcre_debug(LIBRARY) +findpcre_debug(LIBRARIES) +findpcre_debug(LIBRARY_DEBUG) +findpcre_debug(LIBRARY_RELEASE) +findpcre_debug(VERSION_STRING) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + PCRE + REQUIRED_VARS + PCRE_LIBRARY + PCRE_INCLUDE_DIR + VERSION_VAR + PCRE_VERSION_STRING +) diff --git a/cmake/FindPCRE2.cmake b/cmake/FindPCRE2.cmake new file mode 100644 index 00000000..6ab092b6 --- /dev/null +++ b/cmake/FindPCRE2.cmake @@ -0,0 +1,97 @@ +# Locate the PCRE library +# +# This module defines: +# +# :: +# +# PCRE2_LIBRARIES, the name of the pcre2 library to link against +# PCRE2_INCLUDE_DIRS, where to find the pcre2 headers +# PCRE2_FOUND, if false, do not try to compile or link with pcre2 +# PCRE2_VERSION_STRING - human-readable string containing the version of pcre or pcre2 +# +# Tweaks: +# 1. PCRE_PATH: A list of directories in which to search +# 2. PCRE_DIR: An environment variable to the directory where you've unpacked or installed PCRE. +# +# "scooter me fecit" + +find_path(PCRE2_INCLUDE_DIR pcre2.h + HINTS + ENV PCRE_DIR + # path suffixes to search inside ENV{PCRE_DIR} + PATHS ${PCRE_PATH} + PATH_SUFFIXES + include/pcre + include/PCRE + include + ) + +if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(LIB_PATH_SUFFIXES lib64 x64 amd64 x86_64-linux-gnu aarch64-linux-gnu lib) +else () + set(LIB_PATH_SUFFIXES x86) +endif () + +find_library(PCRE2_LIBRARY_RELEASE + NAMES + pcre2-8 + pcre2-8-static + HINTS + ENV PCRE_DIR + PATH_SUFFIXES + ${LIB_PATH_SUFFIXES} + PATHS + ${PCRE_PATH} + ) + +find_library(PCRE2_LIBRARY_DEBUG + NAMES + pcre2-8d + pcre2-8-staticd + HINTS + ENV PCRE_DIR + PATH_SUFFIXES + ${LIB_PATH_SUFFIXES} + PATHS + ${PCRE_PATH} + ) + +if (PCRE2_INCLUDE_DIR) + if (EXISTS "${PCRE2_INCLUDE_DIR}/pcre2.h") + file(STRINGS "${PCRE2_INCLUDE_DIR}/pcre2.h" PCRE2_VERSION_MAJOR_LINE REGEX "^#define[ \t]+PCRE2_MAJOR[ \t]+[0-9]+$") + file(STRINGS "${PCRE2_INCLUDE_DIR}/pcre2.h" PCRE2_VERSION_MINOR_LINE REGEX "^#define[ \t]+PCRE2_MINOR[ \t]+[0-9]+$") + endif () + + string(REGEX REPLACE "^#define[ \t]+PCRE2?_MAJOR[ \t]+([0-9]+)$" "\\1" PCRE2_VERSION_MAJOR "${PCRE2_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+PCRE2?_MINOR[ \t]+([0-9]+)$" "\\1" PCRE2_VERSION_MINOR "${PCRE2_VERSION_MINOR_LINE}") + + set(PCRE2_VERSION_STRING "${PCRE2_VERSION_MAJOR}.${PCRE2_VERSION_MINOR}") + unset(PCRE2_VERSION_MAJOR_LINE) + unset(PCRE2_VERSION_MINOR_LINE) + unset(PCRE2_VERSION_MAJOR) + unset(PCRE2_VERSION_MINOR) +endif () + +include(SelectLibraryConfigurations) + +SELECT_LIBRARY_CONFIGURATIONS(PCRE2) + +## message("== PCRE_INCLUDE_DIR ${PCRE_INCLUDE_DIR}") +## message("== PCRE2_LIBRARY ${PCRE2_LIBRARY}") +## message("== PCRE2_LIBRARIES ${PCRE2_LIBRARIES}") +## message("== PCRE2_LIBRARY_DEBUG ${PCRE2_LIBRARY_DEBUG}") +## message("== PCRE2_LIBRARY_RELEASE ${PCRE2_LIBRARY_RELEASE}") + +set(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR}) +set(PCRE2_LIBRARIES ${PCRE2_LIBRARY}) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS( + PCRE2 + REQUIRED_VARS + PCRE2_LIBRARY + PCRE2_INCLUDE_DIR + VERSION_VAR + PCRE2_VERSION_STRING +) diff --git a/cmake/FindPTW.cmake b/cmake/FindPTW.cmake new file mode 100644 index 00000000..8581f92b --- /dev/null +++ b/cmake/FindPTW.cmake @@ -0,0 +1,75 @@ +# Locate the pthreads4w library and pthreads.h header +# +# This module defines: +# +# :: +# +# PTW_C_LIBRARY, the "pthread[GV]C3" library +# PTW_CE_LIBRARY, the "pthread[GV]CE3" library +# PTW_SE_LIBRARY, the "pthread[GV]SE3" library +# PTW_INCLUDE_DIR, where to find the headers +# PTW_FOUND, if false, do not try to link against +# +# Tweaks: +# 1. PTW_PATH: A list of directories in which to search +# 2. PTW_DIR: An environment variable to the directory where you've unpacked or installed PCRE. +# +# "scooter me fecit" + +if (WIN32) + include(SelectLibraryConfigurations) + + find_path(PTW_INCLUDE_DIR pthread.h + HINTS + ENV PTW_DIR + # path suffixes to search inside ENV{PTW_DIR} + PATH_SUFFIXES include include/pthreads4w + PATHS ${PTW_PATH} + ) + + # if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # set(LIB_PATH_SUFFIXES lib64 x64 amd64 x86_64-linux-gnu) + # else () + # set(LIB_PATH_SUFFIXES x86) + # endif () + + foreach (flavor C CE SE) + if (MSVC) + set(libflavor V${flavor}3) + elseif (MINGW) + set(libflavor G${flavor}3) + endif (MSVC) + + find_library(PTW_${flavor}_LIBRARY_RELEASE + NAMES + libpthread${libflavor} pthread${libflavor} + HINTS + ENV PTW_ DIR + PATH_SUFFIXES + ${LIB_PATH_SUFFIXES} + PATHS + ${PTW_PATH} + ) + + find_library(PTW_${flavor}_LIBRARY_DEBUG + NAMES + libpthread${libflavor}d pthread${libflavor}d + HINTS + ENV PTW_ DIR + PATH_SUFFIXES + ${LIB_PATH_SUFFIXES} + PATHS + ${PTW_PATH} + ) + + SELECT_LIBRARY_CONFIGURATIONS(PTW_${flavor}) + endforeach () + + include(FindPackageHandleStandardArgs) + + # Minimally, we want the include directory and the C library... + find_package_handle_standard_args( + PTW + REQUIRED_VARS PTW_C_LIBRARY PTW_INCLUDE_DIR + ) +endif () diff --git a/cmake/FindVDE.cmake b/cmake/FindVDE.cmake new file mode 100644 index 00000000..3ee3c295 --- /dev/null +++ b/cmake/FindVDE.cmake @@ -0,0 +1,64 @@ +## Locate the VDE2/VDE4 libvdeplug headers and library. +## +## ::: +## +## Author: B. Scott Michel +## "scooter me fecit" + +if (WITH_VDE) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(PC_VDE QUIET VDEPLUG) + + if (PC_VDE_VERSION) + set(VDEPLUG_VERSION "${PC_VDE_VERSION}") + endif (PC_VDE_VERSION) + endif () + + find_path(VDEPLUG_INCLUDE_DIR libvdeplug.h + HINTS + ${PC_VDE_INCLUDE_DIRS} + PATH_SUFFIXES + include/libvdeplug + include/vde2 + include/VDE2 + include + ) + + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(LIB_PATH_SUFFIXES lib64 x64 amd64 x86_64-linux-gnu aarch64-linux-gnu) + else () + set(LIB_PATH_SUFFIXES x86) + endif () + + find_library(VDEPLUG_LIBRARY_RELEASE + NAMES + vdeplug + HINTS + ${PC_VDE_LIBRARY_DIRS} + PATH_SUFFIXES + ${LIB_PATH_SUFFIXES} + ) + + if (VDEPLUG_INCLUDE_DIR) + ## TBD: Get version info. The header file doesn't provide a way to grep + ## for it. vde_switch will output a version number, but can't really + ## depend on the user having installed the whole VDE package. + endif () + + include(SelectLibraryConfigurations) + + select_library_configurations(VDEPLUG) + + set(VDEPLUG_LIBRARIES ${VDEPLUG_LIBRARY}) + set(VDEPLUG_INCLUDE_DIRS ${VDEPLUG_INCLUDE_DIR}) + + include(FindPackageHandleStandardArgs) + + FIND_PACKAGE_HANDLE_STANDARD_ARGS(VDE + REQUIRED + VDEPLUG_LIBRARY + VDEPLUG_INCLUDE_DIR + # VERSION_VAR VDEPLUG_VERSION_STRING + ) +endif (WITH_VDE) diff --git a/cmake/GitHub-release.md b/cmake/GitHub-release.md new file mode 100644 index 00000000..7575702b --- /dev/null +++ b/cmake/GitHub-release.md @@ -0,0 +1,41 @@ +# SIMH pre-built binaries + +Welcome to SIMH's pre-built binaries! + +- `.deb`: Debian packages for Linux. To install: + + ``` + $ sudo dpkg -i + ``` + +- `.zip`: ZIP-ed executable archive. Use your favorite or appropriate ZIP + software to unzip the archive. The `simh-/bin` subdirectory is the + location of the simulators. + +- `.exe`: Nullsoft Scriptable Install System (NSIS)-created Windows installer. + + NOTE: The executble is not code-signed. DO NOT DOUBLE CLICK ON THE EXECUTABLE + TO INSTALL. If you do, you are likely to get a Windows Defender popup box that + will prevent you from installing SIMH. Instead, use a CMD or PowerShell + command window and execute the `.exe` from the command line prompt. For + example, to install `simh-4.1.0-win32-native.exe`: + + ``` + ## PowerShell: + PS> .\simh-4.1.0-win32-native + + ## CMD: + > .\simh-4.1.0-win32-native + ``` + +- `.msi`: WiX toolkit-created Windows MSI installer. + + These MSI files are not code-signed. DO NOT DOUBLE CLICK ON THE EXECUTABLE TO + INSTALL. If you do, you are likely to get a Windows Defender popup box that + will prevent you from installing SIMH. Instead, use a CMD or PowerShell command + window to manually invoke `msiexec` to install SIMH. From either a PowerShell + or CMD command window: + + ``` + > msiexec /qf /i simh-4.1.0-win32-native.msi + ``` diff --git a/cmake/__pycache__/generate.cpython-310.pyc b/cmake/__pycache__/generate.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40057ce03e4abcd14f93e0408478b66a3e6c74af GIT binary patch literal 5308 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 M^`$ur9q4cV163QdEC2ui literal 0 HcmV?d00001 diff --git a/cmake/add_simulator.cmake b/cmake/add_simulator.cmake new file mode 100644 index 00000000..74185a51 --- /dev/null +++ b/cmake/add_simulator.cmake @@ -0,0 +1,427 @@ +## Put everything together into one nice function. + +include (CTest) + +## Regenerate the git commit ID if git exists. +find_program(GIT_COMMAND git) +if (GIT_COMMAND) + message(STATUS "Git command is ${GIT_COMMAND}") +else () + message(STATUS "Git not found -- will not update or include .git-commit-id.h") +endif () + +add_custom_target(update_sim_commit ALL + COMMAND ${CMAKE_COMMAND} + -D GIT_COMMIT_DEST=${CMAKE_SOURCE_DIR} + -P ${CMAKE_SOURCE_DIR}/cmake/git-commit-id.cmake + BYPRODUCTS + ${CMAKE_SOURCE_DIR}/.git-commit-id + ${CMAKE_SOURCE_DIR}/.git-commit-id.h + WORKING_DIRECTORY + ${CMAKE_SOURCE_DIR} +) + +## Simulator sources and library: +set(SIM_SOURCES + ${CMAKE_SOURCE_DIR}/scp.c + ${CMAKE_SOURCE_DIR}/sim_card.c + ${CMAKE_SOURCE_DIR}/sim_console.c + ${CMAKE_SOURCE_DIR}/sim_disk.c + ${CMAKE_SOURCE_DIR}/sim_ether.c + ${CMAKE_SOURCE_DIR}/sim_fio.c + ${CMAKE_SOURCE_DIR}/sim_imd.c + ${CMAKE_SOURCE_DIR}/sim_scsi.c + ${CMAKE_SOURCE_DIR}/sim_serial.c + ${CMAKE_SOURCE_DIR}/sim_sock.c + ${CMAKE_SOURCE_DIR}/sim_tape.c + ${CMAKE_SOURCE_DIR}/sim_timer.c + ${CMAKE_SOURCE_DIR}/sim_tmxr.c + ${CMAKE_SOURCE_DIR}/sim_video.c) + +set(SIM_VIDEO_SOURCES + ${CMAKE_SOURCE_DIR}/display/display.c + ${CMAKE_SOURCE_DIR}/display/sim_ws.c) + +## Build a simulator core library, with and without AIO support. The AIO variant +## has "_aio" appended to its name, e.g., "simhz64_aio" or "simhz64_video_aio". +function(build_simcore _targ) + cmake_parse_arguments(SIMH "VIDEO;INT64;ADDR64;BESM6_SDL_HACK" "" "" ${ARGN}) + + # Additional library targets that depend on simulator I/O: + add_library(${_targ} STATIC ${SIM_SOURCES}) + + set(sim_aio_lib "${_targ}_aio") + add_library(${sim_aio_lib} STATIC ${SIM_SOURCES}) + + # Components that need to be turned on while building the library, but + # don't export out to the dependencies (hence PRIVATE.) + foreach (lib IN ITEMS "${_targ}" "${sim_aio_lib}") + set_target_properties(${lib} PROPERTIES + C_STANDARD 99 + EXCLUDE_FROM_ALL True + ) + target_compile_definitions(${lib} PRIVATE USE_SIM_CARD USE_SIM_IMD) + target_compile_options(${lib} PRIVATE ${EXTRA_TARGET_CFLAGS}) + target_link_options(${lib} PRIVATE ${EXTRA_TARGET_LFLAGS}) + + # Make sure that the top-level directory is part of the libary's include path: + target_include_directories("${lib}" PUBLIC "${CMAKE_SOURCE_DIR}") + + if (SIMH_INT64) + target_compile_definitions(${lib} PUBLIC USE_INT64) + endif (SIMH_INT64) + + if (SIMH_ADDR64) + target_compile_definitions(${lib} PUBLIC USE_ADDR64) + endif (SIMH_ADDR64) + + if (SIMH_VIDEO) + if (WITH_VIDEO) + # It's the video library + target_sources(${lib} PRIVATE ${SIM_VIDEO_SOURCES}) + target_link_libraries(${lib} PUBLIC simh_video) + endif () + if (CMAKE_HOST_APPLE AND NOT SIMH_BESM6_SDL_HACK) + ## (a) The BESM6 SDL hack is temporary. If SDL_MAIN_AVAILABLE needs + ## to be defined, it belongs in the simh_video interface library. + ## (b) BESM6 doesn't use SIMH's video capabilities correctly and + ## the makefile filters out SDL_MAIN_AVAILABLE on macOS. + ## (c) This shouldn't be just an Apple platform quirk; SDL_main should + ## be used by all platforms. + target_compile_definitions("${lib}" PUBLIC SDL_MAIN_AVAILABLE) + endif () + endif () + + # Define SIM_BUILD_TOOL for the simulator' + target_compile_definitions("${lib}" PRIVATE + "SIM_BUILD_TOOL=CMake (${CMAKE_GENERATOR})" + ) + + target_link_libraries(${lib} PUBLIC + simh_network + simh_regexp + os_features + thread_lib + ) + + # Ensure that sim_rev.h picks up .git-commit-id.h if the git command is + # available. + if (GIT_COMMAND) + target_compile_definitions("${lib}" PRIVATE SIM_NEED_GIT_COMMIT_ID) + endif () + + add_dependencies(${lib} update_sim_commit) + endforeach () + + target_compile_definitions(${sim_aio_lib} PUBLIC ${AIO_FLAGS}) + + # Create target cppcheck rule, if detected. + if (ENABLE_CPPCHECK AND cppcheck_cmd) + get_property(cppcheck_includes TARGET ${_targ} PROPERTY INCLUDE_DIRECTORIES) + get_property(cppcheck_defines TARGET ${_targ} PROPERTY COMPILE_DEFINITIONS) + list(TRANSFORM cppcheck_includes PREPEND "-I") + list(TRANSFORM cppcheck_defines PREPEND "-D") + + add_custom_target("${_targ}_cppcheck" + COMMAND ${cppcheck_cmd} ${cppcheck_defines} ${cppcheck_includes} ${SIM_SOURCES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + VERBATIM + ) + + add_dependencies(cppcheck "${_targ}_cppcheck") + endif (ENABLE_CPPCHECK AND cppcheck_cmd) +endfunction(build_simcore _targ) + + +##+ +## Basic template for simh executables and unit tests. +##- +## FEATURE_INT64: Use the simhi64 library (defines USE_INT64) +## FEATURE_FULL64: Use the simhz64 library (defines USE_INT64, USE_ADDR64) +## BUILDROMS: Build the hardcoded boot rooms +## FEATURE_VIDEO: Add video support +## FEATURE_DISPLAY: Add display support +## +## BESM6_SDL_HACK: A TEMPORARY feature to work around issues with BESM6 and +## SDL and SIMH video. Because it's a day ending in "y", there's going to +## be another makefile quirk. +list(APPEND ADD_SIMULATOR_OPTIONS + "FEATURE_INT64" + "FEATURE_FULL64" + "BUILDROMS" + "FEATURE_VIDEO" + "FEATURE_DISPLAY" + "NO_INSTALL" + "BESM6_SDL_HACK" + "USES_AIO" +) + +## TEST: The test script name that will be executed by the simulator within CTest. +## LABEL: The test name label, used to group tests, e.g., "VAX" for all of the +## VAX simulator tests. If you want to run a subset of tests, add the "-L " +## argument to the ctest command line. +## PKG_FAMILY: The simulator family to which a simulator belongs. If not specificed, +## defaults to "default_family". +list(APPEND ADD_SIMULATOR_1ARG + "TEST" + "LABEL" + "PKG_FAMILY" +) + +## DEFINES: List of extra command line manifest constants ("-D" items) +## INCLUDES: List of extra include directories +## SOURCES: List of source files +list(APPEND ADD_SIMULATOR_NARG + "DEFINES" + "INCLUDES" + "SOURCES" +) + +function (simh_executable_template _targ) + cmake_parse_arguments(SIMH "${ADD_SIMULATOR_OPTIONS}" "${ADD_SIMULATOR_1ARG}" "${ADD_SIMULATOR_NARG}" ${ARGN}) + + if (NOT DEFINED SIMH_SOURCES) + message(FATAL_ERROR "${_targ}: No source files?") + endif (NOT DEFINED SIMH_SOURCES) + + if (SIMH_USES_AIO AND NOT WITH_ASYNC) + message(WARNING + "!!! ${_targ}: Asynchronous I/O not enabled, but this simulator specifies USES_AIO\n" + "!!! Some features will be crippled, notably networking.") + endif () + + add_executable("${_targ}" "${SIMH_SOURCES}") + set_target_properties(${_targ} PROPERTIES + C_STANDARD 99 + RUNTIME_OUTPUT_DIRECTORY ${SIMH_LEGACY_INSTALL} + ) + target_compile_options(${_targ} PRIVATE ${EXTRA_TARGET_CFLAGS}) + target_link_options(${_targ} PRIVATE ${EXTRA_TARGET_LFLAGS}) + + if (MINGW) + ## target_compile_options(${_targ} PUBLIC "-fms-extensions") + target_link_options(${_targ} PUBLIC "-mconsole") + elseif (MSVC) + target_link_options(${_targ} PUBLIC "/SUBSYSTEM:CONSOLE") + endif () + + if (DEFINED SIMH_DEFINES) + target_compile_definitions("${_targ}" PUBLIC "${SIMH_DEFINES}") + endif (DEFINED SIMH_DEFINES) + + # This is a quick cheat to make sure that all of the include paths are + # absolute paths. + if (DEFINED SIMH_INCLUDES) + set(_normalized_includes) + foreach (inc IN LISTS SIMH_INCLUDES) + if (NOT IS_ABSOLUTE "${inc}") + message(">> Fixing include for ${_targ}: ${inc} -> ${CMAKE_SOURCE_DIR}/${inc}") + get_filename_component(inc "${CMAKE_SOURCE_DIR}/${inc}" ABSOLUTE) + endif () + list(APPEND _normalized_includes "${inc}") + endforeach () + + target_include_directories("${_targ}" PUBLIC "${_normalized_includes}") + endif () + + if (WITH_VIDEO) + if (SIMH_FEATURE_DISPLAY) + target_compile_definitions(${_targ} PUBLIC USE_DISPLAY) + endif () + endif () + + set(SIMH_SIMLIB simhcore) + if (SIMH_FEATURE_INT64) + set(SIMH_SIMLIB simhi64) + elseif (SIMH_FEATURE_FULL64) + set(SIMH_SIMLIB simhz64) + endif () + + if (SIMH_FEATURE_VIDEO OR SIMH_FEATURE_DISPLAY) + if (NOT SIMH_BESM6_SDL_HACK) + string(APPEND SIMH_SIMLIB "_video") + else () + string(APPEND SIMH_SIMLIB "_besm6") + endif () + endif () + + # Uses AIO... + if (SIMH_USES_AIO) + set(SIMH_SIMLIB "${SIMH_SIMLIB}_aio") + endif() + + target_link_libraries("${_targ}" PUBLIC "${SIMH_SIMLIB}") +endfunction () + + +function (add_simulator _targ) + simh_executable_template(${_targ} "${ARGN}") + cmake_parse_arguments(SIMH "${ADD_SIMULATOR_OPTIONS}" "${ADD_SIMULATOR_1ARG}" "${ADD_SIMULATOR_NARG}" ${ARGN}) + + set(pkg_family "default_family") + if (SIMH_PKG_FAMILY) + set(pkg_family ${SIMH_PKG_FAMILY}) + endif () + + set(_install_opts) + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.21") + list(APPEND _install_opts RUNTIME_DEPENDENCY_SET simhRuntime) + endif () + + install(TARGETS ${_targ} + ${_install_opts} + RUNTIME + COMPONENT ${pkg_family} + ) + + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.21") + ## Collect runtime dependencies. The simhRuntime install() is invoked by cpack-setup.cmake + install(IMPORTED_RUNTIME_ARTIFACTS ${_targ} COMPONENT ${pkg_family} BUNDLE COMPONENT ${pkg_family}) + endif() + + ## Simulator-specific tests: + list(APPEND test_cmd "${_targ}" "RegisterSanityCheck") + + if (DEFINED SIMH_TEST) + string(APPEND test_fname ${CMAKE_CURRENT_SOURCE_DIR} "/tests/${SIMH_TEST}_test.ini") + IF (EXISTS "${test_fname}") + list(APPEND test_cmd "${test_fname}" "-v") + ENDIF () + endif () + + add_test(NAME "simh-${_targ}" COMMAND ${test_cmd}) + + if (SIMH_LABEL) + set_tests_properties("simh-${_targ}" PROPERTIES LABELS "simh-${SIMH_LABEL}") + endif () + + if (BUILD_SHARED_DEPS) + ## Make sure that the tests can find the DLLs/shared objects: + file(TO_NATIVE_PATH "${SIMH_DEP_TOPDIR}/bin" native_dep_bindir) + file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}" native_binary_dir) + endif () + + ## Build up test environment: + ## - Simulators that link SDL2 need to use the dummy (null) drivers on tests within + ## the CI/CD environment. While not STRICTLY necessary, it's a good idea. + list(APPEND test_add_env "SDL_VIDEODRIVER=dummy") + list(APPEND test_add_env "SDL_AUDIODRIVER=dummy") + + if (WIN32) + if (BUILD_SHARED_DEPS) + set(test_path "PATH=${native_dep_bindir}\\\$${native_binary_dir}\\$") + string(REPLACE ";" "\\\$" escaped_path "$ENV{PATH}") + string(APPEND test_path "${escaped_path}") + list(APPEND test_add_env "${test_path}") + endif () + else () + if (BUILD_SHARED_DEPS) + list(APPEND test_add_env "LD_LIBRARY_PATH=${native_dep_bindir}:${native_binary_dir}:\$LD_LIBRARY_PATH") + endif () + endif () + + set_property(TEST "simh-${_targ}" PROPERTY ENVIRONMENT "${test_add_env}") + + if (DONT_USE_ROMS) + target_compile_definitions(DONT_USE_INTERNAL_ROM) + elseif (SIMH_BUILDROMS) + add_dependencies(${_targ} BuildROMs) + endif () + + # Create target 'cppcheck' rule, if cppcheck detected: + if (ENABLE_CPPCHECK AND cppcheck_cmd) + get_property(cppcheck_includes TARGET ${_targ} PROPERTY INCLUDE_DIRECTORIES) + get_property(cppcheck_defines TARGET ${_targ} PROPERTY COMPILE_DEFINITIONS) + list(TRANSFORM cppcheck_includes PREPEND "-I") + list(TRANSFORM cppcheck_defines PREPEND "-D") + add_custom_target("${_targ}_cppcheck" + COMMAND ${cppcheck_cmd} ${cppcheck_defines} ${cppcheck_includes} ${SIMH_SOURCES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + + add_dependencies(cppcheck "${_targ}_cppcheck") + endif (ENABLE_CPPCHECK AND cppcheck_cmd) +endfunction () + + +function(add_unit_test _targ) + set(UNIT_TARGET "simbase-${_targ}") + set(UNIT_TEST "simbase-${_targ}") + + simh_executable_template(${UNIT_TARGET} "${ARGN}") + cmake_parse_arguments(SIMH "FEATURE_INT64;FEATURE_FULL64;BUILDROMS;FEATURE_VIDEO,FEATURE_DISPLAY" + "SOURCE_DIR;LABEL" + "DEFINES;INCLUDES;SOURCES" + ${ARGN}) + + target_link_libraries(${UNIT_TARGET} PUBLIC unittest) + add_test(NAME ${UNIT_TEST} COMMAND ${UNIT_TARGET}) + + set(TEST_LABEL "simbase;unit") + if (SIMH_LABEL) + list(APPEND TEST_LABEL "simbase-${SIMH_LABEL}") + endif () + set_tests_properties(${UNIT_TEST} PROPERTIES LABELS "${TEST_LABEL}") +endfunction () + +##~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= +## Now build things! +##~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= + +if (ENABLE_CPPCHECK AND cppcheck_cmd) + add_custom_target(cppcheck) +endif () + +build_simcore(simhcore) +build_simcore(simhi64 INT64) +build_simcore(simhz64 INT64 ADDR64) +build_simcore(simhcore_video VIDEO) +build_simcore(simhi64_video VIDEO INT64) +build_simcore(simhz64_video VIDEO INT64 ADDR64) + +## Temporary hack for BESM6's breakage. +build_simcore(simhi64_besm6 VIDEO INT64 BESM6_SDL_HACK) + +if (NOT DONT_USE_ROMS) + add_executable(BuildROMs sim_BuildROMs.c) + target_include_directories(BuildROMs PUBLIC "${CMAKE_SOURCE_DIR}") + target_link_libraries(BuildROMs os_features) + add_custom_command( + OUTPUT + ${CMAKE_SOURCE_DIR}/VAX/vax_ka655x_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka620_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka630_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka610_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka410_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka411_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka412_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka41a_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka41d_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka42a_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka42b_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka43a_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka46a_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka47a_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka48a_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_is1000_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka410_xs_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka420_rdrz_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka420_rzrz_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka4xx_4pln_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka4xx_8pln_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka4xx_dz_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka4xx_spx_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka750_bin_new.h + ${CMAKE_SOURCE_DIR}/VAX/vax_ka750_bin_old.h + ${CMAKE_SOURCE_DIR}/VAX/vax_vcb02_bin.h + ${CMAKE_SOURCE_DIR}/VAX/vax_vmb_exe.h + ${CMAKE_SOURCE_DIR}/PDP11/pdp11_vt_lunar_rom.h + ${CMAKE_SOURCE_DIR}/PDP11/pdp11_dazzle_dart_rom.h + ${CMAKE_SOURCE_DIR}/PDP11/pdp11_11logo_rom.h + ${CMAKE_SOURCE_DIR}/swtp6800/swtp6800/swtp_swtbugv10_bin.h + MAIN_DEPENDENCY BuildROMs + COMMAND BuildROMS + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) +endif () + diff --git a/cmake/build_dep_matrix.cmake b/cmake/build_dep_matrix.cmake new file mode 100644 index 00000000..cc85fdbf --- /dev/null +++ b/cmake/build_dep_matrix.cmake @@ -0,0 +1,85 @@ +#~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= +# build_dep_matrix.cmake +# +# This is a minor hack to build all of the various library compile +# configurations. Might take a bit more time upfront to build the +# dependencies, but the user doesn't have to go backward and attempt +# to build the dependencies themselves. +# +# Author: B. Scott Michel +# "scooter me fecit" +#~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= + + +function(BuildDepMatrix dep pretty) + cmake_parse_arguments(_BDM "" "RELEASE_BUILD;DEBUG_BUILD" "CMAKE_ARGS" ${ARGN}) + + set(cmake_cfg_args + "-G${CMAKE_GENERATOR}" + "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}" + "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") + + if (CMAKE_GENERATOR_PLATFORM) + list(APPEND cmake_cfg_args "-A" "${CMAKE_GENERATOR_PLATFORM}") + endif () + if (CMAKE_GENERATOR_TOOLSET) + list(APPEND cmake_cfg_args "-T" "${CMAKE_GENERATOR_TOOLSET}") + endif () + string(REPLACE ";" "$" _amend_cmake_prefix_path "${SIMH_PREFIX_PATH_LIST}") + string(REPLACE ";" "$" _amend_cmake_include_path "${SIMH_INCLUDE_PATH_LIST}") + + list(APPEND cmake_cfg_args ${DEP_CMAKE_ARGS}) + list(APPEND cmake_cfg_args -DCMAKE_PREFIX_PATH=${_amend_cmake_prefix_path} + -DCMAKE_INCLUDE_PATH=${_amend_cmake_include_path} + ${_BDM_CMAKE_ARGS} + "" + ) + + if (NOT _BDM_RELEASE_BUILD) + set(_BDM_RELEASE_BUILD "Release") + endif (NOT _BDM_RELEASE_BUILD) + + if (NOT _BDM_DEBUG_BUILD) + set(_BDM_DEBUG_BUILD "Debug") + endif (NOT _BDM_DEBUG_BUILD) + + set(dep_cmds) + foreach (cfg IN ITEMS ${_BDM_DEBUG_BUILD} ${_BDM_RELEASE_BUILD}) + ## Set the MSVC runtime. Can't use a generator expression here, + ## have to "nail it down." + set(use_msvcrt "MultiThreaded") + if (cfg STREQUAL ${_BDM_DEBUG_BUILD}) + string(APPEND use_msvcrt "Debug") + endif () + if (BUILD_SHARED_DEPS) + string(APPEND use_msvcrt "DLL") + endif () + list(APPEND dep_cmds COMMAND ${CMAKE_COMMAND} -E echo "-- Building ${pretty} '${cfg}' configuration") + list(APPEND dep_cmds COMMAND ${CMAKE_COMMAND} -E remove -f CMakeCache.txt) + list(APPEND dep_cmds COMMAND ${CMAKE_COMMAND} -E remove_directory CMakeFiles) + list(APPEND dep_cmds COMMAND ${CMAKE_COMMAND} + ${cmake_cfg_args} + -DCMAKE_BUILD_TYPE:STRING=${cfg} + -DCMAKE_INSTALL_PREFIX:STRING=${SIMH_DEP_TOPDIR} + -DCMAKE_POLICY_DEFAULT_CMP0091:STRING=NEW + -DCMAKE_MSVC_RUNTIME_LIBRARY:STRING=${use_msvcrt} + ) + list(APPEND dep_cmds COMMAND ${CMAKE_COMMAND} --build --config "${cfg}" --clean-first) + list(APPEND dep_cmds COMMAND ${CMAKE_COMMAND} --install --config ${cfg}) + endforeach () + + ## Unset CMAKE_MODULE_PATH temporarily for external projects + set(_saved_cmake_module_path ${CMAKE_MODULE_PATH}) + set(CMAKE_MODULE_PATH "") + + ## message("${dep_cmds}") + ExternalProject_Add_Step(${dep} build-dbg-release + DEPENDEES configure + WORKING_DIRECTORY + ${dep_cmds} + ) + + set(CMAKE_MODULE_PATH ${_saved_cmake_module_path}) + unset(_saved_cmake_module_path) +endfunction () + diff --git a/cmake/cmake-builder.ps1 b/cmake/cmake-builder.ps1 new file mode 100644 index 00000000..947ca3e1 --- /dev/null +++ b/cmake/cmake-builder.ps1 @@ -0,0 +1,584 @@ +# Author: B. Scott Michel (scooter.phd@gmail.com) +# "scooter me fecit" + +<# +.SYNOPSIS +Configure and build SIMH's dependencies and simulators using the Microsoft Visual +Studio C compiler or MinGW-W64-based gcc compiler. + +.DESCRIPTION +This script executes the three (3) phases of building the entire suite of SIMH +simulators using the CMake meta-build tool. The phases are: + +1. Configure and generate the build environment selected by '-flavor' option. +2. Build missing runtime dependencies and the simulator suite with the compiler + configuration selected by the '-config' option. The "Release" configuration + generates optimized executables; the "Debug" configuration generates + development executables with debugger information. +3. Test the simulators + +There is an install phase that can be invoked separately as part of the SIMH +packaging process. + +The test and install phases can be enabled or disabled by the appropriate command line +flag (e.g., '-noInstall', '-noTest', '-testOnly', '-installOnly'.) + +Build environment and artifact locations: +----------------------------------------- +cmake/build-vs* MSVC build products and artifacts +cmake/build-mingw MinGW-W64 products and artifacts +cmake/build-ninja Ninja builder products and artifacts + +.EXAMPLE +PS> cmake-builder.ps1 -flavor vs2022 -config Release + +Generate/configure, build, test and install the SIMH simulator suite using +the Visual Studio 2022 toolchain in the Release (optimized) compile +configuration. + +.EXAMPLE +PS> cmake-builder.ps1 vs2022 Release + +Another way to generate/configure, build, test and install the SIMH simulator +suite using the Visual Studio 2022 toolchain in the Release (optimized) +compile configuration. + +.EXAMPLE +PS> cmake-builder.ps1 vs2019 Debug -notest -noinstall + +Generate/configure and build the SIMH simulator suite with the Visual Studio +2019 toolchain in the Debug compile configuration. Does not execute tests and +does not install the simulators under the BIN subdirectory in the top of the +source tree. + +.EXAMPLE + +PS> cmake-builder.ps1 -flavor vs2019 -config Release -installonly + +Install the simulators under the BIN subdirectory in the top of the source +tree. Does not generate/configure, but will build to ensure that compile +targets (simulator executables) are up-to-date. +#> + +param ( + ## String arguments are positional, so if the user invokes this script + ## as "cmake-builder.ps1 vs2022 Debug", it's the same as saying + ## "cmake-builder.ps1 -flavor vs2022 -config Debug" + + + ## The build environment's "flavor" that determines which CMake generator is used + ## to create all of the build machinery to compile the SIMH simulator suite + ## and the target compiler. + ## + ## Supported flavors: + ## ------------------ + ## vs2022 Visual Studio 2022 (default) + ## vs2022-xp Visual Studio 2022 XP compat + ## vs2022-x64 Visual Studio 2022 64-bit + ## vs2019 Visual Studio 2019 + ## vs2019-xp Visual Studio 2019 XP compat + ## vs2019-x64 Visual Studio 2019 64-bit + ## vs2017 Visual Studio 2017 + ## vs2017-xp Visual Studio 2017 XP compat + ## vs2017-x64 Visual Studio 2017 64-bit + ## vs2015 Visual Studio 2015 + ## mingw-make MinGW GCC/mingw32-make + ## mingw-ninja MinGW GCC/ninja + [Parameter(Mandatory=$false)] + [string] $flavor = "vs2022", + + ## The target build configuration. Valid values: "Release" and "Debug" + [Parameter(Mandatory=$false)] + [string] $config = "Release", + + ## Supply a suffix for CPack package names via -DSIMH_PACKAGE_SUFFIX + [Parameter(Mandatory=$false)] + [string] $cpack_suffix = "", + + ## (optional) Build a specific simulator or simulators. Separate multiple + ## targets with a comma, ## e.g. "--target pdp8,pdp11,vax750,altairz80,3b2" + [Parameter(Mandatory=$false)] + [string[]] $target = "", + + ## The rest are flag arguments + + ## Clean (remove) the CMake build directory before configuring + [Parameter(Mandatory=$false)] + [switch] $clean = $false, + + ## Get help. + [Parameter(Mandatory=$false)] + [switch] $help = $false, + + ## Compile the SIMH simulator suite without network support. + [Parameter(Mandatory=$false)] + [switch] $nonetwork = $false, + + ## Compile the SIMH simulator suite without video support. + [Parameter(Mandatory=$false)] + [switch] $novideo = $false, + + ## Compile the SIMH simulator without AIO support. + [Parameter(Mandatory=$false)] + [switch] $noaio = $false, + + ## Compile the SIMH simulator without AIO instrinsics ("lock-free" AIO), + ## using lock-based AIO via thread mutexes instead. + [Parameter(Mandatory=$false)] + [switch] $noaiointrinsics = $false, + + ## Disable the build's tests. + [Parameter(Mandatory=$false)] + [switch] $notest = $false, + + ## Do not install the simulator suite in the source directory's BIN + ## subdirectory. + [Parameter(Mandatory=$false)] + [switch] $noinstall = $false, + + ## Enable parallel builds. + [Parameter(Mandatory=$false)] + [switch] $parallel = $false, + + ## Configure and generate the build environment. Don't compile, test or install. + [Parameter(Mandatory=$false)] + [switch] $generate = $false, + + ## Only run the tests. + [Parameter(Mandatory=$false)] + [switch] $testonly = $false, + + ## Only install the SIMH simulator suite in the source directory's BIN + ## subdirectory. + [Parameter(Mandatory=$false)] + [switch] $installOnly = $false, + + ## Turn on Windows API deprecation warnings. NOTE: These warnings are OFF by + ## default. + [Parameter(Mandatory=$false)] + [switch] $windeprecation = $false, + + ## Enable Link-Time Optimization (LTO). + [Parameter(Mandatory=$false)] + [switch] $lto = $false, + + ## Turn on maximal compiler warnings for Debug builds (e.g. "-Wall" or "/W3") + [Parameter(Mandatory=$false)] + [switch] $debugWall = $false, + + ## Enable the cppcheck static code analysis rules + [Parameter(Mandatory=$false)] + [switch] $cppcheck = $false +) + +$scriptName = $(Split-Path -Leaf $PSCommandPath) +$scriptCmd = ${PSCommandPath} + +function Show-Help +{ + Get-Help -full ${scriptCmd} + exit 0 +} + + +## CMake generator info: +class GeneratorInfo +{ + [string] $Generator + [bool] $SingleConfig + [bool] $UCRT + [string] $UCRTVersion + [string[]]$ArchArgs + + GeneratorInfo([string]$gen, $configFlag, $ucrtFlag, $ucrtVer, [string[]]$arch) + { + $this.Generator = $gen + $this.SingleConfig = $configFlag + $this.UCRT = $ucrtFlag + $this.UCRTVersion = $ucrtVer + $this.ArchArgs = $arch + } +} + +## Multiple build configurations selected at compile time +$multiConfig = $false +## Single configuration selected at configuration time +$singleConfig = $true + +$cmakeGenMap = @{ + "vs2022" = [GeneratorInfo]::new("Visual Studio 17 2022", $multiConfig, $false, "", @("-A", "Win32")); + "vs2022-xp" = [GeneratorInfo]::new("Visual Studio 17 2022", $multiConfig, $false, "", @("-A", "Win32", "-T", "v141_xp")); + "vs2022-x64" = [GeneratorInfo]::new("Visual Studio 17 2022", $multiConfig, $false, "", @("-A", "x64", "-T", "host=x64")); + "vs2019" = [GeneratorInfo]::new("Visual Studio 16 2019", $multiConfig, $false, "", @("-A", "Win32")); + "vs2019-xp" = [GeneratorInfo]::new("Visual Studio 16 2019", $multiConfig, $false, "", @("-A", "Win32", "-T", "v141_xp")); + "vs2019-x64" = [GeneratorInfo]::new("Visual Studio 17 2022", $multiConfig, $false, "", @("-A", "x64", "-T", "host=x64")); + "vs2017" = [GeneratorInfo]::new("Visual Studio 15 2017", $multiConfig, $false, "", @("-A", "Win32")); + "vs2017-xp" = [GeneratorInfo]::new("Visual Studio 15 2017", $multiConfig, $false, "", @("-A", "Win32", "-T", "v141_xp")); + "vs2017-x64" = [GeneratorInfo]::new("Visual Studio 17 2022", $multiConfig, $false, "", @("-A", "x64", "-T", "host=x64")); + "vs2015" = [GeneratorInfo]::new("Visual Studio 14 2015", $multiConfig, $false, "", @()); + "mingw-make" = [GeneratorInfo]::new("MinGW Makefiles", $singleConfig, $false, "", @()); + "mingw-ninja" = [GeneratorInfo]::new("Ninja", $singleConfig, $false, "", @()) +} + + +function Get-GeneratorInfo([string]$flavor) +{ + return $cmakeGenMap[$flavor] +} + +function Quote-Args([string[]]$arglist) +{ + return ($arglist | foreach-object { if ($_ -like "* *") { "`"$_`"" } else { $_ } }) +} + + +## Output help early and exit. +if ($help) +{ + Show-Help +} + +### CTest params: +## timeout is 180 seconds +$ctestTimeout = "300" + +## Sanity checking: Check that utilities we expect exist... +## CMake: Save the location of the command because we'll invoke it later. Same +## with CTest +$cmakeCmd = $(Get-Command -Name cmake.exe -ErrorAction Ignore).Path +$ctestCmd = $(Get-Command -Name ctest.exe -ErrorAction Ignore).Path +if ($cmakeCmd.Length -gt 0) +{ + Write-Host "** ${scriptName}: cmake is '${cmakeCmd}'" + Write-Host "** $(& ${cmakeCmd} --version)" +} +else { + @" +!! ${scriptName} error: + +The 'cmake' command was not found. Please ensure that you have installed CMake +and that your PATH environment variable references the directory in which it +was installed. +"@ + + exit 1 +} + +if (!$testonly) +{ + ## Check for GCC and mingw32-make if user wants the mingw flavor build. + if ($flavor -eq "mingw" -or $flavor -eq "ninja") + { + if ($(Get-Command gcc -ErrorAction Ignore).Path.Length -eq 0) { + @" + !! ${scriptName} error: + + Did not find 'gcc', the GNU C/C++ compiler toolchain. Please ensure you have + installed gcc and that your PATH environment variables references the directory + in which it was installed. +"@ + exit 1 + } + + if ($(Get-Command mingw32-make -ErrorAction Ignore).Path.Length -eq 0) { + @" + !! ${scriptName} error: + + Did not find 'mingw32-make'. Please ensure you have installed mingw32-make and + that your PATH environment variables references the directory in which it was + installed. + + See the .travis/deps.sh functions mingw64() and ucrt64() for the pacman packages + that should be installed. +"@ + exit 1 + } + } +} + +## Validate the requested configuration. +if (!@("Release", "Debug").Contains($config)) +{ + @" +${scriptName}: Invalid configuration: "${config}". + +"@ + Show-Help +} + +## Look for Git's /usr/bin subdirectory: CMake (and other utilities) have issues +## with the /bin/sh installed there (Git's version of MinGW.) + +$tmp_path = $env:PATH +$git_usrbin = "${env:ProgramFiles}\Git\usr\bin" +$tmp_path = ($tmp_path.Split(';') | Where-Object { $_ -ne "${git_usrbin}"}) -join ';' +if ($tmp_path -ne ${env:PATH}) +{ + Write-Host "** ${scriptName}: Removed ${git_usrbin} from PATH (Git MinGW problem)" + $env:PATH = $tmp_path +} + +## Also make sure that none of the other cmake-* directories are in the user's PATH +## because CMake's find_package does traverse PATH looking for potential candidates +## for dependency libraries. + +$origPath = $env:PATH +$modPath = $origPath + +if (Test-Path -Path cmake\dependencies) { + $bdirs = $(Get-ChildItem -Attribute Directory cmake\dependencies\*).ForEach({ $_.FullName + "\bin" }) + $modPath = (${env:Path}.Split(';') | Where-Object { $bdirs -notcontains $_ }) -join ';' + if ($modPath -ne $origPath) { + Write-Host "** ${scriptName}: Removed cmake\dependencies 'bin' directories from PATH." + } +} + +## Setup: +$simhTopDir = $(Split-Path -Parent $(Resolve-Path -Path $PSCommandPath).Path) +While (!([String]::IsNullOrEmpty($simhTopDir) -or (Test-Path -Path ${simhTopDir}\CMakeLists.txt))) { + $simhTopDir = $(Split-Path -Parent $simhTopDir) +} +if ([String]::IsNullOrEmpty($simhTopDir)) { + @" +!! ${scriptName}: Cannot locate SIMH top-level source directory from +the script's path name. You should really not see this message. +"@ + + exit 1 +} else { + Write-Host "** ${scriptName}: SIMH top-level source directory is ${simhTopDir}" +} + +$buildDir = "${simhTopDir}\cmake\build-${flavor}" +$genInfo = $(Get-GeneratorInfo $flavor) +if ($null -eq $genInfo) +{ + Write-Host "" + Write-Host "!! ${scriptName}: Unrecognized build flavor '${flavor}'." + Write-Host "" + Show-Help +} + +if ($testonly) +{ + $scriptPhases = @("test") +} +elseif ($generate) +{ + $scriptPhases = @("generate") +} +elseif ($installOnly) +{ + $scriptPhases = @("install") +} +else +{ + $scriptPhases = @( "generate", "build", "test") + if ($notest) + { + $scriptPhases = $scriptPhases | Where-Object { $_ -ne 'test' } + } + if ($noinstall -or ![String]::IsNullOrEmpty($target)) + { + $scriptPhases = $scriptPhases | Where-Object { $_ -ne 'install' } + } +} + +if (($scriptPhases -contains "generate") -or ($scriptPhases -contains "build")) +{ + ## Clean out the build subdirectory + if ((Test-Path -Path ${buildDir}) -and $clean) + { + Write-Host "** ${scriptName}: Removing ${buildDir}" + Remove-Item -recurse -force -Path ${buildDir} -ErrorAction SilentlyContinue | Out-Null + } + + if (!(Test-Path -Path ${buildDir})) + { + Write-Host "** ${scriptName}: Creating ${buildDir} subdirectory" + New-Item -Path ${buildDir} -ItemType Directory | Out-Null + } + else + { + Write-Host "** ${scriptName}: ${buildDir} exists." + } + + ## Unconditionally remove the CMake cache. + Remove-Item -Force -Path ${buildDir}/CMakeCache.txt -ErrorAction SilentlyContinue | Out-Null + Remove-Item -Recurse -Force -Path ${buildDir}/CMakeFiles -ErrorAction SilentlyContinue | Out-Null + + ## Where we do the heaving lifting: + $generateArgs = @("-G", $genInfo.Generator) + if ($genInfo.SingleConfig) { + ## Single configuration set at compile time: + $generateArgs += @("-DCMAKE_BUILD_TYPE=${config}") + } + if ($genInfo.UCRT) { + ## Universal Windows Platform + $generateArgs += @("-DCMAKE_SYSTEM_NAME=WindowsStore", "-DCMAKE_SYSTEM_VERSION=$($genInfo.UCRTVersion)") + } + $generateArgs += $genInfo.ArchArgs + @("-Wno-dev", "--no-warn-unused-cli") + if ($nonetwork) + { + $generateArgs += @("-DWITH_NETWORK:Bool=Off") + } + if ($novideo) + { + $generateArgs += @("-DWITH_VIDEO:Bool=Off") + } + if ($noaio) + { + $generateArgs += @("-DWITH_ASYNC:Bool=Off") + } + if ($noaiointrinsics) + { + $generateArgs += @("-DDONT_USE_AIO_INTRINSICS:Bool=On") + } + if ($lto) + { + $generateArgs += @("-DRELEASE_LTO:Bool=On") + } + if ($debugWall) + { + $generateArgs += @("-DDEBUG_WALL:Bool=On") + } + if ($cppcheck) + { + $generateArgs += @("-DENABLE_CPPCHECK:Bool=On") + } + if (![String]::IsNullOrEmpty($cpack_suffix)) + { + $generateArgs += @("-DSIMH_PACKAGE_SUFFIX:Bool=${cpack_suffix}") + } + + $buildArgs = @("--build", "${buildDir}", "--config", "${config}") + if ($parallel) + { + $buildArgs += "--parallel" + } + if ($verbose) + { + $buildArgs += "--verbose" + } + if ($windeprecation) + { + $buildArgs += "-DWINAPI_DEPRECATION:Bool=TRUE" + } + if (![String]::IsNullOrEmpty($target)) { + foreach ($targ in $target) { + $buildArgs += @("--target", "$targ") + } + } + + $buildSpecificArgs = @() + if ($flavor -eq "mingw" -and $parallel) + { + ## Limit the number of parallel jobs mingw32-make can spawn. Otherwise + ## it'll overwhelm the machine. + $buildSpecificArgs += @("-j", "8") + } +} + +$exitval = 0 + +foreach ($phase in $scriptPhases) { + $savedPATH = $env:PATH + $argList = @() + $phaseCommand = "Write-Output" + + switch -exact ($phase) + { + "generate" { + $generateArgs += @("-S", ${simhTopDir}) + $generateArgs += @("-B", ${buildDir}) + + Write-Host "** ${scriptName}: Configuring and generating" + + $phaseCommand = ${cmakeCmd} + $argList = Quote-Args $generateArgs + } + + "build" { + Write-Host "** ${scriptName}: Building simulators." + + $phaseCommand = ${cmakeCmd} + $argList = $(Quote-Args $buildArgs) + $(Quote-Args $buildSpecificArgs) + } + + "test" { + Write-Host "** ${scriptName}: Testing simulators." + + ## CTest arguments: + $testArgs = @("-C", $config, "--timeout", $ctestTimeout, "-T", "test", + "--output-on-failure") + + ## Output gets confusing (and tests can time out when executing in parallel) + ## if ($parallel) + ## { + ## $testArgs += @("--parallel", $ctestParallel) + ## } + + if ($verbose) + { + $testArgs += @("--verbose") + } + + if (![String]::IsNullOrEmpty($target)) { + $tests = "simh-(" + ($target -join "|") + ")`$" + $testArgs += @("-R", $tests) + } + + $phaseCommand = ${ctestCmd} + $argList = Quote-Args $testArgs + + $env:PATH = $modPath + + $depTopDir = $(& $cmakeCmd -L -N ${buildDir} | Select-String "SIMH_DEP_TOPDIR") + if ($depTopDir) { + ## RHS of the cached variable's value. + $depTopDir = $depTopDir.Line.Split('=')[1] + $env:PATH = "${depTopdir}\bin;${env:PATH}" + } + } + + "install" { + Write-Host "** ${scriptName}: Installing simulators." + + $installPrefix = $(& $cmakeCmd -L -N ${buildDir} | Select-String "CMAKE_INSTALL_PREFIX") + $installPrefix = $installPrefix.Line.Split('=')[1] + $installPath = $installPrefix + + Write-Host "** ${scriptName}: Install directory ${installPath}" + if (!(Test-Path -Path ${installPath})) + { + Write-Host "** ${scriptName}: Creating ${installPath}" + New-Item -${installPath} -ItemType Directory -ErrorAction SilentlyContinue + } + + $phaseCommand = ${cmakeCmd} + $argList = Quote-Args @( "--install", "${buildDir}", "--config", "${config}") + } + } + + try { + Push-Location ${buildDir} + Write-Host "** ${phaseCommand} ${argList}" + & $phaseCommand @arglist + if ($LastExitCode -gt 0) { + $printPhase = (Get-Culture).TextInfo.ToTitleCase($phase) + Write-Error $("${printPhase} phase exited with non-zero status: " + $LastExitCode) + exit 1 + } + } + catch { + Write-Host "Error running '${phaseCommand} ${argList}' command: $($_.Exception.Message)" -ForegroundColor Red + throw $_ + } + finally { + Pop-Location + } + + $env:PATH = $savedPATH +} + +exit $exitval diff --git a/cmake/cmake-builder.sh b/cmake/cmake-builder.sh new file mode 100755 index 00000000..fc9015f1 --- /dev/null +++ b/cmake/cmake-builder.sh @@ -0,0 +1,426 @@ +#!/bin/bash + +##-- Bash functions -- +showHelp() +{ + [ x"$1" != x ] && { echo "${scriptName}: $1"; echo ""; } + cat < /dev/null 2>&1 + if [[ $? -eq 4 ]]; then + getopt_prog="${p}/getopt" + break + fi +done +IFS="${IFS_SAVE}" + +if [[ "x${getopt_prog}" = "x" ]]; then + echo "${scriptName}: GNU getopt needed for this script to function properly." + echo "${scriptName}: Specifically, a 'getopt' that supports the '-T' flag (enhanced getopt)" + exit 1 +fi + +## This script also needs GNU coreutils +realpath=$(which realpath) || { + echo "${scriptName}: Could not find 'realpath'. Please install and re-execute this script." + echo "${scriptName}: 'realpath' is a component of the GNU coreutils collection." +} +dirname=$(which dirname) || { + echo "${scriptName}: Could not find 'dirname'. Please install and re-execute this script." + echo "${scriptName}: 'dirname' is a component of the GNU coreutils collection." +} + +## Check if CMake supports parallel +cmake=$(which cmake) || { + echo "${scriptName}: Could not find 'cmake'. Please install and re-execute this script." + exit 1 +} + +ctest=$(which ctest) || { + echo "${scriptName}: Could not find 'ctest'. Please check your 'cmake' installation." + exit 1 +} + +echo "** $(${cmake} --version)" + +$(${cmake} -h 2>&1 | grep -- "-S" > /dev/null) && { + cmakeSFlag=yes +} + +canParallel=no +(${cmake} --build /tmp --help 2>&1 | grep parallel > /dev/null) && { + canParallel=yes +} + +canTestParallel=no +# (${ctest} --help 2>&1 | grep parallel > /dev/null) && { +# canTestParallel=yes +# } + +if [[ "x${MSYSTEM}" != x ]]; then + case "${MSYSTEM}" in + MSYS|MINGW64) + buildFlavor="MinGW Makefiles" + buildSubdir=build-mingw + ;; + UCRT64) + buildFlavor="Ninja" + buildSubdir=build-ninja + ;; + esac +fi + +longopts=clean,help,flavor:,config:,nonetwork,novideo,notest,parallel,generate,testonly +longopts=${longopts},noinstall,installonly,verbose,target:,lto,debugWall,cppcheck,cpack_suffix: +longopts=${longopts},cache,no-aio,no-aio-intrinsics + +ARGS=$(${getopt_prog} --longoptions $longopts --options xhf:c:pg -- "$@") +if [ $? -ne 0 ] ; then + showHelp "${scriptName}: Usage error (use -h for help.)" +fi + +eval set -- ${ARGS} +while true; do + case $1 in + -x | --clean) + buildClean=yes; shift + ;; + -h | --help) + showHelp + ;; + -f | --flavor) + case "$2" in + unix) + buildFlavor="Unix Makefiles" + buildSubdir=build-unix + shift 2 + ;; + ninja|ucrt64) + buildFlavor=Ninja + buildSubdir=build-ninja + shift 2 + ;; + xcode) + buildFlavor=Xcode + buildSubdir=build-xcode + shift 2 + ;; + xcode-universal) + buildFlavor=Xcode + buildSubdir=build-xcode-universal + generateArgs="${generateArgs} -DMAC_UNIVERSAL:Bool=On" + shift 2 + ;; + mingw|mingw64|msys|msys2) + buildFlavor="MinGW Makefiles" + buildSubdir=build-mingw + shift 2 + ;; + *) + showHelp "Invalid build flavor: $2" + ;; + esac + ;; + -c | --config) + case "$2" in + Release|Debug) + buildConfig=$2 + shift 2 + ;; + *) + showHelp "Invalid build configuration: $2" + ;; + esac + ;; + --nonetwork) + generateArgs="${generateArgs} -DWITH_NETWORK:Bool=Off" + shift + ;; + --novideo) + generateArgs="${generateArgs} -DWITH_VIDEO:Bool=Off" + shift + ;; + --no-aio) + generateArgs="${generateArgs} -DWITH_ASYNC:Bool=Off" + shift + ;; + --no-aio-intrinsics) + generateArgs="${generateArgs} -DDONT_USE_AIO_INTRINSICS:Bool=On" + shift + ;; + --notest) + notest=yes + shift + ;; + --noinstall) + noinstall=yes + shift + ;; + --lto) + generateArgs="${generateArgs} -DRELEASE_LTO:Bool=On" + shift + ;; + --debugWall) + generateArgs="${generateArgs} -DDEBUG_WALL:Bool=On" + shift + ;; + --cppcheck) + generateArgs="${generateArgs} -DENABLE_CPPCHECK:Bool=On" + shift + ;; + --cpack_suffix) + generateArgs="${generateArgs} -DSIMH_PACKAGE_SUFFIX=$2" + shift 2 + ;; + -p | --parallel) + buildParallel=yes + shift + ;; + -g | --generate) + generateOnly=yes + shift + ;; + --cache) + generateOnly=yes + generateArgs="${generateArgs} -LA" + shift + ;; + --testonly) + testOnly=yes + shift + ;; + --installonly) + installOnly=yes + shift + ;; + --verbose) + verboseMode="--verbose" + shift + ;; + --target) + noinstall=yes + simTarget="${simTarget} $2" + shift 2 + ;; + --) + ## End of options. we'll ignore. + shift + break + ;; + esac +done + +# Sanity check: buildSubdir should be set, unless the '-f' flag wasn't present. +if [ "x${buildSubdir}" = x ]; then + echo "" + echo "${scriptName}: Build flavor is NOT SET -- see the \"--flavor\"/\"-f\" flag in the help." + echo "" + showHelp +fi + +## Determine the SIMH top-level source directory: +simhTopDir=$(${dirname} $(${realpath} $0)) +while [ "x${simhTopDir}" != x -a ! -f "${simhTopDir}/CMakeLists.txt" ]; do + simhTopDir=$(${dirname} "${simhTopDir}") +done + +if [[ "x${simhTopDir}" = x ]]; then + echo "${scriptName}: Can't determine SIMH top-level source directory." + echo "Did this really happen?" + exit 1 +else + buildSubdir=$(${realpath} "${simhTopDir}/cmake/")"/${buildSubdir}" + echo "${scriptName}: SIMH top-evel directory: ${simhTopDir}" + echo "${scriptName}: Build directory: ${buildSubdir}" +fi + +if [[ x"$buildClean" != x ]]; then + echo "${scriptName}: Cleaning ${buildSubdir}" + rm -rf ${buildSubdir} +fi + +if [[ ! -d ${buildSubdir} ]]; then + mkdir ${buildSubdir} +fi + +## Setup test arguments (and add parallel later) +testArgs="-C ${buildConfig} --timeout 180 --output-on-failure" + +## Parallel only applies to the unix flavor. GNU make will overwhelm your +## machine if the number of jobs isn't capped. +if [[ x"$canParallel" = xyes ]] ; then + if [ x"$buildParallel" = xyes -a "$buildFlavor" != Ninja ] ; then + (${cmake} --build . --help 2>&1 | grep parallel 2>&1 > /dev/null) && { + buildArgs="${buildArgs} --parallel" + buildPostArgs="${buildPostArgs} -j 8" + } + + # Don't execute ctest in parallel... + # [ x${canTestParallel} = xyes ] && { + # testArgs="${testArgs} --parallel 4" + # } + fi +else + buildParallel= +fi + +if [[ x"${simTarget}" != x ]]; then + simTests="" + for tgt in $(echo ${simTarget} | sed 's/,/ /g'); do + buildArgs="${buildArgs} --target ${tgt}" + [[ x"${simTests}" != x ]] && simTests="${simTests}|" + simTests="${simTests}${tgt}" + done + testArgs="${testArgs} -R simh-(${simTests})\$" +fi + +buildArgs="${buildArgs} --config ${buildConfig}" + +if [[ x$generateOnly = xyes ]]; then + phases=generate +elif [[ x$testOnly = xyes ]]; then + phases=test +elif [[ x$installOnly = xyes ]]; then + phases=install +else + phases="generate build" + if [[ x${notest} != xyes ]]; then + phases="${phases} test" + fi +fi + +for ph in ${phases}; do + case $ph in + generate) + ## Uncondintionally remove the CMake cache. + echo "${scriptName}: Removing CMakeCache.txt and CMakeFiles" + rm -rf ${buildSubdir}/CMakeCache.txt ${buildSubdir}/CMakefiles + + if [[ "x${cmakeSFlag}" != x ]]; then + echo "${cmake} -G "\"${buildFlavor}\"" -DCMAKE_BUILD_TYPE="${buildConfig}" -S "${simhTopDir}" -B ${buildSubdir} ${generateArgs}" + ${cmake} -G "${buildFlavor}" -DCMAKE_BUILD_TYPE="${buildConfig}" -S "${simhTopDir}" -B "${buildSubdir}" ${generateArgs} || { \ + echo "*** ${scriptName}: Errors detected during environment generation. Exiting." + exit 1 + } + else + echo "${cmake} -G "\"${buildFlavor}\"" -DCMAKE_BUILD_TYPE="${buildConfig}" "${simhTopDir}" ${generateArgs}" + ( cd "${buildSubdir}"; \ + ${cmake} -G "${buildFlavor}" -DCMAKE_BUILD_TYPE="${buildConfig}" "${simhTopDir}" ${generateArgs}) || { \ + echo "*** ${scriptName}: Errors detected during environment generation. Exiting."; + exit 1 + } + fi + ;; + build) + ${cmake} --build "${buildSubdir}" ${buildArgs} ${verboseMode} -- ${buildPostArgs} || { + echo "*** ${scriptName}: Build errors detected. Exiting." + exit 1 + } + ;; + test) + (cd "${buildSubdir}" \ + && echo ${ctest} ${testArgs} ${verboseMode} \ + && ${ctest} ${testArgs} ${verboseMode}) || { + echo "*** ${scriptName}: Errors detected during testing. Exiting." + exit 1 + } + ;; + install) + ${cmake} --build "${buildSubdir}" --target install --config "${buildConfig}" + ;; + package) + (cd "${buildSubdir}" \ + && ${cpack} -G ZIP -C ${buildConfig} ${verboseMode} \ + && mv *.zip ${simhTopDir}/PACKAGES \ + ) + ;; + esac +done diff --git a/cmake/cpack-setup.cmake b/cmake/cpack-setup.cmake new file mode 100644 index 00000000..400c2aad --- /dev/null +++ b/cmake/cpack-setup.cmake @@ -0,0 +1,139 @@ +## CPack setup -- sets the CPACK_* variables for the sundry installers +## +## Author: B. Scott Michel (scooter.phd@gmail.com) +## "scooter me fecit" + + +## pre_runtime_exclusions: These are the names of dependency libraries, esp. on Windows +## that should not get installed as runtime or library dependencies. +## +## post_runtime_exclusions: These are regex expressions for the dependency paths to filter out, +## notably Windows system32 DLLs. +set(pre_runtime_exclusions) +list(APPEND pre_runtime_exclusions + ## Windows: + "(ext|api)-ms-.*" + "hvsifiletrust.dll" + "pdmutilities.dll" +) +set(post_runtime_exclusions) +list(APPEND post_runtime_exclusions + ".*system32/.*\\.dll" +) + +## Make runtime_support the default component (vice "Unspecified") +set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "runtime_support") + +# After we know where everything will install, let CPack figure out +# how to assemble it into a package file. +set(CPACK_PACKAGE_VENDOR "The Open-SIMH project") + +if (SIMH_PACKAGE_SUFFIX) + set(buildSuffix "${SIMH_PACKAGE_SUFFIX}") +else () + set(buildSuffix "") + if (WIN32) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND buildSuffix "win64") + else () + list(APPEND buildSuffix "win32") + endif () + + list(APPEND buildSuffix "\${CPACK_BUILD_CONFIG}") + ## If using Visual Studio, append the compiler and toolkit: + if (CMAKE_GENERATOR MATCHES "Visual Studio 17 .*") + list(APPEND buildSuffix "vs2022") + elseif (CMAKE_GENERATOR MATCHES "Visual Studio 16 .*") + list(APPEND buildSuffix "vs2019") + elseif (CMAKE_GENERATOR MATCHES "Visual Studio 15 .*") + list(APPEND buildSuffix "vs2017") + elseif (CMAKE_GENERATOR MATCHES "Visual Studio 14 .*") + list(APPEND buildSuffix "vs2015") + endif () + if (CMAKE_GENERATOR_TOOLSET MATCHES "v[0-9][0-9][0-9]_xp") + string(APPEND buildSuffix "xp") + endif () + else () + list(APPEND buildSuffix ${CMAKE_SYSTEM_NAME}) + endif () + + list(JOIN buildSuffix "-" buildSuffix) + + message(STATUS "No SIMH_PACKAGE_SUFFIX supplied, default is ${buildSuffix}.") +endif () + +string(JOIN "-" CPACK_PACKAGE_FILE_NAME + "${CMAKE_PROJECT_NAME}" + "${CMAKE_PROJECT_VERSION}" + "${buildSuffix}" +) + +message(STATUS "CPack output file name: ${CPACK_PACKAGE_FILE_NAME}") +unset(buildSuffix) + +## When applicable (e.g., NSIS Windows), install under the SIMH-x.y directory: +set(CPACK_PACKAGE_INSTALL_DIRECTORY "SIMH-${SIMH_VERSION_MAJOR}.${SIMH_VERSION_MINOR}") +## License file: +set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.txt) + +set(CPACK_PACKAGE_CONTACT "open-simh@nowhere.org") +set(CPACK_PACKAGE_MAINTAINER "open-simh@nowhere.org") + +## Runtime dependencies: +if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.21") + ## Don't install runtime dependencies on Linux platforms. The platform's + ## package management system will take care of this for us. + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + install(RUNTIME_DEPENDENCY_SET simhRuntime + COMPONENT runtime_support + PRE_EXCLUDE_REGEXES ${pre_runtime_exclusions} + POST_EXCLUDE_REGEXES ${post_runtime_exclusions} + ) + endif () +endif () + + +## Extra properties and variables: +set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_BINARY_DIR}/CPackSimhCustom.cmake) +configure_file(${CMAKE_SOURCE_DIR}/cmake/installer-customizations/CPackSimhCustom.cmake.in + ${CMAKE_BINARY_DIR}/CPackSimhCustom.cmake + @ONLY) + +## CPack generator-specific configs: + +##+ +## NullSoft Installation System (NSIS) Windows installer. Creates an installer EXE. +##- +set(CPACK_NSIS_PACKAGE_NAME ${CPACK_PACKAGE_INSTALL_DIRECTORY}) +set(CPACK_NSIS_INSTALL_ROOT "$LocalAppData\\\\Programs") + +## CPack does this configure_file on its own to genreate the project.nsi file. +## Keeping these lines for history. +# configure_file(${CMAKE_SOURCE_DIR}/cmake/installer-customizations/NSIS.template.in +# ${CMAKE_BINARY_DIR}/NSIS.template +# @ONLY) + +###+ +### WIX MSI Windows installer. +### +### +### Upgrade GUID shouldn't really change. +###- +set(CPACK_WIX_UPGRADE_GUID "ed5dba4c-7c9e-4af8-ac36-37e14c637696") + +##+ +## Debian: +##- + +list(APPEND debian_depends + libsdl2-2.0-0 + libsdl2-ttf-2.0-0 + libpcap0.8 + libvdeplug2 + libedit2 +) + +string(JOIN ", " CPACK_DEBIAN_PACKAGE_DEPENDS ${debian_depends}) + + +include(CPack) diff --git a/cmake/dep-link.cmake b/cmake/dep-link.cmake new file mode 100644 index 00000000..90c7707e --- /dev/null +++ b/cmake/dep-link.cmake @@ -0,0 +1,367 @@ +##+ +## dep-link.cmake: Create the dependency interface libraries +##- + +add_library(simh_regexp INTERFACE) +add_library(simh_video INTERFACE) +add_library(simh_network INTERFACE) + +## LIBPCAP is a special case +set(LIBPCAP_PROJECT "libpcap") +set(LIBPCAP_ARCHIVE_NAME "libpcap") +set(LIBPCAP_RELEASE "1.10.1") +set(LIBPCAP_ARCHIVE_TYPE "tar.gz") +set(LIBPCAP_TAR_ARCHIVE "${LIBPCAP_ARCHIVE_NAME}-${LIBPCAP_RELEASE}.${LIBPCAP_ARCHIVE_TYPE}") +set(LIBPCAP_SOURCE_URL "https://github.com/the-tcpdump-group/libpcap/archive/refs/tags/${LIBPCAP_TAR_ARCHIVE}") + +function(fix_interface_libs _targ) +get_target_property(_aliased ${_targ} ALIASED_TARGET) + if(NOT _aliased) + set(fixed_libs) + get_property(orig_libs TARGET ${_targ} PROPERTY INTERFACE_LINK_LIBRARIES) + foreach(each_lib IN LISTS ${_lib}) + get_filename_component(stripped_lib "${each_lib}" DIRECTORY) + if (stripped_lib) + string(STRIP ${each_lib} stripped_lib) + file(TO_CMAKE_PATH "${stripped_lib}" stripped_lib) + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.19") + file(REAL_PATH "${stripped_lib}" stripped_lib) + endif () + endif () + list(APPEND fixed_libs ${stripped_lib}) + message("** \"${each_lib}\" -> \"${stripped_lib}\"") + endforeach () + set_property(TARGET ${_targ} PROPERTY INTERFACE_LINK_LIBRARIES ${fixed_libs}) + endif () +endfunction () + +## Ubuntu 16.04 -- when we find the SDL2 library, there are trailing spaces. Strip +## spaces from SDL2_LIBRARIES (and potentially others as we find them). +function (fix_libraries _lib) + set(fixed_libs) + foreach(each_lib IN LISTS ${_lib}) + get_filename_component(stripped_lib "${each_lib}" DIRECTORY) + if (stripped_lib) + string(STRIP ${stripped_lib} stripped_lib) + file(TO_CMAKE_PATH "${stripped_lib}" stripped_lib) + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.19") + file(REAL_PATH "${stripped_lib}" stripped_lib) + endif () + endif () + list(APPEND fixed_libs ${stripped_lib}) + endforeach () + set(${_lib} ${fixed_libs} PARENT_SCOPE) +endfunction () + +set(BUILD_WITH_VIDEO FALSE) +IF (WITH_VIDEO) + ## +10 chaotic neutral hack: The SDL2_ttf CMake configuration include "-lfreetype" and + ## "-lharfbuzz", but, if you're on MacOS, you need to tell the linker where these libraries + ## are located... + set(ldirs) + foreach (lname ${FREETYPE_LIBRARIES} ${FREETYPE_LIBRARY} ${HARFBUZZ_LIBRARIES} ${HARFBUZZ_LIBRARY}) + get_filename_component(dirname "${lname}" DIRECTORY) + if (dirname) + string(STRIP ${dirname} dirname) + file(TO_CMAKE_PATH "${dirname}" dirname) + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.19") + file(REAL_PATH "${dirname}" dirname) + endif () + list(APPEND ldirs ${dirname}) + endif() + endforeach () + get_property(ilink_dirs TARGET simh_video PROPERTY INTERFACE_LINK_DIRECTORIES) + list(APPEND ilink_dirs ${ldirs}) + set_property(TARGET simh_video PROPERTY INTERFACE_LINK_DIRECTORIES ${ilink_dirs}) + unset(ilink_dirs) + unset(ldirs) + + IF (SDL2_ttf_FOUND) + IF (WIN32 AND TARGET SDL2_ttf::SDL2_ttf-static) + target_link_libraries(simh_video INTERFACE SDL2_ttf::SDL2_ttf-static) + list(APPEND VIDEO_PKG_STATUS "SDL2_ttf static") + ELSEIF (TARGET SDL2_ttf::SDL2_ttf) + target_link_libraries(simh_video INTERFACE SDL2_ttf::SDL2_ttf) + list(APPEND VIDEO_PKG_STATUS "SDL2_ttf dynamic") + ELSEIF (TARGET PkgConfig::SDL2_ttf) + target_link_libraries(simh_video INTERFACE PkgConfig::SDL2_ttf) + list(APPEND VIDEO_PKG_STATUS "pkg-config SDL2_ttf") + ELSEIF (DEFINED SDL_ttf_LIBRARIES AND DEFINED SDL_ttf_INCLUDE_DIRS) + target_link_libraries(simh_video INTERFACE ${SDL_ttf_LIBRARIES}) + target_include_directories(simh_video INTERFACE ${SDL_ttf_INCLUDE_DIRS}) + list(APPEND VIDEO_PKG_STATUS "detected SDL2_ttf") + ELSE () + message(FATAL_ERROR "SDL2_ttf_FOUND set but no SDL2_ttf::SDL2_ttf import library or SDL_ttf_LIBRARIES/SDL_ttf_INCLUDE_DIRS? ") + ENDIF () + ENDIF (SDL2_ttf_FOUND) + + IF (SDL2_FOUND) + target_compile_definitions(simh_video INTERFACE USE_SIM_VIDEO HAVE_LIBSDL) + ## + ## Hopefully this hack can go away. Had to move the target_compile_definitions + ## over to add_simulator.cmake to accomodate the BESM6 SDL irregularity. + ## + ## (keep) if (CMAKE_HOST_APPLE) + ## (keep) ## NOTE: This shouldn't be just an Apple platform quirk; SDL_main should + ## (keep) ## be used by all platforms. + ## (keep) target_compile_definitions(simh_video INTERFACE SDL_MAIN_AVAILABLE) + ## (keep) endif () + + ## Link to SDL2main if defined for this platform. + target_link_libraries(simh_video INTERFACE $) + + IF (WIN32 AND TARGET SDL2::SDL2-static AND TARGET SDL2_ttf::SDL2_ttf-static) + ## Prefer the static version on Windows, but only if SDL2_ttf is also static. + target_link_libraries(simh_video INTERFACE SDL2::SDL2-static) + list(APPEND VIDEO_PKG_STATUS "SDL2 static") + ELSEIF (TARGET SDL2::SDL2) + fix_interface_libs(SDL2::SDL2) + target_link_libraries(simh_video INTERFACE SDL2::SDL2) + list(APPEND VIDEO_PKG_STATUS "SDL2 dynamic") + ELSEIF (TARGET PkgConfig::SDL2) + fix_interface_libs(PkgConfig::SDL2) + target_link_libraries(simh_video INTERFACE PkgConfig::SDL2) + list(APPEND VIDEO_PKG_STATUS "pkg-config SDL2") + ELSEIF (DEFINED SDL2_LIBRARIES AND DEFINED SDL2_INCLUDE_DIRS) + fix_libraries(SDL2_LIBRARIES) + target_link_libraries(simh_video INTERFACE ${SDL2_LIBRARIES}) + target_include_directories(simh_video INTERFACE ${SDL2_INCLUDE_DIRS}) + list(APPEND VIDEO_PKG_STATUS "detected SDL2") + ELSE () + message(FATAL_ERROR "SDL2_FOUND set but no SDL2::SDL2 import library or SDL2_LIBRARIES/SDL2_INCLUDE_DIRS?") + ENDIF () + ENDIF (SDL2_FOUND) + + IF (NOT USING_VCPKG AND FREETYPE_FOUND) + if (TARGET Freetype::Freetype) + target_link_libraries(simh_video INTERFACE freetype) + list(APPEND VIDEO_PKG_STATUS "Freetype::Freetype") + ELSEIF (TARGET PkgConfig::Freetype) + target_link_libraries(simh_video INTERFACE PkgConfig::Freetype) + list(APPEND VIDEO_PKG_STATUS "pkg-config Freetype") + ELSE () + target_link_libraries(simh_video INTERFACE ${FREETYPE_LIBRARIES}) + target_include_directories(simh_video INTERFACE ${FREETYPE_INCLUDE_DIRS}) + list(APPEND VIDEO_PKG_STATUS "detected Freetype") + ENDIF () + ENDIF () + + IF (PNG_FOUND) + target_compile_definitions(simh_video INTERFACE HAVE_LIBPNG) + + if (TARGET PNG::PNG) + target_link_libraries(simh_video INTERFACE PNG::PNG) + list(APPEND VIDEO_PKG_STATUS "interface PNG") + elseif (TARGET PkgConfig::PNG) + target_link_libraries(simh_video INTERFACE PkgConfig::PNG) + list(APPEND VIDEO_PKG_STATUS "pkg-config PNG") + else () + target_include_directories(simh_video INTERFACE ${PNG_INCLUDE_DIRS}) + target_link_libraries(simh_video INTERFACE ${PNG_LIBRARIES}) + list(APPEND VIDEO_PKG_STATUS "detected PNG") + endif () + ENDIF (PNG_FOUND) + + set(BUILD_WITH_VIDEO TRUE) +ELSE () + set(VIDEO_PKG_STATUS "video support disabled") +ENDIF() + +if (WITH_REGEX) + ## TEMP: Use PCRE until patches for PCRE2 are avaiable. + ## + ## 1. Prefer PCRE2 over PCRE (unless PREFER_PCRE is set) + ## 2. Prefer interface libraries before using detected find_package + ## variables. + IF (TARGET PkgConfig::PCRE) + target_link_libraries(simh_regexp INTERFACE PkgConfig::PCRE) + if (PREFER_PCRE) + target_compile_definitions(simh_regexp INTERFACE HAVE_PCRE_H) + set(PCRE_PKG_STATUS "pkg-config pcre") + else () + target_compile_definitions(simh_regexp INTERFACE HAVE_PCRE2_H) + if (WIN32) + ## Use static linkage (vice DLL) on Windows: + target_compile_definitions(simh_regexp INTERFACE PCRE2_STATIC) + endif () + set(PCRE_PKG_STATUS "pkg-config pcre2") + endif () + ELSEIF (TARGET unofficial::pcre::pcre) + ## vcpkg: + target_link_libraries(simh_regexp INTERFACE unofficial::pcre::pcre) + target_compile_definitions(simh_regexp INTERFACE HAVE_PCRE_H) + target_compile_definitions(simh_regexp INTERFACE PCRE_STATIC) + set(PCRE_PKG_STATUS "vcpkg pcre") + ELSEIF (NOT PREFER_PCRE AND PCRE2_FOUND) + target_compile_definitions(simh_regexp INTERFACE HAVE_PCRE2_H) + target_include_directories(simh_regexp INTERFACE ${PCRE2_INCLUDE_DIRS}) + if (NOT WIN32) + target_link_libraries(simh_regexp INTERFACE ${PCRE2_LIBRARY}) + else () + ## Use static linkage (vice DLL) on Windows: + target_compile_definitions(simh_regexp INTERFACE PCRE2_STATIC) + endif () + + set(PCRE_PKG_STATUS "detected pcre2") + ELSEIF (PCRE_FOUND) + target_compile_definitions(simh_regexp INTERFACE HAVE_PCRE_H) + target_include_directories(simh_regexp INTERFACE ${PCRE_INCLUDE_DIRS}) + target_link_libraries(simh_regexp INTERFACE ${PCRE_LIBRARY}) + if (WIN32) + target_compile_definitions(simh_regexp INTERFACE PCRE_STATIC) + endif () + set(PCRE_PKG_STATUS "detected pcre") + endif () +endif () + +if ((WITH_REGEX OR WITH_VIDEO) AND ZLIB_FOUND) + target_compile_definitions(simh_regexp INTERFACE HAVE_ZLIB) + target_compile_definitions(simh_video INTERFACE HAVE_ZLIB) + if (TARGET ZLIB::ZLIB) + target_link_libraries(simh_regexp INTERFACE ZLIB::ZLIB) + target_link_libraries(simh_video INTERFACE ZLIB::ZLIB) + set(ZLIB_PKG_STATUS "interface ZLIB") + elseif (TARGET PkgConfig::ZLIB) + target_link_libraries(simh_regexp INTERFACE PkgConfig::ZLIB) + target_link_libraries(simh_video INTERFACE PkgConfig::ZLIB) + set(ZLIB_PKG_STATUS "pkg-config ZLIB") + else () + target_include_directories(simh_regexp INTERFACE ${ZLIB_INCLUDE_DIRS}) + target_link_libraries(simh_regexp INTERFACE ${ZLIB_LIBRARIES}) + target_include_directories(simh_video INTERFACE ${ZLIB_INCLUDE_DIRS}) + target_link_libraries(simh_video INTERFACE ${ZLIB_LIBRARIES}) + set(ZLIB_PKG_STATUS "detected ZLIB") + endif () +endif () + + +if (WITH_NETWORK) + set(network_runtime USE_SHARED) + ## pcap is special: Headers only and dynamically loaded. + if (WITH_PCAP) + find_package(PCAP) + + if (NOT PCAP_FOUND) + list(APPEND NETWORK_PKG_STATUS "PCAP dynamic (unpacked)") + + message(STATUS "Downloading ${LIBPCAP_SOURCE_URL}") + message(STATUS "Destination ${CMAKE_BINARY_DIR}/libpcap") + execute_process( + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/libpcap" + RESULT_VARIABLE LIBPCAP_MKDIR + ) + if (NOT (${LIBPCAP_MKDIR} EQUAL 0)) + message(FATAL_ERROR "Could not create ${CMAKE_CMAKE_BINARY_DIR}/libpcap") + endif (NOT (${LIBPCAP_MKDIR} EQUAL 0)) + + file(DOWNLOAD "${LIBPCAP_SOURCE_URL}" "${CMAKE_BINARY_DIR}/libpcap/libpcap.${LIBPCAP_ARCHIVE_TYPE}" + STATUS LIBPCAP_DOWNLOAD + ) + list(GET LIBPCAP_DOWNLOAD 0 LIBPCAP_DL_STATUS) + if (NOT (${LIBPCAP_DL_STATUS} EQUAL 0)) + list(GET LIBPCAP_DOWNLOAD 1 LIBPCAP_DL_ERROR) + message(FATAL_ERROR "Download failed: ${LIBPCAP_DL_ERROR}") + endif (NOT (${LIBPCAP_DL_STATUS} EQUAL 0)) + + message(STATUS "Extracting headers ${LIBPCAP_SOURCE_URL}") + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xvf "${CMAKE_BINARY_DIR}/libpcap/libpcap.${LIBPCAP_ARCHIVE_TYPE}" + "${LIBPCAP_PROJECT}-${LIBPCAP_ARCHIVE_NAME}-${LIBPCAP_RELEASE}/pcap.h" + "${LIBPCAP_PROJECT}-${LIBPCAP_ARCHIVE_NAME}-${LIBPCAP_RELEASE}/pcap/*.h" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/libpcap" + RESULT_VARIABLE LIBPCAP_EXTRACT + ) + if (NOT (${LIBPCAP_EXTRACT} EQUAL 0)) + message(FATAL_ERROR "Extract failed.") + endif (NOT (${LIBPCAP_EXTRACT} EQUAL 0)) + + message(STATUS "Copying headers from ${CMAKE_BINARY_DIR}/libpcap/${LIBPCAP_PROJECT}-${LIBPCAP_ARCHIVE_NAME}-${LIBPCAP_RELEASE}/pcap") + message(STATUS "Destination ${CMAKE_BINARY_DIR}/include/pcap") + execute_process( + COMMAND "${CMAKE_COMMAND}" -E copy_directory + "${LIBPCAP_PROJECT}-${LIBPCAP_ARCHIVE_NAME}-${LIBPCAP_RELEASE}/" + "${CMAKE_BINARY_DIR}/include/" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/libpcap" + RESULT_VARIABLE LIBPCAP_COPYDIR + ) + if (NOT (${LIBPCAP_COPYDIR} EQUAL 0)) + message(FATAL_ERROR "Copy failed.") + endif (NOT (${LIBPCAP_COPYDIR} EQUAL 0)) + + ## And try finding it again... + find_package(PCAP) + else () + list (APPEND NETWORK_PKG_STATUS "PCAP dynamic") + endif () + + + if (PCAP_FOUND) + set(network_runtime USE_SHARED) + foreach(hdr "${PCAP_INCLUDE_DIRS}") + file(STRINGS ${hdr}/pcap/pcap.h hdrcontent REGEX "pcap_compile *\\(.*const") + # message("hdrcontent: ${hdrcontent}") + list(LENGTH hdrcontent have_bpf_const) + if (${have_bpf_const} GREATER 0) + message(STATUS "pcap_compile requires BPF_CONST_STRING") + list(APPEND network_runtime BPF_CONST_STRING) + endif() + endforeach() + + target_include_directories(simh_network INTERFACE "${PCAP_INCLUDE_DIRS}") + target_compile_definitions(simh_network INTERFACE HAVE_PCAP_NETWORK) + endif () + endif () + + ## TAP/TUN devices + if (WITH_TAP) + target_compile_definitions(simh_network INTERFACE ${NETWORK_TUN_DEFS}) + endif (WITH_TAP) + + if (WITH_VDE AND VDE_FOUND) + if (TARGET PkgConfig::VDE) + target_compile_definitions(simh_network INTERFACE $) + target_include_directories(simh_network INTERFACE $) + target_link_libraries(simh_network INTERFACE PkgConfig::VDE) + list(APPEND NETWORK_PKG_STATUS "pkg-config VDE") + else () + target_include_directories(simh_network INTERFACE "${VDEPLUG_INCLUDE_DIRS}") + target_link_libraries(simh_network INTERFACE "${VDEPLUG_LIBRARY}") + list(APPEND NETWORK_PKG_STATUS "detected VDE") + endif () + + target_compile_definitions(simh_network INTERFACE HAVE_VDE_NETWORK) + endif () + + if (WITH_TAP) + if (HAVE_TAP_NETWORK) + target_compile_definitions(simh_network INTERFACE HAVE_TAP_NETWORK) + + if (HAVE_BSDTUNTAP) + target_compile_definitions(simh_network INTERFACE HAVE_BSDTUNTAP) + list(APPEND NETWORK_PKG_STATUS "BSD TUN/TAP") + else (HAVE_BSDTUNTAP) + list(APPEND NETWORK_PKG_STATUS "TAP") + endif (HAVE_BSDTUNTAP) + + endif (HAVE_TAP_NETWORK) + endif (WITH_TAP) + + if (WITH_SLIRP) + target_link_libraries(simh_network INTERFACE slirp) + list(APPEND NETWORK_PKG_STATUS "NAT(SLiRP)") + endif (WITH_SLIRP) + + ## Finally, set the network runtime + if (NOT network_runtime) + ## Default to USE_SHARED... USE_NETWORK is deprecated. + set(network_runtime USE_SHARED) + endif (NOT network_runtime) + + target_compile_definitions(simh_network INTERFACE ${network_runtime}) + + set(BUILD_WITH_NETWORK TRUE) +else (WITH_NETWORK) + set(NETWORK_STATUS "networking disabled") + set(NETWORK_PKG_STATUS "network disabled") + set(BUILD_WITH_NETWORK FALSE) +endif (WITH_NETWORK) diff --git a/cmake/dep-locate.cmake b/cmake/dep-locate.cmake new file mode 100644 index 00000000..bd810159 --- /dev/null +++ b/cmake/dep-locate.cmake @@ -0,0 +1,361 @@ +##=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= +## dep-locate.cmake +## +## Consolidated list of runtime dependencies for simh, probed/found via +## CMake's find_package() and pkg_check_modules() when 'pkgconfig' is +## available. +##=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= + +##-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ +## Find packages: +##-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ + +if (WITH_REGEX) + if (PREFER_PCRE) + if (USING_VCPKG) + find_package(unofficial-pcre CONFIG) + else () + ## LEGACY strategy: + find_package(PCRE) + endif () + else () + find_package(PCRE2) + endif () +endif () + +if (WITH_REGEX OR WITH_VIDEO) + set(ZLIB_USE_STATIC_LIBS ON) + find_package(ZLIB) +endif () + +if (WITH_VIDEO) + if (NOT USING_VCPKG) + ## LEGACY strategy: + find_package(PNG) + find_package(Freetype) + find_package(SDL2 NAMES sdl2 SDL2) + find_package(SDL2_ttf NAMES sdl2_ttf SDL2_ttf) + else () + ## vcpkg strategy: + find_package(PNG REQUIRED) + find_package(SDL2 CONFIG) + find_package(SDL2_ttf CONFIG) + endif () +endif () + +if (WITH_NETWORK) + if (WITH_VDE) + find_package(VDE) + endif () + + ## pcap is special: Headers only and dynamically loaded. + if (WITH_PCAP) + find_package(PCAP) + endif (WITH_PCAP) +endif (WITH_NETWORK) + +if (NOT WIN32 OR MINGW) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + if (WITH_REGEX) + if (PREFER_PCRE AND NOT PCRE_FOUND) + pkg_check_modules(PCRE IMPORTED_TARGET libpcre) + elseif (NOT PREFER_PCRE AND NOT PCRE2_FOUND) + pkg_check_modules(PCRE IMPORTED_TARGET libpcre2-8) + endif () + endif (WITH_REGEX) + + if (WITH_REGEX OR WITH_VIDEO) + if (NOT ZLIB_FOUND) + pkg_check_modules(ZLIB IMPORTED_TARGET zlib) + endif () + endif () + + if (WITH_VIDEO) + if (NOT PNG_FOUND) + pkg_check_modules(PNG IMPORTED_TARGET libpng16) + endif () + if (NOT SDL2_FOUND) + pkg_check_modules(SDL2 IMPORTED_TARGET sdl2) + if (NOT SDL2_FOUND) + pkg_check_modules(SDL2 IMPORTED_TARGET SDL2) + endif () + endif () + + if (NOT SDL2_ttf_FOUND) + pkg_check_modules(SDL2_ttf IMPORTED_TARGET SDL2_ttf) + if (NOT SDL2_ttf_FOUND) + pkg_check_modules(SDL2_ttf IMPORTED_TARGET sdl2_ttf) + endif () + endif () + endif (WITH_VIDEO) + + if (WITH_NETWORK) + if (WITH_VDE AND NOT VDE_FOUND) + pkg_check_modules(VDE IMPORTED_TARGET vdeplug) + endif () + endif (WITH_NETWORK) + endif () +endif () + +##-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ +## Add rules for the superbuild if dependencies need to be built: +##-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ + +if (NO_DEP_BUILD) + ## Not going to build dependencies... + return () +endif () + +include (ExternalProject) + +# Source URLs (to make it easy to update versions): +set(ZLIB_SOURCE_URL "https://github.com/madler/zlib/archive/v1.2.13.zip") +set(PCRE2_SOURCE_URL "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.40/pcre2-10.40.zip") +## PCRE needs multiple URLs to chase a working SF mirror: +list(APPEND PCRE_SOURCE_URL + "https://sourceforge.net/projects/pcre/files/pcre/8.45/pcre-8.45.zip/download?use_mirror=cytranet" + "https://sourceforge.net/projects/pcre/files/pcre/8.45/pcre-8.45.zip/download?use_mirror=phoenixnap" + "https://sourceforge.net/projects/pcre/files/pcre/8.45/pcre-8.45.zip/download?use_mirror=versaweb" + "https://sourceforge.net/projects/pcre/files/pcre/8.45/pcre-8.45.zip/download?use_mirror=netactuate" + "https://sourceforge.net/projects/pcre/files/pcre/8.45/pcre-8.45.zip/download?use_mirror=cfhcable" + "https://sourceforge.net/projects/pcre/files/pcre/8.45/pcre-8.45.zip/download?use_mirror=freefr" + "https://sourceforge.net/projects/pcre/files/pcre/8.45/pcre-8.45.zip/download?use_mirror=master" +) +set(PNG_SOURCE_URL "https://github.com/glennrp/libpng/archive/refs/tags/v1.6.40.tar.gz") +## Freetype also needs multiple URLs to chase a working mirror: +list(APPEND FREETYPE_SOURCE_URL + "https://github.com/freetype/freetype/archive/refs/tags/VER-2-13-0.zip" + "https://sourceforge.net/projects/freetype/files/freetype2/2.13.1/ft2131.zip/download?use_mirror=cytranet" + "https://sourceforge.net/projects/freetype/files/freetype2/2.13.1/ft2131.zip/download?use_mirror=phoenixnap" + "https://sourceforge.net/projects/freetype/files/freetype2/2.13.1/ft2131.zip/download?use_mirror=versaweb" + "https://sourceforge.net/projects/freetype/files/freetype2/2.13.1/ft2131.zip/download?use_mirror=netactuate" + "https://sourceforge.net/projects/freetype/files/freetype2/2.13.1/ft2131.zip/download?use_mirror=cfhcable" + "https://sourceforge.net/projects/freetype/files/freetype2/2.13.1/ft2131.zip/download?use_mirror=freefr" + "https://sourceforge.net/projects/freetype/files/freetype2/2.13.1/ft2131.zip/download?use_mirror=master" + "https://download.savannah.gnu.org/releases/freetype/freetype-2.13.1.tar.xz" + "https://gitlab.freedesktop.org/freetype/freetype/-/archive/VER-2-13-0/freetype-VER-2-13-0.zip" +) +set(SDL2_SOURCE_URL "https://github.com/libsdl-org/SDL/archive/refs/tags/release-2.28.1.zip") +set(SDL2_TTF_SOURCE_URL "https://github.com/libsdl-org/SDL_ttf/archive/refs/tags/release-2.20.2.zip") + +## Need to build ZLIB for both PCRE and libpng16: +if ((WITH_REGEX OR WITH_VIDEO) AND NOT ZLIB_FOUND) + ExternalProject_Add(zlib-dep + URL ${ZLIB_SOURCE_URL} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ## These patches come from vcpkg so that only the static libraries are built and + ## installed. If the patches don't apply cleanly (and there's a build error), that + ## means a version number got bumped and need to see what patches, if any, are + ## still applicable. + PATCH_COMMAND + git -c core.longpaths=true -c core.autocrlf=false --work-tree=. --git-dir=.git + apply + "${SIMH_DEP_PATCHES}/zlib/0001-Prevent-invalid-inclusions-when-HAVE_-is-set-to-0.patch" + "${SIMH_DEP_PATCHES}/zlib/0002-skip-building-examples.patch" + "${SIMH_DEP_PATCHES}/zlib/0003-build-static-or-shared-not-both.patch" + "${SIMH_DEP_PATCHES}/zlib/0004-android-and-mingw-fixes.patch" + --ignore-whitespace --whitespace=nowarn --verbose + ) + + BuildDepMatrix(zlib-dep zlib CMAKE_ARGS -DBUILD_SHARED_LIBS:Bool=${BUILD_SHARED_DEPS}) + + list(APPEND SIMH_BUILD_DEPS zlib) + list(APPEND SIMH_DEP_TARGETS zlib-dep) + message(STATUS "Building ZLIB from ${ZLIB_SOURCE_URL}.") + set(ZLIB_PKG_STATUS "ZLIB source build") +endif () + +IF (WITH_REGEX AND NOT (PCRE_FOUND OR PCRE2_FOUND OR TARGET unofficial::pcre::pcre)) + set(PCRE_DEPS) + IF (TARGET zlib-dep) + list(APPEND PCRE_DEPS zlib-dep) + ENDIF (TARGET zlib-dep) + + set(PCRE_CMAKE_ARGS -DBUILD_SHARED_LIBS:Bool=${BUILD_SHARED_DEPS}) + if (NOT PREFER_PCRE) + set(PCRE_URL ${PCRE2_SOURCE_URL}) + list(APPEND PCRE_CMAKE_ARGS + -DPCRE2_BUILD_PCREGREP:Bool=Off + -DPCRE2_SUPPORT_LIBEDIT:Bool=Off + -DPCRE2_SUPPORT_LIBREADLINE:Bool=Off + ) + + # IF(MSVC) + # list(APPEND PCRE_CMAKE_ARGS -DINSTALL_MSVC_PDB=On) + # ENDIF(MSVC) + + message(STATUS "Building PCRE2 from ${PCRE_URL}") + set(PCRE_PKG_STATUS "pcre2 source build") + ELSE () + set(PCRE_URL ${PCRE_SOURCE_URL}) + list(APPEND PCRE_CMAKE_ARGS + -DPCRE_BUILD_PCREGREP:Bool=Off + -DPCRE_SUPPORT_LIBEDIT:Bool=Off + -DPCRE_SUPPORT_LIBREADLINE:Bool=Off + ) + if (WIN32) + list(APPEND PCRE_CMAKE_ARGS + -DBUILD_SHARED_LIBS:Bool=Off + -DPCRE_STATIC_RUNTIME:Bool=On + ) + endif () + + message(STATUS "Building PCRE from ${PCRE_URL}") + set(PCRE_PKG_STATUS "pcre source build") + ENDIF () + + ExternalProject_Add(pcre-ext + URL + ${PCRE_URL} + DEPENDS + ${PCRE_DEPS} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + BuildDepMatrix(pcre-ext pcre CMAKE_ARGS ${PCRE_CMAKE_ARGS}) + + list(APPEND SIMH_BUILD_DEPS pcre) + list(APPEND SIMH_DEP_TARGETS pcre-ext) +ELSE () + set(PCRE_PKG_STATUS "regular expressions disabled") +ENDIF () + +set(BUILD_WITH_VIDEO FALSE) +IF (WITH_VIDEO) + IF (NOT PNG_FOUND) + set(PNG_DEPS) + if (NOT ZLIB_FOUND) + list(APPEND PNG_DEPS zlib-dep) + endif (NOT ZLIB_FOUND) + + ExternalProject_Add(png-dep + URL + ${PNG_SOURCE_URL} + DEPENDS + ${PNG_DEPS} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + ## Work around the GCC 8.1.0 SEH index regression. + set(PNG_CMAKE_BUILD_TYPE_RELEASE "Release") + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND + CMAKE_C_COMPILER_VERSION VERSION_EQUAL "8.1" AND + NOT CMAKE_BUILD_VERSION) + message(STATUS "PNG: Build using MinSizeRel CMAKE_BUILD_TYPE with GCC 8.1") + set(PNG_CMAKE_BUILD_TYPE_RELEASE "MinSizeRel") + endif() + + BuildDepMatrix(png-dep libpng + CMAKE_ARGS + -DPNG_SHARED:Bool=${BUILD_SHARED_DEPS} + -DPNG_STATUS:Bool=On + -DPNG_EXECUTABLES:Bool=Off + -DPNG_TESTS:Bool=Off + RELEASE_BUILD ${PNG_CMAKE_BUILD_TYPE_RELEASE} + ) + + list(APPEND SIMH_BUILD_DEPS "png") + list(APPEND SIMH_DEP_TARGETS "png-dep") + message(STATUS "Building PNG from ${PNG_SOURCE_URL}") + list(APPEND VIDEO_PKG_STATUS "PNG source build") + ENDIF (NOT PNG_FOUND) + + IF (NOT SDL2_FOUND) + ExternalProject_Add(sdl2-dep + URL ${SDL2_SOURCE_URL} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + BuildDepMatrix(sdl2-dep SDL2 CMAKE_ARGS "-DBUILD_SHARED_LIBS:Bool=${BUILD_SHARED_DEPS}") + + list(APPEND SIMH_BUILD_DEPS "SDL2") + list(APPEND SIMH_DEP_TARGETS "sdl2-dep") + message(STATUS "Building SDL2 from ${SDL2_SOURCE_URL}.") + list(APPEND VIDEO_PKG_STATUS "SDL2 source build") + ENDIF (NOT SDL2_FOUND) + + IF (NOT FREETYPE_FOUND) + set(FREETYPE_DEPS) + if (TARGET zlib-dep) + list(APPEND FREETYPE_DEPS zlib-dep) + endif () + if (TARGET png-dep) + list(APPEND FREETYPE_DEPS png-dep) + endif () + + ExternalProject_Add(freetype-dep + URL + ${FREETYPE_SOURCE_URL} + DEPENDS + ${FREETYPE_DEPS} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + BuildDepMatrix(freetype-dep Freetype + CMAKE_ARGS + "-DBUILD_SHARED_LIBS:Bool=${BUILD_SHARED_DEPS}" + "-DFT_DISABLE_BZIP2:Bool=TRUE" + "-DFT_DISABLE_HARFBUZZ:Bool=TRUE" + "-DFT_DISABLE_BROTLI:Bool=TRUE" + ) + + list(APPEND SIMH_BUILD_DEPS "Freetype") + list(APPEND SIMH_DEP_TARGETS freetype-dep) + message(STATUS "Building Freetype from ${FREETYPE_SOURCE_URL}.") + ENDIF () + + IF (NOT SDL2_ttf_FOUND) + set(SDL2_ttf_DEPS) + if (TARGET sdl2-dep) + list(APPEND SDL2_ttf_DEPS sdl2-dep) + endif (TARGET sdl2-dep) + if (TARGET freetype-dep) + list(APPEND SDL2_ttf_DEPS freetype-dep) + endif () + + ExternalProject_Add(sdl2-ttf-dep + URL + ${SDL2_TTF_SOURCE_URL} + DEPENDS + ${SDL2_ttf_DEPS} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + PATCH_COMMAND + git -c core.longpaths=true -c core.autocrlf=false --work-tree=. --git-dir=.git + apply + "${SIMH_DEP_PATCHES}/SDL_ttf/fix-pkgconfig.patch" + --ignore-whitespace --whitespace=nowarn --verbose + ) + + set(sdl2_ttf_cmake_args) + list(APPEND sdl2_ttf_cmake_args + "-DBUILD_SHARED_LIBS:Bool=${BUILD_SHARED_DEPS}" + "-DSDL2TTF_SAMPLES:Bool=Off" + "-DSDL2TTF_VENDORED:Bool=Off" + "-DSDL2TTF_HARFBUZZ:Bool=Off" + ) + + BuildDepMatrix(sdl2-ttf-dep SDL2_ttf CMAKE_ARGS ${sdl2_ttf_cmake_args}) + + list(APPEND SIMH_BUILD_DEPS "SDL2_ttf") + list(APPEND SIMH_DEP_TARGETS "sdl2-ttf-dep") + message(STATUS "Building SDL2_ttf from https://www.libsdl.org/release/SDL2_ttf-2.0.15.zip.") + list(APPEND VIDEO_PKG_STATUS "SDL2_ttf source build") + ENDIF (NOT SDL2_ttf_FOUND) + + set(BUILD_WITH_VIDEO TRUE) +ELSE () + set(VIDEO_PKG_STATUS "video support disabled") +ENDIF(WITH_VIDEO) diff --git a/cmake/diff-master.ps1 b/cmake/diff-master.ps1 new file mode 100644 index 00000000..8b8d2904 --- /dev/null +++ b/cmake/diff-master.ps1 @@ -0,0 +1,14 @@ +## Make looking at divergence from simh/master easier... + +$excludes = @( + "/*CMakeLists.txt", + "/.gitignore", + "/Visual Studio Projects/", + "/build_*.bat", + "/cmake/", + "/PDP8/tests/diags/*.pal", + "/PDP8/tests/diags/*.txt", + "/appveyor.yml" +) | % { "`":!" + $_ + "`"" } + +git diff --ignore-space-at-eol simh/master HEAD -- ${excludes} diff --git a/cmake/file-link-copy.cmake b/cmake/file-link-copy.cmake new file mode 100644 index 00000000..f686499c --- /dev/null +++ b/cmake/file-link-copy.cmake @@ -0,0 +1,50 @@ +## File link or copy +## +## Written initially for the VAX to link vax to microvax3900, this +## evolved into a more general-purpose utility. + +if (NOT SRCFILE) + message(FATAL_ERROR "SRCFILE not defined") +endif () +if (NOT DSTFILE) + mesasge(FATAL_ERROR "DSTFILE not defined") +endif () +if (NOT WORKING_DIR) + message(FATAL_ERROR "WORKING_DIR not defined") +endif () + +if (NOT EXISTS ${WORKING_DIR}) + message(FATAL_ERROR "Working directory does not exist: ${WORKING_DIR}") +endif () + +file(TO_NATIVE_PATH "${WORKING_DIR}/${SRCFILE}" _source) +file(TO_NATIVE_PATH "${WORKING_DIR}/${DSTFILE}" _dest) + +if (EXISTS ${_dest}) + message("Removing destination ${_dest}") + file(REMOVE ${_dest}) + if (EXISTS ${_dest}) + message(FATAL_ERROR "Could not remove ${_dest}") + endif () +endif () + +execute_process( + COMMAND + ${CMAKE_COMMAND} -E create_symlink ${SRCFILE} ${DSTFILE} + WORKING_DIRECTORY + ${WORKING_DIR} + RESULT_VARIABLE + _file_symlink + ERROR_QUIET +) + +if (NOT _file_symlink EQUAL 0) + file(CREATE_LINK ${_source} ${_dest} COPY_ON_ERROR RESULT _result) + if (NOT _result EQUAL 0) + message(FATAL_ERROR "Could not link or copy ${_source} to ${_dest}") + else () + message(":::: Hard link/copy ${_source} -> ${_dest}") + endif () +else () + message(":::: Symlink ${SRCFILE} -> ${DSTFILE} in ${WORKING_DIR}") +endif() diff --git a/cmake/fpintrin.cmake b/cmake/fpintrin.cmake new file mode 100644 index 00000000..7664de80 --- /dev/null +++ b/cmake/fpintrin.cmake @@ -0,0 +1,79 @@ +## Check for various GNU-specific floating point math flags +## +## Not entirely sure that they will make a huge difference to code +## generation in the simulators. + +set(EXTRA_TARGET_CFLAGS) + +set(CMAKE_REQUIRED_FLAGS "-msse") +check_c_source_compiles(" + #ifdef __MINGW32__ + #include <_mingw.h> + #ifdef __MINGW64_VERSION_MAJOR + #include + #else + #include + #endif + #else + #include + #endif + #ifndef __SSE__ + #error Assembler CPP flag not enabled + #endif + int main(int argc, char **argv) { }" HAVE_SSE) +if(HAVE_SSE) + list(APPEND EXTRA_TARGET_CFLAGS "-msse") +endif() +set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS}) + +set(CMAKE_REQUIRED_FLAGS "-msse2") +check_c_source_compiles(" + #ifdef __MINGW32__ + #include <_mingw.h> + #ifdef __MINGW64_VERSION_MAJOR + #include + #else + #include + #endif + #else + #include + #endif + #ifndef __SSE2__ + #error Assembler CPP flag not enabled + #endif + int main(int argc, char **argv) { }" HAVE_SSE2) +if(HAVE_SSE2) + list(APPEND EXTRA_TARGET_CFLAGS "-msse2") +endif() +set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS}) + +set(CMAKE_REQUIRED_FLAGS "-msse3") +check_c_source_compiles(" + #ifdef __MINGW32__ + #include <_mingw.h> + #ifdef __MINGW64_VERSION_MAJOR + #include + #else + #include + #endif + #else + #include + #endif + #ifndef __SSE3__ + #error Assembler CPP flag not enabled + #endif + int main(int argc, char **argv) { }" HAVE_SSE3) +if(HAVE_SSE3) + list(APPEND EXTRA_TARGET_CFLAGS "-msse3") +endif() +set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS}) + +if(SSE OR SSE2 OR SSE3) + if(USE_GCC) + check_c_compiler_flag(-mfpmath=387 HAVE_FP_387) + if(HAVE_FP_387) + list(APPEND EXTRA_TARGET_CFLAGS "-mfpmath=387") + endif() + endif() + set(HAVE_SSEMATH TRUE) +endif() diff --git a/cmake/generate.py b/cmake/generate.py new file mode 100644 index 00000000..1091ef68 --- /dev/null +++ b/cmake/generate.py @@ -0,0 +1,193 @@ +## generate.py +## +## Generate the simulator CMakeLists.txt from the top-level makefile. +## +## This is the top-level driver: process options, search for the +## makefile, parse the makefile and walk its dependencies, and, +## finally, output the CMakeLists.txt(s) and simh-simulators.cmake. +## +## Author: B. Scott Michel +## ("scooter me fecit") + +import sys +import os.path +import argparse +import re + +GEN_SCRIPT_DIR = os.path.dirname(__file__) +GEN_SCRIPT_NAME = os.path.basename(__file__) + +import pprint + +import simgen.cmake_container as SCC +import simgen.parse_makefile as SPM +import simgen.packaging as SPKG + + +def process_makefile(makefile_dir, debug=0): + the_makefile = os.path.join(makefile_dir, "makefile") + print('{0}: Processing {1}'.format(GEN_SCRIPT_NAME, the_makefile)) + + (defs, rules, actions) = SPM.parse_makefile(the_makefile) + if debug >= 4: + pprint.pp(defs) + + all_rule = rules.get('all') or rules.get('ALL') + if all_rule is None: + print('{0}: "all" rule not found. Cannot process.'.format(GEN_SCRIPT_NAME)) + + simulators = SCC.CMakeBuildSystem() + for all_targ in SPM.shallow_expand_vars(all_rule, defs).split(): + print("{0}: all target {1}".format(GEN_SCRIPT_NAME, all_targ)) + walk_target_deps(all_targ, defs, rules, actions, simulators, debug=debug) + + experimental_rule = rules.get('experimental') + if experimental_rule is not None: + for experimental_targ in SPM.shallow_expand_vars(experimental_rule, defs).split(): + print("{0}: exp target {1}".format(GEN_SCRIPT_NAME, experimental_targ)) + walk_target_deps(experimental_targ, defs, rules, actions, simulators, debug=debug) + + simulators.collect_vars(defs, debug=debug) + return simulators + + +## Makefile target dependencies to filter out. +_ignored_deps = [ + '${SIM}', + '${BUILD_ROMS}' +] + +## Simulator compile/link action pattern +_compile_act_rx = re.compile(r"\$[({]CC[)}]\s*(.*)") +_test_name_rx = re.compile(r"\$@\s*\$\(call\s+find_test,\s*(.*),(.*)\)\s+\$") + +def walk_target_deps(target, defs, rules, actions, simulators, depth='', debug=0): + """ Recursively walk a target's dependencies, i.e., the right hand side of a make rule. + Descend into each dependency to find something that looks like a simulator's + source code list. Once source code list is found, extract simulator defines, includes, + source files and set flags. + """ + if debug >= 1: + print('{0}-- target: {1}'.format(depth, target)) + + target_deps = SPM.target_dep_list(target, rules, defs) + + has_buildrom = any(filter(lambda dep: dep == '${BUILD_ROMS}', target_deps)) + if debug >= 1: + print('{0} has_buildrom {1}', has_buildrom) + + deps = [dep for dep in target_deps if dep not in _ignored_deps] + targ_actions = actions.get(target) + if targ_actions: + depth3 = depth + ' ' + if debug >= 2: + print('{0}deps {1}'.format(depth3, deps)) + + # Are the dependencies a source code list? + expanded_deps = [l for slist in [ SPM.shallow_expand_vars(dep, defs).split() for dep in deps ] for l in slist] + if debug >= 3: + print('{0}expanded_deps {1}'.format(depth3, expanded_deps)) + + if any(filter(lambda f: f.endswith('.c'), expanded_deps)): + if debug >= 1: + print('{0}sim sources {1}'.format(depth3, deps)) + if debug >= 2: + print('{0}targ_actions {1}'.format(depth3, targ_actions)) + + # The simulators' compile and test actions are very regular and easy to find: + compile_act = None + test_name = None + sim_dir = None + for act in targ_actions: + m_cact = _compile_act_rx.match(act) + m_test = _test_name_rx.match(act) + if m_cact: + compile_act = m_cact.group(1) + elif m_test: + (sim_dir, test_name) = m_test.group(1, 2) + + if debug >= 2: + print('{0}sim_dir {1}'.format(depth3, sim_dir)) + print('{0}compile_act {1}'.format(depth3, compile_act)) + print('{0}test_name {1}'.format(depth3, test_name)) + + if compile_act and test_name and sim_dir: + sim_name = target.replace("${BIN}", "").replace("${EXE}", "") + # Just in case there are vestiges of old-style make variables + sim_name = sim_name.replace("$(BIN)", "").replace("$(EXE)", "") + if debug >= 2: + print('{0}sim_name {1}'.format(depth3, sim_name)) + + simulators.extract(compile_act, test_name, sim_dir, sim_name, defs, has_buildrom, debug, depth+' ') + else: + # No actions associated with the dependency(ies), which means that the dependency(ies) + # are meta-targets. Continue to walk. + for dep in deps: + walk_target_deps(dep, defs, rules, actions, simulators, depth=depth+' ', debug=debug) + + +if __name__ == '__main__': + args = argparse.ArgumentParser(description="SIMH simulator CMakeLists.txt generator.") + args.add_argument('--debug', nargs='?', const=1, default=0, type=int, + help='Debug level (0-3, 0 == off)') + args.add_argument('--srcdir', default=None, + help='makefile source directory.') + args.add_argument('--orpanes', action='store_true', + help='Check for packaging orphans') + flags = vars(args.parse_args()) + + debug_level = flags.get('debug') + makefile_dir = flags.get('srcdir') + + found_makefile = True + if makefile_dir is None: + ## Find the makefile, which should be one directory up from this Python + ## module + makefile_dir = GEN_SCRIPT_DIR + print('{0}: Looking for makefile, starting in {1}'.format(GEN_SCRIPT_NAME, makefile_dir)) + the_makefile = '' + while makefile_dir: + the_makefile = os.path.join(makefile_dir, "makefile") + if os.path.exists(the_makefile): + break + else: + makefile_dir = os.path.dirname(makefile_dir) + print('{0}: Looking for makefile, trying {1}'.format(GEN_SCRIPT_NAME, makefile_dir)) + + if not the_makefile: + found_makefile = False + else: + the_makefile = os.path.join(makefile_dir, "makefile") + if not os.path.exists(the_makefile): + found_makefile = False + + if not found_makefile: + print('{0}: SIMH top-level makefile not found, relative to {1}'.format(GEN_SCRIPT_NAME, GEN_SCRIPT_DIR)) + sys.exit(1) + + sims = process_makefile(makefile_dir, debug=debug_level) + + ## Sanity check: Make sure that all of the simulators in SPKG.package_info have + ## been encountered + for simdir in sims.dirs.keys(): + for sim in sims.dirs[simdir].simulators.keys(): + SPKG.package_info[sim].encountered() + + if flags.get('orphans'): + print('{0}: Expecting to emit {1} simulators.'.format(GEN_SCRIPT_NAME, len(SPKG.package_info.keys()))) + + orphans = [ sim for sim, pkg_info in SPKG.package_info.items() if not pkg_info.was_processed() ] + if len(orphans) > 0: + print('{0}: Simulators not extracted from makefile:'.format(GEN_SCRIPT_NAME)) + for orphan in orphans: + print('{0}{1}'.format(' ' * 4, orphan)) + sys.exit(1) + + if debug_level >= 1: + pp = pprint.PrettyPrinter() + pp.pprint(sims) + + ## Emit all of the individual CMakeLists.txt + sims.write_simulators(makefile_dir, debug=debug_level) + ## Emit the packaging data + SPKG.write_packaging(makefile_dir) diff --git a/cmake/git-commit-id.cmake b/cmake/git-commit-id.cmake new file mode 100644 index 00000000..6c7df4e0 --- /dev/null +++ b/cmake/git-commit-id.cmake @@ -0,0 +1,89 @@ +## git-commit-id.cmake +## +## Get the current Git commit hash code and commit time, update +## .git-commit-id and .git-commit-id.h + +set(GIT_COMMIT_ID ${GIT_COMMIT_DEST}/.git-commit-id) +set(GIT_COMMIT_ID_H ${GIT_COMMIT_DEST}/.git-commit-id.h) + +find_program(GIT_COMMAND git) +if (GIT_COMMAND) + execute_process(COMMAND ${GIT_COMMAND} "log" "-1" "--pretty=%H" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE HAVE_GIT_COMMIT_HASH + OUTPUT_VARIABLE SIMH_GIT_COMMIT_HASH) + + execute_process(COMMAND ${GIT_COMMAND} "log" "-1" "--pretty=%aI" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE HAVE_GIT_COMMIT_TIME + OUTPUT_VARIABLE SIMH_GIT_COMMIT_TIME) + + execute_process(COMMAND ${GIT_COMMAND} "update-index" "--refresh" "--" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE HAVE_UNCOMMITTED_CHANGES + OUTPUT_VARIABLE SIMH_UNCOMMITTED_CHANGES) +endif () + +if (GIT_COMMAND AND NOT (HAVE_GIT_COMMIT_HASH OR HAVE_GIT_COMMIT_TIME)) + string(STRIP ${SIMH_GIT_COMMIT_HASH} SIMH_GIT_COMMIT_HASH) + string(STRIP ${SIMH_GIT_COMMIT_TIME} SIMH_GIT_COMMIT_TIME) + string(REPLACE "T" " " SIMH_GIT_COMMIT_TIME ${SIMH_GIT_COMMIT_TIME}) + + if (HAVE_UNCOMMITTED_CHANGES) + ## message(STATUS "Git detected uncommitted changes.") + string(APPEND SIMH_GIT_COMMIT_HASH "+uncommitted-changes") + else () + message(STATUS "Clean working directory, no uncommitted changes.") + endif () + + set(WRITE_GIT_COMMIT_FILES True) + if (EXISTS ${GIT_COMMIT_ID}) + set(EXISTING_GIT_COMMIT_HASH) + set(EXISTING_GIT_COMMIT_TIME) + file(STRINGS ${GIT_COMMIT_ID} git_info) + foreach (inp IN LISTS git_info) + if (inp MATCHES "SIM_GIT_COMMIT_ID (.*)") + set(EXISTING_GIT_COMMIT_HASH ${CMAKE_MATCH_1}) + elseif (inp MATCHES "SIM_GIT_COMMIT_TIME (.*)") + set(EXISTING_GIT_COMMIT_TIME ${CMAKE_MATCH_1}) + endif () + endforeach() + if (EXISTING_GIT_COMMIT_HASH STREQUAL SIMH_GIT_COMMIT_HASH AND + EXISTING_GIT_COMMIT_TIME STREQUAL SIMH_GIT_COMMIT_TIME) + ## message(STATUS "GIT hash and time match, not writing files.") + set(WRITE_GIT_COMMIT_FILES False) + endif () + endif () + + if (WRITE_GIT_COMMIT_FILES) + message(STATUS "Updating GIT commit ID") + message(STATUS "SIM_GIT_COMMIT_ID: ${SIMH_GIT_COMMIT_HASH}") + message(STATUS "SIM_GIT_COMMIT_TIME: ${SIMH_GIT_COMMIT_TIME}") + + message(STATUS "Writing ${GIT_COMMIT_ID}") + file(WRITE ${GIT_COMMIT_ID} + "SIM_GIT_COMMIT_ID ${SIMH_GIT_COMMIT_HASH}\n" + "SIM_GIT_COMMIT_TIME ${SIMH_GIT_COMMIT_TIME}\n") + + message(STATUS "Writing ${GIT_COMMIT_ID_H}") + file(WRITE ${GIT_COMMIT_ID_H} + "#define SIM_GIT_COMMIT_ID ${SIMH_GIT_COMMIT_HASH}\n" + "#define SIM_GIT_COMMIT_TIME ${SIMH_GIT_COMMIT_TIME}\n") + ## else () + ## message(STATUS "No changes to ${GIT_COMMIT_ID}") + ## message(STATUS "No changes to ${GIT_COMMIT_ID_H}") + endif () +else () + message(STATUS "SIM_GIT_COMMIT_ID not set.") + message(STATUS "SIM_GIT_COMMIT_TIME not set.") + + if (NOT EXISTS ${GIT_COMMIT_ID_H}) + message(STATUS "Writing default ${GIT_COMMIT_ID_H}") + file(WRITE ${GIT_COMMIT_ID_H} + "#undef SIM_GIT_COMMIT_ID\n" + "#undef SIM_GIT_COMMIT_TIME\n" + ) + else () + message(STATUS "Leaving ${GIT_COMMIT_ID_H} intact") + endif () +endif() diff --git a/cmake/github_v141_xp.ps1 b/cmake/github_v141_xp.ps1 new file mode 100644 index 00000000..bee747d9 --- /dev/null +++ b/cmake/github_v141_xp.ps1 @@ -0,0 +1,153 @@ +<# +.SYNOPSIS +Install Visual Studio's 'v141_xp' XP toolkit on Github. + +.DESCRIPTION +Update the existing Github Visual Studio installation in-place. This script +will iterate through all VS installations identified by the `vswhere` utility. + +This script is Grey Magic. The `vs_installer` installer utility exits almost +immediately if you run it from the command line. `vs_installer`'s subprocesses +are reasonably well known, which allows this script to query the processes and +wait for them to terminate. + +GitHub Actions does something strange with stdout and stderr, so you won't get any +indication of failure or output that shows you that something is happening. + +The waiting code was adapted from the Chocolatey VS installer scripts (Wait-VSIstallerProcesses). + +Ref: https://github.com/jberezanski/ChocolateyPackages/blob/master/chocolatey-visualstudio.extension/extensions/Wait-VSInstallerProcesses.ps1 +#> + +$exitcode = $null +$vswhere = "${env:ProgramFiles} (x86)\Microsoft Visual Studio\Installer\vswhere" +$vsinstaller = "${env:ProgramFiles} (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" +$vsInstallOut = "$env:TEMP\vsinstall-out.txt" +$vsInstallErr = "$env:TEMP\vsinstall-err.txt" + +& ${vswhere} -property installationPath | Foreach-Object -process { + # Save the installlation path for the current iteration + $installPath = $_ + + # Make sure that previously running installers have all exited. + Write-Debug ('Looking for previously running VS installer processes') + $lazyQuitterProcessNames = @('vs_installershell', 'vs_installerservice') + do + { + $lazyQuitterProcesses = Get-Process -Name $lazyQuitterProcessNames -ErrorAction SilentlyContinue | ` + Where-Object { $null -ne $_ -and -not $_.HasExited } + $lazyQuitterProcessCount = ($lazyQuitterProcesses | Measure-Object).Count + if ($lazyQuitterProcessCount -gt 0) + { + try + { + $lazyQuitterProcesses | Sort-Object -Property Name, Id | ForEach-Object { '[{0}] {1}' -f $_.Id, $_.Name } | Write-Debug + $lazyQuitterProcesses | Wait-Process -Timeout 10 -ErrorAction SilentlyContinue + } + finally + { + $lazyQuitterProcesses | ForEach-Object { $_.Dispose() } + $lazyQuitterProcesses = $null + } + } + } + while ($lazyQuitterProcessCount -gt 0) + + ## Now kick off our install: + ## + ## --quiet: Don't open/show UI + ## --force: Terminate any VS instances forcibly + ## --norestart: Delay reboot after install, if needed + ## --installWhileDownloading: Self-explanitory. + ## + ## Note: "--wait" doesn't. + $vsinstallParams = @( + "modify", + "--installPath", "$installPath", + "--add", "Microsoft.VisualStudio.Component.VC.v141.x86.x64", + "--add", "Microsoft.VisualStudio.Component.WinXP", + "--quiet", "--force", "--norestart", "--installWhileDownloading" + ) + + & $vsInstaller $vsinstallParams 2> $vsInstallErr > $vsInstallOut + + ## VS installer processes for which we want to wait because installation isn't complete. Yet. + $vsinstallerProcesses = @( 'vs_bootstrapper', 'vs_setup_bootstrapper', 'vs_installer', 'vs_installershell', ` + 'vs_installerservice', 'setup') + $vsInstallerProcessFilter = { $_.Name -ne 'setup' -or $_.Path -like '*\Microsoft Visual Studio\Installer*\setup.exe' } + do + { + Write-Debug ('Looking for running VS installer processes') + $vsInstallerRemaining = Get-Process -Name $vsinstallerProcesses -ErrorAction SilentlyContinue | ` + Where-Object { $null -ne $_ -and -not $_.HasExited } | ` + Where-Object $vsInstallerProcessFilter + $vsInstallerProcessCount = ($vsInstallerRemaining | Measure-Object).Count + if ($vsInstallerProcessCount -gt 0) + { + try + { + Write-Debug "Found $vsInstallerProcessCount running Visual Studio installer processes:" + $vsInstallerRemaining | Sort-Object -Property Name, Id | ForEach-Object { '[{0}] {1}' -f $_.Id, $_.Name } | Write-Debug + + foreach ($p in $vsInstallerProcesses) + { + [void] $p.Handle # make sure we get the exit code http://stackoverflow.com/a/23797762/266876 + } + + Write-Debug ('Waiting 60 seconds for process(es) to exit...') + $vsInstallerRemaining | Wait-Process -Timeout 60 -ErrorAction SilentlyContinue + + foreach ($proc in $vsInstallerProcesses) + { + if (-not $proc.HasExited) + { + continue + } + if ($null -eq $exitCode) + { + $exitCode = $proc.ExitCode + } + if ($proc.ExitCode -ne 0 -and $null -ne $proc.ExitCode) + { + Write-Debug "$($proc.Name) process $($proc.Id) exited with code $($proc.ExitCode)" + if ($exitCode -eq 0) + { + $exitCode = $proc.ExitCode + } + } + } + } + finally + { + $vsInstallerRemaining | ForEach-Object { $_.Dispose() } + $vsInstallerRemaining = $null + } + } + } + while (($vsInstallerStartup -and $vsInstallerStartCount -gt 0) -or $vsInstallerProcessCount -gt 0) +} + +if ((Test-Path $vsInstallOut -PathType Leaf) -and (Get-Item $vsInstallOut).length -gt 0kb) +{ + Write-Output "-- vsinstaller output:" + Get-Content $vsInstallOut +} +else +{ + Write-Debug "-- No vsinstaller output." +} + +if ((Test-Path $vsInstallErr -PathType Leaf) -and (Get-Item $vsInstallErr).length -gt 0kb) +{ + Write-Output "-- vsinstaller error output:" + Get-Content $vsInstallErr +} +else +{ + Write-Debug "-- No vsinstaller error/diag output." +} + +if ($null -ne $exitcode -and $exitcode -ne 0) +{ + throw "VS installer exited with non-zero exit status: $exitcode" +} diff --git a/cmake/installer-customizations/CPackSimhCustom.cmake.in b/cmake/installer-customizations/CPackSimhCustom.cmake.in new file mode 100644 index 00000000..47741782 --- /dev/null +++ b/cmake/installer-customizations/CPackSimhCustom.cmake.in @@ -0,0 +1,3 @@ +## Additional variables needed to drive CPack: + +file(TO_NATIVE_PATH "@CMAKE_SOURCE_DIR@/cmake/installer-customizations/NSIS" SIMH_NSIS_INCLUDE_DIR) diff --git a/cmake/installer-customizations/NSIS.template.in b/cmake/installer-customizations/NSIS.template.in new file mode 100644 index 00000000..4baf8986 --- /dev/null +++ b/cmake/installer-customizations/NSIS.template.in @@ -0,0 +1,1018 @@ +; CPack install script designed for a nmake build + +;-------------------------------- +; You must define these values + + !define VERSION "@CPACK_PACKAGE_VERSION@" + !define PATCH "@CPACK_PACKAGE_VERSION_PATCH@" + !define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@" + + !addincludedir "@SIMH_NSIS_INCLUDE_DIR@" + +;-------------------------------- +;Variables + + Var MUI_TEMP + Var STARTMENU_FOLDER + Var SV_ALLUSERS + Var START_MENU + Var DO_NOT_ADD_TO_PATH + Var ADD_TO_PATH_ALL_USERS + Var ADD_TO_PATH_CURRENT_USER + Var INSTALL_DESKTOP + Var IS_DEFAULT_INSTALLDIR +;-------------------------------- +;Include Modern UI + + !include "MUI.nsh" + + ;Default installation folder + InstallDir "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + +;-------------------------------- +;General + + ;Name and file + Name "@CPACK_NSIS_PACKAGE_NAME@" + OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@" + + ;Set compression + SetCompressor @CPACK_NSIS_COMPRESSOR@ + + ; Execution level: none, access, admin, user + ; User execution level -- there's nothing in SIMH that has to install + ; in ProgramFiles or ProgramFiles (x86) + RequestExecutionLevel user + +@CPACK_NSIS_DEFINES@ +@CPACK_NSIS_MANIFEST_DPI_AWARE_CODE@ +@CPACK_NSIS_BRANDING_TEXT_CODE@ + + !include Sections.nsh + +;-------------------------------- +; Symbolic and hard file link support: + + !include "FileFunc.nsh" + !include "FileLinks.nsh" + +;--- Component support macros: --- +; The code for the add/remove functionality is from: +; https://nsis.sourceforge.io/Add/Remove_Functionality +; It has been modified slightly and extended to provide +; inter-component dependencies. +Var AR_SecFlags +Var AR_RegFlags +@CPACK_NSIS_SECTION_SELECTED_VARS@ + +; Loads the "selected" flag for the section named SecName into the +; variable VarName. +!macro LoadSectionSelectedIntoVar SecName VarName + SectionGetFlags ${${SecName}} $${VarName} + IntOp $${VarName} $${VarName} & ${SF_SELECTED} ;Turn off all other bits +!macroend + +; Loads the value of a variable... can we get around this? +!macro LoadVar VarName + IntOp $R0 0 + $${VarName} +!macroend + +; Sets the value of a variable +!macro StoreVar VarName IntValue + IntOp $${VarName} 0 + ${IntValue} +!macroend + +!macro InitSection SecName + ; This macro reads component installed flag from the registry and + ;changes checked state of the section on the components page. + ;Input: section index constant name specified in Section command. + + ClearErrors + ;Reading component status from registry + ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" "Installed" + IfErrors "default_${SecName}" + ;Status will stay default if registry value not found + ;(component was never installed) + IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading default section flags + IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE ;Turn lowest (enabled) bit off + IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags ;Change lowest bit + + ; Note whether this component was installed before + !insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags + IntOp $R0 $AR_RegFlags & $AR_RegFlags + + ;Writing modified flags + SectionSetFlags ${${SecName}} $AR_SecFlags + + "default_${SecName}:" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected +!macroend + +!macro FinishSection SecName + ; This macro reads section flag set by user and removes the section + ;if it is not selected. + ;Then it writes component installed flag to registry + ;Input: section index constant name specified in Section command. + + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags + ;Checking lowest bit: + IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED} + IntCmp $AR_SecFlags 1 "leave_${SecName}" + ;Section is not selected: + ;Calling Section uninstall macro and writing zero installed flag + !insertmacro "Remove_${${SecName}}" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \ + "Installed" 0 + Goto "exit_${SecName}" + + "leave_${SecName}:" + ;Section is selected: + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \ + "Installed" 1 + + "exit_${SecName}:" +!macroend + +!macro RemoveSection_CPack SecName + ; This macro is used to call section's Remove_... macro + ;from the uninstaller. + ;Input: section index constant name specified in Section command. + + !insertmacro "Remove_${${SecName}}" +!macroend + +; Determine whether the selection of SecName changed +!macro MaybeSelectionChanged SecName + !insertmacro LoadVar ${SecName}_selected + SectionGetFlags ${${SecName}} $R1 + IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits + + ; See if the status has changed: + IntCmp $R0 $R1 "${SecName}_unchanged" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected + + IntCmp $R1 ${SF_SELECTED} "${SecName}_was_selected" + !insertmacro "Deselect_required_by_${SecName}" + goto "${SecName}_unchanged" + + "${SecName}_was_selected:" + !insertmacro "Select_${SecName}_depends" + + "${SecName}_unchanged:" +!macroend +;--- End of Add/Remove macros --- + +;-------------------------------- +;Interface Settings + + !define MUI_HEADERIMAGE + !define MUI_ABORTWARNING + +;---------------------------------------- +; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02" +;---------------------------------------- +!verbose 3 +!include "WinMessages.NSH" +!verbose 4 +;==================================================== +; get_NT_environment +; Returns: the selected environment +; Output : head of the stack +;==================================================== +!macro select_NT_profile UN +Function ${UN}select_NT_profile + StrCmp $ADD_TO_PATH_ALL_USERS "1" 0 environment_single + DetailPrint "Selected environment for all users" + Push "all" + Return + environment_single: + DetailPrint "Selected environment for current user only." + Push "current" + Return +FunctionEnd +!macroend +!insertmacro select_NT_profile "" +!insertmacro select_NT_profile "un." +;---------------------------------------------------- +!define NT_current_env 'HKCU "Environment"' +!define NT_all_env 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + +!ifndef WriteEnvStr_RegKey + !ifdef ALL_USERS + !define WriteEnvStr_RegKey \ + 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + !else + !define WriteEnvStr_RegKey 'HKCU "Environment"' + !endif +!endif + +; AddToPath - Adds the given dir to the search path. +; Input - head of the stack +; Note - Win9x systems requires reboot + +Function AddToPath + Exch $0 + Push $1 + Push $2 + Push $3 + + # don't add if the path doesn't exist + IfFileExists "$0\*.*" "" AddToPath_done + + ReadEnvStr $1 PATH + ; if the path is too long for a NSIS variable NSIS will return a 0 + ; length string. If we find that, then warn and skip any path + ; modification as it will trash the existing path. + StrLen $2 $1 + IntCmp $2 0 CheckPathLength_ShowPathWarning CheckPathLength_Done CheckPathLength_Done + CheckPathLength_ShowPathWarning: + Messagebox MB_OK|MB_ICONEXCLAMATION "Warning! PATH too long installer unable to modify PATH!" + Goto AddToPath_done + CheckPathLength_Done: + Push "$1;" + Push "$0;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$0\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + GetFullPathName /SHORT $3 $0 + Push "$1;" + Push "$3;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$3\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + + Call IsNT + Pop $1 + StrCmp $1 1 AddToPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" a + FileSeek $1 -1 END + FileReadByte $1 $2 + IntCmp $2 26 0 +2 +2 # DOS EOF + FileSeek $1 -1 END # write over EOF + FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n" + FileClose $1 + SetRebootFlag true + Goto AddToPath_done + + AddToPath_NT: + StrCmp $ADD_TO_PATH_ALL_USERS "1" ReadAllKey + ReadRegStr $1 ${NT_current_env} "PATH" + Goto DoTrim + ReadAllKey: + ReadRegStr $1 ${NT_all_env} "PATH" + DoTrim: + StrCmp $1 "" AddToPath_NTdoIt + Push $1 + Call Trim + Pop $1 + StrCpy $0 "$1;$0" + AddToPath_NTdoIt: + StrCmp $ADD_TO_PATH_ALL_USERS "1" WriteAllKey + WriteRegExpandStr ${NT_current_env} "PATH" $0 + Goto DoSend + WriteAllKey: + WriteRegExpandStr ${NT_all_env} "PATH" $0 + DoSend: + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + AddToPath_done: + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + + +; RemoveFromPath - Remove a given dir from the path +; Input: head of the stack + +Function un.RemoveFromPath + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + + IntFmt $6 "%c" 26 # DOS EOF + + Call un.IsNT + Pop $1 + StrCmp $1 1 unRemoveFromPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" r + GetTempFileName $4 + FileOpen $2 $4 w + GetFullPathName /SHORT $0 $0 + StrCpy $0 "SET PATH=%PATH%;$0" + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoop: + FileRead $1 $3 + StrCpy $5 $3 1 -1 # read last char + StrCmp $5 $6 0 +2 # if DOS EOF + StrCpy $3 $3 -1 # remove DOS EOF so we can compare + StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "" unRemoveFromPath_dosLoopEnd + FileWrite $2 $3 + Goto unRemoveFromPath_dosLoop + unRemoveFromPath_dosLoopRemoveLine: + SetRebootFlag true + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoopEnd: + FileClose $2 + FileClose $1 + StrCpy $1 $WINDIR 2 + Delete "$1\autoexec.bat" + CopyFiles /SILENT $4 "$1\autoexec.bat" + Delete $4 + Goto unRemoveFromPath_done + + unRemoveFromPath_NT: + StrCmp $ADD_TO_PATH_ALL_USERS "1" unReadAllKey + ReadRegStr $1 ${NT_current_env} "PATH" + Goto unDoTrim + unReadAllKey: + ReadRegStr $1 ${NT_all_env} "PATH" + unDoTrim: + StrCpy $5 $1 1 -1 # copy last char + StrCmp $5 ";" +2 # if last char != ; + StrCpy $1 "$1;" # append ; + Push $1 + Push "$0;" + Call un.StrStr ; Find `$0;` in $1 + Pop $2 ; pos of our dir + StrCmp $2 "" unRemoveFromPath_done + ; else, it is in path + # $0 - path to add + # $1 - path var + StrLen $3 "$0;" + StrLen $4 $2 + StrCpy $5 $1 -$4 # $5 is now the part before the path to remove + StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove + StrCpy $3 $5$6 + + StrCpy $5 $3 1 -1 # copy last char + StrCmp $5 ";" 0 +2 # if last char == ; + StrCpy $3 $3 -1 # remove last char + + StrCmp $ADD_TO_PATH_ALL_USERS "1" unWriteAllKey + WriteRegExpandStr ${NT_current_env} "PATH" $3 + Goto unDoSend + unWriteAllKey: + WriteRegExpandStr ${NT_all_env} "PATH" $3 + unDoSend: + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + unRemoveFromPath_done: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Uninstall stuff +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +########################################### +# Utility Functions # +########################################### + +;==================================================== +; IsNT - Returns 1 if the current system is NT, 0 +; otherwise. +; Output: head of the stack +;==================================================== +; IsNT +; no input +; output, top of the stack = 1 if NT or 0 if not +; +; Usage: +; Call IsNT +; Pop $R0 +; ($R0 at this point is 1 or 0) + +!macro IsNT un +Function ${un}IsNT + Push $0 + ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + StrCmp $0 "" 0 IsNT_yes + ; we are not NT. + Pop $0 + Push 0 + Return + + IsNT_yes: + ; NT!!! + Pop $0 + Push 1 +FunctionEnd +!macroend +!insertmacro IsNT "" +!insertmacro IsNT "un." + +; StrStr +; input, top of stack = string to search for +; top of stack-1 = string to search in +; output, top of stack (replaces with the portion of the string remaining) +; modifies no other variables. +; +; Usage: +; Push "this is a long ass string" +; Push "ass" +; Call StrStr +; Pop $R0 +; ($R0 at this point is "ass string") + +!macro StrStr un +Function ${un}StrStr +Exch $R1 ; st=haystack,old$R1, $R1=needle + Exch ; st=old$R1,haystack + Exch $R2 ; st=old$R1,old$R2, $R2=haystack + Push $R3 + Push $R4 + Push $R5 + StrLen $R3 $R1 + StrCpy $R4 0 + ; $R1=needle + ; $R2=haystack + ; $R3=len(needle) + ; $R4=cnt + ; $R5=tmp + loop: + StrCpy $R5 $R2 $R3 $R4 + StrCmp $R5 $R1 done + StrCmp $R5 "" done + IntOp $R4 $R4 + 1 + Goto loop +done: + StrCpy $R1 $R2 "" $R4 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Exch $R1 +FunctionEnd +!macroend +!insertmacro StrStr "" +!insertmacro StrStr "un." + +Function Trim ; Added by Pelaca + Exch $R1 + Push $R2 +Loop: + StrCpy $R2 "$R1" 1 -1 + StrCmp "$R2" " " RTrim + StrCmp "$R2" "$\n" RTrim + StrCmp "$R2" "$\r" RTrim + StrCmp "$R2" ";" RTrim + GoTo Done +RTrim: + StrCpy $R1 "$R1" -1 + Goto Loop +Done: + Pop $R2 + Exch $R1 +FunctionEnd + +Function ConditionalAddToRegistry + Pop $0 + Pop $1 + StrCmp "$0" "" ConditionalAddToRegistry_EmptyString + WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \ + "$1" "$0" + ;MessageBox MB_OK "Set Registry: '$1' to '$0'" + DetailPrint "Set install registry entry: '$1' to '$0'" + ConditionalAddToRegistry_EmptyString: +FunctionEnd + +;-------------------------------- + +!ifdef CPACK_USES_DOWNLOAD +Function DownloadFile + IfFileExists $INSTDIR\* +2 + CreateDirectory $INSTDIR + Pop $0 + + ; Skip if already downloaded + IfFileExists $INSTDIR\$0 0 +2 + Return + + StrCpy $1 "@CPACK_DOWNLOAD_SITE@" + + try_again: + NSISdl::download "$1/$0" "$INSTDIR\$0" + + Pop $1 + StrCmp $1 "success" success + StrCmp $1 "Cancelled" cancel + MessageBox MB_OK "Download failed: $1" + cancel: + Return + success: +FunctionEnd +!endif + +;-------------------------------- +; Define some macro setting for the gui +@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@ +@CPACK_NSIS_INSTALLER_ICON_CODE@ +@CPACK_NSIS_INSTALLER_MUI_WELCOMEFINISH_CODE@ +@CPACK_NSIS_INSTALLER_MUI_UNWELCOMEFINISH_CODE@ +@CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE@ + +;-------------------------------- +;Pages + @CPACK_NSIS_INSTALLER_WELCOME_TITLE_CODE@ + @CPACK_NSIS_INSTALLER_WELCOME_TITLE_3LINES_CODE@ + !insertmacro MUI_PAGE_WELCOME + + @CPACK_NSIS_LICENSE_PAGE@ + Page custom InstallOptionsPage + !insertmacro MUI_PAGE_DIRECTORY + + ;Start Menu Folder Page Configuration + !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" + !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" + !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER + + @CPACK_NSIS_PAGE_COMPONENTS@ + + !insertmacro MUI_PAGE_INSTFILES + @CPACK_NSIS_INSTALLER_FINISH_TITLE_CODE@ + @CPACK_NSIS_INSTALLER_FINISH_TITLE_3LINES_CODE@ + !insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" ;first language is the default language + !insertmacro MUI_LANGUAGE "Afrikaans" + !insertmacro MUI_LANGUAGE "Albanian" + !insertmacro MUI_LANGUAGE "Arabic" + !insertmacro MUI_LANGUAGE "Asturian" + !insertmacro MUI_LANGUAGE "Basque" + !insertmacro MUI_LANGUAGE "Belarusian" + !insertmacro MUI_LANGUAGE "Bosnian" + !insertmacro MUI_LANGUAGE "Breton" + !insertmacro MUI_LANGUAGE "Bulgarian" + !insertmacro MUI_LANGUAGE "Catalan" + !insertmacro MUI_LANGUAGE "Corsican" + !insertmacro MUI_LANGUAGE "Croatian" + !insertmacro MUI_LANGUAGE "Czech" + !insertmacro MUI_LANGUAGE "Danish" + !insertmacro MUI_LANGUAGE "Dutch" + !insertmacro MUI_LANGUAGE "Esperanto" + !insertmacro MUI_LANGUAGE "Estonian" + !insertmacro MUI_LANGUAGE "Farsi" + !insertmacro MUI_LANGUAGE "Finnish" + !insertmacro MUI_LANGUAGE "French" + !insertmacro MUI_LANGUAGE "Galician" + !insertmacro MUI_LANGUAGE "German" + !insertmacro MUI_LANGUAGE "Greek" + !insertmacro MUI_LANGUAGE "Hebrew" + !insertmacro MUI_LANGUAGE "Hungarian" + !insertmacro MUI_LANGUAGE "Icelandic" + !insertmacro MUI_LANGUAGE "Indonesian" + !insertmacro MUI_LANGUAGE "Irish" + !insertmacro MUI_LANGUAGE "Italian" + !insertmacro MUI_LANGUAGE "Japanese" + !insertmacro MUI_LANGUAGE "Korean" + !insertmacro MUI_LANGUAGE "Kurdish" + !insertmacro MUI_LANGUAGE "Latvian" + !insertmacro MUI_LANGUAGE "Lithuanian" + !insertmacro MUI_LANGUAGE "Luxembourgish" + !insertmacro MUI_LANGUAGE "Macedonian" + !insertmacro MUI_LANGUAGE "Malay" + !insertmacro MUI_LANGUAGE "Mongolian" + !insertmacro MUI_LANGUAGE "Norwegian" + !insertmacro MUI_LANGUAGE "NorwegianNynorsk" + !insertmacro MUI_LANGUAGE "Pashto" + !insertmacro MUI_LANGUAGE "Polish" + !insertmacro MUI_LANGUAGE "Portuguese" + !insertmacro MUI_LANGUAGE "PortugueseBR" + !insertmacro MUI_LANGUAGE "Romanian" + !insertmacro MUI_LANGUAGE "Russian" + !insertmacro MUI_LANGUAGE "ScotsGaelic" + !insertmacro MUI_LANGUAGE "Serbian" + !insertmacro MUI_LANGUAGE "SerbianLatin" + !insertmacro MUI_LANGUAGE "SimpChinese" + !insertmacro MUI_LANGUAGE "Slovak" + !insertmacro MUI_LANGUAGE "Slovenian" + !insertmacro MUI_LANGUAGE "Spanish" + !insertmacro MUI_LANGUAGE "SpanishInternational" + !insertmacro MUI_LANGUAGE "Swedish" + !insertmacro MUI_LANGUAGE "Tatar" + !insertmacro MUI_LANGUAGE "Thai" + !insertmacro MUI_LANGUAGE "TradChinese" + !insertmacro MUI_LANGUAGE "Turkish" + !insertmacro MUI_LANGUAGE "Ukrainian" + !insertmacro MUI_LANGUAGE "Uzbek" + !insertmacro MUI_LANGUAGE "Vietnamese" + !insertmacro MUI_LANGUAGE "Welsh" + +;-------------------------------- +;Reserve Files + + ;These files should be inserted before other files in the data block + ;Keep these lines before any File command + ;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA) + + ReserveFile "NSIS.InstallOptions.ini" + !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + + ; for UserInfo::GetName and UserInfo::GetAccountType + ReserveFile /plugin 'UserInfo.dll' + +;-------------------------------- +; Installation types +@CPACK_NSIS_INSTALLATION_TYPES@ + +;-------------------------------- +; Component sections +@CPACK_NSIS_COMPONENT_SECTIONS@ +@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@ +;-------------------------------- +;Installer Sections + +Section "-Core installation" + ;Use the entire tree produced by the INSTALL target. Keep the + ;list of directories here in sync with the RMDir commands below. + SetOutPath "$INSTDIR" + @CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@ + @CPACK_NSIS_FULL_INSTALL@ + + ;Store installation folder + WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR + + ;Create uninstaller + WriteUninstaller "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe" + Push "DisplayName" + Push "@CPACK_NSIS_DISPLAY_NAME@" + Call ConditionalAddToRegistry + Push "DisplayVersion" + Push "@CPACK_PACKAGE_VERSION@" + Call ConditionalAddToRegistry + Push "Publisher" + Push "@CPACK_PACKAGE_VENDOR@" + Call ConditionalAddToRegistry + Push "UninstallString" + Push "$\"$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe$\"" + Call ConditionalAddToRegistry + Push "NoRepair" + Push "1" + Call ConditionalAddToRegistry + + !ifdef CPACK_NSIS_ADD_REMOVE + ;Create add/remove functionality + Push "ModifyPath" + Push "$INSTDIR\AddRemove.exe" + Call ConditionalAddToRegistry + !else + Push "NoModify" + Push "1" + Call ConditionalAddToRegistry + !endif + + ; Optional registration + Push "DisplayIcon" + Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@" + Call ConditionalAddToRegistry + Push "HelpLink" + Push "@CPACK_NSIS_HELP_LINK@" + Call ConditionalAddToRegistry + Push "URLInfoAbout" + Push "@CPACK_NSIS_URL_INFO_ABOUT@" + Call ConditionalAddToRegistry + Push "Contact" + Push "@CPACK_NSIS_CONTACT@" + Call ConditionalAddToRegistry + !insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State" + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + + ;Create shortcuts + CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" +@CPACK_NSIS_CREATE_ICONS@ +@CPACK_NSIS_CREATE_ICONS_EXTRA@ + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe" + + ;Read a value from an InstallOptions INI file + !insertmacro MUI_INSTALLOPTIONS_READ $DO_NOT_ADD_TO_PATH "NSIS.InstallOptions.ini" "Field 2" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_ALL_USERS "NSIS.InstallOptions.ini" "Field 3" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_CURRENT_USER "NSIS.InstallOptions.ini" "Field 4" "State" + + ; Write special uninstall registry entries + Push "StartMenu" + Push "$STARTMENU_FOLDER" + Call ConditionalAddToRegistry + Push "DoNotAddToPath" + Push "$DO_NOT_ADD_TO_PATH" + Call ConditionalAddToRegistry + Push "AddToPathAllUsers" + Push "$ADD_TO_PATH_ALL_USERS" + Call ConditionalAddToRegistry + Push "AddToPathCurrentUser" + Push "$ADD_TO_PATH_CURRENT_USER" + Call ConditionalAddToRegistry + Push "InstallToDesktop" + Push "$INSTALL_DESKTOP" + Call ConditionalAddToRegistry + + !insertmacro MUI_STARTMENU_WRITE_END + +@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@ + +SectionEnd + +Section "-Add to path" + Push $INSTDIR\bin + StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath + StrCmp $DO_NOT_ADD_TO_PATH "1" doNotAddToPath 0 + Call AddToPath + doNotAddToPath: +SectionEnd + +;-------------------------------- +; Create custom pages +Function InstallOptionsPage + !insertmacro MUI_HEADER_TEXT "Install Options" "Choose options for installing @CPACK_NSIS_PACKAGE_NAME@" + !insertmacro MUI_INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini" + +FunctionEnd + +;-------------------------------- +; determine admin versus local install +Function un.onInit + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + Goto done + StrCmp $1 "Power" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + Goto done + + noLM: + ;Get installation folder from registry if available + + done: + +FunctionEnd + +;--- Add/Remove callback functions: --- +!macro SectionList MacroName + ;This macro used to perform operation on multiple sections. + ;List all of your components in following manner here. +@CPACK_NSIS_COMPONENT_SECTION_LIST@ +!macroend + +Section -FinishComponents + ;Removes unselected components and writes component status to registry + !insertmacro SectionList "FinishSection" + +!ifdef CPACK_NSIS_ADD_REMOVE + ; Get the name of the installer executable + System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1' + StrCpy $R3 $R0 + + ; Strip off the last 13 characters, to see if we have AddRemove.exe + StrLen $R1 $R0 + IntOp $R1 $R0 - 13 + StrCpy $R2 $R0 13 $R1 + StrCmp $R2 "AddRemove.exe" addremove_installed + + ; We're not running AddRemove.exe, so install it + CopyFiles $R3 $INSTDIR\AddRemove.exe + + addremove_installed: +!endif +SectionEnd +;--- End of Add/Remove callback functions --- + +;-------------------------------- +; Component dependencies +Function .onSelChange + !insertmacro SectionList MaybeSelectionChanged +FunctionEnd + +;-------------------------------- +;Uninstaller Section + +Section "Uninstall" + ReadRegStr $START_MENU SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" + ;MessageBox MB_OK "Start menu is in: $START_MENU" + ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "DoNotAddToPath" + ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathAllUsers" + ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathCurrentUser" + ;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS" + ReadRegStr $INSTALL_DESKTOP SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "InstallToDesktop" + ;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP " + +@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@ + + ;Remove files we installed. + ;Keep the list of directories here in sync with the File commands above. +@CPACK_NSIS_DELETE_FILES@ +@CPACK_NSIS_DELETE_DIRECTORIES@ + +!ifdef CPACK_NSIS_ADD_REMOVE + ;Remove the add/remove program + Delete "$INSTDIR\AddRemove.exe" +!endif + + ;Remove the uninstaller itself. + Delete "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe" + DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + ;Remove the installation directory if it is empty. + RMDir "$INSTDIR" + + ; Remove the registry entries. + DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + ; Removes all optional components + !insertmacro SectionList "RemoveSection_CPack" + + !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP + + Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS@ +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent directories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + startMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors startMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop + startMenuDeleteLoopDone: + + ; If the user changed the shortcut, then uninstall may not work. This should + ; try to fix it. + StrCpy $MUI_TEMP "$START_MENU" + Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent directories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + secondStartMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors secondStartMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop + secondStartMenuDeleteLoopDone: + + DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + Push $INSTDIR\bin + StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0 + Call un.RemoveFromPath + doNotRemoveFromPath: +SectionEnd + +;-------------------------------- +; determine admin versus local install +; Is install for "AllUsers" or "JustMe"? +; Default to "JustMe" - set to "AllUsers" if admin or on Win9x +; This function is used for the very first "custom page" of the installer. +; This custom page does not show up visibly, but it executes prior to the +; first visible page and sets up $INSTDIR properly... +; Choose different default installation folder based on SV_ALLUSERS... +; "Program Files" for AllUsers, "My Documents" for JustMe... + +Function .onInit + StrCmp "@CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL@" "ON" 0 inst + + ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString" + StrCmp $0 "" inst + + MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \ + "@CPACK_NSIS_PACKAGE_NAME@ is already installed. $\n$\nDo you want to uninstall the old version before installing the new one?" \ + /SD IDYES IDYES uninst IDNO inst + Abort + +;Run the uninstaller +uninst: + ClearErrors + # $0 should _always_ be quoted, however older versions of CMake did not + # do this. We'll conditionally remove the begin/end quotes. + # Remove first char if quote + StrCpy $2 $0 1 0 # copy first char + StrCmp $2 "$\"" 0 +2 # if char is quote + StrCpy $0 $0 "" 1 # remove first char + # Remove last char if quote + StrCpy $2 $0 1 -1 # copy last char + StrCmp $2 "$\"" 0 +2 # if char is quote + StrCpy $0 $0 -1 # remove last char + + StrLen $2 "\@CPACK_NSIS_UNINSTALL_NAME@.exe" + StrCpy $3 $0 -$2 # remove "\@CPACK_NSIS_UNINSTALL_NAME@.exe" from UninstallString to get path + ExecWait '"$0" /S _?=$3' ;Do not copy the uninstaller to a temp file + + IfErrors uninst_failed inst +uninst_failed: + MessageBox MB_OK|MB_ICONSTOP "Uninstall failed." + Abort + + +inst: + ; Reads components status for registry + !insertmacro SectionList "InitSection" + + ; check to see if /D has been used to change + ; the install directory by comparing it to the + ; install directory that is expected to be the + ; default + StrCpy $IS_DEFAULT_INSTALLDIR 0 + StrCmp "$INSTDIR" "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" 0 +2 + StrCpy $IS_DEFAULT_INSTALLDIR 1 + + StrCpy $SV_ALLUSERS "JustMe" + ; if default install dir then change the default + ; if it is installed for JustMe + StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 + StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +4 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + StrCmp $1 "Power" 0 +4 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + + noLM: + StrCpy $SV_ALLUSERS "AllUsers" + ;Get installation folder from registry if available + + done: + StrCmp $SV_ALLUSERS "AllUsers" 0 +3 + StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 + StrCpy $INSTDIR "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + + StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 noOptionsPage + !insertmacro MUI_INSTALLOPTIONS_EXTRACT "NSIS.InstallOptions.ini" + + noOptionsPage: +FunctionEnd + +Function .onInstSuccess + MessageBox MB_OK "Installed successfully!" + +FunctionEnd \ No newline at end of file diff --git a/cmake/installer-customizations/NSIS/FileLinks.nsh b/cmake/installer-customizations/NSIS/FileLinks.nsh new file mode 100644 index 00000000..81e30b1b --- /dev/null +++ b/cmake/installer-customizations/NSIS/FileLinks.nsh @@ -0,0 +1,198 @@ +; misc +!define CreateParentFolder "!insertmacro CreateParentFolder" + +!macro CreateParentFolder Path + Push $1 + ${GetParent} "${Path}" $1 + CreateDirectory "$1" + Pop $1 +!macroend + +; info +!define IsLink "!insertmacro IsLink" +!define IsSoftLink "!insertmacro IsSoftLink" +!define IsHardLink "!insertmacro IsHardLink" + +Function IsSoftLink + Exch $0 + ${GetFileAttributes} "$0" "REPARSE_POINT" $0 + + ${If} $0 != "1" + StrCpy $0 "0" + ${EndIf} + Exch $0 +FunctionEnd + +!macro IsSoftLink Path outVar + Push "${Path}" + Call IsSoftLink + Pop ${outVar} +!macroend + +Function IsHardLink + Exch $1 + System::Call "kernel32::CreateFileW(w `$1`, i 0x40000000, i 0, i 0, i 3, i 0, i 0) i .r0" + + ${If} $0 = "-1" + StrCpy $0 "0" + goto is_hard_link_end + ${EndIf} + + System::Call "*(&i256 0) i. r1" + System::Call "kernel32::GetFileInformationByHandle(i r0, i r1) i .s" + System::Call "kernel32::CloseHandle(i r0) i.r0" + Pop $0 + + ${If} $0 == "0" + goto is_hard_link_end + ${EndIf} + + System::Call "*$1(&i40 0, &i4 .r0)" + + ${If} $0 != "0" + IntOp $0 $0 - 1 + ${EndIf} + + is_hard_link_end: + Pop $1 +FunctionEnd + +!macro IsHardLink Path outVar + Push $0 + Push "${Path}" + Call IsHardLink + StrCpy ${outVar} $0 + Pop $0 +!macroend + +!macro IsLink Path outVar + ${IsSoftLink} "${Path}" ${outVar} + + ${If} ${outVar} == 0 + ${IsHardLink} "${Path}" ${outVar} + ${EndIf} +!macroend + +; files +!define CreateHardLink "!insertmacro CreateHardLink" +!define CreateSymbolicLinkFile "!insertmacro CreateSymbolicLinkFile" +!define CreateLinkFile "!insertmacro CreateLinkFile" +!define DeleteLinkFile "!insertmacro DeleteLinkFile" + +!macro CreateSymbolicLinkFile Junction Target outVar + ${CreateParentFolder} "${Junction}" + System::Call "kernel32::CreateSymbolicLinkW(w `${Junction}`, w `${Target}`, i 0) i .s" + Pop ${outVar} + + ${If} ${outVar} == "error" + StrCpy ${outVar} "0" + ${EndIf} +!macroend + +!macro CreateHardLink Junction Target outVar + ${CreateParentFolder} "${Junction}" + System::Call "kernel32::CreateHardLinkW(w `${Junction}`, w `${Target}`, i 0) i .s" + Pop ${outVar} +!macroend + +!macro CreateLinkFile Junction Target outVar + ${CreateSymbolicLinkFile} "${Junction}" "${Target}" ${outVar} + + ${If} ${outVar} == 0 + ${CreateHardLink} "${Junction}" "${Target}" ${outVar} + ${EndIf} +!macroend + +!macro DeleteLinkFile Path outVar + ${IsLink} "${Path}" ${outVar} + + ${If} ${outVar} != 0 + SetFileAttributes "${Path}" "NORMAL" + System::Call "kernel32::DeleteFileW(w `${Path}`) i.s" + Pop ${outVar} + ${EndIf} +!macroend + +; folders +!define CreateJunction "!insertmacro CreateJunction" +!define CreateSymbolicLinkFolder "!insertmacro CreateSymbolicLinkFolder" +!define CreateLinkFolder "!insertmacro CreateLinkFolder" +!define DeleteLinkFolder "!insertmacro DeleteLinkFolder" + +Function CreateJunction + Exch $4 + Exch + Exch $5 + Push $1 + Push $2 + Push $3 + Push $6 + CreateDirectory "$5" + System::Call "kernel32::CreateFileW(w `$5`, i 0x40000000, i 0, i 0, i 3, i 0x02200000, i 0) i .r6" + + ${If} $0 = "-1" + StrCpy $0 "0" + RMDir "$5" + goto create_junction_end + ${EndIf} + + CreateDirectory "$4" ; Windows XP requires that the destination exists + StrCpy $4 "\??\$4" + StrLen $0 $4 + IntOp $0 $0 * 2 + IntOp $1 $0 + 2 + IntOp $2 $1 + 10 + IntOp $3 $1 + 18 + System::Call "*(i 0xA0000003, &i4 $2, &i2 0, &i2 $0, &i2 $1, &i2 0, &w$1 `$4`, &i2 0)i.r2" + System::Call "kernel32::DeviceIoControl(i r6, i 0x900A4, i r2, i r3, i 0, i 0, *i r4r4, i 0) i.r0" + System::Call "kernel32::CloseHandle(i r6) i.r1" + + ${If} $0 == "0" + RMDir "$5" + ${EndIf} + + create_junction_end: + Pop $6 + Pop $3 + Pop $2 + Pop $1 + Pop $5 + Pop $4 +FunctionEnd + +!macro CreateJunction Junction Target outVar + Push $0 + Push "${Junction}" + Push "${Target}" + Call CreateJunction + StrCpy ${outVar} $0 + Pop $0 +!macroend + +!macro CreateSymbolicLinkFolder Junction Target outVar + ${CreateParentFolder} "${Junction}" + System::Call "kernel32::CreateSymbolicLinkW(w `${Junction}`, w `${Target}`, i 1) i .s" + Pop ${outVar} + + ${If} ${outVar} == "error" + StrCpy ${outVar} "0" + ${EndIf} +!macroend + +!macro CreateLinkFolder Junction Target outVar + ${CreateSymbolicLinkFolder} "${Junction}" "${Target}" ${outVar} + + ${If} ${outVar} == 0 + ${CreateJunction} "${Junction}" "${Target}" ${outVar} + ${EndIf} +!macroend + +!macro DeleteLinkFolder Path outVar + ${IsSoftLink} "${Path}" ${outVar} + + ${If} ${outVar} != 0 + SetFileAttributes "${Path}" "NORMAL" + System::Call "kernel32::RemoveDirectoryW(w `${Path}`) i.s" + Pop ${outVar} + ${EndIf} +!macroend \ No newline at end of file diff --git a/cmake/os-features.cmake b/cmake/os-features.cmake new file mode 100644 index 00000000..d0741b4f --- /dev/null +++ b/cmake/os-features.cmake @@ -0,0 +1,207 @@ +## Various and sundry operating system features. +## +## Author: B. Scott Michel +## "scooter me fecit" + +include(CheckSymbolExists) +include(CMakePushCheckState) + +include(pthreads-dep) + +set(NEED_LIBRT FALSE) + +add_library(os_features INTERFACE) + +## Editline support? +find_package(EDITLINE) +if (TARGET Editline::Editline) + target_link_libraries(os_features INTERFACE Editline::Editline) +endif () + +if (WITH_ASYNC) + ## semaphores and sem_timedwait support (OS feature): + check_include_file(semaphore.h semaphore_h_found) + if (semaphore_h_found) + cmake_push_check_state() + + get_property(zz_thread_defs TARGET thread_lib PROPERTY INTERFACE_COMPILE_DEFINITIONS) + get_property(zz_thread_incs TARGET thread_lib PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + get_property(zz_thread_lopts TARGET thread_lib PROPERTY INTERFACE_LINK_OPTIONS) + get_property(zz_thread_libs TARGET thread_lib PROPERTY INTERFACE_LINK_LIBRARIES) + + list(APPEND CMAKE_REQUIRE_DEFINITIONS ${zz_thread_defs}) + list(APPEND CMAKE_REQUIRED_INCLUDES ${zz_thread_incs}) + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${zz_thread_lopts}) + list(APPEND CMAKE_REQUIRED_LIBRARIES ${zz_thread_libs}) + + check_symbol_exists(sem_timedwait semaphore.h have_sem_timedwait) + + if (NOT have_sem_timedwait) + ## Maybe it's in librt, like shm_open (and more likely, it's not.) + list(APPEND CMAKE_REQUIRED_LIBRARIES rt) + check_symbol_exists(sem_timedwait semaphore.h have_sem_timedwait_rt) + if (have_sem_timedwait_rt) + set(NEED_LIBRT TRUE) + endif (have_sem_timedwait_rt) + endif (NOT have_sem_timedwait) + + cmake_pop_check_state() + + if (have_sem_timedwait OR have_sem_timedwait_rt) + target_compile_definitions(os_features INTERFACE HAVE_SEMAPHORE) + endif () + endif (semaphore_h_found) +endif (WITH_ASYNC) + +## Note: We could use this to enforce better type safety with file I/O. +## +## _LARGEFILE64_SOURCE and _FILE_OFFSET_BITS for Linux +## check_type_size(off_t SIZE_OFF_T) +## if (SIZE_OFF_T) +## target_compile_definitions(os_features INTERFACE SIZE_OFF_T=${SIZE_OFF_T}) +## endif () +## +## check_type_size(off64_t SIZE_OFF64_T) +## if (NOT SIZE_OFF64_T) +## set(xxx_CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}) +## list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1) +## check_type_size(off64_t SIZE_OFF64_T) +## set(xxx_CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}) +## +## if (SIZE_OFF64_T) +## target_compile_definitions(os_features INTERFACE _FILE_OFFSET_BITS=64 _LARGEFILE64_SOURCE=1) +## endif () +## endif() +## +## if (SIZE_OFF64_T) +## target_compile_definitions(os_features INTERFACE SIZE_OFF64_T=${SIZE_OFF64_T}) +## endif () + +if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang") + target_compile_definitions(os_features INTERFACE _GNU_SOURCE) +endif () + +## +check_include_file(sys/ioctl.h have_sys_ioctl_h) +if (have_sys_ioctl_h) + target_compile_definitions(os_features INTERFACE HAVE_SYS_IOCTL) +endif (have_sys_ioctl_h) + +## +check_include_file(linux/cdrom.h have_linux_cdrom_h) +if (have_linux_cdrom_h) + target_compile_definitions(os_features INTERFACE HAVE_LINUX_CDROM) +endif (have_linux_cdrom_h) + +## +check_include_file(utime.h have_utime_h) +if (have_utime_h) + target_compile_definitions(os_features INTERFACE HAVE_UTIME) +endif (have_utime_h) + +## +check_include_file(glob.h have_glob_h) +if (have_glob_h) + target_compile_definitions(os_features INTERFACE HAVE_GLOB) +else () + ## + check_include_file(fnmatch.h have_fnmatch_h) + if (have_fnmatch_h) + target_compile_definitions(os_features INTERFACE HAVE_FNMATCH) + endif (have_fnmatch_h) +endif (have_glob_h) + +## and shm_open +check_include_file(sys/mman.h have_sys_mman_h) +if (have_sys_mman_h) + cmake_push_check_state() + + check_symbol_exists(shm_open sys/mman.h have_shm_open) + + if (NOT have_shm_open OR NEED_LIBRT) + ## Linux: shm_open is in the rt library? + set(CMAKE_REQUIRED_LIBRARIES rt) + check_symbol_exists(shm_open sys/mman.h have_shm_open_lrt) + endif (NOT have_shm_open OR NEED_LIBRT) + + if (have_shm_open OR have_shm_open_lrt) + target_compile_definitions(os_features INTERFACE HAVE_SHM_OPEN) + endif (have_shm_open OR have_shm_open_lrt) + if (have_shm_open_lrt) + set(NEED_LIBRT TRUE) + endif (have_shm_open_lrt) + + cmake_pop_check_state() +endif (have_sys_mman_h) + +IF (NEED_LIBRT) + target_link_libraries(os_features INTERFACE rt) +ENDIF (NEED_LIBRT) + +check_include_file(dlfcn.h have_dlfcn_h) +if (have_dlfcn_h) + cmake_push_check_state() + + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS}) + check_symbol_exists(dlopen dlfcn.h have_dlopen) + + if (have_dlopen) + target_link_libraries(os_features INTERFACE ${CMAKE_DL_LIBS}) + + set(dlext ${CMAKE_SHARED_LIBRARY_SUFFIX}) + string(REPLACE "." "" dlext "${dlext}") + target_compile_definitions(os_features INTERFACE SIM_HAVE_DLOPEN=${dlext}) + endif (have_dlopen) + + cmake_pop_check_state() +endif (have_dlfcn_h) + +if (NOT MSVC AND NOT (WIN32 AND CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + # Need the math library on non-Windows platforms + target_link_libraries(os_features INTERFACE m) +endif () + +set(HAVE_TAP_NETWORK False) +set(HAVE_BSDTUNTAP False) + +if (WITH_NETWORK) + ## TAP/TUN devices + if (WITH_TAP) + check_include_file(linux/if_tun.h if_tun_found) + + if (NOT if_tun_found) + check_include_file(net/if_tun.h net_if_tun_found) + if (net_if_tun_found OR EXISTS /Library/Extensions/tap.kext) + set(HAVE_BSDTUNTAP True) + endif (net_if_tun_found OR EXISTS /Library/Extensions/tap.kext) + endif (NOT if_tun_found) + + if (if_tun_found OR net_if_tun_found) + set(HAVE_TAP_NETWORK True) + endif (if_tun_found OR net_if_tun_found) + endif (WITH_TAP) +endif (WITH_NETWORK) + +## Windows: winmm (for ms timer functions), socket functions (even when networking is +## disabled. Also squelch the deprecation warnings (these warnings can be enabled +## via the -DWINAPI_DEPRECATION:Bool=On flag at configure time.) +if (WIN32) + target_link_libraries(os_features INTERFACE ws2_32 wsock32 winmm) + target_compile_definitions(os_features INTERFACE HAVE_WINMM) + if (NOT WINAPI_DEPRECATION) + target_compile_definitions(os_features INTERFACE + _WINSOCK_DEPRECATED_NO_WARNINGS + _CRT_NONSTDC_NO_WARNINGS + _CRT_SECURE_NO_WARNINGS + ) + endif () +endif () + +## Cygwin also wants winmm. Note: Untested but should work. +if (CYGWIN) + check_library_exists(winmm timeGetTime "" HAS_WINMM) + if (HAS_WINMM) + target_link_libraries(os_features INTERFACE ws2_32 wsock32 winmm) + target_compile_definitions(os_features INTERFACE HAVE_WINMM) + endif () +endif () diff --git a/cmake/patches/SDL_ttf/fix-pkgconfig.patch b/cmake/patches/SDL_ttf/fix-pkgconfig.patch new file mode 100644 index 00000000..590eaf51 --- /dev/null +++ b/cmake/patches/SDL_ttf/fix-pkgconfig.patch @@ -0,0 +1,22 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 4ea903d..35be59d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -325,7 +325,7 @@ if(SDL2TTF_INSTALL) + COMPONENT devel + ) + +- if(SDL2TTF_BUILD_SHARED_LIBS) ++ if(1) + # Only create a .pc file for a shared SDL2_ttf + set(prefix "${CMAKE_INSTALL_PREFIX}") + set(exec_prefix "\${prefix}") +@@ -353,7 +353,7 @@ if(SDL2TTF_INSTALL) + \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttf.pc\") + file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${PC_DESTDIR}\" + TYPE FILE +- FILES \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttf.pc\")" CONFIG Release) ++ FILES \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttf.pc\")") + endif() + + if(SDL2TTF_BUILD_SHARED_LIBS AND (APPLE OR (UNIX AND NOT ANDROID))) diff --git a/cmake/patches/zlib/0001-Prevent-invalid-inclusions-when-HAVE_-is-set-to-0.patch b/cmake/patches/zlib/0001-Prevent-invalid-inclusions-when-HAVE_-is-set-to-0.patch new file mode 100644 index 00000000..8fe2b2f5 --- /dev/null +++ b/cmake/patches/zlib/0001-Prevent-invalid-inclusions-when-HAVE_-is-set-to-0.patch @@ -0,0 +1,53 @@ +diff --git a/zconf.h.cmakein b/zconf.h.cmakein +index a7f24cc..a1b359b 100644 +--- a/zconf.h.cmakein ++++ b/zconf.h.cmakein +@@ -434,11 +434,19 @@ typedef uLong FAR uLongf; + #endif + + #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +-# define Z_HAVE_UNISTD_H ++# if ~(~HAVE_UNISTD_H + 0) == 0 && ~(~HAVE_UNISTD_H + 1) == 1 ++# define Z_HAVE_UNISTD_H ++# elif HAVE_UNISTD_H != 0 ++# define Z_HAVE_UNISTD_H ++# endif + #endif + + #ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +-# define Z_HAVE_STDARG_H ++# if ~(~HAVE_STDARG_H + 0) == 0 && ~(~HAVE_STDARG_H + 1) == 1 ++# define Z_HAVE_STDARG_H ++# elif HAVE_STDARG_H != 0 ++# define Z_HAVE_STDARG_H ++# endif + #endif + + #ifdef STDC +diff --git a/zconf.h.in b/zconf.h.in +index 5e1d68a..32f53c8 100644 +--- a/zconf.h.in ++++ b/zconf.h.in +@@ -432,11 +432,19 @@ typedef uLong FAR uLongf; + #endif + + #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +-# define Z_HAVE_UNISTD_H ++# if ~(~HAVE_UNISTD_H + 0) == 0 && ~(~HAVE_UNISTD_H + 1) == 1 ++# define Z_HAVE_UNISTD_H ++# elif HAVE_UNISTD_H != 0 ++# define Z_HAVE_UNISTD_H ++# endif + #endif + + #ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +-# define Z_HAVE_STDARG_H ++# if ~(~HAVE_STDARG_H + 0) == 0 && ~(~HAVE_STDARG_H + 1) == 1 ++# define Z_HAVE_STDARG_H ++# elif HAVE_STDARG_H != 0 ++# define Z_HAVE_STDARG_H ++# endif + #endif + + #ifdef STDC + diff --git a/cmake/patches/zlib/0002-skip-building-examples.patch b/cmake/patches/zlib/0002-skip-building-examples.patch new file mode 100644 index 00000000..8183f2ab --- /dev/null +++ b/cmake/patches/zlib/0002-skip-building-examples.patch @@ -0,0 +1,17 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b412dc7..f46c8e6 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -194,6 +194,7 @@ endif() + # Example binaries + #============================================================================ + ++if (0) + add_executable(example test/example.c) + target_link_libraries(example zlib) + add_test(example example) +@@ -211,3 +212,4 @@ if(HAVE_OFF64_T) + target_link_libraries(minigzip64 zlib) + set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") + endif() ++endif() diff --git a/cmake/patches/zlib/0003-build-static-or-shared-not-both.patch b/cmake/patches/zlib/0003-build-static-or-shared-not-both.patch new file mode 100644 index 00000000..c9f2ecf1 --- /dev/null +++ b/cmake/patches/zlib/0003-build-static-or-shared-not-both.patch @@ -0,0 +1,53 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index f46c8e6..6fa5575 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -121,9 +121,11 @@ set(ZLIB_SRCS + ) + + if(NOT MINGW) ++ if(BUILD_SHARED_LIBS) + set(ZLIB_DLL_SRCS + win32/zlib1.rc # If present will override custom build rule below. + ) ++ endif() + endif() + + # parse the full version number from zlib.h and include in ZLIB_FULL_VERSION +@@ -144,13 +146,16 @@ if(MINGW) + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) ++ if(BUILD_SHARED_LIBS) + set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) ++ endif() + endif(MINGW) + +-add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +-add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) ++add_library(zlib ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) ++if (BUILD_SHARED_LIBS) + set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) + set_target_properties(zlib PROPERTIES SOVERSION 1) ++endif() + + if(NOT CYGWIN) + # This property causes shared libraries on Linux to have the full version +@@ -165,7 +170,7 @@ endif() + + if(UNIX) + # On unix-like platforms the library is almost always called libz +- set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) ++ set_target_properties(zlib PROPERTIES OUTPUT_NAME z) + if(NOT APPLE) + set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") + endif() +@@ -175,7 +180,7 @@ elseif(BUILD_SHARED_LIBS AND WIN32) + endif() + + if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) +- install(TARGETS zlib zlibstatic ++ install(TARGETS zlib + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) diff --git a/cmake/patches/zlib/0004-android-and-mingw-fixes.patch b/cmake/patches/zlib/0004-android-and-mingw-fixes.patch new file mode 100644 index 00000000..e93173f2 --- /dev/null +++ b/cmake/patches/zlib/0004-android-and-mingw-fixes.patch @@ -0,0 +1,31 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6fa5575..7c345db 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -56,7 +56,7 @@ endif() + # + check_include_file(unistd.h Z_HAVE_UNISTD_H) + +-if(MSVC) ++if(WIN32) + set(CMAKE_DEBUG_POSTFIX "d") + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) +@@ -133,7 +133,7 @@ file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) + string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" + "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) + +-if(MINGW) ++if(MINGW AND NOT ANDROID) + # This gets us DLL resource information when compiling on MinGW. + if(NOT CMAKE_RC_COMPILER) + set(CMAKE_RC_COMPILER windres.exe) +@@ -149,7 +149,7 @@ if(MINGW) + if(BUILD_SHARED_LIBS) + set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) + endif() +-endif(MINGW) ++endif(MINGW AND NOT ANDROID) + + add_library(zlib ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) + if (BUILD_SHARED_LIBS) diff --git a/cmake/platform-quirks.cmake b/cmake/platform-quirks.cmake new file mode 100644 index 00000000..2113fec9 --- /dev/null +++ b/cmake/platform-quirks.cmake @@ -0,0 +1,266 @@ +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the names of The Authors shall not be +# used in advertising or otherwise to promote the sale, use or other dealings +# in this Software without prior written authorization from the Authors. + +## platform_quirks.cmake +## +## This is the place where the CMake build handles various platform quirks, +## such as architecture-specific prefixes (Linux, Windows) and MacOS +## HomeBrew +## +## Author: B. Scott Michel +# "scooter me fecit" + + +set(EXTRA_TARGET_CFLAGS) +set(EXTRA_TARGET_CFLAGS) + +# For 64-bit builds (and this is especially true for MSVC), set the library +# architecture. +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + ## Strongly encourage (i.e., force) CMake to look in the x64 architecture + ## directories: + if (MSVC OR MINGW) + # set(CMAKE_C_LIBRARY_ARCHITECTURE "x64") + # set(CMAKE_LIBRARY_ARCHITECTURE "x64") + elseif (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux") + ## Linux has architecture-specific subdirectories where CMake needs to + ## search for headers. Currently, we know about x64 and ARM architecture + ## variants. + foreach (arch "x86_64-linux-gnu" "aarch64-linux-gnu" "arm-linux-gnueabihf") + if (EXISTS "/usr/lib/${arch}") + message(STATUS "CMAKE_LIBRARY_ARCHITECTURE set to ${arch}") + set(CMAKE_C_LIBRARY_ARCHITECTURE "${arch}") + set(CMAKE_LIBRARY_ARCHITECTURE "${arch}") + endif() + endforeach() + endif () +endif() + +if (WIN32) + ## At some point, bring this back in to deal with MS ISO C99 deprecation. + ## Right now, it's not in the code base and the warnings are squelched. + ## + ## (keep): if (MSVC_VERSION GREATER_EQUAL 1920) + ## (keep): add_compile_definitions(USE_ISO_C99_NAMES) + ## (keep): endif () + + if (MSVC) + ## Flags enabled in the SIMH VS solution (diff redution): + ## + ## /EHsc: Standard C++ exception handling, extern "C" functions never + ## throw exceptions. + ## /FC: Output full path name of source in diagnostics + ## /GF: String pooling + ## /GL: Whole program optimization + ## /Gy: Enable function-level linking + ## /Oi: Emit intrinsic functions + ## /Ot: Favor fast code + ## /Oy: Suppress generating a stack frame (??? why?) + add_compile_options("$<$:/EHsc;/GF;/Gy;/Oi;/Ot;/Oy;/Zi>") + add_compile_options("$<$:/EHsc;/FC>") + + if (RELEASE_LTO) + ## /LTCG: Link-Time Code Generation. Pair with /GL at compile time. + add_compile_options("$<$:/GL>") + add_link_options("$<$:/LTCG>") + message(STATUS "Adding LTO to Release compiler and linker flags") + endif () + + ## Set the MSVC runtime. Note CMP0091 policy is set to new early on in + ## the top-level CMakeLists.txt + if (BUILD_SHARED_DEPS) + set(use_rtdll "$<$") + else () + set(use_rtdll "") + endif () + + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>${use_rtll}") + + ## Disable automagic add for _MBCS: + add_definitions(-D_SBCS) + + if (CMAKE_VERSION VERSION_LESS "3.23") + ## -5 Evil hack to ensure that find_package() can match against an empty + ## prefix and not trigger the "CMAKE_FIND_LIBRARY_PREFIXES not set" bug. + list(APPEND CMAKE_FIND_LIBRARY_PREFIXES "lib" "|") + endif () + + list(APPEND EXTRA_TARGET_CFLAGS + "$<$:$<$:/W4>>" + "$<$:/W3>" + ) + + ## Uncomment this line if you end up with /NODEFAULTLIB warninigs. You will also + ## need to build with the '--verbose' flag and check the values of "/M*" flags + ## (typically you should see /MT or /MTd for the static runtime libraries.) + ## + # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /verbose:lib") + + if (WARNINGS_FATAL) + message(STATUS "WARNINGS_FATAL: Compiler warnings are errors!! (/WX)") + list(APPEND EXTRA_TARGET_CFLAGS "/WX") + endif () + endif () +elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + # The MSVC solution builds as 32-bit, but none of the *nix platforms do. + # + # If 32-bit compiles have to be added back, uncomment the following 2 lines: + # + # add_compile_options("-m32") + # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") +endif () + + +if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang") + # include(fpintrin) + + # Turn on warnings about strict overflow/potential overflows. + ## LIST(APPEND EXTRA_TARGET_CFLAGS "-Wall" "-fno-inline" "-fstrict-overflow" "-Wstrict-overflow=3") + LIST(APPEND EXTRA_TARGET_CFLAGS + "-U__STRICT_ANSI__" + "$<$:$<$:-Wall>>" + ## Only add if WARNINGS_FATAL set; has undesirable consequences with LTO. + "$<$:-Wall>" + ) + + # 07 NOV 2022: Apparently, -O3 is kosher now. + # + # 'O3' optimization and strict overflow cause all kinds of simulator issues, especially inside + # the VAX simulators. Reduce optimization and ensure strict overflow is turned off. + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + set(update_o2 TRUE) + if (NOT MINGW) + if (RELEASE_LTO AND (NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "Release")) + check_c_compiler_flag("-flto" GCC_LTO_FLAG) + if (GCC_LTO_FLAG) + message(STATUS "Adding LTO to Release compiler and linker flags") + set(lto_flag "$<$:-flto>") + list(APPEND EXTRA_TARGET_CFLAGS "${lto_flag}") + list(APPEND EXTRA_TARGET_LFLAGS "${lto_flag}") + set(update_o2 FALSE) + else () + message(STATUS "Compiler does not support Link Time Optimization.") + endif () + else () + message(STATUS "Link Time Optimization NOT ENABLED.") + endif () + elseif (MINGW) + message(STATUS "MinGW: Link Time Optimization BROKEN, not added to Release flags") + endif () + + if (update_o2) + message(STATUS "Replacing '-O3' with '-O2'") + string(REGEX REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + string(REGEX REPLACE "-O3" "-O2" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") + endif () + + if (WARNINGS_FATAL` OR RELEASE_LTO) + check_c_compiler_flag("-Werror" GCC_W_ERROR_FLAG) + if (GCC_W_ERROR_FLAG) + if (WARNINGS_FATAL) + message(STATUS "WARNINGS_FATAL: Compiler warnings are errors!! (-Werror)") + list(APPEND EXTRA_TARGET_CFLAGS "-Werror") + endif () + if (RELEASE_LTO) + message(STATUS "WARNINGS_FATAL: Link-time optimization warnings are errors!! (-Werror)") + list(APPEND EXTRA_TARGET_LFLAGS "-Werror") + endif () + endif () + endif () + + message(STATUS "Adding GNU-specific optimizations to CMAKE_C_FLAGS_RELEASE") + list(APPEND opt_flags "-finline-functions" "-fgcse-after-reload" "-fpredictive-commoning" + "-fipa-cp-clone" "-fno-unsafe-loop-optimizations" "-fno-strict-overflow") + elseif (CMAKE_C_COMPILER_ID MATCHES ".*Clang") + message(STATUS "Adding Clang-specific optimizations to CMAKE_C_FLAGS_RELEASE") + list(APPEND opt_flags "-fno-strict-overflow") + endif() + + foreach (opt_flag ${opt_flags}) + message(STATUS " ${opt_flag}") + string(REGEX REPLACE "${opt_flag}[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + string(APPEND CMAKE_C_FLAGS_RELEASE " ${opt_flag}") + string(REGEX REPLACE "${opt_flag}[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") + string(APPEND CMAKE_C_FLAGS_MINSIZEREL " ${opt_flag}") + endforeach () +else () + message(STATUS "Not changing CMAKE_C_FLAGS_RELEASE on ${CMAKE_C_COMPILER_ID}") +endif () + + +if (CMAKE_HOST_APPLE) + ## Look for app bundles and frameworks after looking for Unix-style packages: + set(CMAKE_FIND_FRAMEWORK "LAST") + set(CMAKE_FIND_APPBUNDLE "LAST") + + if (EXISTS "/usr/local/Cellar" OR EXISTS "/opt/homebrew/Cellar") + ## Smells like HomeBrew. Bulk add the includes and library subdirectories + message(STATUS "Adding HomeBrew paths to library and include search") + set(hb_topdir "/usr/local/Cellar") + if (EXISTS "/opt/homebrew/Cellar") + set(hb_topdir "/opt/homebrew/Cellar") + endif() + + file(GLOB hb_lib_candidates LIST_DIRECTORIES TRUE "${hb_topdir}/*/*/lib") + file(GLOB hb_include_candidates LIST_DIRECTORIES TRUE "${hb_topdir}/*/*/include") + + # message("@@ lib candidates ${hb_lib_candidates}") + # message("@@ inc candidates ${hb_include_candidates}") + + set(hb_libs "") + foreach (hb_path ${hb_lib_candidates}) + if (IS_DIRECTORY "${hb_path}") + # message("@@ consider ${hb_path}") + list(APPEND hb_libs "${hb_path}") + endif() + endforeach() + + set(hb_includes "") + foreach (hb_path ${hb_include_candidates}) + if (IS_DIRECTORY "${hb_path}") + # message("@@ consider ${hb_path}") + list(APPEND hb_includes "${hb_path}") + endif() + endforeach() + + # message("hb_libs ${hb_libs}") + # message("hb_includes ${hb_includes}") + + list(PREPEND CMAKE_LIBRARY_PATH ${hb_libs}) + list(PREPEND CMAKE_INCLUDE_PATH ${hb_includes}) + + unset(hb_lib_candidates) + unset(hb_include_candidates) + unset(hb_includes) + unset(hb_libs) + unset(hb_path) + elseif(EXISTS /opt/local/bin/port) + # MacPorts + list(PREPEND CMAKE_LIBRARY_PATH /opt/local/lib) + list(PREPEND CMAKE_INCLUDE_PATH /opt/local/include) + endif() + + ## Universal binaries? + if (MAC_UNIVERSAL) + set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64") + endif () +endif() diff --git a/cmake/pthreads-dep.cmake b/cmake/pthreads-dep.cmake new file mode 100644 index 00000000..ff7b0614 --- /dev/null +++ b/cmake/pthreads-dep.cmake @@ -0,0 +1,76 @@ +#~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= +# Manage the pthreads dependency +# +# (a) Try to locate the system's installed pthreads library, which is very +# platform dependent (MSVC -> Pthreads4w, MinGW -> pthreads, *nix -> pthreads.) +# (b) MSVC: Build Pthreads4w as a dependent +#~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~= + +add_library(thread_lib INTERFACE) +set(AIO_FLAGS) + +if (WITH_ASYNC) + include(ExternalProject) + + if (MSVC OR (WIN32 AND CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + # Pthreads4w: pthreads for windows. + if (USING_VCPKG) + find_package(PThreads4W REQUIRED) + target_link_libraries(thread_lib INTERFACE PThreads4W::PThreads4W) + set(THREADING_PKG_STATUS "vcpkg PThreads4W") + else () + find_package(PTW) + + if (PTW_FOUND) + target_compile_definitions(thread_lib INTERFACE PTW32_STATIC_LIB) + target_include_directories(thread_lib INTERFACE ${PTW_INCLUDE_DIRS}) + target_link_libraries(thread_lib INTERFACE ${PTW_C_LIBRARY}) + + set(THREADING_PKG_STATUS "detected PTW/PThreads4W") + else () + ## Would really like to build from the original jwinarske repo, but it + ## ends up installing in ${CMAKE_INSTALL_PREFIX}/> prefix. + ## Which completely breaks how CMake Find*.cmake works. + ## + ## set(PTHREADS4W_URL "https://github.com/jwinarske/pthreads4w") + ## set(PTHREADS4W_URL "https://github.com/bscottm/pthreads4w") + set(PTHREADS4W_URL "https://github.com/bscottm/pthreads4w/archive/refs/tags/version-3.1.0-release.zip") + + ExternalProject_Add(pthreads4w-ext + URL ${PTHREADS4W_URL} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + BuildDepMatrix(pthreads4w-ext pthreads4w + # CMAKE_ARGS + # -DDIST_ROOT=${SIMH_DEP_TOPDIR} + ) + + list(APPEND SIMH_BUILD_DEPS pthreads4w) + list(APPEND SIMH_DEP_TARGETS pthreads4w-ext) + message(STATUS "Building Pthreads4w from ${PTHREADS4W_URL}") + set(THREADING_PKG_STATUS "pthreads4w source build") + endif () + endif () + else () + # Let CMake determine which threading library ought be used. + set(THREADS_PREFER_PTHREAD_FLAG On) + find_package(Threads) + if (THREADS_FOUND) + target_link_libraries(thread_lib INTERFACE Threads::Threads) + endif (THREADS_FOUND) + + set(THREADING_PKG_STATUS "Platform-detected threading support") + endif () + + if (THREADS_FOUND OR PTW_FOUND OR PThreads4W_FOUND) + set(AIO_FLAGS USE_READER_THREAD SIM_ASYNCH_IO) + else () + set(AIO_FLAGS DONT_USE_READER_THREAD) + endif () +else() + target_compile_definitions(thread_lib INTERFACE DONT_USE_READER_THREAD) + set(THREADING_PKG_STATUS "asynchronous I/O disabled.") +endif() diff --git a/cmake/simgen/__pycache__/basic_simulator.cpython-310.pyc b/cmake/simgen/__pycache__/basic_simulator.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2e43287a35f44f3a77326ecd46ba714fcbcc515 GIT binary patch literal 12221 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 literal 0 HcmV?d00001 diff --git a/cmake/simgen/__pycache__/packaging.cpython-310.pyc b/cmake/simgen/__pycache__/packaging.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..acff598d9856cce51886b35c424814e7c6531f91 GIT binary patch literal 7513 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 YNS94fw7+bZ@|VzqO+5qWpn1*zKOQz(9{>OV literal 0 HcmV?d00001 diff --git a/cmake/simgen/__pycache__/utils.cpython-310.pyc b/cmake/simgen/__pycache__/utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..56a763c676c014b684e4783d3503599231a4473c GIT binary patch literal 416 zcmZWky-ve05Vm8dgwXCt@B)z#egTA#*t>M=g4)lTZWfZg<;>I3)-lXJ@;c>?#h0Fp>*$ePGZvUjqklFJ-8lXOL@ z**A2MWzCRIhB0n<2KUzhBN^!~cV!@B_C_geTqQr!WkqA&JG~DTi(DQyCgw&Rl!?sx z=1ANHjQ`w;wzEn&UALmqp&houYwJaAH#>!4qxND5+W7naHI~Zi@FLZAXgDgE0Tgsj z`LDZ#@Sju)#UvHGQJO>X>2k#!7F`Yy*`^MuIzfT8LUz+7%skF<>aKv`oy@6pFy&{1 W_>!BZA8aQFqaIPhq>~hE&i??$r%giu literal 0 HcmV?d00001 diff --git a/cmake/simgen/__pycache__/vax_simulators.cpython-310.pyc b/cmake/simgen/__pycache__/vax_simulators.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e83e5be1a642d39c6bb87a3c1161f321070984a1 GIT binary patch literal 2501 zcmbUj$!^<5ltWS*YbTAHxLXd2>$YYATS1pYfh4FbQLYf15=1IZga8AYL)lD7(Vd~v z*p^QTkW>G`KKcXt8@-p;o_fwLK!LtTO0r@%MbZ)YG<@^+Z5YkZYZ9za_kQ>OC`i(u z_%gdxc=-Vy@ihP@F%n22>B&UekeJMr=Mqyq`H}KW>8XHGSq?BcPlfj!BbKD+{{lYA zbP>)jW&9$(f{iEj2$Om;BR%DX)F-LrVozm7mS=_Mq?daksZuWw@=D2-bw~K_z3P3- z4~KyhNBmVzE5mYgGYW8@hX?h%Tm%qH&!l5AA|rXEjMNjAfH#(OO3YI^$%)~f$CDzZ z{=knZJ;&OBui-Ir!v) zuWJ(<8%cqAeP6_rLI6LzPt^gUiU$`H8$$a`p$Baq7AMwzM`Fr3;QUuaq$UGqD=wXr< zG54G>$%B4x5c3ZK$v;AHWeOIM@Ny<~>Irg-IRF~DL^PtpPy74e#>H5lq6V!2KMhKSLD8Ck0AbDW*(bP zU@a6SmCVTtN{YSELr8{8tO0mq4;9jm%CY?O(o7!}leyUz;@Bq_3Te_n95r!lDUK*! zLXeuAdXU}#FH`NXem9$VYgbh zI<-b~)3^=%6EfqzQR~{(^-Y6X-A1E%|7eE3ZrLe)=)({Lrf True if there is a specific display used by the simulator. + self.has_display = False + ## self.uses_video -> True if USE_SIM_VIDEO appears in the simulator's preprocessor defn's. + self.uses_video = False + ## self.besm6_sdl_hack -> Only set/used by the BESM6 simulator. + self.besm6_sdl_hack = False + ## self.uses_aio -> True if the simulator uses AIO + self.uses_aio = False + self.sources = [] + self.defines = [] + self.includes = [] + + def add_source(self, src): + if src not in self.sources: + self.sources.append(src) + + def add_include(self, incl): + if incl not in self.includes: + self.includes.append(incl) + + def add_define(self, define): + if define not in self.defines: + self.defines.append(define) + + def scan_for_flags(self, defs): + """Scan for USE_INT64/USE_ADDR64 in the simulator's defines and set the + 'int64' and 'full64' instance variables. If found, these defines are + removed. Also look for any of the "DISPLAY" make macros, and, if found, + set the 'video' instance variable. + """ + use_int64 = 'USE_INT64' in self.defines + use_addr64 = 'USE_ADDR64' in self.defines + if use_int64 or use_addr64: + self.int64 = use_int64 and not use_addr64 + self.full64 = use_int64 and use_addr64 + for defn in ['USE_INT64', 'USE_ADDR64']: + try: + self.defines.remove(defn) + except: + pass + + ## Video support: + + self.has_display = any(map(lambda s: 'DISPLAY' in SPM.shallow_expand_vars(s, defs), self.sources)) + if self.has_display: + for src in ['${DISPLAYL}', '$(DISPLAYL)']: + try: + self.sources.remove(src) + except: + pass + + self.uses_video = 'USE_SIM_VIDEO' in self.defines or self.has_display + + ## AIO support: + self.uses_aio = 'SIM_ASYNCH_IO' in self.defines + if self.uses_aio: + for defn in ['SIM_ASYNCH_IO', 'USE_READER_THREAD']: + try: + self.defines.remove(defn) + except: + pass + + def cleanup_defines(self): + """Remove command line defines that aren't needed (because the CMake interface libraries + already define them.) + """ + for define in ['USE_SIM_CARD', 'USE_SIM_VIDEO', 'USE_NETWORK', 'USE_SHARED']: + try: + self.defines.remove(define) + except: + pass + + def get_source_vars(self): + srcvars = set() + for src in self.sources: + srcvars = srcvars.union(set(SPM.extract_variables(src))) + return srcvars + + def get_include_vars(self): + incvars = set() + for inc in self.includes: + incvars = incvars.union(set(SPM.extract_variables(inc))) + return incvars + + def write_section(self, stream, section, indent, test_label='default', additional_text=[], + section_name=None, section_srcs=None, section_incs=None): + indent4 = ' ' * (indent + 4) + indent8 = ' ' * (indent + 8) + + pkg_info = SPKG.package_info.get(section_name) + install_flag = pkg_info.install_flag if pkg_info is not None else None + pkg_family = pkg_info.family.component_name if pkg_info is not None else None + + stream.write(' ' * indent + '{}({}\n'.format(section, section_name)) + stream.write(' ' * (indent + 4) + 'SOURCES\n') + stream.write('\n'.join(map(lambda src: indent8 + src, section_srcs))) + if len(self.includes) > 0: + stream.write('\n' + indent4 + 'INCLUDES\n') + stream.write('\n'.join([ indent8 + inc for inc in section_incs])) + if len(self.defines) > 0: + stream.write('\n' + indent4 + 'DEFINES\n') + stream.write('\n'.join(map(lambda dfn: indent8 + dfn, self.defines))) + if self.int64: + stream.write('\n' + indent4 + 'FEATURE_INT64') + if self.full64: + stream.write('\n' + indent4 + 'FEATURE_FULL64') + if self.uses_video: + stream.write('\n' + indent4 + "FEATURE_VIDEO") + if self.has_display: + stream.write('\n' + indent4 + "FEATURE_DISPLAY") + if self.besm6_sdl_hack: + stream.write('\n' + indent4 + "BESM6_SDL_HACK") + if self.uses_aio: + stream.write('\n' + indent4 + "USES_AIO") + if self.buildrom: + stream.write('\n' + indent4 + "BUILDROMS") + stream.write('\n' + indent4 + "LABEL " + test_label) + if install_flag: + if pkg_family: + stream.write('\n' + indent4 + "PKG_FAMILY " + pkg_family) + else: + stream.write('\n' + indent4 + "NO_INSTALL") + stream.write('\n' + '\n'.join(additional_text)) + stream.write(')\n') + + def write_simulator(self, stream, indent, test_label='default'): + ## When writing an individual CMakeList.txt, we can take advantage of the CMAKE_CURRENT_SOURCE_DIR + ## as a replacement for the SIMH directory macro. + srcs = [ src.replace(self.dir_macro + '/', '') for src in self.sources] + incs = [ inc if inc != self.dir_macro else '${CMAKE_CURRENT_SOURCE_DIR}' for inc in self.includes] + + indent4 = ' ' * (indent + 4) + + addl_text = [ + indent4 + "TEST " + self.test_name, + ] + + self.write_section(stream, 'add_simulator', indent, test_label, additional_text=addl_text, + section_name=self.sim_name, section_srcs=srcs, section_incs=incs) + + # Default: Don't generate a unit test CMakeFiles.txt. Yet. + def write_unit_test(self, stream, indent, test_label='default'): + pass + + def __repr__(self): + return '{0}({1},{2},{3},{4})'.format(self.__class__.__name__, self.sim_name.__repr__(), + self.sources.__repr__(), self.includes.__repr__(), self.defines.__repr__()) + + +class BESM6Simulator(SIMHBasicSimulator): + """The (fine Communist) BESM6 simulator needs some extra code + in the CMakeLists.txt to detect a suitable font that supports + Cyrillic. + """ + def __init__(self, sim_name, dir_macro, test_name, buildrom): + super().__init__(sim_name, dir_macro, test_name, buildrom) + + def scan_for_flags(self, defs): + super().scan_for_flags(defs) + + def write_simulator(self, stream, indent, test_label='besm6'): + ## Fixups... :-) + for macro in ['FONTFILE=$(FONTFILE)', 'FONTFILE=${FONTFILE}']: + try: + self.defines.remove(macro) + except: + pass + + ## Add the search for a font file. + stream.write('\n'.join([ + 'set(besm6_font)', + 'set(cand_fonts', + ' "DejaVuSans.ttf"', + ' "LucidaSansRegular.ttf"', + ' "FreeSans.ttf"', + ' "AppleGothic.ttf"', + ' "tahoma.ttf")', + 'set(cand_fontdirs', + ' "/usr/share/fonts"', + ' "/usr/lib/jvm"', + ' "/Library/Fonts"', + ' "/System/Library/Fonts"', + ' "/System/Library/Frameworks/JavaVM.framework/Versions"', + ' "$ENV{WINDIR}/Fonts")', + '', + 'foreach (fdir ${cand_fontdirs})', + ' foreach (font ${cand_fonts})', + ' if (EXISTS ${fdir}/${font})', + ' get_filename_component(fontfile ${fdir}/${font} ABSOLUTE)', + ' list(APPEND besm6_font ${fontfile})', + ' endif ()', + '', + ' file(GLOB besm6_font_cand_1 LIST_DIRECTORIES FALSE "${fdir}/*/${font}")', + ' file(GLOB besm6_font_cand_2 LIST_DIRECTORIES FALSE "${fdir}/*/*/${font}")', + ' file(GLOB besm6_font_cand_3 LIST_DIRECTORIES FALSE "${fdir}/*/*/*/${font}")', + ' list(APPEND besm6_font ${besm6_font_cand_1} ${besm6_font_cand_2} ${besm6_font_cand_3})', + ' endforeach()', + 'endforeach()', + '', + 'if (besm6_font)', + ' set(besm6_found_fonts "BESM6: Fonts found")', + ' foreach(bfont ${besm6_font})', + ' string(APPEND besm6_found_fonts "\n .. ${bfont}")', + ' endforeach ()', + ' message(STATUS ${besm6_found_fonts})', + ' unset(besm6_found_fonts)', + ' list(GET besm6_font 0 besm6_font)', + ' message(STATUS "BESM6: Using ${besm6_font}")', + 'else ()', + ' set(besm6_no_fonts "BESM6: No applicable Cyrillic fonts found.")', + ' string(APPEND besm6_no_fonts "\n Font names tried:")', + ' foreach (font ${cand_fonts})', + ' string(APPEND besm6_no_fonts "\n .. ${font}")', + ' endforeach ()', + ' string(APPEND besm6_no_fonts "\n\n Looked in:")', + ' foreach (fdir ${cand_fontdirs})', + ' string(APPEND besm6_no_fonts "\n .. ${fdir}")', + ' endforeach()', + ' string(APPEND besm6_no_fonts "\n\nBESM6: Not building with panel display.")', + ' message(STATUS ${besm6_no_fonts})', + ' unset(besm6_no_fonts)', + 'endif ()', + '', + 'if (NOT (besm6_font AND WITH_VIDEO))\n'])) + super().write_simulator(stream, indent + 4, test_label) + stream.write('else ()\n') + self.defines.append("FONTFILE=${besm6_font}") + self.has_display = True + self.uses_video = True + self.besm6_sdl_hack = True + super().write_simulator(stream, indent + 4, test_label) + stream.write('\n'.join([ + 'endif()', + 'unset(cand_fonts)', + 'unset(cand_fontdirs)\n'])) + +class KA10Simulator(SIMHBasicSimulator): + def __init__(self, sim_name, dir_macro, test_name, buildrom): + super().__init__(sim_name, dir_macro, test_name, buildrom) + + def write_simulator(self, stream, indent, test_label='ka10'): + super().write_simulator(stream, indent, test_label) + stream.write('\n') + stream.write('\n'.join([ + 'if (PANDA_LIGHTS)', + ' target_sources({0} PUBLIC {1}/ka10_lights.c)'.format(self.sim_name, self.dir_macro), + ' target_compile_definitions({0} PUBLIC PANDA_LIGHTS)'.format(self.sim_name), + ' target_link_libraries({0} PUBLIC usb-1.0)'.format(self.sim_name), + 'endif (PANDA_LIGHTS)' + ])) + stream.write('\n') + +class IBM650Simulator(SIMHBasicSimulator): + '''The IBM650 simulator creates relatively deep stacks, which will fail on Windows. + Adjust target simulator link flags to provide a 8M stack, similar to Linux. + ''' + def __init__(self, sim_name, dir_macro, test_name, buildrom): + super().__init__(sim_name, dir_macro, test_name, buildrom) + self.stack_size = 8 * 1024 * 1024 + + def write_simulator(self, stream, indent, test_label='ibm650'): + super().write_simulator(stream, indent, test_label) + stream.write('\n') + ## Link i650 with a 8M stack on windows + stream.write('\n'.join([ + 'if (WIN32)', + ' if (MSVC)', + ' set(I650_STACK_FLAG "/STACK:{0}")'.format(self.stack_size), + ' else ()', + ' set(I650_STACK_FLAG "-Wl,--stack,{0}")'.format(self.stack_size), + ' endif ()', + ' if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.13")', + ' target_link_options({0} PUBLIC "${{I650_STACK_FLAG}}")'.format(self.sim_name), + ' else ()', + ' set_property(TARGET {0} LINK_FLAGS " ${{I650_STACK_FLAG}}")'.format(self.sim_name), + ' endif ()', + 'endif()' + ])) + +class IBM1130Simulator(SIMHBasicSimulator): + '''The IBM650 simulator creates relatively deep stacks, which will fail on Windows. + Adjust target simulator link flags to provide a 8M stack, similar to Linux. + ''' + def __init__(self, sim_name, dir_macro, test_name, buildrom): + super().__init__(sim_name, dir_macro, test_name, buildrom) + + def write_simulator(self, stream, indent, test_label='ibm650'): + super().write_simulator(stream, indent, test_label) + stream.write('\n'.join([ + '', + 'if (WIN32)', + ' target_compile_definitions(ibm1130 PRIVATE GUI_SUPPORT)', + ' ## missing source in IBM1130?' + ' ## target_sources(ibm1130 PRIVATE ibm1130.c)', + 'endif()' + ])) + + +if '_dispatch' in pprint.PrettyPrinter.__dict__: + def sim_pprinter(pprinter, sim, stream, indent, allowance, context, level): + cls = sim.__class__ + stream.write(cls.__name__ + '(') + indent += len(cls.__name__) + 1 + pprinter._format(sim.sim_name, stream, indent, allowance + 2, context, level) + stream.write(',') + pprinter._format(sim.dir_macro, stream, indent, allowance + 2, context, level) + stream.write(',') + pprinter._format(sim.int64, stream, indent, allowance + 2, context, level) + stream.write(',') + pprinter._format(sim.full64, stream, indent, allowance + 2, context, level) + stream.write(',') + pprinter._format(sim.has_display, stream, indent, allowance + 2, context, level) + stream.write(',') + pprinter._format(sim.sources, stream, indent, allowance + 2, context, level) + stream.write(',\n' + ' ' * indent) + pprinter._format(sim.defines, stream, indent, allowance + 2, context, level) + stream.write(',\n' + ' ' * indent) + pprinter._format(sim.includes, stream, indent, allowance + 2, context, level) + stream.write(')') + + pprint.PrettyPrinter._dispatch[SIMHBasicSimulator.__repr__] = sim_pprinter diff --git a/cmake/simgen/cmake_container.py b/cmake/simgen/cmake_container.py new file mode 100644 index 00000000..053a7549 --- /dev/null +++ b/cmake/simgen/cmake_container.py @@ -0,0 +1,411 @@ +## cmake_container.py +## +## A container for a collection of SIMH simulators +## +## + +import sys +import os +import re +import pprint +import functools + +import simgen.parse_makefile as SPM +import simgen.sim_collection as SC +import simgen.utils as SU + +## Corresponding special variable uses in the makefile: +_special_sources = frozenset(['${DISPLAYL}', '$(DISPLAYL)']) + +## Banner header for individual CMakeLists.txt files: +_individual_header = [ + '##', + '## This is an automagically generated file. Do NOT EDIT.', + '## Any changes you make will be overwritten!!', + '##', + '## Make changes to the SIMH top-level makefile and then run the', + '## "cmake/generate.py" script to regenerate these files.', + '##', + '## cd cmake; python -m generate --help', + '##', + '## ' + '-' * 60 + '\n' + ] + +## Banner header for individual unit test CMakeLists.txt files: +_unit_test_header = [ + '##', + '## This is an automagically generated file. Do NOT EDIT.', + '## Any changes you make will be overwritten!!', + '##', + '## If you need to make changes, modify write_unit_test()', + '## method in the the underlying Python class in ', + '## cmake/simgen/basic_simulator.py, then execute the', + '## "cmake/generate.py" script to regenerate these files.', + '##', + '## cd cmake; python -m generate --help', + '##', + '## ' + '-' * 60 + '\n' + ] +## Unset the display variables when not building with video. A +10 +## kludge. +_unset_display_vars = ''' +if (NOT WITH_VIDEO) + ### Hack: Unset these variables so that they don't expand if + ### not building with video: + set(DISPLAY340 "") + set(DISPLAYIII "") + set(DISPLAYNG "") + set(DISPLAYVT "") +endif () +''' + +class CMakeBuildSystem: + """A container for collections of SIMH simulators and automagic + CMakeLists.txt driver. + + This is the top-level container that stores collections of SIMH simulators + in the 'SIM' + """ + + ## Compile command line elements that are ignored. + _ignore_compile_elems = frozenset(['${LDFLAGS}', '$(LDFLAGS)', + '${CC_OUTSPEC}', '$(CC_OUTSPEC)', + '${SIM}', '$(SIM)', + '-o', '$@', + '${NETWORK_OPT}', '$(NETWORK_OPT)', + '${SCSI}', '$(SCSI)', + '${DISPLAY_OPT}', '$(DISPLAY_OPT)', + '${VIDEO_CCDEFS}', '$(VIDEO_CCDEFS)', + '${VIDEO_LDFLAGS}', '$(VIDEO_LDFLAGS)', + '${BESM6_PANEL_OPT}', '$(BESM6_PANEL_OPT)']) + + def __init__(self): + # "Special" variables that we look for in source code lists and which we'll + # emit into the CMakeLists.txt files. + self.vars = SC.ignored_display_macros.copy() + # Subdirectory -> SimCollection mapping + self.dirs = {} + + + def extract(self, compile_action, test_name, sim_dir, sim_name, defs, buildrom, debug=0, depth=''): + """Extract sources, defines, includes and flags from the simulator's + compile action in the makefile. + """ + sim_dir_path = SPM.expand_vars(sim_dir, defs).replace('./', '') + simcoll = self.dirs.get(sim_dir_path) + if simcoll is None: + simcoll = SC.SimCollection(sim_dir) + self.dirs[sim_dir_path] = simcoll + + sim = simcoll.get_simulator(sim_name, sim_dir, sim_dir_path, test_name, buildrom) + + # Remove compile command line elements and do one level of variable expansion, split the resulting + # string into a list. + all_comps = [] + for comp in [ SPM.normalize_variables(act) for act in compile_action.split() if not self.compile_elems_to_ignore(act) ]: + all_comps.extend(comp.split()) + + if debug >= 3: + print('{0}all_comps after filtering:'.format(depth)) + pprint.pp(all_comps) + + # Iterate through the final compile component list and extract source files, includes + # and defines. + # + # Deferred: Looking for options that set the i64, z64, video library options. + while all_comps: + comp = all_comps[0] + # print(':: comp {0}'.format(comp)) + if self.is_source(comp): + # Source file... + ## sim.add_source(comp.replace(sim_dir + '/', '')) + sim.add_source(comp) + elif comp.startswith('-I'): + all_comps = self.process_flag(all_comps, defs, sim.add_include, depth) + elif comp.startswith('-D'): + all_comps = self.process_flag(all_comps, defs, sim.add_define, depth) + elif comp.startswith('-L') or comp.startswith('-l'): + ## It's a library path or library. Skip. + pass + else: + # Solitary variable expansion? + m = SPM._var_rx.match(comp) + if m: + varname = m.group(1) + if varname not in SC._special_vars: + if not self.is_source_macro(comp, defs): + expand = [ SPM.normalize_variables(elem) for elem in SPM.shallow_expand_vars(comp, defs).split() + if not self.source_elems_to_ignore(elem) ] + SU.emit_debug(debug, 3, '{0}var expanded {1} -> {2}'.format(depth, comp, expand)) + all_comps[1:] = expand + all_comps[1:] + else: + ## Source macro + self.collect_source_macros(comp, defs, varname, simcoll, sim, debug, depth) + else: + sim.add_source(comp) + else: + # Nope. + print('{0}unknown component: {1}'.format(depth, comp)) + all_comps = all_comps[1:] + + sim.scan_for_flags(defs) + sim.cleanup_defines() + + if debug >= 2: + pprint.pprint(sim) + + + def compile_elems_to_ignore(self, elem): + return (elem in self._ignore_compile_elems or elem.endswith('_LDFLAGS')) + + def source_elems_to_ignore(self, elem): + return self.compile_elems_to_ignore(elem) or elem in _special_sources + + + def is_source_macro(self, var, defs): + """Is the macro/variable a list of sources? + """ + expanded = SPM.expand_vars(var, defs).split() + # print('is_source_macro {}'.format(expanded)) + return all(map(lambda src: self.is_source(src), expanded)) + + + def is_source(self, thing): + return thing.endswith('.c') + + + def process_flag(self, comps, defs, process_func, depth): + if len(comps[0]) > 2: + # "-Ddef" + val = comps[0][2:] + else: + # "-D def" + val = comps[1] + comps = comps[1:] + m = SPM._var_rx.match(val) + if m: + var = m.group(1) + ## Gracefully deal with undefined variables (ATT3B2M400B2D is a good example) + if var in defs: + if var not in self.vars: + self.vars[var] = defs[var] + else: + print('{0}undefined make macro: {1}'.format(depth, var)) + + process_func(val) + return comps + + + def collect_vars(self, defs, debug=0): + """Add indirectly referenced macros and variables, adding them to the defines dictionary. + + Indirectly referenced macros and variables are macros and variables embedded in existing + variables, source macros and include lists. For example, SIMHD is an indirect reference + in "KA10D = ${SIMHD}/ka10" because KA10D might never have been expanded by 'extract()'. + """ + + def scan_var(varset, var): + tmp = var + return varset.union(set(SPM.extract_variables(tmp))) + + def replace_simhd(l, v): + l.append(v.replace('SIMHD', 'CMAKE_SOURCE_DIR')) + return l + + simvars = set() + for v in self.vars.values(): + if isinstance(v, list): + simvars = functools.reduce(scan_var, v, simvars) + else: + simvars = scan_var(simvars, v) + + for dir in self.dirs.keys(): + simvars = simvars.union(self.dirs[dir].get_simulator_vars(debug)) + + if debug >= 2: + print('Collected simvars:') + pprint.pprint(simvars) + + for var in simvars: + if var not in self.vars: + if var in defs: + self.vars[var] = defs[var] + else: + print('{0}: variable not defined.'.format(var)) + + ## Replace SIMHD with CMAKE_SOURCE_DIR + for k, v in self.vars.items(): + if isinstance(v, list): + v = functools.reduce(replace_simhd, v, []) + else: + v = v.replace('SIMHD', 'CMAKE_SOURCE_DIR') + self.vars[k] = v + + def collect_source_macros(self, comp, defs, varname, simcoll, sim, debug=0, depth=''): + def inner_sources(srcmacro): + for v in srcmacro: + if not self.source_elems_to_ignore(v): + m = SPM._var_rx.match(v) + if m is not None: + vname = m.group(1) + vardef = defs.get(vname) + if vardef is not None: + ## Convert the macro variable into a list + vardef = [ SPM.normalize_variables(v) \ + for v in vardef.split() if not self.source_elems_to_ignore(v) ] + SU.emit_debug(debug, 3, '{0}source macro: {1} -> {2}'.format(depth, vname, vardef)) + simcoll.add_source_macro(vname, vardef, sim) + ## Continue into the macro variable's definitions + inner_sources(vardef) + + vardef = defs.get(varname) + if vardef is not None: + vardef = [ SPM.normalize_variables(v) \ + for v in vardef.split() if not self.source_elems_to_ignore(v) ] + SU.emit_debug(debug, 3, '{0}source macro: {1} -> {2}'.format(depth, varname, vardef)) + simcoll.add_source_macro(varname, vardef, sim) + inner_sources(vardef) + SU.emit_debug(debug, 3, '{0}source added: {1}'.format(depth, comp)) + sim.add_source(comp) + else: + print('{0}undefined make macro: {1}'.format(depth, varname)) + + def write_vars(self, stream): + def collect_vars(varlist, var): + varlist.extend(SPM.extract_variables(var)) + return varlist + + varnames = list(self.vars.keys()) + namewidth = max(map(lambda s: len(s), varnames)) + # vardeps maps the parent variable to its dependents, e.g., + # INTELSYSD -> [ISYS8010D, ...] + vardeps = dict() + # alldeps is the set of all parent and dependents, which will be + # deleted from a copy of self.vars. The copy has variables that + # don't depend on anything (except for CMAKE_SOURCE_DIR, but we + # know that's defined by CMake.) + alldeps = set() + for var in varnames: + if isinstance(self.vars[var], list): + mvars = functools.reduce(collect_vars, self.vars[var], []) + else: + mvars = SPM.extract_variables(self.vars[var]) + mvars = [mvar for mvar in mvars if mvar != "CMAKE_SOURCE_DIR"] + if mvars: + alldeps.add(var) + for mvar in mvars: + if mvar not in vardeps: + vardeps[mvar] = [] + vardeps[mvar].append(var) + alldeps.add(mvar) + + nodeps = self.vars.copy() + ## SIMHD will never be used. + if 'SIMHD' in nodeps: + del nodeps['SIMHD'] + for dep in alldeps: + del nodeps[dep] + + varnames = list(nodeps.keys()) + varnames.sort() + for var in varnames: + self.emit_value(var, self.vars[var], stream, namewidth) + + ## Now to emit the dependencies + depnames = list(vardeps.keys()) + depnames.sort() + for dep in depnames: + self.write_dep(dep, vardeps, alldeps, namewidth, stream) + + ## stream.write('\n## ' + '-' * 40 + '\n') + + def write_dep(self, dep, vardeps, alldeps, width, stream): + # Not the most efficient, but it works + alldeps.discard(dep) + for parent in [ v for v in vardeps.keys() if dep in vardeps[v]]: + if dep in parent.values(): + self.write_dep(parent, vardeps, alldeps, width, stream) + + stream.write('\n') + self.emit_value(dep, self.vars[dep], stream, width) + + children = vardeps[dep] + children.sort() + for child in children: + if child in alldeps: + self.emit_value(child, self.vars[child], stream, width) + alldeps -= set(children) + + def emit_value(self, var, value, stream, width=0): + if isinstance(value, list): + stream.write('set({:{width}} {})\n'.format(var, ' '.join(map(lambda s: '"' + s + '"', value)), + width=width)) + else: + stream.write('set({:{width}} "{}")\n'.format(var, value, width=width)) + + def write_simulators(self, toplevel_dir, debug=0): + dirnames = list(self.dirs.keys()) + dirnames.sort() + + for subdir in dirnames: + simcoll = self.dirs[subdir] + test_label = subdir + # Group tests under subdirectories together + has_slash = test_label.find('/') + if has_slash < 0: + has_slash = test_label.find('\\') + if has_slash >= 0: + test_label = test_label[:has_slash] + ## Write out individual CMakeLists.txt: + subdir_cmake = os.path.join(toplevel_dir, subdir, 'CMakeLists.txt') + print('==== writing to {0}'.format(subdir_cmake)) + with open(subdir_cmake, "w", newline='\r\n') as stream2: + plural = '' if len(self.dirs[subdir]) == 1 else 's' + stream2.write('## {} simulator{plural}\n'.format(subdir, plural=plural)) + stream2.write('\n'.join(_individual_header)) + stream2.write('\n') + stream2.write('if (HAVE_UNITY_FRAMEWORK AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/CMakeLists.txt")\n') + stream2.write(' add_subdirectory(unit-tests)\n') + stream2.write('endif ()') + stream2.write('\n') + simcoll.write_simulators(stream2, debug=debug, test_label=test_label) + + ## Write out unit tests, if the unit test subdirectory exists: + subdir_units_dir = os.path.join(toplevel_dir, subdir, 'unit-tests') + subdir_units = os.path.join(subdir_units_dir, 'CMakeLists.txt') + if os.path.exists(subdir_units): + with open(subdir_units, "w") as stream2: + plural = '' if len(self.dirs[subdir]) == 1 else 's' + stream2.write('## {} simulator{plural}\n'.format(subdir, plural=plural)) + stream2.write('\n'.join(_unit_test_header)) + stream2.write('\n') + simcoll.write_unit_tests(stream2, debug, subdir) + + simh_subdirs = os.path.join(toplevel_dir, 'cmake', 'simh-simulators.cmake') + print("==== writing {0}".format(simh_subdirs)) + with open(simh_subdirs, "w") as stream2: + stream2.write('\n'.join(_individual_header)) + self.write_vars(stream2) + stream2.write('\n## ' + '-' * 40 + '\n') + stream2.write(_unset_display_vars) + stream2.write('\n## ' + '-' * 40 + '\n\n') + stmts = [ 'add_subdirectory(' + dir + ')' for dir in dirnames ] + stream2.write('\n'.join(stmts)) + stream2.write('\n') + + ## Representation when printed + def __repr__(self): + return '{0}({1}, {2})'.format(self.__class__.__name__, self.dirs.__repr__(), self.vars.__repr__()) + + +if '_dispatch' in pprint.PrettyPrinter.__dict__: + def cmake_pprinter(pprinter, cmake, stream, indent, allowance, context, level): + cls = cmake.__class__ + stream.write(cls.__name__ + '(') + indent += len(cls.__name__) + 1 + pprinter._format(cmake.dirs, stream, indent, allowance + 2, context, level) + stream.write(',\n' + ' ' * indent) + pprinter._format(cmake.vars, stream, indent, allowance + 2, context, level) + stream.write(')') + + pprint.PrettyPrinter._dispatch[CMakeBuildSystem.__repr__] = cmake_pprinter diff --git a/cmake/simgen/packaging.py b/cmake/simgen/packaging.py new file mode 100644 index 00000000..c2d023e2 --- /dev/null +++ b/cmake/simgen/packaging.py @@ -0,0 +1,253 @@ +import os +import functools + +## Initialize package_info to an empty dictionary here so +## that it's visible to write_packaging(). +package_info = {} + + +class SIMHPackaging: + def __init__(self, family, install_flag = True) -> None: + self.family = family + self.processed = False + self.install_flag = install_flag + + def was_processed(self) -> bool: + return self.processed == True + + def encountered(self) -> None: + self.processed = True + +class PkgFamily: + def __init__(self, component_name, display_name, description) -> None: + self.component_name = component_name + self.display_name = display_name + self.description = description + + def write_component_info(self, stream, indent) -> None: + pkg_description = self.description + if pkg_description[-1] != '.': + pkg_description += '.' + sims = [] + for sim, pkg in package_info.items(): + if pkg.family is self and pkg.was_processed(): + sims.append(sim) + + if len(sims) > 0: + sims.sort() + pkg_description += " Simulators: " + ', '.join(sims) + indent0 = ' ' * indent + indent4 = ' ' * (indent + 4) + stream.write(indent0 + "cpack_add_component(" + self.component_name + "\n") + stream.write(indent4 + "DISPLAY_NAME \"" + self.display_name + "\"\n") + stream.write(indent4 + "DESCRIPTION \"" + pkg_description + "\"\n") + stream.write(indent0 + ")\n") + + def __lt__(self, obj): + return self.component_name < obj.component_name + def __eq__(self, obj): + return self.component_name == obj.component_name + def __gt__(self, obj): + return self.component_name > obj.component_name + def __hash__(self): + return hash(self.component_name) + +def write_packaging(toplevel_dir) -> None: + families = set([sim.family for sim in package_info.values()]) + pkging_file = os.path.join(toplevel_dir, 'cmake', 'simh-packaging.cmake') + print("==== writing {0}".format(pkging_file)) + with open(pkging_file, "w") as stream: + ## Runtime support family: + stream.write("""## The default runtime support component/family: +cpack_add_component(runtime_support + DISPLAY_NAME "Runtime support" + DESCRIPTION "Required SIMH runtime support (documentation, shared libraries)" + REQUIRED +) + +## Basic documentation for SIMH +install(FILES doc/simh.doc TYPE DOC COMPONENT runtime_support) + +""") + + ## Simulators: + for family in sorted(families): + family.write_component_info(stream, 0) + + +default_family = PkgFamily("default_family", "Default SIMH simulator family.", + """The SIMH simulator collection of historical processors and computing systems that do not belong to +any other simulated system family""" +) + +att3b2_family = PkgFamily("att3b2_family", "ATT&T 3b2 collection", + """The AT&T 3b2 simulator family""" +) + +vax_family = PkgFamily("vax_family", "DEC VAX simulator collection", + """The Digital Equipment Corporation VAX (plural: VAXen) simulator family.""" +) + +pdp10_family = PkgFamily("pdp10_family", "DEC PDP-10 collection", + """DEC PDP-10 architecture simulators and variants.""" +) + +pdp11_family = PkgFamily("pdp11_family", "DEC PDP-11 collection.", + """DEC PDP-11 and PDP-11-derived architecture simulators""" +) + +experimental_family = PkgFamily("experimental", "Experimental (work-in-progress) simulators", + """Experimental or work-in-progress simulators not in the SIMH mainline simulator suite.""" +) + +altairz80_family = PkgFamily("altairz80_family", "Altair Z80 simulator.", + """The Altair Z80 simulator with M68000 support.""" +) + +b5500_family = PkgFamily("b5500_family", "Burroughs 5500", + """The Burroughs 5500 system simulator""") + +cdc1700_family = PkgFamily("cdc1700_family", "CDC 1700", + """The Control Data Corporation's systems""" +) + +dgnova_family = PkgFamily("dgnova_family", "DG Nova and Eclipse", + """Data General NOVA and Eclipse system simulators""" +) + +grisys_family = PkgFamily("grisys_family", "GRI Systems GRI-909", + """GRI Systems GRI-909 system simulator""" +) + +honeywell_family = PkgFamily("honeywell_family", "Honeywell H316", + """Honeywell H-316 system simulator""" +) + +hp_family = PkgFamily("hp_family", "HP 2100, 3000", + """Hewlett-Packard H2100 and H3000 simulators""") + +ibm_family = PkgFamily("ibm_family", "IBM", + """IBM system simulators: i650""" +) + +imlac_family = PkgFamily("imlac_family", "IMLAC", + """IMLAC system simulators""" +) + +intel_family = PkgFamily("intel_family", "Intel", + """Intel system simulators""" +) + +interdata_family = PkgFamily("interdata_family", "Interdata", + """Interdata systems simulators""" +) + +lgp_family = PkgFamily("lgp_family", "LGP", + """Librascope systems""" +) + +decpdp_family = PkgFamily("decpdp_family", "DEC PDP family", + """Digital Equipment Corporation PDP systems""" +) + +sds_family = PkgFamily("sds_family", "SDS simulators", + """Scientific Data Systems (SDS) systems""" +) + +gould_family = PkgFamily("gould_family", "Gould simulators", + """Gould Systems simulators""" +) + +swtp_family = PkgFamily("swtp_family", "SWTP simulators", + """Southwest Technical Products (SWTP) system simulators""" +) + +norsk_family = PkgFamily("norsk_family", "ND simulators", + """Norsk Data systems simulator family""") + +icl_family = PkgFamily("icl_family", "ICL simulators", + """ICL systems simulator family""") + +package_info["3b2"] = SIMHPackaging(att3b2_family) +package_info["3b2-700"] = SIMHPackaging(att3b2_family) +package_info["altair"] = SIMHPackaging(default_family) +package_info["altairz80"] = SIMHPackaging(altairz80_family) +package_info["b5500"] = SIMHPackaging(b5500_family) +package_info["besm6"] = SIMHPackaging(default_family) +package_info["cdc1700"] = SIMHPackaging(cdc1700_family) +package_info["eclipse"] = SIMHPackaging(dgnova_family) +package_info["gri"] = SIMHPackaging(grisys_family) +package_info["h316"] = SIMHPackaging(honeywell_family) +package_info["hp2100"] = SIMHPackaging(hp_family) +package_info["hp3000"] = SIMHPackaging(hp_family) +package_info["i1401"] = SIMHPackaging(ibm_family) +package_info["i1620"] = SIMHPackaging(ibm_family) +package_info["i650"] = SIMHPackaging(ibm_family) +package_info["i701"] = SIMHPackaging(ibm_family) +package_info["i7010"] = SIMHPackaging(ibm_family) +package_info["i704"] = SIMHPackaging(ibm_family) +package_info["i7070"] = SIMHPackaging(ibm_family) +package_info["i7080"] = SIMHPackaging(ibm_family) +package_info["i7090"] = SIMHPackaging(ibm_family) +package_info["i7094"] = SIMHPackaging(ibm_family) +package_info["ibm360"] = SIMHPackaging(ibm_family) +package_info["ibm1130"] = SIMHPackaging(ibm_family) +package_info["icl1900"] = SIMHPackaging(icl_family) +package_info["id16"] = SIMHPackaging(interdata_family) +package_info["id32"] = SIMHPackaging(interdata_family) +package_info["imlac"] = SIMHPackaging(imlac_family) +package_info["infoserver100"] = SIMHPackaging(vax_family) +package_info["infoserver1000"] = SIMHPackaging(vax_family) +package_info["infoserver150vxt"] = SIMHPackaging(vax_family) +package_info["intel-mds"] = SIMHPackaging(intel_family) +package_info["lgp"] = SIMHPackaging(lgp_family) +package_info["microvax1"] = SIMHPackaging(vax_family) +package_info["microvax2"] = SIMHPackaging(vax_family) +package_info["microvax2000"] = SIMHPackaging(vax_family) +package_info["microvax3100"] = SIMHPackaging(vax_family) +package_info["microvax3100e"] = SIMHPackaging(vax_family) +package_info["microvax3100m80"] = SIMHPackaging(vax_family) +package_info["nd100"] = SIMHPackaging(norsk_family) +package_info["nova"] = SIMHPackaging(dgnova_family) +package_info["pdp1"] = SIMHPackaging(decpdp_family) +## Don't install pdp10 per Rob Cromwell +package_info["pdp10"] = SIMHPackaging(pdp10_family, install_flag=False) +package_info["pdp10-ka"] = SIMHPackaging(pdp10_family) +package_info["pdp10-ki"] = SIMHPackaging(pdp10_family) +package_info["pdp10-kl"] = SIMHPackaging(pdp10_family) +package_info["pdp10-ks"] = SIMHPackaging(pdp10_family) +package_info["pdp11"] = SIMHPackaging(pdp11_family) +package_info["pdp15"] = SIMHPackaging(decpdp_family) +package_info["pdp4"] = SIMHPackaging(decpdp_family) +package_info["pdp6"] = SIMHPackaging(decpdp_family) +package_info["pdp7"] = SIMHPackaging(decpdp_family) +package_info["pdp8"] = SIMHPackaging(decpdp_family) +package_info["pdp9"] = SIMHPackaging(decpdp_family) +package_info["rtvax1000"] = SIMHPackaging(vax_family) +package_info["s3"] = SIMHPackaging(ibm_family) +package_info["scelbi"] = SIMHPackaging(intel_family) +package_info["sds"] = SIMHPackaging(sds_family) +package_info["sel32"] = SIMHPackaging(gould_family) +package_info["sigma"] = SIMHPackaging(sds_family) +package_info["ssem"] = SIMHPackaging(default_family) +package_info["swtp6800mp-a"] = SIMHPackaging(swtp_family) +package_info["swtp6800mp-a2"] = SIMHPackaging(swtp_family) +package_info["tt2500"] = SIMHPackaging(default_family) +package_info["tx-0"] = SIMHPackaging(default_family) +package_info["uc15"] = SIMHPackaging(pdp11_family) +package_info["vax"] = SIMHPackaging(vax_family) +package_info["vax730"] = SIMHPackaging(vax_family) +package_info["vax750"] = SIMHPackaging(vax_family) +package_info["vax780"] = SIMHPackaging(vax_family) +package_info["vax8200"] = SIMHPackaging(vax_family) +package_info["vax8600"] = SIMHPackaging(vax_family) +package_info["vaxstation3100m30"] = SIMHPackaging(vax_family) +package_info["vaxstation3100m38"] = SIMHPackaging(vax_family) +package_info["vaxstation3100m76"] = SIMHPackaging(vax_family) +package_info["vaxstation4000m60"] = SIMHPackaging(vax_family) +package_info["vaxstation4000vlc"] = SIMHPackaging(vax_family) + +## Experimental simulators: +package_info["alpha"] = SIMHPackaging(experimental_family) +package_info["pdq3"] = SIMHPackaging(experimental_family) +package_info["sage"] = SIMHPackaging(experimental_family) diff --git a/cmake/simgen/parse_makefile.py b/cmake/simgen/parse_makefile.py new file mode 100644 index 00000000..e80bb5b1 --- /dev/null +++ b/cmake/simgen/parse_makefile.py @@ -0,0 +1,185 @@ +"""Makefile parsing and variable expansion. + +Read and collect variable, rule and action information from a [Mm]akefile. +This isn't a precise collection; for example, it does not respect GNU Makefile +directives such as 'ifeq' and 'ifneq'. +""" + +import re + +# Regexes needed for parsing Makefile (and similar syntaxes, +# like old-style Setup files). +_variable_rx = re.compile(r"\s*([A-Za-z][\w_-]+)\s*=\s*(.*)") +_rule_rx = re.compile(r"(((\$[({])*\w[\w_-]+[)}]*)+)\s*:\s*(.*)") + +# Regex that recognizes variables. Group 1 is the variable's name. +_var_rx = re.compile(r"^\$[{(]([A-Za-z][\w_-]*)[)}]$") +_var_rx2 = re.compile(r"\$[{(]([A-Za-z][\w_-]*)[)}]") +_norm_var_rx = re.compile(r"\$\(([A-Za-z][\w_-]*)\)") + +def parse_makefile(fn, g_vars=None, g_rules=None, g_actions=None): + """Parse a Makefile-style file. + + Collects all of the variable definitions, rules and actions associated with rules. + + """ + ## Python 3.11 and onward dropped distuitls, so import our local copy. + from simgen.text_file import TextFile + + fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape") + + if g_vars is None: + g_vars = {} + if g_rules is None: + g_rules = {} + if g_actions is None: + g_actions = {} + done = {} + rules = {} + actions = {} + + line = fp.readline() + while line is not None: + vmatch = _variable_rx.match(line) + rmatch = _rule_rx.match(line) + if vmatch: + n, v = vmatch.group(1, 2) + v = v.strip() + + try: + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + line = fp.readline() + elif rmatch: + n, v = rmatch.group(1, 4) + rules[n] = v + + ## Collect the actions: + collected = [] + line = fp.readline() + while line is not None: + m = _variable_rx.match(line) or _rule_rx.match(line) + if m is None: + collected.append(line.lstrip()) + line = fp.readline() + else: + break + actions[n] = collected + else: + line = fp.readline() + + fp.close() + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip().replace('\t', ' ') + + # save the results in the global dictionary + g_vars.update(done) + g_rules.update(rules) + g_actions.update(actions) + return (g_vars, g_rules, g_actions) + + +def target_dep_list(target, rules, defs): + return (rules.get(target) or '').split() + +def expand_vars(s, defs): + """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in + 'string' according to 'defs' (a dictionary mapping variable names to + values). Variables not present in 'defs' are silently expanded to the + empty string. + + Returns a variable-expanded version of 's'. + """ + + # This algorithm does multiple expansion, so if defs['foo'] contains + # "${bar}", it will expand ${foo} to ${bar}, and then expand + # ${bar}... and so forth. This is fine as long as 'defs' comes from + # 'parse_makefile()', which takes care of such expansions eagerly, + # according to make's variable expansion semantics. + + while True: + m = _var_rx2.search(s) + if m: + (beg, end) = m.span() + s = s[0:beg] + (defs.get(m.group(1)) or '') + s[end:] + else: + break + return s + + +def shallow_expand_vars(s, defs): + """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in + 'string' according to 'defs' (a dictionary mapping variable names to + values). Variables not present in 'defs' are silently expanded to the + empty string. + + Returns a variable-expanded version of 's'. + """ + + # This algorithm does multiple expansion, so if defs['foo'] contains + # "${bar}", it will expand ${foo} to ${bar}, and then expand + # ${bar}... and so forth. This is fine as long as 'defs' comes from + # 'parse_makefile()', which takes care of such expansions eagerly, + # according to make's variable expansion semantics. + m = _var_rx2.search(s) + if m: + (beg, end) = m.span() + return s[0:beg] + (defs.get(m.group(1)) or '') + shallow_expand_vars(s[end:], defs) + + return s + + +def extract_variables(varstr): + """Extracct all variable references, e.g., "${foo}" or "$(foo)" + from a string. + """ + retval = [] + tmp = varstr + while True: + m = _var_rx2.search(tmp) + if m: + retval.append(m[1]) + tmp = tmp[m.end():] + else: + break + return retval + + +def normalize_variables(varstr): + """Convert '$(var)' to '${var}' -- normalizes all variables to a consistent + form. + """ + retval = "" + tmp = varstr + while tmp: + m = _norm_var_rx.search(tmp) + if m: + retval += tmp[:m.start()] + "${" + m[1] + "}" + tmp = tmp[m.end():] + else: + retval += tmp + tmp = "" + return retval + + +def test_rule_rx(): + result = _rule_rx.match('${BIN}frontpaneltest${EXE} : frontpanel/FrontPanelTest.c sim_sock.c sim_frontpanel.c') + print('{0}: {1}'.format('${BIN}frontpaneltest${EXE}...', result)) + print(result.groups()) + + +def test_normalize_variables(): + result = normalize_variables('foo: bar baz') + print('{0}: {1}'.format('foo:...', result)) + result = normalize_variables('$(var): dep1 dep2') + print('{0}: {1}'.format('$(var)...', result)) + result = normalize_variables('$(var): dep1 ${var2} dep2 $(var3)') + print('{0}: {1}'.format('$(var)...', result)) diff --git a/cmake/simgen/sim_collection.py b/cmake/simgen/sim_collection.py new file mode 100644 index 00000000..d4ca850c --- /dev/null +++ b/cmake/simgen/sim_collection.py @@ -0,0 +1,158 @@ +import pprint + +import simgen.parse_makefile as SPM +import simgen.basic_simulator as SBS +import simgen.vax_simulators as VAXen +import simgen.utils as SU + +## Special variables that should __not__ expand into their definitions: +_special_vars = frozenset(['DISPLAYL', + 'DISPLAYVT', + 'DISPLAY340', + 'DISPLAYNG', + 'DISPLAYIII']) + +## Map simulator name to its class, for special cases +_special_simulators = { + "besm6": SBS.BESM6Simulator, + "i650": SBS.IBM650Simulator, + "ibm1130": SBS.IBM1130Simulator, + "pdp10-ka": SBS.KA10Simulator, + "vax": VAXen.VAXSimulator, + "vax730": VAXen.BasicVAXSimulator +} + +ignored_display_macros = { + 'DISPLAYVT': ['${DISPLAYD}/vt11.c'], + 'DISPLAY340': ['${DISPLAYD}/type340.c'], + 'DISPLAYNG': ['${DISPLAYD}/ng.c'], + 'DISPLAYIII': ['${DISPLAYD}/iii.c'] +} + +def get_simulator_ctor(name): + """Return the class object for special case simulators, otherwise + return the base 'SIMHBasicSimulator' + """ + return _special_simulators.get(name) or SBS.SIMHBasicSimulator + + +class SimCollection: + """A collection of simulators. + """ + def __init__(self, dir_macro): + self.source_macros = {} + self.macro_uses = {} + self.simulators = {} + + def get_simulator(self, name, dir_macro, _dir_path, test_name, buildrom): + sim = self.simulators.get(name) + if sim is None: + sim = (get_simulator_ctor(name))(name, dir_macro, test_name, buildrom) + self.simulators[name] = sim + return sim + + def add_source_macro(self, macro, macro_def, sim): + if macro not in self.source_macros: + self.source_macros[macro] = macro_def + + used = self.macro_uses.get(macro) + if used is None: + self.macro_uses[macro] = [] + used = self.macro_uses[macro] + used.append(sim) + + def get_simulator_vars(self, debug=0): + simvars = set() + ignored = set(self.source_macros.keys()) + for macval in self.source_macros.values(): + ## This could be replaced by a functools.reduce() + for val in macval: + simvars = simvars.union(set(SPM.extract_variables(val))) + + for sim in self.simulators.values(): + simvars = simvars.union(sim.get_source_vars().union(sim.get_include_vars())) + + simvars = simvars.difference(ignored).difference(_special_vars) + SU.emit_debug(debug, 2, 'simvars {0}'.format(simvars)) + return simvars + + def write_simulators(self, stream, debug=0, test_label='default'): + ## Emit source macros + dontexpand = set([smac for smac, uses in self.macro_uses.items() if smac not in ignored_display_macros and len(uses) > 1]) + SU.emit_debug(debug, 2, "{0}: dontexpand {1}".format(self.__class__.__name__, dontexpand)) + + if len(dontexpand) > 0: + smac_sorted = list(dontexpand) + smac_sorted.sort() + for smac in smac_sorted: + stream.write('\n\n') + stream.write('set({0}\n'.format(smac)) + stream.write('\n'.join([' ' * 4 + f for f in self.source_macros[smac]])) + stream.write(')') + stream.write('\n\n') + + ## Emit the simulators + simnames = list(self.simulators.keys()) + simnames.sort() + SU.emit_debug(debug, 2, "{0}: Writing {1}".format(self.__class__.__name__, simnames)) + for simname in simnames: + sim = self.simulators[simname] + + ## Patch up the simulator source lists, expanding macros that aren't + ## in the macro sources: + sim.sources = self.expand_sources(sim.sources, dontexpand, debug) + + stream.write('\n') + sim.write_simulator(stream, 0, test_label) + + def write_unit_tests(self, stream, debug=0, test_label='default'): + dontexpand = set([smac for smac, uses in self.macro_uses.items() if len(uses) > 1]) + + simnames = list(self.simulators.keys()) + simnames.sort() + SU.emit_debug(debug, 2, "{0}: Writing {1}".format(self.__class__.__name__, simnames)) + for simname in simnames: + sim = self.simulators[simname] + + ## Patch up the simulator source lists, expanding macros that aren't + ## in the macro sources: + sim.sources = self.expand_sources(sim.sources, dontexpand, debug) + sim.write_unit_test(stream, 0, test_label) + + def expand_sources(self, srcs, dontexpand, debug=0): + updated_srcs = [] + for src in srcs: + SU.emit_debug(debug, 2, "{0}: Source {1}".format(self.__class__.__name__, src)) + m = SPM._var_rx.match(src) + if m and m[1] not in dontexpand.union(_special_vars): + SU.emit_debug(debug, 2, "{0}: Expanding {1}".format(self.__class__.__name__, m[1])) + varexp = self.source_macros.get(m[1]) + if varexp is not None: + updated_srcs.extend(self.source_macros[m[1]]) + else: + print('!! Could not expand {0}'.format(m[1])) + else: + updated_srcs.append(src) + + if updated_srcs == srcs: + return srcs + else: + return self.expand_sources(updated_srcs, dontexpand, debug) + + def __len__(self): + return len(self.simulators) + +if '_dispatch' in pprint.PrettyPrinter.__dict__: + def simcoll_pprinter(pprinter, simcoll, stream, indent, allowance, context, level): + cls = simcoll.__class__ + stream.write(cls.__name__ + '(') + indent += len(cls.__name__) + 1 + pprinter._format(simcoll.source_macros, stream, indent, allowance + 2, context, level) + stream.write(',\n' + ' ' * indent) + uses_dict = dict([(sim, len(uses)) for (sim, uses) in simcoll.macro_uses.items()]) + pprinter._format(uses_dict, stream, indent, allowance + 2, context, level) + stream.write(',\n' + ' ' * indent) + pprinter._format(simcoll.simulators, stream, indent, allowance + 2, context, level) + stream.write(')') + + pprint.PrettyPrinter._dispatch[SimCollection.__repr__] = simcoll_pprinter diff --git a/cmake/simgen/simulators.py b/cmake/simgen/simulators.py new file mode 100644 index 00000000..71e8b406 --- /dev/null +++ b/cmake/simgen/simulators.py @@ -0,0 +1,75 @@ +"3b2" +"3b2-700" +"altair" +"altairz80" +"b5500" +"besm6" +"cdc1700" +"eclipse" +"gri" +"h316" +"hp2100" +"hp3000" +"i1401" +"i1620" +"i650" +"i701" +"i7010" +"i704" +"i7070" +"i7080" +"i7090" +"i7094" +"ibm1130" +"id16" +"id32" +"imlac" +"infoserver100" +"infoserver1000" +"infoserver150vxt" +"intel-mds" +"lgp" +"microvax1" +"microvax2" +"microvax2000" +"microvax3100" +"microvax3100e" +"microvax3100m80" +"microvax3900" +"nova" +"pdp1" +"pdp10" +"pdp10-ka" +"pdp10-ki" +"pdp10-kl" +"pdp10-ks" +"pdp11" +"pdp15" +"pdp4" +"pdp6" +"pdp7" +"pdp8" +"pdp9" +"rtvax1000" +"s3" +"scelbi" +"sds" +"sel32" +"sigma" +"ssem" +"swtp6800mp-a" +"swtp6800mp-a2" +"tt2500" +"tx-0" +"uc15" +"vax" +"vax730" +"vax750" +"vax780" +"vax8200" +"vax8600" +"vaxstation3100m30" +"vaxstation3100m38" +"vaxstation3100m76" +"vaxstation4000m60" +"vaxstation4000vlc" \ No newline at end of file diff --git a/cmake/simgen/text_file.py b/cmake/simgen/text_file.py new file mode 100644 index 00000000..818155c9 --- /dev/null +++ b/cmake/simgen/text_file.py @@ -0,0 +1,286 @@ +"""text_file + +provides the TextFile class, which gives an interface to text files +that (optionally) takes care of stripping comments, ignoring blank +lines, and joining lines with backslashes.""" + +import sys, io + + +class TextFile: + """Provides a file-like object that takes care of all the things you + commonly want to do when processing a text file that has some + line-by-line syntax: strip comments (as long as "#" is your + comment character), skip blank lines, join adjacent lines by + escaping the newline (ie. backslash at end of line), strip + leading and/or trailing whitespace. All of these are optional + and independently controllable. + + Provides a 'warn()' method so you can generate warning messages that + report physical line number, even if the logical line in question + spans multiple physical lines. Also provides 'unreadline()' for + implementing line-at-a-time lookahead. + + Constructor is called as: + + TextFile (filename=None, file=None, **options) + + It bombs (RuntimeError) if both 'filename' and 'file' are None; + 'filename' should be a string, and 'file' a file object (or + something that provides 'readline()' and 'close()' methods). It is + recommended that you supply at least 'filename', so that TextFile + can include it in warning messages. If 'file' is not supplied, + TextFile creates its own using 'io.open()'. + + The options are all boolean, and affect the value returned by + 'readline()': + strip_comments [default: true] + strip from "#" to end-of-line, as well as any whitespace + leading up to the "#" -- unless it is escaped by a backslash + lstrip_ws [default: false] + strip leading whitespace from each line before returning it + rstrip_ws [default: true] + strip trailing whitespace (including line terminator!) from + each line before returning it + skip_blanks [default: true} + skip lines that are empty *after* stripping comments and + whitespace. (If both lstrip_ws and rstrip_ws are false, + then some lines may consist of solely whitespace: these will + *not* be skipped, even if 'skip_blanks' is true.) + join_lines [default: false] + if a backslash is the last non-newline character on a line + after stripping comments and whitespace, join the following line + to it to form one "logical line"; if N consecutive lines end + with a backslash, then N+1 physical lines will be joined to + form one logical line. + collapse_join [default: false] + strip leading whitespace from lines that are joined to their + predecessor; only matters if (join_lines and not lstrip_ws) + errors [default: 'strict'] + error handler used to decode the file content + + Note that since 'rstrip_ws' can strip the trailing newline, the + semantics of 'readline()' must differ from those of the builtin file + object's 'readline()' method! In particular, 'readline()' returns + None for end-of-file: an empty string might just be a blank line (or + an all-whitespace line), if 'rstrip_ws' is true but 'skip_blanks' is + not.""" + + default_options = { 'strip_comments': 1, + 'skip_blanks': 1, + 'lstrip_ws': 0, + 'rstrip_ws': 1, + 'join_lines': 0, + 'collapse_join': 0, + 'errors': 'strict', + } + + def __init__(self, filename=None, file=None, **options): + """Construct a new TextFile object. At least one of 'filename' + (a string) and 'file' (a file-like object) must be supplied. + They keyword argument options are described above and affect + the values returned by 'readline()'.""" + if filename is None and file is None: + raise RuntimeError("you must supply either or both of 'filename' and 'file'") + + # set values for all options -- either from client option hash + # or fallback to default_options + for opt in self.default_options.keys(): + if opt in options: + setattr(self, opt, options[opt]) + else: + setattr(self, opt, self.default_options[opt]) + + # sanity check client option hash + for opt in options.keys(): + if opt not in self.default_options: + raise KeyError("invalid TextFile option '%s'" % opt) + + if file is None: + self.open(filename) + else: + self.filename = filename + self.file = file + self.current_line = 0 # assuming that file is at BOF! + + # 'linebuf' is a stack of lines that will be emptied before we + # actually read from the file; it's only populated by an + # 'unreadline()' operation + self.linebuf = [] + + def open(self, filename): + """Open a new file named 'filename'. This overrides both the + 'filename' and 'file' arguments to the constructor.""" + self.filename = filename + self.file = io.open(self.filename, 'r', errors=self.errors) + self.current_line = 0 + + def close(self): + """Close the current file and forget everything we know about it + (filename, current line number).""" + file = self.file + self.file = None + self.filename = None + self.current_line = None + file.close() + + def gen_error(self, msg, line=None): + outmsg = [] + if line is None: + line = self.current_line + outmsg.append(self.filename + ", ") + if isinstance(line, (list, tuple)): + outmsg.append("lines %d-%d: " % tuple(line)) + else: + outmsg.append("line %d: " % line) + outmsg.append(str(msg)) + return "".join(outmsg) + + def error(self, msg, line=None): + raise ValueError("error: " + self.gen_error(msg, line)) + + def warn(self, msg, line=None): + """Print (to stderr) a warning message tied to the current logical + line in the current file. If the current logical line in the + file spans multiple physical lines, the warning refers to the + whole range, eg. "lines 3-5". If 'line' supplied, it overrides + the current line number; it may be a list or tuple to indicate a + range of physical lines, or an integer for a single physical + line.""" + sys.stderr.write("warning: " + self.gen_error(msg, line) + "\n") + + def readline(self): + """Read and return a single logical line from the current file (or + from an internal buffer if lines have previously been "unread" + with 'unreadline()'). If the 'join_lines' option is true, this + may involve reading multiple physical lines concatenated into a + single string. Updates the current line number, so calling + 'warn()' after 'readline()' emits a warning about the physical + line(s) just read. Returns None on end-of-file, since the empty + string can occur if 'rstrip_ws' is true but 'strip_blanks' is + not.""" + # If any "unread" lines waiting in 'linebuf', return the top + # one. (We don't actually buffer read-ahead data -- lines only + # get put in 'linebuf' if the client explicitly does an + # 'unreadline()'. + if self.linebuf: + line = self.linebuf[-1] + del self.linebuf[-1] + return line + + buildup_line = '' + + while True: + # read the line, make it None if EOF + line = self.file.readline() + if line == '': + line = None + + if self.strip_comments and line: + + # Look for the first "#" in the line. If none, never + # mind. If we find one and it's the first character, or + # is not preceded by "\", then it starts a comment -- + # strip the comment, strip whitespace before it, and + # carry on. Otherwise, it's just an escaped "#", so + # unescape it (and any other escaped "#"'s that might be + # lurking in there) and otherwise leave the line alone. + + pos = line.find("#") + if pos == -1: # no "#" -- no comments + pass + + # It's definitely a comment -- either "#" is the first + # character, or it's elsewhere and unescaped. + elif pos == 0 or line[pos-1] != "\\": + # Have to preserve the trailing newline, because it's + # the job of a later step (rstrip_ws) to remove it -- + # and if rstrip_ws is false, we'd better preserve it! + # (NB. this means that if the final line is all comment + # and has no trailing newline, we will think that it's + # EOF; I think that's OK.) + eol = (line[-1] == '\n') and '\n' or '' + line = line[0:pos] + eol + + # If all that's left is whitespace, then skip line + # *now*, before we try to join it to 'buildup_line' -- + # that way constructs like + # hello \\ + # # comment that should be ignored + # there + # result in "hello there". + if line.strip() == "": + continue + else: # it's an escaped "#" + line = line.replace("\\#", "#") + + # did previous line end with a backslash? then accumulate + if self.join_lines and buildup_line: + # oops: end of file + if line is None: + self.warn("continuation line immediately precedes " + "end-of-file") + return buildup_line + + if self.collapse_join: + line = line.lstrip() + line = buildup_line + line + + # careful: pay attention to line number when incrementing it + if isinstance(self.current_line, list): + self.current_line[1] = self.current_line[1] + 1 + else: + self.current_line = [self.current_line, + self.current_line + 1] + # just an ordinary line, read it as usual + else: + if line is None: # eof + return None + + # still have to be careful about incrementing the line number! + if isinstance(self.current_line, list): + self.current_line = self.current_line[1] + 1 + else: + self.current_line = self.current_line + 1 + + # strip whitespace however the client wants (leading and + # trailing, or one or the other, or neither) + if self.lstrip_ws and self.rstrip_ws: + line = line.strip() + elif self.lstrip_ws: + line = line.lstrip() + elif self.rstrip_ws: + line = line.rstrip() + + # blank line (whether we rstrip'ed or not)? skip to next line + # if appropriate + if (line == '' or line == '\n') and self.skip_blanks: + continue + + if self.join_lines: + if line[-1] == '\\': + buildup_line = line[:-1] + continue + + if line[-2:] == '\\\n': + buildup_line = line[0:-2] + '\n' + continue + + # well, I guess there's some actual content there: return it + return line + + def readlines(self): + """Read and return the list of all logical lines remaining in the + current file.""" + lines = [] + while True: + line = self.readline() + if line is None: + return lines + lines.append(line) + + def unreadline(self, line): + """Push 'line' (a string) onto an internal buffer that will be + checked by future 'readline()' calls. Handy for implementing + a parser with line-at-a-time lookahead.""" + self.linebuf.append(line) diff --git a/cmake/simgen/utils.py b/cmake/simgen/utils.py new file mode 100644 index 00000000..3c071b04 --- /dev/null +++ b/cmake/simgen/utils.py @@ -0,0 +1,9 @@ +import re + + +def emit_debug(dval, level, msg): + if dval >= level: + print(msg) + +def do_debug(dval, level, act): + pass diff --git a/cmake/simgen/vax_simulators.py b/cmake/simgen/vax_simulators.py new file mode 100644 index 00000000..e2cba2d2 --- /dev/null +++ b/cmake/simgen/vax_simulators.py @@ -0,0 +1,51 @@ + +import simgen.basic_simulator as SBS + +class BasicVAXSimulator(SBS.SIMHBasicSimulator): + """ + """ + def __init__(self, sim_name, dir_macro, test_name, buildrom): + super().__init__(sim_name, dir_macro, test_name, buildrom) + + def write_unit_test(self, stream, indent, individual=False, test_label='default'): + stream.write('\n') + self.write_section(stream, 'add_unit_test', indent, individual=False, test_label=test_label, + section_name='vax_cc_{}'.format(self.sim_name), + section_srcs=['vax_cc.c'], + section_incs=self.includes) + +class VAXSimulator(BasicVAXSimulator): + """ + """ + def __init__(self, sim_name, dir_macro, test_name, buildrom): + super().__init__(sim_name, dir_macro, test_name, buildrom) + + def write_simulator(self, stream, indent, test_label='VAX'): + super().write_simulator(stream, indent, test_label) + stream.write(''' +set(vax_binary_dir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) +if (CMAKE_CONFIGURATION_TYPES) + string(APPEND vax_binary_dir "/$") +endif (CMAKE_CONFIGURATION_TYPES) + +add_custom_command(TARGET vax POST_BUILD + COMMAND "${CMAKE_COMMAND}" + -DSRCFILE=vax${CMAKE_EXECUTABLE_SUFFIX} + -DDSTFILE=microvax3900${CMAKE_EXECUTABLE_SUFFIX} + -DWORKING_DIR=${vax_binary_dir} + -P ${CMAKE_SOURCE_DIR}/cmake/file-link-copy.cmake + COMMENT "Symlink vax${CMAKE_EXECUTABLE_SUFFIX} to microvax3900${CMAKE_EXECUTABLE_SUFFIX}" + WORKING_DIRECTORY ${vax_binary_dir}) + +install( + CODE " + execute_process( + COMMAND ${CMAKE_COMMAND} + -DSRCFILE=vax${CMAKE_EXECUTABLE_SUFFIX} + -DDSTFILE=microvax3900${CMAKE_EXECUTABLE_SUFFIX} + -DWORKING_DIR=\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin + -P ${CMAKE_SOURCE_DIR}/cmake/file-link-copy.cmake)" + COMPONENT vax_family) +''') + stream.write('\n') + diff --git a/cmake/simh-packaging.cmake b/cmake/simh-packaging.cmake new file mode 100644 index 00000000..25c6fed2 --- /dev/null +++ b/cmake/simh-packaging.cmake @@ -0,0 +1,34 @@ +## The default runtime support component/family: +cpack_add_component(runtime_support + DISPLAY_NAME "Runtime support" + DESCRIPTION "Required SIMH runtime support (documentation, shared libraries)" + REQUIRED +) + +## Basic documentation for SIMH +install(FILES doc/simh.doc TYPE DOC COMPONENT runtime_support) + +cpack_add_component(b5500_family + DISPLAY_NAME "Burroughs 5500" + DESCRIPTION "The Burroughs 5500 system simulator. Simulators: b5500" +) +cpack_add_component(decpdp_family + DISPLAY_NAME "DEC PDP family" + DESCRIPTION "Digital Equipment Corporation PDP systems. Simulators: pdp6" +) +cpack_add_component(gould_family + DISPLAY_NAME "Gould simulators" + DESCRIPTION "Gould Systems simulators. Simulators: sel32" +) +cpack_add_component(ibm_family + DISPLAY_NAME "IBM" + DESCRIPTION "IBM system simulators: i650. Simulators: i701, i7010, i704, i7070, i7080, i7090, ibm360" +) +cpack_add_component(icl_family + DISPLAY_NAME "ICL simulators" + DESCRIPTION "ICL systems simulator family. Simulators: icl1900" +) +cpack_add_component(pdp10_family + DISPLAY_NAME "DEC PDP-10 collection" + DESCRIPTION "DEC PDP-10 architecture simulators and variants. Simulators: pdp10-ka, pdp10-ki, pdp10-kl, pdp10-ks" +) diff --git a/cmake/simh-simulators.cmake b/cmake/simh-simulators.cmake new file mode 100644 index 00000000..3fc7e6aa --- /dev/null +++ b/cmake/simh-simulators.cmake @@ -0,0 +1,48 @@ +## +## This is an automagically generated file. Do NOT EDIT. +## Any changes you make will be overwritten!! +## +## Make changes to the SIMH top-level makefile and then run the +## "cmake/generate.py" script to regenerate these files. +## +## cd cmake; python -m generate --help +## +## ------------------------------------------------------------ +set(B5500D "${CMAKE_SOURCE_DIR}/B5500") +set(I7000D "${CMAKE_SOURCE_DIR}/I7000") +set(I7010D "${CMAKE_SOURCE_DIR}/I7000") +set(IBM360D "${CMAKE_SOURCE_DIR}/IBM360") +set(ICL1900D "${CMAKE_SOURCE_DIR}/ICL1900") +set(KA10D "${CMAKE_SOURCE_DIR}/PDP10") +set(KI10D "${CMAKE_SOURCE_DIR}/PDP10") +set(KL10D "${CMAKE_SOURCE_DIR}/PDP10") +set(KS10D "${CMAKE_SOURCE_DIR}/PDP10") +set(PDP10D "${CMAKE_SOURCE_DIR}/PDP10") +set(PDP6D "${CMAKE_SOURCE_DIR}/PDP10") +set(SEL32D "${CMAKE_SOURCE_DIR}/SEL32") + +set(DISPLAYD "${CMAKE_SOURCE_DIR}/display") +set(DISPLAY340 "${DISPLAYD}/type340.c") +set(DISPLAYIII "${DISPLAYD}/iii.c") +set(DISPLAYNG "${DISPLAYD}/ng.c") +set(DISPLAYVT "${DISPLAYD}/vt11.c") + +## ---------------------------------------- + +if (NOT WITH_VIDEO) + ### Hack: Unset these variables so that they don't expand if + ### not building with video: + set(DISPLAY340 "") + set(DISPLAYIII "") + set(DISPLAYNG "") + set(DISPLAYVT "") +endif () + +## ---------------------------------------- + +add_subdirectory(B5500) +add_subdirectory(I7000) +add_subdirectory(IBM360) +add_subdirectory(ICL1900) +add_subdirectory(PDP10) +add_subdirectory(SEL32) diff --git a/cmake/vcpkg-setup.cmake b/cmake/vcpkg-setup.cmake new file mode 100644 index 00000000..54af50a2 --- /dev/null +++ b/cmake/vcpkg-setup.cmake @@ -0,0 +1,88 @@ +##+=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ +## vcpkg setup for MSVC. MinGW builds should use 'pacman' to install +## required dependency libraries. +##-=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ + +if (NOT USING_VCPKG) + return () +endif () + +if (NOT DEFINED VCPKG_TARGET_TRIPLET) + if (DEFINED ENV{VCPKG_DEFAULT_TRIPLET}) + ## User has a target triplet in mind, so use it. + set(VCPKG_TARGET_TRIPLET ENV{VCPKG_DEFAULT_TRIPLET}) + else () + ## Set the target triplet: + if (CMAKE_SYSTEM_NAME STREQUAL "Windows") + ## Default to x64, unless otherwise directed: + set(SIMH_VCPKG_ARCH "x64") + if(CMAKE_GENERATOR_PLATFORM MATCHES "[Ww][Ii][Nn]32") + set(SIMH_VCPKG_ARCH "x86") + elseif(CMAKE_GENERATOR_PLATFORM MATCHES "[Aa][Rr][Mm]64") + set(SIMH_VCPKG_ARCH "arm64") + elseif(CMAKE_GENERATOR_PLATFORM MATCHES "[Aa][Rr][Mm]") + set(SIMH_VCPKG_ARCH "arm") + endif() + + if (MSVC OR CMAKE_C_COMPILER_ID MATCHES ".*Clang") + set(SIMH_VCPKG_PLATFORM "windows") + set(SIMH_VCPKG_RUNTIME "") + if (NOT BUILD_SHARED_DEPS) + set(SIMH_VCPKG_RUNTIME "static") + endif () + elseif (MINGW OR CMAKE_C_COMPILER_ID STREQUAL "GNU") + set(SIMH_VCPKG_PLATFORM "mingw") + set(SIMH_VCPKG_RUNTIME "dynamic") + endif () + elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux") + if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(SIMH_VCPKG_ARCH "arm64") + else () + set(SIMH_VCPKG_ARCH "x64") + endif () + + set (SIMH_VCPKG_PLATFORM "linux") + else () + message(FATAL_ERROR "Could not determine VCPKG platform and system triplet." + "\n" + "(a) Are you sure that VCPKG is usable on this system? Check VCPKG_ROOT and ensure that" + "you have properly boostrapped VCPKG." + "\n" + "(b) If VCPKG is not usable on this system, unset the VCPKG_ROOT environment variable.") + endif () + + ## Set the default triplet in the environment; older vcpkg installs on + ## appveyor don't necessarily support the "--triplet" command line argument. + set(use_triplet "${SIMH_VCPKG_ARCH}-${SIMH_VCPKG_PLATFORM}") + if (SIMH_VCPKG_RUNTIME) + string(APPEND use_triplet "-${SIMH_VCPKG_RUNTIME}") + endif () + + set(VCPKG_TARGET_TRIPLET "${use_triplet}" CACHE STRING "Vcpkg target triplet (ex. x86-windows)" FORCE) + unset(use_triplet) + + set(ENV{VCPKG_DEFAULT_TRIPLET} ${VCPKG_TARGET_TRIPLET}) + endif () +endif () + +## Set VCPKG_CRT_LINKAGE to pass down so that SIMH matches the triplet's link +## environment. Otherwise, the build will get a lot of "/NODEFAULTLIB" warnings. +set(VCPKG_CRT_LINKAGE "dynamic") +if (VCPKG_TARGET_TRIPLET MATCHES ".*-static") + set(VCPKG_CRT_LINKAGE "static") +endif () + +message(STATUS "Executing deferred vcpkg toolchain initialization.\n" + " .. VCPKG target triplet is ${VCPKG_TARGET_TRIPLET}\n" + " .. VCPKG_CRT_LINKAGE is ${VCPKG_CRT_LINKAGE}") + +## Initialize vcpkg after CMake detects the compiler and we've to set the platform triplet. +## VCPKG_INSTALL_OPTIONS are additional args to 'vcpkg install'. Don't need to see the +## usage instructions each time... +if (NOT ("--no-print-usage" IN_LIST VCPKG_INSTALL_OPTIONS)) + list(APPEND VCPKG_INSTALL_OPTIONS + "--no-print-usage" + ) +endif () + +include(${SIMH_CMAKE_TOOLCHAIN_FILE}) diff --git a/slirp/CMakeLists.txt b/slirp/CMakeLists.txt new file mode 100644 index 00000000..4875471c --- /dev/null +++ b/slirp/CMakeLists.txt @@ -0,0 +1,56 @@ +## Compile SLirp as its own standalone library + +if (WITH_NETWORK) + set(SLIRP_SOURCES + "${CMAKE_SOURCE_DIR}/slirp/arp_table.c" + "${CMAKE_SOURCE_DIR}/slirp/bootp.c" + "${CMAKE_SOURCE_DIR}/slirp/bootp.h" + "${CMAKE_SOURCE_DIR}/slirp/cksum.c" + "${CMAKE_SOURCE_DIR}/slirp/dnssearch.c" + "${CMAKE_SOURCE_DIR}/slirp/if.c" + "${CMAKE_SOURCE_DIR}/slirp/ip_icmp.c" + "${CMAKE_SOURCE_DIR}/slirp/ip_input.c" + "${CMAKE_SOURCE_DIR}/slirp/ip_output.c" + "${CMAKE_SOURCE_DIR}/slirp/mbuf.c" + "${CMAKE_SOURCE_DIR}/slirp/misc.c" + "${CMAKE_SOURCE_DIR}/slirp/sbuf.c" + "${CMAKE_SOURCE_DIR}/slirp/slirp.c" + "${CMAKE_SOURCE_DIR}/slirp/socket.c" + "${CMAKE_SOURCE_DIR}/slirp/tcp_input.c" + "${CMAKE_SOURCE_DIR}/slirp/tcp_output.c" + "${CMAKE_SOURCE_DIR}/slirp/tcp_subr.c" + "${CMAKE_SOURCE_DIR}/slirp/tcp_timer.c" + "${CMAKE_SOURCE_DIR}/slirp/tftp.c" + "${CMAKE_SOURCE_DIR}/slirp/udp.c" + "${CMAKE_SOURCE_DIR}/slirp_glue/glib_qemu_stubs.c" + "${CMAKE_SOURCE_DIR}/slirp_glue/sim_slirp.c") + + add_library(slirp STATIC "${SLIRP_SOURCES}") + target_compile_definitions(slirp + PRIVATE + HAVE_SLIRP_NETWORK + USE_SIMH_SLIRP_DEBUG + $<$,$>>: + _WINSOCK_DEPRECATED_NO_WARNINGS + _CRT_NONSTDC_NO_WARNINGS + _CRT_SECURE_NO_WARNINGS> + INTERFACE + HAVE_SLIRP_NETWORK + USE_SIMH_SLIRP_DEBUG) + + target_include_directories(slirp + PRIVATE + "${CMAKE_SOURCE_DIR}" + "${CMAKE_SOURCE_DIR}/slirp" + "${CMAKE_SOURCE_DIR}/slirp_glue/qemu" + PUBLIC + "${CMAKE_SOURCE_DIR}/slirp_glue" + $<$:${CMAKE_SOURCE_DIR}/slirp_glue/qemu/win32/include>) + + target_compile_options(slirp PRIVATE ${EXTRA_TARGET_CFLAGS}) + target_link_options(slirp PRIVATE ${EXTRA_TARGET_LFLAGS}) + target_link_libraries(slirp PUBLIC $<$:Iphlpapi>) +else (WITH_NETWORK) + # Otherwise, just make slirp an empty interface library. + add_library(slirp INTERFACE) +endif (WITH_NETWORK)