Hive Hive
Sign in

Test failed when using swift macros as external dependencies

GitHub issue · Open

Metadata
Source
tuist/tuist #7164
Updated
Jun 11, 2026
Domains
Generated projects
Details

What happened?

My app and modules have some swift macros as external dependencies. Everything works well when run through Xcode. But it failed when run by xcodebuild no matter on CI nodes or my machine.

How do we reproduce it?

  1. cd fixtures/multiplatform_app_with_macros_and_embedded_watchos_app \
    && tuist install \
    && tuist generate
  2. ⌘ + U in Xcode and it will build and test successfully

  3. Open terminal and run xcodebuild -workspace AppWithWatchApp.xcworkspace -scheme AppWithWatchApp-Workspace -configuration Debug -scmProvider system -disableAutomaticPackageResolution -sdk 'iphonesimulator' -destination 'platform=iOS Simulator,id=theUUIDofYourSimulator' -enableCodeCoverage YES -skipPackagePluginValidation -skipMacroValidation -retry-tests-on-failure -test-iterations 11 clean test

  4. The tests build failed with below errors: Multiple commands produce '/yourDerivedData/AppWithWatchApp-ddfnoigpczzvcocxhnuttxpcsxlc/Build/Products/Debug-iphonesimulator/CasePathsMacros'

    Multiple commands produce '/yourDerivedData/AppWithWatchApp-ddfnoigpczzvcocxhnuttxpcsxlc/Build/Products/Debug-iphonesimulator/ModuleAMacros'

  5. Same errors when changed to other swift macros such as MetaCodable and swift-composable-architecture

Error log

Multiple commands produce '/yourDerivedData/AppWithWatchApp-ddfnoigpczzvcocxhnuttxpcsxlc/Build/Products/Debug-iphonesimulator/CasePathsMacros'

Multiple commands produce '/yourDerivedData/AppWithWatchApp-ddfnoigpczzvcocxhnuttxpcsxlc/Build/Products/Debug-iphonesimulator/ModuleAMacros'

macOS version

14.6.1

Tuist version

4.37.0

Xcode version

15.4

Flights

Investigate, reproduce, or fix this item in an isolated repository. Each Flight preserves its outcome and agent session.

New Flights are paused Configure model inference, GitHub, and a sandbox provider to start another Flight. Existing results remain available below.
No Flights yet

Start a Flight and preserve its objective, outcome, and session here.

Comments
D
dosubot[bot] Dec 15, 2024

Hey @mo5tone! I’m here to help you with your software development issues and questions. Let’s tackle this bug together!

The “Multiple commands produce” error typically occurs when there are conflicting build settings or configurations that result in the same output file being generated by multiple build steps. Here are a few steps you can take to resolve this issue when using Swift macros as external dependencies:

  1. Check Build Phases: Ensure that the build phases in your Xcode project or workspace do not have duplicate entries for the same output files. This can happen if a macro or its dependencies are being built multiple times.

  2. Review Tuist Configuration: Make sure that your Tuist configuration does not inadvertently create duplicate targets or build settings that could lead to this conflict. This includes checking your Project.swift and any related configuration files for duplicate entries.

  3. Use Tuist Caching: Tuist offers a caching feature that can help mitigate build time issues and potentially resolve conflicts. You can use the tuist cache command to cache your Swift Macros and other dependencies, which might help in avoiding duplicate builds:

    tuist cache
  4. Derived Data Management: Clear your derived data to ensure there are no stale build artifacts causing conflicts. You can do this by running:

    rm -rf ~/Library/Developer/Xcode/DerivedData
  5. Xcode and xcodebuild Differences: Sometimes, Xcode and xcodebuild handle build settings differently. Ensure that any custom build settings or flags used in Xcode are also correctly applied in your xcodebuild command.

If these steps do not resolve the issue, you may need to further investigate the specific build settings and configurations in your project that could be causing the conflict.

To continue talking to Dosu, mention @dosu.


Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Other

M
mo5tone Dec 15, 2024

Same errors when try with Xcode 16.2 on macOS 14.6.1.

M
mo5tone Dec 15, 2024

After comparing with BuildAcceptanceTestMultiplatformAppWithMacrosAndEmbeddedWatchOSApp, I found removing -sdk 'iphonesimulator' make everyhing work well again. But I don’t know why 🤔

F
fortmarek Dec 16, 2024

I believe the issue is that you’re specifying an SDK for a multiplatform target. I’d be curious to know how xcodebuild command behaves when the macro is integrated with the default Xcode integration, instead of the XcodeProj-based one.

@pepicrft, do you have an idea why adding an SDK would make the issue fixed in https://github.com/tuist/tuist/pull/6109 reappear?

M
mo5tone Dec 17, 2024

I believe the issue is that you’re specifying an SDK for a multiplatform target.

My project only supports iOS which have one app target and a few static framework targets.

F
fortmarek Dec 17, 2024

My project only supports iOS which have one app target and a few static framework targets.

I see – macros are in the end macOS executables, so technically you are still compiling for multiple platforms even if your project itself is only building for iOS. I agree this is a problem solving – though, I don’t know how, yet 😅

E
escapeanaemia Mar 18, 2025

Any updates from here? I also have a same problem 👀

E
Engwar Dec 1, 2025

