Skip to content

Commit

Permalink
Pass environment in all CMake calls and add UTs (#236)
Browse files Browse the repository at this point in the history
  • Loading branch information
LeStarch authored Jan 14, 2025
1 parent b8911c3 commit 4735570
Show file tree
Hide file tree
Showing 6 changed files with 621 additions and 25 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ subparser
Subproc
subtopology
sys
symlink
tcanham
Tcp
td
Expand Down
11 changes: 11 additions & 0 deletions src/fprime/fbuild/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,17 @@ def install_dest_exists(self) -> Path:
path = Path(self.settings["install_destination"])
return path if path.exists() else None

def refresh(self):
"""Refresh this build (i.e. the cmake build cache)
Some build systems (e.g. CMake) require the build to be refreshed (i.e. refresh the build cache). When this
happens it is imperative that the appropriate environment is set. For this reason, refresh is exposed as a
helper in this layer rather than the previous pattern of calling builder.cmake.cmake_refresh_cache directly.
"""
self.cmake.cmake_refresh_cache(
self.build_dir, environment=self.settings.get("environment", None)
)

@staticmethod
def find_nearest_parent_project(path: Path) -> Path:
"""Recurse up the directory stack looking for a valid CMake project.
Expand Down
45 changes: 21 additions & 24 deletions src/fprime/fbuild/cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def execute_known_target(
:param target: target to execute at the path, using above build_dir
:param path: path to run target against. (default) current working directory
:param cmake_args: cmake args input
:param make_args: arguments to pass to make
:param top_target: top-level target. Do not append path name
:param environment: environment to setup when executing CMake
:param full_cache_rebuild: rebuild the cache fully. Default: False, use the short version
Expand Down Expand Up @@ -151,7 +152,7 @@ def execute_known_target(
print(
"[CMAKE] CMake failed to detect target, attempting CMake cache refresh and retry"
)
self.cmake_refresh_cache(build_dir, full=full_cache_rebuild)
self.cmake_refresh_cache(build_dir, environment, full=full_cache_rebuild)
return self._run_cmake(
run_args + fleshed_args,
write_override=True,
Expand Down Expand Up @@ -477,16 +478,18 @@ def _cmake_validate_build_dir(build_dir):
if not os.path.isfile(cache_file):
raise CMakeInvalidBuildException(build_dir)

def cmake_refresh_cache(self, build_dir, full=False):
"""
def cmake_refresh_cache(self, build_dir, environment=None, full=False):
"""Refresh the CMake cache by calling a known cache-refresh target
Runs the cmake target required to refresh the cmake cache. This will allow for unknown targets to be searched
for before the utility gives up and produces.
:param build_dir: directory to build in
:param full: full re-generate of the cache. Default: false, attempt to build 'refresh_cache' target instead
:param build_dir: cache directory to run in
:param environment: environment to pass in when refreshing
:param full: perform a full rebuild
"""
environment = {} if environment is None else environment
if full:
environment = {}
run_args = ["--build", str(build_dir)]
if self.verbose:
print("[CMAKE] Refreshing CMake build cache")
Expand All @@ -503,24 +506,18 @@ def cmake_refresh_cache(self, build_dir, full=False):
if self.verbose:
print("[CMAKE] Checking CMake cache for rebuild")
# Backwards compatibility: refresh_cache was named noop until v3.3.x
if self._is_noop_supported(str(build_dir)):
self.execute_known_target(
"noop",
build_dir,
None,
top_target=True,
full_cache_rebuild=True,
print_output=True,
)
else:
self.execute_known_target(
"refresh_cache",
build_dir,
None,
top_target=True,
full_cache_rebuild=True,
print_output=True,
)
refresh_target = (
"noop" if self._is_noop_supported(str(build_dir)) else "refresh_cache"
)
self.execute_known_target(
refresh_target,
build_dir,
None,
top_target=True,
full_cache_rebuild=True,
print_output=True,
environment=environment,
)

def _run_cmake(
self,
Expand Down
2 changes: 1 addition & 1 deletion src/fprime/fpp/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def execute(
)
return 1

builder.cmake.cmake_refresh_cache(builder.build_dir, False)
builder.refresh()

# Read files and arguments
locations = self.get_locations_file(builder)
Expand Down
36 changes: 36 additions & 0 deletions test/fprime/fbuild/echoer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python
""" Fake CMake script for testing purposes
This script can be added to the front of the path to echo what arguments are sent to CMake allowing for tests that are
slightly closer to integration tests without involving the entirety of F Prime.
"""
import sys
import os
from pathlib import Path
import json

if __name__ == "__main__":
print("[INFO] Running echoer program (stdout)")
print("[INFO] Running echoer program (stderr)", file=sys.stderr)
executable_path = Path(sys.argv[0])
for i in range(0, 100):
output_file_path = (
executable_path.parent / f"faux-{executable_path.name}-{i}.json"
)
if not output_file_path.exists():
with open(output_file_path, "w") as output_file:
json.dump(
{
"arguments": sys.argv,
"cwd": str(Path.cwd()),
"environment": dict(os.environ),
},
output_file,
)
break
else:
print(
f"[ERROR] Too many invocations of: {executable_path.name}", file=sys.stderr
)
sys.exit(1)
sys.exit(0)
Loading

0 comments on commit 4735570

Please sign in to comment.