ENH: Rename SET_PROPERITES command to SET_PROPERTY and give it a more powerful signature.

This commit is contained in:
Brad King 2008-01-17 15:54:49 -05:00
parent 456631225b
commit b8357db11d
15 changed files with 537 additions and 303 deletions

View File

@ -21,7 +21,7 @@ SET(CMAKE_FIND_LIBRARY_PREFIXES "lib")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a") SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
# basically all general purpose OSs support shared libs # basically all general purpose OSs support shared libs
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS TRUE) SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
SET (CMAKE_SKIP_RPATH "NO" CACHE BOOL SET (CMAKE_SKIP_RPATH "NO" CACHE BOOL
"If set, runtime paths are not added when using shared libraries.") "If set, runtime paths are not added when using shared libraries.")

View File

@ -21,12 +21,12 @@
MACRO(SET_FEATURE_INFO _name _desc) MACRO(SET_FEATURE_INFO _name _desc)
SET(_url "${ARGV2}") SET(_url "${ARGV2}")
SET(_comment "${ARGV3}") SET(_comment "${ARGV3}")
SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_DESCRIPTION "${_desc}" ) SET_PROPERTY(GLOBAL PROPERTY ${_name}_DESCRIPTION "${_desc}" )
IF(_url MATCHES ".+") IF(_url MATCHES ".+")
SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_URL "${_url}" ) SET_PROPERTY(GLOBAL PROPERTY ${_name}_URL "${_url}" )
ENDIF(_url MATCHES ".+") ENDIF(_url MATCHES ".+")
IF(_comment MATCHES ".+") IF(_comment MATCHES ".+")
SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_COMMENT "${_comment}" ) SET_PROPERTY(GLOBAL PROPERTY ${_name}_COMMENT "${_comment}" )
ENDIF(_comment MATCHES ".+") ENDIF(_comment MATCHES ".+")
ENDMACRO(SET_FEATURE_INFO) ENDMACRO(SET_FEATURE_INFO)

View File

@ -1,5 +1,5 @@
#the compute nodes on BlueGene/L don't support shared libs #the compute nodes on BlueGene/L don't support shared libs
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE) SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared

View File

@ -1,5 +1,5 @@
#Catamount, which runs on the compute nodes of Cray machines, e.g. RedStorm, doesn't support shared libs #Catamount, which runs on the compute nodes of Cray machines, e.g. RedStorm, doesn't support shared libs
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE) SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared

View File

@ -8,5 +8,4 @@
# and/or ${CMAKE_SYSTEM_NAME}-<compiler_basename>-${CMAKE_SYSTEM_PROCESSOR}.cmake # and/or ${CMAKE_SYSTEM_NAME}-<compiler_basename>-${CMAKE_SYSTEM_PROCESSOR}.cmake
# (embedded) targets without operating system usually don't support shared libraries # (embedded) targets without operating system usually don't support shared libraries
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE) SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)

View File

@ -52,5 +52,5 @@ INCLUDE(Platform/UnixPaths)
# Debian has lib64 paths only for compatibility so they should not be # Debian has lib64 paths only for compatibility so they should not be
# searched. # searched.
IF(EXISTS "/etc/debian_version") IF(EXISTS "/etc/debian_version")
SET_PROPERTIES(GLOBAL PROPERTIES FIND_LIBRARY_USE_LIB64_PATHS FALSE) SET_PROPERTY(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE)
ENDIF(EXISTS "/etc/debian_version") ENDIF(EXISTS "/etc/debian_version")

View File

@ -54,4 +54,4 @@ LIST(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
) )
# Enable use of lib64 search path variants by default. # Enable use of lib64 search path variants by default.
SET_PROPERTIES(GLOBAL PROPERTIES FIND_LIBRARY_USE_LIB64_PATHS TRUE) SET_PROPERTY(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)

View File

