diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 41c3373..934ced0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,6 +23,7 @@ repos: entry: pylint language: system types: [python] + exclude: 'site_scons/' args: - --disable=C,R,W0613,W0511,W0212,W0201,W0311,W0106,W0603,W0621,W0703,E1136 - repo: local diff --git a/SConscript b/SConscript index c0ade46..192e26c 100644 --- a/SConscript +++ b/SConscript @@ -1,4 +1,4 @@ -Import('env', 'arch', 'zmq', 'cython_dependencies') +Import('env', 'envCython', 'arch', 'zmq') import shutil @@ -55,11 +55,7 @@ Depends('messaging/bridge.cc', services_h) # different target? #env.Program('messaging/demo', ['messaging/demo.cc'], LIBS=[messaging_lib, 'zmq']) - -env.Command(['messaging/messaging_pyx.so', 'messaging/messaging_pyx.cpp'], - cython_dependencies + [messaging_lib, 'messaging/messaging_pyx_setup.py', 'messaging/messaging_pyx.pyx', 'messaging/messaging.pxd'], - "cd " + messaging_dir.path + " && python3 messaging_pyx_setup.py build_ext --inplace") - +envCython.Program('messaging/messaging_pyx.so', 'messaging/messaging_pyx.pyx', LIBS=envCython["LIBS"]+[messaging_lib, "zmq"]) if GetOption('test'): env.Program('messaging/test_runner', ['messaging/test_runner.cc', 'messaging/msgq_tests.cc'], LIBS=[messaging_lib]) diff --git a/SConstruct b/SConstruct index e9de920..6cc7650 100644 --- a/SConstruct +++ b/SConstruct @@ -1,21 +1,17 @@ -import Cython -import distutils import os import subprocess -import sys +import sysconfig zmq = 'zmq' arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() -# Rebuild cython extensions if python, distutils, or cython change -cython_dependencies = [Value(v) for v in (sys.version, distutils.__version__, Cython.__version__)] -Export('cython_dependencies') cereal_dir = Dir('.') cpppath = [ cereal_dir, '/usr/lib/include', + sysconfig.get_paths()['include'], ] AddOption('--test', @@ -46,7 +42,28 @@ env = Environment( CFLAGS="-std=gnu11", CXXFLAGS="-std=c++1z", CPPPATH=cpppath, + CYTHONCFILESUFFIX=".cpp", + tools=["default", "cython"] ) Export('env', 'zmq', 'arch') + +envCython = env.Clone() +envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-deprecated-declarations"] + +python_libs = [] +if arch == "Darwin": + envCython["LINKFLAGS"] = ["-bundle", "-undefined", "dynamic_lookup"] +elif arch == "aarch64": + envCython["LINKFLAGS"] = ["-shared"] + + python_libs.append(os.path.basename(python_path)) +else: + envCython["LINKFLAGS"] = ["-pthread", "-shared"] + +envCython["LIBS"] = python_libs + +Export('envCython') + + SConscript(['SConscript']) diff --git a/messaging/messaging_pyx.pyx b/messaging/messaging_pyx.pyx index 8b3e847..467b5a2 100644 --- a/messaging/messaging_pyx.pyx +++ b/messaging/messaging_pyx.pyx @@ -7,11 +7,11 @@ from libcpp cimport bool from libc cimport errno -from messaging cimport Context as cppContext -from messaging cimport SubSocket as cppSubSocket -from messaging cimport PubSocket as cppPubSocket -from messaging cimport Poller as cppPoller -from messaging cimport Message as cppMessage +from messaging.messaging cimport Context as cppContext +from messaging.messaging cimport SubSocket as cppSubSocket +from messaging.messaging cimport PubSocket as cppPubSocket +from messaging.messaging cimport Poller as cppPoller +from messaging.messaging cimport Message as cppMessage class MessagingError(Exception): diff --git a/messaging/messaging_pyx_setup.py b/messaging/messaging_pyx_setup.py deleted file mode 100644 index 43dc9c9..0000000 --- a/messaging/messaging_pyx_setup.py +++ /dev/null @@ -1,58 +0,0 @@ -import os -import subprocess -import sysconfig -from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module - -from Cython.Build import cythonize -from Cython.Distutils import build_ext - -TICI = os.path.isfile('/TICI') - -def get_ext_filename_without_platform_suffix(filename): - name, ext = os.path.splitext(filename) - ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') - - if ext_suffix == ext: - return filename - - ext_suffix = ext_suffix.replace(ext, '') - idx = name.find(ext_suffix) - - if idx == -1: - return filename - else: - return name[:idx] + ext - - -class BuildExtWithoutPlatformSuffix(build_ext): - def get_ext_filename(self, ext_name): - filename = super().get_ext_filename(ext_name) - return get_ext_filename_without_platform_suffix(filename) - - -sourcefiles = ['messaging_pyx.pyx'] -extra_compile_args = ["-std=c++1z", "-Wno-nullability-completeness"] -libraries = ['zmq'] -ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg - -if ARCH == "aarch64" and not TICI: - # android - extra_compile_args += ["-Wno-deprecated-register"] - libraries += ['gnustl_shared'] - -setup(name='messaging', - cmdclass={'build_ext': BuildExtWithoutPlatformSuffix}, - ext_modules=cythonize( - Extension( - "messaging_pyx", - language="c++", - sources=sourcefiles, - extra_compile_args=extra_compile_args, - libraries=libraries, - extra_objects=[ - os.path.join(os.path.dirname(os.path.realpath(__file__)), '../', 'libmessaging.a'), - ] - ), - nthreads=4, - ), -) diff --git a/site_scons/site_tools/cython.py b/site_scons/site_tools/cython.py new file mode 100644 index 0000000..45ba797 --- /dev/null +++ b/site_scons/site_tools/cython.py @@ -0,0 +1,38 @@ +import SCons +from SCons.Action import Action + +cythonAction = Action("$CYTHONCOM") + +def create_builder(env): + try: + cython = env['BUILDERS']['Cython'] + except KeyError: + cython = SCons.Builder.Builder( + action = cythonAction, + emitter = {}, + suffix = cython_suffix_emitter, + single_source = 1 + ) + env['BUILDERS']['Cython'] = cython + return cython + +def cython_suffix_emitter(env, source): + return "$CYTHONCFILESUFFIX" + +def generate(env): + env["CYTHON"] = "cythonize" + env["CYTHONCOM"] = "$CYTHON $CYTHONFLAGS $SOURCE" + env["CYTHONCFILESUFFIX"] = ".cpp" + + c_file, _ = SCons.Tool.createCFileBuilders(env) + + c_file.suffix['.pyx'] = cython_suffix_emitter + c_file.add_action('.pyx', cythonAction) + + c_file.suffix['.py'] = cython_suffix_emitter + c_file.add_action('.py', cythonAction) + + create_builder(env) + +def exists(env): + return True