diff SConstruct @ 2:e2a8e3805b04

Made parpg-core the main repository to pull from and build. * Added parpg-assets as a subrepo under the data folder. * Moved the SConstruct script into parpg-core and modified it to build and install parpg-assets as well. * Made a few minor changes to the SConstruct file from the defunct parpg-main repository. * Modified unix parpg executable script template to be more forgiving of installing the parpg Python package outside of PYTHONPATH. * Updated the .hgignore file to include temporary SCons files.
author M. George Hansen <technopolitica@gmail.com>
date Sun, 15 May 2011 14:51:41 -0700
parents
children 33684971cdb1
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SConstruct	Sun May 15 14:51:41 2011 -0700
@@ -0,0 +1,298 @@
+import sys
+import os
+import platform
+import compileall
+import fnmatch
+from collections import Sequence
+from multiprocessing import cpu_count
+
+def InstallChmod(env, dest, source, mode):
+    targets = env.Install(dest, source)
+    for target in targets:
+        env.AddPostAction(target, Chmod(target, mode))
+    return targets
+
+def InstallExecutable(env, dest, source):
+    return env.InstallChmod(dest, source, mode=0755)
+
+def InstallReadOnly(env, dest, source):
+    if not isinstance(source, Sequence):
+        source = [source]
+    targets = []
+    for entry in map(Entry, source):
+        entry.disambiguate()
+        if entry.isdir():
+            target = env.InstallChmod(dest, entry, mode=0755)
+        elif entry.isfile():
+            target = env.InstallChmod(dest, entry, mode=0644)
+        else:
+            # Something really weird happened and entry is not a Dir or a
+            # File... (Note: Yes this can happen!)
+            error_message = \
+                'expected entry to be a Dir or a File, but got {0!r}'
+            raise ValueError(error_message.format(entry))
+        targets.append(target)
+    return targets
+
+def InstallPyPackages(env, dest, source, compile=True):
+    # Remove all existing *.pyc and *.pyo files for a sanitary install
+    # environment.
+    def _remove_compiled_modules(path):
+        for dir_path, dir_names, file_names in os.walk(path):
+            for file_name in fnmatch.filter(file_names, '*.py[co]'):
+                file_path = os.path.join(dir_path, file_name)
+                os.remove(file_path)
+    
+    def _add_targets(path):
+         for dir_path, dir_names, file_names in os.walk(path):
+            for file_name in fnmatch.filter(file_names, '*.py[co]'):
+                file_path = os.path.join(dir_path, file_name)
+                env.Clean(path, file_path)
+                source_file_path = file_path.rstrip('oc')
+                env.Depends(file_path, source_file_path)
+
+    if not isinstance(source, Sequence):
+        source = [source]
+    for dir in source:
+        _remove_compiled_modules(str(dir))
+        if compile:
+            compileall.compile_dir(str(dir), ddir=str(dest), force=True)
+            _add_targets(str(dir))
+    targets = env.InstallReadOnly(dest, source)
+    return targets
+
+AddMethod(Environment, InstallChmod)
+AddMethod(Environment, InstallExecutable)
+AddMethod(Environment, InstallReadOnly)
+AddMethod(Environment, InstallPyPackages)
+
+EnsurePythonVersion(2, 6)
+
+AddOption(
+    '--stand-alone',
+    dest='stand_alone',
+    action='store_true',
+    default=False,
+    help='install the entire program under installation prefix instead of in '
+         'various system folders'
+)
+AddOption(
+    '--no-compile',
+    dest='compile',
+    action='store_false',
+    default=True,
+    help='don\'t compile any Python modules into .pyc files',
+)
+SetOption('num_jobs', cpu_count())
+
+def is_abs_path(key, val, env):
+    if not os.path.isabs(val):
+        error_message = '${key} must be an absolute path'
+        raise ValueError(error_message.format(key=key))
+    env[key] = os.path.normpath(val)
+
+variables = Variables()
+# NOTE M. George Hansen 2011-05-13: Path variables are based on the GNU
+#     standards as defined at http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
+
+# Platform-specific variable defaults.
+# FIXME M. George Hansen 2011-05-12: Define the MacOS-specific
+#     environmental variables (and check version...)
+platform_name = platform.system()
+if platform_name in ['Linux', 'MacOS']:
+    if GetOption('stand_alone'):
+        PREFIX_DEFAULT = '/opt'
+    else:
+        PREFIX_DEFAULT = '/usr/local'
+    BIN_DIR_DEFAULT = '$EXEC_PREFIX/bin'
+    DATA_ROOT_DIR_DEFAULT = '$PREFIX/share/$PROJECT_NAME'
+    SYS_CONF_DIR_DEFAULT = '$PREFIX/etc/$PROJECT_NAME'
+    INCLUDE_DIR_DEFAULT = '$PREFIX/include/$PROJECT_NAME'
+    DOC_DIR_DEFAULT = '$DATA_ROOT_DIR/doc/$PROJECT_NAME'
+    LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib' 
+    dist_name, dist_version, dist_id = \
+        platform.linux_distribution(full_distribution_name=False)
+    if dist_name in ['debian', 'Ubuntu']:
+        # Debian uses dist-packages instead of site-packages for Python
+        #     versions > 2.5.
+        PY_LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib/python$PY_VERSION_SHORT/' \
+                             'dist-packages'
+    else:
+        PY_LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib/python$PY_VERSION_SHORT/' \
+                             'site-packages'
+elif platform_name == 'Windows':
+    try:
+        PREFIX_DEFAULT = os.environ['ProgramFiles'] + r'\$PROGRAM_NAME'
+    except KeyError:
+        PREFIX_DEFAULT = ''
+        error_message = '%ProgramFiles% environmental variable is not ' \
+                        'set, unable to determine path to Program Files ' \
+                        'folder (use --prefix to override)'
+        raise SConfWarning(error_message)
+    BIN_DIR_DEFAULT = '$EXEC_PREFIX'
+    DATA_ROOT_DIR_DEFAULT = '$PREFIX/data'
+    SYS_CONF_DIR_DEFAULT = '$PREFIX/config'
+    INCLUDE_DIR_DEFAULT = '$PREFIX/include'
+    DOC_DIR_DEFAULT = '$PREFIX/doc/'
+    LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib'
+    PY_LIB_DIR_DEFAULT = '$EXEC_PREFIX/lib'
+    if GetOption('stand_alone'):
+        PY_LIB_DIR_DEFAULT = '$PREFIX/lib'
+    else:
+        python_prefix = sys.prefix
+        # FIXME M. George Hansen 2011-05-12: Does sys.prefix include the
+        #     PythonX.Y part on Windows?
+        PY_LIB_DIR_DEFAULT = \
+            os.path.join(python_prefix, 'Lib', 'site-packages')
+
+# Platform-independant variables:
+variables.AddVariables(
+    PathVariable(
+        'PREFIX',
+        'directory under which most or all of the program components should '
+            'be installed',
+        PREFIX_DEFAULT,
+        is_abs_path,
+    ),
+    PathVariable(
+        'EXEC_PREFIX',
+        'directory under which machine-specific compiled libraries and '
+            'objects should be installed',
+        '$PREFIX',
+        is_abs_path,
+    ),
+    PathVariable(
+        'BIN_DIR',
+        'directory where program executables should be installed',
+        BIN_DIR_DEFAULT,
+        is_abs_path,
+    ),
+    PathVariable(
+        'DATA_ROOT_DIR',
+        'directory under which read-only, architecture-independant data files '
+            'should be installed',
+        DATA_ROOT_DIR_DEFAULT,
+        is_abs_path,
+    ),
+    PathVariable(
+        'DATA_DIR',
+        'directory where read-only, architecture-independant data files '
+            'should be installed',
+        '$DATA_ROOT_DIR',
+        is_abs_path,
+    ),
+    PathVariable(
+        'SYS_CONF_DIR',
+        'directory where read-only, machine-specific data files should be '
+            'installed',
+        SYS_CONF_DIR_DEFAULT,
+        is_abs_path,
+    ),
+    PathVariable(
+        'INCLUDE_DIR',
+        'directory where C/C++ header files should be installed',
+        INCLUDE_DIR_DEFAULT,
+        is_abs_path,
+    ),
+    PathVariable(
+        'DOC_DIR',
+        'directory where program documentation should be installed',
+        DOC_DIR_DEFAULT,
+        is_abs_path,
+    ),
+    PathVariable(
+        'LIB_DIR',
+        'directory where platform-dependant, compiled library and object '
+            'files should be installed',
+        LIB_DIR_DEFAULT,
+        is_abs_path,
+    ),
+    PathVariable(
+        'PY_LIB_DIR',
+        'directory where pure Python modules and packages should be installed',
+        PY_LIB_DIR_DEFAULT,
+        is_abs_path,
+    ),
+    PathVariable(
+        'INCLUDE_DIR',
+        'directory where C/C++ header files should be installed',
+        INCLUDE_DIR_DEFAULT,
+        is_abs_path,
+    ),
+)
+
+platform_name = platform.system()
+python_version_tuple = platform.python_version_tuple()
+
+environment = Environment(
+    tools=['default', 'textfile', 'packaging'],
+    variables=variables,
+    PROJECT_NAME='parpg',
+    PROJECT_VERSION_MAJOR=0,
+    PROJECT_VERSION_MINOR=2,
+    PROJECT_VERSION_PATCH=0,
+    PROJECT_VERSION_SHORT='$PROJECT_VERSION_MAJOR.$PROJECT_VERSION_MAJOR',
+    PROJECT_VERSION_LONG='$PROJECT_VERSION_MAJOR.$PROJECT_VERSION_MINOR.'
+                         '$PROJECT_VERSION_PATCH',
+    PYTHON=sys.executable,
+    PY_VERSION_SHORT='.'.join(python_version_tuple[:-1]),
+    PY_VERSION_LONG='.'.join(python_version_tuple),
+    PY_PACKAGES=[],
+    CONFIG_FILES=[],
+    DATA_FILES=[],
+    EXECUTABLES=[],
+)
+Help(variables.GenerateHelpText(environment))
+
+config_dict = [('@{0}@'.format(key), environment.Dictionary()[key]) for key in
+               ('PREFIX', 'LIB_DIR', 'PY_LIB_DIR', 'BIN_DIR', 'SYS_CONF_DIR',
+                'DATA_DIR', 'PYTHON')]
+
+environment['PY_PACKAGES'] += [
+    Dir('src/parpg'),
+]
+config_file_template = File('system.cfg.in')
+subst_config_file = environment.Substfile(config_file_template,
+                                          SUBST_DICT=config_dict)
+environment['CONFIG_FILES'] += [subst_config_file]
+environment['DATA_FILES'] += Glob('data/*')
+# TODO M. George Hansen 2011-05-12: Implement windows executable.
+executable_template = File('bin/unix/parpg.in')
+subst_executable = environment.Substfile(executable_template,
+                                         SUBST_DICT=config_dict)
+environment['EXECUTABLES'] += [subst_executable] 
+
+sources = environment.InstallPyPackages(
+    '$PY_LIB_DIR',
+    environment['PY_PACKAGES'],
+    compile=GetOption('compile'),
+)
+config_files = environment.InstallChmod(
+    '$SYS_CONF_DIR',
+    environment['CONFIG_FILES'],
+    mode=0755,
+)
+Requires(config_files, subst_config_file)
+data_files = environment.InstallReadOnly(
+    '$DATA_DIR',
+    environment['DATA_FILES'],
+)
+executables = environment.InstallExecutable(
+    '$BIN_DIR',
+    environment['EXECUTABLES'],
+)
+Requires(executables, subst_executable)
+
+# TODO M. George Hansen 2011-05-12: Implement package builder.
+#package = environment.Package(
+#    NAME='parpg',
+#    VERSION='0.2.0',
+#    PACKAGEVERSION=0,
+#    LICENSE='gpl',
+#    SUMMARY='',
+#    DESCRIPTION='',
+#    X_RPM_GROUP='Application/parpg',
+#)
+
+Default([sources, config_files, data_files, executables])
+Alias('install', [sources, config_files, data_files, executables])