diff --git a/public/wscript b/public/wscript index 170af699..c2f797dd 100644 --- a/public/wscript +++ b/public/wscript @@ -2,22 +2,111 @@ # encoding: utf-8 # mittorn, 2018 -from waflib import Logs +from waflib import Logs, Configure import os top = '.' +TGMATH_H_TEST = '''#include +const float val = 2, val2 = 3; +int main(void){ return (int)(-asin(val) + cos(val2)); }''' + +STRNCASECMP_TEST = '''#include +int main(int, char **argv) { return strncasecmp(argv[1], argv[2], 10); }''' + +STRCASECMP_TEST = '''#include +int main(int, char **argv) { return strcasecmp(argv[1], argv[2]); }''' + +STRCASESTR_TEST = '''#include +int main(int, char **argv) { argv[0] = strcasestr(argv[1], argv[2]); return 0; }''' + +STRCHRNUL_TEST = '''#include +int main(int, char **argv) { argv[2] = strchrnul(argv[1], 'x'); return 0; }''' + +STRLCPY_TEST = '''#include +int main(int, char **argv) { return strlcpy(argv[1], argv[2], 10); }''' + +STRLCAT_TEST = '''#include +int main(int, char **argv) { return strlcat(argv[1], argv[2], 10); }''' + +ALLOCA_TEST = '''#include <%s> +int main(void) { alloca(1); return 0; }''' + +HEADER_TEST = '''#include <%s> +int main(void) { return 0; } +''' + def options(opt): # stub return +def header_frag(header_name): + return '#include <%s>' % header_name + EMPTY_PROGRAM + +@Configure.conf +def export_define(conf, define, value=1): + if not value: + return + if value is True: + value = 1 # so python won't define it as string True + + conf.env.EXPORT_DEFINES_LIST += ['%s=%s' % (define, value)] + +@Configure.conf +def simple_check(conf, fragment, msg, mandatory=False, **kw): + return conf.check_cc(fragment=fragment, msg='Checking for %s' % msg, mandatory=mandatory, **kw) + def configure(conf): + # private to libpublic conf.load('gitversion') conf.define('XASH_BUILD_COMMIT', conf.env.GIT_VERSION if conf.env.GIT_VERSION else 'unknown-commit') conf.define('XASH_BUILD_BRANCH', conf.env.GIT_BRANCH if conf.env.GIT_BRANCH else 'unknown-branch') + # need to expose it for everyone using libpublic headers + conf.env.EXPORT_DEFINES_LIST = [] + conf.export_define('_CRT_SILENCE_NONCONFORMING_TGMATH_H', conf.env.COMPILER_CC == 'msvc') + conf.export_define('_GNU_SOURCE', conf.env.DEST_OS != 'win32') + + # create temporary uselib that just enables extensions + conf.env.DEFINES_export = list(conf.env.EXPORT_DEFINES_LIST) + + # check platform-specific header name for alloca(3) + if conf.simple_check(ALLOCA_TEST % 'alloca.h', msg='alloca in alloca.h'): + conf.export_define('ALLOCA_H', '') + elif conf.simple_check(ALLOCA_TEST % 'malloc.h', msg='alloca in malloc.h'): + conf.export_define('ALLOCA_H', '') + elif conf.simple_check(ALLOCA_TEST % 'stdlib.h', msg='alloca in stdlib.h'): + conf.export_define('ALLOCA_H', '') + + conf.export_define('STDINT_H', '' if conf.simple_check(HEADER_TEST % 'stdint.h', 'stdint.h') else '') + conf.export_define('HAVE_TGMATH_H', conf.simple_check(TGMATH_H_TEST, 'tgmath.h', use='M werror export')) + + # save some time on Windows, msvc is too slow + # these calls must be available with both msvc and mingw + if conf.env.DEST_OS == 'win32': + conf.export_define('HAVE_STRNICMP') + conf.export_define('HAVE_STRICMP') + conf.export_define('HAVE_STRISTR') + else: + # TODO: multicheck for speed + def check_libc_extension(frag, msg, define): + conf.export_define(define, conf.simple_check(frag, msg, use='werror export')) + + check_libc_extension(STRNCASECMP_TEST, 'strncasecmp', 'HAVE_STRNCASECMP') + check_libc_extension(STRCASECMP_TEST, 'strcasecmp', 'HAVE_STRCASECMP') + check_libc_extension(STRCASESTR_TEST, 'strcasestr', 'HAVE_STRCASESTR') + check_libc_extension(STRCHRNUL_TEST, 'strchrnul', 'HAVE_STRCHRNUL') + check_libc_extension(STRLCPY_TEST, 'strlcpy', 'HAVE_STRLCPY') + check_libc_extension(STRLCAT_TEST, 'strlcat', 'HAVE_STRLCAT') + + # kill temporary uselib + del conf.env.DEFINES_export + def build(bld): - bld(name = 'sdk_includes', export_includes = '. ../common ../pm_shared ../engine') + bld(name = 'sdk_includes', + export_includes = '. ../common ../pm_shared ../engine', + export_defines = bld.env.EXPORT_DEFINES_LIST) + bld.stlib(source = bld.path.ant_glob('*.c'), target = 'public', features = 'c', diff --git a/wscript b/wscript index 9a9a62d9..632ea06e 100644 --- a/wscript +++ b/wscript @@ -3,7 +3,7 @@ # a1batross, mittorn, 2018 from waflib import Build, Context, Logs -from waflib.Tools import waf_unit_test +from waflib.Tools import waf_unit_test, c_tests import sys import os @@ -379,18 +379,6 @@ def configure(conf): conf.define('XASH_GAMEDIR', conf.options.GAMEDIR) conf.define_cond('XASH_ALL_SERVERS', conf.options.ALL_SERVERS) - # check if we can use C99 stdint - conf.define('STDINT_H', 'stdint.h' if conf.check_cc(header_name='stdint.h', mandatory=False) else 'pstdint.h') - - # check if we can use alloca.h or malloc.h - if conf.check_cc(header_name='alloca.h', mandatory=False): - conf.define('ALLOCA_H', 'alloca.h') - elif conf.check_cc(header_name='malloc.h', mandatory=False): - conf.define('ALLOCA_H', 'malloc.h') - elif conf.check_cc(fragment = '''#include - int main(void) { alloca(1); }''', msg = 'Checking for alloca in stdlib.h'): - conf.define('ALLOCA_H', 'stdlib.h') - if conf.env.DEST_OS == 'nswitch': conf.check_cfg(package='solder', args='--cflags --libs', uselib_store='SOLDER') if conf.env.HAVE_SOLDER and conf.env.LIB_SOLDER and conf.options.BUILD_TYPE == 'debug': @@ -422,50 +410,10 @@ def configure(conf): 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 - 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 werror') - conf.define_cond('HAVE_TGMATH_H', tgmath_usable) - else: - conf.undefine('HAVE_TGMATH_H') - # set _FILE_OFFSET_BITS=64 for filesystems with 64-bit inodes - if conf.env.DEST_OS != 'win32' and conf.env.DEST_SIZEOF_VOID_P == 4: - # check was borrowed from libarchive source code - file_offset_bits_usable = conf.check_cc(fragment=''' -#define _FILE_OFFSET_BITS 64 -#include -#define KB ((off_t)1024) -#define MB ((off_t)1024 * KB) -#define GB ((off_t)1024 * MB) -#define TB ((off_t)1024 * GB) -int t2[(((64 * GB -1) % 671088649) == 268434537) - && (((TB - (64 * GB -1) + 255) % 1792151290) == 305159546)? 1: -1]; -int main(void) { return 0; }''', - msg='Checking if _FILE_OFFSET_BITS can be defined to 64', mandatory=False, use='werror') - if file_offset_bits_usable: - conf.define('_FILE_OFFSET_BITS', 64) - else: conf.undefine('_FILE_OFFSET_BITS') - - if conf.env.DEST_OS != 'win32': - strcasestr_frag = '''#include -int main(int argc, char **argv) { strcasestr(argv[1], argv[2]); return 0; }''' - strchrnul_frag = '''#include -int main(int argc, char **argv) { strchrnul(argv[1], 'x'); return 0; }''' - - def check_gnu_function(frag, msg, define): - if conf.check_cc(msg=msg, mandatory=False, fragment=frag, use='werror'): - conf.define(define, 1) - elif conf.check_cc(msg='... with _GNU_SOURCE?', mandatory=False, fragment=frag, defines='_GNU_SOURCE=1', use='werror'): - conf.define(define, 1) - conf.define('_GNU_SOURCE', 1) - check_gnu_function(strcasestr_frag, 'Checking for strcasestr', 'HAVE_STRCASESTR') - check_gnu_function(strchrnul_frag, 'Checking for strchrnul', 'HAVE_STRCHRNUL') + # must be set globally as it changes ABI + conf.check_large_file(compiler='c', fragment='''#include +int check[sizeof(off_t) >= 8 ? 1 : -1]; int main(void) { return 0; }''') # indicate if we are packaging for Linux/BSD conf.env.PACKAGING = conf.options.PACKAGING