@ -47,7 +47,7 @@ SET(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLA
SET(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -nostdlib -nostartfiles -L${ECOS_LIBTARGET_DIRECTORY} -Ttarget.ld <LINK_LIBRARIES>") SET(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -nostdlib -nostartfiles -L${ECOS_LIBTARGET_DIRECTORY} -Ttarget.ld <LINK_LIBRARIES>")
# eCos doesn't support shared libs # eCos doesn't support shared libs
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE) SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
SET(CMAKE_CXX_LINK_SHARED_LIBRARY ) SET(CMAKE_CXX_LINK_SHARED_LIBRARY )
SET(CMAKE_CXX_LINK_MODULE_LIBRARY ) SET(CMAKE_CXX_LINK_MODULE_LIBRARY )

View File

@ -72,7 +72,7 @@
#include "cmProjectCommand.cxx" #include "cmProjectCommand.cxx"
#include "cmRaiseScopeCommand.cxx" #include "cmRaiseScopeCommand.cxx"
#include "cmSetCommand.cxx" #include "cmSetCommand.cxx"
#include "cmSetPropertiesCommand.cxx" #include "cmSetPropertyCommand.cxx"
#include "cmSetSourceFilesPropertiesCommand.cxx" #include "cmSetSourceFilesPropertiesCommand.cxx"
#include "cmSetTargetPropertiesCommand.cxx" #include "cmSetTargetPropertiesCommand.cxx"
#include "cmSetTestsPropertiesCommand.cxx" #include "cmSetTestsPropertiesCommand.cxx"
@ -132,7 +132,7 @@ void GetBootstrapCommands(std::list<cmCommand*>& commands)
commands.push_back(new cmProjectCommand); commands.push_back(new cmProjectCommand);
commands.push_back(new cmRaiseScopeCommand); commands.push_back(new cmRaiseScopeCommand);
commands.push_back(new cmSetCommand); commands.push_back(new cmSetCommand);
commands.push_back(new cmSetPropertiesCommand); commands.push_back(new cmSetPropertyCommand);
commands.push_back(new cmSetSourceFilesPropertiesCommand); commands.push_back(new cmSetSourceFilesPropertiesCommand);
commands.push_back(new cmSetTargetPropertiesCommand); commands.push_back(new cmSetTargetPropertiesCommand);
commands.push_back(new cmSetTestsPropertiesCommand); commands.push_back(new cmSetTestsPropertiesCommand);

View File

