diff options
126 files changed, 1506 insertions, 338 deletions
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 3499da8..5daaf9c 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -28,7 +28,7 @@ License We do not require any formal copyright assignment or contributor license agreement. Any contributions intentionally sent upstream are presumed -to be offerred under terms of the OSI-approved BSD 3-clause License. +to be offered under terms of the OSI-approved BSD 3-clause License. See `Copyright.txt`_ for details. .. _`Copyright.txt`: Copyright.txt diff --git a/Help/command/ctest_memcheck.rst b/Help/command/ctest_memcheck.rst index 2800511..29bdf7d 100644 --- a/Help/command/ctest_memcheck.rst +++ b/Help/command/ctest_memcheck.rst @@ -14,6 +14,7 @@ Perform the :ref:`CTest MemCheck Step` as a :ref:`Dashboard Client`. [EXCLUDE_LABEL <label-exclude-regex>] [INCLUDE_LABEL <label-include-regex>] [PARALLEL_LEVEL <level>] + [TEST_LOAD <threshold>] [SCHEDULE_RANDOM <ON|OFF>] [STOP_TIME <time-of-day>] [RETURN_VALUE <result-var>] diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index af422b6..162db69 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -14,6 +14,7 @@ Perform the :ref:`CTest Test Step` as a :ref:`Dashboard Client`. [EXCLUDE_LABEL <label-exclude-regex>] [INCLUDE_LABEL <label-include-regex>] [PARALLEL_LEVEL <level>] + [TEST_LOAD <threshold>] [SCHEDULE_RANDOM <ON|OFF>] [STOP_TIME <time-of-day>] [RETURN_VALUE <result-var>] @@ -61,6 +62,13 @@ The options are: Specify a positive number representing the number of tests to be run in parallel. +``TEST_LOAD <threshold>`` + While running tests in parallel, try not to start tests when they + may cause the CPU load to pass above a given threshold. If not + specified the :variable:`CTEST_TEST_LOAD` variable will be checked, + and then the ``--test-load`` command-line argument to :manual:`ctest(1)`. + See also the ``TestLoad`` setting in the :ref:`CTest Test Step`. + ``SCHEDULE_RANDOM <ON|OFF>`` Launch tests in a random order. This may be useful for detecting implicit test dependencies. diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 7c7db5e..f54436a 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -387,6 +387,7 @@ Variables for CTest /variable/CTEST_SVN_COMMAND /variable/CTEST_SVN_OPTIONS /variable/CTEST_SVN_UPDATE_OPTIONS + /variable/CTEST_TEST_LOAD /variable/CTEST_TEST_TIMEOUT /variable/CTEST_TRIGGER_SITE /variable/CTEST_UPDATE_COMMAND diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index c91321b..50c856a 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -66,6 +66,13 @@ Options number of jobs. This option can also be set by setting the environment variable ``CTEST_PARALLEL_LEVEL``. +``--test-load <level>`` + While running tests in parallel (e.g. with ``-j``), try not to start + tests when they may cause the CPU load to pass above a given threshold. + + When ``ctest`` is run as a `Dashboard Client`_ this sets the + ``TestLoad`` option of the `CTest Test Step`_. + ``-Q,--quiet`` Make ctest quiet. @@ -776,6 +783,13 @@ Arguments to the command may specify some of the step settings. Configuration settings include: +``TestLoad`` + While running tests in parallel (e.g. with ``-j``), try not to start + tests when they may cause the CPU load to pass above a given threshold. + + * `CTest Script`_ variable: :variable:`CTEST_TEST_LOAD` + * :module:`CTest` module variable: ``CTEST_TEST_LOAD`` + ``TimeOut`` The default timeout for each test if not specified by the :prop_test:`TIMEOUT` test property. diff --git a/Help/release/dev/ExternalProject-USES_TERMINAL.rst b/Help/release/dev/ExternalProject-USES_TERMINAL.rst new file mode 100644 index 0000000..415540d --- /dev/null +++ b/Help/release/dev/ExternalProject-USES_TERMINAL.rst @@ -0,0 +1,7 @@ +ExternalProject-USES_TERMINAL +----------------------------- + +* The :module:`ExternalProject` module learned new ``USES_TERMINAL`` + arguments for giving steps exclusive terminal access. Especially + useful with the :generator:`Ninja` generator to monitor CMake + superbuild progress and prevent CPU oversubscription. diff --git a/Help/release/dev/ctest-test-load-option.rst b/Help/release/dev/ctest-test-load-option.rst new file mode 100644 index 0000000..069f49a --- /dev/null +++ b/Help/release/dev/ctest-test-load-option.rst @@ -0,0 +1,9 @@ +ctest-test-load-option +---------------------- + +* CTest learned to optionally measure the CPU load during parallel + testing and avoid starting tests that may cause the load to exceed + a given threshold. See the :manual:`ctest(1)` command ``--test-load`` + option, the ``TestLoad`` setting of the :ref:`CTest Test Step`, + the :variable:`CTEST_TEST_LOAD` variable, and the ``TEST_LOAD`` + option of the :command:`ctest_test` command. diff --git a/Help/variable/CTEST_TEST_LOAD.rst b/Help/variable/CTEST_TEST_LOAD.rst new file mode 100644 index 0000000..80823fe --- /dev/null +++ b/Help/variable/CTEST_TEST_LOAD.rst @@ -0,0 +1,7 @@ +CTEST_TEST_LOAD +--------------- + +Specify the ``TestLoad`` setting in the :ref:`CTest Test Step` +of a :manual:`ctest(1)` dashboard client script. This sets the +default value for the ``TEST_LOAD`` option of the :command:`ctest_test` +command. diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index 40d4ce6..492c3ea 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -105,6 +105,14 @@ if(NOT CMAKE_C_COMPILER_ID_RUN) set(CMAKE_C_COMPILER_ID_VENDOR_FLAGS_IAR ) set(CMAKE_C_COMPILER_ID_VENDOR_REGEX_IAR "IAR .+ Compiler") + # Match the link line from xcodebuild output of the form + # Ld ... + # ... + # /path/to/cc ...CompilerIdC/... + # to extract the compiler front-end for the language. + set(CMAKE_C_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdC/(\\./)?(CompilerIdC.xctest/)?CompilerIdC[ \t\n\\\"]") + set(CMAKE_C_COMPILER_ID_TOOL_MATCH_INDEX 2) + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) CMAKE_DETERMINE_COMPILER_ID(C CFLAGS CMakeCCompilerId.c) diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index a673525..2032015 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -100,6 +100,14 @@ if(NOT CMAKE_CXX_COMPILER_ID_RUN) set(CMAKE_CXX_COMPILER_ID_VENDOR_FLAGS_IAR ) set(CMAKE_CXX_COMPILER_ID_VENDOR_REGEX_IAR "IAR .+ Compiler") + # Match the link line from xcodebuild output of the form + # Ld ... + # ... + # /path/to/cc ...CompilerIdCXX/... + # to extract the compiler front-end for the language. + set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdCXX/(\\./)?(CompilerIdCXX.xctest/)?CompilerIdCXX[ \t\n\\\"]") + set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_INDEX 2) + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) CMAKE_DETERMINE_COMPILER_ID(CXX CXXFLAGS CMakeCXXCompilerId.cpp) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 68f2194..c699315 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -217,7 +217,7 @@ Id flags: ${testflags} set(id_subsystem 1) endif() set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR}) - get_filename_component(id_src "${src}" NAME) + set(id_src "${src}") configure_file(${CMAKE_ROOT}/Modules/CompilerId/VS-${v}.${ext}.in ${id_dir}/CompilerId${lang}.${ext} @ONLY) if(CMAKE_VS_MSBUILD_COMMAND AND NOT lang STREQUAL "Fortran") @@ -256,7 +256,7 @@ Id flags: ${testflags} set(id_lang "${lang}") set(id_type ${CMAKE_${lang}_COMPILER_XCODE_TYPE}) set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR}) - get_filename_component(id_src "${src}" NAME) + set(id_src "${src}") if(CMAKE_XCODE_PLATFORM_TOOLSET) set(id_toolset "GCC_VERSION = ${CMAKE_XCODE_PLATFORM_TOOLSET};") else() @@ -304,15 +304,12 @@ Id flags: ${testflags} set(ENV{MACOSX_DEPLOYMENT_TARGET} "${_ENV_MACOSX_DEPLOYMENT_TARGET}") endif() - # Match the link line from xcodebuild output of the form - # Ld ... - # ... - # /path/to/cc ...CompilerId${lang}/... - # to extract the compiler front-end for the language. - if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerId${lang}/(\\./)?(CompilerId${lang}.xctest/)?CompilerId${lang}[ \t\n\\\"]") - set(_comp "${CMAKE_MATCH_2}") - if(EXISTS "${_comp}") - set(CMAKE_${lang}_COMPILER_ID_TOOL "${_comp}" PARENT_SCOPE) + if(DEFINED CMAKE_${lang}_COMPILER_ID_TOOL_MATCH_REGEX) + if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "${CMAKE_${lang}_COMPILER_ID_TOOL_MATCH_REGEX}") + set(_comp "${CMAKE_MATCH_${CMAKE_${lang}_COMPILER_ID_TOOL_MATCH_INDEX}}") + if(EXISTS "${_comp}") + set(CMAKE_${lang}_COMPILER_ID_TOOL "${_comp}" PARENT_SCOPE) + endif() endif() endif() else() diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index 52ec25a..911ffac 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -127,6 +127,14 @@ if(NOT CMAKE_Fortran_COMPILER_ID_RUN) set(CMAKE_Fortran_COMPILER_ID_VENDOR_FLAGS_NAG "-V") set(CMAKE_Fortran_COMPILER_ID_VENDOR_REGEX_NAG "NAG Fortran Compiler") + # Match the link line from xcodebuild output of the form + # Ld ... + # ... + # /path/to/cc ...CompilerIdFortran/... + # to extract the compiler front-end for the language. + set(CMAKE_Fortran_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdFortran/(\\./)?(CompilerIdFortran.xctest/)?CompilerIdFortran[ \t\n\\\"]") + set(CMAKE_Fortran_COMPILER_ID_TOOL_MATCH_INDEX 2) + set(_version_info "") foreach(m MAJOR MINOR PATCH TWEAK) set(_COMP "_${m}") diff --git a/Modules/Compiler/XL-ASM.cmake b/Modules/Compiler/XL-ASM.cmake index 07507f9..212179e 100644 --- a/Modules/Compiler/XL-ASM.cmake +++ b/Modules/Compiler/XL-ASM.cmake @@ -1,9 +1,8 @@ set(CMAKE_ASM_VERBOSE_FLAG "-V") # -qthreaded = Ensures that all optimizations will be thread-safe -# -qalias=noansi = Turns off type-based aliasing completely (safer optimizer) # -qhalt=e = Halt on error messages (rather than just severe errors) -set(CMAKE_ASM_FLAGS_INIT "-qthreaded -qalias=noansi -qhalt=e -qsourcetype=assembler") +set(CMAKE_ASM_FLAGS_INIT "-qthreaded -qhalt=e -qsourcetype=assembler") set(CMAKE_ASM_FLAGS_DEBUG_INIT "-g") set(CMAKE_ASM_FLAGS_RELEASE_INIT "-O -DNDEBUG") diff --git a/Modules/Compiler/XL-C.cmake b/Modules/Compiler/XL-C.cmake index 09a5529..97dd017 100644 --- a/Modules/Compiler/XL-C.cmake +++ b/Modules/Compiler/XL-C.cmake @@ -4,6 +4,5 @@ set(CMAKE_C_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT} -DNDEBUG") set(CMAKE_C_FLAGS_MINSIZEREL_INIT "${CMAKE_C_FLAGS_MINSIZEREL_INIT} -DNDEBUG") # -qthreaded = Ensures that all optimizations will be thread-safe -# -qalias=noansi = Turns off type-based aliasing completely (safer optimizer) # -qhalt=e = Halt on error messages (rather than just severe errors) -set(CMAKE_C_FLAGS_INIT "-qthreaded -qalias=noansi -qhalt=e") +set(CMAKE_C_FLAGS_INIT "-qthreaded -qhalt=e") diff --git a/Modules/DartConfiguration.tcl.in b/Modules/DartConfiguration.tcl.in index 37a0a40..918b407 100644 --- a/Modules/DartConfiguration.tcl.in +++ b/Modules/DartConfiguration.tcl.in @@ -95,6 +95,10 @@ SlurmRunCommand: @SLURM_SRUN_COMMAND@ # Currently set to 25 minutes TimeOut: @DART_TESTING_TIMEOUT@ +# During parallel testing CTest will not start a new test if doing +# so would cause the system load to exceed this value. +TestLoad: @CTEST_TEST_LOAD@ + UseLaunchers: @CTEST_USE_LAUNCHERS@ CurlOptions: @CTEST_CURL_OPTIONS@ # warning, if you add new options here that have to do with submit, diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index eee1841..f6844be 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -175,6 +175,23 @@ Create custom targets to build projects in external trees ``LOG_INSTALL 1`` Wrap install in script to log output + Steps can be given direct access to the terminal if possible. With + the :generator:`Ninja` generator, this places the steps in the + ``console`` :prop_gbl:`pool <JOB_POOLS>`. Options are: + + ``USES_TERMINAL_DOWNLOAD 1`` + Give download terminal access. + ``USES_TERMINAL_UPDATE 1`` + Give update terminal access. + ``USES_TERMINAL_CONFIGURE 1`` + Give configure terminal access. + ``USES_TERMINAL_BUILD 1`` + Give build terminal access. + ``USES_TERMINAL_TEST 1`` + Give test terminal access. + ``USES_TERMINAL_INSTALL 1`` + Give install terminal access. + Other options are: ``STEP_TARGETS <step-target>...`` @@ -256,6 +273,8 @@ Create custom targets to build projects in external trees Working directory for command ``LOG 1`` Wrap step in script to log output + ``USES_TERMINAL 1`` + Give the step direct access to the terminal if possible. The command line, comment, working directory, and byproducts of every standard and custom step are processed to replace tokens ``<SOURCE_DIR>``, @@ -1463,6 +1482,14 @@ function(ExternalProject_Add_Step name step) get_property(comment TARGET ${name} PROPERTY _EP_${step}_COMMENT) endif() + # Uses terminal? + get_property(uses_terminal TARGET ${name} PROPERTY _EP_${step}_USES_TERMINAL) + if(uses_terminal) + set(uses_terminal USES_TERMINAL) + else() + set(uses_terminal "") + endif() + # Run every time? get_property(always TARGET ${name} PROPERTY _EP_${step}_ALWAYS) if(always) @@ -1505,6 +1532,7 @@ function(ExternalProject_Add_Step name step) DEPENDS ${depends} WORKING_DIRECTORY ${work_dir} VERBATIM + ${uses_terminal} ) set_property(TARGET ${name} APPEND PROPERTY _EP_STEPS ${step}) @@ -1890,6 +1918,14 @@ function(_ep_add_download_command name) set(log "") endif() + get_property(uses_terminal TARGET ${name} PROPERTY + _EP_USES_TERMINAL_DOWNLOAD) + if(uses_terminal) + set(uses_terminal USES_TERMINAL 1) + else() + set(uses_terminal "") + endif() + ExternalProject_Add_Step(${name} download COMMENT ${comment} COMMAND ${cmd} @@ -1897,6 +1933,7 @@ function(_ep_add_download_command name) DEPENDS ${depends} DEPENDEES mkdir ${log} + ${uses_terminal} ) endfunction() @@ -2001,6 +2038,14 @@ Update to Mercurial >= 2.1.1. set(log "") endif() + get_property(uses_terminal TARGET ${name} PROPERTY + _EP_USES_TERMINAL_UPDATE) + if(uses_terminal) + set(uses_terminal USES_TERMINAL 1) + else() + set(uses_terminal "") + endif() + ExternalProject_Add_Step(${name} update COMMENT ${comment} COMMAND ${cmd} @@ -2009,6 +2054,7 @@ Update to Mercurial >= 2.1.1. WORKING_DIRECTORY ${work_dir} DEPENDEES download ${log} + ${uses_terminal} ) if(always AND update_disconnected) @@ -2021,6 +2067,7 @@ Update to Mercurial >= 2.1.1. WORKING_DIRECTORY ${work_dir} DEPENDEES download ${log} + ${uses_terminal} ) set_property(SOURCE ${skip-update_stamp_file} PROPERTY SYMBOLIC 1) endif() @@ -2149,6 +2196,14 @@ function(_ep_add_configure_command name) set(log "") endif() + get_property(uses_terminal TARGET ${name} PROPERTY + _EP_USES_TERMINAL_CONFIGURE) + if(uses_terminal) + set(uses_terminal USES_TERMINAL 1) + else() + set(uses_terminal "") + endif() + get_property(update_disconnected_set TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED SET) if(update_disconnected_set) get_property(update_disconnected TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED) @@ -2167,6 +2222,7 @@ function(_ep_add_configure_command name) DEPENDEES ${update_dep} patch DEPENDS ${file_deps} ${log} + ${uses_terminal} ) endfunction() @@ -2188,6 +2244,14 @@ function(_ep_add_build_command name) set(log "") endif() + get_property(uses_terminal TARGET ${name} PROPERTY + _EP_USES_TERMINAL_BUILD) + if(uses_terminal) + set(uses_terminal USES_TERMINAL 1) + else() + set(uses_terminal "") + endif() + get_property(build_always TARGET ${name} PROPERTY _EP_BUILD_ALWAYS) if(build_always) set(always 1) @@ -2204,6 +2268,7 @@ function(_ep_add_build_command name) DEPENDEES configure ALWAYS ${always} ${log} + ${uses_terminal} ) endfunction() @@ -2225,11 +2290,20 @@ function(_ep_add_install_command name) set(log "") endif() + get_property(uses_terminal TARGET ${name} PROPERTY + _EP_USES_TERMINAL_INSTALL) + if(uses_terminal) + set(uses_terminal USES_TERMINAL 1) + else() + set(uses_terminal "") + endif() + ExternalProject_Add_Step(${name} install COMMAND ${cmd} WORKING_DIRECTORY ${binary_dir} DEPENDEES build ${log} + ${uses_terminal} ) endfunction() @@ -2277,6 +2351,14 @@ function(_ep_add_test_command name) set(log "") endif() + get_property(uses_terminal TARGET ${name} PROPERTY + _EP_USES_TERMINAL_TEST) + if(uses_terminal) + set(uses_terminal USES_TERMINAL 1) + else() + set(uses_terminal "") + endif() + ExternalProject_Add_Step(${name} test COMMAND ${cmd} WORKING_DIRECTORY ${binary_dir} @@ -2284,6 +2366,7 @@ function(_ep_add_test_command name) ${dependers_args} ${exclude_args} ${log} + ${uses_terminal} ) endif() endfunction() diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 028bf5a..a47a69c 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -55,7 +55,7 @@ # returning an exit code can be used as well (0 indicating a success). # # Module Input Variables -# ---------------------- +# ^^^^^^^^^^^^^^^^^^^^^^ # # Users or projects may set the following variables to configure the module # behaviour: @@ -69,10 +69,10 @@ # versions. # # Variables defined by the module -# ------------------------------- +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # # Result variables -# ^^^^^^^^^^^^^^^^ +# """""""""""""""" # # ``Matlab_FOUND`` # ``TRUE`` if the Matlab installation is found, ``FALSE`` @@ -100,7 +100,7 @@ # Available only if the component ``MEX_COMPILER`` is asked # # Cached variables -# ^^^^^^^^^^^^^^^^ +# """""""""""""""" # # ``Matlab_MEX_EXTENSION`` # the extension of the mex files for the current platform (given by Matlab). @@ -109,7 +109,7 @@ # is changed by the user, the result variables are recomputed. # # Provided macros -# --------------- +# ^^^^^^^^^^^^^^^ # # :command:`matlab_get_version_from_release_name` # returns the version from the release name @@ -117,7 +117,7 @@ # returns the release name from the Matlab version # # Provided functions -# ------------------ +# ^^^^^^^^^^^^^^^^^^ # # :command:`matlab_add_mex` # adds a target compiling a MEX file. @@ -139,7 +139,7 @@ # # # Known issues -# ------------ +# ^^^^^^^^^^^^ # # **Symbol clash in a MEX target** # By default, every symbols inside a MEX @@ -166,7 +166,7 @@ # # # Reference -# -------------- +# ^^^^^^^^^ # # .. variable:: Matlab_ROOT_DIR # diff --git a/Modules/FindPythonLibs.cmake b/Modules/FindPythonLibs.cmake index cc875ad..b80d3ce 100644 --- a/Modules/FindPythonLibs.cmake +++ b/Modules/FindPythonLibs.cmake @@ -53,6 +53,15 @@ include(${CMAKE_CURRENT_LIST_DIR}/CMakeFindFrameworks.cmake) # Search for the python framework on Apple. CMAKE_FIND_FRAMEWORKS(Python) +# Save CMAKE_FIND_FRAMEWORK +if(DEFINED CMAKE_FIND_FRAMEWORK) + set(_PythonLibs_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK}) +else() + unset(_PythonLibs_CMAKE_FIND_FRAMEWORK) +endif() +# To avoid picking up the system Python.h pre-maturely. +set(CMAKE_FIND_FRAMEWORK LAST) + set(_PYTHON1_VERSIONS 1.6 1.5) set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) set(_PYTHON3_VERSIONS 3.4 3.3 3.2 3.1 3.0) @@ -111,14 +120,22 @@ foreach(_CURRENT_VERSION ${_Python_VERSIONS}) ) endif() + set(PYTHON_FRAMEWORK_LIBRARIES) + if(Python_FRAMEWORKS AND NOT PYTHON_LIBRARY) + foreach(dir ${Python_FRAMEWORKS}) + list(APPEND PYTHON_FRAMEWORK_LIBRARIES + ${dir}/Versions/${_CURRENT_VERSION}/lib) + endforeach() + endif() find_library(PYTHON_LIBRARY NAMES - python${_CURRENT_VERSION_NO_DOTS} - python${_CURRENT_VERSION}mu - python${_CURRENT_VERSION}m - python${_CURRENT_VERSION}u - python${_CURRENT_VERSION} + python${_CURRENT_VERSION_NO_DOTS} + python${_CURRENT_VERSION}mu + python${_CURRENT_VERSION}m + python${_CURRENT_VERSION}u + python${_CURRENT_VERSION} PATHS + ${PYTHON_FRAMEWORK_LIBRARIES} [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs # Avoid finding the .dll in the PATH. We want the .lib. @@ -143,8 +160,8 @@ foreach(_CURRENT_VERSION ${_Python_VERSIONS}) set(PYTHON_FRAMEWORK_INCLUDES) if(Python_FRAMEWORKS AND NOT PYTHON_INCLUDE_DIR) foreach(dir ${Python_FRAMEWORKS}) - set(PYTHON_FRAMEWORK_INCLUDES ${PYTHON_FRAMEWORK_INCLUDES} - ${dir}/Versions/${_CURRENT_VERSION}/include/python${_CURRENT_VERSION}) + list(APPEND PYTHON_FRAMEWORK_INCLUDES + ${dir}/Versions/${_CURRENT_VERSION}/include/python${_CURRENT_VERSION}) endforeach() endif() @@ -201,6 +218,14 @@ SELECT_LIBRARY_CONFIGURATIONS(PYTHON) # for historical reasons. unset(PYTHON_FOUND) +# Restore CMAKE_FIND_FRAMEWORK +if(DEFINED _PythonLibs_CMAKE_FIND_FRAMEWORK) + set(CMAKE_FIND_FRAMEWORK ${_PythonLibs_CMAKE_FIND_FRAMEWORK}) + unset(_PythonLibs_CMAKE_FIND_FRAMEWORK) +else() + unset(CMAKE_FIND_FRAMEWORK) +endif() + include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibs REQUIRED_VARS PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index aeaa2bd..f72a7f2 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -232,6 +232,7 @@ elseif(MSVC_Fortran_ARCHITECTURE_ID) set(_MACHINE_ARCH_FLAG "/machine:${MSVC_Fortran_ARCHITECTURE_ID}") endif() set(CMAKE_EXE_LINKER_FLAGS_INIT "${CMAKE_EXE_LINKER_FLAGS_INIT} ${_MACHINE_ARCH_FLAG}") +set(CMAKE_STATIC_LINKER_FLAGS_INIT "${CMAKE_STATIC_LINKER_FLAGS_INIT} ${_MACHINE_ARCH_FLAG}") unset(_MACHINE_ARCH_FLAG) # add /debug and /INCREMENTAL:YES to DEBUG and RELWITHDEBINFO also add pdbtype @@ -82,7 +82,7 @@ If you have found a bug: 1. If you have a patch, please read the `CONTRIBUTING.rst`_ document. -2. Otherwise, please join the the `CMake Users List`_ and ask about +2. Otherwise, please join the `CMake Users List`_ and ask about the expected and observed behaviors to determine if it is really a bug. diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 5eefed0..1348c2789 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 3) -set(CMake_VERSION_PATCH 20150625) +set(CMake_VERSION_PATCH 20150708) #set(CMake_VERSION_RC 1) diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index e141b60..6dbb245 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -920,7 +920,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, char* data; int length; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Each symbol represents " << tick_len << " bytes of output." << std::endl << (this->UseCTestLaunch? "" : @@ -968,7 +968,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, this->ProcessBuffer(0, 0, tick, tick_len, ofs, &this->BuildProcessingQueue); this->ProcessBuffer(0, 0, tick, tick_len, ofs, &this->BuildProcessingErrorQueue); - cmCTestOptionalLog(this->CTest, OUTPUT, " Size of output: " + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size of output: " << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl, this->Quiet); @@ -1175,12 +1175,12 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, int length, while ( this->BuildOutputLogSize > (tick * tick_len) ) { tick ++; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, this->LastTickChar, - this->Quiet); + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, + this->LastTickChar, this->Quiet); tickDisplayed = true; if ( tick % tick_line_len == 0 && tick > 0 ) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Size: " + cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size: " << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl << " ", this->Quiet); } diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 81eb0a8..ad79ba2 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -23,6 +23,7 @@ cmCTestGenericHandler::cmCTestGenericHandler() this->SubmitIndex = 0; this->AppendXML = false; this->Quiet = false; + this->TestLoad = 0; } //---------------------------------------------------------------------- @@ -70,6 +71,7 @@ void cmCTestGenericHandler::SetPersistentOption(const std::string& op, void cmCTestGenericHandler::Initialize() { this->AppendXML = false; + this->TestLoad = 0; this->Options.clear(); t_StringToString::iterator it; for ( it = this->PersistentOptions.begin(); diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 8567dd7..4b7ae79 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -89,6 +89,8 @@ public: void SetAppendXML(bool b) { this->AppendXML = b; } void SetQuiet(bool b) { this->Quiet = b; } bool GetQuiet() { return this->Quiet; } + void SetTestLoad(unsigned long load) { this->TestLoad = load; } + unsigned long GetTestLoad() const { return this->TestLoad; } protected: bool StartResultingXML(cmCTest::Part part, @@ -97,6 +99,7 @@ protected: bool AppendXML; bool Quiet; + unsigned long TestLoad; cmSystemTools::OutputOption HandlerVerbose; cmCTest *CTest; t_StringToString Options; diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index bd090db..4832186 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -13,12 +13,15 @@ #include "cmProcess.h" #include "cmStandardIncludes.h" #include "cmCTest.h" +#include "cmCTestScriptHandler.h" #include "cmSystemTools.h" #include <stdlib.h> #include <stack> #include <list> #include <float.h> +#include <math.h> #include <cmsys/FStream.hxx> +#include <cmsys/SystemInformation.hxx> class TestComparator { @@ -40,10 +43,12 @@ private: cmCTestMultiProcessHandler::cmCTestMultiProcessHandler() { this->ParallelLevel = 1; + this->TestLoad = 0; this->Completed = 0; this->RunningCount = 0; this->StopTimePassed = false; this->HasCycles = false; + this->SerialTestRunning = false; } cmCTestMultiProcessHandler::~cmCTestMultiProcessHandler() @@ -83,6 +88,11 @@ void cmCTestMultiProcessHandler::SetParallelLevel(size_t level) this->ParallelLevel = level < 1 ? 1 : level; } +void cmCTestMultiProcessHandler::SetTestLoad(unsigned long load) +{ + this->TestLoad = load; +} + //--------------------------------------------------------- void cmCTestMultiProcessHandler::RunTests() { @@ -172,6 +182,11 @@ void cmCTestMultiProcessHandler::LockResources(int index) this->LockedResources.insert( this->Properties[index]->LockedResources.begin(), this->Properties[index]->LockedResources.end()); + + if (this->Properties[index]->RunSerial) + { + this->SerialTestRunning = true; + } } //--------------------------------------------------------- @@ -198,17 +213,20 @@ inline size_t cmCTestMultiProcessHandler::GetProcessorsUsed(int test) { size_t processors = static_cast<int>(this->Properties[test]->Processors); - //If this is set to run serially, it must run alone. - //Also, if processors setting is set higher than the -j + //If processors setting is set higher than the -j //setting, we default to using all of the process slots. - if(this->Properties[test]->RunSerial - || processors > this->ParallelLevel) + if (processors > this->ParallelLevel) { processors = this->ParallelLevel; } return processors; } +std::string cmCTestMultiProcessHandler::GetName(int test) +{ + return this->Properties[test]->Name; +} + //--------------------------------------------------------- bool cmCTestMultiProcessHandler::StartTest(int test) { @@ -248,22 +266,136 @@ void cmCTestMultiProcessHandler::StartNextTests() return; } + // Don't start any new tests if one with the RUN_SERIAL property + // is already running. + if (this->SerialTestRunning) + { + return; + } + + bool allTestsFailedTestLoadCheck = false; + bool usedFakeLoadForTesting = false; + size_t minProcessorsRequired = this->ParallelLevel; + std::string testWithMinProcessors = ""; + + cmsys::SystemInformation info; + + unsigned long systemLoad = 0; + size_t spareLoad = 0; + if (this->TestLoad > 0) + { + // Activate possible wait. + allTestsFailedTestLoadCheck = true; + + // Check for a fake load average value used in testing. + if (const char* fake_load_value = + cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING")) + { + usedFakeLoadForTesting = true; + if (!cmSystemTools::StringToULong(fake_load_value, &systemLoad)) + { + cmSystemTools::Error("Failed to parse fake load value: ", + fake_load_value); + } + } + // If it's not set, look up the true load average. + else + { + systemLoad = static_cast<unsigned long>(ceil(info.GetLoadAverage())); + } + spareLoad = (this->TestLoad > systemLoad ? + this->TestLoad - systemLoad : 0); + + // Don't start more tests than the spare load can support. + if (numToStart > spareLoad) + { + numToStart = spareLoad; + } + } + TestList copy = this->SortedTests; for(TestList::iterator test = copy.begin(); test != copy.end(); ++test) { + // Take a nap if we're currently performing a RUN_SERIAL test. + if (this->SerialTestRunning) + { + break; + } + // We can only start a RUN_SERIAL test if no other tests are also running. + if (this->Properties[*test]->RunSerial && this->RunningCount > 0) + { + continue; + } + size_t processors = GetProcessorsUsed(*test); + bool testLoadOk = true; + if (this->TestLoad > 0) + { + if (processors <= spareLoad) + { + cmCTestLog(this->CTest, DEBUG, + "OK to run " << GetName(*test) << + ", it requires " << processors << + " procs & system load is: " << + systemLoad << std::endl); + allTestsFailedTestLoadCheck = false; + } + else + { + testLoadOk = false; + } + } - if(processors <= numToStart && this->StartTest(*test)) + if (processors <= minProcessorsRequired) { - if(this->StopTimePassed) - { - return; - } - numToStart -= processors; + minProcessorsRequired = processors; + testWithMinProcessors = GetName(*test); + } + + if(testLoadOk && processors <= numToStart && this->StartTest(*test)) + { + if(this->StopTimePassed) + { + return; + } + + numToStart -= processors; } else if(numToStart == 0) { - return; + break; + } + } + + if (allTestsFailedTestLoadCheck) + { + cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, "); + if (this->SerialTestRunning) + { + cmCTestLog(this->CTest, HANDLER_OUTPUT, + "Waiting for RUN_SERIAL test to finish."); + } + else + { + cmCTestLog(this->CTest, HANDLER_OUTPUT, + "System Load: " << systemLoad << ", " + "Max Allowed Load: " << this->TestLoad << ", " + "Smallest test " << testWithMinProcessors << + " requires " << minProcessorsRequired); + } + cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl); + + if (usedFakeLoadForTesting) + { + // Break out of the infinite loop of waiting for our fake load + // to come down. + this->StopTimePassed = true; + } + else + { + // Wait between 1 and 5 seconds before trying again. + cmCTestScriptHandler::SleepInSeconds( + cmSystemTools::RandomSeed() % 5 + 1); } } } @@ -319,6 +451,11 @@ bool cmCTestMultiProcessHandler::CheckOutput() this->WriteCheckpoint(test); this->UnlockResources(test); this->RunningCount -= GetProcessorsUsed(test); + if (this->Properties[test]->RunSerial) + { + this->SerialTestRunning = false; + } + delete p; } return true; diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 6440fbc..ed3e155 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -37,6 +37,7 @@ public: void SetTests(TestMap& tests, PropertiesMap& properties); // Set the max number of tests that can be run at the same time. void SetParallelLevel(size_t); + void SetTestLoad(unsigned long load); virtual void RunTests(); void PrintTestList(); void PrintLabels(); @@ -93,6 +94,7 @@ protected: bool CheckCycles(); int FindMaxIndex(); inline size_t GetProcessorsUsed(int index); + std::string GetName(int index); void LockResources(int index); void UnlockResources(int index); @@ -116,11 +118,13 @@ protected: std::set<std::string> LockedResources; std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults; size_t ParallelLevel; // max number of process that can be run at once + unsigned long TestLoad; std::set<cmCTestRunTest*> RunningTests; // current running tests cmCTestTestHandler * TestHandler; cmCTest* CTest; bool HasCycles; bool Quiet; + bool SerialTestRunning; }; #endif diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 8b357ac..b7d8318 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -26,6 +26,7 @@ cmCTestTestCommand::cmCTestTestCommand() this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL"; this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM"; this->Arguments[ctt_STOP_TIME] = "STOP_TIME"; + this->Arguments[ctt_TEST_LOAD] = "TEST_LOAD"; this->Arguments[ctt_LAST] = 0; this->Last = ctt_LAST; } @@ -103,6 +104,38 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() { this->CTest->SetStopTime(this->Values[ctt_STOP_TIME]); } + + // Test load is determined by: TEST_LOAD argument, + // or CTEST_TEST_LOAD script variable, or ctest --test-load + // command line argument... in that order. + unsigned long testLoad; + const char* ctestTestLoad + = this->Makefile->GetDefinition("CTEST_TEST_LOAD"); + if(this->Values[ctt_TEST_LOAD] && *this->Values[ctt_TEST_LOAD]) + { + if (!cmSystemTools::StringToULong(this->Values[ctt_TEST_LOAD], &testLoad)) + { + testLoad = 0; + cmCTestLog(this->CTest, WARNING, "Invalid value for 'TEST_LOAD' : " + << this->Values[ctt_TEST_LOAD] << std::endl); + } + } + else if(ctestTestLoad && *ctestTestLoad) + { + if (!cmSystemTools::StringToULong(ctestTestLoad, &testLoad)) + { + testLoad = 0; + cmCTestLog(this->CTest, WARNING, + "Invalid value for 'CTEST_TEST_LOAD' : " << + ctestTestLoad << std::endl); + } + } + else + { + testLoad = this->CTest->GetTestLoad(); + } + handler->SetTestLoad(testLoad); + handler->SetQuiet(this->Quiet); return handler; } diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index a1e5f36..0dfca97 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -60,6 +60,7 @@ protected: ctt_PARALLEL_LEVEL, ctt_SCHEDULE_RANDOM, ctt_STOP_TIME, + ctt_TEST_LOAD, ctt_LAST }; }; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 70b7f5c..5faf001 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -656,9 +656,8 @@ int cmCTestTestHandler::ProcessHandler() void cmCTestTestHandler::PrintLabelSummary() { cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin(); - cmCTestTestHandler::TestResultsVector::iterator ri = - this->TestResults.begin(); std::map<std::string, double> labelTimes; + std::map<std::string, int> labelCounts; std::set<std::string> labels; // initialize maps std::string::size_type maxlen = 0; @@ -676,10 +675,12 @@ void cmCTestTestHandler::PrintLabelSummary() } labels.insert(*l); labelTimes[*l] = 0; + labelCounts[*l] = 0; } } } - ri = this->TestResults.begin(); + cmCTestTestHandler::TestResultsVector::iterator ri = + this->TestResults.begin(); // fill maps for(; ri != this->TestResults.end(); ++ri) { @@ -691,6 +692,7 @@ void cmCTestTestHandler::PrintLabelSummary() l != p.Labels.end(); ++l) { labelTimes[*l] += result.ExecutionTime; + ++labelCounts[*l]; } } } @@ -705,10 +707,21 @@ void cmCTestTestHandler::PrintLabelSummary() { std::string label = *i; label.resize(maxlen +3, ' '); + char buf[1024]; sprintf(buf, "%6.2f sec", labelTimes[*i]); + + std::ostringstream labelCountStr; + labelCountStr << "(" << labelCounts[*i] << " test"; + if (labelCounts[*i] > 1) + { + labelCountStr << "s"; + } + labelCountStr << ")"; + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n" - << label << " = " << buf, this->Quiet ); + << label << " = " << buf << " " << labelCountStr.str(), + this->Quiet ); if ( this->LogFile ) { *this->LogFile << "\n" << *i << " = " @@ -1062,6 +1075,14 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string> &passed, parallel->SetParallelLevel(this->CTest->GetParallelLevel()); parallel->SetTestHandler(this); parallel->SetQuiet(this->Quiet); + if(this->TestLoad > 0) + { + parallel->SetTestLoad(this->TestLoad); + } + else + { + parallel->SetTestLoad(this->CTest->GetTestLoad()); + } *this->LogFile << "Start testing: " << this->CTest->CurrentTime() << std::endl diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 72818f5..44d0d4e 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -84,7 +84,8 @@ cmArchiveWrite::cmArchiveWrite( Stream(os), Archive(archive_write_new()), Disk(archive_read_disk_new()), - Verbose(false) + Verbose(false), + Format(format) { switch (c) { @@ -282,6 +283,14 @@ bool cmArchiveWrite::AddFile(const char* file, archive_entry_acl_clear(e); archive_entry_xattr_clear(e); archive_entry_set_fflags(e, 0, 0); + + if (this->Format == "pax" || this->Format == "paxr") + { + // Sparse files are a GNU tar extension. + // Do not use them in standard tar files. + archive_entry_sparse_clear(e); + } + if(archive_write_header(this->Archive, e) != ARCHIVE_OK) { this->Error = "archive_write_header: "; diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index 794cb28..e6f515d 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -84,6 +84,7 @@ private: struct archive* Archive; struct archive* Disk; bool Verbose; + std::string Format; std::string Error; std::string MTime; }; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index e3b7a2b..5676dda 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -294,6 +294,7 @@ cmCTest::cmCTest() this->LabelSummary = true; this->ParallelLevel = 1; this->ParallelLevelSetInCli = false; + this->TestLoad = 0; this->SubmitIndex = 0; this->Failover = false; this->BatchJobs = false; @@ -393,6 +394,11 @@ void cmCTest::SetParallelLevel(int level) this->ParallelLevel = level < 1 ? 1 : level; } +void cmCTest::SetTestLoad(unsigned long load) +{ + this->TestLoad = load; +} + //---------------------------------------------------------------------------- bool cmCTest::ShouldCompressTestOutput() { @@ -820,6 +826,20 @@ bool cmCTest::UpdateCTestConfiguration() cmSystemTools::ChangeDirectory(this->BinaryDir); } this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str()); + std::string const& testLoad = this->GetCTestConfiguration("TestLoad"); + if (!testLoad.empty()) + { + unsigned long load; + if (cmSystemTools::StringToULong(testLoad.c_str(), &load)) + { + this->SetTestLoad(load); + } + else + { + cmCTestLog(this, WARNING, "Invalid value for 'Test Load' : " + << testLoad << std::endl); + } + } if ( this->ProduceXML ) { this->CompressXMLFiles = cmSystemTools::IsOn( @@ -1200,7 +1220,7 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, char* data; int length; - cmCTestLog(this, HANDLER_OUTPUT, + cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Each . represents " << tick_len << " bytes of output" << std::endl << " " << std::flush); while(cmsysProcess_WaitForData(cp, &data, &length, 0)) @@ -1216,10 +1236,10 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, while ( output.size() > (tick * tick_len) ) { tick ++; - cmCTestLog(this, HANDLER_OUTPUT, "." << std::flush); + cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush); if ( tick % tick_line_len == 0 && tick > 0 ) { - cmCTestLog(this, HANDLER_OUTPUT, + cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size: " << int((double(output.size()) / 1024.0) + 1) << "K" << std::endl @@ -1232,7 +1252,7 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, ofs << cmCTestLogWrite(data, length); } } - cmCTestLog(this, OUTPUT, " Size of output: " + cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size of output: " << int(double(output.size()) / 1024.0) << "K" << std::endl); cmsysProcess_WaitForExit(cp, 0); @@ -2051,6 +2071,21 @@ bool cmCTest::HandleCommandLineArguments(size_t &i, } } + if(this->CheckArgument(arg, "--test-load") && i < args.size() - 1) + { + i++; + unsigned long load; + if (cmSystemTools::StringToULong(args[i].c_str(), &load)) + { + this->SetTestLoad(load); + } + else + { + cmCTestLog(this, WARNING, + "Invalid value for 'Test Load' : " << args[i] << std::endl); + } + } + if(this->CheckArgument(arg, "--no-compress-output")) { this->CompressTestOutput = false; @@ -3066,6 +3101,7 @@ static const char* cmCTestStringLogType[] = "DEBUG", "OUTPUT", "HANDLER_OUTPUT", + "HANDLER_PROGRESS_OUTPUT", "HANDLER_VERBOSE_OUTPUT", "WARNING", "ERROR_MESSAGE", @@ -3104,6 +3140,11 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, { return; } + if ( logType == cmCTest::HANDLER_PROGRESS_OUTPUT && + ( this->Debug || this->ExtraVerbose ) ) + { + return; + } if ( this->OutputLogFile ) { bool display = true; diff --git a/Source/cmCTest.h b/Source/cmCTest.h index db3ea10..73c2807 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -161,6 +161,9 @@ public: int GetParallelLevel() { return this->ParallelLevel; } void SetParallelLevel(int); + unsigned long GetTestLoad() { return this->TestLoad; } + void SetTestLoad(unsigned long); + /** * Check if CTest file exists */ @@ -379,6 +382,7 @@ public: DEBUG = 0, OUTPUT, HANDLER_OUTPUT, + HANDLER_PROGRESS_OUTPUT, HANDLER_VERBOSE_OUTPUT, WARNING, ERROR_MESSAGE, @@ -499,6 +503,8 @@ private: int ParallelLevel; bool ParallelLevelSetInCli; + unsigned long TestLoad; + int CompatibilityMode; // information for the --build-and-test options diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 87b47b4..c4a03a0 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -147,12 +147,12 @@ bool cmComputeTargetDepends::Compute() //---------------------------------------------------------------------------- void -cmComputeTargetDepends::GetTargetDirectDepends(cmTarget const* t, +cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t, cmTargetDependSet& deps) { // Lookup the index for this target. All targets should be known by // this point. - std::map<cmTarget const*, int>::const_iterator tii + std::map<cmGeneratorTarget const*, int>::const_iterator tii = this->TargetIndex.find(t); assert(tii != this->TargetIndex.end()); int i = tii->second; @@ -161,7 +161,7 @@ cmComputeTargetDepends::GetTargetDirectDepends(cmTarget const* t, EdgeList const& nl = this->FinalGraph[i]; for(EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) { - cmTarget const* dep = this->Targets[*ni]; + cmGeneratorTarget const* dep = this->Targets[*ni]; cmTargetDependSet::iterator di = deps.insert(dep).first; di->SetType(ni->IsStrong()); } @@ -180,9 +180,11 @@ void cmComputeTargetDepends::CollectTargets() ti != targets.end(); ++ti) { cmTarget const* target = &ti->second; + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(target); int index = static_cast<int>(this->Targets.size()); - this->TargetIndex[target] = index; - this->Targets.push_back(target); + this->TargetIndex[gt] = index; + this->Targets.push_back(gt); } } } @@ -204,7 +206,7 @@ void cmComputeTargetDepends::CollectDepends() void cmComputeTargetDepends::CollectTargetDepends(int depender_index) { // Get the depender. - cmTarget const* depender = this->Targets[depender_index]; + cmGeneratorTarget const* depender = this->Targets[depender_index]; if (depender->GetType() == cmTarget::INTERFACE_LIBRARY) { return; @@ -216,10 +218,9 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // deal with config-specific dependencies. { std::set<std::string> emitted; - cmGeneratorTarget* gt = this->GlobalGenerator->GetGeneratorTarget(depender); std::vector<std::string> configs; - depender->GetMakefile()->GetConfigurations(configs); + depender->Makefile->GetConfigurations(configs); if (configs.empty()) { configs.push_back(""); @@ -228,7 +229,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) it != configs.end(); ++it) { std::vector<cmSourceFile const*> objectFiles; - gt->GetExternalObjects(objectFiles, *it); + depender->GetExternalObjects(objectFiles, *it); for(std::vector<cmSourceFile const*>::const_iterator oi = objectFiles.begin(); oi != objectFiles.end(); ++oi) { @@ -244,15 +245,15 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) ->IssueMessage(cmake::FATAL_ERROR, "Only executables and non-OBJECT libraries may " "reference target objects.", - depender->GetBacktrace()); + depender->Target->GetBacktrace()); return; } - const_cast<cmTarget*>(depender)->AddUtility(objLib); + const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib); } } cmTarget::LinkImplementation const* impl = - depender->GetLinkImplementation(*it); + depender->Target->GetLinkImplementation(*it); // A target should not depend on itself. emitted.insert(depender->GetName()); @@ -272,7 +273,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // Loop over all utility dependencies. { - std::set<cmLinkItem> const& tutils = depender->GetUtilityItems(); + std::set<cmLinkItem> const& tutils = depender->Target->GetUtilityItems(); std::set<std::string> emitted; // A target should not depend on itself. emitted.insert(depender->GetName()); @@ -290,13 +291,14 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) //---------------------------------------------------------------------------- void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, - cmTarget const* dependee, - const std::string& config, - std::set<std::string> &emitted) + const cmGeneratorTarget* dependee, + const std::string& config, + std::set<std::string> &emitted) { - cmTarget const* depender = this->Targets[depender_index]; + cmGeneratorTarget const* depender = this->Targets[depender_index]; if(cmTarget::LinkInterface const* iface = - dependee->GetLinkInterface(config, depender)) + dependee->Target->GetLinkInterface(config, + depender->Target)) { for(std::vector<cmLinkItem>::const_iterator lib = iface->Libraries.begin(); @@ -317,7 +319,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, std::set<std::string> &emitted) { - cmTarget const* depender = this->Targets[depender_index]; + cmGeneratorTarget const* depender = this->Targets[depender_index]; cmTarget const* dependee = dependee_name.Target; // Skip targets that will not really be linked. This is probably a // name conflict between an external library and an executable @@ -331,16 +333,17 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, if(dependee) { - this->AddInterfaceDepends(depender_index, dependee, "", emitted); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(dependee); + this->AddInterfaceDepends(depender_index, gt, "", emitted); std::vector<std::string> configs; - depender->GetMakefile()->GetConfigurations(configs); + depender->Makefile->GetConfigurations(configs); for (std::vector<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it) { // A target should not depend on itself. emitted.insert(depender->GetName()); - this->AddInterfaceDepends(depender_index, dependee, - *it, emitted); + this->AddInterfaceDepends(depender_index, gt, *it, emitted); } } } @@ -351,7 +354,7 @@ void cmComputeTargetDepends::AddTargetDepend( bool linking) { // Get the depender. - cmTarget const* depender = this->Targets[depender_index]; + cmGeneratorTarget const* depender = this->Targets[depender_index]; // Check the target's makefile first. cmTarget const* dependee = dependee_name.Target; @@ -362,7 +365,7 @@ void cmComputeTargetDepends::AddTargetDepend( cmake::MessageType messageType = cmake::AUTHOR_WARNING; bool issueMessage = false; std::ostringstream e; - switch(depender->GetPolicyStatusCMP0046()) + switch(depender->Target->GetPolicyStatusCMP0046()) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0046) << "\n"; @@ -383,7 +386,7 @@ void cmComputeTargetDepends::AddTargetDepend( << "\" of target \"" << depender->GetName() << "\" does not exist."; cmListFileBacktrace const* backtrace = - depender->GetUtilityBacktrace(dependee_name); + depender->Target->GetUtilityBacktrace(dependee_name); if(backtrace) { cm->IssueMessage(messageType, e.str(), *backtrace); @@ -408,27 +411,31 @@ void cmComputeTargetDepends::AddTargetDepend( if(dependee) { - this->AddTargetDepend(depender_index, dependee, linking); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(dependee); + this->AddTargetDepend(depender_index, gt, linking); } } //---------------------------------------------------------------------------- void cmComputeTargetDepends::AddTargetDepend(int depender_index, - cmTarget const* dependee, + const cmGeneratorTarget* dependee, bool linking) { - if(dependee->IsImported() || + if(dependee->Target->IsImported() || dependee->GetType() == cmTarget::INTERFACE_LIBRARY) { // Skip IMPORTED and INTERFACE targets but follow their utility // dependencies. - std::set<cmLinkItem> const& utils = dependee->GetUtilityItems(); + std::set<cmLinkItem> const& utils = dependee->Target->GetUtilityItems(); for(std::set<cmLinkItem>::const_iterator i = utils.begin(); i != utils.end(); ++i) { if(cmTarget const* transitive_dependee = i->Target) { - this->AddTargetDepend(depender_index, transitive_dependee, false); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(transitive_dependee); + this->AddTargetDepend(depender_index, gt, false); } } } @@ -436,7 +443,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, { // Lookup the index for this target. All targets should be known by // this point. - std::map<cmTarget const*, int>::const_iterator tii = + std::map<cmGeneratorTarget const*, int>::const_iterator tii = this->TargetIndex.find(dependee); assert(tii != this->TargetIndex.end()); int dependee_index = tii->second; @@ -457,13 +464,13 @@ cmComputeTargetDepends::DisplayGraph(Graph const& graph, for(int depender_index = 0; depender_index < n; ++depender_index) { EdgeList const& nl = graph[depender_index]; - cmTarget const* depender = this->Targets[depender_index]; + cmGeneratorTarget const* depender = this->Targets[depender_index]; fprintf(stderr, "target %d is [%s]\n", depender_index, depender->GetName().c_str()); for(EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) { int dependee_index = *ni; - cmTarget const* dependee = this->Targets[dependee_index]; + cmGeneratorTarget const* dependee = this->Targets[dependee_index]; fprintf(stderr, " depends on target %d [%s] (%s)\n", dependee_index, dependee->GetName().c_str(), ni->IsStrong()? "strong" : "weak"); } @@ -550,11 +557,11 @@ cmComputeTargetDepends { // Get the depender. int i = *ci; - cmTarget const* depender = this->Targets[i]; + cmGeneratorTarget const* depender = this->Targets[i]; // Describe the depender. e << " \"" << depender->GetName() << "\" of type " - << cmTarget::GetTargetTypeName(depender->GetType()) << "\n"; + << cmTarget::GetTargetTypeName(depender->Target->GetType()) << "\n"; // List its dependencies that are inside the component. EdgeList const& nl = this->InitialGraph[i]; @@ -563,7 +570,7 @@ cmComputeTargetDepends int j = *ni; if(cmap[j] == c) { - cmTarget const* dependee = this->Targets[j]; + cmGeneratorTarget const* dependee = this->Targets[j]; e << " depends on \"" << dependee->GetName() << "\"" << " (" << (ni->IsStrong()? "strong" : "weak") << ")\n"; } diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 902f342..6100d97 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -21,7 +21,7 @@ class cmComputeComponentGraph; class cmGlobalGenerator; class cmLinkItem; -class cmTarget; +class cmGeneratorTarget; class cmTargetDependSet; /** \class cmComputeTargetDepends @@ -39,9 +39,10 @@ public: bool Compute(); - std::vector<cmTarget const*> const& + std::vector<cmGeneratorTarget const*> const& GetTargets() const { return this->Targets; } - void GetTargetDirectDepends(cmTarget const* t, cmTargetDependSet& deps); + void GetTargetDirectDepends(cmGeneratorTarget const* t, + cmTargetDependSet& deps); private: void CollectTargets(); void CollectDepends(); @@ -49,13 +50,14 @@ private: void AddTargetDepend(int depender_index, cmLinkItem const& dependee_name, bool linking); - void AddTargetDepend(int depender_index, cmTarget const* dependee, + void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee, bool linking); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, std::set<std::string> &emitted); - void AddInterfaceDepends(int depender_index, cmTarget const* dependee, + void AddInterfaceDepends(int depender_index, + cmGeneratorTarget const* dependee, const std::string& config, std::set<std::string> &emitted); cmGlobalGenerator* GlobalGenerator; @@ -63,8 +65,8 @@ private: bool NoCycles; // Collect all targets. - std::vector<cmTarget const*> Targets; - std::map<cmTarget const*, int> TargetIndex; + std::vector<cmGeneratorTarget const*> Targets; + std::map<cmGeneratorTarget const*, int> TargetIndex; // Represent the target dependency graph. The entry at each // top-level index corresponds to a depender whose dependencies are diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index f12116e..1b2586c 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -143,7 +143,7 @@ cmDependsFortran std::vector<std::string> definitions; cmMakefile* mf = this->LocalGenerator->GetMakefile(); if(const char* c_defines = - mf->GetDefinition("CMAKE_TARGET_DEFINITIONS")) + mf->GetDefinition("CMAKE_TARGET_DEFINITIONS_Fortran")) { cmSystemTools::ExpandListArgument(c_defines, definitions); } diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index b3576c3..78853ce 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -95,6 +95,7 @@ bool cmFunctionHelperCommand::InvokeInitialPass } cmMakefile::FunctionPushPop functionScope(this->Makefile, + this->FilePath, this->Policies); // set the value of argc diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 14efc3e..2f9265a 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -355,11 +355,11 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries() { // library directories cmTargetDependSet tds = - this->GetGlobalGenerator()->GetTargetDirectDepends(*this->Target); + this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget); for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end(); ++tdsI) { - const cmTarget *tg(*tdsI); + const cmTarget *tg = (*tdsI)->Target; *this->GetFolderBuildStreams() << " -L\"" << GetAbsBuildFilePath(tg) << "\"" << std::endl; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 14eaeac..88ac0bc 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -564,6 +564,10 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, cmSystemTools::Error("Could not find cmake module file: ", determineCompiler.c_str()); } + if (cmSystemTools::GetFatalErrorOccured()) + { + return; + } needTestLanguage[lang] = true; // Some generators like visual studio should not use the env variables // So the global generator can specify that in this variable @@ -1102,6 +1106,7 @@ void cmGlobalGenerator::Configure() // now do it lg->GetMakefile()->Configure(); + lg->GetMakefile()->EnforceDirectoryLevelRules(); // update the cache entry for the number of local generators, this is used // for progress @@ -1350,9 +1355,9 @@ bool cmGlobalGenerator::ComputeTargetDepends() { return false; } - std::vector<cmTarget const*> const& targets = ctd.GetTargets(); - for(std::vector<cmTarget const*>::const_iterator ti = targets.begin(); - ti != targets.end(); ++ti) + std::vector<cmGeneratorTarget const*> const& targets = ctd.GetTargets(); + for(std::vector<cmGeneratorTarget const*>::const_iterator ti + = targets.begin(); ti != targets.end(); ++ti) { ctd.GetTargetDirectDepends(*ti, this->TargetDependencies[*ti]); } @@ -2039,19 +2044,19 @@ void cmGlobalGenerator::FillLocalGeneratorToTargetMap() clg = clg->GetParent()) { // This local generator includes the target. - std::set<cmTarget const*>& targetSet = + std::set<cmGeneratorTarget const*>& targetSet = this->LocalGeneratorToTargetMap[clg]; - targetSet.insert(&target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(&target); + targetSet.insert(gt); // Add dependencies of the included target. An excluded // target may still be included if it is a dependency of a // non-excluded target. - TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target); + TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(gt); for(TargetDependSet::const_iterator ti = tgtdeps.begin(); ti != tgtdeps.end(); ++ti) { - cmTarget const* ttt = *ti; - targetSet.insert(ttt); + targetSet.insert(*ti); } } } @@ -2513,9 +2518,9 @@ void cmGlobalGenerator::AppendDirectoryForConfig(const std::string&, //---------------------------------------------------------------------------- cmGlobalGenerator::TargetDependSet const& -cmGlobalGenerator::GetTargetDirectDepends(cmTarget const& target) +cmGlobalGenerator::GetTargetDirectDepends(cmGeneratorTarget const* target) { - return this->TargetDependencies[&target]; + return this->TargetDependencies[target]; } void cmGlobalGenerator::AddTarget(cmTarget* t) @@ -2615,9 +2620,10 @@ void cmGlobalGenerator::GetTargetSets(TargetDependSet& projectTargets, continue; } // put the target in the set of original targets - originalTargets.insert(target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); + originalTargets.insert(gt); // Get the set of targets that depend on target - this->AddTargetDepends(target, projectTargets); + this->AddTargetDepends(gt, projectTargets); } } } @@ -2630,7 +2636,7 @@ bool cmGlobalGenerator::IsRootOnlyTarget(cmTarget* target) const } //---------------------------------------------------------------------------- -void cmGlobalGenerator::AddTargetDepends(cmTarget const* target, +void cmGlobalGenerator::AddTargetDepends(cmGeneratorTarget const* target, TargetDependSet& projectTargets) { // add the target itself @@ -2638,11 +2644,10 @@ void cmGlobalGenerator::AddTargetDepends(cmTarget const* target, { // This is the first time we have encountered the target. // Recursively follow its dependencies. - TargetDependSet const& ts = this->GetTargetDirectDepends(*target); + TargetDependSet const& ts = this->GetTargetDirectDepends(target); for(TargetDependSet::const_iterator i = ts.begin(); i != ts.end(); ++i) { - cmTarget const* dtarget = *i; - this->AddTargetDepends(dtarget, projectTargets); + this->AddTargetDepends(*i, projectTargets); } } } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index d606cc9..398335b 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -292,7 +292,8 @@ public: // what targets does the specified target depend on directly // via a target_link_libraries or add_dependencies - TargetDependSet const& GetTargetDirectDepends(cmTarget const& target); + TargetDependSet const& GetTargetDirectDepends( + const cmGeneratorTarget* target); /** Get per-target generator information. */ cmGeneratorTarget* GetGeneratorTarget(cmTarget const*) const; @@ -368,7 +369,7 @@ protected: TargetDependSet& originalTargets, cmLocalGenerator* root, GeneratorVector const&); bool IsRootOnlyTarget(cmTarget* target) const; - void AddTargetDepends(cmTarget const* target, + void AddTargetDepends(const cmGeneratorTarget* target, TargetDependSet& projectTargets); void SetLanguageEnabledFlag(const std::string& l, cmMakefile* mf); void SetLanguageEnabledMaps(const std::string& l, cmMakefile* mf); @@ -405,7 +406,7 @@ protected: cmMakefile* CurrentMakefile; // map from project name to vector of local generators in that project std::map<std::string, std::vector<cmLocalGenerator*> > ProjectMap; - std::map<cmLocalGenerator*, std::set<cmTarget const*> > + std::map<cmLocalGenerator*, std::set<cmGeneratorTarget const*> > LocalGeneratorToTargetMap; // Set of named installation components requested by the project. @@ -477,7 +478,7 @@ private: std::vector<std::string> FilesReplacedDuringGenerate; // Store computed inter-target dependencies. - typedef std::map<cmTarget const*, TargetDependSet> TargetDependMap; + typedef std::map<cmGeneratorTarget const*, TargetDependSet> TargetDependMap; TargetDependMap TargetDependencies; // Per-target generator information. diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 103d75a..722294b 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -949,8 +949,8 @@ cmGlobalNinjaGenerator std::set<std::string> const& utils = target->GetUtilities(); std::copy(utils.begin(), utils.end(), std::back_inserter(outputs)); } else { - cmTargetDependSet const& targetDeps = - this->GetTargetDirectDepends(*target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); + cmTargetDependSet const& targetDeps = this->GetTargetDirectDepends(gt); for (cmTargetDependSet::const_iterator i = targetDeps.begin(); i != targetDeps.end(); ++i) { @@ -958,7 +958,7 @@ cmGlobalNinjaGenerator { continue; } - this->AppendTargetOutputs(*i, outputs); + this->AppendTargetOutputs((*i)->Target, outputs); } } } diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 0f61225..e6a67d3 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -804,7 +804,7 @@ cmGlobalUnixMakefileGenerator3 lg->AppendEcho(commands, "Built target " + name, cmLocalUnixMakefileGenerator3::EchoNormal, &progress); - this->AppendGlobalTargetDepends(depends,*gtarget->Target); + this->AppendGlobalTargetDepends(depends, gtarget); lg->WriteMakeRule(ruleFileStream, "All Build rule for target.", localName, depends, commands, true); @@ -830,9 +830,9 @@ cmGlobalUnixMakefileGenerator3 cmLocalGenerator::FULL, cmLocalGenerator::SHELL); // - std::set<cmTarget const*> emitted; + std::set<cmGeneratorTarget const*> emitted; progCmd << " " - << this->CountProgressMarksInTarget(gtarget->Target, emitted); + << this->CountProgressMarksInTarget(gtarget, emitted); commands.push_back(progCmd.str()); } std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash(); @@ -908,14 +908,14 @@ cmGlobalUnixMakefileGenerator3 //---------------------------------------------------------------------------- size_t cmGlobalUnixMakefileGenerator3 -::CountProgressMarksInTarget(cmTarget const* target, - std::set<cmTarget const*>& emitted) +::CountProgressMarksInTarget(cmGeneratorTarget const* target, + std::set<cmGeneratorTarget const*>& emitted) { size_t count = 0; if(emitted.insert(target).second) { - count = this->ProgressMap[target].Marks.size(); - TargetDependSet const& depends = this->GetTargetDirectDepends(*target); + count = this->ProgressMap[target->Target].Marks.size(); + TargetDependSet const& depends = this->GetTargetDirectDepends(target); for(TargetDependSet::const_iterator di = depends.begin(); di != depends.end(); ++di) { @@ -935,10 +935,10 @@ cmGlobalUnixMakefileGenerator3 ::CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg) { size_t count = 0; - std::set<cmTarget const*> emitted; - std::set<cmTarget const*> const& targets + std::set<cmGeneratorTarget const*> emitted; + std::set<cmGeneratorTarget const*> const& targets = this->LocalGeneratorToTargetMap[lg]; - for(std::set<cmTarget const*>::const_iterator t = targets.begin(); + for(std::set<cmGeneratorTarget const*>::const_iterator t = targets.begin(); t != targets.end(); ++t) { count += this->CountProgressMarksInTarget(*t, emitted); @@ -987,22 +987,21 @@ cmGlobalUnixMakefileGenerator3::TargetProgress void cmGlobalUnixMakefileGenerator3 ::AppendGlobalTargetDepends(std::vector<std::string>& depends, - cmTarget& target) + cmGeneratorTarget* target) { TargetDependSet const& depends_set = this->GetTargetDirectDepends(target); for(TargetDependSet::const_iterator i = depends_set.begin(); i != depends_set.end(); ++i) { // Create the target-level dependency. - cmTarget const* dep = *i; + cmGeneratorTarget const* dep = *i; if (dep->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; } cmLocalUnixMakefileGenerator3* lg3 = - static_cast<cmLocalUnixMakefileGenerator3*> - (dep->GetMakefile()->GetLocalGenerator()); - std::string tgtName = lg3->GetRelativeTargetDirectory(*dep); + static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator()); + std::string tgtName = lg3->GetRelativeTargetDirectory(*(*dep).Target); tgtName += "/all"; depends.push_back(tgtName); } diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index a639ff0..14adf2e 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -153,7 +153,7 @@ protected: cmLocalUnixMakefileGenerator3* lg); void AppendGlobalTargetDepends(std::vector<std::string>& depends, - cmTarget& target); + cmGeneratorTarget* target); // does this generator need a requires step for any of its targets bool NeedRequiresStep(cmTarget const&); @@ -198,8 +198,8 @@ protected: cmStrictTargetComparison> ProgressMapType; ProgressMapType ProgressMap; - size_t CountProgressMarksInTarget(cmTarget const* target, - std::set<cmTarget const*>& emitted); + size_t CountProgressMarksInTarget(cmGeneratorTarget const* target, + std::set<cmGeneratorTarget const*>& emitted); size_t CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg); cmGeneratedFileStream *CommandDatabase; diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index 632141a..65a15ee 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -224,7 +224,7 @@ void cmGlobalVisualStudio6Generator tt = orderedProjectTargets.begin(); tt != orderedProjectTargets.end(); ++tt) { - cmTarget const* target = *tt; + cmTarget const* target = (*tt)->Target; if(target->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index f453da1..1674e98 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -402,7 +402,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( for(OrderedTargetDependSet::const_iterator tt = projectTargets.begin(); tt != projectTargets.end(); ++tt) { - cmTarget const* target = *tt; + cmTarget const* target = (*tt)->Target; if(target->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; @@ -442,7 +442,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( for(OrderedTargetDependSet::const_iterator tt = projectTargets.begin(); tt != projectTargets.end(); ++tt) { - cmTarget const* target = *tt; + cmTarget const* target = (*tt)->Target; if(target->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; @@ -534,7 +534,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends( for(OrderedTargetDependSet::const_iterator tt = projectTargets.begin(); tt != projectTargets.end(); ++tt) { - cmTarget const* target = *tt; + cmTarget const* target = (*tt)->Target; if(target->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; @@ -1045,12 +1045,12 @@ cmGlobalVisualStudio7Generator ::IsDependedOn(OrderedTargetDependSet const& projectTargets, cmTarget const* targetIn) { + cmGeneratorTarget* gtIn = this->GetGeneratorTarget(targetIn); for (OrderedTargetDependSet::const_iterator l = projectTargets.begin(); l != projectTargets.end(); ++l) { - cmTarget const& target = **l; - TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target); - if(tgtdeps.count(targetIn)) + TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(*l); + if(tgtdeps.count(gtIn)) { return true; } diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index b96a799..f3cf36e 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -441,7 +441,8 @@ bool cmGlobalVisualStudio8Generator::ComputeTargetDepends() void cmGlobalVisualStudio8Generator::WriteProjectDepends( std::ostream& fout, const std::string&, const char*, cmTarget const& t) { - TargetDependSet const& unordered = this->GetTargetDirectDepends(t); + cmGeneratorTarget* gt = this->GetGeneratorTarget(&t); + TargetDependSet const& unordered = this->GetTargetDirectDepends(gt); OrderedTargetDependSet depends(unordered); for(OrderedTargetDependSet::const_iterator i = depends.begin(); i != depends.end(); ++i) diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index bc134e1..1d583eb 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -301,13 +301,14 @@ void cmGlobalVisualStudioGenerator::FillLinkClosure(cmTarget const* target, { if(linked.insert(target).second) { - TargetDependSet const& depends = this->GetTargetDirectDepends(*target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); + TargetDependSet const& depends = this->GetTargetDirectDepends(gt); for(TargetDependSet::const_iterator di = depends.begin(); di != depends.end(); ++di) { if(di->IsLink()) { - this->FillLinkClosure(*di, linked); + this->FillLinkClosure((*di)->Target, linked); } } } @@ -340,13 +341,14 @@ void cmGlobalVisualStudioGenerator::FollowLinkDepends( { // Static library targets do not list their link dependencies so // we must follow them transitively now. - TargetDependSet const& depends = this->GetTargetDirectDepends(*target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(target); + TargetDependSet const& depends = this->GetTargetDirectDepends(gt); for(TargetDependSet::const_iterator di = depends.begin(); di != depends.end(); ++di) { if(di->IsLink()) { - this->FollowLinkDepends(*di, linked); + this->FollowLinkDepends((*di)->Target, linked); } } } @@ -415,7 +417,8 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) target.GetType() != cmTarget::MODULE_LIBRARY && target.GetType() != cmTarget::EXECUTABLE); - TargetDependSet const& depends = this->GetTargetDirectDepends(target); + cmGeneratorTarget* gt = this->GetGeneratorTarget(&target); + TargetDependSet const& depends = this->GetTargetDirectDepends(gt); // Collect implicit link dependencies (target_link_libraries). // Static libraries cannot depend on their link implementation @@ -429,7 +432,7 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) cmTargetDepend dep = *di; if(dep.IsLink()) { - this->FollowLinkDepends(dep, linkDepends); + this->FollowLinkDepends(dep->Target, linkDepends); } } } @@ -442,7 +445,7 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) cmTargetDepend dep = *di; if(dep.IsUtil()) { - this->FollowLinkDepends(dep, utilDepends); + this->FollowLinkDepends(dep->Target, utilDepends); } } @@ -845,7 +848,7 @@ cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget const& target) //---------------------------------------------------------------------------- bool cmGlobalVisualStudioGenerator::TargetCompare -::operator()(cmTarget const* l, cmTarget const* r) const +::operator()(cmGeneratorTarget const* l, cmGeneratorTarget const* r) const { // Make sure ALL_BUILD is first so it is the default active project. if(r->GetName() == "ALL_BUILD") @@ -870,7 +873,13 @@ cmGlobalVisualStudioGenerator::OrderedTargetDependSet cmGlobalVisualStudioGenerator::OrderedTargetDependSet ::OrderedTargetDependSet(TargetSet const& targets) { - this->insert(targets.begin(), targets.end()); + for (TargetSet::const_iterator it = targets.begin(); + it != targets.end(); ++it) + { + cmGeneratorTarget* gt = + (*it)->GetMakefile()->GetGlobalGenerator()->GetGeneratorTarget(*it); + this->insert(gt); + } } std::string cmGlobalVisualStudioGenerator::ExpandCFGIntDir( diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 022e190..8e2d6a4 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -91,7 +91,8 @@ public: class TargetSet: public std::set<cmTarget const*> {}; struct TargetCompare { - bool operator()(cmTarget const* l, cmTarget const* r) const; + bool operator()(cmGeneratorTarget const* l, + cmGeneratorTarget const* r) const; }; class OrderedTargetDependSet; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 1301e3e..505929e 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2895,10 +2895,11 @@ void cmGlobalXCodeGenerator } // Add dependencies on other CMake targets. - TargetDependSet const& deps = this->GetTargetDirectDepends(*cmtarget); + cmGeneratorTarget* gt = this->GetGeneratorTarget(cmtarget); + TargetDependSet const& deps = this->GetTargetDirectDepends(gt); for(TargetDependSet::const_iterator i = deps.begin(); i != deps.end(); ++i) { - if(cmXCodeObject* dptarget = this->FindXCodeTarget(*i)) + if(cmXCodeObject* dptarget = this->FindXCodeTarget((*i)->Target)) { this->AddDependTarget(target, dptarget); } diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h index d2339c4..df00b30 100644 --- a/Source/cmLinkedTree.h +++ b/Source/cmLinkedTree.h @@ -87,6 +87,24 @@ public: return this->Tree->GetPointer(this->Position - 1); } + ReferenceType operator*() const + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + return this->Tree->GetReference(this->Position - 1); + } + + ReferenceType operator*() + { + assert(this->Tree); + assert(this->Tree->UpPositions.size() == this->Tree->Data.size()); + assert(this->Position <= this->Tree->Data.size()); + assert(this->Position > 0); + return this->Tree->GetReference(this->Position - 1); + } + bool operator==(iterator other) const { assert(this->Tree); diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 006ca4c..1097dc2 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -251,7 +251,6 @@ bool cmListFileParser::ParseFunction(const char* name, long line) { // Inintialize a new function call. this->Function = cmListFileFunction(); - this->Function.FilePath = this->FileName; this->Function.Name = name; this->Function.Line = line; @@ -399,40 +398,50 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token, } } -void cmListFileBacktrace::Append(cmListFileContext const& context) -{ - this->push_back(context); -} - void cmListFileBacktrace::PrintTitle(std::ostream& out) { - if (this->empty()) + if (!this->Snapshot.IsValid()) { return; } - cmOutputConverter converter(this->Snapshot); - cmListFileContext lfc = this->front(); + cmListFileContext lfc = + cmListFileContext::FromCommandContext( + this->Context, this->Snapshot.GetExecutionListFile()); lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME); out << (lfc.Line ? " at " : " in ") << lfc; } void cmListFileBacktrace::PrintCallStack(std::ostream& out) { - if (size() <= 1) + if (!this->Snapshot.IsValid()) + { + return; + } + cmState::Snapshot parent = this->Snapshot.GetCallStackParent(); + if (!parent.IsValid() || parent.GetExecutionListFile().empty()) { return; } cmOutputConverter converter(this->Snapshot); - const_iterator i = this->begin() + 1; + std::string commandName = this->Snapshot.GetEntryPointCommand(); + long commandLine = this->Snapshot.GetEntryPointLine(); + out << "Call Stack (most recent call first):\n"; - while(i != this->end()) + while(parent.IsValid()) { - cmListFileContext lfc = *i; - lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME); + cmListFileContext lfc; + lfc.Name = commandName; + lfc.Line = commandLine; + + lfc.FilePath = converter.Convert(parent.GetExecutionListFile(), + cmOutputConverter::HOME); out << " " << lfc << "\n"; - ++i; + + commandName = parent.GetEntryPointCommand(); + commandLine = parent.GetEntryPointLine(); + parent = parent.GetCallStackParent(); } } diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index f5859ec..aa8a34c 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -25,6 +25,13 @@ class cmMakefile; +struct cmCommandContext +{ + std::string Name; + long Line; + cmCommandContext(): Name(), Line(0) {} +}; + struct cmListFileArgument { enum Delimiter @@ -57,6 +64,16 @@ struct cmListFileContext std::string FilePath; long Line; cmListFileContext(): Name(), FilePath(), Line(0) {} + + static cmListFileContext FromCommandContext(cmCommandContext const& lfcc, + std::string const& fileName) + { + cmListFileContext lfc; + lfc.FilePath = fileName; + lfc.Line = lfcc.Line; + lfc.Name = lfcc.Name; + return lfc; + } }; std::ostream& operator<<(std::ostream&, cmListFileContext const&); @@ -64,24 +81,24 @@ bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs); bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs); bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs); -struct cmListFileFunction: public cmListFileContext +struct cmListFileFunction: public cmCommandContext { std::vector<cmListFileArgument> Arguments; }; -class cmListFileBacktrace: private std::vector<cmListFileContext> +class cmListFileBacktrace { public: - cmListFileBacktrace(cmState::Snapshot snapshot = cmState::Snapshot()) - : Snapshot(snapshot) + cmListFileBacktrace(cmState::Snapshot snapshot = cmState::Snapshot(), + cmCommandContext const& cc = cmCommandContext()) + : Context(cc), Snapshot(snapshot) { } - void Append(cmListFileContext const& context); - void PrintTitle(std::ostream& out); void PrintCallStack(std::ostream& out); private: + cmCommandContext Context; cmState::Snapshot Snapshot; }; diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 0b945b2..6d3054a 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -97,6 +97,7 @@ bool cmMacroHelperCommand::InvokeInitialPass } cmMakefile::MacroPushPop macroScope(this->Makefile, + this->FilePath, this->Policies); // set the value of argc @@ -131,7 +132,6 @@ bool cmMacroHelperCommand::InvokeInitialPass newLFF.Arguments.clear(); newLFF.Arguments.reserve(this->Functions[c].Arguments.size()); newLFF.Name = this->Functions[c].Name; - newLFF.FilePath = this->Functions[c].FilePath; newLFF.Line = this->Functions[c].Line; // for each argument of the current function diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index a3ba134..94c77e1 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -247,11 +247,11 @@ void cmMakefile::IssueMessage(cmake::MessageType t, std::string const& text) const { // Collect context information. - if(!this->CallStack.empty()) + if(!this->ExecutionStatusStack.empty()) { if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) { - this->CallStack.back().Status->SetNestedError(true); + this->ExecutionStatusStack.back()->SetNestedError(true); } this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace()); } @@ -275,33 +275,29 @@ void cmMakefile::IssueMessage(cmake::MessageType t, //---------------------------------------------------------------------------- cmListFileBacktrace cmMakefile::GetBacktrace() const { - cmListFileBacktrace backtrace(this->StateSnapshot); - for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin(); - i != this->CallStack.rend(); ++i) + cmListFileBacktrace backtrace; + if (!this->ContextStack.empty()) { - backtrace.Append(*i->Context); + backtrace = cmListFileBacktrace(this->StateSnapshot, + *this->ContextStack.back()); } return backtrace; } //---------------------------------------------------------------------------- cmListFileBacktrace -cmMakefile::GetBacktrace(cmListFileContext const& lfc) const +cmMakefile::GetBacktrace(cmCommandContext const& cc) const { - cmListFileBacktrace backtrace(this->StateSnapshot); - backtrace.Append(lfc); - for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin(); - i != this->CallStack.rend(); ++i) - { - backtrace.Append(*i->Context); - } - return backtrace; + cmState::Snapshot snp = this->StateSnapshot; + return cmListFileBacktrace(snp, cc); } //---------------------------------------------------------------------------- cmListFileContext cmMakefile::GetExecutionContext() const { - return *this->CallStack.back().Context; + return cmListFileContext::FromCommandContext( + *this->ContextStack.back(), + this->StateSnapshot.GetExecutionListFile()); } //---------------------------------------------------------------------------- @@ -460,11 +456,24 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, // The included file cannot pop our policy scope. this->Makefile->PushPolicyBarrier(); this->Makefile->ListFileStack.push_back(filenametoread); + this->Makefile->PushFunctionBlockerBarrier(); + + this->Makefile->StateSnapshot = + this->Makefile->GetState()->CreateCallStackSnapshot( + this->Makefile->StateSnapshot, + this->Makefile->ContextStack.back()->Name, + this->Makefile->ContextStack.back()->Line, + filenametoread); } //---------------------------------------------------------------------------- cmMakefile::IncludeScope::~IncludeScope() { + this->Makefile->StateSnapshot = + this->Makefile->GetState()->Pop(this->Makefile->StateSnapshot); + assert(this->Makefile->StateSnapshot.IsValid()); + + this->Makefile->PopFunctionBlockerBarrier(this->ReportError); // Enforce matching policy scopes inside the included file. this->Makefile->PopPolicyBarrier(this->ReportError); @@ -532,25 +541,24 @@ void cmMakefile::IncludeScope::EnforceCMP0011() } } -bool cmMakefile::ProcessBuildsystemFile(const char* filename) +class cmParseFileScope { - this->AddDefinition("CMAKE_PARENT_LIST_FILE", filename); - std::string curSrc = this->GetCurrentSourceDirectory(); - - this->ListFileStack.push_back(filename); +public: + cmParseFileScope(cmMakefile* mf) + : Makefile(mf) + { + this->Makefile->ContextStack.push_back(&this->Context); + } - cmListFile listFile; - if (!listFile.ParseFile(filename, curSrc == this->GetHomeDirectory(), this)) - { - return false; - } + ~cmParseFileScope() + { + this->Makefile->ContextStack.pop_back(); + } - this->PushPolicyBarrier(); - this->ReadListFile(listFile, filename); - this->PopPolicyBarrier(!cmSystemTools::GetFatalErrorOccured()); - this->EnforceDirectoryLevelRules(); - return true; -} +private: + cmMakefile* Makefile; + cmCommandContext Context; +}; bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope) { @@ -563,11 +571,14 @@ bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope) IncludeScope incScope(this, filenametoread, noPolicyScope); cmListFile listFile; + { + cmParseFileScope pfs(this); if (!listFile.ParseFile(filenametoread.c_str(), false, this)) { - incScope.Quiet(); return false; } + } + this->ReadListFile(listFile, filenametoread); if(cmSystemTools::GetFatalErrorOccured()) { @@ -576,24 +587,68 @@ bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope) return true; } +class cmMakefile::ListFileScope +{ +public: + ListFileScope(cmMakefile* mf, std::string const& filenametoread) + : Makefile(mf), ReportError(true) + { + this->Makefile->ListFileStack.push_back(filenametoread); + this->Makefile->PushPolicyBarrier(); + + long line = 0; + std::string name; + if (!this->Makefile->ContextStack.empty()) + { + line = this->Makefile->ContextStack.back()->Line; + name = this->Makefile->ContextStack.back()->Name; + } + this->Makefile->StateSnapshot = + this->Makefile->GetState()->CreateInlineListFileSnapshot( + this->Makefile->StateSnapshot, name, line, filenametoread); + assert(this->Makefile->StateSnapshot.IsValid()); + this->Makefile->PushFunctionBlockerBarrier(); + } + + ~ListFileScope() + { + this->Makefile->StateSnapshot = + this->Makefile->GetState()->Pop(this->Makefile->StateSnapshot); + assert(this->Makefile->StateSnapshot.IsValid()); + + this->Makefile->PopFunctionBlockerBarrier(this->ReportError); + this->Makefile->PopPolicyBarrier(this->ReportError); + this->Makefile->ListFileStack.pop_back(); + } + + void Quiet() { this->ReportError = false; } +private: + cmMakefile* Makefile; + bool ReportError; +}; + bool cmMakefile::ReadListFile(const char* filename) { std::string filenametoread = cmSystemTools::CollapseFullPath(filename, this->GetCurrentSourceDirectory()); - this->ListFileStack.push_back(filenametoread); + ListFileScope scope(this, filenametoread); cmListFile listFile; + { + cmParseFileScope pfs(this); if (!listFile.ParseFile(filenametoread.c_str(), false, this)) { return false; } + } - this->PushPolicyBarrier(); this->ReadListFile(listFile, filenametoread); - this->PopPolicyBarrier(!cmSystemTools::GetFatalErrorOccured()); - this->ListFileStack.pop_back(); + if(cmSystemTools::GetFatalErrorOccured()) + { + scope.Quiet(); + } return true; } @@ -616,9 +671,6 @@ void cmMakefile::ReadListFile(cmListFile const& listFile, this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE"); this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR"); - // Enforce balanced blocks (if/endif, function/endfunction, etc.). - LexicalPushPop lexScope(this); - // Run the parsed commands. const size_t numberFunctions = listFile.Functions.size(); for(size_t i =0; i < numberFunctions; ++i) @@ -627,8 +679,6 @@ void cmMakefile::ReadListFile(cmListFile const& listFile, this->ExecuteCommand(listFile.Functions[i],status); if(cmSystemTools::GetFatalErrorOccured()) { - // Exit early due to error. - lexScope.Quiet(); break; } if(status.GetReturnInvoked()) @@ -1570,8 +1620,16 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) this->ImportedTargets = parent->ImportedTargets; } -void cmMakefile::PushFunctionScope(const cmPolicies::PolicyMap& pm) +void cmMakefile::PushFunctionScope(std::string const& fileName, + const cmPolicies::PolicyMap& pm) { + this->StateSnapshot = + this->GetState()->CreateFunctionCallSnapshot( + this->StateSnapshot, + this->ContextStack.back()->Name, this->ContextStack.back()->Line, + fileName); + assert(this->StateSnapshot.IsValid()); + this->Internal->PushDefinitions(); this->PushLoopBlockBarrier(); @@ -1591,6 +1649,9 @@ void cmMakefile::PopFunctionScope(bool reportError) this->PopPolicyBarrier(reportError); this->PopPolicy(); + this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot); + assert(this->StateSnapshot.IsValid()); + this->PopFunctionBlockerBarrier(reportError); #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -1604,8 +1665,16 @@ void cmMakefile::PopFunctionScope(bool reportError) this->Internal->PopDefinitions(); } -void cmMakefile::PushMacroScope(const cmPolicies::PolicyMap& pm) +void cmMakefile::PushMacroScope(std::string const& fileName, + const cmPolicies::PolicyMap& pm) { + this->StateSnapshot = + this->GetState()->CreateMacroCallSnapshot( + this->StateSnapshot, + this->ContextStack.back()->Name, this->ContextStack.back()->Line, + fileName); + assert(this->StateSnapshot.IsValid()); + this->PushFunctionBlockerBarrier(); this->PushPolicy(true, pm); @@ -1617,6 +1686,9 @@ void cmMakefile::PopMacroScope(bool reportError) this->PopPolicyBarrier(reportError); this->PopPolicy(); + this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot); + assert(this->StateSnapshot.IsValid()); + this->PopFunctionBlockerBarrier(reportError); } @@ -1625,17 +1697,22 @@ bool cmMakefile::IsRootMakefile() const return !this->StateSnapshot.GetBuildsystemDirectoryParent().IsValid(); } -//---------------------------------------------------------------------------- -class cmMakefileCurrent +class cmMakefile::BuildsystemFileScope { - cmGlobalGenerator* GG; - cmMakefile* MF; - cmState::Snapshot Snapshot; public: - cmMakefileCurrent(cmMakefile* mf) - { + BuildsystemFileScope(cmMakefile* mf) + : Makefile(mf), ReportError(true) + { + std::string currentStart = + this->Makefile->StateSnapshot.GetCurrentSourceDirectory(); + currentStart += "/CMakeLists.txt"; + this->Makefile->StateSnapshot.SetListFile(currentStart); + this->Makefile->ListFileStack.push_back(currentStart); + this->Makefile->PushPolicyBarrier(); + this->Makefile->PushFunctionBlockerBarrier(); + this->GG = mf->GetGlobalGenerator(); - this->MF = this->GG->GetCurrentMakefile(); + this->CurrentMakefile = this->GG->GetCurrentMakefile(); this->Snapshot = this->GG->GetCMakeInstance()->GetCurrentSnapshot(); this->GG->GetCMakeInstance()->SetCurrentSnapshot( this->GG->GetCMakeInstance()->GetCurrentSnapshot()); @@ -1643,21 +1720,32 @@ public: #if defined(CMAKE_BUILD_WITH_CMAKE) this->GG->GetFileLockPool().PushFileScope(); #endif - } - ~cmMakefileCurrent() - { + } + + ~BuildsystemFileScope() + { + this->Makefile->PopFunctionBlockerBarrier(this->ReportError); + this->Makefile->PopPolicyBarrier(this->ReportError); #if defined(CMAKE_BUILD_WITH_CMAKE) this->GG->GetFileLockPool().PopFileScope(); #endif - this->GG->SetCurrentMakefile(this->MF); + this->GG->SetCurrentMakefile(this->CurrentMakefile); this->GG->GetCMakeInstance()->SetCurrentSnapshot(this->Snapshot); - } + } + + void Quiet() { this->ReportError = false; } +private: + cmMakefile* Makefile; + cmGlobalGenerator* GG; + cmMakefile* CurrentMakefile; + cmState::Snapshot Snapshot; + bool ReportError; }; //---------------------------------------------------------------------------- void cmMakefile::Configure() { - cmMakefileCurrent cmf(this); + BuildsystemFileScope scope(this); // make sure the CMakeFiles dir is there std::string filesDir = this->StateSnapshot.GetCurrentBinaryDirectory(); @@ -1667,7 +1755,22 @@ void cmMakefile::Configure() std::string currentStart = this->StateSnapshot.GetCurrentSourceDirectory(); currentStart += "/CMakeLists.txt"; assert(cmSystemTools::FileExists(currentStart.c_str(), true)); - this->ProcessBuildsystemFile(currentStart.c_str()); + this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart.c_str()); + + cmListFile listFile; + { + cmParseFileScope pfs(this); + if (!listFile.ParseFile(currentStart.c_str(), this->IsRootMakefile(), this)) + { + this->SetConfigured(); + return; + } + } + this->ReadListFile(listFile, currentStart); + if(cmSystemTools::GetFatalErrorOccured()) + { + scope.Quiet(); + } // at the end handle any old style subdirs std::vector<cmMakefile*> subdirs = this->UnConfiguredDirectories; @@ -1750,7 +1853,9 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, } cmState::Snapshot newSnapshot = this->GetState() - ->CreateBuildsystemDirectorySnapshot(this->StateSnapshot); + ->CreateBuildsystemDirectorySnapshot(this->StateSnapshot, + this->ContextStack.back()->Name, + this->ContextStack.back()->Line); // create a new local generator and set its parent cmLocalGenerator *lg2 = this->GetGlobalGenerator() @@ -1968,7 +2073,7 @@ void cmMakefile::LogUnused(const char* reason, { std::string path; cmListFileContext lfc; - if (!this->CallStack.empty()) + if (!this->ExecutionStatusStack.empty()) { lfc = this->GetExecutionContext(); path = lfc.FilePath; @@ -3332,11 +3437,12 @@ bool cmMakefile::IsLoopBlock() const std::string cmMakefile::GetExecutionFilePath() const { - if (this->CallStack.empty()) + if (this->ContextStack.empty()) { return std::string(); } - return this->CallStack.back().Context->FilePath; + assert(this->StateSnapshot.IsValid()); + return this->StateSnapshot.GetExecutionListFile(); } //---------------------------------------------------------------------------- @@ -3427,7 +3533,7 @@ bool cmMakefile::ExpandArguments( //---------------------------------------------------------------------------- void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb) { - if(!this->CallStack.empty()) + if(!this->ExecutionStatusStack.empty()) { // Record the context in which the blocker is created. fb->SetStartingContext(this->GetExecutionContext()); @@ -3460,11 +3566,13 @@ cmMakefile::RemoveFunctionBlocker(cmFunctionBlocker* fb, if(!(*pos)->ShouldRemove(lff, *this)) { cmListFileContext const& lfc = fb->GetStartingContext(); + cmListFileContext closingContext = + cmListFileContext::FromCommandContext(lff, lfc.FilePath); std::ostringstream e; e << "A logical block opening on the line\n" << " " << lfc << "\n" << "closes on the line\n" - << " " << lff << "\n" + << " " << closingContext << "\n" << "with mis-matching arguments."; this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); } @@ -3477,19 +3585,6 @@ cmMakefile::RemoveFunctionBlocker(cmFunctionBlocker* fb, return cmsys::auto_ptr<cmFunctionBlocker>(); } -//---------------------------------------------------------------------------- -cmMakefile::LexicalPushPop::LexicalPushPop(cmMakefile* mf): - Makefile(mf), ReportError(true) -{ - this->Makefile->PushFunctionBlockerBarrier(); -} - -//---------------------------------------------------------------------------- -cmMakefile::LexicalPushPop::~LexicalPushPop() -{ - this->Makefile->PopFunctionBlockerBarrier(this->ReportError); -} - const char* cmMakefile::GetHomeDirectory() const { return this->GetCMakeInstance()->GetHomeDirectory(); @@ -5461,10 +5556,11 @@ AddRequiredTargetCFeature(cmTarget *target, const std::string& feature) const cmMakefile::FunctionPushPop::FunctionPushPop(cmMakefile* mf, + const std::string& fileName, cmPolicies::PolicyMap const& pm) : Makefile(mf), ReportError(true) { - this->Makefile->PushFunctionScope(pm); + this->Makefile->PushFunctionScope(fileName, pm); } cmMakefile::FunctionPushPop::~FunctionPushPop() @@ -5474,10 +5570,11 @@ cmMakefile::FunctionPushPop::~FunctionPushPop() cmMakefile::MacroPushPop::MacroPushPop(cmMakefile* mf, + const std::string& fileName, const cmPolicies::PolicyMap& pm) : Makefile(mf), ReportError(true) { - this->Makefile->PushMacroScope(pm); + this->Makefile->PushMacroScope(fileName, pm); } cmMakefile::MacroPushPop::~MacroPushPop() @@ -5485,14 +5582,15 @@ cmMakefile::MacroPushPop::~MacroPushPop() this->Makefile->PopMacroScope(this->ReportError); } -cmMakefileCall::cmMakefileCall(cmMakefile* mf, const cmListFileContext& lfc, +cmMakefileCall::cmMakefileCall(cmMakefile* mf, const cmCommandContext& lfc, cmExecutionStatus& status): Makefile(mf) { - cmMakefile::CallStackEntry entry = {&lfc, &status}; - this->Makefile->CallStack.push_back(entry); + this->Makefile->ContextStack.push_back(&lfc); + this->Makefile->ExecutionStatusStack.push_back(&status); } cmMakefileCall::~cmMakefileCall() { - this->Makefile->CallStack.pop_back(); + this->Makefile->ExecutionStatusStack.pop_back(); + this->Makefile->ContextStack.pop_back(); } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 85f117b..82a2279 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -100,19 +100,6 @@ public: cmsys::auto_ptr<cmFunctionBlocker> RemoveFunctionBlocker(cmFunctionBlocker* fb, const cmListFileFunction& lff); - /** Push/pop a lexical (function blocker) barrier automatically. */ - class LexicalPushPop - { - public: - LexicalPushPop(cmMakefile* mf); - ~LexicalPushPop(); - void Quiet() { this->ReportError = false; } - private: - cmMakefile* Makefile; - bool ReportError; - }; - friend class LexicalPushPop; - /** * Try running cmake and building a file. This is used for dynalically * loaded commands, not as part of the usual build process. @@ -560,7 +547,7 @@ public: * Get the current context backtrace. */ cmListFileBacktrace GetBacktrace() const; - cmListFileBacktrace GetBacktrace(cmListFileContext const& lfc) const; + cmListFileBacktrace GetBacktrace(cmCommandContext const& lfc) const; cmListFileContext GetExecutionContext() const; /** @@ -733,7 +720,7 @@ public: class FunctionPushPop { public: - FunctionPushPop(cmMakefile* mf, + FunctionPushPop(cmMakefile* mf, std::string const& fileName, cmPolicies::PolicyMap const& pm); ~FunctionPushPop(); @@ -746,8 +733,8 @@ public: class MacroPushPop { public: - MacroPushPop(cmMakefile* mf, - cmPolicies::PolicyMap const& pm); + MacroPushPop(cmMakefile* mf, std::string const& fileName, + cmPolicies::PolicyMap const& pm); ~MacroPushPop(); void Quiet() { this->ReportError = false; } @@ -756,9 +743,11 @@ public: bool ReportError; }; - void PushFunctionScope(cmPolicies::PolicyMap const& pm); + void PushFunctionScope(std::string const& fileName, + cmPolicies::PolicyMap const& pm); void PopFunctionScope(bool reportError); - void PushMacroScope(cmPolicies::PolicyMap const& pm); + void PushMacroScope(std::string const& fileName, + cmPolicies::PolicyMap const& pm); void PopMacroScope(bool reportError); void PushScope(); void PopScope(); @@ -838,6 +827,8 @@ public: std::string GetExecutionFilePath() const; + void EnforceDirectoryLevelRules() const; + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const std::string& name, cmTarget& target); @@ -946,15 +937,10 @@ private: // stack of list files being read std::vector<std::string> ListFileStack; - // stack of commands being invoked. - struct CallStackEntry - { - cmListFileContext const* Context; - cmExecutionStatus* Status; - }; - typedef std::vector<CallStackEntry> CallStackType; - CallStackType CallStack; + std::vector<cmCommandContext const*> ContextStack; + std::vector<cmExecutionStatus*> ExecutionStatusStack; friend class cmMakefileCall; + friend class cmParseFileScope; std::vector<cmTarget*> ImportedTargetsOwned; TargetMap ImportedTargets; @@ -968,6 +954,10 @@ private: friend class cmCMakePolicyCommand; class IncludeScope; friend class IncludeScope; + class ListFileScope; + friend class ListFileScope; + class BuildsystemFileScope; + friend class BuildsystemFileScope; // stack of policy settings struct PolicyStackEntry: public cmPolicies::PolicyMap @@ -984,9 +974,6 @@ private: cmPolicies::PolicyStatus GetPolicyStatusInternal(cmPolicies::PolicyID id) const; - // Enforce rules about CMakeLists.txt files. - void EnforceDirectoryLevelRules() const; - // CMP0053 == old cmake::MessageType ExpandVariablesInStringOld( std::string& errorstr, @@ -1068,7 +1055,7 @@ class cmMakefileCall { public: cmMakefileCall(cmMakefile* mf, - cmListFileContext const& lfc, + cmCommandContext const& lfc, cmExecutionStatus& status); ~cmMakefileCall(); private: diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 58500cc..d918f65 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -20,10 +20,14 @@ struct cmState::SnapshotDataType { + cmState::PositionType CallStackParent; cmState::PositionType DirectoryParent; cmState::SnapshotType SnapshotType; + cmLinkedTree<std::string>::iterator ExecutionListFile; cmLinkedTree<cmState::BuildsystemDirectoryStateType>::iterator BuildSystemDirectory; + std::string EntryPointCommand; + long EntryPointLine; }; struct cmState::BuildsystemDirectoryStateType @@ -226,6 +230,7 @@ cmState::Snapshot cmState::Reset() this->BuildsystemDirectory.Truncate(); PositionType pos = this->SnapshotData.Truncate(); + this->ExecutionListFiles.Truncate(); this->DefineProperty ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, @@ -682,22 +687,113 @@ cmState::Snapshot cmState::CreateBaseSnapshot() pos->SnapshotType = BuildsystemDirectoryType; pos->BuildSystemDirectory = this->BuildsystemDirectory.Extend(this->BuildsystemDirectory.Root()); + pos->ExecutionListFile = + this->ExecutionListFiles.Extend(this->ExecutionListFiles.Root()); return cmState::Snapshot(this, pos); } cmState::Snapshot -cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot) +cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine) { assert(originSnapshot.IsValid()); PositionType pos = this->SnapshotData.Extend(originSnapshot.Position); + pos->CallStackParent = originSnapshot.Position; + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; pos->DirectoryParent = originSnapshot.Position; pos->SnapshotType = BuildsystemDirectoryType; pos->BuildSystemDirectory = this->BuildsystemDirectory.Extend( originSnapshot.Position->BuildSystemDirectory); + pos->ExecutionListFile = + this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile); return cmState::Snapshot(this, pos); } +cmState::Snapshot +cmState::CreateFunctionCallSnapshot(cmState::Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->CallStackParent = originSnapshot.Position; + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = FunctionCallType; + pos->ExecutionListFile = this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile, fileName); + return cmState::Snapshot(this, pos); +} + + +cmState::Snapshot +cmState::CreateMacroCallSnapshot(cmState::Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->CallStackParent = originSnapshot.Position; + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = MacroCallType; + pos->ExecutionListFile = this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile, fileName); + return cmState::Snapshot(this, pos); +} + +cmState::Snapshot +cmState::CreateCallStackSnapshot(cmState::Snapshot originSnapshot, + const std::string& entryPointCommand, + long entryPointLine, + const std::string& fileName) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->CallStackParent = originSnapshot.Position; + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = CallStackType; + pos->ExecutionListFile = this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile, fileName); + return cmState::Snapshot(this, pos); +} + +cmState::Snapshot +cmState::CreateInlineListFileSnapshot(cmState::Snapshot originSnapshot, + const std::string& entryPointCommand, + long entryPointLine, + const std::string& fileName) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->CallStackParent = originSnapshot.Position; + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = InlineListFileType; + pos->ExecutionListFile = this->ExecutionListFiles.Extend( + originSnapshot.Position->ExecutionListFile, fileName); + return cmState::Snapshot(this, pos); +} + +cmState::Snapshot cmState::Pop(cmState::Snapshot originSnapshot) +{ + PositionType pos = originSnapshot.Position; + PositionType prevPos = pos; + ++prevPos; + if (prevPos == this->SnapshotData.Root()) + { + return Snapshot(this, prevPos); + } + return Snapshot(this, originSnapshot.Position->CallStackParent); +} + cmState::Snapshot::Snapshot(cmState* state, PositionType position) : State(state), Position(position) @@ -742,6 +838,11 @@ void cmState::Snapshot::SetCurrentBinaryDirectory(std::string const& dir) this->ComputeRelativePathTopBinary(); } +void cmState::Snapshot::SetListFile(const std::string& listfile) +{ + *this->Position->ExecutionListFile = listfile; +} + std::vector<std::string> const& cmState::Snapshot::GetCurrentSourceDirectoryComponents() const { @@ -776,6 +877,21 @@ void cmState::Snapshot::SetRelativePathTopBinary(const char* dir) this->Position->BuildSystemDirectory->RelativePathTopBinary = dir; } +std::string cmState::Snapshot::GetExecutionListFile() const +{ + return *this->Position->ExecutionListFile; +} + +std::string cmState::Snapshot::GetEntryPointCommand() const +{ + return this->Position->EntryPointCommand; +} + +long cmState::Snapshot::GetEntryPointLine() const +{ + return this->Position->EntryPointLine; +} + bool cmState::Snapshot::IsValid() const { return this->State && this->Position.IsValid() @@ -799,6 +915,28 @@ cmState::Snapshot cmState::Snapshot::GetBuildsystemDirectoryParent() const return snapshot; } +cmState::Snapshot cmState::Snapshot::GetCallStackParent() const +{ + assert(this->State); + assert(this->Position != this->State->SnapshotData.Root()); + + Snapshot snapshot; + if (this->Position->SnapshotType == cmState::BuildsystemDirectoryType) + { + return snapshot; + } + + PositionType parentPos = this->Position; + ++parentPos; + if (parentPos == this->State->SnapshotData.Root()) + { + return snapshot; + } + + snapshot = Snapshot(this->State, parentPos); + return snapshot; +} + cmState* cmState::Snapshot::GetState() const { return this->State; diff --git a/Source/cmState.h b/Source/cmState.h index 9c7574f..473a194 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -31,7 +31,11 @@ public: enum SnapshotType { - BuildsystemDirectoryType + BuildsystemDirectoryType, + FunctionCallType, + MacroCallType, + CallStackType, + InlineListFileType }; class Snapshot { @@ -43,6 +47,8 @@ public: const char* GetCurrentBinaryDirectory() const; void SetCurrentBinaryDirectory(std::string const& dir); + void SetListFile(std::string const& listfile); + std::vector<std::string> const& GetCurrentSourceDirectoryComponents() const; std::vector<std::string> const& @@ -53,8 +59,13 @@ public: void SetRelativePathTopSource(const char* dir); void SetRelativePathTopBinary(const char* dir); + std::string GetExecutionListFile() const; + std::string GetEntryPointCommand() const; + long GetEntryPointLine() const; + bool IsValid() const; Snapshot GetBuildsystemDirectoryParent() const; + Snapshot GetCallStackParent() const; cmState* GetState() const; @@ -69,7 +80,27 @@ public: }; Snapshot CreateBaseSnapshot(); - Snapshot CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot); + Snapshot + CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine); + Snapshot CreateFunctionCallSnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName); + Snapshot CreateMacroCallSnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName); + Snapshot CreateCallStackSnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine, + std::string const& fileName); + Snapshot CreateInlineListFileSnapshot(Snapshot originSnapshot, + const std::string& entryPointCommand, + long entryPointLine, + std::string const& fileName); + Snapshot Pop(Snapshot originSnapshot); enum CacheEntryType{ BOOL=0, PATH, FILEPATH, STRING, INTERNAL,STATIC, UNINITIALIZED }; @@ -175,6 +206,8 @@ private: struct BuildsystemDirectoryStateType; cmLinkedTree<BuildsystemDirectoryStateType> BuildsystemDirectory; + cmLinkedTree<std::string> ExecutionListFiles; + cmLinkedTree<SnapshotDataType> SnapshotData; std::vector<std::string> SourceDirectoryComponents; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index e2adabe..7230a64 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2955,3 +2955,12 @@ bool cmSystemTools::StringToLong(const char* str, long* value) *value = strtol(str, &endp, 10); return (*endp == '\0') && (endp != str) && (errno == 0); } + +//---------------------------------------------------------------------------- +bool cmSystemTools::StringToULong(const char* str, unsigned long* value) +{ + errno = 0; + char *endp; + *value = strtoul(str, &endp, 10); + return (*endp == '\0') && (endp != str) && (errno == 0); +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 6feb6c5..8ebb4e3 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -469,6 +469,7 @@ public: /** Convert string to long. Expected that the whole string is an integer */ static bool StringToLong(const char* str, long* value); + static bool StringToULong(const char* str, unsigned long* value); #ifdef _WIN32 struct WindowsFileRetry diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 8448431..d309927 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1222,7 +1222,8 @@ static std::string targetNameGenex(const std::string& lib) } //---------------------------------------------------------------------------- -bool cmTarget::PushTLLCommandTrace(TLLSignature signature) +bool cmTarget::PushTLLCommandTrace(TLLSignature signature, + cmListFileContext const& lfc) { bool ret = true; if (!this->TLLCommands.empty()) @@ -1232,7 +1233,6 @@ bool cmTarget::PushTLLCommandTrace(TLLSignature signature) ret = false; } } - cmListFileContext lfc = this->Makefile->GetExecutionContext(); if (this->TLLCommands.empty() || this->TLLCommands.back().second != lfc) { this->TLLCommands.push_back(std::make_pair(signature, lfc)); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 6916bd3..1920312 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -207,7 +207,8 @@ public: KeywordTLLSignature, PlainTLLSignature }; - bool PushTLLCommandTrace(TLLSignature signature); + bool PushTLLCommandTrace(TLLSignature signature, + cmListFileContext const& lfc); void GetTllSignatureTraces(std::ostringstream &s, TLLSignature sig) const; void MergeLinkLibraries( cmMakefile& mf, const std::string& selfname, diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h index 1feb072..c5059ee 100644 --- a/Source/cmTargetDepend.h +++ b/Source/cmTargetDepend.h @@ -14,23 +14,24 @@ #include "cmStandardIncludes.h" -class cmTarget; +class cmGeneratorTarget; /** One edge in the global target dependency graph. It may be marked as a 'link' or 'util' edge or both. */ class cmTargetDepend { - cmTarget const* Target; + cmGeneratorTarget const* Target; // The set order depends only on the Target, so we use // mutable members to acheive a map with set syntax. mutable bool Link; mutable bool Util; public: - cmTargetDepend(cmTarget const* t): Target(t), Link(false), Util(false) {} - operator cmTarget const*() const { return this->Target; } - cmTarget const* operator->() const { return this->Target; } - cmTarget const& operator*() const { return *this->Target; } + cmTargetDepend(cmGeneratorTarget const* t) + : Target(t), Link(false), Util(false) {} + operator cmGeneratorTarget const*() const { return this->Target; } + cmGeneratorTarget const* operator->() const { return this->Target; } + cmGeneratorTarget const& operator*() const { return *this->Target; } friend bool operator < (cmTargetDepend const& l, cmTargetDepend const& r) { return l.Target < r.Target; } void SetType(bool strong) const diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index df37d66..b57b921 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -368,7 +368,8 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, || this->CurrentProcessingState == ProcessingKeywordPublicInterface || this->CurrentProcessingState == ProcessingKeywordLinkInterface) ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature; - if (!this->Target->PushTLLCommandTrace(sig)) + if (!this->Target->PushTLLCommandTrace( + sig, this->Makefile->GetExecutionContext())) { std::ostringstream e; const char *modal = 0; diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index 6521c04..98a397c 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -63,7 +63,6 @@ static void cmVariableWatchCommandVariableAccessed( cmListFileArgument(stack, cmListFileArgument::Quoted, 9999)); newLFF.Name = data->Command; - newLFF.FilePath = "unknown"; newLFF.Line = 9999; cmExecutionStatus status; if(!makefile->ExecuteCommand(newLFF,status)) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 57ec212..a2f9bca 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2686,7 +2686,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent( void cmVisualStudio10TargetGenerator::WriteProjectReferences() { cmGlobalGenerator::TargetDependSet const& unordered - = this->GlobalGenerator->GetTargetDirectDepends(*this->Target); + = this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget); typedef cmGlobalVisualStudioGenerator::OrderedTargetDependSet OrderedTargetDependSet; OrderedTargetDependSet depends(unordered); @@ -2694,7 +2694,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() for( OrderedTargetDependSet::const_iterator i = depends.begin(); i != depends.end(); ++i) { - cmTarget const* dt = *i; + cmTarget const* dt = (*i)->Target; if(dt->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; diff --git a/Source/ctest.cxx b/Source/ctest.cxx index e784759..afcbd61 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -98,6 +98,7 @@ static const char * cmDocumentationOptions[][2] = {"--test-command", "The test to run with the --build-and-test option."}, {"--test-timeout", "The time limit in seconds, internal use only."}, + {"--test-load", "CPU load threshold for starting new parallel tests."}, {"--tomorrow-tag", "Nightly or experimental starts with next day tag."}, {"--ctest-config", "The configuration file used to initialize CTest state " "when submitting dashboards."}, diff --git a/Source/kwsys/CONTRIBUTING.rst b/Source/kwsys/CONTRIBUTING.rst index e097b76..960eea4 100644 --- a/Source/kwsys/CONTRIBUTING.rst +++ b/Source/kwsys/CONTRIBUTING.rst @@ -29,7 +29,7 @@ License We do not require any formal copyright assignment or contributor license agreement. Any contributions intentionally sent upstream are presumed -to be offerred under terms of the OSI-approved BSD 3-clause License. +to be offered under terms of the OSI-approved BSD 3-clause License. See `Copyright.txt`_ for details. .. _`Copyright.txt`: Copyright.txt diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt index 8700c94..753ce27 100644 --- a/Tests/Fortran/CMakeLists.txt +++ b/Tests/Fortran/CMakeLists.txt @@ -168,7 +168,7 @@ if(CMAKE_Fortran_COMPILER_SUPPORTS_F90) add_definitions(-DFOO -DBAR=1) include_directories(${testf_SOURCE_DIR}/include) - add_executable(test_preprocess test_preprocess.F90) + add_executable(test_preprocess test_preprocess.F90 test_preprocess_module.F90) set(TEST_MODULE_DEPENDS 1) endif() diff --git a/Tests/Fortran/test_preprocess.F90 b/Tests/Fortran/test_preprocess.F90 index e4f1fbe..3a09976 100644 --- a/Tests/Fortran/test_preprocess.F90 +++ b/Tests/Fortran/test_preprocess.F90 @@ -46,6 +46,8 @@ PROGRAM PPTEST #endif ! 0 ; <empty> +USE PPAvailable + #include "test_preprocess.h" END PROGRAM diff --git a/Tests/Fortran/test_preprocess_module.F90 b/Tests/Fortran/test_preprocess_module.F90 new file mode 100644 index 0000000..5849b62 --- /dev/null +++ b/Tests/Fortran/test_preprocess_module.F90 @@ -0,0 +1,5 @@ +#ifdef FOO +MODULE PPAvailable +! no conent +END MODULE +#endif diff --git a/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt b/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt new file mode 100644 index 0000000..7fe04eb --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt @@ -0,0 +1,7 @@ +100% tests passed, 0 tests failed out of 4 ++ ++Label Time Summary: ++'bar' = +[0-9.]+ sec \(3 tests\) ++'foo' = +[0-9.]+ sec \(1 test\) ++ +Total Test time \(real\) = +[0-9.]+ sec diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake index a3ce139..dfc1e33 100644 --- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -1,4 +1,5 @@ include(RunCMake) +set(RunCMake_TEST_TIMEOUT 60) unset(ENV{CTEST_PARALLEL_LEVEL}) unset(ENV{CTEST_OUTPUT_ON_FAILURE}) @@ -52,3 +53,58 @@ add_test(MergeOutput \"${CMAKE_COMMAND}\" -P \"${RunCMake_SOURCE_DIR}/MergeOutpu run_cmake_command(MergeOutput ${CMAKE_CTEST_COMMAND} -V) endfunction() run_MergeOutput() + +function(run_LabelCount) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LabelCount) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" " +add_test(test1 \"${CMAKE_COMMAND}\" -E echo \"test1\") +set_tests_properties(test1 PROPERTIES LABELS 'bar') + +add_test(test2 \"${CMAKE_COMMAND}\" -E echo \"test2\") +set_tests_properties(test2 PROPERTIES LABELS 'bar') + +add_test(test3 \"${CMAKE_COMMAND}\" -E echo \"test3\") +set_tests_properties(test3 PROPERTIES LABELS 'foo') + +add_test(test4 \"${CMAKE_COMMAND}\" -E echo \"test4\") +set_tests_properties(test4 PROPERTIES LABELS 'bar') +") + + run_cmake_command(LabelCount ${CMAKE_CTEST_COMMAND} -V) +endfunction() + +run_LabelCount() + +function(run_TestLoad name load) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestLoad) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" " + add_test(TestLoad1 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\") + add_test(TestLoad2 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\") +") + run_cmake_command(${name} ${CMAKE_CTEST_COMMAND} -j2 --test-load ${load} --test-timeout 5) +endfunction() + +# Tests for the --test-load feature of ctest +# +# Spoof a load average value to make these tests more reliable. +set(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING} 5) + +# Verify that new tests are not started when the load average exceeds +# our threshold. +run_TestLoad(test-load-fail 2) + +# Verify that warning message is displayed but tests still start when +# an invalid argument is given. +run_TestLoad(test-load-invalid 'two') + +# Verify that new tests are started when the load average falls below +# our threshold. +run_TestLoad(test-load-pass 10) + +unset(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING}) diff --git a/Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt b/Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt new file mode 100644 index 0000000..eafba1c --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt @@ -0,0 +1 @@ +No tests were found!!! diff --git a/Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt new file mode 100644 index 0000000..153da09 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt @@ -0,0 +1,2 @@ +^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad +\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 2, Smallest test TestLoad[1-2] requires 1\*\*\*\*\* diff --git a/Tests/RunCMake/CTestCommandLine/test-load-invalid-stderr.txt b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stderr.txt new file mode 100644 index 0000000..caab3b9 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stderr.txt @@ -0,0 +1 @@ +Invalid value for 'Test Load' : 'two' diff --git a/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt new file mode 100644 index 0000000..7ee3dae --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt @@ -0,0 +1,7 @@ +^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad + Start 1: TestLoad1 + Start 2: TestLoad2 +1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec +2/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 2 diff --git a/Tests/RunCMake/CTestCommandLine/test-load-pass-stderr.txt b/Tests/RunCMake/CTestCommandLine/test-load-pass-stderr.txt new file mode 100644 index 0000000..10f3293 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test-load-pass-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt new file mode 100644 index 0000000..7ee3dae --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt @@ -0,0 +1,7 @@ +^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad + Start 1: TestLoad1 + Start 2: TestLoad2 +1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec +2/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 2 diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake index e038409..47d6129 100644 --- a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake @@ -11,3 +11,4 @@ run_cmake(Add_StepDependencies) run_cmake(Add_StepDependencies_iface) run_cmake(Add_StepDependencies_iface_step) run_cmake(Add_StepDependencies_no_target) +run_cmake(UsesTerminal) diff --git a/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake b/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake new file mode 100644 index 0000000..201d822 --- /dev/null +++ b/Tests/RunCMake/ExternalProject/UsesTerminal-check.cmake @@ -0,0 +1,97 @@ +cmake_minimum_required(VERSION 3.3) + +# If we are using the Ninja generator, we can check and verify that the +# USES_TERMINAL option actually works by examining the Ninja build file. +# This is the only way, since CMake doesn't offer a way to examine the +# options on a custom command after it has been added. Furthermore, +# there isn't an easy way to test for this by actually running Ninja. +# +# Other generators don't currently support USES_TERMINAL at this time. +# This file can be improved to support them if they do. Until then, we +# simply assume success for new generator types. +# +# For Ninja, there is a complication. If the Ninja generator detects a +# version of Ninja < 1.5, it won't actually emit the console pool command, +# because those Ninja versions don't yet support the console pool. In +# that case, we also have to assume success. + +# Check Ninja build output to verify whether or not a target step is in the +# console pool. +macro(CheckNinjaStep _target _step _require) + if("${_build}" MATCHES +" DESC = Performing ${_step} step for '${_target}' + pool = console" + ) + if(NOT ${_require}) + set(RunCMake_TEST_FAILED "${_target} ${_step} step is in console pool") + return() + endif() + else() + if(${_require}) + set(RunCMake_TEST_FAILED "${_target} ${_step} step not in console pool") + return() + endif() + endif() +endmacro() + +# Check Ninja build output to verify whether each target step is in the +# console pool. +macro(CheckNinjaTarget _target + _download _update _configure _build _test _install + ) + CheckNinjaStep(${_target} download ${_download}) + CheckNinjaStep(${_target} update ${_update}) + CheckNinjaStep(${_target} configure ${_configure}) + CheckNinjaStep(${_target} build ${_build}) + CheckNinjaStep(${_target} test ${_test}) + CheckNinjaStep(${_target} install ${_install}) +endmacro() + +# Load build/make file, depending on generator +if(RunCMake_GENERATOR STREQUAL Ninja) + # Check the Ninja version. If < 1.5, console pool isn't supported and + # so the generator would not emit console pool usage. That would cause + # this test to fail. + execute_process(COMMAND ${RunCMake_MAKE_PROGRAM} --version + RESULT_VARIABLE _version_result + OUTPUT_VARIABLE _version + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(_version_result OR _version VERSION_EQUAL "0") + set(RunCMake_TEST_FAILED "Failed to get Ninja version") + return() + endif() + if(_version VERSION_LESS "1.5") + return() # console pool not supported on Ninja < 1.5 + endif() + + # Read the Ninja build file + set(_build_file "${RunCMake_TEST_BINARY_DIR}/build.ninja") + + if(NOT EXISTS "${_build_file}") + set(RunCMake_TEST_FAILED "Ninja build file not created") + return() + endif() + + file(READ "${_build_file}" _build) + + set(_target_check_macro CheckNinjaTarget) +elseif((RunCMake_GENERATOR STREQUAL "") OR NOT DEFINED RunCMake_GENERATOR) + # protection in case somebody renamed RunCMake_GENERATOR + set(RunCMake_TEST_FAILED "Unknown generator") + return() +else() + # We don't yet know how to test USES_TERMINAL on this generator. + return() +endif() + +# Actual tests: +CheckNinjaTarget(TerminalTest1 + true true true true true true ) +CheckNinjaTarget(TerminalTest2 + true false true false true false) +CheckNinjaTarget(TerminalTest3 + false true false true false true ) +CheckNinjaTarget(TerminalTest4 + false false false false false false) diff --git a/Tests/RunCMake/ExternalProject/UsesTerminal.cmake b/Tests/RunCMake/ExternalProject/UsesTerminal.cmake new file mode 100644 index 0000000..cd87403 --- /dev/null +++ b/Tests/RunCMake/ExternalProject/UsesTerminal.cmake @@ -0,0 +1,45 @@ +if(NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE Debug) +endif() +include(ExternalProject) + +# Test various combinations of USES_TERMINAL with ExternalProject_Add. + +macro(DoTerminalTest _target) + ExternalProject_Add(${_target} + DOWNLOAD_COMMAND "${CMAKE_COMMAND}" -E echo "download" + UPDATE_COMMAND "${CMAKE_COMMAND}" -E echo "update" + CONFIGURE_COMMAND "${CMAKE_COMMAND}" -E echo "configure" + BUILD_COMMAND "${CMAKE_COMMAND}" -E echo "build" + TEST_COMMAND "${CMAKE_COMMAND}" -E echo "test" + INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "install" + ${ARGN} + ) +endmacro() + +# USES_TERMINAL on all steps +DoTerminalTest(TerminalTest1 + USES_TERMINAL_DOWNLOAD 1 + USES_TERMINAL_UPDATE 1 + USES_TERMINAL_CONFIGURE 1 + USES_TERMINAL_BUILD 1 + USES_TERMINAL_TEST 1 + USES_TERMINAL_INSTALL 1 + ) + +# USES_TERMINAL on every other step, starting with download +DoTerminalTest(TerminalTest2 + USES_TERMINAL_DOWNLOAD 1 + USES_TERMINAL_CONFIGURE 1 + USES_TERMINAL_TEST 1 + ) + +# USES_TERMINAL on every other step, starting with update +DoTerminalTest(TerminalTest3 + USES_TERMINAL_UPDATE 1 + USES_TERMINAL_BUILD 1 + USES_TERMINAL_INSTALL 1 + ) + +# USES_TERMINAL on no step +DoTerminalTest(TerminalTest4) diff --git a/Tests/RunCMake/Languages/DetermineFail-result.txt b/Tests/RunCMake/Languages/DetermineFail-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Languages/DetermineFail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Languages/DetermineFail-stderr.txt b/Tests/RunCMake/Languages/DetermineFail-stderr.txt new file mode 100644 index 0000000..3b4743e --- /dev/null +++ b/Tests/RunCMake/Languages/DetermineFail-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at Modules/CMakeDetermineFailCompiler.cmake:[0-9]+ \(message\): + This language is not supported. +Call Stack \(most recent call first\): + DetermineFail.cmake:[0-9]+ \(enable_language\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/Languages/DetermineFail.cmake b/Tests/RunCMake/Languages/DetermineFail.cmake new file mode 100644 index 0000000..3c8d17d --- /dev/null +++ b/Tests/RunCMake/Languages/DetermineFail.cmake @@ -0,0 +1,2 @@ +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Modules) +enable_language(Fail) diff --git a/Tests/RunCMake/Languages/Modules/CMakeDetermineFailCompiler.cmake b/Tests/RunCMake/Languages/Modules/CMakeDetermineFailCompiler.cmake new file mode 100644 index 0000000..3b2d50a --- /dev/null +++ b/Tests/RunCMake/Languages/Modules/CMakeDetermineFailCompiler.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This language is not supported.") diff --git a/Tests/RunCMake/Languages/RunCMakeTest.cmake b/Tests/RunCMake/Languages/RunCMakeTest.cmake index 6517a81..732baae 100644 --- a/Tests/RunCMake/Languages/RunCMakeTest.cmake +++ b/Tests/RunCMake/Languages/RunCMakeTest.cmake @@ -4,3 +4,5 @@ run_cmake(NoLangSHARED) run_cmake(LINK_LANGUAGE-genex) run_cmake(link-libraries-TARGET_FILE-genex) run_cmake(link-libraries-TARGET_FILE-genex-ok) + +run_cmake(DetermineFail) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index 70c0d6c..46bc494 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -66,6 +66,11 @@ function(run_cmake test) else() set(actual_stderr_var actual_stderr) endif() + if(DEFINED RunCMake_TEST_TIMEOUT) + set(maybe_timeout TIMEOUT ${RunCMake_TEST_TIMEOUT}) + else() + set(maybe_timeout "") + endif() if(RunCMake_TEST_COMMAND) execute_process( COMMAND ${RunCMake_TEST_COMMAND} @@ -73,6 +78,7 @@ function(run_cmake test) OUTPUT_VARIABLE actual_stdout ERROR_VARIABLE ${actual_stderr_var} RESULT_VARIABLE actual_result + ${maybe_timeout} ) else() execute_process( @@ -87,6 +93,7 @@ function(run_cmake test) OUTPUT_VARIABLE actual_stdout ERROR_VARIABLE ${actual_stderr_var} RESULT_VARIABLE actual_result + ${maybe_timeout} ) endif() set(msg "") diff --git a/Tests/RunCMake/Syntax/BOM-UTF-16-BE-stderr.txt b/Tests/RunCMake/Syntax/BOM-UTF-16-BE-stderr.txt index b3f1e47..a845ffb 100644 --- a/Tests/RunCMake/Syntax/BOM-UTF-16-BE-stderr.txt +++ b/Tests/RunCMake/Syntax/BOM-UTF-16-BE-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BOM-UTF-16-BE.cmake: File .*/Tests/RunCMake/Syntax/BOM-UTF-16-BE.cmake starts with a Byte-Order-Mark that is not UTF-8. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/BOM-UTF-16-LE-stderr.txt b/Tests/RunCMake/Syntax/BOM-UTF-16-LE-stderr.txt index c08c902..cc4244b 100644 --- a/Tests/RunCMake/Syntax/BOM-UTF-16-LE-stderr.txt +++ b/Tests/RunCMake/Syntax/BOM-UTF-16-LE-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BOM-UTF-16-LE.cmake: File .*/Tests/RunCMake/Syntax/BOM-UTF-16-LE.cmake starts with a Byte-Order-Mark that is not UTF-8. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/BOM-UTF-32-BE-stderr.txt b/Tests/RunCMake/Syntax/BOM-UTF-32-BE-stderr.txt index 5dde4e3..5f851bf 100644 --- a/Tests/RunCMake/Syntax/BOM-UTF-32-BE-stderr.txt +++ b/Tests/RunCMake/Syntax/BOM-UTF-32-BE-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BOM-UTF-32-BE.cmake: File .*/Tests/RunCMake/Syntax/BOM-UTF-32-BE.cmake starts with a Byte-Order-Mark that is not UTF-8. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/BOM-UTF-32-LE-stderr.txt b/Tests/RunCMake/Syntax/BOM-UTF-32-LE-stderr.txt index eb054ec..d8fafd0 100644 --- a/Tests/RunCMake/Syntax/BOM-UTF-32-LE-stderr.txt +++ b/Tests/RunCMake/Syntax/BOM-UTF-32-LE-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BOM-UTF-32-LE.cmake: File .*/Tests/RunCMake/Syntax/BOM-UTF-32-LE.cmake starts with a Byte-Order-Mark that is not UTF-8. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/BracketNoSpace0-stderr.txt b/Tests/RunCMake/Syntax/BracketNoSpace0-stderr.txt index afd91f9..a288280 100644 --- a/Tests/RunCMake/Syntax/BracketNoSpace0-stderr.txt +++ b/Tests/RunCMake/Syntax/BracketNoSpace0-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BracketNoSpace0.cmake: Syntax Error in cmake code at .*/Tests/RunCMake/Syntax/BracketNoSpace0.cmake:1:27 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/BracketNoSpace1-stderr.txt b/Tests/RunCMake/Syntax/BracketNoSpace1-stderr.txt index 826e511..391e11b 100644 --- a/Tests/RunCMake/Syntax/BracketNoSpace1-stderr.txt +++ b/Tests/RunCMake/Syntax/BracketNoSpace1-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BracketNoSpace1.cmake: Syntax Error in cmake code at .*/Tests/RunCMake/Syntax/BracketNoSpace1.cmake:1:24 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/BracketNoSpace2-stderr.txt b/Tests/RunCMake/Syntax/BracketNoSpace2-stderr.txt index 23ecdcd..acaf7fe 100644 --- a/Tests/RunCMake/Syntax/BracketNoSpace2-stderr.txt +++ b/Tests/RunCMake/Syntax/BracketNoSpace2-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BracketNoSpace2.cmake: Syntax Error in cmake code at .*/Tests/RunCMake/Syntax/BracketNoSpace2.cmake:1:44 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/BracketNoSpace3-stderr.txt b/Tests/RunCMake/Syntax/BracketNoSpace3-stderr.txt index 906d6fc..f12b2e5 100644 --- a/Tests/RunCMake/Syntax/BracketNoSpace3-stderr.txt +++ b/Tests/RunCMake/Syntax/BracketNoSpace3-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BracketNoSpace3.cmake: Syntax Error in cmake code at .*/Tests/RunCMake/Syntax/BracketNoSpace3.cmake:1:45 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/BracketNoSpace4-stderr.txt b/Tests/RunCMake/Syntax/BracketNoSpace4-stderr.txt index a461e93..7157763 100644 --- a/Tests/RunCMake/Syntax/BracketNoSpace4-stderr.txt +++ b/Tests/RunCMake/Syntax/BracketNoSpace4-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BracketNoSpace4.cmake: Syntax Error in cmake code at .*/Tests/RunCMake/Syntax/BracketNoSpace4.cmake:1:44 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/BracketNoSpace5-stderr.txt b/Tests/RunCMake/Syntax/BracketNoSpace5-stderr.txt index ff8bf1c..c13969d 100644 --- a/Tests/RunCMake/Syntax/BracketNoSpace5-stderr.txt +++ b/Tests/RunCMake/Syntax/BracketNoSpace5-stderr.txt @@ -1,6 +1,8 @@ -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in BracketNoSpace5.cmake: Syntax Error in cmake code at .*/Tests/RunCMake/Syntax/BracketNoSpace5.cmake:1:45 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/ParenInENV-stderr.txt b/Tests/RunCMake/Syntax/ParenInENV-stderr.txt index 7ecfe11..37c5d6e 100644 --- a/Tests/RunCMake/Syntax/ParenInENV-stderr.txt +++ b/Tests/RunCMake/Syntax/ParenInENV-stderr.txt @@ -1,9 +1,11 @@ -CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): +CMake Warning \(dev\) in ParenInENV.cmake: Syntax Warning in cmake code at .*/Tests/RunCMake/Syntax/ParenInENV.cmake:2:21 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) This warning is for project developers. Use -Wno-dev to suppress it. CMake Error at ParenInENV.cmake:2 \(message\): diff --git a/Tests/RunCMake/Syntax/ParenNoSpace1-stderr.txt b/Tests/RunCMake/Syntax/ParenNoSpace1-stderr.txt index 64ef8b1..45b2e6a 100644 --- a/Tests/RunCMake/Syntax/ParenNoSpace1-stderr.txt +++ b/Tests/RunCMake/Syntax/ParenNoSpace1-stderr.txt @@ -1,22 +1,28 @@ -CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): +CMake Warning \(dev\) in ParenNoSpace1.cmake: Syntax Warning in cmake code at .*/Tests/RunCMake/Syntax/ParenNoSpace1.cmake:1:26 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) This warning is for project developers. Use -Wno-dev to suppress it. -CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): +CMake Warning \(dev\) in ParenNoSpace1.cmake: Syntax Warning in cmake code at .*/Tests/RunCMake/Syntax/ParenNoSpace1.cmake:2:26 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) This warning is for project developers. Use -Wno-dev to suppress it. -CMake Error at CMakeLists.txt:3 \(include\): +CMake Error in ParenNoSpace1.cmake: Syntax Error in cmake code at .*/Tests/RunCMake/Syntax/ParenNoSpace1.cmake:3:29 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt b/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt index 89c2d2a..a4ec6e7 100644 --- a/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt +++ b/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt @@ -1,17 +1,21 @@ -CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): +CMake Warning \(dev\) in StringNoSpace.cmake: Syntax Warning in cmake code at .*/Tests/RunCMake/Syntax/StringNoSpace.cmake:2:28 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) This warning is for project developers. Use -Wno-dev to suppress it. -CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): +CMake Warning \(dev\) in StringNoSpace.cmake: Syntax Warning in cmake code at .*/Tests/RunCMake/Syntax/StringNoSpace.cmake:2:31 Argument not separated from preceding token by whitespace. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) This warning is for project developers. Use -Wno-dev to suppress it. \[1 \${var} \\n 4\] diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadFail-result.txt b/Tests/RunCMake/ctest_test/CTestTestLoadFail-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_test/CTestTestLoadFail-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadFail-stderr.txt b/Tests/RunCMake/ctest_test/CTestTestLoadFail-stderr.txt new file mode 100644 index 0000000..eafba1c --- /dev/null +++ b/Tests/RunCMake/ctest_test/CTestTestLoadFail-stderr.txt @@ -0,0 +1 @@ +No tests were found!!! diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadFail-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadFail-stdout.txt new file mode 100644 index 0000000..e203c10 --- /dev/null +++ b/Tests/RunCMake/ctest_test/CTestTestLoadFail-stdout.txt @@ -0,0 +1,2 @@ +Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadFail-build +\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 4, Smallest test RunCMakeVersion requires 1\*\*\*\*\*$ diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stderr.txt b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stderr.txt new file mode 100644 index 0000000..7f2d7f6 --- /dev/null +++ b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stderr.txt @@ -0,0 +1 @@ +^Invalid value for 'CTEST_TEST_LOAD' : ERR2 diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt new file mode 100644 index 0000000..b54220c --- /dev/null +++ b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt @@ -0,0 +1,7 @@ +Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-build + Start 1: RunCMakeVersion +1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt new file mode 100644 index 0000000..c221eed --- /dev/null +++ b/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt @@ -0,0 +1,7 @@ +Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadPass-build + Start 1: RunCMakeVersion +1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index d906290..21d0447 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -1,6 +1,8 @@ include(RunCTest) +set(RunCMake_TEST_TIMEOUT 60) set(CASE_CTEST_TEST_ARGS "") +set(CASE_CTEST_TEST_LOAD "") function(run_ctest_test CASE_NAME) set(CASE_CTEST_TEST_ARGS "${ARGN}") @@ -8,3 +10,42 @@ function(run_ctest_test CASE_NAME) endfunction() run_ctest_test(TestQuiet QUIET) + +# Tests for the 'Test Load' feature of ctest +# +# Spoof a load average value to make these tests more reliable. +set(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING} 5) + +# Verify that new tests are started when the load average falls below +# our threshold. +run_ctest_test(TestLoadPass TEST_LOAD 6) + +# Verify that new tests are not started when the load average exceeds +# our threshold. +run_ctest_test(TestLoadFail TEST_LOAD 2) + +# Verify that when an invalid "TEST_LOAD" value is given, a warning +# message is displayed and the value is ignored. +run_ctest_test(TestLoadInvalid TEST_LOAD "ERR1") + +# Verify that new tests are started when the load average falls below +# our threshold. +set(CASE_CTEST_TEST_LOAD 7) +run_ctest_test(CTestTestLoadPass) + +# Verify that new tests are not started when the load average exceeds +# our threshold. +set(CASE_CTEST_TEST_LOAD 4) +run_ctest_test(CTestTestLoadFail) + +# Verify that when an invalid "CTEST_TEST_LOAD" value is given, +# a warning message is displayed and the value is ignored. +set(CASE_CTEST_TEST_LOAD "ERR2") +run_ctest_test(CTestTestLoadInvalid) + +# Verify that the "TEST_LOAD" value has higher precedence than +# the "CTEST_TEST_LOAD" value +set(CASE_CTEST_TEST_LOAD "ERR3") +run_ctest_test(TestLoadOrder TEST_LOAD "ERR4") + +unset(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING}) diff --git a/Tests/RunCMake/ctest_test/TestLoadFail-result.txt b/Tests/RunCMake/ctest_test/TestLoadFail-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestLoadFail-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_test/TestLoadFail-stderr.txt b/Tests/RunCMake/ctest_test/TestLoadFail-stderr.txt new file mode 100644 index 0000000..eafba1c --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestLoadFail-stderr.txt @@ -0,0 +1 @@ +No tests were found!!! diff --git a/Tests/RunCMake/ctest_test/TestLoadFail-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadFail-stdout.txt new file mode 100644 index 0000000..4d7ce48 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestLoadFail-stdout.txt @@ -0,0 +1,2 @@ +Test project .*/Tests/RunCMake/ctest_test/TestLoadFail-build +\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 2, Smallest test RunCMakeVersion requires 1\*\*\*\*\*$ diff --git a/Tests/RunCMake/ctest_test/TestLoadInvalid-stderr.txt b/Tests/RunCMake/ctest_test/TestLoadInvalid-stderr.txt new file mode 100644 index 0000000..40ddb3a --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestLoadInvalid-stderr.txt @@ -0,0 +1 @@ +^Invalid value for 'TEST_LOAD' : ERR1 diff --git a/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt new file mode 100644 index 0000000..c4fd35b --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt @@ -0,0 +1,7 @@ +Test project .*/Tests/RunCMake/ctest_test/TestLoadInvalid-build + Start 1: RunCMakeVersion +1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_test/TestLoadOrder-stderr.txt b/Tests/RunCMake/ctest_test/TestLoadOrder-stderr.txt new file mode 100644 index 0000000..1de730e --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestLoadOrder-stderr.txt @@ -0,0 +1 @@ +^Invalid value for 'TEST_LOAD' : ERR4 diff --git a/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt new file mode 100644 index 0000000..22da092 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt @@ -0,0 +1,7 @@ +Test project .*/Tests/RunCMake/ctest_test/TestLoadOrder-build + Start 1: RunCMakeVersion +1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt new file mode 100644 index 0000000..e5048f4 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt @@ -0,0 +1,7 @@ +Test project .*/Tests/RunCMake/ctest_test/TestLoadPass-build + Start 1: RunCMakeVersion +1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_test/test.cmake.in b/Tests/RunCMake/ctest_test/test.cmake.in index 1350abe..a8de6a3 100644 --- a/Tests/RunCMake/ctest_test/test.cmake.in +++ b/Tests/RunCMake/ctest_test/test.cmake.in @@ -8,6 +8,7 @@ set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@") set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@") set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") +set(CTEST_TEST_LOAD "@CASE_CTEST_TEST_LOAD@") set(ctest_test_args "@CASE_CTEST_TEST_ARGS@") ctest_start(Experimental) diff --git a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake index f97022e..533c6a1 100644 --- a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake @@ -6,3 +6,4 @@ run_cmake(CMP0023-WARN-2) run_cmake(CMP0023-NEW-2) run_cmake(MixedSignature) run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses) +run_cmake(SubDirTarget) diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-result.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/SubDirTarget-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-stderr.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget-stderr.txt new file mode 100644 index 0000000..5cd1f23 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/SubDirTarget-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at SubDirTarget.cmake:[0-9]+ \(target_link_libraries\): + Attempt to add link library "m" to target "subexe" which is not built in + this directory. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget.cmake b/Tests/RunCMake/target_link_libraries/SubDirTarget.cmake new file mode 100644 index 0000000..32431ce --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/SubDirTarget.cmake @@ -0,0 +1,3 @@ +enable_language(C) +add_subdirectory(SubDirTarget) +target_link_libraries(subexe m) diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget/CMakeLists.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget/CMakeLists.txt new file mode 100644 index 0000000..b0b2380 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/SubDirTarget/CMakeLists.txt @@ -0,0 +1 @@ +add_executable(subexe ../empty.c) diff --git a/Tests/RunCMake/target_link_libraries/empty.c b/Tests/RunCMake/target_link_libraries/empty.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/empty.c diff --git a/Tests/VSResource/CMakeLists.txt b/Tests/VSResource/CMakeLists.txt index 17eb041..3b9cfc3 100644 --- a/Tests/VSResource/CMakeLists.txt +++ b/Tests/VSResource/CMakeLists.txt @@ -46,7 +46,10 @@ else() include_directories(${CMAKE_CURRENT_BINARY_DIR}) endif() +add_library(ResourceLib STATIC lib.cpp lib.rc) + add_executable(VSResource main.cpp test.rc) +target_link_libraries(VSResource ResourceLib) set_property(TARGET VSResource PROPERTY VS_GLOBAL_CMakeTestVsGlobalVariable "test val") diff --git a/Tests/VSResource/lib.cpp b/Tests/VSResource/lib.cpp new file mode 100644 index 0000000..006e3e4 --- /dev/null +++ b/Tests/VSResource/lib.cpp @@ -0,0 +1 @@ +int lib() { return 0; } diff --git a/Tests/VSResource/lib.rc b/Tests/VSResource/lib.rc new file mode 100644 index 0000000..1ffade6 --- /dev/null +++ b/Tests/VSResource/lib.rc @@ -0,0 +1,4 @@ +STRINGTABLE +BEGIN + 1234 "5" +END diff --git a/Tests/VSResource/main.cpp b/Tests/VSResource/main.cpp index 7ee0c74..ccf700c 100644 --- a/Tests/VSResource/main.cpp +++ b/Tests/VSResource/main.cpp @@ -1,6 +1,8 @@ #include <windows.h> #include <stdio.h> +extern int lib(); + struct x { const char *txt; @@ -76,5 +78,5 @@ int main(int argc, char** argv) } } - return ret; + return ret + lib(); } |