Przeglądaj źródła

Merge topic 'refactor-module-def'

f36eaf6a Refactor WINDOWS_EXPORT_ALL_SYMBOLS implementation
25d261ef Refactor module definition file selection
1e0a9ac4 Refactor module definition source enumeration

Acked-by: Kitware Robot <[email protected]>
Merge-request: !570
Brad King 8 lat temu
rodzic
commit
abfc55a362

+ 4 - 11
Source/cmCommonTargetGenerator.cxx

@@ -26,7 +26,6 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
   , GlobalGenerator(static_cast<cmGlobalCommonGenerator*>(
       gt->LocalGenerator->GetGlobalGenerator()))
   , ConfigName(LocalGenerator->GetConfigName())
-  , ModuleDefinitionFile(GeneratorTarget->GetModuleDefinitionFile(ConfigName))
 {
 }
 
@@ -63,14 +62,9 @@ void cmCommonTargetGenerator::AddFeatureFlags(std::string& flags,
 void cmCommonTargetGenerator::AddModuleDefinitionFlag(
   cmLinkLineComputer* linkLineComputer, std::string& flags)
 {
-  // A module definition file only makes sense on certain target types.
-  if (this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY &&
-      this->GeneratorTarget->GetType() != cmStateEnums::MODULE_LIBRARY &&
-      this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE) {
-    return;
-  }
-
-  if (!this->ModuleDefinitionFile) {
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
+  if (!mdi || mdi->DefFile.empty()) {
     return;
   }
 
@@ -85,8 +79,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(
   // vs6's "cl -link" pass it to the linker.
   std::string flag = defFileFlag;
   flag += this->LocalGenerator->ConvertToOutputFormat(
-    linkLineComputer->ConvertToLinkReference(
-      this->ModuleDefinitionFile->GetFullPath()),
+    linkLineComputer->ConvertToLinkReference(mdi->DefFile),
     cmOutputConverter::SHELL);
   this->LocalGenerator->AppendFlags(flags, flag);
 }

+ 0 - 3
Source/cmCommonTargetGenerator.h

@@ -44,9 +44,6 @@ protected:
   cmGlobalCommonGenerator* GlobalGenerator;
   std::string ConfigName;
 
-  // The windows module definition source file (.def), if any.
-  cmSourceFile const* ModuleDefinitionFile;
-
   void AppendFortranFormatFlags(std::string& flags,
                                 cmSourceFile const& source);
 

+ 45 - 11
Source/cmGeneratorTarget.cxx

@@ -112,7 +112,7 @@ struct IDLSourcesTag
 struct ResxTag
 {
 };
-struct ModuleDefinitionFileTag
+struct ModuleDefinitionSourcesTag
 {
 };
 struct AppManifestTag
@@ -236,8 +236,8 @@ struct TagVisitor
     } else if (!sf->GetLanguage().empty()) {
       DoAccept<IsSameTag<Tag, ObjectSourcesTag>::Result>::Do(this->Data, sf);
     } else if (ext == "def") {
-      DoAccept<IsSameTag<Tag, ModuleDefinitionFileTag>::Result>::Do(this->Data,
-                                                                    sf);
+      DoAccept<IsSameTag<Tag, ModuleDefinitionSourcesTag>::Result>::Do(
+        this->Data, sf);
       if (this->IsObjLib) {
         this->BadObjLibFiles.push_back(sf);
       }
@@ -681,6 +681,12 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
   return it != this->ExplicitObjectName.end();
 }
 
+void cmGeneratorTarget::GetModuleDefinitionSources(
+  std::vector<cmSourceFile const*>& data, const std::string& config) const
+{
+  IMPLEMENT_VISIT(ModuleDefinitionSources);
+}
+
 void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile const*>& data,
                                       const std::string& config) const
 {
@@ -1938,17 +1944,45 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
   return &i->second;
 }
 
-cmSourceFile const* cmGeneratorTarget::GetModuleDefinitionFile(
-  const std::string& config) const
+cmGeneratorTarget::ModuleDefinitionInfo const*
+cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const
 {
-  std::vector<cmSourceFile const*> data;
-  IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile,
-                       COMMA std::vector<cmSourceFile const*>)
-  if (!data.empty()) {
-    return data.front();
+  // A module definition file only makes sense on certain target types.
+  if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+      this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+      !this->IsExecutableWithExports()) {
+    return CM_NULLPTR;
   }
 
-  return CM_NULLPTR;
+  // Lookup/compute/cache the compile information for this configuration.
+  std::string config_upper;
+  if (!config.empty()) {
+    config_upper = cmSystemTools::UpperCase(config);
+  }
+  ModuleDefinitionInfoMapType::const_iterator i =
+    this->ModuleDefinitionInfoMap.find(config_upper);
+  if (i == this->ModuleDefinitionInfoMap.end()) {
+    ModuleDefinitionInfo info;
+    this->ComputeModuleDefinitionInfo(config, info);
+    ModuleDefinitionInfoMapType::value_type entry(config_upper, info);
+    i = this->ModuleDefinitionInfoMap.insert(entry).first;
+  }
+  return &i->second;
+}
+
+void cmGeneratorTarget::ComputeModuleDefinitionInfo(
+  std::string const& config, ModuleDefinitionInfo& info) const
+{
+  std::vector<cmSourceFile const*> sources;
+  this->GetModuleDefinitionSources(sources, config);
+  info.WindowsExportAllSymbols =
+    this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
+    this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
+  if (info.WindowsExportAllSymbols) {
+    info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
+  } else if (!sources.empty()) {
+    info.DefFile = sources.front()->GetFullPath();
+  }
 }
 
 bool cmGeneratorTarget::IsDLLPlatform() const

