Mac OS X only: added deployment scripts. Finally managed to cope with 10.4 SDK and...
authorMarcus Eggenberger <egs@quassel-irc.org>
Fri, 27 Jun 2008 15:14:41 +0000 (17:14 +0200)
committerMarcus Eggenberger <egs@quassel-irc.org>
Fri, 27 Jun 2008 15:15:05 +0000 (17:15 +0200)
CMakeLists.txt
scripts/build/macosx_DeployApp.py [new file with mode: 0755]
scripts/build/macosx_makePackage.sh [new file with mode: 0755]
scripts/build/macosx_makebundle.py

index 3f074e8..16dac30 100644 (file)
@@ -5,6 +5,7 @@
 # -DQT=/path/to/qt : Choose a Qt4 installation to use instead of the system Qt4
 # -DSTATIC=ON      : Enable static building of Quassel. Use with care.
 # -DSPUTDEV=ON     : Do not use.
+# -DDEPLOY=ON      : Mac OS X only. Use only fore redistribution Quassel Packages!!
 #
 # NOTE: You need to remove CMakeCache.txt if you plan to change any of these values!
 
@@ -27,6 +28,7 @@ option(WANT_QTCLIENT "Build the Qt4 GUI client binary"          ON)
 option(WANT_MONO     "Build the monolithic (all-in-one) binary" OFF)
 
 option(STATIC        "Enable static building (might not be portable)" OFF)
+option(DEPLOY        "Mac OS X only! Adds required libs to bundle resources and create a dmg. Note: requires Qt to be built with 10.4u SDK" OFF)
 option(SPUTDEV       "Do not use!" OFF)
 
 set(QT "" CACHE STRING "Path to a Qt installation to use instead of the system Qt")
@@ -54,10 +56,11 @@ endif(CMAKE_COMPILER_IS_GNUCXX)
 
 set(QT_MIN_VERSION "4.3.0")
 
-if(APPLE)
+if(APPLE AND DEPLOY)
   set(CMAKE_OSX_ARCHITECTURES "i386;ppc")
-#  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.4")
-endif(APPLE)
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.4")
+  set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.4u.sdk/")
+endif(APPLE AND DEPLOY)
 
 # Enable mostly b0rked stuff (new ChatView), do not enable this unless you know what you do...
 if(SPUTDEV)
@@ -83,10 +86,6 @@ include_directories(${QT_INCLUDES})
 # We need to create a version.gen
 # For this, we create our genversion binary and make sure it is run every time.
 add_executable(genversion ${CMAKE_SOURCE_DIR}/src/common/genversion.cpp)
