#!/usr/bin/python2.4 # Copyright 2007 Google Inc. # # 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 # of the License, 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; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Build the include server module. The version number should be passed to this script through the environment variable DISTCC_VERSION. Also, the CPPFLAGS of the Makefile must be passed through the enviroment. This is how we figure out the locations of include directories. SRCDIR must be passed as well; it explains where to find the C sources and the include_server directory of Python source files and C extensions. Because SRCDIR is appended to build location and we don't want to end up outside this location through a relative SRCDIR path with '..'s, SRCDIR is absolutized. """ __author__ = 'Manos Renieris and Nils Klarlund' import distutils.core import distutils.extension import doctest import os import shlex import sys OPTIONS_NOT_ALLOWED = ['-Iquote', '-Isystem', '-I-'] # We include a partial command line parser instead of using the more the more # complicated one in parse_command.py. This cuts down on dependencies in the # build system itself. def GetIncludes(flags): """Parse a flags string for includes of the form -I. Args: flags: a string in shell syntax denoting compiler options Returns: a list of s of the includes Raises: ValueError: In the doctests below, note that a single quoted backslash takes four backslashes to represent if it is inside a single quoted string inside this present triple-quoted string. >>> GetIncludes('-I x -X -I"y" -Y') ['x', 'y'] >>> GetIncludes('-Ix -Dfoo -Iy') ['x', 'y'] >>> GetIncludes(r'-Ix -I"y\\z" -I"y\\\\z" -Y') ['x', 'y\\\\z', 'y\\\\z'] >>> GetIncludes('-DX -Iquote Y') Traceback (most recent call last): ... ValueError: These options are not allowed: -Iquote, -Isystem, -I-. >>> GetIncludes('-DX -I x -I') Traceback (most recent call last): ... ValueError: Argument expected after '-I'. """ flags = shlex.split(flags) if set(OPTIONS_NOT_ALLOWED) & set(flags): raise ValueError('These options are not allowed: %s.' % ', '.join(OPTIONS_NOT_ALLOWED)) # Fish out the directories of '-I' options. i = 0 inc_dirs = [] while i < len(flags): if flags[i].startswith('-I'): inc_dir = flags[i][len('-I'):] if inc_dir: # "-Idir" inc_dirs.append(inc_dir) i += 1 continue else: # "-I dir" if i == len(flags) - 1: raise ValueError("Argument expected after '-I'.") inc_dirs.append(flags[i+1]) i += 2 else: i += 1 return inc_dirs cpp_flags_env = os.getenv('CPPFLAGS', '') if not cpp_flags_env: # Don't quit; perhaps the user is asking for help using '--help'. # CPPFLAGS checking. print >> sys.stderr, 'setup.py: CPPFLAGS must be defined.' # CPPFLAGS is passed to us as it's used in the Makefile: a string that the shell # will interpret. GetInclude uses shlex to do the same kind of interpretation # in order to identify the include directory options. cpp_flags_includes = GetIncludes(cpp_flags_env) # SRCDIR checking. if not os.getenv('SRCDIR'): # Don't quit; perhaps the user is asking for help using '--help'. print >> sys.stderr, 'setup.py: SRCDIR must be defined.' srcdir = 'UNDEFINED' srcdir_include_server = 'UNDEFINED' else: # The distutils build system appends the source location to the build # location, and so to avoid that relative source paths with '..' make built # files end up outside the build location, the location is changed to an # absolute path. srcdir = os.path.abspath(os.getenv('SRCDIR')) if not os.path.isdir(srcdir): sys.exit("""Could not cd to SRCDIR '%s'.""" % srcdir) srcdir_include_server = os.path.join(srcdir, 'include_server') # Specify extension. ext = distutils.extension.Extension( name='include_server.distcc_pump_c_extensions', sources=[os.path.join(srcdir, source) for source in ['src/clirpc.c', 'src/clinet.c', 'src/state.c', 'src/srvrpc.c', 'src/pump.c', 'src/rpc.c', 'src/io.c', 'src/include_server_if.c', 'src/trace.c', 'src/snprintf.c', 'src/util.c', 'src/tempfile.c', 'src/filename.c', 'src/bulk.c', 'src/sendfile.c', 'src/compress.c', 'src/argutil.c', 'src/cleanup.c', 'src/emaillog.c', 'src/timeval.c', 'src/netutil.c', 'lzo/minilzo.c', 'include_server/c_extensions/distcc_pump_c_extensions_module.c', ]], include_dirs=cpp_flags_includes, define_macros=[('_GNU_SOURCE', 1)], library_dirs=[], libraries=[], runtime_library_dirs=[], extra_objects=[], extra_compile_args=[] ) args = { 'name': 'include_server', # The 'include_server' package is in the srcdir_include_server. 'package_dir': {'include_server': srcdir_include_server}, 'version': os.getenv('DISTCC_VERSION') or 'unknown', 'description': """Include server for distcc's pump-mode""", 'author': 'Nils Klarlund', 'author_email': 'opensource@google.com', 'url': 'http://code.google.com/p/distcc', 'long_description': 'The include server is part of distcc.', 'packages': ['include_server'], 'ext_modules': [ext], } # First, do a little self-testing. doctest.testmod() # Second, do the setup. distutils.core.setup(**args)