+ 15 - 1
Source/cmGeneratorTarget.h

@@ -77,6 +77,8 @@ public:
   bool HasExplicitObjectName(cmSourceFile const* file) const;
   void AddExplicitObjectName(cmSourceFile const* sf);
 
+  void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&,
+                                  const std::string& config) const;
   void GetResxSources(std::vector<cmSourceFile const*>&,
                       const std::string& config) const;
   void GetIDLSources(std::vector<cmSourceFile const*>&,
@@ -233,7 +235,13 @@ public:
   cmLocalGenerator* LocalGenerator;
   cmGlobalGenerator const* GlobalGenerator;
 
-  cmSourceFile const* GetModuleDefinitionFile(const std::string& config) const;
+  struct ModuleDefinitionInfo
+  {
+    std::string DefFile;
+    bool WindowsExportAllSymbols;
+  };
+  ModuleDefinitionInfo const* GetModuleDefinitionInfo(
+    std::string const& config) const;
 
   /** Return whether or not the target is for a DLL platform.  */
   bool IsDLLPlatform() const;
@@ -721,6 +729,12 @@ private:
   typedef std::map<std::string, OutputInfo> OutputInfoMapType;
   mutable OutputInfoMapType OutputInfoMap;
 
+  typedef std::map<std::string, ModuleDefinitionInfo>
+    ModuleDefinitionInfoMapType;
+  mutable ModuleDefinitionInfoMapType ModuleDefinitionInfoMap;
+  void ComputeModuleDefinitionInfo(std::string const& config,
+                                   ModuleDefinitionInfo& info) const;
+
   typedef std::pair<std::string, bool> OutputNameKey;
   typedef std::map<OutputNameKey, std::string> OutputNameMapType;
   mutable OutputNameMapType OutputNameMap;

+ 8 - 4
Source/cmGlobalVisualStudioGenerator.cxx

@@ -814,10 +814,14 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
   cmGeneratorTarget* gt, std::vector<cmCustomCommand>& commands,
   std::string const& configName)
 {
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    gt->GetModuleDefinitionInfo(configName);
+  if (!mdi || !mdi->WindowsExportAllSymbols) {
+    return;
+  }
+
   std::vector<std::string> outputs;
-  std::string deffile = gt->ObjectDirectory;
-  deffile += "/exportall.def";
-  outputs.push_back(deffile);
+  outputs.push_back(mdi->DefFile);
   std::vector<std::string> empty;
   std::vector<cmSourceFile const*> objectSources;
   gt->GetObjectSources(objectSources, configName);
@@ -835,7 +839,7 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
   cmdl.push_back(cmakeCommand);
   cmdl.push_back("-E");
   cmdl.push_back("__create_def");
-  cmdl.push_back(deffile);
+  cmdl.push_back(mdi->DefFile);
   std::string obj_dir_expanded = obj_dir;
   cmSystemTools::ReplaceString(obj_dir_expanded, this->GetCMakeCFGIntDir(),
                                configName.c_str());

+ 14 - 25
Source/cmLocalVisualStudio7Generator.cxx

@@ -996,19 +996,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
   linkOptions.AddTable(cmLocalVisualStudio7GeneratorLinkFlagTable);
 
   linkOptions.Parse(extraLinkOptions.c_str());
-  if (!this->ModuleDefinitionFile.empty()) {
-    std::string defFile = this->ConvertToOutputFormat(
-      this->ModuleDefinitionFile, cmOutputConverter::SHELL);
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    target->GetModuleDefinitionInfo(configName);
+  if (mdi && !mdi->DefFile.empty()) {
+    std::string defFile =
+      this->ConvertToOutputFormat(mdi->DefFile, cmOutputConverter::SHELL);
     linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
   }
 
-  if ((target->GetType() == cmStateEnums::SHARED_LIBRARY ||
-       target->IsExecutableWithExports()) &&
-      this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)/exportall.def");
-    }
-  }
   switch (target->GetType()) {
     case cmStateEnums::UNKNOWN_LIBRARY:
       break;
@@ -1362,7 +1357,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
 
   // get the classes from the source lists then add them to the groups
-  this->ModuleDefinitionFile = "";
   std::vector<cmSourceFile*> classes;
   if (!target->GetConfigCommonSourceFiles(classes)) {
     return;
@@ -1374,9 +1368,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
     }
     // Add the file to the list of sources.
     std::string source = (*i)->GetFullPath();
-    if (cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF") {
-      this->ModuleDefinitionFile = (*i)->GetFullPath();
-    }
     cmSourceGroup* sourceGroup =
       this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
     sourceGroup->AssignSource(*i);
@@ -1825,17 +1816,15 @@ void cmLocalVisualStudio7Generator::OutputTargetRules(
   tool = this->FortranProject ? "VFPreLinkEventTool" : "VCPreLinkEventTool";
   event.Start(tool);
   bool addedPrelink = false;
-  if ((target->GetType() == cmStateEnums::SHARED_LIBRARY ||
-       target->IsExecutableWithExports()) &&
-      this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      addedPrelink = true;
-      std::vector<cmCustomCommand> commands = target->GetPreLinkCommands();
-      cmGlobalVisualStudioGenerator* gg =
-        static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
-      gg->AddSymbolExportCommand(target, commands, configName);
-      event.Write(commands);
-    }
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    target->GetModuleDefinitionInfo(configName);
+  if (mdi && mdi->WindowsExportAllSymbols) {
+    addedPrelink = true;
+    std::vector<cmCustomCommand> commands = target->GetPreLinkCommands();
+    cmGlobalVisualStudioGenerator* gg =
+      static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
+    gg->AddSymbolExportCommand(target, commands, configName);
+    event.Write(commands);
   }
   if (!addedPrelink) {
     event.Write(target->GetPreLinkCommands());

+ 0 - 1
Source/cmLocalVisualStudio7Generator.h

@@ -128,7 +128,6 @@ private:
 
   friend class EventWriter;
 
-  std::string ModuleDefinitionFile;
   bool FortranProject;
   bool WindowsCEProject;
   cmLocalVisualStudio7GeneratorInternals* Internal;

+ 1 - 4
Source/cmMakefileExecutableTargetGenerator.cxx

@@ -556,10 +556,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     }
 
     // maybe create .def file from list of objects
-    if (this->GeneratorTarget->IsExecutableWithExports() &&
-        this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      this->GenDefFile(real_link_commands, linkFlags);
-    }
+    this->GenDefFile(real_link_commands);
 
     std::string manifests = this->GetManifests();
 

+ 1 - 4
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -750,10 +750,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     }
 
     // maybe create .def file from list of objects
-    if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY &&
-        this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      this->GenDefFile(real_link_commands, linkFlags);
-    }
+    this->GenDefFile(real_link_commands);
 
     std::string manifests = this->GetManifests();
 

