Xcode Circular Dependency Between Modules 'Core' and 'UserInterface'

I have an xcode workspace with two nested projects, and several custom carthage frameworks that build a dependency tree. Everything is laid out like:

.
├─ MainApp
│  └─ UserInterface.framework
├─ DataLayer.framework
└─ Core.framework

DataLayer and Core are built as stand alone frameworks (using carthage) and are linked to UserInterface and MainApp using the "Do Not Embed" option. DataLayer and Core are added to the Frameworks and Library section for UserInterface and MainApp, and the framework search paths include DataLayer and Core. There is a copy script inside the MainApp to move the frameworks to the BUILT_PRODUCTS_DIR.

DataLayer and Core also define custom module maps to include objc in the framework. The custom module maps look like:

framework module DataLayer {
    umbrella header "DataLayer.h"
    header "NSData+CommonCrypto.h"

    export *
    module * { export * }
}

Everything looks good, but I am getting this error when trying to build the main app:

<unknown>:0: error: circular dependency between modules 'Core' and 'UserInterface'
Stack dump:
0.
// Compile Command + Source Files
---
3.	While reading from 'DataLayer'
4.	While reading from 'Core'
0  swift                    0x000000010daf64ea PrintStackTraceSignalHandler(void*) + 42
1  swift                    0x000000010daf5cc0 SignalHandler(int) + 352
2  libsystem_platform.dylib 0x00007fff726c65fd _sigtramp + 29
3  libsystem_platform.dylib 0x00007fa91c080200 _sigtramp + 2845547552
4  swift                    0x000000010a90c4d6 swift::namelookup::ImportCache::getImportSet(swift::DeclContext const*) + 2614
5  swift                    0x000000010a63a33a swift::ClangImporter::Implementation::finishLoadingClangModule(clang::Module const*, bool) + 1066
6  swift                    0x000000010a64c608 swift::ClangImporter::Implementation::handleDeferredImports() + 520
7  swift                    0x000000010a64c03a swift::ClangImporter::Implementation::importHeader(swift::ModuleDecl*, llvm::StringRef, swift::SourceLoc, bool, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >, bool) + 2026
8  swift                    0x000000010a64d0b3 swift::ClangImporter::importBridgingHeader(llvm::StringRef, swift::ModuleDecl*, swift::SourceLoc, bool, bool) + 1075
9  swift                    0x000000010a64cad4 swift::ClangImporter::importHeader(llvm::StringRef, swift::ModuleDecl*, long long, long, llvm::StringRef, swift::SourceLoc) + 148
10 swift                    0x000000010a5f69ea swift::SerializedModuleLoaderBase::loadAST(swift::ModuleDecl&, llvm::Optional<swift::SourceLoc>, llvm::StringRef, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >, bool, bool) + 2298
11 swift                    0x000000010a5f4ca5 swift::SerializedModuleLoaderBase::loadModule(swift::SourceLoc, llvm::ArrayRef<std::__1::pair<swift::Identifier, swift::SourceLoc> >) + 581
12 swift                    0x000000010a540d14 swift::ModuleFile::getModule(llvm::ArrayRef<swift::Identifier>, bool) + 852
13 swift                    0x000000010a5f6baf swift::SerializedModuleLoaderBase::loadAST(swift::ModuleDecl&, llvm::Optional<swift::SourceLoc>, llvm::StringRef, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >, bool, bool) + 2751
14 swift                    0x000000010a5f4ca5 swift::SerializedModuleLoaderBase::loadModule(swift::SourceLoc, llvm::ArrayRef<std::__1::pair<swift::Identifier, swift::SourceLoc> >) + 581
15 swift                    0x000000010a6323a9 swift::ClangModuleUnit::getOverlayModule() const + 473
16 swift                    0x000000010a6350d7 swift::ClangModuleUnit::getImportedModulesForLookup(llvm::SmallVectorImpl<std::__1::pair<llvm::ArrayRef<std::__1::pair<swift::Identifier, swift::SourceLoc> >, swift::ModuleDecl*> >&) const + 247
17 swift                    0x000000010a90b7c1 collectExports(std::__1::pair<llvm::ArrayRef<std::__1::pair<swift::Identifier, swift::SourceLoc> >, swift::ModuleDecl*>, llvm::SmallVectorImpl<std::__1::pair<llvm::ArrayRef<std::__1::pair<swift::Identifier, swift::SourceLoc> >, swift::ModuleDecl*> >&) + 113
18 swift                    0x000000010a90c42a swift::namelookup::ImportCache::getImportSet(swift::DeclContext const*) + 2442
19 swift                    0x000000010a63a33a swift::ClangImporter::Implementation::finishLoadingClangModule(clang::Module const*, bool) + 1066
20 swift                    0x000000010a64c608 swift::ClangImporter::Implementation::handleDeferredImports() + 520
21 swift                    0x000000010a64c03a swift::ClangImporter::Implementation::importHeader(swift::ModuleDecl*, llvm::StringRef, swift::SourceLoc, bool, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >, bool) + 2026
22 swift                    0x000000010a64d0b3 swift::ClangImporter::importBridgingHeader(llvm::StringRef, swift::ModuleDecl*, swift::SourceLoc, bool, bool) + 1075
23 swift                    0x0000000109b520d4 swift::CompilerInstance::performSemaUpTo(swift::SourceFile::ASTStage_t) + 3108
24 swift                    0x000000010983ed99 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 10281
25 swift                    0x00000001097bff53 main + 1283
26 libdyld.dylib            0x00007fff724cdcc9 start + 1
27 libdyld.dylib            0x000000000000015c start + 2377327764
error: Segmentation fault: 11 (in target 'MainApp' from project 'MainApp')

There isn't a real circular dependency, but everything relied on Core. I know Core doesn't rely on UserInterface because it is built separately. Any help on how I could debug this would be greatly appreciated. I have been stuck on this for more hours then I'd like admit.

I've tried triple checking my configurations, and even relinking everything but that didn't help.

I also posted a similar question on stackoverflow, and someone pointed me to file a swift bug so I thought the swift forums might be a better place to ask for help.

Edit 1: I am able to build UserInterface on its own so there can't be a real cycle.

1 Like