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) | 
 Swift
 Swift