+ 35 - 43
Source/cmMakefileTargetGenerator.cxx

@@ -1414,8 +1414,10 @@ void cmMakefileTargetGenerator::AppendLinkDepends(
   this->AppendTargetDepends(depends);
 
   // Add a dependency on the link definitions file, if any.
-  if (this->ModuleDefinitionFile) {
-    depends.push_back(this->ModuleDefinitionFile->GetFullPath());
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
+  if (mdi && !mdi->WindowsExportAllSymbols && !mdi->DefFile.empty()) {
+    depends.push_back(mdi->DefFile);
   }
 
   // Add a dependency on user-specified manifest files, if any.
@@ -1718,49 +1720,39 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
 }
 
 void cmMakefileTargetGenerator::GenDefFile(
-  std::vector<std::string>& real_link_commands, std::string& linkFlags)
+  std::vector<std::string>& real_link_commands)
 {
-  if (this->GeneratorTarget->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    std::string name_of_def_file =
-      this->GeneratorTarget->GetSupportDirectory();
-    name_of_def_file += std::string("/") + this->GeneratorTarget->GetName();
-    name_of_def_file += ".def";
-    std::string cmd = cmSystemTools::GetCMakeCommand();
-    cmd = this->LocalGenerator->ConvertToOutputFormat(
-      cmd, cmOutputConverter::SHELL);
-    cmd += " -E __create_def ";
-    cmd += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file),
-      cmOutputConverter::SHELL);
-    cmd += " ";
-    std::string objlist_file = name_of_def_file;
-    objlist_file += ".objs";
-    cmd += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
-      cmOutputConverter::SHELL);
-    real_link_commands.insert(real_link_commands.begin(), cmd);
-    // create a list of obj files for the -E __create_def to read
-    cmGeneratedFileStream fout(objlist_file.c_str());
-    for (std::vector<std::string>::const_iterator i = this->Objects.begin();
-         i != this->Objects.end(); ++i) {
-      if (cmHasLiteralSuffix(*i, ".obj")) {
-        fout << *i << "\n";
-      }
-    }
-    for (std::vector<std::string>::const_iterator i =
-           this->ExternalObjects.begin();
-         i != this->ExternalObjects.end(); ++i) {
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
+  if (!mdi || !mdi->WindowsExportAllSymbols) {
+    return;
+  }
+  std::string cmd = cmSystemTools::GetCMakeCommand();
+  cmd =
+    this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL);
+  cmd += " -E __create_def ";
+  cmd += this->LocalGenerator->ConvertToOutputFormat(
+    this->LocalGenerator->MaybeConvertToRelativePath(
+      this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile),
+    cmOutputConverter::SHELL);
+  cmd += " ";
+  std::string objlist_file = mdi->DefFile + ".objs";
+  cmd += this->LocalGenerator->ConvertToOutputFormat(
+    this->LocalGenerator->MaybeConvertToRelativePath(
+      this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
+    cmOutputConverter::SHELL);
+  real_link_commands.insert(real_link_commands.begin(), cmd);
+  // create a list of obj files for the -E __create_def to read
+  cmGeneratedFileStream fout(objlist_file.c_str());
+  for (std::vector<std::string>::const_iterator i = this->Objects.begin();
+       i != this->Objects.end(); ++i) {
+    if (cmHasLiteralSuffix(*i, ".obj")) {
       fout << *i << "\n";
     }
-    // now add the def file link flag
-    linkFlags += " ";
-    linkFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
-    linkFlags += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file),
-      cmOutputConverter::SHELL);
-    linkFlags += " ";
+  }
+  for (std::vector<std::string>::const_iterator i =
+         this->ExternalObjects.begin();
+       i != this->ExternalObjects.end(); ++i) {
+    fout << *i << "\n";
   }
 }

