From b9ce326714d56bf0332657dab5d9254eb75f29d2 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Mon, 17 Apr 2023 05:23:19 +0300 Subject: [PATCH] wscript: rework waf script, add mod_options.txt support, synchronize with engine as much as possible --- wscript | 285 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 159 insertions(+), 126 deletions(-) diff --git a/wscript b/wscript index f125a186..46cc1510 100644 --- a/wscript +++ b/wscript @@ -2,16 +2,16 @@ # encoding: utf-8 # a1batross, mittorn, 2018 -from __future__ import print_function -from waflib import Logs, Context, Configure +from waflib import Build, Configure, Context, Logs import sys import os +import re VERSION = '2.4' -APPNAME = 'hlsdk-xash3d' +APPNAME = 'hlsdk-portable' top = '.' -Context.Context.line_just = 55 # should fit for everything on 80x26 +Context.Context.line_just = 60 # should fit for everything on 80x26 @Configure.conf def get_taskgen_count(self): @@ -20,45 +20,29 @@ def get_taskgen_count(self): return idx def options(opt): + opt.load('reconfigure compiler_optimizations xcompile compiler_cxx compiler_c clang_compilation_database strip_on_install msdev msvs msvc subproject') + grp = opt.add_option_group('Common options') grp.add_option('-8', '--64bits', action = 'store_true', dest = 'ALLOW64', default = False, help = 'allow targetting 64-bit engine(Linux/Windows/OSX x86 only) [default: %default]') + grp.add_option('--disable-werror', action = 'store_true', dest = 'DISABLE_WERROR', default = False, + help = 'disable compilation abort on warning') + grp.add_option('--enable-voicemgr', action = 'store_true', dest = 'USE_VOICEMGR', default = False, + help = 'Enable VOICE MANAGER') - grp.add_option('--enable-voicemgr', action = 'store_true', dest = 'VOICEMGR', default = False, - help = 'enable voice manager [default: %default]') - - grp.add_option('--disable-goldsrc-support', action = 'store_false', dest = 'GOLDSRC', default = True, - help = 'disable GoldSource engine support [default: %default]') - - opt.load('compiler_optimizations subproject') - - opt.add_subproject(['cl_dll', 'dlls']) - - opt.load('xcompile compiler_cxx compiler_c clang_compilation_database strip_on_install msdev msvs') - if sys.platform == 'win32': - opt.load('msvc') - opt.load('reconfigure') + opt.add_subproject('dlls') + opt.add_subproject('cl_dll') def configure(conf): - # Configuration - conf.env.GAMEDIR = 'valve' - conf.env.CLIENT_DIR = 'cl_dlls' - conf.env.SERVER_DIR = 'dlls' - conf.env.SERVER_NAME = 'hl' - conf.env.PREFIX = '' + conf.load('fwgslib reconfigure compiler_optimizations') - conf.load('fwgslib reconfigure compiler_optimizations enforce_pic') + # Force XP compatibility, all build targets should add subsystem=bld.env.MSVC_SUBSYSTEM + if conf.env.MSVC_TARGETS[0] == 'x86': + conf.env.MSVC_SUBSYSTEM = 'WINDOWS,5.01' + else: + conf.env.MSVC_SUBSYSTEM = 'WINDOWS' - enforce_pic = True # modern defaults - - conf.env.VOICEMGR = conf.options.VOICEMGR - conf.env.GOLDSRC = conf.options.GOLDSRC - - # Force XP compability, all build targets should add - # subsystem=bld.env.MSVC_SUBSYSTEM - # TODO: wrapper around bld.stlib, bld.shlib and so on? - conf.env.MSVC_SUBSYSTEM = 'WINDOWS,5.01' conf.env.MSVC_TARGETS = ['x86' if not conf.options.ALLOW64 else 'x64'] # Load compilers early @@ -71,108 +55,138 @@ def configure(conf): if conf.env.COMPILER_CC == 'msvc': conf.load('msvc_pdb') - conf.load('msvs msdev strip_on_install') - - if conf.env.DEST_OS == 'android': - conf.options.GOLDSRC = conf.env.GOLDSRC = False - conf.env.SERVER_NAME = 'server' # can't be any other name, until specified - elif conf.env.DEST_OS in ['nswitch', 'psvita']: - conf.options.GOLDSRC = conf.env.GOLDSRC = False - - if conf.env.MAGX: - enforce_pic = False + conf.load('msvs msdev subproject clang_compilation_database strip_on_install enforce_pic') + enforce_pic = True # modern defaults conf.check_pic(enforce_pic) # We restrict 64-bit builds ONLY for Win/Linux/OSX running on Intel architecture # Because compatibility with original GoldSrc - if conf.env.DEST_OS in ['win32', 'linux', 'darwin'] and conf.env.DEST_CPU in ['x86_64']: - conf.env.BIT32_ALLOW64 = conf.options.ALLOW64 - if not conf.env.BIT32_ALLOW64: - Logs.info('WARNING: will build engine for 32-bit target') + if conf.env.DEST_OS in ['win32', 'linux', 'darwin'] and conf.env.DEST_CPU == 'x86_64': + conf.env.BIT32_MANDATORY = not conf.options.ALLOW64 + if conf.env.BIT32_MANDATORY: + Logs.info('WARNING: will build game for 32-bit target') else: - conf.env.BIT32_ALLOW64 = True - conf.env.BIT32_MANDATORY = not conf.env.BIT32_ALLOW64 - conf.load('force_32bit library_naming') + conf.env.BIT32_MANDATORY = False - compiler_optional_flags = [ - '-fdiagnostics-color=always', - '-Werror=return-type', - '-Werror=parentheses', - '-Werror=vla', - '-Werror=tautological-compare', - '-Werror=duplicated-cond', - '-Werror=bool-compare', - '-Werror=bool-operation', - '-Wstrict-aliasing', - ] - - c_compiler_optional_flags = [ - '-Werror=implicit-function-declaration', - '-Werror=int-conversion', - '-Werror=implicit-int', - '-Werror=declaration-after-statement' - ] + conf.load('force_32bit') cflags, linkflags = conf.get_optimization_flags() + cxxflags = list(cflags) # optimization flags are common between C and C++ but we need a copy - # Here we don't differentiate C or C++ flags - if conf.options.LTO: - lto_cflags = { - 'msvc': ['/GL'], - 'gcc': ['-flto'], - 'clang': ['-flto'] - } - - lto_linkflags = { - 'msvc': ['/LTCG'], - 'gcc': ['-flto'], - 'clang': ['-flto'] - } - cflags += conf.get_flags_by_compiler(lto_cflags, conf.env.COMPILER_CC) - linkflags += conf.get_flags_by_compiler(lto_linkflags, conf.env.COMPILER_CC) - - if conf.options.POLLY: - polly_cflags = { - 'gcc': ['-fgraphite-identity'], - 'clang': ['-mllvm', '-polly'] - # msvc sosat :( - } - - cflags += conf.get_flags_by_compiler(polly_cflags, conf.env.COMPILER_CC) - - # And here C++ flags starts to be treated separately - cxxflags = list(cflags) - if conf.env.COMPILER_CC != 'msvc': - conf.check_cc(cflags=cflags, msg= 'Checking for required C flags') - conf.check_cxx(cxxflags=cflags, msg= 'Checking for required C++ flags') - - cflags += conf.filter_cflags(compiler_optional_flags + c_compiler_optional_flags, cflags) - cxxflags += conf.filter_cxxflags(compiler_optional_flags, cflags) - - # on the Switch and the PSVita, allow undefined symbols by default, - # which is needed for the dynamic loaders to work - # additionally, shared libs are linked without libc + # on the Switch, allow undefined symbols by default, which is needed for libsolder to work + # we'll specifically disallow them for the engine executable + # additionally, shared libs are linked without standard libs, we'll add those back in the engine wscript if conf.env.DEST_OS == 'nswitch': linkflags.remove('-Wl,--no-undefined') conf.env.append_unique('LINKFLAGS_cshlib', ['-nostdlib', '-nostartfiles']) conf.env.append_unique('LINKFLAGS_cxxshlib', ['-nostdlib', '-nostartfiles']) + # same on the vita elif conf.env.DEST_OS == 'psvita': - linkflags.remove('-Wl,--no-undefined') conf.env.append_unique('CFLAGS_cshlib', ['-fPIC']) conf.env.append_unique('CXXFLAGS_cxxshlib', ['-fPIC', '-fno-use-cxa-atexit']) conf.env.append_unique('LINKFLAGS_cshlib', ['-nostdlib', '-Wl,--unresolved-symbols=ignore-all']) conf.env.append_unique('LINKFLAGS_cxxshlib', ['-nostdlib', '-Wl,--unresolved-symbols=ignore-all']) + # check if we need to use irix linkflags + elif conf.env.DEST_OS == 'irix' and conf.env.COMPILER_CC == 'gcc': + linkflags.remove('-Wl,--no-undefined') + linkflags.append('-Wl,--unresolved-symbols=ignore-all') + # check if we're in a sgug environment + if 'sgug' in os.environ['LD_LIBRARYN32_PATH']: + linkflags.append('-lc') + + conf.check_cc(cflags=cflags, linkflags=linkflags, msg='Checking for required C flags') + conf.check_cxx(cxxflags=cxxflags, linkflags=linkflags, msg='Checking for required C++ flags') conf.env.append_unique('CFLAGS', cflags) conf.env.append_unique('CXXFLAGS', cxxflags) conf.env.append_unique('LINKFLAGS', linkflags) + if conf.env.COMPILER_CC != 'msvc' and not conf.options.DISABLE_WERROR: + opt_flags = [ + # '-Wall', '-Wextra', '-Wpedantic', + '-fdiagnostics-color=always', + + # stable diagnostics, forced to error, sorted + '-Werror=bool-compare', + '-Werror=bool-operation', + '-Werror=cast-align=strict', + '-Werror=duplicated-cond', + # '-Werror=format=2', + '-Werror=implicit-fallthrough=2', + # '-Werror=logical-op', + '-Werror=packed', + '-Werror=packed-not-aligned', + '-Werror=parentheses', + '-Werror=return-type', + '-Werror=sequence-point', + '-Werror=sizeof-pointer-memaccess', + '-Werror=sizeof-array-div', + '-Werror=sizeof-pointer-div', + # '-Werror=strict-aliasing', + '-Werror=string-compare', + '-Werror=tautological-compare', + '-Werror=use-after-free=3', + '-Werror=vla', + '-Werror=write-strings', + + # unstable diagnostics, may cause false positives + '-Winit-self', + '-Wmisleading-indentation', + '-Wunintialized', + + # disabled, flood + # '-Wdouble-promotion', + ] + + opt_cflags = [ + '-Werror=declaration-after-statement', + '-Werror=enum-conversion', + '-Werror=implicit-int', + '-Werror=implicit-function-declaration', + '-Werror=incompatible-pointer-types', + '-Werror=int-conversion', + '-Werror=jump-misses-init', + # '-Werror=old-style-declaration', + # '-Werror=old-style-definition', + # '-Werror=strict-prototypes', + '-fnonconst-initializers' # owcc + ] + + opt_cxxflags = [] # TODO: + + cflags = conf.filter_cflags(opt_flags + opt_cflags, cflags) + cxxflags = conf.filter_cxxflags(opt_flags + opt_cxxflags, cxxflags) + + conf.env.append_unique('CFLAGS', cflags) + conf.env.append_unique('CXXFLAGS', cxxflags) + + if conf.env.DEST_OS == 'android': + # LIB_M added in xcompile! + pass + elif conf.env.DEST_OS == 'win32': + a = [ 'user32', 'winmm' ] + if conf.env.COMPILER_CC == 'msvc': + for i in a: + conf.start_msg('Checking for MSVC library') + conf.check_lib_msvc(i) + conf.end_msg(i) + else: + for i in a: + conf.check_cc(lib = i) + else: + if conf.env.GOLDSOURCE_SUPPORT: + conf.check_cc(lib='dl') + conf.check_cc(lib='m') + # check if we can use C99 tgmath if conf.check_cc(header_name='tgmath.h', mandatory=False): + if conf.env.COMPILER_CC == 'msvc': + conf.define('_CRT_SILENCE_NONCONFORMING_TGMATH_H', 1) tgmath_usable = conf.check_cc(fragment='''#include - int main(void){ return (int)sin(2.0f); }''', - msg='Checking if tgmath.h is usable', mandatory=False) + const float val = 2, val2 = 3; + int main(void){ return (int)(-asin(val) + cos(val2)); }''', + msg='Checking if tgmath.h is usable', mandatory=False, use='M') conf.define_cond('HAVE_TGMATH_H', tgmath_usable) else: conf.undefine('HAVE_TGMATH_H') @@ -187,29 +201,48 @@ def configure(conf): elif conf.env.COMPILER_CC == 'owcc': pass else: - conf.env.append_unique('DEFINES', ['stricmp=strcasecmp', 'strnicmp=strncasecmp', '_snprintf=snprintf', '_vsnprintf=vsnprintf', '_LINUX', 'LINUX']) - conf.env.append_unique('CXXFLAGS', ['-Wno-invalid-offsetof', '-fno-rtti', '-fno-exceptions']) + conf.env.append_unique('CXXFLAGS', ['-Wno-invalid-offsetof', '-fno-exceptions']) + conf.define('stricmp', 'strcasecmp', quote=False) + conf.define('strnicmp', 'strncasecmp', quote=False) + conf.define('_snprintf', 'snprintf', quote=False) + conf.define('_vsnprintf', 'vsnprintf', quote=False) + conf.define('_LINUX', True) + conf.define('LINUX', True) + + conf.msg(msg='-> processing mod options', result='...', color='BLUE') + regex = re.compile('^([A-Za-z0-9_]+)=([A-Za-z0-9_]+)\ \#\ (.*)$') + with open('mod_options.txt') as fd: + lines = fd.readlines() + for line in lines: + p = regex.match(line.strip()) + if p: + conf.start_msg("* " + p[3]) + if p[2] == 'ON': + conf.env[p[1]] = True + conf.define(p[1], 1) + elif p[2] == 'OFF': + conf.env[p[1]] = False + conf.undefine(p[1]) + else: + conf.env[p[1]] = p[2] + conf.end_msg(p[2]) + if conf.env.HLDEMO_BUILD and conf.env.OEM_BUILD: + conf.fatal('Don\'t mix Demo and OEM builds!') # strip lib from pattern if conf.env.DEST_OS not in ['android']: - if conf.env.cshlib_PATTERN.startswith('lib'): - conf.env.cshlib_PATTERN = conf.env.cshlib_PATTERN[3:] if conf.env.cxxshlib_PATTERN.startswith('lib'): conf.env.cxxshlib_PATTERN = conf.env.cxxshlib_PATTERN[3:] - conf.define('BARNACLE_FIX_VISIBILITY', False) - conf.define('CLIENT_WEAPONS', True) - conf.define('CROWBAR_IDLE_ANIM', False) - conf.define('CROWBAR_DELAY_FIX', False) - conf.define('CROWBAR_FIX_RAPID_CROWBAR', False) - conf.define('GAUSS_OVERCHARGE_FIX', False) - conf.define('OEM_BUILD', False) - conf.define('HLDEMO_BUILD', False) - - conf.add_subproject(["cl_dll", "dlls"]) + conf.load('library_naming') + conf.add_subproject('dlls') + conf.add_subproject('cl_dll') def build(bld): - bld.add_subproject(["cl_dll", "dlls"]) - - + # don't clean QtCreator files and reconfigure saved options + bld.clean_files = bld.bldnode.ant_glob('**', + excl='*.user configuration.py .lock* *conf_check_*/** config.log %s/*' % Build.CACHE_DIR, + quiet=True, generator=True) + bld.add_subproject('dlls') + bld.add_subproject('cl_dll')