View Issue Details

IDProjectCategoryView StatusLast Update
0005234The Dark ModCodingpublic02.01.2023 16:06
Reportert405 Assigned Tostgatilov  
PrioritylowSeveritynormalReproducibilityalways
Status closedResolutionwon't fix 
PlatformLinuxOSArchOS Version5.6.7
Fixed in VersionTDM 2.10 
Summary0005234: compilation: scons configuration and documentation
DescriptionIf scons is really no longer supported as a compilation method, then only one thing needs to be done:

The wiki and COMPILING.txt need to be brought in sync and the scons configuration files removed from the svn repo.

If people are still using scons, then this will be helpful.

After trying to compile according to the wiki instructions, using scons, a number of errors occurred. Most of these errors were due to the code being written in python2 and being incompatible with python3.

The problematic files were

SConstruct
sys/scons/scons_utils.py
tdm_update/SConstruct
tdm_update/scons_utils.py

I was confused by the conflicting instructions in the wiki and in COMPILING.txt

the last update on the wiki is older ( 14:58, 30 September 2019‎ Duzenko ) than the svn ( r8453 | cabalistic | 2019-12-19 14:51:53 -0500 (Thu, 19 Dec 2019) )
Steps To ReproduceI checked out the svn repo 8693 and attempted to compile using the wiki instructions

Immediately got an error:
scons: Reading SConscript files ...
  File "/home/shawn/Code/darkmod-svn-wd/trunk/SConstruct", line 150
    print 'Loading build configuration from ' + conf_filename + ':'
          ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print('Loading build configuration from ' + conf_filename + ':')?

There were a number of other errors: a missing module (popen2) and problems with the pickle and raise syntax.
Additional Information    Compilation was successful after I patched the files by translating them with 2to3, cleaning them up with black, and manually fixing the other errors.

`uname -a`:
 Linux 5.6.7-arch1-1 0000001 SMP PREEMPT Thu, 23 Apr 2020 09:13:56 +0000 x86_64 GNU/Linux
`scons --version | xargs`:
 SCons by Steven Knight et al.: script: v3.1.2.__BUILD__, 2019-12-17 02:06:27, by none on none engine: v3.1.2.__BUILD__, 2019-12-17 02:06:27, by none on none engine path: [/usr/lib/python3.8/site-packages/SCons] Copyright (c) 2001 - 2019 The SCons Foundation
`black --version`:
 black, version 19.10b0

Patch is included in uploads.
TagsNo tags attached.
Attached Files
scons-fix-python3-001.patch (43,655 bytes)   
diff --git a/SConstruct b/SConstruct
index 14e504ed5..a3e043322 100644
--- a/SConstruct
+++ b/SConstruct
@@ -3,32 +3,50 @@
 # TTimo <ttimo@idsoftware.com>
 # http://scons.sourceforge.net
 
-import sys, os, time, commands, re, pickle, StringIO, popen2, commands, pdb, zipfile, string
+import sys, os, time, subprocess, re, pickle, io, subprocess, pdb, zipfile, string
 import SCons
 
-sys.path.append( 'sys/scons' )
+sys.path.append("sys/scons")
 import scons_utils
 
-conf_filename='site.conf'
+conf_filename = "site.conf"
 # choose configuration variables which should be saved between runs
 # ( we handle all those as strings )
-serialized=['CC', 'CXX', 'JOBS', 'BUILD', 'GL_HARDLINK',
-	'DEBUG_MEMORY', 'LIBC_MALLOC', 'ID_MCHECK', 'NOCURL',
-	'BUILD_ROOT', 'BASEFLAGS', 'SILENT', 'NO_GCH', 'OPENMP',
-	'TARGET_ARCH' ]
+serialized = [
+    "CC",
+    "CXX",
+    "JOBS",
+    "BUILD",
+    "GL_HARDLINK",
+    "DEBUG_MEMORY",
+    "LIBC_MALLOC",
+    "ID_MCHECK",
+    "NOCURL",
+    "BUILD_ROOT",
+    "BASEFLAGS",
+    "SILENT",
+    "NO_GCH",
+    "OPENMP",
+    "TARGET_ARCH",
+]
 
 # ------------------------------------------------
 
 # help -------------------------------------------
 
-help_string = """
+help_string = (
+    """
 Usage: scons [OPTIONS] [TARGET] [CONFIG]
 
 [OPTIONS] and [TARGET] are covered in command line options, use scons -H
 
 [CONFIG]: KEY="VALUE" [...]
-a number of configuration options saved between runs in the """ + conf_filename + """ file
-erase """ + conf_filename + """ to start with default settings again
+a number of configuration options saved between runs in the """
+    + conf_filename
+    + """ file
+erase """
+    + conf_filename
+    + """ to start with default settings again
 
 CC (default gcc)
 CXX (default g++)