-#set_target_properties(genversion PROPERTIES 
-#                                 LINK_FLAGS "-mmacosx-version-min=10.4")
-#                                 COMPILE_FLAGS "-mmacosx-version-min=10.4"
-
 target_link_libraries(genversion ${QT_LIBRARIES} ${QT_CORE_LIB_DEPENDENCIES})
 
 add_custom_target(genversion_run ALL ${CMAKE_BINARY_DIR}/genversion
@@ -195,6 +194,12 @@ if(APPLE)
   add_custom_command(TARGET quassel POST_BUILD
                      COMMAND ${CMAKE_SOURCE_DIR}/scripts/build/macosx_makebundle.py
                              ${CMAKE_SOURCE_DIR} "Quassel" quassel)
+  if(DEPLOY)
+    add_custom_command(TARGET quasselclient POST_BUILD
+                       COMMAND ${CMAKE_SOURCE_DIR}/scripts/build/macosx_makePackage.sh Client)
+    add_custom_command(TARGET quasselcore POST_BUILD
+                       COMMAND ${CMAKE_SOURCE_DIR}/scripts/build/macosx_makePackage.sh Core)
+  endif(DEPLOY)
 endif(APPLE)
 
 # Install rules
diff --git a/scripts/build/macosx_DeployApp.py b/scripts/build/macosx_DeployApp.py
new file mode 100755 (executable)
index 0000000..4be32f7
--- /dev/null
@@ -0,0 +1,113 @@
+#!/usr/bin/python
+# -*- coding: iso-8859-1 -*-
+
+################################################################################
+#                                                                              #
+# 2008 June 27th by Marcus 'EgS' Eggenberger <egs@quassel-irc.org>             #
+#                                                                              #
+# The author disclaims copyright to this source code.                          #
+# This Python Script is in the PUBLIC DOMAIN.                                  #
+#                                                                              #
+################################################################################
+
+# ==============================
+#  Imports
+# ==============================
+import sys
+import os
+
+class InstallQt(object):
+    def __init__(self, appdir, bundle = True):
+        self.appDir = appdir
+        self.bundle = bundle
+        self.executableDir = self.appDir
+        if bundle:
+            self.executableDir += "/MacOS"
+
+        if bundle:
+            self.frameworkDir = self.appDir + "/Frameworks"
+        else:
+            self.frameworkDir = self.executableDir + "/Frameworks"
+
+        self.needFrameworks = []
+
+        executables = [self.executableDir + "/" + executable for executable in os.listdir(self.executableDir)]
+
+        for executable in executables:
+            for framework,lib in self.determineDependancies(executable):
+                if framework not in self.needFrameworks:
+                    self.needFrameworks.append(framework)
+                    self.installFramework(framework)
+            self.changeDylPath(executable)
+
+    def installFramework(self, framework):
+        try:
+            os.mkdir(self.frameworkDir)
+        except:
+            pass
+
+        # Copy Framework
+        os.system('cp -R "%s" "%s"' % (framework, self.frameworkDir))
+
+        frameworkname = framework.split('/')[-1]
+        localframework = self.frameworkDir + "/" + frameworkname
+
+        # De-Myllify
+        os.system('find "%s" -name *debug* -exec rm -f {} \;' % localframework)
+        os.system('find "%s" -name Headers -exec rm -rf {} \; 2>/dev/null' % localframework)
+
+        # Install new Lib ID and Change Path to Frameworks for the Dynamic linker
+        for lib in os.listdir(localframework + "/Versions/Current"):
+            lib = "%s/Versions/Current/%s" % (localframework, lib)
+            otoolpipe = os.popen('otool -D "%s"' % lib)
+            libname = [line for line in otoolpipe][1].strip()
+            otoolpipe.close()
+            frameworkpath, libpath = libname.split(frameworkname)
+            if self.bundle:
+                newlibname = "@executable_path/../%s%s" % (frameworkname, libpath)
+            else:
+                newlibname = "@executable_path/%s%s" % (frameworkname, libpath)
+            #print 'install_name_tool -id "%s" "%s"' % (newlibname, lib)
+            os.system('install_name_tool -id "%s" "%s"' % (newlibname, lib))
+            self.changeDylPath(lib)
+            
+    def determineDependancies(self, app):
+        otoolPipe = os.popen('otool -L "%s"' % app)
+        otoolOutput = [line for line in otoolPipe]
+        otoolPipe.close()
+        libs = [line.split()[0] for line in otoolOutput[1:] if "Qt" in line and not "@executable_path" in line]
+        frameworks = [lib[:lib.find(".framework")+len(".framework")] for lib in libs]
+        return zip(frameworks, libs)
+
+    def changeDylPath(self, obj):
+        for framework, lib in self.determineDependancies(obj):
+            frameworkname = framework.split('/')[-1]
+            frameworkpath, libpath = lib.split(frameworkname)
+            if self.bundle:
+                newlibname = "@executable_path/../Frameworks/%s%s" % (frameworkname, libpath)
+            else:
+                newlibname = "@executable_path/Frameworks/%s%s" % (frameworkname, libpath)
+
+            #print 'install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj)
+            os.system('install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj))
+
+if __name__ == "__main__":
+    if len(sys.argv) < 2:
+        print "Wrong Argument Count (Syntax: %s [--nobundle] $TARGET_APP)" % sys.argv[0]
+        sys.exit(1)
+    else:
+        bundle = True
+        offset = 1
+
+        if sys.argv[1].startswith("--"):
+            offset = 2
+            if sys.argv[1] == "--nobundle":
+                bundle = False
+
+        targetDir = sys.argv[offset]
+        if bundle:
+            targetDir += "/Contents"
+
+        InstallQt(targetDir, bundle)
+    
+    
diff --git a/scripts/build/macosx_makePackage.sh b/scripts/build/macosx_makePackage.sh
new file mode 100755 (executable)
index 0000000..35b4f88
--- /dev/null
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+myname=$0
+if [ -s "$myname" ] && [ -x "$myname" ]; then
+    # $myname is already a valid file name
+
+    mypath=$myname
+else
+    case "$myname" in
+    /*) exit 1;;             # absolute path - do not search PATH
+    *)
+        # Search all directories from the PATH variable. Take
+        # care to interpret leading and trailing ":" as meaning
+        # the current directory; the same is true for "::" within
+        # the PATH.
+    
+        # Replace leading : with . in PATH, store in p
+        p=${PATH/#:/.:}
+        # Replace trailing : with .
+        p=${p//%:/:.}
+        # Replace :: with :.:
+        p=${p//::/:.:}
+        # Temporary input field separator, see FAQ #1
+        OFS=$IFS IFS=:
+        # Split the path on colons and loop through each of them
+        for dir in $p; do
+                [ -f "$dir/$myname" ] || continue # no file
+                [ -x "$dir/$myname" ] || continue # not executable
+                mypath=$dir/$myname
+                break           # only return first matching file
+        done
+        # Restore old input field separator
+        IFS=$OFS
+        ;;
+    esac
+fi
+
+if [ ! -f "$mypath" ]; then
+    echo >&2 "cannot find full path name: $myname"
+    exit 1
+fi
+
+SCRIPTDIR=$(dirname $mypath)
+QUASSEL_VERSION=$(git-describe)
+BUILDTYPE=$1
+if [[ $BUILDTYPE = "Core" ]] || [[ $BUILDTYPE = "Client" ]]; then
+    QUASSEL_DMG="Quassel${BUILDTYPE}_MacOSX-universal_${QUASSEL_VERSION}.dmg"
+    mkdir $BUILDTYPE
+    if [[ $BUILDTYPE = "Client" ]]; then
+       cp -r Quassel\ Client.app Client/
+       ${SCRIPTDIR}/macosx_DeployApp.py "Client/Quassel Client.app"
+    else
+       cp quasselcore Core/
+       ${SCRIPTDIR}/macosx_DeployApp.py --nobundle Core
+    fi
+    hdiutil create -srcfolder ${BUILDTYPE} -format UDBZ -volname "Quassel ${BUILDTYPE} - ${QUASSEL_VERSION}" "Quassel${BUILDTYPE}_MacOSX-universal_${QUASSEL_VERSION}.dmg" >/dev/null
+else
+    echo >&2 "Valid parameters are \"Client\" or \"Core\""
+fi
index 821ce74..72e7379 100755 (executable)
@@ -1,6 +1,15 @@
 #!/usr/bin/python
 # -*- coding: iso-8859-1 -*-
 
+################################################################################
+#                                                                              #
+# 2008 June 27th by Marcus 'EgS' Eggenberger <egs@quassel-irc.org>             #
+#                                                                              #
+# The author disclaims copyright to this source code.                          #
+# This Python Script is in the PUBLIC DOMAIN.                                  #
+#                                                                              #
+################################################################################
+
 # ==============================
 #  Imports
 # ==============================