]> granicus.if.org Git - clang/commitdiff
Infer "link" lines for top-level frameworks. Essentially, a framework
authorDouglas Gregor <dgregor@apple.com>
Mon, 14 Jan 2013 17:57:51 +0000 (17:57 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 14 Jan 2013 17:57:51 +0000 (17:57 +0000)
will have a shared library with the same name as its framework (and no
suffix!) within its .framework directory. Detect this both when
inferring the whole top-level framework and when parsing a module map.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172439 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Module.h
lib/Lex/ModuleMap.cpp
test/Modules/Inputs/Module.framework/Module [new file with mode: 0644]
test/Modules/Inputs/NoUmbrella.framework/NoUmbrella [new file with mode: 0644]
test/Modules/autolink.m

index 2bda801d188dc33a5b09c17e5c3abe65ad9b3e3f..6264c2db7b2ae2cb9162009fe088af06ac46ab4d 100644 (file)
@@ -237,7 +237,13 @@ public:
     
     return false;
   }
-  
+
+  /// \brief Determine whether this module is a subframework of another
+  /// framework.
+  bool isSubFramework() const {
+    return IsFramework && Parent && Parent->isPartOfFramework();
+  }
+
   /// \brief Retrieve the full name of this module, including the path from
   /// its top-level module.
   std::string getFullModuleName() const;
index 6b0eb79a10a3f42058b0eb18c104b2346ac838a6..72e79511eeb1539946fc012e9ca0086a97988242 100644 (file)
@@ -383,6 +383,23 @@ bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
   return canInfer;
 }
 
+/// \brief For a framework module, infer the framework against which we
+/// should link.
+static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
+                               FileManager &FileMgr) {
+  assert(Mod->IsFramework && "Can only infer linking for framework modules");
+  assert(!Mod->isSubFramework() &&
+         "Can only infer linking for top-level frameworks");
+
+  SmallString<128> LibName;
+  LibName += FrameworkDir->getName();
+  llvm::sys::path::append(LibName, Mod->Name);
+  if (FileMgr.getFile(LibName)) {
+    Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
+                                                     /*IsFramework=*/true));
+  }
+}
+
 Module *
 ModuleMap::inferFrameworkModule(StringRef ModuleName,
                                 const DirectoryEntry *FrameworkDir,
@@ -537,6 +554,12 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
     }
   }
 
+  // If the module is a top-level framework, automatically link against the
+  // framework.
+  if (!Result->isSubFramework()) {
+    inferFrameworkLink(Result, FrameworkDir, FileMgr);
+  }
+
   return Result;
 }
 
@@ -1147,6 +1170,13 @@ void ModuleMapParser::parseModuleDecl() {
     HadError = true;
   }
 
+  // If the active module is a top-level framework, and there are no link
+  // libraries, automatically link against the framework.
+  if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
+      ActiveModule->LinkLibraries.empty()) {
+    inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
+  }
+
   // We're done parsing this module. Pop back to the previous module.
   ActiveModule = PreviousActiveModule;
 }
diff --git a/test/Modules/Inputs/Module.framework/Module b/test/Modules/Inputs/Module.framework/Module
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Modules/Inputs/NoUmbrella.framework/NoUmbrella b/test/Modules/Inputs/NoUmbrella.framework/NoUmbrella
new file mode 100644 (file)
index 0000000..e69de29
index e4db6991fca1275f04e2510fd3543d14ace21215..3c6998f7bf3c6314d19f5293f42a407d3ef594eb 100644 (file)
@@ -13,6 +13,18 @@ int g() {
   return autolink;
 }
 
-// CHECK: !llvm.link.libraries = !{![[AUTOLINK:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]]}
+@import Module.SubFramework;
+const char *get_module_subframework() {
+  return module_subframework;
+}
+
+@import NoUmbrella;
+int use_no_umbrella() {
+  return no_umbrella_A;
+}
+
+// CHECK: !llvm.link.libraries = !{![[AUTOLINK:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]], ![[MODULE:[0-9]+]], ![[NOUMBRELLA:[0-9]+]]}
 // CHECK: ![[AUTOLINK]] = metadata !{metadata !"autolink", i1 false}
 // CHECK: ![[AUTOLINK_FRAMEWORK]] = metadata !{metadata !"autolink_framework", i1 true}
+// CHECK: ![[MODULE]] = metadata !{metadata !"Module", i1 true}
+// CHECK: ![[NOUMBRELLA]] = metadata !{metadata !"NoUmbrella", i1 true}