Merge topic 'cxxmodules-try-compile'

be53c75852 cmExperimental: recycle the C++ modules API UUID
deb1c3cbd5 cmCoreTryCompile: forward module-related binutils variables
b768d293c5 cmCoreTryCompile: use the source type context for source files
93993c7ad4 cmArgumentParser: support storing a context value with parsing
c9ca5f6326 cmCoreTryCompile: parse `SOURCES_TYPE` argument
07551f35de cmCoreTryCompile: use `target_sources` for `try_compile` targets
aad9033b56 cmExperimental: support forwarding associated variables to `try_compile`
f6cf433256 cmExperimental: only forward C++ module support to non-ABI checks
...

Acked-by: Kitware Robot <kwrobot@kitware.com>
Tested-by: buildbot <buildbot@kitware.com>
Merge-request: !8639
This commit is contained in:
Brad King
2023-08-07 15:56:46 +00:00
committed by Kitware Robot
27 changed files with 296 additions and 41 deletions

View File

@@ -65,6 +65,7 @@ Try Compiling Source Files
.. code-block:: cmake
try_compile(<compileResultVar>
[SOURCES_TYPE <type>]
<SOURCES <srcfile...> |
SOURCE_FROM_CONTENT <name> <content> |
SOURCE_FROM_VAR <name> <var> |
@@ -244,6 +245,27 @@ The options are:
``SOURCE_FROM_VAR`` may be specified multiple times.
``SOURCES_TYPE <type>``
.. versionadded:: 3.28
Sources may be classified using the ``SOURCES_TYPE`` argument. Once
specified, all subsequent sources specified will be treated as that type
until another ``SOURCES_TYPE`` is given. Available types are:
``NORMAL``
Sources are not added to any ``FILE_SET`` in the generated project.
``CXX_MODULE``
Sources are added to a ``FILE_SET`` of type ``CXX_MODULES`` in the
generated project.
.. note ::
Experimental. Sources of type ``CXX_MODULE`` are gated by
``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
The default type of sources is ``NORMAL``.
``<LANG>_STANDARD <std>``
.. versionadded:: 3.8

View File

@@ -13,6 +13,7 @@ Try Compiling and Running Source Files
.. code-block:: cmake
try_run(<runResultVar> <compileResultVar>
[SOURCES_TYPE <type>]
<SOURCES <srcfile...> |
SOURCE_FROM_CONTENT <name> <content> |
SOURCE_FROM_VAR <name> <var> |

View File

@@ -37,6 +37,7 @@ macro(_record_compiler_features lang compile_flags feature_list)
LINK_LIBRARIES "${compile_flags_for_link}"
COPY_FILE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin"
COPY_FILE_ERROR _copy_error
__CMAKE_INTERNAL FEATURE_TESTING
)
if(NOT CMAKE_${lang}_FEATURE_TEST)
set(_result 255)

View File

@@ -7,6 +7,7 @@
#include <cassert>
#include <cstddef>
#include <functional>
#include <iterator>
#include <map>
#include <string>
#include <utility>
@@ -176,6 +177,17 @@ public:
void Bind(MaybeEmpty<std::vector<std::string>>& val);
void Bind(NonEmpty<std::vector<std::string>>& val);
void Bind(std::vector<std::vector<std::string>>& val);
template <typename U>
void Bind(NonEmpty<std::vector<std::pair<std::string, U>>>& val,
U const& context)
{
this->Bind(
[&val, &context](cm::string_view arg) -> Continue {
val.emplace_back(std::string(arg), context);
return Continue::Yes;
},
ExpectAtLeast{ 1 });
}
// cm::optional<> records the presence the keyword to which it binds.
template <typename T>
@@ -187,6 +199,15 @@ public:
this->Bind(*optVal);
}
template <typename T, typename U>
void Bind(cm::optional<T>& optVal, U const& context)
{
if (!optVal) {
optVal.emplace();
}
this->Bind(*optVal, context);
}
template <typename Range>
void Parse(Range const& args, std::size_t pos = 0)
{
@@ -232,6 +253,17 @@ public:
return *this;
}
template <typename T, typename U>
cmArgumentParser& BindWithContext(cm::static_string_view name,
T Result::*member, U Result::*context)
{
this->Base::Bind(name, [member, context](Instance& instance) {
auto* result = static_cast<Result*>(instance.Result);
instance.Bind(result->*member, result->*context);
});
return *this;
}
cmArgumentParser& Bind(cm::static_string_view name,
Continue (Result::*member)(cm::string_view),
ExpectAtLeast expect = { 1 })

