From c28715b16c7a71cd8ea0416277cc87ee9bc8eaa1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 9 Jul 2013 15:26:15 -0400 Subject: [PATCH] try_compile: Add COPY_FILE_ERROR option to capture failure When the COPY_FILE operation fails optionally capture the error message with a COPY_FILE_ERROR option instead of reporting the error immediately. This gives callers a chance to do something else or report the error. Teach the RunCMake.try_compile test to cover bad argument combinations involving COPY_FILE_ERROR. Teach the TryCompile test to cover the case of a COPY_FILE error message captured by COPY_FILE_ERROR. --- Source/cmCoreTryCompile.cxx | 46 +++++++++++++++++-- Source/cmTryCompileCommand.h | 4 +- .../CopyFileErrorNoCopyFile-result.txt | 1 + .../CopyFileErrorNoCopyFile-stderr.txt | 4 ++ .../try_compile/CopyFileErrorNoCopyFile.cmake | 2 + .../try_compile/NoCopyFileError-result.txt | 1 + .../try_compile/NoCopyFileError-stderr.txt | 4 ++ .../try_compile/NoCopyFileError.cmake | 2 + Tests/RunCMake/try_compile/RunCMakeTest.cmake | 2 + Tests/TryCompile/CMakeLists.txt | 17 +++++++ 10 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-result.txt create mode 100644 Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt create mode 100644 Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake create mode 100644 Tests/RunCMake/try_compile/NoCopyFileError-result.txt create mode 100644 Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt create mode 100644 Tests/RunCMake/try_compile/NoCopyFileError.cmake diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 860417fc9..91b721530 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -32,18 +32,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) std::vector compileDefs; std::string outputVariable; std::string copyFile; + std::string copyFileError; std::vector targets; std::string libsToLink = " "; bool useOldLinkLibs = true; char targetNameBuf[64]; bool didOutputVariable = false; bool didCopyFile = false; + bool didCopyFileError = false; bool useSources = argv[2] == "SOURCES"; std::vector sources; enum Doing { DoingNone, DoingCMakeFlags, DoingCompileDefinitions, DoingLinkLibraries, DoingOutputVariable, DoingCopyFile, - DoingSources }; + DoingCopyFileError, DoingSources }; Doing doing = useSources? DoingSources : DoingNone; for(size_t i=3; i < argv.size(); ++i) { @@ -74,6 +76,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) doing = DoingCopyFile; didCopyFile = true; } + else if(argv[i] == "COPY_FILE_ERROR") + { + doing = DoingCopyFileError; + didCopyFileError = true; + } else if(doing == DoingCMakeFlags) { cmakeFlags.push_back(argv[i]); @@ -121,6 +128,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) copyFile = argv[i].c_str(); doing = DoingNone; } + else if(doing == DoingCopyFileError) + { + copyFileError = argv[i].c_str(); + doing = DoingNone; + } else if(doing == DoingSources) { sources.push_back(argv[i]); @@ -149,6 +161,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) return -1; } + if(didCopyFileError && copyFileError.empty()) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "COPY_FILE_ERROR must be followed by a variable name"); + return -1; + } + + if(didCopyFileError && !didCopyFile) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "COPY_FILE_ERROR may be used only with COPY_FILE"); + return -1; + } + if(didOutputVariable && outputVariable.empty()) { this->Makefile->IssueMessage(cmake::FATAL_ERROR, @@ -444,6 +470,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) if (this->SrcFileSignature) { + std::string copyFileErrorMessage; this->FindOutputFile(targetName); if ((res==0) && (copyFile.size())) @@ -461,10 +488,23 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) { emsg << this->FindErrorMessage.c_str(); } - this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str()); - return -1; + if(copyFileError.empty()) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str()); + return -1; + } + else + { + copyFileErrorMessage = emsg.str(); + } } } + + if(!copyFileError.empty()) + { + this->Makefile->AddDefinition(copyFileError.c_str(), + copyFileErrorMessage.c_str()); + } } return res; } diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h index 163756d0c..a20594cbe 100644 --- a/Source/cmTryCompileCommand.h +++ b/Source/cmTryCompileCommand.h @@ -69,14 +69,14 @@ public: " [COMPILE_DEFINITIONS flags...]\n" " [LINK_LIBRARIES libs...]\n" " [OUTPUT_VARIABLE ]\n" - " [COPY_FILE ])\n" + " [COPY_FILE [COPY_FILE_ERROR ]])\n" "Try building an executable from one or more source files. " "In this form the user need only supply one or more source files " "that include a definition for 'main'. " "CMake will create a CMakeLists.txt file to build the source(s) " "as an executable. " "Specify COPY_FILE to get a copy of the linked executable at the " - "given fileName." + "given fileName and optionally COPY_FILE_ERROR to capture any error." "\n" "In this version all files in bindir/CMakeFiles/CMakeTmp " "will be cleaned automatically. For debugging, --debug-trycompile can " diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-result.txt b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt new file mode 100644 index 000000000..5d09c0c61 --- /dev/null +++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at CopyFileErrorNoCopyFile.cmake:1 \(try_compile\): + COPY_FILE_ERROR may be used only with COPY_FILE +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake new file mode 100644 index 000000000..8d7cb0e7f --- /dev/null +++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE_ERROR _copied) diff --git a/Tests/RunCMake/try_compile/NoCopyFileError-result.txt b/Tests/RunCMake/try_compile/NoCopyFileError-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFileError-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt new file mode 100644 index 000000000..ed552fd8e --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NoCopyFileError.cmake:1 \(try_compile\): + COPY_FILE_ERROR must be followed by a variable name +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoCopyFileError.cmake b/Tests/RunCMake/try_compile/NoCopyFileError.cmake new file mode 100644 index 000000000..d4d69ee01 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFileError.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copied.bin COPY_FILE_ERROR) diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake index 3494695be..c93445876 100644 --- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake @@ -1,10 +1,12 @@ include(RunCMake) +run_cmake(CopyFileErrorNoCopyFile) run_cmake(NoArgs) run_cmake(OneArg) run_cmake(TwoArgs) run_cmake(NoCopyFile) run_cmake(NoCopyFile2) +run_cmake(NoCopyFileError) run_cmake(NoOutputVariable) run_cmake(NoOutputVariable2) run_cmake(NoSources) diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt index 4540fd086..173929b0d 100644 --- a/Tests/TryCompile/CMakeLists.txt +++ b/Tests/TryCompile/CMakeLists.txt @@ -44,6 +44,23 @@ else() file(REMOVE "${TryCompile_BINARY_DIR}/CopyOfPass") endif() +# try to compile a file that should compile +# also check that COPY_FILE_ERROR works +file(WRITE ${TryCompile_BINARY_DIR}/invalid "") +try_compile(SHOULD_PASS + ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp + ${TryCompile_SOURCE_DIR}/pass.c + OUTPUT_VARIABLE TRY_OUT + COPY_FILE ${TryCompile_BINARY_DIR}/invalid/path + COPY_FILE_ERROR _captured + ) +if(NOT SHOULD_PASS) + message(SEND_ERROR "should pass failed ${TRY_OUT}") +endif() +if(NOT _captured MATCHES "Cannot copy output executable.*/invalid/path") + message(SEND_ERROR "COPY_FILE_ERROR did not capture expected message") +endif() + # try to compile a file that should not compile try_compile(SHOULD_FAIL ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp