Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions crytic_compile/cryticparser/cryticparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,3 +473,11 @@ def _init_foundry(parser: ArgumentParser) -> None:
dest="foundry_deny",
default=DEFAULTS_FLAG_IN_CONFIG["foundry_deny"],
)

group_foundry.add_argument(
"--foundry-no-force",
help="Enable incremental compilation (skips forge clean and --force flag)",
action="store_true",
dest="foundry_no_force",
default=DEFAULTS_FLAG_IN_CONFIG["foundry_no_force"],
)
1 change: 1 addition & 0 deletions crytic_compile/cryticparser/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"foundry_build_info_directory": None,
"foundry_compile_all": False,
"foundry_deny": None,
"foundry_no_force": False,
"export_dir": "crytic-export",
"compile_libraries": None,
}
24 changes: 20 additions & 4 deletions crytic_compile/platform/foundry.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import json
import logging
import re
import shutil
import subprocess
from pathlib import Path
from typing import TYPE_CHECKING, TypeVar
Expand Down Expand Up @@ -68,7 +69,7 @@ def compile(self, crytic_compile: "CryticCompile", **kwargs: str) -> None:
Args:
crytic_compile (CryticCompile): CryticCompile object to populate
**kwargs: optional arguments. Used: "foundry_ignore_compile", "foundry_out_directory",
"foundry_build_info_directory", "foundry_deny"
"foundry_build_info_directory", "foundry_deny", "foundry_no_force"

"""

Expand Down Expand Up @@ -105,9 +106,22 @@ def compile(self, crytic_compile: "CryticCompile", **kwargs: str) -> None:
]

compile_all = kwargs.get("foundry_compile_all", False)
no_force = kwargs.get("foundry_no_force", False)

foundry_config = self.config(self._project_root)

# When no_force is enabled, we must compile all files (including tests)
# to ensure test changes are detected. Otherwise tests would be skipped
# and test modifications wouldn't trigger recompilation.
# We also clean build-info to prevent multiple compilation units from accumulating.
if no_force:
compile_all = True
out_dir = foundry_config.out_path if foundry_config else "out"
build_info_dir = Path(self._project_root, out_dir, "build-info")
if build_info_dir.exists():
shutil.rmtree(build_info_dir)
LOGGER.info("Cleaned %s for fresh build-info generation", build_info_dir)
Comment on lines +117 to +123
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this goes against the objective described on the PR.


if not targeted_build and not compile_all and foundry_config:
compilation_command += [
"--skip",
Expand Down Expand Up @@ -142,14 +156,16 @@ def clean(self, **kwargs: str) -> None:
"""Clean compilation artifacts

Args:
**kwargs: optional arguments.
**kwargs: optional arguments. Used: "foundry_ignore_compile", "ignore_compile",
"foundry_no_force"
"""

ignore_compile = kwargs.get("foundry_ignore_compile", False) or kwargs.get(
"ignore_compile", False
)
no_force = kwargs.get("foundry_no_force", False)

if ignore_compile:
# Skip cleaning when using incremental compilation mode
if ignore_compile or no_force:
return

run(["forge", "clean"], cwd=self._project_root)
Expand Down