Skip to content

fix: keep multi-target executables independent of sibling shared targets - #761

Merged
Sunrisepeak merged 3 commits into
mcpp-community:mainfrom
julixian:fix/workspace-self-contained-executables
Oct 5, 2026
Merged

Sunrisepeak merged 3 commits into
mcpp-community:mainfrom
julixian:fix/workspace-self-contained-executables

Conversation

@julixian

@julixian julixian commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

A package with both shared and bin targets must build each executable from its own implementation. Workspace-member planning instead omitted the owner's objects, while artifact planning could link the owner's sibling DLL through an unrelated consumer. A build-only request for a tool from such a package also left an empty shared-library target in the consuming plan.

Keep the owner's module and implementation objects in independently linked executables, and collect artifact shared links from that program's own dependency closure. Mark packages reached only through build-time edges and omit their shared products from the target plan. A provider also reached through a target-side edge retains its shared products.

Closes #760.

Criteria

  • E2E 880_a_members_executable_keeps_its_own_implementation.sh exercises a module interface, separate implementation unit, static dependency, external shared dependency, --workspace, and explicit member selection. The original case failed against freshly built, unmodified 6e3cb974 with undefined answer() and interface_value() symbols. It passes with the patch.
  • The extended artifact case failed against the original PR commit cc5234c: the shipped EXE depended on its sibling shared library. It now passes, including feature-gated artifact selection and --workspace. Every runtime placement of the sibling library is removed before running the executable; external consumers still require that shared library.
  • With only the artifact fix applied, the extended host-tool case built and executed the requested tool, then failed with target 'dual_dll' (shared library) has no inputs to link. It now passes. The test also adds a target-side dependency on that same provider, runs the consumer through its shared library, and verifies that the shared product exists.
  • The extended E2E 880 passes with a freshly bootstrapped patch binary on Windows x64 / LLVM 22.1.8. It declares no platform-only requirement; Linux and macOS execution of the extended cases is left to the updated CI run.
  • Fresh-binary E2E 00, 01, 836, and 872 pass on Windows. E2E 872 checks that changing workspace selections does not recompile shared compile units. GCC/ELF-specific host-tool and shared-image tests are left to their corresponding CI hosts.
  • Fresh-binary root tests: 144 test executables pass and unit/test_modgraph fails in Glob.EscapedSpellingIsUtf8WhateverTheName with a Windows code-page conversion exception. A clean, freshly built 6e3cb974 reproduces that same failure. This pre-existing failure is not changed by this PR.
  • An actual x64 AVPlayer package with shared and executable targets builds after removing its sibling import-library workaround. Its executable starts with that DLL moved away, and llvm-readobj --coff-imports confirms that the sibling DLL is absent; external FFmpeg and SDL dependencies remain.

Intersections

New rule or feature Invariant it crosses Test at the crossing
Independent executables retain their owner's objects Interface, implementation and static dependency objects reach the link E2E 880: workspace owner and shipped artifact
Shared links come from the program's own closure External shared dependencies remain, without importing the sibling image E2E 880: external support library and removal of every sibling DLL placement
Artifact requests activate their feature-gated target Workspace selection and artifact placement coexist E2E 880: -p shipped, requested feature, then --workspace
Host-only packages contribute no shared products to the consumer The requested host tool is still built and available through dep_bin E2E 880: build-only multi-target provider; build.mcpp executes the tool
A build-time edge does not subtract a target-side dependency A provider can be both a tool and a shared library E2E 880: dual-role provider supplies and runs both products
Link planning changes without duplicating compile units Compile commands remain stable across workspace selections Existing E2E 872

Compatibility

No manifest keys or defaults change. Executables belonging to a multi-target package link their own code, including when requested as artifacts or tools. Ordinary library consumers retain shared-library linkage. Build-only packages no longer create empty shared link units in the target build; a package also requested as a target dependency remains available. Automatic exports and LTO handling are unchanged.

Checks before merging

  • Documentation style, structure and version-pin checks pass locally. Move the Chinese README's CI badge outside its navigation table to match the English layout and correct the existing table-row mismatch. Windows checks use PYTHONUTF8=1.
  • python3 .github/tools/check_workflow_assertions.py passes (22 workflows, 0 problems).
  • Module wiring, narrow-conversion checks, E2E fixture path hygiene and git diff --check pass.
  • No commit carries an attribution trailer: git log origin/main..HEAD -i --grep='Co-Authored-By' prints nothing.
  • All applicable CI checks pass. The preceding revision passed platform builds and Linux/macOS E2E. Windows E2E 880 failed before compilation because native C:\Users\... in MCPP_HOME was not normalized before being written into TOML. The shared fixture helper now normalizes drive-absolute paths, and E2E 00 checks native and mixed Windows spelling plus relative-path preservation. E2E 880 passes locally with native Windows MCPP_HOME. The new CI run verifies commit 19637260; its results are pending.
  • A squash merge, if used, has an explicit subject and body. Suggested subject: fix: keep multi-target executables independent of sibling shared targets. Suggested body: Retain executable-owned objects and declared shared dependencies in workspace and artifact plans, omit host-only shared products from consumers, and cover artifact/tool and dual-role providers. Closes #760.

Retain a member's own module and implementation objects when it also produces a shared target. Keep declared external shared dependencies and test independent executable linkage with the sibling library removed.
@julixian julixian changed the title fix: keep workspace executables independent of sibling shared targets fix: keep multi-target executables independent of sibling shared targets Oct 4, 2026
@Sunrisepeak
Sunrisepeak merged commit c313c02 into mcpp-community:main Oct 5, 2026
51 checks passed
Sunrisepeak added a commit that referenced this pull request Oct 5, 2026
…ow-ups of #766 (#767)

mcpp run, mcpp run -q --release and the named runners now give the program the terminal. On POSIX mcpp replaces itself with the program once the build is done; on Windows the program runs in mcpp's console and process group while mcpp ignores Ctrl-C. A death by signal reaches the caller as that signal, and closing notices precede the Running line.

The follow-ups of #761, #763 and #765 recorded in #766: members and artifacts link the shared dependencies of the statics placed in their own image and not the objects of statics placed in another image; exports narrows discovered symbols on the MSVC ABI, with a warning beside source declarations and an error for an empty surface a program of the build links; auto_export is renamed windows_auto_export before its first release under SPEC-004 section 5.3; build-program glob inputs share the walk of sources globs, report unwatchable patterns, match absolute patterns and refuse patterns leaving a registry or git dependency; run_all.sh bounds each test where GNU timeout is absent.

SPEC-004 v1.11 and SPEC-009 v0.2. Closes #766.
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.

fix: workspace executables omit their own objects when the package also has a shared target

2 participants