#!/usr/bin/env python3 # -*- coding: utf-8 -* """Small portable helper script to generate test or doc configuration for the flight software framework """ import os import argparse import webbrowser import shutil import sys import time from shutil import which from typing import List UNITTEST_FOLDER_NAME = "cmake-build-tests" DOCS_FOLDER_NAME = "build-docs" def main(): parser = argparse.ArgumentParser(description="FSFW helper script") choices = ("docs", "tests") parser.add_argument( "type", metavar="type", choices=choices, help=f"Target type. Choices: {choices}" ) parser.add_argument( "-a", "--all", action="store_true", help="Create, build and open specified type" ) parser.add_argument( "-c", "--create", action="store_true", help="Create docs or test build configuration", ) parser.add_argument( "-b", "--build", action="store_true", help="Build the specified type" ) parser.add_argument( "-o", "--open", action="store_true", help="Open test or documentation data in webbrowser", ) parser.add_argument( "-v", "--valgrind", action="store_true", help="Run valgrind on generated test binary", ) parser.add_argument( "-g", "--generators", default="Ninja", action="store", help="CMake generators", ) parser.add_argument( "-w", "--windows", default=False, action="store_true", help="Run on windows", ) args = parser.parse_args() if args.all: args.build = True args.create = True args.open = True elif not args.build and not args.create and not args.open and not args.valgrind: print( "Please select at least one operation to perform. " "Use helper.py -h for more information" ) sys.exit(1) # This script can be called from root and from script folder if not os.path.isfile("README.md"): os.chdir("..") build_dir_list = [] if not args.create: build_dir_list = build_build_dir_list() if args.type == "tests": handle_tests_type(args, build_dir_list) elif args.type == "docs": handle_docs_type(args, build_dir_list) else: print("Invalid or unknown type") sys.exit(1) def handle_docs_type(args, build_dir_list: list): if args.create: if os.path.exists(DOCS_FOLDER_NAME): shutil.rmtree(DOCS_FOLDER_NAME) create_docs_build_cfg() build_directory = DOCS_FOLDER_NAME elif len(build_dir_list) == 0: print( "No valid CMake docs build directory found. Trying to set up docs build system" ) shutil.rmtree(DOCS_FOLDER_NAME) create_docs_build_cfg() build_directory = DOCS_FOLDER_NAME elif len(build_dir_list) == 1: build_directory = build_dir_list[0] else: print("Multiple build directories found!") build_directory = determine_build_dir(build_dir_list) os.chdir(build_directory) if args.build: cmd_runner("cmake --build . -j") if args.open: if not os.path.isfile("docs/sphinx/index.html"): # try again.. cmd_runner("cmake --build . -j") if not os.path.isfile("docs/sphinx/index.html"): print( "No Sphinx documentation file detected. " "Try to build it first with the -b argument" ) sys.exit(1) webbrowser.open("docs/sphinx/index.html") def handle_tests_type(args, build_dir_list: list): if args.create: if os.path.exists(UNITTEST_FOLDER_NAME): shutil.rmtree(UNITTEST_FOLDER_NAME) create_tests_build_cfg(args) build_directory = UNITTEST_FOLDER_NAME elif len(build_dir_list) == 0: print( "No valid CMake tests build directory found. " "Trying to set up test build system" ) create_tests_build_cfg(args) build_directory = UNITTEST_FOLDER_NAME elif len(build_dir_list) == 1: build_directory = build_dir_list[0] else: print("Multiple build directories found!") build_directory = determine_build_dir(build_dir_list) os.chdir(build_directory) if args.build: perform_lcov_operation(build_directory, False) if args.open: if not os.path.isdir("fsfw-tests_coverage"): print( "No Unittest folder detected. Try to build them first with the -b argument" ) sys.exit(1) webbrowser.open("fsfw-tests_coverage/index.html") if args.valgrind: if which("valgrind") is None: print("Please install valgrind first") sys.exit(1) cmd_runner("valgrind --leak-check=full ./fsfw-tests") os.chdir("..") def create_tests_build_cfg(args): os.mkdir(UNITTEST_FOLDER_NAME) os.chdir(UNITTEST_FOLDER_NAME) if args.windows: cmake_cmd = ( 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON \ -DGCOVR_PATH="py -m gcovr" ..' ) else: cmake_cmd = ( 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON ..' ) cmd_runner(cmake_cmd) os.chdir("..") def create_docs_build_cfg(): os.mkdir(DOCS_FOLDER_NAME) os.chdir(DOCS_FOLDER_NAME) cmd_runner("cmake -DFSFW_OSAL=host -DFSFW_BUILD_DOCS=ON ..") os.chdir("..") def build_build_dir_list() -> list: build_dir_list = [] for directory in os.listdir("."): if os.path.isdir(directory): os.chdir(directory) build_dir_list = check_for_cmake_build_dir(build_dir_list) os.chdir("..") return build_dir_list def check_for_cmake_build_dir(build_dir_list: list) -> list: if os.path.isfile("CMakeCache.txt"): build_dir_list.append(os.getcwd()) return build_dir_list def perform_lcov_operation(directory: str, chdir: bool): if chdir: os.chdir(directory) cmd_runner("cmake --build . -j -- fsfw-tests_coverage") def determine_build_dir(build_dir_list: List[str]): build_directory = "" for idx, directory in enumerate(build_dir_list): print(f"{idx + 1}: {directory}") while True: idx = input("Pick the directory: ") if not idx.isdigit(): print("Invalid input!") continue idx = int(idx) if idx > len(build_dir_list) or idx < 1: print("Invalid input!") continue build_directory = build_dir_list[idx - 1] break return build_directory def cmd_runner(cmd: str): print(f"Executing command: {cmd}") os.system(cmd) if __name__ == "__main__": main()