diff options
Diffstat (limited to 'BuildTools/SCons')
-rw-r--r-- | BuildTools/SCons/SConscript.boot | 17 | ||||
-rw-r--r-- | BuildTools/SCons/SConstruct | 60 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/AppBundle.py | 4 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/InstallWithSymLinks.py | 8 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/WindowsBundle.py | 26 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/qt4.py | 51 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/textfile.py | 175 | ||||
-rw-r--r-- | BuildTools/SCons/Tools/wix.py | 8 | ||||
-rw-r--r-- | BuildTools/SCons/Version.py | 253 |
9 files changed, 325 insertions, 277 deletions
diff --git a/BuildTools/SCons/SConscript.boot b/BuildTools/SCons/SConscript.boot index fc943f7..7b29c06 100644 --- a/BuildTools/SCons/SConscript.boot +++ b/BuildTools/SCons/SConscript.boot @@ -37,7 +37,8 @@ if os.name == "mac" or (os.name == "posix" and os.uname()[0] == "Darwin"): vars.Add(BoolVariable("mac105", "Link against the 10.5 frameworks", "no")) vars.Add(BoolVariable("mac106", "Link against the 10.6 frameworks", "no")) if os.name == "nt" : - vars.Add(PathVariable("vcredist", "MSVC redistributable dir", None, PathVariable.PathAccept)) + vars.Add(PathVariable("vcredist", "MSVC redistributable path", None, PathVariable.PathAccept)) + vars.Add(PathVariable("vcredistdir", "MSVC redistributable dir", None, PathVariable.PathAccept)) if os.name == "nt" : vars.Add(PathVariable("wix_bindir", "Path to WiX binaries", "", PathVariable.PathAccept)) if os.name == "nt" : @@ -53,6 +54,7 @@ vars.Add(PathVariable("boost_includedir", "Boost headers location", None, PathVa vars.Add(PathVariable("boost_libdir", "Boost library location", None, PathVariable.PathAccept)) vars.Add(BoolVariable("boost_bundled_enable", "Allow use of bundled Boost as last resort", "true")) vars.Add(BoolVariable("boost_force_bundled", "Force use of bundled Boost.", False)) +vars.Add(BoolVariable("allow_boost_1_64", "Allow use of Boost 1.64", False)) vars.Add(PathVariable("zlib_includedir", "Zlib headers location", None, PathVariable.PathAccept)) vars.Add(PathVariable("zlib_libdir", "Zlib library location", None, PathVariable.PathAccept)) vars.Add(PathVariable("zlib_libfile", "Zlib library file (full path to file)", None, PathVariable.PathAccept)) @@ -106,10 +108,12 @@ vars.Add(BoolVariable("enable_variants", "Build in a separate dir under build/, vars.Add(BoolVariable("experimental_ft", "Build experimental file transfer", "yes")) vars.Add(BoolVariable("experimental", "Build experimental features", "no")) vars.Add(BoolVariable("set_iterator_debug_level", "Set _ITERATOR_DEBUG_LEVEL=0", "yes")) +vars.Add(EnumVariable("msvc_runtime", "Choose MSVC runtime library", "MD", ["MT", "MTd", "MD", "MDd"])) vars.Add(BoolVariable("unbound", "Build bundled ldns and unbound. Use them for DNS lookup.", "no")) vars.Add(BoolVariable("check_headers", "Independently build compilation units for all Swiften headers for detecting missing dependencies.", "no")) vars.Add("win_target_arch", "Target architecture for Windows builds. x86 for 32-bit (default) or x86_64 for 64-bit.", "x86") vars.Add(BoolVariable("install_git_hooks", "Install git hooks", "true")) +vars.Add(BoolVariable("help2man", "Run help2man to geneate man pages", "false")) # Code Signing Options vars.Add("codesign_identity", "macOS code signing identity to be passed to codesign when building the distribution package. Must match the Commen Name of the Subject of the code signing certificate.", "") @@ -128,6 +132,7 @@ env_ENV = { 'PATH' : os.environ['PATH'], 'LD_LIBRARY_PATH' : os.environ.get("LD_LIBRARY_PATH", ""), 'TERM' : os.environ.get("TERM", ""), + 'SDKROOT' : os.environ.get("SDKROOT", ""), } if "MSVC_VERSION" in ARGUMENTS : @@ -273,11 +278,13 @@ if env["debug"] : if env["set_iterator_debug_level"] : env.Append(CPPDEFINES = ["_ITERATOR_DEBUG_LEVEL=0"]) env.Append(LINKFLAGS = ["/OPT:NOREF"]) - env.Append(CCFLAGS = ["/MD"]) else : env.Append(CCFLAGS = ["-g"]) -elif env["PLATFORM"] == "win32" : - env.Append(CCFLAGS = ["/MD"]) + +if env["PLATFORM"] == "win32" : + env.AppendUnique(CCFLAGS = ["/{}".format(env.get("msvc_runtime"))]) + # debug builds against debug MSVC runtime can cause some more sections in the object file + env.AppendUnique(CCFLAGS = ["/bigobj"]) if env.get("universal", 0) : assert(env["PLATFORM"] == "darwin") @@ -426,6 +433,8 @@ for path in ["SWIFT_INSTALLDIR", "SWIFTEN_INSTALLDIR", "SLUIFT_INSTALLDIR"] : env[path] = Dir(ARGUMENTS[path]).abspath else : env[path] = Dir("#/" + ARGUMENTS[path]).abspath +if ARGUMENTS.get("SWIFTEN_LIBDIR", "") : + env["SWIFTEN_LIBDIR"] = ARGUMENTS["SWIFTEN_LIBDIR"] ################################################################################ diff --git a/BuildTools/SCons/SConstruct b/BuildTools/SCons/SConstruct index bef388a..78f388b 100644 --- a/BuildTools/SCons/SConstruct +++ b/BuildTools/SCons/SConstruct @@ -7,9 +7,9 @@ root = Dir("../..").abspath # 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) +def SConscript(*args, **kwargs) : + if not kwargs.get("test_only", False) or env["TEST"] : + return oldSConscript(*args, **kwargs) env.SConscript = SConscript ################################################################################ @@ -142,11 +142,11 @@ conf = Configure(conf_env, custom_tests = { }) if not conf.CheckCXX() or not conf.CheckCC() : - print "Error: You need a working compiler" + print("Error: You need a working compiler") Exit(1) if not conf.CheckCpp11Support() : - print "Error: You need a compiler with support for the C++11 standard" + print("Error: You need a compiler with support for the C++11 standard") Exit(1) @@ -170,7 +170,7 @@ if (not zlib_okay) and conf.CheckLib("z") : if zlib_okay : env["ZLIB_FLAGS"] = zlib_flags elif not env.get("zlib_bundled_enable", True) : - print "Error: Zlib not found and zlib_bundled_enable is false" + print("Error: Zlib not found and zlib_bundled_enable is false") Exit(1) else : env["ZLIB_BUNDLED"] = True @@ -238,10 +238,16 @@ if not env.get("boost_force_bundled") and allLibsPresent : # FIXME: Remove this workaround when UUID is available in most distros env["BOOST_BUNDLED_UUID_ONLY"] = True elif not env.get("boost_bundled_enable", True) : - print "Error: Boost not found and boost_bundled_enable is false" + print("Error: Boost not found and boost_bundled_enable is false") Exit(1) else : env["BOOST_BUNDLED"] = True +boost_version = GetVersion(conf, "BOOST_VERSION", "boost/version.hpp") +if boost_version == 106400 : + #Version 1.64 has some issues with the serialization of boost::optional, see https://svn.boost.org/trac10/ticket/13050 + env["BOOST_1_64_DETECTED"] = True +else: + env["BOOST_1_64_DETECTED"] = False conf.Finish() @@ -367,7 +373,7 @@ if env.get("try_expat", True) and not env.get("HAVE_LIBXML",0) : # Bundled expat bundledExpat = False if not env.get("HAVE_EXPAT", 0) and not env.get("HAVE_LIBXML", 0) : - print "Expat or LibXML not found. Using bundled Expat" + print("Expat or LibXML not found. Using bundled Expat") SConscript("#/3rdParty/Expat/SConscript") env["HAVE_EXPAT"] = 1 env["EXPAT_BUNDLED"] = True @@ -418,10 +424,10 @@ if not env.get("HAVE_ICU", False) and not env.get("HAVE_LIBIDN", False) : env["HAVE_LIBIDN"] = 1 env["LIBIDN_BUNDLED"] = 1 elif env.get("need_idn", True): - print "Error: ICU and LIBIDN not found, and libidn_bundled_enable is false" + print("Error: ICU and LIBIDN not found, and libidn_bundled_enable is false") Exit(1) else: - print "Proceeding without an IDN library because need_idn was false. This will break all internal binaries" + print("Proceeding without an IDN library because need_idn was false. This will break all internal binaries") # Unbound if env["unbound"] : @@ -508,7 +514,7 @@ if not env.get("lua_force_bundled", False) and conf.CheckLibWithHeader(env["lua_ if lua_version > 0 : env["LUA_FLAGS"]["LUA_VERSION"] = str(lua_version // 100) + "." + str(lua_version % 100) else : - print "Warning: Unable to determine Lua version. Not installing Lua libraries." + print("Warning: Unable to determine Lua version. Not installing Lua libraries.") env["LUA_FLAGS"].update(lua_flags) else : env["LUA_BUNDLED"] = 1 @@ -664,7 +670,7 @@ try : except SCons.Errors.StopError: env["HAVE_QT"] = False except Exception as e: - print "Info: %s" % str(e) + print("Info: %s" % str(e)) env["HAVE_QT"] = False ################################################################################ @@ -686,7 +692,7 @@ try: if not env.GetOption("clean") and env.get("install_git_hooks", True) : env.Install("#/.git/hooks", Glob("#/BuildTools/Git/Hooks/*")) except TypeError: - print "You seem to be using Swift in a Git submodule. Not installing hooks." + print("You seem to be using Swift in a Git submodule. Not installing hooks.") ################################################################################ @@ -701,6 +707,8 @@ if ARGUMENTS.get("replace_pragma_once", False) : return path[i+1:] for actual_root, dirs, files in os.walk(root) : + dirs.sort() + files.sort() if "3rdParty" in actual_root : continue for file in files : @@ -727,14 +735,14 @@ if ARGUMENTS.get("dump_trace", False) : # Modules modules = [] if os.path.isdir(Dir("#/3rdParty").abspath) : - for dir in os.listdir(Dir("#/3rdParty").abspath) : + for dir in sorted(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) -for dir in os.listdir(Dir("#").abspath) : +for dir in sorted(os.listdir(Dir("#").abspath)) : full_dir = os.path.join(Dir("#").abspath, dir) if not os.path.isdir(full_dir) : continue @@ -750,7 +758,7 @@ modules.append("QA") env["PROJECTS"] = [m for m in modules if m not in ["Documentation", "QA", "SwifTools"] and not m.startswith("3rdParty")] for stage in ["flags", "build"] : env["SCONS_STAGE"] = stage - SConscript(dirs = map(lambda x : root + "/" + x, modules)) + SConscript(dirs = list(map(lambda x : root + "/" + x, modules))) # SLOCCount if ARGUMENTS.get("sloccount", False) : @@ -762,9 +770,9 @@ if ARGUMENTS.get("sloccount", False) : # Print summary ################################################################################ -print -print " Build Configuration" -print " -------------------" +print("") +print(" Build Configuration") +print(" -------------------") parsers = [] if env.get("HAVE_LIBXML", 0): @@ -773,14 +781,14 @@ if env.get("HAVE_EXPAT", 0): parsers.append("Expat") if env.get("EXPAT_BUNDLED", False) : parsers.append("(Bundled)") -print " Projects: " + ' '.join(env["PROJECTS"]) -print "" -print " XML Parsers: " + ' '.join(parsers) +print(" Projects: " + ' '.join(env["PROJECTS"])) +print("") +print(" XML Parsers: " + ' '.join(parsers)) -print " TLS Support: " + (env.get("HAVE_OPENSSL",0) and "OpenSSL" or env.get("HAVE_SECURETRANSPORT",0) and "Secure Transport" or env.get("HAVE_SCHANNEL", 0) and "Schannel" or "Disabled") -print " DNSSD Support: " + (env.get("HAVE_BONJOUR") and "Bonjour" or (env.get("HAVE_AVAHI") and "Avahi" or "Disabled")) -print +print(" TLS Support: " + (env.get("HAVE_OPENSSL",0) and "OpenSSL" or env.get("HAVE_SECURETRANSPORT",0) and "Secure Transport" or env.get("HAVE_SCHANNEL", 0) and "Schannel" or "Disabled")) +print(" DNSSD Support: " + (env.get("HAVE_BONJOUR") and "Bonjour" or (env.get("HAVE_AVAHI") and "Avahi" or "Disabled"))) +print("") if not GetOption("help") and not env.get("HAVE_OPENSSL", 0) and not env.get("HAVE_SCHANNEL", 0) and not env.get("HAVE_SECURETRANSPORT", 0): - print "Error: A working TLS backend is required. Please check the documentation for more information." + print("Error: A working TLS backend is required. Please check the documentation for more information.") Exit(1) diff --git a/BuildTools/SCons/Tools/AppBundle.py b/BuildTools/SCons/Tools/AppBundle.py index 337e83f..31cfef1 100644 --- a/BuildTools/SCons/Tools/AppBundle.py +++ b/BuildTools/SCons/Tools/AppBundle.py @@ -34,7 +34,7 @@ def generate(env) : """ for key, value in infoDict.items() : plist += "<key>" + key + "</key>\n" - plist += "<string>" + value.encode("utf-8") + "</string>\n" + plist += "<string>" + value + "</string>\n" if handlesXMPPURIs : plist += """<key>CFBundleURLTypes</key> <array> @@ -50,7 +50,7 @@ def generate(env) : if sparklePublicDSAKey : plist += "<key>SUPublicDSAKeyFile</key>" - plist += "<string>" + sparklePublicDSAKey.name.encode("utf-8") + "</string>" + plist += "<string>" + sparklePublicDSAKey.name + "</string>" env.Install(resourcesDir, sparklePublicDSAKey) plist += """</dict> </plist> diff --git a/BuildTools/SCons/Tools/InstallWithSymLinks.py b/BuildTools/SCons/Tools/InstallWithSymLinks.py index 23d12ed..4955192 100644 --- a/BuildTools/SCons/Tools/InstallWithSymLinks.py +++ b/BuildTools/SCons/Tools/InstallWithSymLinks.py @@ -74,21 +74,21 @@ def scons_copytree(src, dst, symlinks=False): else: shutil.copy2(srcname, dstname) # XXX What about devices, sockets etc.? - except (IOError, os.error), why: + except (IOError, os.error) as why: errors.append((srcname, dstname, str(why))) # catch the CopytreeError from the recursive copytree so that we can # continue with other files - except CopytreeError, err: + except CopytreeError as err: errors.extend(err.args[0]) try: shutil.copystat(src, dst) except WindowsError: # can't copy file access times on Windows pass - except OSError, why: + except OSError as why: errors.extend((src, dst, str(why))) if errors: - raise CopytreeError, errors + raise CopytreeError(errors) def symlinkBuilderImpl(target, source, env): diff --git a/BuildTools/SCons/Tools/WindowsBundle.py b/BuildTools/SCons/Tools/WindowsBundle.py index 20d41ff..9781deb 100644 --- a/BuildTools/SCons/Tools/WindowsBundle.py +++ b/BuildTools/SCons/Tools/WindowsBundle.py @@ -33,9 +33,13 @@ def generate(env) : mappings = [] - p = re.compile(ur'"([^\"]*)" "([^\"]*)"') + regex = re.compile(r'"([^\"]*)" "([^\"]*)"') + + if SCons.Util.PY3: + matches = re.findall(regex, stdout.decode('utf8')) + else: + matches = re.findall(regex, stdout) - matches = re.findall(p, stdout) for match in matches: mappings.append(match) return mappings @@ -83,8 +87,21 @@ def generate(env) : qtmappings = captureWinDeployQtMapping() assert(qtmappings) + # Add QtWebKit dependencies. + # This is needed as QtWebKit since 5.6 is developed and released seperately + # of Qt and windeployqt does not know about its dependencies anymore. + for map_from, map_to in qtmappings: + if map_to == "Qt5WebKit.dll": + # hidden Qt5WebKit dependencies + hidden_dependencies = ["libxml2.dll", "libxslt.dll"] + for dependency in hidden_dependencies: + dependency_from_path = os.path.join(env["QTDIR"], "bin", dependency) + if os.path.isfile(dependency_from_path): + qtmappings.append((dependency_from_path, dependency)) + break + # handle core DLLs - qt_corelib_regex = re.compile(ur".*bin.*\\(.*)\.dll") + qt_corelib_regex = re.compile(r".*bin.*\\(.*)\.dll") for qtlib in qtlibs: if qtlib.startswith("Qt5"): @@ -98,7 +115,7 @@ def generate(env) : all_files += env.Install(bundle, src_path) # handle plugins - qt_plugin_regex = re.compile(ur".*plugins.*\\(.*)\\(.*)\.dll") + qt_plugin_regex = re.compile(r".*plugins.*\\(.*)\\(.*)\.dll") for (src_path, target_path) in qtmappings: if qt_plugin_regex.match(src_path): plugin_folder, filename = qt_plugin_regex.match(src_path).groups() @@ -119,4 +136,3 @@ def generate(env) : def exists(env) : return env["PLATFORM"] == "win32" - diff --git a/BuildTools/SCons/Tools/qt4.py b/BuildTools/SCons/Tools/qt4.py index d5c14e2..372b261 100644 --- a/BuildTools/SCons/Tools/qt4.py +++ b/BuildTools/SCons/Tools/qt4.py @@ -37,6 +37,7 @@ __revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/T import os.path import re import subprocess +from string import Template import SCons.Action import SCons.Builder @@ -129,7 +130,9 @@ class _Automoc: # The following is kind of hacky to get builders working properly (FIXME) objBuilderEnv = objBuilder.env - objBuilder.env = env + objBuilder.env = env.Clone() + if os.path.basename(objBuilder.env ["CXX"]).startswith(("gcc", "clang")): + objBuilder.env.Append(CXXFLAGS = "-w") mocBuilderEnv = env.Moc4.env env.Moc4.env = env @@ -137,23 +140,23 @@ class _Automoc: 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) + if isinstance(obj,str): # 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) + 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) + 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() + cpp_contents = str(cpp.get_contents()) except: continue # may be an still not generated source h=None for h_ext in header_extensions: @@ -163,12 +166,12 @@ class _Automoc: 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)) + print("scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp))) #h_contents = comment.sub('', h.get_contents()) - h_contents = h.get_contents() + h_contents = str(h.get_contents()) break if not h and debug: - print "scons: qt: no header for '%s'." % (str(cpp)) + 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) @@ -176,14 +179,14 @@ class _Automoc: 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)) + 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)) + 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 @@ -344,7 +347,7 @@ def generate(env): else: result.append(itemPath) return result - contents = node.get_contents() + contents = str(node.get_contents()) includes = [included[1] for included in 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))] @@ -368,8 +371,30 @@ def generate(env): env.Append( BUILDERS = { 'Qrc': qrcbuilder } ) # Interface builder + def addDisableWarningsPragmaToFile(target, source, env): + assert( len(target) == 1 ) + assert( len(source) == 1 ) + srcf = str(source[0]) + dstf = str(target[0]) + with open(dstf, 'r+') as uiHeader: + data=uiHeader.read() + + template = Template( +"""#pragma once +#pragma warning(push, 0) +#pragma GCC system_header +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wall" +$uiheadertext +#pragma clang diagnostic pop +#pragma warning(pop) +""") + uiHeader.seek(0) + uiHeader.write(template.substitute(uiheadertext=data)) + uiHeader.truncate() + uic4builder = Builder( - action = SCons.Action.Action('$QT4_UICCOM', cmdstr = '$QT4_UICCOMSTR'), + action = [SCons.Action.Action('$QT4_UICCOM', cmdstr = '$QT4_UICCOMSTR'), SCons.Action.Action(addDisableWarningsPragmaToFile, None)], src_suffix='$QT4_UISUFFIX', suffix='$QT4_UICDECLSUFFIX', prefix='$QT4_UICDECLPREFIX', diff --git a/BuildTools/SCons/Tools/textfile.py b/BuildTools/SCons/Tools/textfile.py deleted file mode 100644 index 89f8963..0000000 --- a/BuildTools/SCons/Tools/textfile.py +++ /dev/null @@ -1,175 +0,0 @@ -# -*- python -*- -# -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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. -# - -__doc__ = """ -Textfile/Substfile builder for SCons. - - Create file 'target' which typically is a textfile. The 'source' - may be any combination of strings, Nodes, or lists of same. A - 'linesep' will be put between any part written and defaults to - os.linesep. - - The only difference between the Textfile builder and the Substfile - builder is that strings are converted to Value() nodes for the - former and File() nodes for the latter. To insert files in the - former or strings in the latter, wrap them in a File() or Value(), - respectively. - - The values of SUBST_DICT first have any construction variables - expanded (its keys are not expanded). If a value of SUBST_DICT is - a python callable function, it is called and the result is expanded - as the value. Values are substituted in a "random" order; if any - substitution could be further expanded by another subsitition, it - is unpredictible whether the expansion will occur. -""" - -__revision__ = "src/engine/SCons/Tool/textfile.py 5357 2011/09/09 21:31:03 bdeegan" - -import SCons - -import os -import re - -from SCons.Node import Node -from SCons.Node.Python import Value -from SCons.Util import is_String, is_Sequence, is_Dict - -def _do_subst(node, subs): - """ - Fetch the node contents and replace all instances of the keys with - their values. For example, if subs is - {'%VERSION%': '1.2345', '%BASE%': 'MyProg', '%prefix%': '/bin'}, - then all instances of %VERSION% in the file will be replaced with - 1.2345 and so forth. - """ - contents = node.get_text_contents() - if not subs: return contents - for (k,v) in subs: - contents = re.sub(k, v, contents) - return contents - -def _action(target, source, env): - # prepare the line separator - linesep = env['LINESEPARATOR'] - if linesep is None: - linesep = os.linesep - elif is_String(linesep): - pass - elif isinstance(linesep, Value): - linesep = linesep.get_text_contents() - else: - raise SCons.Errors.UserError( - 'unexpected type/class for LINESEPARATOR: %s' - % repr(linesep), None) - - # create a dictionary to use for the substitutions - if 'SUBST_DICT' not in env: - subs = None # no substitutions - else: - d = env['SUBST_DICT'] - if is_Dict(d): - d = list(d.items()) - elif is_Sequence(d): - pass - else: - raise SCons.Errors.UserError('SUBST_DICT must be dict or sequence') - subs = [] - for (k,v) in d: - if callable(v): - v = v() - if is_String(v): - v = env.subst(v) - else: - v = str(v) - subs.append((k,v)) - - # write the file - try: - fd = open(target[0].get_path(), "wb") - except (OSError,IOError), e: - raise SCons.Errors.UserError("Can't write target file %s" % target[0]) - # separate lines by 'linesep' only if linesep is not empty - lsep = None - for s in source: - if lsep: fd.write(lsep) - fd.write(_do_subst(s, subs)) - lsep = linesep - fd.close() - -def _strfunc(target, source, env): - return "Creating '%s'" % target[0] - -def _convert_list_R(newlist, sources): - for elem in sources: - if is_Sequence(elem): - _convert_list_R(newlist, elem) - elif isinstance(elem, Node): - newlist.append(elem) - else: - newlist.append(Value(elem)) -def _convert_list(target, source, env): - if len(target) != 1: - raise SCons.Errors.UserError("Only one target file allowed") - newlist = [] - _convert_list_R(newlist, source) - return target, newlist - -_common_varlist = ['SUBST_DICT', 'LINESEPARATOR'] - -_text_varlist = _common_varlist + ['TEXTFILEPREFIX', 'TEXTFILESUFFIX'] -_text_builder = SCons.Builder.Builder( - action = SCons.Action.Action(_action, _strfunc, varlist = _text_varlist), - source_factory = Value, - emitter = _convert_list, - prefix = '$TEXTFILEPREFIX', - suffix = '$TEXTFILESUFFIX', - ) - -_subst_varlist = _common_varlist + ['SUBSTFILEPREFIX', 'TEXTFILESUFFIX'] -_subst_builder = SCons.Builder.Builder( - action = SCons.Action.Action(_action, _strfunc, varlist = _subst_varlist), - source_factory = SCons.Node.FS.File, - emitter = _convert_list, - prefix = '$SUBSTFILEPREFIX', - suffix = '$SUBSTFILESUFFIX', - src_suffix = ['.in'], - ) - -def generate(env): - env['LINESEPARATOR'] = os.linesep - env['BUILDERS']['MyTextfile'] = _text_builder - env['TEXTFILEPREFIX'] = '' - env['TEXTFILESUFFIX'] = '.txt' - env['BUILDERS']['MySubstfile'] = _subst_builder - env['SUBSTFILEPREFIX'] = '' - env['SUBSTFILESUFFIX'] = '' - -def exists(env): - return 1 - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/BuildTools/SCons/Tools/wix.py b/BuildTools/SCons/Tools/wix.py index 907b6d9..986ea23 100644 --- a/BuildTools/SCons/Tools/wix.py +++ b/BuildTools/SCons/Tools/wix.py @@ -15,7 +15,10 @@ def generate(env) : def WiX_IncludeScanner(source, env, path, arg): wixIncludeRegexp = re.compile(r'^\s*\<\?include (\S+.wxs)\s*\?\>\S*', re.M) - contents = source.get_contents() + if SCons.Util.PY3: + contents = source.get_contents().decode("utf8") + else: + contents = source.get_contents() includes = wixIncludeRegexp.findall(contents) return [ "" + include for include in includes ] @@ -38,7 +41,7 @@ def generate(env) : light_builder = SCons.Builder.Builder( - action = '"$WIX_LIGHT" $WIX_LIGHT_OPTIONS -b "$WIX_SOURCE_OBJECT_DIR" ${SOURCES} -o ${TARGET}', + action = '"$WIX_LIGHT" $WIX_LIGHT_OPTIONS -b "$WIX_SOURCE_OBJECT_DIR" ${SOURCES} -loc Swift\\Packaging\\WiX\\Swift_en-us.wxl -o ${TARGET}', src_suffix = '.wixobj', src_builder = candle_builder) @@ -48,4 +51,3 @@ def generate(env) : def exists(env) : return True - diff --git a/BuildTools/SCons/Version.py b/BuildTools/SCons/Version.py index d34c2a7..23cd850 100644 --- a/BuildTools/SCons/Version.py +++ b/BuildTools/SCons/Version.py @@ -1,26 +1,34 @@ -import subprocess, os, datetime, re, os.path - -def getGitBuildVersion(root, project) : - tag = git("describe --tags --exact --match \"" + project + "-*\"", root) - if tag : - return tag.rstrip()[len(project)+1:] - tag = git("describe --tags --match \"" + project + "-*\"", root) - if tag : - m = re.match(project + "-(.*)-(.*)-(.*)", tag) - if m : - return m.group(1) + "-dev" + m.group(2) +from __future__ import print_function +import subprocess, os, datetime, re, os.path, sys, unittest + +def gitDescribeToVersion(tag, tagPrefix): + m = re.match(r'^' + tagPrefix + r'-(.+?)(?:-(.+?)-(.+?))?$', tag) + if not m: + return None + result = m.group(1) + if m.group(2): + result += "-dev" + m.group(2) + return result + +def getGitBuildVersion(root, tagPrefix) : + tag = git("describe --tags --match \"" + tagPrefix + "-*\"", root) + if tag: + return gitDescribeToVersion(tag, tagPrefix) return None -def git(cmd, root) : +def git(cmd, root): full_cmd = "git " + cmd + # Would've used with .. as p, but that's not supported by Python 2.7 p = subprocess.Popen(full_cmd, cwd=root, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=(os.name != "nt")) gitVersion = p.stdout.read() - # error = p.stderr.read() - # if error: - # print "Git error: " + error - p.stdin.close() - if p.wait() == 0 : - return gitVersion + try: + p.stdin.close() + p.stdout.close() + p.stderr.close() + except: + pass + if p.wait() == 0: + return bytes(gitVersion).decode('utf-8') return None def getBuildVersion(root, project) : @@ -37,32 +45,187 @@ def getBuildVersion(root, project) : return datetime.date.today().strftime("%Y%m%d") -def convertToWindowsVersion(version) : - version_match = re.match("(\d+)\.(\d+)(.*)", version) - major = version_match and int(version_match.group(1)) or 0 - minor = version_match and int(version_match.group(2)) or 0 - if version_match and len(version_match.group(3)) == 0 : - patch = 60000 - else : - match = re.match("^beta(\d+)(.*)", version_match.group(3)) - build_string = "" - if match : - patch = 1000*int(match.group(1)) - build_string = match.group(2) - else : - rc_match = re.match("^rc(\d+)(.*)", version_match.group(3)) - if rc_match : - patch = 10000*int(rc_match.group(1)) - build_string = rc_match.group(2) - else : - patch = 0 - alpha_match = re.match("^alpha(.*)", version_match.group(3)) - if alpha_match : - build_string = alpha_match.group(1) - - if len(build_string) > 0 : - build_match = re.match("^-dev(\d+)", build_string) - if build_match : - patch += int(build_match.group(1)) +# The following conversion allows us to use version tags the format: +# major.0 +# major.0.(0 to 9) +# +# Either from above followed by: +# alpha(0 to 4) +# beta(0 to 6) +# rc(1 to 11) +# +# Followed by an optional -dev(1-65535) for off tag builds. +def convertToWindowsVersion(version): + match = re.match(r"(?P<major>\d+)\.(?P<minor>\d+)\.?(?P<patch>\d+)?(?:(?P<stage>rc|beta|alpha)(?P<stage_number>\d+)?)?(?:-dev(?P<dev>\d+))?", version) + assert(match) + major, minor, patch = (0, 0, 0) + + groups = match.groupdict() + assert(groups['major']) + major = int(groups['major']) + + if groups['minor']: + assert(int(groups['minor']) == 0) + + if groups['patch']: + assert(0 <= int(groups['patch']) <= 9) + minor = int(groups['patch']) * 25 + + stage = groups["stage"] + if stage: + stageNumber = groups['stage_number'] + if not stageNumber or stageNumber == "": + stageNumber = 0 + else: + stageNumber = int(stageNumber) + + if stage == "alpha": + assert(0 <= stageNumber <= 4) + minor = 1 + stageNumber + elif stage == "beta": + assert(0 <= stageNumber <= 6) + minor = 6 + stageNumber + elif stage == "rc": + assert(1 <= stageNumber <= 11) + minor = 12 + stageNumber + else: + assert(False) + else: + minor = minor + 24 + if groups['dev']: + patch = 1 + int(groups['dev']) + + # The following constraints are set by Windows Installer framework + assert(0 <= major <= 255) + assert(0 <= minor <= 255) + assert(0 <= patch <= 65535) return (major, minor, patch) + +# Test Windows version mapping scheme +class TestCases(unittest.TestCase): + def testWindowsVersionsAreDescending(self): + versionStringsWithOldVersions = [ + ("5.0rc11", None), + ("5.0rc1", None), + ("5.0beta6", None), + ("5.0alpha4", None), + ("5.0alpha2", None), + ("5.0alpha", None), + ("4.0.9", None), + ("4.0.1", None), + ("4.0", (4, 0, 60000)), + ("4.0rc6", (4, 0, 60000)), + ("4.0rc5", (4, 0, 50000)), + ("4.0rc4", (4, 0, 40000)), + ("4.0rc3", (4, 0, 30000)), + ('4.0rc2-dev39', (4, 0, 20039)), + ('4.0rc2-dev34', (4, 0, 20034)), + ('4.0rc2-dev33', (4, 0, 20033)), + ('4.0rc2-dev31', (4, 0, 20031)), + ('4.0rc2-dev30', (4, 0, 20030)), + ('4.0rc2-dev29', (4, 0, 20029)), + ('4.0rc2-dev27', (4, 0, 20027)), + ('4.0rc2', (4, 0, 20000)), + ('4.0rc1', (4, 0, 10000)), + ('4.0beta2-dev203', (4, 0, 2203)), + ('4.0beta2-dev195', (4, 0, 2195)), + ('4.0beta2-dev177', (4, 0, 2177)), + ('4.0beta2-dev171', (4, 0, 2171)), + ('4.0beta2-dev154', (4, 0, 2154)), + ('4.0beta2-dev150', (4, 0, 2150)), + ('4.0beta2-dev142', (4, 0, 2142)), + ('4.0beta2-dev140', (4, 0, 2140)), + ('4.0beta2-dev133', (4, 0, 2133)), + ('4.0beta2-dev118', (4, 0, 2118)), + ('4.0beta2-dev112', (4, 0, 2112)), + ('4.0beta2-dev93', (4, 0, 2093)), + ('4.0beta2-dev80', (4, 0, 2080)), + ('4.0beta2-dev72', (4, 0, 2072)), + ('4.0beta2-dev57', (4, 0, 2057)), + ('4.0beta2-dev44', (4, 0, 2044)), + ('4.0beta2-dev38', (4, 0, 2038)), + ('4.0beta2-dev29', (4, 0, 2029)), + ('4.0beta2-dev15', (4, 0, 2015)), + ('4.0beta2', (4, 0, 2000)), + ('4.0beta1', (4, 0, 1000)), + ('4.0alpha-dev80', (4, 0, 80)), + ('4.0alpha-dev50', (4, 0, 50)), + ('4.0alpha-dev43', (4, 0, 43)), + ('4.0alpha-dev21', (4, 0, 21)), + ('3.0', (3, 0, 60000)), + ('3.0rc3', (3, 0, 30000)), + ('3.0rc2', (3, 0, 20000)), + ('3.0rc1', (3, 0, 10000)), + ('3.0beta2-dev124', (3, 0, 2124)), + ('3.0beta2-dev81', (3, 0, 2081)), + ('3.0beta2-dev50', (3, 0, 2050)), + ('3.0beta2-dev44', (3, 0, 2044)), + ('3.0beta2-dev40', (3, 0, 2040)), + ('3.0beta2-dev26', (3, 0, 2026)), + ('3.0beta2', (3, 0, 2000)), + ('3.0beta1', (3, 0, 1000)), + ('3.0alpha-dev529', (3, 0, 529)), + ('3.0alpha-dev528', (3, 0, 528)), + ('3.0alpha-dev526', (3, 0, 526)), + ('3.0alpha-dev524', (3, 0, 524)), + ('3.0alpha-dev515', (3, 0, 515)), + ] + prevParsed = None + prevOldVersion = None + for string, oldVersion in versionStringsWithOldVersions: + parsed = convertToWindowsVersion(string) + if prevOldVersion and oldVersion: + self.assertTrue(oldVersion <= prevOldVersion, "Old version %r must come before %r" % (oldVersion, prevOldVersion)) + if prevParsed: + self.assertTrue(parsed < prevParsed, "%s => %r must be smaller than %s => %r" % (string, parsed, prevString, prevParsed)) + prevString = string + prevParsed = parsed + prevOldVersion = oldVersion + + def testThatBetaIsHigherThanAlpha(self): + self.assertTrue(convertToWindowsVersion("3.0beta0") > convertToWindowsVersion("3.0alpha0")) + self.assertTrue(convertToWindowsVersion("3.0beta6") > convertToWindowsVersion("3.0alpha1")) + self.assertTrue(convertToWindowsVersion("3.0beta6") > convertToWindowsVersion("3.0alpha4")) + + def testThatRcIsHigherThanAlphaAndBeta(self): + self.assertTrue(convertToWindowsVersion("3.0rc11") > convertToWindowsVersion("3.0alpha0")) + self.assertTrue(convertToWindowsVersion("3.0rc11") > convertToWindowsVersion("3.0alpha4")) + self.assertTrue(convertToWindowsVersion("3.0rc1") > convertToWindowsVersion("3.0alpha0")) + self.assertTrue(convertToWindowsVersion("3.0rc1") > convertToWindowsVersion("3.0alpha4")) + self.assertTrue(convertToWindowsVersion("3.0rc11") > convertToWindowsVersion("3.0beta0")) + self.assertTrue(convertToWindowsVersion("3.0rc11") > convertToWindowsVersion("3.0beta6")) + self.assertTrue(convertToWindowsVersion("3.0rc1") > convertToWindowsVersion("3.0beta0")) + self.assertTrue(convertToWindowsVersion("3.0rc1") > convertToWindowsVersion("3.0beta6")) + + def testThatStableIsHigherThanAlphaAndBetaAndRc(self): + self.assertTrue(convertToWindowsVersion("3.0") > convertToWindowsVersion("3.0alpha0")) + self.assertTrue(convertToWindowsVersion("3.0") > convertToWindowsVersion("3.0alpha4")) + self.assertTrue(convertToWindowsVersion("3.0") > convertToWindowsVersion("3.0alpha0")) + self.assertTrue(convertToWindowsVersion("3.0") > convertToWindowsVersion("3.0alpha4")) + self.assertTrue(convertToWindowsVersion("3.0") > convertToWindowsVersion("3.0beta0")) + self.assertTrue(convertToWindowsVersion("3.0") > convertToWindowsVersion("3.0beta6")) + self.assertTrue(convertToWindowsVersion("3.0") > convertToWindowsVersion("3.0rc1")) + self.assertTrue(convertToWindowsVersion("3.0") > convertToWindowsVersion("3.0rc11")) + + def testGitDescribeToVersion(self): + self.assertEqual("5.0alpha2-dev100", gitDescribeToVersion("swift-5.0alpha2-100-g33d5f6571", "swift")) + self.assertEqual("5.0alpha2", gitDescribeToVersion("swift-5.0alpha2", "swift")) + self.assertEqual("5.0-dev1", gitDescribeToVersion("swift-5.0-1-g012312312", "swift")) + self.assertIsNone(gitDescribeToVersion("swiften-5.0-1-g012312312", "swift")) + self.assertIsNone(gitDescribeToVersion("quickly-5.0-1-g012312312", "swift")) + self.assertIsNone(gitDescribeToVersion("swift-", "swift")) + self.assertIsNone(gitDescribeToVersion("swift", "swift")) + +if __name__ == '__main__': + if len(sys.argv) == 1: + unittest.main() + elif len(sys.argv) == 2: + if sys.argv[1] == "--git-build-version": + print(getGitBuildVersion(os.path.dirname(os.path.dirname(__file__)), "swift")) + else: + print(convertToWindowsVersion(sys.argv[1])) + sys.exit(0) + else: + print("Error: Simply run the script without arguments or pass a single argument.") + sys.exit(-1) |