diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index d5f3f4f0a..c073fe106 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -30,7 +30,7 @@ on: - '.github/workflows/macos.yml' jobs: - build: + build-intel-macos: # use lowest possible macOS running on x86_64 supported by brew to support more users runs-on: macos-13 steps: @@ -70,3 +70,44 @@ jobs: with: name: luanti-macos path: ./build/macos/*.zip + build-arm-macos-xcode: + runs-on: macos-14 + steps: + - uses: actions/checkout@v4 + - name: Install deps + run: | + source ./util/ci/common.sh + install_macos_deps + # brew jsoncpp do not include libjsoncpp.a, and if installed header conflict caused build failure + brew uninstall jsoncpp + + - name: Build with Cmake + run: | + mkdir build + cd build + cmake .. \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=14 \ + -DCMAKE_FIND_FRAMEWORK=LAST \ + -DCMAKE_INSTALL_PREFIX=../build/macos/ \ + -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE \ + -DENABLE_SYSTEM_JSONCPP=OFF + cmake --build . -j$(sysctl -n hw.logicalcpu) + make install + + - name: Build and Archive with Xcode + run: | + mkdir build_xcode + cd build_xcode + ../util/ci/build_xcode.sh + + - name: Tests + run: | + mkdir -p "${HOME}/Library/Application Support/minetest/games/" + ln -s "${PWD}/games/devtest" "${HOME}/Library/Application Support/minetest/games/" + ./build/macos/luanti.app/Contents/MacOS/luanti --run-unittests + ./build_xcode/luanti.xcarchive/Products/Applications/luanti.app/Contents/MacOS/luanti --run-unittests + + - name: Diff Resources + run: | + diff -rd ./build/macos/luanti.app/Contents/Resources ./build_xcode/build/Release/luanti.app/Contents/Resources || exit 1 + diff -rd ./build/macos/luanti.app/Contents/Resources ./build_xcode/luanti.xcarchive/Products/Applications/luanti.app/Contents/Resources || exit 1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 282fea4df..e496c0b7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,7 +272,11 @@ endif() if(APPLE) install(FILES "misc/luanti-icon.icns" DESTINATION "${SHAREDIR}") - install(FILES "misc/Info.plist" DESTINATION "${BUNDLE_PATH}/Contents") + install(FILES "${CMAKE_BINARY_DIR}/Info.plist" DESTINATION "${BUNDLE_PATH}/Contents") +endif() + +if(CMAKE_GENERATOR STREQUAL "Xcode") + set(client_RESOURCES "${CMAKE_SOURCE_DIR}/misc/luanti-icon.icns") endif() # Library pack diff --git a/doc/compiling/macos.md b/doc/compiling/macos.md index 6b9b4b6b8..09452004e 100644 --- a/doc/compiling/macos.md +++ b/doc/compiling/macos.md @@ -16,11 +16,13 @@ brew install cmake freetype gettext gmp hiredis jpeg-turbo jsoncpp leveldb libog Download source (this is the URL to the latest of source repository, which might not work at all times) using Git: ```bash -git clone --depth 1 https://github.com/minetest/minetest.git -cd minetest +git clone --depth 1 https://github.com/minetest/minetest.git luanti +cd luanti ``` -## Build +## Building for personal usage + +### Build ```bash mkdir build @@ -34,12 +36,65 @@ cmake .. \ make -j$(sysctl -n hw.logicalcpu) make install -# M1 Macs w/ MacOS >= BigSur -codesign --force --deep -s - macos/minetest.app +# Apple Silicon (M1/M2) Macs w/ MacOS >= BigSur signature for local run +codesign --force --deep -s - --entitlements ../misc/macos/entitlements/debug.entitlements macos/luanti.app ``` -## Run +If you are using LuaJIT with `MAP_JIT` support use `debug_map_jit.entitlements`. + +### Run ``` -open ./build/macos/minetest.app +open ./build/macos/luanti.app ``` + +## Building for distribution + +### Generate Xcode project + +```bash +mkdir build +cd build + +cmake .. \ + -DCMAKE_FIND_FRAMEWORK=LAST \ + -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE \ + -DFREETYPE_LIBRARY=/path/to/lib/dir/libfreetype.a \ + -DGETTEXT_INCLUDE_DIR=/path/to/include/dir \ + -DGETTEXT_LIBRARY=/path/to/lib/dir/libintl.a \ + -DLUA_LIBRARY=/path/to/lib/dir/libluajit-5.1.a \ + -DOGG_LIBRARY=/path/to/lib/dir/libogg.a \ + -DVORBIS_LIBRARY=/path/to/lib/dir/libvorbis.a \ + -DVORBISFILE_LIBRARY=/path/to/lib/dir/libvorbisfile.a \ + -DZSTD_LIBRARY=/path/to/lib/dir/libzstd.a \ + -DGMP_LIBRARY=/path/to/lib/dir/libgmp.a \ + -DJSON_LIBRARY=/path/to/lib/dir/libjsoncpp.a \ + -DENABLE_LEVELDB=OFF \ + -DENABLE_POSTGRESQL=OFF \ + -DENABLE_REDIS=OFF \ + -DJPEG_LIBRARY=/path/to/lib/dir/libjpeg.a \ + -DPNG_LIBRARY=/path/to/lib/dir/libpng.a \ + -DCMAKE_EXE_LINKER_FLAGS=-lbz2\ + -GXcode +``` + +If you are using LuaJIT with `MAP_JIT` support add `-DXCODE_CODE_SIGN_ENTITLEMENTS=../misc/macos/entitlements/release_map_jit.entitlements`. + +*WARNING:* You have to regenerate Xcode project if you switch commit, branch or etc. + +### Build and Run + +* Open generated Xcode project +* Select scheme `luanti` +* Configure signing Team etc. +* Run Build command +* Open application from `build/build/Debug/` directory or run it from Xcode + +### Archive and Run + +* Open generated Xcode project +* Select scheme `luanti` +* Configure signing Team etc. +* Run Build command +* Open application archive in finder, go into it, copy application and test it. + diff --git a/irr/src/CMakeLists.txt b/irr/src/CMakeLists.txt index 41d6645e9..1d2996734 100644 --- a/irr/src/CMakeLists.txt +++ b/irr/src/CMakeLists.txt @@ -313,21 +313,6 @@ add_library(IRRMESHOBJ OBJECT target_link_libraries(IRRMESHOBJ PUBLIC tiniergltf::tiniergltf) -add_library(IRROBJ OBJECT - CBillboardSceneNode.cpp - CCameraSceneNode.cpp - CDummyTransformationSceneNode.cpp - CEmptySceneNode.cpp - CMeshManipulator.cpp - CSceneCollisionManager.cpp - CSceneManager.cpp - CMeshCache.cpp -) - -# Make sure IRROBJ gets the transitive include directories for -# tiniergltf from IRRMESHOBJ. -target_link_libraries(IRROBJ PRIVATE IRRMESHOBJ) - set(IRRDRVROBJ CNullDriver.cpp CGLXManager.cpp @@ -460,14 +445,29 @@ add_library(IRRGUIOBJ OBJECT # Library -add_library(IrrlichtMt STATIC) +# There have to be some sources in IrrlichtMt to workaround Cmake Xcode generator bug +add_library(IrrlichtMt STATIC + CBillboardSceneNode.cpp + CCameraSceneNode.cpp + CDummyTransformationSceneNode.cpp + CEmptySceneNode.cpp + CMeshManipulator.cpp + CSceneCollisionManager.cpp + CSceneManager.cpp + CMeshCache.cpp +) foreach(object_lib - IRRMESHOBJ IRROBJ IRRVIDEOOBJ + IRRMESHOBJ IRRVIDEOOBJ IRRIOOBJ IRROTHEROBJ IRRGUIOBJ) # Set include directories for object library compilation target_include_directories(${object_lib} PRIVATE ${link_includes}) - # Add objects from object library to main library - target_sources(IrrlichtMt PRIVATE $) + if(CMAKE_GENERATOR STREQUAL "Xcode") + # Workaround for Cmake Xcode project generator + target_link_libraries(IrrlichtMt PRIVATE ${object_lib}) + else() + # Add objects from object library to main library + target_sources(IrrlichtMt PRIVATE $) + endif() if(BUILD_WITH_TRACY) target_link_libraries(${object_lib} PRIVATE Tracy::TracyClient) diff --git a/misc/Info.plist b/misc/macos/Info.plist.in similarity index 69% rename from misc/Info.plist rename to misc/macos/Info.plist.in index 74ed6fe5c..3daf446b6 100644 --- a/misc/Info.plist +++ b/misc/macos/Info.plist.in @@ -9,11 +9,15 @@ CFBundleIconFile luanti-icon.icns CFBundleName - Luanti + @PROJECT_NAME_CAPITALIZED@ CFBundleDisplayName - Luanti + @PROJECT_NAME_CAPITALIZED@ CFBundleIdentifier org.luanti.luanti + CFBundleVersion + @VERSION_STRING@ + LSApplicationCategoryType + public.app-category.games NSHighResolutionCapable diff --git a/misc/macos/entitlements/debug.entitlements b/misc/macos/entitlements/debug.entitlements new file mode 100644 index 000000000..0b35f6b0f --- /dev/null +++ b/misc/macos/entitlements/debug.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.get-task-allow + + + diff --git a/misc/macos/entitlements/debug_map_jit.entitlements b/misc/macos/entitlements/debug_map_jit.entitlements new file mode 100644 index 000000000..39760e5a1 --- /dev/null +++ b/misc/macos/entitlements/debug_map_jit.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.get-task-allow + + + diff --git a/misc/macos/entitlements/release.entitlements b/misc/macos/entitlements/release.entitlements new file mode 100644 index 000000000..a1c430a57 --- /dev/null +++ b/misc/macos/entitlements/release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.cs.allow-unsigned-executable-memory + + + diff --git a/misc/macos/entitlements/release_map_jit.entitlements b/misc/macos/entitlements/release_map_jit.entitlements new file mode 100644 index 000000000..d35e43ae5 --- /dev/null +++ b/misc/macos/entitlements/release_map_jit.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.cs.allow-jit + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2275a2075..65e5ab6bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -598,6 +598,14 @@ if(PRECOMPILE_HEADERS) target_precompile_headers(EngineCommon PRIVATE ${PRECOMPILED_HEADERS_LIST}) endif() +if(APPLE) + # Configure the Info.plist file + configure_file( + "${CMAKE_SOURCE_DIR}/misc/macos/Info.plist.in" + "${CMAKE_BINARY_DIR}/Info.plist" + ) +endif() + if(BUILD_CLIENT) # client target if(ANDROID) @@ -605,6 +613,47 @@ if(BUILD_CLIENT) else() add_executable(${PROJECT_NAME}) endif() + + + if(CMAKE_GENERATOR STREQUAL "Xcode") + # File with used entitlements + set(XCODE_CODE_SIGN_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/misc/macos/entitlements/release.entitlements" CACHE FILEPATH "Path to entitlements file to be used with Xcode signing") + + set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/build") + set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/build") + + target_sources(${PROJECT_NAME} PUBLIC ${client_RESOURCES}) + + add_dependencies(${PROJECT_NAME} translations) + + set_target_properties(${PROJECT_NAME} PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_BINARY_DIR}/Info.plist" + RESOURCE "${client_RESOURCES}" + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.luanti.luanti" + XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES" + XCODE_ATTRIBUTE_INSTALL_PATH "/Applications" + XCODE_ATTRIBUTE_SKIP_INSTALL "NO" + XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym" + XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS "YES" + XCODE_ATTRIBUTE_CONFIGURATION_BUILD_DIR "$(inherited)" + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${XCODE_CODE_SIGN_ENTITLEMENTS}" + ) + + # Prinv env variables to file, for debugging purposes + #add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + # COMMAND ${CMAKE_COMMAND} -E env bash ${CMAKE_SOURCE_DIR}/util/xcode/capture_env.sh ${CMAKE_BINARY_DIR}/post_env.log + #) + + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/util/xcode/install_resources.cmake + -DTARGET_DIR=$ + -DBINARY_DIR=${CMAKE_BINARY_DIR} + -DPROJECT_NAME=${PROJECT_NAME} + COMMENT "Checking INSTALL_ROOT and copying resources" + ) + endif() + list(SORT client_SRCS) target_sources(${PROJECT_NAME} PRIVATE $ diff --git a/util/ci/build_xcode.sh b/util/ci/build_xcode.sh new file mode 100755 index 000000000..b31d22789 --- /dev/null +++ b/util/ci/build_xcode.sh @@ -0,0 +1,24 @@ +#!/bin/bash -e + +cmake .. \ + -DCMAKE_FIND_FRAMEWORK=LAST \ + -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE \ + -DFREETYPE_LIBRARY=/opt/homebrew/lib/libfreetype.a \ + -DGETTEXT_INCLUDE_DIR=/path/to/include/dir \ + -DGETTEXT_LIBRARY=/opt/homebrew/lib/libintl.a \ + -DLUA_LIBRARY=/opt/homebrew/lib/libluajit-5.1.a \ + -DOGG_LIBRARY=/opt/homebrew/lib/libogg.a \ + -DVORBIS_LIBRARY=/opt/homebrew/lib/libvorbis.a \ + -DVORBISFILE_LIBRARY=/opt/homebrew/lib/libvorbisfile.a \ + -DZSTD_LIBRARY=/opt/homebrew/lib/libzstd.a \ + -DGMP_LIBRARY=/opt/homebrew/lib/libgmp.a \ + -DENABLE_SYSTEM_JSONCPP=OFF \ + -DENABLE_LEVELDB=OFF \ + -DENABLE_POSTGRESQL=OFF \ + -DENABLE_REDIS=OFF \ + -DJPEG_LIBRARY=/opt/homebrew/lib/libjpeg.a \ + -DPNG_LIBRARY=/opt/homebrew/lib/libpng.a \ + -DCMAKE_EXE_LINKER_FLAGS=-lbz2\ + -GXcode +xcodebuild -project luanti.xcodeproj -scheme luanti -configuration Release build +xcodebuild -project luanti.xcodeproj -scheme luanti -archivePath ./luanti.xcarchive archive diff --git a/util/xcode/capture_env.sh b/util/xcode/capture_env.sh new file mode 100644 index 000000000..a447e5bbc --- /dev/null +++ b/util/xcode/capture_env.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +env > $1 diff --git a/util/xcode/install_resources.cmake b/util/xcode/install_resources.cmake new file mode 100644 index 000000000..01fb663f0 --- /dev/null +++ b/util/xcode/install_resources.cmake @@ -0,0 +1,63 @@ + +# This is only one working solution I found to be working for normal and Archive builds under Xcode 15.4 +# I expect higger sensitivity to Xcode version. + +if(DEFINED ENV{INSTALL_ROOT} AND EXISTS "$ENV{INSTALL_ROOT}") + set(RESOURCES_DIR "$ENV{INSTALL_ROOT}/Applications/$ENV{PRODUCT_NAME}.app/Contents/Resources") +else() + set(RESOURCES_DIR "$ENV{TARGET_BUILD_DIR}/$ENV{UNLOCALIZED_RESOURCES_FOLDER_PATH}") +endif() + +# Write debug information to a file +#file(WRITE "$ENV{PROJECT_FILE_PATH}/../debug_output.txt" "INSTALL_ROOT: $ENV{INSTALL_ROOT}\n") +#file(APPEND "$ENV{PROJECT_FILE_PATH}/../debug_output.txt" "RESOURCES_DIR: ${RESOURCES_DIR}\n") +#file(APPEND "$ENV{PROJECT_FILE_PATH}/../debug_output.txt" "TARGET_BUILD_DIR: $ENV{TARGET_BUILD_DIR}\n") +#file(APPEND "$ENV{PROJECT_FILE_PATH}/../debug_output.txt" "BUILT_PRODUCTS_DIR: $ENV{BUILT_PRODUCTS_DIR}\n") +#file(APPEND "$ENV{PROJECT_FILE_PATH}/../debug_output.txt" "SOURCE_ROOT: $ENV{SOURCE_ROOT}\n") +#file(APPEND "$ENV{PROJECT_FILE_PATH}/../debug_output.txt" "PRODUCT_NAME: $ENV{PRODUCT_NAME}\n") + +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_directory + "$ENV{SOURCE_ROOT}/builtin" + "${RESOURCES_DIR}/builtin" +) +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_directory + "$ENV{SOURCE_ROOT}/client/shaders" + "${RESOURCES_DIR}/client/shaders" +) +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_directory + "$ENV{SOURCE_ROOT}/fonts" + "${RESOURCES_DIR}/fonts" +) +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_directory + "$ENV{PROJECT_FILE_PATH}/../locale" + "${RESOURCES_DIR}/locale" +) +execute_process( + COMMAND ${CMAKE_COMMAND} -E make_directory + "${RESOURCES_DIR}/$ENV{PRODUCT_NAME}" +) +set(RESOURCE_LUANTI_FILES + "$ENV{SOURCE_ROOT}/README.md" + "$ENV{SOURCE_ROOT}/doc/client_lua_api.md" + "$ENV{SOURCE_ROOT}/doc/lua_api.md" + "$ENV{SOURCE_ROOT}/doc/menu_lua_api.md" + "$ENV{SOURCE_ROOT}/minetest.conf.example" + "$ENV{SOURCE_ROOT}/doc/texture_packs.md" + "$ENV{SOURCE_ROOT}/doc/world_format.md" +) +foreach (file ${RESOURCE_LUANTI_FILES}) + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy + "${file}" + "${RESOURCES_DIR}/$ENV{PRODUCT_NAME}/" + ) +endforeach() +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_directory + "$ENV{SOURCE_ROOT}/textures/base/pack" + "${RESOURCES_DIR}/textures/base/pack" +)