@@ -90,122 +108,118 @@ ID_MCHECK (default 2)
 NOCURL (default 0)
 	set to 1 to disable usage of libcurl and http/ftp downloads feature
 """
+)
 
-Help( help_string )
+Help(help_string)
 
 # end help ---------------------------------------
 
 # sanity -----------------------------------------
 
-EnsureSConsVersion( 0, 96 )
+EnsureSConsVersion(0, 96)
 
 # end sanity -------------------------------------
 
 # system detection -------------------------------
 
 # CPU type
-cpu = commands.getoutput('uname -m')
-exp = re.compile('.*i?86.*')
+cpu = subprocess.getoutput("uname -m")
+exp = re.compile(".*i?86.*")
 if exp.match(cpu):
-	cpu = 'x86'
+    cpu = "x86"
 else:
-	cpu = commands.getoutput('uname -p')
-	if ( cpu == 'powerpc' ):
-		cpu = 'ppc'
-	else:
-		cpu = 'cpu'
-g_os = 'Linux'
+    cpu = subprocess.getoutput("uname -p")
+    if cpu == "powerpc":
+        cpu = "ppc"
+    else:
+        cpu = "cpu"
+g_os = "Linux"
 
 # end system detection ---------------------------
 
 # default settings -------------------------------
 
-CC = 'gcc'
-CXX = 'g++'
-JOBS = '1'
-BUILD = 'debug'
-GL_HARDLINK = '0'
-DEBUG_MEMORY = '0'
-LIBC_MALLOC = '1'
-ID_MCHECK = '2'
-BUILD_ROOT = 'build'
-NOCONF = '0'
-NOCURL = '0'
-BASEFLAGS = ''
-SILENT = '0'
-NO_GCH = '0'
-OPENMP = '0'
-TARGET_ARCH = 'x86'
+CC = "gcc"
+CXX = "g++"
+JOBS = "1"
+BUILD = "debug"
+GL_HARDLINK = "0"
+DEBUG_MEMORY = "0"
+LIBC_MALLOC = "1"
+ID_MCHECK = "2"
+BUILD_ROOT = "build"
+NOCONF = "0"
+NOCURL = "0"
+BASEFLAGS = ""
+SILENT = "0"
+NO_GCH = "0"
+OPENMP = "0"
+TARGET_ARCH = "x86"
 
 # end default settings ---------------------------
 
 # site settings ----------------------------------
-
-if ( not ARGUMENTS.has_key( 'NOCONF' ) or ARGUMENTS['NOCONF'] != '1' ):
-	site_dict = {}
-	if (os.path.exists(conf_filename)):
-		site_file = open(conf_filename, 'r')
-		p = pickle.Unpickler(site_file)
-		site_dict = p.load()
-		print 'Loading build configuration from ' + conf_filename + ':'
-		for k, v in site_dict.items():
-			exec_cmd = k + '=\'' + v + '\''
-			print '  ' + exec_cmd
-			exec(exec_cmd)
+if "NOCONF" not in ARGUMENTS or ARGUMENTS["NOCONF"] != "1":
+    site_dict = {}
+    if os.path.exists(conf_filename):
+        print("Loading build configuration from " + conf_filename + ":")
+        with open(conf_filename, "rb") as handle:
+            site_dict = pickle.load(handle)
+        for k, v in list(site_dict.items()):
+            exec_cmd = k + "='" + v + "'"
+            print("  " + exec_cmd)
+            exec(exec_cmd)
 else:
-	print 'Site settings ignored'
+    print("Site settings ignored")
 
 # end site settings ------------------------------
 
 # command line settings --------------------------
 
-for k in ARGUMENTS.keys():
-	exec_cmd = k + '=\'' + ARGUMENTS[k] + '\''
-	print 'Command line: ' + exec_cmd
-	exec( exec_cmd )
+for k in list(ARGUMENTS.keys()):
+    exec_cmd = k + "='" + ARGUMENTS[k] + "'"
+    print("Command line: " + exec_cmd)
+    exec(exec_cmd)
 
 # stgatilov: avoid annoying human errors when you set target='x32'
 # and get surprised that it does not build properly =)
-if TARGET_ARCH == 'x32':
-	TARGET_ARCH = 'x86'
+if TARGET_ARCH == "x32":
+    TARGET_ARCH = "x86"
 
 # end command line settings ----------------------
 
 # save site configuration ----------------------
 
-if ( not ARGUMENTS.has_key( 'NOCONF' ) or ARGUMENTS['NOCONF'] != '1' ):
-	for k in serialized:
-		exec_cmd = 'site_dict[\'' + k + '\'] = ' + k
-		exec(exec_cmd)
-
-	site_file = open(conf_filename, 'w')
-	p = pickle.Pickler(site_file)
-	p.dump(site_dict)
-	site_file.close()
+if "NOCONF" not in ARGUMENTS or ARGUMENTS["NOCONF"] != "1":
+    for k in serialized:
+        exec_cmd = "site_dict['" + k + "'] = " + k
+        exec(exec_cmd)
+    with open(conf_filename, "wb") as handle:
+        pickle.dump(site_dict, handle, protocol=pickle.HIGHEST_PROTOCOL)
 
 # end save site configuration ------------------
 
 # general configuration, target selection --------
 
-g_build = BUILD_ROOT + '/scons_' + TARGET_ARCH + '/' + BUILD
+g_build = BUILD_ROOT + "/scons_" + TARGET_ARCH + "/" + BUILD
 
-# 
+#
 # Use an absolute path to a single signature file to avoid a problem
 # whereby everything gets rebuilt every time due to the signature file
 # not being detected.
-# 
-SConsignFile(os.path.join(Dir('#').abspath, 'scons.signatures'))
+#
+SConsignFile(os.path.join(Dir("#").abspath, "scons.signatures"))
 
-if ( GL_HARDLINK != '0' ):
-	g_build += '-hardlink'
+if GL_HARDLINK != "0":
+    g_build += "-hardlink"
 
-if ( DEBUG_MEMORY != '0' ):
-	g_build += '-debugmem'
-	
-if ( LIBC_MALLOC != '1' ):
-	g_build += '-nolibcmalloc'
+if DEBUG_MEMORY != "0":
+    g_build += "-debugmem"
 
-SetOption('num_jobs', JOBS)
+if LIBC_MALLOC != "1":
+    g_build += "-nolibcmalloc"
+
+SetOption("num_jobs", JOBS)
 
 LINK = CXX
 
@@ -214,126 +228,141 @@ LINK = CXX
 # BASE + GAME + OPT for game
 # _noopt versions of the environements are built without the OPT
 
-BASECPPFLAGS = [ ]
-CORECPPPATH = [ ]
-CORELIBPATH = [ ]
-CORECPPFLAGS = [ ]
-BASELINKFLAGS = [ ]
-CORELINKFLAGS = [ ]
+BASECPPFLAGS = []
+CORECPPPATH = []
+CORELIBPATH = []
+CORECPPFLAGS = []
+BASELINKFLAGS = []
+CORELINKFLAGS = []
 
 # for release build, further optimisations that may not work on all files
-OPTCPPFLAGS = [ ]
+OPTCPPFLAGS = []
 
-BASECPPFLAGS.append( BASEFLAGS )
-BASECPPFLAGS.append( '-pipe' )
+BASECPPFLAGS.append(BASEFLAGS)
+BASECPPFLAGS.append("-pipe")
 # warn all
-BASECPPFLAGS.append( '-Wall' )
-BASECPPFLAGS.append( '-Wno-unknown-pragmas' )               # MSVC-specific pragmas
-BASECPPFLAGS.append( '-Wno-unused-variable' )               # too many, often happens from commenting out code
-BASECPPFLAGS.append( '-Wno-unused-but-set-variable' )       # useful for debugging, also may remain after commenting stuff
-BASECPPFLAGS.append( '-Wno-sign-compare' )                  # very nasty warning in the world of STL and size_t
+BASECPPFLAGS.append("-Wall")
+BASECPPFLAGS.append("-Wno-unknown-pragmas")  # MSVC-specific pragmas
+BASECPPFLAGS.append(
+    "-Wno-unused-variable"
+)  # too many, often happens from commenting out code
+BASECPPFLAGS.append(
+    "-Wno-unused-but-set-variable"
+)  # useful for debugging, also may remain after commenting stuff
+BASECPPFLAGS.append(
+    "-Wno-sign-compare"
+)  # very nasty warning in the world of STL and size_t
 
 # this define is necessary to make sure threading support is enabled in X
-CORECPPFLAGS.append( '-DXTHREADS' )
+CORECPPFLAGS.append("-DXTHREADS")
 # don't wrap gcc messages
-BASECPPFLAGS.append( '-fmessage-length=0' )
+BASECPPFLAGS.append("-fmessage-length=0")
 # C++11 features
-BASECPPFLAGS.append( '-std=c++14' )
+BASECPPFLAGS.append("-std=c++14")
 # maintain this dangerous optimization off at all times
-BASECPPFLAGS.append( '-fno-strict-aliasing' )
-
-if ( g_os == 'Linux' ):
-	# use old ABI for std::string and std::list (which is not fully compliant with C++11 standard)
-	# this allows to run TDM binary on OSes which have old glibcxx (e.g. Ubuntu 14.04 from years 2014-2016)
-	BASECPPFLAGS.append( '-D_GLIBCXX_USE_CXX11_ABI=0' )
-	# gcc 4.x option only - only export what we mean to from the game SO
-	BASECPPFLAGS.append( '-fvisibility=hidden' )
-	# get the 64 bits machine on the distcc array to produce 32 bit binaries :)
-	if ( TARGET_ARCH == 'x86' ):
-		BASECPPFLAGS.append( '-m32' )
-		BASELINKFLAGS.append( '-m32' )
-		BASECPPFLAGS.append( '-msse2' );
-	if ( TARGET_ARCH == 'x64' ):
-		BASECPPFLAGS.append( '-m64' )
-		BASELINKFLAGS.append( '-m64' )
-		# current ffmpeg dep was built without -fPIC, so can't use position-independent code generation
-		BASELINKFLAGS.append( '-no-pie' )
-    
-	if ( OPENMP != '0' ):
-		# openmp support for changes made to the renderer
-		BASECPPFLAGS.append( '-fopenmp' )
-		BASELINKFLAGS.append( '-fopenmp' )
-
-if ( BUILD == 'debug-all' ):
-	OPTCPPFLAGS = [ '-g', '-D_DEBUG' ]
-	if ( ID_MCHECK == '0' ):
-		ID_MCHECK = '1'
-elif ( BUILD == 'debug' ):
-	OPTCPPFLAGS = [ '-g', '-O1', '-D_DEBUG' ]
-	if ( ID_MCHECK == '0' ):
-		ID_MCHECK = '1'
-elif ( BUILD == 'profile' ):
-	# -fprofile-arcs is needed for gcc 3.x and 4.x
-	OPTCPPFLAGS = [ '-pg', '-fprofile-arcs', '-ftest-coverage', '-O1', '-D_DEBUG' ]
-	BASELINKFLAGS.append( '-pg' );
-	BASELINKFLAGS.append( '-fprofile-arcs' );
-	if ( ID_MCHECK == '0' ):
-		ID_MCHECK = '1'
-elif ( BUILD == 'release' ):
-	# -fomit-frame-pointer: not set because if prohibits debugging (which is necessary even on release build)
-	# -finline-functions: implicit at -O3
-	# -fschedule-insns2: implicit at -O2
-	# -fno-unsafe-math-optimizations: that should be on by default really. hit some wonko bugs in physics code because of that
-	OPTCPPFLAGS = [ '-g', '-O3', '-ffast-math', '-fno-unsafe-math-optimizations' ] 
-	if ( ID_MCHECK == '0' ):
-		ID_MCHECK = '2'
+BASECPPFLAGS.append("-fno-strict-aliasing")
+
+if g_os == "Linux":
+    # use old ABI for std::string and std::list (which is not fully compliant with C++11 standard)
+    # this allows to run TDM binary on OSes which have old glibcxx (e.g. Ubuntu 14.04 from years 2014-2016)
+    BASECPPFLAGS.append("-D_GLIBCXX_USE_CXX11_ABI=0")
+    # gcc 4.x option only - only export what we mean to from the game SO
+    BASECPPFLAGS.append("-fvisibility=hidden")
+    # get the 64 bits machine on the distcc array to produce 32 bit binaries :)
+    if TARGET_ARCH == "x86":
+        BASECPPFLAGS.append("-m32")
+        BASELINKFLAGS.append("-m32")
+        BASECPPFLAGS.append("-msse2")
+    if TARGET_ARCH == "x64":
+        BASECPPFLAGS.append("-m64")
+        BASELINKFLAGS.append("-m64")
+        # current ffmpeg dep was built without -fPIC, so can't use position-independent code generation
+        BASELINKFLAGS.append("-no-pie")
+
+    if OPENMP != "0":
+        # openmp support for changes made to the renderer
+        BASECPPFLAGS.append("-fopenmp")
+        BASELINKFLAGS.append("-fopenmp")
+
+if BUILD == "debug-all":
+    OPTCPPFLAGS = ["-g", "-D_DEBUG"]
+    if ID_MCHECK == "0":
+        ID_MCHECK = "1"
+elif BUILD == "debug":
+    OPTCPPFLAGS = ["-g", "-O1", "-D_DEBUG"]
+    if ID_MCHECK == "0":
+        ID_MCHECK = "1"
+elif BUILD == "profile":
+    # -fprofile-arcs is needed for gcc 3.x and 4.x
+    OPTCPPFLAGS = ["-pg", "-fprofile-arcs", "-ftest-coverage", "-O1", "-D_DEBUG"]
+    BASELINKFLAGS.append("-pg")
+    BASELINKFLAGS.append("-fprofile-arcs")
+    if ID_MCHECK == "0":
+        ID_MCHECK = "1"
+elif BUILD == "release":
+    # -fomit-frame-pointer: not set because if prohibits debugging (which is necessary even on release build)
+    # -finline-functions: implicit at -O3
+    # -fschedule-insns2: implicit at -O2
+    # -fno-unsafe-math-optimizations: that should be on by default really. hit some wonko bugs in physics code because of that
+    OPTCPPFLAGS = ["-g", "-O3", "-ffast-math", "-fno-unsafe-math-optimizations"]
+    if ID_MCHECK == "0":
+        ID_MCHECK = "2"
 else:
-	print 'Unknown build configuration ' + BUILD
-	sys.exit(0)
+    print("Unknown build configuration " + BUILD)
+    sys.exit(0)
 
-if ( GL_HARDLINK != '0' ):
-	CORECPPFLAGS.append( '-DID_GL_HARDLINK' )
+if GL_HARDLINK != "0":
+    CORECPPFLAGS.append("-DID_GL_HARDLINK")
 
-if ( DEBUG_MEMORY != '0' ):
-	BASECPPFLAGS += [ '-DID_DEBUG_MEMORY', '-DID_REDIRECT_NEWDELETE' ]
-	
-if ( LIBC_MALLOC != '1' ):
-	BASECPPFLAGS.append( '-DUSE_LIBC_MALLOC=0' )
+if DEBUG_MEMORY != "0":
+    BASECPPFLAGS += ["-DID_DEBUG_MEMORY", "-DID_REDIRECT_NEWDELETE"]
+
+if LIBC_MALLOC != "1":
+    BASECPPFLAGS.append("-DUSE_LIBC_MALLOC=0")
+
+if ID_MCHECK == "1":
+    BASECPPFLAGS.append("-DID_MCHECK")
 
-if ( ID_MCHECK == '1' ):
-	BASECPPFLAGS.append( '-DID_MCHECK' )
-	
 # create the build environements
-g_env_base = Environment( ENV = os.environ, CC = CC, CXX = CXX, LINK = LINK, CPPFLAGS = BASECPPFLAGS, LINKFLAGS = BASELINKFLAGS, CPPPATH = CORECPPPATH, LIBPATH = CORELIBPATH )
-scons_utils.SetupUtils( g_env_base )
-
-g_env_base.Prepend(CPPPATH=['.'])
-path_template = '#/ThirdParty/artefacts/{0}/include'
-g_env_base.Append(CPPPATH = path_template.format('zlib'))
-g_env_base.Append(CPPPATH = path_template.format('libcurl'))
-g_env_base.Append(CPPPATH = path_template.format('openal'))
-g_env_base.Append(CPPPATH = path_template.format('ogg'))
-g_env_base.Append(CPPPATH = path_template.format('vorbis'))
-g_env_base.Append(CPPPATH = path_template.format('devil'))
-g_env_base.Append(CPPPATH = path_template.format('libjpeg'))
-g_env_base.Append(CPPPATH = path_template.format('ffmpeg'))
-g_env_base.Append(CPPPATH = path_template.format('doctest'))
-g_env_base.Append(CPPPATH = path_template.format('pugixml'))
-g_env_base.Append(CPPPATH = '#/renderer')
-g_env_base.Append(CPPPATH = '#/')
-
-g_env_base['CPPFLAGS'] += OPTCPPFLAGS
-g_env_base['CPPFLAGS'] += CORECPPFLAGS
-g_env_base['LINKFLAGS'] += CORELINKFLAGS
-
-
-#if ( int(JOBS) > 1 ):
-#	print 'Using buffered process output'
-#	silent = False
-#	if ( SILENT == '1' ):
-#		silent = True
-#	scons_utils.SetupBufferedOutput( g_env, silent )
-#	scons_utils.SetupBufferedOutput( g_game_env, silent )
+g_env_base = Environment(
+    ENV=os.environ,
+    CC=CC,
+    CXX=CXX,
+    LINK=LINK,
+    CPPFLAGS=BASECPPFLAGS,
+    LINKFLAGS=BASELINKFLAGS,
+    CPPPATH=CORECPPPATH,
+    LIBPATH=CORELIBPATH,
+)
+scons_utils.SetupUtils(g_env_base)
+
+g_env_base.Prepend(CPPPATH=["."])
+path_template = "#/ThirdParty/artefacts/{0}/include"
+g_env_base.Append(CPPPATH=path_template.format("zlib"))
+g_env_base.Append(CPPPATH=path_template.format("libcurl"))
+g_env_base.Append(CPPPATH=path_template.format("openal"))
+g_env_base.Append(CPPPATH=path_template.format("ogg"))
+g_env_base.Append(CPPPATH=path_template.format("vorbis"))
+g_env_base.Append(CPPPATH=path_template.format("devil"))
+g_env_base.Append(CPPPATH=path_template.format("libjpeg"))
+g_env_base.Append(CPPPATH=path_template.format("ffmpeg"))
+g_env_base.Append(CPPPATH=path_template.format("doctest"))
+g_env_base.Append(CPPPATH=path_template.format("pugixml"))
+g_env_base.Append(CPPPATH="#/renderer")
+g_env_base.Append(CPPPATH="#/")
+
+g_env_base["CPPFLAGS"] += OPTCPPFLAGS
+g_env_base["CPPFLAGS"] += CORECPPFLAGS
+g_env_base["LINKFLAGS"] += CORELINKFLAGS
+
+
+# if ( int(JOBS) > 1 ):
+#     print 'Using buffered process output'
+#     silent = False
+#     if ( SILENT == '1' ):
+#         silent = True
+#     scons_utils.SetupBufferedOutput( g_env, silent )
+#     scons_utils.SetupBufferedOutput( g_game_env, silent )
 
 # mark the globals
 
@@ -341,50 +370,50 @@ g_env_base['LINKFLAGS'] += CORELINKFLAGS
 local_curl = 0
 curl_lib = []
 
-GLOBALS = 'g_env_base g_os ID_MCHECK curl_lib local_curl NO_GCH TARGET_ARCH'
+GLOBALS = "g_env_base g_os ID_MCHECK curl_lib local_curl NO_GCH TARGET_ARCH"
 
 # end general configuration ----------------------
 
 # targets ----------------------------------------
 
-Export( 'GLOBALS ' + GLOBALS )
+Export("GLOBALS " + GLOBALS)
 
 thedarkmod = None
 
 # insert SVN revision number into header (requires svnversion)
 # svnversion must be run from SVN root, otherwise revision information may be incomplete
-os.chdir(Dir('#').abspath)
+os.chdir(Dir("#").abspath)
 svnversion_command = r'sed "s/\!SVNVERSION\!/$(svnversion -c)/g" idlib/svnversion_template.h >idlib/svnversion.h'
 if os.system(svnversion_command) != 0:
-	exit()
+    exit()
 print("Inserted SVN revision number into svnversion.h")
 
 
 # build curl if needed
-if ( NOCURL == '0' ):
-	# 1: debug, 2: release
-	if ( BUILD == 'release' ):
-		local_curl = 2
-	else:
-		local_curl = 1
-	Export( 'GLOBALS ' + GLOBALS )
-	if ( TARGET_ARCH == 'x86' ):
-		curl_lib = [ '#linux/libcurl/libcurl.a' ] # Use the static one built for TDM
-	if ( TARGET_ARCH == 'x64' ):
-		curl_lib = [ '#linux/libcurl/lib64/libcurl.a' ]
-
-
-VariantDir( g_build + '/core', '.', duplicate = 0 )
-thedarkmod = SConscript( g_build + '/core/sys/scons/SConscript.darkmod' )
-
-exe_name = 'thedarkmod.' + ('x64' if TARGET_ARCH == 'x64' else cpu)
+if NOCURL == "0":
+    # 1: debug, 2: release
+    if BUILD == "release":
+        local_curl = 2
+    else:
+        local_curl = 1
+    Export("GLOBALS " + GLOBALS)
+    if TARGET_ARCH == "x86":
+        curl_lib = ["#linux/libcurl/libcurl.a"]  # Use the static one built for TDM
+    if TARGET_ARCH == "x64":
+        curl_lib = ["#linux/libcurl/lib64/libcurl.a"]
+
+
+VariantDir(g_build + "/core", ".", duplicate=0)
+thedarkmod = SConscript(g_build + "/core/sys/scons/SConscript.darkmod")
+
+exe_name = "thedarkmod." + ("x64" if TARGET_ARCH == "x64" else cpu)
 # Note: this target only runs if you append ".." (without quotes) as the last argument to scons command line
 # It copies executable into ../darkmod, which is default location of darkmod installation in development environment
-InstallAs( '../darkmod/' + exe_name, thedarkmod )
+InstallAs("../darkmod/" + exe_name, thedarkmod)
 # this runs always and produces TDM binary in local directory
-if ( BUILD == 'release' ):	# strip debug info in release
-	Command(exe_name, thedarkmod, "strip $SOURCE -o $TARGET")
+if BUILD == "release":  # strip debug info in release
+    Command(exe_name, thedarkmod, "strip $SOURCE -o $TARGET")
 else:
-	InstallAs( '#' + exe_name, thedarkmod )
+    InstallAs("#" + exe_name, thedarkmod)
 
 # end targets ------------------------------------
diff --git a/sys/scons/scons_utils.py b/sys/scons/scons_utils.py
index 377562c16..6593f64eb 100644
--- a/sys/scons/scons_utils.py
+++ b/sys/scons/scons_utils.py
@@ -1,189 +1,201 @@
 # -*- mode: python -*-
-import sys, os, string, time, commands, re, pickle, StringIO, popen2, commands, pdb, zipfile, tempfile
+import sys, os, time, subprocess, re, pickle, io, subprocess, pdb, zipfile, tempfile
 import SCons
 
 # need an Environment and a matching buffered_spawn API .. encapsulate
 class idBuffering:
-	silent = False
-
-	def buffered_spawn( self, sh, escape, cmd, args, env ):
-		stderr = StringIO.StringIO()
-		stdout = StringIO.StringIO()
-		command_string = ''
-		for i in args:
-			if ( len( command_string ) ):
-				command_string += ' '
-			command_string += i
-		try:
-			retval = self.env['PSPAWN']( sh, escape, cmd, args, env, stdout, stderr )
-		except OSError, x:
-			if x.errno != 10:
-				raise x
-			print 'OSError ignored on command: %s' % command_string
-			retval = 0
-		print command_string
-		if ( retval != 0 or not self.silent ):
-			sys.stdout.write( stdout.getvalue() )
-			sys.stderr.write( stderr.getvalue() )
-		return retval		
+    silent = False
+
+    def buffered_spawn(self, sh, escape, cmd, args, env):
+        stderr = io.StringIO()
+        stdout = io.StringIO()
+        command_string = ""
+        for i in args:
+            if len(command_string):
+                command_string += " "
+            command_string += i
+        try:
+            retval = self.env["PSPAWN"](sh, escape, cmd, args, env, stdout, stderr)
+        except OSError as x:
+            if x.errno != 10:
+                raise x
+            print("OSError ignored on command: %s" % command_string)
+            retval = 0
+        print(command_string)
+        if retval != 0 or not self.silent:
+            sys.stdout.write(stdout.getvalue())
+            sys.stderr.write(stderr.getvalue())
+        return retval
+
 
 class idSetupBase:
-	
-	def SimpleCommand( self, cmd ):
-		print cmd
-		ret = commands.getstatusoutput( cmd )
-		if ( len( ret[ 1 ] ) ):
-			sys.stdout.write( ret[ 1 ] )
-			sys.stdout.write( '\n' )
-		if ( ret[ 0 ] != 0 ):
-			raise 'command failed'
-		return ret[ 1 ]
-
-	def TrySimpleCommand( self, cmd ):
-		print cmd
-		ret = commands.getstatusoutput( cmd )
-		sys.stdout.write( ret[ 1 ] )
-
-	def M4Processing( self, file, d ):
-		file_out = file[:-3]
-		cmd = 'm4 '
-		for ( key, val ) in d.items():
-			cmd += '--define=%s="%s" ' % ( key, val )
-		cmd += '%s > %s' % ( file, file_out )
-		self.SimpleCommand( cmd )	
-
-	def ExtractProtocolVersion( self ):
-		f = open( 'framework/Licensee.h' )
-		l = f.readlines()
-		f.close()
-
-		major = 'X'
-		p = re.compile( '^#define ASYNC_PROTOCOL_MAJOR\t*(.*)' )
-		for i in l:
-			if ( p.match( i ) ):
-				major = p.match( i ).group(1)
-				break
-
-		f = open( 'framework/async/AsyncNetwork.h' )
-		l = f.readlines()
-		f.close()
-
-		minor = 'X'
-		p = re.compile( '^const int ASYNC_PROTOCOL_MINOR\t*= (.*);' )
-		for i in l:
-			if ( p.match( i ) ):
-				minor = p.match( i ).group(1)
-				break	
-	
-		return '%s.%s' % ( major, minor )
-
-	def ExtractEngineVersion( self ):
-		f = open( 'framework/Licensee.h' )
-		l = f.readlines()
-		f.close()
-
-		version = 'X'
-		p = re.compile( '^#define.*ENGINE_VERSION\t*"DOOM (.*)"' )
-		for i in l:
-			if ( p.match( i ) ):
-				version = p.match( i ).group(1)
-				break
-	
-		return version
-
-	def ExtractBuildVersion( self ):
-		f = open( 'framework/BuildVersion.h' )
-		l = f.readlines()[ 4 ]
-		f.close()
-		pat = re.compile( '.* = (.*);\n' )
-		return pat.split( l )[ 1 ]
-
-def checkLDD( target, source, env ):
-	file = target[0]
-	if (not os.path.isfile(file.abspath)):
-		print('ERROR: CheckLDD: target %s not found\n' % target[0])
-		Exit(1)
-	( status, output ) = commands.getstatusoutput( 'ldd -r %s' % file )
-	if ( status != 0 ):
-		print 'ERROR: ldd command returned with exit code %d' % ldd_ret
-		os.system( 'rm %s' % target[ 0 ] )
-		sys.exit(1)
-	lines = string.split( output, '\n' )
-	have_undef = 0
-	for i_line in lines:
-		#print repr(i_line)
-		regex = re.compile('undefined symbol: (.*)\t\\((.*)\\)')
-		if ( regex.match(i_line) ):
-			symbol = regex.sub('\\1', i_line)
-			try:
-				env['ALLOWED_SYMBOLS'].index(symbol)
-			except:
-				have_undef = 1
-	if ( have_undef ):
-		print output
-		print "ERROR: undefined symbols"
-		os.system('rm %s' % target[0])
-		sys.exit(1)
-
-def SharedLibrarySafe( env, target, source ):
-	ret = env.SharedLibrary( target, source )
-	env.AddPostAction( ret, checkLDD )
-	return ret
-
-def NotImplementedStub( *whatever ):
-	print 'Not Implemented'
-	sys.exit( 1 )
+    def SimpleCommand(self, cmd):
+        print(cmd)
+        ret = subprocess.getstatusoutput(cmd)
+        if len(ret[1]):
+            sys.stdout.write(ret[1])
+            sys.stdout.write("\n")
+        if ret[0] != 0:
+            raise RuntimeError("command failed")
+        return ret[1]
+
+    def TrySimpleCommand(self, cmd):
+        print(cmd)
+        ret = subprocess.getstatusoutput(cmd)
+        sys.stdout.write(ret[1])
+
+    def M4Processing(self, file, d):
+        file_out = file[:-3]
+        cmd = "m4 "
+        for (key, val) in list(d.items()):
+            cmd += '--define=%s="%s" ' % (key, val)
+        cmd += "%s > %s" % (file, file_out)
+        self.SimpleCommand(cmd)
+
+    def ExtractProtocolVersion(self):
+        f = open("framework/Licensee.h")
+        l = f.readlines()
+        f.close()
+
+        major = "X"
+        p = re.compile("^#define ASYNC_PROTOCOL_MAJOR\t*(.*)")
+        for i in l:
+            if p.match(i):
+                major = p.match(i).group(1)
+                break
+
+        f = open("framework/async/AsyncNetwork.h")
+        l = f.readlines()
+        f.close()
+
+        minor = "X"
+        p = re.compile("^const int ASYNC_PROTOCOL_MINOR\t*= (.*);")
+        for i in l:
+            if p.match(i):
+                minor = p.match(i).group(1)
+                break
+
+        return "%s.%s" % (major, minor)
+
+    def ExtractEngineVersion(self):
+        f = open("framework/Licensee.h")
+        l = f.readlines()
+        f.close()
+
+        version = "X"
+        p = re.compile('^#define.*ENGINE_VERSION\t*"DOOM (.*)"')
+        for i in l:
+            if p.match(i):
+                version = p.match(i).group(1)
+                break
+
+        return version
+
+    def ExtractBuildVersion(self):
+        f = open("framework/BuildVersion.h")
+        l = f.readlines()[4]
+        f.close()
+        pat = re.compile(".* = (.*);\n")
+        return pat.split(l)[1]
+
+
+def checkLDD(target, source, env):
+    file = target[0]
+    if not os.path.isfile(file.abspath):
+        print(("ERROR: CheckLDD: target %s not found\n" % target[0]))
+        Exit(1)
+    (status, output) = subprocess.getstatusoutput("ldd -r %s" % file)
+    if status != 0:
+        print("ERROR: ldd command returned with exit code %d" % ldd_ret)
+        os.system("rm %s" % target[0])
+        sys.exit(1)
+    lines = output.split("\n")
+    have_undef = 0
+    for i_line in lines:
+        # print repr(i_line)
+        regex = re.compile("undefined symbol: (.*)\t\\((.*)\\)")
+        if regex.match(i_line):
+            symbol = regex.sub("\\1", i_line)
+            try:
+                env["ALLOWED_SYMBOLS"].index(symbol)
+            except:
+                have_undef = 1
+    if have_undef:
+        print(output)
+        print("ERROR: undefined symbols")
+        os.system("rm %s" % target[0])
+        sys.exit(1)
+
+
+def SharedLibrarySafe(env, target, source):
+    ret = env.SharedLibrary(target, source)
+    env.AddPostAction(ret, checkLDD)
+    return ret
+
+
+def NotImplementedStub(*whatever):
+    print("Not Implemented")
+    sys.exit(1)
+
 
 # --------------------------------------------------------------------
 
-class idGamePaks( idSetupBase ):
-
-	def BuildGamePak( self, target = None, source = None, env = None ):
-		# NOTE: ew should have done with zipfile module
-		temp_dir = tempfile.mkdtemp( prefix = 'gamepak' )
-		# source[0] is the binary path of the game DLL
-		# source[2] is the DLL name 'gamex64.so'
-		dllName = source[2].name
-		self.SimpleCommand( 'cp %s %s' % ( source[0].abspath, os.path.join( temp_dir, dllName ) ) )
-		self.SimpleCommand( 'strip %s' % os.path.join( temp_dir, dllName ) )
-		self.SimpleCommand( 'echo 2 > %s' % ( os.path.join( temp_dir, 'binary.conf' ) ) )
-		self.SimpleCommand( 'cd %s ; zip %s %s binary.conf' % ( temp_dir, os.path.join( temp_dir, target[0].abspath ), dllName ) )
-		self.SimpleCommand( 'rm -r %s' % temp_dir )
-		return None
+
+class idGamePaks(idSetupBase):
+    def BuildGamePak(self, target=None, source=None, env=None):
+        # NOTE: ew should have done with zipfile module
+        temp_dir = tempfile.mkdtemp(prefix="gamepak")
+        # source[0] is the binary path of the game DLL
+        # source[2] is the DLL name 'gamex64.so'
+        dllName = source[2].name
+        self.SimpleCommand(
+            "cp %s %s" % (source[0].abspath, os.path.join(temp_dir, dllName))
+        )
+        self.SimpleCommand("strip %s" % os.path.join(temp_dir, dllName))
+        self.SimpleCommand("echo 2 > %s" % (os.path.join(temp_dir, "binary.conf")))
+        self.SimpleCommand(
+            "cd %s ; zip %s %s binary.conf"
+            % (temp_dir, os.path.join(temp_dir, target[0].abspath), dllName)
+        )
+        self.SimpleCommand("rm -r %s" % temp_dir)
+        return None
+
 
 # --------------------------------------------------------------------
 
 # get a clean error output when running multiple jobs
-def SetupBufferedOutput( env, silent ):
-	buf = idBuffering()
-	buf.silent = silent
-	buf.env = env
-	env['SPAWN'] = buf.buffered_spawn
+def SetupBufferedOutput(env, silent):
+    buf = idBuffering()
+    buf.silent = silent
+    buf.env = env
+    env["SPAWN"] = buf.buffered_spawn
+
 
 # setup utilities on an environement
-def SetupUtils( env ):
-	gamepaks = idGamePaks()
-	env.BuildGamePak = gamepaks.BuildGamePak
-	env.SharedLibrarySafe = SharedLibrarySafe
-	# no longer used by TDM
-	env.PreBuildSDK = NotImplementedStub
-	env.BuildSDK = NotImplementedStub
-	env.BuildSetup = NotImplementedStub
-
-def BuildList( s_prefix, s_string ):
-	s_list = string.split( s_string )
-	for i in range( len( s_list ) ):
-		s_list[i] = os.path.join(s_prefix, s_list[i])
-	return s_list
+def SetupUtils(env):
+    gamepaks = idGamePaks()
+    env.BuildGamePak = gamepaks.BuildGamePak
+    env.SharedLibrarySafe = SharedLibrarySafe
+    # no longer used by TDM
+    env.PreBuildSDK = NotImplementedStub
+    env.BuildSDK = NotImplementedStub
+    env.BuildSetup = NotImplementedStub
 
-def CloneWithoutOptimization(env, opt_level):
-	res = env.Clone()
-	try:
-		res['CPPFLAGS'].remove('-O3')
-	except:
-		print('Error: -O3 not found in CPPFLAGS, optimization not suppressed.')
-		pass
-	if opt_level is not None:
-		res.Append(CPPFLAGS = opt_level)
-	return res
 
+def BuildList(s_prefix, s_string):
+    s_list = s_string.split()
+    for i in range(len(s_list)):
+        s_list[i] = os.path.join(s_prefix, s_list[i])
+    return s_list
+
+
+def CloneWithoutOptimization(env, opt_level):
+    res = env.Clone()
+    try:
+        res["CPPFLAGS"].remove("-O3")
+    except:
+        print("Error: -O3 not found in CPPFLAGS, optimization not suppressed.")
+        pass
+    if opt_level is not None:
+        res.Append(CPPFLAGS=opt_level)
+    return res
diff --git a/tdm_update/SConstruct b/tdm_update/SConstruct
index 6d12703e2..119bc3c7c 100644
--- a/tdm_update/SConstruct
+++ b/tdm_update/SConstruct
@@ -1,32 +1,32 @@
 # -*- mode: python -*-
 # coding=utf-8
 
-#*****************************************************************************
+# *****************************************************************************
 #                    The Dark Mod GPL Source Code
-# 
-# This file is part of the The Dark Mod Source Code, originally based 
+#
+# This file is part of the The Dark Mod Source Code, originally based
 # on the Doom 3 GPL Source Code as published in 2011.
-# 
-# The Dark Mod Source Code is free software: you can redistribute it 
-# and/or modify it under the terms of the GNU General Public License as 
-# published by the Free Software Foundation, either version 3 of the License, 
+#
+# The Dark Mod Source Code is free software: you can redistribute it
+# and/or modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the License,
 # or (at your option) any later version. For details, see LICENSE.TXT.
-# 
+#
 # Project: The Dark Mod Updater & Packager (http://www.thedarkmod.com/)
-# 
-#*****************************************************************************
+#
+# *****************************************************************************
 
 # The Dark Mod Updater & Packager build script for Linux
 # Based on id's game sconscript
 # Author: greebo
 
-import sys, os, time, commands, re, pickle, StringIO, commands, pdb, string
+import sys, os, time, subprocess, re, pickle, io, subprocess, pdb, string
 import SCons
 import scons_utils
 
 # choose configuration variables which should be saved between runs
 # ( we handle all those as strings )
-serialized=['CC', 'CXX', 'JOBS', 'BUILD', 'TARGET_ARCH']
+serialized = ["CC", "CXX", "JOBS", "BUILD", "TARGET_ARCH"]
 
 # global build mode ------------------------------
 
@@ -59,199 +59,211 @@ TARGET_ARCH (default: "x86")
 
 """
 
