941: Add cross-compiled DMG archives r=Learath2 a=heinrich5991

Currently they only contain the client and the archives are a lot larger
than the current release artifacts.
This commit is contained in:
bors[bot] 2017-12-08 14:20:49 +00:00
commit a2f010c1fe
10 changed files with 393 additions and 133 deletions

View file

@ -21,6 +21,7 @@ else()
set(PROJECT_VERSION_MAJOR ${VERSION_MAJOR})
set(PROJECT_VERSION_MINOR ${VERSION_MINOR})
set(PROJECT_VERSION_PATCH ${VERSION_PATCH})
set(PROJECT_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
@ -149,6 +150,19 @@ else()
set(ZLIB_FOUND NO)
endif()
if(TARGET_OS AND TARGET_OS STREQUAL "mac")
find_program(DMG dmg)
find_program(HFSPLUS hfsplus)
find_program(NEWFS_HFS newfs_hfs)
if(DMG AND HFSPLUS AND NEWFS_HFS)
set(DMGTOOLS_FOUND ON)
else()
set(DMGTOOLS_FOUND OFF)
endif()
find_program(HDIUTIL hdiutil)
endif()
message(STATUS "******** DDNet ********")
message(STATUS "Target OS: ${TARGET_OS} ${TARGET_BITS}bit")
message(STATUS "Compiler: ${CMAKE_CXX_COMPILER}")
@ -169,11 +183,17 @@ function(show_dependency_status NAME FOUND PATH)
endfunction()
show_dependency_status("Curl" ${CURL_FOUND} "${CURL_LIBRARY}")
if(TARGET_OS AND TARGET_OS STREQUAL "mac")
show_dependency_status("Dmg tools" ${DMGTOOLS_FOUND} "")
endif()
show_dependency_status("Freetype" ${FREETYPE_FOUND} "${FREETYPE_LIBRARY}")
if(DOWNLOAD_GTEST)
show_dependency_status("Git" ${GIT_FOUND} "${GIT_EXECUTABLE}")
endif()
show_dependency_status("GTest" ${GTEST_FOUND} "${GTEST_LIBRARY}")
if(TARGET_OS AND TARGET_OS STREQUAL "mac")
show_dependency_status("Hdiutil" ${HDIUTIL} "")
endif()
if(MYSQL)
show_dependency_status("MySQL" ${MYSQL_FOUND} "${MYSQL_LIBRARY}")
endif()
@ -935,6 +955,15 @@ target_link_libraries(${TARGET_SERVER} ${LIBS_SERVER})
list(APPEND TARGETS_OWN ${TARGET_SERVER})
list(APPEND TARGETS_LINK ${TARGET_SERVER})
if(TARGET_OS AND TARGET_OS STREQUAL "mac")
set(SERVER_LAUNCHER_SRC src/osxlaunch/server.mm)
set(TARGET_SERVER_LAUNCHER ${TARGET_SERVER}-Launcher)
add_executable(${TARGET_SERVER_LAUNCHER} ${SERVER_LAUNCHER_SRC})
target_link_libraries(${TARGET_SERVER_LAUNCHER} ${COCOA})
list(APPEND TARGETS_OWN ${TARGET_SERVER_LAUNCHER})
list(APPEND TARGETS_LINK ${TARGET_SERVER_LAUNCHER})
endif()
########################################################################
# VARIOUS TARGETS
########################################################################
@ -1146,6 +1175,7 @@ if(TARGET_OS AND TARGET_BITS)
endif()
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME})
set(CPACK_ARCHIVE_PORTABLE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})
set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-src)
set(CPACK_SOURCE_FILES
CMakeLists.txt
@ -1201,7 +1231,7 @@ if(TARGET_OS STREQUAL "windows")
endif()
if(CMAKE_VERSION VERSION_GREATER 3.6 OR CMAKE_VERSION VERSION_EQUAL 3.6)
set(EXTRA_ARGS DESTINATION ${CPACK_PACKAGE_FILE_NAME} COMPONENT portable)
set(EXTRA_ARGS DESTINATION ${CPACK_PACKAGE_FILE_NAME} COMPONENT portable EXCLUDE_FROM_ALL)
install(TARGETS ${CPACK_TARGETS} ${EXTRA_ARGS})
install(DIRECTORY ${CPACK_DIRS} ${EXTRA_ARGS})
install(FILES ${CPACK_FILES} ${EXTRA_ARGS})
@ -1209,23 +1239,97 @@ else()
message(WARNING "Cannot create CPack targets, CMake version too old. Use CMake 3.6 or newer.")
endif()
set(COPY_FILE_COMMANDS)
set(COPY_DIR_COMMANDS)
set(COPY_TARGET_COMMANDS)
foreach(file ${CPACK_FILES})
list(APPEND COPY_FILE_COMMANDS COMMAND cmake -E copy ${PROJECT_SOURCE_DIR}/${file} ${CPACK_PACKAGE_FILE_NAME}/)
endforeach()
foreach(dir ${CPACK_DIRS})
list(APPEND COPY_DIR_COMMAND COMMAND cmake -E copy_directory ${PROJECT_SOURCE_DIR}/${dir} ${CPACK_PACKAGE_FILE_NAME}/${dir})
endforeach()
foreach(target ${CPACK_TARGETS})
list(APPEND COPY_TARGET_COMMANDS COMMAND cmake -E copy $<TARGET_FILE:${target}> ${CPACK_PACKAGE_FILE_NAME}/)
endforeach()
set(PACKAGE_TARGETS)
if(DMGTOOLS_FOUND OR HDIUTIL)
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/bundle/client/")
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/bundle/server/")
configure_file(other/bundle/client/Info.plist.in bundle/client/Info.plist)
configure_file(other/bundle/server/Info.plist.in bundle/server/Info.plist)
if(HDIUTIL)
set(DMG_PARAMS --hdiutil ${HDIUTIL})
elseif(DMGTOOLS_FOUND)
set(DMG_PARAMS --dmgtools ${DMG} ${HFSPLUS} ${NEWFS_HFS})
endif()
set(DMG_TMPDIR pack_${CPACK_PACKAGE_FILE_NAME}_dmg)
set(DMG_MKDIRS
${TARGET_CLIENT}.app
${TARGET_CLIENT}.app/Contents
${TARGET_CLIENT}.app/Contents/Frameworks
${TARGET_CLIENT}.app/Contents/MacOS
${TARGET_CLIENT}.app/Contents/Resources
${TARGET_SERVER}.app
${TARGET_SERVER}.app/Contents
${TARGET_SERVER}.app/Contents/MacOS
${TARGET_SERVER}.app/Contents/Resources
${TARGET_SERVER}.app/Contents/Resources/data
${TARGET_SERVER}.app/Contents/Resources/data/mapres
)
set(DMG_MKDIR_COMMANDS)
foreach(dir ${DMG_MKDIRS})
list(APPEND DMG_MKDIR_COMMANDS COMMAND ${CMAKE_COMMAND} -E make_directory ${DMG_TMPDIR}/${dir})
endforeach()
add_custom_command(OUTPUT ${CPACK_PACKAGE_FILE_NAME}.dmg
COMMAND ${CMAKE_COMMAND} -E remove_directory ${DMG_TMPDIR}
${DMG_MKDIR_COMMANDS}
# CLIENT
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/data ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Resources/data
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 $<TARGET_FILE:${TARGET_CLIENT}> ${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/freetype/mac/lib64/libfreetype.6.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change @rpath/SDL2.framework/Versions/A/SDL2 @executable_path/../Frameworks/SDL2.framework/SDL2 ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/MacOS/${TARGET_CLIENT}
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/lib/libfreetype.6.dylib @executable_path/../Frameworks/libfreetype.6.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/MacOS/${TARGET_CLIENT}
# SERVER
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/data/maps ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/Resources/data/maps
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/other/icons/${TARGET_SERVER}.icns ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/Resources/
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 $<TARGET_FILE:${TARGET_SERVER}> $<TARGET_FILE:${TARGET_SERVER_LAUNCHER}> ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/MacOS/
# DMG
COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/dmg.py create ${DMG_PARAMS} ${CPACK_PACKAGE_FILE_NAME}.dmg ${CPACK_PACKAGE_FILE_NAME} ${DMG_TMPDIR}
DEPENDS
${TARGET_CLIENT}
${TARGET_SERVER_LAUNCHER}
${TARGET_SERVER}
${CMAKE_BINARY_DIR}/bundle/client/Info.plist
${CMAKE_BINARY_DIR}/bundle/server/Info.plist
data
other/bundle/client/PkgInfo
other/bundle/server/PkgInfo
other/icons/${TARGET_CLIENT}.icns
other/icons/${TARGET_SERVER}.icns
scripts/dmg.py
)
add_custom_target(package_dmg DEPENDS ${CPACK_PACKAGE_FILE_NAME}.dmg)
list(APPEND PACKAGE_TARGETS package_dmg)
endif()
foreach(ext zip tar.gz tar.xz)
set(TAR_MODE c)
set(TAR_EXTRA_ARGS)
string(REPLACE . _ EXT_SLUG ${ext})
set(TMPDIR pack_${CPACK_PACKAGE_FILE_NAME}_${EXT_SLUG}/${CPACK_PACKAGE_FILE_NAME})
set(COPY_FILE_COMMANDS)
set(COPY_DIR_COMMANDS)
set(COPY_TARGET_COMMANDS)
foreach(file ${CPACK_FILES})
list(APPEND COPY_FILE_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/${file} ${TMPDIR}/)
endforeach()
foreach(dir ${CPACK_DIRS})
list(APPEND COPY_DIR_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/${dir} ${TMPDIR}/${dir})
endforeach()
foreach(target ${CPACK_TARGETS})
list(APPEND COPY_TARGET_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${target}> ${TMPDIR}/)
endforeach()
if(ext STREQUAL zip)
set(TAR_EXTRA_ARGS --format=zip)
elseif(ext STREQUAL tar.gz)
@ -1234,27 +1338,27 @@ foreach(ext zip tar.gz tar.xz)
set(TAR_MODE cJ)
endif()
add_custom_command(OUTPUT ${CPACK_PACKAGE_FILE_NAME}.${ext}
COMMAND cmake -E make_directory ${CPACK_PACKAGE_FILE_NAME}
COMMAND ${CMAKE_COMMAND} -E remove_directory ${TMPDIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${TMPDIR}
${COPY_FILE_COMMANDS}
${COPY_DIR_COMMANDS}
${COPY_TARGET_COMMANDS}
COMMAND cmake -E tar ${TAR_MODE} ${CPACK_PACKAGE_FILE_NAME}.${ext} ${TAR_EXTRA_ARGS} -- ${CPACK_PACKAGE_FILE_NAME}/
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E chdir pack_${CPACK_PACKAGE_FILE_NAME}_${EXT_SLUG} ${CMAKE_COMMAND} -E tar ${TAR_MODE} ../${CPACK_PACKAGE_FILE_NAME}.${ext} ${TAR_EXTRA_ARGS} -- ${CPACK_PACKAGE_FILE_NAME}/
DEPENDS ${CPACK_TARGETS}
)
add_custom_target(package_${EXT_SLUG} DEPENDS ${CPACK_PACKAGE_FILE_NAME}.${ext})
list(APPEND PACKAGE_TARGETS package_${EXT_SLUG})
endforeach()
set(PACKAGE_DEFAULT tar_xz)
if(TARGET_OS STREQUAL "windows")
set(PACKAGE_DEFAULT zip)
elseif(TARGET_OS STREQUAL "mac")
set(PACKAGE_DEFAULT dmg)
endif()
add_custom_target(package_default DEPENDS package_${PACKAGE_DEFAULT})
add_custom_target(package_all DEPENDS
package_tar_gz
package_tar_xz
package_zip
)
add_custom_target(package_all DEPENDS ${PACKAGE_TARGETS})
# Unset these variables, they might do something in the future of CPack.
unset(CPACK_SOURCE_FILES)

View file

@ -94,6 +94,12 @@ Install [osxcross](https://github.com/tpoechtrager/osxcross), then add
`-DCMAKE_OSX_SYSROOT=/path/to/osxcross/target/SDK/MacOSX10.11.sdk/` to the
**initial** CMake command line.
Install `dmg` and `hfsplus` from
[libdmg-hfsplus](https://github.com/mozilla/libdmg-hfsplus) and `newfs_hfs`
from
[diskdev_cmds](http://pkgs.fedoraproject.org/repo/pkgs/hfsplus-tools/diskdev_cmds-540.1.linux3.tar.gz/0435afc389b919027b69616ad1b05709/diskdev_cmds-540.1.linux3.tar.gz)
to unlock the `package_dmg` target that outputs a macOS disk image.
Importing the official DDNet Database
-------------------------------------

View file

@ -2,6 +2,7 @@ set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_C_COMPILER o64-clang)
set(CMAKE_CXX_COMPILER o64-clang++)
set(CMAKE_INSTALL_NAME_TOOL x86_64-apple-darwin15-install_name_tool)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${TARGET_CLIENT}</string>
<key>CFBundleIconFile</key>
<string>${TARGET_CLIENT}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${PROJECT_VERSION}</string>
<key>CFBundleIdentifier</key>
<string>org.DDNetClient.app</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1 @@
APPL????

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${TARGET_SERVER_LAUNCHER}</string>
<key>CFBundleIconFile</key>
<string>${TARGET_SERVER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${PROJECT_VERSION}</string>
</dict>
</plist>

View file

@ -0,0 +1 @@
APPL????

106
scripts/dmg.py Normal file
View file

@ -0,0 +1,106 @@
from collections import namedtuple
import os
import shlex
import subprocess
import tempfile
ConfigDmgtools = namedtuple('Config', 'dmg hfsplus newfs_hfs verbose')
ConfigHdiutil = namedtuple('Config', 'hdiutil verbose')
def chunks(l, n):
"""
Yield successive n-sized chunks from l.
From https://stackoverflow.com/a/312464.
"""
for i in range(0, len(l), n):
yield l[i:i + n]
class Dmg:
def __init__(self, config):
self.config = config
def _check_call(self, process_args, *args, **kwargs):
if self.config.verbose >= 1:
print("EXECUTING {}".format(" ".join(shlex.quote(x) for x in process_args)))
if not (self.config.verbose >= 2 and "stdout" not in kwargs):
kwargs["stdout"] = open(os.devnull, 'wb')
subprocess.check_call(process_args, *args, **kwargs)
class Dmgtools(Dmg):
def _mkfs_hfs(self, *args):
self._check_call((self.config.newfs_hfs,) + args)
def _hfs(self, *args):
self._check_call((self.config.hfsplus,) + args)
def _dmg(self, *args):
self._check_call((self.config.dmg,) + args)
def _create_hfs(self, hfs, volume_name, size):
if self.config.verbose >= 1:
print("TRUNCATING {} to {} bytes".format(hfs, size))
with open(hfs, 'wb') as f:
f.truncate(size)
self._mkfs_hfs('-v', volume_name, hfs)
def _symlink(self, hfs, target, link_name):
self._hfs(hfs, 'symlink', link_name, target)
def _add(self, hfs, directory):
self._hfs(hfs, 'addall', directory)
def _finish(self, hfs, dmg):
self._dmg('build', hfs, dmg)
def create(self, dmg, volume_name, directory, symlinks):
input_size = sum(os.stat(os.path.join(path, f)).st_size for path, dirs, files in os.walk(directory) for f in files)
output_size = max(input_size * 2, 1024**2)
hfs = tempfile.mktemp(prefix=dmg + '.', suffix='.hfs')
self._create_hfs(hfs, volume_name, output_size)
self._add(hfs, directory)
for target, link_name in symlinks:
self._symlink(hfs, target, link_name)
self._finish(hfs, dmg)
if self.config.verbose >= 1:
print("REMOVING {}".format(hfs))
os.remove(hfs)
class Hdiutil(Dmg):
def _hdiutil(self, *args):
self._check_call((self.config.hdiutil,) + args)
def create(self, dmg, volume_name, directory, symlinks):
if symlinks:
raise NotImplementedError("symlinks are not yet implemented")
self._hdiutil('create', '-volname', volume_name, '-srcdir', directory, dmg)
def main():
import argparse
p = argparse.ArgumentParser(description="Manipulate dmg archives")
subcommands = p.add_subparsers(help="Subcommand", dest='command', metavar="COMMAND")
subcommands.required = True
create = subcommands.add_parser("create", help="Create a dmg archive from files or directories")
create.add_argument('-v', '--verbose', action='count', help="Verbose output")
createx = create.add_mutually_exclusive_group(required=True)
createx.add_argument('--dmgtools', nargs=3, help="Paths to the dmg and hfsplus executable (https://github.com/mozilla/libdmg-hfsplus) and the newfs_hfs executable (http://pkgs.fedoraproject.org/repo/pkgs/hfsplus-tools/diskdev_cmds-540.1.linux3.tar.gz/0435afc389b919027b69616ad1b05709/diskdev_cmds-540.1.linux3.tar.gz)")
createx.add_argument('--hdiutil', help="Path to the hdiutil (only exists for macOS at time of writing)")
create.add_argument('output', metavar="OUTPUT", help="Filename of the output dmg archive")
create.add_argument('volume_name', metavar="VOLUME_NAME", help="Name of the dmg archive")
create.add_argument('directory', metavar="DIR", help="Directory to create the archive from")
create.add_argument('--symlink', metavar="SYMLINK", nargs=2, action="append", help="Symlink the first argument under the second name")
args = p.parse_args()
verbose = args.verbose or 0
symlinks = args.symlink or []
if args.dmgtools:
dmg, hfsplus, newfs_hfs = args.dmgtools
dmg = Dmgtools(ConfigDmgtools(dmg=dmg, hfsplus=hfsplus, newfs_hfs=newfs_hfs, verbose=verbose))
elif args.hdiutil:
dmg = Hdiutil(ConfigHdiutil(hdiutil=args.hdiutil, verbose=verbose))
else:
raise RuntimeError("unreachable")
dmg.create(volume_name=args.volume_name, directory=args.directory, dmg=args.output, symlinks=symlinks)
if __name__ == '__main__':
main()

View file

@ -1,112 +0,0 @@
#import <Cocoa/Cocoa.h>
@interface ServerView : NSTextView
{
NSTask *task;
NSFileHandle *file;
}
- (void)listenTo: (NSTask*)t;
@end
@implementation ServerView
- (void)listenTo: (NSTask*)t;
{
NSPipe *pipe;
task = t;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
file = [pipe fileHandleForReading];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(outputNotification:) name: NSFileHandleReadCompletionNotification object: file];
[file readInBackgroundAndNotify];
}
- (void) outputNotification: (NSNotification *) notification
{
NSData *data = [[[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] retain];
NSString *string = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
NSAttributedString *attrstr = [[NSAttributedString alloc] initWithString: string];
[[self textStorage] appendAttributedString: attrstr];
int length = [[self textStorage] length];
NSRange range = NSMakeRange(length, 0);
[self scrollRangeToVisible: range];
[attrstr release];
[string release];
[file readInBackgroundAndNotify];
}
-(void)windowWillClose:(NSNotification *)notification
{
[task terminate];
[NSApp terminate:self];
}
@end
void runServer()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSApp = [NSApplication sharedApplication];
NSBundle* mainBundle = [NSBundle mainBundle];
NSTask *task;
task = [[NSTask alloc] init];
[task setCurrentDirectoryPath: [mainBundle resourcePath]];
// get a server config
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseFiles:YES];
if([openDlg runModalForDirectory:nil file:nil] != NSOKButton)
return;
NSArray* filenames = [openDlg filenames];
if([filenames count] != 1)
return;
NSString* filename = [filenames objectAtIndex: 0];
NSArray* arguments = [NSArray arrayWithObjects: @"-f", filename, nil];
// run server
NSWindow *window;
ServerView *view;
NSRect graphicsRect;
graphicsRect = NSMakeRect(100.0, 1000.0, 600.0, 400.0);
window = [[NSWindow alloc]
initWithContentRect: graphicsRect
styleMask: NSTitledWindowMask
| NSClosableWindowMask
| NSMiniaturizableWindowMask
backing: NSBackingStoreBuffered
defer: NO];
[window setTitle: @"DDNet Server"];
view = [[[ServerView alloc] initWithFrame: graphicsRect] autorelease];
[view setEditable: NO];
[view setRulerVisible: YES];
[window setContentView: view];
[window setDelegate: view];
[window makeKeyAndOrderFront: nil];
[view listenTo: task];
[task setLaunchPath: [mainBundle pathForAuxiliaryExecutable: @"DDNet-Server"]];
[task setArguments: arguments];
[task launch];
[NSApp run];
[task terminate];
[NSApp release];
[pool release];
}
int main (int argc, char **argv)
{
runServer();
return 0;
}

1
src/osxlaunch/server.m Symbolic link
View file

@ -0,0 +1 @@
server.mm

108
src/osxlaunch/server.mm Normal file
View file

@ -0,0 +1,108 @@
#import <Cocoa/Cocoa.h>
@interface ServerView : NSTextView
{
NSTask *task;
NSFileHandle *file;
}
- (void)listenTo: (NSTask *)t;
@end
@implementation ServerView
- (void)listenTo: (NSTask *)t
{
NSPipe *pipe;
task = t;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
file = [pipe fileHandleForReading];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(outputNotification:) name: NSFileHandleReadCompletionNotification object: file];
[file readInBackgroundAndNotify];
}
- (void) outputNotification: (NSNotification *) notification
{
NSData *data = [[[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] retain];
NSString *string = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
NSAttributedString *attrstr = [[NSAttributedString alloc] initWithString: string];
[[self textStorage] appendAttributedString: attrstr];
int length = [[self textStorage] length];
NSRange range = NSMakeRange(length, 0);
[self scrollRangeToVisible: range];
[attrstr release];
[string release];
[file readInBackgroundAndNotify];
}
-(void)windowWillClose:(NSNotification *)notification
{
[task terminate];
[NSApp terminate:self];
}
@end
void runServer()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSApp = [NSApplication sharedApplication];
NSBundle *mainBundle = [NSBundle mainBundle];
NSTask *task;
task = [[NSTask alloc] init];
[task setCurrentDirectoryPath: [mainBundle resourcePath]];
// get a server config
NSOpenPanel *openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseFiles:YES];
if([openDlg runModal] != NSOKButton)
return;
NSString *filename = [[openDlg URL] path];
NSArray *arguments = [NSArray arrayWithObjects: @"-f", filename, nil];
// run server
NSWindow *window;
ServerView *view;
NSRect graphicsRect;
graphicsRect = NSMakeRect(100.0, 1000.0, 600.0, 400.0);
window = [[NSWindow alloc]
initWithContentRect: graphicsRect
styleMask: NSTitledWindowMask
| NSClosableWindowMask
| NSMiniaturizableWindowMask
backing: NSBackingStoreBuffered
defer: NO];
[window setTitle: @"DDNet Server"];
view = [[[ServerView alloc] initWithFrame: graphicsRect] autorelease];
[view setEditable: NO];
[view setRulerVisible: YES];
[window setContentView: view];
[window setDelegate: (id<NSWindowDelegate>)view];
[window makeKeyAndOrderFront: nil];
[view listenTo: task];
[task setLaunchPath: [mainBundle pathForAuxiliaryExecutable: @"DDNet-Server"]];
[task setArguments: arguments];
[task launch];
[NSApp run];
[task terminate];
[NSApp release];
[pool release];
}
int main(int argc, char **argv)
{
runServer();
return 0;
}