summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Woehlke <matthew.woehlke@kitware.com>2022-09-22 13:43:14 -0400
committerMatthew Woehlke <matthew.woehlke@kitware.com>2022-09-22 14:56:50 -0400
commit611d80179006ba6670273fcfcad46b0bb64a36c2 (patch)
tree1975420c55f72ce6e9beb22c80aeae18398ded6b
parenta04eaf6742d98dd415ee939eae8c955c8afd1ce6 (diff)
downloadcmake-611d80179006ba6670273fcfcad46b0bb64a36c2.tar.gz
try_compile: Add SOURCE_FROM_FILE
Add ability to copy try_compile (and try_run) source files from arbitrary locations into the operation directory. This is included for the sake of completion and consolidation, although use cases which actually require this may be rare.
-rw-r--r--Help/command/try_compile.rst13
-rw-r--r--Help/command/try_run.rst3
-rw-r--r--Source/cmCoreTryCompile.cxx32
-rw-r--r--Source/cmCoreTryCompile.h2
-rw-r--r--Tests/RunCMake/try_compile/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/try_compile/SourceFromBadFile-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt4
-rw-r--r--Tests/RunCMake/try_compile/SourceFromBadFile.cmake1
-rw-r--r--Tests/TryCompile/CMakeLists.txt6
9 files changed, 61 insertions, 2 deletions
diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst
index ed61a2f2fe..4632cd9331 100644
--- a/Help/command/try_compile.rst
+++ b/Help/command/try_compile.rst
@@ -58,7 +58,8 @@ Try Compiling Source Files
try_compile(<resultVar>
<SOURCES <srcfile...>] |
SOURCE_FROM_ARG <name> <content>] |
- SOURCE_FROM_VAR <name> <var>] >...
+ SOURCE_FROM_VAR <name> <var>] |
+ SOURCE_FROM_FILE <name> <path> >...
[CMAKE_FLAGS <flags>...]
[COMPILE_DEFINITIONS <defs>...]
[LINK_OPTIONS <options>...]
@@ -178,6 +179,16 @@ The options are:
``SOURCE_FROM_ARG`` may be specified multiple times.
+``SOURCE_FROM_FILE <name> <path>``
+ .. versionadded:: 3.25
+
+ Copy ``<path>`` to a file named ``<name>`` in the operation directory. This
+ can be used to consolidate files into the operation directory, which may be
+ useful if a source which already exists (i.e. as a stand-alone file in a
+ project's source repository) needs to refer to other file(s) created by
+ ``SOURCE_FROM_*``. (Otherwise, ``SOURCES`` is usually more convenient.) The
+ specified ``<name>`` is not allowed to contain path components.
+
``SOURCE_FROM_VAR <name> <content>``
.. versionadded:: 3.25
diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst
index 5498344660..efc10ec4b1 100644
--- a/Help/command/try_run.rst
+++ b/Help/command/try_run.rst
@@ -15,7 +15,8 @@ Try Compiling and Running Source Files
try_run(<runResultVar> <compileResultVar>
<SOURCES <srcfile...>] |
SOURCE_FROM_ARG <name> <content>] |
- SOURCE_FROM_VAR <name> <var>] >...
+ SOURCE_FROM_VAR <name> <var>] |
+ SOURCE_FROM_FILE <name> <path> >...
[CMAKE_FLAGS <flags>...]
[COMPILE_DEFINITIONS <defs>...]
[LINK_OPTIONS <options>...]
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 0ef32c03da..839cb7b9f9 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -174,6 +174,7 @@ auto const TryCompileBaseNewSourcesArgParser =
cmArgumentParser<Arguments>{ TryCompileBaseSourcesArgParser }
.Bind("SOURCE_FROM_ARG"_s, &Arguments::SourceFromArg)
.Bind("SOURCE_FROM_VAR"_s, &Arguments::SourceFromVar)
+ .Bind("SOURCE_FROM_FILE"_s, &Arguments::SourceFromFile)
/* keep semicolon on own line */;
auto const TryCompileBaseProjectArgParser =
@@ -416,6 +417,12 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
"SOURCE_FROM_VAR requires exactly two arguments");
return false;
}
+ if (arguments.SourceFromFile && arguments.SourceFromFile->size() % 2) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "SOURCE_FROM_FILE requires exactly two arguments");
+ return false;
+ }
} else {
// only valid for srcfile signatures
if (!arguments.LangProps.empty()) {
@@ -497,6 +504,31 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
sources.emplace_back(std::move(out));
}
}
+ 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];
+
+ if (!cmSystemTools::GetFilenamePath(dst).empty()) {
+ const auto& msg =
+ cmStrCat("SOURCE_FROM_FILE given invalid filename \"", dst, "\"");
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg);
+ return false;
+ }
+
+ auto dstPath = cmStrCat(this->BinaryDirectory, "/", dst);
+ auto const result = cmSystemTools::CopyFileAlways(src, dstPath);
+ if (!result.IsSuccess()) {
+ const auto& msg = cmStrCat("SOURCE_FROM_FILE failed to copy \"", src,
+ "\": ", result.GetString());
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg);
+ return false;
+ }
+
+ sources.emplace_back(std::move(dstPath));
+ }
+ }
// TODO: ensure sources is not empty
// Detect languages to enable.
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index 75dcf6ef0a..3f4a4dcf85 100644
--- a/Source/cmCoreTryCompile.h
+++ b/Source/cmCoreTryCompile.h
@@ -44,6 +44,8 @@ public:
SourceFromArg;
cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
SourceFromVar;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ SourceFromFile;
ArgumentParser::MaybeEmpty<std::vector<std::string>> CMakeFlags{
1, "CMAKE_FLAGS"
}; // fake argv[0]
diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
index 0aa9039e41..d63624c197 100644
--- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
@@ -23,6 +23,7 @@ unset(RunCMake_TEST_OPTIONS)
run_cmake(SourceFromOneArg)
run_cmake(SourceFromThreeArgs)
run_cmake(SourceFromBadName)
+run_cmake(SourceFromBadFile)
run_cmake(ProjectCopyFile)
run_cmake(NonSourceCopyFile)
diff --git a/Tests/RunCMake/try_compile/SourceFromBadFile-result.txt b/Tests/RunCMake/try_compile/SourceFromBadFile-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromBadFile-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt b/Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt
new file mode 100644
index 0000000000..53a6d8df6a
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourceFromBadFile.cmake:[0-9]+ \(try_compile\):
+ SOURCE_FROM_FILE failed to copy "bad#source.c": No such file or directory
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/SourceFromBadFile.cmake b/Tests/RunCMake/try_compile/SourceFromBadFile.cmake
new file mode 100644
index 0000000000..0a37f1168f
--- /dev/null
+++ b/Tests/RunCMake/try_compile/SourceFromBadFile.cmake
@@ -0,0 +1 @@
+try_compile(RESULT SOURCE_FROM_FILE bad.c "bad#source.c")
diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt
index cca19bc9d7..9396cfa57d 100644
--- a/Tests/TryCompile/CMakeLists.txt
+++ b/Tests/TryCompile/CMakeLists.txt
@@ -89,6 +89,12 @@ if(SHOULD_FAIL_DUE_TO_EMPTY_SOURCE)
message(SEND_ERROR "Trying to compile an empty source succeeded?")
endif()
+# try to compile a copied source
+try_compile(SHOULD_PASS
+ SOURCE_FROM_FILE pass.c ${TryCompile_SOURCE_DIR}/pass.c
+ OUTPUT_VARIABLE TRY_OUT)
+EXPECT_COMPILED("SOURCE_FROM_FILE" SHOULD_PASS "${TRY_OUT}")
+
# try to run a source specified directly
set(TRY_RUN_MAIN_CODE
"extern int answer(); \n"