diff options
author | Hood Chatham <roberthoodchatham@gmail.com> | 2022-03-05 16:00:54 -0800 |
---|---|---|
committer | Hood Chatham <roberthoodchatham@gmail.com> | 2022-03-07 12:17:37 -0800 |
commit | 3e4d87b1ba76b245dcbf45bb26b1f7118861f286 (patch) | |
tree | 2abb65c7cb317f25565f8a1390fb7f01c2c6de32 /numpy/core/setup.py | |
parent | 64cfb046e86692daa1119ba1b1de2ab50d00afde (diff) | |
download | numpy-3e4d87b1ba76b245dcbf45bb26b1f7118861f286.tar.gz |
MAINT, BLD Fix math feature detection for wasm
The web assembly linker is strict about function types, it is unwilling
to link a function defined with signature say `double f(double, double)`
to an invocation with signature `void f(void)`. This causes trouble in
`numpy/core/setup.py` in the functions `check_math_capabilities` and
`check_mathlib`.
This patch fixes the problem by giving config.try_link the correct
function signatures for these functions. In particular I added a separate
header file with all the math declarations. It would be be possible to
just include 'math.h' but we also need to parse the declarations to figure
out how to call the functions. If f has arguments type1, type2, type3, we
want to call it like f((type1)0, (type2)0, (type3)0). Anyways it is easier
to parse the arguments out of our feature_detection_math.h than to worry
about the possibility that someone will have a differently formatted system
math.h. We do a test where we include both math.h and feature_detection_math.h
to ensure consistency between the signatures.
I also separated out the fcntl functions, backtrace and madvise, and strtold_l.
This is because they require separate headers. strtold_l requires testing both
with the locale.h header and with the xlocale.h header (this seems to vary even
among different linuxes). All of the functions I moved out of OPTIONAL_STDFUNCS
are absent on windows and some are absent on OSX so separating them out of the
OPTIONAL_STDFUNCS should mildly improve the speed of feature detection on mac
and windows (since they have all the functions remaining in OPTIONAL_STDFUNCS).
Diffstat (limited to 'numpy/core/setup.py')
-rw-r--r-- | numpy/core/setup.py | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/numpy/core/setup.py b/numpy/core/setup.py index f6b31075d..abc1b54b1 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -129,32 +129,48 @@ def win32_checks(deflist): deflist.append('FORCE_NO_LONG_DOUBLE_FORMATTING') def check_math_capabilities(config, ext, moredefs, mathlibs): - def check_func(func_name): - return config.check_func(func_name, libraries=mathlibs, - decl=True, call=True) - - def check_funcs_once(funcs_name): - decl = dict([(f, True) for f in funcs_name]) - st = config.check_funcs_once(funcs_name, libraries=mathlibs, - decl=decl, call=decl) + def check_func( + func_name, + decl=False, + headers=["feature_detection_math.h"], + ): + return config.check_func( + func_name, + libraries=mathlibs, + decl=decl, + call=True, + call_args=FUNC_CALL_ARGS[func_name], + headers=headers, + ) + + def check_funcs_once(funcs_name, headers=["feature_detection_math.h"]): + call = dict([(f, True) for f in funcs_name]) + call_args = dict([(f, FUNC_CALL_ARGS[f]) for f in funcs_name]) + st = config.check_funcs_once( + funcs_name, + libraries=mathlibs, + decl=False, + call=call, + call_args=call_args, + headers=headers, + ) if st: moredefs.extend([(fname2def(f), 1) for f in funcs_name]) return st - def check_funcs(funcs_name): + def check_funcs(funcs_name, headers=["feature_detection_math.h"]): # Use check_funcs_once first, and if it does not work, test func per # func. Return success only if all the functions are available - if not check_funcs_once(funcs_name): + if not check_funcs_once(funcs_name, headers=headers): # Global check failed, check func per func for f in funcs_name: - if check_func(f): + if check_func(f, headers=headers): moredefs.append((fname2def(f), 1)) return 0 else: return 1 #use_msvc = config.check_decl("_MSC_VER") - if not check_funcs_once(MANDATORY_FUNCS): raise SystemError("One of the required function to build numpy is not" " available (the list is %s)." % str(MANDATORY_FUNCS)) @@ -169,15 +185,34 @@ def check_math_capabilities(config, ext, moredefs, mathlibs): for f in OPTIONAL_STDFUNCS_MAYBE: if config.check_decl(fname2def(f), headers=["Python.h", "math.h"]): - OPTIONAL_STDFUNCS.remove(f) + if f in OPTIONAL_STDFUNCS: + OPTIONAL_STDFUNCS.remove(f) + else: + OPTIONAL_FILE_FUNCS.remove(f) + check_funcs(OPTIONAL_STDFUNCS) + check_funcs(OPTIONAL_FILE_FUNCS, headers=["feature_detection_stdio.h"]) + check_funcs(OPTIONAL_MISC_FUNCS, headers=["feature_detection_misc.h"]) + + for h in OPTIONAL_HEADERS: if config.check_func("", decl=False, call=False, headers=[h]): h = h.replace(".", "_").replace(os.path.sep, "_") moredefs.append((fname2def(h), 1)) + # Try with both "locale.h" and "xlocale.h" + locale_headers = [ + "stdlib.h", + "xlocale.h", + "feature_detection_locale.h", + ] + if not check_funcs(OPTIONAL_LOCALE_FUNCS, headers=locale_headers): + # It didn't work with xlocale.h, maybe it will work with locale.h? + locale_headers[1] = "locale.h" + check_funcs(OPTIONAL_LOCALE_FUNCS, headers=locale_headers) + for tup in OPTIONAL_INTRINSICS: headers = None if len(tup) == 2: @@ -398,20 +433,28 @@ def check_types(config_cmd, ext, build_dir): def check_mathlib(config_cmd): # Testing the C math library mathlibs = [] - mathlibs_choices = [[], ['m'], ['cpml']] - mathlib = os.environ.get('MATHLIB') + mathlibs_choices = [[], ["m"], ["cpml"]] + mathlib = os.environ.get("MATHLIB") if mathlib: - mathlibs_choices.insert(0, mathlib.split(',')) + mathlibs_choices.insert(0, mathlib.split(",")) for libs in mathlibs_choices: - if config_cmd.check_func("exp", libraries=libs, decl=True, call=True): + if config_cmd.check_func( + "log", + libraries=libs, + call_args="0", + decl="double log(double);", + call=True + ): mathlibs = libs break else: raise RuntimeError( "math library missing; rerun setup.py after setting the " - "MATHLIB env variable") + "MATHLIB env variable" + ) return mathlibs + def visibility_define(config): """Return the define value to use for NPY_VISIBILITY_HIDDEN (may be empty string).""" |