Skip to content

Commit

Permalink
Deployment template for F Prime, mainly targeting Arduino (ATmega) de…
Browse files Browse the repository at this point in the history
…ployments
  • Loading branch information
SterlingPeet committed Aug 27, 2020
1 parent 0d74f99 commit 572ebe6
Show file tree
Hide file tree
Showing 26 changed files with 1,058 additions and 2 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Changelog
#########

Use cookiecutter's ``--checkout`` options to use a specific version.

v1.0 (2020-08-15)
-----------------

* Initial Release
2 changes: 0 additions & 2 deletions README.md

This file was deleted.

156 changes: 156 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
===============================
Cookiecutter: F Prime Component
===============================

**WARNING:** The template is currently intended to support ATmega specific deployments, so if that is not your goal, the results may be somewhat unexpected.

**WARNING:** Beta version, the documentation is not up to date yet (working on it, but needed to crank out some test deployments internally. Sorry!).

Cookiecutter_ template for a `F Prime`_ deployment, to help with reducing the copy-pasta effect while creating new deployments.
There are just enough pieces to remember to change/fix, that it is rather challenging to do without a template.
So here is a template to fill in all the major adjustments, so you can spend time develping a deployment or writing a component instead of scratching your head over why you get weird errors.

.. contents:: Table of Contents

Features
--------

* Choice of various licenses. (maybe, eventually)

Requirements
------------

Projects using this template have these minimal dependencies:

* Cookiecutter_ - just for creating the project

To get quickly started on a new system, just install Cookiecutter_. You
should do this in your ``fprime-venv``. To install it, just run this
in your shell or command prompt, within the ``venv`` environment::

pip install cookiecutter

Usage and options
-----------------

This template is intended to make it easy to generate all the boilerplate required for a `F Prime`_ deployment and a single component internal to that deployment.
A collection of components along with a mission/project configuration [deployment] completes the framework to fill out a robotic software project; e.g.: a balloon payload, an wheeled rover, or maybe a satellite.

First navigate to the directory where you want to add your deployment.
The template is going to create the folder containing your component in the current directory (you should *not* try to create the folder ahead of the template).
Next, generate the deployment's boilerplate::

cookiecutter gh:SterlingPeet/cookiecutter-fprime-deployment

You will be asked for these fields:

.. list-table::
:header-rows: 1

* - Template variable
- Default
- Description

* - ``full_name``
- .. code:: python

"Sterling Peet"
- Main author of this component.

Can be set in your ``~/.cookiecutterrc`` config file.

* - ``email``
- .. code:: python

"[email protected]"
- Contact email of the author.

Can be set in your ``~/.cookiecutterrc`` config file.

* - ``component_name``
- .. code:: python

"My Example"
- The printed name of this component for documentation and strings. It should be concise and convey the purpose of the component.

* - ``short_description``
- .. code:: python

"An example component [...]"
- One line description of the project (used in headers and comments).

* - ``component_class_name``
- .. code:: python

"MyExampleComponent"
- The name of this component's class in the code. It should be ``CamelCase``. The autocoder requires the suffix ``Component`` to function properly.

* - ``component_explicit_common``
- .. code:: python

""
- If preferred, the cpp file with the common implementation code can be appended with the suffix ``Common``.

* - ``component_suffix``
- .. code:: python

""
- If preferred, the files and classes can be appended with the suffix ``Impl``.

* - ``component_path``
- .. code:: python

"Prjct/Grp"
- This is the path from the F Prime root to the current directory, not including the component's folder.

* - ``component_namespace``
- .. code:: python

"Prjct::Grp"
- This is the namespace where your component's implementation class resides. It is usually the same but can be different from the path.

* - ``component_kind``
- .. code:: python

"active"
- You can choose and active or passive component type. If you change your mind, is it set in the Autocoder input file.

* - ``license``
- .. code:: python

"None"
- License to use. Available options:

* None (no license text, assume project level license)
* BSD license
* MIT license

What license to pick? https://choosealicense.com/

You will still need to run ``fprime-util`` to generate the templates from your autocoder input file.

This requires your component to be included in a deployment.
This can be done by adding a line like this, near the bottom of the deployment's ``CMakeLists.txt`` file::

add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../Prjct/Grp/MyExample")

Then you need to (possibly purge) and generate the new cmake config in that deployment::

fprime-util generate

Now you can edit your ``MyExampleComponentAi.xml`` file define the component to your liking, and generate the implementation boilerplate::

cd MyExample
fprime-util impl -b {path/to/your/deployment}

Next, copy the ``-template`` code contents into your ``.hpp`` and ``.cpp`` files.
Try not to overwrite the freshly generated comments at the top!


