Skip to content

Commit

Permalink
Implementation for cookiecutter new component
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-bc committed Oct 11, 2023
1 parent 717fc8e commit 84a370f
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 51 deletions.
62 changes: 44 additions & 18 deletions src/fprime/fpp/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,22 @@
from fprime.util.code_formatter import ClangFormatter


def run_fpp_impl(
def fpp_generate_implementation(
build: "Build",
parsed: argparse.Namespace,
_: Dict[str, str],
__: Dict[str, str],
___: List[str],
):
output_dir: Path,
context: Path,
apply_formatting: bool,
ut: bool,
) -> int:
"""
Generate implementation files from FPP templates.
Args:
build: build directory output
parsed: parsed input arguments
_: unused cmake_args
__: unused make_args
___: unused pass-through arguments
build: Build object
output_dir: The directory where the generated files will be written
context: The path to the F´ module to generate files for
apply_formatting: Whether to format the generated files using clang-format
ut: Generates UT files if set to True
"""

prefixes = [
Expand All @@ -50,20 +51,20 @@ def run_fpp_impl(
# Holds the list of generated files to be passed to clang-format
gen_files = tempfile.NamedTemporaryFile(prefix="fprime-impl-")

output_path = Path(parsed.output_dir)
if parsed.ut:
output_path = Path(output_dir)
if ut:
output_path = output_path / "test/ut"
output_path.mkdir(parents=True, exist_ok=True)

# Run fpp-to-cpp --template
FppUtility("fpp-to-cpp", imports_as_sources = False).execute(
FppUtility("fpp-to-cpp", imports_as_sources=False).execute(
build,
parsed.path,
context,
args=(
{},
[
"--template",
*(["--unit-test"] if parsed.ut else []),
*(["--unit-test"] if ut else []),
"--names",
gen_files.name,
"--directory",
Expand All @@ -82,9 +83,8 @@ def run_fpp_impl(
)
return 0

# Format generated files
clang_formatter = ClangFormatter("clang-format", format_file, {"backup": False})
if not parsed.no_format and clang_formatter.is_supported():
if apply_formatting and clang_formatter.is_supported():
for line in gen_files.readlines():
# FPP --names outputs a list of file names. output_dir is added to get relative path
filename = Path(line.decode("utf-8").strip())
Expand All @@ -94,6 +94,32 @@ def run_fpp_impl(
return 0


def run_fpp_impl(
build: "Build",
parsed: argparse.Namespace,
_: Dict[str, str],
__: Dict[str, str],
___: List[str],
):
"""
Args:
build: build object
parsed: parsed input arguments
_: unused cmake_args
__: unused make_args
___: unused pass-through arguments
"""

return fpp_generate_implementation(
build,
parsed.output_dir,
parsed.path,
not parsed.no_format,
parsed.ut,
)


def add_fpp_impl_parsers(
subparsers, common: argparse.ArgumentParser
) -> Tuple[Dict[str, Callable], Dict[str, argparse.ArgumentParser]]:
Expand Down
2 changes: 1 addition & 1 deletion src/fprime/util/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def run_new(
___: unused pass through arguments
"""
if parsed.new_component:
return new_component(build)
return new_component(build, parsed)
if parsed.new_deployment:
return new_deployment(build, parsed)
if parsed.new_project:
Expand Down
48 changes: 16 additions & 32 deletions src/fprime/util/cookiecutter_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
from fprime.common.utils import confirm
from fprime.fbuild.builder import Build
from fprime.fbuild.cmake import CMakeExecutionException
from fprime.fbuild.target import Target
from fprime.util.code_formatter import ClangFormatter
from fprime.fpp.impl import fpp_generate_implementation


def run_impl(build: Build, source_path: Path):
def run_impl(build: Build, parsed_args, source_path: Path):
"""Run implementation of files in source_path"""
target = Target.get_target("impl", set())
if not confirm("Generate implementation files?"):
return False
print(
"Refreshing cache and generating implementation files..."
)

hpp_files = glob.glob(f"{source_path}/*.hpp", recursive=False)
cpp_files = glob.glob(f"{source_path}/*.cpp", recursive=False)
Expand All @@ -36,43 +38,25 @@ def run_impl(build: Build, source_path: Path):
hpp_dest = hpp_files[0]
cpp_dest = common[0] if common else cpp_files[0]

if not confirm("Generate implementation files?"):
return False
print(
"Refreshing cache and generating implementation files (ignore 'Stop' CMake warning)..."
)
with suppress_stdout():
target.execute(build, source_path, ({}, [], {}))
fpp_generate_implementation(
build, source_path, source_path, True, False
)

hpp_files_template = glob.glob(f"{source_path}/*.hpp-template", recursive=False)
cpp_files_template = glob.glob(f"{source_path}/*.cpp-template", recursive=False)
hpp_files_template = glob.glob(f"{source_path}/*.template.hpp", recursive=False)
cpp_files_template = glob.glob(f"{source_path}/*.template.cpp", recursive=False)

if not hpp_files_template or not cpp_files_template:
print("[WARNING] Failed to find generated .cpp-template or .hpp-template files")
print("[WARNING] Failed to find generated .template.cpp or .template.hpp files")
return False

hpp_src = hpp_files_template[0]
cpp_src = cpp_files_template[0]

# Move (and overwrite) files from *.(c|h)pp-template to *.(c|h)pp
# Move (and overwrite) files from *.template.(c|h)pp to *.(c|h)pp
shutil.move(hpp_src, hpp_dest)
shutil.move(cpp_src, cpp_dest)

# Format files if clang-format is available
format_file = build.settings.get("framework_path", Path(".")) / ".clang-format"
if not format_file.is_file():
print(
f"[WARNING] .clang-format file not found at {format_file.resolve()}. Skipping formatting."
)
return True
clang_formatter = ClangFormatter("clang-format", format_file, {"backup": False})
if clang_formatter.is_supported():
clang_formatter.stage_file(Path(hpp_dest))
clang_formatter.stage_file(Path(cpp_dest))
clang_formatter.execute(None, None, ({}, []))
else:
print("[WARNING] clang-format not found in PATH. Skipping formatting.")

return True


Expand Down Expand Up @@ -152,7 +136,7 @@ def find_nearest_cmake_file(component_dir: Path, cmake_root: Path, proj_root: Pa
return None


def new_component(build: Build):
def new_component(build: Build, parsed_args: "argparse.Namespace"):
"""Uses cookiecutter for making new components"""
try:
proj_root = build.get_settings("project_root", None)
Expand Down Expand Up @@ -201,7 +185,7 @@ def new_component(build: Build):
)
return 0
# Attempt implementation
if not run_impl(build, final_component_dir):
if not run_impl(build, parsed_args, final_component_dir):
print(
f"[INFO] Did not generate implementations for {final_component_dir}. Please do so manually."
)
Expand Down

0 comments on commit 84a370f

Please sign in to comment.