@ -1,210 +0,0 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "cmSetPropertiesCommand.h"
#include "cmSetTargetPropertiesCommand.h"
#include "cmSetTestsPropertiesCommand.h"
#include "cmSetSourceFilesPropertiesCommand.h"
// cmSetPropertiesCommand
bool cmSetPropertiesCommand::InitialPass(
std::vector<std::string> const& args)
{
if(args.size() < 2 )
{
this->SetError("called with incorrect number of arguments");
return false;
}
// first collect up the list of files
std::vector<std::string> propertyPairs;
bool doingFiles = true;
int numFiles = 0;
std::vector<std::string>::const_iterator j;
for(j= args.begin(); j != args.end();++j)
{
if(*j == "PROPERTIES")
{
doingFiles = false;
// now loop through the rest of the arguments, new style
++j;
while (j != args.end())
{
propertyPairs.push_back(*j);
++j;
if(j == args.end())
{
this->SetError("called with incorrect number of arguments.");
return false;
}
propertyPairs.push_back(*j);
++j;
}
// break out of the loop because j is already == end
break;
}
else if (doingFiles)
{
numFiles++;
}
else
{
this->SetError("called with illegal arguments, maybe missing "
"a PROPERTIES specifier?");
return false;
}
}
if(propertyPairs.size() == 0)
{
this->SetError("called with illegal arguments, maybe missing "
"a PROPERTIES specifier?");
return false;
}
cmProperty::ScopeType scope;
const char *scopeName = 0;
if (args[0] == "GLOBAL" && numFiles == 1)
{
scope = cmProperty::GLOBAL;
}
else if (args[0] == "DIRECTORY" && numFiles >= 1)
{
scope = cmProperty::DIRECTORY;
if (numFiles == 2)
{
scopeName = args[1].c_str();
}
}
else if (args[0] == "TARGET" && numFiles == 2)
{
scope = cmProperty::TARGET;
scopeName = args[1].c_str();
}
else if (args[0] == "TEST" && numFiles == 2)
{
scope = cmProperty::TEST;
scopeName = args[1].c_str();
}
else if (args[0] == "SOURCE_FILE" && numFiles == 2)
{
scope = cmProperty::SOURCE_FILE;
scopeName = args[1].c_str();
}
else
{
this->SetError("called with illegal arguments.");
return false;
}
switch (scope)
{
case cmProperty::TARGET:
{
bool ret = cmSetTargetPropertiesCommand::
SetOneTarget(scopeName,propertyPairs, this->Makefile);
if (!ret)
{
std::string message = "Can not find target to add properties to: ";
message += scopeName;
this->SetError(message.c_str());
return ret;
}
}
break;
case cmProperty::DIRECTORY:
{
// lookup the makefile from the directory name
cmLocalGenerator *lg = this->Makefile->GetLocalGenerator();
if (numFiles == 2)
{
std::string sd = scopeName;
// make sure the start dir is a full path
if (!cmSystemTools::FileIsFullPath(sd.c_str()))
{
sd = this->Makefile->GetStartDirectory();
sd += "/";
sd += scopeName;
}
// The local generators are associated with collapsed paths.
sd = cmSystemTools::CollapseFullPath(sd.c_str());
lg = this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
FindLocalGenerator(sd.c_str());
}
if (!lg)
{
this->SetError
("DIRECTORY argument provided but requested directory not found. "
"This could be because the directory argument was invalid or, "
"it is valid but has not been processed yet.");
return false;
}
for(j= propertyPairs.begin(); j != propertyPairs.end(); ++j)
{
const char *pn = j->c_str();
++j;
lg->GetMakefile()->SetProperty(pn,j->c_str());
}
}
break;
case cmProperty::GLOBAL:
{
for(j= propertyPairs.begin(); j != propertyPairs.end(); ++j)
{
const char *pn = j->c_str();
++j;
this->Makefile->GetCMakeInstance()->SetProperty(pn, j->c_str());
}
}
break;
case cmProperty::TEST:
{
std::string errors;
bool ret = cmSetTestsPropertiesCommand::
SetOneTest(scopeName,propertyPairs, this->Makefile, errors);
if (!ret)
{
this->SetError(errors.c_str());
return ret;
}
}
break;
case cmProperty::SOURCE_FILE:
{
std::string errors;
bool ret = cmSetSourceFilesPropertiesCommand::
RunCommand(this->Makefile,
args.begin()+1, args.begin()+2,
args.begin() + 2, args.end(),
errors);
if (!ret)
{
this->SetError(errors.c_str());
return ret;
}
}
break;
case cmProperty::VARIABLE:
case cmProperty::CACHED_VARIABLE:
// not handled by SetProperty
break;
}
return true;
}

View File

@ -1,74 +0,0 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef cmSetsPropertiesCommand_h
#define cmSetsPropertiesCommand_h
#include "cmCommand.h"
class cmSetPropertiesCommand : public cmCommand
{
public:
virtual cmCommand* Clone()
{
return new cmSetPropertiesCommand;
}
/**
* This is called when the command is first encountered in
* the input file.
*/
virtual bool InitialPass(std::vector<std::string> const& args);
/**
* The name of the command as specified in CMakeList.txt.
*/
virtual const char* GetName() { return "set_properties";}
/**
* Succinct documentation.
*/
virtual const char* GetTerseDocumentation()
{
return "Set properties used by CMake.";
}
/**
* Longer documentation.
*/
virtual const char* GetFullDocumentation()
{
return
" set_properties(scope_value\n"
" PROPERTIES prop1 value1\n"
" prop2 value2 ...)\n"
"Set properties on something. The scope_value is either GLOBAL, "
"DIRECTORY dir_name, TARGET tgt_name, SOURCE_FILE src_name, "
"or TEST test_name."
;
}
/**
* This determines if the command is invoked when in script mode.
*/
virtual bool IsScriptable() { return true; }
cmTypeMacro(cmSetPropertiesCommand, cmCommand);
};
#endif

View File