Changelog
---------

See `CHANGELOG.rst <https://github.com/SterlingPeet/cookiecutter-fprime-component/tree/master/CHANGELOG.rst>`_.

.. _Cookiecutter: https://github.gatech.edu/audreyr/cookiecutter
.. _F Prime: https://github.com/nasa/fprime/
24 changes: 24 additions & 0 deletions cookiecutter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"full_name": "Sterling Peet",
"email": "[email protected]",
"deployment_display_name": "My Example",
"dep_short_description": "Example deployment for F Prime FSW framework.",
"deployment_assembly": "{{ cookiecutter.deployment_display_name|replace(' ','')|replace('-','')|replace('_','') }}",
"deployment_dir_name": "{{ cookiecutter.deployment_assembly }}",
"deployment_path": "example/path",
"path_to_fprime_root": "../..",
"component_display_name": "Led Blinker",
"component_short_description": "Example component to support {{ cookiecutter.deployment_display_name }} deployment.",
"component_name": "{{ cookiecutter.component_display_name|replace(' ','')|replace('-','')|replace('_','') }}",
"component_dir_name": "{{ cookiecutter.component_name }}",
"component_explicit_common": ["", "Common"],
"component_suffix": ["", "Impl"],
"component_namespace": "{{ cookiecutter.deployment_path|replace('/','::')|replace('\\\\','::') }}",
"component_kind": ["active", "passive"],
"component_instance_name": "{{ cookiecutter.component_name|replace(' ','_')|replace('-','_') }}",
"startup_delay_msec": ["2000", "1000", "500", "0"],
"startup_arduino_led_flash": ["yes", "no"],
"arduino_log_stream": ["Serial", "Serial1", "Serial2", "Serial3"],
"license": ["None", "MIT license", "BSD 2-Clause License", "BSD 3-Clause License"]
}

81 changes: 81 additions & 0 deletions hooks/post_gen_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from __future__ import print_function

import datetime
# import os
# import shutil
# import subprocess
# import sys
from os.path import join

try:
from click.termui import secho
except ImportError:
warn = print
else:
def warn(text):
for line in text.splitlines():
secho(line, fg="white", bg="red", bold=True)


def replace_contents(filename, what, replacement):
with open(filename) as fh:
changelog = fh.read()
with open(filename, 'w') as fh:
fh.write(changelog.replace(what, replacement))

if __name__ == "__main__":
today = datetime.date.today()
# replace_contents('CHANGELOG.rst', '<TODAY>', today.strftime("%Y-%m-%d"))
replace_contents(join('{{ cookiecutter.component_dir_name }}', 'docs', 'sdd.md'), '<TODAY>', today.strftime("%m/%d/%Y"))
replace_contents('README.md', '<TODAY>', today.strftime("%m/%d/%Y"))

# /{/% if cookiecutter.sphinx_docs == "no" %}
# shutil.rmtree('docs')
# /{/% endif %}

# /{/%- if cookiecutter.command_line_interface == 'no' %}
# os.unlink(join('src', '/{/{ cookiecutter.package_name }}', '__main__.py'))
# os.unlink(join('src', '/{/{ cookiecutter.package_name }}', 'cli.py'))
# /{/% endif %}

print("""
################################################################################
################################################################################
You have succesfully created the `{{ cookiecutter.component_name }}` component.
################################################################################
You've used these cookiecutter parameters:
{% for key, value in cookiecutter.items()|sort %}
{{ "{0:26}".format(key + ":") }} {{ "{0!r}".format(value).strip("u") }}
{%- endfor %}
################################################################################
You will still need to run `fprime-util` to generate the templates
from your autocoder input file.
This requires your component to be included in a deployment. This
can be done by adding a line like this, near the bottom of the
deployment's CMakeLists.txt file:
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../{{ cookiecutter.deployment_path }}/{{ cookiecutter.component_dir_name }}/{{ cookiecutter.component_dir_name }}")
Then you need to (possibly purge) and generate the new cmake config
in that deployment:
fprime-util generate
Now you can edit your {{ cookiecutter.component_name }}ComponentAi.xml file
define the component to your liking, and generate the implementation
boilerplate:
cd {{ cookiecutter.component_dir_name }}
fprime-util impl -b {path/to/your/deployment}
Next, copy the `-template` code contents into your .hpp and .cpp files.
Try not to overwrite the freshly generated comments at the top!
""")

