diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index 45a26740e..2c3114e25 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -23,12 +23,22 @@ jobs: os: ubuntu-20.04 test: 0 preset: linux-gcc-release - - platform: mac - os: macos-10.15 + - platform: mac-intel + os: macos-12 test: 0 pack: 1 extension: dmg - preset: macos-ninja-release + preset: macos-conan-ninja-release + conan_profile: macos-intel + artifact_platform: intel + - platform: mac-arm + os: macos-12 + test: 0 + pack: 1 + extension: dmg + preset: macos-arm-conan-ninja-release + conan_profile: macos-arm + artifact_platform: arm - platform: mxe os: ubuntu-20.04 mxe: i686-w64-mingw32.shared @@ -59,6 +69,18 @@ jobs: MXE_TARGET: ${{ matrix.mxe }} VCMI_BUILD_PLATFORM: x64 + - name: Conan setup + if: "${{ matrix.conan_profile != '' }}" + run: | + pip3 install conan + conan profile new default --detect + conan install . \ + --install-folder=conan-generated \ + --no-imports \ + --build=never \ + --profile:build=default \ + --profile:host=CI/conan/${{ matrix.conan_profile }} + - name: Git branch name id: git-branch-name uses: EthanSK/git-branch-name-action@v1 @@ -66,6 +88,9 @@ jobs: - name: Build Number run: | source '${{github.workspace}}/CI/get_package_name.sh' + if [ '${{ matrix.artifact_platform }}' ]; then + VCMI_PACKAGE_FILE_NAME+="-${{ matrix.artifact_platform }}" + fi echo VCMI_PACKAGE_FILE_NAME="$VCMI_PACKAGE_FILE_NAME" >> $GITHUB_ENV echo VCMI_PACKAGE_NAME_SUFFIX="$VCMI_PACKAGE_NAME_SUFFIX" >> $GITHUB_ENV env: diff --git a/.gitignore b/.gitignore index 37b8cb4e1..fb947fc5c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /server/vcmiserver /launcher/vcmilauncher /launcher/vcmilauncher_automoc.cpp +/conan-generated build/ .cache/* diff --git a/CI/conan/macos-arm b/CI/conan/macos-arm new file mode 100644 index 000000000..4e58922ba --- /dev/null +++ b/CI/conan/macos-arm @@ -0,0 +1,11 @@ +[settings] +os=Macos +os.version=11.0 +arch=armv8 +compiler=apple-clang +compiler.version=13 +compiler.libcxx=libc++ +build_type=Release +[options] +[build_requires] +[env] diff --git a/CI/conan/macos-intel b/CI/conan/macos-intel new file mode 100644 index 000000000..f1717b4aa --- /dev/null +++ b/CI/conan/macos-intel @@ -0,0 +1,11 @@ +[settings] +os=Macos +os.version=10.13 +arch=x86_64 +compiler=apple-clang +compiler.version=13 +compiler.libcxx=libc++ +build_type=Release +[options] +[build_requires] +[env] diff --git a/CI/mac-arm/before_install.sh b/CI/mac-arm/before_install.sh new file mode 100755 index 000000000..c90b6a1b1 --- /dev/null +++ b/CI/mac-arm/before_install.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +DEPS_FILENAME=intel-cross-arm +. CI/mac/before_install.sh diff --git a/CI/mac-intel/before_install.sh b/CI/mac-intel/before_install.sh new file mode 100755 index 000000000..fcbcea328 --- /dev/null +++ b/CI/mac-intel/before_install.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +DEPS_FILENAME=intel +. CI/mac/before_install.sh diff --git a/CI/mac/before_install.sh b/CI/mac/before_install.sh old mode 100644 new mode 100755 index 209d3657c..62ab43c42 --- a/CI/mac/before_install.sh +++ b/CI/mac/before_install.sh @@ -1,8 +1,9 @@ -#!/bin/sh +#!/usr/bin/env bash -brew update -#brew pin python@3.9 -brew install smpeg2 libpng freetype qt5 ffmpeg ninja boost tbb luajit -brew install sdl2 sdl2_ttf sdl2_image sdl2_mixer +echo DEVELOPER_DIR=/Applications/Xcode_13.4.1.app >> $GITHUB_ENV -echo CMAKE_PREFIX_PATH="$(brew --prefix)/opt/qt5:$CMAKE_PREFIX_PATH" >> $GITHUB_ENV +brew install ninja + +mkdir ~/.conan ; cd ~/.conan +curl -L "https://github.com/vcmi/vcmi-deps-macos/releases/latest/download/$DEPS_FILENAME.txz" \ + | tar -xf - diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f09fc070..86674ddf5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,9 +9,6 @@ project(VCMI) # - There is problem with running fixup_bundle in main project after subdirectories. # Cmake put them after all install code of main CMakelists in cmake_install.cmake # Currently I just added extra add_subdirectory and CMakeLists.txt in osx directory to bypass that. -# - Try to fix build with RPATH. -# Currently if CMAKE_MACOSX_RPATH=1 then AI libs unable to find @rpath/libvcmi.dylib -# I tried to set few different INSTALL_RPATH for all targets in AI directory, but nothing worked. # # MXE: # - Try to implement MXE support into BundleUtilities so we can deploy deps automatically @@ -131,10 +128,6 @@ set(CMAKE_MAP_IMPORTED_CONFIG_MINSIZEREL MinSizeRel Release RelWithDebInfo "") # Release falls back to RelWithDebInfo, then MinSizeRel set(CMAKE_MAP_IMPORTED_CONFIG_RELEASE Release RelWithDebInfo MinSizeRel "") -if(APPLE) - set(CMAKE_MACOSX_RPATH 0) -endif(APPLE) - if(MINGW OR MSVC) # Windows Vista or newer for FuzzyLite 6 to compile add_definitions(-D_WIN32_WINNT=0x0600) @@ -226,7 +219,13 @@ endif() ############################################ find_package(Boost 1.48.0 REQUIRED COMPONENTS date_time filesystem locale program_options system thread) + find_package(ZLIB REQUIRED) +# Conan compatibility +if(TARGET zlib::zlib) + add_library(ZLIB::ZLIB ALIAS zlib::zlib) +endif() + find_package(ffmpeg REQUIRED COMPONENTS avutil swscale avformat avcodec) option(FORCE_BUNDLED_MINIZIP "Force bundled Minizip library" OFF) if(NOT FORCE_BUNDLED_MINIZIP) @@ -291,6 +290,7 @@ elseif(APPLE) # includes lib path which determines where to install shared libraries (either /lib or /lib64) include(GNUInstallDirs) + set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks") if(ENABLE_MONOLITHIC_INSTALL) set(BIN_DIR "." CACHE STRING "Where to install binaries") set(LIB_DIR "." CACHE STRING "Where to install main library") @@ -302,7 +302,7 @@ elseif(APPLE) set(APP_BUNDLE_RESOURCES_DIR "${APP_BUNDLE_CONTENTS_DIR}/Resources") set(BIN_DIR "${APP_BUNDLE_BINARY_DIR}" CACHE STRING "Where to install binaries") - set(LIB_DIR "${APP_BUNDLE_BINARY_DIR}" CACHE STRING "Where to install main library") + set(LIB_DIR "${APP_BUNDLE_CONTENTS_DIR}/Frameworks" CACHE STRING "Where to install main library") set(DATA_DIR "${APP_BUNDLE_RESOURCES_DIR}/Data" CACHE STRING "Where to install data files") endif() else() diff --git a/CMakePresets.json b/CMakePresets.json index 8118819a9..e1735cbfd 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -11,8 +11,8 @@ "PACKAGE_FILE_NAME" : "$env{VCMI_PACKAGE_FILE_NAME}", "PACKAGE_NAME_SUFFIX" : "$env{VCMI_PACKAGE_NAME_SUFFIX}", "CMAKE_BUILD_TYPE": "RelWithDebInfo", - "FORCE_BUNDLED_FL" : "0", - "ENABLE_TEST": "0" + "FORCE_BUNDLED_FL": "OFF", + "ENABLE_TEST": "OFF" } }, { @@ -65,6 +65,26 @@ "description": "VCMI MacOS Ninja", "inherits": "default-release" }, + { + "name": "macos-conan-ninja-release", + "displayName": "Ninja+Conan release", + "description": "VCMI MacOS Ninja using Conan", + "inherits": "default-release", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/conan-generated/conan_toolchain.cmake", + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "macos-arm-conan-ninja-release", + "displayName": "Ninja+Conan arm64 release", + "description": "VCMI MacOS-arm64 Ninja using Conan", + "inherits": "macos-conan-ninja-release", + "cacheVariables": { + "ENABLE_ERM": "OFF", + "ENABLE_LUA": "OFF" + } + }, { "name": "macos-xcode-release", "displayName": "XCode release", @@ -99,6 +119,16 @@ "configurePreset": "macos-ninja-release", "inherits": "default-release" }, + { + "name": "macos-conan-ninja-release", + "configurePreset": "macos-conan-ninja-release", + "inherits": "default-release" + }, + { + "name": "macos-arm-conan-ninja-release", + "configurePreset": "macos-arm-conan-ninja-release", + "inherits": "default-release" + }, { "name": "windows-msvc-release", "configurePreset": "windows-msvc-release", diff --git a/client/CMT.cpp b/client/CMT.cpp index 41e8b7396..00d7615f5 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -10,7 +10,6 @@ // CMT.cpp : Defines the entry point for the console application. // #include "StdInc.h" -#include #include @@ -160,7 +159,7 @@ static void SDLLogCallback(void* userdata, #if defined(VCMI_WINDOWS) && !defined(__GNUC__) && defined(VCMI_WITH_DEBUG_CONSOLE) int wmain(int argc, wchar_t* argv[]) -#elif defined(VCMI_APPLE) || defined(VCMI_ANDROID) +#elif defined(VCMI_ANDROID) int SDL_main(int argc, char *argv[]) #else int main(int argc, char * argv[]) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index b9c7b841a..7304518b4 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -142,7 +142,6 @@ set(client_HEADERS Graphics.h mapHandler.h resource.h - SDLMain.h SDLRWwrapper.h ) @@ -152,9 +151,7 @@ if(ANDROID) # android needs client/server to be libraries, not executables, so w return() endif() -if(APPLE) - set(client_SRCS ${client_SRCS} SDLMain.m) -elseif(WIN32) +if(WIN32) set(client_ICON "VCMI_client.rc") endif() diff --git a/client/SDLMain.h b/client/SDLMain.h deleted file mode 100644 index c56d90cbe..000000000 --- a/client/SDLMain.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#ifndef _SDLMain_h_ -#define _SDLMain_h_ - -#import - -@interface SDLMain : NSObject -@end - -#endif /* _SDLMain_h_ */ diff --git a/client/SDLMain.m b/client/SDLMain.m deleted file mode 100644 index b065a2009..000000000 --- a/client/SDLMain.m +++ /dev/null @@ -1,383 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#include "SDL.h" -#include "SDLMain.h" -#include /* for MAXPATHLEN */ -#include - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ -@interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; -@end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - const NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ -@interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; -@end -#endif - -@interface SDLApplication : NSApplication -@end - -@implementation SDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} -@end - -/* The main class of the application, the application's delegate */ -@implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { - chdir(parentdir); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} -@end - - -@implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - -@end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff --git a/client/gui/CAnimation.cpp b/client/gui/CAnimation.cpp index 803b1811d..3828056fe 100644 --- a/client/gui/CAnimation.cpp +++ b/client/gui/CAnimation.cpp @@ -10,8 +10,6 @@ #include "StdInc.h" #include "CAnimation.h" -#include - #include "../CBitmapHandler.h" #include "../Graphics.h" #include "../gui/SDL_Extensions.h" diff --git a/client/lobby/CLobbyScreen.cpp b/client/lobby/CLobbyScreen.cpp index 6eca3d0dd..22a26e244 100644 --- a/client/lobby/CLobbyScreen.cpp +++ b/client/lobby/CLobbyScreen.cpp @@ -131,25 +131,19 @@ void CLobbyScreen::startScenario(bool allowOnlyAI) CSH->sendStartGame(allowOnlyAI); buttonStart->block(true); } - catch(ExceptionMapMissing & e) + catch(std::exception & e) { - (void)e; // unused - } - catch(ExceptionNoHuman & e) - { - (void)e; // unused - // You must position yourself prior to starting the game. - CInfoWindow::showInfoDialog(std::ref(CGI->generaltexth->allTexts[530]), CInfoWindow::TCompsInfo(), PlayerColor(1)); - } - catch(ExceptionNoTemplate & e) - { - (void)e; // unused - // Could not create a random map that fits current choices. - CInfoWindow::showInfoDialog(std::ref(CGI->generaltexth->allTexts[751]), CInfoWindow::TCompsInfo(), PlayerColor(1)); + logGlobal->error("Exception during startScenario: %s", e.what()); + + if(std::string(e.what()) == "ExceptionNoHuman") + CInfoWindow::showInfoDialog(std::ref(CGI->generaltexth->allTexts[530]), CInfoWindow::TCompsInfo(), PlayerColor(1)); + + if(std::string(e.what()) == "ExceptionNoTemplate") + CInfoWindow::showInfoDialog(std::ref(CGI->generaltexth->allTexts[751]), CInfoWindow::TCompsInfo(), PlayerColor(1)); } catch(...) { - + logGlobal->error("Unknown exception"); } } diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 000000000..f2b564057 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,197 @@ +from conan import ConanFile +from conan.tools.apple import is_apple_os +from conan.tools.cmake import CMakeDeps +from conans import tools + +import os + +class VCMI(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "CMakeToolchain" + requires = [ + "boost/1.79.0", + "ffmpeg/4.4", + "minizip/1.2.12", + "onetbb/2021.3.0", # Nullkiller AI + "qt/5.15.5", # launcher + "sdl/2.0.20", + "sdl_image/2.0.5", + "sdl_mixer/2.0.4", + "sdl_ttf/2.0.18", + ] + + def _disableQtOptions(disableFlag, options): + return " ".join([f"-{disableFlag}-{tool}" for tool in options]) + + _qtOptions = [ + _disableQtOptions("no", [ + "gif", + "ico", + ]), + _disableQtOptions("no-feature", [ + # xpm format is required for Drag'n'Drop support + "imageformat_bmp", + "imageformat_jpeg", + "imageformat_ppm", + "imageformat_xbm", + + # we need only macdeployqt + # TODO: disabling these doesn't disable generation of CMake targets + # TODO: in Qt 6.3 it's a part of qtbase + # "assistant", + # "designer", + # "distancefieldgenerator", + # "kmap2qmap", + # "linguist", + # "makeqpf", + # "pixeltool", + # "qdbus", + # "qev", + # "qtattributionsscanner", + # "qtdiag", + # "qtpaths", + # "qtplugininfo", + ]), + ] + + default_options = { + # shared libs + "boost/*:shared": True, + "libpng/*:shared": True, # SDL_image and Qt depend on it + "minizip/*:shared": True, + "onetbb/*:shared": True, + "qt/*:shared": True, + + # we need only the following Boost parts: + # date_time filesystem locale program_options system thread + # some other parts are also enabled because they're dependents + # see e.g. conan-center-index/recipes/boost/all/dependencies + "boost/*:without_context": True, + "boost/*:without_contract": True, + "boost/*:without_coroutine": True, + "boost/*:without_fiber": True, + "boost/*:without_graph": True, + "boost/*:without_graph_parallel": True, + "boost/*:without_iostreams": True, + "boost/*:without_json": True, + "boost/*:without_log": True, + "boost/*:without_math": True, + "boost/*:without_mpi": True, + "boost/*:without_nowide": True, + "boost/*:without_python": True, + "boost/*:without_random": True, + "boost/*:without_regex": True, + "boost/*:without_serialization": True, + "boost/*:without_stacktrace": True, + "boost/*:without_test": True, + "boost/*:without_timer": True, + "boost/*:without_type_erasure": True, + "boost/*:without_wave": True, + + "ffmpeg/*:avdevice": False, + "ffmpeg/*:avfilter": False, + "ffmpeg/*:postproc": False, + "ffmpeg/*:swresample": False, + "ffmpeg/*:with_freetype": False, + "ffmpeg/*:with_libfdk_aac": False, + "ffmpeg/*:with_libmp3lame": False, + "ffmpeg/*:with_libvpx": False, + "ffmpeg/*:with_libwebp": False, + "ffmpeg/*:with_libx264": False, + "ffmpeg/*:with_libx265": False, + "ffmpeg/*:with_openh264": False, + "ffmpeg/*:with_openjpeg": False, + "ffmpeg/*:with_opus": False, + "ffmpeg/*:with_programs": False, + "ffmpeg/*:with_ssl": False, + "ffmpeg/*:with_vorbis": False, + + "sdl/*:vulkan": False, + + "sdl_image/*:imageio": True, + "sdl_image/*:lbm": False, + "sdl_image/*:pnm": False, + "sdl_image/*:svg": False, + "sdl_image/*:tga": False, + "sdl_image/*:with_libjpeg": False, + "sdl_image/*:with_libtiff": False, + "sdl_image/*:with_libwebp": False, + "sdl_image/*:xcf": False, + "sdl_image/*:xpm": False, + "sdl_image/*:xv": False, + + "sdl_mixer/*:flac": False, + "sdl_mixer/*:mad": False, + "sdl_mixer/*:mikmod": False, + "sdl_mixer/*:modplug": False, + "sdl_mixer/*:nativemidi": False, + "sdl_mixer/*:opus": False, + "sdl_mixer/*:wav": False, + + "qt/*:config": " ".join(_qtOptions), + "qt/*:openssl": False, + "qt/*:qttools": True, + "qt/*:with_freetype": False, + "qt/*:with_libjpeg": False, + "qt/*:with_md4c": False, + "qt/*:with_mysql": False, + "qt/*:with_odbc": False, + "qt/*:with_openal": False, + "qt/*:with_pq": False, + + # transitive deps + "pcre2/*:build_pcre2grep": False, # doesn't link to overridden bzip2 & zlib, the tool isn't needed anyway + } + + def configure(self): + # workaround: macOS deployment target isn't passed to linker when building Boost + # TODO: remove when https://github.com/conan-io/conan-center-index/pull/12468 is merged + if is_apple_os(self): + osVersion = self.settings.get_safe("os.version") + if osVersion: + deploymentTargetFlag = tools.apple_deployment_target_flag( + self.settings.os, + osVersion, + self.settings.get_safe("os.sdk"), + self.settings.get_safe("os.subsystem"), + self.settings.get_safe("arch") + ) + self.options["boost"].extra_b2_flags = f"linkflags={deploymentTargetFlag}" + + def requirements(self): + # use Apple system libraries instead of external ones + if is_apple_os(self): + systemLibsOverrides = [ + "bzip2/1.0.8", + "libiconv/1.17", + "sqlite3/3.39.2", + "zlib/1.2.12", + ] + for lib in systemLibsOverrides: + self.requires(f"{lib}@kambala/apple", override=True) + + # TODO: the latest official release of LuaJIT (which is quite old) can't be built for arm Mac + if self.settings.os != "Macos" or self.settings.arch != "armv8": + self.requires("luajit/2.0.5") + + def generate(self): + deps = CMakeDeps(self) + if os.getenv("USE_CONAN_WITH_ALL_CONFIGS", "0") == "0": + deps.generate() + return + + # allow using prebuilt deps with all configs + # credits to https://github.com/conan-io/conan/issues/11607#issuecomment-1188500937 for the workaround + configs = [ + "Debug", + "MinSizeRel", + "Release", + "RelWithDebInfo", + ] + for config in configs: + print(f"generating CMakeDeps for {config}") + deps.configuration = config + deps.generate() + + def imports(self): + self.copy("*.dylib", "Frameworks", "lib") diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 49d8c338d..2675d68df 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -396,7 +396,7 @@ assign_source_group(${lib_SRCS} ${lib_HEADERS}) add_library(vcmi SHARED ${lib_SRCS} ${lib_HEADERS}) set_target_properties(vcmi PROPERTIES COMPILE_DEFINITIONS "VCMI_DLL=1") target_link_libraries(vcmi PUBLIC - minizip::minizip SDL2::SDL2 ZLIB::ZLIB + minizip::minizip ZLIB::ZLIB ${SYSTEM_LIBS} Boost::boost Boost::thread Boost::filesystem Boost::program_options Boost::locale Boost::date_time ) @@ -404,6 +404,7 @@ target_include_directories(vcmi PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${CMAKE_HOME_DIRECTORY} PUBLIC ${CMAKE_HOME_DIRECTORY}/include + PRIVATE ${SDL2_INCLUDE_DIR} ) if(WIN32) diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index d8b457f38..5a59862cc 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -948,7 +948,7 @@ void CBonusSystemNode::getAllBonusesRec(BonusList &out) const getAllParents(lparents); for(auto parent : lparents) - parent->bonuses.getAllBonuses(beforeUpdate); + parent->getAllBonusesRec(beforeUpdate); bonuses.getAllBonuses(beforeUpdate); diff --git a/lib/StartInfo.cpp b/lib/StartInfo.cpp index 0b92a5e56..97b703616 100644 --- a/lib/StartInfo.cpp +++ b/lib/StartInfo.cpp @@ -64,7 +64,7 @@ std::string StartInfo::getCampaignName() const void LobbyInfo::verifyStateBeforeStart(bool ignoreNoHuman) const { if(!mi) - throw ExceptionMapMissing(); + throw std::domain_error("ExceptionMapMissing"); //there must be at least one human player before game can be started std::map::const_iterator i; @@ -73,12 +73,12 @@ void LobbyInfo::verifyStateBeforeStart(bool ignoreNoHuman) const break; if(i == si->playerInfos.cend() && !ignoreNoHuman) - throw ExceptionNoHuman(); + throw std::domain_error("ExceptionNoHuman"); if(si->mapGenOptions && si->mode == StartInfo::NEW_GAME) { if(!si->mapGenOptions->checkOptions()) - throw ExceptionNoTemplate(); + throw std::domain_error("ExceptionNoTemplate"); } } diff --git a/lib/StartInfo.h b/lib/StartInfo.h index 913161220..e42b88555 100644 --- a/lib/StartInfo.h +++ b/lib/StartInfo.h @@ -187,6 +187,3 @@ struct DLL_LINKAGE LobbyInfo : public LobbyState TeamID getPlayerTeamId(PlayerColor color); }; -class ExceptionMapMissing : public std::exception {}; -class ExceptionNoHuman : public std::exception {}; -class ExceptionNoTemplate : public std::exception {}; diff --git a/lib/filesystem/CBinaryReader.cpp b/lib/filesystem/CBinaryReader.cpp index 643dcdd71..5a4808003 100644 --- a/lib/filesystem/CBinaryReader.cpp +++ b/lib/filesystem/CBinaryReader.cpp @@ -10,6 +10,7 @@ #include "StdInc.h" #include "CBinaryReader.h" +//FIXME:library file depends on SDL - make cause troubles #include #include "CInputStream.h" #include "../CGeneralTextHandler.h" diff --git a/lib/spells/TargetCondition.cpp b/lib/spells/TargetCondition.cpp index 47d1e113c..cb4ddc976 100644 --- a/lib/spells/TargetCondition.cpp +++ b/lib/spells/TargetCondition.cpp @@ -298,7 +298,7 @@ protected: //this stack is from other player else if(battleWideNegation) { - if(!m->ownerMatches(target, false)) + if(m->ownerMatches(target, false)) return true; } return false; diff --git a/osx/CMakeLists.txt b/osx/CMakeLists.txt index 84f0d2d0b..990a0ee15 100644 --- a/osx/CMakeLists.txt +++ b/osx/CMakeLists.txt @@ -1,38 +1,49 @@ # We need to keep this code into separate directory so CMake will execute it after all other subdirectories install code # Otherwise we can't fix Mac bundle dependencies since binaries wouldn't be there when this code executed if(APPLE) + set(bundleDir "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_DIR}") + set(bundleContentsDir "${bundleDir}/Contents") + if(ENABLE_LAUNCHER) - find_program(TOOL_MACDEPLOYQT NAMES macdeployqt PATHS ${qt_base_dir}/bin) - if(NOT TOOL_MACDEPLOYQT) - message(FATAL_ERROR "Could not find macdeployqt") + # cross-compiled Qt 5 builds macdeployqt for target platform instead of host + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_SYSTEM_PROCESSOR) + # deploy Qt dylibs with macdeployqt + find_program(TOOL_MACDEPLOYQT NAMES macdeployqt PATHS ${qt_base_dir}/bin) + if(NOT TOOL_MACDEPLOYQT) + message(FATAL_ERROR "Could not find macdeployqt") + endif() + install(CODE " + execute_process(COMMAND + \"${TOOL_MACDEPLOYQT}\" \"${bundleDir}\" -verbose=2 + ) + ") + else() + # simulate macdeployqt behavior, main Qt libs are copied by conan + get_target_property(qmakePath Qt5::qmake IMPORTED_LOCATION) + execute_process(COMMAND + "${qmakePath}" -query QT_INSTALL_PLUGINS + OUTPUT_VARIABLE qtPluginsDir + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + install(DIRECTORY + ${qtPluginsDir}/ + DESTINATION ${APP_BUNDLE_DIR}/Contents/PlugIns + ) + install(CODE " + file(WRITE ${bundleContentsDir}/Resources/qt.conf + \"[Paths]\nPlugins = PlugIns\" + ) + ") endif() - install(CODE " - execute_process(COMMAND ${TOOL_MACDEPLOYQT} \"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_DIR}\" -verbose=2) - ") endif() - # Manually fix VCMI library links in AI libraries with install_name_tool + # deploy other dylibs with conan install(CODE " - set(BU_CHMOD_BUNDLE_ITEMS ON) - include(BundleUtilities) - fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_DIR}\" \"\" \"\") - execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change \"libvcmi.dylib\" \"@executable_path/../Frameworks/libvcmi.dylib\" \"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_BINARY_DIR}/AI/libBattleAI.dylib\") - execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change \"libvcmi.dylib\" \"@executable_path/../Frameworks/libvcmi.dylib\" \"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_BINARY_DIR}/AI/libEmptyAI.dylib\") - execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change \"libvcmi.dylib\" \"@executable_path/../Frameworks/libvcmi.dylib\" \"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_BINARY_DIR}/AI/libNullkiller.dylib\") - execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change \"libvcmi.dylib\" \"@executable_path/../Frameworks/libvcmi.dylib\" \"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_BINARY_DIR}/AI/libStupidAI.dylib\") - execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change \"libvcmi.dylib\" \"@executable_path/../Frameworks/libvcmi.dylib\" \"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_BINARY_DIR}/AI/libVCAI.dylib\") - - set(ENABLE_ERM ${ENABLE_ERM}) - if(ENABLE_ERM) - execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change \"libvcmi.dylib\" \"@executable_path/../Frameworks/libvcmi.dylib\" \"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_BINARY_DIR}/scripting/libvcmiERM.dylib\") - endif() - set(ENABLE_LUA ${ENABLE_LUA}) - if(ENABLE_LUA) - execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change \"libvcmi.dylib\" \"@executable_path/../Frameworks/libvcmi.dylib\" \"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_BINARY_DIR}/scripting/libvcmiLua.dylib\") - endif() - - execute_process(COMMAND rm \"\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_BINARY_DIR}/libvcmi.dylib\") - " COMPONENT Runtime) + execute_process(COMMAND + conan imports \"${CMAKE_SOURCE_DIR}\" --install-folder \"${CMAKE_SOURCE_DIR}/conan-generated\" --import-folder \"${bundleContentsDir}\" + ) + file(REMOVE \"${bundleContentsDir}/conan_imports_manifest.txt\") + ") endif(APPLE) # This will likely only work for Vcpkg diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7c8a5aa05..4f4a562a2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,4 @@ -if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0") - include(GoogleTest) -endif() +include(GoogleTest) set(googleTest_Dir ${CMAKE_CURRENT_SOURCE_DIR}/googletest) if(EXISTS ${googleTest_Dir})