simh-testsetgenerator/cmake/add_simulator.cmake
B. Scott Michel 8b14bb69be
CMake build infrastructure II (#53)
* CMake build infrastructure

The squashed commit that builds and packages releases for the SIMH
simulator suite with CMake, version 3.14 or newer.

See README-CMake.md for documentation.
2023-05-17 20:18:42 -04:00

426 lines
16 KiB
CMake

## 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)
function(build_simcore _targ)
cmake_parse_arguments(SIMH "VIDEO;INT64;ADDR64;BESM6_SDL_HACK" "" "" ${ARGN})
add_library(${_targ} STATIC ${SIM_SOURCES})
# Components that need to be turned on while building the library, but
# don't export out to the dependencies (hence PRIVATE.)
set_target_properties(${_targ} PROPERTIES
C_STANDARD 99
)
target_compile_definitions(${_targ} PRIVATE USE_SIM_CARD USE_SIM_IMD)
target_compile_options(${_targ} PRIVATE ${EXTRA_TARGET_CFLAGS})
target_link_options(${_targ} PRIVATE ${EXTRA_TARGET_LFLAGS})
# Make sure that the top-level directory is part of the libary's include path:
target_include_directories("${_targ}" PUBLIC "${CMAKE_SOURCE_DIR}")
if (SIMH_INT64)
target_compile_definitions(${_targ} PUBLIC USE_INT64)
endif (SIMH_INT64)
if (SIMH_ADDR64)
target_compile_definitions(${_targ} PUBLIC USE_ADDR64)
endif (SIMH_ADDR64)
if (SIMH_VIDEO)
if (WITH_VIDEO)
# It's the video library
target_sources(${_targ} PRIVATE ${SIM_VIDEO_SOURCES})
target_link_libraries(${_targ} 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. <sigh!>
target_compile_definitions("${_targ}" PUBLIC SDL_MAIN_AVAILABLE)
endif ()
endif ()
target_link_libraries(${_targ} PUBLIC
simh_network
simh_regexp
os_features
thread_lib
)
# Define SIM_BUILD_TOOL for the simulator'
target_compile_definitions("${_targ}" PRIVATE
"SIM_BUILD_TOOL=CMake (${CMAKE_GENERATOR})"
)
# Ensure that sim_rev.h picks up .git-commit-id.h if the git command is
# available.
if (GIT_COMMAND)
target_compile_definitions("${_targ}" PRIVATE SIM_NEED_GIT_COMMIT_ID)
endif ()
add_dependencies(${_targ} update_sim_commit)
# 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"
)
## 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 <regexp>"
## 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)
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 ()
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}\\\$<SEMICOLON>${native_binary_dir}\\$<SEMICOLON>")
string(REPLACE ";" "\\\$<SEMICOLON>" 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 ()
## Front panel test.
##
## From all evidence in makefile, sim_frontpanel isn't used yet by any targets.
##
## Needs curses...
add_executable(frontpaneltest
${CMAKE_SOURCE_DIR}/frontpanel/FrontPanelTest.c
${CMAKE_SOURCE_DIR}/sim_sock.c
${CMAKE_SOURCE_DIR}/sim_frontpanel.c)
target_include_directories(frontpaneltest PUBLIC "${CMAKE_SOURCE_DIR}")
target_link_libraries(frontpaneltest PUBLIC os_features thread_lib)
if (WIN32)
target_link_libraries(frontpaneltest PUBLIC simh_network)
if (MSVC)
target_link_options(frontpaneltest PUBLIC "/SUBSYSTEM:CONSOLE")
elseif (MINGW)
target_link_options(frontpaneltest PUBLIC "-mconsole")
endif ()
endif (WIN32)