diff options
Diffstat (limited to 'BuildTools/SCons')
-rw-r--r-- | BuildTools/SCons/SConstruct | 399 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/AppBundle.py | 52 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/BuildVersion.py | 17 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/Nib.py | 12 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/Test.py | 13 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/WindowsBundle.py | 17 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/WriteVal.py | 14 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/nsis.py | 37 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/qt4.py | 517 | ||||
-rw-r--r-- | BuildTools/SCons/Version.py | 15 |
10 files changed, 1093 insertions, 0 deletions
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") |