Skip to content

Replace ad-hoc argument parser with native cmake_parse_arguments()#152

Open
devin-ai-integration[bot] wants to merge 4 commits into
develfrom
devin/1780587798-replace-adhoc-cmake-parse-arguments
Open

Replace ad-hoc argument parser with native cmake_parse_arguments()#152
devin-ai-integration[bot] wants to merge 4 commits into
develfrom
devin/1780587798-replace-adhoc-cmake-parse-arguments

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 4, 2026

Copy link
Copy Markdown
Related Issue(s) nasa#5236
Has Unit Tests (y/n) n
Documentation Included (y/n) n
Generative AI was used in this contribution (y/n) AI

Change Description

Replace the ad-hoc argument parser in fprime__process_module_setup (cmake/module.cmake) with CMake's native cmake_parse_arguments().

The ad-hoc parser iterated through arguments manually, tracking a "current list name" and appending values. When a keyword had no arguments (e.g. empty DEPENDS), set("LIST_${CURRENT_LIST_NAME}") was called — but in CMake, set(VAR) with no value unsets the variable. A subsequent flag check then saw it as undefined and set it to TRUE. This caused multi-value keywords like DEPENDS to become the string "TRUE", which downstream code tried to resolve as a build target.

With cmake_parse_arguments:

  • Control sets are categorized into <options> (flags like EXCLUDE_FROM_ALL, OBJECT, INTERFACE, UT_AUTO_HELPERS, etc.) and <multi_value_keywords> (like SOURCES, DEPENDS, HEADERS).
  • Empty multi-value keywords remain as empty lists rather than becoming TRUE.
  • PARSED_UNPARSED_ARGUMENTS provides clear errors for arguments before any keyword.
  • PARSED_KEYWORDS_MISSING_VALUES warns about empty keyword sections (e.g. DEPENDS with no arguments).
  • Duplicate keyword detection is preserved via a scan of the input arguments.
  • File existence validation for FILE_CONTROL_SETS is preserved.

Also removes the STREQUAL "TRUE" workaround in register_fprime_implementation since IMPLEMENTS can no longer become TRUE.

Rationale

Fixes the bizarre "F Prime/CMake target 'TRUE' not available" error from nasa#5236. The root cause was the ad-hoc parser treating empty DEPENDS as a boolean flag. Using cmake_parse_arguments() eliminates this class of bugs and provides better diagnostics.

Testing/Review Recommendations

  • Verify that a register_fprime_library() with an empty DEPENDS section now produces a clear warning instead of the "target 'TRUE' not available" error.
  • Verify flag-type directives (EXCLUDE_FROM_ALL, OBJECT, INTERFACE, INCLUDE_GTEST, UT_AUTO_HELPERS, BASE_CONFIG) still work as boolean flags.
  • Run existing CI/build tests to confirm no regressions.

Future Work

None.

AI Usage (see policy)

AI was used to analyze the root cause of the bug, implement the fix (replacing the ad-hoc parser with cmake_parse_arguments), and write this PR description.

IAMAI

Link to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/4974f331e8484c77bf9636c3b2a3bf00


Open in Devin Review

The custom argument parser in fprime__process_module_setup had a bug where
set("LIST_${CURRENT_LIST_NAME}") (meant to initialize an empty list)
actually unsets the variable in CMake, causing the flag check to set
multi-value keywords like DEPENDS to TRUE when they have no arguments.
This results in downstream code trying to resolve 'TRUE' as a build
target, producing the confusing error from issue nasa#5236.

Replace the ad-hoc parser with CMake's native cmake_parse_arguments(),
which properly distinguishes between options (flags) and multi-value
keywords. Empty multi-value keywords now remain as empty lists instead
of being set to TRUE.

Benefits:
- Empty DEPENDS no longer causes 'target TRUE not found' errors
- cmake_parse_arguments reports UNPARSED_ARGUMENTS for better errors
- KEYWORDS_MISSING_VALUES warns about empty keyword sections
- Remove the STREQUAL TRUE workaround in register_fprime_implementation

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Author
Original prompt from thomas.boyer.chammard

