chelper: Set compiler flags to never use "x387" floating point math

The default on X86 32bit machines is to use 80bit floating point math
(as found in the ancient "387 coprocessor").  This can cause numerical
stability problems.  Set the compiler flags to make sure the newer SSE
math is always used on X86.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2020-09-15 17:04:40 -04:00
parent 054762da3d
commit a92d995727
1 changed files with 18 additions and 7 deletions

View File

@ -1,6 +1,6 @@
# Wrapper around C helper code # Wrapper around C helper code
# #
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net> # Copyright (C) 2016-2020 Kevin O'Connor <kevin@koconnor.net>
# #
# This file may be distributed under the terms of the GNU GPLv3 license. # This file may be distributed under the terms of the GNU GPLv3 license.
import os, logging import os, logging
@ -11,9 +11,11 @@ import cffi
# c_helper.so compiling # c_helper.so compiling
###################################################################### ######################################################################
COMPILE_CMD = ("gcc -Wall -g -O2 -shared -fPIC" GCC_CMD = "gcc"
" -flto -fwhole-program -fno-use-linker-plugin" COMPILE_ARGS = ("-Wall -g -O2 -shared -fPIC"
" -o %s %s") " -flto -fwhole-program -fno-use-linker-plugin"
" -o %s %s")
SSE_FLAGS = "-mfpmath=sse -msse2"
SOURCE_FILES = [ SOURCE_FILES = [
'pyhelper.c', 'serialqueue.c', 'stepcompress.c', 'itersolve.c', 'trapq.c', 'pyhelper.c', 'serialqueue.c', 'stepcompress.c', 'itersolve.c', 'trapq.c',
'kin_cartesian.c', 'kin_corexy.c', 'kin_corexz.c', 'kin_delta.c', 'kin_cartesian.c', 'kin_corexy.c', 'kin_corexz.c', 'kin_delta.c',
@ -190,7 +192,7 @@ def get_mtimes(srcdir, filelist):
# Check if the code needs to be compiled # Check if the code needs to be compiled
def check_build_code(srcdir, target, sources, cmd, other_files=[]): def check_build_code(srcdir, target, sources, cmd, other_files=[]):
src_times = get_mtimes(srcdir, sources + other_files) src_times = get_mtimes(srcdir, sources + other_files + [__file__])
obj_times = get_mtimes(srcdir, [target]) obj_times = get_mtimes(srcdir, [target])
if not obj_times or max(src_times) > min(obj_times): if not obj_times or max(src_times) > min(obj_times):
logging.info("Building C code module %s", target) logging.info("Building C code module %s", target)
@ -202,6 +204,12 @@ def check_build_code(srcdir, target, sources, cmd, other_files=[]):
logging.error(msg) logging.error(msg)
raise Exception(msg) raise Exception(msg)
def check_gcc_option(option):
cmd = "%s %s -S -o /dev/null -xc /dev/null > /dev/null 2>&1" % (
GCC_CMD, option)
res = os.system(cmd)
return res == 0
FFI_main = None FFI_main = None
FFI_lib = None FFI_lib = None
pyhelper_logging_callback = None pyhelper_logging_callback = None
@ -211,8 +219,11 @@ def get_ffi():
global FFI_main, FFI_lib, pyhelper_logging_callback global FFI_main, FFI_lib, pyhelper_logging_callback
if FFI_lib is None: if FFI_lib is None:
srcdir = os.path.dirname(os.path.realpath(__file__)) srcdir = os.path.dirname(os.path.realpath(__file__))
check_build_code(srcdir, DEST_LIB, SOURCE_FILES, COMPILE_CMD if check_gcc_option(SSE_FLAGS):
, OTHER_FILES) cmd = "%s %s %s" % (GCC_CMD, SSE_FLAGS, COMPILE_ARGS)
else:
cmd = "%s %s" % (GCC_CMD, COMPILE_ARGS)
check_build_code(srcdir, DEST_LIB, SOURCE_FILES, cmd, OTHER_FILES)
FFI_main = cffi.FFI() FFI_main = cffi.FFI()
for d in defs_all: for d in defs_all:
FFI_main.cdef(d) FFI_main.cdef(d)