Skip to content

Conversation

@claui
Copy link
Contributor

@claui claui commented Dec 2, 2025

If findsymbols fails, it prints a helpful usage message to standard output:

Usage: findsymbols file [-p prefix] symbol ...
  file:
    Symbol file created with the -Ln option in ld65
  -p prefix:
    A prefix added to all returned symbol names
  symbol:
    Name of one or more symbols

Unfortunately, the Makefile ignores the exit status of findsymbols. It then misinterprets the whole help text as legitimate output and rolls it all into the linker command line.

Because the help text happens to contain the word -Ln and there’s another -Ln in the command line already, the linker treats this duplication as an error and bails with the error message from issue #363:

ld65: Error: Cannot use -Ln twice

This PR is to improve the error message and fix the leaky help text.

It redirects the help text to stderr (so the help text is no longer misinterpreted as legitimate output) and adds an exit status guard (so the build fails early with a more useful error message.)

See my commit message for more details.

Note that this PR does not fix the root cause of #363, which I think should be a separate PR.

@mooinglemur Review would be appreciated.

If `findsymbols` fails, it prints a helpful usage message to standard
output:

> Usage: findsymbols file [-p prefix] symbol ...
>   file:
>     Symbol file created with the -Ln option in ld65
>   -p prefix:
>     A prefix added to all returned symbol names
>   symbol:
>     Name of one or more symbols

Unfortunately, the Makefile ignores the exit status of `findsymbols`. It
then misinterprets the whole help text as legitimate output and rolls it
all into the linker command line.

Because the help text happens to contain the word `-Ln` and there’s
another `-Ln` in the command line already, so the linker treats this
duplication as an error and bails:

> ld65: Error: Cannot use -Ln twice

which was also reported in GitHub issue X16Community#363 [1].

To improve the error message and fix the leaky help text:

1. Add a conditional block that queries `.SHELLSTATUS`, a variable which
was introduced in GNU Make v4.2, and if it is nonzero, error out early
with the message "findsymbols failed with exit code $(.SHELLSTATUS)."

2. Additionally, improve `findsymbols` so it redirects the usage text to
standard error and includes the file name in its "File not found"
message.
That way, the message can be seen by the user who ran `make`. It can
also no longer be mistaken for machine-readable output.

Example output of `make`:

> File not found: build/x16/dos.sym
> Usage: findsymbols file [-p prefix] symbol ...
>   file:
>     Symbol file created with the -Ln option in ld65
>   -p prefix:
>     A prefix added to all returned symbol names
>   symbol:
>     Name of one or more symbols
> Makefile:407: *** findsymbols failed with exit code 1.  Stop.

3. To avoid peppering the whole Makefile with exit code guards, declare
a `findsymbols` function that hides the complexity.

4. As an unwanted side effect, calling a function causes Make to
misinterpret the `$` address prefixes that occur in the `findsymbols`
output. To counteract that, escape every `$` with `$$`.

5. As a graceful fallback for users of GNU Make versions older than 4.2,
default `.SHELLSTATUS` to 0. In that case, we have no early returns, but
users still get a somewhat meaningful error message that says e.g.,
"Unresolved external 'skip_mask' referenced in: fat32/match.s", which is
still much more helpful than "ld65: Error: Cannot use -Ln twice".

[1]: X16Community#363
@claui
Copy link
Contributor Author

claui commented Dec 2, 2025

Output of make clean && make -j2, which causes a findsymbols failure 50 % of the time:

Before

