Browse Source

ENH: different way of testing properties

Ken Martin 18 years ago
parent
commit
433a914910
5 changed files with 154 additions and 74 deletions
  1. 42 0
      Source/cmDocumentVariables.cxx
  2. 6 12
      Source/cmMakefile.cxx
  3. 4 62
      Source/cmPropertyMap.cxx
  4. 97 0
      Source/cmake.cxx
  5. 5 0
      Source/cmake.h

+ 42 - 0
Source/cmDocumentVariables.cxx

@@ -936,4 +936,46 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
   cm->DefineProperty("CMAKE_MATCH_7", cmProperty::VARIABLE,0,0);  
   cm->DefineProperty("CMAKE_MATCH_8", cmProperty::VARIABLE,0,0);  
   cm->DefineProperty("CMAKE_MATCH_9", cmProperty::VARIABLE,0,0);  
+
+  cm->DefineProperty("CMAKE_<LANG>_COMPILER_ARG1", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_COMPILER_ENV_VAR", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_COMPILER_ID_RUN", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_COMPILER_LOADED", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_CREATE_ASSEMBLY_SOURCE", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_CREATE_PREPROCESSED_SOURCE", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_FLAGS_DEBUG_INIT", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_FLAGS_INIT", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_FLAGS_MINSIZEREL_INIT", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_FLAGS_RELEASE_INIT", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_FLAGS_RELWITHDEBINFO_INIT", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_INFORMATION_LOADED", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_LINK_EXECUTABLE", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_LINK_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_STANDARD_LIBRARIES", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_<LANG>_STANDARD_LIBRARIES_INIT", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_EXECUTABLE_SUFFIX_<LANG>", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_EXE_LINK_DYNAMIC_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_EXE_LINK_STATIC_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_GENERATOR_<LANG>", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_IMPORT_LIBRARY_PREFIX_<LANG>", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_IMPORT_LIBRARY_SUFFIX_<LANG>", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_INCLUDE_FLAG_<LANG>", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_INCLUDE_FLAG_SEP_<LANG>", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_INCLUDE_SYSTEM_FLAG_<LANG>", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_NEEDS_REQUIRES_STEP_<LANG>_FLAG", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_LIBRARY_CREATE_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_LIBRARY_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_LIBRARY_LINK_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_LIBRARY_LINK_STATIC_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_LIBRARY_RUNTIME_<LANG>_FLAG", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_LIBRARY_RUNTIME_<LANG>_FLAG_SEP", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_MODULE_CREATE_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_MODULE_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_MODULE_LINK_DYNAMIC_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_MODULE_LINK_STATIC_<LANG>_FLAGS", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_MODULE_RUNTIME_<LANG>_FLAG", cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_MODULE_RUNTIME_<LANG>_FLAG_SEP", cmProperty::VARIABLE,0,0);
+
 }

+ 6 - 12
Source/cmMakefile.cxx

@@ -1217,13 +1217,10 @@ void cmMakefile::AddDefinition(const char* name, const char* value)
     }
 
 #ifdef CMAKE_STRICT
-  if (this->GetCMakeInstance() &&
-      !this->GetCMakeInstance()->IsPropertyDefined(name,cmProperty::VARIABLE))
+  if (this->GetCMakeInstance())
     {
-    std::string msg = "Variable ";
-    msg += name;
-    msg += " set yet not defined!";
-    cmSystemTools::Error(msg.c_str()); 
+    this->GetCMakeInstance()->
+      RecordPropertyAccess(name,cmProperty::VARIABLE);
     }
 #endif
 
