Add support for *.manifest source files with MSVC tools

Classify .manifest sources separately, add dependencies on them, and
pass them to the MS manifest tool to merge with linker-generated
manifest files.

Inspired-by: Gilles Khouzam <gillesk@microsoft.com>
This commit is contained in:
Brad King
2015-09-16 10:24:16 -04:00
parent da00be6359
commit e134e53b47
29 changed files with 212 additions and 7 deletions
+17
View File
@@ -412,3 +412,20 @@ cmCommonTargetGenerator::GetLinkedTargetDirectories() const
}
return dirs;
}
std::string cmCommonTargetGenerator::GetManifests()
{
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
std::vector<std::string> manifests;
for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin();
mi != manifest_srcs.end(); ++mi)
{
manifests.push_back(this->Convert((*mi)->GetFullPath(),
this->WorkingDirectory,
cmOutputConverter::SHELL));
}
return cmJoin(manifests, " ");
}
+1
View File
@@ -88,6 +88,7 @@ protected:
ByLanguageMap DefinesByLanguage;
std::string GetIncludes(std::string const& l);
ByLanguageMap IncludesByLanguage;
std::string GetManifests();
std::vector<std::string> GetLinkedTargetDirectories() const;
};
+14
View File
@@ -75,6 +75,7 @@ struct IDLSourcesTag {};
struct ResxTag {};
struct ModuleDefinitionFileTag {};
struct AppManifestTag{};
struct ManifestsTag{};
struct CertificatesTag{};
struct XamlTag{};
@@ -216,6 +217,10 @@ struct TagVisitor
{
DoAccept<IsSameTag<Tag, AppManifestTag>::Result>::Do(this->Data, sf);
}
else if (ext == "manifest")
{
DoAccept<IsSameTag<Tag, ManifestsTag>::Result>::Do(this->Data, sf);
}
else if (ext == "pfx")
{
DoAccept<IsSameTag<Tag, CertificatesTag>::Result>::Do(this->Data, sf);
@@ -623,6 +628,15 @@ cmGeneratorTarget
IMPLEMENT_VISIT(AppManifest);
}
//----------------------------------------------------------------------------
void
cmGeneratorTarget
::GetManifests(std::vector<cmSourceFile const*>& data,
const std::string& config) const
{
IMPLEMENT_VISIT(Manifests);
}
//----------------------------------------------------------------------------
void
cmGeneratorTarget
+2
View File
@@ -71,6 +71,8 @@ public:
const std::string& config) const;
void GetAppManifest(std::vector<cmSourceFile const*>&,
const std::string& config) const;
void GetManifests(std::vector<cmSourceFile const*>&,
const std::string& config) const;
void GetCertificates(std::vector<cmSourceFile const*>&,
const std::string& config) const;
void GetXamlSources(std::vector<cmSourceFile const*>&,
+7
View File
@@ -525,6 +525,13 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
return replaceValues.LinkFlags;
}
}
if(replaceValues.Manifests)
{
if(variable == "MANIFESTS")
{
return replaceValues.Manifests;
}
}
if(replaceValues.Flags)
{
if(variable == "FLAGS")
+1
View File
@@ -219,6 +219,7 @@ public:
const char* TargetSOName;
const char* TargetInstallNameDir;
const char* LinkFlags;
const char* Manifests;
const char* LanguageCompileFlags;
const char* Defines;
const char* Includes;
+14
View File
@@ -984,6 +984,20 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
"\t\t\t<Tool\n"
"\t\t\t\tName=\"" << manifestTool << "\"";
std::vector<cmSourceFile const*> manifest_srcs;
gt->GetManifests(manifest_srcs, configName);
if (!manifest_srcs.empty())
{
fout << "\n\t\t\t\tAdditionalManifestFiles=\"";
for (std::vector<cmSourceFile const*>::const_iterator
mi = manifest_srcs.begin(); mi != manifest_srcs.end(); ++mi)
{
std::string m = (*mi)->GetFullPath();
fout << this->ConvertToXMLOutputPath(m.c_str()) << ";";
}
fout << "\"";
}
// Check if we need the FAT32 workaround.
// Check the filesystem type where the target will be written.
if (cmLVS6G_IsFAT(target.GetDirectory(configName).c_str()))
@@ -353,6 +353,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
useResponseFileForObjects, buildObjs, depends,
useWatcomQuote);
std::string manifests = this->GetManifests();
cmLocalGenerator::RuleVariables vars;
vars.RuleLauncher = "RULE_LAUNCH_LINK";
vars.CMTarget = this->Target;
@@ -391,6 +393,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
vars.LinkLibraries = linkLibs.c_str();
vars.Flags = flags.c_str();
vars.LinkFlags = linkFlags.c_str();
vars.Manifests = manifests.c_str();
// Expand placeholders in the commands.
this->LocalGenerator->TargetImplib = targetOutPathImport;
for(std::vector<std::string>::iterator i = real_link_commands.begin();
@@ -616,6 +616,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
}
}
std::string manifests = this->GetManifests();
cmLocalGenerator::RuleVariables vars;
vars.TargetPDB = targetOutPathPDB.c_str();
@@ -660,6 +662,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
}
vars.LinkFlags = linkFlags.c_str();
vars.Manifests = manifests.c_str();
// Compute the directory portion of the install_name setting.
std::string install_name_dir;
if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
+9
View File
@@ -1493,6 +1493,15 @@ void cmMakefileTargetGenerator
depends.push_back(this->ModuleDefinitionFile);
}
// Add a dependency on user-specified manifest files, if any.
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin();
mi != manifest_srcs.end(); ++mi)
{
depends.push_back((*mi)->GetFullPath());
}
// Add user-specified dependencies.
if(const char* linkDepends =
this->Target->GetProperty("LINK_DEPENDS"))
+3
View File
@@ -237,6 +237,7 @@ cmNinjaNormalTargetGenerator
vars.Flags = "$FLAGS";
vars.LinkFlags = "$LINK_FLAGS";
vars.Manifests = "$MANIFESTS";
std::string langFlags;
if (targetType != cmTarget::EXECUTABLE)
@@ -509,6 +510,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
vars["LINK_FLAGS"] = cmGlobalNinjaGenerator
::EncodeLiteral(vars["LINK_FLAGS"]);
vars["MANIFESTS"] = this->GetManifests();
vars["LINK_PATH"] = frameworkPath + linkPath;
// Compute architecture specific link flags. Yes, these go into a different
+9
View File
@@ -209,6 +209,15 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
result.push_back(this->ConvertToNinjaPath(this->ModuleDefinitionFile));
}
// Add a dependency on user-specified manifest files, if any.
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin();
mi != manifest_srcs.end(); ++mi)
{
result.push_back(this->ConvertToNinjaPath((*mi)->GetFullPath()));
}
// Add user-specified dependencies.
if (const char* linkDepends = this->Target->GetProperty("LINK_DEPENDS"))
{
@@ -2203,6 +2203,33 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config)
}
}
void cmVisualStudio10TargetGenerator::WriteManifestOptions(
std::string const& config)
{
if (this->Target->GetType() != cmTarget::EXECUTABLE &&
this->Target->GetType() != cmTarget::SHARED_LIBRARY &&
this->Target->GetType() != cmTarget::MODULE_LIBRARY)
{
return;
}
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, config);
if (!manifest_srcs.empty())
{
this->WriteString("<Manifest>\n", 2);
this->WriteString("<AdditionalManifestFiles>", 3);
for (std::vector<cmSourceFile const*>::const_iterator
mi = manifest_srcs.begin(); mi != manifest_srcs.end(); ++mi)
{
std::string m = this->ConvertPath((*mi)->GetFullPath(), false);
this->ConvertToWindowsSlash(m);
(*this->BuildFileStream) << m << ";";
}
(*this->BuildFileStream) << "</AdditionalManifestFiles>\n";
this->WriteString("</Manifest>\n", 2);
}
}
//----------------------------------------------------------------------------
void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
@@ -2740,6 +2767,8 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
this->WriteLinkOptions(*i);
// output lib flags <Lib></Lib>
this->WriteLibOptions(*i);
// output manifest flags <Manifest></Manifest>
this->WriteManifestOptions(*i);
if(this->NsightTegra &&
this->Target->GetType() == cmTarget::EXECUTABLE &&
this->Target->GetPropertyAsBool("ANDROID_GUI"))
+1
View File
@@ -111,6 +111,7 @@ private:
void AddLibraries(cmComputeLinkInformation& cli,
std::vector<std::string>& libVec);
void WriteLibOptions(std::string const& config);
void WriteManifestOptions(std::string const& config);
void WriteEvents(std::string const& configName);
void WriteEvent(const char* name,
std::vector<cmCustomCommand> const& commands,
+16 -5
View File
@@ -1362,6 +1362,7 @@ class cmVSLink
bool Incremental;
bool LinkGeneratesManifest;
std::vector<std::string> LinkCommand;
std::vector<std::string> UserManifests;
std::string LinkerManifestFile;
std::string ManifestFile;
std::string ManifestFileRC;
@@ -1480,6 +1481,13 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
++arg;
break;
}
else if (*arg == "--manifests")
{
for (++arg; arg != argEnd && !cmHasLiteralPrefix(*arg, "-"); ++arg)
{
this->UserManifests.push_back(*arg);
}
}
else if (cmHasLiteralPrefix(*arg, "--intdir="))
{
intDir = arg->substr(9);
@@ -1544,10 +1552,11 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
this->ManifestFileRes = intDir + "/manifest.res";
this->LinkCommand.push_back(this->ManifestFileRes);
}
else
else if (this->UserManifests.empty())
{
// CMake places the linker-generated manifest next to the binary (as if it
// were not to be embedded) when not linking incrementally.
// Prior to support for user-specified manifests CMake placed the
// linker-generated manifest next to the binary (as if it were not to be
// embedded) when not linking incrementally. Preserve this behavior.
this->ManifestFile = this->TargetFile + ".manifest";
this->LinkerManifestFile = this->ManifestFile;
}
@@ -1564,7 +1573,7 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
int cmVSLink::Link()
{
if (this->Incremental &&
this->LinkGeneratesManifest)
(this->LinkGeneratesManifest || !this->UserManifests.empty()))
{
if (this->Verbose)
{
@@ -1688,7 +1697,7 @@ int cmVSLink::LinkNonIncremental()
}
// If we have no manifest files we are done.
if (!this->LinkGeneratesManifest)
if (!this->LinkGeneratesManifest && this->UserManifests.empty())
{
return 0;
}
@@ -1709,6 +1718,8 @@ int cmVSLink::RunMT(std::string const& out, bool notify)
{
mtCommand.push_back(this->LinkerManifestFile);
}
mtCommand.insert(mtCommand.end(),
this->UserManifests.begin(), this->UserManifests.end());
mtCommand.push_back(out);
if (notify)
{