-Help( help_string )
+Help(help_string)
 
 # end help ---------------------------------------
 
 # sanity -----------------------------------------
 
-EnsureSConsVersion( 0, 98 )
+EnsureSConsVersion(0, 98)
 
 # end sanity -------------------------------------
 
 # system detection -------------------------------
 
 # CPU type
-cpu = commands.getoutput('uname -m')
-exp = re.compile('.*i?86.*')
+cpu = subprocess.getoutput("uname -m")
+exp = re.compile(".*i?86.*")
 if exp.match(cpu):
-	cpu = 'x86'
+    cpu = "x86"
 else:
-	cpu = commands.getoutput('uname -p')
-	if ( cpu == 'powerpc' ):
-		cpu = 'ppc'
-	elif ( cpu == 'amd64' ):
-		# leave as is
-		pass
-	else:
-		cpu = 'cpu'
-
-if sys.platform == 'darwin':
-	g_os = 'MacOSX'
-elif sys.platform == 'freebsd10':
-	# taaaki: only tested on FreeBSD 10 so far
-	g_os = 'FreeBSD'
+    cpu = subprocess.getoutput("uname -p")
+    if cpu == "powerpc":
+        cpu = "ppc"
+    elif cpu == "amd64":
+        # leave as is
+        pass
+    else:
+        cpu = "cpu"
+
+if sys.platform == "darwin":
+    g_os = "MacOSX"
+elif sys.platform == "freebsd10":
+    # taaaki: only tested on FreeBSD 10 so far
+    g_os = "FreeBSD"
 else:
