aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas "Cakeisalie5" Touhey <thomas@touhey.fr>2017-07-20 17:01:01 +0200
committerThomas "Cakeisalie5" Touhey <thomas@touhey.fr>2017-07-20 17:01:01 +0200
commit2aa28ebaf493e8c75ac5114a7f2a9280c04b3654 (patch)
treed715699f7868a424dc6a514c3808d28541690359
parent9bd5ee0017cb7ddbcbd1dca50e292e68c6eca312 (diff)
Continuing to correct the tools.
-rw-r--r--tools/Internals/exceptions.py148
-rw-r--r--tools/Internals/locale.py14
-rw-r--r--tools/Internals/locales/en_US.yml41
-rwxr-xr-xtools/Internals/module.py133
-rwxr-xr-xtools/Internals/suph.py23
-rwxr-xr-xtools/Internals/tools/__init__.py128
-rwxr-xr-xtools/Internals/tools/__util__.py23
-rw-r--r--tools/Internals/tools/gnu_ar.py100
-rw-r--r--tools/Internals/tools/gnu_as.py85
-rwxr-xr-xtools/Internals/tools/gnu_gcc.py159
-rwxr-xr-xtools/Internals/tools/renesas_asmsh.py24
-rwxr-xr-xtools/Internals/tools/renesas_optlnk.py29
-rwxr-xr-xtools/Internals/tools/renesas_shc.py46
-rwxr-xr-xtools/configure.py16
-rwxr-xr-xtools/make.py27
15 files changed, 744 insertions, 252 deletions
diff --git a/tools/Internals/exceptions.py b/tools/Internals/exceptions.py
index 5b2d6d7..2a18a56 100644
--- a/tools/Internals/exceptions.py
+++ b/tools/Internals/exceptions.py
@@ -4,6 +4,7 @@
"""
import sys
+from .locale import *
#*****************************************************************************#
# Main definitions #
@@ -16,10 +17,29 @@ import sys
class PotatoException(Exception):
''' The base class for PotatoSDK exceptions. '''
+
ret = 1
+ ags = ()
+ msg = None
+
+ def __init__(self, *args):
+ if self.msg == None:
+ message = "Internal exception '%s'"%type(self).__name__
+ else:
+ if len(args) != len(self.ags):
+ raise TypeError("Expected arguments: '%s'"%"', '".join(self.ags))
+
+ try: args = self.prepare(args)
+ except: pass
+
+ message = self.msg % args
+
+ super(PotatoException, self).__init__(message)
+
class PotatoWarning(Exception):
''' The base class for PotatoSDK warnings. '''
- pass
+ def __init__(self, *args):
+ super(PotatoWarning, self).__init__(self.message % args)
# Function to raise one of these.
@@ -28,7 +48,7 @@ def Raise(exc):
try:
raise exc
except PotatoWarning as e:
- print("WARNING: %s"%str(e))
+ print(loc['prefix']['warning'], str(e), file=sys.stderr)
# Main function wrapper.
@@ -40,10 +60,17 @@ def do_main(main_func):
except SilentException:
exit(1)
except PotatoException as e:
- print("ERROR: %s"%str(e), file=sys.stderr)
+ print(loc['prefix']['error'], str(e), file=sys.stderr)
exit(e.ret)
#*****************************************************************************#
-# Exceptions definitions #
+# Internal exceptions #
+#*****************************************************************************#
+class ToolNotFoundException(PotatoException):
+ """ (internal) A tool was not found! """
+
+ ret = 2
+#*****************************************************************************#
+# 'Public' exceptions #
#*****************************************************************************#
class SilentException(PotatoException):
""" The silent exception, for exiting silently (usually because the
@@ -56,95 +83,110 @@ class UnsupportedLanguageException(PotatoException):
""" One of the given languages were unsupported. """
ret = 2
- def __init__(self, lang):
- super(UnsupportedLanguageException, self).__init__("""\
-Language '%s' is unsupported."""%lang)
+ ags = ('language',)
+ msg = loc['exceptions']['UnsupportedLanguage']
class UnsupportedArchException(PotatoException):
""" The given arch was unsupported. """
ret = 2
- def __init__(self, arch):
- super(UnsupportedArchException, self).__init__("""\
-Architecture '%s' is unsupported."""%arch)
-
-class UnsupportedPlatformException(PotatoException):
- """ The given platform was unsupported. """
-
- ret = 2
- def __init__(self, platform):
- super(UnsupportedPlatformException, self).__init__("""\
-Platform '%s' is unsupported."""%platform)
+ ags = ('arch',)
+ msg = loc['exceptions']['UnsupportedArch']
class UpdatedModuleException(PotatoException):
""" The configuration of a module has been updated since the
last user configuration. """
ret = 2
- def __init__(self, name):
- super(UpdatedModuleException, self).__init__("""\
-Module '%s' config has been updated since last configuration.
-Please re-configure."""%name)
+ ags = ('module',)
+ msg = loc['exceptions']['UpdatedModule']
class UpdatedPlatformException(PotatoException):
""" The configuration of a platform has been updated since the
last user configuration. """
ret = 2
- def __init__(self, name):
- super(UpdatedPlatformException, self).__init__("""\
-Platform '%s' config has been updated since last configuration.
-Please re-configure."""%name)
+ ags = ('platform',)
+ msg = loc['exceptions']['UpdatedPlatform']
class UpdatedGlobalException(PotatoException):
""" The global configuration has been updated since the
last user configuration. """
ret = 2
- def __init__(self, name):
- super(UpdatedGlobalException, self).__init__("""\
-Global config has been updated since last configuration.
-Please re-configure."""%name)
+ msg = loc['exceptions']['UpdatedGlobal']
class UnresolvedDependencyException(PotatoException):
""" A module dependency could not be resolved. """
ret = 2
- def __init__(self, name, from_modules):
- super(UnresolvedDependencyException, self).__init__("""\
-Dependency '%s' from '%s' does not exist or could not be loaded!""" \
- %(name, "', '".join(from_modules)))
+ ags = ('dependency', 'from_modules')
+ msg = loc['exceptions']['UnresolvedDependency']
+
+ def prepare(self, dependency, from_modules):
+ return (dependency, "', '".join(from_modules))
class InvalidCommandException(PotatoException):
""" The given command was unknown. """
ret = 2
- def __init__(self, command):
- super(InvalidCommandException, self).__init__("""\
-Unknown command '%s'."""%command)
-
-class ToolNotFoundException(PotatoException):
- """ A tool was not found! """
-
- ret = 2
- def __init__(self, name):
- super(ToolNotFoundException, self).__init__("""\
-Tool '%s' was not found for this architecture, please add the utility
-directory to your path, or use the `--tooldir` configuration option."""%name)
+ ags = ('command',)
+ msg = loc['exceptions']['InvalidCommand']
class UnsupportedArchForModuleException(PotatoWarning):
""" A module doesn't support an architecture. """
- def __init__(self, name, arch):
- super(UnsupportedArchForModuleException, self).__init__("""\
-'%s' additional module doesn't support '%s' arch!"""%(name, arch))
+ ags = ('module', 'arch')
+ msg = loc['exceptions']['UnsupportedArchForModule']
class UnsupportedCompilerForModuleException(PotatoWarning):
""" A module doesn't support a compiler. """
- def __init__(self, name, compiler):
- super(UnsupportedCompilerForModuleException, self).__init__("""\
-'%s' additional module doesn't support '%s' compiler from '%s'!""" \
- %(name, compiler[1], compiler[0]))
+ ags = ('module', 'compiler', 'compiler_maker')
+ msg = loc['exceptions']['UnsupportedCompilerForModule']
+
+class PlatformNotFoundException(PotatoException):
+ """ The given platform was unsupported. """
+
+ ret = 2
+ ags = ('platform',)
+ msg = loc['exceptions']['PlatformNotFound']
+
+class ModuleNotFoundException(PotatoException):
+ """ A module was not found! """
+
+ ret = 2
+ ags = ('module',)
+ msg = loc['exceptions']['ModuleNotFound']
+
+class NoCCompilerException(PotatoException):
+ """ No appropriate C compiler was found. """
+
+ ret = 2
+ msg = loc['exceptions']['NoCCompiler']
+
+class NoCppCompilerException(PotatoException):
+ """ No appropriate C++ compiler was found. """
+
+ ret = 2
+ msg = loc['exceptions']['NoCppCompiler']
+
+class NoCAssemblerException(PotatoException):
+ """ No appropriate ASM-C compiler was found. """
+
+ ret = 2
+ msg = loc['exceptions']['NoCAssembler']
+
+class NoAssemblerException(PotatoException):
+ """ No appropriate assembler was found. """
+
+ ret = 2
+ msg = loc['exceptions']['NoAssembler']
+
+class NoPackerException(PotatoException):
+ """ No appropriate packer was found. """
+
+ ret = 2
+ msg = loc['exceptions']['NoPacker']
# End of file.
diff --git a/tools/Internals/locale.py b/tools/Internals/locale.py
new file mode 100644
index 0000000..34c1df0
--- /dev/null
+++ b/tools/Internals/locale.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python3
+""" Locale management.
+ Here, we load the appropriate locale among the ones in the `locales`
+ folder, and put it in the `loc` variable, which the modules will
+ then include.
+"""
+
+import os
+import yaml
+
+loc = yaml.load(open(os.path.join(os.path.dirname(__file__),
+ 'locales', 'en_US.yml')).read())
+
+# End of file.
diff --git a/tools/Internals/locales/en_US.yml b/tools/Internals/locales/en_US.yml
new file mode 100644
index 0000000..825efb0
--- /dev/null
+++ b/tools/Internals/locales/en_US.yml
@@ -0,0 +1,41 @@
+%YAML 1.2
+---
+prefix:
+ warning: "Warning:"
+ error: "Error:"
+exceptions:
+ UnsupportedLanguage: >-
+ Language '%s' is unsupported.
+ UnsupportedArch: >-
+ Architecture '%s' is unsupported.
+ UpdatedModule: >-
+ Module '%s' configuration has been updated since last configuration.
+ Please re-configure.
+ UpdatedPlatform: >-
+ Platform '%s' configuration has been updated since last configuration.
+ Please re-configure.
+ UpdatedGlobal: >-
+ Global configuration has been updated since last configuration.
+ Please re-configure.
+ UnresolvedDependency: >-
+ Dependency '%s' from '%s' does not exist or could not be loaded!
+ InvalidCommand: >-
+ Unknown command '%s'.
+ UnsupportedArchForModule: >-
+ '%s' additional module doesn't support '%s' arch!
+ UnsupportedCompilerForModule: >-
+ '%s' additional module doesn't support '%s' compiler from '%s'!
+ PlatformNotFound: >-
+ Platform '%s' was not found or invalid!
+ ModuleNotFound: >-
+ Module '%s' was not found or invalid!
+ NoCCompiler: >-
+ No appropriate C compiler was found.
+ NoCppCompiler: >-
+ No appropriate C++ compiler was found.
+ NoCAssembler: >-
+ No appropriate ASM-C compiler was found.
+ NoAssembler: >-
+ No appropriate assembler was found.
+ NoPacker: >-
+ No appropriate archiver was found.
diff --git a/tools/Internals/module.py b/tools/Internals/module.py
index 0ef9159..cb46592 100755
--- a/tools/Internals/module.py
+++ b/tools/Internals/module.py
@@ -1,70 +1,105 @@
#!/usr/bin/env python3
-''' Source module class and functions for libcarrot build. '''
+""" The main thing about libcarrot's organization, if you haven't understood
+ yet, is that it works using modules. This is the main management file
+ for modules: module object, finding modules out of user configuration
+ options, and gather modules out of a list.
+
+ The used configuration formats are in `FORMATS.md`.
+"""
import os, sys
import yaml
+from time import time
from .exceptions import *
-# The module class.
+#*****************************************************************************#
+# Source module object #
+#*****************************************************************************#
class SourceModule:
- ''' The source module class.
- `root` is the modules root.
- `name` is the module category and name, e.g. `casiowin/fxlib`. '''
- def __init__(self, root, name):
- ''' Initialize the class, gather the information from the FS. '''
- nameparts = name.split('/') + ['info.yml']
- configpath = os.path.join(root, *nameparts)
- config = yaml.load(open(configpath).read())
-
- # Get the meta information.
+ """ The source module class.
+ Extracts data from the filesystem, and offer utilities to interact
+ with its elements easily.
+ """
+
+ def __init__(self, root, name, mtim):
+ """ Initialize the class, gather the information from the platform
+ then the module configuration, and deduce module properties
+ out of it.
+
+ `root` is the modules root (generally `./arch`).
+ `name` is the module platform and name, e.g. `casiowin/fxlib`.
+ `mtim` is the reference modification time for the user config.
+ """
+
+ # Open the platform configuration, then the module configuration.
+ namepts = name.split('/')
+ pconfigpath = os.path.join(root, namepts[0], 'info.yml')
+ mconfigpath = os.path.join(root, namepts[0], namepts[1], 'info.yml')
+ try:
+ pconfig = yaml.load(open(pconfigpath))
+ except FileNotFoundError:
+ Raise(PlatformNotFoundException(namepts[0]))
+ try:
+ mconfig = yaml.load(open(mconfigpath))
+ except FileNotFoundError:
+ Raise(ModuleNotFoundException(name))
+
+ if os.path.getmtime(pconfigpath) > mtim:
+ Raise(UpdatedPlatformException(namepts[0]))
+ if os.path.getmtime(mconfigpath) > mtim:
+ Raise(UpdatedModuleException(name))
+
+ # Keep the arguments.
self.root = root
self.name = name
- nameparts = name.split('/')
- self.__root = os.path.join(self.root, *nameparts)
- self.description = config['description']
- self.compiler = config['compiler'] if 'compiler' in config else []
- self.deps = config['deps'] if 'deps' in config else []
- self.conflicts = config['conflicts'] if 'conflicts' in config else []
- self.out = config['out'] if 'out' in config else 'libc'
- self.mtim = os.path.getmtime(configpath)
- if 'requires' in config:
- req = config['requires']
- self.compiler = req['compiler'] if 'compiler' in req else None
- self.arch = req['arch'] if 'arch' in req else []
- else:
- self.compiler = None
- self.arch = []
-
- # Get non-initialized options from the parent configuration.
- platform_config_path = \
- os.path.join(root, name.split('/')[0], 'info.yml')
- try: cfile = open(platform_config_path)
- except: True
- else:
- platform_config = yaml.load(cfile); del cfile
- if not 'arch' in config and 'arch' in platform_config:
- self.arch = platform_config['arch']
+ self.__root = os.path.join(self.root, namepts[0], namepts[1])
+ self.__objroot = os.path.normpath(os.path.join(self.root, '..',
+ 'obj', namepts[0], namepts[1]))
+ self.mtim = os.path.getmtime(mconfigpath)
+
+ # Get the usual things.
+ self.description = mconfig['description']
+ self.out = mconfig['out'] if 'out' in mconfig else 'libc'
+ self.deps = mconfig['deps'] if 'deps' in mconfig else []
+ self.conflicts = mconfig['conflicts'] if 'conflicts' in mconfig else []
+
+ # Get the requirements.
+ self.compiler = []
+ self.arch = []
+ if 'requires' in mconfig:
+ r = mconfig['requires']
+ if 'compiler' in r:
+ self.compiler = r['compiler']
+ if 'arch' in r:
+ self.arch = r['arch']
+ if not self.arch and 'arch' in pconfig:
+ self.arch = pconfig['arch']
def getpath(self, *elements):
- ''' Get the complete path of a subdirectory. '''
- return os.path.join(self.__root, *elements)
+ """ Get the complete path within a directory. """
+
+ # Get the root, adjust the elements if necessary.
+ rt = self.__root
+ if elements and elements[0] == 'obj':
+ rt = self.__objroot
+ elements = elements[1:]
+
+ # Join it all and send it back!
+ return os.path.join(rt, *elements)
def getfiles(self, directory, extensions):
''' Get the files list. '''
- # Check if it is the object directory.
- if directory == 'obj':
- root = os.path.join(directory, self.name, '')
- else:
- root = os.path.join(self.root, self.name, directory, '')
+ # Get the root.
+ root = self.getpath(directory)
# Get the source files.
files = []
for r, _, filenames in os.walk(root):
for f in filenames:
pos = f.find('.')
- if pos < 0 and None in extensions:
+ if pos < 0 and not None in extensions:
continue
elif pos >= 0 and not f[pos + 1:] in extensions:
continue
@@ -99,7 +134,7 @@ def list_modules(root, arch, compiler = ('GNU', 'GCC'), \
# First, get the additional modules, and check if one of them is of
# an unsupported language.
for name in set(additional_modules):
- module = SourceModule(root, name)
+ module = SourceModule(root, name, time())
if arch and module.arch and not arch in module.arch:
Raise(UnsupportedArchForModuleException(name, arch))
continue
@@ -126,7 +161,7 @@ def list_modules(root, arch, compiler = ('GNU', 'GCC'), \
if not key in default: default[key] = []
default[key] += config['default'][key]
except FileNotFoundError:
- Raise(UnsupportedPlatformException(platform))
+ Raise(PlatformNotFoundException(platform))
# Add C dependencies to C++ dependencies.
if not 'c++' in default:
@@ -141,7 +176,7 @@ def list_modules(root, arch, compiler = ('GNU', 'GCC'), \
for name in lmod:
if name in modules:
continue
- module = SourceModule(root, name)
+ module = SourceModule(root, name, time())
if arch and module.arch and not arch in module.arch:
continue
if module.compiler and not compiler in module.compiler:
@@ -156,7 +191,7 @@ def list_modules(root, arch, compiler = ('GNU', 'GCC'), \
for dep in newdeps:
name = dep[0]
try:
- module = SourceModule(root, name, default)
+ module = SourceModule(root, name, time())
except Exception:
Raise(UnresolvedDependencyException(name, dep[1]))
blacklist.append(name)
diff --git a/tools/Internals/suph.py b/tools/Internals/suph.py
index 251401c..6324f4a 100755
--- a/tools/Internals/suph.py
+++ b/tools/Internals/suph.py
@@ -1,12 +1,25 @@
#!/usr/bin/env python3
-''' This tool makes an include file from libcasio files. '''
+''' This tool is the libcarrot super-preprocessor.
+ It was previously called 'makeinc' or 'makeinc.py', but has been merged
+ into the internals for more efficient calls.
+
+ What it basically does is:
+ - add full (comment) headers out of metas, with licence content & stuff;
+ - add include guards;
+ - reindent preprocessor directives;
+ - add the `#include_bits` preprocessor directive, which embeds zero or
+ more "header bits" using the bits PATH (list of directories where to
+ find bits).
+
+ Features to come are:
+ - macro profiling, in order to skip some conditions and optimize the
+ headers for the end user;
+ - better header metadata (different licences from LGPLv3, ...).
+'''
import os, yaml
from sys import stderr
-#*****************************************************************************#
-# Useful functions #
-#*****************************************************************************#
def getheader(path_in):
''' Gets the header information from a file. '''
@@ -227,8 +240,6 @@ def make_header(base, name, out_path):
ics[name] = {'base': base, 'bits': bdeps,
'mtim': os.path.getmtime(out_path)}
-
-
def suph(incdir, incdirs, bitdirs):
# Open the cache.
try:
diff --git a/tools/Internals/tools/__init__.py b/tools/Internals/tools/__init__.py
index af725b6..4bd6f2a 100755
--- a/tools/Internals/tools/__init__.py
+++ b/tools/Internals/tools/__init__.py
@@ -1,4 +1,97 @@
#!/usr/bin/env python3
+""" This is the main build tool directory/interface.
+
+ It is responsible for finding tools and their configuration
+ out of user configuration, such as the used languages, the output
+ formats (object format, library format),
+ and for applying these tools and configurations and make them available
+ through a platform-agnostic interface.
+
+ Tools are identified by their manufacturer, e.g. 'GNU' or 'Borland',
+ and by their name, e.g. 'GCC' or 'Turbo C++'.
+ Each tool interface is a simple {"function": function} dictionary, where:
+ - "getparams": get the tool configuration for which the tool class will
+ be able to do the job (raises an exception if it doesn't manage);
+ this function takes different parameters depending on the role it
+ is supposed to occupy;
+ - "cc": make an object file out of a C source file (and headers);
+ - "cxx": make an object file out of a C++ source file (and headers);
+ - "asmc": make an object file out of an ASM-C source file (and headers);
+ - "asm": make an object file out of an ASM source file;
+ - "pack": make a static library out of object files.
+
+ For a C compiler, the `getparams` function should have this prototype:
+
+ def <getparams>(typ, arch, obj_format, std)
+
+ Where `typ` is "cc", `arch` is the architecture for which we're building,
+ `std` is the C standards list the compiler shall support, and `obj_format`
+ is the object format the compiler should produce.
+
+ The C compilation function itself should have this prototype:
+
+ def <cc>(params, obj, src, incdirs, std)
+
+ Where `params` is the parameters object generated by the `getparams`
+ function, `obj` is the path of the object to make, `src` is the path
+ of the C source file, `incdirs` is the list of header directories,
+ and `std` is the C standard to compile in.
+
+ The C++ interface is more or less the same, except it is for C++,
+ so the `typ` parameter of the `getparams` function is "cxx",
+ and the "cxx" function should be set.
+
+ For the ASM-C interface, the `getparams` function should have this
+ prototype:
+
+ def <getparams>(typ, arch, obj_format)
+
+ Where `typ` is "asmc", and the rest of the arguments are the same than
+ for the C compiler `getparams` function.
+
+ The ASM-C compilation function itself should have this prototype:
+
+ def <asmc>(params, obj, src, incdirs)
+
+ Where `params` is the parameters object generated by the `getparams`
+ function, `obj` is the path of the object to make, `src` is the
+ path of the ASM-C source file, and `incdirs` is the list of header
+ directories.
+
+ For the ASM interface, the `getparams` function should have this
+ prototype:
+
+ def <getparams>(typ, arch, obj_format, syntax)
+
+ Where `typ` is "asm", `arch` is the architecture for which to build,
+ `obj_format` is the object format to produce, and `syntax` is the
+ syntax name, depending on the architecture.
+
+ The `asm` function itself should be defined as:
+
+ def <asm>(params, obj, src)
+
+ Where `params` is the parameters object generated by the `getparams`
+ function, `obj` is the path of the object to make, and `src` is the
+ path of the assembly source file.
+
+ For the static library generator interface, the `getparams` function
+ should have this prototype:
+
+ def <getparams>(typ, arch, lib_format, object_format)
+
+ Where `typ` is "pack", `arch` is the architecture for which to build,
+ `lib_format` is the library format, and `obj_format` is the object
+ format the function takes.
+
+ The `pack` function itself should be defined as:
+
+ def <pack>(params, lib, objs)
+
+ Where `params` is the parameters object generated by the `getparams`
+ function, `lib` is the path where to make the library, and `objs` is
+ the list of objects to pack.
+"""
import os, sys, functools as ft
from subprocess import call
@@ -70,11 +163,36 @@ def find(languages, arch):
asmc_name = ('GNU', 'GCC')
pack_name = ('GNU', 'ar')
- cp = __c_compilers[cc_name]['getparams']('cc', arch)
- cxxp = __cxx_compilers[cxx_name]['getparams']('cxx', arch)
- asmcp = __c_assemblers[asmc_name]['getparams']('asmc', arch)
- asp = __assemblers[asm_name]['getparams']('asm', arch)
- arp = __archivers[pack_name]['getparams']('pack', arch)
+ # Setup the C compiler.
+ try:
+ cp = __c_compilers[cc_name]['getparams']('cc', arch, 'elf', ['c89'])
+ except ToolNotFoundException:
+ Raise(NoCCompilerException)
+
+ # Setup the C++ compiler.
+ try:
+ cxxp = __cxx_compilers[cxx_name]['getparams']('cxx', arch,
+ 'elf', ['c++98'])
+ except ToolNotFoundException:
+ Raise(NoCppCompilerException)
+
+ # Setup the C-ASM compiler.
+ try:
+ asmcp = __c_assemblers[asmc_name]['getparams']('asmc', arch, 'elf')
+ except ToolNotFoundException:
+ Raise(NoCAssemblerException)
+
+ # Setup the assembler.
+ try:
+ asp = __assemblers[asm_name]['getparams']('asm', arch, 'elf', 'gnu')
+ except ToolNotFoundException:
+ Raise(NoAssemblerException)
+
+ # Setup the packer.
+ try:
+ arp = __archivers[pack_name]['getparams']('pack', arch, 'coff', 'elf')
+ except ToolNotFoundException:
+ Raise(NoPackerException)
return {
'cc': cc_name, 'cc_params': cp,
diff --git a/tools/Internals/tools/__util__.py b/tools/Internals/tools/__util__.py
index 8ec1e79..637a7a2 100755
--- a/tools/Internals/tools/__util__.py
+++ b/tools/Internals/tools/__util__.py
@@ -14,7 +14,7 @@ def add_tooldir(tooldir):
__path.append(tooldir)
# Tool management.
-def getutil(name, tools):
+def getutil(tools):
# Check that the tools is a list.
if type(tools) != list:
tools = [tools]
@@ -24,10 +24,7 @@ def getutil(name, tools):
l = os.listdir(udir)
for tool in tools:
if tool in l:
- return os.path.join(udir, tool)
-
- # There is no such utility :(
- Raise(ToolNotFoundException(name))
+ yield os.path.join(udir, tool)
#*****************************************************************************#
# GNU-specific utilities #
#*****************************************************************************#
@@ -46,9 +43,17 @@ def getgnu(arch, tool):
for arches, prefixes in __gnu_prefixes:
if not arch in arches:
continue
- return getutil(tool,
- ['%s-elf-%s' %(pre, tool) for pre in prefixes] +
- ['%s-elf-%s.exe'%(pre, tool) for pre in prefixes])
- Raise(ToolNotFoundException(tool))
+ tools = \
+ ['%s-elf-%s' %(pre, tool) for pre in prefixes] + \
+ ['%s-elf-%s.exe'%(pre, tool) for pre in prefixes]
+ for path in getutil(tools):
+ yield path
+
+def check_bfd_arch(arch, bfd_arch):
+ for arches, prefixes in __gnu_prefixes:
+ if not arch in arches:
+ continue
+ return bfd_arch in prefixes
+ return False
# End of file.
diff --git a/tools/Internals/tools/gnu_ar.py b/tools/Internals/tools/gnu_ar.py
index b4a2fb3..2dcdbe4 100644
--- a/tools/Internals/tools/gnu_ar.py
+++ b/tools/Internals/tools/gnu_ar.py
@@ -1,41 +1,86 @@
#!/usr/bin/env python3
-''' The GNU archiver. '''
+""" These functions bring the GNU archive manager, part of GNU binutils,
+ to the libcarrot build tools.
+
+ When configured for a non-native target, as for all GNU Binutils elements,
+ GCC will install the binary as `<bfd target>-ar`, so we're looking for
+ something like `<arch>-<os or format>-ar`, e.g. `sh3eb-elf-ar` for
+ platform-independent assembler for the SuperH Core 3, big endian version,
+ generating ELF object files or executables.
+
+ If there is no appropriate non-native target, the native assembler might
+ just be usable. We just have to check the BFD target in GNU ar's help
+ message (non-translated version).
+"""
import os
import tempfile
from subprocess import call, check_output
from .__util__ import *
-def __getparams(typ, arch):
+#*****************************************************************************#
+# Discovery, configuration #
+#*****************************************************************************#
+def __get_ar_bfd(path):
+ """ Get the supported BFD targets out of the ar binary path. """
+
+ # Make the help command with the default locale, get the output.
+ env = os.environ.copy()
+ env['LANG'] = 'en_US'
+ out = check_output([path, '--help'], env=env).decode()
+
+ # Get the appropriate line.
+ lines = [line for line in out.splitlines() if len(line.split(':')) == 3 \
+ and line.split(':')[1] == ' supported targets']
+ if len(lines) != 1:
+ return []
+
+ # Get the BFD targets.
+ bfd = []
+ for element in lines[0].split(':')[2].split():
+ t = element.split('-')
+ if len(t) == 1:
+ continue
+ bfd.append((t[0], '_'.join(t[1:])))
+ return bfd
+
+def __iter_ar(arch):
+ """ Iterate through all of the `ar` occurrences among the system. """
+
+ for elt in getgnu(arch, 'ar'):
+ yield elt
+ for elt in getutil(['ar', 'ar.exe']):
+ yield elt
+
+def __getparams(typ, arch, lib_format, obj_format):
''' Get the params. '''
+ if obj_format[:3] != 'elf':
+ raise ToolNotFound
+
# Get the utility
- try: gar = getgnu(arch, 'ar')
- except ToolNotFoundException:
- gar = getutil('ar', ['ar', 'ar.exe'])
- env = os.environ.copy()
- env['LANG'] = 'en_US'
- out = check_output([gar, '--help'], env=env).decode()
- lns = [line for line in out.splitlines() if len(line.split(':')) == 3 \
- and line.split(':')[1] == ' supported targets']
- if len(lns) != 1:
- Raise(ToolNotFoundException('ar'))
- targets = lns[0].split(':')[2].split()
- target_found = False
- for target in targets:
- target = '_'.join(target.split('-')[1:])
- if target == arch:
- target_found = True
- break
- if not target_found:
- Raise(ToolNotFoundException('ar'))
-
- return {'path': gar}
-
-def __getformats(params):
- ''' Get the supported archive formats. '''
- return ['coff']
+ path = None
+ for gar in __iter_ar(arch):
+ bfd_list = __get_ar_bfd(gar)
+
+ for bfd in bfd_list:
+ if not check_bfd_arch(arch, bfd[1]):
+ continue
+ if bfd[0] != lib_format:
+ continue
+
+ path = gar
+ break
+
+ if path: break
+
+ if not path:
+ Raise(ToolNotFoundException)
+ return {'path': path}
+#*****************************************************************************#
+# Usage #
+#*****************************************************************************#
def __pack(params, lib, objs):
# Set up the MRI script.
tmp_fd, tmp_path = tempfile.mkstemp(suffix='.mri')
@@ -57,7 +102,6 @@ def __pack(params, lib, objs):
__all__ = ["GNU_AR"]
GNU_AR = {
'getparams': __getparams,
- 'getfmt_ar': __getformats,
'pack': __pack
}
diff --git a/tools/Internals/tools/gnu_as.py b/tools/Internals/tools/gnu_as.py
index efe7e08..241bd26 100644
--- a/tools/Internals/tools/gnu_as.py
+++ b/tools/Internals/tools/gnu_as.py
@@ -1,23 +1,78 @@
#!/usr/bin/env python3
-''' The GNU assembler. '''
+""" These functions bring the GNU assembler, part of GNU binutils,
+ to the libcarrot build tools.
+
+ When configured for a non-native target, as for all GNU Binutils elements,
+ GCC will install the binary as `<bfd target>-as`, so we're looking for
+ something like `<arch>-<os or format>-as`, e.g. `sh3eb-elf-as` for
+ platform-independent assembler for the SuperH Core 3, big endian version,
+ generating ELF object files or executables.
+
+ If there is no appropriate non-native target, the native assembler might
+ just be usable. We just have to check the BFD target in GNU as' version
+ message (non-translated version).
+"""
import os
from subprocess import call, check_output
from .__util__ import *
-def __getparams(typ, arch):
- ''' Get the parameters. '''
+#*****************************************************************************#
+# Discovery, configuration #
+#*****************************************************************************#
+def __get_as_bfd(path):
+ """ Get the BFD target out of the as binary path. """
+
+ # Make the version command with the default locale, get the output.
+ env = os.environ.copy()
+ env['LANG'] = 'en_US'
+ out = check_output([path, '--version'], env=env).decode()
+
+ # Get the BFD target, which is on the last line, e.g.
+ # This assembler was configured for a target of `sh3eb-elf'.
+ bfd = out.splitlines()[-1].split('`')[1].split("'")[0]
+
+ # Get the format using the platform.
+ bfd = bfd.split('-')
+ arch = bfd[0]
+ plt = '-'.join(bfd[1:])
+ if plt == "pc-linux-gnu":
+ plt = "elf"
+ # TODO: others
+
+ # Return.
+ return (arch, plt)
+
+def __iter_as(arch):
+ """ Iterate through all of the `as` occurrences among the system. """
+
+ for elt in getgnu(arch, 'as'):
+ yield elt
+ for elt in getutil(['as', 'as.exe']):
+ yield elt
+
+def __getparams(typ, arch, objfmt, syntax):
+ """ Get the assembler parameters. """
+
+ # Check the object format.
+ # TODO: some configurations of AS produce other formats such as PE...?
+ if objfmt != 'elf':
+ raise ToolNotFound
# Get the utility.
- try: gas = [getgnu(arch, 'as')]
- except ToolNotFoundException:
- gas = getutil('as', ['as', 'as.exe'])
- env = os.environ.copy()
- env['LANG'] = 'en_US'
- out = check_output([gas, '--version'], env=env).decode()
- bfd = out.splitlines()[-1].split('`')[1].split("'")[0]
- if bfd.split('-')[0] != arch:
- Raise(ToolNotFoundException('as'))
+ path = None
+ for gas in __iter_as(arch):
+ bfd = __get_as_bfd(gas)
+
+ if not check_bfd_arch(arch, bfd[0]):
+ continue
+ if bfd[1] != objfmt:
+ continue
+
+ path = gas
+ break
+ if not path:
+ Raise(ToolNotFoundException)
# Get the flags.
flags = []
@@ -26,8 +81,10 @@ def __getparams(typ, arch):
arch = arch[:-3]
flags += ['--isa=' + arch, '--big']
- return {'path': gas, 'flags': flags}
-
+ return {'path': path, 'flags': flags}
+#*****************************************************************************#
+# Usage #
+#*****************************************************************************#
def __asm(params, obj, src):
# Set up the command line.
commandline = [params['path']]
diff --git a/tools/Internals/tools/gnu_gcc.py b/tools/Internals/tools/gnu_gcc.py
index d849a50..a6d2dee 100755
--- a/tools/Internals/tools/gnu_gcc.py
+++ b/tools/Internals/tools/gnu_gcc.py
@@ -1,71 +1,138 @@
#!/usr/bin/env python3
-''' The GNU C Compiler. '''
+""" These functions bring the GNU Compiler Collection, more precisely
+ the C/C++ compiler, to the libcarrot build tools.
+
+ When configured for a non-native target, GCC will install its binary as
+ `<bfd target>-gcc` in the host binary directory, so we're looking for
+ something like `<arch>-<os or format>-gcc`, e.g. `sh3eb-elf-gcc` for
+ platform-independent gcc for the SuperH Core 3, big endian version,
+ generating ELF object files or executables.
+
+ If there is no appropriate non-native target, the native compiler might
+ just be usable. We just have to check the BFD target using
+ GCC's `-dumpmachine` option.
+"""
import os
from subprocess import call, check_output, DEVNULL
from tempfile import mkstemp
from .__util__ import *
-def __teststd(path, standards):
- ''' Test if GCC supports those standards using the `-std` option. '''
+#*****************************************************************************#
+# Discovery, configuration #
+#*****************************************************************************#
+def __get_gcc_bfd(path):
+ """ Get the BFD target out of the gcc binary path. """
- sfd, sf = mkstemp(suffix='.c', text='int main(void) { return (0); }')
+ # Make the dump command with the default locale, get the output.
+ env = os.environ.copy()
+ env['LANG'] = 'en_US'
+ out = check_output([path, '-dumpmachine'], env=env).decode().strip()
+
+ # Check the BFD target.
+ bfd = out.split('-')
+ arch = bfd[0]
+ plt = '-'.join(bfd[1:])
+ if plt == "pc-linux-gnu":
+ plt = "elf"
+ # TODO: others
+
+ # Return
+ return (arch, plt)
+
+def __iter_gcc(arch):
+ """ Iterate through all of the `gcc` occurrences among the system. """
+
+ for elt in getgnu(arch, 'gcc'):
+ yield elt
+ for elt in getutil(['gcc', 'gcc.exe']):
+ yield elt
+
+def __testcc(typ, path='/usr/bin/gcc', flags=[],
+ text='int main(void) { return (0); }'):
+ """ Try to compile, see if it works. """
+
+ if typ == "cc":
+ source_suffix = '.c'
+ gcc_lang = 'c'
+ elif typ == "cxx":
+ source_suffix = '.cpp'
+ gcc_lang = 'c++'
+ elif typ == "asmc":
+ source_suffix = '.sx'
+ gcc_lang = 'assembler-with-cpp'
+
+ sfd, sf = mkstemp(suffix=source_suffix, text=text)
os.close(sfd)
- std = []
- for s in standards:
- ofd, of = mkstemp(suffix='.o')
- os.close(ofd)
+ ofd, of = mkstemp(suffix='.o')
+ os.close(ofd)
- cl = [path, '-x', 'c', '-std=%s'%s, '-o', of, sf, '-nostdlib']
- if not call(cl, shell=False, stdout=DEVNULL, stderr=DEVNULL):
- std.append(s)
+ cl = [path, '-x', gcc_lang, '-o', of, sf, '-nostdlib'] + flags
+ if call(cl, shell=False, stdout=DEVNULL, stderr=DEVNULL):
+ worked = False
+ else:
+ worked = True
- try: os.remove(of)
- except: pass
+ try: os.remove(of)
+ except: pass
+ try: os.remove(sf)
+ except: pass
- os.remove(sf)
- return std
+ return worked
-def __getparams(typ, arch):
- ''' Get the parameters. '''
+def __teststd(typ, path, standards):
+ ''' Test if GCC supports those standards using the `-std` option. '''
- # Get the compiler path.
- try: gcc = getgnu(arch, 'gcc')
- except ToolNotFoundException:
- gcc = getutil('gcc', ['gcc', 'gcc.exe'])
- bfd = check_output([gcc, '-dumpmachine']).decode().strip()
- if bfd.split('-')[0] != arch:
- Raise(ToolNotFoundException('gcc'))
+ for s in standards:
+ if not __testcc(typ, path, ['-std=%s'%s]):
+ return False
+ return True
- # Get the compilation flags.
- # TODO: use `-ffreestanding` (implies `-fno-builtin`?)
- cflags = ['-Wall', '-Wextra', '-Wno-attributes',
- '-O2', '-nostartfiles', '-fno-builtin-function']
+def __getparams(typ, arch, objfmt, std=[]):
+ """ Get the GNU Compiler Collection respecting some
+ pre-defined constraints. """
- # Get the CPU flags.
+ # Prepare the minimum compilation flags.
+ cflags = []
if arch[:2] == 'sh':
cflags += ['-mhitachi', '-fomit-frame-pointer']
if arch[-3:] == 'dsp':
cflags.append('-Wa,-dsp')
arch = arch[:-3]
- cflags += ['-m' + arch[2:], '-mb']
+ cflags += ['-m%s'%arch[2:], '-mb']
else:
- # FIXME: raise exception?
- cflags.append('-march=' + arch)
-
- ret = {'path': gcc, 'flags': cflags}
- if typ == 'cc':
- ret['std'] = __teststd(gcc, ['c89', 'c95', 'c99', 'c11'])
- elif typ == 'cxx':
- ret['std'] = __teststd(gcc, ['c++98', 'c++11', 'c++14', 'c++17'])
- return ret
-
-def __getstd(params):
- ''' Get the supported C standards. '''
-
- return params['std']
+ # FIXME: is it like this for everything? raise exception here?
+ cflags.append('-march=%s'%arch)
+
+ # Get the utility.
+ path = None
+ for gcc in __iter_gcc(arch):
+ bfd = __get_gcc_bfd(gcc)
+
+ if not check_bfd_arch(arch, bfd[0]):
+ continue
+ if bfd[1] != objfmt:
+ continue
+ if not __testcc(typ, gcc, cflags):
+ continue
+ if typ != "asmc" and not __teststd(typ, gcc, std):
+ continue
+
+ path = gcc
+ break
+ if not path:
+ Raise(ToolNotFoundException)
+
+ # Get the rest of the compilation flags.
+ # TODO: use `-ffreestanding` (implies `-fno-builtin`?)
+ cflags += ['-Wall', '-Wextra', '-Wno-attributes',
+ '-O2', '-nostartfiles', '-fno-builtin-function']
+ return {'path': path, 'flags': cflags}
+#*****************************************************************************#
+# Use the parameters #
+#*****************************************************************************#
def __makeenv(incdirs):
incpath = os.pathsep.join(incdirs)
env = os.environ.copy()
@@ -102,11 +169,11 @@ def __asmc(params, obj, src, incdirs):
# Make the call.
return call(commandline, env=__makeenv(incdirs))
+# Main entry.
+
__all__ = ["GNU_GCC"]
GNU_GCC = {
'getparams': __getparams,
- 'getcstd': __getstd,
- 'getcxxstd': __getstd,
'cc': __cc,
'cxx': __cxx,
'asmc': __asmc
diff --git a/tools/Internals/tools/renesas_asmsh.py b/tools/Internals/tools/renesas_asmsh.py
index 8fff98c..4d76c3f 100755
--- a/tools/Internals/tools/renesas_asmsh.py
+++ b/tools/Internals/tools/renesas_asmsh.py
@@ -1,23 +1,37 @@
#!/usr/bin/env python3
-''' The Renesas SuperH assembler. '''
+""" These functions bring the Renesas SuperH proprietary Assembler to
+ the libcarrot build tools.
+
+ You can find more information about this assembler in the toolchain manual:
+ https://bible.planet-casio.com/renesas/rej10b0152_sh.pdf
+"""
import os, tempfile
from subprocess import call
from .__util__ import *
-def __getparams(typ, arch):
+#*****************************************************************************#
+# Discovery, configuration #
+#*****************************************************************************#
+def __getparams(typ, arch, obj_format, std):
''' Get the parameters. '''
+
if arch[:2] != 'sh':
- raise Exception
+ raise UnsupportedArchException(arch)
+
+ # Get the tool.
+ try: asmsh = next(getutil(['asmsh.exe']))
+ except StopIteration: Raise(ToolNotFoundException)
- asmsh = getutil('asmsh', ['asmsh.exe'])
CPU = arch.upper()
flags = ['-cpu=%s'%arch, '-endian=big']
if arch[-3:] == 'dsp':
flags.append('-dspc')
return {'path': asmsh, 'CPU': CPU, 'flags': flags}
-
+#*****************************************************************************#
+# Usage #
+#*****************************************************************************#
def __asm(self, obj, src, incdirs):
''' Assemble a source assembly file. '''
diff --git a/tools/Internals/tools/renesas_optlnk.py b/tools/Internals/tools/renesas_optlnk.py
index 50fe02a..d6aeb78 100755
--- a/tools/Internals/tools/renesas_optlnk.py
+++ b/tools/Internals/tools/renesas_optlnk.py
@@ -1,20 +1,34 @@
#!/usr/bin/env python3
-''' The Renesas Optimize Linker. '''
+""" These functions bring the Renesas SuperH proprietary Optimizing Linker
+ (and archiver) to the libcarrot build tools.
+
+ You can find more information about this tool in the toolchain manual:
+ https://bible.planet-casio.com/renesas/rej10b0152_sh.pdf
+"""
import os, tempfile
from subprocess import call
from .__util__ import *
-def __getparams(typ, arch):
+#*****************************************************************************#
+# Discovery, configuration #
+#*****************************************************************************#
+def __getparams(typ, arch, lib_format, obj_format):
''' Get the parameters. '''
- return {'path': getutil('optlnk', ['Optlnk.exe'])}
-
-def __getformats(params):
- ''' Get the supported archive formats. '''
+ # Check the format.
+ if lib_format != 'HLIB' or obj_format != 'ELF':
+ Raise(ToolNotFoundException)
- return ['hlib']
+ # Check the path.
+ try: optlnk = next(getutil(['optlnk.exe']))
+ except: Raise(ToolNotFoundException)
+ # Return the parameters.
+ return {'path': optlnk}
+#*****************************************************************************#
+# Usage #
+#*****************************************************************************#
def __pack(params, lib, objs):
''' Pack the object files into an archive. '''
@@ -40,7 +54,6 @@ def __pack(params, lib, objs):
__all__ = ["Renesas_OptLnk"]
Renesas_OptLnk = {
'getparams': __getparams,
- 'getfmt_ar': __getformats,
'pack': __pack
}
diff --git a/tools/Internals/tools/renesas_shc.py b/tools/Internals/tools/renesas_shc.py
index 836f781..288d8e2 100755
--- a/tools/Internals/tools/renesas_shc.py
+++ b/tools/Internals/tools/renesas_shc.py
@@ -1,36 +1,42 @@
#!/usr/bin/env python3
-''' The Renesas C/C++ Compiler. '''
+""" These functions bring the Renesas SuperH C/C++ proprietary Compiler to
+ the libcarrot build tools.
+
+ You can find more information about this compiler in the toolchain manual:
+ https://bible.planet-casio.com/renesas/rej10b0152_sh.pdf
+"""
import os
from subprocess import call
from .__util__ import *
-def __getparams(typ, arch):
- ''' Get the parameters. '''
+#*****************************************************************************#
+# Discovery, configuration #
+#*****************************************************************************#
+def __getparams(typ, arch, objfmt, std):
+ """ Get the parameters. """
+
+ # Check the architecture, the output format, and the standards.
+ if arch[:2] != 'sh' or objfmt != 'elf' or \
+ (typ == "cc" and std != ['c89']) or (typ == "cxx" and std != ['c++98']):
+ Raise(ToolNotFoundException)
- if arch[:2] != 'sh':
- raise UnsupportedArchException(arch)
+ # Get the tool path.
+ try: shc = next(getutil(['shc.exe']))
+ except StopIteration: Raise(ToolNotFoundException)
- shc = getutil('shc', ['shc.exe'])
+ # Get the flags.
CPU = arch.upper()
flags = ['-cpu=%s'%arch, '-endian=big']
if arch[-3:] == 'dsp':
flags.append('-dspc')
return {'path': shc, 'CPU': CPU, 'flags': flags}
-
-def __getstd_c(params):
- ''' Get the supported C standards. '''
-
- return ['c89']
-
-def __getstd_cxx(params):
- ''' Get the supported C++ standards. '''
-
- return ['c++98']
-
+#*****************************************************************************#
+# Usage #
+#*****************************************************************************#
def __cc(params, obj, src, incdirs, std):
- ''' Compile a C file. '''
+ """ Compile a C source file into an object file. """
# Make the temporary thing with all of the subcommands.
tmpinfo = tempfile.mkstemp()
@@ -66,7 +72,7 @@ def __cxx(self, obj, src, incdirs=[]):
print(src, *params['flags'], sep='\n', file=tmp)
print('-object="%s"'%obj, '-lang=cpp', sep='\n', file=tmp)
print('-size', '-gbr=auto', '-noinline', '-chgincpath', '-errorpath',
- '-nologo', '-debug', sep='\n', file=tmp)
+ '-nologo', '-debug', sep='\n', file=tmp)
tmp.close()
# Edit the environment.
@@ -88,8 +94,6 @@ def __cxx(self, obj, src, incdirs=[]):
__all__ = ["Renesas_SHC"]
Renesas_SHC = {
'getparams': __getparams,
- 'getcstd': __getstd_c,
- 'getcxxstd': __getstd_cxx,
'cc': __cc,
'cxx': __cxx
}
diff --git a/tools/configure.py b/tools/configure.py
index cf9fdb8..c5ff51d 100755
--- a/tools/configure.py
+++ b/tools/configure.py
@@ -1,5 +1,16 @@
#!/usr/bin/env python3
-''' Configure how to build libcarrot. '''
+""" This tool serves for user configuration of the libcarrot.
+ Basically, it takes the user parameters (architecture, platform,
+ programming languages, additional modules, build tools), and makes
+ a configuration that the actual tool, 'make.py', can read to know
+ what he is supposed to do.
+
+ It is responsible for finding the modules corresponding to what the
+ user asks, finding a configuration of the build tools that work and
+ produce the expected result, and warn if what the user asks for is
+ incorrect or if there are any mistakes in the involved
+ global, platform or module configurations.
+"""
import os, sys, platform, shlex, argparse
from subprocess import call
@@ -13,8 +24,7 @@ def __getplatform():
# Internal function to get the architecture.
def __getarch():
- name = platform.machine()
- return name
+ return platform.machine().lower()
#*****************************************************************************#
# Set up the arguments parser #
#*****************************************************************************#
diff --git a/tools/make.py b/tools/make.py
index 922b7d5..3da0659 100755
--- a/tools/make.py
+++ b/tools/make.py
@@ -1,5 +1,13 @@
#!/usr/bin/env python3
-''' The PotatoSDK is an SDK using different toolchains to compile libcarrot. '''
+""" This tool is responsable for actually building the library.
+ It takes the configuration from the file generated by 'configure.py',
+ which contains the modules to build and the build tools configuration,
+ finds out what is left to do, what has been updated (to re-build),
+ and finishes the job.
+
+ It is possible to make several times out of a single configuration,
+ and this is cool when you are just programming in one or more modules.
+"""
import os, traceback
from argparse import ArgumentParser
@@ -14,7 +22,7 @@ argparser = ArgumentParser(prog='make.py')
# Set up the arguments.
argparser.add_argument('-c', '--config', dest='config',
- default='build.yml', help='the build configuration path')
+ default='.config.yml', help='the build configuration path')
argparser.add_argument('-i', '--include', dest='incdir', default='include',
help='the generated include directory')
argparser.add_argument('--obj', dest='objdir', default='obj',
@@ -23,8 +31,9 @@ argparser.add_argument('command', help='the command to execute')
#*****************************************************************************#
# Commands #
#*****************************************************************************#
-# `tool clean`: clean the project.
def clean(args):
+ """ Clean the project (remove generated files in order to
+ force rebuild). """
# Remove the caches.
try: os.remove('.makeinc-cache')
except FileNotFoundError: pass
@@ -37,16 +46,21 @@ def clean(args):
try: rmtree('obj')
except FileNotFoundError: pass
-# `tool mrproper`: clean the project and the configuration.
def mrproper(args):
+ """ Clean the project for distribution (remove generated files and
+ configurations). """
+
+ # Clean generated files.
clean(args)
# Remove the configuration.
+ try: os.remove('.config.yml')
+ except FileNotFoundError: pass
try: os.remove('build.yml')
except FileNotFoundError: pass
-# `tool [build]`: make the project.
def build(args):
+ """ Build the project with the current configuration. """
args.config = yaml.load(open(args.config).read())
# Open the main configuration
@@ -209,6 +223,9 @@ def build(args):
# Main interface. #
#*****************************************************************************#
def main():
+ """ Main function, checks the command and runs the appropriate
+ function. """
+
# Parse the arguments, get the configuration.
args = argparser.parse_args()