1
0
mirror of https://github.com/open-simh/simh.git synced 2026-02-16 04:43:32 +00:00
Files
open-simh.simh/cmake/dep-link.cmake
Calvin Buckley 361ef76dbc Initial support for vmnet.framework
On macOS, tap devices for L2 networking are not supported out of the
box. While a kext can be added to provide tap support, the kext
experience is not very good; Apple has strongly recommended against
their usage.

As a replacement that's documented and recommended, Apple introduced the
vmnet framework, intended for emulators and virtualization software
explicitly. This API requires macOS 10.10, with bridged network support
coming in macOS 10.15.

This introduces basic support for vmnet.framework in SIMH. I've tested
it by booting an emulated MicroVAX 3800 from an emulated InfoServer 150,
where it was able to reach OpenVMS 7.3 standalone BACKUP.
2025-08-17 15:25:22 -04:00

373 lines
17 KiB
CMake

##+
## 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. <sigh!>
## (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 $<TARGET_NAME_IF_EXISTS:SDL2::SDL2main>)
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_PROPERTY:PkgConfig::VDE,INTERFACE_COMPILE_DEFINITIONS>)
target_include_directories(simh_network INTERFACE $<TARGET_PROPERTY:PkgConfig::VDE,INTERFACE_INCLUDE_DIRECTORIES>)
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)
if (WITH_VMNET AND APPLE)
target_link_libraries(simh_network INTERFACE "-framework vmnet")
target_compile_definitions(simh_network INTERFACE HAVE_VMNET_NETWORK)
endif(WITH_VMNET AND APPLE)
## 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)