-	g_os = 'Linux'
+    g_os = "Linux"
 
 # end system detection ---------------------------
 
 # default settings -------------------------------
 
-CC = 'gcc'
-CXX = 'g++'
-if g_os == 'FreeBSD':
-	# FreeBSD 10 uses Clang instead of GCC
-	CC = 'cc'
-	CXX = 'c++'
-JOBS = '1'
-BUILD = 'release'
-BASEFLAGS = ''
-TARGET_ARCH = 'x86'
+CC = "gcc"
+CXX = "g++"
+if g_os == "FreeBSD":
+    # FreeBSD 10 uses Clang instead of GCC
+    CC = "cc"
+    CXX = "c++"
+JOBS = "1"
+BUILD = "release"
+BASEFLAGS = ""
+TARGET_ARCH = "x86"
 
 # end default settings ---------------------------
 
 # command line settings --------------------------
 
-for k in ARGUMENTS.keys():
-	exec_cmd = k + '=\'' + ARGUMENTS[k] + '\''
-	print 'Command line: ' + exec_cmd
-	exec( exec_cmd )
+for k in list(ARGUMENTS.keys()):
+    exec_cmd = k + "='" + ARGUMENTS[k] + "'"
+    print("Command line: " + exec_cmd)
+    exec(exec_cmd)
 
-if TARGET_ARCH == 'x32':
-	TARGET_ARCH = 'x86'
+if TARGET_ARCH == "x32":
+    TARGET_ARCH = "x86"
 
 # end command line settings ----------------------
 
 # general configuration, target selection --------
 
-BUILD_ROOT = 'build'
-g_build = BUILD_ROOT + '/scons_' + TARGET_ARCH + '/' + BUILD
+BUILD_ROOT = "build"
+g_build = BUILD_ROOT + "/scons_" + TARGET_ARCH + "/" + BUILD
 
-SConsignFile( 'scons.signatures' )
-Decider('MD5-timestamp')
+SConsignFile("scons.signatures")
+Decider("MD5-timestamp")
 
-SetOption('num_jobs', JOBS)
+SetOption("num_jobs", JOBS)
 
 LINK = CXX
 
 # common flags
-BASECPPFLAGS = [ ]
-CORECPPPATH = [ ]
-CORELIBPATH = [ ]
-CORECPPFLAGS = [ ]
-BASELINKFLAGS = [ ]
+BASECPPFLAGS = []
+CORECPPPATH = []
+CORELIBPATH = []
+CORECPPFLAGS = []
+BASELINKFLAGS = []
 
 # for release build, further optimisations that may not work on all files
-OPTCPPFLAGS = [ ]
+OPTCPPFLAGS = []
 
