Several fixes/improvements:

- Fixed CollapseFullPath to work on relative paths with base paths
    not in the current working directory.
  - INCLUDE command now supports relative paths (using above fix).
  - Added ABSOLUTE option to GET_FILENAME_COMPONENT command to
    unwind symlinks and relative paths.
  - Fixed libName_EXPORTS macro definition to be valid C identifier.
  - Added DEFINE_SYMBOL target propterty for customizing the export symbol.
  - Implemented LINK_FLAGS target propterty for libraries in VC6 and VC7.

Several of these fixes were contributed by Gareth Jones.
This commit is contained in:
Brad King 2003-02-07 14:04:16 -05:00
parent f2b4750169
commit cde384411d
12 changed files with 208 additions and 40 deletions

View File

@ -73,9 +73,13 @@ bool cmGetFilenameComponentCommand::InitialPass(std::vector<std::string> const&
{
result = cmSystemTools::GetFilenameWithoutExtension(filename);
}
else if (args[2] == "ABSOLUTE")
{
result = cmSystemTools::CollapseFullPath(filename.c_str());
}
else
{
std::string err = "unknow component " + args[2];
std::string err = "unknown component " + args[2];
this->SetError(err.c_str());
return false;
}

View File

@ -67,9 +67,10 @@ public:
virtual const char* GetFullDocumentation()
{
return
"GET_FILENAME_COMPONENT(VarName FileName PATH|NAME|EXT|NAME_WE|PROGRAM [PROGRAM_ARGS ArgVarName] [CACHE])\n"
"GET_FILENAME_COMPONENT(VarName FileName PATH|ABSOLUTE|NAME|EXT|NAME_WE|PROGRAM [PROGRAM_ARGS ArgVarName] [CACHE])\n"
"Set VarName to be the path (PATH), file name (NAME), file "
"extension (EXT) or file name without extension (NAME_WE) of FileName.\n"
"extension (EXT), file name without extension (NAME_WE) of FileName, "
"or the full absolute (ABSOLUTE) file name without symlinks. "
"Note that the path is converted to Unix slashes format and has no "
"trailing slashes. The longest file extension is always considered.\n"
"Warning: as a utility command, the resulting value is not put in the "

View File

@ -2477,7 +2477,18 @@ void cmLocalUnixMakefileGenerator::OutputSourceObjectBuildRules(std::ostream& fo
std::string exportsDef = "";
if(shared)
{
exportsDef = "-D"+target->first+"_EXPORTS ";
std::string export_symbol;
if (const char* custom_export_name = target->second.GetProperty("DEFINE_SYMBOL"))
{
export_symbol = custom_export_name;
}
else
{
std::string in = target->first + "_EXPORTS";
export_symbol = cmSystemTools::MakeCindentifier(in.c_str());
}
exportsDef = "-D"+ export_symbol;
}
// Iterate over every source for this target.
const std::vector<cmSourceFile*>& sources = target->second.GetSourceFiles();

View File

@ -82,20 +82,20 @@ void cmLocalVisualStudio6Generator::OutputDSPFile()
switch(l->second.GetType())
{
case cmTarget::STATIC_LIBRARY:
this->SetBuildType(STATIC_LIBRARY, l->first.c_str());
this->SetBuildType(STATIC_LIBRARY, l->first.c_str(), l->second);
break;
case cmTarget::SHARED_LIBRARY:
case cmTarget::MODULE_LIBRARY:
this->SetBuildType(DLL, l->first.c_str());
this->SetBuildType(DLL, l->first.c_str(), l->second);
break;
case cmTarget::EXECUTABLE:
this->SetBuildType(EXECUTABLE,l->first.c_str());
this->SetBuildType(EXECUTABLE,l->first.c_str(), l->second);
break;
case cmTarget::WIN32_EXECUTABLE:
this->SetBuildType(WIN32_EXECUTABLE,l->first.c_str());
this->SetBuildType(WIN32_EXECUTABLE,l->first.c_str(), l->second);
break;
case cmTarget::UTILITY:
this->SetBuildType(UTILITY, l->first.c_str());
this->SetBuildType(UTILITY, l->first.c_str(), l->second);
break;
case cmTarget::INSTALL_FILES:
break;
@ -444,11 +444,25 @@ void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream& fout)
void cmLocalVisualStudio6Generator::SetBuildType(BuildType b, const char *libName)
void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
const char* libName,
const cmTarget& target)
{
std::string root= m_Makefile->GetDefinition("CMAKE_ROOT");
const char *def= m_Makefile->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
std::string exportSymbol;
if (const char* custom_export_name = target.GetProperty("DEFINE_SYMBOL"))
{
exportSymbol = custom_export_name;
}
else
{
std::string in = libName;
in += "_EXPORTS";
exportSymbol = cmSystemTools::MakeCindentifier(in.c_str());
}
if( def)
{
root = def;
@ -510,6 +524,8 @@ void cmLocalVisualStudio6Generator::SetBuildType(BuildType b, const char *libNam
{
fin.getline(buffer, 2048);
std::string line = buffer;
cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
exportSymbol.c_str());
cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
if (reg.find(line))
{
@ -793,6 +809,17 @@ void cmLocalVisualStudio6Generator::WriteDSPHeader(std::ostream& fout, const cha
libMultiLineOptions += extraLinkOptions;
libMultiLineOptions += " \n";
}
if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"))
{
libOptions += " ";
libOptions += targetLinkFlags;
libOptions += " ";
libMultiLineOptions += "# ADD LINK32 ";
libMultiLineOptions += targetLinkFlags;
libMultiLineOptions += " \n";
}
// are there any custom rules on the target itself
// only if the target is a lib or exe

View File

@ -56,7 +56,7 @@ public:
/**
* Specify the type of the build: static, dll, or executable.
*/
void SetBuildType(BuildType,const char *name);
void SetBuildType(BuildType, const char* libName, const cmTarget&);
/**
* Return array of created DSP names in a STL vector.

View File

@ -320,7 +320,18 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
if(target.GetType() == cmTarget::SHARED_LIBRARY
|| target.GetType() == cmTarget::MODULE_LIBRARY)
{
fout << "," << libName << "_EXPORTS";
std::string exportSymbol;
if (const char* custom_export_name = target.GetProperty("DEFINE_SYMBOL"))
{
exportSymbol = custom_export_name;
}
else
{
std::string id = libName;
id += "_EXPORTS";
exportSymbol = cmSystemTools::MakeCindentifier(id.c_str());
}
fout << "," << exportSymbol;
}
this->OutputDefineFlags(fout);
fout << "\"\n";
@ -368,6 +379,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
{
debugPostfix = m_Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
}
const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
switch(target.GetType())
{
case cmTarget::STATIC_LIBRARY:
@ -384,7 +397,13 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
case cmTarget::MODULE_LIBRARY:
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"VCLinkerTool\"\n"
<< "\t\t\t\tAdditionalOptions=\"/MACHINE:I386\"\n"
<< "\t\t\t\tAdditionalOptions=\"/MACHINE:I386";
if(targetLinkFlags)
{
fout << " " << cmLocalVisualStudio7Generator::EscapeForXML(
targetLinkFlags).c_str();
}
fout << "\"\n"
<< "\t\t\t\tAdditionalDependencies=\" odbc32.lib odbccp32.lib ";
this->OutputLibraries(fout, configName, libName, target);
fout << "\"\n";
@ -429,7 +448,13 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"VCLinkerTool\"\n"
<< "\t\t\t\tAdditionalOptions=\"/MACHINE:I386\"\n"
<< "\t\t\t\tAdditionalOptions=\"/MACHINE:I386";
if(targetLinkFlags)
{
fout << " " << cmLocalVisualStudio7Generator::EscapeForXML(
targetLinkFlags).c_str();
}
fout << "\"\n"
<< "\t\t\t\tAdditionalDependencies=\" odbc32.lib odbccp32.lib ";
this->OutputLibraries(fout, configName, libName, target);
fout << "\"\n";
@ -980,11 +1005,17 @@ void cmLocalVisualStudio7Generator::WriteVCProjFooter(std::ostream& fout)
}
std::string cmLocalVisualStudio7Generator::EscapeForXML(const char* s)
{
std::string ret = s;
cmSystemTools::ReplaceString(ret, "\"", "&quot;");
return ret;
}
std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPath(const char* path)
{
std::string ret = cmSystemTools::ConvertToOutputPath(path);
cmSystemTools::ReplaceString(ret, "\"", "&quot;");
return ret;
return cmLocalVisualStudio7Generator::EscapeForXML(ret.c_str());
}
std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPathSingle(const char* path)

View File

@ -81,6 +81,7 @@ private:
const char* configName,
const char* libName,
const cmTarget &tgt);
std::string EscapeForXML(const char* s);
std::string ConvertToXMLOutputPath(const char* path);
std::string ConvertToXMLOutputPathSingle(const char* path);
void OutputDefineFlags(std::ostream& fout);

View File

@ -231,12 +231,34 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff)
// #include has been called). We DO NOT look at the parents of this
// list-file, and for all other purposes, the name of this list-file
// is "filename" and not "external".
bool cmMakefile::ReadListFile(const char* filename, const char* external)
bool cmMakefile::ReadListFile(const char* filename_in, const char* external_in)
{
// used to watch for blockers going out of scope
// e.g. mismatched IF statement
std::set<cmFunctionBlocker *> originalBlockers;
const char* external = 0;
std::string external_abs;
const char* filename = filename_in;
std::string filename_abs;
if (external_in)
{
external_abs =
cmSystemTools::CollapseFullPath(external_in,
m_cmCurrentDirectory.c_str());
external = external_abs.c_str();
if (filename_in)
{
filename_abs =
cmSystemTools::CollapseFullPath(filename_in,
m_cmCurrentDirectory.c_str());
filename = filename_abs.c_str();
}
}
// keep track of the current file being read
if (filename)
{

View File

@ -55,7 +55,15 @@ public:
return
"SET_SOURCE_FILES_PROPERTIES(file1 file2 .. filen PROPERTIES prop1 value1 prop2 value2 ... prop2 valuen)"
"Set properties on a file. The syntax for the command is to list all the files you want "
"to change, and then provide the values you want to set next. Common boolean properties ABSTRACT, WRAP_EXCLUDE, GENERATED and COMPILE_FLAGS. The first three are boolean properties (use a 1 or 0, TRUE or FALSE) while the COMPILE_FLAGS accepts any string. You can make up your own properties as well.";
"to change, and then provide the values you want to set next. You can make up your own properties as well. "
"The following are used by CMake. "
"The ABSTRACT flag (boolean) appears to have some effect on the VTK wrapper commands. "
"If WRAP_EXCLUDE (boolean) is true then the wrapping commands (FLTKWrapUI, QTWrapCC, QTWrapUI, VTKMakeInstantiator, VTKWrapJava, VTKWrapPython, and VTKWrapTcl) will ignore this file. "
"If GENERATED (boolean) is true then it is not an error if this source file does not exist when it is added to a target. Obviously, it must be created (presumably by a custom command) before the target is built. "
"If the HEADER_FILE_ONLY (boolean) property is true then dependency information is not created for that file (this is set automatically, based on the file's name's extension and is probably only used by Makefiles). "
"OBJECT_DEPENDS (string) adds dependencies to the object file. "
"COMPILE_FLAGS (string) is passed to the compiler as additional command line arguments when the source file is compiled. ";
}
cmTypeMacro(cmSetSourceFilesPropertiesCommand, cmCommand);

View File

@ -55,7 +55,11 @@ public:
return
"SET_TARGET_PROPERTIES(target1 target2 .. filen PROPERTIES prop1 value1 prop2 value2 ... prop2 valuen)"
"Set properties on a target. The syntax for the command is to list all the files you want "
"to change, and then provide the values you want to set next. Properties that cmake knows about are PREFIX and POSTFIX for Unix systems and libraries. CMake also knows about LINK_FLAGS, which can be used to add extra flags to the link step of a target. You can use and prop value pair you want and extract it later with the GET_TARGET_PROPERTY command.";
"to change, and then provide the values you want to set next. Properties that cmake knows about are PREFIX and POSTFIX for Unix systems and libraries. CMake also knows about LINK_FLAGS, which can be used to add extra flags to the link step of a target."
"DEFINE_SYMBOL is a symbol that is defined when compiling C or C++ sources. "
"If not set here then it is set to target_EXPORTS by default "
"(with some substitutions if target is not a valid C identifier). "
"You can use and prop value pair you want and extract it later with the GET_TARGET_PROPERTY command.";
}
cmTypeMacro(cmSetTargetPropertiesCommand, cmCommand);

View File

@ -1768,24 +1768,42 @@ void cmSystemTools::SplitProgramPath(const char* in_name,
/**
* Given a path to a file or directory, convert it to a full path.
* This collapses away relative paths. The full path is returned.
* This collapses away relative paths relative to the cwd argument
* (which defaults to the current working directory). The full path
* is returned.
*/
std::string cmSystemTools::CollapseFullPath(const char* in_name)
std::string cmSystemTools::CollapseFullPath(const char* in_relative)
{
return cmSystemTools::CollapseFullPath(in_relative, 0);
}
std::string cmSystemTools::CollapseFullPath(const char* in_relative,
const char* in_base)
{
std::string dir, file;
cmSystemTools::SplitProgramPath(in_name, dir, file);
cmSystemTools::SplitProgramPath(in_relative, dir, file);
// Save original working directory.
std::string orig = cmSystemTools::GetCurrentWorkingDirectory();
// Change to base of relative path.
if(in_base)
{
Chdir(in_base);
}
#ifdef _WIN32
// Ultra-hack warning:
// This changes to the target directory, saves the working directory,
// and then changes back to the original working directory.
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
if(dir != "") { Chdir(dir.c_str()); }
// Follow relative path.
if(dir != "")
{
Chdir(dir.c_str());
}
// Get the resulting directory.
std::string newDir = cmSystemTools::GetCurrentWorkingDirectory();
Chdir(cwd.c_str());
// Add the file back on to the directory.
cmSystemTools::ConvertToUnixSlashes(newDir);
std::string newPath = newDir+"/"+file;
return newPath;
#else
# ifdef MAXPATHLEN
char resolved_name[MAXPATHLEN];
@ -1796,21 +1814,31 @@ std::string cmSystemTools::CollapseFullPath(const char* in_name)
char resolved_name[5024];
# endif
# endif
// Resolve relative path.
std::string newDir;
if(dir != "")
{
realpath(dir.c_str(), resolved_name);
dir = resolved_name;
newDir = resolved_name;
}
else
{
dir = cmSystemTools::GetCurrentWorkingDirectory();
newDir = cmSystemTools::GetCurrentWorkingDirectory();
}
if(file == "")
{
return dir;
}
return dir + "/" + file;
#endif
// Restore original working directory.
Chdir(orig.c_str());
// Construct and return the full path.
std::string newPath = newDir;
if(file != "")
{
newPath += "/";
newPath += file;
}
return newPath;
}
bool cmSystemTools::Split(const char* str, std::vector<cmStdString>& lines)
@ -2330,6 +2358,26 @@ void cmSystemTools::SplitProgramFromArgs(const char* path,
args = "";
}
std::string cmSystemTools::MakeCindentifier(const char* s)
{
std::string str(s);
if (str.find_first_of("0123456789") == 0)
{
str = "_" + str;
}
std::string permited_chars("_"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789");
std::string::size_type pos = 0;
while ((pos = str.find_first_not_of(permited_chars, pos)) != std::string::npos)
{
str[pos] = '_';
}
return str;
}
#if defined(_MSC_VER) && defined(_DEBUG)
# include <crtdbg.h>
# include <stdio.h>

View File

@ -28,6 +28,15 @@
class cmSystemTools
{
public:
/**
* Replace symbols in str that are not valid in C identifiers as
* defined by the 1999 standard, ie. anything except [A-Za-z0-9_].
* They are replaced with `_' and if the first character is a digit
* then an underscore is prepended. Note that this can produce
* identifiers that the standard reserves (_[A-Z].* and __.*).
*/
static std::string MakeCindentifier(const char* s);
/**
* Make a new directory if it is not there. This function
* can make a full path even if none of the directories existed
@ -256,8 +265,10 @@ public:
static void SplitProgramPath(const char* in_name,
std::string& dir,
std::string& file);
static std::string CollapseFullPath(const char*);
static std::string CollapseFullPath(const char* in_relative);
static std::string CollapseFullPath(const char* in_relative,
const char* in_base);
///! return path of a full filename (no trailing slashes).
static std::string GetFilenamePath(const std::string&);