[Distutils] Compilation of extension modules

Florent Rougon flo@via.ecp.fr
Sun Mar 3 18:40:01 2002


--=-=-=

Hello,

I am currently packaging an extension module that uses the glib library.
The correct way to compile such a program is:

gcc `glib-config --cflags` ... -c ... -o ...

That is, the output of "glib-config --cflags" must be near the beginning
of the compilation command (it usually contains -I options).

I tried to use the extra_compile_args argument to Extension's __init__()
method but it only adds arguments to the end of the compilation command.

I looked into Distutils' sources and found that the extra_preargs
argument to UnixCCompiler.compile() would do the trick, but it can't be
set from Extension's __init__() method. When the compile() method is
called in build_ext.py, no extra_preargs is passed, so it always gets
its default value: None.

Currently, I adopted the following "solution": strip the leading -I from
each argument output by "glib-config --cflags" and give it as
include_dirs to Extension.__init__().

This is somewhat ugly since the output of "glib-config --cflags" could
contain arguments that are not include directory specifications. My hack
would fail in such cases.

Is there a better solution I couldn't see? I searched the mailing-list
archive and didn't find anything really satisfactory.

If not, could we consider adding the possibility of specifying
some-arguments-of-any-kind (not only include dirs of macros or whatever)
to be put near the beginning of the compilation command from the setup()
call?

[ BTW, there is a similar issue with linking, but as `glib-config --libs`
is OK at the end of the link command line, extra_link_args does the
trick. However, it would be nice to be able to customize the beginning
if the link command. ]

Thank you for your comments. Here is my current setup.py.

--=-=-=
Content-Disposition: attachment; filename=setup.py

#! /usr/bin/env python

# setup.py --- Setup script for Python-XMMS
# Copyright (c) 2002 Florent Rougon
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA.

import os, string, sys
from distutils.core import setup, Extension

# Notes:
#  1) The Distutils included in Python 2.1 don't understand the "license"
#     keyword argument of setup correctly (they only understand licence); as I
#     don't want to mispell it, if you run the Distutils from Python 2.1, you
#     will get License: UNKNOWN.
#  2) I would like to use the keyword argument "extra_compile_args" of setup to
#     pass the output of glib-config --cflags to Distutils but it goes to the
#     end of the gcc command, which is useless in this case. So, I use
#     "include_dirs" instead.

GLIB_CONFIG = "glib-config"

glib_opts = {}
for op in ("cflags", "libs"):
    glib_config_pipe = os.popen("%s --%s" % (GLIB_CONFIG, op), 'r')
    glib_opts[op] = glib_config_pipe.read()[:-1] # strip the trailing newline
    if glib_config_pipe.close() != None:
        sys.exit("%s returned a non-zero exit status. Aborting." % GLIB_CONFIG)

# Suppress the -I in each -Idir output by glib-config --cflags (ugly)
glib_include_dirs = map(lambda s: s[2:],
                        string.split(glib_opts["cflags"], ' '))

setup(name="Python-XMMS",
      version="1.0",
      description="A Python interface to XMMS",
      author="Florent Rougon",
      author_email="flo@via.ecp.fr",
      maintainer="Florent Rougon",
      maintainer_email="flo@via.ecp.fr",
      url="http://www.via.ecp.fr/~flo/",
      license="GPL",
      platforms="Unix",
      long_description = """\
A Python interface to XMMS consisting of all the xmms_remote_* functions
from libxmms plus some higher-level functions. This should provide anything
needed to control XMMS from an external program.""",
      py_modules=["xmms"],
      ext_modules=[Extension("_xmms", ["_xmmsmodule.c"],
                             include_dirs=glib_include_dirs,
                             libraries=["xmms"],
                             extra_link_args=[glib_opts["libs"]])])

--=-=-=


-- 
Florent

--=-=-=--