From fdbfcfdf0173c34845e495f4c0bd407faafc45b4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 22 Dec 2014 19:41:17 -0500 Subject: [PATCH 1/2] Ninja: Generate rules only for languages compiled in a target (#15325) Refactoring in commit v3.1.0-rc1~688^2~2 (cmTarget: Compute languages from object libraries on demand, 2014-03-18) taught cmTarget::GetLanguages to (correctly) include the languages of object library sources. Previously this was done only in cmTarget::ComputeLinkImplementationLanguages to choose the linker language. The Ninja generator writes out generic build rules for each language compiled within a target using the rule variables defined in the directory of the target. This only needs to be done for languages actually compiled within the current target. Switch from using the cmTarget::GetLanguages method to get the list of languages over to using cmTarget::GetSourceFiles directly so we do not get the languages in object libraries. Strictly speaking this should make no difference because it is not safe to use objects from a language not enabled in the directory containing a target or else the link information for the language may not be considered. However, in cases when no link information happens to be needed for a language it was possible in CMake 3.0 and below to enable a language only in a subdirectory providing an object library, and then use the objects from a containing directory. The above change teaches the Ninja generator to continue working in this case. --- Source/cmNinjaNormalTargetGenerator.cxx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index e344df4f3..a05719d8d 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -110,13 +110,26 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules() << "\n\n"; #endif + // Write rules for languages compiled in this target. std::set languages; - this->GetTarget()->GetLanguages(languages, - this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE")); + std::vector sourceFiles; + this->GetTarget()->GetSourceFiles(sourceFiles, + this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE")); + for(std::vector::const_iterator + i = sourceFiles.begin(); i != sourceFiles.end(); ++i) + { + const std::string& lang = (*i)->GetLanguage(); + if(!lang.empty()) + { + languages.insert(lang); + } + } for(std::set::const_iterator l = languages.begin(); l != languages.end(); ++l) + { this->WriteLanguageRules(*l); + } } const char *cmNinjaNormalTargetGenerator::GetVisibleTypeName() const From 07fc7b75ef981300e7d873091ee90083b18d1c4a Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 22 Dec 2014 19:55:08 -0500 Subject: [PATCH 2/2] Tests: Test using objects from a language enabled in a subdirectory (#15325) Add a test case that enables CXX in the top level and C in a subdirectory. Create an executable in the top level that uses C objects compiled in the subdirectory. Strictly speaking this is not defined behavior for all language combinations, but happens to work in this case. Test this behavior since projects might try to use it. --- Tests/CMakeLists.txt | 1 + Tests/CxxSubdirC/CMakeLists.txt | 4 ++++ Tests/CxxSubdirC/Cdir/CMakeLists.txt | 2 ++ Tests/CxxSubdirC/Cdir/Cobj.c | 1 + Tests/CxxSubdirC/main.cxx | 2 ++ 5 files changed, 10 insertions(+) create mode 100644 Tests/CxxSubdirC/CMakeLists.txt create mode 100644 Tests/CxxSubdirC/Cdir/CMakeLists.txt create mode 100644 Tests/CxxSubdirC/Cdir/Cobj.c create mode 100644 Tests/CxxSubdirC/main.cxx diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index a9cad1456..f6543304f 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -255,6 +255,7 @@ if(BUILD_TESTING) endif() ADD_TEST_MACRO(COnly COnly) ADD_TEST_MACRO(CxxOnly CxxOnly) + ADD_TEST_MACRO(CxxSubdirC CxxSubdirC) ADD_TEST_MACRO(IPO COnly/COnly) ADD_TEST_MACRO(OutDir runtime/OutDir) ADD_TEST_MACRO(ObjectLibrary UseCshared) diff --git a/Tests/CxxSubdirC/CMakeLists.txt b/Tests/CxxSubdirC/CMakeLists.txt new file mode 100644 index 000000000..52474f8dc --- /dev/null +++ b/Tests/CxxSubdirC/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.0) +project(CxxSubdirC CXX) +add_subdirectory(Cdir) +add_executable(CxxSubdirC main.cxx $) diff --git a/Tests/CxxSubdirC/Cdir/CMakeLists.txt b/Tests/CxxSubdirC/Cdir/CMakeLists.txt new file mode 100644 index 000000000..08a87579b --- /dev/null +++ b/Tests/CxxSubdirC/Cdir/CMakeLists.txt @@ -0,0 +1,2 @@ +enable_language(C) +add_library(Cobj OBJECT Cobj.c) diff --git a/Tests/CxxSubdirC/Cdir/Cobj.c b/Tests/CxxSubdirC/Cdir/Cobj.c new file mode 100644 index 000000000..75a00458b --- /dev/null +++ b/Tests/CxxSubdirC/Cdir/Cobj.c @@ -0,0 +1 @@ +int Cobj(void) { return 0; } diff --git a/Tests/CxxSubdirC/main.cxx b/Tests/CxxSubdirC/main.cxx new file mode 100644 index 000000000..049220f11 --- /dev/null +++ b/Tests/CxxSubdirC/main.cxx @@ -0,0 +1,2 @@ +extern "C" int Cobj(void); +int main() { return Cobj(); }