@ -0,0 +1,408 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "cmSetPropertyCommand.h"
#include "cmSetTargetPropertiesCommand.h"
#include "cmSetTestsPropertiesCommand.h"
#include "cmSetSourceFilesPropertiesCommand.h"
//----------------------------------------------------------------------------
cmSetPropertyCommand::cmSetPropertyCommand()
{
this->AppendMode = false;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args)
{
if(args.size() < 2 )
{
this->SetError("called with incorrect number of arguments");
return false;
}
// Get the scope on which to set the property.
std::vector<std::string>::const_iterator arg = args.begin();
cmProperty::ScopeType scope;
if(*arg == "GLOBAL")
{
scope = cmProperty::GLOBAL;
}
else if(*arg == "DIRECTORY")
{
scope = cmProperty::DIRECTORY;
}
else if(*arg == "TARGET")
{
scope = cmProperty::TARGET;
}
else if(*arg == "SOURCE")
{
scope = cmProperty::SOURCE_FILE;
}
else if(*arg == "TEST")
{
scope = cmProperty::TEST;
}
else
{
cmOStringStream e;
e << "given invalid scope " << *arg << ". "
<< "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST.";
this->SetError(e.str().c_str());
return false;
}
// Parse the rest of the arguments up to the values.
enum Doing { DoingNone, DoingNames, DoingProperty, DoingValues };
Doing doing = DoingNames;
const char* sep = "";
for(++arg; arg != args.end(); ++arg)
{
if(*arg == "PROPERTY")
{
doing = DoingProperty;
}
else if(*arg == "APPEND")
{
doing = DoingNone;
this->AppendMode = true;
}
else if(doing == DoingNames)
{
this->Names.insert(*arg);
}
else if(doing == DoingProperty)
{
this->PropertyName = *arg;
doing = DoingValues;
}
else if(doing == DoingValues)
{
this->PropertyValue += sep;
sep = ";";
this->PropertyValue += *arg;
}
else
{
cmOStringStream e;
e << "given invalid argument \"" << *arg << "\".";
this->SetError(e.str().c_str());
return false;
}
}
// Make sure a property name was found.
if(this->PropertyName.empty())
{
this->SetError("not given a PROPERTY <name> argument.");
return false;
}
// Dispatch property setting.
switch(scope)
{
case cmProperty::GLOBAL: return this->HandleGlobalMode();
case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
case cmProperty::TARGET: return this->HandleTargetMode();
case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
case cmProperty::TEST: return this->HandleTestMode();
case cmProperty::VARIABLE:
case cmProperty::CACHED_VARIABLE:
break; // should never happen
}
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::ConstructValue(std::string& value,
const char* old)
{
if(this->AppendMode)
{
// This is an append. Start with the original value.
if(old)
{
value = old;
}
}
else if(this->PropertyValue.empty())
{
// This is a set to no values. Remove the property.
return false;
}
// Add the new value.
if(!this->PropertyValue.empty())
{
if(!value.empty())
{
value += ";";
}
value += this->PropertyValue;
}
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleGlobalMode()
{
if(!this->Names.empty())
{
this->SetError("given names for GLOBAL scope.");
return false;
}
// Set or append the property.
cmake* cm = this->Makefile->GetCMakeInstance();
const char* name = this->PropertyName.c_str();
std::string value;
if(this->ConstructValue(value, cm->GetProperty(name)))
{
// Set the new property.
cm->SetProperty(name, value.c_str());
}
else
{
// Remove the property.
cm->SetProperty(name, 0);
}
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleDirectoryMode()
{
if(this->Names.size() > 1)
{
this->SetError("allows at most one name for DIRECTORY scope.");
return false;
}
// Default to the current directory.
cmMakefile* mf = this->Makefile;
// Lookup the directory if given.
if(!this->Names.empty())
{
// Construct the directory name. Interpret relative paths with
// respect to the current directory.
std::string dir = *this->Names.begin();
if(!cmSystemTools::FileIsFullPath(dir.c_str()))
{
dir = this->Makefile->GetCurrentDirectory();
dir += "/";
dir += *this->Names.begin();
}
// The local generators are associated with collapsed paths.
dir = cmSystemTools::CollapseFullPath(dir.c_str());
// Lookup the generator.
if(cmLocalGenerator* lg =
(this->Makefile->GetLocalGenerator()
->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
{
// Use the makefile for the directory found.
mf = lg->GetMakefile();
}
else
{
// Could not find the directory.
this->SetError
("DIRECTORY scope provided but requested directory was not found. "
"This could be because the directory argument was invalid or, "
"it is valid but has not been processed yet.");
return false;
}
}
// Set or append the property.
const char* name = this->PropertyName.c_str();
std::string value;
if(this->ConstructValue(value, mf->GetProperty(name)))
{
// Set the new property.
mf->SetProperty(name, value.c_str());
}
else
{
// Remove the property.
mf->SetProperty(name, 0);
}
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleTargetMode()
{
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
ni != this->Names.end(); ++ni)
{
if(cmTarget* target =
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->FindTarget(0, ni->c_str(), true))
{
// Handle the current target.
if(!this->HandleTarget(target))
{
return false;
}
}
else
{
cmOStringStream e;
e << "could not find TARGET " << *ni
<< ". Perhaps it has not yet been created.";
this->SetError(e.str().c_str());
return false;
}
}
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
{
// Set or append the property.
const char* name = this->PropertyName.c_str();
std::string value;
if(this->ConstructValue(value, target->GetProperty(name)))
{
// Set the new property.
target->SetProperty(name, value.c_str());
}
else
{
// Remove the property.
target->SetProperty(name, 0);
}
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleSourceMode()
{
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
ni != this->Names.end(); ++ni)
{
// Get the source file.
if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(ni->c_str()))
{
if(!this->HandleSource(sf))
{
return false;
}
}
else
{
cmOStringStream e;
e << "given SOURCE name that could not be found or created: " << *ni;
this->SetError(e.str().c_str());
return false;
}
}
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
{
// Set or append the property.
const char* name = this->PropertyName.c_str();
std::string value;
if(this->ConstructValue(value, sf->GetProperty(name)))
{
// Set the new property.
sf->SetProperty(name, value.c_str());
}
else
{
// Remove the property.
sf->SetProperty(name, 0);
}
// TODO: MACOSX_PACKAGE_LOCATION special case in
// cmSetSourceFilesPropertiesCommand
// The logic should be moved to cmSourceFile.
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleTestMode()
{
// Loop over all tests looking for matching names.
std::vector<cmTest*> const& tests = *this->Makefile->GetTests();
for(std::vector<cmTest*>::const_iterator ti = tests.begin();
ti != tests.end(); ++ti)
{
cmTest* test = *ti;
std::set<cmStdString>::const_iterator ni =
this->Names.find(test->GetName());
if(ni != this->Names.end())
{
if(this->HandleTest(test))
{
this->Names.erase(ni);
}
else
{
return false;
}
}
}
// Names that are still left were not found.
if(!this->Names.empty())
{
cmOStringStream e;
e << "given TEST names that do not exist:\n";
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
ni != this->Names.end(); ++ni)
{
e << " " << *ni << "\n";
}
this->SetError(e.str().c_str());
return false;
}
return true;
}
//----------------------------------------------------------------------------
bool cmSetPropertyCommand::HandleTest(cmTest* test)
{
// Set or append the property.
const char* name = this->PropertyName.c_str();
std::string value;
if(this->ConstructValue(value, test->GetProperty(name)))
{
// Set the new property.
test->SetProperty(name, value.c_str());
}
else
{
// Remove the property.
test->SetProperty(name, 0);
}
return true;
}

View File

@ -0,0 +1,112 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef cmSetsPropertiesCommand_h
#define cmSetsPropertiesCommand_h
#include "cmCommand.h"
class cmSetPropertyCommand : public cmCommand
{
public:
cmSetPropertyCommand();
virtual cmCommand* Clone()
{
return new cmSetPropertyCommand;
}
/**
* This is called when the command is first encountered in
* the input file.
*/
virtual bool InitialPass(std::vector<std::string> const& args);
/**
* The name of the command as specified in CMakeList.txt.
*/
virtual const char* GetName() { return "set_property";}
/**
* Succinct documentation.
*/
virtual const char* GetTerseDocumentation()
{
return "Set a named property in a given scope.";
}
/**
* Longer documentation.
*/
virtual const char* GetFullDocumentation()
{
return
" set_property(<GLOBAL |\n"
" DIRECTORY [dir] |\n"
" TARGET [target1 [target2 ...]] |\n"
" SOURCE [src1 [src2 ...]] |\n"
" TEST [test1 [test2 ...]]>\n"
" [APPEND]\n"
" PROPERTY <name> [value1 [value2 ...]])\n"
"Set one property on zero or more objects of a scope. "
"The first argument determines the scope in which the property "
"is set. It must be one of the following:\n"
"GLOBAL scope is unique and does not accept a name.\n"
"DIRECTORY scope defaults to the current directory but another "
"directory (already processed by CMake) may be named by full or "
"relative path.\n"
"TARGET scope may name zero or more existing targets.\n"
"SOURCE scope may name zero or more source files.\n"
"TEST scope may name zero or more existing tests.\n"
"The required PROPERTY option is immediately followed by the name "
"of the property to set. Remaining arguments are used to "
"compose the property value in the form of a semicolon-separated "
"list. "
"If the APPEND option is given the list is appended to any "
"existing property value."
;
}
/**
* This determines if the command is invoked when in script mode.
*/
virtual bool IsScriptable() { return true; }
cmTypeMacro(cmSetPropertyCommand, cmCommand);
private:
std::set<cmStdString> Names;
std::string PropertyName;
std::string PropertyValue;
bool AppendMode;
// Implementation of value construction.
bool ConstructValue(std::string& value, const char* old);
// Implementation of each property type.
bool HandleGlobalMode();
bool HandleDirectoryMode();
bool HandleTargetMode();
bool HandleTarget(cmTarget* target);
bool HandleSourceMode();
bool HandleSource(cmSourceFile* sf);
bool HandleTestMode();
bool HandleTest(cmTest* test);
};
#endif

View File

@ -2,5 +2,5 @@ project (DocTest)
add_executable (DocTest DocTest.cxx) add_executable (DocTest DocTest.cxx)
set_properties(GLOBAL PROPERTIES REPORT_UNDEFINED_PROPERTIES set_property(GLOBAL PROPERTY REPORT_UNDEFINED_PROPERTIES
"${CMAKE_CURRENT_BINARY_DIR}/UndefinedProperties.txt") "${CMAKE_CURRENT_BINARY_DIR}/UndefinedProperties.txt")

View File

@ -24,10 +24,9 @@ include_directories("${Properties_SOURCE_DIR}" "${Properties_BINARY_DIR}")
# test generic property interfaces # test generic property interfaces
define_property(GLOBALTEST GLOBAL "A test property" define_property(GLOBALTEST GLOBAL "A test property"
"A long description of this test property" 0) "A long description of this test property" 0)
set_properties(GLOBAL PROPERTIES GLOBALTEST 1) set_property(GLOBAL PROPERTY GLOBALTEST 1)
set_properties(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" set_property(DIRECTORY PROPERTY DIRECTORYTEST 1)
PROPERTIES DIRECTORYTEST 1) set_property(SOURCE SubDir/properties3.cxx PROPERTY SOURCETEST 1)
set_properties(SOURCE_FILE SubDir/properties3.cxx PROPERTIES SOURCETEST 1)
get_property(GLOBALRESULT GLOBAL GLOBALTEST) get_property(GLOBALRESULT GLOBAL GLOBALTEST)
get_property(DIRECTORYRESULT DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" get_property(DIRECTORYRESULT DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DIRECTORYTEST) DIRECTORYTEST)
@ -46,7 +45,7 @@ endif (RESULT1 AND RESULT2 AND RESULT3 AND GLOBALRESULT AND
DIRECTORYRESULT AND SOURCE_FILERESULT) DIRECTORYRESULT AND SOURCE_FILERESULT)
# test the target property # test the target property
set_properties(TARGET Properties PROPERTIES TARGETTEST 1) set_property(TARGET Properties PROPERTY TARGETTEST 1)
get_property(TARGETRESULT TARGET Properties TARGETTEST) get_property(TARGETRESULT TARGET Properties TARGETTEST)
if (NOT TARGETRESULT) if (NOT TARGETRESULT)
message("Error: target result is TARGETRESULT=${TARGETRESULT}") message("Error: target result is TARGETRESULT=${TARGETRESULT}")