summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2017-03-22 12:48:56 (GMT)
committerKitware Robot <kwrobot@kitware.com>2017-03-22 12:49:09 (GMT)
commit989484d51fa78f0fc0014212148b52c90872f57e (patch)
tree8cceb3ea36d2478386c9b31ffd6dfd415c9c1e93
parent053317480a12464d405490502dfde75c5fc17b1f (diff)
parent075f6454092ae058add228eda8220a3680b2f9e4 (diff)
downloadCMake-989484d51fa78f0fc0014212148b52c90872f57e.zip
CMake-989484d51fa78f0fc0014212148b52c90872f57e.tar.gz
CMake-989484d51fa78f0fc0014212148b52c90872f57e.tar.bz2
Merge topic 'module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS'
075f6454 Support WINDOWS_EXPORT_ALL_SYMBOLS with `.def` files 21c4ec4f cmGlobalVisualStudioGenerator: Simplify __create_def command generation 24361a45 bindexplib: Add support for parsing and integrating `.def` files 845c4824 bindexplib: Add method for parsing and integrating `.def` files 4f90e793 bindexplib: Revise coding style of CMake-specific methods Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !581
-rw-r--r--Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst7
-rw-r--r--Help/release/dev/module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS.rst8
-rw-r--r--Source/bindexplib.cxx50
-rw-r--r--Source/bindexplib.h1
-rw-r--r--Source/cmGeneratorTarget.cxx11
-rw-r--r--Source/cmGeneratorTarget.h2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx73
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx2
-rw-r--r--Source/cmMakefileTargetGenerator.cxx37
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx20
-rw-r--r--Source/cmNinjaTargetGenerator.cxx12
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx2
-rw-r--r--Source/cmcmd.cxx15
-rw-r--r--Tests/ModuleDefinition/CMakeLists.txt9
-rw-r--r--Tests/ModuleDefinition/example_exe.c6
-rw-r--r--Tests/ModuleDefinition/split_dll.c9
-rw-r--r--Tests/ModuleDefinition/split_dll_1.def2
-rw-r--r--Tests/ModuleDefinition/split_dll_2.def2
18 files changed, 188 insertions, 80 deletions
diff --git a/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst b/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst
index 06c3e6d..86711bf 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 0000000..dfa9ef1
--- /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/bindexplib.cxx b/Source/bindexplib.cxx
index e41850a..47c7565 100644
--- a/Source/bindexplib.cxx
+++ b/Source/bindexplib.cxx
@@ -64,7 +64,7 @@
#include "bindexplib.h"
#include <cmsys/Encoding.hxx>
-#include <fstream>
+#include <cmsys/FStream.hxx>
#include <iostream>
#include <windows.h>
@@ -426,24 +426,46 @@ DumpFile(const char* filename,
bool bindexplib::AddObjectFile(const char* filename)
{
- if(!DumpFile(filename, this->Symbols, this->DataSymbols))
- {
- return false;
- }
- return true;
+ return DumpFile(filename, this->Symbols, this->DataSymbols);
+}
+
+bool bindexplib::AddDefinitionFile(const char* filename)
+{
+ cmsys::ifstream infile(filename);
+ if (!infile) {
+ fprintf(stderr, "Couldn't open definition file '%s'\n", filename);
+ return false;
+ }
+ std::string str;
+ while (std::getline(infile, str)) {
+ // skip the LIBRAY and EXPORTS lines (if any)
+ if ((str.compare(0,7,"LIBRARY") == 0) ||
+ (str.compare(0,7,"EXPORTS") == 0)) {
+ continue;
+ }
+ // remove leading tabs & spaces
+ str.erase(0, str.find_first_not_of(" \t"));
+ std::size_t found = str.find(" \t DATA");
+ if (found != std::string::npos) {
+ str.erase (found, std::string::npos);
+ this->DataSymbols.insert(str);
+ } else {
+ this->Symbols.insert(str);
+ }
+ }
+ infile.close();
+ return true;
}
void bindexplib::WriteFile(FILE* file)
{
fprintf(file,"EXPORTS \n");
- for(std::set<std::string>::const_iterator i = this->DataSymbols.begin();
- i!= this->DataSymbols.end(); ++i)
- {
+ for (std::set<std::string>::const_iterator i = this->DataSymbols.begin();
+ i != this->DataSymbols.end(); ++i) {
fprintf(file, "\t%s \t DATA\n", i->c_str());
- }
- for(std::set<std::string>::const_iterator i = this->Symbols.begin();
- i!= this->Symbols.end(); ++i)
- {
+ }
+ for (std::set<std::string>::const_iterator i = this->Symbols.begin();
+ i != this->Symbols.end(); ++i) {
fprintf(file, "\t%s\n", i->c_str());
- }
+ }
}
diff --git a/Source/bindexplib.h b/Source/bindexplib.h
index d6900ba..7f0615f 100644
--- a/Source/bindexplib.h
+++ b/Source/bindexplib.h
@@ -13,6 +13,7 @@ class bindexplib
{
public:
bindexplib() {}
+ bool AddDefinitionFile(const char* filename);
bool AddObjectFile(const char* filename);
void WriteFile(FILE* file);
private:
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 29698cf..e27424f 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 92285f3..68d6ef8 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 81d9765..32579aa 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -815,7 +815,7 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
{
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
gt->GetModuleDefinitionInfo(configName);
- if (!mdi || !mdi->WindowsExportAllSymbols) {
+ if (!mdi || !mdi->DefFileGenerated) {
return;
}
@@ -842,46 +842,55 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
std::string obj_dir_expanded = obj_dir;
cmSystemTools::ReplaceString(obj_dir_expanded, this->GetCMakeCFGIntDir(),
configName.c_str());
- std::string objs_file = obj_dir_expanded;
- cmSystemTools::MakeDirectory(objs_file.c_str());
- objs_file += "/objects.txt";
+ cmSystemTools::MakeDirectory(obj_dir_expanded);
+ std::string const objs_file = obj_dir_expanded + "/objects.txt";
cmdl.push_back(objs_file);
cmGeneratedFileStream fout(objs_file.c_str());
if (!fout) {
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 f8490bf..7c33821 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -1819,7 +1819,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 1fa8702..ed38024 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 300618f..cd1407d 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 917383d..5866950 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 052cc7f..84767a8 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -3300,7 +3300,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/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 823b38f..9e08b9c 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -258,11 +258,18 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
<< "\n";
return 1;
}
- std::string objfile;
+ std::string file;
bindexplib deffile;
- while (cmSystemTools::GetLineFromStream(fin, objfile)) {
- if (!deffile.AddObjectFile(objfile.c_str())) {
- return 1;
+ while (cmSystemTools::GetLineFromStream(fin, file)) {
+ std::string const& ext = cmSystemTools::GetFilenameLastExtension(file);
+ if (cmSystemTools::LowerCase(ext) == ".def") {
+ if (!deffile.AddDefinitionFile(file.c_str())) {
+ return 1;
+ }
+ } else {
+ if (!deffile.AddObjectFile(file.c_str())) {
+ return 1;
+ }
}
}
deffile.WriteFile(fout);
diff --git a/Tests/ModuleDefinition/CMakeLists.txt b/Tests/ModuleDefinition/CMakeLists.txt
index bfbb343..e49ebea 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 dff566f..8e86fc4 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 0000000..1546a2d
--- /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 0000000..ced9f10
--- /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 0000000..b072c50
--- /dev/null
+++ b/Tests/ModuleDefinition/split_dll_2.def
@@ -0,0 +1,2 @@
+EXPORTS
+split_dll_2