Skip to content

Commit

Permalink
New Project generation feature (#124)
Browse files Browse the repository at this point in the history
* Added minimal project generation

* Print instructions

* Process tags + lots of changes

* Return gracefully instead of sys.exit

* require Git to run new project

* path override and help text

* formatting

* how is "website" not in the default dictionary ?

* sp

* Adding project.cmake

* Review changes
  • Loading branch information
thomas-bc authored Apr 13, 2023
1 parent 67a6e1d commit e2056e2
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 4 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ vals
venv
versioning
viewcode
Website
whitelist
whitespaces
workdir
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"project_name": "MyProject",
"fprime_branch_or_tag": "devel",
"install_venv": ["yes", "no"],
"venv_install_path": "{% if cookiecutter.install_venv == 'yes' %}./venv{% else %}None{% endif %}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""
This script is run as a cookiecutter hook after the project is generated.
"""

import subprocess

DEFAULT_BRANCH = "devel"

# Add F' as a submodule
subprocess.run(["git", "init"])
subprocess.run(
[
"git",
"submodule",
"add",
"-b",
DEFAULT_BRANCH,
"https://github.com/nasa/fprime.git",
]
)

# Checkout requested branch/tag
res = subprocess.run(
["git", "checkout", "{{cookiecutter.fprime_branch_or_tag}}"],
cwd="./fprime",
capture_output=True,
)
if res.returncode != 0:
print(
"[WARNING] Unable to checkout branch/tag: {{cookiecutter.fprime_branch_or_tag}}"
)
print(f"[WARNING] Reverted to default branch: {DEFAULT_BRANCH}")
else:
print(
"[INFO] F' submodule checked out to branch/tag: {{cookiecutter.fprime_branch_or_tag}}"
)

# Install venv if requested
if "{{cookiecutter.install_venv}}" == "yes":
subprocess.run(["python", "-m", "venv", "{{cookiecutter.venv_install_path}}"])
subprocess.run(
[
"{{cookiecutter.venv_install_path}}/bin/pip",
"install",
"-r",
"fprime/requirements.txt",
]
)

print(
"""
################################################################
Congratulations! You have successfully created a new F' project.
A git repository has been initialized and F' has been added as a
submodule, you can now create your first commit.
Get started with your F' project:
-- Activate the virtual environment --
Linux/MacOS: source venv/bin/activate
-- Generate a new component --
fprime-util new --component
-- Generate a new deployment --
fprime-util new --deployment
################################################################
"""
)

if res.returncode != 0:
print(
"[WARNING] Unable to checkout branch/tag: {{cookiecutter.fprime_branch_or_tag}}"
)
print(f"[WARNING] Reverted to default branch: {DEFAULT_BRANCH}")
else:
print(
"[INFO] F' submodule checked out to branch/tag: {{cookiecutter.fprime_branch_or_tag}}"
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
####
#
####
cmake_minimum_required(VERSION 3.13)
project({{cookiecutter.project_name}} C CXX)

###
# F' Core Setup
# This includes all of the F prime core components, and imports the make-system.
###
include("${CMAKE_CURRENT_LIST_DIR}/fprime/cmake/FPrime.cmake")
# NOTE: register custom targets between these two lines
include("${FPRIME_FRAMEWORK_PATH}/cmake/FPrime-Code.cmake")


# This includes project-wide objects
include("${CMAKE_CURRENT_LIST_DIR}/project.cmake")
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# {{cookiecutter.project_name}} F' project

This project was auto-generated by the F' utility tool.

F´ (F Prime) is a component-driven framework that enables rapid development and deployment of spaceflight and other embedded software applications.
**Please Visit the F´ Website:** https://nasa.github.io/fprime/.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# This CMake file is intended to register project-wide objects so they can be
# reused easily between deployments, but also by other projects.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[fprime]
project_root: .
framework_path: ./fprime
34 changes: 33 additions & 1 deletion src/fprime/fbuild/interaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from pathlib import Path
import re
from contextlib import contextmanager
import shutil

from cookiecutter.main import cookiecutter
from cookiecutter.exceptions import OutputDirExistsException
Expand Down Expand Up @@ -496,6 +497,37 @@ def new_deployment(parsed_args):
f"{out_directory_error}. Use --overwrite to overwrite (will not delete non-generated files).",
file=sys.stderr,
)
sys.exit(1)
return 1
print(f"New deployment successfully created: {gen_path}")
return 0


def new_project(parsed_args):
"""Creates a new F' project"""

# Check if Git is installed and available - needed for cloning F' as submodule
if not shutil.which("git"):
print(
"[ERROR] Git is not installed or in PATH. Please install Git and try again.",
file=sys.stderr,
)
return 1

source = (
os.path.dirname(__file__)
+ "/../cookiecutter_templates/cookiecutter-fprime-project"
)
try:
gen_path = cookiecutter(
source,
overwrite_if_exists=parsed_args.overwrite,
output_dir=parsed_args.path,
)
except OutputDirExistsException as out_directory_error:
print(
f"{out_directory_error}. Use --overwrite to overwrite (will not delete non-generated files).",
file=sys.stderr,
)
return 1
print(f"[INFO] New project successfully created: {gen_path}")
return 0
8 changes: 8 additions & 0 deletions src/fprime/util/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ def skip_build_loading(parsed):
should manually be added here by the developer."""
if parsed.command == "new" and parsed.deployment:
return True
if parsed.command == "new" and parsed.project:
return True
return False


Expand Down Expand Up @@ -131,6 +133,12 @@ def add_special_parsers(
action="store_true",
help="Tells the new command to generate a deployment",
)
new_exclusive.add_argument(
"--project",
default=False,
action="store_true",
help="Tells the new command to generate a deployment",
)

# Code formatting with clang-format
format_parser = subparsers.add_parser(
Expand Down
9 changes: 8 additions & 1 deletion src/fprime/util/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
from typing import List, Dict

from fprime.fbuild.builder import Build, InvalidBuildCacheException
from fprime.fbuild.interaction import new_component, new_port, new_deployment
from fprime.fbuild.interaction import (
new_component,
new_port,
new_deployment,
new_project,
)

from fprime.util.code_formatter import ClangFormatter

Expand Down Expand Up @@ -128,6 +133,8 @@ def run_new(
return new_port(build.deployment, build)
if parsed.deployment:
return new_deployment(parsed)
if parsed.project:
return new_project(parsed)
raise NotImplementedError(
"`fprime-util new` target is missing or not implemented. See usage (--help)."
)
Expand Down
9 changes: 7 additions & 2 deletions src/fprime/util/help_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,14 @@
updated to use FPP models. Please check back later.
Usage:
-- New Project --
Generate a new F' project. This will create a Git repository and add F' as a submodule, optionally creating a new
virtual environment. Defaults to current directory, but --path can be used to point to a different location.
Using --overwrite will overwrite only the files that are generated by the new project.
-- New Deployment --
The new deployment command is expected to be ran at the root of the project and will create a new deployment in
the current directory. Using --overwrite will overwrite only the files that are generated by the new deployment.
Generate a new F' deployment within a F' project. The new deployment command is expected to be ran at the root of
the project and will create a new deployment in the current directory. Using --overwrite will overwrite only the
files that are generated by the new deployment.
-- New Component --
WARNING: prototype code generating XML only. Not recommended for inexperienced users. Please check back later.
-- New Port --
Expand Down

0 comments on commit e2056e2

Please sign in to comment.