ENH: Added versioned executable support. This partially addresses bug#2143. Also made OUTPUT_NAME work when installing executables.
This commit is contained in:
parent
78112eef25
commit
d392acb4e6
|
@ -570,6 +570,9 @@ bool cmFileCommand::HandleInstallCommand(
|
|||
smanifest_files += soname.substr(destDirLength);
|
||||
}
|
||||
}
|
||||
|
||||
// Reconstruct the source file path taking into account the
|
||||
// extra directory and possible new file name.
|
||||
cmOStringStream str;
|
||||
str << cmSystemTools::GetFilenamePath(ctarget) << "/";
|
||||
if ( extra_dir.size() > 0 )
|
||||
|
@ -581,14 +584,48 @@ bool cmFileCommand::HandleInstallCommand(
|
|||
}
|
||||
break;
|
||||
case cmTarget::EXECUTABLE:
|
||||
{
|
||||
// Handle executable versioning
|
||||
const char* exe_version = 0;
|
||||
if ( properties.find("VERSION") != properties.end() )
|
||||
{
|
||||
exe_version = properties["VERSION"];
|
||||
}
|
||||
if ( exe_version )
|
||||
{
|
||||
std::string exename = destfile;
|
||||
std::string exename_nopath = fname;
|
||||
exename_nopath += "-";
|
||||
exename_nopath += exe_version;
|
||||
|
||||
fname += "-";
|
||||
fname += exe_version;
|
||||
destfile += "-";
|
||||
destfile += exe_version;
|
||||
|
||||
cmSystemTools::RemoveFile(exename.c_str());
|
||||
|
||||
if (!cmSystemTools::CreateSymlink(exename_nopath.c_str(), exename.c_str()) )
|
||||
{
|
||||
std::string errstring = "error when creating symlink from: " + exename + " to " + exename_nopath;
|
||||
this->SetError(errstring.c_str());
|
||||
return false;
|
||||
}
|
||||
smanifest_files += ";";
|
||||
smanifest_files += exename.substr(destDirLength);
|
||||
}
|
||||
|
||||
// Reconstruct the source file path taking into account the
|
||||
// extra directory and possible new file name.
|
||||
cmOStringStream str;
|
||||
str << cmSystemTools::GetFilenamePath(ctarget) << "/";
|
||||
if ( extra_dir.size() > 0 )
|
||||
{
|
||||
cmOStringStream str;
|
||||
str << cmSystemTools::GetFilenamePath(ctarget)
|
||||
<< "/" << extra_dir << "/"
|
||||
<< fname;
|
||||
ctarget = str.str();
|
||||
str << extra_dir << "/";
|
||||
}
|
||||
str << fname;
|
||||
ctarget = str.str();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -369,6 +369,18 @@ void cmLocalGenerator::GenerateInstallRules()
|
|||
}
|
||||
break;
|
||||
case cmTarget::EXECUTABLE:
|
||||
{
|
||||
std::string properties;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
const char* exe_version = 0;
|
||||
#else
|
||||
const char* exe_version = l->second.GetProperty("VERSION");
|
||||
#endif
|
||||
if(exe_version)
|
||||
{
|
||||
properties += " VERSION ";
|
||||
properties += exe_version;
|
||||
}
|
||||
if(l->second.GetPropertyAsBool("MACOSX_BUNDLE"))
|
||||
{
|
||||
fname = exeOutPath;
|
||||
|
@ -385,7 +397,8 @@ void cmLocalGenerator::GenerateInstallRules()
|
|||
pdest += ".app/Contents";
|
||||
bdest += ".app/Contents/MacOS";
|
||||
// first install the actual executable
|
||||
this->AddInstallRule(fout, bdest.c_str(), type, files);
|
||||
this->AddInstallRule(fout, bdest.c_str(), type, files,
|
||||
false, properties.c_str());
|
||||
files = plist.c_str();
|
||||
// now install the Info.plist file
|
||||
this->AddInstallRule(fout, pdest.c_str(),
|
||||
|
@ -396,8 +409,10 @@ void cmLocalGenerator::GenerateInstallRules()
|
|||
fname = exeOutPath;
|
||||
fname += l->second.GetFullName(m_Makefile);
|
||||
files = fname.c_str();
|
||||
this->AddInstallRule(fout, dest, type, files);
|
||||
this->AddInstallRule(fout, dest, type, files, false,
|
||||
properties.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cmTarget::INSTALL_FILES:
|
||||
{
|
||||
|
|
|
@ -1279,35 +1279,34 @@ cmLocalUnixMakefileGenerator3
|
|||
// Add a dependency on the rule file itself.
|
||||
this->AppendRuleDepend(depends, ruleFileName);
|
||||
|
||||
// Construct the full path to the executable that will be generated.
|
||||
std::string targetFullPath = m_ExecutableOutputPath;
|
||||
if(targetFullPath.length() == 0)
|
||||
// Get the name of the executable to generate.
|
||||
std::string targetName;
|
||||
std::string targetNameReal;
|
||||
target.GetExecutableNames(m_Makefile, targetName, targetNameReal);
|
||||
|
||||
// Construct the full path version of the names.
|
||||
std::string outpath = m_ExecutableOutputPath;
|
||||
if(outpath.length() == 0)
|
||||
{
|
||||
targetFullPath = m_Makefile->GetStartOutputDirectory();
|
||||
targetFullPath += "/";
|
||||
outpath = m_Makefile->GetStartOutputDirectory();
|
||||
outpath += "/";
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
if(target.GetPropertyAsBool("MACOSX_BUNDLE"))
|
||||
{
|
||||
// Make bundle directories
|
||||
targetFullPath += target.GetName();
|
||||
targetFullPath += ".app/Contents/MacOS/";
|
||||
outpath += target.GetName();
|
||||
outpath += ".app/Contents/MacOS/";
|
||||
}
|
||||
#endif
|
||||
|
||||
// do we have a different executable name?
|
||||
if (target.GetProperty("OUTPUT_NAME"))
|
||||
{
|
||||
targetFullPath += target.GetProperty("OUTPUT_NAME");
|
||||
}
|
||||
else
|
||||
{
|
||||
targetFullPath += target.GetName();
|
||||
}
|
||||
targetFullPath += cmSystemTools::GetExecutableExtension();
|
||||
std::string targetFullPath = outpath + targetName;
|
||||
std::string targetFullPathReal = outpath + targetNameReal;
|
||||
|
||||
// Convert to the output path to use in constructing commands.
|
||||
std::string targetOutPath = this->Convert(targetFullPath.c_str(),HOME_OUTPUT,MAKEFILE);
|
||||
std::string targetOutPath =
|
||||
this->Convert(targetFullPath.c_str(),HOME_OUTPUT,MAKEFILE);
|
||||
std::string targetOutPathReal =
|
||||
this->Convert(targetFullPathReal.c_str(),HOME_OUTPUT,MAKEFILE);
|
||||
|
||||
// Get the language to use for linking this executable.
|
||||
const char* linkLanguage =
|
||||
|
@ -1387,6 +1386,27 @@ cmLocalUnixMakefileGenerator3
|
|||
// Add target-specific linker flags.
|
||||
this->AppendFlags(linkFlags, target.GetProperty("LINK_FLAGS"));
|
||||
|
||||
// Construct a list of files associated with this executable that
|
||||
// may need to be cleaned.
|
||||
std::vector<std::string> exeCleanFiles;
|
||||
{
|
||||
std::string cleanName;
|
||||
std::string cleanRealName;
|
||||
target.GetExecutableCleanNames(m_Makefile, cleanName,
|
||||
cleanRealName);
|
||||
std::string cleanFullName = outpath + cleanName;
|
||||
std::string cleanFullRealName = outpath + cleanRealName;
|
||||
exeCleanFiles.push_back
|
||||
(this->Convert(cleanFullName.c_str(),HOME_OUTPUT,MAKEFILE));
|
||||
if(cleanRealName != cleanName)
|
||||
{
|
||||
exeCleanFiles.push_back
|
||||
(this->Convert(cleanFullRealName.c_str(),HOME_OUTPUT,MAKEFILE));
|
||||
}
|
||||
}
|
||||
// Add a command to remove any existing files for this executable.
|
||||
this->AppendCleanCommand(commands, exeCleanFiles);
|
||||
|
||||
// Add the pre-build and pre-link rules.
|
||||
this->AppendCustomCommands(commands, target.GetPreBuildCommands());
|
||||
this->AppendCustomCommands(commands, target.GetPreLinkCommands());
|
||||
|
@ -1398,6 +1418,16 @@ cmLocalUnixMakefileGenerator3
|
|||
std::string linkRule = m_Makefile->GetRequiredDefinition(linkRuleVar.c_str());
|
||||
cmSystemTools::ExpandListArgument(linkRule, commands);
|
||||
|
||||
// Add a rule to create necessary symlinks for the library.
|
||||
if(targetOutPath != targetOutPathReal)
|
||||
{
|
||||
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable ";
|
||||
symlink += targetOutPathReal;
|
||||
symlink += " ";
|
||||
symlink += targetOutPath;
|
||||
commands.push_back(symlink);
|
||||
}
|
||||
|
||||
// Add the post-build rules.
|
||||
this->AppendCustomCommands(commands, target.GetPostBuildCommands());
|
||||
|
||||
|
@ -1427,7 +1457,7 @@ cmLocalUnixMakefileGenerator3
|
|||
this->ExpandRuleVariables(*i,
|
||||
linkLanguage,
|
||||
buildObjs.c_str(),
|
||||
targetOutPath.c_str(),
|
||||
targetOutPathReal.c_str(),
|
||||
linklibs.str().c_str(),
|
||||
0,
|
||||
0,
|
||||
|
@ -1453,9 +1483,9 @@ cmLocalUnixMakefileGenerator3
|
|||
this->WriteConvenienceRule(ruleFileStream, targetFullPath.c_str(),
|
||||
buildTargetRuleName.c_str());
|
||||
|
||||
// Clean all the possible executable names and symlinks and object files.
|
||||
cleanFiles.insert(cleanFiles.end(),exeCleanFiles.begin(),exeCleanFiles.end());
|
||||
cleanFiles.push_back(cleanObjs);
|
||||
cleanFiles.push_back
|
||||
(this->Convert(targetFullPath.c_str(),HOME_OUTPUT,MAKEFILE));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
@ -71,6 +71,9 @@ public:
|
|||
"supports symlinks and the linker supports so-names. "
|
||||
"If only one of both is specified the missing is assumed to have "
|
||||
"the same version number. "
|
||||
"For executables VERSION can be used to specify the build version. "
|
||||
"When building or installing appropriate symlinks are created if "
|
||||
"the platform supports symlinks. "
|
||||
"The OUTPUT_NAME can be used to set an output name that is "
|
||||
"used in place of the target name when creating executables."
|
||||
"If not set here then it is set to target_EXPORTS by default "
|
||||
|
|
|
@ -939,7 +939,7 @@ std::string cmTarget::GetFullNameInternal(cmMakefile* mf,
|
|||
{
|
||||
const char* targetPrefix = this->GetProperty("PREFIX");
|
||||
const char* targetSuffix = this->GetProperty("SUFFIX");
|
||||
if(!targetSuffix && this->GetType() == cmTarget::EXECUTABLE)
|
||||
if(!targetSuffix && type == cmTarget::EXECUTABLE)
|
||||
{
|
||||
targetSuffix = cmSystemTools::GetExecutableExtension();
|
||||
}
|
||||
|
@ -973,9 +973,26 @@ std::string cmTarget::GetFullNameInternal(cmMakefile* mf,
|
|||
{
|
||||
targetSuffix = mf->GetSafeDefinition(suffixVar);
|
||||
}
|
||||
|
||||
// Begin the final name with the prefix.
|
||||
std::string name = targetPrefix?targetPrefix:"";
|
||||
name += this->GetName();
|
||||
|
||||
// Append the target name or property-specified name. Support this
|
||||
// only for executable targets.
|
||||
const char* outname = this->GetProperty("OUTPUT_NAME");
|
||||
if(outname && type == cmTarget::EXECUTABLE)
|
||||
{
|
||||
name += outname;
|
||||
}
|
||||
else
|
||||
{
|
||||
name += this->GetName();
|
||||
}
|
||||
|
||||
// Append the suffix.
|
||||
name += targetSuffix?targetSuffix:"";
|
||||
|
||||
// Return the final name.
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -1125,3 +1142,49 @@ void cmTarget::GetLibraryNamesInternal(cmMakefile* mf,
|
|||
realName += soversion;
|
||||
}
|
||||
}
|
||||
|
||||
void cmTarget::GetExecutableNames(cmMakefile* mf,
|
||||
std::string& name,
|
||||
std::string& realName)
|
||||
{
|
||||
// Get the names based on the real type of the executable.
|
||||
this->GetExecutableNamesInternal(mf, name, realName, this->GetType());
|
||||
}
|
||||
|
||||
void cmTarget::GetExecutableCleanNames(cmMakefile* mf,
|
||||
std::string& name,
|
||||
std::string& realName)
|
||||
{
|
||||
// Get the name and versioned name of this executable.
|
||||
this->GetExecutableNamesInternal(mf, name, realName, cmTarget::EXECUTABLE);
|
||||
}
|
||||
|
||||
void cmTarget::GetExecutableNamesInternal(cmMakefile* mf,
|
||||
std::string& name,
|
||||
std::string& realName,
|
||||
TargetType type)
|
||||
{
|
||||
// This versioning is supported only for executables and then only
|
||||
// when the platform supports symbolic links.
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
const char* version = 0;
|
||||
#else
|
||||
// Check for executable version properties.
|
||||
const char* version = this->GetProperty("VERSION");
|
||||
if(type != cmTarget::EXECUTABLE)
|
||||
{
|
||||
version = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// The executable name.
|
||||
name = this->GetFullNameInternal(mf, type);
|
||||
|
||||
// The executable's real name on disk.
|
||||
realName = name;
|
||||
if(version)
|
||||
{
|
||||
realName += "-";
|
||||
realName += version;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,6 +186,19 @@ public:
|
|||
std::string& sharedName,
|
||||
std::string& sharedSOName,
|
||||
std::string& sharedRealName);
|
||||
|
||||
/** Get the names of the executable needed to generate a build rule
|
||||
that takes into account executable version numbers. This should
|
||||
be called only on an executable target. */
|
||||
void GetExecutableNames(cmMakefile* mf, std::string& name,
|
||||
std::string& realName);
|
||||
|
||||
/** Get the names of the executable used to remove existing copies
|
||||
of the executable from the build tree either before linking or
|
||||
during a clean step. This should be called only on an
|
||||
executable target. */
|
||||
void GetExecutableCleanNames(cmMakefile* mf, std::string& name,
|
||||
std::string& realName);
|
||||
private:
|
||||
/**
|
||||
* A list of direct dependencies. Use in conjunction with DependencyMap.
|
||||
|
@ -249,6 +262,10 @@ private:
|
|||
std::string& soName,
|
||||
std::string& realName,
|
||||
TargetType type);
|
||||
void GetExecutableNamesInternal(cmMakefile* mf,
|
||||
std::string& name,
|
||||
std::string& realName,
|
||||
TargetType type);
|
||||
|
||||
// update the value of the LOCATION var
|
||||
void UpdateLocation();
|
||||
|
|
Loading…
Reference in New Issue