Skip to content
Merged
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
70 changes: 35 additions & 35 deletions ntxbuild/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,59 +302,59 @@ def start(apps_dir, nuttx_dir, store_nxtmpdir, use_cmake, board, defconfig):


@main.command()
@click.option("--read", "-r", help="Path to apps folder (relative or absolute)")
@click.option("--set-value", help="Set Kconfig value")
@click.option("--set-str", help="Set Kconfig string")
@click.option("--read", "-r", help="Read Kconfig option", nargs=1)
@click.option("--enable", "-e", help="Enable Kconfig option", nargs=1)
@click.option("--disable", "-d", help="Disable Kconfig option", nargs=1)
@click.option("--set-value", help="Set Kconfig value (int or hex)", nargs=2)
@click.option("--set-str", help="Set Kconfig string", nargs=2)
@click.option("--apply", "-a", help="Apply Kconfig options", is_flag=True)
@click.option("--merge", "-m", help="Merge Kconfig file", is_flag=True)
@click.argument("value", nargs=1, required=False)
def kconfig(read, set_value, set_str, apply, value, merge):
@click.option("--merge", "-m", help="Merge Kconfig file", nargs=1)
def kconfig(
read: str,
enable: str,
disable: str,
set_value: str,
set_str: str,
apply: bool,
merge: int,
):
"""Manage Kconfig options.

Provides commands to read, set, and manage Kconfig configuration
options. Only one action can be performed at a time.

Args:
read: Path to the Kconfig option to read (use with --read/-r).
set_value: Name of the Kconfig option to set a numerical value
(use with --set-value). Requires value argument.
set_str: Name of the Kconfig option to set a string value
(use with --set-str). Requires value argument.
apply: If True, apply Kconfig changes by running olddefconfig
(use with --apply/-a flag).
merge: If True, merge a Kconfig file (use with --merge/-m flag).
Requires value argument with the source file path.
value: Value to set (for --set-value or --set-str) or source
file path (for --merge). Defaults to None.
Example usage:

Exits with code 0 on success, 1 on error.
ntxbuild kconfig --enable CONFIG_DEBUG_INFO

ntxbuild kconfig --set-value CONFIG_RAM_START 0x1000

ntxbuild kconfig --merge ../configs/my_config
"""
env = prepare_env()
try:
config_manager = ConfigManager(
env.get("nuttxspace_path"), env.get("nuttx_dir"), env.get("apps_dir")
)
if read:

if apply:
config_manager.kconfig_apply_changes()
elif merge:
config_manager.kconfig_merge_config_file(merge)
elif read:
config_manager.kconfig_read(read)
elif set_value:
if not value:
click.echo("❌ Set value is required")
sys.exit(1)
config_manager.kconfig_set_value(set_value, value)
config_manager.kconfig_set_value(set_value[0], set_value[1])
elif set_str:
if not value:
click.echo("❌ Set string is required")
sys.exit(1)
config_manager.kconfig_set_str(set_str, value)
elif apply:
config_manager.kconfig_apply_changes()
elif merge:
if not value:
click.echo("❌ Merge file is required")
sys.exit(1)
config_manager.kconfig_merge_config_file(value)
config_manager.kconfig_set_str(set_str[0], set_str[1])
elif enable:
config_manager.kconfig_enable(enable)
elif disable:
config_manager.kconfig_disable(disable)
else:
click.echo("❌ No action specified")
sys.exit(1)

except click.ClickException as e:
click.echo(f"❌ {e}")
sys.exit(1)
Expand Down
23 changes: 17 additions & 6 deletions ntxbuild/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,14 @@ class KconfigParser(kconfiglib.Kconfig):
KCONFIG_FILE = "Kconfig"
KCONFIG_CONFIG = ".config"

def __init__(self, nuttx_path: Path, apps_path: Path = None):
def __init__(self, nuttx_path: Path, apps_path: Path = None, warn: bool = False):
"""Initialize the Kconfig parser.

Args:
nuttx_path: Path to the NuttX source directory.
apps_path: Path to the NuttX apps directory. If None, defaults
to nuttx_path.parent / "nuttx-apps".
warn: Whether to show warnings. Defaults to True.

Raises:
FileNotFoundError: If the apps_path does not exist.
Expand Down Expand Up @@ -131,7 +132,7 @@ def __init__(self, nuttx_path: Path, apps_path: Path = None):

os.chdir(self.nuttx_path)
try:
super().__init__(self.KCONFIG_FILE, suppress_traceback=False)
super().__init__(self.KCONFIG_FILE, warn=warn, suppress_traceback=False)
except Exception as e:
logger.error(f"Error initializing Kconfig parser: {e}")
self.environment_context.restore_environment()
Expand Down Expand Up @@ -159,7 +160,11 @@ class ConfigManager(KconfigParser):
"""