@@ -1682,13 +1679,10 @@ bool cmMakefile::IsDefinitionSet(const char* name) const
 const char* cmMakefile::GetDefinition(const char* name) const
 {
 #ifdef CMAKE_STRICT
-  if (this->GetCMakeInstance() &&
-      !this->GetCMakeInstance()->IsPropertyDefined(name,cmProperty::VARIABLE))
+  if (this->GetCMakeInstance())
     {
-    std::string msg = "Variable ";
-    msg += name;
-    msg += " queried yet undefined!";
-    cmSystemTools::Error(msg.c_str()); 
+    this->GetCMakeInstance()->
+      RecordPropertyAccess(name,cmProperty::VARIABLE);
     }
 #endif
   const char* def = 0;

+ 4 - 62
Source/cmPropertyMap.cxx

@@ -51,38 +51,9 @@ void cmPropertyMap::SetProperty(const char *name, const char *value,
     cmSystemTools::Error("CMakeInstance not set on a property map!"); 
     abort();
     }
-  else if (!this->CMakeInstance->IsPropertyDefined(name,scope))
+  else
     {
-    // is a property being queried without being defined first? If so then
-    // report it as we probably need to document it
-    std::string msg = "Property ";
-    msg += name;
-    msg += " set yet undefined on ";
-    switch (scope)
-      {
-      case cmProperty::TARGET: 
-        msg += "target.";
-        break;
-      case cmProperty::SOURCE_FILE:
-        msg += "source file.";
-        break;
-      case cmProperty::DIRECTORY:
-        msg += "directory.";
-        break;
-      case cmProperty::TEST:
-        msg += "test.";
-        break;
-      case cmProperty::VARIABLE:
-        msg += "variable.";
-        break;
-      case cmProperty::CACHED_VARIABLE:
-        msg += "cached variable.";
-        break;
-      default:
-        msg += "unknown.";
-        break;
-      }
-    cmSystemTools::Error(msg.c_str()); 
+    this->CMakeInstance->RecordPropertyAccess(name,scope);
     }
 #else
   (void)scope;
@@ -110,38 +81,9 @@ const char *cmPropertyMap
     cmSystemTools::Error("CMakeInstance not set on a property map!"); 
     abort();
     }
-  else if (!this->CMakeInstance->IsPropertyDefined(name,scope))
+  else
     {
-    // is a property being queried without being defined first? If so then
-    // report it as we probably need to document it
-    std::string msg = "Property ";
-    msg += name;
-    msg += " queried yet undefined on ";
-    switch (scope)
-      {
-      case cmProperty::TARGET: 
-        msg += "target.";
-        break;
-      case cmProperty::SOURCE_FILE:
-        msg += "source file.";
-        break;
-      case cmProperty::DIRECTORY:
-        msg += "directory.";
-        break;
-      case cmProperty::TEST:
-        msg += "test.";
-        break;
-      case cmProperty::VARIABLE:
-        msg += "variable.";
-        break;
-      case cmProperty::CACHED_VARIABLE:
-        msg += "cached variable.";
-        break;
-      default:
-        msg += "unknown.";
-        break;
-      }
-    cmSystemTools::Error(msg.c_str()); 
+    this->CMakeInstance->RecordPropertyAccess(name,scope);
     }
 #endif
 

+ 97 - 0
Source/cmake.cxx

@@ -2084,6 +2084,11 @@ int cmake::Generate()
     {
     return -1;
     }
+  if (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"))
+    {
+    this->ReportUndefinedPropertyAccesses
+      (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"));
+    }
   return 0;
 }
 
@@ -3033,6 +3038,14 @@ int cmake::ExecuteLinkScript(std::vector<std::string>& args)
 
 void cmake::DefineProperties(cmake *cm)
 {
+  cm->DefineProperty
+    ("REPORT_UNDEFINED_PROPERTIES", cmProperty::GLOBAL, 
+     "If set, report any undefined properties to this file.",
+     "If this property is set to a filename then when CMake runs "
+     "it will report any properties or variables that were accessed "
+     "but not defined into the filename specified in this property."
+     );
+
   cm->DefineProperty
     ("TARGET_SUPPORTS_SHARED_LIBS", cmProperty::GLOBAL, 
      "Does the target platform support shared libraries.",
@@ -3104,6 +3117,90 @@ cmPropertyDefinition *cmake
   return 0;
 }
 
+void cmake::RecordPropertyAccess(const char *name, 
+                                 cmProperty::ScopeType scope)
+{
+  this->AccessedProperties.insert
+    (std::pair<cmStdString,cmProperty::ScopeType>(name,scope));
+}
+
+void cmake::ReportUndefinedPropertyAccesses(const char *filename)
+{
+  FILE *progFile = fopen(filename,"w");
+  if (!progFile || !this->GlobalGenerator)
+    {
+    return;
+    }
+
+  // what are the enabled languages?
+  std::vector<std::string> enLangs;
+  this->GlobalGenerator->GetEnabledLanguages(enLangs);
+
+  // take all the defined properties and add definitions for all the enabled
+  // languages
+  std::set<std::pair<cmStdString,cmProperty::ScopeType> > aliasedProperties;
+  std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::iterator i;
+  i = this->PropertyDefinitions.begin();
+  for (;i != this->PropertyDefinitions.end(); ++i)
+    {
+    cmPropertyDefinitionMap::iterator j;
+    for (j = i->second.begin(); j != i->second.end(); ++j)
+      {
+      if (j->first.find("<LANG>"))
+        {
+        std::vector<std::string>::const_iterator k;
+        for (k = enLangs.begin(); k != enLangs.end(); ++k)
+          {
+          std::string tmp = j->first;
+          cmSystemTools::ReplaceString(tmp, "<LANG>", k->c_str());
+          // add alias
+          aliasedProperties.insert
+            (std::pair<cmStdString,cmProperty::ScopeType>(tmp,i->first));
+          }
+        }
+      }
+    }
+
+  std::set<std::pair<cmStdString,cmProperty::ScopeType> >::const_iterator ap;
+  ap = this->AccessedProperties.begin();
+  for (;ap != this->AccessedProperties.end(); ++ap)
+    {
+    if (!this->IsPropertyDefined(ap->first.c_str(),ap->second) &&
+        aliasedProperties.find(std::pair<cmStdString,cmProperty::ScopeType>
+                               (ap->first,ap->second)) == 
+        aliasedProperties.end())
+      {
+      const char *scopeStr = "";
+      switch (ap->second)
+        {
+        case cmProperty::TARGET: 
+          scopeStr = "TARGET";
+          break;
+        case cmProperty::SOURCE_FILE:
+          scopeStr = "SOURCE_FILE";
+        break;
+        case cmProperty::DIRECTORY:
+          scopeStr = "DIRECTORY";
+          break;
+        case cmProperty::TEST:
+          scopeStr = "TEST";
+          break;
+        case cmProperty::VARIABLE:
+          scopeStr = "VARIABLE";
+          break;
+        case cmProperty::CACHED_VARIABLE:
+          scopeStr = "CACHED_VARIABLE";
+          break;
+        default:
+          scopeStr = "unknown";
+        break;
+        }
+      fprintf(progFile,"%s with scope %s\n",ap->first.c_str(),scopeStr);
+      }
+    }
+  fclose(progFile);
+}
+
 bool cmake::IsPropertyDefined(const char *name, cmProperty::ScopeType scope)
 {
   return this->PropertyDefinitions[scope].IsPropertyDefined(name);

+ 5 - 0
Source/cmake.h

@@ -320,11 +320,16 @@ class cmake
   bool IsPropertyDefined(const char *name, cmProperty::ScopeType scope);
   bool IsPropertyChained(const char *name, cmProperty::ScopeType scope);
 
+  // record accesses of properties and variables
+  void RecordPropertyAccess(const char *name, cmProperty::ScopeType scope);
+  void ReportUndefinedPropertyAccesses(const char *filename);
+
   // Define the properties
   static void DefineProperties(cmake *cm);
 
 protected:
   cmPropertyMap Properties;
+  std::set<std::pair<cmStdString,cmProperty::ScopeType> > AccessedProperties;
 
   std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> 
   PropertyDefinitions;