From eab47c4f2674516d9499e837eff5b6b40f48213d Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Mon, 19 Feb 2024 08:14:16 +0000 Subject: Fixed compile on macOS Since Guichan is currently disabled on Homebrew, I've opted for adding it as a submodule instead. It currently references the 0.8 branch of Guichan, after I cherry-picked the CMake support from the master branch. When using SDL2 installed through Homebrew, it was necessary to use SDL2_LINK_LIBRARIES, since the libraries occupy various different directories. It no longer seems necessary to include an SDLMain.m, so I deleted it. Removed obsolete OS X instructions. Also added instructions for installing dependencies on Fedora. Removed mentioning of /announce and /who in the README, since they were removed for tmwAthena. --- .gitmodules | 3 + CMakeLists.txt | 14 ++ README.cmake | 12 -- README.md | 29 ++-- libs/guichan | 1 + src/CMakeLists.txt | 26 ++-- src/SDLMain.h | 16 --- src/SDLMain.m | 381 ----------------------------------------------------- 8 files changed, 53 insertions(+), 429 deletions(-) create mode 100644 .gitmodules create mode 160000 libs/guichan delete mode 100644 src/SDLMain.h delete mode 100644 src/SDLMain.m diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..316458cc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libs/guichan"] + path = libs/guichan + url = https://github.com/darkbitsorg/guichan.git diff --git a/CMakeLists.txt b/CMakeLists.txt index c9798acd..cff832e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,20 @@ IF (ENABLE_MANASERV) ADD_SUBDIRECTORY(libs/enet) ENDIF() +# On macOS we need to build Guichan ourselves since it is disabled in Homebrew +# This might also be a good idea for the Windows build +if(APPLE) + # This policy makes sure that the below options are not ignored by the + # added Guichan CMakeLists.txt + SET(CMAKE_POLICY_DEFAULT_CMP0077 NEW) + SET(ENABLE_ALLEGRO OFF) + SET(ENABLE_IRRLICHT OFF) + SET(ENABLE_SDL OFF) + SET(ENABLE_OPENGL OFF) + SET(BUILD_GUICHAN_SHARED OFF) + ADD_SUBDIRECTORY(libs/guichan) +endif() + ADD_SUBDIRECTORY(src) IF (GETTEXT_FOUND AND ENABLE_NLS) diff --git a/README.cmake b/README.cmake index b5691ff1..8471473f 100644 --- a/README.cmake +++ b/README.cmake @@ -4,7 +4,6 @@ 2. How do I... 3. Crosscompiling using CMake 4. Creating an installer binary for Windows - 5. Building on OS X This readme explains the most common parameters to CMake needed for building mana, as well as setting up a cross build environement to @@ -135,14 +134,3 @@ $ makensis -DDLLDIR=/build/mana-libs/lib/ -DPRODUCT_VERSION=0.1.0.0 \ -DUPX=true -DEXESUFFIX=/src setup.nsi and end up with the installer in mana-0.1.0.0-win32.exe - -5. Building on OS X -------------------- - -In your mana directory: - -$ export CC=/usr/bin/clang -$ export CXX=/usr/bin/clang++ -$ cmake . -$ make -$ src/mana diff --git a/README.md b/README.md index 1b001857..14e03fb1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The Mana client is written in C++ and builds upon: - SDL2, SDL2\_gfx, SDL2\_image, SDL2\_mixer, SDL2\_ttf, SDL2\_net (Media framework) - Guichan (GUI framework) - libxml2 (XML parsing and writing) -- PhysFS (Data files) +- PhysicsFS (Data files) - ENet (UDP networking library) - libcurl (HTTP downloads) - zlib (Archives) @@ -66,9 +66,7 @@ window. Here's a list of common commands: ``` - /help Displays the list of commands -- /announce broadcasts a global msg(Gm Cammand only) - /clear clears the chat window -- /who shows how many players are online - /where displays the map name your currently on - /whisper send a private msg to another player (format: /whisper ) @@ -111,19 +109,32 @@ to contact the developers of the game instead. Compiling the Client -------------------- -Installing the dependencies on Ubuntu +Installing the dependencies on Ubuntu: - sudo apt install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev \ + sudo apt install build-essential cmake \ + libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev \ libsdl2-net-dev libsdl2-ttf-dev libsdl2-gfx-dev \ libcurl4-openssl-dev libphysfs-dev libxml2-dev \ libguichan-dev libpng-dev gettext +Installing the dependencies on macOS (with Homebrew): + + brew install sdl2 sdl2_gfx sdl2_image sdl2_mixer sdl2_net sdl2_ttf \ + physfs curl + +Installing the dependencies on Fedora: + + sudo dnf install gcc-c++ cmake physfs-devel libcurl-devel guichan-devel \ + SDL2_image-devel SDL2_mixer-devel SDL2_net-devel \ + SDL2_ttf-devel SDL2_gfx-devel + Once the dependencies are installed, use CMake: - cmake . - cmake --build . --parallel + cmake -B build . + cmake --build build --parallel -This produces an executable in `src/mana`. If running it without installing, be -sure to run it from the repository root so that it can find its data files. +This produces an executable in `build/src/mana`. If running it without +installing, be sure to run it from the repository root so that it can find its +data files. See `README.cmake` for additional information. diff --git a/libs/guichan b/libs/guichan new file mode 160000 index 00000000..94914a02 --- /dev/null +++ b/libs/guichan @@ -0,0 +1 @@ +Subproject commit 94914a027276b8f60a028717bcbea4e674298c26 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 227302c1..628fab82 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,6 +23,12 @@ IF (ENABLE_MANASERV) SET(INTERNAL_LIBRARIES enet) ENDIF() +IF (APPLE) + INCLUDE_DIRECTORIES("../libs/guichan/include") + LINK_DIRECTORIES("../libs/guichan") + SET(INTERNAL_LIBRARIES ${INTERNAL_LIBRARIES} guichan) +ENDIF() + SET(FLAGS "-DPACKAGE_VERSION=\\\"${VERSION}\\\"") SET(FLAGS "${FLAGS} -DPKG_DATADIR=\\\"${PKG_DATADIR}/\\\"") SET(FLAGS "${FLAGS} -DLOCALEDIR=\\\"${LOCALEDIR}/\\\"") @@ -56,7 +62,9 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL SunOS) SET(EXTRA_LIBRARIES intl) ENDIF() -FIND_PACKAGE(Guichan REQUIRED) +IF(NOT APPLE) + FIND_PACKAGE(Guichan REQUIRED) +ENDIF() IF (WITH_OPENGL) FIND_PACKAGE(OpenGL REQUIRED) @@ -620,14 +628,6 @@ IF (WIN32) ) ENDIF (WIN32) -IF (APPLE) - SET(SRCS - ${SRCS} - SDLMain.h - SDLMain.m - ) -ENDIF (APPLE) - SET (PROGRAMS mana) IF (ENABLE_MANASERV) @@ -636,9 +636,9 @@ ELSE(ENABLE_MANASERV) ADD_EXECUTABLE(mana WIN32 ${SRCS} ${SRCS_TMWA}) ENDIF(ENABLE_MANASERV) -TARGET_LINK_LIBRARIES(mana +TARGET_LINK_LIBRARIES(mana PRIVATE ${INTERNAL_LIBRARIES} - ${SDL2_LIBRARIES} + ${SDL2_LINK_LIBRARIES} ${PNG_LIBRARIES} ${PHYSFS_LIBRARY} ${CURL_LIBRARIES} @@ -648,6 +648,10 @@ TARGET_LINK_LIBRARIES(mana ${LIBINTL_LIBRARIES} ${EXTRA_LIBRARIES}) +if(APPLE) + target_link_libraries(mana PRIVATE "-framework Foundation") +endif() + INSTALL(TARGETS mana RUNTIME DESTINATION ${PKG_BINDIR}) IF (CMAKE_SYSTEM_NAME STREQUAL SunOS) diff --git a/src/SDLMain.h b/src/SDLMain.h deleted file mode 100644 index c56d90cb..00000000 --- a/src/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/src/SDLMain.m b/src/SDLMain.m deleted file mode 100644 index 2434f81a..00000000 --- a/src/SDLMain.m +++ /dev/null @@ -1,381 +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 NSApplication (SDLApplication) -@end - -@implementation NSApplication (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]; - } -} - -#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 */ - [NSApplication 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)) - [NSApplication 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 - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - -- cgit v1.2.3-70-g09d2