71 changes: 71 additions & 0 deletions {{cookiecutter.deployment_dir_name}}/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
####
# {{cookiecutter.deployment_display_name}} Deployment:
#
# This sets up the {{cookiecutter.deployment_display_name}} deployment using CMake
# for use with F prime.
#
# This file has several sections.
#
# 1. Header Section: define basic properties of the build
# 2. F´ core: includes all F´ core components, and build-system properties
# 3. Local subdirectories: contains all deployment specific directory additions
####

##
# Section 1: Basic Project Setup
#
# This contains the basic project information. Specifically, a cmake version and
# project definition.
#
# The project name does need to take into account the path to the deployment folder,
# if it is not at the F Prime root, e.g.: path_to_{{cookiecutter.deployment_dir_name}}
# not having this will confuse the `fprime-util` tool.
##
project({{cookiecutter.deployment_path|replace('/','_')}}_{{cookiecutter.deployment_dir_name}} C CXX ASM)
cmake_minimum_required(VERSION 3.5)

set(FPRIME_FRAMEWORK_PATH "${CMAKE_CURRENT_LIST_DIR}/../{{cookiecutter.path_to_fprime_root}}" CACHE PATH "Location of F prime framework" FORCE)
set(FPRIME_PROJECT_ROOT "${CMAKE_CURRENT_LIST_DIR}/../{{cookiecutter.path_to_fprime_root}}" CACHE PATH "Root path of F prime project" FORCE)

set(BAREMETAL_SCHEDULER CACHE BOOL ON "Uses the baremetal scheduler")

# Use file hashes instead of full file paths in the compiled binary. This can be
# converted back to a filename with the `fprime-util hashes` tool.
add_definitions(-DFW_ASSERT_LEVEL=2)


##
# Section 2: F´ Core
#
# This includes all of the F´ core components, and imports the make-system. F´ core
# components will be placed in the F-Prime binary subdirectory to keep them from
# colliding with deployment specific items.
##
include("${CMAKE_CURRENT_LIST_DIR}/../{{cookiecutter.path_to_fprime_root}}/cmake/FPrime.cmake")
# NOTE: register custom targets between these two lines
include("${CMAKE_CURRENT_LIST_DIR}/../{{cookiecutter.path_to_fprime_root}}/cmake/FPrime-Code.cmake")
# Note: when building a deployment outside of the F´ core directories, then the
# build root must be re-mapped for use with the standard build system components.
#
# In this way, the module names can be predicted as an offset from the (new) build
# root, without breaking the standard locations of F´.
#
# Uncomment the following lines, and set them to the BUILD_ROOT of your deployment,
# which is typically one directory up from the CMakeLists.txt in the deployment dir.
set(FPRIME_CURRENT_BUILD_ROOT "${CMAKE_CURRENT_LIST_DIR}/../{{cookiecutter.path_to_fprime_root}}")
message(STATUS "F´ BUILD_ROOT currently set to: ${FPRIME_CURRENT_BUILD_ROOT}")

##
# Section 3: Components and Topology
#
# This section includes deployment specific directories. This allows use of non-
# core components in the topology, which is also added here.
##
# Add component subdirectories
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../{{cookiecutter.path_to_fprime_root}}/ATmega/AssertReset/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../{{cookiecutter.path_to_fprime_root}}/ATmega/HardwareRateDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/{{cookiecutter.component_dir_name}}/")

# Add Topology subdirectory
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Top/")

10 changes: 10 additions & 0 deletions {{cookiecutter.deployment_dir_name}}/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# {{cookiecutter.deployment_display_name}} F Prime Deployment

{{cookiecutter.dep_short_description}}

## 6. Change Log

Date | Description
---- | -----------
<TODAY> | Initial Deployment Design

1 change: 1 addition & 0 deletions {{cookiecutter.deployment_dir_name}}/Top/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.html
27 changes: 27 additions & 0 deletions {{cookiecutter.deployment_dir_name}}/Top/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
####
# F prime CMakeLists.txt:
#
# SOURCE_FILES: combined list of source and autocoding files
# MOD_DEPS: (optional) module dependencies
#
# Note: using PROJECT_NAME as EXECUTABLE_NAME
####
set(SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/{{cookiecutter.deployment_assembly}}TopologyAppAi.xml"
"${CMAKE_CURRENT_LIST_DIR}/Main.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Topology.cpp"
)
# Note: supply non-explicit dependencies here
set(MOD_DEPS
Fw/Logger
# Svc/GroundInterface
Svc/LinuxTime
Os
Os/Baremetal/TaskRunner
)

register_fprime_executable()

if(${CMAKE_SYSTEM_NAME} STREQUAL "Arduino")
add_arduino_dependency("${PROJECT_NAME}")
endif()
Loading

0 comments on commit 572ebe6

Please sign in to comment.