From 28ac9396ccb8d9fd4bb7c478e2e7e86edb8ea383 Mon Sep 17 00:00:00 2001 From: def Date: Tue, 14 Dec 2021 15:12:48 +0100 Subject: [PATCH] Support libfat directory for macOS, use arm64 libs (fixes #3250) Builds and runs successfully with: cmake -DCMAKE_BUILD_TYPE=Release -GNinja -DPREFER_BUNDLED_LIBS=ON -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" ninja package_dmg Tested successfully with native arm64 and rosetta No discord support for universal binary --- CMakeLists.txt | 50 +++++++++++++++++++++++------------ cmake/FindFreetype.cmake | 4 +-- ddnet-libs | 2 +- scripts/darwin_strip_rpath.py | 2 +- scripts/dmg.py | 4 +++ 5 files changed, 41 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e51dd288..81220d4c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -319,6 +319,20 @@ set(TARGETS_LINK) # Targets with a linking stage. # DEPENDENCIES ######################################################################## +if((CMAKE_OSX_ARCHITECTURES STREQUAL "arm64;x86_64" OR CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64;arm64") AND TARGET_OS STREQUAL "mac") + set(FAT ON) +else() + set(FAT OFF) +endif() + +if(FAT) + set(LIB_DIR "${TARGET_OS}/libfat") +elseif(TARGET_CPU_ARCHITECTURE STREQUAL "arm" OR TARGET_CPU_ARCHITECTURE STREQUAL "arm64") + set(LIB_DIR "${TARGET_OS}/lib${TARGET_CPU_ARCHITECTURE}") +else() + set(LIB_DIR "${TARGET_OS}/lib${TARGET_BITS}") +endif() + function(set_extra_dirs_lib VARIABLE NAME) set("PATHS_${VARIABLE}_LIBDIR" PARENT_SCOPE) set("HINTS_${VARIABLE}_LIBDIR" PARENT_SCOPE) @@ -328,11 +342,7 @@ function(set_extra_dirs_lib VARIABLE NAME) set(TYPE PATHS) endif() if(TARGET_BITS AND TARGET_OS) - if(TARGET_CPU_ARCHITECTURE STREQUAL "arm" OR TARGET_CPU_ARCHITECTURE STREQUAL "arm64") - set(DIR "ddnet-libs/${NAME}/${TARGET_OS}/lib${TARGET_CPU_ARCHITECTURE}") - else() - set(DIR "ddnet-libs/${NAME}/${TARGET_OS}/lib${TARGET_BITS}") - endif() + set(DIR "ddnet-libs/${NAME}/${LIB_DIR}") set("${TYPE}_${VARIABLE}_LIBDIR" "${DIR}" PARENT_SCOPE) set("EXTRA_${VARIABLE}_LIBDIR" "${DIR}" PARENT_SCOPE) endif() @@ -448,7 +458,7 @@ message(STATUS "******** DDNet ********") if(NOT TARGET_OS STREQUAL "mac") message(STATUS "Target OS: ${TARGET_OS} ${TARGET_BITS}bit") else() - message(STATUS "Target OS: ${TARGET_OS} ${TARGET_BITS}bit (SDK: ${CMAKE_OSX_SYSROOT})") + message(STATUS "Target OS: ${TARGET_OS} ${TARGET_BITS}bit (SDK: ${CMAKE_OSX_SYSROOT}, architectures: ${CMAKE_OSX_ARCHITECTURES})") endif() message(STATUS "Compiler: ${CMAKE_CXX_COMPILER}") message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") @@ -2557,6 +2567,12 @@ if(CLIENT AND (DMGTOOLS_FOUND OR HDIUTIL)) foreach(dir ${DMG_MKDIRS}) list(APPEND DMG_MKDIR_COMMANDS COMMAND ${CMAKE_COMMAND} -E make_directory ${DMG_TMPDIR}/${dir}) endforeach() + + set(DMG_DISCORD_COPY_COMMAND) + if(NOT FAT) + set(DMG_DISCORD_COPY_COMMAND COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/discord/${LIB_DIR}/discord_game_sdk.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/) + endif() + add_custom_command(OUTPUT ${CPACK_PACKAGE_FILE_NAME}.dmg COMMAND ${CMAKE_COMMAND} -E remove_directory ${DMG_TMPDIR} ${DMG_MKDIR_COMMANDS} @@ -2566,15 +2582,15 @@ if(CLIENT AND (DMGTOOLS_FOUND OR HDIUTIL)) COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/other/icons/${TARGET_CLIENT}.icns ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Resources/ COMMAND ${CMAKE_COMMAND} -E copy bundle/client/Info.plist ${PROJECT_SOURCE_DIR}/other/bundle/client/PkgInfo ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/ COMMAND ${CMAKE_COMMAND} -E copy $ ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/MacOS/ - COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/ddnet-libs/sdl/mac/lib64/SDL2.framework ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/SDL2.framework - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/discord/mac/lib64/discord_game_sdk.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/freetype/mac/lib64/libfreetype.6.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/mac/lib64/libavcodec.58.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/mac/lib64/libavformat.58.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/mac/lib64/libavutil.56.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/mac/lib64/libswresample.3.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/mac/lib64/libswscale.5.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/websockets/mac/lib64/libwebsockets.18.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ + COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/ddnet-libs/sdl/${LIB_DIR}/SDL2.framework ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/SDL2.framework + ${DMG_DISCORD_COPY_COMMAND} + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/freetype/${LIB_DIR}/libfreetype.6.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/${LIB_DIR}/libavcodec.58.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/${LIB_DIR}/libavformat.58.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/${LIB_DIR}/libavutil.56.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/${LIB_DIR}/libswresample.3.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/ffmpeg/${LIB_DIR}/libswscale.5.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/websockets/${LIB_DIR}/libwebsockets.18.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/libsteam_api.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/ COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/darwin_strip_rpath.py ${CMAKE_OTOOL} ${CMAKE_INSTALL_NAME_TOOL} ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/MacOS/${TARGET_CLIENT} COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath @loader_path/../Frameworks ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/MacOS/${TARGET_CLIENT} @@ -2605,8 +2621,8 @@ if(CLIENT AND (DMGTOOLS_FOUND OR HDIUTIL)) COMMAND ${CMAKE_COMMAND} -E copy bundle/server/Info.plist ${PROJECT_SOURCE_DIR}/other/bundle/server/PkgInfo ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/ COMMAND ${CMAKE_COMMAND} -E copy $ $ ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/MacOS/ COMMAND ${CMAKE_COMMAND} -E make_directory ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/Frameworks/ - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/sqlite3/mac/lib64/libsqlite3.0.dylib ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/Frameworks/ - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/websockets/mac/lib64/libwebsockets.18.dylib ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/Frameworks/ + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/sqlite3/${LIB_DIR}/libsqlite3.0.dylib ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/Frameworks/ + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/ddnet-libs/websockets/${LIB_DIR}/libwebsockets.18.dylib ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/Frameworks/ COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/darwin_strip_rpath.py ${CMAKE_OTOOL} ${CMAKE_INSTALL_NAME_TOOL} ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/MacOS/${TARGET_SERVER} COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath @loader_path/../Frameworks ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/MacOS/${TARGET_SERVER} COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/lib/libsqlite3.0.dylib @rpath/libsqlite3.0.dylib ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/MacOS/${TARGET_SERVER} diff --git a/cmake/FindFreetype.cmake b/cmake/FindFreetype.cmake index 1e755d66a..a8f53daae 100644 --- a/cmake/FindFreetype.cmake +++ b/cmake/FindFreetype.cmake @@ -5,14 +5,14 @@ endif() set_extra_dirs_lib(FREETYPE freetype) find_library(FREETYPE_LIBRARY - NAMES freetype freetype.6 + NAMES freetype.6 freetype HINTS ${HINTS_FREETYPE_LIBDIR} ${PC_FREETYPE_LIBDIR} ${PC_FREETYPE_LIBRARY_DIRS} PATHS ${PATHS_FREETYPE_LIBDIR} ${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH} ) set_extra_dirs_include(FREETYPE freetype "${FREETYPE_LIBRARY}") find_path(FREETYPE_INCLUDEDIR - NAMES config/ftheader.h freetype/config/ftheader.h + NAMES freetype/config/ftheader.h config/ftheader.h PATH_SUFFIXES freetype2 HINTS ${HINTS_FREETYPE_INCLUDEDIR} ${PC_FREETYPE_INCLUDEDIR} ${PC_FREETYPE_INCLUDE_DIRS} PATHS ${PATHS_FREETYPE_INCLUDEDIR} diff --git a/ddnet-libs b/ddnet-libs index 381d44a07..8a58ccfba 160000 --- a/ddnet-libs +++ b/ddnet-libs @@ -1 +1 @@ -Subproject commit 381d44a072c1bc05b3765af9c207dce3286ac3e8 +Subproject commit 8a58ccfbaec23b02119a8ef466657f82b12104e3 diff --git a/scripts/darwin_strip_rpath.py b/scripts/darwin_strip_rpath.py index 25a931820..0e4595f45 100644 --- a/scripts/darwin_strip_rpath.py +++ b/scripts/darwin_strip_rpath.py @@ -32,7 +32,7 @@ def main(): lc_rpath_cmds = [cmd for cmd in cmds if cmd[0] == "cmd LC_RPATH"] path_regex = re.compile(r"^path (.*) \(offset \d+\)$") - rpaths = [k[0] for k in [[path_regex.match(part).group(1) for part in cmd if path_regex.match(part)] for cmd in lc_rpath_cmds]] + rpaths = {k[0] for k in [[path_regex.match(part).group(1) for part in cmd if path_regex.match(part)] for cmd in lc_rpath_cmds]} print("Found paths:") for path in rpaths: diff --git a/scripts/dmg.py b/scripts/dmg.py index 517814fee..cd68c3018 100644 --- a/scripts/dmg.py +++ b/scripts/dmg.py @@ -74,6 +74,10 @@ class Hdiutil(Dmg): if symlinks: raise NotImplementedError("symlinks are not yet implemented") for i in range(5): + try: + os.remove(dmg) + except FileNotFoundError: + pass try: self._hdiutil('create', '-volname', volume_name, '-srcdir', directory, dmg) except subprocess.CalledProcessError as e: