diff --git a/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst b/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst
index 06c3e6d5f9e6efd0057372c50846ddae11b0c82f..86711bf29d05cb21122bd2344f3836390998e13a 100644
--- a/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst
+++ b/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst
@@ -14,6 +14,13 @@ be automatically exported and imported by callers.  This simplifies porting
 projects to Windows by reducing the need for explicit ``dllexport`` markup,
 even in ``C++`` classes.
 
+When this property is enabled, zero or more ``.def`` files may also be
+specified as source files of the target.  The exports named by these files
+will be merged with those detected from the object files to generate a
+single module definition file to be passed to the linker.  This can be
+used to export symbols from a ``.dll`` that are not in any of its object
+files but are added by the linker from dependencies (e.g. ``msvcrt.lib``).
+
 This property is initialized by the value of
 the :variable:`CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS` variable if it is set
 when a target is created.
diff --git a/Help/release/dev/module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS.rst b/Help/release/dev/module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS.rst
new file mode 100644
index 0000000000000000000000000000000000000000..dfa9ef17402ac47c0d1ccb5ef992e1f9c36ababd
--- /dev/null
+++ b/Help/release/dev/module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS.rst
@@ -0,0 +1,8 @@
+module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS
+-----------------------------------------
+
+* The :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property may now
+  be used in combination with explicit ``.def`` files in order to
+  export all symbols from the object files within a target plus
+  an explicit list of symbols that the linker finds in dependencies
+  (e.g. ``msvcrt.lib``).
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 29698cf913eeae6fd80a248e5ebd2a9a324d99e6..e27424f812478c52481d512eeb88b769e616e901 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1973,15 +1973,16 @@ cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const
 void cmGeneratorTarget::ComputeModuleDefinitionInfo(
   std::string const& config, ModuleDefinitionInfo& info) const
 {
-  std::vector<cmSourceFile const*> sources;
-  this->GetModuleDefinitionSources(sources, config);
+  this->GetModuleDefinitionSources(info.Sources, config);
   info.WindowsExportAllSymbols =
     this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
     this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
-  if (info.WindowsExportAllSymbols) {
+  info.DefFileGenerated =
+    info.WindowsExportAllSymbols || info.Sources.size() > 1;
+  if (info.DefFileGenerated) {
     info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
-  } else if (!sources.empty()) {
-    info.DefFile = sources.front()->GetFullPath();
+  } else if (!info.Sources.empty()) {
+    info.DefFile = info.Sources.front()->GetFullPath();
   }
 }
 
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 92285f3d3243c92314b1854bee7bfc0922b8d402..68d6ef8d38928cdd6aa1e8b38c2558eab2638d0c 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -238,7 +238,9 @@ public:
   struct ModuleDefinitionInfo
   {
     std::string DefFile;
+    bool DefFileGenerated;
     bool WindowsExportAllSymbols;
+    std::vector<cmSourceFile const*> Sources;
   };
   ModuleDefinitionInfo const* GetModuleDefinitionInfo(
     std::string const& config) const;
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 4e7d92a767f16c40d0b32e45f543297ab3800e28..d052f030a89bb5f8d1e4071af15c191679ce7ba8 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -816,7 +816,7 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
 {
   cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
     gt->GetModuleDefinitionInfo(configName);
-  if (!mdi || !mdi->WindowsExportAllSymbols) {
+  if (!mdi || !mdi->DefFileGenerated) {
     return;
   }
 
@@ -851,37 +851,47 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
     cmSystemTools::Error("could not open ", objs_file.c_str());
     return;
   }
-  std::vector<std::string> objs;
-  for (std::vector<cmSourceFile const*>::const_iterator it =
-         objectSources.begin();
-       it != objectSources.end(); ++it) {
-    // Find the object file name corresponding to this source file.
-    std::map<cmSourceFile const*, std::string>::const_iterator map_it =
-      mapping.find(*it);
-    // It must exist because we populated the mapping just above.
-    assert(!map_it->second.empty());
-    std::string objFile = obj_dir + map_it->second;
-    objs.push_back(objFile);
-  }
-  std::vector<cmSourceFile const*> externalObjectSources;
-  gt->GetExternalObjects(externalObjectSources, configName);
-  for (std::vector<cmSourceFile const*>::const_iterator it =
-         externalObjectSources.begin();
-       it != externalObjectSources.end(); ++it) {
-    objs.push_back((*it)->GetFullPath());
-  }
 
-  gt->UseObjectLibraries(objs, configName);
-  for (std::vector<std::string>::iterator it = objs.begin(); it != objs.end();
-       ++it) {
-    std::string objFile = *it;
-    // replace $(ConfigurationName) in the object names
-    cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(),
-                                 configName.c_str());
-    if (cmHasLiteralSuffix(objFile, ".obj")) {
-      fout << objFile << "\n";
+  if (mdi->WindowsExportAllSymbols) {
+    std::vector<std::string> objs;
+    for (std::vector<cmSourceFile const*>::const_iterator it =
+           objectSources.begin();
+         it != objectSources.end(); ++it) {
+      // Find the object file name corresponding to this source file.
+      std::map<cmSourceFile const*, std::string>::const_iterator map_it =
+        mapping.find(*it);
+      // It must exist because we populated the mapping just above.
+      assert(!map_it->second.empty());
+      std::string objFile = obj_dir + map_it->second;
+      objs.push_back(objFile);
+    }
+    std::vector<cmSourceFile const*> externalObjectSources;
+    gt->GetExternalObjects(externalObjectSources, configName);
+    for (std::vector<cmSourceFile const*>::const_iterator it =
+           externalObjectSources.begin();
+         it != externalObjectSources.end(); ++it) {
+      objs.push_back((*it)->GetFullPath());
+    }
+
+    gt->UseObjectLibraries(objs, configName);
+    for (std::vector<std::string>::iterator it = objs.begin();
+         it != objs.end(); ++it) {
+      std::string objFile = *it;
+      // replace $(ConfigurationName) in the object names
+      cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(),
+                                   configName.c_str());
+      if (cmHasLiteralSuffix(objFile, ".obj")) {
+        fout << objFile << "\n";
+      }
     }
   }
+
+  for (std::vector<cmSourceFile const*>::const_iterator i =
+         mdi->Sources.begin();
+       i != mdi->Sources.end(); ++i) {
+    fout << (*i)->GetFullPath() << "\n";
+  }
+
   cmCustomCommandLines commandLines;
   commandLines.push_back(cmdl);
   cmCustomCommand command(gt->Target->GetMakefile(), outputs, empty, empty,
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 8026de9f0b92ebf56c34a97eff6d3c3ffeb54173..06cca2a2469c90a1604a2433741b99b704cd757a 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -1818,7 +1818,7 @@ void cmLocalVisualStudio7Generator::OutputTargetRules(
   bool addedPrelink = false;
   cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
     target->GetModuleDefinitionInfo(configName);
-  if (mdi && mdi->WindowsExportAllSymbols) {
+  if (mdi && mdi->DefFileGenerated) {
     addedPrelink = true;
     std::vector<cmCustomCommand> commands = target->GetPreLinkCommands();
     cmGlobalVisualStudioGenerator* gg =
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 1fa87027504e0c6689b0119d8ef5daaeb3c9bb56..ed380242aa6a10de9c472d4d86774585c1a0a764 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1414,10 +1414,14 @@ void cmMakefileTargetGenerator::AppendLinkDepends(
   this->AppendTargetDepends(depends);
 
   // Add a dependency on the link definitions file, if any.
-  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
-    this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
-  if (mdi && !mdi->WindowsExportAllSymbols && !mdi->DefFile.empty()) {
-    depends.push_back(mdi->DefFile);
+  if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+        this->GeneratorTarget->GetModuleDefinitionInfo(
+          this->GetConfigName())) {
+    for (std::vector<cmSourceFile const*>::const_iterator i =
+           mdi->Sources.begin();
+         i != mdi->Sources.end(); ++i) {
+      depends.push_back((*i)->GetFullPath());
+    }
   }
 
   // Add a dependency on user-specified manifest files, if any.
@@ -1724,7 +1728,7 @@ void cmMakefileTargetGenerator::GenDefFile(
 {
   cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
     this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
-  if (!mdi || !mdi->WindowsExportAllSymbols) {
+  if (!mdi || !mdi->DefFileGenerated) {
     return;
   }
   std::string cmd = cmSystemTools::GetCMakeCommand();
@@ -1744,15 +1748,24 @@ void cmMakefileTargetGenerator::GenDefFile(
   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")) {
+
+  if (mdi->WindowsExportAllSymbols) {
+    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) {
       fout << *i << "\n";
     }
   }
-  for (std::vector<std::string>::const_iterator i =
-         this->ExternalObjects.begin();
-       i != this->ExternalObjects.end(); ++i) {
-    fout << *i << "\n";
+
+  for (std::vector<cmSourceFile const*>::const_iterator i =
+         mdi->Sources.begin();
+       i != mdi->Sources.end(); ++i) {
+    fout << (*i)->GetFullPath() << "\n";
   }
 }
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 300618ff442d82b6dfe115570a69c69f5b56579f..cd1407df627874a963fce0120020c1c7eb2b4e37 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -978,7 +978,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   // maybe create .def file from list of objects
   cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
     gt.GetModuleDefinitionInfo(this->GetConfigName());
-  if (mdi && mdi->WindowsExportAllSymbols) {
+  if (mdi && mdi->DefFileGenerated) {
     std::string cmakeCommand =
       this->GetLocalGenerator()->ConvertToOutputFormat(
         cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
@@ -987,18 +987,28 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     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";
+
+    if (mdi->WindowsExportAllSymbols) {
+      cmNinjaDeps objs = this->GetObjects();
+      for (cmNinjaDeps::iterator i = objs.begin(); i != objs.end(); ++i) {
+        if (cmHasLiteralSuffix(*i, ".obj")) {
+          fout << *i << "\n";
+        }
       }
     }
+
+    for (std::vector<cmSourceFile const*>::const_iterator i =
+           mdi->Sources.begin();
+         i != mdi->Sources.end(); ++i) {
+      fout << (*i)->GetFullPath() << "\n";
+    }
   }
   // If we have any PRE_LINK commands, we need to go back to CMAKE_BINARY_DIR
   // for
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 917383d352a222deec98dbaa3851cd6b4a4f48a5..5866950dae60b6129c2c7e96d42372a95e477647 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -212,10 +212,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
   std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
 
   // Add a dependency on the link definitions file, if any.
-  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
-    this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
-  if (mdi && !mdi->WindowsExportAllSymbols && !mdi->DefFile.empty()) {
-    result.push_back(this->ConvertToNinjaPath(mdi->DefFile));
+  if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+        this->GeneratorTarget->GetModuleDefinitionInfo(
+          this->GetConfigName())) {
+    for (std::vector<cmSourceFile const*>::const_iterator i =
+           mdi->Sources.begin();
+         i != mdi->Sources.end(); ++i) {
+      result.push_back(this->ConvertToNinjaPath((*i)->GetFullPath()));
+    }
   }
 
   // Add a dependency on user-specified manifest files, if any.
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 4aea6f8e651d0dd48a0dc9fdeda579b188fcd1d1..68f4e1d1dfd0258c9106a6695b460400f0964754 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -3162,7 +3162,7 @@ void cmVisualStudio10TargetGenerator::WriteEvents(
   bool addedPrelink = false;
   cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
     this->GeneratorTarget->GetModuleDefinitionInfo(configName);
-  if (mdi && mdi->WindowsExportAllSymbols) {
+  if (mdi && mdi->DefFileGenerated) {
     addedPrelink = true;
     std::vector<cmCustomCommand> commands =
       this->GeneratorTarget->GetPreLinkCommands();
diff --git a/Tests/ModuleDefinition/CMakeLists.txt b/Tests/ModuleDefinition/CMakeLists.txt
index bfbb343bc1410090f579a35bc4328161fdec4a60..e49ebea529c6c1b11e9ae83258b6974d51456fc1 100644
--- a/Tests/ModuleDefinition/CMakeLists.txt
+++ b/Tests/ModuleDefinition/CMakeLists.txt
@@ -4,6 +4,8 @@ project(ModuleDefinition C)
 # Test .def file source recognition for DLLs.
 add_library(example_dll SHARED example_dll.c example_dll.def)
 
+add_library(split_dll SHARED split_dll.c split_dll_1.def split_dll_2.def)
+
 # Test generated .def file.
 add_custom_command(OUTPUT example_dll_gen.def
   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/example_dll_gen.def.in
@@ -24,7 +26,12 @@ endif()
 # Test .def file source recognition for EXEs.
 add_executable(example_exe example_exe.c example_exe.def)
 set_property(TARGET example_exe PROPERTY ENABLE_EXPORTS 1)
-target_link_libraries(example_exe example_dll example_dll_gen ${example_dll_2})
+target_link_libraries(example_exe
+  example_dll
+  example_dll_gen
+  ${example_dll_2}
+  split_dll
+  )
 
 # Test linking to the executable.
 add_library(example_mod_1 MODULE example_mod_1.c)
diff --git a/Tests/ModuleDefinition/example_exe.c b/Tests/ModuleDefinition/example_exe.c
index dff566f10592a349c005205b99a886bee45a7b5d..8e86fc454d1d03ebf22a8177429bd1fb95cdce11 100644
--- a/Tests/ModuleDefinition/example_exe.c
+++ b/Tests/ModuleDefinition/example_exe.c
@@ -3,15 +3,19 @@ extern int __declspec(dllimport) example_dll_gen_function(void);
 #ifdef EXAMPLE_DLL_2
 extern int __declspec(dllimport) example_dll_2_function(void);
 #endif
+extern int __declspec(dllimport) split_dll_1(void);
+extern int __declspec(dllimport) split_dll_2(void);
+
 int example_exe_function(void)
 {
   return 0;
 }
+
 int main(void)
 {
   return example_dll_function() + example_dll_gen_function() +
 #ifdef EXAMPLE_DLL_2
     example_dll_2_function() +
 #endif
-    example_exe_function();
+    split_dll_1() + split_dll_2() + example_exe_function();
 }
diff --git a/Tests/ModuleDefinition/split_dll.c b/Tests/ModuleDefinition/split_dll.c
new file mode 100644
index 0000000000000000000000000000000000000000..1546a2dc93f52206ea564c0c326f1abaf3b51cf6
--- /dev/null
+++ b/Tests/ModuleDefinition/split_dll.c
@@ -0,0 +1,9 @@
+int split_dll_1(void)
+{
+  return 0;
+}
+
+int split_dll_2(void)
+{
+  return 0;
+}
diff --git a/Tests/ModuleDefinition/split_dll_1.def b/Tests/ModuleDefinition/split_dll_1.def
new file mode 100644
index 0000000000000000000000000000000000000000..ced9f1020a467d825260d642d6125b828b8fe08c
--- /dev/null
+++ b/Tests/ModuleDefinition/split_dll_1.def
@@ -0,0 +1,2 @@
+EXPORTS
+split_dll_1
diff --git a/Tests/ModuleDefinition/split_dll_2.def b/Tests/ModuleDefinition/split_dll_2.def
new file mode 100644
index 0000000000000000000000000000000000000000..b072c506f438fac6302dffb8e87fc8b6f9da267a
--- /dev/null
+++ b/Tests/ModuleDefinition/split_dll_2.def
@@ -0,0 +1,2 @@
+EXPORTS
+split_dll_2