-BASECPPFLAGS.append( BASEFLAGS )
-BASECPPFLAGS.append( '-pipe' )
+BASECPPFLAGS.append(BASEFLAGS)
+BASECPPFLAGS.append("-pipe")
 # warn all
-BASECPPFLAGS.append( '-Wall' )
+BASECPPFLAGS.append("-Wall")
 # Use C++11 features
-BASECPPFLAGS.append( '-std=c++11' )
-if ( g_os == 'Linux' ):
-	# Use old ABI for std::string and std::list (which is not fully compliant with C++11)
-	# This allows to link with C++ libraries, which were built in older versions of GCC
-	BASECPPFLAGS.append( '-D_GLIBCXX_USE_CXX11_ABI=0' )
+BASECPPFLAGS.append("-std=c++11")
+if g_os == "Linux":
+    # Use old ABI for std::string and std::list (which is not fully compliant with C++11)
+    # This allows to link with C++ libraries, which were built in older versions of GCC
+    BASECPPFLAGS.append("-D_GLIBCXX_USE_CXX11_ABI=0")
 
 # Don't throw warnings for unknown pragmas (used by VC++)
-BASECPPFLAGS.append('-Wno-unknown-pragmas')
+BASECPPFLAGS.append("-Wno-unknown-pragmas")
 
 # this define is necessary to make sure threading support is enabled in X
-CORECPPFLAGS.append( '-DXTHREADS' )
+CORECPPFLAGS.append("-DXTHREADS")
 
 # don't wrap gcc messages
-BASECPPFLAGS.append( '-fmessage-length=0' )
-
-if ( TARGET_ARCH == 'x86' ):
-	BASECPPFLAGS.append( '-m32' )
-	BASELINKFLAGS.append( '-m32' )
-if ( TARGET_ARCH == 'x64' ):
-	BASECPPFLAGS.append( '-m64' )
-	BASELINKFLAGS.append( '-m64' )
-
-if g_os == 'Linux':
-	BASELINKFLAGS.append( '-pthread' )
-	BASELINKFLAGS.append( '-lrt' )
-	# Add the __linux__ define
-	BASECPPFLAGS.append('-D__linux__')
-elif g_os == 'FreeBSD':
-	# FreeBSD 10
-	BASELINKFLAGS.append( '-L/usr/local/lib' )
-	BASELINKFLAGS.append( '-pthread' )
-	BASELINKFLAGS.append( '-lrt' )
- 	# Add the __linux__ define - leave as is even though it isn't true
-	BASECPPFLAGS.append('-D__linux__')
-elif g_os == 'MacOSX':
-	# Mac OS X
-	BASECPPFLAGS.append('-DMACOS_X')
-	if TARGET_ARCH == 'x86':
-		# Perform an Intel build
-		BASECPPFLAGS.append(['-arch', 'i386', '-D__i386__'])
-		BASELINKFLAGS.append(['-arch', 'i386'])
-	elif TARGET_ARCH == 'ppc':
-		# Perform a PowerPC build
-		BASECPPFLAGS.append(['-arch', 'ppc', '-D__ppc__'])
-		BASELINKFLAGS.append(['-arch', 'ppc'])
-
-if ( BUILD == 'debug' ):
-	OPTCPPFLAGS = [ '-g', '-O1', '-D_DEBUG' ]
-elif ( BUILD == 'release' ):
-	OPTCPPFLAGS = [ '-O2' ]
+BASECPPFLAGS.append("-fmessage-length=0")
+
+if TARGET_ARCH == "x86":
+    BASECPPFLAGS.append("-m32")
+    BASELINKFLAGS.append("-m32")
+if TARGET_ARCH == "x64":
+    BASECPPFLAGS.append("-m64")
+    BASELINKFLAGS.append("-m64")
+
+if g_os == "Linux":
+    BASELINKFLAGS.append("-pthread")
+    BASELINKFLAGS.append("-lrt")
+    # Add the __linux__ define
+    BASECPPFLAGS.append("-D__linux__")
+elif g_os == "FreeBSD":
+    # FreeBSD 10
+    BASELINKFLAGS.append("-L/usr/local/lib")
+    BASELINKFLAGS.append("-pthread")
+    BASELINKFLAGS.append("-lrt")
+    # Add the __linux__ define - leave as is even though it isn't true
+    BASECPPFLAGS.append("-D__linux__")
+elif g_os == "MacOSX":
+    # Mac OS X
+    BASECPPFLAGS.append("-DMACOS_X")
+    if TARGET_ARCH == "x86":
+        # Perform an Intel build
+        BASECPPFLAGS.append(["-arch", "i386", "-D__i386__"])
+        BASELINKFLAGS.append(["-arch", "i386"])
+    elif TARGET_ARCH == "ppc":
+        # Perform a PowerPC build
+        BASECPPFLAGS.append(["-arch", "ppc", "-D__ppc__"])
+        BASELINKFLAGS.append(["-arch", "ppc"])
+
+if BUILD == "debug":
+    OPTCPPFLAGS = ["-g", "-O1", "-D_DEBUG"]
+elif BUILD == "release":
+    OPTCPPFLAGS = ["-O2"]
 else:
