diff options
61 files changed, 1816 insertions, 39 deletions
diff --git a/Help/generator/Qbs.rst b/Help/generator/Qbs.rst new file mode 100644 index 0000000..e569b77 --- /dev/null +++ b/Help/generator/Qbs.rst @@ -0,0 +1,25 @@ +Qbs +--- + +Generates Qbs project files. + +Project files for Qbs will be created in the top directory and +in every subdirectory which features a CMakeLists.txt file containing +a PROJECT() call. Additionally a hierarchy of makefiles is generated +into the build tree. The appropriate make program can build the +project through the default make target. A "make install" target is +also provided. + +This "extra" generator may be specified as: + +``Qbs - MinGW Makefiles`` + Generate with :generator:`MinGW Makefiles`. + +``Qbs - NMake Makefiles`` + Generate with :generator:`NMake Makefiles`. + +``Qbs - Ninja`` + Generate with :generator:`Ninja`. + +``Qbs - Unix Makefiles`` + Generate with :generator:`Unix Makefiles`. diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst index bda7eef..804229b 100644 --- a/Help/manual/cmake-generators.7.rst +++ b/Help/manual/cmake-generators.7.rst @@ -85,3 +85,4 @@ The following extra generators are known to CMake. /generator/KDevelop3 /generator/Kate /generator/Sublime Text 2 + /generator/Qbs diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 2b26cc9..c9219d5 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -212,6 +212,7 @@ All Modules /module/FindWish /module/FindwxWidgets /module/FindwxWindows + /module/FindXCTest /module/FindXercesC /module/FindX11 /module/FindXMLRPC diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 19fdf23..1dff33e 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -243,6 +243,7 @@ Properties on Targets /prop_tgt/VS_WINRT_REFERENCES /prop_tgt/WIN32_EXECUTABLE /prop_tgt/XCODE_ATTRIBUTE_an-attribute + /prop_tgt/XCTEST Properties on Tests =================== diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index cc132c2..dd3bcfb 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -194,6 +194,11 @@ Options subsequent calls to ctest with the --rerun-failed option will run the set of tests that most recently failed (if any). +``--repeat-until-fail <n>`` + Require each test to run ``<n>`` times without failing in order to pass. + + This is useful in finding sporadic failures in test cases. + ``--max-width <width>`` Set the max width for a test name to output diff --git a/Help/module/FindXCTest.rst b/Help/module/FindXCTest.rst new file mode 100644 index 0000000..ff6273c --- /dev/null +++ b/Help/module/FindXCTest.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindXCTest.cmake diff --git a/Help/prop_tgt/XCTEST.rst b/Help/prop_tgt/XCTEST.rst new file mode 100644 index 0000000..eb47e60 --- /dev/null +++ b/Help/prop_tgt/XCTEST.rst @@ -0,0 +1,13 @@ +XCTEST +------ + +This target is a XCTest CFBundle on the Mac. + +This property will usually get set via the :command:`xctest_add_bundle` +macro in :module:`FindXCTest` module. + +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 depends on :prop_tgt:`BUNDLE` to be effective. diff --git a/Help/release/dev/add-extra-qbs-generator.rst b/Help/release/dev/add-extra-qbs-generator.rst new file mode 100644 index 0000000..edb441f --- /dev/null +++ b/Help/release/dev/add-extra-qbs-generator.rst @@ -0,0 +1,6 @@ +add-extra-qbs-geneator +---------------------- + +* It is now possible to generate :generator:`Qbs` project files + for use with QtCreator IDE, matching make tool must be used + to build the project through the generated makefiles. diff --git a/Help/release/dev/ctest-repeat-until-fail.rst b/Help/release/dev/ctest-repeat-until-fail.rst new file mode 100644 index 0000000..8a679c6 --- /dev/null +++ b/Help/release/dev/ctest-repeat-until-fail.rst @@ -0,0 +1,5 @@ +ctest-repeat-until-fail +----------------------- + +* The :manual:`ctest(1)` tool learned a new ``--repeat-until-fail <n>`` + option to help find sporadic test failures. diff --git a/Help/release/dev/xcode-xctest.rst b/Help/release/dev/xcode-xctest.rst new file mode 100644 index 0000000..7a2f07b --- /dev/null +++ b/Help/release/dev/xcode-xctest.rst @@ -0,0 +1,6 @@ +xcode-xctest +------------ + +* On OS X, CMake learned to create XCTest bundles to test Frameworks + and App Bundles within Xcode. The :module:`FindXCTest` module + provides convenience functions to handle :prop_tgt:`XCTEST` bundles. diff --git a/Modules/CPackBundle.cmake b/Modules/CPackBundle.cmake index d26a0b3..b412216 100644 --- a/Modules/CPackBundle.cmake +++ b/Modules/CPackBundle.cmake @@ -52,6 +52,11 @@ # list the main application folder, or the main executable. You should # list any frameworks and plugins that are included in your app bundle. # +# .. variable:: CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER +# +# Additional parameter that will passed to codesign. +# Default value: "--deep -f" +# # .. variable:: CPACK_COMMAND_CODESIGN # # Path to the codesign(1) command used to sign applications with an diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake index 539a0aa..162eba7 100644 --- a/Modules/CPackRPM.cmake +++ b/Modules/CPackRPM.cmake @@ -408,6 +408,16 @@ # # May be used to set per component CPACK_PACKAGING_INSTALL_PREFIX for # relocatable RPM packages. +# +# .. variable:: CPACK_RPM_NO_INSTALL_PREFIX_RELOCATION +# CPACK_RPM_NO_<COMPONENT>_INSTALL_PREFIX_RELOCATION +# +# * Mandatory : NO +# * Default : CPACK_PACKAGING_INSTALL_PREFIX or CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX +# are treated as one of relocation paths +# +# May be used to remove CPACK_PACKAGING_INSTALL_PREFIX and CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX +# from relocatable RPM prefix paths. #============================================================================= # Copyright 2007-2009 Kitware, Inc. @@ -437,8 +447,15 @@ function(cpack_rpm_prepare_relocation_paths) # set base path prefix if(EXISTS "${WDIR}/${PATH_PREFIX}") - set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}Prefix: ${PATH_PREFIX}\n") - list(APPEND RPM_USED_PACKAGE_PREFIXES "${PATH_PREFIX}") + if(NOT CPACK_RPM_NO_INSTALL_PREFIX_RELOCATION AND + NOT CPACK_RPM_NO_${CPACK_RPM_PACKAGE_COMPONENT}_INSTALL_PREFIX_RELOCATION) + set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}Prefix: ${PATH_PREFIX}\n") + list(APPEND RPM_USED_PACKAGE_PREFIXES "${PATH_PREFIX}") + + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: removing '${PATH_PREFIX}' from relocation paths") + endif() + endif() endif() # set other path prefixes diff --git a/Modules/Compiler/SunPro-Fortran.cmake b/Modules/Compiler/SunPro-Fortran.cmake index e4db1e8..196aae4 100644 --- a/Modules/Compiler/SunPro-Fortran.cmake +++ b/Modules/Compiler/SunPro-Fortran.cmake @@ -2,6 +2,7 @@ set(CMAKE_Fortran_VERBOSE_FLAG "-v") set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-fixed") set(CMAKE_Fortran_FORMAT_FREE_FLAG "-free") +set(CMAKE_Fortran_COMPILE_OPTIONS_PIC "-KPIC") set(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "-KPIC") set(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-G") set(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG "-R") diff --git a/Modules/FindXCTest.cmake b/Modules/FindXCTest.cmake new file mode 100644 index 0000000..3cd9c22 --- /dev/null +++ b/Modules/FindXCTest.cmake @@ -0,0 +1,196 @@ +#[=======================================================================[.rst: +FindXCTest +---------- + +Functions to help creating and executing XCTest bundles. + +An XCTest bundle is a CFBundle with a special product-type +and bundle extension. The Mac Developer Library provides more +information in the `Testing with Xcode`_ document. + +.. _Testing with Xcode: http://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/testing_with_xcode/ + +Module Functions +^^^^^^^^^^^^^^^^ + +.. command:: xctest_add_bundle + + The ``xctest_add_bundle`` function creates a XCTest bundle named + <target> which will test the target <testee>. Supported target types + for testee are Frameworks and App Bundles:: + + xctest_add_bundle( + <target> # Name of the XCTest bundle + <testee> # Target name of the testee + ) + +.. command:: xctest_add_test + + The ``xctest_add_test`` function adds an XCTest bundle to the + project to be run by :manual:`ctest(1)`. The test will be named + <name> and tests <bundle>:: + + xctest_add_test( + <name> # Test name + <bundle> # Target name of XCTest bundle + ) + +Module Variables +^^^^^^^^^^^^^^^^ + +The following variables are set by including this module: + +.. variable:: XCTest_FOUND + + True if the XCTest Framework and executable were found. + +.. variable:: XCTest_EXECUTABLE + + The path to the xctest command line tool used to execute XCTest bundles. + +.. variable:: XCTest_INCLUDE_DIRS + + The directory containing the XCTest Framework headers. + +.. variable:: XCTest_LIBRARIES + + The location of the XCTest Framework. + +#]=======================================================================] + +#============================================================================= +# Copyright 2015 Gregor Jasny +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +find_path(XCTest_INCLUDE_DIR + NAMES "XCTest/XCTest.h" + DOC "XCTest include directory") +mark_as_advanced(XCTest_INCLUDE_DIR) + +find_library(XCTest_LIBRARY + NAMES XCTest + DOC "XCTest Framework library") +mark_as_advanced(XCTest_LIBRARY) + +execute_process( + COMMAND xcrun --find xctest + OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _xcrun_err) +if(_xcrun_out) + set(XCTest_EXECUTABLE "${_xcrun_out}" CACHE FILEPATH "XCTest executable") + mark_as_advanced(XCTest_EXECUTABLE) +endif() + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +find_package_handle_standard_args(XCTest + FOUND_VAR XCTest_FOUND + REQUIRED_VARS XCTest_LIBRARY XCTest_INCLUDE_DIR XCTest_EXECUTABLE) + +if(XCTest_FOUND) + set(XCTest_INCLUDE_DIRS "${XCTest_INCLUDE_DIR}") + set(XCTest_LIBRARIES "${XCTest_LIBRARY}") +endif(XCTest_FOUND) + + +function(xctest_add_bundle target testee) + if(NOT XCTest_FOUND) + message(FATAL_ERROR "XCTest is required to create a XCTest Bundle.") + endif(NOT XCTest_FOUND) + + if(NOT CMAKE_OSX_SYSROOT) + message(FATAL_ERROR "Adding XCTest bundles requires CMAKE_OSX_SYSROOT to be set.") + endif() + + add_library(${target} MODULE ${ARGN}) + + set_target_properties(${target} PROPERTIES + BUNDLE TRUE + XCTEST TRUE + XCTEST_TESTEE ${testee}) + + target_link_libraries(${target} PRIVATE "-framework Foundation") + target_link_libraries(${target} PRIVATE ${XCTest_LIBRARIES}) + target_include_directories(${target} PRIVATE ${XCTest_INCLUDE_DIRS}) + + # retrieve testee target type + if(NOT TARGET ${testee}) + message(FATAL_ERROR "${testee} is not a target.") + endif() + get_property(_testee_type TARGET ${testee} PROPERTY TYPE) + get_property(_testee_framework TARGET ${testee} PROPERTY FRAMEWORK) + get_property(_testee_macosx_bundle TARGET ${testee} PROPERTY MACOSX_BUNDLE) + + if(_testee_type STREQUAL "SHARED_LIBRARY" AND _testee_framework) + # testee is a Framework + target_link_libraries(${target} PRIVATE ${testee}) + + elseif(_testee_type STREQUAL "EXECUTABLE" AND _testee_macosx_bundle) + # testee is an App Bundle + add_dependencies(${target} ${testee}) + if(XCODE) + set_target_properties(${target} PROPERTIES + XCODE_ATTRIBUTE_BUNDLE_LOADER "$(TEST_HOST)" + XCODE_ATTRIBUTE_TEST_HOST "$<TARGET_FILE:${testee}>") + else(XCODE) + target_link_libraries(${target} + PRIVATE -bundle_loader $<TARGET_FILE:${testee}>) + endif(XCODE) + + else() + message(FATAL_ERROR "Testee ${testee} is of unsupported type.") + endif() +endfunction(xctest_add_bundle) + + +function(xctest_add_test name bundle) + if(NOT XCTest_EXECUTABLE) + message(FATAL_ERROR "XCTest executable is required to register a test.") + endif() + + # check that bundle is a XCTest Bundle + + if(NOT TARGET ${bundle}) + message(FATAL_ERROR "${bundle} is not a target.") + endif(NOT TARGET ${bundle}) + + get_property(_test_type TARGET ${bundle} PROPERTY TYPE) + get_property(_test_bundle TARGET ${bundle} PROPERTY BUNDLE) + get_property(_test_xctest TARGET ${bundle} PROPERTY XCTEST) + + if(NOT _test_type STREQUAL "MODULE_LIBRARY" + OR NOT _test_xctest OR NOT _test_bundle) + message(FATAL_ERROR "Test ${bundle} is not an XCTest Bundle") + endif() + + # get and check testee properties + + get_property(_testee TARGET ${bundle} PROPERTY XCTEST_TESTEE) + if(NOT TARGET ${_testee}) + message(FATAL_ERROR "${_testee} is not a target.") + endif() + + get_property(_testee_type TARGET ${_testee} PROPERTY TYPE) + get_property(_testee_framework TARGET ${_testee} PROPERTY FRAMEWORK) + + # register test + + add_test( + NAME ${name} + COMMAND ${XCTest_EXECUTABLE} $<TARGET_LINKER_FILE_DIR:${bundle}>/../..) + + # point loader to testee in case rpath is disabled + + if(_testee_type STREQUAL "SHARED_LIBRARY" AND _testee_framework) + set_property(TEST ${name} APPEND PROPERTY + ENVIRONMENT DYLD_FRAMEWORK_PATH=$<TARGET_LINKER_FILE_DIR:${_testee}>/..) + endif() +endfunction(xctest_add_test) diff --git a/Modules/Platform/Linux-PGI.cmake b/Modules/Platform/Linux-PGI.cmake index 3cbb35c..baa2248 100644 --- a/Modules/Platform/Linux-PGI.cmake +++ b/Modules/Platform/Linux-PGI.cmake @@ -21,7 +21,7 @@ set(__LINUX_COMPILER_PGI 1) macro(__linux_compiler_pgi lang) # Shared library compile and link flags. set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") - set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "") set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") endmacro() diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 3a6acd8..5eb0ca8 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -340,6 +340,13 @@ set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake) function(add_jar _TARGET_NAME) + cmake_parse_arguments(_add_jar + "" + "VERSION;OUTPUT_DIR;OUTPUT_NAME;ENTRY_POINT;MANIFEST" + "SOURCES;INCLUDE_JARS" + ${ARGN} + ) + # In CMake < 2.8.12, add_jar used variables which were set prior to calling # add_jar for customizing the behavior of add_jar. In order to be backwards # compatible, check if any of those variables are set, and use them to @@ -347,28 +354,21 @@ function(add_jar _TARGET_NAME) # argument will override the value set here.) # # New features should use named arguments only. - if(DEFINED CMAKE_JAVA_TARGET_VERSION) + if(NOT DEFINED _add_jar_VERSION AND DEFINED CMAKE_JAVA_TARGET_VERSION) set(_add_jar_VERSION "${CMAKE_JAVA_TARGET_VERSION}") endif() - if(DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) + if(NOT DEFINED _add_jar_OUTPUT_DIR AND DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) set(_add_jar_OUTPUT_DIR "${CMAKE_JAVA_TARGET_OUTPUT_DIR}") endif() - if(DEFINED CMAKE_JAVA_TARGET_OUTPUT_NAME) + if(NOT DEFINED _add_jar_OUTPUT_NAME AND DEFINED CMAKE_JAVA_TARGET_OUTPUT_NAME) set(_add_jar_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}") # reset set(CMAKE_JAVA_TARGET_OUTPUT_NAME) endif() - if(DEFINED CMAKE_JAVA_JAR_ENTRY_POINT) + if(NOT DEFINED _add_jar_ENTRY_POINT AND DEFINED CMAKE_JAVA_JAR_ENTRY_POINT) set(_add_jar_ENTRY_POINT "${CMAKE_JAVA_JAR_ENTRY_POINT}") endif() - cmake_parse_arguments(_add_jar - "" - "VERSION;OUTPUT_DIR;OUTPUT_NAME;ENTRY_POINT;MANIFEST" - "SOURCES;INCLUDE_JARS" - ${ARGN} - ) - set(_JAVA_SOURCE_FILES ${_add_jar_SOURCES} ${_add_jar_UNPARSED_ARGUMENTS}) if (NOT DEFINED _add_jar_OUTPUT_DIR) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 482bd39..04f6a81 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -229,6 +229,8 @@ set(SRCS cmExtraKateGenerator.h cmExtraSublimeTextGenerator.cxx cmExtraSublimeTextGenerator.h + cmExtraQbsGenerator.cxx + cmExtraQbsGenerator.h cmFileLock.cxx cmFileLock.h cmFileLockPool.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8127464..5ef57ab 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 2) -set(CMake_VERSION_PATCH 20150320) +set(CMake_VERSION_PATCH 20150323) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index 6e7a26b..b2d7019 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -221,6 +221,11 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) bundle_path += ".app"; // A list of additional files to sign, ie. frameworks and plugins. + const std::string sign_parameter = + this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER") + ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER") + : "--deep -f"; + const std::string sign_files = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES") ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES") : ""; @@ -234,7 +239,8 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) { std::ostringstream temp_sign_file_cmd; temp_sign_file_cmd << this->GetOption("CPACK_COMMAND_CODESIGN"); - temp_sign_file_cmd << " --deep -f -s \"" << cpack_apple_cert_app; + temp_sign_file_cmd << " " << sign_parameter << " -s \"" + << cpack_apple_cert_app; temp_sign_file_cmd << "\" -i "; temp_sign_file_cmd << this->GetOption("CPACK_APPLE_BUNDLE_ID"); temp_sign_file_cmd << " \""; @@ -254,7 +260,8 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) // sign main binary std::ostringstream temp_sign_binary_cmd; temp_sign_binary_cmd << this->GetOption("CPACK_COMMAND_CODESIGN"); - temp_sign_binary_cmd << " --deep -f -s \"" << cpack_apple_cert_app; + temp_sign_binary_cmd << " " << sign_parameter << " -s \"" + << cpack_apple_cert_app; temp_sign_binary_cmd << "\" \"" << bundle_path << "\""; if(!this->RunCommand(temp_sign_binary_cmd, &output)) @@ -269,7 +276,8 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) // sign app bundle std::ostringstream temp_codesign_cmd; temp_codesign_cmd << this->GetOption("CPACK_COMMAND_CODESIGN"); - temp_codesign_cmd << " --deep -f -s \"" << cpack_apple_cert_app << "\""; + temp_codesign_cmd << " " << sign_parameter << " -s \"" + << cpack_apple_cert_app << "\""; if(this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS")) { temp_codesign_cmd << " --entitlements "; diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index eb33d8e..bd090db 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -121,6 +121,11 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test) this->RunningCount += GetProcessorsUsed(test); cmCTestRunTest* testRun = new cmCTestRunTest(this->TestHandler); + if(this->CTest->GetRepeatUntilFail()) + { + testRun->SetRunUntilFailOn(); + testRun->SetNumberOfRuns(this->CTest->GetTestRepeat()); + } testRun->SetIndex(test); testRun->SetTestProperties(this->Properties[test]); @@ -289,7 +294,13 @@ bool cmCTestMultiProcessHandler::CheckOutput() cmCTestRunTest* p = *i; int test = p->GetIndex(); - if(p->EndTest(this->Completed, this->Total, true)) + bool testResult = p->EndTest(this->Completed, this->Total, true); + if(p->StartAgain()) + { + this->Completed--; // remove the completed test because run again + continue; + } + if(testResult) { this->Passed->push_back(p->GetTestProperties()->Name); } diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 01a7884..d7da2b4 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -33,6 +33,9 @@ cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler) this->CompressedOutput = ""; this->CompressionRatio = 2; this->StopTimePassed = false; + this->NumberOfRunsLeft = 1; // default to 1 run of the test + this->RunUntilFail = false; // default to run the test once + this->RunAgain = false; // default to not having to run again } cmCTestRunTest::~cmCTestRunTest() @@ -357,13 +360,50 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) this->MemCheckPostProcess(); this->ComputeWeightedCost(); } - // Always push the current TestResult onto the + // If the test does not need to rerun push the current TestResult onto the // TestHandler vector - this->TestHandler->TestResults.push_back(this->TestResult); + if(!this->NeedsToRerun()) + { + this->TestHandler->TestResults.push_back(this->TestResult); + } delete this->TestProcess; return passed; } +bool cmCTestRunTest::StartAgain() +{ + if(!this->RunAgain) + { + return false; + } + this->RunAgain = false; // reset + // change to tests directory + std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); + cmSystemTools::ChangeDirectory(this->TestProperties->Directory); + this->StartTest(this->TotalNumberOfTests); + // change back + cmSystemTools::ChangeDirectory(current_dir); + return true; +} + +bool cmCTestRunTest::NeedsToRerun() +{ + this->NumberOfRunsLeft--; + if(this->NumberOfRunsLeft == 0) + { + return false; + } + // if number of runs left is not 0, and we are running until + // we find a failed test, then return true so the test can be + // restarted + if(this->RunUntilFail + && this->TestResult.Status == cmCTestTestHandler::COMPLETED) + { + this->RunAgain = true; + return true; + } + return false; +} //---------------------------------------------------------------------- void cmCTestRunTest::ComputeWeightedCost() { @@ -400,6 +440,7 @@ void cmCTestRunTest::MemCheckPostProcess() // Starts the execution of a test. Returns once it has started bool cmCTestRunTest::StartTest(size_t total) { + this->TotalNumberOfTests = total; // save for rerun case cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(2*getNumWidth(total) + 8) << "Start " << std::setw(getNumWidth(this->TestHandler->GetMaxIndex())) @@ -494,10 +535,10 @@ bool cmCTestRunTest::StartTest(size_t total) //---------------------------------------------------------------------- void cmCTestRunTest::ComputeArguments() { + this->Arguments.clear(); // reset becaue this might be a rerun std::vector<std::string>::const_iterator j = this->TestProperties->Args.begin(); ++j; // skip test name - // find the test executable if(this->TestHandler->MemCheck) { @@ -697,10 +738,28 @@ bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout, void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) - << completed << "/"); - cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) - << total << " "); + // if this is the last or only run of this test + // then print out completed / total + // Only issue is if a test fails and we are running until fail + // then it will never print out the completed / total, same would + // got for run until pass. Trick is when this is called we don't + // yet know if we are passing or failing. + if(this->NumberOfRunsLeft == 1) + { + cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) + << completed << "/"); + cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) + << total << " "); + } + // if this is one of several runs of a test just print blank space + // to keep things neat + else + { + cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) + << " " << " "); + cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total)) + << " " << " "); + } if ( this->TestHandler->MemCheck ) { diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 476f3e1..3b5c831 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -27,6 +27,8 @@ public: cmCTestRunTest(cmCTestTestHandler* handler); ~cmCTestRunTest(); + void SetNumberOfRuns(int n) {this->NumberOfRunsLeft = n;} + void SetRunUntilFailOn() { this->RunUntilFail = true;} void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties * prop) { this->TestProperties = prop; } @@ -58,7 +60,10 @@ public: void ComputeArguments(); void ComputeWeightedCost(); + + bool StartAgain(); private: + bool NeedsToRerun(); void DartProcessing(); void ExeNotFound(std::string exe); // Figures out a final timeout which is min(STOP_TIME, NOW+TIMEOUT) @@ -92,6 +97,10 @@ private: std::string ActualCommand; std::vector<std::string> Arguments; bool StopTimePassed; + bool RunUntilFail; + int NumberOfRunsLeft; + bool RunAgain; + size_t TotalNumberOfTests; }; inline int getNumWidth(size_t n) diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 1d0df69..0026fd7 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -329,6 +329,8 @@ cmCTest::cmCTest() this->OutputTestOutputOnTestFailure = false; this->ComputedCompressTestOutput = false; this->ComputedCompressMemCheckOutput = false; + this->RepeatTests = 1; // default to run each test once + this->RepeatUntilFail = false; if(cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE")) { this->OutputTestOutputOnTestFailure = true; @@ -1984,11 +1986,11 @@ bool cmCTest::CheckArgument(const std::string& arg, const char* varg1, //---------------------------------------------------------------------- // Processes one command line argument (and its arguments if any) // for many simple options and then returns -void cmCTest::HandleCommandLineArguments(size_t &i, - std::vector<std::string> &args) +bool cmCTest::HandleCommandLineArguments(size_t &i, + std::vector<std::string> &args, + std::string& errormsg) { std::string arg = args[i]; - if(this->CheckArgument(arg, "-F")) { this->Failover = true; @@ -2006,6 +2008,27 @@ void cmCTest::HandleCommandLineArguments(size_t &i, this->SetParallelLevel(plevel); this->ParallelLevelSetInCli = true; } + if(this->CheckArgument(arg, "--repeat-until-fail")) + { + if( i >= args.size() - 1) + { + errormsg = "'--repeat-until-fail' requires an argument"; + return false; + } + i++; + long repeat = 1; + if(!cmSystemTools::StringToLong(args[i].c_str(), &repeat)) + { + errormsg = "'--repeat-until-fail' given non-integer value '" + + args[i] + "'"; + return false; + } + this->RepeatTests = static_cast<int>(repeat); + if(repeat > 1) + { + this->RepeatUntilFail = true; + } + } if(this->CheckArgument(arg, "--no-compress-output")) { @@ -2191,6 +2214,7 @@ void cmCTest::HandleCommandLineArguments(size_t &i, this->GetHandler("test")->SetPersistentOption("RerunFailed", "true"); this->GetHandler("memcheck")->SetPersistentOption("RerunFailed", "true"); } + return true; } //---------------------------------------------------------------------- @@ -2273,7 +2297,12 @@ int cmCTest::Run(std::vector<std::string> &args, std::string* output) for(size_t i=1; i < args.size(); ++i) { // handle the simple commandline arguments - this->HandleCommandLineArguments(i,args); + std::string errormsg; + if(!this->HandleCommandLineArguments(i,args, errormsg)) + { + cmSystemTools::Error(errormsg.c_str()); + return 1; + } // handle the script arguments -S -SR -SP this->HandleScriptArguments(i,args,SRArgumentSpecified); diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 88191c4..3f033d9 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -429,8 +429,13 @@ public: { return this->Definitions; } - + // return the number of times a test should be run + int GetTestRepeat() { return this->RepeatTests;} + // return true if test should run until fail + bool GetRepeatUntilFail() { return this->RepeatUntilFail;} private: + int RepeatTests; + bool RepeatUntilFail; std::string ConfigType; std::string ScheduleType; std::string StopTime; @@ -535,8 +540,9 @@ private: bool AddVariableDefinition(const std::string &arg); //! parse and process most common command line arguments - void HandleCommandLineArguments(size_t &i, - std::vector<std::string> &args); + bool HandleCommandLineArguments(size_t &i, + std::vector<std::string> &args, + std::string& errormsg); //! hande the -S -SP and -SR arguments void HandleScriptArguments(size_t &i, diff --git a/Source/cmExtraQbsGenerator.cxx b/Source/cmExtraQbsGenerator.cxx new file mode 100644 index 0000000..5a1f9ef --- /dev/null +++ b/Source/cmExtraQbsGenerator.cxx @@ -0,0 +1,260 @@ +#include "cmExtraQbsGenerator.h" + +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmGeneratedFileStream.h" +#include "cmSourceFile.h" + +cmExtraQbsGenerator::cmExtraQbsGenerator() +{ +#if defined(_WIN32) + this->SupportedGlobalGenerators.push_back("MinGW Makefiles"); + this->SupportedGlobalGenerators.push_back("NMake Makefiles"); +#endif + this->SupportedGlobalGenerators.push_back("Ninja"); + this->SupportedGlobalGenerators.push_back("Unix Makefiles"); +} + +cmExtraQbsGenerator::~cmExtraQbsGenerator() {} + +void cmExtraQbsGenerator::GetDocumentation(cmDocumentationEntry &entry, + const std::string &) const +{ + entry.Name = this->GetName(); + entry.Brief = "Generates Qbs project files."; +} + +void cmExtraQbsGenerator::Generate() +{ + for (std::map<std::string, std::vector<cmLocalGenerator *> >::const_iterator + it = this->GlobalGenerator->GetProjectMap().begin(); + it != this->GlobalGenerator->GetProjectMap().end(); ++it) + { + // create a project file + this->CreateProjectFile(it->first, it->second); + } +} + +void cmExtraQbsGenerator::CreateProjectFile( + const std::string &name, + const std::vector<cmLocalGenerator *> &lgs) +{ + const cmMakefile *mf = lgs[0]->GetMakefile(); + std::string outputDir = mf->GetStartOutputDirectory(); + + const std::string filename = outputDir + "/" + name + ".qbs"; + + this->CreateNewProjectFile(name, lgs, filename); +} + +void cmExtraQbsGenerator::CreateNewProjectFile( + const std::string &projectName, const std::vector<cmLocalGenerator *> &lgs, + const std::string &filename) +{ + cmGeneratedFileStream fout(filename.c_str()); + if (!fout) + { + return; + } + + fout << "import qbs\n" + << "import qbs.File\n\n" + << "Project {\n" + << "\tname:\"" << projectName << "\"\n"; + std::vector<cmLocalGenerator *>::const_iterator itr = lgs.begin(); + for (; itr != lgs.end(); ++itr) + { + cmLocalGenerator *lg = (*itr); + this->AppendSubProject(fout, lg); + } + fout << "}\n"; +} + +void cmExtraQbsGenerator::AppendSubProject(cmGeneratedFileStream &fout, + cmLocalGenerator *lg) +{ + const cmMakefile *mk = lg->GetMakefile(); + if (!mk || mk->GetTargets().size() == 0) + { + return; + } + + const std::string &relativePath = cmSystemTools::RelativePath( + mk->GetHomeDirectory(), mk->GetCurrentDirectory()); + fout << "\tProject {\n" + << "\t\tname:\"" << relativePath << "\"\n"; + this->AppendProduct(fout, lg); + fout << "\t}\n"; +} + +void cmExtraQbsGenerator::AppendProduct(cmGeneratedFileStream &fout, + cmLocalGenerator *lg) +{ + const cmMakefile *mk = lg->GetMakefile(); + const cmTargets &ts = mk->GetTargets(); + std::string cfg = mk->GetSafeDefinition("CMAKE_BUILD_TYPE"); + cmTargets::const_iterator itr = ts.begin(); + for (; itr != ts.end(); ++itr) + { + const cmTarget &t = itr->second; + this->AppendTarget(fout, lg, t, cfg); + } +} + +void cmExtraQbsGenerator::AppendTarget(cmGeneratedFileStream &fout, + cmLocalGenerator *lg, const cmTarget &t, + const std::string &cfg) +{ + std::string type; + bool isBuildable = true; + switch (t.GetType()) + { + case cmTarget::EXECUTABLE: + type = "application"; + break; + case cmTarget::SHARED_LIBRARY: + type = "dynamiclibrary"; + break; + case cmTarget::STATIC_LIBRARY: + type = "staticlibrary"; + break; + default: + isBuildable = false; + break; + } + + if (type.empty()) + { + fout << "\t\tProject {\n"; + } + else + { + fout << "\t\tProduct {\n"; + fout << "\t\t\tdestinationDirectory: \"" << t.GetDirectory(cfg) << "\"\n"; + } + fout << "\t\t\tname:\"" << t.GetName() << "\"\n"; + + if (!type.empty()) + { + fout << "\t\t\ttype: \"" << type << "\"\n"; + fout << "\t\t\ttargetName: \"" << t.GetName() << "\"\n"; + } + + if (isBuildable) + { + fout << "\t\t\tDepends { name: \"cpp\" }\n"; + cmGeneratorTarget *gt = this->GlobalGenerator->GetGeneratorTarget(&t); + this->AppendSources(fout, gt, t, cfg); + + std::set<std::string> langs, incPaths, defs; + t.GetLanguages(langs, cfg); + for (std::set<std::string>::const_iterator lang = langs.begin(); + lang != langs.end(); + ++ lang) + { + const std::vector<std::string> &paths = + gt->GetIncludeDirectories(cfg, *lang); + std::copy(paths.begin(), paths.end(), + std::inserter(incPaths, incPaths.end())); + + lg->AddCompileDefinitions(defs, &t, cfg, *lang); + } + this->AppendIncludePaths(fout, incPaths); + this->AppendCompileDefinitions(fout, defs); + } + + fout << "\t\t}\n"; +} + +void cmExtraQbsGenerator::AppendSources(cmGeneratedFileStream &fout, + cmGeneratorTarget *gt, + const cmTarget &t, + const std::string &cfg) +{ + std::vector<cmSourceFile *> sources; + gt->GetSourceFiles(sources, cfg); + if (sources.empty()) + { + return; + } + + std::vector<cmSourceFile *> genSources; + std::vector<cmSourceFile *>::const_iterator itr = sources.begin(); + fout << "\t\t\tfiles: [\n" + << "\t\t\t\t\"" << t.GetMakefile()->GetCurrentListFile() << "\",\n"; + for (; itr != sources.end(); ++itr) + { + if (!(*itr)->GetPropertyAsBool("GENERATED")) + { + fout << "\t\t\t\t\"" << (*itr)->GetFullPath() << "\",\n"; + } + else + { + genSources.push_back(*itr); + } + } + fout << "\t\t\t]\n"; + + if (!genSources.empty()) + { + fout << "\t\t\tGroup {\n" + << "\t\t\t\tname:\"Generated\"\n" + << "\t\t\t\tfiles: [\n"; + itr = genSources.begin(); + std::string groupCondition; + bool initialCondition = true; + for (; itr != genSources.end(); ++itr) + { + const std::string &path = (*itr)->GetFullPath(); + fout << "\t\t\t\t\t\"" << path << "\",\n"; + if (initialCondition) + { + initialCondition = false; + } + else + { + groupCondition += "\t\t\t\t\t && "; + } + groupCondition += "File.exists(\"" + path + "\")\n"; + } + fout << "\t\t\t\t]\n" + << "\t\t\t\tcondition: " << groupCondition << "\t\t\t}\n"; + } +} + +void cmExtraQbsGenerator::AppendIncludePaths( + cmGeneratedFileStream &fout, + const std::set<std::string> &paths) +{ + if (paths.empty()) + { + return; + } + + std::set<std::string>::const_iterator itr = paths.begin(); + fout << "\t\t\tcpp.includePaths: [\n"; + for (; itr != paths.end(); ++ itr) + { + fout << "\t\t\t\t\"" << (*itr) << "\",\n"; + } + fout << "\t\t\t]\n"; +} + +void cmExtraQbsGenerator::AppendCompileDefinitions( + cmGeneratedFileStream &fout, + const std::set<std::string> &defs) +{ + if (defs.empty()) + { + return; + } + + std::set<std::string>::const_iterator itr = defs.begin(); + fout << "\t\t\tcpp.defines: [\n"; + for (; itr != defs.end(); ++ itr) + { + fout << "\t\t\t\t'" << (*itr) << "',\n"; + } + fout << "\t\t\t]\n"; +} diff --git a/Source/cmExtraQbsGenerator.h b/Source/cmExtraQbsGenerator.h new file mode 100644 index 0000000..531ccc9 --- /dev/null +++ b/Source/cmExtraQbsGenerator.h @@ -0,0 +1,48 @@ +#ifndef CMEXTRAQBSGENERATOR_H +#define CMEXTRAQBSGENERATOR_H + +#include "cmExternalMakefileProjectGenerator.h" + +class cmGeneratorTarget; + +class cmExtraQbsGenerator : public cmExternalMakefileProjectGenerator +{ +public: + cmExtraQbsGenerator(); + ~cmExtraQbsGenerator(); + + virtual std::string GetName() const + { return cmExtraQbsGenerator::GetActualName(); } + static std::string GetActualName() { return "Qbs"; } + static cmExternalMakefileProjectGenerator *New() + { return new cmExtraQbsGenerator; } + + /** Get the documentation entry for this generator. */ + virtual void GetDocumentation(cmDocumentationEntry &entry, + const std::string &fullName) const; + + virtual void Generate(); + +private: + void CreateProjectFile(const std::string &name, + const std::vector<cmLocalGenerator *> &lgs); + void CreateNewProjectFile(const std::string &projectName, + const std::vector<cmLocalGenerator *> &lgs, + const std::string &filename); + void AppendSubProject(cmGeneratedFileStream &fout, cmLocalGenerator *lg); + void AppendProduct(cmGeneratedFileStream &fout, cmLocalGenerator *lg); + void AppendTarget(cmGeneratedFileStream &fout, + cmLocalGenerator *lg, + const cmTarget &t, + const std::string &cfg); + void AppendSources(cmGeneratedFileStream &fout, + cmGeneratorTarget *gt, + const cmTarget &t, + const std::string &cfg); + void AppendIncludePaths(cmGeneratedFileStream &fout, + const std::set<std::string> &paths); + void AppendCompileDefinitions(cmGeneratedFileStream &fout, + const std::set<std::string> &defs); +}; + +#endif // CMEXTRAQBSGENERATOR_H diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index bd8a1f5..d340e72 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -804,6 +804,10 @@ GetSourcecodeValueFromFileExtension(const std::string& _ext, { sourcecode = "compiled.mach-o.objfile"; } + else if(ext == "xctest") + { + sourcecode = "wrapper.cfbundle"; + } else if(ext == "xib") { keepLastKnownFileType = true; @@ -2598,7 +2602,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)? @@ -2622,7 +2628,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/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 42c18f7..08092c7 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -22,6 +22,8 @@ # include "cmLocalVisualStudioGenerator.h" #endif +#include <sys/stat.h> + #include <cmsys/Terminal.h> #include <cmsys/ios/sstream> #include <cmsys/FStream.hxx> @@ -582,6 +584,18 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true, false); + // Ensure we have write permission in case .in was read-only. + mode_t perm = 0; +#if defined(WIN32) && !defined(__CYGWIN__) + mode_t mode_write = S_IWRITE; +#else + mode_t mode_write = S_IWUSR; +#endif + cmSystemTools::GetPermissions(outputFile, perm); + if (!(perm & mode_write)) + { + cmSystemTools::SetPermissions(outputFile, perm | mode_write); + } if (!configDefines.empty() || !configIncludes.empty() || !configUicOptions.empty()) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index b70f60d..b3d1155 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -616,6 +616,13 @@ bool cmTarget::IsCFBundleOnApple() const } //---------------------------------------------------------------------------- +bool cmTarget::IsXCTestOnApple() const +{ + return (this->IsCFBundleOnApple() && + this->GetPropertyAsBool("XCTEST")); +} + +//---------------------------------------------------------------------------- bool cmTarget::IsBundleOnApple() const { return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() || @@ -6791,7 +6798,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 5170b31..a4ef977 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -527,6 +527,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; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 11196e4..51df7f2 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -86,6 +86,8 @@ # include "cmGlobalKdevelopGenerator.h" #endif +#include "cmExtraQbsGenerator.h" + #ifdef CMAKE_USE_ECLIPSE # include "cmExtraEclipseCDT4Generator.h" #endif @@ -1029,6 +1031,8 @@ void cmake::AddDefaultExtraGenerators() &cmExtraSublimeTextGenerator::New); this->AddExtraGenerator(cmExtraKateGenerator::GetActualName(), &cmExtraKateGenerator::New); + this->AddExtraGenerator(cmExtraQbsGenerator::GetActualName(), + &cmExtraQbsGenerator::New); #ifdef CMAKE_USE_ECLIPSE this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(), diff --git a/Source/ctest.cxx b/Source/ctest.cxx index c0eb8ac..0fc47b7 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -75,6 +75,8 @@ static const char * cmDocumentationOptions[][2] = "Run a specific number of tests by number."}, {"-U, --union", "Take the Union of -I and -R"}, {"--rerun-failed", "Run only the tests that failed previously"}, + {"--repeat-until-fail <n>", "Require each test to run <n> " + "times without failing in order to pass"}, {"--max-width <width>", "Set the max width for a test name to output"}, {"--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1."}, {"--no-label-summary", "Disable timing summary information for labels."}, diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 40bea51..49fd02b 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -172,6 +172,7 @@ if(BUILD_TESTING) ON) mark_as_advanced(CTEST_TEST_CPACK) set(CTEST_TEST_OSX_ARCH 0) + set(CMake_TEST_XCODE_VERSION 0) if(APPLE) execute_process( COMMAND sw_vers -productVersion @@ -185,6 +186,17 @@ if(BUILD_TESTING) else() set(CTEST_TEST_OSX_ARCH 1) endif() + if(XCODE_VERSION) + set(CMake_TEST_XCODE_VERSION "${XCODE_VERSION}") + else() + execute_process( + COMMAND xcodebuild -version + OUTPUT_VARIABLE _version ERROR_VARIABLE _version + ) + if(_version MATCHES "^Xcode ([0-9]+(\\.[0-9]+)*)") + set(CMake_TEST_XCODE_VERSION "${CMAKE_MATCH_1}") + endif() + endif() endif() # Use 1500 or CTEST_TEST_TIMEOUT for long test timeout value, @@ -560,7 +572,21 @@ if(BUILD_TESTING) --test-command Simple) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Simple_KDevelop3Generator") endif () - + # check for the Qbs generator + if ("${cmakeOutput}" MATCHES Qbs) + add_test(Simple_QbsGenerator ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Simple" + "${CMake_BINARY_DIR}/Tests/Simple_QbsGenerator" + --build-two-config + --build-generator "Qbs - Unix Makefiles" + --build-generator-platform "${CMAKE_GENERATOR_PLATFORM}" + --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}" + --build-project Simple + --build-options ${build_options} + --test-command Simple) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Simple_QbsGenerator") + endif () endif() # test for correct sub-project generation @@ -1493,6 +1519,12 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release ) endif() + if(CMake_TEST_XCODE_VERSION AND NOT CMake_TEST_XCODE_VERSION VERSION_LESS 6 + AND OSX_VERSION MATCHES "^([0-9]+\\.[0-9]+)") + set(XCTest_BUILD_OPTIONS -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_MATCH_1}) + ADD_TEST_MACRO(XCTest ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> -V) + endif() + add_test(linkorder1 ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/LinkLineOrder" diff --git a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in index 109bb1c..ac9b552 100644 --- a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in +++ b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in @@ -28,6 +28,10 @@ if(CPACK_GENERATOR MATCHES "RPM") # test package description override - headers rpm is generated in the middle set(CPACK_RPM_headers_PACKAGE_DESCRIPTION "headers description") + + # test package do not use CPACK_PACKAGING_INSTALL_PREFIX + # as relocation path + set(CPACK_RPM_NO_libraries_INSTALL_PREFIX_RELOCATION true) endif() if(CPACK_GENERATOR MATCHES "DEB") diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake index 6762b45..cf4da74 100644 --- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake @@ -174,10 +174,10 @@ if(CPackGen MATCHES "RPM") if(check_file_libraries_match) set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*") set(check_file_match_expected_description ".*${CPACK_COMPONENT_LIBRARIES_DESCRIPTION}.*") - set(check_file_match_expected_relocation_path "Relocations${whitespaces}:${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") + set(check_file_match_expected_relocation_path "Relocations${whitespaces}:${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") set(check_file_match_expected_architecture "") # we don't explicitly set this value so it is different on each platform - ignore it set(spec_regex "*libraries*") - set(check_content_list "^/usr/foo/bar\n/usr/foo/bar/lib.*\n/usr/foo/bar/lib.*/libmylib.a$") + set(check_content_list "^/usr/foo/bar/lib.*\n/usr/foo/bar/lib.*/libmylib.a$") elseif(check_file_headers_match) set(check_file_match_expected_summary ".*${CPACK_RPM_headers_PACKAGE_SUMMARY}.*") set(check_file_match_expected_description ".*${CPACK_RPM_headers_PACKAGE_DESCRIPTION}.*") diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 7cbc9fe..fa249c7 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -199,6 +199,7 @@ add_RunCMake_test(CommandLine) add_RunCMake_test(install) add_RunCMake_test(CPackInstallProperties) add_RunCMake_test(ExternalProject) +add_RunCMake_test(CTestCommandLine) set(IfacePaths_INCLUDE_DIRECTORIES_ARGS -DTEST_PROP=INCLUDE_DIRECTORIES) add_RunCMake_test(IfacePaths_INCLUDE_DIRECTORIES TEST_DIR IfacePaths) diff --git a/Tests/RunCMake/CTestCommandLine/CMakeLists.txt b/Tests/RunCMake/CTestCommandLine/CMakeLists.txt new file mode 100644 index 0000000..2897109 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.0) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake new file mode 100644 index 0000000..2e5156c --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -0,0 +1,25 @@ +include(RunCMake) + +run_cmake_command(repeat-until-fail-bad1 + ${CMAKE_CTEST_COMMAND} --repeat-until-fail + ) +run_cmake_command(repeat-until-fail-bad2 + ${CMAKE_CTEST_COMMAND} --repeat-until-fail foo + ) +run_cmake_command(repeat-until-fail-good + ${CMAKE_CTEST_COMMAND} --repeat-until-fail 2 + ) + +function(run_repeat_until_fail_tests) + # Use a single build tree for a few tests without cleaning. + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/repeat-until-fail-build) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake(repeat-until-fail-cmake) + run_cmake_command(repeat-until-fail-ctest + ${CMAKE_CTEST_COMMAND} -C Debug --repeat-until-fail 3 + ) +endfunction() +run_repeat_until_fail_tests() diff --git a/Tests/RunCMake/CTestCommandLine/init.cmake b/Tests/RunCMake/CTestCommandLine/init.cmake new file mode 100644 index 0000000..a900f67 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/init.cmake @@ -0,0 +1,3 @@ +# This is run by test initialization in repeat-until-fail-cmake.cmake +# with cmake -P. It creates TEST_OUTPUT_FILE with a 0 in it. +file(WRITE "${TEST_OUTPUT_FILE}" "0") diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad1-result.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad1-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad1-stderr.txt new file mode 100644 index 0000000..5ea8816 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad1-stderr.txt @@ -0,0 +1 @@ +^CMake Error: '--repeat-until-fail' requires an argument$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad2-result.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad2-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad2-stderr.txt new file mode 100644 index 0000000..a79faae --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-bad2-stderr.txt @@ -0,0 +1 @@ +^CMake Error: '--repeat-until-fail' given non-integer value 'foo'$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-cmake.cmake b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-cmake.cmake new file mode 100644 index 0000000..4654416 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-cmake.cmake @@ -0,0 +1,15 @@ +enable_testing() + +set(TEST_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/test_output.txt") +add_test(NAME initialization + COMMAND ${CMAKE_COMMAND} + "-DTEST_OUTPUT_FILE=${TEST_OUTPUT_FILE}" + -P "${CMAKE_CURRENT_SOURCE_DIR}/init.cmake") +add_test(NAME test1 + COMMAND ${CMAKE_COMMAND} + "-DTEST_OUTPUT_FILE=${TEST_OUTPUT_FILE}" + -P "${CMAKE_CURRENT_SOURCE_DIR}/test1.cmake") +set_tests_properties(test1 PROPERTIES DEPENDS "initialization") + +add_test(hello ${CMAKE_COMMAND} -E echo hello) +add_test(goodbye ${CMAKE_COMMAND} -E echo goodbye) diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-result.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-result.txt new file mode 100644 index 0000000..45a4fb7 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-result.txt @@ -0,0 +1 @@ +8 diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stderr.txt new file mode 100644 index 0000000..7593783 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stderr.txt @@ -0,0 +1 @@ +^Errors while running CTest$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stdout.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stdout.txt new file mode 100644 index 0000000..0bc4f70 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stdout.txt @@ -0,0 +1,30 @@ +^Test project .*/Tests/RunCMake/CTestCommandLine/repeat-until-fail-build + Start 1: initialization + Test #1: initialization ................... Passed [0-9.]+ sec + Start 1: initialization + Test #1: initialization ................... Passed [0-9.]+ sec + Start 1: initialization +1/4 Test #1: initialization ................... Passed [0-9.]+ sec + Start 2: test1 + Test #2: test1 ............................ Passed [0-9.]+ sec + Start 2: test1 + Test #2: test1 ............................\*\*\*Failed [0-9.]+ sec + Start 3: hello + Test #3: hello ............................ Passed [0-9.]+ sec + Start 3: hello + Test #3: hello ............................ Passed [0-9.]+ sec + Start 3: hello +3/4 Test #3: hello ............................ Passed [0-9.]+ sec + Start 4: goodbye + Test #4: goodbye .......................... Passed [0-9.]+ sec + Start 4: goodbye + Test #4: goodbye .......................... Passed [0-9.]+ sec + Start 4: goodbye +4/4 Test #4: goodbye .......................... Passed [0-9.]+ sec ++ +75% tests passed, 1 tests failed out of 4 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests FAILED: +[ ]+2 - test1 \(Failed\)$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-good-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-good-stderr.txt new file mode 100644 index 0000000..a7c4b11 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-good-stderr.txt @@ -0,0 +1 @@ +^No tests were found!!!$ diff --git a/Tests/RunCMake/CTestCommandLine/test1.cmake b/Tests/RunCMake/CTestCommandLine/test1.cmake new file mode 100644 index 0000000..eeae7a2 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test1.cmake @@ -0,0 +1,13 @@ +# This is run by test test1 in repeat-until-fail-cmake.cmake with cmake -P. +# It reads the file TEST_OUTPUT_FILE and increments the number +# found in the file by 1. When the number is 2, then the +# code sends out a cmake error causing the test to fail +# the second time it is run. +message("TEST_OUTPUT_FILE = ${TEST_OUTPUT_FILE}") +file(READ "${TEST_OUTPUT_FILE}" COUNT) +message("COUNT= ${COUNT}") +math(EXPR COUNT "${COUNT} + 1") +file(WRITE "${TEST_OUTPUT_FILE}" "${COUNT}") +if(${COUNT} EQUAL 2) + message(FATAL_ERROR "this test fails on the 2nd run") +endif() diff --git a/Tests/XCTest/CMakeLists.txt b/Tests/XCTest/CMakeLists.txt new file mode 100644 index 0000000..e866623 --- /dev/null +++ b/Tests/XCTest/CMakeLists.txt @@ -0,0 +1,57 @@ +cmake_minimum_required(VERSION 3.1) +project(XCTest) +enable_testing() + +find_package(XCTest REQUIRED) + +# Framework + +add_library(FrameworkExample SHARED + FrameworkExample/FrameworkExample.c + FrameworkExample/FrameworkExample.h + FrameworkExample/Info.plist) + +target_include_directories(FrameworkExample PUBLIC .) + +set_target_properties(FrameworkExample PROPERTIES + FRAMEWORK TRUE + VERSION "1.0.0" + SOVERSION "1.0.0" + FRAMEWORK_VERSION "A" + MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/FrameworkExample/Info.plist + PUBLIC_HEADER FrameworkExample/FrameworkExample.h) + +# XCTest for Framework + +xctest_add_bundle(FrameworkExampleTests FrameworkExample + FrameworkExampleTests/FrameworkExampleTests.m + FrameworkExampleTests/Info.plist) + +set_target_properties(FrameworkExampleTests PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/FrameworkExampleTests/Info.plist + ) + +xctest_add_test(XCTest.FrameworkExample FrameworkExampleTests) + +# Cocoa App Bundle + +add_executable(CocoaExample MACOSX_BUNDLE + CocoaExample/main.m + CocoaExample/AppDelegate.m + CocoaExample/AppDelegate.h + CocoaExample/MainMenu.xib +) + +target_link_libraries(CocoaExample PRIVATE "-framework Foundation") +target_link_libraries(CocoaExample PRIVATE "-framework AppKit") + +set_target_properties(CocoaExample PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/CocoaExample/Info.plist + RESOURCE "CocoaExample/MainMenu.xib") + +# XCTest for Cocoa App Bundle + +xctest_add_bundle(CocoaExampleTests CocoaExample + CocoaExampleTests/CocoaExampleTests.m) + +xctest_add_test(XCTest.CocoaExample CocoaExampleTests) diff --git a/Tests/XCTest/CocoaExample/AppDelegate.h b/Tests/XCTest/CocoaExample/AppDelegate.h new file mode 100644 index 0000000..4bf4101 --- /dev/null +++ b/Tests/XCTest/CocoaExample/AppDelegate.h @@ -0,0 +1,6 @@ +#import <Cocoa/Cocoa.h> + +@interface AppDelegate : NSObject <NSApplicationDelegate> + + +@end diff --git a/Tests/XCTest/CocoaExample/AppDelegate.m b/Tests/XCTest/CocoaExample/AppDelegate.m new file mode 100644 index 0000000..07af62f --- /dev/null +++ b/Tests/XCTest/CocoaExample/AppDelegate.m @@ -0,0 +1,18 @@ +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (assign) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/Tests/XCTest/CocoaExample/Info.plist b/Tests/XCTest/CocoaExample/Info.plist new file mode 100644 index 0000000..5267c63 --- /dev/null +++ b/Tests/XCTest/CocoaExample/Info.plist @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>CocoaExample</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>org.cmake.CocoaExample</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>CocoaExample</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> +</dict> +</plist> diff --git a/Tests/XCTest/CocoaExample/MainMenu.xib b/Tests/XCTest/CocoaExample/MainMenu.xib new file mode 100644 index 0000000..9498a0a --- /dev/null +++ b/Tests/XCTest/CocoaExample/MainMenu.xib @@ -0,0 +1,680 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6233" systemVersion="14A329f" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct"> + <dependencies> + <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6233"/> + </dependencies> + <objects> + <customObject id="-2" userLabel="File's Owner" customClass="NSApplication"> + <connections> + <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/> + </connections> + </customObject> + <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> + <customObject id="-3" userLabel="Application" customClass="NSObject"/> + <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider=""> + <connections> + <outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/> + </connections> + </customObject> + <customObject id="YLy-65-1bz" customClass="NSFontManager"/> + <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6"> + <items> + <menuItem title="CocoaExample" id="1Xt-HY-uBw"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="CocoaExample" systemMenu="apple" id="uQy-DD-JDr"> + <items> + <menuItem title="About CocoaExample" id="5kV-Vb-QxS"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/> + <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/> + <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/> + <menuItem title="Services" id="NMo-om-nkz"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/> + </menuItem> + <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/> + <menuItem title="Hide CocoaExample" keyEquivalent="h" id="Olw-nP-bQN"> + <connections> + <action selector="hide:" target="-1" id="PnN-Uc-m68"/> + </connections> + </menuItem> + <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/> + </connections> + </menuItem> + <menuItem title="Show All" id="Kd2-mp-pUS"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/> + <menuItem title="Quit CocoaExample" keyEquivalent="q" id="4sb-4s-VLi"> + <connections> + <action selector="terminate:" target="-1" id="Te7-pn-YzF"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="File" id="dMs-cI-mzQ"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="File" id="bib-Uj-vzu"> + <items> + <menuItem title="New" keyEquivalent="n" id="Was-JA-tGl"> + <connections> + <action selector="newDocument:" target="-1" id="4Si-XN-c54"/> + </connections> + </menuItem> + <menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9"> + <connections> + <action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/> + </connections> + </menuItem> + <menuItem title="Open Recent" id="tXI-mr-wws"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ"> + <items> + <menuItem title="Clear Menu" id="vNY-rz-j42"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem isSeparatorItem="YES" id="m54-Is-iLE"/> + <menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG"> + <connections> + <action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/> + </connections> + </menuItem> + <menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV"> + <connections> + <action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/> + </connections> + </menuItem> + <menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A"> + <connections> + <action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/> + </connections> + </menuItem> + <menuItem title="Revert to Saved" id="KaW-ft-85H"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="aJh-i4-bef"/> + <menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK"> + <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/> + <connections> + <action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/> + </connections> + </menuItem> + <menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS"> + <connections> + <action selector="print:" target="-1" id="qaZ-4w-aoO"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Edit" id="5QF-Oa-p0T"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Edit" id="W48-6f-4Dl"> + <items> + <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg"> + <connections> + <action selector="undo:" target="-1" id="M6e-cu-g7V"/> + </connections> + </menuItem> + <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam"> + <connections> + <action selector="redo:" target="-1" id="oIA-Rs-6OD"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/> + <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG"> + <connections> + <action selector="cut:" target="-1" id="YJe-68-I9s"/> + </connections> + </menuItem> + <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU"> + <connections> + <action selector="copy:" target="-1" id="G1f-GL-Joy"/> + </connections> + </menuItem> + <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL"> + <connections> + <action selector="paste:" target="-1" id="UvS-8e-Qdg"/> + </connections> + </menuItem> + <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/> + </connections> + </menuItem> + <menuItem title="Delete" id="pa3-QI-u2k"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="delete:" target="-1" id="0Mk-Ml-PaM"/> + </connections> + </menuItem> + <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m"> + <connections> + <action selector="selectAll:" target="-1" id="VNm-Mi-diN"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/> + <menuItem title="Find" id="4EN-yA-p0u"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Find" id="1b7-l0-nxx"> + <items> + <menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W"> + <connections> + <action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/> + </connections> + </menuItem> + <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/> + </connections> + </menuItem> + <menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye"> + <connections> + <action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/> + </connections> + </menuItem> + <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV"> + <connections> + <action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/> + </connections> + </menuItem> + <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt"> + <connections> + <action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/> + </connections> + </menuItem> + <menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd"> + <connections> + <action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Spelling and Grammar" id="Dv1-io-Yv7"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Spelling" id="3IN-sU-3Bg"> + <items> + <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI"> + <connections> + <action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/> + </connections> + </menuItem> + <menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7"> + <connections> + <action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="bNw-od-mp5"/> + <menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/> + </connections> + </menuItem> + <menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/> + </connections> + </menuItem> + <menuItem title="Correct Spelling Automatically" id="78Y-hA-62v"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Substitutions" id="9ic-FL-obx"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Substitutions" id="FeM-D8-WVr"> + <items> + <menuItem title="Show Substitutions" id="z6F-FW-3nz"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/> + <menuItem title="Smart Copy/Paste" id="9yt-4B-nSM"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/> + </connections> + </menuItem> + <menuItem title="Smart Quotes" id="hQb-2v-fYv"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/> + </connections> + </menuItem> + <menuItem title="Smart Dashes" id="rgM-f4-ycn"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/> + </connections> + </menuItem> + <menuItem title="Smart Links" id="cwL-P1-jid"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/> + </connections> + </menuItem> + <menuItem title="Data Detectors" id="tRr-pd-1PS"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/> + </connections> + </menuItem> + <menuItem title="Text Replacement" id="HFQ-gK-NFA"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Transformations" id="2oI-Rn-ZJC"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Transformations" id="c8a-y6-VQd"> + <items> + <menuItem title="Make Upper Case" id="vmV-6d-7jI"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/> + </connections> + </menuItem> + <menuItem title="Make Lower Case" id="d9M-CD-aMd"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/> + </connections> + </menuItem> + <menuItem title="Capitalize" id="UEZ-Bs-lqG"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Speech" id="xrE-MZ-jX0"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Speech" id="3rS-ZA-NoH"> + <items> + <menuItem title="Start Speaking" id="Ynk-f8-cLZ"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/> + </connections> + </menuItem> + <menuItem title="Stop Speaking" id="Oyz-dy-DGm"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Format" id="jxT-CU-nIS"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Format" id="GEO-Iw-cKr"> + <items> + <menuItem title="Font" id="Gi5-1S-RQB"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq"> + <items> + <menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq"> + <connections> + <action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/> + </connections> + </menuItem> + <menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27"> + <connections> + <action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/> + </connections> + </menuItem> + <menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq"> + <connections> + <action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/> + </connections> + </menuItem> + <menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S"> + <connections> + <action selector="underline:" target="-1" id="FYS-2b-JAY"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/> + <menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL"> + <connections> + <action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/> + </connections> + </menuItem> + <menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST"> + <connections> + <action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/> + <menuItem title="Kern" id="jBQ-r6-VK2"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Kern" id="tlD-Oa-oAM"> + <items> + <menuItem title="Use Default" id="GUa-eO-cwY"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/> + </connections> + </menuItem> + <menuItem title="Use None" id="cDB-IK-hbR"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/> + </connections> + </menuItem> + <menuItem title="Tighten" id="46P-cB-AYj"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/> + </connections> + </menuItem> + <menuItem title="Loosen" id="ogc-rX-tC1"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Ligatures" id="o6e-r0-MWq"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Ligatures" id="w0m-vy-SC9"> + <items> + <menuItem title="Use Default" id="agt-UL-0e3"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/> + </connections> + </menuItem> + <menuItem title="Use None" id="J7y-lM-qPV"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/> + </connections> + </menuItem> + <menuItem title="Use All" id="xQD-1f-W4t"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Baseline" id="OaQ-X3-Vso"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Baseline" id="ijk-EB-dga"> + <items> + <menuItem title="Use Default" id="3Om-Ey-2VK"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="unscript:" target="-1" id="0vZ-95-Ywn"/> + </connections> + </menuItem> + <menuItem title="Superscript" id="Rqc-34-cIF"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="superscript:" target="-1" id="3qV-fo-wpU"/> + </connections> + </menuItem> + <menuItem title="Subscript" id="I0S-gh-46l"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="subscript:" target="-1" id="Q6W-4W-IGz"/> + </connections> + </menuItem> + <menuItem title="Raise" id="2h7-ER-AoG"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/> + </connections> + </menuItem> + <menuItem title="Lower" id="1tx-W0-xDw"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/> + <menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk"> + <connections> + <action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/> + <menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="copyFont:" target="-1" id="GJO-xA-L4q"/> + </connections> + </menuItem> + <menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="pasteFont:" target="-1" id="JfD-CL-leO"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Text" id="Fal-I4-PZk"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Text" id="d9c-me-L2H"> + <items> + <menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1"> + <connections> + <action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/> + </connections> + </menuItem> + <menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb"> + <connections> + <action selector="alignCenter:" target="-1" id="spX-mk-kcS"/> + </connections> + </menuItem> + <menuItem title="Justify" id="J5U-5w-g23"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="alignJustified:" target="-1" id="ljL-7U-jND"/> + </connections> + </menuItem> + <menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4"> + <connections> + <action selector="alignRight:" target="-1" id="r48-bG-YeY"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/> + <menuItem title="Writing Direction" id="H1b-Si-o9J"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd"> + <items> + <menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH"> + <modifierMask key="keyEquivalentModifierMask"/> + </menuItem> + <menuItem id="YGs-j5-SAR"> + <string key="title"> Default</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/> + </connections> + </menuItem> + <menuItem id="Lbh-J2-qVU"> + <string key="title"> Left to Right</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/> + </connections> + </menuItem> + <menuItem id="jFq-tB-4Kx"> + <string key="title"> Right to Left</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="swp-gr-a21"/> + <menuItem title="Selection" enabled="NO" id="cqv-fj-IhA"> + <modifierMask key="keyEquivalentModifierMask"/> + </menuItem> + <menuItem id="Nop-cj-93Q"> + <string key="title"> Default</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/> + </connections> + </menuItem> + <menuItem id="BgM-ve-c93"> + <string key="title"> Left to Right</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/> + </connections> + </menuItem> + <menuItem id="RB4-Sm-HuC"> + <string key="title"> Right to Left</string> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/> + <menuItem title="Show Ruler" id="vLm-3I-IUL"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/> + </connections> + </menuItem> + <menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5"> + <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/> + <connections> + <action selector="copyRuler:" target="-1" id="71i-fW-3W2"/> + </connections> + </menuItem> + <menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI"> + <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/> + <connections> + <action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="View" id="H8h-7b-M4v"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="View" id="HyV-fh-RgO"> + <items> + <menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5"> + <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> + <connections> + <action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/> + </connections> + </menuItem> + <menuItem title="Customize Toolbar…" id="1UK-8n-QPP"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Window" id="aUF-d1-5bR"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo"> + <items> + <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV"> + <connections> + <action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/> + </connections> + </menuItem> + <menuItem title="Zoom" id="R4o-n2-Eq4"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="performZoom:" target="-1" id="DIl-cC-cCs"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/> + <menuItem title="Bring All to Front" id="LE2-aR-0XJ"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + <menuItem title="Help" id="wpr-3q-Mcd"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ"> + <items> + <menuItem title="CocoaExample Help" keyEquivalent="?" id="FKE-Sm-Kum"> + <connections> + <action selector="showHelp:" target="-1" id="y7X-2Q-9no"/> + </connections> + </menuItem> + </items> + </menu> + </menuItem> + </items> + </menu> + <window title="CocoaExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g"> + <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/> + <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> + <rect key="contentRect" x="335" y="390" width="480" height="360"/> + <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1177"/> + <view key="contentView" id="EiT-Mj-1SZ"> + <rect key="frame" x="0.0" y="0.0" width="480" height="360"/> + <autoresizingMask key="autoresizingMask"/> + </view> + </window> + </objects> +</document> diff --git a/Tests/XCTest/CocoaExample/main.m b/Tests/XCTest/CocoaExample/main.m new file mode 100644 index 0000000..8a6799b --- /dev/null +++ b/Tests/XCTest/CocoaExample/main.m @@ -0,0 +1,5 @@ +#import <Cocoa/Cocoa.h> + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/Tests/XCTest/CocoaExampleTests/CocoaExampleTests.m b/Tests/XCTest/CocoaExampleTests/CocoaExampleTests.m new file mode 100644 index 0000000..70d61d6 --- /dev/null +++ b/Tests/XCTest/CocoaExampleTests/CocoaExampleTests.m @@ -0,0 +1,13 @@ +#import <XCTest/XCTest.h> + +@interface CocoaExampleTests : XCTestCase + +@end + +@implementation CocoaExampleTests + +- (void)testExample { + XCTAssert(YES, @"Pass"); +} + +@end diff --git a/Tests/XCTest/FrameworkExample/FrameworkExample.c b/Tests/XCTest/FrameworkExample/FrameworkExample.c new file mode 100644 index 0000000..2da78da --- /dev/null +++ b/Tests/XCTest/FrameworkExample/FrameworkExample.c @@ -0,0 +1,6 @@ +#include "FrameworkExample.h" + +int FourtyTwo() +{ + return 42; +} diff --git a/Tests/XCTest/FrameworkExample/FrameworkExample.h b/Tests/XCTest/FrameworkExample/FrameworkExample.h new file mode 100644 index 0000000..2e0b499 --- /dev/null +++ b/Tests/XCTest/FrameworkExample/FrameworkExample.h @@ -0,0 +1 @@ +int FourtyTwo(); diff --git a/Tests/XCTest/FrameworkExample/Info.plist b/Tests/XCTest/FrameworkExample/Info.plist new file mode 100644 index 0000000..a22acea --- /dev/null +++ b/Tests/XCTest/FrameworkExample/Info.plist @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>FrameworkExample</string> + <key>CFBundleIdentifier</key> + <string>org.cmake.FrameworkExample</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>FrameworkExample</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string></string> + <key>NSHumanReadableCopyright</key> + <string></string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/Tests/XCTest/FrameworkExampleTests/FrameworkExampleTests.m b/Tests/XCTest/FrameworkExampleTests/FrameworkExampleTests.m new file mode 100644 index 0000000..7cba23e --- /dev/null +++ b/Tests/XCTest/FrameworkExampleTests/FrameworkExampleTests.m @@ -0,0 +1,16 @@ +#import <XCTest/XCTest.h> + +#import "FrameworkExample/FrameworkExample.h" + +@interface FrameworkExampleTests : XCTestCase + +@end + +@implementation FrameworkExampleTests + +- (void)testFourtyTwo { + // This is an example of a functional test case. + XCTAssertEqual(42, FourtyTwo()); +} + +@end diff --git a/Tests/XCTest/FrameworkExampleTests/Info.plist b/Tests/XCTest/FrameworkExampleTests/Info.plist new file mode 100644 index 0000000..293921b --- /dev/null +++ b/Tests/XCTest/FrameworkExampleTests/Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>FrameworkExampleTests</string> + <key>CFBundleIdentifier</key> + <string>org.cmake.FrameworkExampleTests</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>FrameworkExampleTests</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> +</dict> +</plist> |