[…]
ld65 -C build/x16/cfg/keymap-x16.cfg build/x16/keymap/keymap.o -o build/x16/keymap.bin -m build/x16/keymap.map -Ln build/x16/keymap.sym
ld65: Warning: build/x16/cfg/keymap-x16.cfg(49): Segment 'VECTORS' does not exist
ld65 -C build/x16/cfg/dos-x16.cfg build/x16/dos/declare.o build/x16/dos/zeropage.o build/x16/dos/jumptab.o build/x16/dos/main.o build/x16/dos/file.o build/x16/dos/cmdch.o build/x16/dos/dir.o build/x16/dos/parser.o build/x16/dos/functions.o build/x16/dos/djsrfar.o -o build/x16/dos.bin -m build/x16/dos.map -Ln build/x16/dos.sym
./scripts/trace_info.py 14 x16-edit/conf/x16edit-rom.cfg x16-edit/build/x16edit-rom.lst  build/x16/x16edit-rom_E.rlst build/x16/x16edit_E_labels.h
./scripts/relist.py build/x16/dos.map build/x16/dos
ld65 -C build/x16/cfg/fat32-x16.cfg build/x16/fat32/fat32.o build/x16/fat32/mkfs.o build/x16/fat32/sdcard.o build/x16/fat32/text_input.o build/x16/fat32/match.o build/x16/fat32/main.o -o build/x16/fat32.bin -m build/x16/fat32.map -Ln build/x16/fat32.sym \
`build/x16/../../findsymbols build/x16/dos.sym bank_save fat32_bufptr fat32_lfn_bufptr fat32_ptr fat32_ptr2 krn_ptr1` \
`build/x16/../../findsymbols build/x16/dos.sym fat32_dirent fat32_errno fat32_readonly fat32_size skip_mask`
ld65: Warning: Address size mismatch for 'bank_save': Exported from [linker generated] as 'absolute', import in fat32.o, fat32/fat32.s(3471) as 'zeropage'
ld65: Warning: Address size mismatch for 'fat32_bufptr': Exported from [linker generated] as 'absolute', import in mkfs.o, fat32/regs.inc(3) as 'zeropage'
ld65: Warning: Address size mismatch for 'fat32_bufptr': Exported from [linker generated] as 'absolute', import in fat32.o, fat32/regs.inc(3) as 'zeropage'
ld65: Warning: Address size mismatch for 'fat32_lfn_bufptr': Exported from [linker generated] as 'absolute', import in fat32.o, fat32/regs.inc(3) as 'zeropage'
ld65: Warning: Address size mismatch for 'fat32_ptr': Exported from [linker generated] as 'absolute', import in match.o, fat32/regs.inc(3) as 'zeropage'
ld65: Warning: Address size mismatch for 'fat32_ptr': Exported from [linker generated] as 'absolute', import in mkfs.o, fat32/regs.inc(3) as 'zeropage'
ld65: Warning: Address size mismatch for 'fat32_ptr': Exported from [linker generated] as 'absolute', import in fat32.o, fat32/regs.inc(3) as 'zeropage'
ld65: Warning: Address size mismatch for 'fat32_ptr2': Exported from [linker generated] as 'absolute', import in mkfs.o, fat32/regs.inc(3) as 'zeropage'
ld65: Warning: Address size mismatch for 'fat32_ptr2': Exported from [linker generated] as 'absolute', import in fat32.o, fat32/regs.inc(3) as 'zeropage'
ld65: Warning: Address size mismatch for 'krn_ptr1': Exported from [linker generated] as 'absolute', import in fat32.o, fat32/fat32.s(3423) as 'zeropage'
ld65 -C build/x16/cfg/basic-x16.cfg build/x16/kernsup/kernsup_basic.o build/x16/basic/basic.o build/x16/math/math.o -o build/x16/basic.bin -m build/x16/basic.map -Ln build/x16/basic.sym `build/x16/../../findsymbols build/x16/kernal.sym shflag mode wheel`
./scripts/relist.py build/x16/fat32.map build/x16/fat32
ld65: Error: Cannot use -Ln twice
make: *** [Makefile:409: build/x16/basic.bin] Error 1
make: *** Waiting for unfinished jobs....

After

[…]
ld65 -C build/x16/cfg/charset-x16.cfg build/x16/charset/petscii.o build/x16/charset/iso-8859-15.o build/x16/charset/petscii2.o build/x16/charset/iso-8859-15_2.o build/x16/charset/ascii-cp437.o build/x16/charset/iso-8859-5.o build/x16/charset/iso-8859-5_2.o build/x16/charset/iso-8859-16.o build/x16/charset/iso-8859-16_2.o build/x16/charset/katakana.o -o build/x16/charset.bin -m build/x16/charset.map -Ln build/x16/charset.sym
ld65 -C build/x16/cfg/keymap-x16.cfg build/x16/keymap/keymap.o -o build/x16/keymap.bin -m build/x16/keymap.map -Ln build/x16/keymap.sym
ld65: Warning: build/x16/cfg/keymap-x16.cfg(49): Segment 'VECTORS' does not exist
File not found: build/x16/dos.sym
Usage: findsymbols file [-p prefix] symbol ...
  file:
    Symbol file created with the -Ln option in ld65
  -p prefix:
    A prefix added to all returned symbol names
  symbol:
    Name of one or more symbols
./scripts/trace_info.py 14 x16-edit/conf/x16edit-rom.cfg x16-edit/build/x16edit-rom.lst  build/x16/x16edit-rom_E.rlst build/x16/x16edit_E_labels.h
ld65 -C build/x16/cfg/dos-x16.cfg build/x16/dos/declare.o build/x16/dos/zeropage.o build/x16/dos/jumptab.o build/x16/dos/main.o build/x16/dos/file.o build/x16/dos/cmdch.o build/x16/dos/dir.o build/x16/dos/parser.o build/x16/dos/functions.o build/x16/dos/djsrfar.o -o build/x16/dos.bin -m build/x16/dos.map -Ln build/x16/dos.sym
Makefile:412: *** findsymbols failed with exit code 1.  Stop.
make: *** Waiting for unfinished jobs....
./scripts/relist.py build/x16/dos.map build/x16/dos

Copy link
Collaborator

@mooinglemur mooinglemur left a comment

Choose a reason for hiding this comment

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

Thanks! This definitely helps.

@mooinglemur mooinglemur merged commit 8efde2d into X16Community:master Dec 2, 2025
1 check failed
@claui claui deleted the findsymbols-guard-exit-code branch December 2, 2025 20:04
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.

2 participants