Fix use of module .def files for MS tools

We recognize .def source files and map them to the /DEF:<file> option in
the MSVC tools.  Previously this worked only for shared libraries.  This
commit cleans up the implementation and makes it work for executables
too.  See issue #9613.
This commit is contained in:
Brad King 2009-09-29 16:39:07 -04:00
parent caee3af3c5
commit 024d05adad
7 changed files with 51 additions and 45 deletions

View File

@ -887,6 +887,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
Options linkOptions(this, this->Version, Options::Linker,
cmLocalVisualStudio7GeneratorLinkFlagTable);
linkOptions.Parse(extraLinkOptions.c_str());
if(!this->ModuleDefinitionFile.empty())
{
std::string defFile =
this->ConvertToXMLOutputPath(this->ModuleDefinitionFile.c_str());
linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
}
switch(target.GetType())
{
case cmTarget::STATIC_LIBRARY:
@ -960,7 +966,6 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
this->OutputLibraryDirectories(fout, cli.GetDirectories());
fout << "\"\n";
this->OutputModuleDefinitionFile(fout, target);
temp = target.GetDirectory(configName);
temp += "/";
temp += targetNamePDB;
@ -1080,26 +1085,6 @@ cmLocalVisualStudio7Generator
fout << "\t\t\t\tVersion=\"" << major << "." << minor << "\"\n";
}
void cmLocalVisualStudio7Generator
::OutputModuleDefinitionFile(std::ostream& fout,
cmTarget &target)
{
std::vector<cmSourceFile*> const& classes = target.GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
i != classes.end(); i++)
{
cmSourceFile* sf = *i;
if(cmSystemTools::UpperCase(sf->GetExtension()) == "DEF")
{
fout << "\t\t\t\tModuleDefinitionFile=\""
<< this->ConvertToXMLOutputPath(sf->GetFullPath().c_str())
<< "\"\n";
return;
}
}
}
//----------------------------------------------------------------------------
void
cmLocalVisualStudio7GeneratorInternals
@ -1174,6 +1159,7 @@ 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*>const & classes = target.GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
i != classes.end(); i++)

View File

@ -102,7 +102,6 @@ private:
cmTarget& t, bool debug);
void OutputLibraryDirectories(std::ostream& fout,
std::vector<std::string> const& dirs);
void OutputModuleDefinitionFile(std::ostream& fout, cmTarget &target);
void WriteProjectStart(std::ostream& fout, const char *libName,
cmTarget &tgt, std::vector<cmSourceGroup> &sgs);
void WriteProjectStartFortran(std::ostream& fout, const char *libName,

View File

@ -243,6 +243,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
this->LocalGenerator->AppendFlags
(linkFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
this->AddModuleDefinitionFlag(linkFlags);
// Construct a list of files associated with this executable that
// may need to be cleaned.
std::vector<std::string> exeCleanFiles;

View File

@ -146,27 +146,8 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
this->LocalGenerator->AddConfigVariableFlags
(extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
if(this->Makefile->IsOn("WIN32") && !(this->Makefile->IsOn("CYGWIN")
|| this->Makefile->IsOn("MINGW")))
{
const std::vector<cmSourceFile*>& sources =
this->Target->GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
i != sources.end(); ++i)
{
cmSourceFile* sf = *i;
if(sf->GetExtension() == "def")
{
extraFlags += " ";
extraFlags +=
this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
extraFlags +=
this->Convert(sf->GetFullPath().c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::SHELL);
}
}
}
this->AddModuleDefinitionFlag(extraFlags);
this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
}
@ -191,8 +172,8 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
(extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
this->LocalGenerator->AddConfigVariableFlags
(extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
this->AddModuleDefinitionFlag(extraFlags);
// TODO: .def files should be supported here also.
this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
}
@ -218,7 +199,6 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
this->LocalGenerator->AddConfigVariableFlags
(extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName);
// TODO: .def files should be supported here also.
this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
}

View File

@ -170,6 +170,10 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
// This is an external object file. Just add it.
this->ExternalObjects.push_back((*source)->GetFullPath());
}
else if(cmSystemTools::UpperCase((*source)->GetExtension()) == "DEF")
{
this->ModuleDefinitionFile = (*source)->GetFullPath();
}
else
{
// We only get here if a source file is not an external object
@ -1734,3 +1738,27 @@ void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
}
}
}
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
{
if(this->ModuleDefinitionFile.empty())
{
return;
}
// TODO: Create a per-language flag variable.
const char* defFileFlag =
this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
if(!defFileFlag)
{
return;
}
// Append the flag and value.
std::string flag = defFileFlag;
flag += this->Convert(this->ModuleDefinitionFile.c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::SHELL);
this->LocalGenerator->AppendFlags(flags, flag.c_str());
}

View File

@ -186,6 +186,9 @@ protected:
std::vector<std::string> Objects;
std::vector<std::string> ExternalObjects;
// The windows module definition source file (.def), if any.
std::string ModuleDefinitionFile;
// Set of object file names that will be built in this directory.
std::set<cmStdString> ObjectFiles;
@ -214,6 +217,9 @@ protected:
// Compute target-specific Fortran language flags.
void AddFortranFlags(std::string& flags);
// Helper to add flag for windows .def file.
void AddModuleDefinitionFlag(std::string& flags);
//==================================================================
// Convenience routines that do nothing more than forward to
// implementaitons

View File

@ -1125,6 +1125,11 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
linkOptions.AddFlag("ImportLibrary", imLib.c_str());
linkOptions.AddFlag("ProgramDataBaseFileName", pdb.c_str());
linkOptions.Parse(flags.c_str());
if(!this->ModuleDefinitionFile.empty())
{
linkOptions.AddFlag("ModuleDefinitionFile",
this->ModuleDefinitionFile.c_str());
}
linkOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
linkOptions.OutputFlagMap(*this->BuildFileStream, " ");