Hello - this bug was reported: nasa#5236
I believe it is because we have implemented our own version of cmake_parse_arguments() in F Prime, and maybe it's not great. Please find it, and replace all usages of the adhoc implementation with the native cmake_parse_arguments(). Would it help warning better ?

@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

WORKING_DIRECTORY was being used in Svc/FileWorker/CMakeLists.txt but
was not in the recognized control sets. The old ad-hoc parser silently
consumed it as arguments to the preceding keyword, while
cmake_parse_arguments correctly flags it as unrecognized. Add it to the
UT-specific additional control directives so it is accepted.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Store INTERNAL_WORKING_DIRECTORY as the FPRIME_WORKING_DIRECTORY target
property in fprime__internal_add_build_target_helper. Read it in
ut_add_ctest and use it in add_test(), falling back to
CMAKE_CURRENT_SOURCE_DIR if not set.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown

Coverage report — base devel

No baseline branch coverage/devel found. This run becomes the seed once it lands on devel.

Overall (line): 81.27% (no baseline)
Regression threshold: 0.50% (line).

Regressions

(none over threshold)

Modules changed

(no measurable change)

New modules

Module Line Function Branch
CFDP/Checksum 71.15 57.14 44.44
Drv/AsyncByteStreamBufferAdapter 100.00 100.00 100.00
Drv/ByteStreamBufferAdapter 100.00 100.00 80.00
Drv/Ip 44.32 57.38 21.25
Drv/TcpClient 75.00 100.00 31.03
Drv/TcpServer 84.72 100.00 44.26
Drv/Udp 68.09 90.91 28.12
Fw/Buffer 81.25 89.47 43.75
Fw/DataStructures 98.48 97.14 57.37
Fw/Dp 94.83 96.67 47.92
Fw/FilePacket 75.24 89.06 41.43
Fw/Log 71.43 72.41 34.48
Fw/Logger 100.00 100.00 62.50
Fw/SerializableFile 90.00 100.00 44.44
Fw/Time 88.62 85.48 50.00
Fw/Tlm 53.76 60.00 24.29
Fw/Types 54.63 57.49 29.48
Os 18.82 20.59 12.70
Os/Generic 89.10 96.30 48.02
Os/Generic/Types 92.45 91.67 60.94
Os/Posix 60.75 83.72 39.74
Svc/ActiveRateGroup 100.00 100.00 60.87
Svc/ActiveTextLogger 79.05 90.00 53.85
Svc/AssertFatalAdapter 94.55 100.00 59.09
Svc/BufferAccumulator 88.00 94.12 54.79
Svc/BufferLogger 92.62 86.96 57.46
Svc/BufferManager 99.05 100.00 55.93
Svc/BufferRepeater 91.67 100.00 55.56
Svc/ChronoTime 100.00 100.00 50.00
Svc/CmdDispatcher 96.97 91.67 52.60
Svc/CmdSequencer 93.89 97.12 56.64
Svc/CmdSplitter 100.00 100.00 54.55
Svc/ComLogger 97.37 91.67 59.15
Svc/ComSplitter 100.00 100.00 66.67
Svc/ComStub 98.51 100.00 59.76
Svc/DpCatalog 78.00 100.00 42.92
Svc/DpManager 97.44 100.00 52.27
Svc/DpWriter 97.58 90.00 62.07
Svc/FileDownlink 84.15 90.91 45.29
Svc/FileManager 88.41 93.33 50.45
Svc/FileUplink 92.78 96.55 54.78
Svc/FileWorker 90.29 100.00 47.53
Svc/FprimeDeframer 100.00 100.00 58.04
Svc/FprimeFramer 100.00 100.00 42.19
Svc/FprimeRouter 88.89 100.00 48.65
Svc/FpySequencer 86.41 99.02 51.67
Svc/GenericHub 100.00 100.00 50.29
Svc/Health 100.00 100.00 60.00
Svc/LinuxTimer 97.06 100.00 47.06
Svc/OsTime 70.00 83.33 37.80
Svc/PassiveRateGroup 100.00 100.00 52.50
Svc/PolyDb 100.00 100.00 42.50
Svc/PosixTime 100.00 100.00 50.00
Svc/PrmDb 92.20 90.00 51.29
Svc/RateGroupDriver 100.00 100.00 62.50
Svc/SeqDispatcher 73.08 80.00 49.18
Svc/StaticMemory 100.00 100.00 55.00
Svc/SystemResources 98.63 100.00 55.00
Svc/TlmChan 82.40 85.71 48.57
Svc/TlmPacketizer 92.54 100.00 54.46
Svc/Version 96.10 100.00 54.91
Utils 19.93 26.44 14.53
Utils/Types 92.11 95.83 58.45

