1
0
forked from 0ad/0ad

Rework bundle creation scripts.

This reworks the OSX bundle script, to run it easily on CI and to
further also build the unix tarballs and the windows installer.

Clean up the MacOS bundle detection, by not forcing a compilation-time
switch.
Clean up shared library compilation: changing the installation name
isn't necessary for 0 A.D.

Differential Revision: https://code.wildfiregames.com/D3161
This was SVN commit r24343.
This commit is contained in:
wraitii 2020-12-07 13:44:42 +00:00
parent a2f3b25923
commit d95550248b
11 changed files with 352 additions and 424 deletions

View File

@ -23,28 +23,46 @@ pipeline {
buildDiscarder(logRotator(artifactNumToKeepStr: '1')) buildDiscarder(logRotator(artifactNumToKeepStr: '1'))
} }
parameters {
booleanParam(name: 'release', defaultValue: false)
}
stages { stages {
stage("Checkout") { stage("Checkout") {
steps { steps {
svn "https://svn.wildfiregames.com/public/ps/trunk" svn "https://svn.wildfiregames.com/public/ps/trunk"
sh "svn cleanup" sh "svn cleanup"
sh "svn st --no-ignore | cut -c 9- | xargs rm -rf" sh "svn revert . -R"
sh "svn st --no-ignore | cut -c 9- | xargs rm -rfv"
} }
} }
stage("Bundle") { stage("Compile Mac Executable") {
steps { steps {
sh "cd source/tools/dist && ./build-osx-bundle.sh" sh "source/tools/dist/build-osx-executable.sh"
}
}
stage("Create archive data") {
steps {
sh "source/tools/dist/build-archives.sh"
}
}
stage("Create Mac Bundle") {
steps {
sh "python3 source/tools/dist/build-osx-bundle.py '0.0.24dev'"
}
}
stage("Create Windows installer & *nix files") {
steps {
// The files created by the mac compilation need to be deleted
sh "svn st binaries/ --no-ignore | cut -c 9- | xargs rm -rf"
sh "svn st build/ --no-ignore | cut -c 9- | xargs rm -rf"
sh "svn st libraries/ --no-ignore | cut -c 9- | xargs rm -rf"
sh "svn revert build/ -R"
sh "BUNDLE_VERSION='0.0.24dev' source/tools/dist/build-unix-win32.sh"
} }
} }
} }
post { post {
success { success {
archiveArtifacts 'build/workspaces/*.dmg' archiveArtifacts '*.dmg,*.exe,*.tar.gz,*.tar.xz'
} }
} }
} }

View File

