diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..25e63ef --- /dev/null +++ b/COPYING @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2018, Inria. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +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 HOLDER 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. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..357a192 --- /dev/null +++ b/README.rst @@ -0,0 +1,5 @@ +RIOT generator +============== + +RIOT generator provides a command line interface for generating RIOT source +files for new applications, board support, drivers and tests. \ No newline at end of file diff --git a/riotgen.egg-info/PKG-INFO b/riotgen.egg-info/PKG-INFO new file mode 100644 index 0000000..6749893 --- /dev/null +++ b/riotgen.egg-info/PKG-INFO @@ -0,0 +1,22 @@ +Metadata-Version: 1.1 +Name: riotgen +Version: 0.1.0.dev0 +Summary: riotgen: generator for RIOT application/driver/board code +Home-page: https://github.com/aabadie/riot-generator +Author: Alexandre Abadie +Author-email: alexandre.abadie@inria.fr +License: UNKNOWN +Description-Content-Type: UNKNOWN +Description: UNKNOWN +Keywords: generator code +Platform: any +Classifier: Development Status :: 3 - Alpha +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Science/Research +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Topic :: Utilities diff --git a/riotgen.egg-info/SOURCES.txt b/riotgen.egg-info/SOURCES.txt new file mode 100644 index 0000000..e45efe1 --- /dev/null +++ b/riotgen.egg-info/SOURCES.txt @@ -0,0 +1,10 @@ +README.rst +riotgen/__init__.py +riotgen/application.py +riotgen/generator.py +riotgen.egg-info/PKG-INFO +riotgen.egg-info/SOURCES.txt +riotgen.egg-info/dependency_links.txt +riotgen.egg-info/entry_points.txt +riotgen.egg-info/requires.txt +riotgen.egg-info/top_level.txt \ No newline at end of file diff --git a/riotgen.egg-info/dependency_links.txt b/riotgen.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/riotgen.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/riotgen.egg-info/entry_points.txt b/riotgen.egg-info/entry_points.txt new file mode 100644 index 0000000..bcb0a6b --- /dev/null +++ b/riotgen.egg-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +riotgen = riotgen:cli + diff --git a/riotgen.egg-info/requires.txt b/riotgen.egg-info/requires.txt new file mode 100644 index 0000000..dca9a90 --- /dev/null +++ b/riotgen.egg-info/requires.txt @@ -0,0 +1 @@ +click diff --git a/riotgen.egg-info/top_level.txt b/riotgen.egg-info/top_level.txt new file mode 100644 index 0000000..b04ab70 --- /dev/null +++ b/riotgen.egg-info/top_level.txt @@ -0,0 +1 @@ +riotgen diff --git a/riotgen/__init__.py b/riotgen/__init__.py new file mode 100644 index 0000000..1b63325 --- /dev/null +++ b/riotgen/__init__.py @@ -0,0 +1,14 @@ +"""RIOT generator is a helper library for bootstraping RIOT code. + +It can be used to generate: +- a new board support with the default structure +- a new driver support +- a new application +- a new test +""" + +__version__ = '0.1.0-dev0' + +import os.path + +from .generator import cli diff --git a/riotgen/__pycache__/__init__.cpython-35.pyc b/riotgen/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 0000000..9004c9c Binary files /dev/null and b/riotgen/__pycache__/__init__.cpython-35.pyc differ diff --git a/riotgen/__pycache__/application.cpython-35.pyc b/riotgen/__pycache__/application.cpython-35.pyc new file mode 100644 index 0000000..3d4ca93 Binary files /dev/null and b/riotgen/__pycache__/application.cpython-35.pyc differ diff --git a/riotgen/__pycache__/board.cpython-35.pyc b/riotgen/__pycache__/board.cpython-35.pyc new file mode 100644 index 0000000..62e8e33 Binary files /dev/null and b/riotgen/__pycache__/board.cpython-35.pyc differ diff --git a/riotgen/__pycache__/driver.cpython-35.pyc b/riotgen/__pycache__/driver.cpython-35.pyc new file mode 100644 index 0000000..2b0af46 Binary files /dev/null and b/riotgen/__pycache__/driver.cpython-35.pyc differ diff --git a/riotgen/__pycache__/generator.cpython-35.pyc b/riotgen/__pycache__/generator.cpython-35.pyc new file mode 100644 index 0000000..0fb0c64 Binary files /dev/null and b/riotgen/__pycache__/generator.cpython-35.pyc differ diff --git a/riotgen/__pycache__/helpers.cpython-35.pyc b/riotgen/__pycache__/helpers.cpython-35.pyc new file mode 100644 index 0000000..328a21a Binary files /dev/null and b/riotgen/__pycache__/helpers.cpython-35.pyc differ diff --git a/riotgen/__pycache__/test.cpython-35.pyc b/riotgen/__pycache__/test.cpython-35.pyc new file mode 100644 index 0000000..2f0da55 Binary files /dev/null and b/riotgen/__pycache__/test.cpython-35.pyc differ diff --git a/riotgen/application.py b/riotgen/application.py new file mode 100644 index 0000000..8406c27 --- /dev/null +++ b/riotgen/application.py @@ -0,0 +1,120 @@ +"""RIOT application generator module.""" + +import os.path +import datetime + +import click + +from .helpers import _get_usermail, _get_username +from .helpers import TEMPLATES_DIR +from .helpers import _read_config, _prompt_common_information + + +def _read_application_config(filename): + return _read_config(filename, section='application') + + +def _prompt_application(): + params = {} + params['application_name'] = click.prompt(text='Application name') + params['desc'] = click.prompt(text='Application short description') + params['board'] = click.prompt(text='Target board', default='native') + params['modules'] = click.prompt( + text='Required modules (comma separated)', + default=[], type=list) + params['packages'] = click.prompt( + text='Required packages (comma separated)', + default=[], type=list) + params['features'] = click.prompt( + text='Required board features (comma separated)', + default=[], type=list) + + params.update(_prompt_common_information()) + return params + + +def _check_params(params): + return dict() + + +@click.command() +@click.argument('output_dir', type=click.Path(exists=True)) +@click.option('--config', type=click.File(mode='r')) +def application(output_dir, config): + # click.echo('Generating application: ', nl=False) + # click.echo(click.style('{}'.format(application), bold=True)) + # click.echo('Target board: ', nl=False) + # click.echo(click.style('{}'.format(board), bold=True)) + + # Use config file is set + if config is not None: + params = _read_application_config(config) + else: + params = _prompt_application() + + print(params) + + includes = '' + # Modules required + # if modules: + # click.echo('Modules: ', nl=False) + # click.echo(click.style(', '.join(modules), bold=True)) + # for module in modules: + # includes += 'USEMODULE += {}\n'.format(module) + + # # External packages required + # if packages: + # click.echo('Packages: ', nl=False) + # click.echo(click.style(', '.join(packages), bold=True)) + # for pkg in packages: + # includes += 'USEPKG += {}\n'.format(pkg) + + # # Board/CPU features required + # if features: + # click.echo('Features: ', nl=False) + # click.echo(click.style(', '.join(features), bold=True)) + # for feature in features: + # includes += 'FEATURES_REQUIRED += {}\n'.format(feature) + + # User name + username = _get_username() + click.echo('Username: ', nl=False) + click.echo(click.style(username, bold=True)) + + # User email + usermail = _get_usermail() + click.echo('Email: ', nl=False) + click.echo(click.style(usermail, bold=True)) + + # params = dict( + # application_name=application_name, + # application_name_underline='=' * len(application_name), + # board=board, + # year=datetime.datetime.now().year, + # # organization=organization if organization is not None else username, + # # desc=description, + # author_name=username, + # author_email=usermail, + # includes=includes, + # ) + + application_dir = os.path.join(TEMPLATES_DIR, 'application') + main_in = os.path.join(application_dir, 'main.c') + makefile_in = os.path.join(application_dir, 'Makefile') + readme_in = os.path.join(application_dir, 'README.md') + main_out = os.path.join(output_dir, 'main.c') + makefile_out = os.path.join(output_dir, 'Makefile') + readme_out = os.path.join(output_dir, 'README.md') + + files = { + main_in: main_out, + makefile_in: makefile_out, + readme_in: readme_out + } + + for file_in, file_out in files.items(): + with open(file_in, 'r') as f_in: + with open(file_out, 'w') as f_out: + f_out.write(f_in.read().format(**params)) + + click.echo(click.style('Application generated!', bold=True)) diff --git a/riotgen/board.py b/riotgen/board.py new file mode 100644 index 0000000..24ffb15 --- /dev/null +++ b/riotgen/board.py @@ -0,0 +1,12 @@ +import logging +import click + +logger = logging.getLogger("riotgen.generator.board") + + +@click.command() +@click.argument('board') +@click.option('--riotbase', '-r', envvar='RIOTBASE') +def board(board, riotbase): + logger.debug('Generating board support for %s' % board) + logger.debug('Using RIOTBASE in %s' % riotbase) diff --git a/riotgen/driver.py b/riotgen/driver.py new file mode 100644 index 0000000..8ff3725 --- /dev/null +++ b/riotgen/driver.py @@ -0,0 +1,14 @@ +import logging +import click + +logger = logging.getLogger("riotgen.generator.driver") + + +@click.command() +@click.argument('driver') +@click.option('--riotbase', '-r', envvar='RIOTBASE') +@click.option('--dependency', '-d', multiple=True) +def driver(driver, riotbase, dependency): + logger.debug('Generating driver support for %s' % driver) + logger.debug('Driver dependencies: %s' % ', '.join(dependency)) + logger.debug('Using RIOTBASE in %s' % riotbase) \ No newline at end of file diff --git a/riotgen/generator.py b/riotgen/generator.py new file mode 100644 index 0000000..6438c45 --- /dev/null +++ b/riotgen/generator.py @@ -0,0 +1,23 @@ +import logging +import click + +from .application import application +from .board import board +from .driver import driver +from .test import test + +logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s - %(name)14s - ' + '%(levelname)5s - %(message)s') +logger = logging.getLogger("riotgen.generator") + + +@click.group() +def cli(): + pass + +# register subcommands +cli.add_command(application) +cli.add_command(board) +cli.add_command(driver) +cli.add_command(test) \ No newline at end of file diff --git a/riotgen/helpers.py b/riotgen/helpers.py new file mode 100644 index 0000000..fb9739a --- /dev/null +++ b/riotgen/helpers.py @@ -0,0 +1,64 @@ +"""Internal helper functions""" + +import os.path +import datetime +from configparser import ConfigParser +from subprocess import check_output + +import click + +PKG_DIR = os.path.abspath(os.path.dirname(__file__)) +TEMPLATES_DIR = os.path.join(PKG_DIR, 'templates') + + +def _get_username(): + try: + name = check_output( + ['git', 'config', '--get', 'user.name']).decode()[:-1] + except: + name = '' + + return name + + +def _get_usermail(): + try: + email = check_output( + ['git', 'config', '--get', 'user.email']).decode()[:-1] + except: + email = '' + + return email + + +def _prompt_common_information(): + params = {} + params['year'] = datetime.datetime.now().year + params['author_name'] = click.prompt( + text='Author name', default=_get_username()) + params['author_email'] = click.prompt( + text='Author email', default=_get_usermail()) + params['organization'] = click.prompt( + text='Organization', default=_get_username()) + return params + + +def _read_config(filename, section=None): + parser = ConfigParser() + parser.read(filename) + config = dict(parser.items('common')) + if section is not None: + config.update(dict(parser.items(section))) + return config + + +def _read_board_config(filename): + return _read_config(filename, section='board') + + +def _read_driver_config(filename): + return _read_config(filename, section='driver') + + +def _read_test_config(filename): + return _read_config(filename, section='test') diff --git a/riotgen/templates/application/Makefile b/riotgen/templates/application/Makefile new file mode 100644 index 0000000..1fca78e --- /dev/null +++ b/riotgen/templates/application/Makefile @@ -0,0 +1,20 @@ +# name of the application +APPLICATION = {application_name} + +# If no BOARD is found in the environment, use this default: +BOARD ?= {board} + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +# required modules +{includes} +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include \ No newline at end of file diff --git a/riotgen/templates/application/README.md b/riotgen/templates/application/README.md new file mode 100644 index 0000000..a56e073 --- /dev/null +++ b/riotgen/templates/application/README.md @@ -0,0 +1,9 @@ +{application_name} +{application_name_underline} + +Describe here what the application is about. + +Usage +===== + +Describe here how to use this application diff --git a/riotgen/templates/application/main.c b/riotgen/templates/application/main.c new file mode 100644 index 0000000..ea49f99 --- /dev/null +++ b/riotgen/templates/application/main.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) {year} {organization} + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{{ + * + * @file + * @brief {desc} + * + * @author {author_name} <{author_email}> + * + * @}} + */ + +#include + +int main(void) +{{ + puts("A generated RIOT application"); + return 0; +}} \ No newline at end of file diff --git a/riotgen/templates/board/Makefile b/riotgen/templates/board/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/board/Makefile.dep b/riotgen/templates/board/Makefile.dep new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/board/Makefile.features b/riotgen/templates/board/Makefile.features new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/board/Makefile.include b/riotgen/templates/board/Makefile.include new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/board/board.c b/riotgen/templates/board/board.c new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/board/board.h b/riotgen/templates/board/board.h new file mode 100644 index 0000000..a201cf3 --- /dev/null +++ b/riotgen/templates/board/board.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) {year} {copyright_group} + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup boards_{board} {board_name} + * @ingroup boards + * @brief Support for the {board_name} board. + * @{ + * + * @file + * @brief Board specific definitions for the {board_name} + * + * @author Alexandre Abadie + */ + +#ifndef BOARD_H +#define BOARD_H + +#include "cpu.h" +#include "periph_conf.h" +#include "periph_cpu.h" + +#ifdef __cplusplus +extern "C" { +#endif + +{xtimer_config} +{led_defs} +{btn_defs} + +/** + * @brief Initialize board specific hardware + */ +void board_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* BOARD_H */ +/** @} */ \ No newline at end of file diff --git a/riotgen/templates/board/periph_conf.h b/riotgen/templates/board/periph_conf.h new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/driver/Makefile b/riotgen/templates/driver/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/driver/driver.c b/riotgen/templates/driver/driver.c new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/driver/driver.h b/riotgen/templates/driver/driver.h new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/driver/driver_params.h b/riotgen/templates/driver/driver_params.h new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/test/Makefile b/riotgen/templates/test/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/test/README.md b/riotgen/templates/test/README.md new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/templates/test/main.c b/riotgen/templates/test/main.c new file mode 100644 index 0000000..e69de29 diff --git a/riotgen/test.py b/riotgen/test.py new file mode 100644 index 0000000..a1f21a8 --- /dev/null +++ b/riotgen/test.py @@ -0,0 +1,20 @@ +import logging +import click + +logger = logging.getLogger("riotgen.generator.test") + + +@click.command() +@click.argument('test') +@click.option('--riotbase', '-r', envvar='RIOTBASE') +@click.option('--modules', '-m', multiple=True) +@click.option('--packages', '-p', multiple=True) +@click.option('--features', '-f', multiple=True) +@click.option('--board', envvar='BOARD', default='native') +def test(test, riotbase, modules, packages, features, board): + logger.debug('Generating test %s' % test) + logger.debug('Using modules %s' % ', '.join(modules)) + logger.debug('Using packages %s' % ', '.join(packages)) + logger.debug('Using features %s' % ', '.join(features)) + logger.debug('Targetting board %s' % board) + logger.debug('Using RIOTBASE in %s' % riotbase) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..f2648b1 --- /dev/null +++ b/setup.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python + +from setuptools import setup +# To use a consistent encoding +from codecs import open +from os import path + +PACKAGE = 'riotgen' + + +def get_long_description(): + # Get the long description from the README file + with open('README.rst', encoding='utf-8') as f: + return f.read() + + +def get_version(): + """Get the version from package __init__.py file.""" + with open(path.join(PACKAGE, '__init__.py'), encoding='utf-8') as f: + for line in f: + if line.startswith('__version__'): + return eval(line.split('=')[-1]) + +setup( + name=PACKAGE, + version=get_version(), + + description='riotgen: generator for RIOT application/driver/board code', + long_description=get_long_description(), + + url='https://github.com/aabadie/riot-generator', + + author='Alexandre Abadie', + author_email='alexandre.abadie@inria.fr', + + license='', + + # See https://pypi.python.org/pypi?%3Aaction=list_classifiers + classifiers=[ + # How mature is this project? Common values are + # 3 - Alpha + # 4 - Beta + # 5 - Production/Stable + 'Development Status :: 3 - Alpha', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: BSD License', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Topic :: Utilities', + ], + + keywords='generator code', + platforms='any', + packages=[PACKAGE], + package_data={'templates': ['riotgen/templates/*']}, + # package_data={'templates': ['templates/application/Makefile', + # 'templates/application/main.c', + # 'templates/application/README.md', + + # 'templates/board/Makefile', + # 'templates/board/Makefile.dep', + # 'templates/board/Makefile.features', + # 'templates/board/Makefile.include', + # 'templates/board/board.h', + # 'templates/board/periph_conf.h', + + # 'templates/driver/Makefile', + # 'templates/driver/driver.h', + # 'templates/driver/driver.c', + # 'templates/driver/driver_params.h', + + # 'templates/test/Makefile', + # 'templates/test/main.c', + # 'templates/test/README.md', + # ]}, + install_requires=['click'], + entry_points={ + 'console_scripts': [ + '{}=riotgen:cli'.format(PACKAGE), + ], + }, +) \ No newline at end of file