View File

@@ -167,7 +167,9 @@ auto const TryCompileBaseArgParser =
auto const TryCompileBaseSourcesArgParser =
cmArgumentParser<Arguments>{ TryCompileBaseArgParser }
.Bind("SOURCES"_s, &Arguments::Sources)
.Bind("SOURCES_TYPE"_s, &Arguments::SetSourceType)
.BindWithContext("SOURCES"_s, &Arguments::Sources,
&Arguments::SourceTypeContext)
.Bind("COMPILE_DEFINITIONS"_s, TryCompileCompileDefs,
ArgumentParser::ExpectAtLeast{ 0 })
.Bind("LINK_LIBRARIES"_s, &Arguments::LinkLibraries)
@@ -184,9 +186,12 @@ auto const TryCompileBaseSourcesArgParser =
auto const TryCompileBaseNewSourcesArgParser =
cmArgumentParser<Arguments>{ TryCompileBaseSourcesArgParser }
.Bind("SOURCE_FROM_CONTENT"_s, &Arguments::SourceFromContent)
.Bind("SOURCE_FROM_VAR"_s, &Arguments::SourceFromVar)
.Bind("SOURCE_FROM_FILE"_s, &Arguments::SourceFromFile)
.BindWithContext("SOURCE_FROM_CONTENT"_s, &Arguments::SourceFromContent,
&Arguments::SourceTypeContext)
.BindWithContext("SOURCE_FROM_VAR"_s, &Arguments::SourceFromVar,
&Arguments::SourceTypeContext)
.BindWithContext("SOURCE_FROM_FILE"_s, &Arguments::SourceFromFile,
&Arguments::SourceTypeContext)
/* keep semicolon on own line */;
auto const TryCompileBaseProjectArgParser =
@@ -221,12 +226,44 @@ auto const TryRunOldArgParser = makeTryRunParser(TryCompileOldArgParser);
std::string const TryCompileDefaultConfig = "DEBUG";
}
ArgumentParser::Continue cmCoreTryCompile::Arguments::SetSourceType(
cm::string_view sourceType)
{
bool matched = false;
if (sourceType == "NORMAL"_s) {
this->SourceTypeContext = SourceType::Normal;
matched = true;
} else if (sourceType == "CXX_MODULE"_s) {
bool const supportCxxModuleSources = cmExperimental::HasSupportEnabled(
*this->Makefile, cmExperimental::Feature::CxxModuleCMakeApi);
if (supportCxxModuleSources) {
this->SourceTypeContext = SourceType::CxxModule;
matched = true;
}
}
if (!matched && this->SourceTypeError.empty()) {
bool const supportCxxModuleSources = cmExperimental::HasSupportEnabled(
*this->Makefile, cmExperimental::Feature::CxxModuleCMakeApi);
auto const* message = "'SOURCE'";
if (supportCxxModuleSources) {
message = "one of 'SOURCE' or 'CXX_MODULE'";
}
// Only remember one error at a time; all other errors related to argument
// parsing are "indicate one error and return" anyways.
this->SourceTypeError =
cmStrCat("Invalid 'SOURCE_TYPE' '", sourceType, "'; must be ", message);
}
return ArgumentParser::Continue::Yes;
}
Arguments cmCoreTryCompile::ParseArgs(
const cmRange<std::vector<std::string>::const_iterator>& args,
const cmArgumentParser<Arguments>& parser,
std::vector<std::string>& unparsedArguments)
{
auto arguments = parser.Parse(args, &unparsedArguments, 0);
Arguments arguments{ this->Makefile };
parser.Parse(arguments, args, &unparsedArguments, 0);
if (!arguments.MaybeReportError(*(this->Makefile)) &&
!unparsedArguments.empty()) {
std::string m = "Unknown arguments:";
@@ -434,6 +471,11 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
"SOURCE_FROM_FILE requires exactly two arguments");
return cm::nullopt;
}
if (!arguments.SourceTypeError.empty()) {
this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
arguments.SourceTypeError);
return cm::nullopt;
}
} else {
// only valid for srcfile signatures
if (!arguments.LangProps.empty()) {
@@ -486,42 +528,45 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
cmSystemTools::RemoveFile(ccFile);
// Choose sources.
std::vector<std::string> sources;
std::vector<std::pair<std::string, Arguments::SourceType>> sources;
if (arguments.Sources) {
sources = std::move(*arguments.Sources);
} else if (arguments.SourceDirectoryOrFile) {
sources.emplace_back(*arguments.SourceDirectoryOrFile);
sources.emplace_back(*arguments.SourceDirectoryOrFile,
Arguments::SourceType::Directory);
}
if (arguments.SourceFromContent) {
auto const k = arguments.SourceFromContent->size();
for (auto i = decltype(k){ 0 }; i < k; i += 2) {
const auto& name = (*arguments.SourceFromContent)[i + 0];
const auto& content = (*arguments.SourceFromContent)[i + 1];
const auto& name = (*arguments.SourceFromContent)[i + 0].first;
const auto& content = (*arguments.SourceFromContent)[i + 1].first;
auto out = this->WriteSource(name, content, "SOURCE_FROM_CONTENT");
if (out.empty()) {
return cm::nullopt;
}
sources.emplace_back(std::move(out));
sources.emplace_back(std::move(out),
(*arguments.SourceFromContent)[i + 0].second);
}
}
if (arguments.SourceFromVar) {
auto const k = arguments.SourceFromVar->size();
for (auto i = decltype(k){ 0 }; i < k; i += 2) {
const auto& name = (*arguments.SourceFromVar)[i + 0];
const auto& var = (*arguments.SourceFromVar)[i + 1];
const auto& name = (*arguments.SourceFromVar)[i + 0].first;
const auto& var = (*arguments.SourceFromVar)[i + 1].first;
const auto& content = this->Makefile->GetDefinition(var);
auto out = this->WriteSource(name, content, "SOURCE_FROM_VAR");
if (out.empty()) {
return cm::nullopt;
}
sources.emplace_back(std::move(out));
sources.emplace_back(std::move(out),
(*arguments.SourceFromVar)[i + 0].second);
}
}
if (arguments.SourceFromFile) {
auto const k = arguments.SourceFromFile->size();
for (auto i = decltype(k){ 0 }; i < k; i += 2) {
const auto& dst = (*arguments.SourceFromFile)[i + 0];
const auto& src = (*arguments.SourceFromFile)[i + 1];
const auto& dst = (*arguments.SourceFromFile)[i + 0].first;
const auto& src = (*arguments.SourceFromFile)[i + 1].first;
if (!cmSystemTools::GetFilenamePath(dst).empty()) {
const auto& msg =
@@ -539,7 +584,8 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
return cm::nullopt;
}
sources.emplace_back(std::move(dstPath));
sources.emplace_back(std::move(dstPath),
(*arguments.SourceFromFile)[i + 0].second);
}
}
// TODO: ensure sources is not empty
@@ -547,7 +593,8 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
// Detect languages to enable.
cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
std::set<std::string> testLangs;
for (std::string const& si : sources) {
for (auto const& source : sources) {
auto const& si = source.first;
std::string ext = cmSystemTools::GetFilenameLastExtension(si);
std::string lang = gg->GetLanguageFromExtension(ext.c_str());
if (!lang.empty()) {
@@ -837,17 +884,43 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
fprintf(fout, "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n",
this->BinaryDirectory.c_str());
/* Create the actual executable. */
fprintf(fout, "add_executable(%s", targetName.c_str());
fprintf(fout, "add_executable(%s)\n", targetName.c_str());
} else // if (targetType == cmStateEnums::STATIC_LIBRARY)
{
/* Put the static library at a known location (for COPY_FILE). */
fprintf(fout, "set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY \"%s\")\n",
this->BinaryDirectory.c_str());
/* Create the actual static library. */
fprintf(fout, "add_library(%s STATIC", targetName.c_str());
fprintf(fout, "add_library(%s STATIC)\n", targetName.c_str());
}
for (std::string const& si : sources) {
fprintf(fout, " \"%s\"", si.c_str());
fprintf(fout, "target_sources(%s PRIVATE\n", targetName.c_str());
std::string file_set_name;
bool in_file_set = false;
for (auto const& source : sources) {
auto const& si = source.first;
switch (source.second) {
case Arguments::SourceType::Normal: {
if (in_file_set) {
fprintf(fout, " PRIVATE\n");
in_file_set = false;
}
} break;
case Arguments::SourceType::CxxModule: {
if (!in_file_set) {
file_set_name += 'a';
fprintf(fout,
" PRIVATE FILE_SET %s TYPE CXX_MODULES BASE_DIRS \"%s\" "
"FILES\n",
file_set_name.c_str(),
this->Makefile->GetCurrentSourceDirectory().c_str());
in_file_set = true;
}
} break;
case Arguments::SourceType::Directory:
/* Handled elsewhere. */
break;
}
fprintf(fout, " \"%s\"\n", si.c_str());
// Add dependencies on any non-temporary sources.
if (!IsTemporary(si)) {
@@ -1025,6 +1098,7 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s);
vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s);
vars.emplace("CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"_s);
vars.emplace("CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS"_s);
if (cmValue varListStr = this->Makefile->GetDefinition(
kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) {
@@ -1077,8 +1151,16 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
i++) {
auto const& data = cmExperimental::DataForFeature(
static_cast<cmExperimental::Feature>(i));
if (data.ForwardThroughTryCompile) {
if (data.ForwardThroughTryCompile ==
cmExperimental::TryCompileCondition::Always ||
(data.ForwardThroughTryCompile ==
cmExperimental::TryCompileCondition::SkipCompilerChecks &&
arguments.CMakeInternal != "ABI"_s &&
arguments.CMakeInternal != "FEATURE_TESTING"_s)) {
vars.insert(data.Variable);
for (auto const& var : data.TryCompileVariables) {
vars.insert(var);
}
}
}

View File

@@ -6,9 +6,11 @@
#include <map>
#include <string>
#include <utility>
#include <vector>
#include <cm/optional>
#include <cm/string_view>
#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
@@ -51,17 +53,36 @@ public:
struct Arguments : public ArgumentParser::ParseResult
{
Arguments(cmMakefile const* mf)
: Makefile(mf)
{
}
cmMakefile const* Makefile;
enum class SourceType
{
Normal,
CxxModule,
Directory,
};
cm::optional<std::string> CompileResultVariable;
cm::optional<std::string> BinaryDirectory;
cm::optional<std::string> SourceDirectoryOrFile;
cm::optional<std::string> ProjectName;
cm::optional<std::string> TargetName;
cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> Sources;
cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
cm::optional<ArgumentParser::NonEmpty<
std::vector<std::pair<std::string, SourceType>>>>
Sources;
cm::optional<ArgumentParser::NonEmpty<
std::vector<std::pair<std::string, SourceType>>>>
SourceFromContent;
cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
cm::optional<ArgumentParser::NonEmpty<
std::vector<std::pair<std::string, SourceType>>>>
SourceFromVar;
cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
cm::optional<ArgumentParser::NonEmpty<
std::vector<std::pair<std::string, SourceType>>>>
SourceFromFile;
ArgumentParser::MaybeEmpty<std::vector<std::string>> CMakeFlags{
1, "CMAKE_FLAGS"
@@ -79,6 +100,10 @@ public:
bool NoCache = false;
bool NoLog = false;
ArgumentParser::Continue SetSourceType(cm::string_view sourceType);
SourceType SourceTypeContext = SourceType::Normal;
std::string SourceTypeError;
// Argument for try_run only.
// Keep in sync with warnings in cmCoreTryCompile::ParseArgs.
cm::optional<std::string> CompileOutputVariable;

View File

@@ -20,18 +20,25 @@ namespace {
*/
cmExperimental::FeatureData LookupTable[] = {
// CxxModuleCMakeApi
{ "CxxModuleCMakeApi", "bf70d4b0-9fb7-465c-9803-34014e70d112",
{ "CxxModuleCMakeApi",
"a816ed09-43d1-40e5-bc8c-1a2824ee194e",
"CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API",
"CMake's C++ module support is experimental. It is meant only for "
"experimentation and feedback to CMake developers.",
false, // https://gitlab.kitware.com/cmake/cmake/-/issues/25097
{ "CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE",
"CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT",
"CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG" },
cmExperimental::TryCompileCondition::SkipCompilerChecks,
false },
// WindowsKernelModeDriver
{ "WindowsKernelModeDriver", "5c2d848d-4efa-4529-a768-efd57171bf68",
{ "WindowsKernelModeDriver",
"5c2d848d-4efa-4529-a768-efd57171bf68",
"CMAKE_EXPERIMENTAL_WINDOWS_KERNEL_MODE_DRIVER",
"CMake's Windows kernel-mode driver support is experimental. It is meant "
"only for experimentation and feedback to CMake developers.",
true, false },
{},
cmExperimental::TryCompileCondition::Always,
false },
};
static_assert(sizeof(LookupTable) / sizeof(LookupTable[0]) ==
static_cast<size_t>(cmExperimental::Feature::Sentinel),

View File

@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
class cmMakefile;
@@ -20,13 +21,21 @@ public:
Sentinel,
};
enum class TryCompileCondition
{
Always,
SkipCompilerChecks,
Never,
};
struct FeatureData
{
std::string const Name;
std::string const Uuid;
std::string const Variable;
std::string const Description;
bool const ForwardThroughTryCompile;
std::vector<std::string> const TryCompileVariables;
TryCompileCondition const ForwardThroughTryCompile;
bool Warned;
};

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.23)
project(${RunCMake_TEST} NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
include(${RunCMake_TEST}.cmake)

View File

@@ -148,6 +148,8 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION)
run_cxx_module_test(duplicate)
set(RunCMake_CXXModules_NO_TEST 1)
run_cxx_module_test(circular)
run_cxx_module_test(try-compile)
run_cxx_module_test(try-run)
unset(RunCMake_CXXModules_NO_TEST)
run_cxx_module_test(same-src-name)
run_cxx_module_test(scan_properties)

View File

@@ -1,4 +1,4 @@
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
if (NOT EXISTS "${CMake_TEST_MODULE_COMPILATION_RULES}")
message(FATAL_ERROR

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
find_package(export_bmi_and_interfaces REQUIRED)

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
find_package(export_bmi_and_interfaces REQUIRED)

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
find_package(export_interfaces REQUIRED)

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
find_package(export_interfaces REQUIRED)

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
find_package(export_interfaces_no_properties REQUIRED)

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_library NONE)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
find_package(export_interfaces_no_properties REQUIRED)

View File

@@ -0,0 +1,4 @@
CMake Warning \(dev\) at CMakeLists.txt:[0-9]* \(try_compile\):
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.

View File

@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_try_compile CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
try_compile(can_use_modules
SOURCES_TYPE CXX_MODULE
SOURCES
"${CMAKE_CURRENT_LIST_DIR}/importable.cxx"
SOURCES_TYPE NORMAL
SOURCE_FROM_FILE
use_importable.cxx "${CMAKE_CURRENT_LIST_DIR}/use_importable.cxx"
CXX_STANDARD 20)
if (NOT can_use_modules)
message(FATAL_ERROR
"`try_compile` could not compile sources using modules.")
endif ()

View File

@@ -0,0 +1,6 @@
export module importable;
export int from_import()
{
return 0;
}

View File

@@ -0,0 +1,6 @@
import importable;
int foo()
{
return from_import();
}

View File

@@ -0,0 +1,4 @@
CMake Warning \(dev\) at CMakeLists.txt:[0-9]* \(try_run\):
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.

View File

@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_try_run CXX)
include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
try_run(can_run_modules_result can_compile_modules
SOURCES_TYPE CXX_MODULE
SOURCES
"${CMAKE_CURRENT_LIST_DIR}/importable.cxx"
SOURCES_TYPE NORMAL
SOURCE_FROM_FILE
main.cxx "${CMAKE_CURRENT_LIST_DIR}/main.cxx"
CXX_STANDARD 20)
if (NOT can_compile_modules)
message(FATAL_ERROR
"`try_run` could not compile sources using modules.")
endif ()
if (can_run_modules_result)
message(FATAL_ERROR
"`try_run` could not run sources using modules.")
endif ()

View File

@@ -0,0 +1,6 @@
export module importable;
export int from_import()
{
return 0;
}

View File

@@ -0,0 +1,6 @@
import importable;
int main(int argc, char* argv[])
{
return from_import() == 1;
}

View File

@@ -1,6 +1,6 @@
enable_language(C)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
add_library(lib1 STATIC empty.c)
target_sources(lib1 PRIVATE FILE_SET UNKNOWN)

View File

@@ -1,6 +1,6 @@
enable_language(C)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e")
add_library(lib1 STATIC empty.c)
target_sources(lib1 PRIVATE FILE_SET a TYPE UNKNOWN)