blob: 2497951069e6d790bc3a66bdac75988da7a883da [file] [log] [blame]
#!/usr/bin/env -S python3 -B
# Copyright (c) 2025 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os
import sys
import click
import coloredlogs
import jinja2
# Supported log levels, mapping string values required for argument
# parsing into logging constants
__LOG_LEVELS__ = {
"debug": logging.DEBUG,
"info": logging.INFO,
"warn": logging.WARN,
"fatal": logging.FATAL,
}
# This repesents the code that is generated according to
# https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#using-the-profiling-runtime-without-static-initializers
#
# So that the output of coverage is customized and does not go to `default.profraw`
_CPP_TEMPLATE = """\
extern "C" {
int __llvm_profile_runtime = 0;
void __llvm_profile_initialize_file();
void __llvm_profile_write_file();
void __llvm_profile_set_filename(const char *);
} // extern "C"
struct StaticInitLLVMProfile {
StaticInitLLVMProfile() {
__llvm_profile_set_filename("{{raw_profile_filename}}");
}
~StaticInitLLVMProfile() {
__llvm_profile_write_file();
}
} gInitLLVMProfilingPaths;
"""
@click.command()
@click.option(
"--log-level",
default="INFO",
type=click.Choice([k for k in __LOG_LEVELS__.keys()], case_sensitive=False),
help="Determines the verbosity of script output.",
)
@click.option(
"--no-log-timestamps",
default=False,
is_flag=True,
help="Skip timestaps in log output",
)
@click.option(
"--output",
help="What file to output when runnning under clang profiling",
)
@click.option(
"--raw-profile-filename",
help="Filename to use for output",
)
def main(log_level, no_log_timestamps, output, raw_profile_filename):
log_fmt = "%(asctime)s %(levelname)-7s %(message)s"
if no_log_timestamps:
log_fmt = "%(levelname)-7s %(message)s"
coloredlogs.install(level=__LOG_LEVELS__[log_level], fmt=log_fmt)
expected_output = jinja2.Template(_CPP_TEMPLATE).render(raw_profile_filename=raw_profile_filename)
if os.path.exists(output):
with open(output, 'rt') as f:
if f.read() == expected_output:
logging.info("File %s is already as expected. Will not re-write", output)
sys.exit(0)
logging.info("Writing output to %s (profile name: %s)", output, raw_profile_filename)
with open(output, "wt") as f:
f.write(expected_output)
logging.debug("Writing completed")
if __name__ == "__main__":
main(auto_envvar_prefix="CHIP")