summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'BuildTools')
-rw-r--r--BuildTools/SCons/Tools/AppBundle.py4
-rw-r--r--BuildTools/SCons/Tools/InstallWithSymLinks.py114
2 files changed, 117 insertions, 1 deletions
diff --git a/BuildTools/SCons/Tools/AppBundle.py b/BuildTools/SCons/Tools/AppBundle.py
index 6b7fc8b..337e83f 100644
--- a/BuildTools/SCons/Tools/AppBundle.py
+++ b/BuildTools/SCons/Tools/AppBundle.py
@@ -3,6 +3,8 @@ from datetime import date
def generate(env) :
def createAppBundle(env, bundle, version = "1.0", resources = [], frameworks = [], info = {}, handlesXMPPURIs = False, sparklePublicDSAKey = None) :
+ env.Tool("InstallWithSymLinks", toolpath = ["#/BuildTools/SCons/Tools"])
+
bundleDir = bundle + ".app"
bundleContentsDir = bundleDir + "/Contents"
resourcesDir = bundleContentsDir + "/Resources"
@@ -59,7 +61,7 @@ def generate(env) :
env.Install(os.path.join(resourcesDir, target), resource)
for framework in frameworks :
- env.Install(frameworksDir, framework)
+ env.InstallWithSymLinks(frameworksDir, framework)
return env.Dir(bundleDir)
diff --git a/BuildTools/SCons/Tools/InstallWithSymLinks.py b/BuildTools/SCons/Tools/InstallWithSymLinks.py
new file mode 100644
index 0000000..23d12ed
--- /dev/null
+++ b/BuildTools/SCons/Tools/InstallWithSymLinks.py
@@ -0,0 +1,114 @@
+"""SCons.Tool.install
+
+Tool-specific initialization for the install tool.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001 - 2015 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+from SCons.Script import Action, Builder
+from SCons.Node import FS
+import shutil
+import stat
+import os
+from os import path
+
+class CopytreeError(EnvironmentError):
+ pass
+
+# This is a patched version of shutil.copytree from python 2.5. It
+# doesn't fail if the dir exists, which regular copytree does
+# (annoyingly). Note the XXX comment in the docstring.
+def scons_copytree(src, dst, symlinks=False):
+ """Recursively copy a directory tree using copy2().
+
+ The destination directory must not already exist.
+ If exception(s) occur, an CopytreeError is raised with a list of reasons.
+
+ If the optional symlinks flag is true, symbolic links in the
+ source tree result in symbolic links in the destination tree; if
+ it is false, the contents of the files pointed to by symbolic
+ links are copied.
+
+ XXX Consider this example code rather than the ultimate tool.
+
+ """
+ names = os.listdir(src)
+ # garyo@genarts.com fix: check for dir before making dirs.
+ if not os.path.exists(dst):
+ os.makedirs(dst)
+ errors = []
+ for name in names:
+ srcname = os.path.join(src, name)
+ dstname = os.path.join(dst, name)
+ try:
+ if symlinks and os.path.islink(srcname):
+ linkto = os.readlink(srcname)
+ os.symlink(linkto, dstname)
+ elif os.path.isdir(srcname):
+ scons_copytree(srcname, dstname, symlinks)
+ else:
+ shutil.copy2(srcname, dstname)
+ # XXX What about devices, sockets etc.?
+ except (IOError, os.error), why:
+ errors.append((srcname, dstname, str(why)))
+ # catch the CopytreeError from the recursive copytree so that we can
+ # continue with other files
+ except CopytreeError, err:
+ errors.extend(err.args[0])
+ try:
+ shutil.copystat(src, dst)
+ except WindowsError:
+ # can't copy file access times on Windows
+ pass
+ except OSError, why:
+ errors.extend((src, dst, str(why)))
+ if errors:
+ raise CopytreeError, errors
+
+
+def symlinkBuilderImpl(target, source, env):
+ lnk = target[0].abspath
+ src = source[0].abspath
+ lnkdir,lnkname = path.split(lnk)
+ srcdir,srcname = path.split(src)
+
+ scons_copytree(src, os.path.join(lnk, srcname), True)
+
+ return None
+
+def symlinkBuilderPrinter(target, source, env):
+ lnk = path.basename(target[0].abspath)
+ src = path.basename(source[0].abspath)
+ return 'INSTALL PRESERVING SYMLINKS ' + target[0].get_internal_path()
+
+def generate(env) :
+ symlinkBuilder = Builder(action = Action(symlinkBuilderImpl, symlinkBuilderPrinter), target_factory = FS.Entry, source_factory = FS.Entry)
+ env.Append(BUILDERS = {'InstallWithSymLinks' : symlinkBuilder})
+
+def exists(env) :
+ return True \ No newline at end of file