I have the same problem with two local frameworks which inslude macros

JB
jrcmramos-bumble Dec 15, 2025

We also faced the same problem here.

Just confirmed that this problem is reproducible on other iOS only fixture projects. Example

How to reproduce it:

xcodebuild -workspace App.xcworkspace -scheme App -configuration Debug -sdk 'iphonesimulator' -destination 'platform=iOS Simulator,id=DEVICE_ID' build-for-testing
S
shlykovdanylo Jan 18, 2026

We ran into the same issue recently, and after some debugging we concluded that the -sdk flag forces a specific SDK for all targets being built. Macro targets cannot be built with a non-macOS SDK, which leads to build failures.

When building for a simulator or a device, you don’t need to specify the SDK explicitly - just provide the destination and let xcodebuild determine the correct SDK for each target based on project configuration. For example, when you build inside Xcode, it uses the SDKs defined in the project configuration, and xcodebuild should behave the same way.

We removed the -sdk flag from all of our workflows, and everything works as before - now including macro targets.

E
elprl Jul 7, 2026

We hit a related failure mode of the same “Copy Swift Macro executable into $BUILT_PRODUCT_DIR” script phase and root-caused it, so posting here since #7570 was closed as stale and redirected to this issue. This is without the -sdk flag — our symptom is intermittent external macro implementation type ‘CasePathsMacros.CasePathableMacro’ could not be found … produced malformed response instead of “Multiple commands produce”.

Setup: Tuist 4.200.5, Xcode 26.5 (Swift 6.3.2), TCA 1.26.0, ~20 module projects in one workspace, custom configuration names (Develop/Staging/Live — no Debug). Single-module schemes always build clean; the full-app scheme failed on ~100% of clean builds with ~120 “malformed response” errors across every macro-consuming target.

Mechanism: Consumers compile with -load-plugin-executable $BUILD_DIR/Debug$EFFECTIVE_PLATFORM_NAME/CasePathsMacros#CasePathsMacros, i.e. the hardcoded-Debug location populated by the copy phase’s cp -f “$BUILD_DIR/$CONFIGURATION/CasePathsMacros” …. On a large parallel build, that cp -f races the macro target’s final link (CreateUniversalBinary). We caught it in the act on a failed clean build — the copy and the real product differed in the same build:

$BUILD_DIR/Develop/CasePathsMacros 81,863,296 bytes md5 a2a9bed9…
$BUILD_DIR/Debug-iphonesimulator/CasePathsMacros 81,404,888 bytes md5 60db1818…

swiftc then loads the torn/stale copy → “produced malformed response”. Small schemes don’t hit it because there are too few parallel consumers to open the race window; the aggregate build hits it almost every time. (Side note: the phase also emits a second output at Debug-$EFFECTIVE_PLATFORM_NAME, producing a bogus Debug–iphonesimulator/ directory — double dash — since EFFECTIVE_PLATFORM_NAME already includes the leading dash.)

Workaround (verified): stop loading the plugin from the copy. The macro’s real product at $BUILD_DIR/$CONFIGURATION/ already has an explicit target dependency from every consumer, so it’s guaranteed complete before consumers compile. We run this after every tuist generate:

# rewrite -load-plugin-executable to the real macro product path
find Projects Tuist/.build/tuist-derived/Projects -name project.pbxproj \
-exec perl -pi -e 's|\$BUILD_DIR/Debug\$EFFECTIVE_PLATFORM_NAME/([A-Za-z0-9_]+)#|\$BUILD_DIR/\$CONFIGURATION/$1#|g' {} +

We leave the copy phase itself in place so the editor/indexer (the reason for the Debug default, per the script’s comment) keeps working. Results: 4/4 clean full-app builds failed before; 2/2 clean builds pass after, and SwiftUI previews (which build with the scheme’s custom configuration, so $CONFIGURATION resolves correctly there too) render fine.

Suggested real fix: emit -load-plugin-executable $BUILD_DIR/$CONFIGURATION/# for compilation and keep the Debug-located copy only for the indexer — or make the copy atomic (cp to temp + mv) and declare the macro binary as a proper input so the build system orders it after the final link.

G
gmazzo Jul 9, 2026

Thanks @elprl! I was researching this issue we are having as well. Your research was very complete 💪 . I’ll try the workaround now, and hopefully a fix will come soon from Tuist people.

E
elprl Aug 6, 2026

Update: this may now be fixed upstream. #11825 (“fix(cli): use native Xcode macro dependencies”, merged 2026-07-14) removes the Copy Swift Macro executable into $BUILT_PRODUCT_DIR phase entirely.

@gmazzo before you adopt the workaround I posted above, just upgrade instead; it’s no longer needed.

Rather than copying the macro executable to a hardcoded Debug path and pointing every consumer at it via -load-plugin-executable, Tuist now models source-built macros the way Swift Build and SwiftPM do: producer targets advertise SWIFT_IMPLEMENTS_MACROS_FOR_MODULE_NAMES and are reached through real target-dependency edges, so Xcode derives the plugin path itself (precompiled/cached macros use SWIFT_LOAD_BINARY_MACROS). No copy, no hardcoded path, no injected compiler flags, which removes the mechanism behind both failure modes in this thread. There’s no cp left to race the macro’s link, and no duplicated output left to collide.