From 4f90e7931487195b5d540fbaa5dad1c90b26cee1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Dec 2016 09:25:11 -0500 Subject: bindexplib: Revise coding style of CMake-specific methods We exclude this source from `clang-format` due to use of third-party code. However, we can manually format the CMake-specific part of the code using our current style. --- Source/bindexplib.cxx | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index e41850a..7d61ea6 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -426,24 +426,18 @@ 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); } void bindexplib::WriteFile(FILE* file) { fprintf(file,"EXPORTS \n"); - for(std::set::const_iterator i = this->DataSymbols.begin(); - i!= this->DataSymbols.end(); ++i) - { + for (std::set::const_iterator i = this->DataSymbols.begin(); + i != this->DataSymbols.end(); ++i) { fprintf(file, "\t%s \t DATA\n", i->c_str()); - } - for(std::set::const_iterator i = this->Symbols.begin(); - i!= this->Symbols.end(); ++i) - { + } + for (std::set::const_iterator i = this->Symbols.begin(); + i != this->Symbols.end(); ++i) { fprintf(file, "\t%s\n", i->c_str()); - } + } } -- cgit v0.12 From 845c482448e5b60f4934a48eea9c8c1e466f8fea Mon Sep 17 00:00:00 2001 From: Bertrand Bellenot Date: Fri, 9 Dec 2016 11:22:23 +0000 Subject: bindexplib: Add method for parsing and integrating `.def` files --- Source/bindexplib.cxx | 30 +++++++++++++++++++++++++++++- Source/bindexplib.h | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 7d61ea6..47c7565 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -64,7 +64,7 @@ #include "bindexplib.h" #include -#include +#include #include #include @@ -429,6 +429,34 @@ bool bindexplib::AddObjectFile(const char* filename) 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"); 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: -- cgit v0.12 From 24361a455a2a3bd904433ec3b0107493d29d98ba Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 9 Mar 2017 16:42:09 -0500 Subject: bindexplib: Add support for parsing and integrating `.def` files --- Source/cmcmd.cxx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) 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& 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); -- cgit v0.12 From 21c4ec4ffe1c40382f6b435ff49eade31e1137f2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 13 Mar 2017 11:53:26 -0400 Subject: cmGlobalVisualStudioGenerator: Simplify __create_def command generation --- Source/cmGlobalVisualStudioGenerator.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index a073426..4e7d92a 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -843,9 +843,8 @@ 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) { -- cgit v0.12 From 075f6454092ae058add228eda8220a3680b2f9e4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 13 Mar 2017 11:54:30 -0400 Subject: Support WINDOWS_EXPORT_ALL_SYMBOLS with `.def` files The `WINDOWS_EXPORT_ALL_SYMBOLS` target property exports all symbols found in object files explicitly given to the linker. However, the linker may also find additional symbols in dependencies and copy them into the linked binary (e.g. from `msvcrt.lib`). Provide a way to export an explicit list of such symbols by adding a `.def` file as a source file. Fixes: #16473 --- Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst | 7 +++ .../module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS.rst | 8 +++ Source/cmGeneratorTarget.cxx | 11 ++-- Source/cmGeneratorTarget.h | 2 + Source/cmGlobalVisualStudioGenerator.cxx | 68 +++++++++++++--------- Source/cmLocalVisualStudio7Generator.cxx | 2 +- Source/cmMakefileTargetGenerator.cxx | 37 ++++++++---- Source/cmNinjaNormalTargetGenerator.cxx | 20 +++++-- Source/cmNinjaTargetGenerator.cxx | 12 ++-- Source/cmVisualStudio10TargetGenerator.cxx | 2 +- Tests/ModuleDefinition/CMakeLists.txt | 9 ++- Tests/ModuleDefinition/example_exe.c | 6 +- Tests/ModuleDefinition/split_dll.c | 9 +++ Tests/ModuleDefinition/split_dll_1.def | 2 + Tests/ModuleDefinition/split_dll_2.def | 2 + 15 files changed, 138 insertions(+), 59 deletions(-) create mode 100644 Help/release/dev/module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS.rst create mode 100644 Tests/ModuleDefinition/split_dll.c create mode 100644 Tests/ModuleDefinition/split_dll_1.def create mode 100644 Tests/ModuleDefinition/split_dll_2.def 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/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 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 Sources; }; ModuleDefinitionInfo const* GetModuleDefinitionInfo( std::string const& config) const; diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 4e7d92a..d052f03 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 objs; - for (std::vector::const_iterator it = - objectSources.begin(); - it != objectSources.end(); ++it) { - // Find the object file name corresponding to this source file. - std::map::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 externalObjectSources; - gt->GetExternalObjects(externalObjectSources, configName); - for (std::vector::const_iterator it = - externalObjectSources.begin(); - it != externalObjectSources.end(); ++it) { - objs.push_back((*it)->GetFullPath()); - } - gt->UseObjectLibraries(objs, configName); - for (std::vector::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 objs; + for (std::vector::const_iterator it = + objectSources.begin(); + it != objectSources.end(); ++it) { + // Find the object file name corresponding to this source file. + std::map::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 externalObjectSources; + gt->GetExternalObjects(externalObjectSources, configName); + for (std::vector::const_iterator it = + externalObjectSources.begin(); + it != externalObjectSources.end(); ++it) { + objs.push_back((*it)->GetFullPath()); + } + + gt->UseObjectLibraries(objs, configName); + for (std::vector::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::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 8026de9..06cca2a 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 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::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::const_iterator i = this->Objects.begin(); - i != this->Objects.end(); ++i) { - if (cmHasLiteralSuffix(*i, ".obj")) { + + if (mdi->WindowsExportAllSymbols) { + for (std::vector::const_iterator i = this->Objects.begin(); + i != this->Objects.end(); ++i) { + if (cmHasLiteralSuffix(*i, ".obj")) { + fout << *i << "\n"; + } + } + for (std::vector::const_iterator i = + this->ExternalObjects.begin(); + i != this->ExternalObjects.end(); ++i) { fout << *i << "\n"; } } - for (std::vector::const_iterator i = - this->ExternalObjects.begin(); - i != this->ExternalObjects.end(); ++i) { - fout << *i << "\n"; + + for (std::vector::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::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::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 4aea6f8..68f4e1d 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 commands = this->GeneratorTarget->GetPreLinkCommands(); 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 -- cgit v0.12