cython - distutils vs cmake: linking against libpython?

  • Last Update :
  • Techknowledgy :

What I ended up doing for my own use, since I do not know if this is a completely portable solution, was to add a flag to that function to say DYNAMIC_LOOKUP:

function(cython_add_module _name _dynamic_lookup)
set(pyx_module_sources "")
set(other_module_sources "")
foreach(_file $ {
   ARGN
})
if ($ {
      _file
   }
   MATCHES ".*\\.py[x]?$")
   list(APPEND pyx_module_sources $ {
      _file
   })
else()
list(APPEND other_module_sources $ {
   _file
})
endif()
endforeach()
compile_pyx($ {
      _name
   }
   generated_file $ {
      pyx_module_sources
   })
include_directories($ {
   PYTHON_INCLUDE_DIRS
})
python_add_module($ {
      _name
   }
   $ {
      generated_file
   }
   $ {
      other_module_sources
   })
# # # Added here # #
if ($ {
      _dynamic_lookup
   })
   message(STATUS "Not linking target ${_name} against libpython")
set_target_properties($ {
      _name
   }
   PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
target_link_libraries($ {
      _name
   }
   $ {
      PYTHON_LIBRARIES
   })
endif()
endfunction()

Suggestion : 2

On Mar 23, 2013, at 6:56 PM, Matt McCormick wrote:

function(cython_add_module _name _dynamic_lookup)
set(pyx_module_sources "")
set(other_module_sources "")
foreach(_file $ {
   ARGN
})
if ($ {
      _file
   }
   MATCHES ".*\\.py[x]?$")
   list(APPEND pyx_module_sources $ {
      _file
   })
else()
list(APPEND other_module_sources $ {
   _file
})
endif()
endforeach()
compile_pyx($ {
      _name
   }
   generated_file $ {
      pyx_module_sources
   })
include_directories($ {
   PYTHON_INCLUDE_DIRS
})
python_add_module($ {
      _name
   }
   $ {
      generated_file
   }
   $ {
      other_module_sources
   })
if ($ {
      _dynamic_lookup
   })
   message(STATUS "Not linking target ${_name} against libpython")
set_target_properties($ {
      _name
   }
   PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
target_link_libraries($ {
      _name
   }
   $ {
      PYTHON_LIBRARIES
   })
endif()
endfunction()
set(DYNAMIC_LOOKUP "TRUE")
cython_add_module(myModule DYNAMIC_LOOKUP $ {
   src_files
})
Instead, the symbols will be resolved from the python interpreter
when it loads the module.

Suggested-by: Justin Israel <justinisrael@gmail.com>

Suggestion : 3

A C extension for CPython is a shared library (e.g. a .so file on Linux, .pyd on Windows), which exports an initialization function.,It is possible to export multiple modules from a single shared library by defining multiple initialization functions. However, importing them requires using symbolic links or a custom importer, because by default only the function corresponding to the filename is found. See the “Multiple modules in one library” section in PEP 489 for details.,In many cases, building an extension is more complex, since additional preprocessor defines and libraries may be needed. This is demonstrated in the example below.,Extension modules can be built using distutils, which is included in Python. Since distutils also supports creation of binary packages, users don’t necessarily need a compiler and distutils to install the extension.

def initfunc_name(name):
   try:
   suffix = b '_' + name.encode('ascii')
except UnicodeEncodeError:
   suffix = b 'U_' + name.encode('punycode').replace(b '-', b '_')
return b 'PyInit' + suffix
from distutils.core
import setup, Extension

module1 = Extension('demo',
   sources = ['demo.c'])

setup(name = 'PackageName',
   version = '1.0',
   description = 'This is a demo package',
   ext_modules = [module1])
python setup.py build
from distutils.core
import setup, Extension

module1 = Extension('demo',
   define_macros = [('MAJOR_VERSION', '1'),
      ('MINOR_VERSION', '0')
   ],
   include_dirs = ['/usr/local/include'],
   libraries = ['tcl83'],
   library_dirs = ['/usr/local/lib'],
   sources = ['demo.c'])

setup(name = 'PackageName',
   version = '1.0',
   description = 'This is a demo package',
   author = 'Martin v. Loewis',
   author_email = 'martin@v.loewis.de',
   url = 'https://docs.python.org/extending/building',
   long_description = ''
   '
   This is really just a demo package.
   ''
   ',
   ext_modules = [module1])
gcc - DNDEBUG - g - O3 - Wall - Wstrict - prototypes - fPIC - DMAJOR_VERSION = 1 - DMINOR_VERSION = 0 - I / usr / local / include - I / usr / local / include / python2 .2 - c demo.c - o build / temp.linux - i686 - 2.2 / demo.o

gcc - shared build / temp.linux - i686 - 2.2 / demo.o - L / usr / local / lib - ltcl83 - o build / lib.linux - i686 - 2.2 / demo.so
python setup.py install

Suggestion : 4

Builds systems coordinate invocation of the compiler and linker, passing flags, and only out-of-date build targets are built.,MSBuild in Visual Studio,Understand different components of the binary build process and their role: headers, libraries, compilers, linkers, build systems, system introspection tools, package managers,System introspection tools examine the host system for available build tools, the location of build dependencies, and properties of the build target to generate the appropriate build system configuration files.

python setup.py bdist_wheel--plat - name macosx - 10.6 - x86_64
pip install.
pip install - e.
pip wheel - w dist.
cd hello - cpp
pip wheel - w dist--verbose.
cd hello - cython
pip wheel - w dist--verbose.

Suggestion : 5

Но когда я строю с настройкой cmake, он продолжает создавать команду компоновщика, которая связывает libpython с .so: , Модуль, созданный distutils, кажется, отлично работает с любой моей установкой python2.7 (системой или виртуальным файлом для моего проекта). В то время как cmake падает с несоответствием версии, когда я пытаюсь импортировать его с помощью чего-либо, кроме связанного с ним системного python. ,Независимый от платформы способ найти путь к libpython (например, для использования в cmake), Когда я aModule.so свой aModule.so используя стандартные дистрибутивы cython, он, похоже, не связан с libpython :

Когда я aModule.so свой aModule.so используя стандартные дистрибутивы cython, он, похоже, не связан с libpython :

 $ otool - L aModule.so aModule.so: /usr/local / lib / libboost_thread - mt.dylib(compatibility version 0.0 .0, current version 0.0 .0) / usr / local / opt / thrift / lib / libthrift - 0.9 .0.dylib(compatibility version 0.0 .0, current version 0.0 .0) / usr / lib / libstdc++.6.dylib(compatibility version 7.0 .0, current version 7.9 .0) / usr / lib / libSystem.B.dylib(compatibility version 1.0 .0, current version 125.2 .11)

Но когда я строю с настройкой cmake, он продолжает создавать команду компоновщика, которая связывает libpython с .so:

 $ otool - L aModule.so aModule.so: /System/Library / Frameworks / Python.framework / Versions / 2.7 / Python(compatibility version 2.7 .0, current version 2.7 .1) / usr / local / opt / thrift / lib / libthrift - 0.9 .0.dylib(compatibility version 0.0 .0, current version 0.0 .0) / usr / local / lib / libboost_thread - mt.dylib(compatibility version 0.0 .0, current version 0.0 .0) / usr / lib / libstdc++.6.dylib(compatibility version 7.0 .0, current version 52.0 .0) / usr / lib / libSystem.B.dylib(compatibility version 1.0 .0, current version 159.1 .0)

То, что я закончил делать для собственного использования, так как я не знаю, является ли это полностью переносимым решением, было добавить флаг этой функции, чтобы сказать DYNAMIC_LOOKUP :

 function(cython_add_module _name _dynamic_lookup) set(pyx_module_sources "") set(other_module_sources "") foreach(_file $ {
    ARGN
 }) if ($ {
       _file
    }
    MATCHES ".*\\.py[x]?$") list(APPEND pyx_module_sources $ {
    _file
 })
 else() list(APPEND other_module_sources $ {
    _file
 }) endif() endforeach() compile_pyx($ {
       _name
    }
    generated_file $ {
       pyx_module_sources
    }) include_directories($ {
    PYTHON_INCLUDE_DIRS
 }) python_add_module($ {
       _name
    }
    $ {
       generated_file
    }
    $ {
       other_module_sources
    }) # # # Added here # #
 if ($ {
       _dynamic_lookup
    }) message(STATUS "Not linking target ${_name} against libpython") set_target_properties($ {
       _name
    }
    PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
 else() target_link_libraries($ {
       _name
    }
    $ {
       PYTHON_LIBRARIES
    }) endif() endfunction()

То, что я закончил делать для собственного использования, так как я не знаю, является ли это полностью переносимым решением, было добавить флаг этой функции, чтобы сказать DYNAMIC_LOOKUP :

 function(cython_add_module _name _dynamic_lookup) set(pyx_module_sources "") set(other_module_sources "") foreach(_file $ {
    ARGN
 }) if ($ {
       _file
    }
    MATCHES ".*\\.py[x]?$") list(APPEND pyx_module_sources $ {
    _file
 })
 else() list(APPEND other_module_sources $ {
    _file
 }) endif() endforeach() compile_pyx($ {
       _name
    }
    generated_file $ {
       pyx_module_sources
    }) include_directories($ {
    PYTHON_INCLUDE_DIRS
 }) python_add_module($ {
       _name
    }
    $ {
       generated_file
    }
    $ {
       other_module_sources
    }) # # # Added here # #
 if ($ {
       _dynamic_lookup
    }) message(STATUS "Not linking target ${_name} against libpython") set_target_properties($ {
       _name
    }
    PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
 else() target_link_libraries($ {
       _name
    }
    $ {
       PYTHON_LIBRARIES
    }) endif() endfunction()