From 2870a6754085b981d72236c3b716627929e2d9b4 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 21 Jul 2023 16:46:06 -0400 Subject: Tests/FortranOnly: add a test case for issue #25112 Add a test case for Fortran `OBJECT` libraries providing modules to consumers. --- Tests/FortranOnly/CMakeLists.txt | 6 ++++++ Tests/FortranOnly/objmain.f90 | 5 +++++ Tests/FortranOnly/objmod.f90 | 7 +++++++ 3 files changed, 18 insertions(+) create mode 100644 Tests/FortranOnly/objmain.f90 create mode 100644 Tests/FortranOnly/objmod.f90 diff --git a/Tests/FortranOnly/CMakeLists.txt b/Tests/FortranOnly/CMakeLists.txt index ed2a440..b092c42 100644 --- a/Tests/FortranOnly/CMakeLists.txt +++ b/Tests/FortranOnly/CMakeLists.txt @@ -184,3 +184,9 @@ if(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF AND set_property(TARGET no_preprocess_target PROPERTY Fortran_PREPROCESS OFF) set_property(SOURCE no_preprocess_source_upper.F no_preprocess_source_fpp.fpp PROPERTY Fortran_PREPROCESS OFF) endif() + +# Issue 25112 +set(CMAKE_Fortran_MODULE_DIRECTORY "${PROJECT_BINARY_DIR}/include") +add_library(objmod OBJECT objmod.f90) +add_executable(objmain objmain.f90) +target_link_libraries(objmain PRIVATE objmod) diff --git a/Tests/FortranOnly/objmain.f90 b/Tests/FortranOnly/objmain.f90 new file mode 100644 index 0000000..d41d454 --- /dev/null +++ b/Tests/FortranOnly/objmain.f90 @@ -0,0 +1,5 @@ +program main + use objmod, only : hello + implicit none + call hello() +end program diff --git a/Tests/FortranOnly/objmod.f90 b/Tests/FortranOnly/objmod.f90 new file mode 100644 index 0000000..6b79cc7 --- /dev/null +++ b/Tests/FortranOnly/objmod.f90 @@ -0,0 +1,7 @@ +module objmod + implicit none +contains + subroutine hello() + print '(a)', "hello world" + end subroutine hello +end module objmod -- cgit v0.12 From a99b87a6285d9801ed429d5f44308b24c4706fb8 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 22 Jul 2023 06:45:30 -0400 Subject: Tests/RunCMake/CXXModules: add a test for issue #25112 Add a test case for C++ `OBJECT` libraries providing modules to consumers. --- Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 1 + .../CXXModules/examples/object-library-stderr.txt | 4 ++++ .../examples/object-library/CMakeLists.txt | 22 ++++++++++++++++++++++ .../examples/object-library/importable.cxx | 6 ++++++ .../CXXModules/examples/object-library/main.cxx | 6 ++++++ 5 files changed, 39 insertions(+) create mode 100644 Tests/RunCMake/CXXModules/examples/object-library-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/object-library/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/object-library/importable.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/object-library/main.cxx diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 1009ce4..d324ec9 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -142,6 +142,7 @@ string(REPLACE "," ";" CMake_TEST_MODULE_COMPILATION "${CMake_TEST_MODULE_COMPIL if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(simple) run_cxx_module_test(library library-static -DBUILD_SHARED_LIBS=OFF) + run_cxx_module_test(object-library) run_cxx_module_test(generated) run_cxx_module_test(deep-chain) run_cxx_module_test(duplicate) diff --git a/Tests/RunCMake/CXXModules/examples/object-library-stderr.txt b/Tests/RunCMake/CXXModules/examples/object-library-stderr.txt new file mode 100644 index 0000000..4709399 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/object-library-stderr.txt @@ -0,0 +1,4 @@ +CMake Warning \(dev\) at CMakeLists.txt:[0-9]* \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/object-library/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/object-library/CMakeLists.txt new file mode 100644 index 0000000..238e30a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/object-library/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_objlib CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(objlib OBJECT) +target_sources(objlib + PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(objlib PUBLIC cxx_std_20) + +add_executable(objmain) +target_sources(objmain + PRIVATE + main.cxx) +target_link_libraries(objmain PRIVATE objlib) + +add_test(NAME objmain COMMAND objmain) diff --git a/Tests/RunCMake/CXXModules/examples/object-library/importable.cxx b/Tests/RunCMake/CXXModules/examples/object-library/importable.cxx new file mode 100644 index 0000000..607680a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/object-library/importable.cxx @@ -0,0 +1,6 @@ +export module importable; + +export int from_import() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/object-library/main.cxx b/Tests/RunCMake/CXXModules/examples/object-library/main.cxx new file mode 100644 index 0000000..feb38d2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/object-library/main.cxx @@ -0,0 +1,6 @@ +import importable; + +int main(int argc, char* argv[]) +{ + return from_import(); +} -- cgit v0.12 From b665966933c8656d1dafde06b8f29fe7e4901738 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 22 Jul 2023 06:46:31 -0400 Subject: cmComputeLinkInformation: track OBJECT library dependencies In commit b6a5382217 (Ninja: depend on language module information files directly, 2023-02-10), introduced via !8197, language-specific module information files (`CMakeFiles/.dir/Modules.json`) files were added as real dependencies to the dyndep collation steps. Previously, the behavior was to inform the collator of all possible targets and search for the files manually ignoring those which did not exist with ordering enforced by depending on the linker output of all dependent targets. This behavior could lead to stale information being used (e.g., if a target stops providing any targets) and also did not reliably build everything needed on rebuilds. Afterwards, the internal computation changed the dependency from all possible targets to an exact set of "these targets might have modules" query, however one that did not include `OBJECT` libraries since do not have `LinkEntry` items internally (their objects are instead treated as source files). As a stopgap measure, track `OBJECT` libraries in a separate list and query them explicitly when gathering targets which may have interesting information. Future work can add `LinkEntry` items to represent these targets once all `LinkEntry` consumers have been audited to make sure they are not surprised by any `OBJECT` library entries. Fixes: #25112 --- Source/cmCommonTargetGenerator.cxx | 12 +++++++++--- Source/cmComputeLinkInformation.cxx | 14 ++++++++++++-- Source/cmComputeLinkInformation.h | 3 +++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index e635dd9..1924235 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -170,9 +170,15 @@ std::vector cmCommonTargetGenerator::GetLinkedTargetDirectories( cmGlobalCommonGenerator* const gg = this->GlobalCommonGenerator; if (cmComputeLinkInformation* cli = this->GeneratorTarget->GetLinkInformation(config)) { - cmComputeLinkInformation::ItemVector const& items = cli->GetItems(); - for (auto const& item : items) { - cmGeneratorTarget const* linkee = item.Target; + std::vector targets; + for (auto const& item : cli->GetItems()) { + targets.push_back(item.Target); + } + for (auto const* target : cli->GetObjectLibrariesLinked()) { + targets.push_back(target); + } + + for (auto const* linkee : targets) { if (linkee && !linkee->IsImported() // Skip targets that build after this one in a static lib cycle. diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index b80b3cb..ebbb88f 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -525,6 +525,12 @@ cmComputeLinkInformation::GetSharedLibrariesLinked() const return this->SharedLibrariesLinked; } +const std::vector& +cmComputeLinkInformation::GetObjectLibrariesLinked() const +{ + return this->ObjectLibrariesLinked; +} + bool cmComputeLinkInformation::Compute() { // Skip targets that do not link. @@ -1147,8 +1153,12 @@ void cmComputeLinkInformation::AddItem(LinkEntry const& entry) this->AddItem(BT(libName, item.Backtrace)); } } else if (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) { - // Ignore object library! - // Its object-files should already have been extracted for linking. + if (!tgt->HaveCxx20ModuleSources() && !tgt->HaveFortranSources(config)) { + // Ignore object library! + // Its object-files should already have been extracted for linking. + } else { + this->ObjectLibrariesLinked.push_back(entry.Target); + } } else { // Decide whether to use an import library. cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config) diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index a4ada1f..8393a29 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -96,6 +96,8 @@ public: std::string GetRPathString(bool for_install) const; std::string GetChrpathString() const; std::set const& GetSharedLibrariesLinked() const; + std::vector const& GetObjectLibrariesLinked() + const; std::vector const& GetRuntimeDLLs() const { return this->RuntimeDLLs; @@ -132,6 +134,7 @@ private: std::vector FrameworkPaths; std::vector RuntimeSearchPath; std::set SharedLibrariesLinked; + std::vector ObjectLibrariesLinked; std::vector RuntimeDLLs; // Context information. -- cgit v0.12