From 7447aa4b340420b0d55bc17bdd9ca1422b1806cf Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Wed, 6 Nov 2019 23:55:48 +0100 Subject: ObjC: Add try_compile support Fixes: #19920 --- Source/cmCoreTryCompile.cxx | 208 +++++++++++++-------- Tests/RunCMake/CMakeLists.txt | 2 + Tests/RunCMake/try_compile/ObjCStandard-result.txt | 1 + Tests/RunCMake/try_compile/ObjCStandard-stderr.txt | 7 + Tests/RunCMake/try_compile/ObjCStandard.cmake | 7 + .../RunCMake/try_compile/ObjCxxStandard-result.txt | 1 + .../RunCMake/try_compile/ObjCxxStandard-stderr.txt | 7 + Tests/RunCMake/try_compile/ObjCxxStandard.cmake | 7 + Tests/RunCMake/try_compile/RunCMakeTest.cmake | 6 + Tests/RunCMake/try_compile/src.m | 4 + Tests/RunCMake/try_compile/src.mm | 4 + Tests/TryCompile/CMakeLists.txt | 19 ++ Tests/TryCompile/fail.m | 1 + Tests/TryCompile/pass.m | 4 + 14 files changed, 198 insertions(+), 80 deletions(-) create mode 100644 Tests/RunCMake/try_compile/ObjCStandard-result.txt create mode 100644 Tests/RunCMake/try_compile/ObjCStandard-stderr.txt create mode 100644 Tests/RunCMake/try_compile/ObjCStandard.cmake create mode 100644 Tests/RunCMake/try_compile/ObjCxxStandard-result.txt create mode 100644 Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt create mode 100644 Tests/RunCMake/try_compile/ObjCxxStandard.cmake create mode 100644 Tests/RunCMake/try_compile/src.m create mode 100644 Tests/RunCMake/try_compile/src.mm create mode 100644 Tests/TryCompile/fail.m create mode 100644 Tests/TryCompile/pass.m diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 910cc9d..5711cae 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -136,13 +136,19 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, std::string copyFile; std::string copyFileError; std::string cStandard; + std::string objcStandard; std::string cxxStandard; + std::string objcxxStandard; std::string cudaStandard; std::string cStandardRequired; std::string cxxStandardRequired; + std::string objcStandardRequired; + std::string objcxxStandardRequired; std::string cudaStandardRequired; std::string cExtensions; std::string cxxExtensions; + std::string objcExtensions; + std::string objcxxExtensions; std::string cudaExtensions; std::vector targets; std::vector linkOptions; @@ -154,12 +160,18 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, bool didCopyFileError = false; bool didCStandard = false; bool didCxxStandard = false; + bool didObjCStandard = false; + bool didObjCxxStandard = false; bool didCudaStandard = false; bool didCStandardRequired = false; bool didCxxStandardRequired = false; + bool didObjCStandardRequired = false; + bool didObjCxxStandardRequired = false; bool didCudaStandardRequired = false; bool didCExtensions = false; bool didCxxExtensions = false; + bool didObjCExtensions = false; + bool didObjCxxExtensions = false; bool didCudaExtensions = false; bool useSources = argv[2] == "SOURCES"; std::vector sources; @@ -176,12 +188,18 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, DoingCopyFileError, DoingCStandard, DoingCxxStandard, + DoingObjCStandard, + DoingObjCxxStandard, DoingCudaStandard, DoingCStandardRequired, DoingCxxStandardRequired, + DoingObjCStandardRequired, + DoingObjCxxStandardRequired, DoingCudaStandardRequired, DoingCExtensions, DoingCxxExtensions, + DoingObjCExtensions, + DoingObjCxxExtensions, DoingCudaExtensions, DoingSources, DoingCMakeInternal @@ -212,6 +230,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } else if (argv[i] == "CXX_STANDARD") { doing = DoingCxxStandard; didCxxStandard = true; + } else if (argv[i] == "OBJC_STANDARD") { + doing = DoingObjCStandard; + didObjCStandard = true; + } else if (argv[i] == "OBJCXX_STANDARD") { + doing = DoingObjCxxStandard; + didObjCxxStandard = true; } else if (argv[i] == "CUDA_STANDARD") { doing = DoingCudaStandard; didCudaStandard = true; @@ -221,6 +245,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } else if (argv[i] == "CXX_STANDARD_REQUIRED") { doing = DoingCxxStandardRequired; didCxxStandardRequired = true; + } else if (argv[i] == "OBJC_STANDARD_REQUIRED") { + doing = DoingObjCStandardRequired; + didObjCStandardRequired = true; + } else if (argv[i] == "OBJCXX_STANDARD_REQUIRED") { + doing = DoingObjCxxStandardRequired; + didObjCxxStandardRequired = true; } else if (argv[i] == "CUDA_STANDARD_REQUIRED") { doing = DoingCudaStandardRequired; didCudaStandardRequired = true; @@ -230,6 +260,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } else if (argv[i] == "CXX_EXTENSIONS") { doing = DoingCxxExtensions; didCxxExtensions = true; + } else if (argv[i] == "OBJC_EXTENSIONS") { + doing = DoingObjCExtensions; + didObjCExtensions = true; + } else if (argv[i] == "OBJCXX_EXTENSIONS") { + doing = DoingObjCxxExtensions; + didObjCxxExtensions = true; } else if (argv[i] == "CUDA_EXTENSIONS") { doing = DoingCudaExtensions; didCudaExtensions = true; @@ -285,6 +321,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } else if (doing == DoingCxxStandard) { cxxStandard = argv[i]; doing = DoingNone; + } else if (doing == DoingObjCStandard) { + objcStandard = argv[i]; + doing = DoingNone; + } else if (doing == DoingObjCxxStandard) { + objcxxStandard = argv[i]; + doing = DoingNone; } else if (doing == DoingCudaStandard) { cudaStandard = argv[i]; doing = DoingNone; @@ -294,6 +336,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } else if (doing == DoingCxxStandardRequired) { cxxStandardRequired = argv[i]; doing = DoingNone; + } else if (doing == DoingObjCStandardRequired) { + objcStandardRequired = argv[i]; + doing = DoingNone; + } else if (doing == DoingObjCxxStandardRequired) { + objcxxStandardRequired = argv[i]; + doing = DoingNone; } else if (doing == DoingCudaStandardRequired) { cudaStandardRequired = argv[i]; doing = DoingNone; @@ -303,6 +351,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } else if (doing == DoingCxxExtensions) { cxxExtensions = argv[i]; doing = DoingNone; + } else if (doing == DoingObjCExtensions) { + objcExtensions = argv[i]; + doing = DoingNone; + } else if (doing == DoingObjCxxExtensions) { + objcxxExtensions = argv[i]; + doing = DoingNone; } else if (doing == DoingCudaExtensions) { cudaExtensions = argv[i]; doing = DoingNone; @@ -754,16 +808,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, fprintf(fout, ")\n"); bool const testC = testLangs.find("C") != testLangs.end(); + bool const testObjC = testLangs.find("OBJC") != testLangs.end(); bool const testCxx = testLangs.find("CXX") != testLangs.end(); + bool const testObjCxx = testLangs.find("OBJCXX") != testLangs.end(); bool const testCuda = testLangs.find("CUDA") != testLangs.end(); bool warnCMP0067 = false; bool honorStandard = true; - if (!didCStandard && !didCxxStandard && !didCudaStandard && - !didCStandardRequired && !didCxxStandardRequired && - !didCudaStandardRequired && !didCExtensions && !didCxxExtensions && - !didCudaExtensions) { + if (!didCStandard && !didCxxStandard && !didObjCStandard && + !didObjCxxStandard && !didCudaStandard && !didCStandardRequired && + !didCxxStandardRequired && !didObjCStandardRequired && + !didObjCxxStandardRequired && !didCudaStandardRequired && + !didCExtensions && !didCxxExtensions && !didObjCExtensions && + !didObjCxxExtensions && !didCudaExtensions) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) { case cmPolicies::WARN: warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled( @@ -786,45 +844,42 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } if (honorStandard || warnCMP0067) { - if (testC) { - if (!didCStandard) { - cStandard = this->LookupStdVar("CMAKE_C_STANDARD", warnCMP0067); - } - if (!didCStandardRequired) { - cStandardRequired = - this->LookupStdVar("CMAKE_C_STANDARD_REQUIRED", warnCMP0067); - } - if (!didCExtensions) { - cExtensions = this->LookupStdVar("CMAKE_C_EXTENSIONS", warnCMP0067); - } - } - if (testCxx) { - if (!didCxxStandard) { - cxxStandard = this->LookupStdVar("CMAKE_CXX_STANDARD", warnCMP0067); - } - if (!didCxxStandardRequired) { - cxxStandardRequired = - this->LookupStdVar("CMAKE_CXX_STANDARD_REQUIRED", warnCMP0067); - } - if (!didCxxExtensions) { - cxxExtensions = - this->LookupStdVar("CMAKE_CXX_EXTENSIONS", warnCMP0067); - } - } - if (testCuda) { - if (!didCudaStandard) { - cudaStandard = - this->LookupStdVar("CMAKE_CUDA_STANDARD", warnCMP0067); - } - if (!didCudaStandardRequired) { - cudaStandardRequired = - this->LookupStdVar("CMAKE_CUDA_STANDARD_REQUIRED", warnCMP0067); - } - if (!didCudaExtensions) { - cudaExtensions = - this->LookupStdVar("CMAKE_CUDA_EXTENSIONS", warnCMP0067); - } - } + + auto testLanguage = + [&](bool testLang, bool didLangStandard, bool didLangStandardRequired, + bool didLangExtensions, std::string& langStandard, + std::string& langStandardRequired, std::string& langExtensions, + const std::string& lang) { + if (testLang) { + if (!didLangStandard) { + langStandard = this->LookupStdVar( + cmStrCat("CMAKE_", lang, "_STANDARD"), warnCMP0067); + } + if (!didLangStandardRequired) { + langStandardRequired = this->LookupStdVar( + cmStrCat("CMAKE_", lang, "_STANDARD_REQUIRED"), warnCMP0067); + } + if (!didLangExtensions) { + langExtensions = this->LookupStdVar( + cmStrCat("CMAKE_", lang, "_EXTENSIONS"), warnCMP0067); + } + } + }; + + testLanguage(testC, didCStandard, didCStandardRequired, didCExtensions, + cStandard, cStandardRequired, cExtensions, "C"); + testLanguage(testObjC, didObjCStandard, didObjCStandardRequired, + didObjCExtensions, objcStandard, objcStandardRequired, + objcExtensions, "OBJC"); + testLanguage(testCxx, didCxxStandard, didCxxStandardRequired, + didCxxExtensions, cxxStandard, cxxStandardRequired, + cxxExtensions, "CXX"); + testLanguage(testObjCxx, didObjCxxStandard, didObjCxxStandardRequired, + didObjCxxExtensions, objcxxStandard, objcxxStandardRequired, + objcxxExtensions, "OBJCXX"); + testLanguage(testCuda, didCudaStandard, didCudaStandardRequired, + didCudaExtensions, cudaStandard, cudaStandardRequired, + cudaExtensions, "CUDA"); } if (!this->WarnCMP0067.empty()) { @@ -841,44 +896,37 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } - if (testC) { - if (!cStandard.empty()) { - writeProperty(fout, targetName, "C_STANDARD", cStandard); - } - if (!cStandardRequired.empty()) { - writeProperty(fout, targetName, "C_STANDARD_REQUIRED", - cStandardRequired); - } - if (!cExtensions.empty()) { - writeProperty(fout, targetName, "C_EXTENSIONS", cExtensions); - } - } - - if (testCxx) { - if (!cxxStandard.empty()) { - writeProperty(fout, targetName, "CXX_STANDARD", cxxStandard); - } - if (!cxxStandardRequired.empty()) { - writeProperty(fout, targetName, "CXX_STANDARD_REQUIRED", - cxxStandardRequired); - } - if (!cxxExtensions.empty()) { - writeProperty(fout, targetName, "CXX_EXTENSIONS", cxxExtensions); - } - } - - if (testCuda) { - if (!cudaStandard.empty()) { - writeProperty(fout, targetName, "CUDA_STANDARD", cudaStandard); - } - if (!cudaStandardRequired.empty()) { - writeProperty(fout, targetName, "CUDA_STANDARD_REQUIRED", - cudaStandardRequired); - } - if (!cudaExtensions.empty()) { - writeProperty(fout, targetName, "CUDA_EXTENSIONS", cudaExtensions); + auto writeLanguageProperties = [&](bool testLang, + const std::string& langStandard, + const std::string& langStandardRequired, + const std::string& langExtensions, + const std::string& lang) { + if (testLang) { + if (!langStandard.empty()) { + writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD"), + langStandard); + } + if (!langStandardRequired.empty()) { + writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD_REQUIRED"), + langStandardRequired); + } + if (!langExtensions.empty()) { + writeProperty(fout, targetName, cmStrCat(lang, "_EXTENSIONS"), + langExtensions); + } } - } + }; + + writeLanguageProperties(testC, cStandard, cStandardRequired, cExtensions, + "C"); + writeLanguageProperties(testObjC, objcStandard, objcStandardRequired, + objcExtensions, "OBJC"); + writeLanguageProperties(testCxx, cxxStandard, cxxStandardRequired, + cxxExtensions, "CXX"); + writeLanguageProperties(testObjCxx, objcxxStandard, objcxxStandardRequired, + objcxxExtensions, "OBJCXX"); + writeLanguageProperties(testCuda, cudaStandard, cudaStandardRequired, + cudaExtensions, "CUDA"); if (!linkOptions.empty()) { std::vector options; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 0925c0e..19a23e0 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -313,6 +313,8 @@ function(add_RunCMake_test_try_compile) CMAKE_CXX_COMPILER_VERSION CMAKE_CXX_STANDARD_DEFAULT CMake_TEST_CUDA + CMAKE_OBJC_STANDARD_DEFAULT + CMAKE_OBJCXX_STANDARD_DEFAULT ) if(DEFINED ${var}) list(APPEND try_compile_ARGS -D${var}=${${var}}) diff --git a/Tests/RunCMake/try_compile/ObjCStandard-result.txt b/Tests/RunCMake/try_compile/ObjCStandard-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/ObjCStandard-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt b/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt new file mode 100644 index 0000000..f1b4df9 --- /dev/null +++ b/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at .*/Tests/RunCMake/try_compile/ObjCStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\): + OBJC_STANDARD is set to invalid value '3' ++ +CMake Error at ObjCStandard.cmake:[0-9]+ \(try_compile\): + Failed to generate test project build system. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_compile/ObjCStandard.cmake b/Tests/RunCMake/try_compile/ObjCStandard.cmake new file mode 100644 index 0000000..b2066f9 --- /dev/null +++ b/Tests/RunCMake/try_compile/ObjCStandard.cmake @@ -0,0 +1,7 @@ +enable_language(OBJC) +try_compile(result ${CMAKE_CURRENT_BINARY_DIR} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.m + OBJC_STANDARD 3 + OUTPUT_VARIABLE out + ) +message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/ObjCxxStandard-result.txt b/Tests/RunCMake/try_compile/ObjCxxStandard-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/ObjCxxStandard-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt b/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt new file mode 100644 index 0000000..a2f91b4 --- /dev/null +++ b/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at .*/Tests/RunCMake/try_compile/ObjCxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\): + OBJCXX_STANDARD is set to invalid value '3' ++ +CMake Error at ObjCxxStandard.cmake:[0-9]+ \(try_compile\): + Failed to generate test project build system. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_compile/ObjCxxStandard.cmake b/Tests/RunCMake/try_compile/ObjCxxStandard.cmake new file mode 100644 index 0000000..1221805 --- /dev/null +++ b/Tests/RunCMake/try_compile/ObjCxxStandard.cmake @@ -0,0 +1,7 @@ +enable_language(OBJCXX) +try_compile(result ${CMAKE_CURRENT_BINARY_DIR} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.mm + OBJCXX_STANDARD 3 + OUTPUT_VARIABLE out + ) +message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake index 77fb7a0..91f014e 100644 --- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake @@ -37,11 +37,17 @@ if(CMAKE_C_STANDARD_DEFAULT) elseif(DEFINED CMAKE_C_STANDARD_DEFAULT) run_cmake(CStandardNoDefault) endif() +if(CMAKE_OBJC_STANDARD_DEFAULT) + run_cmake(ObjCStandard) +endif() if(CMAKE_CXX_STANDARD_DEFAULT) run_cmake(CxxStandard) elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT) run_cmake(CxxStandardNoDefault) endif() +if(CMAKE_OBJCXX_STANDARD_DEFAULT) + run_cmake(ObjCxxStandard) +endif() if(CMake_TEST_CUDA) if(CMAKE_HOST_WIN32) run_cmake(CudaStandardNoDefault) diff --git a/Tests/RunCMake/try_compile/src.m b/Tests/RunCMake/try_compile/src.m new file mode 100644 index 0000000..f8b643a --- /dev/null +++ b/Tests/RunCMake/try_compile/src.m @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/Tests/RunCMake/try_compile/src.mm b/Tests/RunCMake/try_compile/src.mm new file mode 100644 index 0000000..f8b643a --- /dev/null +++ b/Tests/RunCMake/try_compile/src.mm @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt index 498e556..9ec9b70 100644 --- a/Tests/TryCompile/CMakeLists.txt +++ b/Tests/TryCompile/CMakeLists.txt @@ -365,6 +365,25 @@ if (APPLE) TEST_ASSERT(SIMPLE_OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded") TEST_FAIL(OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_RUNS() succeeds, but should have failed") TEST_ASSERT(OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded") + + # try to compile a file that should compile + try_compile(SHOULD_PASS + ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp + ${TryCompile_SOURCE_DIR}/pass.m + OUTPUT_VARIABLE TRY_OUT) + if(NOT SHOULD_PASS) + message(SEND_ERROR "should pass failed ${TRY_OUT}") + endif() + + # try to compile a file that should not compile + try_compile(SHOULD_FAIL + ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp + ${TryCompile_SOURCE_DIR}/fail.m + OUTPUT_VARIABLE TRY_OUT) + if(SHOULD_FAIL) + message(SEND_ERROR "Should fail passed ${TRY_OUT}") + endif() + endif() ####################################################################### diff --git a/Tests/TryCompile/fail.m b/Tests/TryCompile/fail.m new file mode 100644 index 0000000..b915ebe --- /dev/null +++ b/Tests/TryCompile/fail.m @@ -0,0 +1 @@ +asdflkjasdlj diff --git a/Tests/TryCompile/pass.m b/Tests/TryCompile/pass.m new file mode 100644 index 0000000..f8b643a --- /dev/null +++ b/Tests/TryCompile/pass.m @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} -- cgit v0.12