Skip to content

Commit

Permalink
Implement scripts to generate header file from cmake feature file (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
QuangHaiNguyen authored Nov 10, 2024
1 parent f02cc0f commit 9ea6913
Showing 1 changed file with 134 additions and 0 deletions.
134 changes: 134 additions & 0 deletions tools/header_features_generator/generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
__author__ = "Hai Nguyen"
__credits__ = "Hai Nguyen"
__license__ = "This file is published under the license described in LICENSE.md"
__maintainer__ = "Hai Nguyen"
__email__ = "hainguyen.eeit@gmail.com"

import logging
import argparse
import os
import re
from enum import Enum
from pathlib import Path

# create logger
logger = logging.getLogger('GENERATOR')
logger.setLevel(logging.DEBUG)
logger.propagate = False

ch = logging.StreamHandler()
formatter = logging.Formatter('%(name)s::%(funcName)s::%(levelname)s::%(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)

# Create the parser
my_parser = argparse.ArgumentParser(description='Generate header file containing activated features from cmake file')

class EXTRACT_RESULT(Enum):
COMMENT=1
FEATURE=2
EMPTY_LINE=3
ERROR=4

def extract_feature_by_line(feature_str:str):
"""Check the input line and try to extract the feature from that line
Args:
feature_str (str): input string for feature extraction
Returns:
_type_: (EXTRACT_RESULT, output string)
"""
if feature_str == "":
logger.info("found an empty line")
return (EXTRACT_RESULT.EMPTY_LINE, None)
elif feature_str[0] == '#':
logger.info("found a comment")
ret = "\n/* {} */\n".format(feature_str[1:].lstrip())
return (EXTRACT_RESULT.COMMENT, ret)
else:
# tokenize string from option(ENABLE_EZ_EVENT_NOTIFIER "Enable the Event Notifier module" ON)
# to ["option", "ENABLE_EZ_EVENT_NOTIFIER "Enable the Event Notifier module" ON", ""]
tokens = re.split("[()]", feature_str)
if len(tokens) == 3 and tokens[0] == "option":
# tokenize string from "ENABLE_EZ_EVENT_NOTIFIER "Enable the Event Notifier module" ON"
# to ["ENABLE_EZ_EVENT_NOTIFIER ", "Enable the Event Notifier module", " ON"]
tokens = tokens[1].split("\"")
if len(tokens) == 3:
# cleanup the whitespace
tokens[0] = tokens[0].rstrip()
tokens[2] = tokens[2].lstrip()
if tokens[2] == "ON":
ret = "#define {}_ENABLE 1 /* {} */\n".format(tokens[0], tokens[1])
return (EXTRACT_RESULT.FEATURE, ret)
elif tokens[2] == "OFF":
ret = "#define {}_ENABLE 0 /* {} */\n".format(tokens[0], tokens[1])
return (EXTRACT_RESULT.FEATURE, ret)
else:
return (EXTRACT_RESULT.ERROR, None)
else:
return (EXTRACT_RESULT.ERROR, None)

def generate_output_header(input_path:str, output_path:str)->bool:
"""Generate the header file from the cmake feature file
Args:
input_path (str): path to cmake file
output_path (str): path to output header file
Returns:
bool: True if success else False
"""
with open(input_path, "r") as cmake_file:
if os.path.exists(output_path):
logger.warning("file exists. This file will be overwritten")
os.remove(output_path)
with open(output_path, "a") as header_file:
text = cmake_file.read()
lines = text.splitlines()
header_file.write("#ifndef _{}_H\n".format(Path(output_path).stem.upper()))
header_file.write("#define _{}_H\n".format(Path(output_path).stem.upper()))
for line in lines:
result, feature = extract_feature_by_line(line)
if result == EXTRACT_RESULT.ERROR:
logger.error("Invalid format")
exit()
elif result == EXTRACT_RESULT.FEATURE:
header_file.write(feature)
logger.debug(feature)
elif result == EXTRACT_RESULT.COMMENT:
header_file.write(feature)
logger.debug(feature)
else:
pass # do nothing
header_file.write("\n#endif\n")
logger.info("Generate success")

def main():
"""main, entry point of the application
"""
# read arguments
my_parser.add_argument( '-f',
'--cmake_file',
action='store',
required=True,
type=str,
help='name of the cmake file')

my_parser.add_argument( '-o',
'--output',
action='store',
required=True,
type=str,
help='path to output file')

args = my_parser.parse_args()
logger.debug("Input = {}".format(args.cmake_file))
logger.debug("Output = {}".format(args.output))
if os.path.exists(args.cmake_file) == False:
logger.error("Path does not exist")
else:
generate_output_header(args.cmake_file, args.output)

if __name__ == "__main__":
main()

0 comments on commit 9ea6913

Please sign in to comment.