summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'BuildTools')
-rw-r--r--BuildTools/.gitignore1
-rwxr-xr-xBuildTools/CheckTabs.py41
-rwxr-xr-xBuildTools/Copyrighter.py96
-rw-r--r--BuildTools/Coverage/.gitignore1
-rwxr-xr-xBuildTools/Coverage/FilterLCovData.py32
-rwxr-xr-xBuildTools/Coverage/GenerateCoverageResults.sh32
-rwxr-xr-xBuildTools/Coverage/GenerateOverview.py63
-rwxr-xr-xBuildTools/Coverage/GenerateSummary.py35
-rw-r--r--BuildTools/Coverage/descriptions.txt2
-rwxr-xr-xBuildTools/Git/Hooks/pre-commit7
-rw-r--r--BuildTools/MSVS/.gitignore4
-rw-r--r--BuildTools/MSVS/GenerateProjects.py100
-rw-r--r--BuildTools/MSVS/Swift.sln26
-rw-r--r--BuildTools/SCons/SConstruct399
-rw-r--r--BuildTools/SCons/Tools/AppBundle.py52
-rw-r--r--BuildTools/SCons/Tools/BuildVersion.py17
-rw-r--r--BuildTools/SCons/Tools/Nib.py12
-rw-r--r--BuildTools/SCons/Tools/Test.py13
-rw-r--r--BuildTools/SCons/Tools/WindowsBundle.py17
-rw-r--r--BuildTools/SCons/Tools/WriteVal.py14
-rw-r--r--BuildTools/SCons/Tools/nsis.py37
-rw-r--r--BuildTools/SCons/Tools/qt4.py517
-rw-r--r--BuildTools/SCons/Version.py15
-rwxr-xr-xBuildTools/package_debian.sh10
24 files changed, 1543 insertions, 0 deletions
diff --git a/BuildTools/.gitignore b/BuildTools/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/BuildTools/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/BuildTools/CheckTabs.py b/BuildTools/CheckTabs.py
new file mode 100755
index 0000000..2cc1cf7
--- /dev/null
+++ b/BuildTools/CheckTabs.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+
+import os, sys
+
+foundExpandedTabs = False
+
+for (path, dirs, files) in os.walk(".") :
+ if not "3rdParty" in path and not ".sconf" in path :
+ for filename in [os.path.join(path, file) for file in files if (file.endswith(".cpp") or file.endswith(".h")) and not "ui_" in file and not "moc_" in file and not "qrc_" in file] :
+ file = open(filename, "r")
+ contents = []
+ contentsChanged = False
+ for line in file.readlines() :
+ newline = ""
+ previousChar = None
+ pastInitialSpace = False
+ for char in line :
+ if not pastInitialSpace :
+ if char == ' ' and previousChar == ' ' :
+ contentsChanged = True
+ previousChar = '\t'
+ continue
+ pastInitialSpace = (char != ' ')
+ if previousChar :
+ newline += previousChar
+ previousChar = char
+ if previousChar :
+ newline += previousChar
+ contents.append(newline)
+ file.close()
+ if contentsChanged :
+ if len(sys.argv) > 1 and sys.argv[1] == "--fix" :
+ print "Fixing tabs in " + filename
+ file = open(filename, "w")
+ file.write(''.join(contents))
+ file.close()
+ else :
+ foundExpandedTabs = True
+ print filename + " contains expanded tabs"
+
+sys.exit(foundExpandedTabs)
diff --git a/BuildTools/Copyrighter.py b/BuildTools/Copyrighter.py
new file mode 100755
index 0000000..189dcf5
--- /dev/null
+++ b/BuildTools/Copyrighter.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+#coding=utf-8
+
+import os, re, datetime
+
+TEMPLATE = """/*
+ * Copyright (c) %(year)s %(author)s.
+ * See the included COPYING file for license details.
+ */
+
+"""
+
+def updateCopyright(fileName) :
+ file = open(fileName)
+ fileData = ""
+
+ author = ""
+ startYear = ""
+ endYear = ""
+ previousCopyright = ""
+
+ # Retrieve previous copyright information
+ header = ""
+ inHeader = False
+ inSpaceBelowHeader = False
+ lines = file.readlines()
+ lines2 = lines
+ for line in lines2 :
+ lines.pop(0)
+ if inSpaceBelowHeader :
+ if line.strip() != "" :
+ break
+ elif inHeader :
+ if line.startswith(" */") :
+ inSpaceBelowHeader = True
+ else :
+ header += line
+ else :
+ if line.strip() == "" :
+ continue
+ elif line.startswith("/*") :
+ inHeader = True
+ header += line
+ else :
+ fileData += line
+ break
+ if "Copyright" in header :
+ previousCopyright = header
+ m = re.match("\* Copyright \(c\) (?P<startYear>\d\d\d\d)(-(?P<endYear>\d\d\d\d))? (?P<author>.*)", header)
+ if m :
+ author = m.group("author")
+ startYear = m.group("startYear")
+ endYear = m.group("endYear")
+ elif header != "" :
+ fileData = header
+ file.close()
+
+ # Read in the rest of the data
+ fileData += "".join(lines)
+
+ # Guess empty values
+ if author == "" :
+ if "Swift/" in fileName :
+ author = "Kevin Smith"
+ else :
+ author = u"Remko Tronçon"
+ if startYear == "" :
+ startYear = datetime.date.today().strftime("%Y")
+ elif endYear == "" :
+ ## TODO: Guess end year by looking at git log --pretty=format:%ai -- <filename>
+ pass
+
+ # Generate a copyright
+ year = startYear + "-" + endYear if len(endYear) > 0 else startYear
+ copyright = TEMPLATE % {
+ "author" : author,
+ "year" : year
+ }
+
+ # Write the copyright to the file
+ if copyright.encode("utf-8") != previousCopyright :
+ file = open(fileName, "w")
+ file.write(copyright.encode("utf-8"))
+ file.write(fileData)
+ file.close()
+
+for (path, dirs, files) in os.walk("Swiften/JID") :
+ if "3rdParty" in path :
+ continue
+ for filename in files :
+ if not filename.endswith(".cpp") and not filename.endswith(".h") :
+ continue
+ if filename.startswith("moc_") :
+ continue
+ fullFilename = path + "/" + filename
+ updateCopyright(fullFilename)
diff --git a/BuildTools/Coverage/.gitignore b/BuildTools/Coverage/.gitignore
new file mode 100644
index 0000000..1a06816
--- /dev/null
+++ b/BuildTools/Coverage/.gitignore
@@ -0,0 +1 @@
+results
diff --git a/BuildTools/Coverage/FilterLCovData.py b/BuildTools/Coverage/FilterLCovData.py
new file mode 100755
index 0000000..a3a7ee5
--- /dev/null
+++ b/BuildTools/Coverage/FilterLCovData.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+
+# TODO: Add uncovered non-ignored files
+
+import sys, re, os.path
+
+assert(len(sys.argv) == 2)
+
+def isIgnored(file) :
+ return (file.find("/Swiften/") == -1 and file.find("/Slimber/") == -1 and file.find("/Swift/") == -1) or (file.find("/UnitTest/") != -1 or file.find("/QA/") != -1)
+
+
+output = []
+inputFile = open(sys.argv[1])
+inIgnoredFile = False
+for line in inputFile.readlines() :
+ if inIgnoredFile :
+ if line == "end_of_record\n" :
+ inIgnoredFile = False
+ else :
+ if line.startswith("SF:") and isIgnored(line) :
+ inIgnoredFile = True
+ else :
+ m = re.match("SF:(.*)", line)
+ if m :
+ line = "SF:" + os.path.realpath(m.group(1)) + "\n"
+ output.append(line)
+inputFile.close()
+
+outputFile = open(sys.argv[1], 'w')
+outputFile.write(''.join(output))
+outputFile.close()
diff --git a/BuildTools/Coverage/GenerateCoverageResults.sh b/BuildTools/Coverage/GenerateCoverageResults.sh
new file mode 100755
index 0000000..f06c484
--- /dev/null
+++ b/BuildTools/Coverage/GenerateCoverageResults.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# This script assumes that it is run from the toplevel directory
+
+SOURCE_DIR=.
+SCRIPT_DIR=BuildTools/Coverage
+LCOVDIR=3rdParty/LCov
+
+RESULTS_DIR=BuildTools/Coverage/results
+OUTPUT_DIR=$RESULTS_DIR/coverage-`git log --pretty=format:%ct-%h | head -n 1`
+
+if [ ! -d $OUTPUT_DIR ]; then
+ mkdir -p $OUTPUT_DIR
+fi
+
+# Reset counters
+$LCOVDIR/lcov --zerocounters --directory $SOURCE_DIR
+
+# Build & run all tests
+scons coverage=1 test=all
+
+# Run SCons
+$LCOVDIR/lcov --capture --directory $SOURCE_DIR -b $SOURCE_DIR --output-file $OUTPUT_DIR/all.info --test-name all
+cp $OUTPUT_DIR/all.info $OUTPUT_DIR/all.info.orig
+$SCRIPT_DIR/FilterLCovData.py $OUTPUT_DIR/all.info
+
+# Generate HTML
+$LCOVDIR/gendesc -o $OUTPUT_DIR/descriptions $SCRIPT_DIR/descriptions.txt
+$LCOVDIR/genhtml --no-function-coverage --title "Swift Coverage" --output-directory $OUTPUT_DIR $OUTPUT_DIR/all.info
+
+# Generate summary
+$SCRIPT_DIR/GenerateSummary.py $OUTPUT_DIR/all.info $OUTPUT_DIR/summary
diff --git a/BuildTools/Coverage/GenerateOverview.py b/BuildTools/Coverage/GenerateOverview.py
new file mode 100755
index 0000000..8928afd
--- /dev/null
+++ b/BuildTools/Coverage/GenerateOverview.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+import sys, os.path
+
+assert(len(sys.argv) == 4)
+
+resultsDir = sys.argv[1]
+summaryFile = sys.argv[2]
+overviewFile = sys.argv[3]
+
+results = []
+for dir in os.listdir(resultsDir) :
+ summary = os.path.join(resultsDir, dir, summaryFile)
+ if os.path.exists(summary) :
+ file = open(summary)
+ lines = file.readlines()
+ if len(lines) == 0 or len(lines[0].split("/")) != 2 :
+ continue
+ coveredCount = int(lines[0].split("/")[0])
+ totalCount = int(lines[0].split("/")[1])
+ results.append((dir,coveredCount,totalCount))
+
+# Compute coverage chart URL
+chartparams = ["chs=320x240", "cht=lc", "chtt=Coverage (Relative)", "chxt=y", "chxl=0:|50%|80%|100%|", "chxp=0,50,80,100"]
+chartdata = []
+for (url,covered,total) in results :
+ chartdata.append(str(100*covered/total))
+chartparams.append("chd=t:" + ",".join(chartdata))
+coverageChartURL = "http://chart.apis.google.com/chart?" + '&'.join(chartparams)
+
+# Compute the maximum of lines over time
+maximumNumberOfLines = 0
+for (url,covered,total) in results :
+ maximumNumberOfLines = max(maximumNumberOfLines,total)
+
+# Compute code chart URL
+chartparams = ["chs=320x240", "cht=lc", "chtt=Coverage (Absolute)", "chxt=y", "chxl=0:|" + str(maximumNumberOfLines) + "|", "chxp=0,100", "chm=b,FF0000,0,1,0|b,80C65A,1,2,0", "chco=00000000,00000000,00000000"]
+coveredLinesData = []
+totalLinesData = []
+nullLinesData = []
+for (url,covered,total) in results :
+ coveredLinesData.append(str(100*covered/maximumNumberOfLines))
+ totalLinesData.append(str(100*total/maximumNumberOfLines))
+ nullLinesData.append("0")
+chartparams.append("chd=t:" + ",".join(totalLinesData) + "|" + ",".join(coveredLinesData) + "|" + ",".join(nullLinesData))
+codeChartURL = "http://chart.apis.google.com/chart?" + '&'.join(chartparams)
+
+
+# Output page
+output = open(os.path.join(resultsDir,overviewFile), 'w')
+output.write("<img src=\"%(url)s\"s/>" % {'url' : coverageChartURL})
+output.write("<img src=\"%(url)s\"s/>" % {'url' : codeChartURL})
+output.write("<ul>\n")
+for (url,covered,total) in results :
+ output.write("<li><a href='%(url)s/index.html'>%(url)s</a> %(percentage)s%% (%(covered)s/%(total)s)</li>\n" % {
+ 'url' : url,
+ 'percentage' : 100*covered / total,
+ 'covered' : covered,
+ 'total' : total
+ })
+output.write("</ul>")
+output.close()
+
diff --git a/BuildTools/Coverage/GenerateSummary.py b/BuildTools/Coverage/GenerateSummary.py
new file mode 100755
index 0000000..ec94a4f
--- /dev/null
+++ b/BuildTools/Coverage/GenerateSummary.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+import sys, re
+
+assert(len(sys.argv) == 3)
+
+inputFile = open(sys.argv[1])
+currentFile = ""
+coverage = {}
+for line in inputFile.readlines() :
+ line = line.strip()
+ m = re.match("^SF:(.*)", line)
+ if m :
+ currentFile = m.group(1)
+ else :
+ m = re.match("^DA:(\d+),(\d+)", line)
+ if m :
+ currentFileCoverage = coverage.get(currentFile, {})
+ line = int(m.group(1))
+ count = int(m.group(2))
+ currentFileCoverage[line] = currentFileCoverage.get(line, 0) + count
+ coverage[currentFile] = currentFileCoverage
+inputFile.close()
+
+totalLines = 0
+coveredLines = 0
+for c in coverage.values() :
+ totalLines += len(c)
+ for l in c.values() :
+ if l > 0 :
+ coveredLines += 1
+
+outputFile = open(sys.argv[2], 'w')
+outputFile.write(str(coveredLines) + "/" + str(totalLines))
+outputFile.close()
diff --git a/BuildTools/Coverage/descriptions.txt b/BuildTools/Coverage/descriptions.txt
new file mode 100644
index 0000000..5b07e04
--- /dev/null
+++ b/BuildTools/Coverage/descriptions.txt
@@ -0,0 +1,2 @@
+all
+ All tests
diff --git a/BuildTools/Git/Hooks/pre-commit b/BuildTools/Git/Hooks/pre-commit
new file mode 100755
index 0000000..9ffc1c7
--- /dev/null
+++ b/BuildTools/Git/Hooks/pre-commit
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+echo "Checking tabs ..."
+if ! BuildTools/CheckTabs.py; then
+ echo "Expanded tabs found. Aborting commit."
+ exit -1
+fi
diff --git a/BuildTools/MSVS/.gitignore b/BuildTools/MSVS/.gitignore
new file mode 100644
index 0000000..95a4834
--- /dev/null
+++ b/BuildTools/MSVS/.gitignore
@@ -0,0 +1,4 @@
+*.suo
+*.ncp
+Slimber
+Swift
diff --git a/BuildTools/MSVS/GenerateProjects.py b/BuildTools/MSVS/GenerateProjects.py
new file mode 100644
index 0000000..d13df08
--- /dev/null
+++ b/BuildTools/MSVS/GenerateProjects.py
@@ -0,0 +1,100 @@
+import os, os.path
+
+projects = [("Swift", "Swift\QtUI\Swift.exe"), ("Slimber", "Slimber\Qt\Slimber.exe")]
+
+for (project, outputbin) in projects :
+ if not os.path.exists(project) :
+ os.mkdir(project)
+ output = open(os.path.join(project, project + ".vcproj"), "w")
+
+ headers = []
+ sources = []
+ for root, dirs, files in os.walk(os.path.join("..", "..", project)) :
+ for file in files :
+ if file.endswith(".h") :
+ headers.append('<File RelativePath="' + os.path.join("..", root, file) + '" />')
+ elif file.endswith(".cpp") :
+ sources.append('<File RelativePath="' + os.path.join("..", root, file) + '" />')
+
+ output.write("""<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="%(project)s"
+ Keyword="MakeFileProj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="cd ..\..\..\ &amp;&amp; scons debug=1 %(project)s"
+ ReBuildCommandLine=""
+ CleanCommandLine="cd ..\..\..\ &amp;&amp; scons -c debug=1 %(project)s"
+ Output="..\..\..\%(output)s"
+ PreprocessorDefinitions="WIN32;_DEBUG"
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="cd ..\..\..\ &amp;&amp; scons %(project)s"
+ ReBuildCommandLine=""
+ CleanCommandLine="cd ..\..\..\ &amp;&amp; scons -c %(project)s"
+ Output="..\..\..\%(output)s"
+ PreprocessorDefinitions="WIN32;NDEBUG"
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ >
+ %(sources)s
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ >
+ %(headers)s
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>""" % { "project": project, "output" : outputbin, "headers" : '\n'.join(headers), "sources": '\n'.join(sources) })
+ output.close()
diff --git a/BuildTools/MSVS/Swift.sln b/BuildTools/MSVS/Swift.sln
new file mode 100644
index 0000000..2724f81
--- /dev/null
+++ b/BuildTools/MSVS/Swift.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Swift", "Swift\Swift.vcproj", "{C67C3A5B-1382-4B4A-88F7-3BFC98DA43A2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Slimber", "Slimber\Slimber.vcproj", "{597242B2-A667-47A1-B69E-D2C4281183D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C67C3A5B-1382-4B4A-88F7-3BFC98DA43A2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C67C3A5B-1382-4B4A-88F7-3BFC98DA43A2}.Debug|Win32.Build.0 = Debug|Win32
+ {C67C3A5B-1382-4B4A-88F7-3BFC98DA43A2}.Release|Win32.ActiveCfg = Release|Win32
+ {C67C3A5B-1382-4B4A-88F7-3BFC98DA43A2}.Release|Win32.Build.0 = Release|Win32
+ {597242B2-A667-47A1-B69E-D2C4281183D0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {597242B2-A667-47A1-B69E-D2C4281183D0}.Debug|Win32.Build.0 = Debug|Win32
+ {597242B2-A667-47A1-B69E-D2C4281183D0}.Release|Win32.ActiveCfg = Release|Win32
+ {597242B2-A667-47A1-B69E-D2C4281183D0}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/BuildTools/SCons/SConstruct b/BuildTools/SCons/SConstruct
new file mode 100644
index 0000000..98202a5
--- /dev/null
+++ b/BuildTools/SCons/SConstruct
@@ -0,0 +1,399 @@
+import sys, os
+sys.path.append(Dir("BuildTools/SCons").abspath)
+import SCons.SConf
+
+################################################################################
+# Build variables
+################################################################################
+
+vars = Variables(os.path.join(Dir("#").abspath, "config.py"))
+vars.Add('ccflags', "Extra C(++) compiler flags")
+vars.Add('linkflags', "Extra linker flags")
+vars.Add(EnumVariable("test", "Compile and run tests", "none", ["none", "all", "unit", "system"]))
+vars.Add(BoolVariable("optimize", "Compile with optimizations turned on", "no"))
+vars.Add(BoolVariable("debug", "Compile with debug information", "yes" if os.name != "nt" else "no"))
+vars.Add(BoolVariable("warnings", "Compile with warnings turned on",
+ "yes" if os.name != "nt" else "no"))
+vars.Add(BoolVariable("max_jobs", "Build with maximum number of parallel jobs", "no"))
+vars.Add(EnumVariable("target", "Choose a target platform for compilation", "native", ["native", "iphone-simulator", "iphone-device"]))
+if os.name != "nt" :
+ vars.Add(BoolVariable("coverage", "Compile with coverage information", "no"))
+if os.name == "posix" :
+ vars.Add(BoolVariable("valgrind", "Run tests with valgrind", "no"))
+if os.name == "mac" or (os.name == "posix" and os.uname()[0] == "Darwin"):
+ vars.Add(BoolVariable("universal", "Create universal binaries", "no"))
+if os.name == "nt" :
+ vars.Add(PathVariable("vcredist", "MSVC redistributable dir", "", PathVariable.PathAccept))
+if os.name == "nt" :
+ vars.Add(PackageVariable("bonjour", "Bonjour SDK location", "yes"))
+vars.Add(PackageVariable("openssl", "OpenSSL location", "yes"))
+vars.Add(PathVariable("qt", "Qt location", "", PathVariable.PathAccept))
+
+################################################################################
+# Set up default build & configure environment
+################################################################################
+
+env = Environment(CPPPATH = "#", ENV = {'PATH' : os.environ['PATH']}, variables = vars)
+
+Help(vars.GenerateHelpText(env))
+
+env.Alias("dist", ["."])
+
+# Default custom tools
+env.Tool("Test", toolpath = ["#/BuildTools/SCons/Tools"])
+env.Tool("WriteVal", toolpath = ["#/BuildTools/SCons/Tools"])
+env.Tool("BuildVersion", toolpath = ["#/BuildTools/SCons/Tools"])
+if env["PLATFORM"] == "darwin" :
+ env.Tool("Nib", toolpath = ["#/BuildTools/SCons/Tools"])
+ env.Tool("AppBundle", toolpath = ["#/BuildTools/SCons/Tools"])
+if env["PLATFORM"] == "win32" :
+ env.Tool("WindowsBundle", toolpath = ["#/BuildTools/SCons/Tools"])
+
+# Override SConscript to handle tests
+oldSConscript = SConscript
+def SConscript(*arguments, **keywords) :
+ if not keywords.get("test_only", False) or env["TEST"] :
+ return apply(oldSConscript, arguments, keywords)
+
+# Max out the number of jobs
+if env["max_jobs"] :
+ try :
+ import multiprocessing
+ SetOption("num_jobs", multiprocessing.cpu_count())
+ except NotImplementedError :
+ pass
+
+# Default compiler flags
+env["CCFLAGS"] = env.get("ccflags", [])
+env["LINKFLAGS"] = env.get("linkflags", [])
+if env["optimize"] :
+ env.Append(CCFLAGS = "-O2")
+ if env["PLATFORM"] == "win32" :
+ env.Append(CCFLAGS = ["GL"])
+ env.Append(LINKFLAGS = ["/INCREMENTAL:NO", "/LTCG"])
+
+if env["debug"] :
+ if env["PLATFORM"] == "win32" :
+ env.Append(CCFLAGS = ["/Zi", "/MDd"])
+ env.Append(LINKFLAGS = ["/DEBUG"])
+ else :
+ env.Append(CCFLAGS = "-g")
+elif env["PLATFORM"] == "win32" :
+ env.Append(CCFLAGS = ["/MD"])
+
+if env.get("universal", 0) :
+ assert(env["PLATFORM"] == "darwin")
+ env.Append(CCFLAGS = [
+ "-isysroot", "/Developer/SDKs/MacOSX10.4u.sdk",
+ "-arch", "i386",
+ "-arch", "ppc"])
+ env.Append(LINKFLAGS = [
+ "-mmacosx-version-min=10.4",
+ "-Wl", "-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk",
+ "-arch", "i386",
+ "-arch", "ppc"])
+
+if env["warnings"] :
+ if env["PLATFORM"] == "win32" :
+ env.Append(CCFLAGS = ["/Wall"])
+ else :
+ env.Append(CCFLAGS = ["-W", "-Wall"])
+ #env.Append(CCFLAGS = ["-W", "-Wall", "-Wredundant-decls", "-pedantic", "-Wno-long-long", "-Woverloaded-virtual", "-Wundef", "-Wfloat-equal", "-Wold-style-cast"])
+
+if env.get("coverage", 0) :
+ assert(env["PLATFORM"] != "win32")
+ env.Append(CCFLAGS = ["-fprofile-arcs", "-ftest-coverage"])
+ env.Append(LINKFLAGS = ["-fprofile-arcs", "-ftest-coverage"])
+
+if env["PLATFORM"] == "win32" :
+ env.Append(LIBS = ["user32", "dnsapi", "ws2_32", "wsock32"])
+ env.Append(CCFLAGS = ["/EHsc", "/nologo"])
+ env["LINKCOM"] = [env["LINKCOM"], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1']
+ env["SHLINKCOM"] = [env["SHLINKCOM"], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;2']
+
+if env["PLATFORM"] == "darwin" :
+ env.Append(FRAMEWORKS = ["IOKit", "AppKit"])
+
+# Testing
+env["TEST_TYPE"] = env["test"]
+env.Alias("check", ".")
+if "check" in ARGUMENTS or "check" in COMMAND_LINE_TARGETS :
+ env["TEST_TYPE"] = "unit"
+env["TEST"] = (env["TEST_TYPE"] != "none") or env.GetOption("clean")
+if env.get("valgrind", 0) :
+ env["TEST_RUNNER"] = "valgrind --suppressions=QA/valgrind.supp -q --leak-check=full --track-origins=yes "
+
+# Packaging
+if ARGUMENTS.get("SWIFT_INSTALLDIR", "") :
+ env["SWIFT_INSTALLDIR"] = Dir(ARGUMENTS["SWIFT_INSTALLDIR"]).abspath
+
+# cross-compiling
+target = env["target"]
+if target in ("iphone-device", "iphone-simulator"):
+ if target == "iphone-device":
+ sdkPart = "iPhoneOS"
+ env["CC"] = "/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin9-gcc-4.0.1"
+ env["CXX"] = "/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin9-g++-4.0.1"
+ env["PATH"] = "/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/"
+ env["LD"] = env["CC"]
+# env["openssl"] = "#/3rdParty/openssl-0.9.8l-arm"
+ targetIncludesArch = "arm"
+
+ if target == "iphone-simulator":
+ sdkPart = "iPhoneSimulator"
+ env.Append(CCFLAGS = ["-arch", "i386"])
+ env.Append(LINKFLAGS = ["-arch", "i386"])
+ targetIncludesArch = "i686"
+
+ sdkVer = "3.0"
+ sdk = "/Developer/Platforms/" + sdkPart + ".platform/Developer/SDKs/" + sdkPart + sdkVer + ".sdk"
+
+ env["FRAMEWORKS"] = ["CoreFoundation", "Foundation", "UIKit", "CoreGraphics"]
+ env.Append(LINKFLAGS = ["-L\"" + sdk + "/usr/lib\"", "-F\"" + sdk + "/System/Library/Frameworks\"", "-F\"" + sdk + "/System/Library/PrivateFrameworks\""])
+ env["CPPPATH"] = ["/Users/kismith/devel/swift/iPhone/Swiftly/swift/", "/Developer/Platforms/" + sdkPart + ".platform/Developer/usr/lib/gcc/" + targetIncludesArch + "-apple-darwin9/4.0.1/include/", sdk + "/usr/include", sdk + "/usr/include/c++/4.0.0/" + targetIncludesArch + "-apple-darwin9", sdk + "/usr/include/c++/4.0.0", "/Developer/Platforms/" + sdkPart + ".platform/Developer/usr/include/"]
+
+# end cross compiling stuff
+
+
+conf_env = env.Clone()
+
+Export("env")
+Export("conf_env")
+
+
+################################################################################
+# Extend the default build environment (not affecting the configure env)
+#
+# Keeping both environments separated mostly because of SCons Issue 2391,
+# although it doesn't hurt to separate them (e.g. not have pretty printed
+# strings in config.log)
+################################################################################
+
+#if env["PLATFORM"] == "win32" :
+# env["MSVC_BATCH"] = 1
+
+# Pretty output
+def colorize(command, target, color) :
+ colors = { "red": "31", "green": "32", "yellow": "33", "blue": "34" }
+ prefix = ""
+ suffix = ""
+ if sys.stdout.isatty() and env["PLATFORM"] != "win32":
+ prefix = "\033[0;" + colors[color] + ";140m"
+ suffix = "\033[0m"
+ return " " + prefix + command + suffix + " " + target
+
+if int(ARGUMENTS.get("V", 0)) == 0:
+ env["CCCOMSTR"] = colorize("CC", "$TARGET", "green")
+ env["CXXCOMSTR"] = colorize("CXX", "$TARGET", "green")
+ env["LINKCOMSTR"] = colorize("LINK", "$TARGET", "red")
+ env["ARCOMSTR"] = colorize("AR", "$TARGET", "red")
+ env["RANLIBCOMSTR"] = colorize("RANLIB", "$TARGET", "red")
+ env["QT4_RCCCOMSTR"] = colorize("RCC", "$TARGET", "blue")
+ env["QT4_UICCOMSTR"] = colorize("UIC", "$TARGET", "blue")
+ env["QT4_MOCFROMHCOMSTR"] = colorize("MOC", "$TARGET", "blue")
+ env["QT4_MOCFROMCXXCOMSTR"] = colorize("MOC", "$TARGET", "blue")
+ env["GENCOMSTR"] = colorize("GEN", "$TARGET", "blue")
+ env["RCCOMSTR"] = colorize("RC", "$TARGET", "blue")
+ env["BUNDLECOMSTR"] = colorize("BUNDLE", "$TARGET", "blue")
+ env["NIBCOMSTR"] = colorize("NIB", "$TARGET", "blue")
+ env["NSISCOMSTR"] = colorize("NSIS", "$TARGET", "blue")
+ env["INSTALLSTR"] = colorize("INSTALL", "$TARGET", "blue")
+ env["TESTCOMSTR"] = colorize("TEST", "$SOURCE", "yellow")
+ #Progress(colorize("DEP", "$TARGET", "red")
+
+def checkObjCHeader(context, header) :
+ context.Message("Checking for Objective-C header " + header + " ... ")
+ ret = context.TryCompile("#include <Cocoa/Cocoa.h>\n#include <" + header + ">", ".m")
+ context.Result(ret)
+ return ret
+
+################################################################################
+# Platform configuration
+################################################################################
+
+if ARGUMENTS.get("force-configure", 0) :
+ SCons.SConf.SetCacheMode("force")
+
+conf = Configure(conf_env)
+
+if not conf.CheckCXX() or not conf.CheckCC() :
+ print "Error: You need a working compiler"
+ Exit(1)
+
+env["HAVE_ZLIB"] = True
+if conf.CheckLib("z") :
+ env.Append(LIBS = "z")
+ env["ZLIB_FLAGS"] = ""
+else :
+ env["ZLIB_BUNDLED"] = True
+
+if conf.CheckLib("dl") :
+ env.Append(LIBS = ["dl"])
+
+if conf.CheckLib("c") :
+ env.Append(LIBS = ["c"])
+
+if conf.CheckLib("resolv") :
+ env.Append(LIBS = ["resolv"])
+
+# Expat
+if conf.CheckCHeader("expat.h") and conf.CheckLib("expat") :
+ env["HAVE_EXPAT"] = 1
+ env["EXPAT_FLAGS"] = { "LIBS": ["expat"] }
+
+conf.Finish()
+
+# Xss
+env["HAVE_XSS"] = 0
+if env["PLATFORM"] != "win32" and env["PLATFORM"] != "darwin" :
+ xss_flags = {
+ "LIBPATH": ["/usr/X11R6/lib"],
+ "LIBS": ["X11", "Xss"]
+ }
+ xss_env = conf_env.Clone()
+ xss_env.MergeFlags(xss_flags)
+ conf = Configure(xss_env)
+ if conf.CheckFunc("XScreenSaverQueryExtension") :
+ env["HAVE_XSS"] = 1
+ env["XSS_FLAGS"] = xss_flags
+ conf.Finish()
+
+# Sparkle
+env["HAVE_SPARKLE"] = 0
+if env["PLATFORM"] == "darwin" :
+ sparkle_flags = {
+ "FRAMEWORKPATH": ["/Library/Frameworks"],
+ "FRAMEWORKS": ["Sparkle"]
+ }
+ sparkle_env = conf_env.Clone()
+ sparkle_env.MergeFlags(sparkle_flags)
+ conf = Configure(sparkle_env, custom_tests = { "CheckObjCHeader" : checkObjCHeader })
+ if conf.CheckObjCHeader("Sparkle/Sparkle.h") :
+ env["HAVE_SPARKLE"] = 1
+ env["SPARKLE_FLAGS"] = sparkle_flags
+ env["SPARKLE_FRAMEWORK"] = "/Library/Frameworks/Sparkle.framework"
+ conf.Finish()
+
+# LibXML
+conf = Configure(conf_env)
+if conf.CheckCHeader("libxml/parser.h") and conf.CheckLib("xml2") :
+ env["HAVE_LIBXML"] = 1
+ env["LIBXML_FLAGS"] = { "LIBS": ["xml2"] }
+conf.Finish()
+
+if not env.get("HAVE_LIBXML", 0) :
+ libxml_env = conf_env.Clone()
+ libxml_env.Append(CPPPATH = ["/usr/include/libxml2"])
+ conf = Configure(libxml_env)
+ if conf.CheckCHeader("libxml/parser.h") and conf.CheckLib("xml2") :
+ env["HAVE_LIBXML"] = 1
+ env["LIBXML_FLAGS"] = { "CPPPATH": ["/usr/include/libxml2"], "LIBS": ["xml2"] }
+ conf.Finish()
+
+# Bundled expat
+bundledExpat = False
+if not env.get("HAVE_EXPAT", 0) :
+ print "Expat or LibXML not found. Using bundled Expat"
+ SConscript("#/3rdParty/Expat/SConscript")
+ env["HAVE_EXPAT"] = 1
+ env["EXPAT_BUNDLED"] = True
+
+# Qt
+if env["qt"] :
+ env["QTDIR"] = env["qt"]
+
+# OpenSSL
+openssl_env = conf_env.Clone()
+use_openssl = bool(env["openssl"])
+openssl_prefix = env["openssl"] if isinstance(env["openssl"], str) else ""
+openssl_flags = {}
+if openssl_prefix :
+ openssl_flags = { "CPPPATH": [os.path.join(openssl_prefix, "include")] }
+ if env["PLATFORM"] == "win32" :
+ openssl_flags["LIBPATH"] = [os.path.join(openssl_prefix, "lib", "VC")]
+ env["OPENSSL_DIR"] = openssl_prefix
+ else :
+ openssl_flags["LIBPATH"] = [os.path.join(openssl_prefix, "lib")]
+ openssl_env.MergeFlags(openssl_flags)
+
+openssl_conf = Configure(openssl_env)
+if use_openssl and openssl_conf.CheckCHeader("openssl/ssl.h") :
+ env["HAVE_OPENSSL"] = 1
+ env["OPENSSL_FLAGS"] = openssl_flags
+ if env["PLATFORM"] == "win32" :
+ env["OPENSSL_FLAGS"]["LIBS"] = ["libeay32MT", "ssleay32MT"]
+ else:
+ env["OPENSSL_FLAGS"]["LIBS"] = ["ssl", "crypto"]
+else :
+ env["OPENSSL_FLAGS"] = ""
+
+openssl_conf.Finish()
+
+# Bonjour
+if env["PLATFORM"] == "darwin" :
+ env["HAVE_BONJOUR"] = 1
+elif env.get("bonjour", False) :
+ bonjour_env = conf_env.Clone()
+ bonjour_conf = Configure(bonjour_env)
+ bonjour_flags = {}
+ if env.get("bonjour") != True :
+ bonjour_prefix = env["bonjour"]
+ bonjour_flags["CPPPATH"] = [os.path.join(bonjour_prefix, "include")]
+ bonjour_flags["LIBPATH"] = [os.path.join(bonjour_prefix, "lib", "win32")]
+ bonjour_env.MergeFlags(bonjour_flags)
+ if bonjour_conf.CheckCHeader("dns_sd.h") and bonjour_conf.CheckLib("dnssd") :
+ env["HAVE_BONJOUR"] = 1
+ env["BONJOUR_FLAGS"] = bonjour_flags
+ env["BONJOUR_FLAGS"]["LIBS"] = ["dnssd"]
+ bonjour_conf.Finish()
+
+################################################################################
+# Project files
+# FIXME: We need to explicitly list the order of libraries here, because of
+# the exported FLAGS. We should put FLAGS in separate SConscript files, and
+# read these in before anything else, such that we don't need to manually
+# list modules in order.
+################################################################################
+
+# Modules
+modules = []
+for dir in os.listdir(Dir("#").abspath) :
+ full_dir = os.path.join(Dir("#").abspath, dir)
+ if not os.path.isdir(full_dir) :
+ continue
+ sconscript = os.path.join(full_dir, "SConscript")
+ if os.path.isfile(sconscript) :
+ modules.append(dir)
+for dir in os.listdir(Dir("#/3rdParty").abspath) :
+ full_dir = os.path.join(Dir("#/3rdParty").abspath, dir)
+ if not os.path.isdir(full_dir) :
+ continue
+ sconscript = os.path.join(full_dir, "SConscript")
+ if os.path.isfile(sconscript) :
+ modules.append("3rdParty/" + dir)
+
+# Flags
+for stage in ["flags", "build", "test"] :
+ env["SCONS_STAGE"] = stage
+ SConscript(dirs = map(lambda x : "#/" + x, modules))
+
+################################################################################
+# Print summary
+################################################################################
+
+print
+print " Build Configuration"
+print " -------------------"
+
+parsers = []
+if env.get("HAVE_LIBXML", 0):
+ parsers.append("LibXML")
+if env.get("HAVE_EXPAT", 0):
+ parsers.append("Expat")
+ if env.get("EXPAT_BUNDLED", False) :
+ parsers.append("(Bundled)")
+print " XML Parsers: " + ' '.join(parsers)
+
+print " TLS Support: " + ("OpenSSL" if env.get("HAVE_OPENSSL",0) else "Disabled")
+print " DNSSD Support: " + ("Bonjour" if env.get("HAVE_BONJOUR") else ("Avahi" if env.get("HAVE_AVAHI") else "Disabled"))
+print
diff --git a/BuildTools/SCons/Tools/AppBundle.py b/BuildTools/SCons/Tools/AppBundle.py
new file mode 100644
index 0000000..12667f0
--- /dev/null
+++ b/BuildTools/SCons/Tools/AppBundle.py
@@ -0,0 +1,52 @@
+import SCons.Util
+
+def generate(env) :
+ def createAppBundle(env, bundle, version = "1.0", resources = [], frameworks = [], info = {}) :
+ bundleDir = bundle + ".app"
+ bundleContentsDir = bundleDir + "/Contents"
+ resourcesDir = bundleContentsDir + "/Resources"
+ frameworksDir = bundleContentsDir + "/Frameworks"
+ env.Install(bundleContentsDir + "/MacOS", bundle)
+ env.WriteVal(bundleContentsDir + "/PkgInfo", env.Value("APPL\77\77\77\77"))
+
+ infoDict = {
+ "CFBundleDevelopmentRegion" : "English",
+ "CFBundleExecutable" : bundle,
+ "CFBundleIdentifier" : "im.swift." + bundle,
+ "CFBundleInfoDictionaryVersion" : "6.0",
+ "CFBundleName" : bundle,
+ "CFBundlePackageType" : "APPL",
+ "CFBundleSignature": "\77\77\77\77",
+ "CFBundleVersion" : version,
+ "CFBundleIconFile" : bundle,
+ "NSPrincipalClass" : "NSApplication",
+ "NSHumanReadableCopyright" : unichr(0xA9) + " 2009 Swift Development Team.\nAll Rights Reserved."
+ }
+ infoDict.update(info)
+
+ plist = """<?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+ <plist version="1.0">
+ <dict>
+ """
+ for key, value in infoDict.items() :
+ plist += "<key>" + key + "</key>\n"
+ plist += "<string>" + value.encode("utf-8") + "</string>\n"
+ plist += """</dict>
+ </plist>
+ """
+ env.WriteVal(bundleContentsDir + "/Info.plist", env.Value(plist))
+
+ for resource in resources :
+ env.Install(resourcesDir, resource)
+
+ for framework in frameworks :
+ env.Install(frameworksDir, framework)
+
+ return env.Dir(bundleDir)
+
+ env.AddMethod(createAppBundle, "AppBundle")
+
+
+def exists(env) :
+ return env["PLATFORM"] == "darwin"
diff --git a/BuildTools/SCons/Tools/BuildVersion.py b/BuildTools/SCons/Tools/BuildVersion.py
new file mode 100644
index 0000000..530ef8a
--- /dev/null
+++ b/BuildTools/SCons/Tools/BuildVersion.py
@@ -0,0 +1,17 @@
+import SCons.Util
+
+import Version
+
+def generate(env) :
+ def createBuildVersion(env, target, version = None) :
+ buildVersion = """#pragma once
+
+static const char* buildVersion = \"%(buildVersion)s\";\n
+""" % { "buildVersion" : Version.getBuildVersion(version) }
+ env.WriteVal(target, env.Value(buildVersion))
+
+ env.AddMethod(createBuildVersion, "BuildVersion")
+
+
+def exists(env) :
+ return true
diff --git a/BuildTools/SCons/Tools/Nib.py b/BuildTools/SCons/Tools/Nib.py
new file mode 100644
index 0000000..ccfd884
--- /dev/null
+++ b/BuildTools/SCons/Tools/Nib.py
@@ -0,0 +1,12 @@
+import SCons.Util
+
+def generate(env) :
+ env["IBTOOL"] = "ibtool"
+ env["BUILDERS"]["Nib"] = SCons.Builder.Builder(
+ action = SCons.Action.Action("$IBTOOL --errors --warnings --notices --output-format human-readable-text --compile $TARGET $SOURCE", cmdstr = "$NIBCOMSTR"),
+ suffix = ".nib",
+ src_suffix = ".xib",
+ single_source = True)
+
+def exists(env) :
+ return env["PLATFORM"] == "darwin"
diff --git a/BuildTools/SCons/Tools/Test.py b/BuildTools/SCons/Tools/Test.py
new file mode 100644
index 0000000..aaed222
--- /dev/null
+++ b/BuildTools/SCons/Tools/Test.py
@@ -0,0 +1,13 @@
+import SCons.Util
+
+def generate(env) :
+ def registerTest(env, target, type = "unit") :
+ if env["TEST_TYPE"] == "all" or env["TEST_TYPE"] == type :
+ cmd = target[0].abspath if SCons.Util.is_List(target) else target.abspath
+ env.Command("**dummy**", target,
+ SCons.Action.Action(env.get("TEST_RUNNER", "") + cmd, cmdstr = "$TESTCOMSTR"))
+
+ env.AddMethod(registerTest, "Test")
+
+def exists(env) :
+ return True
diff --git a/BuildTools/SCons/Tools/WindowsBundle.py b/BuildTools/SCons/Tools/WindowsBundle.py
new file mode 100644
index 0000000..bc690af
--- /dev/null
+++ b/BuildTools/SCons/Tools/WindowsBundle.py
@@ -0,0 +1,17 @@
+import SCons.Util, os
+
+def generate(env) :
+ def createWindowsBundle(env, bundle, resources = [], qtimageformats = [], qtlibs = []) :
+ env.Install(bundle, bundle + ".exe")
+ for lib in qtlibs :
+ env.Install(bundle, os.path.join(env["QTDIR"], "bin", lib + ".dll"))
+ env.Install(os.path.join(bundle, "imageformats"), [os.path.join(env["QTDIR"], "plugins", "imageformats", "q" + codec + "4.dll") for codec in qtimageformats])
+
+ for resource in resources :
+ env.Install(bundle, resource)
+
+ env.AddMethod(createWindowsBundle, "WindowsBundle")
+
+def exists(env) :
+ return env["PLATFORM"] == "win32"
+
diff --git a/BuildTools/SCons/Tools/WriteVal.py b/BuildTools/SCons/Tools/WriteVal.py
new file mode 100644
index 0000000..e39ad82
--- /dev/null
+++ b/BuildTools/SCons/Tools/WriteVal.py
@@ -0,0 +1,14 @@
+import SCons.Util
+
+def generate(env) :
+ def writeVal(env, target, source) :
+ f = open(str(target[0]), 'wb')
+ f.write(source[0].get_contents())
+ f.close()
+
+ env["BUILDERS"]["WriteVal"] = SCons.Builder.Builder(
+ action = SCons.Action.Action(writeVal, cmdstr = "$GENCOMSTR"),
+ single_source = True)
+
+def exists(env) :
+ return True
diff --git a/BuildTools/SCons/Tools/nsis.py b/BuildTools/SCons/Tools/nsis.py
new file mode 100644
index 0000000..567876d
--- /dev/null
+++ b/BuildTools/SCons/Tools/nsis.py
@@ -0,0 +1,37 @@
+import re, os
+import SCons.Util
+nsisFiles_re = re.compile(r'^\s*File "([^"]*)"', re.M)
+
+"""
+TODO:
+ - Extract the target from the nsis file
+ - When a target is provided use the output function
+"""
+
+def generate(env) :
+ """Add Builders and construction variables for qt to an Environment."""
+ Builder = SCons.Builder.Builder
+
+ env['NSIS_MAKENSIS'] = 'makensis'
+ env['NSIS_OPTIONS'] = ["/V2"]
+ def winToLocalReformat(path) :
+ return os.path.join(*path.split("\\"))
+ def scanNsisContent(node, env, path, arg):
+ contents = node.get_contents()
+ includes = nsisFiles_re.findall(contents)
+ includes = [ winToLocalReformat(include) for include in includes ]
+ return filter(lambda x: x.rfind('*')==-1, includes)
+ nsisscanner = env.Scanner(name = 'nsisfile',
+ function = scanNsisContent,
+ argument = None,
+ skeys = ['.nsi'])
+ nsisbuilder = Builder(
+ action = SCons.Action.Action('$NSIS_MAKENSIS $NSIS_OPTIONS $SOURCE', cmdstr = '$NSISCOMSTR'),
+ source_scanner = nsisscanner,
+ single_source = True
+ )
+ env.Append( BUILDERS={'Nsis' : nsisbuilder} )
+
+def exists(env) :
+ return True
+
diff --git a/BuildTools/SCons/Tools/qt4.py b/BuildTools/SCons/Tools/qt4.py
new file mode 100644
index 0000000..0a84c03
--- /dev/null
+++ b/BuildTools/SCons/Tools/qt4.py
@@ -0,0 +1,517 @@
+
+"""SCons.Tool.qt
+
+Tool-specific initialization for Qt.
+
+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, 2002, 2003, 2004, 2005, 2006, 2007 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.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/qt.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import re
+
+import SCons.Action
+import SCons.Builder
+import SCons.Defaults
+import SCons.Scanner
+import SCons.Tool
+import SCons.Util
+
+class ToolQtWarning(SCons.Warnings.Warning):
+ pass
+
+class GeneratedMocFileNotIncluded(ToolQtWarning):
+ pass
+
+class QtdirNotFound(ToolQtWarning):
+ pass
+
+SCons.Warnings.enableWarningClass(ToolQtWarning)
+
+qrcinclude_re = re.compile(r'<file>([^<]*)</file>', re.M)
+
+def transformToWinePath(path) :
+ return os.popen('winepath -w "%s"'%path).read().strip().replace('\\','/')
+
+header_extensions = [".h", ".hxx", ".hpp", ".hh"]
+if SCons.Util.case_sensitive_suffixes('.h', '.H'):
+ header_extensions.append('.H')
+# TODO: The following two lines will work when integrated back to SCons
+# TODO: Meanwhile the third line will do the work
+#cplusplus = __import__('c++', globals(), locals(), [])
+#cxx_suffixes = cplusplus.CXXSuffixes
+cxx_suffixes = [".c", ".cxx", ".cpp", ".cc"]
+
+def checkMocIncluded(target, source, env):
+ moc = target[0]
+ cpp = source[0]
+ # looks like cpp.includes is cleared before the build stage :-(
+ # not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/
+ path = SCons.Defaults.CScan.path_function(env, moc.cwd)
+ includes = SCons.Defaults.CScan(cpp, env, path)
+ if not moc in includes:
+ SCons.Warnings.warn(
+ GeneratedMocFileNotIncluded,
+ "Generated moc file '%s' is not included by '%s'" %
+ (str(moc), str(cpp)))
+
+def find_file(filename, paths, node_factory):
+ for dir in paths:
+ node = node_factory(filename, dir)
+ if node.rexists():
+ return node
+ return None
+
+class _Automoc:
+ """
+ Callable class, which works as an emitter for Programs, SharedLibraries and
+ StaticLibraries.
+ """
+
+ def __init__(self, objBuilderName):
+ self.objBuilderName = objBuilderName
+
+ def __call__(self, target, source, env):
+ """
+ Smart autoscan function. Gets the list of objects for the Program
+ or Lib. Adds objects and builders for the special qt files.
+ """
+ try:
+ if int(env.subst('$QT4_AUTOSCAN')) == 0:
+ return target, source
+ except ValueError:
+ pass
+ try:
+ debug = int(env.subst('$QT4_DEBUG'))
+ except ValueError:
+ debug = 0
+
+ # some shortcuts used in the scanner
+ splitext = SCons.Util.splitext
+ objBuilder = getattr(env, self.objBuilderName)
+
+ # some regular expressions:
+ # Q_OBJECT detection
+ q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]')
+ # cxx and c comment 'eater'
+ #comment = re.compile(r'(//.*)|(/\*(([^*])|(\*[^/]))*\*/)')
+ # CW: something must be wrong with the regexp. See also bug #998222
+ # CURRENTLY THERE IS NO TEST CASE FOR THAT
+
+ # The following is kind of hacky to get builders working properly (FIXME)
+ objBuilderEnv = objBuilder.env
+ objBuilder.env = env
+ mocBuilderEnv = env.Moc4.env
+ env.Moc4.env = env
+
+ # make a deep copy for the result; MocH objects will be appended
+ out_sources = source[:]
+
+ for obj in source:
+ if isinstance(obj,basestring): # big kludge!
+ print "scons: qt4: '%s' MAYBE USING AN OLD SCONS VERSION AND NOT CONVERTED TO 'File'. Discarded." % str(obj)
+ continue
+ if not obj.has_builder():
+ # binary obj file provided
+ if debug:
+ print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj)
+ continue
+ cpp = obj.sources[0]
+ if not splitext(str(cpp))[1] in cxx_suffixes:
+ if debug:
+ print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp)
+ # c or fortran source
+ continue
+ #cpp_contents = comment.sub('', cpp.get_contents())
+ try:
+ cpp_contents = cpp.get_contents()
+ except: continue # may be an still not generated source
+ h=None
+ for h_ext in header_extensions:
+ # try to find the header file in the corresponding source
+ # directory
+ hname = splitext(cpp.name)[0] + h_ext
+ h = find_file(hname, (cpp.get_dir(),), env.File)
+ if h:
+ if debug:
+ print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp))
+ #h_contents = comment.sub('', h.get_contents())
+ h_contents = h.get_contents()
+ break
+ if not h and debug:
+ print "scons: qt: no header for '%s'." % (str(cpp))
+ if h and q_object_search.search(h_contents):
+ # h file with the Q_OBJECT macro found -> add moc_cpp
+ moc_cpp = env.Moc4(h)
+ moc_o = objBuilder(moc_cpp)
+ out_sources.append(moc_o)
+ #moc_cpp.target_scanner = SCons.Defaults.CScan
+ if debug:
+ print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp))
+ if cpp and q_object_search.search(cpp_contents):
+ # cpp file with Q_OBJECT macro found -> add moc
+ # (to be included in cpp)
+ moc = env.Moc4(cpp)
+ env.Ignore(moc, moc)
+ if debug:
+ print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc))
+ #moc.source_scanner = SCons.Defaults.CScan
+ # restore the original env attributes (FIXME)
+ objBuilder.env = objBuilderEnv
+ env.Moc4.env = mocBuilderEnv
+
+ return (target, out_sources)
+
+AutomocShared = _Automoc('SharedObject')
+AutomocStatic = _Automoc('StaticObject')
+
+def _detect(env):
+ """Not really safe, but fast method to detect the QT library"""
+ try: return env['QTDIR']
+ except KeyError: pass
+
+ try: return os.environ['QTDIR']
+ except KeyError: pass
+
+ moc = env.WhereIs('moc-qt4') or env.WhereIs('moc4') or env.WhereIs('moc')
+ if moc:
+ import sys
+ if sys.platform == "darwin" :
+ return ""
+ QTDIR = os.path.dirname(os.path.dirname(moc))
+ SCons.Warnings.warn(
+ QtdirNotFound,
+ "QTDIR variable is not defined, using moc executable as a hint (QTDIR=%s)" % QTDIR)
+ return QTDIR
+
+ raise SCons.Errors.StopError(
+ QtdirNotFound,
+ "Could not detect Qt 4 installation")
+ return None
+
+def generate(env):
+ """Add Builders and construction variables for qt to an Environment."""
+
+ def locateQt4Command(env, command, qtdir) :
+ if len(qtdir) == 0 :
+ qtdir = "/usr"
+ suffixes = [
+ '-qt4',
+ '-qt4.exe',
+ '4',
+ '4.exe',
+ '',
+ '.exe',
+ ]
+ triedPaths = []
+ for suffix in suffixes :
+ fullpath = os.path.join(qtdir,'bin',command + suffix)
+ if os.access(fullpath, os.X_OK) :
+ return fullpath
+ triedPaths.append(fullpath)
+
+ fullpath = env.Detect([command+'-qt4', command+'4', command])
+ if not (fullpath is None) : return fullpath
+
+ raise Exception("Qt4 command '" + command + "' not found. Tried: " + ', '.join(triedPaths))
+
+
+ CLVar = SCons.Util.CLVar
+ Action = SCons.Action.Action
+ Builder = SCons.Builder.Builder
+ splitext = SCons.Util.splitext
+
+ env['QTDIR'] = _detect(env)
+ # TODO: 'Replace' should be 'SetDefault'
+# env.SetDefault(
+ env.Replace(
+ QTDIR = _detect(env),
+ # TODO: This is not reliable to QTDIR value changes but needed in order to support '-qt4' variants
+ QT4_MOC = locateQt4Command(env,'moc', env['QTDIR']),
+ QT4_UIC = locateQt4Command(env,'uic', env['QTDIR']),
+ QT4_RCC = locateQt4Command(env,'rcc', env['QTDIR']),
+ QT4_LUPDATE = locateQt4Command(env,'lupdate', env['QTDIR']),
+ QT4_LRELEASE = locateQt4Command(env,'lrelease', env['QTDIR']),
+ QT4_LIB = '', # KLUDGE to avoid linking qt3 library
+
+ QT4_AUTOSCAN = 1, # Should the qt tool try to figure out, which sources are to be moc'ed?
+
+ # Some QT specific flags. I don't expect someone wants to
+ # manipulate those ...
+ QT4_UICFLAGS = CLVar(''),
+ QT4_MOCFROMHFLAGS = CLVar(''),
+ QT4_MOCFROMCXXFLAGS = CLVar('-i'),
+ QT4_QRCFLAGS = '',
+
+ # suffixes/prefixes for the headers / sources to generate
+ QT4_UISUFFIX = '.ui',
+ QT4_UICDECLPREFIX = 'ui_',
+ QT4_UICDECLSUFFIX = '.h',
+ QT4_MOCHPREFIX = 'moc_',
+ QT4_MOCHSUFFIX = '$CXXFILESUFFIX',
+ QT4_MOCCXXPREFIX = '',
+ QT4_MOCCXXSUFFIX = '.moc',
+ QT4_QRCSUFFIX = '.qrc',
+ QT4_QRCCXXSUFFIX = '$CXXFILESUFFIX',
+ QT4_QRCCXXPREFIX = 'qrc_',
+ QT4_MOCCPPPATH = [],
+ QT4_MOCINCFLAGS = '$( ${_concat("-I", QT4_MOCCPPPATH, INCSUFFIX, __env__, RDirs)} $)',
+
+ # Commands for the qt support ...
+ QT4_UICCOM = '$QT4_UIC $QT4_UICFLAGS -o $TARGET $SOURCE',
+ QT4_MOCFROMHCOM = '$QT4_MOC $QT4_MOCFROMHFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE',
+ QT4_MOCFROMCXXCOM = [
+ '$QT4_MOC $QT4_MOCFROMCXXFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE',
+ Action(checkMocIncluded,None)],
+ QT4_LUPDATECOM = '$QT4_LUPDATE $SOURCE -ts $TARGET',
+ QT4_LRELEASECOM = '$QT4_LRELEASE $SOURCE',
+ QT4_RCCCOM = '$QT4_RCC $QT4_QRCFLAGS -name $SOURCE $SOURCE -o $TARGET',
+ )
+ if len(env["QTDIR"]) > 0 :
+ env.Replace(QT4_LIBPATH = os.path.join('$QTDIR', 'lib'))
+
+ # Translation builder
+ tsbuilder = Builder(
+ action = SCons.Action.Action('$QT4_LUPDATECOM'), #,'$QT4_LUPDATECOMSTR'),
+ multi=1
+ )
+ env.Append( BUILDERS = { 'Ts': tsbuilder } )
+ qmbuilder = Builder(
+ action = SCons.Action.Action('$QT4_LRELEASECOM'),# , '$QT4_LRELEASECOMSTR'),
+ src_suffix = '.ts',
+ suffix = '.qm',
+ single_source = True
+ )
+ env.Append( BUILDERS = { 'Qm': qmbuilder } )
+
+ # Resource builder
+ def scanResources(node, env, path, arg):
+ # I've being careful on providing names relative to the qrc file
+ # If that was not needed that code could be simplified a lot
+ def recursiveFiles(basepath, path) :
+ result = []
+ for item in os.listdir(os.path.join(basepath, path)) :
+ itemPath = os.path.join(path, item)
+ if os.path.isdir(os.path.join(basepath, itemPath)) :
+ result += recursiveFiles(basepath, itemPath)
+ else:
+ result.append(itemPath)
+ return result
+ contents = node.get_contents()
+ includes = qrcinclude_re.findall(contents)
+ qrcpath = os.path.dirname(node.path)
+ dirs = [included for included in includes if os.path.isdir(os.path.join(qrcpath,included))]
+ # dirs need to include files recursively
+ for dir in dirs :
+ includes.remove(dir)
+ includes+=recursiveFiles(qrcpath,dir)
+ return includes
+ qrcscanner = SCons.Scanner.Scanner(name = 'qrcfile',
+ function = scanResources,
+ argument = None,
+ skeys = ['.qrc'])
+ qrcbuilder = Builder(
+ action = SCons.Action.Action('$QT4_RCCCOM', cmdstr = '$QT4_RCCCOMSTR'),
+ source_scanner = qrcscanner,
+ src_suffix = '$QT4_QRCSUFFIX',
+ suffix = '$QT4_QRCCXXSUFFIX',
+ prefix = '$QT4_QRCCXXPREFIX',
+ single_source = True
+ )
+ env.Append( BUILDERS = { 'Qrc': qrcbuilder } )
+
+ # Interface builder
+ uic4builder = Builder(
+ action = SCons.Action.Action('$QT4_UICCOM', cmdstr = '$QT4_UICCOMSTR'),
+ src_suffix='$QT4_UISUFFIX',
+ suffix='$QT4_UICDECLSUFFIX',
+ prefix='$QT4_UICDECLPREFIX',
+ single_source = True
+ #TODO: Consider the uiscanner on new scons version
+ )
+ env['BUILDERS']['Uic4'] = uic4builder
+
+ # Metaobject builder
+ mocBld = Builder(action={}, prefix={}, suffix={})
+ for h in header_extensions:
+ act = SCons.Action.Action('$QT4_MOCFROMHCOM', cmdstr = '$QT4_MOCFROMHCOMSTR')
+ mocBld.add_action(h, act)
+ mocBld.prefix[h] = '$QT4_MOCHPREFIX'
+ mocBld.suffix[h] = '$QT4_MOCHSUFFIX'
+ for cxx in cxx_suffixes:
+ act = SCons.Action.Action('$QT4_MOCFROMCXXCOM', cmdstr = '$QT4_MOCFROMCXXCOMSTR')
+ mocBld.add_action(cxx, act)
+ mocBld.prefix[cxx] = '$QT4_MOCCXXPREFIX'
+ mocBld.suffix[cxx] = '$QT4_MOCCXXSUFFIX'
+ env['BUILDERS']['Moc4'] = mocBld
+
+ # er... no idea what that was for
+ static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+ static_obj.src_builder.append('Uic4')
+ shared_obj.src_builder.append('Uic4')
+
+ # We use the emitters of Program / StaticLibrary / SharedLibrary
+ # to scan for moc'able files
+ # We can't refer to the builders directly, we have to fetch them
+ # as Environment attributes because that sets them up to be called
+ # correctly later by our emitter.
+ env.AppendUnique(PROGEMITTER =[AutomocStatic],
+ SHLIBEMITTER=[AutomocShared],
+ LIBEMITTER =[AutomocStatic],
+ # Of course, we need to link against the qt libraries
+ LIBPATH=["$QT4_LIBPATH"],
+ LIBS=['$QT4_LIB'])
+
+ # TODO: Does dbusxml2cpp need an adapter
+ env.AddMethod(enable_modules, "EnableQt4Modules")
+
+def enable_modules(self, modules, debug=False, crosscompiling=False) :
+ import sys
+
+ validModules = [
+ 'QtCore',
+ 'QtGui',
+ 'QtOpenGL',
+ 'Qt3Support',
+ 'QtAssistant',
+ 'QtScript',
+ 'QtDBus',
+ 'QtSql',
+ # The next modules have not been tested yet so, please
+ # maybe they require additional work on non Linux platforms
+ 'QtNetwork',
+ 'QtSvg',
+ 'QtTest',
+ 'QtXml',
+ 'QtXmlPatterns',
+ 'QtUiTools',
+ 'QtDesigner',
+ 'QtDesignerComponents',
+ 'QtWebKit',
+ 'QtHelp',
+ 'QtScript',
+ ]
+ staticModules = [
+ 'QtUiTools',
+ ]
+ invalidModules=[]
+ for module in modules:
+ if module not in validModules :
+ invalidModules.append(module)
+ if invalidModules :
+ raise Exception("Modules %s are not Qt4 modules. Valid Qt4 modules are: %s"% (
+ str(invalidModules),str(validModules)))
+
+ moduleDefines = {
+ 'QtScript' : ['QT_SCRIPT_LIB'],
+ 'QtSvg' : ['QT_SVG_LIB'],
+ 'Qt3Support' : ['QT_QT3SUPPORT_LIB','QT3_SUPPORT'],
+ 'QtSql' : ['QT_SQL_LIB'],
+ 'QtXml' : ['QT_XML_LIB'],
+ 'QtOpenGL' : ['QT_OPENGL_LIB'],
+ 'QtGui' : ['QT_GUI_LIB'],
+ 'QtNetwork' : ['QT_NETWORK_LIB'],
+ 'QtCore' : ['QT_CORE_LIB'],
+ }
+ for module in modules :
+ try : self.AppendUnique(CPPDEFINES=moduleDefines[module])
+ except: pass
+ debugSuffix = ''
+
+ if sys.platform in ["linux2"] and not crosscompiling :
+ if debug : debugSuffix = '_debug'
+ self.AppendUnique(CPPPATH=[os.path.join("$QTDIR","include", "phonon")])
+ for module in modules :
+ self.AppendUnique(LIBS=[module+debugSuffix])
+ self.AppendUnique(LIBPATH=[os.path.join("$QTDIR","lib")])
+ self.AppendUnique(CPPPATH=[os.path.join("$QTDIR","include")])
+ self.AppendUnique(CPPPATH=[os.path.join("$QTDIR","include",module)])
+ self["QT4_MOCCPPPATH"] = self["CPPPATH"]
+ return
+
+ if sys.platform == "win32" or crosscompiling :
+ if crosscompiling:
+ transformedQtdir = transformToWinePath(self['QTDIR'])
+ self['QT4_MOC'] = "QTDIR=%s %s"%( transformedQtdir, self['QT4_MOC'])
+ self.AppendUnique(CPPPATH=[os.path.join("$QTDIR","include")])
+ try: modules.remove("QtDBus")
+ except: pass
+ if debug : debugSuffix = 'd'
+ if "QtAssistant" in modules:
+ self.AppendUnique(CPPPATH=[os.path.join("$QTDIR","include","QtAssistant")])
+ modules.remove("QtAssistant")
+ modules.append("QtAssistantClient")
+ # FIXME: Phonon Hack
+ self.AppendUnique(LIBS=['phonon4'+debugSuffix])
+ self.AppendUnique(LIBS=[lib+'4'+debugSuffix for lib in modules if lib not in staticModules])
+ self.PrependUnique(LIBS=[lib+debugSuffix for lib in modules if lib in staticModules])
+ if 'QtOpenGL' in modules:
+ self.AppendUnique(LIBS=['opengl32'])
+ self.AppendUnique(CPPPATH=[ '$QTDIR/include/'])
+ self.AppendUnique(CPPPATH=[ '$QTDIR/include/'+module for module in modules])
+ if crosscompiling :
+ self["QT4_MOCCPPPATH"] = [
+ path.replace('$QTDIR', transformedQtdir)
+ for path in self['CPPPATH'] ]
+ else :
+ self["QT4_MOCCPPPATH"] = self["CPPPATH"]
+ self.AppendUnique(LIBPATH=[os.path.join('$QTDIR','lib')])
+ return
+
+ if sys.platform=="darwin" :
+ if debug : debugSuffix = 'd'
+
+ if len(self["QTDIR"]) > 0 :
+ self.AppendUnique(LIBPATH=[os.path.join('$QTDIR','lib')])
+ self.AppendUnique(LINKFLAGS="-F$QTDIR/lib")
+ self.AppendUnique(CPPFLAGS="-F$QTDIR/lib")
+ self.AppendUnique(LINKFLAGS="-L$QTDIR/lib") #TODO clean!
+
+ # FIXME: Phonon Hack
+ self.Append(LINKFLAGS=['-framework', "phonon"])
+
+ for module in modules :
+ if module in staticModules :
+ self.AppendUnique(LIBS=[module+debugSuffix]) # TODO: Add the debug suffix
+ self.AppendUnique(LIBPATH=[os.path.join("$QTDIR","lib")])
+ else :
+ if len(self["QTDIR"]) > 0 :
+ self.Append(CPPFLAGS = ["-I" + os.path.join("$QTDIR", "lib", module + ".framework", "Versions", "4", "Headers")])
+ else :
+ self.Append(CPPFLAGS = ["-I" + os.path.join("/Library/Frameworks", module + ".framework", "Versions", "4", "Headers")])
+ self.Append(LINKFLAGS=['-framework', module])
+ if 'QtOpenGL' in modules:
+ self.AppendUnique(LINKFLAGS="-F/System/Library/Frameworks")
+ self.Append(LINKFLAGS=['-framework', 'AGL']) #TODO ughly kludge to avoid quotes
+ self.Append(LINKFLAGS=['-framework', 'OpenGL'])
+ self["QT4_MOCCPPPATH"] = self["CPPPATH"]
+
+def exists(env):
+ return _detect(env)
diff --git a/BuildTools/SCons/Version.py b/BuildTools/SCons/Version.py
new file mode 100644
index 0000000..02edcc9
--- /dev/null
+++ b/BuildTools/SCons/Version.py
@@ -0,0 +1,15 @@
+import subprocess, os, datetime
+
+def getGitBuildVersion() :
+ p = subprocess.Popen("git rev-parse HEAD", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=(os.name != "nt"))
+ gitVersion = p.stdout.read().rstrip()[0:7]
+ p.stdin.close()
+ return gitVersion if p.wait() == 0 else None
+
+def getBuildVersion(version = None) :
+ if version :
+ return version
+ gitVersion = getGitBuildVersion()
+ if gitVersion :
+ return gitVersion
+ return datetime.date.today().strftime("%Y%m%d")
diff --git a/BuildTools/package_debian.sh b/BuildTools/package_debian.sh
new file mode 100755
index 0000000..3d01243
--- /dev/null
+++ b/BuildTools/package_debian.sh
@@ -0,0 +1,10 @@
+VERSION=1.0
+PACKAGE=swift-$VERSION
+
+rm -rf $PACKAGE
+git archive --format=tar --prefix=$PACKAGE/ HEAD | tar x
+cp -r Swift/Packaging/Debian $PACKAGE/debian
+pushd $PACKAGE
+SWIFT_VERSION=$VERSION dpkg-buildpackage -rfakeroot
+popd
+rm -rf $PACKAGE