Merge topic 'ms-manifest-files'
e134e53b Add support for *.manifest source files with MSVC tools da00be63 MSVC: Rewrite manifest file handling with Makefile and Ninja d488b5c9 Ninja: Always add OBJECT_DIR variable to link rules 6d620f5a VS: Add manifest tool settings to VS 8 and 9 project files
This commit is contained in:
commit
309026147a
7
Help/release/dev/ms-manifest-files.rst
Normal file
7
Help/release/dev/ms-manifest-files.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
ms-manifest-files
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
* CMake learned to honor ``*.manifest`` source files with MSVC tools.
|
||||||
|
Manifest files named as sources of ``.exe`` and ``.dll`` targets
|
||||||
|
will be merged with linker-generated manifests and embedded in the
|
||||||
|
binary.
|
@ -274,8 +274,8 @@ set (CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL_INIT ${CMAKE_EXE_LINKER_FLAGS_MINSIZER
|
|||||||
macro(__windows_compiler_msvc lang)
|
macro(__windows_compiler_msvc lang)
|
||||||
if(NOT MSVC_VERSION LESS 1400)
|
if(NOT MSVC_VERSION LESS 1400)
|
||||||
# for 2005 make sure the manifest is put in the dll with mt
|
# for 2005 make sure the manifest is put in the dll with mt
|
||||||
set(_CMAKE_VS_LINK_DLL "<CMAKE_COMMAND> -E vs_link_dll ")
|
set(_CMAKE_VS_LINK_DLL "<CMAKE_COMMAND> -E vs_link_dll --intdir=<OBJECT_DIR> --manifests <MANIFESTS> -- ")
|
||||||
set(_CMAKE_VS_LINK_EXE "<CMAKE_COMMAND> -E vs_link_exe ")
|
set(_CMAKE_VS_LINK_EXE "<CMAKE_COMMAND> -E vs_link_exe --intdir=<OBJECT_DIR> --manifests <MANIFESTS> -- ")
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
|
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
|
||||||
"${_CMAKE_VS_LINK_DLL}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /dll /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
|
"${_CMAKE_VS_LINK_DLL}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /dll /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
|
||||||
|
@ -412,3 +412,20 @@ cmCommonTargetGenerator::GetLinkedTargetDirectories() const
|
|||||||
}
|
}
|
||||||
return dirs;
|
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, " ");
|
||||||
|
}
|
||||||
|
@ -88,6 +88,7 @@ protected:
|
|||||||
ByLanguageMap DefinesByLanguage;
|
ByLanguageMap DefinesByLanguage;
|
||||||
std::string GetIncludes(std::string const& l);
|
std::string GetIncludes(std::string const& l);
|
||||||
ByLanguageMap IncludesByLanguage;
|
ByLanguageMap IncludesByLanguage;
|
||||||
|
std::string GetManifests();
|
||||||
|
|
||||||
std::vector<std::string> GetLinkedTargetDirectories() const;
|
std::vector<std::string> GetLinkedTargetDirectories() const;
|
||||||
};
|
};
|
||||||
|
@ -75,6 +75,7 @@ struct IDLSourcesTag {};
|
|||||||
struct ResxTag {};
|
struct ResxTag {};
|
||||||
struct ModuleDefinitionFileTag {};
|
struct ModuleDefinitionFileTag {};
|
||||||
struct AppManifestTag{};
|
struct AppManifestTag{};
|
||||||
|
struct ManifestsTag{};
|
||||||
struct CertificatesTag{};
|
struct CertificatesTag{};
|
||||||
struct XamlTag{};
|
struct XamlTag{};
|
||||||
|
|
||||||
@ -216,6 +217,10 @@ struct TagVisitor
|
|||||||
{
|
{
|
||||||
DoAccept<IsSameTag<Tag, AppManifestTag>::Result>::Do(this->Data, sf);
|
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")
|
else if (ext == "pfx")
|
||||||
{
|
{
|
||||||
DoAccept<IsSameTag<Tag, CertificatesTag>::Result>::Do(this->Data, sf);
|
DoAccept<IsSameTag<Tag, CertificatesTag>::Result>::Do(this->Data, sf);
|
||||||
@ -623,6 +628,15 @@ cmGeneratorTarget
|
|||||||
IMPLEMENT_VISIT(AppManifest);
|
IMPLEMENT_VISIT(AppManifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
cmGeneratorTarget
|
||||||
|
::GetManifests(std::vector<cmSourceFile const*>& data,
|
||||||
|
const std::string& config) const
|
||||||
|
{
|
||||||
|
IMPLEMENT_VISIT(Manifests);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
cmGeneratorTarget
|
cmGeneratorTarget
|
||||||
|
@ -71,6 +71,8 @@ public:
|
|||||||
const std::string& config) const;
|
const std::string& config) const;
|
||||||
void GetAppManifest(std::vector<cmSourceFile const*>&,
|
void GetAppManifest(std::vector<cmSourceFile const*>&,
|
||||||
const std::string& config) const;
|
const std::string& config) const;
|
||||||
|
void GetManifests(std::vector<cmSourceFile const*>&,
|
||||||
|
const std::string& config) const;
|
||||||
void GetCertificates(std::vector<cmSourceFile const*>&,
|
void GetCertificates(std::vector<cmSourceFile const*>&,
|
||||||
const std::string& config) const;
|
const std::string& config) const;
|
||||||
void GetXamlSources(std::vector<cmSourceFile const*>&,
|
void GetXamlSources(std::vector<cmSourceFile const*>&,
|
||||||
|
@ -525,6 +525,13 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
|
|||||||
return replaceValues.LinkFlags;
|
return replaceValues.LinkFlags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(replaceValues.Manifests)
|
||||||
|
{
|
||||||
|
if(variable == "MANIFESTS")
|
||||||
|
{
|
||||||
|
return replaceValues.Manifests;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(replaceValues.Flags)
|
if(replaceValues.Flags)
|
||||||
{
|
{
|
||||||
if(variable == "FLAGS")
|
if(variable == "FLAGS")
|
||||||
|
@ -219,6 +219,7 @@ public:
|
|||||||
const char* TargetSOName;
|
const char* TargetSOName;
|
||||||
const char* TargetInstallNameDir;
|
const char* TargetInstallNameDir;
|
||||||
const char* LinkFlags;
|
const char* LinkFlags;
|
||||||
|
const char* Manifests;
|
||||||
const char* LanguageCompileFlags;
|
const char* LanguageCompileFlags;
|
||||||
const char* Defines;
|
const char* Defines;
|
||||||
const char* Includes;
|
const char* Includes;
|
||||||
|
@ -972,25 +972,43 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
|
|||||||
fout << "\t\t\t\tProxyFileName=\"$(InputName)_p.c\"/>\n";
|
fout << "\t\t\t\tProxyFileName=\"$(InputName)_p.c\"/>\n";
|
||||||
// end of <Tool Name=VCMIDLTool
|
// end of <Tool Name=VCMIDLTool
|
||||||
|
|
||||||
// Check if we need the FAT32 workaround.
|
// Add manifest tool settings.
|
||||||
if(targetBuilds && this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8)
|
if(targetBuilds && this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8)
|
||||||
{
|
{
|
||||||
|
const char* manifestTool = "VCManifestTool";
|
||||||
|
if (this->FortranProject)
|
||||||
|
{
|
||||||
|
manifestTool = "VFManifestTool";
|
||||||
|
}
|
||||||
|
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.
|
// Check the filesystem type where the target will be written.
|
||||||
if(cmLVS6G_IsFAT(target.GetDirectory(configName).c_str()))
|
if (cmLVS6G_IsFAT(target.GetDirectory(configName).c_str()))
|
||||||
{
|
{
|
||||||
// Add a flag telling the manifest tool to use a workaround
|
// Add a flag telling the manifest tool to use a workaround
|
||||||
// for FAT32 file systems, which can cause an empty manifest
|
// for FAT32 file systems, which can cause an empty manifest
|
||||||
// to be embedded into the resulting executable. See CMake
|
// to be embedded into the resulting executable. See CMake
|
||||||
// bug #2617.
|
// bug #2617.
|
||||||
const char* manifestTool = "VCManifestTool";
|
fout << "\n\t\t\t\tUseFAT32Workaround=\"true\"";
|
||||||
if(this->FortranProject)
|
|
||||||
{
|
|
||||||
manifestTool = "VFManifestTool";
|
|
||||||
}
|
|
||||||
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << manifestTool << "\"\n"
|
|
||||||
<< "\t\t\t\tUseFAT32Workaround=\"true\"\n"
|
|
||||||
<< "\t\t\t/>\n";
|
|
||||||
}
|
}
|
||||||
|
fout << "/>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
this->OutputTargetRules(fout, configName, target, libName);
|
this->OutputTargetRules(fout, configName, target, libName);
|
||||||
|
@ -353,6 +353,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||||||
useResponseFileForObjects, buildObjs, depends,
|
useResponseFileForObjects, buildObjs, depends,
|
||||||
useWatcomQuote);
|
useWatcomQuote);
|
||||||
|
|
||||||
|
std::string manifests = this->GetManifests();
|
||||||
|
|
||||||
cmLocalGenerator::RuleVariables vars;
|
cmLocalGenerator::RuleVariables vars;
|
||||||
vars.RuleLauncher = "RULE_LAUNCH_LINK";
|
vars.RuleLauncher = "RULE_LAUNCH_LINK";
|
||||||
vars.CMTarget = this->Target;
|
vars.CMTarget = this->Target;
|
||||||
@ -391,6 +393,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||||||
vars.LinkLibraries = linkLibs.c_str();
|
vars.LinkLibraries = linkLibs.c_str();
|
||||||
vars.Flags = flags.c_str();
|
vars.Flags = flags.c_str();
|
||||||
vars.LinkFlags = linkFlags.c_str();
|
vars.LinkFlags = linkFlags.c_str();
|
||||||
|
vars.Manifests = manifests.c_str();
|
||||||
|
|
||||||
// Expand placeholders in the commands.
|
// Expand placeholders in the commands.
|
||||||
this->LocalGenerator->TargetImplib = targetOutPathImport;
|
this->LocalGenerator->TargetImplib = targetOutPathImport;
|
||||||
for(std::vector<std::string>::iterator i = real_link_commands.begin();
|
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;
|
cmLocalGenerator::RuleVariables vars;
|
||||||
vars.TargetPDB = targetOutPathPDB.c_str();
|
vars.TargetPDB = targetOutPathPDB.c_str();
|
||||||
|
|
||||||
@ -660,6 +662,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||||||
}
|
}
|
||||||
vars.LinkFlags = linkFlags.c_str();
|
vars.LinkFlags = linkFlags.c_str();
|
||||||
|
|
||||||
|
vars.Manifests = manifests.c_str();
|
||||||
|
|
||||||
// Compute the directory portion of the install_name setting.
|
// Compute the directory portion of the install_name setting.
|
||||||
std::string install_name_dir;
|
std::string install_name_dir;
|
||||||
if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
|
if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
|
||||||
|
@ -1493,6 +1493,15 @@ void cmMakefileTargetGenerator
|
|||||||
depends.push_back(this->ModuleDefinitionFile);
|
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.
|
// Add user-specified dependencies.
|
||||||
if(const char* linkDepends =
|
if(const char* linkDepends =
|
||||||
this->Target->GetProperty("LINK_DEPENDS"))
|
this->Target->GetProperty("LINK_DEPENDS"))
|
||||||
|
@ -237,6 +237,7 @@ cmNinjaNormalTargetGenerator
|
|||||||
|
|
||||||
vars.Flags = "$FLAGS";
|
vars.Flags = "$FLAGS";
|
||||||
vars.LinkFlags = "$LINK_FLAGS";
|
vars.LinkFlags = "$LINK_FLAGS";
|
||||||
|
vars.Manifests = "$MANIFESTS";
|
||||||
|
|
||||||
std::string langFlags;
|
std::string langFlags;
|
||||||
if (targetType != cmTarget::EXECUTABLE)
|
if (targetType != cmTarget::EXECUTABLE)
|
||||||
@ -509,6 +510,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
|||||||
vars["LINK_FLAGS"] = cmGlobalNinjaGenerator
|
vars["LINK_FLAGS"] = cmGlobalNinjaGenerator
|
||||||
::EncodeLiteral(vars["LINK_FLAGS"]);
|
::EncodeLiteral(vars["LINK_FLAGS"]);
|
||||||
|
|
||||||
|
vars["MANIFESTS"] = this->GetManifests();
|
||||||
|
|
||||||
vars["LINK_PATH"] = frameworkPath + linkPath;
|
vars["LINK_PATH"] = frameworkPath + linkPath;
|
||||||
|
|
||||||
// Compute architecture specific link flags. Yes, these go into a different
|
// Compute architecture specific link flags. Yes, these go into a different
|
||||||
@ -579,11 +582,12 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
|||||||
vars["TARGET_PDB"] = base + suffix + dbg_suffix;
|
vars["TARGET_PDB"] = base + suffix + dbg_suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string objPath = GetTarget()->GetSupportDirectory();
|
||||||
|
vars["OBJECT_DIR"] = ConvertToNinjaPath(objPath);
|
||||||
|
EnsureDirectoryExists(objPath);
|
||||||
|
|
||||||
if (this->GetGlobalGenerator()->IsGCCOnWindows())
|
if (this->GetGlobalGenerator()->IsGCCOnWindows())
|
||||||
{
|
{
|
||||||
const std::string objPath = GetTarget()->GetSupportDirectory();
|
|
||||||
vars["OBJECT_DIR"] = ConvertToNinjaPath(objPath);
|
|
||||||
EnsureDirectoryExists(objPath);
|
|
||||||
// ar.exe can't handle backslashes in rsp files (implicitly used by gcc)
|
// ar.exe can't handle backslashes in rsp files (implicitly used by gcc)
|
||||||
std::string& linkLibraries = vars["LINK_LIBRARIES"];
|
std::string& linkLibraries = vars["LINK_LIBRARIES"];
|
||||||
std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/');
|
std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/');
|
||||||
|
@ -209,6 +209,15 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
|
|||||||
result.push_back(this->ConvertToNinjaPath(this->ModuleDefinitionFile));
|
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.
|
// Add user-specified dependencies.
|
||||||
if (const char* linkDepends = this->Target->GetProperty("LINK_DEPENDS"))
|
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(
|
void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
|
||||||
@ -2740,6 +2767,8 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
|
|||||||
this->WriteLinkOptions(*i);
|
this->WriteLinkOptions(*i);
|
||||||
// output lib flags <Lib></Lib>
|
// output lib flags <Lib></Lib>
|
||||||
this->WriteLibOptions(*i);
|
this->WriteLibOptions(*i);
|
||||||
|
// output manifest flags <Manifest></Manifest>
|
||||||
|
this->WriteManifestOptions(*i);
|
||||||
if(this->NsightTegra &&
|
if(this->NsightTegra &&
|
||||||
this->Target->GetType() == cmTarget::EXECUTABLE &&
|
this->Target->GetType() == cmTarget::EXECUTABLE &&
|
||||||
this->Target->GetPropertyAsBool("ANDROID_GUI"))
|
this->Target->GetPropertyAsBool("ANDROID_GUI"))
|
||||||
|
@ -111,6 +111,7 @@ private:
|
|||||||
void AddLibraries(cmComputeLinkInformation& cli,
|
void AddLibraries(cmComputeLinkInformation& cli,
|
||||||
std::vector<std::string>& libVec);
|
std::vector<std::string>& libVec);
|
||||||
void WriteLibOptions(std::string const& config);
|
void WriteLibOptions(std::string const& config);
|
||||||
|
void WriteManifestOptions(std::string const& config);
|
||||||
void WriteEvents(std::string const& configName);
|
void WriteEvents(std::string const& configName);
|
||||||
void WriteEvent(const char* name,
|
void WriteEvent(const char* name,
|
||||||
std::vector<cmCustomCommand> const& commands,
|
std::vector<cmCustomCommand> const& commands,
|
||||||
|
424
Source/cmcmd.cxx
424
Source/cmcmd.cxx
@ -1355,6 +1355,35 @@ int cmcmd::WindowsCEEnvironment(const char* version, const std::string& name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class cmVSLink
|
||||||
|
{
|
||||||
|
int Type;
|
||||||
|
bool Verbose;
|
||||||
|
bool Incremental;
|
||||||
|
bool LinkGeneratesManifest;
|
||||||
|
std::vector<std::string> LinkCommand;
|
||||||
|
std::vector<std::string> UserManifests;
|
||||||
|
std::string LinkerManifestFile;
|
||||||
|
std::string ManifestFile;
|
||||||
|
std::string ManifestFileRC;
|
||||||
|
std::string ManifestFileRes;
|
||||||
|
std::string TargetFile;
|
||||||
|
public:
|
||||||
|
cmVSLink(int type, bool verbose)
|
||||||
|
: Type(type)
|
||||||
|
, Verbose(verbose)
|
||||||
|
, Incremental(false)
|
||||||
|
, LinkGeneratesManifest(true)
|
||||||
|
{}
|
||||||
|
bool Parse(std::vector<std::string>::const_iterator argBeg,
|
||||||
|
std::vector<std::string>::const_iterator argEnd);
|
||||||
|
int Link();
|
||||||
|
private:
|
||||||
|
int LinkIncremental();
|
||||||
|
int LinkNonIncremental();
|
||||||
|
int RunMT(std::string const& out, bool notify);
|
||||||
|
};
|
||||||
|
|
||||||
// For visual studio 2005 and newer manifest files need to be embedded into
|
// For visual studio 2005 and newer manifest files need to be embedded into
|
||||||
// exe and dll's. This code does that in such a way that incremental linking
|
// exe and dll's. This code does that in such a way that incremental linking
|
||||||
// still works.
|
// still works.
|
||||||
@ -1364,11 +1393,7 @@ int cmcmd::VisualStudioLink(std::vector<std::string>& args, int type)
|
|||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bool verbose = false;
|
bool verbose = cmSystemTools::GetEnv("VERBOSE")? true:false;
|
||||||
if(cmSystemTools::GetEnv("VERBOSE"))
|
|
||||||
{
|
|
||||||
verbose = true;
|
|
||||||
}
|
|
||||||
std::vector<std::string> expandedArgs;
|
std::vector<std::string> expandedArgs;
|
||||||
for(std::vector<std::string>::iterator i = args.begin();
|
for(std::vector<std::string>::iterator i = args.begin();
|
||||||
i != args.end(); ++i)
|
i != args.end(); ++i)
|
||||||
@ -1389,79 +1414,19 @@ int cmcmd::VisualStudioLink(std::vector<std::string>& args, int type)
|
|||||||
expandedArgs.push_back(*i);
|
expandedArgs.push_back(*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool hasIncremental = false;
|
|
||||||
bool hasManifest = true;
|
|
||||||
for(std::vector<std::string>::iterator i = expandedArgs.begin();
|
|
||||||
i != expandedArgs.end(); ++i)
|
|
||||||
{
|
|
||||||
if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL:YES") == 0)
|
|
||||||
{
|
|
||||||
hasIncremental = true;
|
|
||||||
}
|
|
||||||
if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL") == 0)
|
|
||||||
{
|
|
||||||
hasIncremental = true;
|
|
||||||
}
|
|
||||||
if(cmSystemTools::Strucmp(i->c_str(), "/MANIFEST:NO") == 0)
|
|
||||||
{
|
|
||||||
hasManifest = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(hasIncremental && hasManifest)
|
|
||||||
{
|
|
||||||
if(verbose)
|
|
||||||
{
|
|
||||||
std::cout << "Visual Studio Incremental Link with embedded manifests\n";
|
|
||||||
}
|
|
||||||
return cmcmd::VisualStudioLinkIncremental(expandedArgs, type, verbose);
|
|
||||||
}
|
|
||||||
if(verbose)
|
|
||||||
{
|
|
||||||
if(!hasIncremental)
|
|
||||||
{
|
|
||||||
std::cout << "Visual Studio Non-Incremental Link\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Visual Studio Incremental Link without manifests\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cmcmd::VisualStudioLinkNonIncremental(expandedArgs,
|
|
||||||
type, hasManifest, verbose);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmcmd::ParseVisualStudioLinkCommand(std::vector<std::string>& args,
|
cmVSLink vsLink(type, verbose);
|
||||||
std::vector<std::string>& command,
|
if (!vsLink.Parse(expandedArgs.begin()+2, expandedArgs.end()))
|
||||||
std::string& targetName)
|
|
||||||
{
|
|
||||||
std::vector<std::string>::iterator i = args.begin();
|
|
||||||
i++; // skip -E
|
|
||||||
i++; // skip vs_link_dll or vs_link_exe
|
|
||||||
command.push_back(*i);
|
|
||||||
i++; // move past link command
|
|
||||||
for(; i != args.end(); ++i)
|
|
||||||
{
|
|
||||||
command.push_back(*i);
|
|
||||||
if(i->find("/Fe") == 0)
|
|
||||||
{
|
|
||||||
targetName = i->substr(3);
|
|
||||||
}
|
|
||||||
if(i->find("/out:") == 0)
|
|
||||||
{
|
|
||||||
targetName = i->substr(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(targetName.empty() || command.empty())
|
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return vsLink.Link();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cmcmd::RunCommand(const char* comment,
|
static bool RunCommand(const char* comment,
|
||||||
std::vector<std::string>& command,
|
std::vector<std::string>& command,
|
||||||
bool verbose,
|
bool verbose,
|
||||||
int* retCodeOut)
|
int* retCodeOut = 0)
|
||||||
{
|
{
|
||||||
if(verbose)
|
if(verbose)
|
||||||
{
|
{
|
||||||
@ -1503,8 +1468,134 @@ bool cmcmd::RunCommand(const char* comment,
|
|||||||
return retCode == 0;
|
return retCode == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmcmd::VisualStudioLinkIncremental(std::vector<std::string>& args,
|
bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
|
||||||
int type, bool verbose)
|
std::vector<std::string>::const_iterator argEnd)
|
||||||
|
{
|
||||||
|
// Parse our own arguments.
|
||||||
|
std::string intDir;
|
||||||
|
std::vector<std::string>::const_iterator arg = argBeg;
|
||||||
|
while (arg != argEnd && cmHasLiteralPrefix(*arg, "-"))
|
||||||
|
{
|
||||||
|
if (*arg == "--")
|
||||||
|
{
|
||||||
|
++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);
|
||||||
|
++arg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "unknown argument '" << *arg << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (intDir.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rest of the arguments form the link command.
|
||||||
|
if (arg == argEnd)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->LinkCommand.insert(this->LinkCommand.begin(), arg, argEnd);
|
||||||
|
|
||||||
|
// Parse the link command to extract information we need.
|
||||||
|
for (; arg != argEnd; ++arg)
|
||||||
|
{
|
||||||
|
if (cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL:YES") == 0)
|
||||||
|
{
|
||||||
|
this->Incremental = true;
|
||||||
|
}
|
||||||
|
else if (cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL") == 0)
|
||||||
|
{
|
||||||
|
this->Incremental = true;
|
||||||
|
}
|
||||||
|
else if (cmSystemTools::Strucmp(arg->c_str(), "/MANIFEST:NO") == 0)
|
||||||
|
{
|
||||||
|
this->LinkGeneratesManifest = false;
|
||||||
|
}
|
||||||
|
else if (cmHasLiteralPrefix(*arg, "/Fe"))
|
||||||
|
{
|
||||||
|
this->TargetFile = arg->substr(3);
|
||||||
|
}
|
||||||
|
else if (cmHasLiteralPrefix(*arg, "/out:"))
|
||||||
|
{
|
||||||
|
this->TargetFile = arg->substr(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->TargetFile.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->ManifestFile = intDir + "/embed.manifest";
|
||||||
|
this->LinkerManifestFile = intDir + "/intermediate.manifest";
|
||||||
|
|
||||||
|
if (this->Incremental)
|
||||||
|
{
|
||||||
|
// We will compile a resource containing the manifest and
|
||||||
|
// pass it to the link command.
|
||||||
|
this->ManifestFileRC = intDir + "/manifest.rc";
|
||||||
|
this->ManifestFileRes = intDir + "/manifest.res";
|
||||||
|
this->LinkCommand.push_back(this->ManifestFileRes);
|
||||||
|
}
|
||||||
|
else if (this->UserManifests.empty())
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->LinkGeneratesManifest)
|
||||||
|
{
|
||||||
|
this->LinkCommand.push_back("/MANIFEST");
|
||||||
|
this->LinkCommand.push_back("/MANIFESTFILE:" + this->LinkerManifestFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmVSLink::Link()
|
||||||
|
{
|
||||||
|
if (this->Incremental &&
|
||||||
|
(this->LinkGeneratesManifest || !this->UserManifests.empty()))
|
||||||
|
{
|
||||||
|
if (this->Verbose)
|
||||||
|
{
|
||||||
|
std::cout << "Visual Studio Incremental Link with embedded manifests\n";
|
||||||
|
}
|
||||||
|
return LinkIncremental();
|
||||||
|
}
|
||||||
|
if (this->Verbose)
|
||||||
|
{
|
||||||
|
if (!this->Incremental)
|
||||||
|
{
|
||||||
|
std::cout << "Visual Studio Non-Incremental Link\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Visual Studio Incremental Link without manifests\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LinkNonIncremental();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmVSLink::LinkIncremental()
|
||||||
{
|
{
|
||||||
// This follows the steps listed here:
|
// This follows the steps listed here:
|
||||||
// http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
|
// http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
|
||||||
@ -1528,161 +1619,118 @@ int cmcmd::VisualStudioLinkIncremental(std::vector<std::string>& args,
|
|||||||
// 7. Finally, the Linker does another incremental link, but since the
|
// 7. Finally, the Linker does another incremental link, but since the
|
||||||
// only thing that has changed is the *.res file that contains the
|
// only thing that has changed is the *.res file that contains the
|
||||||
// manifest it is a short link.
|
// manifest it is a short link.
|
||||||
std::vector<std::string> linkCommand;
|
|
||||||
std::string targetName;
|
// Create a resource file referencing the manifest.
|
||||||
if(cmcmd::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1)
|
std::string absManifestFile =
|
||||||
|
cmSystemTools::CollapseFullPath(this->ManifestFile);
|
||||||
|
if (this->Verbose)
|
||||||
|
{
|
||||||
|
std::cout << "Create " << this->ManifestFileRC << "\n";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cmsys::ofstream fout(this->ManifestFileRC.c_str());
|
||||||
|
if (!fout)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
std::string manifestArg = "/MANIFESTFILE:";
|
fout << this->Type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ "
|
||||||
|
"24 /* RT_MANIFEST */ \"" << absManifestFile << "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have not previously generated a manifest file,
|
||||||
|
// generate an empty one so the resource compiler succeeds.
|
||||||
|
if (!cmSystemTools::FileExists(this->ManifestFile))
|
||||||
|
{
|
||||||
|
if (this->Verbose)
|
||||||
|
{
|
||||||
|
std::cout << "Create empty: " << this->ManifestFile << "\n";
|
||||||
|
}
|
||||||
|
cmsys::ofstream foutTmp(this->ManifestFile.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile the resource file.
|
||||||
std::vector<std::string> rcCommand;
|
std::vector<std::string> rcCommand;
|
||||||
rcCommand.push_back(cmSystemTools::FindProgram("rc.exe"));
|
rcCommand.push_back(cmSystemTools::FindProgram("rc.exe"));
|
||||||
std::vector<std::string> mtCommand;
|
rcCommand.push_back("/fo" + this->ManifestFileRes);
|
||||||
mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
|
rcCommand.push_back(this->ManifestFileRC);
|
||||||
std::string tempManifest;
|
if (!RunCommand("RC Pass 1", rcCommand, this->Verbose))
|
||||||
tempManifest = targetName;
|
|
||||||
tempManifest += ".intermediate.manifest";
|
|
||||||
std::string resourceInputFile = targetName;
|
|
||||||
resourceInputFile += ".resource.txt";
|
|
||||||
if(verbose)
|
|
||||||
{
|
|
||||||
std::cout << "Create " << resourceInputFile << "\n";
|
|
||||||
}
|
|
||||||
// Create input file for rc command
|
|
||||||
cmsys::ofstream fout(resourceInputFile.c_str());
|
|
||||||
if(!fout)
|
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
std::string manifestFile = targetName;
|
|
||||||
manifestFile += ".embed.manifest";
|
// Run the link command (possibly generates intermediate manifest).
|
||||||
std::string fullPath= cmSystemTools::CollapseFullPath(manifestFile);
|
if (!RunCommand("LINK Pass 1", this->LinkCommand, this->Verbose))
|
||||||
fout << type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID "
|
|
||||||
"*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath << "\"";
|
|
||||||
fout.close();
|
|
||||||
manifestArg += tempManifest;
|
|
||||||
// add the manifest arg to the linkCommand
|
|
||||||
linkCommand.push_back("/MANIFEST");
|
|
||||||
linkCommand.push_back(manifestArg);
|
|
||||||
// if manifestFile is not yet created, create an
|
|
||||||
// empty one
|
|
||||||
if(!cmSystemTools::FileExists(manifestFile.c_str()))
|
|
||||||
{
|
|
||||||
if(verbose)
|
|
||||||
{
|
|
||||||
std::cout << "Create empty: " << manifestFile << "\n";
|
|
||||||
}
|
|
||||||
cmsys::ofstream foutTmp(manifestFile.c_str());
|
|
||||||
}
|
|
||||||
std::string resourceFile = manifestFile;
|
|
||||||
resourceFile += ".res";
|
|
||||||
// add the resource file to the end of the link command
|
|
||||||
linkCommand.push_back(resourceFile);
|
|
||||||
std::string outputOpt = "/fo";
|
|
||||||
outputOpt += resourceFile;
|
|
||||||
rcCommand.push_back(outputOpt);
|
|
||||||
rcCommand.push_back(resourceInputFile);
|
|
||||||
// Run rc command to create resource
|
|
||||||
if(!cmcmd::RunCommand("RC Pass 1", rcCommand, verbose))
|
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Now run the link command to link and create manifest
|
|
||||||
if(!cmcmd::RunCommand("LINK Pass 1", linkCommand, verbose))
|
// Run the manifest tool to create the final manifest.
|
||||||
{
|
int mtRet = this->RunMT("/out:" + this->ManifestFile, true);
|
||||||
return -1;
|
|
||||||
}
|
// If mt returns 1090650113 (or 187 on a posix host) then it updated the
|
||||||
// create mt command
|
// manifest file so we need to embed it again. Otherwise we are done.
|
||||||
std::string outArg("/out:");
|
if (mtRet != 1090650113 && mtRet != 187)
|
||||||
outArg+= manifestFile;
|
|
||||||
mtCommand.push_back("/nologo");
|
|
||||||
mtCommand.push_back(outArg);
|
|
||||||
mtCommand.push_back("/notify_update");
|
|
||||||
mtCommand.push_back("/manifest");
|
|
||||||
mtCommand.push_back(tempManifest);
|
|
||||||
// now run mt.exe to create the final manifest file
|
|
||||||
int mtRet =0;
|
|
||||||
if(!cmcmd::RunCommand("MT", mtCommand, verbose, &mtRet))
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// if mt returns 0, then the manifest was not changed and
|
|
||||||
// we do not need to do another link step
|
|
||||||
if(mtRet == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// check for magic mt return value if mt returns the magic number
|
|
||||||
// 1090650113 then it means that it updated the manifest file and we need
|
|
||||||
// to do the final link. If mt has any value other than 0 or 1090650113
|
|
||||||
// then there was some problem with the command itself and there was an
|
|
||||||
// error so return the error code back out of cmake so make can report it.
|
|
||||||
// (when hosted on a posix system the value is 187)
|
|
||||||
if(mtRet != 1090650113 && mtRet != 187)
|
|
||||||
{
|
{
|
||||||
return mtRet;
|
return mtRet;
|
||||||
}
|
}
|
||||||
// update the resource file with the new manifest from the mt command.
|
|
||||||
if(!cmcmd::RunCommand("RC Pass 2", rcCommand, verbose))
|
// Compile the resource file again.
|
||||||
|
if (!RunCommand("RC Pass 2", rcCommand, this->Verbose))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Run the final incremental link that will put the new manifest resource
|
|
||||||
// into the file incrementally.
|
// Link incrementally again to use the updated resource.
|
||||||
if(!cmcmd::RunCommand("FINAL LINK", linkCommand, verbose))
|
if (!RunCommand("FINAL LINK", this->LinkCommand, this->Verbose))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmcmd::VisualStudioLinkNonIncremental(std::vector<std::string>& args,
|
int cmVSLink::LinkNonIncremental()
|
||||||
int type,
|
|
||||||
bool hasManifest,
|
|
||||||
bool verbose)
|
|
||||||
{
|
{
|
||||||
std::vector<std::string> linkCommand;
|
// Run the link command (possibly generates intermediate manifest).
|
||||||
std::string targetName;
|
if (!RunCommand("LINK", this->LinkCommand, this->Verbose))
|
||||||
if(cmcmd::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1)
|
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Run the link command as given
|
|
||||||
if (hasManifest)
|
// If we have no manifest files we are done.
|
||||||
{
|
if (!this->LinkGeneratesManifest && this->UserManifests.empty())
|
||||||
linkCommand.push_back("/MANIFEST");
|
|
||||||
}
|
|
||||||
if(!cmcmd::RunCommand("LINK", linkCommand, verbose))
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(!hasManifest)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run the manifest tool to embed the final manifest in the binary.
|
||||||
|
std::string mtOut =
|
||||||
|
"/outputresource:" + this->TargetFile + (this->Type == 1? ";#1" : ";#2");
|
||||||
|
return this->RunMT(mtOut, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmVSLink::RunMT(std::string const& out, bool notify)
|
||||||
|
{
|
||||||
std::vector<std::string> mtCommand;
|
std::vector<std::string> mtCommand;
|
||||||
mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
|
mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
|
||||||
mtCommand.push_back("/nologo");
|
mtCommand.push_back("/nologo");
|
||||||
mtCommand.push_back("/manifest");
|
mtCommand.push_back("/manifest");
|
||||||
std::string manifestFile = targetName;
|
if (this->LinkGeneratesManifest)
|
||||||
manifestFile += ".manifest";
|
|
||||||
mtCommand.push_back(manifestFile);
|
|
||||||
std::string outresource = "/outputresource:";
|
|
||||||
outresource += targetName;
|
|
||||||
outresource += ";#";
|
|
||||||
if(type == 1)
|
|
||||||
{
|
{
|
||||||
outresource += "1";
|
mtCommand.push_back(this->LinkerManifestFile);
|
||||||
}
|
}
|
||||||
else if(type == 2)
|
mtCommand.insert(mtCommand.end(),
|
||||||
|
this->UserManifests.begin(), this->UserManifests.end());
|
||||||
|
mtCommand.push_back(out);
|
||||||
|
if (notify)
|
||||||
{
|
{
|
||||||
outresource += "2";
|
// Add an undocumented option that enables a special return
|
||||||
|
// code to notify us when the manifest is modified.
|
||||||
|
mtCommand.push_back("/notify_update");
|
||||||
}
|
}
|
||||||
mtCommand.push_back(outresource);
|
int mtRet = 0;
|
||||||
// Now use the mt tool to embed the manifest into the exe or dll
|
if (!RunCommand("MT", mtCommand, this->Verbose, &mtRet))
|
||||||
if(!cmcmd::RunCommand("MT", mtCommand, verbose))
|
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return mtRet;
|
||||||
}
|
}
|
||||||
|
@ -35,20 +35,6 @@ protected:
|
|||||||
static int WindowsCEEnvironment(const char* version,
|
static int WindowsCEEnvironment(const char* version,
|
||||||
const std::string& name);
|
const std::string& name);
|
||||||
static int VisualStudioLink(std::vector<std::string>& args, int type);
|
static int VisualStudioLink(std::vector<std::string>& args, int type);
|
||||||
static int VisualStudioLinkIncremental(std::vector<std::string>& args,
|
|
||||||
int type,
|
|
||||||
bool verbose);
|
|
||||||
static int VisualStudioLinkNonIncremental(std::vector<std::string>& args,
|
|
||||||
int type,
|
|
||||||
bool hasManifest,
|
|
||||||
bool verbose);
|
|
||||||
static int ParseVisualStudioLinkCommand(std::vector<std::string>& args,
|
|
||||||
std::vector<std::string>& command,
|
|
||||||
std::string& targetName);
|
|
||||||
static bool RunCommand(const char* comment,
|
|
||||||
std::vector<std::string>& command,
|
|
||||||
bool verbose,
|
|
||||||
int* retCodeOut = 0);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -276,6 +276,7 @@ if(BUILD_TESTING)
|
|||||||
if(TEST_RESOURCES)
|
if(TEST_RESOURCES)
|
||||||
ADD_TEST_MACRO(VSResource VSResource)
|
ADD_TEST_MACRO(VSResource VSResource)
|
||||||
endif()
|
endif()
|
||||||
|
ADD_TEST_MACRO(MSManifest MSManifest)
|
||||||
ADD_TEST_MACRO(Simple Simple)
|
ADD_TEST_MACRO(Simple Simple)
|
||||||
ADD_TEST_MACRO(PreOrder PreOrder)
|
ADD_TEST_MACRO(PreOrder PreOrder)
|
||||||
ADD_TEST_MACRO(MissingSourceFile MissingSourceFile)
|
ADD_TEST_MACRO(MissingSourceFile MissingSourceFile)
|
||||||
|
5
Tests/MSManifest/CMakeLists.txt
Normal file
5
Tests/MSManifest/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.3)
|
||||||
|
project(MSManifest C)
|
||||||
|
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
add_subdirectory(Subdir)
|
9
Tests/MSManifest/Subdir/CMakeLists.txt
Normal file
9
Tests/MSManifest/Subdir/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
configure_file(test.manifest.in test.manifest)
|
||||||
|
add_executable(MSManifest main.c ${CMAKE_CURRENT_BINARY_DIR}/test.manifest)
|
||||||
|
|
||||||
|
if(MSVC AND NOT MSVC_VERSION LESS 1400)
|
||||||
|
add_custom_command(TARGET MSManifest POST_BUILD VERBATIM
|
||||||
|
COMMAND ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSManifest>
|
||||||
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
|
||||||
|
)
|
||||||
|
endif()
|
6
Tests/MSManifest/Subdir/check.cmake
Normal file
6
Tests/MSManifest/Subdir/check.cmake
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
file(STRINGS "${exe}" content REGEX "name=\"Kitware.CMake.MSManifestTest\"")
|
||||||
|
if(content)
|
||||||
|
message(STATUS "Expected manifest content found:\n ${content}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Expected manifest content not found in\n ${exe}")
|
||||||
|
endif()
|
1
Tests/MSManifest/Subdir/main.c
Normal file
1
Tests/MSManifest/Subdir/main.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
int main(void) { return 0; }
|
4
Tests/MSManifest/Subdir/test.manifest.in
Normal file
4
Tests/MSManifest/Subdir/test.manifest.in
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<assemblyIdentity type="win32" version="1.0.0.0"
|
||||||
|
name="Kitware.CMake.MSManifestTest"/>
|
||||||
|
</assembly>
|
19
Tests/RunCMake/BuildDepends/C-Exe-Manifest.cmake
Normal file
19
Tests/RunCMake/BuildDepends/C-Exe-Manifest.cmake
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
enable_language(C)
|
||||||
|
|
||||||
|
add_executable(main main.c ${CMAKE_CURRENT_BINARY_DIR}/test.manifest)
|
||||||
|
|
||||||
|
if(MSVC AND NOT MSVC_VERSION LESS 1400)
|
||||||
|
set(EXTRA_CHECK [[
|
||||||
|
file(STRINGS "$<TARGET_FILE:main>" content REGEX "name=\"Kitware.CMake.C-Exe-Manifest-step[0-9]\"")
|
||||||
|
if(NOT "${content}" MATCHES "name=\"Kitware.CMake.C-Exe-Manifest-step${check_step}\"")
|
||||||
|
set(RunCMake_TEST_FAILED "Binary has no manifest with name=\"Kitware.CMake.C-Exe-Manifest-step${check_step}\":\n ${content}")
|
||||||
|
endif()
|
||||||
|
]])
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(GENERATE OUTPUT check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
|
||||||
|
set(check_pairs
|
||||||
|
\"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/test.manifest\"
|
||||||
|
)
|
||||||
|
${EXTRA_CHECK}
|
||||||
|
")
|
6
Tests/RunCMake/BuildDepends/C-Exe-Manifest.step1.cmake
Normal file
6
Tests/RunCMake/BuildDepends/C-Exe-Manifest.step1.cmake
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
file(WRITE "${RunCMake_TEST_BINARY_DIR}/test.manifest" [[
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<assemblyIdentity type="win32" version="1.0.0.0"
|
||||||
|
name="Kitware.CMake.C-Exe-Manifest-step1"/>
|
||||||
|
</assembly>
|
||||||
|
]])
|
6
Tests/RunCMake/BuildDepends/C-Exe-Manifest.step2.cmake
Normal file
6
Tests/RunCMake/BuildDepends/C-Exe-Manifest.step2.cmake
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
file(WRITE "${RunCMake_TEST_BINARY_DIR}/test.manifest" [[
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<assemblyIdentity type="win32" version="1.0.0.0"
|
||||||
|
name="Kitware.CMake.C-Exe-Manifest-step2"/>
|
||||||
|
</assembly>
|
||||||
|
]])
|
@ -14,6 +14,9 @@ function(run_BuildDepends CASE)
|
|||||||
set(RunCMake-check-file check.cmake)
|
set(RunCMake-check-file check.cmake)
|
||||||
set(check_step 1)
|
set(check_step 1)
|
||||||
run_cmake_command(${CASE}-build1 ${CMAKE_COMMAND} --build . --config Debug)
|
run_cmake_command(${CASE}-build1 ${CMAKE_COMMAND} --build . --config Debug)
|
||||||
|
if(run_BuildDepends_skip_step_2)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1.125) # handle 1s resolution
|
execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1.125) # handle 1s resolution
|
||||||
include(${RunCMake_SOURCE_DIR}/${CASE}.step2.cmake OPTIONAL)
|
include(${RunCMake_SOURCE_DIR}/${CASE}.step2.cmake OPTIONAL)
|
||||||
set(check_step 2)
|
set(check_step 2)
|
||||||
@ -21,3 +24,11 @@ function(run_BuildDepends CASE)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
run_BuildDepends(C-Exe)
|
run_BuildDepends(C-Exe)
|
||||||
|
if(NOT RunCMake_GENERATOR MATCHES "Visual Studio [67]|Xcode")
|
||||||
|
if(RunCMake_GENERATOR MATCHES "Visual Studio 10")
|
||||||
|
# VS 10 forgets to re-link when a manifest changes
|
||||||
|
set(run_BuildDepends_skip_step_2 1)
|
||||||
|
endif()
|
||||||
|
run_BuildDepends(C-Exe-Manifest)
|
||||||
|
unset(run_BuildDepends_skip_step_2)
|
||||||
|
endif()
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
|
if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
|
||||||
include(${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
|
include(${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
|
||||||
|
if(RunCMake_TEST_FAILED)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
foreach(exe IN LISTS check_exes)
|
foreach(exe IN LISTS check_exes)
|
||||||
execute_process(COMMAND ${exe} RESULT_VARIABLE res)
|
execute_process(COMMAND ${exe} RESULT_VARIABLE res)
|
||||||
if(NOT res EQUAL ${check_step})
|
if(NOT res EQUAL ${check_step})
|
||||||
|
1
Tests/RunCMake/BuildDepends/main.c
Normal file
1
Tests/RunCMake/BuildDepends/main.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
int main(void) { return 0; }
|
Loading…
x
Reference in New Issue
Block a user