-	print 'Unknown build configuration ' + BUILD
-	sys.exit(0)
+    print("Unknown build configuration " + BUILD)
+    sys.exit(0)
 
 # create the build environements
-g_base_env = Environment( ENV = os.environ, CC = CC, CXX = CXX, LINK = LINK, CPPFLAGS = BASECPPFLAGS, LINKFLAGS = BASELINKFLAGS, CPPPATH = CORECPPPATH, LIBPATH = CORELIBPATH )
+g_base_env = Environment(
+    ENV=os.environ,
+    CC=CC,
+    CXX=CXX,
+    LINK=LINK,
+    CPPFLAGS=BASECPPFLAGS,
+    LINKFLAGS=BASELINKFLAGS,
+    CPPPATH=CORECPPPATH,
+    LIBPATH=CORELIBPATH,
+)
 
 # use includes from fbsd userland before darkmod includes
 # note: used only on TDM server
-if g_os == 'FreeBSD':
-	g_base_env.Append(CPPPATH = '/usr/local/include')
+if g_os == "FreeBSD":
+    g_base_env.Append(CPPPATH="/usr/local/include")
 
-g_base_env.Append(CPPPATH = '#/')
-path_template = '#/../ThirdParty/artefacts/{0}/include'
-g_base_env.Append(CPPPATH = path_template.format('zlib'))
-g_base_env.Append(CPPPATH = path_template.format('libcurl'))
-g_base_env.Append(CPPPATH = path_template.format('tinyformat'))
-g_base_env.Append(CPPPATH = '#/libtdm_update')
+g_base_env.Append(CPPPATH="#/")
+path_template = "#/../ThirdParty/artefacts/{0}/include"
+g_base_env.Append(CPPPATH=path_template.format("zlib"))
+g_base_env.Append(CPPPATH=path_template.format("libcurl"))
+g_base_env.Append(CPPPATH=path_template.format("tinyformat"))
+g_base_env.Append(CPPPATH="#/libtdm_update")
 
 g_env = g_base_env.Clone()
 
-g_env['CPPFLAGS'] += OPTCPPFLAGS
-g_env.Append( CPPFLAGS = '-fno-strict-aliasing' )
-g_env['CPPFLAGS'] += CORECPPFLAGS
+g_env["CPPFLAGS"] += OPTCPPFLAGS
+g_env.Append(CPPFLAGS="-fno-strict-aliasing")
+g_env["CPPFLAGS"] += CORECPPFLAGS
 
 # mark the globals
-GLOBALS = 'g_env g_os TARGET_ARCH libtdm_update_list'
+GLOBALS = "g_env g_os TARGET_ARCH libtdm_update_list"
 
 # end general configuration ----------------------
 
 # targets ----------------------------------------
 
 libtdm_update_list = None
-Export( 'GLOBALS ' + GLOBALS )
+Export("GLOBALS " + GLOBALS)
 
 # map this whole directory into build dir
-VariantDir( g_build, '.', duplicate = 0 )
+VariantDir(g_build, ".", duplicate=0)
 # map 'ThirdParty' dir from parent directory into 'ThirdParty' subdir
-VariantDir( g_build + '/ThirdParty', '../ThirdParty', duplicate = 0 )
-Export( 'GLOBALS ' + GLOBALS )
+VariantDir(g_build + "/ThirdParty", "../ThirdParty", duplicate=0)
+Export("GLOBALS " + GLOBALS)
 
 # build libraries
-libtdm_update_list = SConscript( g_build + '/SConscript.libtdm_update' )
-Export( 'GLOBALS ' + GLOBALS )
+libtdm_update_list = SConscript(g_build + "/SConscript.libtdm_update")
+Export("GLOBALS " + GLOBALS)
 
 # Build the updater
-tdm_update = SConscript(g_build + '/SConscript.tdm_update')
-InstallAs( '#' + scons_utils.ExecutableName('bin/tdm_update', g_os, TARGET_ARCH), tdm_update )
+tdm_update = SConscript(g_build + "/SConscript.tdm_update")
+InstallAs(
+    "#" + scons_utils.ExecutableName("bin/tdm_update", g_os, TARGET_ARCH), tdm_update
+)
 
 # Build the packager
-tdm_package = SConscript(g_build + '/SConscript.tdm_package')
-InstallAs( '#' + scons_utils.ExecutableName('bin/tdm_package', g_os, TARGET_ARCH), tdm_package )
+tdm_package = SConscript(g_build + "/SConscript.tdm_package")
+InstallAs(
+    "#" + scons_utils.ExecutableName("bin/tdm_package", g_os, TARGET_ARCH), tdm_package
+)
 
 # end targets ------------------------------------
-
diff --git a/tdm_update/scons_utils.py b/tdm_update/scons_utils.py
index b61bbc22f..1f144fce8 100644
--- a/tdm_update/scons_utils.py
+++ b/tdm_update/scons_utils.py
@@ -1,19 +1,20 @@
-import sys, os, string
+import sys, os
 
 def BuildList( s_prefix, s_string ):
-	s_list = string.split( s_string )
-	for i in range( len( s_list ) ):
-		s_list[i] = os.path.join(s_prefix, s_list[i])
-	return s_list
+    s_list = s_string.split()
+    for i in range( len( s_list ) ):
+        s_list[i] = os.path.join(s_prefix, s_list[i])
+    return s_list
+
 
 def ExecutableName(base_name, os, arch):
-	if os == 'Linux':
-		if arch == 'x86':
-			return base_name + '.linux'
-		elif arch == 'x64':
-			return base_name + '.linux64'
-	elif os == 'FreeBSD':
-		return base_name + '.fbsd'
-	elif os == 'MacOSX':
-		return base_name + '.macosx'
-	return base_name
+    if os == "Linux":
+        if arch == "x86":
+            return base_name + ".linux"
+        elif arch == "x64":
+            return base_name + ".linux64"
+    elif os == "FreeBSD":
+        return base_name + ".fbsd"
+    elif os == "MacOSX":
+        return base_name + ".macosx"
+    return base_name
scons-fix-python3-001.patch (43,655 bytes)   

Relationships

has duplicate 0005233 closedstgatilov COMPILING.txt is out of sync with the wiki and missing instructions for tdm_update 
has duplicate 0005232 closedstgatilov scons configuration files are not compatible with python3 [patch included] 

Activities

nbohr1more

nbohr1more

02.01.2023 16:05

developer   ~0015673

tdm_update is obsolete

The new tdm_installer tool uses cmake

Issue History

Date Modified Username Field Change
30.04.2020 15:37 t405 New Issue
30.04.2020 15:37 t405 File Added: scons-fix-python3-001.patch
30.04.2020 17:47 greebo Relationship added has duplicate 0005233
30.04.2020 17:48 greebo Relationship added has duplicate 0005232
02.01.2023 16:05 nbohr1more Note Added: 0015673
02.01.2023 16:06 nbohr1more Assigned To => stgatilov
02.01.2023 16:06 nbohr1more Status new => closed
02.01.2023 16:06 nbohr1more Resolution open => won't fix
02.01.2023 16:06 nbohr1more Fixed in Version => TDM 2.10