19

Does anyone have a good example of using the build_clib command in distutils to build an external (non-python) C library from setup.py? The documentation on the subject seems to be sparse or non-existent.

My aim is to build a very simple external library, then build a cython wrapper which links to it. The simplest example I've found is here, but this uses a system() call to gcc which I can't imagine is best practice.

Snorfalorpagus
  • 3,348
  • 2
  • 29
  • 51
  • 1
    "How to build third-party C/C++ library from setup.py?" This is an important question and common use case (if you are writing Python bindings for a C library, then setup.py needs to build the library from source before it can build your Python extension). I wish the documentation covered this better (at all!) – Colonel Panic Jul 05 '15 at 20:59
  • 2
    Thanks for sharing, I'd never have figured this out otherwise. Got mine to work at https://github.com/hickford/primesieve-python/blob/master/setup.py – Colonel Panic Jul 10 '15 at 22:37
  • Check https://stackoverflow.com/questions/50938128/multiple-modules-sharing-a-same-method-in-swig-python/51073529#51073529, on how to tweak it in order to generate a **dynamic** library (*shared object*). – CristiFati Jun 28 '18 at 06:39

1 Answers1

18

Instead of passing a library name as a string, pass a tuple with the sources to compile:

setup.py

import sys
from distutils.core import setup
from distutils.command.build_clib import build_clib
from distutils.extension import Extension
from Cython.Distutils import build_ext

libhello = ('hello', {'sources': ['hello.c']})

ext_modules=[
    Extension("demo", ["demo.pyx"])
]

def main():
    setup(
        name = 'demo',
        libraries = [libhello],
        cmdclass = {'build_clib': build_clib, 'build_ext': build_ext},
        ext_modules = ext_modules
    )

if __name__ == '__main__':
    main()

hello.c

int hello(void) { return 42; }

hello.h

int hello(void);

demo.pyx

cimport demo
cpdef test():
    return hello()

demo.pxd

cdef extern from "hello.h":
    int hello()

Code is available as a gist: https://gist.github.com/snorfalorpagus/2346f9a7074b432df959

Snorfalorpagus
  • 3,348
  • 2
  • 29
  • 51
  • Hi. I was trying to do that, but apparently the "libraries" argument is only expecting a list of string with library names. Is that correct?... – dividebyzero Aug 10 '13 at 21:46
  • The libraries argument should be a list of 2-tuples, the first element of which is a name string for the library, and the second as a dictionary of parameters. See the build_libraries() function the the source: http://svn.python.org/projects/python/branches/pep-0384/Lib/distutils/command/build_clib.py – Snorfalorpagus Aug 11 '13 at 15:57
  • 1
    How to pass custom args, like `-O2` to the compiler? – xmedeko Mar 29 '18 at 12:10
  • This isn't supported by distutils. https://github.com/python/cpython/blob/master/Lib/distutils/ccompiler.py#L39-L44 – Snorfalorpagus Mar 29 '18 at 12:19
  • 2
    For everyone else who got confused by this: `python setup.py develop` does NOT call build_clib automatically. You have to do it by hand. `python setup.py build_clib` – olq_plo Aug 17 '19 at 11:11
  • @xmedeko did you cope with passing custom variables to the library – Ivan Mishalkin Apr 09 '20 at 11:49