@ -19,7 +19,6 @@ newoption { trigger = "without-tests", description = "Disable generation of test
newoption { trigger = "prefer-local-libs", description = "Prefer locally built libs. Any local libraries used must also be listed within a file within /etc/ld.so.conf.d so the dynamic linker can find them at runtime." } newoption { trigger = "prefer-local-libs", description = "Prefer locally built libs. Any local libraries used must also be listed within a file within /etc/ld.so.conf.d so the dynamic linker can find them at runtime." }
-- OS X specific options -- OS X specific options
newoption { trigger = "macosx-bundle", description = "Enable OSX bundle, the argument is the bundle identifier string (e.g. com.wildfiregames.0ad)" }
newoption { trigger = "macosx-version-min", description = "Set minimum required version of the OS X API, the build will possibly fail if an older SDK is used, while newer API functions will be weakly linked (i.e. resolved at runtime)" } newoption { trigger = "macosx-version-min", description = "Set minimum required version of the OS X API, the build will possibly fail if an older SDK is used, while newer API functions will be weakly linked (i.e. resolved at runtime)" }
newoption { trigger = "sysroot", description = "Set compiler system root path, used for building against a non-system SDK. For example /usr/local becomes SYSROOT/user/local" } newoption { trigger = "sysroot", description = "Set compiler system root path, used for building against a non-system SDK. For example /usr/local becomes SYSROOT/user/local" }
@ -332,11 +331,6 @@ function project_set_build_flags()
linkoptions { "-mmacosx-version-min=" .. _OPTIONS["macosx-version-min"] } linkoptions { "-mmacosx-version-min=" .. _OPTIONS["macosx-version-min"] }
end end
-- Check if we're building a bundle
if _OPTIONS["macosx-bundle"] then
defines { "BUNDLE_IDENTIFIER=" .. _OPTIONS["macosx-bundle"] }
end
-- Only libc++ is supported on MacOS -- Only libc++ is supported on MacOS
if os.istarget("macosx") then if os.istarget("macosx") then
buildoptions { "-stdlib=libc++" } buildoptions { "-stdlib=libc++" }
@ -1105,26 +1099,6 @@ function setup_atlas_project(project_name, target_type, rel_source_dirs, rel_inc
-- warnings triggered by wxWidgets -- warnings triggered by wxWidgets
buildoptions { "-Wno-unused-local-typedefs" } buildoptions { "-Wno-unused-local-typedefs" }
elseif os.istarget("macosx") then
-- install_name settings aren't really supported yet by premake, but there are plans for the future.
-- we currently use this hack to work around some bugs with wrong install_names.
if target_type == "SharedLib" then
if _OPTIONS["macosx-bundle"] then
-- If we're building a bundle, it will be in ../Frameworks
filter "Debug"
linkoptions { "-install_name @executable_path/../Frameworks/lib"..project_name.."_dbg.dylib" }
filter "Release"
linkoptions { "-install_name @executable_path/../Frameworks/lib"..project_name..".dylib" }
filter { }
else
filter "Debug"
linkoptions { "-install_name @executable_path/lib"..project_name.."_dbg.dylib" }
filter "Release"
linkoptions { "-install_name @executable_path/lib"..project_name..".dylib" }
filter { }
end
end
end end
end end
@ -1292,17 +1266,6 @@ function setup_collada_project(project_name, target_type, rel_source_dirs, rel_i
elseif os.istarget("macosx") then elseif os.istarget("macosx") then
-- define MACOS-something? -- define MACOS-something?
-- install_name settings aren't really supported yet by premake, but there are plans for the future.
-- we currently use this hack to work around some bugs with wrong install_names.
if target_type == "SharedLib" then
if _OPTIONS["macosx-bundle"] then
-- If we're building a bundle, it will be in ../Frameworks
linkoptions { "-install_name @executable_path/../Frameworks/lib"..project_name..".dylib" }
else
linkoptions { "-install_name @executable_path/lib"..project_name..".dylib" }
end
end
buildoptions { "-fno-strict-aliasing" } buildoptions { "-fno-strict-aliasing" }
-- On OSX, fcollada uses a few utility functions from coreservices -- On OSX, fcollada uses a few utility functions from coreservices
links { "CoreServices.framework" } links { "CoreServices.framework" }

View File

@ -26,107 +26,54 @@
#import "osx_bundle.h" #import "osx_bundle.h"
#define STRINGIZE2(id) # id
#define STRINGIZE(id) STRINGIZE2(id)
// Pass the bundle identifier string as a build option
#ifdef BUNDLE_IDENTIFIER
static const char* BUNDLE_ID_STR = STRINGIZE(BUNDLE_IDENTIFIER);
#else
static const char* BUNDLE_ID_STR = "";
#endif
bool osx_IsAppBundleValid() bool osx_IsAppBundleValid()
{ {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
// Check for the existence of bundle with correct identifier property NSBundle *bundle = [NSBundle mainBundle];
// (can't just use mainBundle because that can return a bundle reference // mainBundle can create an NSBundle even with a loose executable.
// even for a loose binary!) // Assume that if the identifier is defined, we are actually inside a bundle.
NSBundle *bundle = [NSBundle bundleWithIdentifier: [NSString stringWithUTF8String: BUNDLE_ID_STR]]; NSString *identifier = [bundle bundleIdentifier];
[pool drain]; [pool drain];
return bundle != nil; return bundle != nil && identifier != nil;
}
namespace {
std::string GetBundlePath(SEL selector)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
std::string path;
NSBundle *bundle = [NSBundle mainBundle];
if (bundle != nil)
{
NSString *pathStr;
// Retrieve NSURL and convert to POSIX path, then get C-string
// encoded as UTF-8, and use it to construct std::string
// NSURL:path "If the receiver does not conform to RFC 1808, returns nil."
pathStr = [[bundle performSelector:selector] path];
if (pathStr != nil)
path = std::string([pathStr UTF8String]);
}
[pool drain];
return path;
}
} }
std::string osx_GetBundlePath() std::string osx_GetBundlePath()
{ {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; return GetBundlePath(@selector(bundleURL));
std::string path;
NSBundle *bundle = [NSBundle bundleWithIdentifier: [NSString stringWithUTF8String: BUNDLE_ID_STR]];
if (bundle != nil)
{
NSString *pathStr;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// Retrieve NSURL and convert to POSIX path, then get C-string
// encoded as UTF-8, and use it to construct std::string
// NSURL:path "If the receiver does not conform to RFC 1808, returns nil."
if ([bundle respondsToSelector: @selector(bundleURL)])
pathStr = [[bundle bundleURL] path];
else
#endif
pathStr = [bundle bundlePath];
if (pathStr != nil)
path = std::string([pathStr UTF8String]);
}
[pool drain];
return path;
} }
std::string osx_GetBundleResourcesPath() std::string osx_GetBundleResourcesPath()
{ {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; return GetBundlePath(@selector(resourceURL));
std::string path;
NSBundle *bundle = [NSBundle bundleWithIdentifier: [NSString stringWithUTF8String: BUNDLE_ID_STR]];
if (bundle != nil)
{
NSString *pathStr;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// Retrieve NSURL and convert to POSIX path, then get C-string
// encoded as UTF-8, and use it to construct std::string
// NSURL:path "If the receiver does not conform to RFC 1808, returns nil."
if ([bundle respondsToSelector: @selector(resourceURL)])
pathStr = [[bundle resourceURL] path];
else
#endif
pathStr = [bundle resourcePath];
if (pathStr != nil)
path = std::string([pathStr UTF8String]);
}
[pool drain];
return path;
} }
std::string osx_GetBundleFrameworksPath() std::string osx_GetBundleFrameworksPath()
{ {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; return GetBundlePath(@selector(privateFrameworksURL));
std::string path;
NSBundle *bundle = [NSBundle bundleWithIdentifier: [NSString stringWithUTF8String: BUNDLE_ID_STR]];
if (bundle != nil)
{
NSString *pathStr;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// Retrieve NSURL and convert to POSIX path, then get C-string
// encoded as UTF-8, and use it to construct std::string
// NSURL:path "If the receiver does not conform to RFC 1808, returns nil."
if ([bundle respondsToSelector: @selector(privateFrameworksURL)])
pathStr = [[bundle privateFrameworksURL] path];
else
#endif
pathStr = [bundle privateFrameworksPath];
if (pathStr != nil)
path = std::string([pathStr UTF8String]);
}
[pool drain];
return path;
} }

View File

@ -2,11 +2,11 @@
; Do an 'svn export' into a directory called e.g. "export-win32" ; Do an 'svn export' into a directory called e.g. "export-win32"
; makensis -nocd -dcheckoutpath=export-win32 -drevision=1234 -dprefix=0ad-0.1.2-alpha export-win32/source/tools/dist/0ad.nsi ; makensis -nocd -dcheckoutpath=export-win32 -drevision=1234 -dprefix=0ad-0.1.2-alpha export-win32/source/tools/dist/0ad.nsi
SetCompressor /SOLID lzma SetCompressor /SOLID ZLIB
!include "MUI2.nsh" !include "MUI2.nsh"
!include "LogicLib.nsh" !include "LogicLib.nsh"
!include "FileAssociation.nsh" !include "source/tools/dist/FileAssociation.nsh"
;Control whether to include source code (and component selection screen) ;Control whether to include source code (and component selection screen)
!define INCLUDE_SOURCE 0 !define INCLUDE_SOURCE 0
@ -116,17 +116,22 @@ Section "!Game and data files" GameSection
File "${CHECKOUTPATH}\*.txt" File "${CHECKOUTPATH}\*.txt"
File "${CHECKOUTPATH}\source\tools\openlogsfolder\*.*" File "${CHECKOUTPATH}\source\tools\openlogsfolder\*.*"
!if INCLUDE_SOURCE !if INCLUDE_SOURCE
File /r /x "public" /x "mod" /x "dev.cfg" "${CHECKOUTPATH}\binaries" File /r /x "*.a" /x "*.dylib" /x "public" /x "mod" /x "dev.cfg" "${CHECKOUTPATH}\binaries"
!else !else
;Exclude debug DLLs and related files ;Exclude debug DLLs and related files
File /r /x "public" /x "mod" /x "dev.cfg" /x "*_d.dll" /x "enetd.dll" /x "FColladaD.dll" /x "gloox-1.0d.dll" /x "glooxwrapper_dbg.*" /x "libcurld.dll" /x "libpng16d.dll" /x "libsodiumd.dll" /x "miniupnpcd.dll" /x "mozjs*-ps-debug*" /x "mozjs*vc140.*" /x "msvc*d.dll" /x "zlib1d.dll" "${CHECKOUTPATH}\binaries" File /r /x "public" /x "mod" /x "dev.cfg" /x "*_d.dll" /x "enetd.dll" /x "FColladaD.dll" /x "gloox-1.0d.dll" /x "glooxwrapper_dbg.*" /x "libcurld.dll" /x "libpng16d.dll" /x "*.a" /x "*.dylib" /x "pyrogenesis" /x "*.dsym*" /x "test" /x "libsodiumd.dll" /x "miniupnpcd.dll" /x "mozjs*-ps-debug*" /x "mozjs*vc140.*" /x "msvc*d.dll" /x "zlib1d.dll" "${CHECKOUTPATH}\binaries\"
!endif !endif
SetOutPath "$INSTDIR\binaries\data\mods\public" !ifdef ARCHIVE_PATH
File "${CHECKOUTPATH}\binaries\data\mods\public\public.zip" SetOutPath "$INSTDIR\binaries\data\mods\"
File "${CHECKOUTPATH}\binaries\data\mods\public\mod.json" File /r "${ARCHIVE_PATH}"
SetOutPath "$INSTDIR\binaries\data\mods\mod" !else
File "${CHECKOUTPATH}\binaries\data\mods\mod\mod.zip" SetOutPath "$INSTDIR\binaries\data\mods\public"
File "${CHECKOUTPATH}\binaries\data\mods\public\public.zip"
File "${CHECKOUTPATH}\binaries\data\mods\public\mod.json"
SetOutPath "$INSTDIR\binaries\data\mods\mod"
File "${CHECKOUTPATH}\binaries\data\mods\mod\mod.zip"
!endif
;Store installation folder ;Store installation folder
WriteRegStr SHCTX "Software\0 A.D." "" $INSTDIR WriteRegStr SHCTX "Software\0 A.D." "" $INSTDIR

47
source/tools/dist/build-archives.sh vendored Normal file
View File

@ -0,0 +1,47 @@
#!/bin/sh
set -e
die()
{
echo ERROR: $*
exit 1
}
# Build the mod .zip using the pyrogenesis executable.
# Assumes it is being run from trunk/
echo "Building archives"
echo "Filtering languages"
# Included languages
# Keep in sync with source/tools/i18n/creditTranslators.py and with the installer languages in 0ad.nsi
LANGS=("ast" "bg" "ca" "cs" "de" "el" "en_GB" "es" "eu" "fr" "gd" "gl" "hu" "id" "it" "ms" "nb" "nl" "pl" "pt_BR" "pt_PT" "ru" "sk" "sv" "tr" "uk")
REGEX=$(printf "\|%s" "${LANGS[@]}")
REGEX=".*/\("${REGEX:2}"\)\.[-A-Za-z0-9_.]\+\.po"
find binaries/ -name "*.po" | grep -v "$REGEX" | xargs rm -v || die "Error filtering languages."
SVN_REV=$(svnversion -n ../..)
echo "${SVN_REV}-release" > build/svn_revision/svn_revision.txt
# Build archive(s) - don't archive the _test.* mods
pushd binaries/data/mods > /dev/null
archives=""
for modname in [a-zA-Z0-9]*
do
archives="${archives} ${modname}"
done
popd > /dev/null
for modname in $archives
do
echo "\nBuilding archive for '${modname}'\n"
ARCHIVEBUILD_INPUT="binaries/data/mods/${modname}"
ARCHIVEBUILD_OUTPUT="archives/${modname}"
mkdir -p "${ARCHIVEBUILD_OUTPUT}"
(./binaries/system/pyrogenesis -archivebuild="${ARCHIVEBUILD_INPUT}" -archivebuild-output="${ARCHIVEBUILD_OUTPUT}/${modname}.zip") || die "Archive build for '${modname}' failed!"
cp "${ARCHIVEBUILD_INPUT}/mod.json" "${ARCHIVEBUILD_OUTPUT}" || true
done

115
source/tools/dist/build-osx-bundle.py vendored Normal file
View File

@ -0,0 +1,115 @@
#!/usr/bin/python3
"""
Builds the OSX bundle from existing elements.
App bundles are intended to be self-contained and portable.
An SDK is required, usually included with Xcode. The SDK ensures
that only those system libraries are used which are available on
the chosen target and compatible systems.
This is Python because plistlib is extremely strict about what it accepts
and it's used by dmgbuild, and saving the Plist doesn't really work otherwise.
"""
import argparse
import datetime
import glob
import os
import plistlib
import shutil
import dmgbuild
parser = argparse.ArgumentParser()
parser.add_argument('bundle_version', help='Bundle version')
parser.add_argument('--min_osx', help='Minimum supported OSX version',
default='10.12')
parser.add_argument('--bundle_identifier', help='Bundle identifier',
default='com.wildfiregames.0ad')
args = parser.parse_args()
BUNDLE_DMG_NAME = "0 A.D."
BUNDLE_OUTPUT = "0 A.D..app"
BUNDLE_CONTENTS = BUNDLE_OUTPUT + "/Contents"
BUNDLE_BIN = BUNDLE_CONTENTS + "/MacOS"
BUNDLE_RESOURCES = BUNDLE_CONTENTS + "/Resources"
BUNDLE_FRAMEWORKS = BUNDLE_CONTENTS + "/Frameworks"
BUNDLE_PLUGINS = BUNDLE_CONTENTS + "/PlugIns"
BUNDLE_SHAREDSUPPORT = BUNDLE_CONTENTS + "/SharedSupport"
BUNDLE_IDENTIFIER = args.bundle_identifier
BUNDLE_VERSION = args.bundle_version
BUNDLE_MIN_OSX_VERSION = args.min_osx
print("Creating bundle directories")
shutil.rmtree(BUNDLE_OUTPUT, ignore_errors=True)
os.makedirs(BUNDLE_BIN)
os.makedirs(BUNDLE_FRAMEWORKS)
os.makedirs(BUNDLE_PLUGINS)
os.makedirs(BUNDLE_RESOURCES)
os.makedirs(BUNDLE_SHAREDSUPPORT)
print("Copying binaries")
# Only pyrogenesis for now, until we find a way to load
# multiple binaries from one app bundle
# TODO: Would be nicer if we could set this path in premake
shutil.copy("binaries/system/pyrogenesis", BUNDLE_BIN)
print("Copying libs")
shutil.copy("binaries/system/libAtlasUI.dylib", BUNDLE_FRAMEWORKS)
shutil.copy("binaries/system/libCollada.dylib", BUNDLE_FRAMEWORKS)
print("Copying archived game data")
for mod in glob.glob("archives/*/"):
print(f"Copying {mod}")
shutil.copytree(mod, BUNDLE_RESOURCES + "/data/mods/" + mod.replace("archives/", ""))
print("Copying non-archived game data")
shutil.copytree("binaries/data/config", BUNDLE_RESOURCES + "/data/config")
shutil.copytree("binaries/data/l10n", BUNDLE_RESOURCES + "/data/l10n")
shutil.copytree("binaries/data/tools", BUNDLE_RESOURCES + "/data/tools")
# Remove the dev.cfg file or 0 A.D. will assume it's running a dev copy.
os.unlink(BUNDLE_RESOURCES + "/data/config/dev.cfg")
shutil.copy("build/resources/0ad.icns", BUNDLE_RESOURCES)
shutil.copy("build/resources/InfoPlist.strings", BUNDLE_RESOURCES)
print("Copying readmes")
# TODO: Also want copies in the DMG - decide on layout
for file in glob.glob("*.txt"):
shutil.copy(file, BUNDLE_RESOURCES)
shutil.copy("libraries/LICENSE.txt", BUNDLE_RESOURCES + "/LIB_LICENSE.txt")
print("Creating Info.plist")
with open(BUNDLE_CONTENTS + "/Info.plist", 'wb') as f:
plistlib.dump({
'CFBundleName': '0 A.D.',
'CFBundleIdentifier': BUNDLE_IDENTIFIER,
'CFBundleVersion': BUNDLE_VERSION,
'CFBundlePackageType': 'APPL',
'CFBundleSignature': 'none',
'CFBundleExecutable': 'pyrogenesis',
'CFBundleShortVersionString': BUNDLE_VERSION,
'CFBundleDevelopmentRegion': 'English',
'CFBundleInfoDictionaryVersion': '6.0',
'CFBundleIconFile': '0ad',
'LSHasLocalizedDisplayName': True,
'LSMinimumSystemVersion': BUNDLE_MIN_OSX_VERSION,
'NSHumanReadableCopyright': f'Copyright © {datetime.datetime.now().year} Wildfire Games',
}, f)
print("Creating .dmg")
# Package the app into a dmg
dmgbuild.build_dmg(
filename=BUNDLE_DMG_NAME + ".dmg",
volume_name=BUNDLE_DMG_NAME,
settings_file="source/tools/dist/dmgbuild-settings.py",
defines={
"app": BUNDLE_OUTPUT,
"background": "build/resources/dmgbackground.png",
"icon": "build/resources/0ad.icns"
})
print(f"Bundle complete! Located in {BUNDLE_OUTPUT}, compressed as {BUNDLE_DMG_NAME}.dmg.")

View File

@ -1,214 +0,0 @@
#!/bin/sh
#
# This script will build an OS X app bundle for 0 A.D.
#
# App bundles are intended to be self-contained and portable.
# An SDK is required, usually included with Xcode. The SDK ensures
# that only those system libraries are used which are available on
# the chosen target and compatible systems.
#
# TODO: is there anything to do for ARM support?
export ARCH=${ARCH:="x86_64"}
# Set mimimum required OS X version, SDK location and tools
# Old SDKs can be found at https://github.com/phracker/MacOSX-SDKs
export MIN_OSX_VERSION=${MIN_OSX_VERSION:="10.12"}
export SYSROOT=${SYSROOT:="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${MIN_OSX_VERSION}.sdk"}
export CC=${CC:="clang"} CXX=${CXX:="clang++"}
# 0 A.D. release version
BUNDLE_VERSION=${BUNDLE_VERSION:="0.0.24dev"}
BUNDLE_FILENAME="0ad-${BUNDLE_VERSION}-alpha-osx64.dmg"
# Unique identifier string for this bundle (reverse-DNS style)
BUNDLE_IDENTIFIER=${BUNDLE_IDENTIFIER:="com.wildfiregames.0ad"}
# Minimum version of OS X on which the bundle will run
BUNDLE_MIN_OSX_VERSION="${MIN_OSX_VERSION}.0"
die()
{
echo ERROR: $*
exit 1
}
# Check that we're actually on OS X
if [ "`uname -s`" != "Darwin" ]; then
die "This script is intended for OS X only"
fi
# Check SDK exists
if [ ! -d "$SYSROOT" ]; then
die "$SYSROOT does not exist! You probably need to install Xcode"
fi
# We assume this script resides in source/tools/dist/
DMGBUILD_CONFIG="$(pwd)/dmgbuild-settings.py"
cd "$(dirname $0)/../../../build/workspaces/"
JOBS=${JOBS:="-j5"}
build_release=false
# Parse command-line options:
for i in "$@"
do
case $i in
-j* ) JOBS=$i ;;
--release ) build_release=true ;;
esac
done
# For release, export an SVN copy
if [ "$build_release" = "true" ]; then
echo "\nExporting SVN and preparing release\n"
SVN_REV=`svnversion -n ../..`
rm -rf "0ad-export"
svn export ../.. "0ad-export" || die "Error exporting SVN working directory"
cd "0ad-export"
rm -f binaries/data/config/dev.cfg
# Only include translations for a subset of languages
. source/tools/dist/remove-incomplete-translations.sh $build_path/binaries/data || die "Error excluding translations"
echo L\"${SVN_REV}-release\" > build/svn_revision/svn_revision.txt
cd build/workspaces
fi
BUNDLE_APP="0ad.app"
BUNDLE_DMG_NAME="0 A.D."
BUNDLE_OUTPUT=${BUNDLE_OUTPUT:="$(pwd)/${BUNDLE_APP}"}
BUNDLE_CONTENTS=$BUNDLE_OUTPUT/Contents
BUNDLE_BIN=$BUNDLE_CONTENTS/MacOS
BUNDLE_RESOURCES=$BUNDLE_CONTENTS/Resources
BUNDLE_FRAMEWORKS=$BUNDLE_CONTENTS/Frameworks
BUNDLE_PLUGINS=$BUNDLE_CONTENTS/PlugIns
BUNDLE_SHAREDSUPPORT=$BUNDLE_CONTENTS/SharedSupport
# TODO: Do we really want to regenerate everything? (consider if one task fails)
./clean-workspaces.sh
# Build libraries against SDK
echo "\nBuilding libraries\n"
pushd ../../libraries/osx > /dev/null
./build-osx-libs.sh $JOBS --force-rebuild || die "Libraries build script failed"
popd > /dev/null
# Update workspaces
echo "\nGenerating workspaces\n"
# Pass OS X options through to Premake
(SYSROOT="$SYSROOT" MIN_OSX_VERSION="$MIN_OSX_VERSION" ./update-workspaces.sh --macosx-bundle="$BUNDLE_IDENTIFIER" --sysroot="$SYSROOT" --macosx-version-min="$MIN_OSX_VERSION") || die "update-workspaces.sh failed!"
pushd gcc > /dev/null
echo "\nBuilding game\n"
(make clean && CC="$CC -arch $ARCH" CXX="$CXX -arch $ARCH" make ${JOBS}) || die "Game build failed!"
popd > /dev/null
# Run test to confirm all is OK
pushd ../../binaries/system > /dev/null
echo "\nRunning tests\n"
./test || die "Post-build testing failed!"
popd > /dev/null
# Create bundle structure
echo "\nCreating bundle directories\n"
rm -rf "${BUNDLE_OUTPUT}"
mkdir -p "${BUNDLE_BIN}"
mkdir -p "${BUNDLE_FRAMEWORKS}"
mkdir -p "${BUNDLE_PLUGINS}"
mkdir -p "${BUNDLE_RESOURCES}"
mkdir -p "${BUNDLE_SHAREDSUPPORT}"
# Build archive(s) - don't archive the _test.* mods
pushd ../../binaries/data/mods > /dev/null
archives=""
for modname in [a-zA-Z0-9]*
do
archives="${archives} ${modname}"
done
popd > /dev/null
pushd ../../binaries/system > /dev/null
for modname in $archives
do
echo "\nBuilding archive for '${modname}'\n"
ARCHIVEBUILD_INPUT="$(pwd)/../data/mods/${modname}"
ARCHIVEBUILD_OUTPUT="${BUNDLE_RESOURCES}/data/mods/${modname}"
# For some reason the output directory has to exist?
mkdir -p "${ARCHIVEBUILD_OUTPUT}"
(./pyrogenesis -archivebuild="${ARCHIVEBUILD_INPUT}" -archivebuild-output="${ARCHIVEBUILD_OUTPUT}/${modname}.zip") || die "Archive build for '${modname}' failed!"
done
# Copy binaries
echo "\nCopying binaries\n"
# Only pyrogenesis for now, until we find a way to load
# multiple binaries from one app bundle
# TODO: Would be nicer if we could set this path in premake
cp pyrogenesis "${BUNDLE_BIN}"
# Copy libs
echo "\nCopying libs\n"
# TODO: Would be nicer if we could set this path in premake
cp -v libAtlasUI.dylib "${BUNDLE_FRAMEWORKS}"
cp -v libCollada.dylib "${BUNDLE_FRAMEWORKS}"
popd > /dev/null
# Copy data
echo "\nCopying non-archived game data\n"
pushd ../../binaries/data > /dev/null
if [ "$build_release" = "false" ]; then
mv config/dev.cfg config/dev.bak
fi
cp -R -v config "${BUNDLE_RESOURCES}/data/"
cp -R -v l10n "${BUNDLE_RESOURCES}/data/"
cp -R -v tools "${BUNDLE_RESOURCES}/data/"
if [ "$build_release" = "false" ]; then
mv config/dev.bak config/dev.cfg
fi
popd > /dev/null
cp -v ../resources/0ad.icns "${BUNDLE_RESOURCES}"
cp -v ../resources/InfoPlist.strings "${BUNDLE_RESOURCES}"
# Copy license/readmes
# TODO: Also want copies in the DMG - decide on layout
echo "\nCopying readmes\n"
cp -v ../../*.txt "${BUNDLE_RESOURCES}"
cp -v ../../libraries/LICENSE.txt "${BUNDLE_RESOURCES}/LIB_LICENSE.txt"
# Create Info.plist
echo "\nCreating Info.plist\n"
INFO_PLIST="${BUNDLE_CONTENTS}/Info.plist"
# This is kind of awful but plistlib is usde by dmgbuild
# and it's very strict about what it accepts, so for now this will do.
python3 -c "import plistlib; pl = { \
'CFBundleName': '0 A.D.', \
'CFBundleIdentifier': '${BUNDLE_IDENTIFIER}', \
'CFBundleVersion': '${BUNDLE_VERSION}', \
'CFBundlePackageType': 'APPL', \
'CFBundleSignature': 'none', \
'CFBundleExecutable': 'pyrogenesis', \
'CFBundleShortVersionString': '${BUNDLE_VERSION}', \
'CFBundleDevelopmentRegion': 'English', \
'CFBundleInfoDictionaryVersion': '6.0', \
'CFBundleIconFile': '0ad', \
'LSHasLocalizedDisplayName': True, \
'LSMinimumSystemVersion': '${BUNDLE_MIN_OSX_VERSION}', \
'NSHumanReadableCopyright': 'Copyright © $(date +%Y) Wildfire Games', \
}; \
fp = open('${INFO_PLIST}', 'wb'); plistlib.dump(pl, fp); fp.close();"
# Package the app into a dmg
dmgbuild \
-s "${DMGBUILD_CONFIG}" \
-D app="${BUNDLE_OUTPUT}" \
-D background="../../build/resources/dmgbackground.png" \
-D icon="../resources/0ad.icns" \
"${BUNDLE_DMG_NAME}" "${BUNDLE_FILENAME}"
echo "\nBundle complete! Located in ${BUNDLE_OUTPUT}, compressed as ${BUNDLE_FILENAME}."

View File

@ -0,0 +1,61 @@
#!/bin/sh
# Build the Pyrogenesis executable, used to create the bundle and run the archiver.
# TODO: is there anything to do for ARM support?
export ARCH=${ARCH:="x86_64"}
# Set mimimum required OS X version, SDK location and tools
# Old SDKs can be found at https://github.com/phracker/MacOSX-SDKs
export MIN_OSX_VERSION=${MIN_OSX_VERSION:="10.12"}
# Note that the 10.12 SDK is know to be too old for FMT 7.
export SYSROOT=${SYSROOT:="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"}
export CC=${CC:="clang"} CXX=${CXX:="clang++"}
die()
{
echo ERROR: $*
exit 1
}
# Check that we're actually on OS X
if [ "`uname -s`" != "Darwin" ]; then
die "This script is intended for OS X only"
fi
# Check SDK exists
if [ ! -d "$SYSROOT" ]; then
die "$SYSROOT does not exist! You probably need to install Xcode"
fi
# Assume this is called from trunk/
cd "build/workspaces/"
JOBS=${JOBS:="-j5"}
# TODO: Do we really want to regenerate everything? (consider if one task fails)
./clean-workspaces.sh
# Build libraries against SDK
echo "\nBuilding libraries\n"
pushd ../../libraries/osx > /dev/null
./build-osx-libs.sh $JOBS --force-rebuild || die "Libraries build script failed"
popd > /dev/null
# Update workspaces
echo "\nGenerating workspaces\n"
# Pass OS X options through to Premake
(SYSROOT="$SYSROOT" MIN_OSX_VERSION="$MIN_OSX_VERSION" ./update-workspaces.sh --sysroot="$SYSROOT" --macosx-version-min="$MIN_OSX_VERSION") || die "update-workspaces.sh failed!"
pushd gcc > /dev/null
echo "\nBuilding game\n"
(make clean && CC="$CC -arch $ARCH" CXX="$CXX -arch $ARCH" make ${JOBS}) || die "Game build failed!"
popd > /dev/null
# Run test to confirm all is OK
pushd ../../binaries/system > /dev/null
echo "\nRunning tests\n"
./test || die "Post-build testing failed!"
popd > /dev/null

46
source/tools/dist/build-unix-win32.sh vendored Normal file
View File

@ -0,0 +1,46 @@
#!/bin/bash
set -ev
XZOPTS="-9 -e"
GZIP7ZOPTS="-mx=9"
BUNDLE_VERSION=${BUNDLE_VERSION:="0.0.xxx"}
PREFIX="0ad-${BUNDLE_VERSION}-alpha"
SVN_REV=$(svnversion -n .)
echo "${SVN_REV}-release" > build/svn_revision/svn_revision.txt
# Collect the relevant files
tar cf $PREFIX-unix-build.tar \
--exclude='*.bat' --exclude='*.dll' --exclude='*.exe' --exclude='*.lib' \
--exclude='libraries/source/fcollada/src/FCollada/FColladaTest' \
--exclude='libraries/source/spidermonkey/include-*' \
--exclude='libraries/source/spidermonkey/lib*' \
{source,build,libraries/source,binaries/system/readme.txt,binaries/data/l10n,binaries/data/tests,binaries/data/mods/_test.*,*.txt}
tar cf $PREFIX-unix-data.tar \
--exclude='binaries/data/config/dev.cfg' \
-s "|archives|binaries/data/mods|" \
binaries/data/{config,tools} archives/
# TODO: ought to include generated docs in here, perhaps?
# Compress
xz -kv ${XZOPTS} $PREFIX-unix-build.tar
xz -kv ${XZOPTS} $PREFIX-unix-data.tar
7z a ${GZIP7ZOPTS} $PREFIX-unix-build.tar.gz $PREFIX-unix-build.tar
7z a ${GZIP7ZOPTS} $PREFIX-unix-data.tar.gz $PREFIX-unix-data.tar
# Create Windows installer
# This needs nsisbi for files > 2GB
makensis -V4 -nocd \
-dcheckoutpath="." \
-drevision=${SVN_REV} \
-dprefix=${PREFIX} \
-darchive_path="archives/" \
source/tools/dist/0ad.nsi
# Fix permissions
chmod -f 644 ${PREFIX}-{unix-{build,data}.tar.{xz,gz},win32.exe}
# Print digests for copying into wiki page
shasum -a 1 ${PREFIX}-{unix-{build,data}.tar.{xz,gz},win32.exe}

View File

@ -1,63 +1,13 @@
#!/bin/bash #!/bin/sh
set -e
set -ev ## This script runs all necessary steps to make a bundle
## It is not used directly by the CI, which calls those steps independently.
## Assume we are being called from trunk/
# Compiled executable for archive-builder tool ./source/tools/dist/build-osx-executable.sh
EXE=/mnt/0ad/0ad/binaries/system/pyrogenesis ./source/tools/dist/build-archives.sh
python3 source/tools/dist/build-osx-bundle.py
# Location of clean checkout # Note that at this point, you'll have left-over compilation files.
SVNWC=/mnt/0ad/0ad/ # The CI cleans them via svn st | cut -c9- | xargs rm -rf
./source/tools/dist/build-unix-win32.sh
SVNREV=`svnversion -n ${SVNWC}`
PREFIX=0ad-0.0.XXX-alpha
XZOPTS="-9 -e"
GZIP7ZOPTS="-mx=9"
# Export files with appropriate line-endings
rm -rf export-unix
rm -rf export-win32
svn export ${SVNWC} export-unix
svn export --native-eol CRLF ${SVNWC} export-win32
# Only include translations for a subset of languages
. remove-incomplete-translations.sh export-{unix,win32}/binaries/data/
# Update the svn_revision, so these builds can be identified
echo L\"${SVNREV}-release\" > export-unix/build/svn_revision/svn_revision.txt
echo L\"${SVNREV}-release\" > export-win32/build/svn_revision/svn_revision.txt
# Package the mod data
# (The platforms differ only in line endings, so just do the Unix one instead of
# generating two needlessly inconsistent packages)
${EXE} -mod=mod -archivebuild=export-unix/binaries/data/mods/public -archivebuild-output=export-unix/binaries/data/mods/public/public.zip
cp export-unix/binaries/data/mods/public/public.zip export-win32/binaries/data/mods/public/public.zip
${EXE} -archivebuild=export-unix/binaries/data/mods/mod -archivebuild-output=export-unix/binaries/data/mods/mod/mod.zip
cp export-unix/binaries/data/mods/mod/mod.zip export-win32/binaries/data/mods/mod/mod.zip
# Collect the relevant files
ln -Tsf export-unix ${PREFIX}
tar cf $PREFIX-unix-build.tar \
--exclude='*.bat' --exclude='*.dll' --exclude='*.exe' --exclude='*.lib' \
--exclude='libraries/source/fcollada/src/FCollada/FColladaTest' \
--exclude='libraries/source/spidermonkey/include-win32-*' \
${PREFIX}/{source,build,libraries/source,binaries/system/readme.txt,binaries/data/l10n,binaries/data/tests,binaries/data/mods/_test.*,*.txt}
tar cf $PREFIX-unix-data.tar \
--exclude='binaries/data/config/dev.cfg' \
${PREFIX}/binaries/data/{config,mods/mod/mod.zip,mods/public/public.zip,tools}
# TODO: ought to include generated docs in here, perhaps?
# Compress
xz -kv ${XZOPTS} $PREFIX-unix-build.tar
xz -kv ${XZOPTS} $PREFIX-unix-data.tar
7z a ${GZIP7ZOPTS} $PREFIX-unix-build.tar.gz $PREFIX-unix-build.tar
7z a ${GZIP7ZOPTS} $PREFIX-unix-data.tar.gz $PREFIX-unix-data.tar
# Create Windows installer
makensis -nocd -dcheckoutpath=export-win32 -drevision=${SVNREV} -dprefix=${PREFIX} export-win32/source/tools/dist/0ad.nsi
# Fix permissions
chmod -f 644 ${PREFIX}-{unix-{build,data}.tar.{xz,gz},win32.exe}
# Print digests for copying into wiki page
sha1sum ${PREFIX}-{unix-{build,data}.tar.{xz,gz},win32.exe}

View File

@ -1,10 +0,0 @@
#!/bin/bash
# Included languages
# Keep in sync with source/tools/i18n/creditTranslators.py and with the installer languages in 0ad.nsi
LANGS=("ast" "bg" "ca" "cs" "de" "el" "en_GB" "es" "eu" "fr" "gd" "gl" "hu" "id" "it" "ms" "nb" "nl" "pl" "pt_BR" "pt_PT" "ru" "sk" "sv" "tr" "uk")
REGEX=$(printf "\|%s" "${LANGS[@]}")
REGEX=".*/\("${REGEX:2}"\)\.[-A-Za-z0-9_.]\+\.po"
find "$@" -name "*.po" | grep -v "$REGEX" | xargs rm