Modules without UTs

CFDP/Checksum/GTest, Drv/ByteStreamDriverModel, Drv/Interfaces, Drv/LinuxGpioDriver, Drv/LinuxI2cDriver, Drv/LinuxSpiDriver, Drv/LinuxUartDriver, Drv/Ports, Drv/Ports/DataTypes, FppTestProject/FppTest/interfaces, FppTestProject/FppTest/topology/async, FppTestProject/FppTest/topology/components/Comp, FppTestProject/FppTest/topology/components/Framework, FppTestProject/FppTest/topology/components/Receiver, FppTestProject/FppTest/topology/components/Sender, FppTestProject/FppTest/topology/guarded, FppTestProject/FppTest/topology/ports, FppTestProject/FppTest/topology/sync, FppTestProject/FppTest/topology/top_ports, FppTestProject/FppTest/topology/types, Fw/Cmd, Fw/Com, Fw/Comp, Fw/FilePacket/GTest, Fw/Fpy, Fw/Interfaces, Fw/Obj, Fw/Port, Fw/Ports/CompletionStatus, Fw/Ports/Ready, Fw/Ports/Signal, Fw/Ports/SuccessCondition, Fw/Prm, Fw/SerializableFile/test/TestSerializable, Fw/Sm, Fw/Test, Fw/Types/GTest, Os/Models, Svc/Cycle, Svc/DpPorts, Svc/Fatal, Svc/FatalHandler, Svc/FileDownlinkPorts, Svc/FprimeProtocol, Svc/Interfaces, Svc/PassiveConsoleTextLogger, Svc/Ping, Svc/PolyIf, Svc/Ports/CommsPorts, Svc/Ports/FilePorts, Svc/Ports/OsTimeEpoch, Svc/Ports/TlmPacketizerPorts, Svc/Ports/VersionPorts, Svc/Sched, Svc/Seq, Svc/Subtopologies/CdhCore, Svc/Subtopologies/ComCcsds, Svc/Subtopologies/ComFprime, Svc/Subtopologies/ComLoggerTee, Svc/Subtopologies/DataProducts, Svc/Subtopologies/FileHandling, Svc/Types/TlmPacketizerTypes, Svc/WatchDog, TestDeploymentsProject/Ref/PingReceiver, TestDeploymentsProject/Ref/RecvBuffApp, TestDeploymentsProject/Ref/SendBuffApp, TestDeploymentsProject/Ref/Top, TestDeploymentsProject/Ref/TypeDemo, Utils/Hash, cmake/test/data/TestDeployment/TestBuildAutocoder, cmake/test/data/TestDeployment/TestChainedAutocoder, cmake/test/data/TestDeployment/TestHeaderAutocoder, cmake/test/data/TestDeployment/TestTargetAutocoder, cmake/test/data/test-fprime-library/TestLibrary/TestComponent, cmake/test/data/test-fprime-library2/TestLibrary2/TestComponent

Many modules legitimately use empty HEADERS sections, which triggers
PARSED_KEYWORDS_MISSING_VALUES. The CMake CI check treats warnings as
errors, causing failures. Remove the warning since it's too noisy for
the existing codebase.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant