Windows: Optionally generate DLL module definition files automatically
Create target property WINDOWS_EXPORT_ALL_SYMBOLS to automatically generate a module definition file from MS-compatible .obj files and give it to the linker in order to export all symbols from the .dll part of a SHARED library.
This commit is contained in:
parent
069aa93b55
commit
8f86407cfd
|
@ -251,6 +251,7 @@ Properties on Targets
|
|||
/prop_tgt/VS_WINRT_EXTENSIONS
|
||||
/prop_tgt/VS_WINRT_REFERENCES
|
||||
/prop_tgt/WIN32_EXECUTABLE
|
||||
/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS
|
||||
/prop_tgt/XCODE_ATTRIBUTE_an-attribute
|
||||
/prop_tgt/XCTEST
|
||||
|
||||
|
|
|
@ -275,6 +275,7 @@ Variables that Control the Build
|
|||
/variable/CMAKE_USE_RELATIVE_PATHS
|
||||
/variable/CMAKE_VISIBILITY_INLINES_HIDDEN
|
||||
/variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD
|
||||
/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
|
||||
/variable/CMAKE_WIN32_EXECUTABLE
|
||||
/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute
|
||||
/variable/EXECUTABLE_OUTPUT_PATH
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
WINDOWS_EXPORT_ALL_SYMBOLS
|
||||
--------------------------
|
||||
|
||||
This property is implemented only for MS-compatible tools on Windows.
|
||||
|
||||
Enable this boolean property to automatically create a module definition
|
||||
(``.def``) file with all global symbols found in the input ``.obj`` files
|
||||
for a ``SHARED`` library on Windows. The module definition file will be
|
||||
passed to the linker causing all symbols to be exported from the ``.dll``.
|
||||
For global *data* symbols, ``__declspec(dllimport)`` must still be used when
|
||||
compiling against the code in the ``.dll``. All other function symbols will
|
||||
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.
|
||||
|
||||
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.
|
|
@ -0,0 +1,6 @@
|
|||
auto_export_dll_symbols
|
||||
-----------------------
|
||||
|
||||
* On Windows with MS-compatible tools, CMake learned to optionally
|
||||
generate a module definition (``.def``) file for ``SHARED`` libraries.
|
||||
See the :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property.
|
|
@ -0,0 +1,6 @@
|
|||
CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
|
||||
--------------------------------
|
||||
|
||||
Default value for :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property.
|
||||
This variable is used to initialize the property on each target as it is
|
||||
created.
|
|
@ -46,8 +46,10 @@ else()
|
|||
set(_PLATFORM_LINK_FLAGS "")
|
||||
endif()
|
||||
|
||||
set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 1)
|
||||
if(CMAKE_GENERATOR MATCHES "Visual Studio 6")
|
||||
set (CMAKE_NO_BUILD_TYPE 1)
|
||||
set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 0) # not implemented for VS6
|
||||
endif()
|
||||
if(NOT CMAKE_NO_BUILD_TYPE AND CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
set (CMAKE_NO_BUILD_TYPE 1)
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
#include "cmGlobalVisualStudioGenerator.h"
|
||||
|
||||
#include "cmCallVisualStudioMacro.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmLocalVisualStudioGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmTarget.h"
|
||||
#include <cmsys/Encoding.hxx>
|
||||
#include "cmAlgorithms.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm)
|
||||
|
@ -887,3 +889,71 @@ std::string cmGlobalVisualStudioGenerator::ExpandCFGIntDir(
|
|||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
|
||||
cmGeneratorTarget* gt, std::vector<cmCustomCommand>& commands,
|
||||
std::string const& configName)
|
||||
{
|
||||
std::vector<std::string> outputs;
|
||||
std::string deffile = gt->ObjectDirectory;
|
||||
deffile += "/exportall.def";
|
||||
outputs.push_back(deffile);
|
||||
std::vector<std::string> empty;
|
||||
std::vector<cmSourceFile const*> objectSources;
|
||||
gt->GetObjectSources(objectSources, configName);
|
||||
std::map<cmSourceFile const*, std::string> mapping;
|
||||
for(std::vector<cmSourceFile const*>::const_iterator it
|
||||
= objectSources.begin(); it != objectSources.end(); ++it)
|
||||
{
|
||||
mapping[*it];
|
||||
}
|
||||
gt->LocalGenerator->
|
||||
ComputeObjectFilenames(mapping, gt);
|
||||
std::string obj_dir = gt->ObjectDirectory;
|
||||
std::string cmakeCommand = cmSystemTools::GetCMakeCommand();
|
||||
cmSystemTools::ConvertToWindowsExtendedPath(cmakeCommand);
|
||||
cmCustomCommandLine cmdl;
|
||||
cmdl.push_back(cmakeCommand);
|
||||
cmdl.push_back("-E");
|
||||
cmdl.push_back("__create_def");
|
||||
cmdl.push_back(deffile);
|
||||
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";
|
||||
cmdl.push_back(objs_file);
|
||||
cmGeneratedFileStream fout(objs_file.c_str());
|
||||
if(!fout)
|
||||
{
|
||||
cmSystemTools::Error("could not open ", objs_file.c_str());
|
||||
return;
|
||||
}
|
||||
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;
|
||||
// replace $(ConfigurationName) in the object names
|
||||
cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(),
|
||||
configName.c_str());
|
||||
if(cmHasLiteralSuffix(objFile, ".obj"))
|
||||
{
|
||||
fout << objFile << "\n";
|
||||
}
|
||||
}
|
||||
cmCustomCommandLines commandLines;
|
||||
commandLines.push_back(cmdl);
|
||||
cmCustomCommand command(gt->Target->GetMakefile(),
|
||||
outputs, empty, empty,
|
||||
commandLines,
|
||||
"Auto build dll exports",
|
||||
".");
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
|
|
@ -102,6 +102,10 @@ public:
|
|||
const std::string& config) const;
|
||||
|
||||
void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
|
||||
|
||||
void AddSymbolExportCommand(
|
||||
cmGeneratorTarget*, std::vector<cmCustomCommand>& commands,
|
||||
std::string const& configName);
|
||||
protected:
|
||||
virtual void Generate();
|
||||
|
||||
|
|
|
@ -1081,6 +1081,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
this->ConvertToOutputFormat(this->ModuleDefinitionFile, SHELL);
|
||||
linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
|
||||
}
|
||||
if (target.GetType() == cmTarget::SHARED_LIBRARY &&
|
||||
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 cmTarget::UNKNOWN_LIBRARY:
|
||||
|
@ -2015,7 +2023,28 @@ void cmLocalVisualStudio7Generator
|
|||
// Add pre-link event.
|
||||
tool = this->FortranProject? "VFPreLinkEventTool":"VCPreLinkEventTool";
|
||||
event.Start(tool);
|
||||
event.Write(target.GetPreLinkCommands());
|
||||
bool addedPrelink = false;
|
||||
if (target.GetType() == cmTarget::SHARED_LIBRARY &&
|
||||
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);
|
||||
cmGeneratorTarget* gt =
|
||||
this->GlobalGenerator->GetGeneratorTarget(&target);
|
||||
gg->AddSymbolExportCommand(
|
||||
gt, commands, configName);
|
||||
event.Write(commands);
|
||||
}
|
||||
}
|
||||
if (!addedPrelink)
|
||||
{
|
||||
event.Write(target.GetPreLinkCommands());
|
||||
}
|
||||
cmsys::auto_ptr<cmCustomCommand> pcc(
|
||||
this->MaybeCreateImplibDir(target, configName, this->FortranProject));
|
||||
if(pcc.get())
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "cmSourceFile.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmake.h"
|
||||
#include "cmAlgorithms.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmMakefileLibraryTargetGenerator
|
||||
|
@ -563,6 +564,58 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||
useResponseFileForObjects, buildObjs, depends,
|
||||
useWatcomQuote);
|
||||
|
||||
// maybe create .def file from list of objects
|
||||
if (this->Target->GetType() == cmTarget::SHARED_LIBRARY &&
|
||||
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||
{
|
||||
if(this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||
{
|
||||
std::string name_of_def_file =
|
||||
this->Target->GetSupportDirectory();
|
||||
name_of_def_file += std::string("/") +
|
||||
this->Target->GetName();
|
||||
name_of_def_file += ".def";
|
||||
std::string cmd = cmSystemTools::GetCMakeCommand();
|
||||
cmd = this->Convert(cmd, cmLocalGenerator::NONE,
|
||||
cmLocalGenerator::SHELL);
|
||||
cmd += " -E __create_def ";
|
||||
cmd += this->Convert(name_of_def_file,
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::SHELL);
|
||||
cmd += " ";
|
||||
std::string objlist_file = name_of_def_file;
|
||||
objlist_file += ".objs";
|
||||
cmd += this->Convert(objlist_file,
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::SHELL);
|
||||
real_link_commands.push_back(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)
|
||||
{
|
||||
fout << *i << "\n";
|
||||
}
|
||||
// now add the def file link flag
|
||||
linkFlags += " ";
|
||||
linkFlags +=
|
||||
this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
|
||||
linkFlags += this->Convert(name_of_def_file,
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::SHELL);
|
||||
linkFlags += " ";
|
||||
}
|
||||
}
|
||||
|
||||
cmLocalGenerator::RuleVariables vars;
|
||||
vars.TargetPDB = targetOutPathPDB.c_str();
|
||||
|
||||
|
|
|
@ -486,6 +486,22 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
|||
linkPath,
|
||||
&genTarget,
|
||||
useWatcomQuote);
|
||||
if(this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")
|
||||
&& target.GetType() == cmTarget::SHARED_LIBRARY)
|
||||
{
|
||||
if(target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||
{
|
||||
std::string dllname = targetOutput;
|
||||
std::string name_of_def_file
|
||||
= target.GetSupportDirectory();
|
||||
name_of_def_file += "/" + target.GetName();
|
||||
name_of_def_file += ".def ";
|
||||
vars["LINK_FLAGS"] += " /DEF:";
|
||||
vars["LINK_FLAGS"] += this->GetLocalGenerator()
|
||||
->ConvertToOutputFormat(name_of_def_file.c_str(),
|
||||
cmLocalGenerator::SHELL);
|
||||
}
|
||||
}
|
||||
|
||||
this->addPoolNinjaVariable("JOB_POOL_LINK", &target, vars);
|
||||
|
||||
|
@ -600,6 +616,44 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
|||
}
|
||||
}
|
||||
|
||||
// maybe create .def file from list of objects
|
||||
if (target.GetType() == cmTarget::SHARED_LIBRARY &&
|
||||
this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||
{
|
||||
if(target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||
{
|
||||
std::string cmakeCommand =
|
||||
this->GetLocalGenerator()->ConvertToOutputFormat(
|
||||
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
|
||||
std::string dllname = targetOutput;
|
||||
std::string name_of_def_file
|
||||
= target.GetSupportDirectory();
|
||||
name_of_def_file += "/" + target.GetName();
|
||||
name_of_def_file += ".def";
|
||||
std::string cmd = cmakeCommand;
|
||||
cmd += " -E __create_def ";
|
||||
cmd += this->GetLocalGenerator()
|
||||
->ConvertToOutputFormat(name_of_def_file.c_str(),
|
||||
cmLocalGenerator::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.c_str(),
|
||||
cmLocalGenerator::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 we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
|
||||
// the link commands.
|
||||
if (!preLinkCmdLines.empty())
|
||||
|
|
|
@ -429,6 +429,11 @@ void cmTarget::SetMakefile(cmMakefile* mf)
|
|||
{
|
||||
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
|
||||
}
|
||||
if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY)
|
||||
{
|
||||
this->SetPropertyDefault("WINDOWS_EXPORT_ALL_SYMBOLS", 0);
|
||||
}
|
||||
|
||||
if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY)
|
||||
{
|
||||
this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0);
|
||||
|
|
|
@ -2466,6 +2466,15 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
|
|||
"%(IgnoreSpecificDefaultLibraries)");
|
||||
}
|
||||
|
||||
if (this->Target->GetType() == cmTarget::SHARED_LIBRARY &&
|
||||
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||
{
|
||||
if (this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||
{
|
||||
linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)exportall.def");
|
||||
}
|
||||
}
|
||||
|
||||
this->LinkOptions[config] = pOptions.release();
|
||||
return true;
|
||||
}
|
||||
|
@ -2613,8 +2622,25 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
|
|||
void
|
||||
cmVisualStudio10TargetGenerator::WriteEvents(std::string const& configName)
|
||||
{
|
||||
this->WriteEvent("PreLinkEvent",
|
||||
this->Target->GetPreLinkCommands(), configName);
|
||||
bool addedPrelink = false;
|
||||
if (this->Target->GetType() == cmTarget::SHARED_LIBRARY &&
|
||||
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||
{
|
||||
if (this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||
{
|
||||
addedPrelink = true;
|
||||
std::vector<cmCustomCommand> commands =
|
||||
this->Target->GetPreLinkCommands();
|
||||
this->GlobalGenerator->AddSymbolExportCommand(
|
||||
this->GeneratorTarget, commands, configName);
|
||||
this->WriteEvent("PreLinkEvent", commands, configName);
|
||||
}
|
||||
}
|
||||
if (!addedPrelink)
|
||||
{
|
||||
this->WriteEvent("PreLinkEvent",
|
||||
this->Target->GetPreLinkCommands(), configName);
|
||||
}
|
||||
this->WriteEvent("PreBuildEvent",
|
||||
this->Target->GetPreBuildCommands(), configName);
|
||||
this->WriteEvent("PostBuildEvent",
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include <time.h>
|
||||
|
||||
#include <stdlib.h> // required for atoi
|
||||
#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
|
||||
// defined in binexplib.cxx
|
||||
bool DumpFile(const char* filename, FILE *fout);
|
||||
#endif
|
||||
|
||||
void CMakeCommandUsage(const char* program)
|
||||
{
|
||||
|
@ -211,6 +215,41 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
|
||||
else if(args[1] == "__create_def")
|
||||
{
|
||||
if(args.size() < 4)
|
||||
{
|
||||
std::cerr <<
|
||||
"__create_def Usage: -E __create_def outfile.def objlistfile\n";
|
||||
return 1;
|
||||
}
|
||||
FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+");
|
||||
if(!fout)
|
||||
{
|
||||
std::cerr << "could not open output .def file: " << args[2].c_str()
|
||||
<< "\n";
|
||||
return 1;
|
||||
}
|
||||
cmsys::ifstream fin(args[3].c_str(),
|
||||
std::ios::in | std::ios::binary);
|
||||
if(!fin)
|
||||
{
|
||||
std::cerr << "could not open object list file: " << args[3].c_str()
|
||||
<< "\n";
|
||||
return 1;
|
||||
}
|
||||
std::string objfile;
|
||||
while(cmSystemTools::GetLineFromStream(fin, objfile))
|
||||
{
|
||||
if (!DumpFile(objfile.c_str(), fout))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
// run include what you use command and then run the compile
|
||||
// command. This is an internal undocumented option and should
|
||||
// only be used by CMake itself when running iwyu.
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
project(autoexport)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${autoexport_BINARY_DIR}/bin)
|
||||
add_subdirectory(sub)
|
||||
add_library(autoexport SHARED hello.cxx world.cxx foo.c)
|
||||
add_executable(say say.cxx)
|
||||
target_link_libraries(say autoexport autoexport2)
|
|
@ -0,0 +1 @@
|
|||
^.*$
|
|
@ -0,0 +1,3 @@
|
|||
cmake_minimum_required(VERSION 3.2)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1,26 @@
|
|||
include(RunCMake)
|
||||
set(RunCMake_TEST_NO_CLEAN TRUE)
|
||||
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/AutoExport-build")
|
||||
# start by cleaning up because we don't clean up along the way
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
# configure the AutoExport test
|
||||
run_cmake(AutoExport)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
# don't run this test on VS 6 as it is not supported
|
||||
if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 6|Watcom WMake|Borland Makefiles")
|
||||
return()
|
||||
endif()
|
||||
# we build debug so the say.exe will be found in Debug/say.exe for
|
||||
# Visual Studio generators
|
||||
if("${RunCMake_GENERATOR}" MATCHES "Visual Studio|Xcode")
|
||||
set(INTDIR "Debug/")
|
||||
endif()
|
||||
# build AutoExport
|
||||
run_cmake_command(AutoExportBuild ${CMAKE_COMMAND} --build
|
||||
${RunCMake_TEST_BINARY_DIR} --config Debug --clean-first)
|
||||
# run the executable that uses symbols from the dll
|
||||
if(WIN32)
|
||||
set(EXE_EXT ".exe")
|
||||
endif()
|
||||
run_cmake_command(AutoExportRun
|
||||
${RunCMake_BINARY_DIR}/AutoExport-build/bin/${INTDIR}say${EXE_EXT})
|
|
@ -0,0 +1,15 @@
|
|||
#ifdef _MSC_VER
|
||||
#include "windows.h"
|
||||
#else
|
||||
#define WINAPI
|
||||
#endif
|
||||
|
||||
int WINAPI foo()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
int bar()
|
||||
{
|
||||
return 5;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include <stdio.h>
|
||||
#include "hello.h"
|
||||
int Hello::Data = 0;
|
||||
void Hello::real()
|
||||
{
|
||||
return;
|
||||
}
|
||||
void hello()
|
||||
{
|
||||
printf("hello");
|
||||
}
|
||||
void Hello::operator delete[](void*) {};
|
||||
void Hello::operator delete(void*) {};
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef _MSC_VER
|
||||
#define winexport
|
||||
#else
|
||||
#ifdef autoexport_EXPORTS
|
||||
#define winexport
|
||||
#else
|
||||
#define winexport __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class Hello
|
||||
{
|
||||
public:
|
||||
static winexport int Data;
|
||||
void real();
|
||||
static void operator delete[](void*);
|
||||
static void operator delete(void*);
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
#include <stdio.h>
|
||||
#include "hello.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "windows.h"
|
||||
#else
|
||||
#define WINAPI
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// test __cdecl stuff
|
||||
int WINAPI foo();
|
||||
// test regular C
|
||||
int bar();
|
||||
}
|
||||
|
||||
// test c++ functions
|
||||
// forward declare hello and world
|
||||
void hello();
|
||||
void world();
|
||||
|
||||
int main()
|
||||
{
|
||||
// test static data (needs declspec to work)
|
||||
Hello::Data = 120;
|
||||
Hello h;
|
||||
h.real();
|
||||
hello();
|
||||
printf(" ");
|
||||
world();
|
||||
printf("\n");
|
||||
foo();
|
||||
printf("\n");
|
||||
bar();
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
add_library(autoexport2 SHARED sub.cxx)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
# Try msvc "big" object format.
|
||||
target_compile_options(autoexport2 PRIVATE /bigobj)
|
||||
endif()
|
|
@ -0,0 +1,4 @@
|
|||
int sub()
|
||||
{
|
||||
return 10;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#include "stdio.h"
|
||||
|
||||
void world()
|
||||
{
|
||||
printf("world");
|
||||
}
|
|
@ -266,3 +266,6 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
|
|||
endif()
|
||||
|
||||
add_RunCMake_test_group(CPack "DEB;RPM")
|
||||
# add a test to make sure symbols are exported from a shared library
|
||||
# for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used
|
||||
add_RunCMake_test(AutoExportDll)
|
||||
|
|
Loading…
Reference in New Issue