Skip to content
Draft
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: 6 additions & 2 deletions templates/linux/cc_toolchain_flags.bzl.template
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,15 @@ OPT_COMPILE_FLAGS = get_flag_group([

# Default link flags when no specific build type is selected.
DEFAULT_LINK_FLAGS = get_flag_group([
"-Wl,-Bstatic",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AI-assisted review (Claude):

[Important] Duplicate C++ runtime linkage — no -nodefaultlibs in this toolchain

This toolchain uses cxx_binary (g++) as the link driver for all link actions, and nowhere in the Linux toolchain do the flags include -nodefaultlibs. Without that flag, g++ automatically appends its own default runtime libraries at the end of every link command — including -lstdc++, -lgcc, and -lgcc_eh.

The result is:

g++ -Wl,-Bstatic -lstdc++ -lgcc -lgcc_eh -Wl,-Bdynamic ... <user libs> ... -lstdc++ -lgcc [from driver, dynamic]

Static versions are linked early, dynamic versions are linked again at the end by the driver. That's dual runtime linkage: two copies of the C++ runtime with different linkage modes in the same binary, which can cause ODR violations, constructor double-invocation, or crashes.

The original -static-libstdc++ and -static-libgcc are precisely the GCC mechanism for avoiding this: they instruct the driver to substitute its own default runtime with the static versions when it appends them at the end — no duplication. They're not a workaround; they're the intended interface.

If the intent is to keep runtime libs static, the correct fix is to keep -static-libstdc++/-static-libgcc and address link order separately (see the second finding below).

"-lstdc++",
"-lgcc",
"-lgcc_eh",
"-Wl,-Bdynamic",
Comment on lines +89 to +93
"-lm",
"-ldl",
"-lrt",
"-static-libstdc++",
"-static-libgcc",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AI-assisted review (Claude):

[Important] This doesn't actually fix the link-order problem from issue #53

Issue #53 describes symbols from libgcc not being found because the static library graph is searched left-to-right and libgcc ends up too early, before user libs that reference it. These flags move libgcc to before -lm, -ldl, -lrt, and the user's static libraries — that's the same problem in reverse.

The flags here tell the linker:

static: libstdc++ libgcc libgcc_eh   →  then dynamic: lm, ldl, lrt, lc   →  then user objects

User objects (which reference __aarch64_ldadd4_acq_rel etc.) appear after libgcc in the link command, so the linker still won't pull those symbols when processing the later objects.

The real solution is link groups. Replace this with:

DEFAULT_LINK_FLAGS = get_flag_group([
    "-static-libstdc++",
    "-static-libgcc",
    "-Wl,--start-group",
    "-lm",
    "-ldl",
    "-lrt",
    "-lgcc",
    "-lgcc_eh",
    "-Wl,--end-group",
])

--start-group/--end-group causes the linker to repeatedly search the grouped archives until no new undefined symbols appear, which is exactly what the issue proposes as "Option 2" and is immune to ordering problems.

"-lc",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AI-assisted review (Claude):

[Suggestion] -lc is unnecessary and potentially harmful

libc is always linked dynamically by default when using g++ without -static or -nodefaultlibs. Adding -lc explicitly here will work in most cases but is redundant, and on some platforms or with some linker configurations can cause a conflict between the implicit libc pulled in by -lm/-ldl/-lrt and the explicit -lc position. It should be removed.

])

# Minimal set of warning flags to enable useful warnings without overwhelming the user.
Expand Down
Loading