[PATCH RSB v2] rtems-kernel: Implement kernel recipe using waf
Ryan Long
ryan.long at oarcorp.com
Mon Nov 1 22:30:57 UTC 2021
ping
-----Original Message-----
From: Ryan Long <ryan.long at oarcorp.com>
Sent: Wednesday, October 27, 2021 10:09 AM
To: devel at rtems.org
Cc: Ryan Long <ryan.long at oarcorp.com>
Subject: [PATCH RSB v2] rtems-kernel: Implement kernel recipe using waf
Closes #4145
---
rtems/config/tools/rtems-kernel-6.cfg | 6 +-
rtems/config/tools/rtems-kernel-common.cfg | 125 ++++++++++++------------
source-builder/rtems-kernel-config-check | 147 +++++++++++++++++++++++++++++
source-builder/sb/options.py | 135 +++++++++++++-------------
4 files changed, 283 insertions(+), 130 deletions(-) create mode 100755 source-builder/rtems-kernel-config-check
diff --git a/rtems/config/tools/rtems-kernel-6.cfg b/rtems/config/tools/rtems-kernel-6.cfg
index f1d0990..9120862 100644
--- a/rtems/config/tools/rtems-kernel-6.cfg
+++ b/rtems/config/tools/rtems-kernel-6.cfg
@@ -2,10 +2,10 @@
# RTEMS 5
#
-%define rtems_kernel_version 3ec5f20484cc4201e1d7b87844505644533b6148
-%hash sha512 rtems-kernel-%{rtems_kernel_version}.tar.bz2 \
- BjMKrf5n1YR6IpiZrY5TUEzKATPRJxA2/6m6f833DdRu+RyLxccXqA4gHRdVUqFelFNQ3o0XdG4o1naBKYfhkQ==
+%define rtems_kernel_version 3bb97a30b17b6c138dead3e3a6b329c3b301cdb3
+%hash sha512 rtems-kernel-%{rtems_kernel_version}.tar.gz \
+
+m/ogwrJj4X60ewDIbV6WRj1MJa/22gQHQd56XiNMfvCr0nsvcXdkXKAObLIGYIGYfUyEwlV
+k3SRjjRFkFalDGQ==
#
# The RTEMS build instructions.
#
diff --git a/rtems/config/tools/rtems-kernel-common.cfg b/rtems/config/tools/rtems-kernel-common.cfg
index 157c7a4..d5b67dd 100644
--- a/rtems/config/tools/rtems-kernel-common.cfg
+++ b/rtems/config/tools/rtems-kernel-common.cfg
@@ -9,7 +9,7 @@
# and BSPs. Only after the source to download.
#
%if %{_dry_run} && %{defined with_download}
- %log Kenrel configuration errors ignored
+ %log Kernel configuration errors ignored
%define rtems_kernel_error 0
%else
%define rtems_kernel_error 1
@@ -19,10 +19,15 @@
%define rtems_kernel_version %{rsb_version} %endif
+%if %{defined with_rtems_bsp_config}
+ %define _target
+%(%{_topdir}/../source-builder/rtems-kernel-config-check -v
+%{rtems_version} -t %{with_rtems_bsp_config}) %define rtems_bsp
+%(%{_topdir}/../source-builder/rtems-kernel-config-check -b
+%{with_rtems_bsp_config}) %endif
+
#
# The target. It could be set in rtems_target.
#
-%if %{defined rtems_target}
+%if %{defined rtems_target} && !%{defined with_rtems_bsp_config}
%define _target %{rtems_target}
%endif
%if %{_target} == %{nil} && %{rtems_kernel_error} @@ -32,10 +37,21 @@ # # The BSP.
#
-%if !%{defined with_rtems_bsp} && %{rtems_kernel_error}
+%if !%{defined with_rtems_bsp} && %{rtems_kernel_error} && !%{defined
+with_rtems_bsp_config}
%error No RTEMS BSP specified: --with-rtems-bsp=bsp %endif -%define rtems_bsp %{with_rtems_bsp}
+%if !%{defined with_rtems_bsp_config}
+ %define rtems_bsp %{with_rtems_bsp}
+%endif
+
+#
+# Configuration file used with waf
+#
+%ifn %{defined with_rtems_bsp_config}
+ %define config_file config-%{_target}-%{rtems_bsp}.ini
+%else
+ %define config_file %{with_rtems_bsp_config} %endif
#
# If no tools are provided use the prefix.
@@ -98,14 +114,6 @@ URL: https://www.rtems.org/
%define rtems_posix 0
%endif
-%if %{defined with_rtems_legacy_network}
- %define rtems_networking 1
-%endif
-
-%if %{defined with_rtems_cxx}
- %define rtems_cxx 1
-%endif
-
%if %{defined with_rtems_bspopts}
%define bspopts %{with_rtems_bspopts}
%endif
@@ -143,43 +151,43 @@ URL: https://www.rtems.org/
# --without-rtems-tests : Supported, forced to no
# --with-rtems-smp : Supported
# --without-rtems-smp : Don't care
-# --with-rtems-legacy-network : Supported
+# --with-rtems-legacy-network : Unsupported
# --without-rtems-legacy-network : Don't care
-# --with-rtems-bspopts : Supported, quote for a list
-# --without-rtems-bspopts : Don't care
-#
%if %{defined without_rtemsbsp}
%error Option --without-rtemsbsp is not supported.
%endif
+%if %{defined with_rtems_legacy_network} echo "RTEMS legacy network
+has been removed."
+ echo "Please review and update your configuration."
+ exit 1
+%endif
+%if %{defined enable_cxx}
+ echo CXX has been removed."
+ echo "Please review and update your configuration."
+ exit 1
+%endif
+
%if %{defined without_rtems_tests}
- %define with_rtems_tests no
+ %define rtems_tests False
+ %define rtems_sample_tests False
%endif
%if %{defined with_rtems_tests}
%if %{with_rtems_tests} == 1
- %define with_rtems_tests yes
+ %define rtems_tests True
+ %define rtems_sample_tests True
%endif
- %if %{with_rtems_tests} == yes || \
- %{with_rtems_tests} == no || \
- %{with_rtems_tests} == samples
- %define rtems_tests %{with_rtems_tests}
+ %if %{with_rtems_tests} == samples
+ %define rtems_tests False
+ %define rtems_sample_tests True
%endif
%endif
%if %{defined with_rtems_smp}
%define rtems_smp 1
%endif
-%if %{defined with_rtems_legacy_network}
- %define rtems_networking 1
-%endif
%if %{defined with_rtems_bspopts}
%define rtems_bspopts %{with_rtems_bspopts} %endif
-#
-# If C++ defined for the tool set use it to control RTEMS's setting..
-#
-%if %{defined enable_cxx}
- %define rtems_cxx %{enable_cxx}
-%endif
#
# Default set up. Override these in a BSP if you want a
@@ -188,14 +196,9 @@ URL: https://www.rtems.org/
%ifn %{defined rtems_posix}
%define rtems_posix 1
%endif
-%ifn %{defined rtems_networking}
- %define rtems_networking 0
-%endif
-%ifn %{defined rtems_cxx}
- %define rtems_cxx 1
-%endif
%ifn %{defined rtems_tests}
- %define rtems_tests samples
+ %define rtems_tests False
+ %define rtems_sample_tests True
%endif
%ifn %{defined rtems_bspopts}
%define rtems_bspopts %{nil}
@@ -213,8 +216,6 @@ URL: https://www.rtems.org/
%if %{defined _internal_autotools_path}
export PATH="%{_internal_autotools_path}/bin:${PATH}"
%endif
- ./bootstrap -c
- ./rtems-bootstrap
%endif
cd ..
@@ -225,38 +226,42 @@ URL: https://www.rtems.org/
else
build_dir="build"
fi
+
+ cd ${source_dir_rtems}
+
+ %if %{defined without_rtems_bsp_config}
+ cpu=`echo %{_target} | cut -d- -f1`
+ echo "[${cpu}/%{rtems_bsp}]" > %{config_file}
+ echo "RTEMS_POSIX_API = %{?rtems_posix:True}%{!?rtems_posix:False}" >> %{config_file}
+ echo "RTEMS_SMP = %{?rtems_smp:True}%{!?rtems_smp:False}" >> %{config_file}
+ echo "BUILD_TESTS = %{rtems_tests}" >> %{config_file}
+ echo "BUILD_SAMPLES = %{rtems_sample_tests}" >> %{config_file}
+ %endif
+
mkdir -p ${build_dir}
- cd ${build_dir}
-
- ../${source_dir_rtems}/configure \
- --build=%{_build} --host=%{_host} \
- --target=%{_target} \
- --enable-rtemsbsp="%{rtems_bsp}" \
- %{?rtems_cxx:--enable-cxx}%{!?rtems_cxx:--disable-cxx} \
- %{?rtems_posix:--enable-posix}%{!?rtems_posix:--disable-posix} \
- %{?rtems_networking:--enable-networking}%{!?rtems_networking:--disable-networking} \
- %{?rtems_tests:--enable-tests=%{rtems_tests}} \
- %{?rtems_smp:--enable-smp} \
+
+ ./waf configure \
+ --rtems-bsps=%{_target}/%{rtems_bsp} \
--prefix=%{_prefix} --bindir=%{_bindir} \
- --exec-prefix=%{_exec_prefix} \
- --includedir=%{_includedir} --libdir=%{_libdir} \
- --mandir=%{_mandir} --infodir=%{_infodir} \
- %{rtems_bspopts}
+ --rtems-config=%{config_file}
+
+ ./waf %{?_smp_mflags}
- %{__make} %{?_smp_mflags} all
cd ..
%install
%{__rmdir} $SB_BUILD_ROOT
- cd ${build_dir}
- %{__make} DESTDIR=$SB_BUILD_ROOT install
+ cd ${source_dir_rtems}
+ ./waf --destdir=$SB_BUILD_ROOT install
+
+ echo "rtems_tests: %{rtems_tests}"
- %if %{rtems_tests} != no
+ %if %{rtems_tests} != False
%define rtems_test_install %{_target}/%{rtems_bsp}/tests
mkdir -p $SB_BUILD_ROOT/%{_prefix}/%{rtems_test_install}
find . -name \*.exe -and -not -name \*.norun.exe \
-exec cp -v \{\} $SB_BUILD_ROOT/%{_prefix}/%{rtems_test_install}/ \;
%endif
- cd ..
+ cd -
diff --git a/source-builder/rtems-kernel-config-check b/source-builder/rtems-kernel-config-check
new file mode 100755
index 0000000..9bdff22
--- /dev/null
+++ b/source-builder/rtems-kernel-config-check
@@ -0,0 +1,147 @@
+#! /usr/bin/env python
+
+"""
+SPDX-License-Identifier: BSD-2-Clause
+
+COPYRIGHT (C) 2021 On-Line Applications Research Corporation (OAR).
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+"""
+
+from __future__ import print_function
+
+import sys
+import argparse
+
+from os.path import exists
+
+try:
+ import ConfigParser
+ configparser = ConfigParser # used for python2 except ImportError:
+ try:
+ import configparser # used for python3
+ except ImportError:
+ print("Could not import configparser. Exiting...", file = sys.stderr)
+ sys.exit(1)
+
+def run():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("config", help="path to config file")
+ parser.add_argument(
+ "-a",
+ "--arch",
+ help="return target architecture specified in the config",
+ action="store_true"
+ )
+ parser.add_argument(
+ "-b",
+ "--bsp",
+ help="return BSP specified in the config",
+ action="store_true"
+ )
+ parser.add_argument(
+ "-c",
+ "--arch-bsp",
+ help="return target architecture and BSP specified in the config",
+ action="store_true"
+ )
+ parser.add_argument(
+ "-v",
+ "--rtems-version",
+ help="version of RTEMS",
+ type=int,
+ default=6
+ )
+ parser.add_argument(
+ "-t",
+ "--target",
+ help="return target (<arch-rtems<rtems-version>)",
+ action="store_true"
+ )
+ args = parser.parse_args()
+ config = configparser.ConfigParser()
+
+ if args.config[-4:] != ".ini":
+ print(
+ "The config file is missing an *.ini extension.",
+ file = sys.stderr
+ )
+ sys.exit(1)
+
+ try:
+ config.read(args.config)
+ except configparser.MissingSectionHeaderError:
+ print(
+ "There is no section header in the config file",
+ file = sys.stderr
+ )
+ sys.exit(1)
+ except configparser.ParsingError:
+ print(
+ "An exception occured when parsing the config file",
+ file = sys.stderr
+ )
+ sys.exit(1)
+ except:
+ print(
+ "An unknown exception occured",
+ file = sys.stderr
+ )
+
+ if len(config.sections()) != 1:
+ print(
+ "You can only have one arch/bsp section in your config.",
+ file = sys.stderr
+ )
+ sys.exit(1)
+
+ arch_bsp_str = config.sections()[0]
+ if arch_bsp_str.find("/") == -1:
+ print(
+ "arch/bsp section in config is missing '/'",
+ file = sys.stderr
+ )
+ sys.exit(1)
+
+ if ( args.arch or args.bsp) and args.arch_bsp:
+ args.arch = False
+
+ if args.arch:
+ print(arch_bsp_str.split("/")[0])
+ return
+
+ if args.bsp:
+ print(arch_bsp_str.split("/")[1])
+ return
+
+ if args.arch_bsp:
+ print(arch_bsp_str.replace("/", " "))
+ return
+
+ if args.target:
+ arch = arch_bsp_str.split("/")[0]
+ print(arch + "-rtems" + str(args.rtems_version))
+ return
+
+if __name__ == "__main__":
+ run()
diff --git a/source-builder/sb/options.py b/source-builder/sb/options.py index a0f196b..6cf4d12 100644
--- a/source-builder/sb/options.py
+++ b/source-builder/sb/options.py
@@ -55,39 +55,39 @@ class command_line:
def __init__(self, argv, optargs, _defaults, command_path):
self._long_opts = {
# key macro handler param defs init
- '--prefix' : ('_prefix', self._lo_path, True, None, False),
- '--topdir' : ('_topdir', self._lo_path, True, None, False),
- '--configdir' : ('_configdir', self._lo_path, True, None, False),
- '--builddir' : ('_builddir', self._lo_path, True, None, False),
- '--sourcedir' : ('_sourcedir', self._lo_path, True, None, False),
- '--patchdir' : ('_patchdir', self._lo_path, True, None, False),
- '--tmppath' : ('_tmppath', self._lo_path, True, None, False),
- '--jobs' : ('_jobs', self._lo_jobs, True, 'max', True),
- '--log' : ('_logfile', self._lo_string, True, None, False),
- '--url' : ('_url_base', self._lo_string, True, None, False),
- '--no-download' : ('_disable_download', self._lo_bool, False, '0', True),
- '--macros' : ('_macros', self._lo_string, True, None, False),
- '--source-only-download' : ('_source_download', self._lo_bool, False, '0', True),
- '--targetcflags' : ('_targetcflags', self._lo_string, True, None, False),
- '--targetcxxflags' : ('_targetcxxflags', self._lo_string, True, None, False),
- '--libstdcxxflags' : ('_libstdcxxflags', self._lo_string, True, None, False),
- '--force' : ('_force', self._lo_bool, False, '0', True),
- '--quiet' : ('_quiet', self._lo_bool, False, '0', True),
- '--trace' : ('_trace', self._lo_bool, False, '0', True),
- '--dry-run' : ('_dry_run', self._lo_bool, False, '0', True),
- '--warn-all' : ('_warn_all', self._lo_bool, False, '0', True),
- '--no-clean' : ('_no_clean', self._lo_bool, False, '0', True),
- '--keep-going' : ('_keep_going', self._lo_bool, False, '0', True),
- '--always-clean' : ('_always_clean', self._lo_bool, False, '0', True),
- '--no-install' : ('_no_install', self._lo_bool, False, '0', True),
- '--regression' : ('_regression', self._lo_bool, False, '0', True),
- '--host' : ('_host', self._lo_triplets, True, None, False),
- '--build' : ('_build', self._lo_triplets, True, None, False),
- '--target' : ('_target', self._lo_triplets, True, None, False),
- '--rtems-tools' : ('_rtems_tools', self._lo_string, True, None, False),
- '--rtems-bsp' : ('_rtems_bsp', self._lo_string, True, None, False),
- '--rtems-version' : ('_rtems_version', self._lo_string, True, None, False),
- '--help' : (None, self._lo_help, False, None, False)
+ '--prefix' : ('_prefix', self._lo_path, True, None, False),
+ '--topdir' : ('_topdir', self._lo_path, True, None, False),
+ '--configdir' : ('_configdir', self._lo_path, True, None, False),
+ '--builddir' : ('_builddir', self._lo_path, True, None, False),
+ '--sourcedir' : ('_sourcedir', self._lo_path, True, None, False),
+ '--patchdir' : ('_patchdir', self._lo_path, True, None, False),
+ '--tmppath' : ('_tmppath', self._lo_path, True, None, False),
+ '--jobs' : ('_jobs', self._lo_jobs, True, 'max', True),
+ '--log' : ('_logfile', self._lo_string, True, None, False),
+ '--url' : ('_url_base', self._lo_string, True, None, False),
+ '--no-download' : ('_disable_download', self._lo_bool, False, '0', True),
+ '--macros' : ('_macros', self._lo_string, True, None, False),
+ '--source-only-download' : ('_source_download', self._lo_bool, False, '0', True),
+ '--targetcflags' : ('_targetcflags', self._lo_string, True, None, False),
+ '--targetcxxflags' : ('_targetcxxflags', self._lo_string, True, None, False),
+ '--libstdcxxflags' : ('_libstdcxxflags', self._lo_string, True, None, False),
+ '--force' : ('_force', self._lo_bool, False, '0', True),
+ '--quiet' : ('_quiet', self._lo_bool, False, '0', True),
+ '--trace' : ('_trace', self._lo_bool, False, '0', True),
+ '--dry-run' : ('_dry_run', self._lo_bool, False, '0', True),
+ '--warn-all' : ('_warn_all', self._lo_bool, False, '0', True),
+ '--no-clean' : ('_no_clean', self._lo_bool, False, '0', True),
+ '--keep-going' : ('_keep_going', self._lo_bool, False, '0', True),
+ '--always-clean' : ('_always_clean', self._lo_bool, False, '0', True),
+ '--no-install' : ('_no_install', self._lo_bool, False, '0', True),
+ '--regression' : ('_regression', self._lo_bool, False, '0', True),
+ '--host' : ('_host', self._lo_triplets, True, None, False),
+ '--build' : ('_build', self._lo_triplets, True, None, False),
+ '--target' : ('_target', self._lo_triplets, True, None, False),
+ '--rtems-tools' : ('_rtems_tools', self._lo_string, True, None, False),
+ '--rtems-bsp' : ('_rtems_bsp', self._lo_string, True, None, False),
+ '--rtems-version' : ('_rtems_version', self._lo_string, True, None, False),
+ '--help' : (None, self._lo_help, False, None, False)
}
self.command_path = command_path @@ -203,40 +203,41 @@ class command_line:
print('%s: [options] [args]' % (self.command_name))
print('RTEMS Source Builder, an RTEMS Tools Project (c) 2012-2019 Chris Johns')
print('Options and arguments:')
- print('--force : Force the build to proceed')
- print('--quiet : Quiet output (not used)')
- print('--trace : Trace the execution')
- print('--dry-run : Do everything but actually run the build')
- print('--warn-all : Generate warnings')
- print('--no-clean : Do not clean up the build tree')
- print('--always-clean : Always clean the build tree, even with an error')
- print('--keep-going : Do not stop on an error.')
- print('--regression : Set --no-install, --keep-going and --always-clean')
- print('--jobs : Run with specified number of jobs, default: num CPUs.')
- print('--host : Set the host triplet')
- print('--build : Set the build triplet')
- print('--target : Set the target triplet')
- print('--prefix path : Tools build prefix, ie where they are installed')
- print('--topdir path : Top of the build tree, default is $PWD')
- print('--configdir path : Path to the configuration directory, default: ./config')
- print('--builddir path : Path to the build directory, default: ./build')
- print('--sourcedir path : Path to the source directory, default: ./source')
- print('--patchdir path : Path to the patches directory, default: ./patches')
- print('--tmppath path : Path to the temp directory, default: ./tmp')
- print('--macros file[,[file] : Macro format files to load after the defaults')
- print('--log file : Log file where all build out is written too')
- print('--url url[,url] : URL to look for source')
- print('--no-download : Disable the source downloader')
- print('--no-install : Do not install the packages to the prefix')
- print('--targetcflags flags : List of C flags for the target code')
- print('--targetcxxflags flags : List of C++ flags for the target code')
- print('--libstdcxxflags flags : List of C++ flags to build the target libstdc++ code')
- print('--source-only-download : Only download the source')
- print('--with-<label> : Add the --with-<label> to the build')
- print('--without-<label> : Add the --without-<label> to the build')
- print('--rtems-tools path : Path to an install RTEMS tool set')
- print('--rtems-bsp arc/bsp : Standard RTEMS architecure and BSP specifier')
- print('--rtems-version ver : The RTEMS major/minor version string')
+ print('--force : Force the build to proceed')
+ print('--quiet : Quiet output (not used)')
+ print('--trace : Trace the execution')
+ print('--dry-run : Do everything but actually run the build')
+ print('--warn-all : Generate warnings')
+ print('--no-clean : Do not clean up the build tree')
+ print('--always-clean : Always clean the build tree, even with an error')
+ print('--keep-going : Do not stop on an error.')
+ print('--regression : Set --no-install, --keep-going and --always-clean')
+ print('--jobs : Run with specified number of jobs, default: num CPUs.')
+ print('--host : Set the host triplet')
+ print('--build : Set the build triplet')
+ print('--target : Set the target triplet')
+ print('--prefix path : Tools build prefix, ie where they are installed')
+ print('--topdir path : Top of the build tree, default is $PWD')
+ print('--configdir path : Path to the configuration directory, default: ./config')
+ print('--builddir path : Path to the build directory, default: ./build')
+ print('--sourcedir path : Path to the source directory, default: ./source')
+ print('--patchdir path : Path to the patches directory, default: ./patches')
+ print('--tmppath path : Path to the temp directory, default: ./tmp')
+ print('--macros file[,[file] : Macro format files to load after the defaults')
+ print('--log file : Log file where all build out is written too')
+ print('--with-rtems-bsp-config : Configuration file to use')
+ print('--url url[,url] : URL to look for source')
+ print('--no-download : Disable the source downloader')
+ print('--no-install : Do not install the packages to the prefix')
+ print('--targetcflags flags : List of C flags for the target code')
+ print('--targetcxxflags flags : List of C++ flags for the target code')
+ print('--libstdcxxflags flags : List of C++ flags to build the target libstdc++ code')
+ print('--source-only-download : Only download the source')
+ print('--with-<label> : Add the --with-<label> to the build')
+ print('--without-<label> : Add the --without-<label> to the build')
+ print('--rtems-tools path : Path to an install RTEMS tool set')
+ print('--rtems-bsp arc/bsp : Standard RTEMS architecure and BSP specifier')
+ print('--rtems-version ver : The RTEMS major/minor version string')
if self.optargs:
for a in self.optargs:
print('%-22s : %s' % (a, self.optargs[a]))
--
1.8.3.1
More information about the devel
mailing list