Skip to content

fix: 외부 SPM 혼합 링킹 정합 — objc 중복 클래스 해소 및 검증 자동화 #18

Description

@alice9547

현상

디바이스에서 Example 앱 실행 시 objc 경고 다수 — Class _TtC12Dependencies12CachedValues is implemented in both …ComposableArchitecture.framework… and …FeatureCommonExample.debug.dylib. Dependencies·Sharing·PerceptionCore·SwiftNavigation 등 TCA 하위 모듈 전반.

원인 — 혼합 링킹

Tuist/Package.swift 가 TCA 만 .framework(dynamic) 매핑, 하위 SPM 은 Tuist 기본(static) → static 산물이 ① TCA dylib 안에 1벌 흡수 + ② composition root 의 -all_load(D4, Target+Templates.swift)가 앱 바이너리에 또 1벌 적재. 의존성 캐시(CachedValues) 이중화 → withDependencies 오버라이드 침묵 무효화 위험.

해결 — 모드 내 완전 통일 (dev 전부 dynamic / release·CI 전부 static)

  • Tuist/Package.swift: TUIST_PRODUCT_TYPE 미설정(dev) → 아래 18개 전부 .framework, static-library[:]. ProjectDescription.Environment.productType 으로 읽기 (⚠️ Product·Environment 는 PackageDescription 과 모호 — ProjectDescription. 한정자 필수)
  • dynamic 매핑 18개 (= Tuist/.build/checkouts/*/Package.swift.library 전수, macro·swift-syntax·TestSupport 제외): ComposableArchitecture, CasePaths, CasePathsCore, Clocks, CombineSchedulers, ConcurrencyExtras, CustomDump, Dependencies, IdentifiedCollections, IssueReporting, OrderedCollections, Perception, PerceptionCore, Sharing, SwiftNavigation, SwiftUINavigation, UIKitNavigation, XCTestDynamicOverlay
  • Target+Templates.swift: -all_loadproductType == .staticLibrary 일 때만 적용 (dynamic 에선 불필요 + 중복 증폭기)
  • Scripts/check-linking.sh + make check-linking: dynamic → 앱 debug.dylib 에 embed 프레임워크 모듈 심볼(_$s<len><Module>) 정의되면 실패 / static → Frameworks 없음 + 13DependencyKey 정의 존재(D4). ⚠️ grep -q 금지(SIGPIPE+pipefail 오탐) → grep -c … || true. ⚠️ Debug 빌드 전제(Release 는 strip 으로 오판). 보강: 프레임워크 간 교차 중복(누락 타겟이 프레임워크 2곳에 흡수)도 검출할 것
  • CI(GitHub Actions): Tuist/Package.swift·Package.resolved 변경 PR 에서 두 모드 모두 검사. ⚠️ CI 전역 env 에 TUIST_PRODUCT_TYPE 금지 — 검사가 static 으로 오염되면 목록 검증 무력화 (아카이브 잡만 static)
  • 문서: architecture.md 에 D6 결정 기록, CLAUDE.md 에 "외부 SPM 버전업·추가·제거 시 목록 최신화 + check-linking" 규칙, lat check 통과

검증 (시뮬레이터 부팅 없이, 격리 -derivedDataPath 사용)

make generate && make check-linking → 중복 임베드 0 확인 → TUIST_PRODUCT_TYPE=static-library tuist generate --no-open && Scripts/check-linking.sh → D4 통과 확인 → make generate 로 dev(dynamic) 복귀

유지 시 주의

매핑은 수동 전수 목록 — TCA 버전업이 하위 타겟을 추가하면 빌드 에러 없이 혼합이 재발한다(런타임 콘솔 경고가 유일한 증상). SPM 을 만지는 PR 은 check-linking 필수.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions