diff options
Diffstat (limited to 'BuildTools')
24 files changed, 391 insertions, 329 deletions
| diff --git a/BuildTools/CheckHeaders.py b/BuildTools/CheckHeaders.py index 79ff85c..752d257 100755 --- a/BuildTools/CheckHeaders.py +++ b/BuildTools/CheckHeaders.py @@ -36,7 +36,7 @@ for line in file.readlines() :          continue      for forbiddenInclude, ignores in FORBIDDEN_INCLUDES :          if forbiddenInclude in line and len([x for x in ignores if x in filename]) == 0 : -            print "Found " + forbiddenInclude + " include in " + filename +            print("Found " + forbiddenInclude + " include in " + filename)              foundBadHeaders = True  sys.exit(foundBadHeaders) diff --git a/BuildTools/CheckTranslations.py b/BuildTools/CheckTranslations.py index 615f81f..0617fba 100755 --- a/BuildTools/CheckTranslations.py +++ b/BuildTools/CheckTranslations.py @@ -41,10 +41,10 @@ for filename in os.listdir("Swift/Translations") :              translationText = getText(translation.childNodes)              translationPlaceholders = set(re.findall("%\d+%?", translationText))              if translationPlaceholders != sourcePlaceholders : -                print "[Error] " + filename + ": Placeholder mismatch in translation '" + sourceText + "'" +                print("[Error] " + filename + ": Placeholder mismatch in translation '" + sourceText + "'")          if not finished : -                print "[Warning] " + filename + ": Unfinished" +                print("[Warning] " + filename + ": Unfinished")          if language not in desktop_generic_names and language != "en" : -                print "[Warning] GenericName field missing in desktop entry for " + language +                print("[Warning] GenericName field missing in desktop entry for " + language)          if language not in desktop_comments and language != "en" : -                print "[Warning] Comment field missing in desktop entry for " + language +                print("[Warning] Comment field missing in desktop entry for " + language) diff --git a/BuildTools/Copyright/find-contribs.py b/BuildTools/Copyright/find-contribs.py index ac30afb..799ae7b 100755 --- a/BuildTools/Copyright/find-contribs.py +++ b/BuildTools/Copyright/find-contribs.py @@ -46,12 +46,12 @@ def print_log(full_log):  full_swiften_log = subprocess.check_output(["git", "log", "--", "Swiften"]) -print "Contributors for Swiften/ subtree:\n" +print("Contributors for Swiften/ subtree:\n")  print_log(full_swiften_log)  full_all_log = subprocess.check_output(["git", "log"]) -print "\n\n\n\n" +print("\n\n\n\n") -print "Contributors for full tree:\n" +print("Contributors for full tree:\n")  print_log(full_all_log) diff --git a/BuildTools/Copyrighter.py b/BuildTools/Copyrighter.py index a16050c..4c7bfeb 100755 --- a/BuildTools/Copyrighter.py +++ b/BuildTools/Copyrighter.py @@ -8,7 +8,7 @@ CONTRIBUTOR_LICENSE = "mit"  LICENSE_DIR = "Documentation/Licenses"  # The following regex parses license comment blocks and its part out of a complete source file. -reParseLicenseCommentBlocks = re.compile(ur'(\/\*\n\s\*\sCopyright \(c\) (?P<startYear>\d\d\d\d)(-(?P<endYear>\d\d\d\d))? (?P<author>[^\n\.]*)\.?\n.\* (?P<license>[^\n]*)\n \* (?P<seeMore>[^\n]+)\n *\*\/)') +reParseLicenseCommentBlocks = re.compile(r'(\/\*\n\s\*\sCopyright \(c\) (?P<startYear>\d\d\d\d)(-(?P<endYear>\d\d\d\d))? (?P<author>[^\n\.]*)\.?\n.\* (?P<license>[^\n]*)\n \* (?P<seeMore>[^\n]+)\n *\*\/)')  class License :      def __init__(self, name, file) : @@ -122,14 +122,14 @@ def check_copyright(filename, hints) :                      return True                  else :                      if hints : -                        print "Copyright block for " + copyrightSetting.author + " does not cover current year in: " + filename +                        print("Copyright block for " + copyrightSetting.author + " does not cover current year in: " + filename)                      return False          if hints : -            print "Missing copyright block for " + copyrightSetting.author + " in: " + filename +            print("Missing copyright block for " + copyrightSetting.author + " in: " + filename)          return False      else :          if hints : -            print "No copyright found in: " + filename +            print("No copyright found in: " + filename)          return False  def replace_data_in_file(filename, begin, end, replaceWith) : @@ -140,7 +140,7 @@ def replace_data_in_file(filename, begin, end, replaceWith) :  def set_or_update_copyright(filename) :      if check_copyright(filename, False) : -        print "No update required for file: " + filename +        print("No update required for file: " + filename)      else :          copyrightBlocks = parse_file_new(filename)          username, email = get_userinfo() @@ -161,7 +161,7 @@ def set_or_update_copyright(filename) :          replace_data_in_file(filename, lastBlock+1, lastBlock+1, "\n" + str(copyrightSetting))  def print_help() : -    print """Usage: +    print("""Usage:      Copyrighter.py check-copyright $filename          Cheks for the existence of a copyright comment block. @@ -172,7 +172,7 @@ def print_help() :          A users license configuration can be set via the SWIFT_LICENSE_CONFIG environment variable           in the format "$copyright holder|$license", e.g. "Jane Doe|mit". Possible values for           $license are default, mit and gpl. -    """ +    """)  if sys.argv[1] == "check-copyright" :      file = sys.argv[2] @@ -183,6 +183,6 @@ elif sys.argv[1] == "set-copyright" :      file = sys.argv[2]      set_or_update_copyright(file)  else : -    print "Unknown command: " + sys.argv[1] +    print("Unknown command: " + sys.argv[1])      print_help()      sys.exit(-1) diff --git a/BuildTools/CrashReportAnalysis/WindowsMinidumpAnalyse.py b/BuildTools/CrashReportAnalysis/WindowsMinidumpAnalyse.py index de0633d..19e5f87 100644 --- a/BuildTools/CrashReportAnalysis/WindowsMinidumpAnalyse.py +++ b/BuildTools/CrashReportAnalysis/WindowsMinidumpAnalyse.py @@ -19,11 +19,11 @@ import time  swiftWindowBuildsPathPrefix = os.getenv("SWIFT_DIST")  if swiftWindowBuildsPathPrefix == None : -    print "Please set the SWIFT_DIST environment variable to a location containing msi and pdb.gz files." +    print("Please set the SWIFT_DIST environment variable to a location containing msi and pdb.gz files.")      sys.exit(1)  if len(sys.argv) != 3: -    print "Usage: python WindowsMinidumpAnalyse.py VERSION MINIDUMP_FILE" +    print("Usage: python WindowsMinidumpAnalyse.py VERSION MINIDUMP_FILE")      sys.exit(1)  version = sys.argv[1] @@ -93,7 +93,7 @@ def printHumanReadableReport():  try:      shutil.rmtree(working_folder)  except: -    print "" +    print("")  # clone local git repository into dedicated directory  call(["git", "clone",  ".", working_folder], shell=True) @@ -120,7 +120,7 @@ assert(len(commit) > 0)  if not os.path.exists(symbol_cache_path):      os.makedirs(symbol_cache_path) -#print "Checking out commit {0}.".format(commit) +#print("Checking out commit {0}.".format(commit))  call(["git", "-C", working_folder, "checkout", commit])  os.chdir(working_folder) diff --git a/BuildTools/DocBook/SCons/DocBook.py b/BuildTools/DocBook/SCons/DocBook.py index ffb0bfc..d7c95ba 100644 --- a/BuildTools/DocBook/SCons/DocBook.py +++ b/BuildTools/DocBook/SCons/DocBook.py @@ -5,6 +5,19 @@  import SCons.Util, SCons.Action  import xml.dom.minidom, re, os.path, sys +def maybeBytesToString(s): +    if isinstance(s, bytes): +        return s.decode('utf-8') +    return s + +def prepareForWrite(s): +    try: +        if isinstance(s, unicode): +            return s.encode('utf-8') +    except NameError: +        pass +    return s +  def generate(env) :      # Location of stylesheets and catalogs      docbook_dir = "#/BuildTools/DocBook" @@ -32,15 +45,15 @@ def generate(env) :              rewritePrefix="%(docbook_xsl_dir)s/" />  </catalog>""" -        docbook_xml_dir = source[0].get_contents() -        docbook_xsl_dir = source[1].get_contents() +        docbook_xml_dir = maybeBytesToString(source[0].get_contents()) +        docbook_xsl_dir = maybeBytesToString(source[1].get_contents())          if env["PLATFORM"] == "win32" :              docbook_xml_dir = docbook_xml_dir.replace("\\","/")              docbook_xsl_dir = docbook_xsl_dir.replace("\\","/")          file = open(target[0].abspath, "w")          file.write(catalog % { -                "docbook_xml_dir" : docbook_xml_dir, -                "docbook_xsl_dir" : docbook_xsl_dir, +                "docbook_xml_dir" : prepareForWrite(docbook_xml_dir), +                "docbook_xsl_dir" : prepareForWrite(docbook_xsl_dir),              })          file.close() diff --git a/BuildTools/DocBook/SCons/XSLT.py b/BuildTools/DocBook/SCons/XSLT.py index 38e36c5..6a40b62 100644 --- a/BuildTools/DocBook/SCons/XSLT.py +++ b/BuildTools/DocBook/SCons/XSLT.py @@ -8,7 +8,7 @@ import xml.dom.minidom, os, os.path  def generate(env) :      def generate_actions(source, target, env, for_signature) :          if not env.has_key("XSLTSTYLESHEET") : -            raise SCons.Errors.UserError, "The XSLTSTYLESHEET construction variable must be defined" +            raise SCons.Errors.UserError("The XSLTSTYLESHEET construction variable must be defined")          # Process the XML catalog files          # FIXME: It's probably not clean to do an ENV assignment globally diff --git a/BuildTools/FixIncludes.py b/BuildTools/FixIncludes.py index 8984944..e532464 100755 --- a/BuildTools/FixIncludes.py +++ b/BuildTools/FixIncludes.py @@ -153,12 +153,12 @@ for line in content[headerStart:headerEnd]:              headerGroups[headerType] = [line]  if containsComplexPreprocessorDirectives: -    print "Cannot format headers containing preprocessor #if, #pragma, #define or #undef statements!" +    print("Cannot format headers containing preprocessor #if, #pragma, #define or #undef statements!")      exit(1)  if filename_base.endswith(".h"):      if not HeaderType.PRAGMA_ONCE in headerGroups: -        print "Missing #pragma once!" +        print("Missing #pragma once!")          exit(2)      cleanHeaderFile(content, headerStart, headerEnd, headerGroups)  elif filename_base.endswith(".cpp") or filename_base.endswith(".mm"): diff --git a/BuildTools/GenerateAppCastFeeds.py b/BuildTools/GenerateAppCastFeeds.py index 8135134..e7493df 100755 --- a/BuildTools/GenerateAppCastFeeds.py +++ b/BuildTools/GenerateAppCastFeeds.py @@ -148,6 +148,6 @@ writeAppcastFile(filename=os.path.join(args.outputFolder, "swift-testing-appcast  writeAppcastFile(filename=os.path.join(args.outputFolder, "swift-development-appcast-mac.xml"),      title="Swift Development Releases",      description="", -    regexPattern="^\d+(\.\d+)?(\.\d+)?(alpha)?(beta\d+)?(rc\d+)?(-dev\d+)?$", +    regexPattern="^\d+(\.\d+)?(\.\d+)?(alpha\d*)?(beta\d+)?(rc\d+)?(-dev\d+)?$",      appcastURL=urlparse.urljoin(args.downloadsURL, "swift-development-appcast-mac.xml"),      releases=automaticReleases) diff --git a/BuildTools/GetBuildVersion.py b/BuildTools/GetBuildVersion.py index 70fdc5c..be7cc03 100755 --- a/BuildTools/GetBuildVersion.py +++ b/BuildTools/GetBuildVersion.py @@ -16,6 +16,6 @@ if only_major :      if version_match :          print version_match.group(1)      else : -        print "0" +        print("0")  else :      print Version.getBuildVersion(os.path.dirname(sys.argv[0]) + "/..", sys.argv[1]) diff --git a/BuildTools/Gource/GetGravatars.py b/BuildTools/Gource/GetGravatars.py index d1f40a4..17198aa 100755 --- a/BuildTools/Gource/GetGravatars.py +++ b/BuildTools/Gource/GetGravatars.py @@ -5,7 +5,7 @@ import subprocess, os, sys, hashlib, urllib  GRAVATAR_URL = "http://www.gravatar.com/avatar/%(id)s?d=404"  if len(sys.argv) != 2 : -    print "Usage: " + sys.argv[0] + " <output-dir>" +    print("Usage: " + sys.argv[0] + " <output-dir>")      sys.exit(-1)  output_dir = sys.argv[1] @@ -18,32 +18,32 @@ for line in p.stdout.readlines() :      authors[author_components[0]] = author_components[1]  p.stdin.close()  if p.wait() != 0 : -    print "Error" +    print("Error")      sys.exit(-1)  # Get & save the avatars  if not os.path.isdir(output_dir) :      os.makedirs(output_dir)  for email, name in authors.items() : -    print "Processing avatar for " + name + " <" + email + ">" +    print("Processing avatar for " + name + " <" + email + ">")      filename = os.path.join(output_dir, name + ".png")      if os.path.isfile(filename) : -        print "-> Already there. Skipping." +        print("-> Already there. Skipping.")          continue      m = hashlib.md5()      m.update(email)      url = GRAVATAR_URL % {"id" : m.hexdigest()} -    print "- Downloading " + url +    print("- Downloading " + url)      f = urllib.urlopen(url)      input = None      if f.getcode() == 200 :          input = f.read()      f.close()      if input : -        print "- Saving file " + filename +        print("- Saving file " + filename)          f = open(filename, "w")          f.write(input)          f.close()      else : -        print "- No Gravatar found" +        print("- No Gravatar found") diff --git a/BuildTools/InstallSwiftDependencies.sh b/BuildTools/InstallSwiftDependencies.sh index 378f141..438e395 100755 --- a/BuildTools/InstallSwiftDependencies.sh +++ b/BuildTools/InstallSwiftDependencies.sh @@ -4,14 +4,14 @@  SYSTEM_NAME=$(uname) -if [ "$SYSTEM_NAME" == "Linux" ]  +if [ "$SYSTEM_NAME" == "Linux" ]  then      # handle linux distributions      SYSTEM_DISTRO=$(lsb_release -i -s)      if [ "$SYSTEM_DISTRO" == "Debian" ]      then          sudo apt-get install build-essential pkg-config libssl-dev qt5-default libqt5x11extras5-dev libqt5webkit5-dev qtmultimedia5-dev qttools5-dev-tools qt5-image-formats-plugins libqt5svg5-dev libminiupnpc-dev libnatpmp-dev libhunspell-dev -    elif [ "$SYSTEM_DISTRO" == "Ubuntu" ] || [ "$SYSTEM_DISTRO" == "LinuxMint" ] +    elif [ "$SYSTEM_DISTRO" == "Ubuntu" ] || [ "$SYSTEM_DISTRO" == "LinuxMint" ] || [ "$SYSTEM_DISTRO" == "neon" ]      then          sudo apt-get install build-essential pkg-config libssl-dev qt5-default libqt5x11extras5-dev libqt5webkit5-dev qtmultimedia5-dev qttools5-dev-tools qt5-image-formats-plugins libqt5svg5-dev libminiupnpc-dev libnatpmp-dev libhunspell-dev      elif [ "$SYSTEM_DISTRO" == "Arch" ] diff --git a/BuildTools/ProjectCopyrightSummary.py b/BuildTools/ProjectCopyrightSummary.py index 6e2d824..f6b18a0 100755 --- a/BuildTools/ProjectCopyrightSummary.py +++ b/BuildTools/ProjectCopyrightSummary.py @@ -17,7 +17,7 @@ def CopyrightNames(filename):      names = []      with open(filename, 'r') as file:          data = file.read() -        p = re.compile(ur'\* Copyright.*\d\d\d\d (.*?)\.?$', re.MULTILINE) +        p = re.compile(r'\* Copyright.*\d\d\d\d (.*?)\.?$', re.MULTILINE)          names = re.findall(p, data)      return names 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) diff --git a/BuildTools/UpdateDebianChangelog.py b/BuildTools/UpdateDebianChangelog.py index 1d0e3ea..d7e1f1b 100755 --- a/BuildTools/UpdateDebianChangelog.py +++ b/BuildTools/UpdateDebianChangelog.py @@ -20,7 +20,7 @@ if m :  if project == "" :      project="swift-im" -if "dev" in version : +if "dev" in version or "alpha" in version :      distribution = "development"  elif "beta" in version or "rc" in version :      distribution = "beta development" @@ -38,4 +38,3 @@ if last_version != version :      changelog.write("\n")      changelog.write(changelog_data)      changelog.close() - diff --git a/BuildTools/scons2ninja.py b/BuildTools/scons2ninja.py index 6c77c88..df4c655 100755 --- a/BuildTools/scons2ninja.py +++ b/BuildTools/scons2ninja.py @@ -1,5 +1,5 @@  #!/usr/bin/env python -# -*- coding: utf-8 -*-  +# -*- coding: utf-8 -*-  ################################################################################  # @@ -204,9 +204,9 @@ class NinjaBuilder :      def to_string(self, lst, quote = False) :          if is_list(lst) :              if quote : -                return ' '.join([quote_spaces(x) for x in lst])  +                return ' '.join([quote_spaces(x) for x in lst])              else : -                return ' '.join([escape(x) for x in lst])  +                return ' '.join([escape(x) for x in lst])          if is_regexp(lst) :              return ' '.join([escape(x) for x in self.targets if lst.match(x)])          return escape(lst) @@ -248,8 +248,8 @@ ninja = NinjaBuilder()  ninja.pool('scons_pool', depth = 1)  if sys.platform == 'win32' : -    ninja.rule('cl',  -        deps = 'msvc',  +    ninja.rule('cl', +        deps = 'msvc',          command = '$cl /showIncludes $clflags -c $in /Fo$out',          description = 'CXX $out') @@ -369,7 +369,7 @@ for line in f.stdout :      # Skip lines if requested from previous command      if skip_nth_line >= 0 : -        skip_nth_line -= 1  +        skip_nth_line -= 1      if skip_nth_line == 0 :          continue @@ -407,7 +407,7 @@ for line in f.stdout :          level = line.index('+-') / 2          filename = line[level*2+2:]          if filename.startswith('[') : -            filename = filename[1:-1]  +            filename = filename[1:-1]          # Check if we use the 'fixed' format which escapes filenamenames          if filename.startswith('\'') and filename.endswith('\'') : @@ -429,7 +429,7 @@ for line in f.stdout :          previous_filename = filename  if f.wait() != 0 : -    print "Error calling '" + scons_generate_cmd + "'" +    print("Error calling '" + scons_generate_cmd + "'")      print f.stderr.read()      exit(-1) @@ -528,10 +528,10 @@ for line in build_lines :          libpaths = get_unary_flags("/libpath:", flags)          deps = get_built_libs(libs, libpaths, ninja.targets)          if out in mtflags : -            ninja.build(out, 'link_mt', objects, deps = sorted(deps),  +            ninja.build(out, 'link_mt', objects, deps = sorted(deps),                  libs = libs, linkflags = flags, mtflags = mtflags[out])          else : -            ninja.build(out, 'link', objects, deps = sorted(deps),  +            ninja.build(out, 'link', objects, deps = sorted(deps),                  libs = libs, linkflags = flags)      elif tool == 'rc': @@ -589,10 +589,12 @@ for line in build_lines :          source = flags[0];          outdir, flags = extract_binary_flag("-o", flags)          basename, flags = extract_binary_flag("--basename", flags) -        ninja.build(os.path.join(outdir, basename + ".h"), 'sdef', [source],  +        ninja.build(os.path.join(outdir, basename + ".h"), 'sdef', [source],                  basename = basename,                  outdir = outdir) +    elif tool == 'checker': +        pass      elif not ninja_custom_command(ninja, line)  :          raise Exception("Unknown tool: '" + line + "'") | 
 Swift
 Swift