+ 1 - 2
Source/cmMakefileTargetGenerator.h

@@ -166,8 +166,7 @@ protected:
                          bool useWatcomQuote);
 
   /** Add commands for generate def files */
-  void GenDefFile(std::vector<std::string>& real_link_commands,
-                  std::string& linkFlags);
+  void GenDefFile(std::vector<std::string>& real_link_commands);
 
   void AddIncludeFlags(std::string& flags,
                        const std::string& lang) CM_OVERRIDE;

+ 21 - 40
Source/cmNinjaNormalTargetGenerator.cxx

@@ -860,19 +860,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"],
     vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget);
 
-  if (this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
-      (gt.GetType() == cmStateEnums::SHARED_LIBRARY ||
-       gt.IsExecutableWithExports())) {
-    if (gt.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      std::string name_of_def_file = gt.GetSupportDirectory();
-      name_of_def_file += "/" + gt.GetName();
-      name_of_def_file += ".def ";
-      vars["LINK_FLAGS"] += " /DEF:";
-      vars["LINK_FLAGS"] += this->GetLocalGenerator()->ConvertToOutputFormat(
-        name_of_def_file, cmOutputConverter::SHELL);
-    }
-  }
-
   // Add OS X version flags, if any.
   if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
       this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
@@ -989,33 +976,27 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   }
 
   // maybe create .def file from list of objects