def __init__(
self, nuttxspace_path: Path, nuttx_dir: str = "nuttx", apps_dir: str = None
self,
nuttxspace_path: Path,
nuttx_dir: str = "nuttx",
apps_dir: str = None,
warnings: bool = False,
):
"""Initialize the ConfigManager.

Expand All @@ -170,6 +175,7 @@ def __init__(
apps_dir: Name of the NuttX apps directory within the workspace.
If None, defaults to "nuttx-apps".
Defaults to None.
warnings: Whether to show warnings. Defaults to True.

Raises:
FileNotFoundError: If the apps directory does not exist.
Expand All @@ -185,7 +191,7 @@ def __init__(
else:
self.apps_path = self.nuttxspace_path / "nuttx-apps"

super().__init__(self.nuttx_path, self.apps_path)
super().__init__(self.nuttx_path, self.apps_path, warn=warnings)

@kconfig_chdir
def kconfig_read(self, config: str) -> str:
Expand Down Expand Up @@ -218,6 +224,7 @@ def kconfig_read(self, config: str) -> str:
)

logger.info(f"Kconfig read: {config}={value}")
print(f"{config}={value}")
return value
except Exception as e:
self.environment_context.restore_environment()
Expand Down Expand Up @@ -258,7 +265,7 @@ def kconfig_enable(self, config: str) -> int:
logger.info(f"Kconfig option '{config}' enabled")
else:
logger.error(f"Kconfig option '{config}' enable failed")

self.write_config()
return ret
except Exception as e:
self.environment_context.restore_environment()
Expand Down Expand Up @@ -299,7 +306,7 @@ def kconfig_disable(self, config: str) -> int:
logger.info(f"Kconfig option '{config}' disabled")
else:
logger.error(f"Kconfig option '{config}' disable failed")

self.write_config()
return ret
except Exception as e:
self.environment_context.restore_environment()
Expand Down Expand Up @@ -396,7 +403,9 @@ def kconfig_set_value(self, config: str, value: str) -> int:
if not ret:
logger.error(f"Kconfig set value: {config}={value} failed")
logger.info(f"Kconfig set value: {config}={value}")
self.write_config()
return ret

except Exception as e:
self.environment_context.restore_environment()
raise e
Expand Down Expand Up @@ -432,6 +441,7 @@ def kconfig_set_str(self, config: str, value: str) -> int:
if not ret:
logger.error(f"Kconfig set string: {config}={value} failed")
logger.info(f"Kconfig set string: {config}={value}")
self.write_config()
return ret
except Exception as e:
self.environment_context.restore_environment()
Expand Down Expand Up @@ -487,6 +497,7 @@ def kconfig_merge_config_file(self, source_file: str) -> int:
logger.info(f"Kconfig merge config file: {source_file}")
source_file = Path(source_file).resolve().as_posix()
result = self.load_config(str(source_file), replace=False)
self.write_config()
logger.info(f"Kconfig merge config file result: {result}")
except Exception as e:
self.environment_context.restore_environment()
Expand Down
8 changes: 4 additions & 4 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ def test_kconfig_set_value_missing_value(self, nuttxspace_path):
result = runner.invoke(kconfig, ["--set-value", "CONFIG_SYSTEM_NSH_PRIORITY"])

assert result.exit_code != 0
assert "Set value is required" in result.output
assert "Option '--set-value' requires 2 arguments." in result.output

def test_kconfig_set_str(self, nuttxspace_path):
"""Test kconfig set-str command."""
Expand All @@ -410,7 +410,7 @@ def test_kconfig_set_str_missing_value(self, nuttxspace_path):
result = runner.invoke(kconfig, ["--set-str", "CONFIG_NSH_PROMPT_STRING"])

assert result.exit_code != 0
assert "Set string is required" in result.output
assert "Option '--set-str' requires 2 arguments." in result.output

def test_kconfig_apply(self, nuttxspace_path):
"""Test kconfig apply command."""
Expand Down Expand Up @@ -442,14 +442,14 @@ def test_kconfig_merge_missing_file(self, nuttxspace_path):
result = runner.invoke(kconfig, ["--merge"])

assert result.exit_code != 0
assert "Merge file is required" in result.output
assert "Option '--merge' requires an argument." in result.output

def test_kconfig_no_action(self, nuttxspace_path):
"""Test kconfig command without any action specified."""
runner = CliRunner()
result = runner.invoke(kconfig, [])

assert result.exit_code == 0
assert result.exit_code == 1
assert "No action specified" in result.output

def test_kconfig_without_ntxenv(self, nuttxspace_path):
Expand Down
19 changes: 13 additions & 6 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,23 @@ def test_merge_config(nuttxspace_path):
this_file = Path(__file__).resolve()

config_file = this_file.parent / "configs" / "test_config"

value_before_nsh = config_manager.kconfig_read("CONFIG_NSH_SYSINITSCRIPT")
value_before_dd = config_manager.kconfig_read("CONFIG_SYSTEM_DD")
value_before_gpio = config_manager.kconfig_read("CONFIG_DEV_GPIO_NSIGNALS")

assert config_file.exists()
config_manager.kconfig_merge_config_file(config_file)
config_manager.kconfig_apply_changes()

value = config_manager.kconfig_read("CONFIG_NSH_SYSINITSCRIPT")
assert value == "test_value"
value = config_manager.kconfig_read("CONFIG_SYSTEM_DD")
assert value == "n"
value = config_manager.kconfig_read("CONFIG_DEV_GPIO_NSIGNALS")
assert value == "2"
new_config_manager = ConfigManager(nuttxspace_path, "nuttx")

value = new_config_manager.kconfig_read("CONFIG_NSH_SYSINITSCRIPT")
assert value == "test_value" and value != value_before_nsh
value = new_config_manager.kconfig_read("CONFIG_SYSTEM_DD")
assert value == "n" and value != value_before_dd
value = new_config_manager.kconfig_read("CONFIG_DEV_GPIO_NSIGNALS")
assert value == "2" and value != value_before_gpio


# Exception tests
Expand Down