From 328c0f65c2a273c6adcdb11f96ee057d80014de2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 19 Mar 2012 11:25:21 -0400 Subject: Simplify cmVisualStudio10TargetGenerator source classification Combine WriteCLSources and WriteObjSources into a single method. Use the cmGeneratorTarget source classification to simplify tool selection for each source file. Extend the classification to handle .idl files. --- Source/cmGeneratorTarget.cxx | 11 ++- Source/cmGeneratorTarget.h | 1 + Source/cmVisualStudio10TargetGenerator.cxx | 143 +++++++++++------------------ Source/cmVisualStudio10TargetGenerator.h | 5 +- 4 files changed, 69 insertions(+), 91 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 4529d1c..7979928 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -37,6 +37,7 @@ void cmGeneratorTarget::ClassifySources() si != sources.end(); ++si) { cmSourceFile* sf = *si; + std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); cmTarget::SourceFileFlags tsFlags = this->Target->GetTargetSourceFileFlags(sf); if(sf->GetCustomCommand()) @@ -57,16 +58,22 @@ void cmGeneratorTarget::ClassifySources() this->ExternalObjects.push_back(sf); if(isObjLib) { badObjLib.push_back(sf); } } - else if(cmSystemTools::LowerCase(sf->GetExtension()) == "def") + else if(ext == "def") { this->ModuleDefinitionFile = sf->GetFullPath(); if(isObjLib) { badObjLib.push_back(sf); } } + else if(ext == "idl") + { + this->IDLSources.push_back(sf); + if(isObjLib) { badObjLib.push_back(sf); } + } else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) { // We only get here if a source file is not an external object // and has an extension that is listed as an ignored file type. // No message or diagnosis should be given. + this->ExtraSources.push_back(sf); } else if(sf->GetLanguage()) { @@ -75,7 +82,7 @@ void cmGeneratorTarget::ClassifySources() else { this->ExtraSources.push_back(sf); - if(isObjLib && cmSystemTools::LowerCase(sf->GetExtension()) != "txt") + if(isObjLib && ext != "txt") { badObjLib.push_back(sf); } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 6319d82..3e50656 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -38,6 +38,7 @@ public: std::vector ObjectSources; std::vector ExternalObjects; std::vector OSXContent; + std::vector IDLSources; std::string ModuleDefinitionFile; std::map Objects; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 054b86b..88ad178 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -253,8 +253,7 @@ void cmVisualStudio10TargetGenerator::Generate() this->WritePathAndIncrementalLinkOptions(); this->WriteItemDefinitionGroups(); this->WriteCustomCommands(); - this->WriteObjSources(); - this->WriteCLSources(); + this->WriteAllSources(); this->WriteDotNetReferences(); this->WriteWinRTReferences(); this->WriteProjectReferences(); @@ -795,107 +794,56 @@ WriteGroupSources(const char* name, this->WriteString("\n", 1); } -void cmVisualStudio10TargetGenerator::WriteObjSources() -{ - if(this->Target->GetType() > cmTarget::MODULE_LIBRARY) - { - return; - } - bool first = true; - std::vectorconst & sources = this->Target->GetSourceFiles(); - for(std::vector::const_iterator source = sources.begin(); - source != sources.end(); ++source) - { - std::string ext = - cmSystemTools::LowerCase((*source)->GetExtension()); - if(ext == "obj" || ext == "o") - { - if(first) - { - this->WriteString("\n", 1); - first = false; - } - // If an object file is generated, then vs10 - // will use it in the build, and we have to list - // it as None instead of Object - if((*source)->GetPropertyAsBool("GENERATED")) - { - this->WriteString("WriteString("BuildFileStream ) << (*source)->GetFullPath() << "\" />\n"; - } - } - if(!first) +void cmVisualStudio10TargetGenerator::WriteSource( + const char* tool, cmSourceFile* sf, bool end) +{ + std::string sourceFile = sf->GetFullPath(); + // do not use a relative path here because it means that you + // can not use as long a path to the file. + this->ConvertToWindowsSlash(sourceFile); + this->WriteString("<", 2); + (*this->BuildFileStream ) << tool << + " Include=\"" << sourceFile << (end? "\" />\n" : "\" "); +} + +void cmVisualStudio10TargetGenerator::WriteSources( + const char* tool, std::vector const& sources) +{ + for(std::vector::const_iterator + si = sources.begin(); si != sources.end(); ++si) { - this->WriteString("\n", 1); + this->WriteSource(tool, *si); } } - -void cmVisualStudio10TargetGenerator::WriteCLSources() +void cmVisualStudio10TargetGenerator::WriteAllSources() { if(this->Target->GetType() > cmTarget::UTILITY) { return; } this->WriteString("\n", 1); - std::vectorconst& sources = this->Target->GetSourceFiles(); - for(std::vector::const_iterator source = sources.begin(); - source != sources.end(); ++source) - { - std::string ext = cmSystemTools::LowerCase((*source)->GetExtension()); - if((*source)->GetCustomCommand() || ext == "o" || ext == "obj") - { - continue; - } - // If it is not a custom command and it is not a pre-built obj file, - // then add it as a source (c/c++/header/rc/idl) file - bool header = (*source)->GetPropertyAsBool("HEADER_FILE_ONLY") - || this->GlobalGenerator->IgnoreFile(ext.c_str()); - const char* lang = (*source)->GetLanguage(); - bool cl = lang && (strcmp(lang, "C") == 0 || strcmp(lang, "CXX") ==0); - bool rc = lang && (strcmp(lang, "RC") == 0); - bool idl = ext == "idl"; - std::string sourceFile = (*source)->GetFullPath(); - // do not use a relative path here because it means that you - // can not use as long a path to the file. - this->ConvertToWindowsSlash(sourceFile); - // output the source file - if(header) - { - this->WriteString("WriteString("WriteString("WriteString("WriteString("BuildFileStream ) << sourceFile << "\""; + + this->WriteSources("ClInclude", this->GeneratorTarget->HeaderSources); + this->WriteSources("Midl", this->GeneratorTarget->IDLSources); + + for(std::vector::const_iterator + si = this->GeneratorTarget->ObjectSources.begin(); + si != this->GeneratorTarget->ObjectSources.end(); ++si) + { + const char* lang = (*si)->GetLanguage(); + bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0; + bool rc = strcmp(lang, "RC") == 0; + const char* tool = cl? "ClCompile" : (rc? "ResourceCompile" : "None"); + this->WriteSource(tool, *si, false); // ouput any flags specific to this source file - if(!header && cl && this->OutputSourceSpecificFlags(*source)) + if(cl && this->OutputSourceSpecificFlags(*si)) { // if the source file has specific flags the tag // is ended on a new line this->WriteString("\n", 2); } - else if(!header && rc && this->OutputSourceSpecificFlags(*source)) + else if(rc && this->OutputSourceSpecificFlags(*si)) { this->WriteString("\n", 2); } @@ -905,6 +853,27 @@ void cmVisualStudio10TargetGenerator::WriteCLSources() } } + for(std::vector::const_iterator + si = this->GeneratorTarget->ExternalObjects.begin(); + si != this->GeneratorTarget->ExternalObjects.end(); ++si) + { + // If an object file is generated, then vs10 + // will use it in the build, and we have to list + // it as None instead of Object + if((*si)->GetPropertyAsBool("GENERATED")) + { + this->WriteSource("None", *si); + } + // If it is not a generated object then we have + // to use the Object type + else + { + this->WriteSource("Object", *si); + } + } + + this->WriteSources("None", this->GeneratorTarget->ExtraSources); + // Add object library contents as external objects. std::vector objs; this->GeneratorTarget->UseObjectLibraries(objs); diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 64fb124..20a443b 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -47,10 +47,11 @@ private: void WriteString(const char* line, int indentLevel); void WriteProjectConfigurations(); void WriteProjectConfigurationValues(); - void WriteCLSources(); + void WriteSource(const char* tool, cmSourceFile* sf, bool end = true); + void WriteSources(const char* tool, std::vector const&); + void WriteAllSources(); void WriteDotNetReferences(); void WriteWinRTReferences(); - void WriteObjSources(); void WritePathAndIncrementalLinkOptions(); void WriteItemDefinitionGroups(); bool ComputeClOptions(); -- cgit v0.12 From b291d9e756b76ce85ebcc314c14de532e8ad477f Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 19 Mar 2012 17:14:52 -0400 Subject: VS10: Fix external objects generated outside target (#13047) Commit 9a6ff950 (Fix for bug where VS2010 did not use .obj files, 2011-04-01) assumed that if an external object is GENERATED that it is the output of a custom command in the current target. If it is generated by another target then VS will not automatically include the external object in the current target. This bug was preserved by the refactoring in the parent commit. Instead use for external objects generated by a custom command in the current target and for all other external objects. Update the ExternalOBJ test to cover this case. --- Source/cmVisualStudio10TargetGenerator.cxx | 17 ++++------------- Tests/ExternalOBJ/CMakeLists.txt | 2 ++ Tests/ExternalOBJ/Sub/CMakeLists.txt | 3 +++ 3 files changed, 9 insertions(+), 13 deletions(-) create mode 100644 Tests/ExternalOBJ/Sub/CMakeLists.txt diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 88ad178..6caaad1 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -857,19 +857,10 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() si = this->GeneratorTarget->ExternalObjects.begin(); si != this->GeneratorTarget->ExternalObjects.end(); ++si) { - // If an object file is generated, then vs10 - // will use it in the build, and we have to list - // it as None instead of Object - if((*si)->GetPropertyAsBool("GENERATED")) - { - this->WriteSource("None", *si); - } - // If it is not a generated object then we have - // to use the Object type - else - { - this->WriteSource("Object", *si); - } + // If an object file is generated in this target, then vs10 will use + // it in the build, and we have to list it as None instead of Object. + std::vector const* d = this->Target->GetSourceDepends(*si); + this->WriteSource((d && !d->empty())? "None":"Object", *si); } this->WriteSources("None", this->GeneratorTarget->ExtraSources); diff --git a/Tests/ExternalOBJ/CMakeLists.txt b/Tests/ExternalOBJ/CMakeLists.txt index f12de11..683e799 100644 --- a/Tests/ExternalOBJ/CMakeLists.txt +++ b/Tests/ExternalOBJ/CMakeLists.txt @@ -59,3 +59,5 @@ ADD_EXECUTABLE(ExternalOBJ executable.cxx ${CUSTOM_OBJECT}) # not didn't work. So, repeat the executable using the object # directly and not from the output of the copy. ADD_EXECUTABLE(ExternalOBJ2 executable.cxx ${EXTERNAL_OBJECT}) + +ADD_SUBDIRECTORY(Sub) diff --git a/Tests/ExternalOBJ/Sub/CMakeLists.txt b/Tests/ExternalOBJ/Sub/CMakeLists.txt new file mode 100644 index 0000000..35cd30c --- /dev/null +++ b/Tests/ExternalOBJ/Sub/CMakeLists.txt @@ -0,0 +1,3 @@ +set_property(SOURCE ${CUSTOM_OBJECT} PROPERTY GENERATED 1) +add_executable(ExternalOBJSub ../executable.cxx ${CUSTOM_OBJECT}) +add_dependencies(ExternalOBJSub ExternalOBJ) # depend on generating target -- cgit v0.12