simh-testsetgenerator/cmake/dep-link.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

346 lines
16 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})
string(STRIP ${each_lib} stripped_lib)
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})
string(STRIP ${each_lib} stripped_lib)
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)
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)
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)
## 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)