Skip to content

Instantly share code, notes, and snippets.

@scivision
Last active April 1, 2024 19:11
Show Gist options
  • Save scivision/79e0dcd418e776d7ddbc12e32449f88c to your computer and use it in GitHub Desktop.
Save scivision/79e0dcd418e776d7ddbc12e32449f88c to your computer and use it in GitHub Desktop.
Read CMakeConfigureLog.yaml from Python

Python read CMakeConfigureLog.yaml

CMake 3.26 introduced CMakeConfigureLog.yaml, which is machine-readable. While we hard-code the location relative to the CMake build directory in this simple example, it is possible toprogrammatically locate it.

The plain trycompile is there just to show in CMakeConfigureLog.yaml how it's distinct from check_source_compiles() in the log.

First configure CMake:

cmake -B build

Then use Python scripts desired:

Check that CMake tests passed. This could be useful for known system configurations e.g. CI to help check that a malicious user hasn't tampered with feature detections:

python CheckPass.py build imp2 imp1 imp3

Print CMake trycompile() results from CMakeConfigureLog.yaml:

python PrintTryCompile.py build
#!/usr/bin/env python3
"""
check that CMake check(s) passed
Usage:
python CheckPass.py cmake_build_dir imp1 imp2 imp3
"""
import argparse
import cmake_configurelog_yaml as cy
p = argparse.ArgumentParser(description="Check if CMake checks passed")
p.add_argument("build_dir", help="CMake build directory")
p.add_argument("must_pass", help="CMake check(s) that must pass", nargs="+")
args = p.parse_args()
log = cy.get_log(args.build_dir)
for check in args.must_pass:
ret = cy.check_code(log, check)
if ret is None:
raise ValueError(f"{check} not found")
elif cy.check_code(log, check) != 0:
raise ValueError(f"{check} failed")
print(f"{check} passed")
"""
read CMakeConfigureLog.yaml
"""
from __future__ import annotations
import yaml
from pathlib import Path
from pprint import pprint
def get_log(build_dir: Path) -> dict:
"""read CMakeConfigureLog.yaml"""
log_file = (
Path(build_dir).expanduser() / "CMakeFiles/CMakeConfigureLog.yaml"
)
with log_file.open("r") as f:
return yaml.safe_load(f)
def print_trycompile(log: dict) -> None:
"""print try_compile events"""
for event in log["events"]:
if event["kind"] == "try_compile-v1":
for e in event["backtrace"]:
# arbitrary filter criteria
# CMake does several try_compile even for targetless project.
if e.startswith("CMakeLists.txt:") and e.endswith(
"try_compile)"
):
r = event["buildResult"]
pprint(r)
def check_code(log: dict, check: str) -> int | None:
"""CMake check return code"""
for event in log["events"]:
if event["kind"] == "try_compile-v1":
r = event["buildResult"]
if r["variable"] == check:
return r["exitCode"]
return None
cmake_minimum_required(VERSION 3.26)
# CMake 3.26 introduced CMakeConfigureLog.yaml
project(dummy LANGUAGES C CXX)
include(CheckSourceCompiles)
try_compile(c_cpp_ok
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/lib.c ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
CMAKE_FLAGS -DINCLUDE_DIRECTORIES=${CMAKE_CURRENT_SOURCE_DIR}
)
# Homoglyphs: https://gist.github.com/StevenACoffman/a5f6f682d94e38ed804182dc2693ed4b
check_source_compiles(C "int mаin(void) { return 0; }" imp1)
check_source_compiles(C "int main(void) { return 0; }" imp2)
if(imp1)
# enable security feature for example
endif()
include(FeatureSummary)
add_feature_info(CppC c_cpp_ok "C and C++ can be compiled together")
add_feature_info(Imp1 imp1 "Feature 1")
add_feature_info(Imp2 imp2 "Feature 2")
feature_summary(WHAT ENABLED_FEATURES)
int add_one(int x) {
return x + 1;
}
#include <cstdlib>
#include "my.h"
int main(){
if(add_one(2) == 3);
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
#ifdef __cplusplus
extern "C" {
#endif
int add_one(int);
#ifdef __cplusplus
}
#endif
#!/usr/bin/env python3
import argparse
import cmake_configurelog_yaml as cy
p = argparse.ArgumentParser(description="Print CMake trycompile log")
p.add_argument("build_dir", help="CMake build directory")
args = p.parse_args()
log = cy.get_log(args.build_dir)
cy.print_trycompile(log)
[tool.black]
line-length = 79
[tool.mypy]
files = ["."]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment