diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 7622cf231..830be0cf7 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -287,7 +287,8 @@ bool cmGetPropertyCommand::HandleSourceMode() if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(this->Name.c_str())) { - return this->StoreResult(sf->GetProperty(this->PropertyName.c_str())); + return + this->StoreResult(sf->GetPropertyForUser(this->PropertyName.c_str())); } else { diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx index a291a0c2f..b89573521 100644 --- a/Source/cmGetSourceFilePropertyCommand.cxx +++ b/Source/cmGetSourceFilePropertyCommand.cxx @@ -38,24 +38,12 @@ bool cmGetSourceFilePropertyCommand } if(sf) { - if(args[2] == "LOCATION") - { - // Make sure the location is known. Update: this is a hack to work - // around a problem with const methods in cmSourceFile, by design - // GetProperty("LOCATION") should work but right now it has to be - // "primed" by calling GetFullPath() first on a non-const cmSourceFile - // instance. This is because LOCATION is a computed-on-demand - // property. Either GetProperty needs to be non-const or the map - // needs to be changed to be mutable etc. for computed properties to - // work properly. - sf->GetFullPath(); - } - else if(args[2] == "LANGUAGE") + if(args[2] == "LANGUAGE") { this->Makefile->AddDefinition(var, sf->GetLanguage()); return true; } - const char *prop = sf->GetProperty(args[2].c_str()); + const char *prop = sf->GetPropertyForUser(args[2].c_str()); if (prop) { this->Makefile->AddDefinition(var, prop); diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 48f975df7..da2664fb7 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -280,6 +280,33 @@ void cmSourceFile::AppendProperty(const char* prop, const char* value) this->Properties.AppendProperty(prop, value, cmProperty::SOURCE_FILE); } +//---------------------------------------------------------------------------- +const char* cmSourceFile::GetPropertyForUser(const char *prop) +{ + // This method is a consequence of design history and backwards + // compatibility. GetProperty is (and should be) a const method. + // Computed properties should not be stored back in the property map + // but instead reference information already known. If they need to + // cache information in a mutable ivar to provide the return string + // safely then so be it. + // + // The LOCATION property is particularly problematic. The CMake + // language has very loose restrictions on the names that will match + // a given source file (for historical reasons). Implementing + // lookups correctly with such loose naming requires the + // cmSourceFileLocation class to commit to a particular full path to + // the source file as late as possible. If the users requests the + // LOCATION property we must commit now. + if(strcmp(prop, "LOCATION") == 0) + { + // Commit to a location. + this->GetFullPath(); + } + + // Perform the normal property lookup. + return this->GetProperty(prop); +} + //---------------------------------------------------------------------------- const char* cmSourceFile::GetProperty(const char* prop) const { diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 423e44030..1eca56ef3 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -53,6 +53,10 @@ public: const char *GetProperty(const char *prop) const; bool GetPropertyAsBool(const char *prop) const; + /** Implement getting a property when called from a CMake language + command like get_property or get_source_file_property. */ + const char* GetPropertyForUser(const char *prop); + /** * The full path to the file. The non-const version of this method * may attempt to locate the file on disk and finalize its location.