-  if ((gt.GetType() == cmStateEnums::SHARED_LIBRARY ||
-       gt.IsExecutableWithExports()) &&
-      this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (gt.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      std::string cmakeCommand =
-        this->GetLocalGenerator()->ConvertToOutputFormat(
-          cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
-      std::string name_of_def_file = gt.GetSupportDirectory();
-      name_of_def_file += "/" + gt.GetName();
-      name_of_def_file += ".def";
-      std::string cmd = cmakeCommand;
-      cmd += " -E __create_def ";
-      cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
-        name_of_def_file, cmOutputConverter::SHELL);
-      cmd += " ";
-      cmNinjaDeps objs = this->GetObjects();
-      std::string obj_list_file = name_of_def_file;
-      obj_list_file += ".objs";
-      cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
-        obj_list_file, cmOutputConverter::SHELL);
-      preLinkCmdLines.push_back(cmd);
-      // create a list of obj files for the -E __create_def to read
-      cmGeneratedFileStream fout(obj_list_file.c_str());
-      for (cmNinjaDeps::iterator i = objs.begin(); i != objs.end(); ++i) {
-        if (cmHasLiteralSuffix(*i, ".obj")) {
-          fout << *i << "\n";
-        }
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    gt.GetModuleDefinitionInfo(this->GetConfigName());
+  if (mdi && mdi->WindowsExportAllSymbols) {
+    std::string cmakeCommand =
+      this->GetLocalGenerator()->ConvertToOutputFormat(
+        cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
+    std::string cmd = cmakeCommand;
+    cmd += " -E __create_def ";
+    cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
+      mdi->DefFile, cmOutputConverter::SHELL);
+    cmd += " ";
+    cmNinjaDeps objs = this->GetObjects();
+    std::string obj_list_file = mdi->DefFile + ".objs";
+    cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
+      obj_list_file, cmOutputConverter::SHELL);
+    preLinkCmdLines.push_back(cmd);
+    // create a list of obj files for the -E __create_def to read
+    cmGeneratedFileStream fout(obj_list_file.c_str());
+    for (cmNinjaDeps::iterator i = objs.begin(); i != objs.end(); ++i) {
+      if (cmHasLiteralSuffix(*i, ".obj")) {
+        fout << *i << "\n";
       }
     }
   }

+ 4 - 3
Source/cmNinjaTargetGenerator.cxx

@@ -212,9 +212,10 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
   std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
 
   // Add a dependency on the link definitions file, if any.
-  if (this->ModuleDefinitionFile) {
-    result.push_back(
-      this->ConvertToNinjaPath(this->ModuleDefinitionFile->GetFullPath()));
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
+  if (mdi && !mdi->WindowsExportAllSymbols && !mdi->DefFile.empty()) {
+    result.push_back(this->ConvertToNinjaPath(mdi->DefFile));
   }
 
   // Add a dependency on user-specified manifest files, if any.

+ 16 - 29
Source/cmVisualStudio10TargetGenerator.cxx

@@ -1841,10 +1841,9 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
     (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\" />\n";
   }
 
-  if (cmSourceFile const* defsrc =
-        this->GeneratorTarget->GetModuleDefinitionFile("")) {
-    this->WriteSource("None", defsrc);
-  }
+  std::vector<cmSourceFile const*> defSources;
+  this->GeneratorTarget->GetModuleDefinitionSources(defSources, "");
+  this->WriteSources("None", defSources);
 
   if (this->IsMissingFiles) {
     this->WriteMissingFiles();
@@ -2915,24 +2914,15 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
   linkOptions.Parse(flags.c_str());
 
   if (this->MSTools) {
-    if (cmSourceFile const* defsrc =
-          this->GeneratorTarget->GetModuleDefinitionFile("")) {
-      linkOptions.AddFlag("ModuleDefinitionFile",
-                          defsrc->GetFullPath().c_str());
+    cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+      this->GeneratorTarget->GetModuleDefinitionInfo(config);
+    if (mdi && !mdi->DefFile.empty()) {
+      linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile.c_str());
     }
     linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
                            "%(IgnoreSpecificDefaultLibraries)");
   }
 
-  if ((this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
-       this->GeneratorTarget->IsExecutableWithExports()) &&
-      this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (this->GeneratorTarget->GetPropertyAsBool(
-          "WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)exportall.def");
-    }
-  }
-
   // Hack to fix flag version selection in a common use case.
   // FIXME: Select flag table based on toolset instead of VS version.
   if (this->LocalGenerator->GetVersion() >=
@@ -3170,18 +3160,15 @@ void cmVisualStudio10TargetGenerator::WriteEvents(
   std::string const& configName)
 {
   bool addedPrelink = false;
-  if ((this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
-       this->GeneratorTarget->IsExecutableWithExports()) &&
-      this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (this->GeneratorTarget->GetPropertyAsBool(
-          "WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      addedPrelink = true;
-      std::vector<cmCustomCommand> commands =
-        this->GeneratorTarget->GetPreLinkCommands();
-      this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
-                                                    commands, configName);
-      this->WriteEvent("PreLinkEvent", commands, configName);
-    }
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    this->GeneratorTarget->GetModuleDefinitionInfo(configName);
+  if (mdi && mdi->WindowsExportAllSymbols) {
+    addedPrelink = true;
+    std::vector<cmCustomCommand> commands =
+      this->GeneratorTarget->GetPreLinkCommands();
+    this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
+                                                  commands, configName);
+    this->WriteEvent("PreLinkEvent", commands, configName);
   }
   if (!addedPrelink) {
     this->WriteEvent("PreLinkEvent",