An XCTest bundle is a CFBundle with a special product-type and bundle extension. It gets loaded directly into the AppBundle it should test. For more information about XCTest visit the Mac Developer library at:
http://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/testing_with_xcode/ To build a XCTest bundle, you need to create a CFBundle and set the XCTEST property. Additionally you need to specify the application target to test within the XCTEST_HOST property. CMake and Xcode will then setup the correct target dependencies. add_library(CocoaExampleTest MODULE ...) set_target_properties(CocoaExampleTest PROPERTIES XCTEST TRUE XCTEST_HOST CocoaExample) Signed-off-by: Gregor Jasny <gja...@googlemail.com> --- Help/manual/cmake-properties.7.rst | 2 ++ Help/prop_tgt/XCTEST.rst | 11 +++++++ Help/prop_tgt/XCTEST_HOST.rst | 8 +++++ Source/cmGlobalXCodeGenerator.cxx | 67 ++++++++++++++++++++++++++++++++++++-- Source/cmTarget.cxx | 19 +++++++++-- Source/cmTarget.h | 3 ++ 6 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 Help/prop_tgt/XCTEST.rst create mode 100644 Help/prop_tgt/XCTEST_HOST.rst diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index cca6d28..7b8aa66 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -242,6 +242,8 @@ Properties on Targets /prop_tgt/VS_WINRT_REFERENCES /prop_tgt/WIN32_EXECUTABLE /prop_tgt/XCODE_ATTRIBUTE_an-attribute + /prop_tgt/XCTEST + /prop_tgt/XCTEST_HOST Properties on Tests =================== diff --git a/Help/prop_tgt/XCTEST.rst b/Help/prop_tgt/XCTEST.rst new file mode 100644 index 0000000..9086485 --- /dev/null +++ b/Help/prop_tgt/XCTEST.rst @@ -0,0 +1,11 @@ +XCTEST +------ + +This target is a XCTest CFBundle on the Mac. + +If a module library target has this property set to true it will be +built as a CFBundle when built on the mac. It will have the directory +structure required for a CFBundle. + +This property implies :prop_tgt:`BUNDLE` and also requires the +:prop_tgt:`XCTEST_HOST` property to be set. diff --git a/Help/prop_tgt/XCTEST_HOST.rst b/Help/prop_tgt/XCTEST_HOST.rst new file mode 100644 index 0000000..5284246 --- /dev/null +++ b/Help/prop_tgt/XCTEST_HOST.rst @@ -0,0 +1,8 @@ +XCTEST_HOST +----------- + +XCTest works by injecting an XCTest CFBundle directly into an AppBundle. +This property names this destination target under test. + +This property is only useful with the Xcode Generator and also needs the +:prop_tgt:`XCTEST` property enabled on the target. diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 6a480a9..7a71e70 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -493,6 +493,15 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, allbuild->AddUtility(target.GetName()); } + if(target.IsXCTestOnApple()) + { + const char *testHostName = target.GetProperty("XCTEST_HOST"); + if(testHostName && this->CurrentMakefile->FindTargetToUse(testHostName)) + { + target.AddUtility(testHostName); + } + } + // Refer to the build configuration file for easy editing. listfile = lg->GetMakefile()->GetStartDirectory(); listfile += "/"; @@ -761,6 +770,10 @@ GetSourcecodeValueFromFileExtension(const std::string& _ext, { sourcecode = "compiled.mach-o.objfile"; } + else if(ext == "xctest") + { + sourcecode = "wrapper.cfbundle"; + } else if(ext == "xib") { keepLastKnownFileType = true; @@ -2321,6 +2334,52 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION", this->CreateString(vso.str().c_str())); } + + if(target.IsXCTestOnApple()) + { + if(this->XcodeVersion < 50) + { + this->CMakeInstance->IssueMessage(cmake::WARNING, + "Xcode 5.0 or later is required for XCTEST support.", + target.GetBacktrace()); + } + + const char *testHostName = target.GetProperty("XCTEST_HOST"); + if(!testHostName) + { + this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, + "target has XCTEST property but no XCTEST_HOST one.", + target.GetBacktrace()); + return; + } + + cmTarget *testHostTarget = + this->CurrentMakefile->FindTargetToUse(testHostName); + if(!testHostTarget) + { + cmOStringStream e; + e << "Cannot find XCTEST_HOST target: " << testHostName; + this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, + e.str(), target.GetBacktrace()); + return; + } + + if (!testHostTarget->IsAppBundleOnApple()) + { + cmOStringStream e; + e << "XCTEST_HOST target " << testHostName; + e << " is not an App Bundle"; + this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, + e.str(), target.GetBacktrace()); + return; + } + + buildSettings->AddAttribute("BUNDLE_LOADER", + this->CreateString("$(TEST_HOST)")); + buildSettings->AddAttribute("TEST_HOST", + this->CreateString(testHostTarget->GetLocationForBuild())); + } + // put this last so it can override existing settings // Convert "XCODE_ATTRIBUTE_*" properties directly. { @@ -2519,7 +2578,9 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(cmTarget& cmtarget) case cmTarget::STATIC_LIBRARY: return "archive.ar"; case cmTarget::MODULE_LIBRARY: - if (cmtarget.IsCFBundleOnApple()) + if (cmtarget.IsXCTestOnApple()) + return "wrapper.cfbundle"; + else if (cmtarget.IsCFBundleOnApple()) return "wrapper.plug-in"; else return ((this->XcodeVersion >= 22)? @@ -2543,7 +2604,9 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(cmTarget& cmtarget) case cmTarget::STATIC_LIBRARY: return "com.apple.product-type.library.static"; case cmTarget::MODULE_LIBRARY: - if (cmtarget.IsCFBundleOnApple()) + if (cmtarget.IsXCTestOnApple()) + return "com.apple.product-type.bundle.unit-test"; + else if (cmtarget.IsCFBundleOnApple()) return "com.apple.product-type.bundle"; else return ((this->XcodeVersion >= 22)? diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 90295c8..db1d0f2 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -624,7 +624,15 @@ bool cmTarget::IsCFBundleOnApple() const { return (this->GetType() == cmTarget::MODULE_LIBRARY && this->Makefile->IsOn("APPLE") && - this->GetPropertyAsBool("BUNDLE")); + (this->GetPropertyAsBool("BUNDLE") || + this->GetPropertyAsBool("XCTEST"))); +} + +//---------------------------------------------------------------------------- +bool cmTarget::IsXCTestOnApple() const +{ + return (this->IsCFBundleOnApple() && + this->GetPropertyAsBool("XCTEST")); } //---------------------------------------------------------------------------- @@ -6842,7 +6850,14 @@ std::string cmTarget::GetCFBundleDirectory(const std::string& config, const char *ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { - ext = "bundle"; + if (this->IsXCTestOnApple()) + { + ext = "xctest"; + } + else + { + ext = "bundle"; + } } fpath += ext; fpath += "/Contents"; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index a3ecca0..5786d78 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -526,6 +526,9 @@ public: /** Return whether this target is a CFBundle (plugin) on Apple. */ bool IsCFBundleOnApple() const; + /** Return whether this target is a XCTest on Apple. */ + bool IsXCTestOnApple() const; + /** Return whether this target is an executable Bundle on Apple. */ bool IsAppBundleOnApple() const; -- 1.9.3 (Apple Git-50) -- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake-developers