Add support for dynamic trice and triceS macro aliases#533
Add support for dynamic trice and triceS macro aliases#533rokath merged 3 commits intorokath:masterfrom
Conversation
Introduced mechanisms to handle customizable macro aliases for trice() and triceS() through cli flags.
|
Thanks a lot for your 2nd contribution @srgg ! I think the |
|
@rokath I have checked and discovered that the CGO test somehow relies on if ((defined(TRICE_OFF) && TRICE_OFF == 1)) || ((defined(TRICE_CLEAN) && TRICE_CLEAN == 1))
...
#include "triceOff.h"And in the trice.c: #if !TRICE_OFF
So it is not excluded if CLEAN is defined. However, as I see it, the CGO test relies on So I'm stuck here: the CGO tests, on the one hand, declare CLEAN=1 to insert IDs (which cause the inclusion of triceOff.h), but on the other hand, they require actual trice functions, not stubs. What is strange is that I did not change anything related to this; moreover, when I attempted to exclude trice either from trice.c ot trice. I'm still getting numerous errors. I'm affraid and I'm sorry for saying it. I would appreciate your help on this one. Just in case: gcc --version
Apple clang version 16.0.0 (clang-1600.0.26.4)
Target: arm64-apple-darwin24.5.0
Thread model: posix |
|
I will probably have time for this only next week. Please be patient. |
|
@rokath I have pushed one more commit in this PR to fix the insert/clean commands behavior when the format string is not the first argument after the Trice ID. Example of the issue: CUSTOM_ASSERT(false, "CUSTOM_ASSERT false test: %s\n", str);Before the fix, insert incorrectly produced: CUSTOM_ASSERT(iD(1234), "CUSTOM_ASSERT false test: %s\n", str);Expected result after fix: CUSTOM_ASSERT(iD(1234), false, "CUSTOM_ASSERT false test: %s\n", str);The issue was that the logic assumed the format string was always the first argument after Trice ID, but in custom macros like assert, the condition comes first. |
|
Hi @srgg, I tried to quickly check after your last update, but now already What I did: git fetch origin pull/533/head:test-alias
...
git switch test-alias
ms@Mac trice % go test ./...
ok github.com/rokath/trice/cmd/trice (cached)
...
FAIL github.com/rokath/trice/internal/id 3.475s
...
ok github.com/rokath/trice/pkg/tst (cached)
FAIL
ms@MacBook-Pro trice % git log | head -n 20
commit 0cac155cc376052b417e86b0186a2ec0a16913aa
Author: srgg <srggal@gmail.com>
Date: Thu May 29 16:16:18 2025 -0600
Refactor alias handling logic, fixing custom macro handling where the format string isn't the first arg after Trice ID.
commit 5a04b94cb01bc13e58e6fdd573d539b5d195c87a
Author: srgg <srggal@gmail.com>
Date: Thu May 22 10:37:38 2025 -0600
Add support for dynamic trice and triceS macro aliases
Introduced mechanisms to handle customizable macro aliases for trice() and triceS() through cli flags.
commit c0419731b5b1a6849a84602c2888cefc5a7074b1
Author: srgg <srggal@gmail.com>
Date: Thu May 15 18:25:41 2025 -0600
Add an IPv4 UDP receiver and introduce the '-exclude' flag to omit specified sources from scanning.
ms@MacBook-Pro trice %
ms@MacBook-Pro trice %
ms@MacBook-Pro trice %
ms@MacBook-Pro trice % git checkout c0419731b5b1a6849a84602c2888cefc5a7074b1
Note: switching to 'c0419731b5b1a6849a84602c2888cefc5a7074b1'.
...
HEAD is now at c0419731 Add an IPv4 UDP receiver and introduce the '-exclude' flag to omit specified sources from scanning.
ms@MacBook-Pro trice % go test ./...
ok github.com/rokath/trice/cmd/trice (cached)
...
ok github.com/rokath/trice/internal/id (cached)
...
ok github.com/rokath/trice/pkg/tst (cached)
ms@MacBook-Pro trice % git switch -
Previous HEAD position was c0419731 Add an IPv4 UDP receiver and introduce the '-exclude' flag to omit specified sources from scanning.
Switched to branch 'test-alias' |
|
@rokath, oops, I'm sorry for that (means confirmed, fails on my side as well). My last commit broke it. I will check/fix? It today. |
|
@rokath I've force-pushed my latest changes, which resolve all test failures except one (see below). Additionally, I've added a trivial test case to TestMatchTrice to verify the correct matching of custom macros: func TestMatchTrice(t *testing.T) {
// Register custom aliases
triceAliasesPtr := &TriceAliases
triceAliasesPtr.Set("MyAssert")
ProcessAliases()
var testSet = []struct {
text, triceType, triceID, triceFmts string
}{
// Test case for assert-style custom macros w/o Trice ID
{`...MyAssert( i<12, "%d+%3d=%u",
(3), 4, (3+4) ); ,...`, `MyAssert`, ``, `i<12, "%d+%3d=%u"`},
// Test case for assert-style custom macros with Trice ID
{`...MyAssert( iD(42), i<12, "%d+%3d=%u",
(3), 4, (3+4) ); ,...`, `MyAssert`, `iD(42)`, `i<12, "%d+%3d=%u"`},
// Test case for built-in macros
...There is only one remaining test failure: === RUN TestInsert_On_valid_iCache_valid_cCache_clean_file_edited
TestInsert_On_valid_iCache_valid_cCache_clean_file_edited ...
require.go:72:
Error Trace: /Users/srg/go/pkg/mod/github.com/tj/assert@v0.0.3/require.go:72
/Users/srg/src/srg-trice/trice/internal/id/cache_help_test.go:52
/Users/srg/src/srg-trice/trice/internal/id/cachedInsert_test.go:392
Error: Not equal:
expected: "trice(iD(999), \"msg:value=%d\\n\", -2);"
actual : "trice(iD(999), i\"msg:value=%d\\n\", -2);"
Diff:
--- Expected
+++ Actual
@@ -1 +1 @@
-trice(iD(999), "msg:value=%d\n", -2);
+trice(iD(999), i"msg:value=%d\n", -2);
Test: TestInsert_On_valid_iCache_valid_cCache_clean_file_edited
TestInsert_On_valid_iCache_valid_cCache_clean_file_edited ...done.
--- FAIL: TestInsert_On_valid_iCache_valid_cCache_clean_file_edited (0.01s)
Expected :trice(iD(999), "msg:value=%d\n", -2);
Actual :trice(iD(999), i"msg:value=%d\n", -2);This test previously passed because the matcher logic omitted everything between '<trice>(' and the format string. After changing the behavior to retain custom macro arguments before the format specifier (previously omitted by the legacy logic), this test now fails. As soon as I remove the trailing "i" at line 384: assertFileCreate(t, FSys, SFName, `trice("msg:value=%d\n", -2);`) // edit fileAll go tests passed: go test ./...
ok github.com/rokath/trice/cmd/trice (cached)
ok github.com/rokath/trice/internal/args (cached)
ok github.com/rokath/trice/internal/charDecoder (cached)
ok github.com/rokath/trice/internal/com (cached)
ok github.com/rokath/trice/internal/decoder (cached)
? github.com/rokath/trice/internal/do [no test files]
ok github.com/rokath/trice/internal/dumpDecoder (cached)
ok github.com/rokath/trice/internal/emitter (cached)
ok github.com/rokath/trice/internal/id 3.067s
ok github.com/rokath/trice/internal/keybcmd (cached)
ok github.com/rokath/trice/internal/link (cached)
ok github.com/rokath/trice/internal/receiver 0.159s
? github.com/rokath/trice/internal/translator [no test files]
ok github.com/rokath/trice/internal/trexDecoder (cached)
? github.com/rokath/trice/pkg/ant [no test files]
ok github.com/rokath/trice/pkg/cipher (cached)
ok github.com/rokath/trice/pkg/endian (cached)
ok github.com/rokath/trice/pkg/msg (cached)
ok github.com/rokath/trice/pkg/tst (cached)At this point, I'm not entirely sure what the purpose of this "i" is. |
|
The trailing "i" at line 384 is definitively a typo, so please remove it and go ahead. I expect to have on Monday, or maybe tomorrow time for yoPR. |
… format string isn't the first arg after Trice ID.
|
Awesome, I have pushed it w/o "i": git log -1 --oneline
bba67434 (HEAD -> master, origin/master, origin/HEAD) Refactor alias handling logic, fixing custom macro handling where the format string isn't the first arg after Trice ID.
go test ./...
go: downloading github.com/rokath/cobs v0.0.0-20230425030040-4ebbe9b903b9
go: downloading github.com/rokath/tcobs v0.9.1
go: downloading github.com/tj/assert v0.0.3
go: downloading github.com/spf13/afero v1.9.5
go: downloading go.bug.st/serial v1.6.0
go: downloading github.com/pkg/errors v0.9.1
go: downloading github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
go: downloading github.com/stretchr/testify v1.8.4
go: downloading github.com/kr/pretty v0.1.0
go: downloading golang.org/x/crypto v0.35.0
go: downloading github.com/fsnotify/fsnotify v1.6.0
go: downloading github.com/udhos/equalfile v0.3.0
go: downloading golang.org/x/sys v0.30.0
go: downloading github.com/kr/text v0.1.0
go: downloading golang.org/x/text v0.22.0
go: downloading github.com/mattn/go-colorable v0.1.13
go: downloading gopkg.in/yaml.v3 v3.0.1
go: downloading github.com/pmezard/go-difflib v1.0.0
go: downloading github.com/davecgh/go-spew v1.1.1
go: downloading github.com/creack/goselect v0.1.2
go: downloading github.com/mattn/go-isatty v0.0.19
ok github.com/rokath/trice/cmd/trice 1.306s
ok github.com/rokath/trice/internal/args 0.852s
ok github.com/rokath/trice/internal/charDecoder 0.575s
ok github.com/rokath/trice/internal/com 3.867s
ok github.com/rokath/trice/internal/decoder 0.689s
? github.com/rokath/trice/internal/do [no test files]
ok github.com/rokath/trice/internal/dumpDecoder 0.799s
ok github.com/rokath/trice/internal/emitter 0.359s
ok github.com/rokath/trice/internal/id 3.146s
ok github.com/rokath/trice/internal/keybcmd 0.483s
ok github.com/rokath/trice/internal/link 0.119s
ok github.com/rokath/trice/internal/receiver 0.237s
? github.com/rokath/trice/internal/translator [no test files]
ok github.com/rokath/trice/internal/trexDecoder 0.551s
? github.com/rokath/trice/pkg/ant [no test files]
ok github.com/rokath/trice/pkg/cipher 0.663s
ok github.com/rokath/trice/pkg/endian 0.759s
ok github.com/rokath/trice/pkg/msg 0.867s
ok github.com/rokath/trice/pkg/tst 0.975s |
…able evaluation for built-in trice macros only.
|
@rokath Added a commit skipping parameter count checks for aliases. Custom macros can have arbitrary behavior, so checking format specifiers or argument count isn't reliable. Example fails in evaluateTriceParameterCount(): "should have exactly one format specifier and not 0": CUSTOM_ASSERT(false, "Whatever failure message");
// or it could be even
CUSTOM_ASSERT(false);
// whereas:
#define CUSTOM_ASSERT(id, condition, ...) \
do { if (!(condition)) { triceS(id, "%s", format_message("ASSERTION FAILED: %s at %s:%d", #condition, __FILE__, __LINE__)); } } while(0)And I have another issue in mind: with such flexibility of custom macros, how can Strg be determined? // Question: What to use as Strg for custom macros when a format string isn't reliably at 1st or 2nd arg after Trice ID?
// Use "%s" for dynamic strings and assume a format string is the first arg after Trice ID for non-dynamic string macros
isAlias := t.Alias != ""
isSAlias := t.Type == "triceS"
if !isSAlias {
t.Strg = rest[loc[5]+1 : loc[6]-1] // Now we have the complete trice t (Type and Strg). We remove the double quotes with +1 and -1.
} else {
t.Strg = "%s"
}Is it ok? The Default implementation for "1111": {
"Type": "triceS",
"Strg": "alse , \"Whatever failure message",
"Alias": "CUSTOM_ASSERT"
} |
|
Hello @srgg, The CGO tests are OK, after commenting out in internal/args/handler.go around line 33: // Trim leading and trailing whitespace
//for i := range args {
// args[i] = strings.TrimSpace(args[i])
//}Before I got: ok github.com/rokath/trice/pkg/tst 1.350s
0 {59 time:feed3322default: Hello World!}
1 {61 time:feed3322default: info:This is a message without values and a 32-bit stamp.}
2 {62 time: be16default: info:This is a message without values and a 16-bit stamp.}
3 {63 time: default: info:This is a message without values and without stamp.}
--- FAIL: TestLogs (0.48s)
require.go:72:
Error Trace: /Users/ms/go/pkg/mod/github.com/tj/assert@v0.0.3/require.go:72
/Users/ms/repos/trice/_test/be_dblB_de_tcobs_ua/generated_cgoPackage.go:184
/Users/ms/repos/trice/_test/be_dblB_de_tcobs_ua/cgo_test.go:24
Error: Not equal:
expected: "time: default: info:This is a message without values and without stamp."
actual : "time:default: info:This is a message without values and without stamp."
Diff:
--- Expected
+++ Actual
@@ -1 +1 @@
-time: default: info:This is a message without values and without stamp.
+time:default: info:This is a message without values and without stamp.
Test: TestLogs
FAIL
FAIL github.com/rokath/trice/_test/be_dblB_de_tcobs_ua 0.736s
FAILFor example in I understand your intension trimming the aruments, but there are some cases, and not only test cases, where this causes issues. We could add a parameter -noargstrim but I have no good feeling with that. Is there any strong reason for the trimming? Concerning your The only thing I miss right now, are some example tests, but that I can add later by myself. |
|
@rokath I added the trim just to get the tests passing—it's fine to remove it if unnecessary. I have another issue in mind: With such flexibility of custom macros, how can Strg be determined? // Question: What to use as Strg for custom macros when a format string isn't reliably at 1st or 2nd arg after Trice ID?
// Use "%s" for dynamic strings and assume a format string is the first arg after Trice ID for non-dynamic string macros
isAlias := t.Alias != ""
isSAlias := t.Type == "triceS"
if !isSAlias {
t.Strg = rest[loc[5]+1 : loc[6]-1] // Now we have the complete trice t (Type and Strg). We remove the double quotes with +1 and -1.
} else {
t.Strg = "%s"
}Is it ok? The Default implementation for "1111": {
"Type": "triceS",
"Strg": "alse , \"Whatever failure message",
"Alias": "CUSTOM_ASSERT"
}Is it possible to revert the PR so that everything can be merged together as one unit? Or would you prefer to handle it differently? |
In which way this PR influences the
Which tests caused a problem? Was it s.th. temporarily? To be honest, I do not clearly understand your question "What to use as Strg for custom macros when a...". Generally we should keeps things simple. I would not consider any possible custom macro signature and stick with the current known ones. If one day a new situation needs handling, we can react on it appropriate. Why you need the
Compiling a project with
I agree to exclude them from parameter count checking. I accepted the PR, assuming the existing PR changes are ok so far and also because in the main branch has already some additional changes, which I liked to see together with your PR to go forward with some additional test and the documentation. But probably I was to early. Sorry for that. I do not mind to revert the PR and to be patient if that is convenient for you. On the other hand, what speaks against a next PR from you? Lets do it the way you prefer. @srgg, I really appreciate your ideas and your work! EDIT: It seems not to be an easy and unproblematic going to revert a PR. |
|
@rokath Thank you for your time and patience. Please see my answers below.
Please take a look at the example in the PR description. Macro definitions (print_macro.h) must be excluded from ID insertion process —otherwise, all the expanded macros will reuse the same hardcoded/inserted Trice ID.
I'm having multiple issues running the CGO tests. Problems include func(void)-style declarations and name clashes between triceOff.h stubs and actual implementations in trice.c. As a result, I can't run these tests locally. If they pass on your side—with or without trailing cleanup—that's fine by me. I'll try to investigate further and open a ticket when I can, though I'm currently behind schedule on related features.
The "Alias": "CUSTOM_ASSERT" option improves usability and debugging by preserving the original macro name. It is beneficial for developers to use aliases the first time. Additionally, I have one more feature in mind (if I have time for that): customizable color mapping based on macro usage (e.g., asserts in red, warnings in purple). Unlike the current intrusive, hardcoded approach, this would allow non-intrusive styling via CLI/config files. Retaining aliases is crucial for enabling this functionality without modifying the source code.
No problem—I’ve opened a new PR #536. Please review it at your convenience. In that PR, I’ve also tried to address your question about "what to use as Strg for custom macros by enforcing the proposed triceS alias format:. My earlier comment may have been unclear, but this new PR should provide us with a better place to collaborate on it. -- Serhii |
|
Please see my reply in PR #536 . |
Summary
This PR introduces support for treating user-defined macros as aliases to trice and triceS within the Trice CLI toolchain. The goal is to enable project-specific logging macros to be processed just like built-in Trice macros — including ID generation, decoding, and binary format support — without requiring projects to directly call
trice()ortriceS()in their source code.PR leverages the --excludeSource feature added in #529.
Motivation
Trice uses a source-scanning and ID generation approach, where the toolchain scans for
trice(...)andtriceS(...)calls, injects numeric trace IDs, and builds a mapping database. However, it currently only supports built-in(hardcoded) macros and allows only global on/off control via compile-time flags.This makes it difficult to:
What This PR Adds
CLI-level aliasing: Developers can now declare custom macros to be treated as trice or triceS equivalents. These user-defined macros will be recognized during scanning, ID injection, and decoding.
Example:
print_macro.h:
example.c
Check with Trice
Insert trice IDs
Flash the MCU and run the trice receiver on your host machine to receive probes (cli command is config and receiver dependent), for UDP4, it can be:
Check without Trice:
Clean trice IDs, if any:
Flash with -DTRICE_OFF