mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-19 19:43:23 +08:00
try_compile: Add PROJECT keyword-dispatched signature
Introduce a new signature for the project flavor of try_compile (and
try_run) which removes the `bindir` argument and adds a required PROJECT
tag. This is similar to the SOURCES flavor added by commit aa9220d3
(try_compile: Add keyword-dispatched signature, 2022-09-02).
This commit is contained in:
@@ -14,10 +14,15 @@ Try Compiling Whole Projects
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
try_compile(<resultVar> <bindir> <srcdir>
|
||||
<projectName> [<targetName>] [CMAKE_FLAGS <flags>...]
|
||||
try_compile(<resultVar> PROJECT <projectName>
|
||||
SOURCE_DIR <srcdir>
|
||||
[BINARY_DIR <bindir>]
|
||||
[TARGET <targetName>]
|
||||
[CMAKE_FLAGS <flags>...]
|
||||
[OUTPUT_VARIABLE <var>])
|
||||
|
||||
.. versionadded:: 3.25
|
||||
|
||||
Try building a project. The success or failure of the ``try_compile``,
|
||||
i.e. ``TRUE`` or ``FALSE`` respectively, is returned in ``<resultVar>``.
|
||||
|
||||
@@ -34,6 +39,15 @@ below for the meaning of other options.
|
||||
Previously this was only done by the
|
||||
:ref:`source file <Try Compiling Source Files>` signature.
|
||||
|
||||
This command also supports an alternate signature
|
||||
which was present in older versions of CMake:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
try_compile(<resultVar> <bindir> <srcdir>
|
||||
<projectName> [<targetName>] [CMAKE_FLAGS <flags>...]
|
||||
[OUTPUT_VARIABLE <var>])
|
||||
|
||||
.. _`Try Compiling Source Files`:
|
||||
|
||||
Try Compiling Source Files
|
||||
|
@@ -121,6 +121,26 @@ ArgumentParser::Continue TryCompileCompileDefs(Arguments& args,
|
||||
return ArgumentParser::Continue::Yes;
|
||||
}
|
||||
|
||||
cmArgumentParser<Arguments> makeTryCompileParser(
|
||||
const cmArgumentParser<Arguments>& base)
|
||||
{
|
||||
return cmArgumentParser<Arguments>{ base }.Bind("OUTPUT_VARIABLE"_s,
|
||||
&Arguments::OutputVariable);
|
||||
}
|
||||
|
||||
cmArgumentParser<Arguments> makeTryRunParser(
|
||||
const cmArgumentParser<Arguments>& base)
|
||||
{
|
||||
return cmArgumentParser<Arguments>{ base }
|
||||
.Bind("COMPILE_OUTPUT_VARIABLE"_s, &Arguments::CompileOutputVariable)
|
||||
.Bind("RUN_OUTPUT_VARIABLE"_s, &Arguments::RunOutputVariable)
|
||||
.Bind("RUN_OUTPUT_STDOUT_VARIABLE"_s, &Arguments::RunOutputStdOutVariable)
|
||||
.Bind("RUN_OUTPUT_STDERR_VARIABLE"_s, &Arguments::RunOutputStdErrVariable)
|
||||
.Bind("WORKING_DIRECTORY"_s, &Arguments::RunWorkingDirectory)
|
||||
.Bind("ARGS"_s, &Arguments::RunArgs)
|
||||
/* keep semicolon on own line */;
|
||||
}
|
||||
|
||||
#define BIND_LANG_PROPS(lang) \
|
||||
Bind(#lang "_STANDARD"_s, TryCompileLangProp) \
|
||||
.Bind(#lang "_STANDARD_REQUIRED"_s, TryCompileLangProp) \
|
||||
@@ -129,13 +149,17 @@ ArgumentParser::Continue TryCompileCompileDefs(Arguments& args,
|
||||
auto const TryCompileBaseArgParser =
|
||||
cmArgumentParser<Arguments>{}
|
||||
.Bind(0, &Arguments::CompileResultVariable)
|
||||
.Bind("SOURCES"_s, &Arguments::Sources)
|
||||
.Bind("CMAKE_FLAGS"_s, &Arguments::CMakeFlags)
|
||||
.Bind("__CMAKE_INTERNAL"_s, &Arguments::CMakeInternal)
|
||||
/* keep semicolon on own line */;
|
||||
|
||||
auto const TryCompileBaseNonProjectArgParser =
|
||||
cmArgumentParser<Arguments>{ TryCompileBaseArgParser }
|
||||
.Bind("SOURCES"_s, &Arguments::Sources)
|
||||
.Bind("COMPILE_DEFINITIONS"_s, TryCompileCompileDefs,
|
||||
ArgumentParser::ExpectAtLeast{ 0 })
|
||||
.Bind("LINK_LIBRARIES"_s, &Arguments::LinkLibraries)
|
||||
.Bind("LINK_OPTIONS"_s, &Arguments::LinkOptions)
|
||||
.Bind("__CMAKE_INTERNAL"_s, &Arguments::CMakeInternal)
|
||||
.Bind("COPY_FILE"_s, &Arguments::CopyFileTo)
|
||||
.Bind("COPY_FILE_ERROR"_s, &Arguments::CopyFileError)
|
||||
.BIND_LANG_PROPS(C)
|
||||
@@ -146,38 +170,35 @@ auto const TryCompileBaseArgParser =
|
||||
.BIND_LANG_PROPS(OBJCXX)
|
||||
/* keep semicolon on own line */;
|
||||
|
||||
auto const TryCompileArgParser =
|
||||
cmArgumentParser<Arguments>{ TryCompileBaseArgParser }.Bind(
|
||||
"OUTPUT_VARIABLE"_s, &Arguments::OutputVariable)
|
||||
auto const TryCompileBaseProjectArgParser =
|
||||
cmArgumentParser<Arguments>{ TryCompileBaseArgParser }
|
||||
.Bind("PROJECT"_s, &Arguments::ProjectName)
|
||||
.Bind("SOURCE_DIR"_s, &Arguments::SourceDirectoryOrFile)
|
||||
.Bind("BINARY_DIR"_s, &Arguments::BinaryDirectory)
|
||||
.Bind("TARGET"_s, &Arguments::TargetName)
|
||||
/* keep semicolon on own line */;
|
||||
|
||||
auto const TryCompileProjectArgParser =
|
||||
makeTryCompileParser(TryCompileBaseProjectArgParser);
|
||||
|
||||
auto const TryCompileSourcesArgParser =
|
||||
makeTryCompileParser(TryCompileBaseNonProjectArgParser);
|
||||
|
||||
auto const TryCompileOldArgParser =
|
||||
cmArgumentParser<Arguments>{ TryCompileArgParser }
|
||||
makeTryCompileParser(TryCompileBaseNonProjectArgParser)
|
||||
.Bind(1, &Arguments::BinaryDirectory)
|
||||
.Bind(2, &Arguments::SourceDirectoryOrFile)
|
||||
.Bind(3, &Arguments::ProjectName)
|
||||
.Bind(4, &Arguments::TargetName)
|
||||
/* keep semicolon on own line */;
|
||||
|
||||
auto const TryRunArgParser =
|
||||
cmArgumentParser<Arguments>{ TryCompileBaseArgParser }
|
||||
.Bind("COMPILE_OUTPUT_VARIABLE"_s, &Arguments::CompileOutputVariable)
|
||||
.Bind("RUN_OUTPUT_VARIABLE"_s, &Arguments::RunOutputVariable)
|
||||
.Bind("RUN_OUTPUT_STDOUT_VARIABLE"_s, &Arguments::RunOutputStdOutVariable)
|
||||
.Bind("RUN_OUTPUT_STDERR_VARIABLE"_s, &Arguments::RunOutputStdErrVariable)
|
||||
.Bind("WORKING_DIRECTORY"_s, &Arguments::RunWorkingDirectory)
|
||||
.Bind("ARGS"_s, &Arguments::RunArgs)
|
||||
/* keep semicolon on own line */;
|
||||
auto const TryRunProjectArgParser =
|
||||
makeTryRunParser(TryCompileBaseProjectArgParser);
|
||||
|
||||
auto const TryRunOldArgParser =
|
||||
cmArgumentParser<Arguments>{ TryCompileOldArgParser }
|
||||
.Bind("COMPILE_OUTPUT_VARIABLE"_s, &Arguments::CompileOutputVariable)
|
||||
.Bind("RUN_OUTPUT_VARIABLE"_s, &Arguments::RunOutputVariable)
|
||||
.Bind("RUN_OUTPUT_STDOUT_VARIABLE"_s, &Arguments::RunOutputStdOutVariable)
|
||||
.Bind("RUN_OUTPUT_STDERR_VARIABLE"_s, &Arguments::RunOutputStdErrVariable)
|
||||
.Bind("WORKING_DIRECTORY"_s, &Arguments::RunWorkingDirectory)
|
||||
.Bind("ARGS"_s, &Arguments::RunArgs)
|
||||
/* keep semicolon on own line */;
|
||||
auto const TryRunSourcesArgParser =
|
||||
makeTryRunParser(TryCompileBaseNonProjectArgParser);
|
||||
|
||||
auto const TryRunOldArgParser = makeTryRunParser(TryCompileOldArgParser);
|
||||
|
||||
#undef BIND_LANG_PROPS
|
||||
}
|
||||
@@ -203,10 +224,23 @@ Arguments cmCoreTryCompile::ParseArgs(
|
||||
cmRange<std::vector<std::string>::const_iterator> args, bool isTryRun)
|
||||
{
|
||||
std::vector<std::string> unparsedArguments;
|
||||
if (cmHasLiteralPrefix(*(++args.begin()), "SOURCE")) {
|
||||
// New signature.
|
||||
auto arguments =
|
||||
this->ParseArgs(args, isTryRun ? TryRunArgParser : TryCompileArgParser,
|
||||
const auto& second = *(++args.begin());
|
||||
|
||||
if (second == "PROJECT") {
|
||||
// New PROJECT signature.
|
||||
auto arguments = this->ParseArgs(
|
||||
args, isTryRun ? TryRunProjectArgParser : TryCompileProjectArgParser,
|
||||
unparsedArguments);
|
||||
if (!arguments.BinaryDirectory) {
|
||||
arguments.BinaryDirectory = unique_binary_directory;
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
if (cmHasLiteralPrefix(second, "SOURCE")) {
|
||||
// New SOURCES signature.
|
||||
auto arguments = this->ParseArgs(
|
||||
args, isTryRun ? TryRunSourcesArgParser : TryCompileSourcesArgParser,
|
||||
unparsedArguments);
|
||||
arguments.BinaryDirectory = unique_binary_directory;
|
||||
return arguments;
|
||||
@@ -256,8 +290,14 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
|
||||
std::string sourceDirectory;
|
||||
std::string projectName;
|
||||
std::string targetName;
|
||||
if (arguments.SourceDirectoryOrFile && arguments.ProjectName) {
|
||||
if (arguments.ProjectName) {
|
||||
this->SrcFileSignature = false;
|
||||
if (!arguments.SourceDirectoryOrFile ||
|
||||
arguments.SourceDirectoryOrFile->empty()) {
|
||||
this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
|
||||
"No <srcdir> specified.");
|
||||
return false;
|
||||
}
|
||||
sourceDirectory = *arguments.SourceDirectoryOrFile;
|
||||
projectName = *arguments.ProjectName;
|
||||
if (arguments.TargetName) {
|
||||
|
@@ -0,0 +1 @@
|
||||
1
|
@@ -0,0 +1,4 @@
|
||||
^CMake Error at OldProjectBinDirEmpty.cmake:[0-9]+ \(try_compile\):
|
||||
No <bindir> specified.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)$
|
1
Tests/RunCMake/try_compile/OldProjectBinDirEmpty.cmake
Normal file
1
Tests/RunCMake/try_compile/OldProjectBinDirEmpty.cmake
Normal file
@@ -0,0 +1 @@
|
||||
try_compile(RESULT "" ${CMAKE_CURRENT_SOURCE_DIR}/proj Foo)
|
@@ -0,0 +1 @@
|
||||
1
|
@@ -0,0 +1,4 @@
|
||||
CMake Error at OldProjectSrcDirEmpty.cmake:[0-9]+ \(try_compile\):
|
||||
No <srcdir> specified.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
1
Tests/RunCMake/try_compile/OldProjectSrcDirEmpty.cmake
Normal file
1
Tests/RunCMake/try_compile/OldProjectSrcDirEmpty.cmake
Normal file
@@ -0,0 +1 @@
|
||||
try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} "" Foo)
|
1
Tests/RunCMake/try_compile/ProjectBinDirEmpty-result.txt
Normal file
1
Tests/RunCMake/try_compile/ProjectBinDirEmpty-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
4
Tests/RunCMake/try_compile/ProjectBinDirEmpty-stderr.txt
Normal file
4
Tests/RunCMake/try_compile/ProjectBinDirEmpty-stderr.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
^CMake Error at ProjectBinDirEmpty.cmake:[0-9]+ \(try_compile\):
|
||||
No <bindir> specified.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)$
|
4
Tests/RunCMake/try_compile/ProjectBinDirEmpty.cmake
Normal file
4
Tests/RunCMake/try_compile/ProjectBinDirEmpty.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
try_compile(RESULT PROJECT Foo
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/proj
|
||||
BINARY_DIR ""
|
||||
)
|
1
Tests/RunCMake/try_compile/ProjectCopyFile-result.txt
Normal file
1
Tests/RunCMake/try_compile/ProjectCopyFile-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
0
|
7
Tests/RunCMake/try_compile/ProjectCopyFile-stderr.txt
Normal file
7
Tests/RunCMake/try_compile/ProjectCopyFile-stderr.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
CMake Warning \(dev\) at ProjectCopyFile.cmake:[0-9]+ \(try_compile\):
|
||||
Unknown arguments:
|
||||
|
||||
"COPY_FILE"
|
||||
"result"
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
4
Tests/RunCMake/try_compile/ProjectCopyFile.cmake
Normal file
4
Tests/RunCMake/try_compile/ProjectCopyFile.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
try_compile(RESULT
|
||||
PROJECT TestProject
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/proj
|
||||
COPY_FILE result)
|
1
Tests/RunCMake/try_compile/ProjectSrcDirEmpty-result.txt
Normal file
1
Tests/RunCMake/try_compile/ProjectSrcDirEmpty-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
4
Tests/RunCMake/try_compile/ProjectSrcDirEmpty-stderr.txt
Normal file
4
Tests/RunCMake/try_compile/ProjectSrcDirEmpty-stderr.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
CMake Error at ProjectSrcDirEmpty.cmake:[0-9]+ \(try_compile\):
|
||||
No <srcdir> specified.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
1
Tests/RunCMake/try_compile/ProjectSrcDirEmpty.cmake
Normal file
1
Tests/RunCMake/try_compile/ProjectSrcDirEmpty.cmake
Normal file
@@ -0,0 +1 @@
|
||||
try_compile(RESULT PROJECT Foo SOURCE_DIR "")
|
@@ -0,0 +1 @@
|
||||
1
|
@@ -0,0 +1,4 @@
|
||||
CMake Error at ProjectSrcDirMissing.cmake:[0-9]+ \(try_compile\):
|
||||
No <srcdir> specified.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
1
Tests/RunCMake/try_compile/ProjectSrcDirMissing.cmake
Normal file
1
Tests/RunCMake/try_compile/ProjectSrcDirMissing.cmake
Normal file
@@ -0,0 +1 @@
|
||||
try_compile(RESULT PROJECT Foo)
|
@@ -6,6 +6,11 @@ run_cmake(TwoArgs)
|
||||
run_cmake(NoSources)
|
||||
run_cmake(BinDirEmpty)
|
||||
run_cmake(BinDirRelative)
|
||||
run_cmake(ProjectSrcDirMissing)
|
||||
run_cmake(ProjectSrcDirEmpty)
|
||||
run_cmake(ProjectBinDirEmpty)
|
||||
run_cmake(OldProjectSrcDirEmpty)
|
||||
run_cmake(OldProjectBinDirEmpty)
|
||||
|
||||
set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=old_signature.cmake)
|
||||
include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake)
|
||||
@@ -15,6 +20,7 @@ set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=new_signature.cmake)
|
||||
include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
|
||||
run_cmake(ProjectCopyFile)
|
||||
run_cmake(NonSourceCopyFile)
|
||||
run_cmake(NonSourceCompileDefinitions)
|
||||
|
||||
|
@@ -65,7 +65,7 @@ set(try_compile_run_output_var RUN_OUTPUT)
|
||||
include(old_and_new_signature_tests.cmake)
|
||||
|
||||
# try to compile a project (old signature)
|
||||
message("Testing try_compile project mode")
|
||||
message("Testing try_compile project mode (old signature)")
|
||||
try_compile(TEST_INNER
|
||||
${TryCompile_BINARY_DIR}/CMakeFiles/Inner
|
||||
${TryCompile_SOURCE_DIR}/Inner
|
||||
@@ -73,6 +73,15 @@ try_compile(TEST_INNER
|
||||
OUTPUT_VARIABLE output)
|
||||
TEST_ASSERT(TEST_INNER "try_compile project mode failed:\n${output}")
|
||||
|
||||
# try to compile a project (new signature)
|
||||
message("Testing try_compile project mode (new signature)")
|
||||
try_compile(TEST_INNER
|
||||
PROJECT TryCompileInner
|
||||
SOURCE_DIR ${TryCompile_SOURCE_DIR}/Inner
|
||||
TARGET innerexe
|
||||
OUTPUT_VARIABLE output)
|
||||
TEST_ASSERT(TEST_INNER "try_compile project mode failed:\n${output}")
|
||||
|
||||
add_executable(TryCompile pass.c)
|
||||
|
||||
#######################################################################
|
||||
|
Reference in New Issue
Block a user