Question or problem
I have an SPM package that compiles C code and includes it as a dependency in my iOS app via Tuist. When building with tuist build, I get compilation errors in system headers (dns_sd.h and xpc/connection.h) that should never fail to parse.
Error Messages:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/dns_sd.h:207:30: expected parameter declarator
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/dns_sd.h:207:30: expected ')'
...
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/dns_sd.h:207:74: expected function body after function declarator
The problematic line 207 in dns_sd.h:
} DNS_SD_API_AVAILABLE(macos(12.0), ios(15.0), tvos(15.0), watchos(8.0)) DNSServiceAAAAPolicy;
This line uses Apple’s availability attribute macros. The error suggests these macros are being disrupted by something in my C library during Xcode’s module compilation.
Expectation
I expect that building my iOS app with tuist build should work the same way as swift build does when using the same SPM dependency. System headers like dns_sd.h should parse correctly regardless of which C library I link.
Key observation:
swift build(SPM directly): Works perfectly
tuist build(Xcode project generated by Tuist): Fails with dns_sd.h parsing errors
This suggests that Tuist or the generated Xcode project is handling module compilation differently, causing my C library’s headers/macros to pollute the global namespace and break system headers.
Context
Tuist version: 4.79.7
Xcode version: 26.0.1 (Build 17A400)
Platform: iOS 16.0+
Swift Tools Version: 5.9
I’m building an iOS app that depends on an SPM package containing a large C codebase (~400 C source files). The SPM package compiles fine with swift build, but when I integrate it into my app via Tuist and run tuist build, the build fails with parsing errors in system headers.
My SPM Package Structure:
MyPackage/
├── Package.swift
├── Sources/
│ └── NetworkLib/
│ ├── lib-ios-config/
│ │ ├── config.h # Custom config header (~250 #defines)
│ │ └── src/ # ~400 C source files
│ │ ├── core/
│ │ ├── feature/
│ │ ├── lib/
│ │ └── ext/
│ └── include/
└── output/
├── openssl/ # Vendored OpenSSL (static lib)
├── libevent/ # Vendored libevent (static lib)
└── xz/ # Vendored XZ (static lib)
Simplified Package.swift:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyPackage",
platforms: [.iOS(.v16)],
products: [
.library(name: "MyPackage", type: .static, targets: ["NetworkLib"])
],
targets: [
// Vendored dependencies with dummy.c files
.target(
name: "COpenSSL",
path: "output/openssl",
sources: ["dummy.c"],
cSettings: [.headerSearchPath("include")],
linkerSettings: [.unsafeFlags(["-Loutput/openssl/lib", "-lssl", "-lcrypto"])]
),
// Similar for CLibevent and CXZ...
// Main C library target
.target(
name: "NetworkLib",
dependencies: ["COpenSSL", "CLibevent", "CXZ"],
path: "Sources/NetworkLib",
exclude: [/* ~60 exclusions for tests, docs, NSS files */],
cSettings: [
.headerSearchPath("lib-ios-config"),
.headerSearchPath("lib-ios-config/src"),
// ... ~20 more header search paths
.define("HAVE_CONFIG_H"),
.define("ENABLE_OPENSSL", to: "1"),
// ... ~50 more defines
.unsafeFlags(["-w", "-fno-modules", "-fno-objc-arc"])
],
linkerSettings: [
.linkedLibrary("z"),
.linkedLibrary("resolv")
]
)
]
)
App’s Dependencies.swift (Tuist):
import ProjectDescription
let dependencies = Dependencies(
swiftPackageManager: SwiftPackageManagerDependencies(
[
.remote(
url: "https://github.com/user/MyPackage.git",
requirement: .exact("1.0.98")
)
],
productTypes: [
"MyPackage": .staticLibrary // Also tried .framework
]
)
)
What I’ve tried:
Changed product type to .staticin Package.swift
Removed TUIST conditional compilation block
Added -fno-modulesand-fno-objc-arcflags
Removed @import MyPackagefrom bridging header
Verified that my C headers don’t directly define ios,macos,tvos, orwatchos
Tested with standalone swift build– works perfectly!
Additional notes:
- My C library’s
config.hhas ~250 platform-specific#definestatements - Manual test with
clangincluding bothconfig.handdns_sd.hcompiles successfully - This issue only appears in Tuist-generated Xcode projects, not with SPM directly
Reproduction (mandatory for problems)
Steps to Reproduce
- Create an SPM package with a C library target (~400 C files, ~250 #defines in config header)
- Add vendored static libraries (OpenSSL, libevent, XZ) as targets with dummy.c sources
- Configure the main target with multiple header search paths and preprocessor defines
- Create an iOS app project using Tuist
- Add the SPM package as a dependency in
Dependencies.swift - Run
tuist installandtuist generate - Run
tuist build --configuration Debug --platform iOS
Expected Result
Build succeeds, just like it does with swift build --triple arm64-apple-ios16.0-simulator
Actual Result
Build fails with parsing errors in system headers:
dns_sd.h:207:30: expected parameter declarator
dns_sd.h:207:74: expected function body after function declarator
Minimal Reproduction
I can test with a minimal project if needed. The key components are:
- Large C codebase with custom config header (many #defines)
- Vendored static libraries as SPM targets
- Integration via Tuist’s SwiftPackageManagerDependencies
Logs
Build log shows the errors occur during compilation of the NetworkLib target in the Tuist-generated Xcode project. The same code compiles successfully when built directly with SPM.
Question
How can I properly isolate my C library’s headers/macros in a Tuist-generated Xcode project to prevent them from polluting the global namespace and breaking system headers?
Is there a Tuist-specific configuration I’m missing, or is this a potential bug in how Tuist handles C library dependencies?