Update upstream source from tag 'upstream/3.28.2'
Update to upstream version '3.28.2' with Debian dir 2a246ae1c682dc45722d8f1999b6d1bf8be1f951
This commit is contained in:
commit
b90b3c6c70
@ -5,11 +5,11 @@ Get a global property of the CMake instance.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
get_cmake_property(<var> <property>)
|
||||
get_cmake_property(<variable> <property>)
|
||||
|
||||
Gets a global property from the CMake instance. The value of
|
||||
the ``<property>`` is stored in the variable ``<var>``.
|
||||
If the property is not found, ``<var>`` will be set to ``NOTFOUND``.
|
||||
the ``<property>`` is stored in the specified ``<variable>``.
|
||||
If the property is not found, ``<variable>`` will be set to ``NOTFOUND``.
|
||||
See the :manual:`cmake-properties(7)` manual for available properties.
|
||||
|
||||
In addition to global properties, this command (for historical reasons)
|
||||
|
@ -9,14 +9,12 @@ Get a property for a source file.
|
||||
[DIRECTORY <dir> | TARGET_DIRECTORY <target>]
|
||||
<property>)
|
||||
|
||||
Gets a property from a source file. The value of the property is
|
||||
stored in the specified ``<variable>``. If the source property is not found,
|
||||
the behavior depends on whether it has been defined to be an ``INHERITED``
|
||||
property or not (see :command:`define_property`). Non-inherited properties
|
||||
will set ``variable`` to ``NOTFOUND``, whereas inherited properties will search
|
||||
the relevant parent scope as described for the :command:`define_property`
|
||||
command and if still unable to find the property, ``variable`` will be set to
|
||||
an empty string.
|
||||
Gets a property from a source file. The value of the property is stored in
|
||||
the specified ``<variable>``. If the ``<file>`` is not a source file, or the
|
||||
source property is not found, ``<variable>`` will be set to ``NOTFOUND``.
|
||||
If the source property was defined to be an ``INHERITED`` property (see
|
||||
:command:`define_property`), the search will include the relevant parent
|
||||
scopes, as described for the :command:`define_property` command.
|
||||
|
||||
By default, the source file's property will be read from the current source
|
||||
directory's scope.
|
||||
|
@ -5,16 +5,14 @@ Get a property from a target.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
get_target_property(<VAR> target property)
|
||||
get_target_property(<variable> <target> <property>)
|
||||
|
||||
Get a property from a target. The value of the property is stored in
|
||||
the variable ``<VAR>``. If the target property is not found, the behavior
|
||||
depends on whether it has been defined to be an ``INHERITED`` property
|
||||
or not (see :command:`define_property`). Non-inherited properties will
|
||||
set ``<VAR>`` to ``<VAR>-NOTFOUND``, whereas inherited properties will search
|
||||
the relevant parent scope as described for the :command:`define_property`
|
||||
command and if still unable to find the property, ``<VAR>`` will be set to
|
||||
an empty string.
|
||||
Get a property from a target. The value of the property is stored in the
|
||||
specified ``<variable>``. If the target property is not found, ``<variable>``
|
||||
will be set to ``<variable>-NOTFOUND``. If the target property was defined to
|
||||
be an ``INHERITED`` property (see :command:`define_property`), the search will
|
||||
include the relevant parent scopes, as described for the
|
||||
:command:`define_property` command.
|
||||
|
||||
Use :command:`set_target_properties` to set target property values.
|
||||
Properties are usually used to control how a target is built, but some
|
||||
|
@ -5,16 +5,14 @@ Get a property of the test.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
get_test_property(test property [DIRECTORY <dir>] VAR)
|
||||
get_test_property(<test> <property> [DIRECTORY <dir>] <variable>)
|
||||
|
||||
Get a property from the test. The value of the property is stored in
|
||||
the variable ``VAR``. If the test property is not found, the behavior
|
||||
depends on whether it has been defined to be an ``INHERITED`` property
|
||||
or not (see :command:`define_property`). Non-inherited properties will
|
||||
set ``VAR`` to "NOTFOUND", whereas inherited properties will search the
|
||||
relevant parent scope as described for the :command:`define_property`
|
||||
command and if still unable to find the property, ``VAR`` will be set to
|
||||
an empty string.
|
||||
the specified ``<variable>``. If the ``<test>`` is not defined, or the
|
||||
test property is not found, ``<variable>`` will be set to ``NOTFOUND``.
|
||||
If the test property was defined to be an ``INHERITED`` property (see
|
||||
:command:`define_property`), the search will include the relevant parent
|
||||
scopes, as described for the :command:`define_property` command.
|
||||
|
||||
For a list of standard properties you can type
|
||||
:option:`cmake --help-property-list`.
|
||||
|
@ -5,9 +5,10 @@ Set properties of the current directory and subdirectories.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set_directory_properties(PROPERTIES prop1 value1 [prop2 value2] ...)
|
||||
set_directory_properties(PROPERTIES <prop1> <value1> [<prop2> <value2>] ...)
|
||||
|
||||
Sets properties of the current directory and its subdirectories in key-value pairs.
|
||||
Sets properties of the current directory and its subdirectories in key-value
|
||||
pairs.
|
||||
|
||||
See also the :command:`set_property(DIRECTORY)` command.
|
||||
|
||||
|
@ -5,9 +5,9 @@ Targets can have properties that affect how they are built.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set_target_properties(target1 target2 ...
|
||||
PROPERTIES prop1 value1
|
||||
prop2 value2 ...)
|
||||
set_target_properties(<targets> ...
|
||||
PROPERTIES <prop1> <value1>
|
||||
[<prop2> <value2>] ...)
|
||||
|
||||
Sets properties on targets. The syntax for the command is to list all
|
||||
the targets you want to change, and then provide the values you want to
|
||||
|
@ -5,7 +5,10 @@ Set a property of the tests.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set_tests_properties(test1 [test2...] PROPERTIES prop1 value1 prop2 value2)
|
||||
set_tests_properties(<tests>...
|
||||
[DIRECTORY <dir>]
|
||||
PROPERTIES <prop1> <value1>
|
||||
[<prop2> <value2>]...)
|
||||
|
||||
Sets a property for the tests. If the test is not found, CMake
|
||||
will report an error.
|
||||
|
@ -22,7 +22,7 @@ Synopsis
|
||||
string(`JOIN`_ <glue> <out-var> [<input>...])
|
||||
string(`TOLOWER`_ <string> <out-var>)
|
||||
string(`TOUPPER`_ <string> <out-var>)
|
||||
string(`LENGTH`_ <string> <out-var>)
|
||||
string(`LENGTH <LENGTH_>`_ <string> <out-var>)
|
||||
string(`SUBSTRING`_ <string> <begin> <length> <out-var>)
|
||||
string(`STRIP`_ <string> <out-var>)
|
||||
string(`GENEX_STRIP`_ <string> <out-var>)
|
||||
|
@ -30,6 +30,10 @@ following queries. The first query that provides a yes/no answer is used.
|
||||
- Otherwise, the source file will be scanned if the compiler and generator
|
||||
support scanning. See policy :policy:`CMP0155`.
|
||||
|
||||
Note that any scanned source will be excluded from any unity build (see
|
||||
:prop_tgt:`UNITY_BUILD`) because module-related statements can only happen at
|
||||
one place within a C++ translation unit.
|
||||
|
||||
Compiler Support
|
||||
================
|
||||
|
||||
|
@ -224,7 +224,7 @@ For example::
|
||||
They interpret the opening bracket as the start of an
|
||||
`Unquoted Argument`_.
|
||||
|
||||
.. _`Lua`: http://www.lua.org/
|
||||
.. _`Lua`: https://www.lua.org/
|
||||
|
||||
.. _`Quoted Argument`:
|
||||
|
||||
|
@ -583,7 +583,7 @@ generator is recommended. The :generator:`Unix Makefiles` or
|
||||
:generator:`Ninja` generators can also be used, but they require the
|
||||
project to handle more areas like target CPU selection and code signing.
|
||||
|
||||
Any of the three systems can be targeted by setting the
|
||||
Any of the Apple device platforms can be targeted by setting the
|
||||
:variable:`CMAKE_SYSTEM_NAME` variable to a value from the table below.
|
||||
By default, the latest Device SDK is chosen. As for all Apple platforms,
|
||||
a different SDK (e.g. a simulator) can be selected by setting the
|
||||
@ -611,9 +611,11 @@ Variable :variable:`CMAKE_OSX_ARCHITECTURES` can be used to set architectures
|
||||
for both device and simulator. Variable :variable:`CMAKE_OSX_DEPLOYMENT_TARGET`
|
||||
can be used to set an iOS/tvOS/visionOS/watchOS deployment target.
|
||||
|
||||
Next configuration will install fat 5 architectures iOS library
|
||||
and add the ``-miphoneos-version-min=9.3``/``-mios-simulator-version-min=9.3``
|
||||
flags to the compiler:
|
||||
The next example installs five architectures in a universal binary for an iOS
|
||||
library. It adds the relevant ``-miphoneos-version-min=9.3`` or
|
||||
``-mios-simulator-version-min=9.3`` compiler flag where appropriate.
|
||||
Note that the :variable:`CMAKE_IOS_INSTALL_COMBINED` variable used in the
|
||||
example is now deprecated, so this approach is no longer recommended.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
|
@ -1592,17 +1592,20 @@ that running several of these tests at once does not exhaust the GPU's memory
|
||||
pool.
|
||||
|
||||
Please note that CTest has no concept of what a GPU is or how much memory it
|
||||
has, nor does it have any way of communicating with a GPU to retrieve this
|
||||
information or perform any memory management. CTest simply keeps track of a
|
||||
list of abstract resource types, each of which has a certain number of slots
|
||||
available for tests to use. Each test specifies the number of slots that it
|
||||
requires from a certain resource, and CTest then schedules them in a way that
|
||||
prevents the total number of slots in use from exceeding the listed capacity.
|
||||
When a test is executed, and slots from a resource are allocated to that test,
|
||||
tests may assume that they have exclusive use of those slots for the duration
|
||||
of the test's process.
|
||||
has. It does not have any way of communicating with a GPU to retrieve this
|
||||
information or perform any memory management, although the project can define
|
||||
a test that provides details about the test machine (see
|
||||
:ref:`ctest-resource-dynamically-generated-spec-file`).
|
||||
|
||||
The CTest resource allocation feature consists of two inputs:
|
||||
CTest keeps track of a list of abstract resource types, each of which has a
|
||||
certain number of slots available for tests to use. Each test specifies the
|
||||
number of slots that it requires from a certain resource, and CTest then
|
||||
schedules them in a way that prevents the total number of slots in use from
|
||||
exceeding the listed capacity. When a test is executed, and slots from a
|
||||
resource are allocated to that test, tests may assume that they have exclusive
|
||||
use of those slots for the duration of the test's process.
|
||||
|
||||
The CTest resource allocation feature consists of at least two inputs:
|
||||
|
||||
* The :ref:`resource specification file <ctest-resource-specification-file>`,
|
||||
described below, which describes the resources available on the system.
|
||||
@ -1643,15 +1646,20 @@ properties to indicate a skipped test.
|
||||
Resource Specification File
|
||||
---------------------------
|
||||
|
||||
The resource specification file is a JSON file which is passed to CTest, either
|
||||
on the command line as :option:`ctest --resource-spec-file`, or as the
|
||||
``RESOURCE_SPEC_FILE`` argument of :command:`ctest_test`. If a dashboard script
|
||||
is used and ``RESOURCE_SPEC_FILE`` is not specified, the value of
|
||||
:variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script is used instead.
|
||||
If :option:`--resource-spec-file <ctest --resource-spec-file>`, ``RESOURCE_SPEC_FILE``,
|
||||
and :variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script are not specified,
|
||||
the value of :variable:`CTEST_RESOURCE_SPEC_FILE` in the CMake build is used
|
||||
instead. If none of these are specified, no resource spec file is used.
|
||||
The resource specification file is a JSON file which is passed to CTest in one
|
||||
of a number of ways. It can be specified on the command line with the
|
||||
:option:`ctest --resource-spec-file` option, it can be given using the
|
||||
``RESOURCE_SPEC_FILE`` argument of :command:`ctest_test`, or it can be
|
||||
generated dynamically as part of test execution (see
|
||||
:ref:`ctest-resource-dynamically-generated-spec-file`).
|
||||
|
||||
If a dashboard script is used and ``RESOURCE_SPEC_FILE`` is not specified, the
|
||||
value of :variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script is used
|
||||
instead. If :option:`--resource-spec-file <ctest --resource-spec-file>`,
|
||||
``RESOURCE_SPEC_FILE``, and :variable:`CTEST_RESOURCE_SPEC_FILE` in the
|
||||
dashboard script are not specified, the value of
|
||||
:variable:`CTEST_RESOURCE_SPEC_FILE` in the CMake build is used instead.
|
||||
If none of these are specified, no resource spec file is used.
|
||||
|
||||
The resource specification file must be a JSON object. All examples in this
|
||||
document assume the following resource specification file:
|
||||
|
@ -11,3 +11,7 @@ in the same way as it would with unity builds disabled.
|
||||
This property helps with "ODR (One definition rule)" problems where combining
|
||||
a particular source file with others might lead to build errors or other
|
||||
unintended side effects.
|
||||
|
||||
Note that sources which are scanned for C++ modules (see
|
||||
:manual:`cmake-cxxmodules(7)`) are not eligible for unity build inclusion and
|
||||
will automatically be excluded.
|
||||
|
@ -64,6 +64,11 @@ a number of measures to help address such problems:
|
||||
:prop_sf:`INCLUDE_DIRECTORIES` source property will not be combined
|
||||
into a unity source.
|
||||
|
||||
* Any source file which is scanned for C++ module sources via
|
||||
:prop_tgt:`CXX_SCAN_FOR_MODULES`, :prop_sf:`CXX_SCAN_FOR_MODULES`, or
|
||||
membership of a ``CXX_MODULES`` file set will not be combined into a unity
|
||||
source. See :manual:`cmake-cxxmodules(7)` for details.
|
||||
|
||||
* Projects can prevent an individual source file from being combined into
|
||||
a unity source by setting its :prop_sf:`SKIP_UNITY_BUILD_INCLUSION`
|
||||
source property to true. This can be a more effective way to prevent
|
||||
|
@ -116,12 +116,6 @@ Modules
|
||||
Additionally, the :command:`ExternalProject_Add_Step` command
|
||||
has been updated to support the new ``JOB_SERVER_AWARE`` option.
|
||||
|
||||
* The :module:`ExternalProject` module now declares ``BYPRODUCTS`` for the
|
||||
downloaded file for generated ``download`` steps. Previously, if multiple
|
||||
external projects downloaded to the same file, hash verification could fail.
|
||||
Now, when using the :ref:`Ninja Generators`, this scenario is detected and
|
||||
Ninja will raise an error stating that multiple rules generate the same file.
|
||||
|
||||
* The :module:`FetchContent` module's :command:`FetchContent_Declare` command
|
||||
gained an ``EXCLUDE_FROM_ALL`` option, which propagates through to the
|
||||
:command:`add_subdirectory` call made by
|
||||
@ -207,9 +201,9 @@ Updates
|
||||
|
||||
Changes made since CMake 3.28.0 include the following.
|
||||
|
||||
3.28.1
|
||||
------
|
||||
3.28.1, 3.28.2
|
||||
--------------
|
||||
|
||||
* This version made no changes to documented features or interfaces.
|
||||
* These versions made no changes to documented features or interfaces.
|
||||
Some implementation updates were made to support ecosystem changes
|
||||
and/or fix regressions.
|
||||
|
@ -41,6 +41,12 @@ or :command:`project` commands:
|
||||
not be set without also setting
|
||||
:variable:`CMAKE_<LANG>_COMPILER` to a NVCC compiler.
|
||||
|
||||
:variable:`CMAKE_<LANG>_PLATFORM <CMAKE_HIP_PLATFORM>`
|
||||
This variable is set to the detected GPU platform when ``<lang>`` is ``HIP``.
|
||||
|
||||
If the variable is already set its value is always preserved. Only compatible values
|
||||
will be considered for :variable:`CMAKE_<LANG>_COMPILER`.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
@ -66,15 +72,23 @@ macro(check_language lang)
|
||||
|
||||
set(extra_compiler_variables)
|
||||
if("${lang}" MATCHES "^(CUDA|HIP)$" AND NOT CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
set(extra_compiler_variables "set(CMAKE_CUDA_HOST_COMPILER \\\"\${CMAKE_CUDA_HOST_COMPILER}\\\")")
|
||||
set(extra_compiler_variables "set(CMAKE_${lang}_HOST_COMPILER \\\"\${CMAKE_${lang}_HOST_COMPILER}\\\")")
|
||||
endif()
|
||||
|
||||
if("${lang}" STREQUAL "HIP")
|
||||
list(APPEND extra_compiler_variables "set(CMAKE_${lang}_PLATFORM \\\"\${CMAKE_${lang}_PLATFORM}\\\")")
|
||||
endif()
|
||||
|
||||
list(TRANSFORM extra_compiler_variables PREPEND "\"")
|
||||
list(TRANSFORM extra_compiler_variables APPEND "\\n\"")
|
||||
list(JOIN extra_compiler_variables "\n " extra_compiler_variables)
|
||||
|
||||
set(_cl_content
|
||||
"cmake_minimum_required(VERSION ${CMAKE_VERSION})
|
||||
project(Check${lang} ${lang})
|
||||
file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
|
||||
\"set(CMAKE_${lang}_COMPILER \\\"\${CMAKE_${lang}_COMPILER}\\\")\\n\"
|
||||
\"${extra_compiler_variables}\\n\"
|
||||
${extra_compiler_variables}
|
||||
)"
|
||||
)
|
||||
|
||||
@ -95,6 +109,11 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
|
||||
else()
|
||||
set(_D_CMAKE_TOOLCHAIN_FILE "")
|
||||
endif()
|
||||
if(CMAKE_${lang}_PLATFORM)
|
||||
set(_D_CMAKE_LANG_PLATFORM "-DCMAKE_${lang}_PLATFORM:STRING=${CMAKE_${lang}_PLATFORM}")
|
||||
else()
|
||||
set(_D_CMAKE_LANG_PLATFORM "")
|
||||
endif()
|
||||
execute_process(
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}
|
||||
COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
|
||||
@ -103,6 +122,7 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
|
||||
${_D_CMAKE_GENERATOR_INSTANCE}
|
||||
${_D_CMAKE_MAKE_PROGRAM}
|
||||
${_D_CMAKE_TOOLCHAIN_FILE}
|
||||
${_D_CMAKE_LANG_PLATFORM}
|
||||
OUTPUT_VARIABLE _cl_output
|
||||
ERROR_VARIABLE _cl_output
|
||||
RESULT_VARIABLE _cl_result
|
||||
@ -130,6 +150,10 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
|
||||
mark_as_advanced(CMAKE_${lang}_HOST_COMPILER)
|
||||
endif()
|
||||
|
||||
if(CMAKE_${lang}_PLATFORM)
|
||||
set(CMAKE_${lang}_PLATFORM "${CMAKE_${lang}_PLATFORM}" CACHE STRING "${lang} platform")
|
||||
mark_as_advanced(CMAKE_${lang}_PLATFORM)
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
@ -2825,7 +2825,6 @@ function(_ep_add_download_command name)
|
||||
set(comment)
|
||||
set(work_dir)
|
||||
set(extra_repo_info)
|
||||
set(byproduct_file)
|
||||
|
||||
if(cmd_set)
|
||||
set(work_dir ${download_dir})
|
||||
@ -3106,16 +3105,14 @@ hash=${hash}
|
||||
get_filename_component(fname "${fname}" NAME)
|
||||
else()
|
||||
# Fall back to a default file name. The actual file name does not
|
||||
# matter as long as it doesn't conflict with other projects because
|
||||
# it is used only internally and our extraction tool inspects the
|
||||
# file content directly. If it turns out the wrong URL was given
|
||||
# that will be revealed during the build which is an easier place for
|
||||
# users to diagnose than an error here anyway.
|
||||
set(fname "${name}-archive.tar")
|
||||
# matter because it is used only internally and our extraction tool
|
||||
# inspects the file content directly. If it turns out the wrong URL
|
||||
# was given that will be revealed during the build which is an easier
|
||||
# place for users to diagnose than an error here anyway.
|
||||
set(fname "archive.tar")
|
||||
endif()
|
||||
string(REPLACE ";" "-" fname "${fname}")
|
||||
set(file ${download_dir}/${fname})
|
||||
set(byproduct_file "${download_dir}/${fname}")
|
||||
get_property(timeout TARGET ${name} PROPERTY _EP_TIMEOUT)
|
||||
get_property(inactivity_timeout
|
||||
TARGET ${name}
|
||||
@ -3292,7 +3289,6 @@ hash=${hash}
|
||||
COMMAND ${__cmdQuoted}
|
||||
WORKING_DIRECTORY \${work_dir}
|
||||
DEPENDS \${depends}
|
||||
BYPRODUCTS \${byproduct_file}
|
||||
DEPENDEES mkdir
|
||||
${log}
|
||||
${uses_terminal}
|
||||
|
@ -17,7 +17,7 @@ packages and/or feature for a build tree such as::
|
||||
PNG, A PNG image library., <http://www.libpng.org/pub/png/>
|
||||
* Enables saving screenshots
|
||||
-- The following OPTIONAL packages have not been found:
|
||||
Lua51, The Lua scripting language., <http://www.lua.org>
|
||||
Lua51, The Lua scripting language., <https://www.lua.org>
|
||||
* Enables macros in MyWordProcessor
|
||||
Foo, Foo provides cool stuff.
|
||||
|
||||
|
@ -1394,7 +1394,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
|
||||
set(_Boost_THREAD_DEPENDENCIES chrono atomic)
|
||||
set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic)
|
||||
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
|
||||
if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.84.0 AND NOT Boost_NO_WARN_NEW_VERSIONS)
|
||||
if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.85.0 AND NOT Boost_NO_WARN_NEW_VERSIONS)
|
||||
message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
|
||||
endif()
|
||||
endif()
|
||||
@ -1669,6 +1669,7 @@ else()
|
||||
# _Boost_COMPONENT_HEADERS. See the instructions at the top of
|
||||
# _Boost_COMPONENT_DEPENDENCIES.
|
||||
set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS}
|
||||
"1.84.0" "1.84"
|
||||
"1.83.0" "1.83" "1.82.0" "1.82" "1.81.0" "1.81" "1.80.0" "1.80" "1.79.0" "1.79"
|
||||
"1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74"
|
||||
"1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69"
|
||||
|
@ -960,7 +960,7 @@ endif()
|
||||
# the version of the CUDA toolchain
|
||||
# Create a separate variable so this directory can be selectively added to math targets.
|
||||
find_path(CUDAToolkit_CUBLAS_INCLUDE_DIR cublas_v2.h PATHS
|
||||
"${CUDAToolkit_INCLUDE_DIRECTORIES}"
|
||||
${CUDAToolkit_INCLUDE_DIRECTORIES}
|
||||
NO_DEFAULT_PATH)
|
||||
|
||||
if(NOT CUDAToolkit_CUBLAS_INCLUDE_DIR)
|
||||
@ -973,7 +973,7 @@ if(NOT CUDAToolkit_CUBLAS_INCLUDE_DIR)
|
||||
cmake_path(NORMAL_PATH CUDAToolkit_MATH_INCLUDE_DIR)
|
||||
|
||||
find_path(CUDAToolkit_CUBLAS_INCLUDE_DIR cublas_v2.h PATHS
|
||||
"${CUDAToolkit_INCLUDE_DIRECTORIES}"
|
||||
${CUDAToolkit_INCLUDE_DIRECTORIES}
|
||||
)
|
||||
if(CUDAToolkit_CUBLAS_INCLUDE_DIR)
|
||||
list(APPEND CUDAToolkit_INCLUDE_DIRECTORIES "${CUDAToolkit_CUBLAS_INCLUDE_DIR}")
|
||||
@ -1246,7 +1246,7 @@ if(CUDAToolkit_FOUND)
|
||||
|
||||
find_path(CUDAToolkit_CUPTI_INCLUDE_DIR cupti.h PATHS
|
||||
"${CUDAToolkit_ROOT_DIR}/extras/CUPTI/include"
|
||||
"${CUDAToolkit_INCLUDE_DIRS}"
|
||||
${CUDAToolkit_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES "../extras/CUPTI/include"
|
||||
"../../../extras/CUPTI/include"
|
||||
NO_DEFAULT_PATH)
|
||||
|
@ -65,104 +65,6 @@ directory of a Freetype installation.
|
||||
# I'm going to attempt to cut out the middleman and hope
|
||||
# everything still works.
|
||||
|
||||
set(_Freetype_args)
|
||||
if (Freetype_FIND_VERSION)
|
||||
list(APPEND _Freetype_args
|
||||
"${Freetype_FIND_VERSION}")
|
||||
if (Freetype_FIND_VERSION_EXACT)
|
||||
list(APPEND _Freetype_args
|
||||
EXACT)
|
||||
endif ()
|
||||
endif ()
|
||||
set(_Freetype_component_req)
|
||||
set(_Freetype_component_opt)
|
||||
foreach (_Freetype_component IN LISTS Freetype_FIND_COMPONENTS)
|
||||
if (Freetype_FIND_REQUIRE_${_Freetype_component})
|
||||
list(APPEND _Freetype_component_req
|
||||
"${_Freetype_component}")
|
||||
else ()
|
||||
list(APPEND _Freetype_component_opt
|
||||
"${_Freetype_component}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
unset(_Freetype_component)
|
||||
if (_Freetype_component_req)
|
||||
list(APPEND _Freetype_args
|
||||
COMPONENTS "${_Freetype_component_req}")
|
||||
endif ()
|
||||
unset(_Freetype_component_req)
|
||||
if (_Freetype_component_opt)
|
||||
list(APPEND _Freetype_args
|
||||
OPTIONAL_COMPONENTS "${_Freetype_component_opt}")
|
||||
endif ()
|
||||
unset(_Freetype_component_opt)
|
||||
# Always find with QUIET to avoid noise when it is not found.
|
||||
find_package(freetype CONFIG QUIET ${_Freetype_args})
|
||||
unset(_Freetype_args)
|
||||
if (freetype_FOUND)
|
||||
if (NOT TARGET Freetype::Freetype)
|
||||
add_library(Freetype::Freetype IMPORTED INTERFACE)
|
||||
set_target_properties(Freetype::Freetype PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES freetype)
|
||||
endif ()
|
||||
get_property(FREETYPE_INCLUDE_DIRS TARGET freetype PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
|
||||
get_property(FREETYPE_LIBRARIES TARGET freetype PROPERTY INTERFACE_LINK_LIBRARIES)
|
||||
get_property(_Freetype_location TARGET freetype PROPERTY IMPORTED_IMPLIB)
|
||||
if (NOT _Freetype_location)
|
||||
get_property(_Freetype_location_release TARGET freetype PROPERTY IMPORTED_IMPLIB_RELEASE)
|
||||
if (NOT _Freetype_location_release)
|
||||
get_property(_Freetype_location_release TARGET freetype PROPERTY IMPORTED_IMPLIB_RELWITHDEBINFO)
|
||||
endif ()
|
||||
get_property(_Freetype_location_debug TARGET freetype PROPERTY IMPORTED_IMPLIB_DEBUG)
|
||||
if (_Freetype_location_release AND _Freetype_location_debug)
|
||||
set(_Freetype_location
|
||||
optimized "${_Freetype_location_release}"
|
||||
debug "${_Freetype_location_debug}")
|
||||
elseif (_Freetype_location_release)
|
||||
set(_Freetype_location "${_Freetype_location_release}")
|
||||
elseif (_Freetype_location_debug)
|
||||
set(_Freetype_location "${_Freetype_location_debug}")
|
||||
else ()
|
||||
get_property(_Freetype_location_release TARGET freetype PROPERTY LOCATION_RELEASE)
|
||||
if (NOT _Freetype_location_release)
|
||||
get_property(_Freetype_location_release TARGET freetype PROPERTY LOCATION_RELWITHDEBINFO)
|
||||
endif ()
|
||||
get_property(_Freetype_location_debug TARGET freetype PROPERTY LOCATION_DEBUG)
|
||||
if (_Freetype_location_release AND _Freetype_location_debug)
|
||||
set(_Freetype_location
|
||||
optimized "${_Freetype_location_release}"
|
||||
debug "${_Freetype_location_debug}")
|
||||
elseif (_Freetype_location_release)
|
||||
set(_Freetype_location "${_Freetype_location_release}")
|
||||
elseif (_Freetype_location_debug)
|
||||
set(_Freetype_location "${_Freetype_location_debug}")
|
||||
else ()
|
||||
get_property(_Freetype_location TARGET freetype PROPERTY LOCATION)
|
||||
endif ()
|
||||
endif ()
|
||||
unset(_Freetype_location_release)
|
||||
unset(_Freetype_location_debug)
|
||||
endif ()
|
||||
list(INSERT FREETYPE_LIBRARIES 0
|
||||
"${_Freetype_location}")
|
||||
unset(_Freetype_location)
|
||||
set(Freetype_FOUND 1)
|
||||
set(FREETYPE_FOUND 1)
|
||||
set(FREETYPE_VERSION_STRING "${freetype_VERSION}")
|
||||
foreach (_Freetype_component IN LISTS Freetype_FIND_COMPONENTS)
|
||||
set(Freetype_${_Freetype_component}_FOUND "${freetype_${_Freetype_component}_FOUND}")
|
||||
endforeach ()
|
||||
unset(_Freetype_component)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
|
||||
find_package_handle_standard_args(Freetype
|
||||
HANDLE_COMPONENTS
|
||||
VERSION_VAR FREETYPE_VERSION_STRING
|
||||
)
|
||||
|
||||
return ()
|
||||
endif ()
|
||||
|
||||
set(FREETYPE_FIND_ARGS
|
||||
HINTS
|
||||
ENV FREETYPE_DIR
|
||||
|
@ -189,17 +189,13 @@ Cached variables
|
||||
the location of the root of the Matlab installation found. If this value
|
||||
is changed by the user, the result variables are recomputed.
|
||||
|
||||
Provided macros
|
||||
^^^^^^^^^^^^^^^
|
||||
Provided commands
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
:command:`matlab_get_version_from_release_name`
|
||||
returns the version from the release name
|
||||
returns the version from the Matlab release name
|
||||
:command:`matlab_get_release_name_from_version`
|
||||
returns the release name from the Matlab version
|
||||
|
||||
Provided functions
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:command:`matlab_add_mex`
|
||||
adds a target compiling a MEX file.
|
||||
:command:`matlab_add_unit_test`
|
||||
@ -350,6 +346,11 @@ file(MAKE_DIRECTORY "${_matlab_temporary_folder}")
|
||||
* Output: ``version`` is the version of Matlab (e.g. 23.2.0)
|
||||
|
||||
Returns the version of Matlab from a release name
|
||||
|
||||
.. note::
|
||||
|
||||
This command provides correct versions mappings for Matlab but not MCR.
|
||||
|
||||
#]=======================================================================]
|
||||
macro(matlab_get_version_from_release_name release_name version_name)
|
||||
|
||||
@ -377,33 +378,27 @@ endmacro()
|
||||
* Output: ``release_name`` is the release name (R2023b)
|
||||
|
||||
Returns the release name from the version of Matlab
|
||||
|
||||
.. note::
|
||||
|
||||
This command provides correct version mappings for Matlab but not MCR.
|
||||
|
||||
#]=======================================================================]
|
||||
macro(matlab_get_release_name_from_version version release_name)
|
||||
function(matlab_get_release_name_from_version version release_name)
|
||||
|
||||
# only the major.minor version is used
|
||||
string(REGEX MATCH "([0-9]+\\.[0-9]+)" _match ${version})
|
||||
if(CMAKE_MATCH_1)
|
||||
set(short_version ${CMAKE_MATCH_1})
|
||||
else()
|
||||
set(short_version ${version})
|
||||
endif()
|
||||
string(REGEX REPLACE "^([0-9]+\\.[0-9]+).*" "\\1" version "${version}")
|
||||
|
||||
set(${release_name} "")
|
||||
foreach(_var IN LISTS MATLAB_VERSIONS_MAPPING)
|
||||
string(REGEX MATCHALL "(.+)=${short_version}" _matched ${_var})
|
||||
if(NOT _matched STREQUAL "")
|
||||
set(${release_name} ${CMAKE_MATCH_1})
|
||||
break()
|
||||
if(_var MATCHES "(.+)=${version}")
|
||||
set(${release_name} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
unset(_var)
|
||||
unset(_matched)
|
||||
if(${release_name} STREQUAL "")
|
||||
message(WARNING "[MATLAB] The version ${short_version} is not registered")
|
||||
endif()
|
||||
message(WARNING "[MATLAB] The version ${version} is not registered")
|
||||
|
||||
endmacro()
|
||||
endfunction()
|
||||
|
||||
|
||||
# extracts all the supported release names (R2022b...) of Matlab
|
||||
@ -453,9 +448,10 @@ endmacro()
|
||||
are installed. The found versions are returned in `matlab_versions`.
|
||||
Set `win64` to `TRUE` if the 64 bit version of Matlab should be looked for
|
||||
The returned list contains all versions under
|
||||
``HKLM\\SOFTWARE\\Mathworks\\MATLAB`` and
|
||||
``HKLM\\SOFTWARE\\Mathworks\\MATLAB Runtime`` or an empty list in case an
|
||||
error occurred (or nothing found).
|
||||
``HKLM\\SOFTWARE\\Mathworks\\MATLAB``,
|
||||
``HKLM\\SOFTWARE\\Mathworks\\MATLAB Runtime`` and
|
||||
``HKLM\\SOFTWARE\\Mathworks\\MATLAB Compiler Runtime`` or an empty list in
|
||||
case an error occurred (or nothing found).
|
||||
|
||||
.. note::
|
||||
|
||||
@ -466,7 +462,7 @@ endmacro()
|
||||
function(matlab_extract_all_installed_versions_from_registry win64 matlab_versions)
|
||||
|
||||
if(NOT CMAKE_HOST_WIN32)
|
||||
message(FATAL_ERROR "[MATLAB] This macro can only be called by a Windows host")
|
||||
message(FATAL_ERROR "[MATLAB] This function can only be called by a Windows host")
|
||||
endif()
|
||||
|
||||
if(${win64} AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "64")
|
||||
@ -485,24 +481,22 @@ function(matlab_extract_all_installed_versions_from_registry win64 matlab_versio
|
||||
)
|
||||
|
||||
if(_reg)
|
||||
string(REGEX MATCHALL "([0-9]+(\\.[0-9]+)+)" _versions_regex "${_reg}")
|
||||
|
||||
string(REGEX MATCHALL "([0-9]+\\.[0-9]+)" _versions_regex "${_reg}")
|
||||
foreach(_match IN LISTS _versions_regex)
|
||||
if(_match MATCHES "([0-9]+(\\.[0-9]+)+)")
|
||||
cmake_host_system_information(RESULT _reg
|
||||
QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Mathworks/${_installation_type}/${CMAKE_MATCH_1}"
|
||||
VALUE "MATLABROOT"
|
||||
VIEW ${_view}
|
||||
)
|
||||
|
||||
foreach(match IN LISTS _versions_regex)
|
||||
string(REGEX MATCH "([0-9]+\\.[0-9]+)" current_match "${match}")
|
||||
|
||||
if(NOT CMAKE_MATCH_1)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
cmake_host_system_information(RESULT _reg
|
||||
QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Mathworks/${_installation_type}/${CMAKE_MATCH_1}"
|
||||
VALUE "MATLABROOT"
|
||||
)
|
||||
|
||||
_Matlab_VersionInfoXML("${_reg}" _matlab_version_tmp)
|
||||
if(NOT "${_matlab_version_tmp}" STREQUAL "unknown")
|
||||
list(APPEND matlabs_from_registry ${_matlab_version_tmp})
|
||||
_Matlab_VersionInfoXML("${_reg}" _matlab_version_tmp)
|
||||
if("${_matlab_version_tmp}" STREQUAL "unknown")
|
||||
list(APPEND matlabs_from_registry ${_match})
|
||||
else()
|
||||
list(APPEND matlabs_from_registry ${_matlab_version_tmp})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
@ -558,42 +552,59 @@ function(matlab_get_all_valid_matlab_roots_from_registry matlab_versions matlab_
|
||||
# extract_matlab_versions_from_registry_brute_force or
|
||||
# matlab_extract_all_installed_versions_from_registry.
|
||||
|
||||
# Mostly the major.minor version is used in Mathworks Windows Registry keys.
|
||||
# If the patch is not zero, major.minor.patch is used.
|
||||
list(TRANSFORM matlab_versions REPLACE "^([0-9]+\\.[0-9]+(\\.[1-9][0-9]*)?).*" "\\1")
|
||||
|
||||
set(_matlab_roots_list )
|
||||
# check for Matlab installations
|
||||
foreach(_matlab_current_version IN LISTS matlab_versions)
|
||||
get_filename_component(
|
||||
current_MATLAB_ROOT
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${_matlab_current_version};MATLABROOT]"
|
||||
ABSOLUTE)
|
||||
cmake_host_system_information(RESULT current_MATLAB_ROOT
|
||||
QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Mathworks/MATLAB/${_matlab_current_version}"
|
||||
VALUE "MATLABROOT"
|
||||
)
|
||||
cmake_path(CONVERT "${current_MATLAB_ROOT}" TO_CMAKE_PATH_LIST current_MATLAB_ROOT)
|
||||
|
||||
if(IS_DIRECTORY "${current_MATLAB_ROOT}")
|
||||
list(APPEND _matlab_roots_list "MATLAB" ${_matlab_current_version} ${current_MATLAB_ROOT})
|
||||
_Matlab_VersionInfoXML("${current_MATLAB_ROOT}" _matlab_version_tmp)
|
||||
if("${_matlab_version_tmp}" STREQUAL "unknown")
|
||||
list(APPEND _matlab_roots_list "MATLAB" ${_matlab_current_version} ${current_MATLAB_ROOT})
|
||||
else()
|
||||
list(APPEND _matlab_roots_list "MATLAB" ${_matlab_version_tmp} ${current_MATLAB_ROOT})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
# Check for MCR installations
|
||||
foreach(_matlab_current_version IN LISTS matlab_versions)
|
||||
get_filename_component(
|
||||
current_MATLAB_ROOT
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB Runtime\\${_matlab_current_version};MATLABROOT]"
|
||||
ABSOLUTE)
|
||||
cmake_host_system_information(RESULT current_MATLAB_ROOT
|
||||
QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Mathworks/MATLAB Runtime/${_matlab_current_version}"
|
||||
VALUE "MATLABROOT"
|
||||
)
|
||||
cmake_path(CONVERT "${current_MATLAB_ROOT}" TO_CMAKE_PATH_LIST current_MATLAB_ROOT)
|
||||
|
||||
# remove the dot
|
||||
string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}")
|
||||
|
||||
if(IS_DIRECTORY "${current_MATLAB_ROOT}")
|
||||
list(APPEND _matlab_roots_list "MCR" ${_matlab_current_version} "${current_MATLAB_ROOT}/v${_matlab_current_version_without_dot}")
|
||||
_Matlab_VersionInfoXML("${current_MATLAB_ROOT}" _matlab_version_tmp)
|
||||
if("${_matlab_version_tmp}" STREQUAL "unknown")
|
||||
list(APPEND _matlab_roots_list "MCR" ${_matlab_current_version} "${current_MATLAB_ROOT}/v${_matlab_current_version_without_dot}")
|
||||
else()
|
||||
list(APPEND _matlab_roots_list "MCR" ${_matlab_version_tmp} "${current_MATLAB_ROOT}/v${_matlab_current_version_without_dot}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
# Check for old MCR installations
|
||||
foreach(_matlab_current_version IN LISTS matlab_versions)
|
||||
get_filename_component(
|
||||
current_MATLAB_ROOT
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB Compiler Runtime\\${_matlab_current_version};MATLABROOT]"
|
||||
ABSOLUTE)
|
||||
cmake_host_system_information(RESULT current_MATLAB_ROOT
|
||||
QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Mathworks/MATLAB Compiler Runtime/${_matlab_current_version}"
|
||||
VALUE "MATLABROOT"
|
||||
)
|
||||
cmake_path(CONVERT "${current_MATLAB_ROOT}" TO_CMAKE_PATH_LIST current_MATLAB_ROOT)
|
||||
|
||||
# remove the dot
|
||||
string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}")
|
||||
@ -1409,20 +1420,11 @@ function(_Matlab_VersionInfoXML matlab_root _version)
|
||||
set(_ver "unknown")
|
||||
|
||||
set(_XMLfile ${matlab_root}/VersionInfo.xml)
|
||||
if(NOT EXISTS ${_XMLfile})
|
||||
return()
|
||||
endif()
|
||||
if(EXISTS ${_XMLfile})
|
||||
file(READ ${_XMLfile} versioninfo_string)
|
||||
|
||||
file(READ ${_XMLfile} versioninfo_string)
|
||||
|
||||
if(versioninfo_string)
|
||||
# parses "<version>23.2.0.2365128</version>"
|
||||
string(REGEX MATCH "<version>([0-9]+(\\.[0-9]+)+)</version>"
|
||||
version_reg_match
|
||||
${versioninfo_string}
|
||||
)
|
||||
|
||||
if(CMAKE_MATCH_1)
|
||||
if(versioninfo_string MATCHES "<version>([0-9]+(\\.[0-9]+)+)</version>")
|
||||
set(_ver "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
@ -1634,7 +1636,17 @@ set(Matlab_VERSION_STRING "NOTFOUND")
|
||||
set(Matlab_Or_MCR "UNKNOWN")
|
||||
if(_numbers_of_matlab_roots GREATER 0)
|
||||
if(Matlab_FIND_VERSION_EXACT)
|
||||
list(FIND _matlab_possible_roots ${Matlab_FIND_VERSION} _list_index)
|
||||
set(_list_index -1)
|
||||
foreach(_matlab_root_index RANGE 1 ${_numbers_of_matlab_roots} 3)
|
||||
list(GET _matlab_possible_roots ${_matlab_root_index} _matlab_root_version)
|
||||
# only the major.minor version is used
|
||||
string(REGEX REPLACE "^([0-9]+\\.[0-9]+).*" "\\1" _matlab_root_version "${_matlab_root_version}")
|
||||
if(_matlab_root_version VERSION_EQUAL Matlab_FIND_VERSION)
|
||||
set(_list_index ${_matlab_root_index})
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(_list_index LESS 0)
|
||||
set(_list_index 1)
|
||||
endif()
|
||||
|
@ -55,23 +55,25 @@ function(cmake_cuda_architectures_all lang lang_var_)
|
||||
endif()
|
||||
|
||||
if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.4)
|
||||
if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA")
|
||||
if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA"
|
||||
OR (CMAKE_${lang}_COMPILER_ID STREQUAL "Clang" AND CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)
|
||||
)
|
||||
list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 87)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.8)
|
||||
if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA")
|
||||
if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA"
|
||||
OR (CMAKE_${lang}_COMPILER_ID STREQUAL "Clang" AND CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)
|
||||
)
|
||||
list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 89 90)
|
||||
list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 90)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 12.0)
|
||||
if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA")
|
||||
list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 35 37)
|
||||
list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 35)
|
||||
endif()
|
||||
list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 35 37)
|
||||
list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 35)
|
||||
endif()
|
||||
|
||||
# only generate jit code for the newest arch for all/all-major
|
||||
|
@ -41,20 +41,19 @@ macro(PKGCONFIG _package _include_DIR _link_DIR _link_FLAGS _cflags)
|
||||
if(NOT _return_VALUE)
|
||||
|
||||
execute_process(COMMAND ${PKGCONFIG_EXECUTABLE} ${_package} --variable=includedir
|
||||
OUTPUT_VARIABLE ${_include_DIR} )
|
||||
OUTPUT_VARIABLE ${_include_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
string(REGEX REPLACE "[\r\n]" " " ${_include_DIR} "${${_include_DIR}}")
|
||||
|
||||
|
||||
execute_process(COMMAND ${PKGCONFIG_EXECUTABLE} ${_package} --variable=libdir
|
||||
OUTPUT_VARIABLE ${_link_DIR} )
|
||||
OUTPUT_VARIABLE ${_link_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
string(REGEX REPLACE "[\r\n]" " " ${_link_DIR} "${${_link_DIR}}")
|
||||
|
||||
execute_process(COMMAND ${PKGCONFIG_EXECUTABLE} ${_package} --libs
|
||||
OUTPUT_VARIABLE ${_link_FLAGS} )
|
||||
OUTPUT_VARIABLE ${_link_FLAGS} OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
string(REGEX REPLACE "[\r\n]" " " ${_link_FLAGS} "${${_link_FLAGS}}")
|
||||
|
||||
execute_process(COMMAND ${PKGCONFIG_EXECUTABLE} ${_package} --cflags
|
||||
OUTPUT_VARIABLE ${_cflags} )
|
||||
OUTPUT_VARIABLE ${_cflags} OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
string(REGEX REPLACE "[\r\n]" " " ${_cflags} "${${_cflags}}")
|
||||
|
||||
else()
|
||||
|
@ -1,7 +1,7 @@
|
||||
# CMake version number components.
|
||||
set(CMake_VERSION_MAJOR 3)
|
||||
set(CMake_VERSION_MINOR 28)
|
||||
set(CMake_VERSION_PATCH 1)
|
||||
set(CMake_VERSION_PATCH 2)
|
||||
#set(CMake_VERSION_RC 0)
|
||||
set(CMake_VERSION_IS_DIRTY 0)
|
||||
|
||||
@ -21,7 +21,7 @@ endif()
|
||||
|
||||
if(NOT CMake_VERSION_NO_GIT)
|
||||
# If this source was exported by 'git archive', use its commit info.
|
||||
set(git_info [==[1eed682d7c CMake 3.28.1]==])
|
||||
set(git_info [==[1f25aa1a0a CMake 3.28.2]==])
|
||||
|
||||
# Otherwise, try to identify the current development source version.
|
||||
if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
|
||||
|
@ -7,8 +7,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
|
||||
#include "cm_sys_stat.h"
|
||||
|
@ -135,14 +135,14 @@ private:
|
||||
std::string cmCTestBZR::LoadInfo()
|
||||
{
|
||||
// Run "bzr info" to get the repository info from the work tree.
|
||||
std::string bzr = this->CommandLineTool;
|
||||
std::vector<std::string> bzr_info = { bzr, "info" };
|
||||
const char* bzr = this->CommandLineTool.c_str();
|
||||
const char* bzr_info[] = { bzr, "info", nullptr };
|
||||
InfoParser iout(this, "info-out> ");
|
||||
OutputLogger ierr(this->Log, "info-err> ");
|
||||
this->RunChild(bzr_info, &iout, &ierr);
|
||||
|
||||
// Run "bzr revno" to get the repository revision number from the work tree.
|
||||
std::vector<std::string> bzr_revno = { bzr, "revno" };
|
||||
const char* bzr_revno[] = { bzr, "revno", nullptr };
|
||||
std::string rev;
|
||||
RevnoParser rout(this, "revno-out> ", rev);
|
||||
OutputLogger rerr(this->Log, "revno-err> ");
|
||||
@ -372,18 +372,22 @@ bool cmCTestBZR::UpdateImpl()
|
||||
// TODO: if(this->CTest->GetTestModel() == cmCTest::NIGHTLY)
|
||||
|
||||
// Use "bzr pull" to update the working tree.
|
||||
std::vector<std::string> bzr_update;
|
||||
bzr_update.push_back(this->CommandLineTool);
|
||||
std::vector<char const*> bzr_update;
|
||||
bzr_update.push_back(this->CommandLineTool.c_str());
|
||||
bzr_update.push_back("pull");
|
||||
|
||||
cm::append(bzr_update, args);
|
||||
for (std::string const& arg : args) {
|
||||
bzr_update.push_back(arg.c_str());
|
||||
}
|
||||
|
||||
bzr_update.push_back(this->URL);
|
||||
bzr_update.push_back(this->URL.c_str());
|
||||
|
||||
bzr_update.push_back(nullptr);
|
||||
|
||||
// For some reason bzr uses stderr to display the update status.
|
||||
OutputLogger out(this->Log, "pull-out> ");
|
||||
UpdateParser err(this, "pull-err> ");
|
||||
return this->RunUpdateCommand(bzr_update, &out, &err);
|
||||
return this->RunUpdateCommand(bzr_update.data(), &out, &err);
|
||||
}
|
||||
|
||||
bool cmCTestBZR::LoadRevisions()
|
||||
@ -404,9 +408,10 @@ bool cmCTestBZR::LoadRevisions()
|
||||
}
|
||||
|
||||
// Run "bzr log" to get all global revisions of interest.
|
||||
std::string bzr = this->CommandLineTool;
|
||||
std::vector<std::string> bzr_log = { bzr, "log", "-v", "-r",
|
||||
revs, "--xml", this->URL };
|
||||
const char* bzr = this->CommandLineTool.c_str();
|
||||
const char* bzr_log[] = {
|
||||
bzr, "log", "-v", "-r", revs.c_str(), "--xml", this->URL.c_str(), nullptr
|
||||
};
|
||||
{
|
||||
LogParser out(this, "log-out> ");
|
||||
OutputLogger err(this->Log, "log-err> ");
|
||||
@ -462,8 +467,8 @@ private:
|
||||
bool cmCTestBZR::LoadModifications()
|
||||
{
|
||||
// Run "bzr status" which reports local modifications.
|
||||
std::string bzr = this->CommandLineTool;
|
||||
std::vector<std::string> bzr_status = { bzr, "status", "-SV" };
|
||||
const char* bzr = this->CommandLineTool.c_str();
|
||||
const char* bzr_status[] = { bzr, "status", "-SV", nullptr };
|
||||
StatusParser out(this, "status-out> ");
|
||||
OutputLogger err(this->Log, "status-err> ");
|
||||
this->RunChild(bzr_status, &out, &err);
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <cstring>
|
||||
#include <ratio>
|
||||
|
||||
#include "cmsys/Process.h"
|
||||
|
||||
#include "cmBuildOptions.h"
|
||||
#include "cmCTest.h"
|
||||
#include "cmCTestTestHandler.h"
|
||||
@ -306,11 +308,12 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<std::string> testCommand;
|
||||
testCommand.push_back(fullPath);
|
||||
std::vector<const char*> testCommand;
|
||||
testCommand.push_back(fullPath.c_str());
|
||||
for (std::string const& testCommandArg : this->TestCommandArgs) {
|
||||
testCommand.push_back(testCommandArg);
|
||||
testCommand.push_back(testCommandArg.c_str());
|
||||
}
|
||||
testCommand.push_back(nullptr);
|
||||
std::string outs;
|
||||
int retval = 0;
|
||||
// run the test from the this->BuildRunDir if set
|
||||
@ -346,10 +349,10 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
|
||||
}
|
||||
}
|
||||
|
||||
bool runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, nullptr,
|
||||
remainingTime, nullptr);
|
||||
int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, nullptr,
|
||||
remainingTime, nullptr);
|
||||
|
||||
if (!runTestRes || retval != 0) {
|
||||
if (runTestRes != cmsysProcess_State_Exited || retval != 0) {
|
||||
out << "Test command failed: " << testCommand[0] << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
|
@ -3,17 +3,15 @@
|
||||
#include "cmCTestBuildHandler.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <ratio>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include <cmext/algorithm>
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
|
||||
#include "cmsys/Directory.hxx"
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/Process.h"
|
||||
|
||||
#include "cmCTest.h"
|
||||
#include "cmCTestLaunchReporter.h"
|
||||
@ -26,9 +24,6 @@
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmStringReplaceHelper.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVHandlePtr.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
#include "cmUVStream.h"
|
||||
#include "cmValue.h"
|
||||
#include "cmXMLWriter.h"
|
||||
|
||||
@ -425,7 +420,7 @@ int cmCTestBuildHandler::ProcessHandler()
|
||||
cmStringReplaceHelper colorRemover("\x1b\\[[0-9;]*m", "", nullptr);
|
||||
this->ColorRemover = &colorRemover;
|
||||
int retVal = 0;
|
||||
bool res = true;
|
||||
int res = cmsysProcess_State_Exited;
|
||||
if (!this->CTest->GetShowOnly()) {
|
||||
res = this->RunMakeCommand(makeCommand, &retVal, buildDirectory.c_str(), 0,
|
||||
ofs);
|
||||
@ -480,7 +475,7 @@ int cmCTestBuildHandler::ProcessHandler()
|
||||
}
|
||||
this->GenerateXMLFooter(xml, elapsed_build_time);
|
||||
|
||||
if (!res || retVal || this->TotalErrors > 0) {
|
||||
if (res != cmsysProcess_State_Exited || retVal || this->TotalErrors > 0) {
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"Error(s) when building project" << std::endl);
|
||||
}
|
||||
@ -769,10 +764,10 @@ void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers(
|
||||
}
|
||||
}
|
||||
|
||||
bool cmCTestBuildHandler::RunMakeCommand(const std::string& command,
|
||||
int* retVal, const char* dir,
|
||||
int timeout, std::ostream& ofs,
|
||||
Encoding encoding)
|
||||
int cmCTestBuildHandler::RunMakeCommand(const std::string& command,
|
||||
int* retVal, const char* dir,
|
||||
int timeout, std::ostream& ofs,
|
||||
Encoding encoding)
|
||||
{
|
||||
// First generate the command and arguments
|
||||
std::vector<std::string> args = cmSystemTools::ParseArguments(command);
|
||||
@ -781,9 +776,19 @@ bool cmCTestBuildHandler::RunMakeCommand(const std::string& command,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<const char*> argv;
|
||||
argv.reserve(args.size() + 1);
|
||||
for (std::string const& arg : args) {
|
||||
argv.push_back(arg.c_str());
|
||||
}
|
||||
argv.push_back(nullptr);
|
||||
|
||||
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"Run command:", this->Quiet);
|
||||
for (auto const& arg : args) {
|
||||
for (char const* arg : argv) {
|
||||
if (!arg) {
|
||||
break;
|
||||
}
|
||||
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
" \"" << arg << "\"", this->Quiet);
|
||||
}
|
||||
@ -795,20 +800,21 @@ bool cmCTestBuildHandler::RunMakeCommand(const std::string& command,
|
||||
static_cast<void>(launchHelper);
|
||||
|
||||
// Now create process object
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand(args)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
|
||||
if (dir) {
|
||||
builder.SetWorkingDirectory(dir);
|
||||
}
|
||||
auto chain = builder.Start();
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
cmsysProcess_SetCommand(cp, argv.data());
|
||||
cmsysProcess_SetWorkingDirectory(cp, dir);
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
|
||||
cmsysProcess_SetTimeout(cp, timeout);
|
||||
cmsysProcess_Execute(cp);
|
||||
|
||||
// Initialize tick's
|
||||
std::string::size_type tick = 0;
|
||||
static constexpr std::string::size_type tick_len = 1024;
|
||||
const std::string::size_type tick_len = 1024;
|
||||
|
||||
char* data;
|
||||
int length;
|
||||
cmProcessOutput processOutput(encoding);
|
||||
std::string strdata;
|
||||
cmCTestOptionalLog(
|
||||
this->CTest, HANDLER_PROGRESS_OUTPUT,
|
||||
" Each symbol represents "
|
||||
@ -830,65 +836,39 @@ bool cmCTestBuildHandler::RunMakeCommand(const std::string& command,
|
||||
this->WarningQuotaReached = false;
|
||||
this->ErrorQuotaReached = false;
|
||||
|
||||
cm::uv_timer_ptr timer;
|
||||
bool timedOut = false;
|
||||
timer.init(chain.GetLoop(), &timedOut);
|
||||
if (timeout > 0) {
|
||||
timer.start(
|
||||
[](uv_timer_t* t) {
|
||||
auto* timedOutPtr = static_cast<bool*>(t->data);
|
||||
*timedOutPtr = true;
|
||||
},
|
||||
timeout * 1000, 0);
|
||||
}
|
||||
|
||||
// For every chunk of data
|
||||
cm::uv_pipe_ptr outputStream;
|
||||
bool outFinished = false;
|
||||
cm::uv_pipe_ptr errorStream;
|
||||
bool errFinished = false;
|
||||
auto startRead = [this, &chain, &processOutput, &tick,
|
||||
&ofs](cm::uv_pipe_ptr& pipe, int stream,
|
||||
t_BuildProcessingQueueType& queue, bool& finished,
|
||||
int id) -> std::unique_ptr<cmUVStreamReadHandle> {
|
||||
pipe.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(pipe, stream);
|
||||
return cmUVStreamRead(
|
||||
pipe,
|
||||
[this, &processOutput, &queue, id, &tick, &ofs](std::vector<char> data) {
|
||||
// Replace '\0' with '\n', since '\0' does not really make sense. This
|
||||
// is for Visual Studio output
|
||||
for (auto& c : data) {
|
||||
if (c == 0) {
|
||||
c = '\n';
|
||||
}
|
||||
}
|
||||
int res;
|
||||
while ((res = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {
|
||||
// Replace '\0' with '\n', since '\0' does not really make sense. This is
|
||||
// for Visual Studio output
|
||||
for (int cc = 0; cc < length; ++cc) {
|
||||
if (data[cc] == 0) {
|
||||
data[cc] = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// Process the chunk of data
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata, id);
|
||||
this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len,
|
||||
ofs, &queue);
|
||||
},
|
||||
[this, &processOutput, &queue, id, &tick, &ofs, &finished]() {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(std::string(), strdata, id);
|
||||
if (!strdata.empty()) {
|
||||
this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len,
|
||||
ofs, &queue);
|
||||
}
|
||||
finished = true;
|
||||
});
|
||||
};
|
||||
auto outputHandle = startRead(outputStream, chain.OutputStream(),
|
||||
this->BuildProcessingQueue, outFinished, 1);
|
||||
auto errorHandle =
|
||||
startRead(errorStream, chain.ErrorStream(),
|
||||
this->BuildProcessingErrorQueue, errFinished, 2);
|
||||
|
||||
while (!timedOut && !(outFinished && errFinished && chain.Finished())) {
|
||||
uv_run(&chain.GetLoop(), UV_RUN_ONCE);
|
||||
// Process the chunk of data
|
||||
if (res == cmsysProcess_Pipe_STDERR) {
|
||||
processOutput.DecodeText(data, length, strdata, 1);
|
||||
this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs,
|
||||
&this->BuildProcessingErrorQueue);
|
||||
} else {
|
||||
processOutput.DecodeText(data, length, strdata, 2);
|
||||
this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs,
|
||||
&this->BuildProcessingQueue);
|
||||
}
|
||||
}
|
||||
processOutput.DecodeText(std::string(), strdata, 1);
|
||||
if (!strdata.empty()) {
|
||||
this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs,
|
||||
&this->BuildProcessingErrorQueue);
|
||||
}
|
||||
processOutput.DecodeText(std::string(), strdata, 2);
|
||||
if (!strdata.empty()) {
|
||||
this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs,
|
||||
&this->BuildProcessingQueue);
|
||||
}
|
||||
|
||||
this->ProcessBuffer(nullptr, 0, tick, tick_len, ofs,
|
||||
&this->BuildProcessingQueue);
|
||||
this->ProcessBuffer(nullptr, 0, tick, tick_len, ofs,
|
||||
@ -899,93 +879,90 @@ bool cmCTestBuildHandler::RunMakeCommand(const std::string& command,
|
||||
<< std::endl,
|
||||
this->Quiet);
|
||||
|
||||
if (chain.Finished()) {
|
||||
auto const& status = chain.GetStatus(0);
|
||||
auto exception = status.GetException();
|
||||
switch (exception.first) {
|
||||
case cmUVProcessChain::ExceptionCode::None:
|
||||
if (retVal) {
|
||||
*retVal = static_cast<int>(status.ExitStatus);
|
||||
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"Command exited with the value: " << *retVal
|
||||
<< std::endl,
|
||||
this->Quiet);
|
||||
// if a non zero return value
|
||||
if (*retVal) {
|
||||
// If there was an error running command, report that on the
|
||||
// dashboard.
|
||||
if (this->UseCTestLaunch) {
|
||||
// For launchers, do not record this top-level error if other
|
||||
// more granular build errors have already been captured.
|
||||
bool launcherXMLFound = false;
|
||||
cmsys::Directory launchDir;
|
||||
launchDir.Load(this->CTestLaunchDir);
|
||||
unsigned long n = launchDir.GetNumberOfFiles();
|
||||
for (unsigned long i = 0; i < n; ++i) {
|
||||
const char* fname = launchDir.GetFile(i);
|
||||
if (cmHasLiteralSuffix(fname, ".xml")) {
|
||||
launcherXMLFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!launcherXMLFound) {
|
||||
cmCTestLaunchReporter reporter;
|
||||
reporter.RealArgs = args;
|
||||
reporter.ComputeFileNames();
|
||||
reporter.ExitCode = *retVal;
|
||||
reporter.Status = status;
|
||||
// Use temporary BuildLog file to populate this error for
|
||||
// CDash.
|
||||
ofs.flush();
|
||||
reporter.LogOut = this->LogFileNames["Build"];
|
||||
reporter.LogOut += ".tmp";
|
||||
reporter.WriteXML();
|
||||
}
|
||||
} else {
|
||||
cmCTestBuildErrorWarning errorwarning;
|
||||
errorwarning.LineNumber = 0;
|
||||
errorwarning.LogLine = 1;
|
||||
errorwarning.Text = cmStrCat(
|
||||
"*** WARNING non-zero return value in ctest from: ", args[0]);
|
||||
errorwarning.PreContext.clear();
|
||||
errorwarning.PostContext.clear();
|
||||
errorwarning.Error = false;
|
||||
this->ErrorsAndWarnings.push_back(std::move(errorwarning));
|
||||
this->TotalWarnings++;
|
||||
// Properly handle output of the build command
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
int result = cmsysProcess_GetState(cp);
|
||||
|
||||
if (result == cmsysProcess_State_Exited) {
|
||||
if (retVal) {
|
||||
*retVal = cmsysProcess_GetExitValue(cp);
|
||||
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"Command exited with the value: " << *retVal
|
||||
<< std::endl,
|
||||
this->Quiet);
|
||||
// if a non zero return value
|
||||
if (*retVal) {
|
||||
// If there was an error running command, report that on the
|
||||
// dashboard.
|
||||
if (this->UseCTestLaunch) {
|
||||
// For launchers, do not record this top-level error if other
|
||||
// more granular build errors have already been captured.
|
||||
bool launcherXMLFound = false;
|
||||
cmsys::Directory launchDir;
|
||||
launchDir.Load(this->CTestLaunchDir);
|
||||
unsigned long n = launchDir.GetNumberOfFiles();
|
||||
for (unsigned long i = 0; i < n; ++i) {
|
||||
const char* fname = launchDir.GetFile(i);
|
||||
if (cmHasLiteralSuffix(fname, ".xml")) {
|
||||
launcherXMLFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!launcherXMLFound) {
|
||||
cmCTestLaunchReporter reporter;
|
||||
reporter.RealArgs = args;
|
||||
reporter.ComputeFileNames();
|
||||
reporter.ExitCode = *retVal;
|
||||
reporter.Process = cp;
|
||||
// Use temporary BuildLog file to populate this error for CDash.
|
||||
ofs.flush();
|
||||
reporter.LogOut = this->LogFileNames["Build"];
|
||||
reporter.LogOut += ".tmp";
|
||||
reporter.WriteXML();
|
||||
}
|
||||
} else {
|
||||
cmCTestBuildErrorWarning errorwarning;
|
||||
errorwarning.LineNumber = 0;
|
||||
errorwarning.LogLine = 1;
|
||||
errorwarning.Text = cmStrCat(
|
||||
"*** WARNING non-zero return value in ctest from: ", argv[0]);
|
||||
errorwarning.PreContext.clear();
|
||||
errorwarning.PostContext.clear();
|
||||
errorwarning.Error = false;
|
||||
this->ErrorsAndWarnings.push_back(std::move(errorwarning));
|
||||
this->TotalWarnings++;
|
||||
}
|
||||
break;
|
||||
case cmUVProcessChain::ExceptionCode::Spawn: {
|
||||
// If there was an error running command, report that on the dashboard.
|
||||
cmCTestBuildErrorWarning errorwarning;
|
||||
errorwarning.LineNumber = 0;
|
||||
errorwarning.LogLine = 1;
|
||||
errorwarning.Text =
|
||||
cmStrCat("*** ERROR executing: ", exception.second);
|
||||
errorwarning.PreContext.clear();
|
||||
errorwarning.PostContext.clear();
|
||||
errorwarning.Error = true;
|
||||
this->ErrorsAndWarnings.push_back(std::move(errorwarning));
|
||||
this->TotalErrors++;
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"There was an error: " << exception.second << std::endl);
|
||||
} break;
|
||||
default:
|
||||
if (retVal) {
|
||||
*retVal = status.TermSignal;
|
||||
cmCTestOptionalLog(
|
||||
this->CTest, WARNING,
|
||||
"There was an exception: " << *retVal << std::endl, this->Quiet);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (result == cmsysProcess_State_Exception) {
|
||||
if (retVal) {
|
||||
*retVal = cmsysProcess_GetExitException(cp);
|
||||
cmCTestOptionalLog(this->CTest, WARNING,
|
||||
"There was an exception: " << *retVal << std::endl,
|
||||
this->Quiet);
|
||||
}
|
||||
} else if (result == cmsysProcess_State_Expired) {
|
||||
cmCTestOptionalLog(this->CTest, WARNING,
|
||||
"There was a timeout" << std::endl, this->Quiet);
|
||||
} else if (result == cmsysProcess_State_Error) {
|
||||
// If there was an error running command, report that on the dashboard.
|
||||
cmCTestBuildErrorWarning errorwarning;
|
||||
errorwarning.LineNumber = 0;
|
||||
errorwarning.LogLine = 1;
|
||||
errorwarning.Text =
|
||||
cmStrCat("*** ERROR executing: ", cmsysProcess_GetErrorString(cp));
|
||||
errorwarning.PreContext.clear();
|
||||
errorwarning.PostContext.clear();
|
||||
errorwarning.Error = true;
|
||||
this->ErrorsAndWarnings.push_back(std::move(errorwarning));
|
||||
this->TotalErrors++;
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"There was an error: " << cmsysProcess_GetErrorString(cp)
|
||||
<< std::endl);
|
||||
}
|
||||
|
||||
return true;
|
||||
cmsysProcess_Delete(cp);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
|
@ -53,9 +53,9 @@ private:
|
||||
|
||||
//! Run command specialized for make and configure. Returns process status
|
||||
// and retVal is return value or exception.
|
||||
bool RunMakeCommand(const std::string& command, int* retVal, const char* dir,
|
||||
int timeout, std::ostream& ofs,
|
||||
Encoding encoding = cmProcessOutput::Auto);
|
||||
int RunMakeCommand(const std::string& command, int* retVal, const char* dir,
|
||||
int timeout, std::ostream& ofs,
|
||||
Encoding encoding = cmProcessOutput::Auto);
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <utility>
|
||||
|
||||
#include <cm/string_view>
|
||||
#include <cmext/algorithm>
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
@ -90,15 +89,18 @@ bool cmCTestCVS::UpdateImpl()
|
||||
}
|
||||
|
||||
// Run "cvs update" to update the work tree.
|
||||
std::vector<std::string> cvs_update;
|
||||
cvs_update.push_back(this->CommandLineTool);
|
||||
std::vector<char const*> cvs_update;
|
||||
cvs_update.push_back(this->CommandLineTool.c_str());
|
||||
cvs_update.push_back("-z3");
|
||||
cvs_update.push_back("update");
|
||||
cm::append(cvs_update, args);
|
||||
for (std::string const& arg : args) {
|
||||
cvs_update.push_back(arg.c_str());
|
||||
}
|
||||
cvs_update.push_back(nullptr);
|
||||
|
||||
UpdateParser out(this, "up-out> ");
|
||||
UpdateParser err(this, "up-err> ");
|
||||
return this->RunUpdateCommand(cvs_update, &out, &err);
|
||||
return this->RunUpdateCommand(cvs_update.data(), &out, &err);
|
||||
}
|
||||
|
||||
class cmCTestCVS::LogParser : public cmCTestVC::LineParser
|
||||
@ -219,8 +221,10 @@ void cmCTestCVS::LoadRevisions(std::string const& file, const char* branchFlag,
|
||||
cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
|
||||
|
||||
// Run "cvs log" to get revisions of this file on this branch.
|
||||
std::string cvs = this->CommandLineTool;
|
||||
std::vector<std::string> cvs_log = { cvs, "log", "-N", branchFlag, file };
|
||||
const char* cvs = this->CommandLineTool.c_str();
|
||||
const char* cvs_log[] = {
|
||||
cvs, "log", "-N", branchFlag, file.c_str(), nullptr
|
||||
};
|
||||
|
||||
LogParser out(this, "log-out> ", revisions);
|
||||
OutputLogger err(this->Log, "log-err> ");
|
||||
|
@ -45,7 +45,7 @@ int cmCTestConfigureHandler::ProcessHandler()
|
||||
auto elapsed_time_start = std::chrono::steady_clock::now();
|
||||
std::string output;
|
||||
int retVal = 0;
|
||||
bool res = false;
|
||||
int res = 0;
|
||||
if (!this->CTest->GetShowOnly()) {
|
||||
cmGeneratedFileStream os;
|
||||
if (!this->StartResultingXML(cmCTest::PartConfigure, "Configure", os)) {
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <ratio>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
@ -19,10 +18,9 @@
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/Glob.hxx"
|
||||
#include "cmsys/Process.h"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include "cm_fileno.hxx"
|
||||
|
||||
#include "cmCTest.h"
|
||||
#include "cmDuration.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
@ -35,7 +33,6 @@
|
||||
#include "cmParsePHPCoverage.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
#include "cmWorkingDirectory.h"
|
||||
#include "cmXMLWriter.h"
|
||||
|
||||
@ -43,6 +40,85 @@ class cmMakefile;
|
||||
|
||||
#define SAFEDIV(x, y) (((y) != 0) ? ((x) / (y)) : (0))
|
||||
|
||||
class cmCTestRunProcess
|
||||
{
|
||||
public:
|
||||
cmCTestRunProcess()
|
||||
{
|
||||
this->Process = cmsysProcess_New();
|
||||
this->PipeState = -1;
|
||||
this->TimeOut = cmDuration(-1);
|
||||
}
|
||||
~cmCTestRunProcess()
|
||||
{
|
||||
if (this->PipeState != -1 && this->PipeState != cmsysProcess_Pipe_None &&
|
||||
this->PipeState != cmsysProcess_Pipe_Timeout) {
|
||||
this->WaitForExit();
|
||||
}
|
||||
cmsysProcess_Delete(this->Process);
|
||||
}
|
||||
cmCTestRunProcess(const cmCTestRunProcess&) = delete;
|
||||
cmCTestRunProcess& operator=(const cmCTestRunProcess&) = delete;
|
||||
void SetCommand(const char* command)
|
||||
{
|
||||
this->CommandLineStrings.clear();
|
||||
this->CommandLineStrings.emplace_back(command);
|
||||
}
|
||||
void AddArgument(const char* arg)
|
||||
{
|
||||
if (arg) {
|
||||
this->CommandLineStrings.emplace_back(arg);
|
||||
}
|
||||
}
|
||||
void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; }
|
||||
void SetTimeout(cmDuration t) { this->TimeOut = t; }
|
||||
bool StartProcess()
|
||||
{
|
||||
std::vector<const char*> args;
|
||||
args.reserve(this->CommandLineStrings.size());
|
||||
for (std::string const& cl : this->CommandLineStrings) {
|
||||
args.push_back(cl.c_str());
|
||||
}
|
||||
args.push_back(nullptr); // null terminate
|
||||
cmsysProcess_SetCommand(this->Process, args.data());
|
||||
if (!this->WorkingDirectory.empty()) {
|
||||
cmsysProcess_SetWorkingDirectory(this->Process,
|
||||
this->WorkingDirectory.c_str());
|
||||
}
|
||||
|
||||
cmsysProcess_SetOption(this->Process, cmsysProcess_Option_HideWindow, 1);
|
||||
if (this->TimeOut >= cmDuration::zero()) {
|
||||
cmsysProcess_SetTimeout(this->Process, this->TimeOut.count());
|
||||
}
|
||||
cmsysProcess_Execute(this->Process);
|
||||
this->PipeState = cmsysProcess_GetState(this->Process);
|
||||
// if the process is running or exited return true
|
||||
return this->PipeState == cmsysProcess_State_Executing ||
|
||||
this->PipeState == cmsysProcess_State_Exited;
|
||||
}
|
||||
void SetStdoutFile(const char* fname)
|
||||
{
|
||||
cmsysProcess_SetPipeFile(this->Process, cmsysProcess_Pipe_STDOUT, fname);
|
||||
}
|
||||
void SetStderrFile(const char* fname)
|
||||
{
|
||||
cmsysProcess_SetPipeFile(this->Process, cmsysProcess_Pipe_STDERR, fname);
|
||||
}
|
||||
int WaitForExit(double* timeout = nullptr)
|
||||
{
|
||||
this->PipeState = cmsysProcess_WaitForExit(this->Process, timeout);
|
||||
return this->PipeState;
|
||||
}
|
||||
int GetProcessState() const { return this->PipeState; }
|
||||
|
||||
private:
|
||||
int PipeState;
|
||||
cmsysProcess* Process;
|
||||
std::vector<std::string> CommandLineStrings;
|
||||
std::string WorkingDirectory;
|
||||
cmDuration TimeOut;
|
||||
};
|
||||
|
||||
cmCTestCoverageHandler::cmCTestCoverageHandler() = default;
|
||||
|
||||
void cmCTestCoverageHandler::Initialize()
|
||||
@ -1864,35 +1940,34 @@ int cmCTestCoverageHandler::RunBullseyeCommand(
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find :" << cmd << "\n");
|
||||
return 0;
|
||||
}
|
||||
std::vector<std::string> args{ cmd };
|
||||
if (arg) {
|
||||
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"Run : " << program << " " << arg << "\n", this->Quiet);
|
||||
args.emplace_back(arg);
|
||||
} else {
|
||||
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"Run : " << program << "\n", this->Quiet);
|
||||
}
|
||||
// create a process object and start it
|
||||
cmUVProcessChainBuilder builder;
|
||||
cmCTestRunProcess runCoverageSrc;
|
||||
runCoverageSrc.SetCommand(program.c_str());
|
||||
runCoverageSrc.AddArgument(arg);
|
||||
std::string stdoutFile =
|
||||
cmStrCat(cont->BinaryDir, "/Testing/Temporary/",
|
||||
this->GetCTestInstance()->GetCurrentTag(), '-', cmd);
|
||||
std::string stderrFile = stdoutFile;
|
||||
stdoutFile += ".stdout";
|
||||
stderrFile += ".stderr";
|
||||
std::unique_ptr<FILE, int (*)(FILE*)> stdoutHandle(
|
||||
cmsys::SystemTools::Fopen(stdoutFile, "w"), fclose);
|
||||
std::unique_ptr<FILE, int (*)(FILE*)> stderrHandle(
|
||||
cmsys::SystemTools::Fopen(stderrFile, "w"), fclose);
|
||||
builder.AddCommand(args)
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT,
|
||||
cm_fileno(stdoutHandle.get()))
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR,
|
||||
cm_fileno(stderrHandle.get()));
|
||||
runCoverageSrc.SetStdoutFile(stdoutFile.c_str());
|
||||
runCoverageSrc.SetStderrFile(stderrFile.c_str());
|
||||
if (!runCoverageSrc.StartProcess()) {
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"Could not run : " << program << " " << arg << "\n"
|
||||
<< "kwsys process state : "
|
||||
<< runCoverageSrc.GetProcessState());
|
||||
return 0;
|
||||
}
|
||||
// since we set the output file names wait for it to end
|
||||
auto chain = builder.Start();
|
||||
chain.Wait();
|
||||
runCoverageSrc.WaitForExit();
|
||||
outputFile = stdoutFile;
|
||||
return 1;
|
||||
}
|
||||
|
@ -9,9 +9,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cmext/algorithm>
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/Process.h"
|
||||
|
||||
#include "cmCTest.h"
|
||||
#include "cmCTestVC.h"
|
||||
@ -19,7 +18,6 @@
|
||||
#include "cmProcessOutput.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major,
|
||||
@ -60,9 +58,9 @@ private:
|
||||
std::string cmCTestGIT::GetWorkingRevision()
|
||||
{
|
||||
// Run plumbing "git rev-list" to get work tree revision.
|
||||
std::string git = this->CommandLineTool;
|
||||
std::vector<std::string> git_rev_list = { git, "rev-list", "-n",
|
||||
"1", "HEAD", "--" };
|
||||
const char* git = this->CommandLineTool.c_str();
|
||||
const char* git_rev_list[] = { git, "rev-list", "-n", "1",
|
||||
"HEAD", "--", nullptr };
|
||||
std::string rev;
|
||||
OneLineParser out(this, "rl-out> ", rev);
|
||||
OutputLogger err(this->Log, "rl-err> ");
|
||||
@ -94,13 +92,13 @@ std::string cmCTestGIT::FindGitDir()
|
||||
std::string git_dir;
|
||||
|
||||
// Run "git rev-parse --git-dir" to locate the real .git directory.
|
||||
std::string git = this->CommandLineTool;
|
||||
std::vector<std::string> git_rev_parse = { git, "rev-parse", "--git-dir" };
|
||||
const char* git = this->CommandLineTool.c_str();
|
||||
char const* git_rev_parse[] = { git, "rev-parse", "--git-dir", nullptr };
|
||||
std::string git_dir_line;
|
||||
OneLineParser rev_parse_out(this, "rev-parse-out> ", git_dir_line);
|
||||
OutputLogger rev_parse_err(this->Log, "rev-parse-err> ");
|
||||
if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err,
|
||||
std::string{}, cmProcessOutput::UTF8)) {
|
||||
if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, nullptr,
|
||||
cmProcessOutput::UTF8)) {
|
||||
git_dir = git_dir_line;
|
||||
}
|
||||
if (git_dir.empty()) {
|
||||
@ -119,10 +117,11 @@ std::string cmCTestGIT::FindGitDir()
|
||||
std::string cygpath_exe =
|
||||
cmStrCat(cmSystemTools::GetFilenamePath(git), "/cygpath.exe");
|
||||
if (cmSystemTools::FileExists(cygpath_exe)) {
|
||||
std::vector<std::string> cygpath = { cygpath_exe, "-w", git_dir };
|
||||
char const* cygpath[] = { cygpath_exe.c_str(), "-w", git_dir.c_str(),
|
||||
0 };
|
||||
OneLineParser cygpath_out(this, "cygpath-out> ", git_dir_line);
|
||||
OutputLogger cygpath_err(this->Log, "cygpath-err> ");
|
||||
if (this->RunChild(cygpath, &cygpath_out, &cygpath_err, std::string{},
|
||||
if (this->RunChild(cygpath, &cygpath_out, &cygpath_err, nullptr,
|
||||
cmProcessOutput::UTF8)) {
|
||||
git_dir = git_dir_line;
|
||||
}
|
||||
@ -137,12 +136,12 @@ std::string cmCTestGIT::FindTopDir()
|
||||
std::string top_dir = this->SourceDirectory;
|
||||
|
||||
// Run "git rev-parse --show-cdup" to locate the top of the tree.
|
||||
std::string git = this->CommandLineTool;
|
||||
std::vector<std::string> git_rev_parse = { git, "rev-parse", "--show-cdup" };
|
||||
const char* git = this->CommandLineTool.c_str();
|
||||
char const* git_rev_parse[] = { git, "rev-parse", "--show-cdup", nullptr };
|
||||
std::string cdup;
|
||||
OneLineParser rev_parse_out(this, "rev-parse-out> ", cdup);
|
||||
OutputLogger rev_parse_err(this->Log, "rev-parse-err> ");
|
||||
if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, "",
|
||||
if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, nullptr,
|
||||
cmProcessOutput::UTF8) &&
|
||||
!cdup.empty()) {
|
||||
top_dir += "/";
|
||||
@ -154,10 +153,10 @@ std::string cmCTestGIT::FindTopDir()
|
||||
|
||||
bool cmCTestGIT::UpdateByFetchAndReset()
|
||||
{
|
||||
std::string git = this->CommandLineTool;
|
||||
const char* git = this->CommandLineTool.c_str();
|
||||
|
||||
// Use "git fetch" to get remote commits.
|
||||
std::vector<std::string> git_fetch;
|
||||
std::vector<char const*> git_fetch;
|
||||
git_fetch.push_back(git);
|
||||
git_fetch.push_back("fetch");
|
||||
|
||||
@ -167,12 +166,17 @@ bool cmCTestGIT::UpdateByFetchAndReset()
|
||||
opts = this->CTest->GetCTestConfiguration("GITUpdateOptions");
|
||||
}
|
||||
std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
|
||||
cm::append(git_fetch, args);
|
||||
for (std::string const& arg : args) {
|
||||
git_fetch.push_back(arg.c_str());
|
||||
}
|
||||
|
||||
// Sentinel argument.
|
||||
git_fetch.push_back(nullptr);
|
||||
|
||||
// Fetch upstream refs.
|
||||
OutputLogger fetch_out(this->Log, "fetch-out> ");
|
||||
OutputLogger fetch_err(this->Log, "fetch-err> ");
|
||||
if (!this->RunUpdateCommand(git_fetch, &fetch_out, &fetch_err)) {
|
||||
if (!this->RunUpdateCommand(git_fetch.data(), &fetch_out, &fetch_err)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -203,22 +207,25 @@ bool cmCTestGIT::UpdateByFetchAndReset()
|
||||
}
|
||||
|
||||
// Reset the local branch to point at that tracked from upstream.
|
||||
std::vector<std::string> git_reset = { git, "reset", "--hard", sha1 };
|
||||
char const* git_reset[] = { git, "reset", "--hard", sha1.c_str(), nullptr };
|
||||
OutputLogger reset_out(this->Log, "reset-out> ");
|
||||
OutputLogger reset_err(this->Log, "reset-err> ");
|
||||
return this->RunChild(git_reset, &reset_out, &reset_err);
|
||||
return this->RunChild(&git_reset[0], &reset_out, &reset_err);
|
||||
}
|
||||
|
||||
bool cmCTestGIT::UpdateByCustom(std::string const& custom)
|
||||
{
|
||||
cmList git_custom_command{ custom, cmList::EmptyElements::Yes };
|
||||
std::vector<std::string> git_custom;
|
||||
git_custom.reserve(git_custom_command.size());
|
||||
cm::append(git_custom, git_custom_command);
|
||||
std::vector<char const*> git_custom;
|
||||
git_custom.reserve(git_custom_command.size() + 1);
|
||||
for (std::string const& i : git_custom_command) {
|
||||
git_custom.push_back(i.c_str());
|
||||
}
|
||||
git_custom.push_back(nullptr);
|
||||
|
||||
OutputLogger custom_out(this->Log, "custom-out> ");
|
||||
OutputLogger custom_err(this->Log, "custom-err> ");
|
||||
return this->RunUpdateCommand(git_custom, &custom_out, &custom_err);
|
||||
return this->RunUpdateCommand(git_custom.data(), &custom_out, &custom_err);
|
||||
}
|
||||
|
||||
bool cmCTestGIT::UpdateInternal()
|
||||
@ -237,14 +244,13 @@ bool cmCTestGIT::UpdateImpl()
|
||||
}
|
||||
|
||||
std::string top_dir = this->FindTopDir();
|
||||
std::string git = this->CommandLineTool;
|
||||
std::string recursive = "--recursive";
|
||||
std::string sync_recursive = "--recursive";
|
||||
const char* git = this->CommandLineTool.c_str();
|
||||
const char* recursive = "--recursive";
|
||||
const char* sync_recursive = "--recursive";
|
||||
|
||||
// Git < 1.6.5 did not support submodule --recursive
|
||||
bool support_recursive = true;
|
||||
if (this->GetGitVersion() < cmCTestGITVersion(1, 6, 5, 0)) {
|
||||
support_recursive = false;
|
||||
recursive = nullptr;
|
||||
// No need to require >= 1.6.5 if there are no submodules.
|
||||
if (cmSystemTools::FileExists(top_dir + "/.gitmodules")) {
|
||||
this->Log << "Git < 1.6.5 cannot update submodules recursively\n";
|
||||
@ -252,9 +258,8 @@ bool cmCTestGIT::UpdateImpl()
|
||||
}
|
||||
|
||||
// Git < 1.8.1 did not support sync --recursive
|
||||
bool support_sync_recursive = true;
|
||||
if (this->GetGitVersion() < cmCTestGITVersion(1, 8, 1, 0)) {
|
||||
support_sync_recursive = false;
|
||||
sync_recursive = nullptr;
|
||||
// No need to require >= 1.8.1 if there are no submodules.
|
||||
if (cmSystemTools::FileExists(top_dir + "/.gitmodules")) {
|
||||
this->Log << "Git < 1.8.1 cannot synchronize submodules recursively\n";
|
||||
@ -269,39 +274,35 @@ bool cmCTestGIT::UpdateImpl()
|
||||
std::string init_submodules =
|
||||
this->CTest->GetCTestConfiguration("GITInitSubmodules");
|
||||
if (cmIsOn(init_submodules)) {
|
||||
std::vector<std::string> git_submodule_init = { git, "submodule", "init" };
|
||||
char const* git_submodule_init[] = { git, "submodule", "init", nullptr };
|
||||
ret = this->RunChild(git_submodule_init, &submodule_out, &submodule_err,
|
||||
top_dir);
|
||||
top_dir.c_str());
|
||||
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> git_submodule_sync = { git, "submodule", "sync" };
|
||||
if (support_sync_recursive) {
|
||||
git_submodule_sync.push_back(sync_recursive);
|
||||
}
|
||||
char const* git_submodule_sync[] = { git, "submodule", "sync",
|
||||
sync_recursive, nullptr };
|
||||
ret = this->RunChild(git_submodule_sync, &submodule_out, &submodule_err,
|
||||
top_dir);
|
||||
top_dir.c_str());
|
||||
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> git_submodule = { git, "submodule", "update" };
|
||||
if (support_recursive) {
|
||||
git_submodule.push_back(recursive);
|
||||
}
|
||||
char const* git_submodule[] = { git, "submodule", "update", recursive,
|
||||
nullptr };
|
||||
return this->RunChild(git_submodule, &submodule_out, &submodule_err,
|
||||
top_dir);
|
||||
top_dir.c_str());
|
||||
}
|
||||
|
||||
unsigned int cmCTestGIT::GetGitVersion()
|
||||
{
|
||||
if (!this->CurrentGitVersion) {
|
||||
std::string git = this->CommandLineTool;
|
||||
std::vector<std::string> git_version = { git, "--version" };
|
||||
const char* git = this->CommandLineTool.c_str();
|
||||
char const* git_version[] = { git, "--version", nullptr };
|
||||
std::string version;
|
||||
OneLineParser version_out(this, "version-out> ", version);
|
||||
OutputLogger version_err(this->Log, "version-err> ");
|
||||
@ -604,49 +605,50 @@ bool cmCTestGIT::LoadRevisions()
|
||||
{
|
||||
// Use 'git rev-list ... | git diff-tree ...' to get revisions.
|
||||
std::string range = this->OldRevision + ".." + this->NewRevision;
|
||||
std::string git = this->CommandLineTool;
|
||||
std::vector<std::string> git_rev_list = { git, "rev-list", "--reverse",
|
||||
range, "--" };
|
||||
std::vector<std::string> git_diff_tree = {
|
||||
git, "diff-tree", "--stdin", "--always",
|
||||
"-z", "-r", "--pretty=raw", "--encoding=utf-8"
|
||||
const char* git = this->CommandLineTool.c_str();
|
||||
const char* git_rev_list[] = { git, "rev-list", "--reverse",
|
||||
range.c_str(), "--", nullptr };
|
||||
const char* git_diff_tree[] = {
|
||||
git, "diff-tree", "--stdin", "--always", "-z",
|
||||
"-r", "--pretty=raw", "--encoding=utf-8", nullptr
|
||||
};
|
||||
this->Log << cmCTestGIT::ComputeCommandLine(git_rev_list) << " | "
|
||||
<< cmCTestGIT::ComputeCommandLine(git_diff_tree) << "\n";
|
||||
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand(git_rev_list)
|
||||
.AddCommand(git_diff_tree)
|
||||
.SetWorkingDirectory(this->SourceDirectory);
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
cmsysProcess_AddCommand(cp, git_rev_list);
|
||||
cmsysProcess_AddCommand(cp, git_diff_tree);
|
||||
cmsysProcess_SetWorkingDirectory(cp, this->SourceDirectory.c_str());
|
||||
|
||||
CommitParser out(this, "dt-out> ");
|
||||
OutputLogger err(this->Log, "dt-err> ");
|
||||
cmCTestGIT::RunProcess(builder, &out, &err, cmProcessOutput::UTF8);
|
||||
cmCTestGIT::RunProcess(cp, &out, &err, cmProcessOutput::UTF8);
|
||||
|
||||
// Send one extra zero-byte to terminate the last record.
|
||||
out.Process("", 1);
|
||||
|
||||
cmsysProcess_Delete(cp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmCTestGIT::LoadModifications()
|
||||
{
|
||||
std::string git = this->CommandLineTool;
|
||||
const char* git = this->CommandLineTool.c_str();
|
||||
|
||||
// Use 'git update-index' to refresh the index w.r.t. the work tree.
|
||||
std::vector<std::string> git_update_index = { git, "update-index",
|
||||
"--refresh" };
|
||||
const char* git_update_index[] = { git, "update-index", "--refresh",
|
||||
nullptr };
|
||||
OutputLogger ui_out(this->Log, "ui-out> ");
|
||||
OutputLogger ui_err(this->Log, "ui-err> ");
|
||||
this->RunChild(git_update_index, &ui_out, &ui_err, "",
|
||||
this->RunChild(git_update_index, &ui_out, &ui_err, nullptr,
|
||||
cmProcessOutput::UTF8);
|
||||
|
||||
// Use 'git diff-index' to get modified files.
|
||||
std::vector<std::string> git_diff_index = { git, "diff-index", "-z", "HEAD",
|
||||
"--" };
|
||||
const char* git_diff_index[] = { git, "diff-index", "-z",
|
||||
"HEAD", "--", nullptr };
|
||||
DiffParser out(this, "di-out> ");
|
||||
OutputLogger err(this->Log, "di-err> ");
|
||||
this->RunChild(git_diff_index, &out, &err, "", cmProcessOutput::UTF8);
|
||||
this->RunChild(git_diff_index, &out, &err, nullptr, cmProcessOutput::UTF8);
|
||||
|
||||
for (Change const& c : out.Changes) {
|
||||
this->DoModification(PathModified, c.Path);
|
||||
|
@ -95,8 +95,8 @@ private:
|
||||
std::string cmCTestHG::GetWorkingRevision()
|
||||
{
|
||||
// Run plumbing "hg identify" to get work tree revision.
|
||||
std::string hg = this->CommandLineTool;
|
||||
std::vector<std::string> hg_identify = { hg, "identify", "-i" };
|
||||
const char* hg = this->CommandLineTool.c_str();
|
||||
const char* hg_identify[] = { hg, "identify", "-i", nullptr };
|
||||
std::string rev;
|
||||
IdentifyParser out(this, "rev-out> ", rev);
|
||||
OutputLogger err(this->Log, "rev-err> ");
|
||||
@ -127,16 +127,16 @@ bool cmCTestHG::UpdateImpl()
|
||||
{
|
||||
// Use "hg pull" followed by "hg update" to update the working tree.
|
||||
{
|
||||
std::string hg = this->CommandLineTool;
|
||||
std::vector<std::string> hg_pull = { hg, "pull", "-v" };
|
||||
const char* hg = this->CommandLineTool.c_str();
|
||||
const char* hg_pull[] = { hg, "pull", "-v", nullptr };
|
||||
OutputLogger out(this->Log, "pull-out> ");
|
||||
OutputLogger err(this->Log, "pull-err> ");
|
||||
this->RunChild(hg_pull, &out, &err);
|
||||
this->RunChild(&hg_pull[0], &out, &err);
|
||||
}
|
||||
|
||||
// TODO: if(this->CTest->GetTestModel() == cmCTest::NIGHTLY)
|
||||
|
||||
std::vector<std::string> hg_update;
|
||||
std::vector<char const*> hg_update;
|
||||
hg_update.push_back(this->CommandLineTool.c_str());
|
||||
hg_update.push_back("update");
|
||||
hg_update.push_back("-v");
|
||||
@ -147,11 +147,16 @@ bool cmCTestHG::UpdateImpl()
|
||||
opts = this->CTest->GetCTestConfiguration("HGUpdateOptions");
|
||||
}
|
||||
std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
|
||||
cm::append(hg_update, args);
|
||||
for (std::string const& arg : args) {
|
||||
hg_update.push_back(arg.c_str());
|
||||
}
|
||||
|
||||
// Sentinel argument.
|
||||
hg_update.push_back(nullptr);
|
||||
|
||||
OutputLogger out(this->Log, "update-out> ");
|
||||
OutputLogger err(this->Log, "update-err> ");
|
||||
return this->RunUpdateCommand(hg_update, &out, &err);
|
||||
return this->RunUpdateCommand(hg_update.data(), &out, &err);
|
||||
}
|
||||
|
||||
class cmCTestHG::LogParser
|
||||
@ -272,8 +277,8 @@ bool cmCTestHG::LoadRevisions()
|
||||
// the project has spaces in the path. Also, they may not have
|
||||
// proper XML escapes.
|
||||
std::string range = this->OldRevision + ":" + this->NewRevision;
|
||||
std::string hg = this->CommandLineTool;
|
||||
std::string hgXMLTemplate = "<logentry\n"
|
||||
const char* hg = this->CommandLineTool.c_str();
|
||||
const char* hgXMLTemplate = "<logentry\n"
|
||||
" revision=\"{node|short}\">\n"
|
||||
" <author>{author|person}</author>\n"
|
||||
" <email>{author|email}</email>\n"
|
||||
@ -283,8 +288,10 @@ bool cmCTestHG::LoadRevisions()
|
||||
" <file_adds>{file_adds}</file_adds>\n"
|
||||
" <file_dels>{file_dels}</file_dels>\n"
|
||||
"</logentry>\n";
|
||||
std::vector<std::string> hg_log = { hg, "log", "--removed", "-r",
|
||||
range, "--template", hgXMLTemplate };
|
||||
const char* hg_log[] = {
|
||||
hg, "log", "--removed", "-r", range.c_str(),
|
||||
"--template", hgXMLTemplate, nullptr
|
||||
};
|
||||
|
||||
LogParser out(this, "log-out> ");
|
||||
out.Process("<?xml version=\"1.0\"?>\n"
|
||||
@ -298,8 +305,8 @@ bool cmCTestHG::LoadRevisions()
|
||||
bool cmCTestHG::LoadModifications()
|
||||
{
|
||||
// Use 'hg status' to get modified files.
|
||||
std::string hg = this->CommandLineTool;
|
||||
std::vector<std::string> hg_status = { hg, "status" };
|
||||
const char* hg = this->CommandLineTool.c_str();
|
||||
const char* hg_status[] = { hg, "status", nullptr };
|
||||
StatusParser out(this, "status-out> ");
|
||||
OutputLogger err(this->Log, "status-err> ");
|
||||
this->RunChild(hg_status, &out, &err);
|
||||
|
@ -2,19 +2,13 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmCTestLaunch.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/Process.h"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include "cm_fileno.hxx"
|
||||
|
||||
#include "cmCTestLaunchReporter.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
@ -23,9 +17,6 @@
|
||||
#include "cmStateSnapshot.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVHandlePtr.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
#include "cmUVStream.h"
|
||||
#include "cmake.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -37,6 +28,8 @@
|
||||
|
||||
cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv)
|
||||
{
|
||||
this->Process = nullptr;
|
||||
|
||||
if (!this->ParseArguments(argc, argv)) {
|
||||
return;
|
||||
}
|
||||
@ -47,9 +40,13 @@ cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv)
|
||||
this->ScrapeRulesLoaded = false;
|
||||
this->HaveOut = false;
|
||||
this->HaveErr = false;
|
||||
this->Process = cmsysProcess_New();
|
||||
}
|
||||
|
||||
cmCTestLaunch::~cmCTestLaunch() = default;
|
||||
cmCTestLaunch::~cmCTestLaunch()
|
||||
{
|
||||
cmsysProcess_Delete(this->Process);
|
||||
}
|
||||
|
||||
bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv)
|
||||
{
|
||||
@ -116,12 +113,15 @@ bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv)
|
||||
|
||||
// Extract the real command line.
|
||||
if (arg0) {
|
||||
for (int i = 0; i < argc - arg0; ++i) {
|
||||
this->RealArgV.emplace_back((argv + arg0)[i]);
|
||||
this->HandleRealArg((argv + arg0)[i]);
|
||||
this->RealArgC = argc - arg0;
|
||||
this->RealArgV = argv + arg0;
|
||||
for (int i = 0; i < this->RealArgC; ++i) {
|
||||
this->HandleRealArg(this->RealArgV[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
this->RealArgC = 0;
|
||||
this->RealArgV = nullptr;
|
||||
std::cerr << "No launch/command separator ('--') found!\n";
|
||||
return false;
|
||||
}
|
||||
@ -151,22 +151,17 @@ void cmCTestLaunch::RunChild()
|
||||
}
|
||||
|
||||
// Prepare to run the real command.
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand(this->RealArgV);
|
||||
cmsysProcess* cp = this->Process;
|
||||
cmsysProcess_SetCommand(cp, this->RealArgV);
|
||||
|
||||
cmsys::ofstream fout;
|
||||
cmsys::ofstream ferr;
|
||||
if (this->Reporter.Passthru) {
|
||||
// In passthru mode we just share the output pipes.
|
||||
builder
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT,
|
||||
cm_fileno(stdout))
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR,
|
||||
cm_fileno(stderr));
|
||||
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
|
||||
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
|
||||
} else {
|
||||
// In full mode we record the child output pipes to log files.
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
|
||||
fout.open(this->Reporter.LogOut.c_str(), std::ios::out | std::ios::binary);
|
||||
ferr.open(this->Reporter.LogErr.c_str(), std::ios::out | std::ios::binary);
|
||||
}
|
||||
@ -179,65 +174,51 @@ void cmCTestLaunch::RunChild()
|
||||
#endif
|
||||
|
||||
// Run the real command.
|
||||
auto chain = builder.Start();
|
||||
cmsysProcess_Execute(cp);
|
||||
|
||||
// Record child stdout and stderr if necessary.
|
||||
cm::uv_pipe_ptr outPipe;
|
||||
cm::uv_pipe_ptr errPipe;
|
||||
bool outFinished = true;
|
||||
bool errFinished = true;
|
||||
cmProcessOutput processOutput;
|
||||
std::unique_ptr<cmUVStreamReadHandle> outputHandle;
|
||||
std::unique_ptr<cmUVStreamReadHandle> errorHandle;
|
||||
if (!this->Reporter.Passthru) {
|
||||
auto beginRead = [&chain, &processOutput](
|
||||
cm::uv_pipe_ptr& pipe, int stream, std::ostream& out,
|
||||
cmsys::ofstream& file, bool& haveData, bool& finished,
|
||||
int id) -> std::unique_ptr<cmUVStreamReadHandle> {
|
||||
pipe.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(pipe, stream);
|
||||
finished = false;
|
||||
return cmUVStreamRead(
|
||||
pipe,
|
||||
[&processOutput, &out, &file, id, &haveData](std::vector<char> data) {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata, id);
|
||||
file.write(strdata.c_str(), strdata.size());
|
||||
out.write(strdata.c_str(), strdata.size());
|
||||
haveData = true;
|
||||
},
|
||||
[&processOutput, &out, &file, &finished, id]() {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(std::string(), strdata, id);
|
||||
if (!strdata.empty()) {
|
||||
file.write(strdata.c_str(), strdata.size());
|
||||
out.write(strdata.c_str(), strdata.size());
|
||||
}
|
||||
finished = true;
|
||||
});
|
||||
};
|
||||
outputHandle = beginRead(outPipe, chain.OutputStream(), std::cout, fout,
|
||||
this->HaveOut, outFinished, 1);
|
||||
errorHandle = beginRead(errPipe, chain.ErrorStream(), std::cerr, ferr,
|
||||
this->HaveErr, errFinished, 2);
|
||||
char* data = nullptr;
|
||||
int length = 0;
|
||||
cmProcessOutput processOutput;
|
||||
std::string strdata;
|
||||
while (int p = cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
|
||||
if (p == cmsysProcess_Pipe_STDOUT) {
|
||||
processOutput.DecodeText(data, length, strdata, 1);
|
||||
fout.write(strdata.c_str(), strdata.size());
|
||||
std::cout.write(strdata.c_str(), strdata.size());
|
||||
this->HaveOut = true;
|
||||
} else if (p == cmsysProcess_Pipe_STDERR) {
|
||||
processOutput.DecodeText(data, length, strdata, 2);
|
||||
ferr.write(strdata.c_str(), strdata.size());
|
||||
std::cerr.write(strdata.c_str(), strdata.size());
|
||||
this->HaveErr = true;
|
||||
}
|
||||
}
|
||||
processOutput.DecodeText(std::string(), strdata, 1);
|
||||
if (!strdata.empty()) {
|
||||
fout.write(strdata.c_str(), strdata.size());
|
||||
std::cout.write(strdata.c_str(), strdata.size());
|
||||
}
|
||||
processOutput.DecodeText(std::string(), strdata, 2);
|
||||
if (!strdata.empty()) {
|
||||
ferr.write(strdata.c_str(), strdata.size());
|
||||
std::cerr.write(strdata.c_str(), strdata.size());
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the real command to finish.
|
||||
while (!(chain.Finished() && outFinished && errFinished)) {
|
||||
uv_run(&chain.GetLoop(), UV_RUN_ONCE);
|
||||
}
|
||||
this->Reporter.Status = chain.GetStatus(0);
|
||||
if (this->Reporter.Status.GetException().first ==
|
||||
cmUVProcessChain::ExceptionCode::Spawn) {
|
||||
this->Reporter.ExitCode = 1;
|
||||
} else {
|
||||
this->Reporter.ExitCode =
|
||||
static_cast<int>(this->Reporter.Status.ExitStatus);
|
||||
}
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
this->Reporter.ExitCode = cmsysProcess_GetExitValue(cp);
|
||||
}
|
||||
|
||||
int cmCTestLaunch::Run()
|
||||
{
|
||||
if (!this->Process) {
|
||||
std::cerr << "Could not allocate cmsysProcess instance!\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->RunChild();
|
||||
|
||||
if (this->CheckResults()) {
|
||||
@ -245,6 +226,7 @@ int cmCTestLaunch::Run()
|
||||
}
|
||||
|
||||
this->LoadConfig();
|
||||
this->Reporter.Process = this->Process;
|
||||
this->Reporter.WriteXML();
|
||||
|
||||
return this->Reporter.ExitCode;
|
||||
|
@ -43,12 +43,15 @@ private:
|
||||
bool ParseArguments(int argc, const char* const* argv);
|
||||
|
||||
// The real command line appearing after launcher arguments.
|
||||
std::vector<std::string> RealArgV;
|
||||
int RealArgC;
|
||||
const char* const* RealArgV;
|
||||
|
||||
// The real command line after response file expansion.
|
||||
std::vector<std::string> RealArgs;
|
||||
void HandleRealArg(const char* arg);
|
||||
|
||||
struct cmsysProcess_s* Process;
|
||||
|
||||
// Whether or not any data have been written to stdout or stderr.
|
||||
bool HaveOut;
|
||||
bool HaveErr;
|
||||
|
@ -2,9 +2,8 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmCTestLaunchReporter.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/Process.h"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include "cmCryptoHash.h"
|
||||
@ -23,7 +22,6 @@
|
||||
cmCTestLaunchReporter::cmCTestLaunchReporter()
|
||||
{
|
||||
this->Passthru = true;
|
||||
this->Status.Finished = true;
|
||||
this->ExitCode = 1;
|
||||
this->CWD = cmSystemTools::GetCurrentWorkingDirectory();
|
||||
|
||||
@ -233,23 +231,35 @@ void cmCTestLaunchReporter::WriteXMLResult(cmXMLElement& e2)
|
||||
|
||||
// ExitCondition
|
||||
cmXMLElement e4(e3, "ExitCondition");
|
||||
if (this->Status.Finished) {
|
||||
auto exception = this->Status.GetException();
|
||||
switch (exception.first) {
|
||||
case cmUVProcessChain::ExceptionCode::None:
|
||||
e4.Content(this->ExitCode);
|
||||
break;
|
||||
case cmUVProcessChain::ExceptionCode::Spawn:
|
||||
e4.Content("Error administrating child process: ");
|
||||
e4.Content(exception.second);
|
||||
break;
|
||||
default:
|
||||
e4.Content("Terminated abnormally: ");
|
||||
e4.Content(exception.second);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
e4.Content("Killed when timeout expired");
|
||||
cmsysProcess* cp = this->Process;
|
||||
switch (cmsysProcess_GetState(cp)) {
|
||||
case cmsysProcess_State_Starting:
|
||||
e4.Content("No process has been executed");
|
||||
break;
|
||||
case cmsysProcess_State_Executing:
|
||||
e4.Content("The process is still executing");
|
||||
break;
|
||||
case cmsysProcess_State_Disowned:
|
||||
e4.Content("Disowned");
|
||||
break;
|
||||
case cmsysProcess_State_Killed:
|
||||
e4.Content("Killed by parent");
|
||||
break;
|
||||
|
||||
case cmsysProcess_State_Expired:
|
||||
e4.Content("Killed when timeout expired");
|
||||
break;
|
||||
case cmsysProcess_State_Exited:
|
||||
e4.Content(this->ExitCode);
|
||||
break;
|
||||
case cmsysProcess_State_Exception:
|
||||
e4.Content("Terminated abnormally: ");
|
||||
e4.Content(cmsysProcess_GetExceptionString(cp));
|
||||
break;
|
||||
case cmsysProcess_State_Error:
|
||||
e4.Content("Error administrating child process: ");
|
||||
e4.Content(cmsysProcess_GetErrorString(cp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include "cmUVProcessChain.h"
|
||||
|
||||
class cmXMLElement;
|
||||
|
||||
/** \class cmCTestLaunchReporter
|
||||
@ -50,7 +48,7 @@ public:
|
||||
void ComputeFileNames();
|
||||
|
||||
bool Passthru;
|
||||
cmUVProcessChain::Status Status;
|
||||
struct cmsysProcess_s* Process;
|
||||
int ExitCode;
|
||||
|
||||
// Temporary log files for stdout and stderr of real command.
|
||||
|
@ -149,16 +149,17 @@ cmCTestP4::User cmCTestP4::GetUserData(const std::string& username)
|
||||
auto it = this->Users.find(username);
|
||||
|
||||
if (it == this->Users.end()) {
|
||||
std::vector<std::string> p4_users;
|
||||
std::vector<char const*> p4_users;
|
||||
this->SetP4Options(p4_users);
|
||||
p4_users.push_back("users");
|
||||
p4_users.push_back("-m");
|
||||
p4_users.push_back("1");
|
||||
p4_users.push_back(username);
|
||||
p4_users.push_back(username.c_str());
|
||||
p4_users.push_back(nullptr);
|
||||
|
||||
UserParser out(this, "users-out> ");
|
||||
OutputLogger err(this->Log, "users-err> ");
|
||||
this->RunChild(p4_users, &out, &err);
|
||||
this->RunChild(p4_users.data(), &out, &err);
|
||||
|
||||
// The user should now be added to the map. Search again.
|
||||
it = this->Users.find(username);
|
||||
@ -302,10 +303,10 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
void cmCTestP4::SetP4Options(std::vector<std::string>& CommandOptions)
|
||||
void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions)
|
||||
{
|
||||
if (this->P4Options.empty()) {
|
||||
std::string p4 = this->CommandLineTool;
|
||||
const char* p4 = this->CommandLineTool.c_str();
|
||||
this->P4Options.emplace_back(p4);
|
||||
|
||||
// The CTEST_P4_CLIENT variable sets the P4 client used when issuing
|
||||
@ -327,12 +328,15 @@ void cmCTestP4::SetP4Options(std::vector<std::string>& CommandOptions)
|
||||
cm::append(this->P4Options, cmSystemTools::ParseArguments(opts));
|
||||
}
|
||||
|
||||
CommandOptions = this->P4Options;
|
||||
CommandOptions.clear();
|
||||
for (std::string const& o : this->P4Options) {
|
||||
CommandOptions.push_back(o.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string cmCTestP4::GetWorkingRevision()
|
||||
{
|
||||
std::vector<std::string> p4_identify;
|
||||
std::vector<char const*> p4_identify;
|
||||
this->SetP4Options(p4_identify);
|
||||
|
||||
p4_identify.push_back("changes");
|
||||
@ -341,13 +345,14 @@ std::string cmCTestP4::GetWorkingRevision()
|
||||
p4_identify.push_back("-t");
|
||||
|
||||
std::string source = this->SourceDirectory + "/...#have";
|
||||
p4_identify.push_back(source);
|
||||
p4_identify.push_back(source.c_str());
|
||||
p4_identify.push_back(nullptr);
|
||||
|
||||
std::string rev;
|
||||
IdentifyParser out(this, "p4_changes-out> ", rev);
|
||||
OutputLogger err(this->Log, "p4_changes-err> ");
|
||||
|
||||
bool result = this->RunChild(p4_identify, &out, &err);
|
||||
bool result = this->RunChild(p4_identify.data(), &out, &err);
|
||||
|
||||
// If there was a problem contacting the server return "<unknown>"
|
||||
if (!result) {
|
||||
@ -383,7 +388,7 @@ bool cmCTestP4::NoteNewRevision()
|
||||
|
||||
bool cmCTestP4::LoadRevisions()
|
||||
{
|
||||
std::vector<std::string> p4_changes;
|
||||
std::vector<char const*> p4_changes;
|
||||
this->SetP4Options(p4_changes);
|
||||
|
||||
// Use 'p4 changes ...@old,new' to get a list of changelists
|
||||
@ -404,36 +409,38 @@ bool cmCTestP4::LoadRevisions()
|
||||
.append(this->NewRevision);
|
||||
|
||||
p4_changes.push_back("changes");
|
||||
p4_changes.push_back(range);
|
||||
p4_changes.push_back(range.c_str());
|
||||
p4_changes.push_back(nullptr);
|
||||
|
||||
ChangesParser out(this, "p4_changes-out> ");
|
||||
OutputLogger err(this->Log, "p4_changes-err> ");
|
||||
|
||||
this->ChangeLists.clear();
|
||||
this->RunChild(p4_changes, &out, &err);
|
||||
this->RunChild(p4_changes.data(), &out, &err);
|
||||
|
||||
if (this->ChangeLists.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// p4 describe -s ...@1111111,2222222
|
||||
std::vector<std::string> p4_describe;
|
||||
std::vector<char const*> p4_describe;
|
||||
for (std::string const& i : cmReverseRange(this->ChangeLists)) {
|
||||
this->SetP4Options(p4_describe);
|
||||
p4_describe.push_back("describe");
|
||||
p4_describe.push_back("-s");
|
||||
p4_describe.push_back(i);
|
||||
p4_describe.push_back(i.c_str());
|
||||
p4_describe.push_back(nullptr);
|
||||
|
||||
DescribeParser outDescribe(this, "p4_describe-out> ");
|
||||
OutputLogger errDescribe(this->Log, "p4_describe-err> ");
|
||||
this->RunChild(p4_describe, &outDescribe, &errDescribe);
|
||||
this->RunChild(p4_describe.data(), &outDescribe, &errDescribe);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmCTestP4::LoadModifications()
|
||||
{
|
||||
std::vector<std::string> p4_diff;
|
||||
std::vector<char const*> p4_diff;
|
||||
this->SetP4Options(p4_diff);
|
||||
|
||||
p4_diff.push_back("diff");
|
||||
@ -441,11 +448,12 @@ bool cmCTestP4::LoadModifications()
|
||||
// Ideally we would use -Od but not all clients support it
|
||||
p4_diff.push_back("-dn");
|
||||
std::string source = this->SourceDirectory + "/...";
|
||||
p4_diff.push_back(source);
|
||||
p4_diff.push_back(source.c_str());
|
||||
p4_diff.push_back(nullptr);
|
||||
|
||||
DiffParser out(this, "p4_diff-out> ");
|
||||
OutputLogger err(this->Log, "p4_diff-err> ");
|
||||
this->RunChild(p4_diff, &out, &err);
|
||||
this->RunChild(p4_diff.data(), &out, &err);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -453,14 +461,17 @@ bool cmCTestP4::UpdateCustom(const std::string& custom)
|
||||
{
|
||||
cmList p4_custom_command{ custom, cmList::EmptyElements::Yes };
|
||||
|
||||
std::vector<std::string> p4_custom;
|
||||
p4_custom.reserve(p4_custom_command.size());
|
||||
cm::append(p4_custom, p4_custom_command);
|
||||
std::vector<char const*> p4_custom;
|
||||
p4_custom.reserve(p4_custom_command.size() + 1);
|
||||
for (std::string const& i : p4_custom_command) {
|
||||
p4_custom.push_back(i.c_str());
|
||||
}
|
||||
p4_custom.push_back(nullptr);
|
||||
|
||||
OutputLogger custom_out(this->Log, "p4_customsync-out> ");
|
||||
OutputLogger custom_err(this->Log, "p4_customsync-err> ");
|
||||
|
||||
return this->RunUpdateCommand(p4_custom, &custom_out, &custom_err);
|
||||
return this->RunUpdateCommand(p4_custom.data(), &custom_out, &custom_err);
|
||||
}
|
||||
|
||||
bool cmCTestP4::UpdateImpl()
|
||||
@ -477,7 +488,7 @@ bool cmCTestP4::UpdateImpl()
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> p4_sync;
|
||||
std::vector<char const*> p4_sync;
|
||||
this->SetP4Options(p4_sync);
|
||||
|
||||
p4_sync.push_back("sync");
|
||||
@ -488,7 +499,9 @@ bool cmCTestP4::UpdateImpl()
|
||||
opts = this->CTest->GetCTestConfiguration("P4UpdateOptions");
|
||||
}
|
||||
std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
|
||||
cm::append(p4_sync, args);
|
||||
for (std::string const& arg : args) {
|
||||
p4_sync.push_back(arg.c_str());
|
||||
}
|
||||
|
||||
std::string source = this->SourceDirectory + "/...";
|
||||
|
||||
@ -502,10 +515,11 @@ bool cmCTestP4::UpdateImpl()
|
||||
source.append("@\"").append(date).append("\"");
|
||||
}
|
||||
|
||||
p4_sync.push_back(source);
|
||||
p4_sync.push_back(source.c_str());
|
||||
p4_sync.push_back(nullptr);
|
||||
|
||||
OutputLogger out(this->Log, "p4_sync-out> ");
|
||||
OutputLogger err(this->Log, "p4_sync-err> ");
|
||||
|
||||
return this->RunUpdateCommand(p4_sync, &out, &err);
|
||||
return this->RunUpdateCommand(p4_sync.data(), &out, &err);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ private:
|
||||
std::vector<std::string> P4Options;
|
||||
|
||||
User GetUserData(const std::string& username);
|
||||
void SetP4Options(std::vector<std::string>& options);
|
||||
void SetP4Options(std::vector<char const*>& options);
|
||||
|
||||
std::string GetWorkingRevision();
|
||||
bool NoteOldRevision() override;
|
||||
|
@ -33,7 +33,7 @@ cmCTestSVN::~cmCTestSVN() = default;
|
||||
|
||||
void cmCTestSVN::CleanupImpl()
|
||||
{
|
||||
std::vector<std::string> svn_cleanup;
|
||||
std::vector<const char*> svn_cleanup;
|
||||
svn_cleanup.push_back("cleanup");
|
||||
OutputLogger out(this->Log, "cleanup-out> ");
|
||||
OutputLogger err(this->Log, "cleanup-err> ");
|
||||
@ -88,9 +88,9 @@ static bool cmCTestSVNPathStarts(std::string const& p1, std::string const& p2)
|
||||
std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo)
|
||||
{
|
||||
// Run "svn info" to get the repository info from the work tree.
|
||||
std::vector<std::string> svn_info;
|
||||
std::vector<const char*> svn_info;
|
||||
svn_info.push_back("info");
|
||||
svn_info.push_back(svninfo.LocalPath);
|
||||
svn_info.push_back(svninfo.LocalPath.c_str());
|
||||
std::string rev;
|
||||
InfoParser out(this, "info-out> ", rev, svninfo);
|
||||
OutputLogger err(this->Log, "info-err> ");
|
||||
@ -251,24 +251,26 @@ bool cmCTestSVN::UpdateImpl()
|
||||
args.push_back("-r{" + this->GetNightlyTime() + " +0000}");
|
||||
}
|
||||
|
||||
std::vector<std::string> svn_update;
|
||||
std::vector<char const*> svn_update;
|
||||
svn_update.push_back("update");
|
||||
cm::append(svn_update, args);
|
||||
for (std::string const& arg : args) {
|
||||
svn_update.push_back(arg.c_str());
|
||||
}
|
||||
|
||||
UpdateParser out(this, "up-out> ");
|
||||
OutputLogger err(this->Log, "up-err> ");
|
||||
return this->RunSVNCommand(svn_update, &out, &err);
|
||||
}
|
||||
|
||||
bool cmCTestSVN::RunSVNCommand(std::vector<std::string> const& parameters,
|
||||
bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters,
|
||||
OutputParser* out, OutputParser* err)
|
||||
{
|
||||
if (parameters.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> args;
|
||||
args.push_back(this->CommandLineTool);
|
||||
std::vector<char const*> args;
|
||||
args.push_back(this->CommandLineTool.c_str());
|
||||
cm::append(args, parameters);
|
||||
args.push_back("--non-interactive");
|
||||
|
||||
@ -276,12 +278,16 @@ bool cmCTestSVN::RunSVNCommand(std::vector<std::string> const& parameters,
|
||||
|
||||
std::vector<std::string> parsedUserOptions =
|
||||
cmSystemTools::ParseArguments(userOptions);
|
||||
cm::append(args, parsedUserOptions);
|
||||
|
||||
if (parameters[0] == "update") {
|
||||
return this->RunUpdateCommand(args, out, err);
|
||||
for (std::string const& opt : parsedUserOptions) {
|
||||
args.push_back(opt.c_str());
|
||||
}
|
||||
return this->RunChild(args, out, err);
|
||||
|
||||
args.push_back(nullptr);
|
||||
|
||||
if (strcmp(parameters[0], "update") == 0) {
|
||||
return this->RunUpdateCommand(args.data(), out, err);
|
||||
}
|
||||
return this->RunChild(args.data(), out, err);
|
||||
}
|
||||
|
||||
class cmCTestSVN::LogParser
|
||||
@ -387,7 +393,7 @@ bool cmCTestSVN::LoadRevisions(SVNInfo& svninfo)
|
||||
}
|
||||
|
||||
// Run "svn log" to get all global revisions of interest.
|
||||
std::vector<std::string> svn_log;
|
||||
std::vector<const char*> svn_log;
|
||||
svn_log.push_back("log");
|
||||
svn_log.push_back("--xml");
|
||||
svn_log.push_back("-v");
|
||||
@ -466,7 +472,7 @@ private:
|
||||
bool cmCTestSVN::LoadModifications()
|
||||
{
|
||||
// Run "svn status" which reports local modifications.
|
||||
std::vector<std::string> svn_status;
|
||||
std::vector<const char*> svn_status;
|
||||
svn_status.push_back("status");
|
||||
StatusParser out(this, "status-out> ");
|
||||
OutputLogger err(this->Log, "status-err> ");
|
||||
@ -528,7 +534,7 @@ bool cmCTestSVN::LoadRepositories()
|
||||
this->RootInfo = &(this->Repositories.back());
|
||||
|
||||
// Run "svn status" to get the list of external repositories
|
||||
std::vector<std::string> svn_status;
|
||||
std::vector<const char*> svn_status;
|
||||
svn_status.push_back("status");
|
||||
ExternalParser out(this, "external-out> ");
|
||||
OutputLogger err(this->Log, "external-err> ");
|
||||
|
@ -33,7 +33,7 @@ private:
|
||||
bool NoteNewRevision() override;
|
||||
bool UpdateImpl() override;
|
||||
|
||||
bool RunSVNCommand(std::vector<std::string> const& parameters,
|
||||
bool RunSVNCommand(std::vector<char const*> const& parameters,
|
||||
OutputParser* out, OutputParser* err);
|
||||
|
||||
// Information about an SVN repository (root repository or external)
|
||||
|
@ -11,9 +11,8 @@
|
||||
|
||||
#include <cm/memory>
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
|
||||
#include "cmsys/Directory.hxx"
|
||||
#include "cmsys/Process.h"
|
||||
|
||||
#include "cmCTest.h"
|
||||
#include "cmCTestBuildCommand.h"
|
||||
@ -41,8 +40,6 @@
|
||||
#include "cmStateSnapshot.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVHandlePtr.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
#include "cmValue.h"
|
||||
#include "cmake.h"
|
||||
|
||||
@ -151,65 +148,66 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
|
||||
// now pass through all the other arguments
|
||||
std::vector<std::string>& initArgs =
|
||||
this->CTest->GetInitialCommandLineArguments();
|
||||
//*** need to make sure this does not have the current script ***
|
||||
for (size_t i = 1; i < initArgs.size(); ++i) {
|
||||
argv.push_back(initArgs[i].c_str());
|
||||
}
|
||||
argv.push_back(nullptr);
|
||||
|
||||
// Now create process object
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand(initArgs)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
|
||||
auto process = builder.Start();
|
||||
cm::uv_pipe_ptr outPipe;
|
||||
outPipe.init(process.GetLoop(), 0);
|
||||
uv_pipe_open(outPipe, process.OutputStream());
|
||||
cm::uv_pipe_ptr errPipe;
|
||||
errPipe.init(process.GetLoop(), 0);
|
||||
uv_pipe_open(errPipe, process.ErrorStream());
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
cmsysProcess_SetCommand(cp, argv.data());
|
||||
// cmsysProcess_SetWorkingDirectory(cp, dir);
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
|
||||
// cmsysProcess_SetTimeout(cp, timeout);
|
||||
cmsysProcess_Execute(cp);
|
||||
|
||||
std::vector<char> out;
|
||||
std::vector<char> err;
|
||||
std::string line;
|
||||
auto pipe =
|
||||
cmSystemTools::WaitForLine(&process.GetLoop(), outPipe, errPipe, line,
|
||||
std::chrono::seconds(100), out, err);
|
||||
while (pipe != cmSystemTools::WaitForLineResult::None) {
|
||||
int pipe =
|
||||
cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out, err);
|
||||
while (pipe != cmsysProcess_Pipe_None) {
|
||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"Output: " << line << "\n");
|
||||
if (pipe == cmSystemTools::WaitForLineResult::STDERR) {
|
||||
if (pipe == cmsysProcess_Pipe_STDERR) {
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE, line << "\n");
|
||||
} else if (pipe == cmSystemTools::WaitForLineResult::STDOUT) {
|
||||
} else if (pipe == cmsysProcess_Pipe_STDOUT) {
|
||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, line << "\n");
|
||||
}
|
||||
pipe =
|
||||
cmSystemTools::WaitForLine(&process.GetLoop(), outPipe, errPipe, line,
|
||||
std::chrono::seconds(100), out, err);
|
||||
pipe = cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out,
|
||||
err);
|
||||
}
|
||||
|
||||
// Properly handle output of the build command
|
||||
process.Wait();
|
||||
auto const& status = process.GetStatus(0);
|
||||
auto result = status.GetException();
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
int result = cmsysProcess_GetState(cp);
|
||||
int retVal = 0;
|
||||
bool failed = false;
|
||||
switch (result.first) {
|
||||
case cmUVProcessChain::ExceptionCode::None:
|
||||
retVal = static_cast<int>(status.ExitStatus);
|
||||
break;
|
||||
case cmUVProcessChain::ExceptionCode::Spawn:
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"\tError executing ctest: " << result.second << std::endl);
|
||||
failed = true;
|
||||
break;
|
||||
default:
|
||||
retVal = status.TermSignal;
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"\tThere was an exception: " << result.second << " " << retVal
|
||||
<< std::endl);
|
||||
failed = true;
|
||||
if (result == cmsysProcess_State_Exited) {
|
||||
retVal = cmsysProcess_GetExitValue(cp);
|
||||
} else if (result == cmsysProcess_State_Exception) {
|
||||
retVal = cmsysProcess_GetExitException(cp);
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"\tThere was an exception: "
|
||||
<< cmsysProcess_GetExceptionString(cp) << " " << retVal
|
||||
<< std::endl);
|
||||
failed = true;
|
||||
} else if (result == cmsysProcess_State_Expired) {
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"\tThere was a timeout" << std::endl);
|
||||
failed = true;
|
||||
} else if (result == cmsysProcess_State_Error) {
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"\tError executing ctest: " << cmsysProcess_GetErrorString(cp)
|
||||
<< std::endl);
|
||||
failed = true;
|
||||
}
|
||||
cmsysProcess_Delete(cp);
|
||||
if (failed) {
|
||||
std::ostringstream message;
|
||||
message << "Error running command: [";
|
||||
message << static_cast<int>(result.first) << "] ";
|
||||
message << result << "] ";
|
||||
for (const char* arg : argv) {
|
||||
if (arg) {
|
||||
message << arg << " ";
|
||||
|
@ -7,9 +7,10 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "cmsys/Process.h"
|
||||
|
||||
#include "cmCTest.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
#include "cmValue.h"
|
||||
#include "cmXMLWriter.h"
|
||||
|
||||
@ -54,12 +55,18 @@ bool cmCTestVC::InitialCheckout(const std::string& command)
|
||||
|
||||
// Construct the initial checkout command line.
|
||||
std::vector<std::string> args = cmSystemTools::ParseArguments(command);
|
||||
std::vector<char const*> vc_co;
|
||||
vc_co.reserve(args.size() + 1);
|
||||
for (std::string const& arg : args) {
|
||||
vc_co.push_back(arg.c_str());
|
||||
}
|
||||
vc_co.push_back(nullptr);
|
||||
|
||||
// Run the initial checkout command and log its output.
|
||||
this->Log << "--- Begin Initial Checkout ---\n";
|
||||
OutputLogger out(this->Log, "co-out> ");
|
||||
OutputLogger err(this->Log, "co-err> ");
|
||||
bool result = this->RunChild(args, &out, &err, parent);
|
||||
bool result = this->RunChild(vc_co.data(), &out, &err, parent.c_str());
|
||||
this->Log << "--- End Initial Checkout ---\n";
|
||||
if (!result) {
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
@ -68,35 +75,35 @@ bool cmCTestVC::InitialCheckout(const std::string& command)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cmCTestVC::RunChild(const std::vector<std::string>& cmd,
|
||||
OutputParser* out, OutputParser* err,
|
||||
std::string workDir, Encoding encoding)
|
||||
bool cmCTestVC::RunChild(char const* const* cmd, OutputParser* out,
|
||||
OutputParser* err, const char* workDir,
|
||||
Encoding encoding)
|
||||
{
|
||||
this->Log << cmCTestVC::ComputeCommandLine(cmd) << "\n";
|
||||
|
||||
cmUVProcessChainBuilder builder;
|
||||
if (workDir.empty()) {
|
||||
workDir = this->SourceDirectory;
|
||||
}
|
||||
builder.AddCommand(cmd).SetWorkingDirectory(workDir);
|
||||
auto status = cmCTestVC::RunProcess(builder, out, err, encoding);
|
||||
return status.front().SpawnResult == 0 && status.front().ExitStatus == 0;
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
cmsysProcess_SetCommand(cp, cmd);
|
||||
workDir = workDir ? workDir : this->SourceDirectory.c_str();
|
||||
cmsysProcess_SetWorkingDirectory(cp, workDir);
|
||||
cmCTestVC::RunProcess(cp, out, err, encoding);
|
||||
int result = cmsysProcess_GetExitValue(cp);
|
||||
cmsysProcess_Delete(cp);
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
std::string cmCTestVC::ComputeCommandLine(const std::vector<std::string>& cmd)
|
||||
std::string cmCTestVC::ComputeCommandLine(char const* const* cmd)
|
||||
{
|
||||
std::ostringstream line;
|
||||
const char* sep = "";
|
||||
for (auto const& arg : cmd) {
|
||||
line << sep << "\"" << arg << "\"";
|
||||
for (const char* const* arg = cmd; *arg; ++arg) {
|
||||
line << sep << "\"" << *arg << "\"";
|
||||
sep = " ";
|
||||
}
|
||||
return line.str();
|
||||
}
|
||||
|
||||
bool cmCTestVC::RunUpdateCommand(const std::vector<std::string>& cmd,
|
||||
OutputParser* out, OutputParser* err,
|
||||
Encoding encoding)
|
||||
bool cmCTestVC::RunUpdateCommand(char const* const* cmd, OutputParser* out,
|
||||
OutputParser* err, Encoding encoding)
|
||||
{
|
||||
// Report the command line.
|
||||
this->UpdateCommandLine = this->ComputeCommandLine(cmd);
|
||||
@ -106,7 +113,7 @@ bool cmCTestVC::RunUpdateCommand(const std::vector<std::string>& cmd,
|
||||
}
|
||||
|
||||
// Run the command.
|
||||
return this->RunChild(cmd, out, err, "", encoding);
|
||||
return this->RunChild(cmd, out, err, nullptr, encoding);
|
||||
}
|
||||
|
||||
std::string cmCTestVC::GetNightlyTime()
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmProcessOutput.h"
|
||||
#include "cmProcessTools.h"
|
||||
@ -109,15 +108,15 @@ protected:
|
||||
};
|
||||
|
||||
/** Convert a list of arguments to a human-readable command line. */
|
||||
static std::string ComputeCommandLine(const std::vector<std::string>& cmd);
|
||||
static std::string ComputeCommandLine(char const* const* cmd);
|
||||
|
||||
/** Run a command line and send output to given parsers. */
|
||||
bool RunChild(const std::vector<std::string>& cmd, OutputParser* out,
|
||||
OutputParser* err, std::string workDir = {},
|
||||
bool RunChild(char const* const* cmd, OutputParser* out, OutputParser* err,
|
||||
const char* workDir = nullptr,
|
||||
Encoding encoding = cmProcessOutput::Auto);
|
||||
|
||||
/** Run VC update command line and send output to given parsers. */
|
||||
bool RunUpdateCommand(const std::vector<std::string>& cmd, OutputParser* out,
|
||||
bool RunUpdateCommand(char const* const* cmd, OutputParser* out,
|
||||
OutputParser* err = nullptr,
|
||||
Encoding encoding = cmProcessOutput::Auto);
|
||||
|
||||
|
@ -667,10 +667,6 @@ Modify cmCTestResourceGroupsLexer.cxx:
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <termios.h>
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#define INITIAL 0
|
||||
|
@ -26,10 +26,6 @@ Modify cmCTestResourceGroupsLexer.cxx:
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <termios.h>
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
%}
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@ -25,13 +24,13 @@
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include <cm3p/curl/curl.h>
|
||||
#include <cm3p/uv.h>
|
||||
#include <cm3p/zlib.h>
|
||||
|
||||
#include "cmsys/Base64.h"
|
||||
#include "cmsys/Directory.hxx"
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/Glob.hxx"
|
||||
#include "cmsys/Process.h"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
#include "cmsys/SystemInformation.hxx"
|
||||
#if defined(_WIN32)
|
||||
@ -65,9 +64,6 @@
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVHandlePtr.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
#include "cmUVStream.h"
|
||||
#include "cmValue.h"
|
||||
#include "cmVersion.h"
|
||||
#include "cmVersionConfig.h"
|
||||
@ -1077,9 +1073,9 @@ int cmCTest::GetTestModelFromString(const std::string& str)
|
||||
// ######################################################################
|
||||
// ######################################################################
|
||||
|
||||
bool cmCTest::RunMakeCommand(const std::string& command, std::string& output,
|
||||
int* retVal, const char* dir, cmDuration timeout,
|
||||
std::ostream& ofs, Encoding encoding)
|
||||
int cmCTest::RunMakeCommand(const std::string& command, std::string& output,
|
||||
int* retVal, const char* dir, cmDuration timeout,
|
||||
std::ostream& ofs, Encoding encoding)
|
||||
{
|
||||
// First generate the command and arguments
|
||||
std::vector<std::string> args = cmSystemTools::ParseArguments(command);
|
||||
@ -1088,107 +1084,107 @@ bool cmCTest::RunMakeCommand(const std::string& command, std::string& output,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<const char*> argv;
|
||||
argv.reserve(args.size() + 1);
|
||||
for (std::string const& a : args) {
|
||||
argv.push_back(a.c_str());
|
||||
}
|
||||
argv.push_back(nullptr);
|
||||
|
||||
output.clear();
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Run command:");
|
||||
for (auto const& arg : args) {
|
||||
for (char const* arg : argv) {
|
||||
if (!arg) {
|
||||
break;
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, " \"" << arg << "\"");
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, std::endl);
|
||||
|
||||
// Now create process object
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand(args).SetMergedBuiltinStreams();
|
||||
if (dir) {
|
||||
builder.SetWorkingDirectory(dir);
|
||||
}
|
||||
auto chain = builder.Start();
|
||||
cm::uv_pipe_ptr outputStream;
|
||||
outputStream.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(outputStream, chain.OutputStream());
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
cmsysProcess_SetCommand(cp, argv.data());
|
||||
cmsysProcess_SetWorkingDirectory(cp, dir);
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
|
||||
cmsysProcess_SetTimeout(cp, timeout.count());
|
||||
cmsysProcess_Execute(cp);
|
||||
|
||||
// Initialize tick's
|
||||
std::string::size_type tick = 0;
|
||||
std::string::size_type tick_len = 1024;
|
||||
std::string::size_type tick_line_len = 50;
|
||||
|
||||
char* data;
|
||||
int length;
|
||||
cmProcessOutput processOutput(encoding);
|
||||
std::string strdata;
|
||||
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
|
||||
" Each . represents " << tick_len
|
||||
<< " bytes of output\n"
|
||||
" "
|
||||
<< std::flush);
|
||||
auto outputHandle = cmUVStreamRead(
|
||||
outputStream,
|
||||
[this, &processOutput, &output, &tick, &tick_len, &tick_line_len,
|
||||
&ofs](std::vector<char> data) {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata);
|
||||
for (char& cc : strdata) {
|
||||
if (cc == 0) {
|
||||
cc = '\n';
|
||||
}
|
||||
while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
|
||||
processOutput.DecodeText(data, length, strdata);
|
||||
for (char& cc : strdata) {
|
||||
if (cc == 0) {
|
||||
cc = '\n';
|
||||
}
|
||||
output.append(strdata);
|
||||
while (output.size() > (tick * tick_len)) {
|
||||
tick++;
|
||||
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush);
|
||||
if (tick % tick_line_len == 0 && tick > 0) {
|
||||
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
|
||||
" Size: " << int((double(output.size()) / 1024.0) + 1)
|
||||
<< "K\n " << std::flush);
|
||||
}
|
||||
}
|
||||
output.append(strdata);
|
||||
while (output.size() > (tick * tick_len)) {
|
||||
tick++;
|
||||
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush);
|
||||
if (tick % tick_line_len == 0 && tick > 0) {
|
||||
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
|
||||
" Size: " << int((double(output.size()) / 1024.0) + 1)
|
||||
<< "K\n " << std::flush);
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
cmCTestLogWrite(strdata.c_str(), strdata.size()));
|
||||
if (ofs) {
|
||||
ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
|
||||
}
|
||||
},
|
||||
[this, &processOutput, &output, &ofs]() {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(std::string(), strdata);
|
||||
if (!strdata.empty()) {
|
||||
output.append(strdata);
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
cmCTestLogWrite(strdata.c_str(), strdata.size()));
|
||||
if (ofs) {
|
||||
ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
bool finished = chain.Wait(static_cast<uint64_t>(timeout.count() * 1000.0));
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
cmCTestLogWrite(strdata.c_str(), strdata.size()));
|
||||
if (ofs) {
|
||||
ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
|
||||
}
|
||||
}
|
||||
processOutput.DecodeText(std::string(), strdata);
|
||||
if (!strdata.empty()) {
|
||||
output.append(strdata);
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
cmCTestLogWrite(strdata.c_str(), strdata.size()));
|
||||
if (ofs) {
|
||||
ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
|
||||
}
|
||||
}
|
||||
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
|
||||
" Size of output: " << int(double(output.size()) / 1024.0) << "K"
|
||||
<< std::endl);
|
||||
|
||||
if (finished) {
|
||||
auto const& status = chain.GetStatus(0);
|
||||
auto exception = status.GetException();
|
||||
switch (exception.first) {
|
||||
case cmUVProcessChain::ExceptionCode::None:
|
||||
*retVal = static_cast<int>(status.ExitStatus);
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
"Command exited with the value: " << *retVal << std::endl);
|
||||
break;
|
||||
case cmUVProcessChain::ExceptionCode::Spawn:
|
||||
output += "\n*** ERROR executing: ";
|
||||
output += exception.second;
|
||||
output += "\n***The build process failed.";
|
||||
cmCTestLog(this, ERROR_MESSAGE,
|
||||
"There was an error: " << exception.second << std::endl);
|
||||
break;
|
||||
default:
|
||||
*retVal = static_cast<int>(exception.first);
|
||||
cmCTestLog(this, WARNING,
|
||||
"There was an exception: " << *retVal << std::endl);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
|
||||
int result = cmsysProcess_GetState(cp);
|
||||
|
||||
if (result == cmsysProcess_State_Exited) {
|
||||
*retVal = cmsysProcess_GetExitValue(cp);
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
"Command exited with the value: " << *retVal << std::endl);
|
||||
} else if (result == cmsysProcess_State_Exception) {
|
||||
*retVal = cmsysProcess_GetExitException(cp);
|
||||
cmCTestLog(this, WARNING,
|
||||
"There was an exception: " << *retVal << std::endl);
|
||||
} else if (result == cmsysProcess_State_Expired) {
|
||||
cmCTestLog(this, WARNING, "There was a timeout" << std::endl);
|
||||
} else if (result == cmsysProcess_State_Error) {
|
||||
output += "\n*** ERROR executing: ";
|
||||
output += cmsysProcess_GetErrorString(cp);
|
||||
output += "\n***The build process failed.";
|
||||
cmCTestLog(this, ERROR_MESSAGE,
|
||||
"There was an error: " << cmsysProcess_GetErrorString(cp)
|
||||
<< std::endl);
|
||||
}
|
||||
|
||||
return true;
|
||||
cmsysProcess_Delete(cp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
@ -1196,10 +1192,9 @@ bool cmCTest::RunMakeCommand(const std::string& command, std::string& output,
|
||||
// ######################################################################
|
||||
// ######################################################################
|
||||
|
||||
bool cmCTest::RunTest(const std::vector<std::string>& argv,
|
||||
std::string* output, int* retVal, std::ostream* log,
|
||||
cmDuration testTimeOut,
|
||||
std::vector<std::string>* environment, Encoding encoding)
|
||||
int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
|
||||
int* retVal, std::ostream* log, cmDuration testTimeOut,
|
||||
std::vector<std::string>* environment, Encoding encoding)
|
||||
{
|
||||
bool modifyEnv = (environment && !environment->empty());
|
||||
|
||||
@ -1238,16 +1233,19 @@ bool cmCTest::RunTest(const std::vector<std::string>& argv,
|
||||
inst.SetStreams(&oss, &oss);
|
||||
|
||||
std::vector<std::string> args;
|
||||
for (auto const& i : argv) {
|
||||
// make sure we pass the timeout in for any build and test
|
||||
// invocations. Since --build-generator is required this is a
|
||||
// good place to check for it, and to add the arguments in
|
||||
if (i == "--build-generator" && timeout != cmCTest::MaxDuration() &&
|
||||
timeout > cmDuration::zero()) {
|
||||
args.emplace_back("--test-timeout");
|
||||
args.push_back(std::to_string(cmDurationTo<unsigned int>(timeout)));
|
||||
for (char const* i : argv) {
|
||||
if (i) {
|
||||
// make sure we pass the timeout in for any build and test
|
||||
// invocations. Since --build-generator is required this is a
|
||||
// good place to check for it, and to add the arguments in
|
||||
if (strcmp(i, "--build-generator") == 0 &&
|
||||
timeout != cmCTest::MaxDuration() &&
|
||||
timeout > cmDuration::zero()) {
|
||||
args.emplace_back("--test-timeout");
|
||||
args.push_back(std::to_string(cmDurationTo<unsigned int>(timeout)));
|
||||
}
|
||||
args.emplace_back(i);
|
||||
}
|
||||
args.emplace_back(i);
|
||||
}
|
||||
if (log) {
|
||||
*log << "* Run internal CTest" << std::endl;
|
||||
@ -1273,7 +1271,7 @@ bool cmCTest::RunTest(const std::vector<std::string>& argv,
|
||||
<< std::endl);
|
||||
}
|
||||
|
||||
return true;
|
||||
return cmsysProcess_State_Exited;
|
||||
}
|
||||
std::vector<char> tempOutput;
|
||||
if (output) {
|
||||
@ -1286,43 +1284,41 @@ bool cmCTest::RunTest(const std::vector<std::string>& argv,
|
||||
cmSystemTools::AppendEnv(*environment);
|
||||
}
|
||||
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand(argv).SetMergedBuiltinStreams();
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
cmsysProcess_SetCommand(cp, argv.data());
|
||||
cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
|
||||
auto chain = builder.Start();
|
||||
if (cmSystemTools::GetRunCommandHideConsole()) {
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
|
||||
}
|
||||
|
||||
cmsysProcess_SetTimeout(cp, timeout.count());
|
||||
cmsysProcess_Execute(cp);
|
||||
|
||||
char* data;
|
||||
int length;
|
||||
cmProcessOutput processOutput(encoding);
|
||||
cm::uv_pipe_ptr outputStream;
|
||||
outputStream.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(outputStream, chain.OutputStream());
|
||||
auto outputHandle = cmUVStreamRead(
|
||||
outputStream,
|
||||
[this, &processOutput, &output, &tempOutput,
|
||||
&log](std::vector<char> data) {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata);
|
||||
if (output) {
|
||||
cm::append(tempOutput, data.data(), data.data() + data.size());
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
cmCTestLogWrite(strdata.c_str(), strdata.size()));
|
||||
if (log) {
|
||||
log->write(strdata.c_str(), strdata.size());
|
||||
}
|
||||
},
|
||||
[this, &processOutput, &log]() {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(std::string(), strdata);
|
||||
if (!strdata.empty()) {
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
cmCTestLogWrite(strdata.c_str(), strdata.size()));
|
||||
if (log) {
|
||||
log->write(strdata.c_str(), strdata.size());
|
||||
}
|
||||
}
|
||||
});
|
||||
std::string strdata;
|
||||
while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
|
||||
processOutput.DecodeText(data, length, strdata);
|
||||
if (output) {
|
||||
cm::append(tempOutput, data, data + length);
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
cmCTestLogWrite(strdata.c_str(), strdata.size()));
|
||||
if (log) {
|
||||
log->write(strdata.c_str(), strdata.size());
|
||||
}
|
||||
}
|
||||
processOutput.DecodeText(std::string(), strdata);
|
||||
if (!strdata.empty()) {
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
cmCTestLogWrite(strdata.c_str(), strdata.size()));
|
||||
if (log) {
|
||||
log->write(strdata.c_str(), strdata.size());
|
||||
}
|
||||
}
|
||||
|
||||
bool complete = chain.Wait(static_cast<uint64_t>(timeout.count() * 1000.0));
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
processOutput.DecodeText(tempOutput, tempOutput);
|
||||
if (output && tempOutput.begin() != tempOutput.end()) {
|
||||
output->append(tempOutput.data(), tempOutput.size());
|
||||
@ -1330,41 +1326,33 @@ bool cmCTest::RunTest(const std::vector<std::string>& argv,
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
|
||||
"-- Process completed" << std::endl);
|
||||
|
||||
bool result = false;
|
||||
int result = cmsysProcess_GetState(cp);
|
||||
|
||||
if (complete) {
|
||||
auto const& status = chain.GetStatus(0);
|
||||
auto exception = status.GetException();
|
||||
switch (exception.first) {
|
||||
case cmUVProcessChain::ExceptionCode::None:
|
||||
*retVal = static_cast<int>(status.ExitStatus);
|
||||
if (*retVal != 0 && this->Impl->OutputTestOutputOnTestFailure) {
|
||||
this->OutputTestErrors(tempOutput);
|
||||
}
|
||||
result = true;
|
||||
break;
|
||||
case cmUVProcessChain::ExceptionCode::Spawn: {
|
||||
std::string outerr =
|
||||
cmStrCat("\n*** ERROR executing: ", exception.second);
|
||||
if (output) {
|
||||
*output += outerr;
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
|
||||
} break;
|
||||
default: {
|
||||
if (this->Impl->OutputTestOutputOnTestFailure) {
|
||||
this->OutputTestErrors(tempOutput);
|
||||
}
|
||||
*retVal = status.TermSignal;
|
||||
std::string outerr =
|
||||
cmStrCat("\n*** Exception executing: ", exception.second);
|
||||
if (output) {
|
||||
*output += outerr;
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
|
||||
} break;
|
||||
if (result == cmsysProcess_State_Exited) {
|
||||
*retVal = cmsysProcess_GetExitValue(cp);
|
||||
if (*retVal != 0 && this->Impl->OutputTestOutputOnTestFailure) {
|
||||
this->OutputTestErrors(tempOutput);
|
||||
}
|
||||
} else if (result == cmsysProcess_State_Exception) {
|
||||
if (this->Impl->OutputTestOutputOnTestFailure) {
|
||||
this->OutputTestErrors(tempOutput);
|
||||
}
|
||||
*retVal = cmsysProcess_GetExitException(cp);
|
||||
std::string outerr = cmStrCat("\n*** Exception executing: ",
|
||||
cmsysProcess_GetExceptionString(cp));
|
||||
if (output) {
|
||||
*output += outerr;
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
|
||||
} else if (result == cmsysProcess_State_Error) {
|
||||
std::string outerr =
|
||||
cmStrCat("\n*** ERROR executing: ", cmsysProcess_GetErrorString(cp));
|
||||
if (output) {
|
||||
*output += outerr;
|
||||
}
|
||||
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
|
||||
}
|
||||
cmsysProcess_Delete(cp);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -3482,70 +3470,49 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args,
|
||||
stdOut->clear();
|
||||
stdErr->clear();
|
||||
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand(args)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
|
||||
if (dir) {
|
||||
builder.SetWorkingDirectory(dir);
|
||||
}
|
||||
auto chain = builder.Start();
|
||||
|
||||
cm::uv_timer_ptr timer;
|
||||
bool timedOut = false;
|
||||
if (timeout.count()) {
|
||||
timer.init(chain.GetLoop(), &timedOut);
|
||||
timer.start(
|
||||
[](uv_timer_t* t) {
|
||||
auto* timedOutPtr = static_cast<bool*>(t->data);
|
||||
*timedOutPtr = true;
|
||||
},
|
||||
static_cast<uint64_t>(timeout.count() * 1000.0), 0);
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
cmsysProcess_SetCommand(cp, argv.data());
|
||||
cmsysProcess_SetWorkingDirectory(cp, dir);
|
||||
if (cmSystemTools::GetRunCommandHideConsole()) {
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
|
||||
}
|
||||
cmsysProcess_SetTimeout(cp, timeout.count());
|
||||
cmsysProcess_Execute(cp);
|
||||
|
||||
std::vector<char> tempOutput;
|
||||
bool outFinished = false;
|
||||
cm::uv_pipe_ptr outStream;
|
||||
std::vector<char> tempError;
|
||||
bool errFinished = false;
|
||||
cm::uv_pipe_ptr errStream;
|
||||
char* data;
|
||||
int length;
|
||||
cmProcessOutput processOutput(encoding);
|
||||
auto startRead = [this, &chain, &processOutput](
|
||||
cm::uv_pipe_ptr& pipe, int stream,
|
||||
std::vector<char>& temp,
|
||||
bool& finished) -> std::unique_ptr<cmUVStreamReadHandle> {
|
||||
pipe.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(pipe, stream);
|
||||
return cmUVStreamRead(
|
||||
pipe,
|
||||
[this, &temp, &processOutput](std::vector<char> data) {
|
||||
cm::append(temp, data);
|
||||
if (this->Impl->ExtraVerbose) {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata);
|
||||
cmSystemTools::Stdout(strdata);
|
||||
}
|
||||
},
|
||||
[&finished]() { finished = true; });
|
||||
};
|
||||
auto outputHandle =
|
||||
startRead(outStream, chain.OutputStream(), tempOutput, outFinished);
|
||||
auto errorHandle =
|
||||
startRead(errStream, chain.ErrorStream(), tempError, errFinished);
|
||||
while (!timedOut && !(outFinished && errFinished)) {
|
||||
uv_run(&chain.GetLoop(), UV_RUN_ONCE);
|
||||
std::string strdata;
|
||||
int res;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
res = cmsysProcess_WaitForData(cp, &data, &length, nullptr);
|
||||
switch (res) {
|
||||
case cmsysProcess_Pipe_STDOUT:
|
||||
cm::append(tempOutput, data, data + length);
|
||||
break;
|
||||
case cmsysProcess_Pipe_STDERR:
|
||||
cm::append(tempError, data, data + length);
|
||||
break;
|
||||
default:
|
||||
done = true;
|
||||
}
|
||||
if ((res == cmsysProcess_Pipe_STDOUT || res == cmsysProcess_Pipe_STDERR) &&
|
||||
this->Impl->ExtraVerbose) {
|
||||
processOutput.DecodeText(data, length, strdata);
|
||||
cmSystemTools::Stdout(strdata);
|
||||
}
|
||||
}
|
||||
if (this->Impl->ExtraVerbose) {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(std::string(), strdata);
|
||||
if (!strdata.empty()) {
|
||||
cmSystemTools::Stdout(strdata);
|
||||
}
|
||||
}
|
||||
|
||||
while (!timedOut && !chain.Finished()) {
|
||||
uv_run(&chain.GetLoop(), UV_RUN_ONCE);
|
||||
}
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
if (!tempOutput.empty()) {
|
||||
processOutput.DecodeText(tempOutput, tempOutput);
|
||||
stdOut->append(tempOutput.data(), tempOutput.size());
|
||||
@ -3556,32 +3523,32 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
if (timedOut) {
|
||||
if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
|
||||
if (retVal) {
|
||||
*retVal = cmsysProcess_GetExitValue(cp);
|
||||
} else {
|
||||
if (cmsysProcess_GetExitValue(cp) != 0) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
} else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) {
|
||||
const char* exception_str = cmsysProcess_GetExceptionString(cp);
|
||||
cmCTestLog(this, ERROR_MESSAGE, exception_str << std::endl);
|
||||
stdErr->append(exception_str, strlen(exception_str));
|
||||
result = false;
|
||||
} else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) {
|
||||
const char* error_str = cmsysProcess_GetErrorString(cp);
|
||||
cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl);
|
||||
stdErr->append(error_str, strlen(error_str));
|
||||
result = false;
|
||||
} else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) {
|
||||
const char* error_str = "Process terminated due to timeout\n";
|
||||
cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl);
|
||||
stdErr->append(error_str, strlen(error_str));
|
||||
result = false;
|
||||
} else {
|
||||
auto const& status = chain.GetStatus(0);
|
||||
auto exception = status.GetException();
|
||||
switch (exception.first) {
|
||||
case cmUVProcessChain::ExceptionCode::None:
|
||||
if (retVal) {
|
||||
*retVal = static_cast<int>(status.ExitStatus);
|
||||
} else {
|
||||
if (status.ExitStatus != 0) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
cmCTestLog(this, ERROR_MESSAGE, exception.second << std::endl);
|
||||
stdErr->append(exception.second);
|
||||
result = false;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
cmsysProcess_Delete(cp);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -254,10 +254,10 @@ public:
|
||||
* Run command specialized for make and configure. Returns process status
|
||||
* and retVal is return value or exception.
|
||||
*/
|
||||
bool RunMakeCommand(const std::string& command, std::string& output,
|
||||
int* retVal, const char* dir, cmDuration timeout,
|
||||
std::ostream& ofs,
|
||||
Encoding encoding = cmProcessOutput::Auto);
|
||||
int RunMakeCommand(const std::string& command, std::string& output,
|
||||
int* retVal, const char* dir, cmDuration timeout,
|
||||
std::ostream& ofs,
|
||||
Encoding encoding = cmProcessOutput::Auto);
|
||||
|
||||
/** Return the current tag */
|
||||
std::string GetCurrentTag();
|
||||
@ -303,10 +303,10 @@ public:
|
||||
* environment variables prior to running the test. After running the test,
|
||||
* environment variables are restored to their previous values.
|
||||
*/
|
||||
bool RunTest(const std::vector<std::string>& args, std::string* output,
|
||||
int* retVal, std::ostream* logfile, cmDuration testTimeOut,
|
||||
std::vector<std::string>* environment,
|
||||
Encoding encoding = cmProcessOutput::Auto);
|
||||
int RunTest(std::vector<const char*> args, std::string* output, int* retVal,
|
||||
std::ostream* logfile, cmDuration testTimeOut,
|
||||
std::vector<std::string>* environment,
|
||||
Encoding encoding = cmProcessOutput::Auto);
|
||||
|
||||
/**
|
||||
* Get the handler object
|
||||
|
@ -260,7 +260,7 @@ cmComputeLinkInformation::cmComputeLinkInformation(
|
||||
, Config(config)
|
||||
{
|
||||
// Check whether to recognize OpenBSD-style library versioned names.
|
||||
this->OpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
|
||||
this->IsOpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
|
||||
"FIND_LIBRARY_USE_OPENBSD_VERSIONING");
|
||||
|
||||
// Allocate internals.
|
||||
@ -553,7 +553,8 @@ bool cmComputeLinkInformation::Compute()
|
||||
this->Target->GetType() == cmStateEnums::MODULE_LIBRARY ||
|
||||
this->Target->GetType() == cmStateEnums::STATIC_LIBRARY ||
|
||||
(this->Target->CanCompileSources() &&
|
||||
(this->Target->HaveCxx20ModuleSources() ||
|
||||
(this->Target->HaveCxxModuleSupport(this->Config) ==
|
||||
cmGeneratorTarget::Cxx20SupportLevel::Supported ||
|
||||
this->Target->HaveFortranSources())))) {
|
||||
return false;
|
||||
}
|
||||
@ -1574,7 +1575,7 @@ std::string cmComputeLinkInformation::CreateExtensionRegex(
|
||||
libext += ')';
|
||||
|
||||
// Add an optional OpenBSD-style version or major.minor.version component.
|
||||
if (this->OpenBSD || type == LinkShared) {
|
||||
if (this->IsOpenBSD || type == LinkShared) {
|
||||
libext += "(\\.[0-9]+)*";
|
||||
}
|
||||
|
||||
|
@ -254,7 +254,7 @@ private:
|
||||
std::unique_ptr<cmOrderDirectories> OrderRuntimeSearchPath;
|
||||
|
||||
bool OldLinkDirMode;
|
||||
bool OpenBSD;
|
||||
bool IsOpenBSD;
|
||||
bool LinkDependsNoShared;
|
||||
bool RuntimeUseChrpath;
|
||||
bool NoSONameUsesPath;
|
||||
|
@ -493,7 +493,8 @@ bool cmDyndepCollation::WriteDyndepMetadata(
|
||||
if (!has_provides) {
|
||||
cmSystemTools::Error(
|
||||
cmStrCat("Output ", object.PrimaryOutput,
|
||||
" is of type `CXX_MODULES` but does not provide a module"));
|
||||
" is of type `CXX_MODULES` but does not provide a module "
|
||||
"interface unit or partition"));
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmExecuteProcessCommand.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype> /* isspace */
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
@ -16,9 +16,7 @@
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
|
||||
#include "cm_fileno.hxx"
|
||||
#include "cmsys/Process.h"
|
||||
|
||||
#include "cmArgumentParser.h"
|
||||
#include "cmExecutionStatus.h"
|
||||
@ -28,9 +26,6 @@
|
||||
#include "cmProcessOutput.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVHandlePtr.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
#include "cmUVStream.h"
|
||||
|
||||
namespace {
|
||||
bool cmExecuteProcessCommandIsWhitespace(char c)
|
||||
@ -41,7 +36,7 @@ bool cmExecuteProcessCommandIsWhitespace(char c)
|
||||
void cmExecuteProcessCommandFixText(std::vector<char>& output,
|
||||
bool strip_trailing_whitespace);
|
||||
void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data,
|
||||
std::size_t length);
|
||||
int length);
|
||||
}
|
||||
|
||||
// cmExecuteProcessCommand
|
||||
@ -166,69 +161,57 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
}
|
||||
// Create a process instance.
|
||||
cmUVProcessChainBuilder builder;
|
||||
std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp_ptr(
|
||||
cmsysProcess_New(), cmsysProcess_Delete);
|
||||
cmsysProcess* cp = cp_ptr.get();
|
||||
|
||||
// Set the command sequence.
|
||||
for (std::vector<std::string> const& cmd : arguments.Commands) {
|
||||
builder.AddCommand(cmd);
|
||||
std::vector<const char*> argv(cmd.size() + 1);
|
||||
std::transform(cmd.begin(), cmd.end(), argv.begin(),
|
||||
[](std::string const& s) { return s.c_str(); });
|
||||
argv.back() = nullptr;
|
||||
cmsysProcess_AddCommand(cp, argv.data());
|
||||
}
|
||||
|
||||
// Set the process working directory.
|
||||
if (!arguments.WorkingDirectory.empty()) {
|
||||
builder.SetWorkingDirectory(arguments.WorkingDirectory);
|
||||
cmsysProcess_SetWorkingDirectory(cp, arguments.WorkingDirectory.c_str());
|
||||
}
|
||||
|
||||
// Always hide the process window.
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
|
||||
|
||||
// Check the output variables.
|
||||
std::unique_ptr<FILE, int (*)(FILE*)> inputFile(nullptr, fclose);
|
||||
if (!inputFilename.empty()) {
|
||||
inputFile.reset(cmsys::SystemTools::Fopen(inputFilename, "rb"));
|
||||
if (inputFile) {
|
||||
builder.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT,
|
||||
cm_fileno(inputFile.get()));
|
||||
}
|
||||
} else {
|
||||
builder.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT,
|
||||
cm_fileno(stdin));
|
||||
bool merge_output = false;
|
||||
if (!arguments.InputFile.empty()) {
|
||||
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN,
|
||||
arguments.InputFile.c_str());
|
||||
}
|
||||
|
||||
std::unique_ptr<FILE, int (*)(FILE*)> outputFile(nullptr, fclose);
|
||||
if (!outputFilename.empty()) {
|
||||
outputFile.reset(cmsys::SystemTools::Fopen(outputFilename, "wb"));
|
||||
if (outputFile) {
|
||||
builder.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT,
|
||||
cm_fileno(outputFile.get()));
|
||||
}
|
||||
} else {
|
||||
if (arguments.OutputVariable == arguments.ErrorVariable &&
|
||||
!arguments.ErrorVariable.empty()) {
|
||||
builder.SetMergedBuiltinStreams();
|
||||
if (!arguments.OutputFile.empty()) {
|
||||
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDOUT,
|
||||
arguments.OutputFile.c_str());
|
||||
}
|
||||
if (!arguments.ErrorFile.empty()) {
|
||||
if (arguments.ErrorFile == arguments.OutputFile) {
|
||||
merge_output = true;
|
||||
} else {
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
|
||||
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR,
|
||||
arguments.ErrorFile.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<FILE, int (*)(FILE*)> errorFile(nullptr, fclose);
|
||||
if (!errorFilename.empty()) {
|
||||
if (errorFilename == outputFilename) {
|
||||
if (outputFile) {
|
||||
builder.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR,
|
||||
cm_fileno(outputFile.get()));
|
||||
}
|
||||
} else {
|
||||
errorFile.reset(cmsys::SystemTools::Fopen(errorFilename, "wb"));
|
||||
if (errorFile) {
|
||||
builder.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR,
|
||||
cm_fileno(errorFile.get()));
|
||||
}
|
||||
}
|
||||
} else if (arguments.ErrorVariable.empty() ||
|
||||
(!arguments.ErrorVariable.empty() &&
|
||||
arguments.OutputVariable != arguments.ErrorVariable)) {
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
|
||||
if (!arguments.OutputVariable.empty() &&
|
||||
arguments.OutputVariable == arguments.ErrorVariable) {
|
||||
merge_output = true;
|
||||
}
|
||||
if (merge_output) {
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1);
|
||||
}
|
||||
|
||||
// Set the timeout if any.
|
||||
int64_t timeoutMillis = static_cast<int64_t>(timeout * 1000.0);
|
||||
if (timeout >= 0) {
|
||||
cmsysProcess_SetTimeout(cp, timeout);
|
||||
}
|
||||
|
||||
bool echo_stdout = false;
|
||||
bool echo_stderr = false;
|
||||
@ -276,86 +259,36 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
}
|
||||
// Start the process.
|
||||
auto chain = builder.Start();
|
||||
|
||||
bool timedOut = false;
|
||||
cm::uv_timer_ptr timer;
|
||||
|
||||
if (timeoutMillis >= 0) {
|
||||
timer.init(chain.GetLoop(), &timedOut);
|
||||
timer.start(
|
||||
[](uv_timer_t* handle) {
|
||||
auto* timeoutPtr = static_cast<bool*>(handle->data);
|
||||
*timeoutPtr = true;
|
||||
},
|
||||
timeoutMillis, 0);
|
||||
}
|
||||
cmsysProcess_Execute(cp);
|
||||
|
||||
// Read the process output.
|
||||
struct ReadData
|
||||
{
|
||||
bool Finished = false;
|
||||
std::vector<char> Output;
|
||||
cm::uv_pipe_ptr Stream;
|
||||
};
|
||||
ReadData outputData;
|
||||
ReadData errorData;
|
||||
std::vector<char> tempOutput;
|
||||
std::vector<char> tempError;
|
||||
int length;
|
||||
char* data;
|
||||
int p;
|
||||
cmProcessOutput processOutput(
|
||||
cmProcessOutput::FindEncoding(arguments.Encoding));
|
||||
std::string strdata;
|
||||
|
||||
std::unique_ptr<cmUVStreamReadHandle> outputHandle;
|
||||
if (chain.OutputStream() >= 0) {
|
||||
outputData.Stream.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(outputData.Stream, chain.OutputStream());
|
||||
outputHandle = cmUVStreamRead(
|
||||
outputData.Stream,
|
||||
[&arguments, &processOutput, &outputData,
|
||||
&strdata](std::vector<char> data) {
|
||||
if (!arguments.OutputQuiet) {
|
||||
if (arguments.OutputVariable.empty() ||
|
||||
arguments.EchoOutputVariable) {
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata, 1);
|
||||
cmSystemTools::Stdout(strdata);
|
||||
}
|
||||
if (!arguments.OutputVariable.empty()) {
|
||||
cmExecuteProcessCommandAppend(outputData.Output, data.data(),
|
||||
data.size());
|
||||
}
|
||||
}
|
||||
},
|
||||
[&outputData]() { outputData.Finished = true; });
|
||||
} else {
|
||||
outputData.Finished = true;
|
||||
}
|
||||
std::unique_ptr<cmUVStreamReadHandle> errorHandle;
|
||||
if (chain.ErrorStream() >= 0 &&
|
||||
chain.ErrorStream() != chain.OutputStream()) {
|
||||
errorData.Stream.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(errorData.Stream, chain.ErrorStream());
|
||||
errorHandle = cmUVStreamRead(
|
||||
errorData.Stream,
|
||||
[&arguments, &processOutput, &errorData,
|
||||
&strdata](std::vector<char> data) {
|
||||
if (!arguments.ErrorQuiet) {
|
||||
if (arguments.ErrorVariable.empty() || arguments.EchoErrorVariable) {
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata, 2);
|
||||
cmSystemTools::Stderr(strdata);
|
||||
}
|
||||
if (!arguments.ErrorVariable.empty()) {
|
||||
cmExecuteProcessCommandAppend(errorData.Output, data.data(),
|
||||
data.size());
|
||||
}
|
||||
}
|
||||
},
|
||||
[&errorData]() { errorData.Finished = true; });
|
||||
} else {
|
||||
errorData.Finished = true;
|
||||
}
|
||||
|
||||
while (chain.Valid() && !timedOut &&
|
||||
!(chain.Finished() && outputData.Finished && errorData.Finished)) {
|
||||
uv_run(&chain.GetLoop(), UV_RUN_ONCE);
|
||||
while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {
|
||||
// Put the output in the right place.
|
||||
if (p == cmsysProcess_Pipe_STDOUT && !arguments.OutputQuiet) {
|
||||
if (arguments.OutputVariable.empty() || arguments.EchoOutputVariable) {
|
||||
processOutput.DecodeText(data, length, strdata, 1);
|
||||
cmSystemTools::Stdout(strdata);
|
||||
}
|
||||
if (!arguments.OutputVariable.empty()) {
|
||||
cmExecuteProcessCommandAppend(tempOutput, data, length);
|
||||
}
|
||||
} else if (p == cmsysProcess_Pipe_STDERR && !arguments.ErrorQuiet) {
|
||||
if (arguments.ErrorVariable.empty() || arguments.EchoErrorVariable) {
|
||||
processOutput.DecodeText(data, length, strdata, 2);
|
||||
cmSystemTools::Stderr(strdata);
|
||||
}
|
||||
if (!arguments.ErrorVariable.empty()) {
|
||||
cmExecuteProcessCommandAppend(tempError, data, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!arguments.OutputQuiet &&
|
||||
(arguments.OutputVariable.empty() || arguments.EchoOutputVariable)) {
|
||||
@ -372,102 +305,151 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
}
|
||||
|
||||
// All output has been read.
|
||||
processOutput.DecodeText(outputData.Output, outputData.Output);
|
||||
processOutput.DecodeText(errorData.Output, errorData.Output);
|
||||
// All output has been read. Wait for the process to exit.
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
processOutput.DecodeText(tempOutput, tempOutput);
|
||||
processOutput.DecodeText(tempError, tempError);
|
||||
|
||||
// Fix the text in the output strings.
|
||||
cmExecuteProcessCommandFixText(outputData.Output,
|
||||
cmExecuteProcessCommandFixText(tempOutput,
|
||||
arguments.OutputStripTrailingWhitespace);
|
||||
cmExecuteProcessCommandFixText(errorData.Output,
|
||||
cmExecuteProcessCommandFixText(tempError,
|
||||
arguments.ErrorStripTrailingWhitespace);
|
||||
|
||||
// Store the output obtained.
|
||||
if (!arguments.OutputVariable.empty() && !outputData.Output.empty()) {
|
||||
if (!arguments.OutputVariable.empty() && !tempOutput.empty()) {
|
||||
status.GetMakefile().AddDefinition(arguments.OutputVariable,
|
||||
outputData.Output.data());
|
||||
tempOutput.data());
|
||||
}
|
||||
if (arguments.ErrorVariable != arguments.OutputVariable &&
|
||||
!arguments.ErrorVariable.empty() && !errorData.Output.empty()) {
|
||||
if (!merge_output && !arguments.ErrorVariable.empty() &&
|
||||
!tempError.empty()) {
|
||||
status.GetMakefile().AddDefinition(arguments.ErrorVariable,
|
||||
errorData.Output.data());
|
||||
tempError.data());
|
||||
}
|
||||
|
||||
// Store the result of running the process.
|
||||
if (!arguments.ResultVariable.empty()) {
|
||||
if (timedOut) {
|
||||
status.GetMakefile().AddDefinition(arguments.ResultVariable,
|
||||
"Process terminated due to timeout");
|
||||
} else {
|
||||
auto const* lastStatus = chain.GetStatus().back();
|
||||
auto exception = lastStatus->GetException();
|
||||
if (exception.first == cmUVProcessChain::ExceptionCode::None) {
|
||||
switch (cmsysProcess_GetState(cp)) {
|
||||
case cmsysProcess_State_Exited: {
|
||||
int v = cmsysProcess_GetExitValue(cp);
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%d", v);
|
||||
status.GetMakefile().AddDefinition(arguments.ResultVariable, buf);
|
||||
} break;
|
||||
case cmsysProcess_State_Exception:
|
||||
status.GetMakefile().AddDefinition(
|
||||
arguments.ResultVariable,
|
||||
std::to_string(static_cast<int>(lastStatus->ExitStatus)));
|
||||
} else {
|
||||
arguments.ResultVariable, cmsysProcess_GetExceptionString(cp));
|
||||
break;
|
||||
case cmsysProcess_State_Error:
|
||||
status.GetMakefile().AddDefinition(arguments.ResultVariable,
|
||||
exception.second);
|
||||
}
|
||||
cmsysProcess_GetErrorString(cp));
|
||||
break;
|
||||
case cmsysProcess_State_Expired:
|
||||
status.GetMakefile().AddDefinition(
|
||||
arguments.ResultVariable, "Process terminated due to timeout");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Store the result of running the processes.
|
||||
if (!arguments.ResultsVariable.empty()) {
|
||||
if (timedOut) {
|
||||
status.GetMakefile().AddDefinition(arguments.ResultsVariable,
|
||||
"Process terminated due to timeout");
|
||||
} else {
|
||||
std::vector<std::string> res;
|
||||
for (auto const* processStatus : chain.GetStatus()) {
|
||||
auto exception = processStatus->GetException();
|
||||
if (exception.first == cmUVProcessChain::ExceptionCode::None) {
|
||||
res.emplace_back(
|
||||
std::to_string(static_cast<int>(processStatus->ExitStatus)));
|
||||
} else {
|
||||
res.emplace_back(exception.second);
|
||||
switch (cmsysProcess_GetState(cp)) {
|
||||
case cmsysProcess_State_Exited: {
|
||||
std::vector<std::string> res;
|
||||
for (size_t i = 0; i < arguments.Commands.size(); ++i) {
|
||||
switch (cmsysProcess_GetStateByIndex(cp, static_cast<int>(i))) {
|
||||
case kwsysProcess_StateByIndex_Exited: {
|
||||
int exitCode =
|
||||
cmsysProcess_GetExitValueByIndex(cp, static_cast<int>(i));
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%d", exitCode);
|
||||
res.emplace_back(buf);
|
||||
} break;
|
||||
case kwsysProcess_StateByIndex_Exception:
|
||||
res.emplace_back(cmsysProcess_GetExceptionStringByIndex(
|
||||
cp, static_cast<int>(i)));
|
||||
break;
|
||||
case kwsysProcess_StateByIndex_Error:
|
||||
default:
|
||||
res.emplace_back("Error getting the child return code");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
status.GetMakefile().AddDefinition(arguments.ResultsVariable,
|
||||
cmList::to_string(res));
|
||||
status.GetMakefile().AddDefinition(arguments.ResultsVariable,
|
||||
cmList::to_string(res));
|
||||
} break;
|
||||
case cmsysProcess_State_Exception:
|
||||
status.GetMakefile().AddDefinition(
|
||||
arguments.ResultsVariable, cmsysProcess_GetExceptionString(cp));
|
||||
break;
|
||||
case cmsysProcess_State_Error:
|
||||
status.GetMakefile().AddDefinition(arguments.ResultsVariable,
|
||||
cmsysProcess_GetErrorString(cp));
|
||||
break;
|
||||
case cmsysProcess_State_Expired:
|
||||
status.GetMakefile().AddDefinition(
|
||||
arguments.ResultsVariable, "Process terminated due to timeout");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto queryProcessStatusByIndex = [&chain](std::size_t index) -> std::string {
|
||||
auto const& processStatus = chain.GetStatus(index);
|
||||
auto exception = processStatus.GetException();
|
||||
if (exception.first == cmUVProcessChain::ExceptionCode::None) {
|
||||
if (processStatus.ExitStatus) {
|
||||
return cmStrCat("Child return code: ", processStatus.ExitStatus);
|
||||
auto queryProcessStatusByIndex = [&cp](int index) -> std::string {
|
||||
std::string processStatus;
|
||||
switch (cmsysProcess_GetStateByIndex(cp, static_cast<int>(index))) {
|
||||
case kwsysProcess_StateByIndex_Exited: {
|
||||
int exitCode = cmsysProcess_GetExitValueByIndex(cp, index);
|
||||
if (exitCode) {
|
||||
processStatus = "Child return code: " + std::to_string(exitCode);
|
||||
}
|
||||
} break;
|
||||
case kwsysProcess_StateByIndex_Exception: {
|
||||
processStatus = cmStrCat(
|
||||
"Abnormal exit with child return code: ",
|
||||
cmsysProcess_GetExceptionStringByIndex(cp, static_cast<int>(index)));
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
case kwsysProcess_StateByIndex_Error:
|
||||
default:
|
||||
processStatus = "Error getting the child return code";
|
||||
break;
|
||||
}
|
||||
return cmStrCat("Abnormal exit with child return code: ",
|
||||
exception.second);
|
||||
return processStatus;
|
||||
};
|
||||
|
||||
if (arguments.CommandErrorIsFatal == "ANY"_s) {
|
||||
bool ret = true;
|
||||
if (timedOut) {
|
||||
status.SetError("Process terminated due to timeout");
|
||||
ret = false;
|
||||
} else {
|
||||
std::map<std::size_t, std::string> failureIndices;
|
||||
auto statuses = chain.GetStatus();
|
||||
for (std::size_t i = 0; i < statuses.size(); ++i) {
|
||||
std::string processStatus = queryProcessStatusByIndex(i);
|
||||
if (!processStatus.empty()) {
|
||||
failureIndices[i] = processStatus;
|
||||
switch (cmsysProcess_GetState(cp)) {
|
||||
case cmsysProcess_State_Exited: {
|
||||
std::map<int, std::string> failureIndices;
|
||||
for (int i = 0; i < static_cast<int>(arguments.Commands.size()); ++i) {
|
||||
std::string processStatus = queryProcessStatusByIndex(i);
|
||||
if (!processStatus.empty()) {
|
||||
failureIndices[i] = processStatus;
|
||||
}
|
||||
if (!failureIndices.empty()) {
|
||||
std::ostringstream oss;
|
||||
oss << "failed command indexes:\n";
|
||||
for (auto const& e : failureIndices) {
|
||||
oss << " " << e.first + 1 << ": \"" << e.second << "\"\n";
|
||||
}
|
||||
status.SetError(oss.str());
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!failureIndices.empty()) {
|
||||
std::ostringstream oss;
|
||||
oss << "failed command indexes:\n";
|
||||
for (auto const& e : failureIndices) {
|
||||
oss << " " << e.first + 1 << ": \"" << e.second << "\"\n";
|
||||
}
|
||||
status.SetError(oss.str());
|
||||
} break;
|
||||
case cmsysProcess_State_Exception:
|
||||
status.SetError(
|
||||
cmStrCat("abnormal exit: ", cmsysProcess_GetExceptionString(cp)));
|
||||
ret = false;
|
||||
}
|
||||
break;
|
||||
case cmsysProcess_State_Error:
|
||||
status.SetError(cmStrCat("error getting child return code: ",
|
||||
cmsysProcess_GetErrorString(cp)));
|
||||
ret = false;
|
||||
break;
|
||||
case cmsysProcess_State_Expired:
|
||||
status.SetError("Process terminated due to timeout");
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
@ -478,23 +460,29 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
|
||||
|
||||
if (arguments.CommandErrorIsFatal == "LAST"_s) {
|
||||
bool ret = true;
|
||||
if (timedOut) {
|
||||
status.SetError("Process terminated due to timeout");
|
||||
ret = false;
|
||||
} else {
|
||||
auto const& lastStatus = chain.GetStatus(arguments.Commands.size() - 1);
|
||||
auto exception = lastStatus.GetException();
|
||||
if (exception.first != cmUVProcessChain::ExceptionCode::None) {
|
||||
status.SetError(cmStrCat("Abnormal exit: ", exception.second));
|
||||
ret = false;
|
||||
} else {
|
||||
switch (cmsysProcess_GetState(cp)) {
|
||||
case cmsysProcess_State_Exited: {
|
||||
int lastIndex = static_cast<int>(arguments.Commands.size() - 1);
|
||||
const std::string processStatus = queryProcessStatusByIndex(lastIndex);
|
||||
if (!processStatus.empty()) {
|
||||
status.SetError("last command failed");
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case cmsysProcess_State_Exception:
|
||||
status.SetError(
|
||||
cmStrCat("Abnormal exit: ", cmsysProcess_GetExceptionString(cp)));
|
||||
ret = false;
|
||||
break;
|
||||
case cmsysProcess_State_Error:
|
||||
status.SetError(cmStrCat("Error getting child return code: ",
|
||||
cmsysProcess_GetErrorString(cp)));
|
||||
ret = false;
|
||||
break;
|
||||
case cmsysProcess_State_Expired:
|
||||
status.SetError("Process terminated due to timeout");
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
if (!ret) {
|
||||
cmSystemTools::SetFatalErrorOccurred();
|
||||
@ -537,7 +525,7 @@ void cmExecuteProcessCommandFixText(std::vector<char>& output,
|
||||
}
|
||||
|
||||
void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data,
|
||||
std::size_t length)
|
||||
int length)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
// HACK on Apple to work around bug with inserting at the
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
@ -13,6 +14,7 @@
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmCryptoHash.h"
|
||||
#include "cmExportSet.h"
|
||||
#include "cmFileSet.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
@ -156,7 +158,19 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
this->GenerateTargetFileSets(gte, os);
|
||||
}
|
||||
|
||||
this->GenerateCxxModuleInformation(os);
|
||||
std::string cxx_modules_name;
|
||||
if (this->ExportSet) {
|
||||
cxx_modules_name = this->ExportSet->GetName();
|
||||
} else {
|
||||
cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_512);
|
||||
constexpr std::size_t HASH_TRUNCATION = 12;
|
||||
for (auto const& target : this->Targets) {
|
||||
hasher.Append(target);
|
||||
}
|
||||
cxx_modules_name = hasher.FinalizeHex().substr(0, HASH_TRUNCATION);
|
||||
}
|
||||
|
||||
this->GenerateCxxModuleInformation(cxx_modules_name, os);
|
||||
|
||||
// Generate import file content for each configuration.
|
||||
for (std::string const& c : this->Configurations) {
|
||||
@ -165,7 +179,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
|
||||
// Generate import file content for each configuration.
|
||||
for (std::string const& c : this->Configurations) {
|
||||
this->GenerateImportCxxModuleConfigTargetInclusion(c);
|
||||
this->GenerateImportCxxModuleConfigTargetInclusion(cxx_modules_name, c);
|
||||
}
|
||||
|
||||
this->GenerateMissingTargetsCheckCode(os);
|
||||
@ -506,7 +520,7 @@ std::string cmExportBuildFileGenerator::GetCxxModulesDirectory() const
|
||||
}
|
||||
|
||||
void cmExportBuildFileGenerator::GenerateCxxModuleConfigInformation(
|
||||
std::ostream& os) const
|
||||
std::string const& name, std::ostream& os) const
|
||||
{
|
||||
const char* opt = "";
|
||||
if (this->Configurations.size() > 1) {
|
||||
@ -519,13 +533,13 @@ void cmExportBuildFileGenerator::GenerateCxxModuleConfigInformation(
|
||||
if (c.empty()) {
|
||||
c = "noconfig";
|
||||
}
|
||||
os << "include(\"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << c << ".cmake\""
|
||||
<< opt << ")\n";
|
||||
os << "include(\"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << name << '-'
|
||||
<< c << ".cmake\"" << opt << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion(
|
||||
std::string config) const
|
||||
std::string const& name, std::string config) const
|
||||
{
|
||||
auto cxx_modules_dirname = this->GetCxxModulesDirectory();
|
||||
if (cxx_modules_dirname.empty()) {
|
||||
@ -536,8 +550,9 @@ bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion(
|
||||
config = "noconfig";
|
||||
}
|
||||
|
||||
std::string fileName = cmStrCat(this->FileDir, '/', cxx_modules_dirname,
|
||||
"/cxx-modules-", config, ".cmake");
|
||||
std::string fileName =
|
||||
cmStrCat(this->FileDir, '/', cxx_modules_dirname, "/cxx-modules-", name,
|
||||
'-', config, ".cmake");
|
||||
|
||||
cmGeneratedFileStream os(fileName, true);
|
||||
if (!os) {
|
||||
|
@ -92,8 +92,10 @@ protected:
|
||||
cmTargetExport* te) override;
|
||||
|
||||
std::string GetCxxModulesDirectory() const override;
|
||||
void GenerateCxxModuleConfigInformation(std::ostream&) const override;
|
||||
bool GenerateImportCxxModuleConfigTargetInclusion(std::string) const;
|
||||
void GenerateCxxModuleConfigInformation(std::string const&,
|
||||
std::ostream&) const override;
|
||||
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&,
|
||||
std::string) const;
|
||||
|
||||
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
|
||||
cmGlobalGenerator* gg, const std::string& name);
|
||||
|
@ -1461,7 +1461,8 @@ void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
|
||||
}
|
||||
}
|
||||
|
||||
void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os)
|
||||
void cmExportFileGenerator::GenerateCxxModuleInformation(
|
||||
std::string const& name, std::ostream& os)
|
||||
{
|
||||
auto const cxx_module_dirname = this->GetCxxModulesDirectory();
|
||||
if (cxx_module_dirname.empty()) {
|
||||
@ -1471,17 +1472,17 @@ void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os)
|
||||
// Write the include.
|
||||
os << "# Include C++ module properties\n"
|
||||
<< "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname
|
||||
<< "/cxx-modules.cmake\")\n\n";
|
||||
<< "/cxx-modules-" << name << ".cmake\")\n\n";
|
||||
|
||||
// Get the path to the file we're going to write.
|
||||
std::string path = this->MainImportFile;
|
||||
path = cmSystemTools::GetFilenamePath(path);
|
||||
auto trampoline_path =
|
||||
cmStrCat(path, '/', cxx_module_dirname, "/cxx-modules.cmake");
|
||||
cmStrCat(path, '/', cxx_module_dirname, "/cxx-modules-", name, ".cmake");
|
||||
|
||||
// Include all configuration-specific include files.
|
||||
cmGeneratedFileStream ap(trampoline_path, true);
|
||||
ap.SetCopyIfDifferent(true);
|
||||
|
||||
this->GenerateCxxModuleConfigInformation(ap);
|
||||
this->GenerateCxxModuleConfigInformation(name, ap);
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ protected:
|
||||
void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
|
||||
cmTargetExport* te = nullptr);
|
||||
|
||||
void GenerateCxxModuleInformation(std::ostream& os);
|
||||
void GenerateCxxModuleInformation(std::string const& name, std::ostream& os);
|
||||
|
||||
virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
|
||||
cmFileSet* fileSet,
|
||||
@ -235,5 +235,6 @@ private:
|
||||
const std::string& config) = 0;
|
||||
|
||||
virtual std::string GetCxxModulesDirectory() const = 0;
|
||||
virtual void GenerateCxxModuleConfigInformation(std::ostream& os) const = 0;
|
||||
virtual void GenerateCxxModuleConfigInformation(std::string const&,
|
||||
std::ostream& os) const = 0;
|
||||
};
|
||||
|
@ -181,10 +181,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
|
||||
bool result = true;
|
||||
|
||||
this->GenerateCxxModuleInformation(os);
|
||||
std::string cxx_modules_name = this->IEGen->GetExportSet()->GetName();
|
||||
this->GenerateCxxModuleInformation(cxx_modules_name, os);
|
||||
if (requiresConfigFiles) {
|
||||
for (std::string const& c : this->Configurations) {
|
||||
if (!this->GenerateImportCxxModuleConfigTargetInclusion(c)) {
|
||||
if (!this->GenerateImportCxxModuleConfigTargetInclusion(cxx_modules_name,
|
||||
c)) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
@ -718,12 +720,12 @@ std::string cmExportInstallFileGenerator::GetCxxModulesDirectory() const
|
||||
}
|
||||
|
||||
void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation(
|
||||
std::ostream& os) const
|
||||
std::string const& name, std::ostream& os) const
|
||||
{
|
||||
// Now load per-configuration properties for them.
|
||||
/* clang-format off */
|
||||
os << "# Load information for each installed configuration.\n"
|
||||
"file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-*.cmake\")\n"
|
||||
"file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << name << "-*.cmake\")\n"
|
||||
"foreach(_cmake_cxx_module_include IN LISTS _cmake_cxx_module_includes)\n"
|
||||
" include(\"${_cmake_cxx_module_include}\")\n"
|
||||
"endforeach()\n"
|
||||
@ -733,7 +735,8 @@ void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation(
|
||||
}
|
||||
|
||||
bool cmExportInstallFileGenerator::
|
||||
GenerateImportCxxModuleConfigTargetInclusion(std::string const& config)
|
||||
GenerateImportCxxModuleConfigTargetInclusion(std::string const& name,
|
||||
std::string const& config)
|
||||
{
|
||||
auto cxx_modules_dirname = this->GetCxxModulesDirectory();
|
||||
if (cxx_modules_dirname.empty()) {
|
||||
@ -748,7 +751,7 @@ bool cmExportInstallFileGenerator::
|
||||
std::string const dest =
|
||||
cmStrCat(this->FileDir, '/', cxx_modules_dirname, '/');
|
||||
std::string fileName =
|
||||
cmStrCat(dest, "cxx-modules-", filename_config, ".cmake");
|
||||
cmStrCat(dest, "cxx-modules-", name, '-', filename_config, ".cmake");
|
||||
|
||||
cmGeneratedFileStream os(fileName, true);
|
||||
if (!os) {
|
||||
|
@ -118,8 +118,10 @@ protected:
|
||||
cmTargetExport* te) override;
|
||||
|
||||
std::string GetCxxModulesDirectory() const override;
|
||||
void GenerateCxxModuleConfigInformation(std::ostream&) const override;
|
||||
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&);
|
||||
void GenerateCxxModuleConfigInformation(std::string const&,
|
||||
std::ostream&) const override;
|
||||
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&,
|
||||
std::string const&);
|
||||
|
||||
cmInstallExportGenerator* IEGen;
|
||||
|
||||
|
@ -56,7 +56,10 @@ protected:
|
||||
cmTargetExport* te) override;
|
||||
|
||||
std::string GetCxxModulesDirectory() const override { return {}; }
|
||||
void GenerateCxxModuleConfigInformation(std::ostream&) const override {}
|
||||
void GenerateCxxModuleConfigInformation(std::string const&,
|
||||
std::ostream&) const override
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
std::string FindTargets(const std::string& prop,
|
||||
|
@ -207,7 +207,7 @@ struct cmFindLibraryHelper
|
||||
std::string BestPath;
|
||||
|
||||
// Support for OpenBSD shared library naming: lib<name>.so.<major>.<minor>
|
||||
bool OpenBSD;
|
||||
bool IsOpenBSD;
|
||||
|
||||
bool DebugMode;
|
||||
|
||||
@ -320,7 +320,7 @@ cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
|
||||
this->RegexFromList(this->SuffixRegexStr, this->Suffixes);
|
||||
|
||||
// Check whether to use OpenBSD-style library version comparisons.
|
||||
this->OpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
|
||||
this->IsOpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
|
||||
"FIND_LIBRARY_USE_OPENBSD_VERSIONING");
|
||||
}
|
||||
|
||||
@ -390,7 +390,7 @@ void cmFindLibraryHelper::AddName(std::string const& name)
|
||||
std::string regex = cmStrCat('^', this->PrefixRegexStr);
|
||||
this->RegexFromLiteral(regex, name);
|
||||
regex += this->SuffixRegexStr;
|
||||
if (this->OpenBSD) {
|
||||
if (this->IsOpenBSD) {
|
||||
regex += "(\\.[0-9]+\\.[0-9]+)?";
|
||||
}
|
||||
regex += "$";
|
||||
@ -472,7 +472,7 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
|
||||
size_type suffix = this->GetSuffixIndex(name.Regex.match(2));
|
||||
unsigned int major = 0;
|
||||
unsigned int minor = 0;
|
||||
if (this->OpenBSD) {
|
||||
if (this->IsOpenBSD) {
|
||||
sscanf(name.Regex.match(3).c_str(), ".%u.%u", &major, &minor);
|
||||
}
|
||||
if (this->BestPath.empty() || prefix < bestPrefix ||
|
||||
|
@ -8319,14 +8319,14 @@ bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache,
|
||||
}
|
||||
|
||||
if (gt->HaveCxx20ModuleSources()) {
|
||||
auto hasher = cmCryptoHash::New("SHA3_512");
|
||||
cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_512);
|
||||
constexpr size_t HASH_TRUNCATION = 12;
|
||||
auto dirhash = hasher->HashString(
|
||||
auto dirhash = hasher.HashString(
|
||||
gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
|
||||
std::string safeName = gt->GetName();
|
||||
cmSystemTools::ReplaceString(safeName, ":", "_");
|
||||
auto targetIdent =
|
||||
hasher->HashString(cmStrCat("@d_", dirhash, "@u_", usage.GetHash()));
|
||||
hasher.HashString(cmStrCat("@d_", dirhash, "@u_", usage.GetHash()));
|
||||
std::string targetName =
|
||||
cmStrCat(safeName, "@synth_", targetIdent.substr(0, HASH_TRUNCATION));
|
||||
|
||||
@ -8762,11 +8762,23 @@ bool cmGeneratorTarget::IsFrameworkOnApple() const
|
||||
bool cmGeneratorTarget::IsImportedFrameworkFolderOnApple(
|
||||
const std::string& config) const
|
||||
{
|
||||
return this->IsApple() && this->IsImported() &&
|
||||
(this->GetType() == cmStateEnums::STATIC_LIBRARY ||
|
||||
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
|
||||
this->GetType() == cmStateEnums::UNKNOWN_LIBRARY) &&
|
||||
cmSystemTools::IsPathToFramework(this->GetLocation(config));
|
||||
if (this->IsApple() && this->IsImported() &&
|
||||
(this->GetType() == cmStateEnums::STATIC_LIBRARY ||
|
||||
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
|
||||
this->GetType() == cmStateEnums::UNKNOWN_LIBRARY)) {
|
||||
std::string cfg = config;
|
||||
if (cfg.empty() && this->GetGlobalGenerator()->IsXcode()) {
|
||||
// FIXME(#25515): Remove the need for this workaround.
|
||||
// The Xcode generator queries include directories without any
|
||||
// specific configuration. Pick one in case this target does
|
||||
// not set either IMPORTED_LOCATION or IMPORTED_CONFIGURATIONS.
|
||||
cfg =
|
||||
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig)[0];
|
||||
}
|
||||
return cmSystemTools::IsPathToFramework(this->GetLocation(cfg));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::IsAppBundleOnApple() const
|
||||
|
@ -1587,6 +1587,13 @@ bool cmGlobalGenerator::Compute()
|
||||
}
|
||||
}
|
||||
|
||||
// Add unity sources after computing compile features. Unity sources do
|
||||
// not change the set of languages or features, but we need to know them
|
||||
// to filter out sources that are scanned for C++ module dependencies.
|
||||
if (!this->AddUnitySources()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& localGen : this->LocalGenerators) {
|
||||
cmMakefile* mf = localGen->GetMakefile();
|
||||
for (const auto& g : mf->GetInstallGenerators()) {
|
||||
@ -1863,7 +1870,6 @@ bool cmGlobalGenerator::AddAutomaticSources()
|
||||
if (!gt->CanCompileSources()) {
|
||||
continue;
|
||||
}
|
||||
lg->AddUnityBuild(gt.get());
|
||||
lg->AddISPCDependencies(gt.get());
|
||||
// Targets that reuse a PCH are handled below.
|
||||
if (!gt->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
|
||||
@ -1895,6 +1901,28 @@ bool cmGlobalGenerator::AddAutomaticSources()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmGlobalGenerator::AddUnitySources()
|
||||
{
|
||||
for (const auto& lg : this->LocalGenerators) {
|
||||
for (const auto& gt : lg->GetGeneratorTargets()) {
|
||||
if (!gt->CanCompileSources()) {
|
||||
continue;
|
||||
}
|
||||
lg->AddUnityBuild(gt.get());
|
||||
}
|
||||
}
|
||||
// The above transformation may have changed the classification of sources.
|
||||
// Clear the source list and classification cache (KindedSources) of all
|
||||
// targets so that it will be recomputed correctly by the generators later
|
||||
// now that the above transformations are done for all targets.
|
||||
for (const auto& lg : this->LocalGenerators) {
|
||||
for (const auto& gt : lg->GetGeneratorTargets()) {
|
||||
gt->ClearSourcesCache();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<cmLinkLineComputer> cmGlobalGenerator::CreateLinkLineComputer(
|
||||
cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const
|
||||
{
|
||||
|
@ -677,6 +677,7 @@ protected:
|
||||
bool AddHeaderSetVerification();
|
||||
|
||||
bool AddAutomaticSources();
|
||||
bool AddUnitySources();
|
||||
|
||||
std::string SelectMakeProgram(const std::string& makeProgram,
|
||||
const std::string& makeDefault = "") const;
|
||||
|
@ -564,6 +564,7 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm)
|
||||
this->Comspec = "cmd.exe";
|
||||
}
|
||||
#endif
|
||||
cm->GetState()->SetNinja(true);
|
||||
this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake";
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "cmImportedCxxModuleInfo.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -60,13 +59,13 @@ std::string ImportedCxxModuleLookup::BmiNameForSource(std::string const& path)
|
||||
|
||||
auto importit = this->ImportedInfo.find(path);
|
||||
std::string bmiName;
|
||||
auto hasher = cmCryptoHash::New("SHA3_512");
|
||||
cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_512);
|
||||
constexpr size_t HASH_TRUNCATION = 12;
|
||||
if (importit != this->ImportedInfo.end()) {
|
||||
auto safename = hasher->HashString(importit->second.Name);
|
||||
auto safename = hasher.HashString(importit->second.Name);
|
||||
bmiName = cmStrCat(safename.substr(0, HASH_TRUNCATION), ".bmi");
|
||||
} else {
|
||||
auto dirhash = hasher->HashString(path);
|
||||
auto dirhash = hasher.HashString(path);
|
||||
bmiName = cmStrCat(dirhash.substr(0, HASH_TRUNCATION), ".bmi");
|
||||
}
|
||||
|
||||
|
@ -158,10 +158,11 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
|
||||
// Remove old per-configuration export files if the main changes.
|
||||
std::string installedDir = cmStrCat(
|
||||
"$ENV{DESTDIR}", ConvertToAbsoluteDestination(cxx_module_dest), '/');
|
||||
std::string installedFile = cmStrCat(installedDir, "/cxx-modules.cmake");
|
||||
std::string installedFile = cmStrCat(installedDir, "/cxx-modules-",
|
||||
this->ExportSet->GetName(), ".cmake");
|
||||
std::string toInstallFile =
|
||||
cmStrCat(cmSystemTools::GetFilenamePath(config_file_example),
|
||||
"/cxx-modules.cmake");
|
||||
"/cxx-modules-", this->ExportSet->GetName(), ".cmake");
|
||||
os << indent << "if(EXISTS \"" << installedFile << "\")\n";
|
||||
Indent indentN = indent.Next();
|
||||
Indent indentNN = indentN.Next();
|
||||
|
@ -3134,6 +3134,15 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
|
||||
std::vector<cmSourceFile*> sources;
|
||||
target->GetSourceFiles(sources, configs[ci]);
|
||||
for (cmSourceFile* sf : sources) {
|
||||
// Files which need C++ scanning cannot participate in unity builds as
|
||||
// there is a single place in TUs that may perform module-dependency bits
|
||||
// and a unity source cannot `#include` them in-order and represent a
|
||||
// valid TU.
|
||||
if (sf->GetLanguage() == "CXX"_s &&
|
||||
target->NeedDyndepForSource("CXX", configs[ci], sf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto mi = index.find(sf);
|
||||
if (mi == index.end()) {
|
||||
unitySources.emplace_back(sf);
|
||||
|
@ -1722,11 +1722,10 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
|
||||
|
||||
if (!ccg.GetCC().GetDepfile().empty()) {
|
||||
// Add dependency over timestamp file for dependencies management
|
||||
auto dependTimestamp = cmSystemTools::ConvertToOutputPath(
|
||||
this->LocalGenerator->MaybeRelativeToTopBinDir(
|
||||
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")));
|
||||
auto dependTimestamp = this->LocalGenerator->MaybeRelativeToTopBinDir(
|
||||
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"));
|
||||
|
||||
depends.push_back(dependTimestamp);
|
||||
depends.emplace_back(std::move(dependTimestamp));
|
||||
}
|
||||
|
||||
// Write the rule.
|
||||
|
@ -1373,8 +1373,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
|
||||
bool const needDyndep = !isPch &&
|
||||
this->GeneratorTarget->NeedDyndepForSource(language, config, source);
|
||||
|
||||
cmNinjaBuild objBuild(this->LanguageCompilerRule(
|
||||
language, config, needDyndep ? WithScanning::Yes : WithScanning::No));
|
||||
WithScanning withScanning =
|
||||
needDyndep ? WithScanning::Yes : WithScanning::No;
|
||||
cmNinjaBuild objBuild(
|
||||
this->LanguageCompilerRule(language, config, withScanning));
|
||||
cmNinjaVars& vars = objBuild.Variables;
|
||||
vars["FLAGS"] =
|
||||
this->ComputeFlagsForObject(source, language, config, objectFileName);
|
||||
@ -1434,7 +1436,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
|
||||
if (firstForConfig) {
|
||||
this->ExportObjectCompileCommand(
|
||||
language, sourceFilePath, objectDir, objectFileName, objectFileDir,
|
||||
vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
|
||||
vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config, withScanning);
|
||||
}
|
||||
|
||||
objBuild.Outputs.push_back(objectFileName);
|
||||
@ -1780,7 +1782,7 @@ void cmNinjaTargetGenerator::WriteCxxModuleBmiBuildStatement(
|
||||
if (firstForConfig) {
|
||||
this->ExportObjectCompileCommand(
|
||||
language, sourceFilePath, bmiDir, bmiFileName, bmiFileDir, vars["FLAGS"],
|
||||
vars["DEFINES"], vars["INCLUDES"], config);
|
||||
vars["DEFINES"], vars["INCLUDES"], config, WithScanning::Yes);
|
||||
}
|
||||
|
||||
bmiBuild.Outputs.push_back(bmiFileName);
|
||||
@ -1992,7 +1994,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
|
||||
std::string const& objectDir, std::string const& objectFileName,
|
||||
std::string const& objectFileDir, std::string const& flags,
|
||||
std::string const& defines, std::string const& includes,
|
||||
std::string const& outputConfig)
|
||||
std::string const& outputConfig, WithScanning withScanning)
|
||||
{
|
||||
if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) {
|
||||
return;
|
||||
@ -2015,14 +2017,12 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
|
||||
escapedSourceFileName, cmOutputConverter::SHELL);
|
||||
|
||||
std::string fullFlags = flags;
|
||||
{
|
||||
bool const needDyndep =
|
||||
this->GetGeneratorTarget()->NeedDyndep(language, outputConfig);
|
||||
if (withScanning == WithScanning::Yes) {
|
||||
std::string const modmapFormatVar =
|
||||
cmStrCat("CMAKE_", language, "_MODULE_MAP_FORMAT");
|
||||
std::string const modmapFormat =
|
||||
this->Makefile->GetSafeDefinition(modmapFormatVar);
|
||||
if (needDyndep && !modmapFormat.empty()) {
|
||||
if (!modmapFormat.empty()) {
|
||||
std::string modmapFlags = this->GetMakefile()->GetRequiredDefinition(
|
||||
cmStrCat("CMAKE_", language, "_MODULE_MAP_FLAG"));
|
||||
// XXX(modmap): If changing this path construction, change
|
||||
|
@ -189,7 +189,7 @@ protected:
|
||||
std::string const& objectDir, std::string const& objectFileName,
|
||||
std::string const& objectFileDir, std::string const& flags,
|
||||
std::string const& defines, std::string const& includes,
|
||||
std::string const& outputConfig);
|
||||
std::string const& outputConfig, WithScanning withScanning);
|
||||
|
||||
void AdditionalCleanFiles(const std::string& config);
|
||||
|
||||
|
@ -275,6 +275,9 @@ std::string cmOutputConverter::EscapeForShell(cm::string_view str,
|
||||
if (this->GetState()->UseNMake()) {
|
||||
flags |= Shell_Flag_NMake;
|
||||
}
|
||||
if (this->GetState()->UseNinja()) {
|
||||
flags |= Shell_Flag_Ninja;
|
||||
}
|
||||
if (!this->GetState()->UseWindowsShell()) {
|
||||
flags |= Shell_Flag_IsUnix;
|
||||
}
|
||||
@ -677,6 +680,12 @@ std::string cmOutputConverter::Shell_GetArgument(cm::string_view in, int flags)
|
||||
/* Otherwise a semicolon is written just ;. */
|
||||
out += ';';
|
||||
}
|
||||
} else if (*cit == '\n') {
|
||||
if (flags & Shell_Flag_Ninja) {
|
||||
out += "$\n";
|
||||
} else {
|
||||
out += '\n';
|
||||
}
|
||||
} else {
|
||||
/* Store this character. */
|
||||
out += *cit;
|
||||
|
@ -100,7 +100,10 @@ public:
|
||||
|
||||
Shell_Flag_UnescapeNinjaConfiguration = (1 << 9),
|
||||
|
||||
Shell_Flag_IsResponse = (1 << 10)
|
||||
Shell_Flag_IsResponse = (1 << 10),
|
||||
|
||||
/** The target shell is in a Ninja build file. */
|
||||
Shell_Flag_Ninja = (1 << 11)
|
||||
};
|
||||
|
||||
std::string EscapeForShell(cm::string_view str, bool makeVars = false,
|
||||
|
@ -2,68 +2,48 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmProcessTools.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <ostream>
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
#include "cmsys/Process.h"
|
||||
|
||||
#include "cmProcessOutput.h"
|
||||
#include "cmUVHandlePtr.h"
|
||||
#include "cmUVStream.h"
|
||||
|
||||
std::vector<cmUVProcessChain::Status> cmProcessTools::RunProcess(
|
||||
cmUVProcessChainBuilder& builder, OutputParser* out, OutputParser* err,
|
||||
Encoding encoding)
|
||||
void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out,
|
||||
OutputParser* err, Encoding encoding)
|
||||
{
|
||||
cmsysProcess_Execute(cp);
|
||||
char* data = nullptr;
|
||||
int length = 0;
|
||||
int p;
|
||||
cmProcessOutput processOutput(encoding);
|
||||
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
|
||||
|
||||
auto chain = builder.Start();
|
||||
|
||||
std::string strdata;
|
||||
cm::uv_pipe_ptr outputPipe;
|
||||
outputPipe.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(outputPipe, chain.OutputStream());
|
||||
auto outputHandle = cmUVStreamRead(
|
||||
outputPipe,
|
||||
[&out, &processOutput, &strdata](std::vector<char> data) {
|
||||
if (out) {
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata, 1);
|
||||
if (!out->Process(strdata.c_str(), static_cast<int>(strdata.size()))) {
|
||||
out = nullptr;
|
||||
}
|
||||
while ((out || err) &&
|
||||
(p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {
|
||||
if (out && p == cmsysProcess_Pipe_STDOUT) {
|
||||
processOutput.DecodeText(data, length, strdata, 1);
|
||||
if (!out->Process(strdata.c_str(), static_cast<int>(strdata.size()))) {
|
||||
out = nullptr;
|
||||
}
|
||||
},
|
||||
[&out]() { out = nullptr; });
|
||||
cm::uv_pipe_ptr errorPipe;
|
||||
errorPipe.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(errorPipe, chain.ErrorStream());
|
||||
auto errorHandle = cmUVStreamRead(
|
||||
errorPipe,
|
||||
[&err, &processOutput, &strdata](std::vector<char> data) {
|
||||
if (err) {
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata, 2);
|
||||
if (!err->Process(strdata.c_str(), static_cast<int>(strdata.size()))) {
|
||||
err = nullptr;
|
||||
}
|
||||
} else if (err && p == cmsysProcess_Pipe_STDERR) {
|
||||
processOutput.DecodeText(data, length, strdata, 2);
|
||||
if (!err->Process(strdata.c_str(), static_cast<int>(strdata.size()))) {
|
||||
err = nullptr;
|
||||
}
|
||||
},
|
||||
[&err]() { err = nullptr; });
|
||||
while (out || err || !chain.Finished()) {
|
||||
uv_run(&chain.GetLoop(), UV_RUN_ONCE);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<cmUVProcessChain::Status> result;
|
||||
auto status = chain.GetStatus();
|
||||
std::transform(
|
||||
status.begin(), status.end(), std::back_inserter(result),
|
||||
[](const cmUVProcessChain::Status* s) -> cmUVProcessChain::Status {
|
||||
return *s;
|
||||
});
|
||||
return result;
|
||||
if (out) {
|
||||
processOutput.DecodeText(std::string(), strdata, 1);
|
||||
if (!strdata.empty()) {
|
||||
out->Process(strdata.c_str(), static_cast<int>(strdata.size()));
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
processOutput.DecodeText(std::string(), strdata, 2);
|
||||
if (!strdata.empty()) {
|
||||
err->Process(strdata.c_str(), static_cast<int>(strdata.size()));
|
||||
}
|
||||
}
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
}
|
||||
|
||||
cmProcessTools::LineParser::LineParser(char sep, bool ignoreCR)
|
||||
|
@ -7,10 +7,8 @@
|
||||
#include <cstring>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmProcessOutput.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
|
||||
/** \class cmProcessTools
|
||||
* \brief Helper classes for process output parsing
|
||||
@ -83,7 +81,7 @@ public:
|
||||
};
|
||||
|
||||
/** Run a process and send output to given parsers. */
|
||||
static std::vector<cmUVProcessChain::Status> RunProcess(
|
||||
cmUVProcessChainBuilder& builder, OutputParser* out,
|
||||
OutputParser* err = nullptr, Encoding encoding = cmProcessOutput::Auto);
|
||||
static void RunProcess(struct cmsysProcess_s* cp, OutputParser* out,
|
||||
OutputParser* err = nullptr,
|
||||
Encoding encoding = cmProcessOutput::Auto);
|
||||
};
|
||||
|
@ -70,7 +70,7 @@ unsigned int GetParallelCPUCount()
|
||||
return count;
|
||||
}
|
||||
|
||||
std::string FileProjectRelativePath(cmMakefile* makefile,
|
||||
std::string FileProjectRelativePath(cmMakefile const* makefile,
|
||||
std::string const& fileName)
|
||||
{
|
||||
std::string res;
|
||||
@ -1369,7 +1369,6 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
|
||||
std::vector<std::string> dependencies(
|
||||
this->AutogenTarget.DependFiles.begin(),
|
||||
this->AutogenTarget.DependFiles.end());
|
||||
|
||||
if (useDepfile) {
|
||||
// Create a custom command that generates a timestamp file and
|
||||
// has a depfile assigned. The depfile is created by JobDepFilesMergeT.
|
||||
@ -1408,6 +1407,16 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
|
||||
cc->SetEscapeOldStyle(false);
|
||||
cmTarget* timestampTarget = this->LocalGen->AddUtilityCommand(
|
||||
timestampTargetName, true, std::move(cc));
|
||||
auto const isMake =
|
||||
this->GlobalGen->GetName().find("Make") != std::string::npos;
|
||||
if (this->AutogenTarget.DependOrigin && isMake) {
|
||||
for (BT<std::pair<std::string, bool>> const& depName :
|
||||
this->GenTarget->GetUtilities()) {
|
||||
timestampTarget->AddUtility(depName.Value.first, false,
|
||||
this->Makefile);
|
||||
}
|
||||
}
|
||||
|
||||
this->LocalGen->AddGeneratorTarget(
|
||||
cm::make_unique<cmGeneratorTarget>(timestampTarget, this->LocalGen));
|
||||
|
||||
|
@ -752,6 +752,16 @@ bool cmState::UseMSYSShell() const
|
||||
return this->MSYSShell;
|
||||
}
|
||||
|
||||
void cmState::SetNinja(bool ninja)
|
||||
{
|
||||
this->Ninja = ninja;
|
||||
}
|
||||
|
||||
bool cmState::UseNinja() const
|
||||
{
|
||||
return this->Ninja;
|
||||
}
|
||||
|
||||
void cmState::SetNinjaMulti(bool ninjaMulti)
|
||||
{
|
||||
this->NinjaMulti = ninjaMulti;
|
||||
|
@ -220,6 +220,8 @@ public:
|
||||
bool UseNMake() const;
|
||||
void SetMSYSShell(bool mSYSShell);
|
||||
bool UseMSYSShell() const;
|
||||
void SetNinja(bool ninja);
|
||||
bool UseNinja() const;
|
||||
void SetNinjaMulti(bool ninjaMulti);
|
||||
bool UseNinjaMulti() const;
|
||||
|
||||
@ -297,6 +299,7 @@ private:
|
||||
bool MinGWMake = false;
|
||||
bool NMake = false;
|
||||
bool MSYSShell = false;
|
||||
bool Ninja = false;
|
||||
bool NinjaMulti = false;
|
||||
Mode StateMode = Unknown;
|
||||
ProjectKind StateProjectKind = ProjectKind::Normal;
|
||||
|
@ -25,17 +25,12 @@
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
|
||||
#include "cm_fileno.hxx"
|
||||
|
||||
#include "cmDuration.h"
|
||||
#include "cmELF.h"
|
||||
#include "cmMessageMetadata.h"
|
||||
#include "cmProcessOutput.h"
|
||||
#include "cmRange.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmUVHandlePtr.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
#include "cmUVStream.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
#if !defined(CMAKE_BOOTSTRAP)
|
||||
@ -64,14 +59,12 @@
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -575,115 +568,85 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
|
||||
const char* dir, OutputOption outputflag,
|
||||
cmDuration timeout, Encoding encoding)
|
||||
{
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT, cm_fileno(stdin))
|
||||
.AddCommand(command);
|
||||
if (dir) {
|
||||
builder.SetWorkingDirectory(dir);
|
||||
std::vector<const char*> argv;
|
||||
argv.reserve(command.size() + 1);
|
||||
for (std::string const& cmd : command) {
|
||||
argv.push_back(cmd.c_str());
|
||||
}
|
||||
argv.push_back(nullptr);
|
||||
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
cmsysProcess_SetCommand(cp, argv.data());
|
||||
cmsysProcess_SetWorkingDirectory(cp, dir);
|
||||
if (cmSystemTools::GetRunCommandHideConsole()) {
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
|
||||
}
|
||||
|
||||
if (outputflag == OUTPUT_PASSTHROUGH) {
|
||||
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
|
||||
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
|
||||
captureStdOut = nullptr;
|
||||
captureStdErr = nullptr;
|
||||
builder
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT,
|
||||
cm_fileno(stdout))
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR,
|
||||
cm_fileno(stderr));
|
||||
} else if (outputflag == OUTPUT_MERGE ||
|
||||
(captureStdErr && captureStdErr == captureStdOut)) {
|
||||
builder.SetMergedBuiltinStreams();
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1);
|
||||
captureStdErr = nullptr;
|
||||
} else {
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
|
||||
}
|
||||
assert(!captureStdErr || captureStdErr != captureStdOut);
|
||||
|
||||
auto chain = builder.Start();
|
||||
bool timedOut = false;
|
||||
cm::uv_timer_ptr timer;
|
||||
if (timeout.count()) {
|
||||
timer.init(chain.GetLoop(), &timedOut);
|
||||
timer.start(
|
||||
[](uv_timer_t* t) {
|
||||
auto* timedOutPtr = static_cast<bool*>(t->data);
|
||||
*timedOutPtr = true;
|
||||
},
|
||||
static_cast<uint64_t>(timeout.count() * 1000.0), 0);
|
||||
}
|
||||
cmsysProcess_SetTimeout(cp, timeout.count());
|
||||
cmsysProcess_Execute(cp);
|
||||
|
||||
std::vector<char> tempStdOut;
|
||||
std::vector<char> tempStdErr;
|
||||
cm::uv_pipe_ptr outStream;
|
||||
bool outFinished = true;
|
||||
cm::uv_pipe_ptr errStream;
|
||||
bool errFinished = true;
|
||||
char* data;
|
||||
int length;
|
||||
int pipe;
|
||||
cmProcessOutput processOutput(encoding);
|
||||
std::unique_ptr<cmUVStreamReadHandle> outputHandle;
|
||||
std::unique_ptr<cmUVStreamReadHandle> errorHandle;
|
||||
std::string strdata;
|
||||
if (outputflag != OUTPUT_PASSTHROUGH &&
|
||||
(captureStdOut || captureStdErr || outputflag != OUTPUT_NONE)) {
|
||||
auto startRead =
|
||||
[&outputflag, &processOutput,
|
||||
&chain](cm::uv_pipe_ptr& pipe, int stream, std::string* captureStd,
|
||||
std::vector<char>& tempStd, int id,
|
||||
void (*outputFunc)(const std::string&),
|
||||
bool& finished) -> std::unique_ptr<cmUVStreamReadHandle> {
|
||||
if (stream < 0) {
|
||||
return nullptr;
|
||||
while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, nullptr)) >
|
||||
0) {
|
||||
// Translate NULL characters in the output into valid text.
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (data[i] == '\0') {
|
||||
data[i] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
pipe.init(chain.GetLoop(), 0);
|
||||
uv_pipe_open(pipe, stream);
|
||||
if (pipe == cmsysProcess_Pipe_STDOUT) {
|
||||
if (outputflag != OUTPUT_NONE) {
|
||||
processOutput.DecodeText(data, length, strdata, 1);
|
||||
cmSystemTools::Stdout(strdata);
|
||||
}
|
||||
if (captureStdOut) {
|
||||
cm::append(tempStdOut, data, data + length);
|
||||
}
|
||||
} else if (pipe == cmsysProcess_Pipe_STDERR) {
|
||||
if (outputflag != OUTPUT_NONE) {
|
||||
processOutput.DecodeText(data, length, strdata, 2);
|
||||
cmSystemTools::Stderr(strdata);
|
||||
}
|
||||
if (captureStdErr) {
|
||||
cm::append(tempStdErr, data, data + length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finished = false;
|
||||
return cmUVStreamRead(
|
||||
pipe,
|
||||
[outputflag, &processOutput, captureStd, &tempStd, id,
|
||||
outputFunc](std::vector<char> data) {
|
||||
// Translate NULL characters in the output into valid text.
|
||||
for (auto& c : data) {
|
||||
if (c == '\0') {
|
||||
c = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
if (outputflag != OUTPUT_NONE) {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(data.data(), data.size(), strdata, id);
|
||||
outputFunc(strdata);
|
||||
}
|
||||
if (captureStd) {
|
||||
cm::append(tempStd, data.data(), data.data() + data.size());
|
||||
}
|
||||
},
|
||||
[&finished, outputflag, &processOutput, id, outputFunc]() {
|
||||
finished = true;
|
||||
if (outputflag != OUTPUT_NONE) {
|
||||
std::string strdata;
|
||||
processOutput.DecodeText(std::string(), strdata, id);
|
||||
if (!strdata.empty()) {
|
||||
outputFunc(strdata);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
outputHandle =
|
||||
startRead(outStream, chain.OutputStream(), captureStdOut, tempStdOut, 1,
|
||||
cmSystemTools::Stdout, outFinished);
|
||||
if (chain.OutputStream() != chain.ErrorStream()) {
|
||||
errorHandle =
|
||||
startRead(errStream, chain.ErrorStream(), captureStdErr, tempStdErr, 2,
|
||||
cmSystemTools::Stderr, errFinished);
|
||||
if (outputflag != OUTPUT_NONE) {
|
||||
processOutput.DecodeText(std::string(), strdata, 1);
|
||||
if (!strdata.empty()) {
|
||||
cmSystemTools::Stdout(strdata);
|
||||
}
|
||||
processOutput.DecodeText(std::string(), strdata, 2);
|
||||
if (!strdata.empty()) {
|
||||
cmSystemTools::Stderr(strdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!timedOut && !(chain.Finished() && outFinished && errFinished)) {
|
||||
uv_run(&chain.GetLoop(), UV_RUN_ONCE);
|
||||
}
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
|
||||
if (captureStdOut) {
|
||||
captureStdOut->assign(tempStdOut.begin(), tempStdOut.end());
|
||||
@ -695,7 +658,37 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
if (timedOut) {
|
||||
if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
|
||||
if (retVal) {
|
||||
*retVal = cmsysProcess_GetExitValue(cp);
|
||||
} else {
|
||||
if (cmsysProcess_GetExitValue(cp) != 0) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
} else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) {
|
||||
const char* exception_str = cmsysProcess_GetExceptionString(cp);
|
||||
if (outputflag != OUTPUT_NONE) {
|
||||
std::cerr << exception_str << std::endl;
|
||||
}
|
||||
if (captureStdErr) {
|
||||
captureStdErr->append(exception_str, strlen(exception_str));
|
||||
} else if (captureStdOut) {
|
||||
captureStdOut->append(exception_str, strlen(exception_str));
|
||||
}
|
||||
result = false;
|
||||
} else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) {
|
||||
const char* error_str = cmsysProcess_GetErrorString(cp);
|
||||
if (outputflag != OUTPUT_NONE) {
|
||||
std::cerr << error_str << std::endl;
|
||||
}
|
||||
if (captureStdErr) {
|
||||
captureStdErr->append(error_str, strlen(error_str));
|
||||
} else if (captureStdOut) {
|
||||
captureStdOut->append(error_str, strlen(error_str));
|
||||
}
|
||||
result = false;
|
||||
} else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) {
|
||||
const char* error_str = "Process terminated due to timeout\n";
|
||||
if (outputflag != OUTPUT_NONE) {
|
||||
std::cerr << error_str << std::endl;
|
||||
@ -704,34 +697,9 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
|
||||
captureStdErr->append(error_str, strlen(error_str));
|
||||
}
|
||||
result = false;
|
||||
} else {
|
||||
auto const& status = chain.GetStatus(0);
|
||||
auto exception = status.GetException();
|
||||
|
||||
switch (exception.first) {
|
||||
case cmUVProcessChain::ExceptionCode::None:
|
||||
if (retVal) {
|
||||
*retVal = static_cast<int>(status.ExitStatus);
|
||||
} else {
|
||||
if (status.ExitStatus != 0) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
if (outputflag != OUTPUT_NONE) {
|
||||
std::cerr << exception.second << std::endl;
|
||||
}
|
||||
if (captureStdErr) {
|
||||
captureStdErr->append(exception.second);
|
||||
} else if (captureStdOut) {
|
||||
captureStdOut->append(exception.second);
|
||||
}
|
||||
result = false;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
cmsysProcess_Delete(cp);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2245,10 +2213,9 @@ bool cmSystemTools::ListTar(const std::string& outFileName,
|
||||
#endif
|
||||
}
|
||||
|
||||
cmSystemTools::WaitForLineResult cmSystemTools::WaitForLine(
|
||||
uv_loop_t* loop, uv_stream_t* outPipe, uv_stream_t* errPipe,
|
||||
std::string& line, cmDuration timeout, std::vector<char>& out,
|
||||
std::vector<char>& err)
|
||||
int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
|
||||
cmDuration timeout, std::vector<char>& out,
|
||||
std::vector<char>& err)
|
||||
{
|
||||
line.clear();
|
||||
auto outiter = out.begin();
|
||||
@ -2270,7 +2237,7 @@ cmSystemTools::WaitForLineResult cmSystemTools::WaitForLine(
|
||||
line.append(out.data(), length);
|
||||
}
|
||||
out.erase(out.begin(), outiter + 1);
|
||||
return WaitForLineResult::STDOUT;
|
||||
return cmsysProcess_Pipe_STDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2288,66 +2255,33 @@ cmSystemTools::WaitForLineResult cmSystemTools::WaitForLine(
|
||||
line.append(err.data(), length);
|
||||
}
|
||||
err.erase(err.begin(), erriter + 1);
|
||||
return WaitForLineResult::STDERR;
|
||||
return cmsysProcess_Pipe_STDERR;
|
||||
}
|
||||
}
|
||||
|
||||
// No newlines found. Wait for more data from the process.
|
||||
struct ReadData
|
||||
{
|
||||
uv_stream_t* Stream;
|
||||
std::vector<char> Buffer;
|
||||
bool Read = false;
|
||||
bool Finished = false;
|
||||
};
|
||||
auto startRead =
|
||||
[](uv_stream_t* stream,
|
||||
ReadData& data) -> std::unique_ptr<cmUVStreamReadHandle> {
|
||||
data.Stream = stream;
|
||||
return cmUVStreamRead(
|
||||
stream,
|
||||
[&data](std::vector<char> buf) {
|
||||
data.Buffer = std::move(buf);
|
||||
data.Read = true;
|
||||
uv_read_stop(data.Stream);
|
||||
},
|
||||
[&data]() { data.Finished = true; });
|
||||
};
|
||||
ReadData outData;
|
||||
auto outHandle = startRead(outPipe, outData);
|
||||
ReadData errData;
|
||||
auto errHandle = startRead(errPipe, errData);
|
||||
|
||||
cm::uv_timer_ptr timer;
|
||||
bool timedOut = false;
|
||||
timer.init(*loop, &timedOut);
|
||||
timer.start(
|
||||
[](uv_timer_t* handle) {
|
||||
auto* timedOutPtr = static_cast<bool*>(handle->data);
|
||||
*timedOutPtr = true;
|
||||
},
|
||||
static_cast<uint64_t>(timeout.count() * 1000.0), 0);
|
||||
|
||||
uv_run(loop, UV_RUN_ONCE);
|
||||
if (timedOut) {
|
||||
int length;
|
||||
char* data;
|
||||
double timeoutAsDbl = timeout.count();
|
||||
int pipe =
|
||||
cmsysProcess_WaitForData(process, &data, &length, &timeoutAsDbl);
|
||||
if (pipe == cmsysProcess_Pipe_Timeout) {
|
||||
// Timeout has been exceeded.
|
||||
return WaitForLineResult::Timeout;
|
||||
return pipe;
|
||||
}
|
||||
if (outData.Read) {
|
||||
processOutput.DecodeText(outData.Buffer.data(), outData.Buffer.size(),
|
||||
strdata, 1);
|
||||
if (pipe == cmsysProcess_Pipe_STDOUT) {
|
||||
processOutput.DecodeText(data, length, strdata, 1);
|
||||
// Append to the stdout buffer.
|
||||
std::vector<char>::size_type size = out.size();
|
||||
cm::append(out, strdata);
|
||||
outiter = out.begin() + size;
|
||||
} else if (errData.Read) {
|
||||
processOutput.DecodeText(errData.Buffer.data(), errData.Buffer.size(),
|
||||
strdata, 2);
|
||||
} else if (pipe == cmsysProcess_Pipe_STDERR) {
|
||||
processOutput.DecodeText(data, length, strdata, 2);
|
||||
// Append to the stderr buffer.
|
||||
std::vector<char>::size_type size = err.size();
|
||||
cm::append(err, strdata);
|
||||
erriter = err.begin() + size;
|
||||
} else if (outData.Finished && errData.Finished) {
|
||||
} else if (pipe == cmsysProcess_Pipe_None) {
|
||||
// Both stdout and stderr pipes have broken. Return leftover data.
|
||||
processOutput.DecodeText(std::string(), strdata, 1);
|
||||
if (!strdata.empty()) {
|
||||
@ -2364,20 +2298,14 @@ cmSystemTools::WaitForLineResult cmSystemTools::WaitForLine(
|
||||
if (!out.empty()) {
|
||||
line.append(out.data(), outiter - out.begin());
|
||||
out.erase(out.begin(), out.end());
|
||||
return WaitForLineResult::STDOUT;
|
||||
return cmsysProcess_Pipe_STDOUT;
|
||||
}
|
||||
if (!err.empty()) {
|
||||
line.append(err.data(), erriter - err.begin());
|
||||
err.erase(err.begin(), err.end());
|
||||
return WaitForLineResult::STDERR;
|
||||
return cmsysProcess_Pipe_STDERR;
|
||||
}
|
||||
return WaitForLineResult::None;
|
||||
}
|
||||
if (!outData.Finished) {
|
||||
uv_read_stop(outPipe);
|
||||
}
|
||||
if (!errData.Finished) {
|
||||
uv_read_stop(errPipe);
|
||||
return cmsysProcess_Pipe_None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,7 @@
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
|
||||
#include "cmsys/Process.h"
|
||||
#include "cmsys/Status.hxx" // IWYU pragma: export
|
||||
#include "cmsys/SystemTools.hxx" // IWYU pragma: export
|
||||
|
||||
@ -340,20 +339,10 @@ public:
|
||||
*/
|
||||
static void ReportLastSystemError(const char* m);
|
||||
|
||||
enum class WaitForLineResult
|
||||
{
|
||||
None,
|
||||
STDOUT,
|
||||
STDERR,
|
||||
Timeout,
|
||||
};
|
||||
|
||||
/** a general output handler for libuv */
|
||||
static WaitForLineResult WaitForLine(uv_loop_t* loop, uv_stream_t* outPipe,
|
||||
uv_stream_t* errPipe, std::string& line,
|
||||
cmDuration timeout,
|
||||
std::vector<char>& out,
|
||||
std::vector<char>& err);
|
||||
/** a general output handler for cmsysProcess */
|
||||
static int WaitForLine(cmsysProcess* process, std::string& line,
|
||||
cmDuration timeout, std::vector<char>& out,
|
||||
std::vector<char>& err);
|
||||
|
||||
static void SetForceUnixPaths(bool v) { s_ForceUnixPaths = v; }
|
||||
static bool GetForceUnixPaths() { return s_ForceUnixPaths; }
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
|
||||
#include "cm_fileno.hxx"
|
||||
|
||||
#include "cmGetPipes.h"
|
||||
#include "cmUVHandlePtr.h"
|
||||
|
||||
@ -57,12 +59,7 @@ struct cmUVProcessChain::InternalData
|
||||
void Finish();
|
||||
};
|
||||
|
||||
cmUVProcessChainBuilder::cmUVProcessChainBuilder()
|
||||
{
|
||||
this->SetNoStream(Stream_INPUT)
|
||||
.SetNoStream(Stream_OUTPUT)
|
||||
.SetNoStream(Stream_ERROR);
|
||||
}
|
||||
cmUVProcessChainBuilder::cmUVProcessChainBuilder() = default;
|
||||
|
||||
cmUVProcessChainBuilder& cmUVProcessChainBuilder::AddCommand(
|
||||
const std::vector<std::string>& arguments)
|
||||
@ -122,6 +119,16 @@ cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetExternalStream(
|
||||
return *this;
|
||||
}
|
||||
|
||||
cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetExternalStream(
|
||||
Stream stdio, FILE* stream)
|
||||
{
|
||||
int fd = cm_fileno(stream);
|
||||
if (fd >= 0) {
|
||||
return this->SetExternalStream(stdio, fd);
|
||||
}
|
||||
return this->SetNoStream(stdio);
|
||||
}
|
||||
|
||||
cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetMergedBuiltinStreams()
|
||||
{
|
||||
this->MergedBuiltinStreams = true;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <array>
|
||||
#include <cstddef> // IWYU pragma: keep
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@ -34,6 +35,7 @@ public:
|
||||
cmUVProcessChainBuilder& SetBuiltinStream(Stream stdio);
|
||||
cmUVProcessChainBuilder& SetMergedBuiltinStreams();
|
||||
cmUVProcessChainBuilder& SetExternalStream(Stream stdio, int fd);
|
||||
cmUVProcessChainBuilder& SetExternalStream(Stream stdio, FILE* stream);
|
||||
cmUVProcessChainBuilder& SetWorkingDirectory(std::string dir);
|
||||
|
||||
cmUVProcessChain Start() const;
|
||||
@ -50,8 +52,8 @@ private:
|
||||
|
||||
struct StdioConfiguration
|
||||
{
|
||||
StdioType Type;
|
||||
int FileDescriptor;
|
||||
StdioType Type = None;
|
||||
int FileDescriptor = -1;
|
||||
};
|
||||
|
||||
struct ProcessConfiguration
|
||||
|
@ -2784,7 +2784,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
isCppModule = true;
|
||||
if (shouldScanForModules &&
|
||||
this->GlobalGenerator->IsScanDependenciesSupported()) {
|
||||
// ScanSourceforModuleDependencies uses 'cl /scanDependencies' and
|
||||
// ScanSourceForModuleDependencies uses 'cl /scanDependencies' and
|
||||
// can distinguish module interface units and internal partitions.
|
||||
compileAsPerConfig = "CompileAsCpp";
|
||||
} else {
|
||||
@ -2827,7 +2827,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
// use them
|
||||
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
|
||||
!includes.empty() || compileAsPerConfig || noWinRT ||
|
||||
!options.empty() || needsPCHFlags) {
|
||||
!options.empty() || needsPCHFlags || shouldScanForModules) {
|
||||
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
|
||||
cmIDEFlagTable const* flagtable = nullptr;
|
||||
const std::string& srclang = source->GetLanguage();
|
||||
@ -2856,9 +2856,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
clOptions.AddFlag("CompileAs", compileAsPerConfig);
|
||||
}
|
||||
if (shouldScanForModules) {
|
||||
clOptions.AddFlag("ScanSourceforModuleDependencies", "true");
|
||||
} else {
|
||||
clOptions.AddFlag("ScanSourceforModuleDependencies", "false");
|
||||
clOptions.AddFlag("ScanSourceForModuleDependencies", "true");
|
||||
}
|
||||
if (noWinRT) {
|
||||
clOptions.AddFlag("CompileAsWinRT", "false");
|
||||
@ -3564,6 +3562,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
|
||||
e2.Element("AdditionalUsingDirectories", dirs);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable C++ source scanning by default.
|
||||
e2.Element("ScanSourceForModuleDependencies", "false");
|
||||
}
|
||||
|
||||
bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "cmsys/Glob.hxx"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include "cm_fileno.hxx"
|
||||
#include "cm_sys_stat.h"
|
||||
|
||||
#include "cmBuildOptions.h"
|
||||
@ -3916,10 +3915,8 @@ std::function<int()> cmake::BuildWorkflowStep(
|
||||
{
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand(args)
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT,
|
||||
cm_fileno(stdout))
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR,
|
||||
cm_fileno(stderr));
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, stdout)
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, stderr);
|
||||
return [builder]() -> int {
|
||||
auto chain = builder.Start();
|
||||
chain.Wait();
|
||||
|
102
Source/cmcmd.cxx
102
Source/cmcmd.cxx
@ -11,8 +11,6 @@
|
||||
#include <cm3p/uv.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "cm_fileno.hxx"
|
||||
|
||||
#include "cmCommandLineArgument.h"
|
||||
#include "cmConsoleBuf.h"
|
||||
#include "cmCryptoHash.h"
|
||||
@ -74,6 +72,7 @@
|
||||
|
||||
#include "cmsys/Directory.hxx"
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/Process.h"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
#include "cmsys/Terminal.h"
|
||||
|
||||
@ -296,8 +295,14 @@ int CLCompileAndDependencies(const std::vector<std::string>& args)
|
||||
}
|
||||
}
|
||||
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand(command).SetWorkingDirectory(currentBinaryDir);
|
||||
std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp(
|
||||
cmsysProcess_New(), cmsysProcess_Delete);
|
||||
std::vector<const char*> argv(command.size() + 1);
|
||||
std::transform(command.begin(), command.end(), argv.begin(),
|
||||
[](std::string const& s) { return s.c_str(); });
|
||||
argv.back() = nullptr;
|
||||
cmsysProcess_SetCommand(cp.get(), argv.data());
|
||||
cmsysProcess_SetWorkingDirectory(cp.get(), currentBinaryDir.c_str());
|
||||
|
||||
cmsys::ofstream fout(depFile.c_str());
|
||||
if (!fout) {
|
||||
@ -308,18 +313,22 @@ int CLCompileAndDependencies(const std::vector<std::string>& args)
|
||||
CLOutputLogger errLogger(std::cerr);
|
||||
|
||||
// Start the process.
|
||||
auto result =
|
||||
cmProcessTools::RunProcess(builder, &includeParser, &errLogger);
|
||||
auto const& subStatus = result.front();
|
||||
cmProcessTools::RunProcess(cp.get(), &includeParser, &errLogger);
|
||||
|
||||
int status = 0;
|
||||
// handle status of process
|
||||
if (subStatus.SpawnResult != 0) {
|
||||
status = 2;
|
||||
} else if (subStatus.TermSignal != 0) {
|
||||
status = 1;
|
||||
} else {
|
||||
status = static_cast<int>(subStatus.ExitStatus);
|
||||
switch (cmsysProcess_GetState(cp.get())) {
|
||||
case cmsysProcess_State_Exited:
|
||||
status = cmsysProcess_GetExitValue(cp.get());
|
||||
break;
|
||||
case cmsysProcess_State_Exception:
|
||||
status = 1;
|
||||
break;
|
||||
case cmsysProcess_State_Error:
|
||||
status = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (status != 0) {
|
||||
@ -1107,8 +1116,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
|
||||
|
||||
int ret = 0;
|
||||
auto time_start = std::chrono::steady_clock::now();
|
||||
cmSystemTools::RunSingleCommand(command, nullptr, nullptr, &ret, nullptr,
|
||||
cmSystemTools::OUTPUT_PASSTHROUGH);
|
||||
cmSystemTools::RunSingleCommand(command, nullptr, nullptr, &ret);
|
||||
auto time_finish = std::chrono::steady_clock::now();
|
||||
|
||||
std::chrono::duration<double> time_elapsed = time_finish - time_start;
|
||||
@ -1882,6 +1890,21 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string> const& args)
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a process instance.
|
||||
cmsysProcess* cp = cmsysProcess_New();
|
||||
if (!cp) {
|
||||
std::cerr << "Error allocating process instance in link script."
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Children should share stdout and stderr with this process.
|
||||
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
|
||||
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
|
||||
|
||||
// Run the command lines verbatim.
|
||||
cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1);
|
||||
|
||||
// Read command lines from the script.
|
||||
cmsys::ifstream fin(args[2].c_str());
|
||||
if (!fin) {
|
||||
@ -1899,24 +1922,9 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string> const& args)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Allocate a process instance.
|
||||
cmUVProcessChainBuilder builder;
|
||||
|
||||
// Children should share stdout and stderr with this process.
|
||||
builder
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT,
|
||||
cm_fileno(stdout))
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR,
|
||||
cm_fileno(stderr));
|
||||
|
||||
// Setup this command line.
|
||||
std::vector<std::string> args2;
|
||||
#ifdef _WIN32
|
||||
cmSystemTools::ParseWindowsCommandLine(command.c_str(), args2);
|
||||
#else
|
||||
cmSystemTools::ParseUnixCommandLine(command.c_str(), args2);
|
||||
#endif
|
||||
builder.AddCommand(args2);
|
||||
const char* cmd[2] = { command.c_str(), nullptr };
|
||||
cmsysProcess_SetCommand(cp, cmd);
|
||||
|
||||
// Report the command if verbose output is enabled.
|
||||
if (verbose) {
|
||||
@ -1924,29 +1932,35 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string> const& args)
|
||||
}
|
||||
|
||||
// Run the command and wait for it to exit.
|
||||
auto chain = builder.Start();
|
||||
chain.Wait();
|
||||
cmsysProcess_Execute(cp);
|
||||
cmsysProcess_WaitForExit(cp, nullptr);
|
||||
|
||||
// Report failure if any.
|
||||
auto const& status = chain.GetStatus(0);
|
||||
auto exception = status.GetException();
|
||||
switch (exception.first) {
|
||||
case cmUVProcessChain::ExceptionCode::None:
|
||||
if (status.ExitStatus != 0) {
|
||||
result = static_cast<int>(status.ExitStatus);
|
||||
switch (cmsysProcess_GetState(cp)) {
|
||||
case cmsysProcess_State_Exited: {
|
||||
int value = cmsysProcess_GetExitValue(cp);
|
||||
if (value != 0) {
|
||||
result = value;
|
||||
}
|
||||
} break;
|
||||
case cmsysProcess_State_Exception:
|
||||
std::cerr << "Error running link command: "
|
||||
<< cmsysProcess_GetExceptionString(cp) << std::endl;
|
||||
result = 1;
|
||||
break;
|
||||
case cmUVProcessChain::ExceptionCode::Spawn:
|
||||
std::cerr << "Error running link command: " << exception.second;
|
||||
case cmsysProcess_State_Error:
|
||||
std::cerr << "Error running link command: "
|
||||
<< cmsysProcess_GetErrorString(cp) << std::endl;
|
||||
result = 2;
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Error running link command: " << exception.second;
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Free the process instance.
|
||||
cmsysProcess_Delete(cp);
|
||||
|
||||
// Return the final resulting return value.
|
||||
return result;
|
||||
}
|
||||
|
@ -12,8 +12,6 @@
|
||||
|
||||
#include <cm3p/uv.h>
|
||||
|
||||
#include "cm_fileno.hxx"
|
||||
|
||||
#include "cmGetPipes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmUVHandlePtr.h"
|
||||
@ -632,8 +630,7 @@ bool testUVProcessChainInputFile(const char* helperCommand)
|
||||
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand({ helperCommand, "dedup" })
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT,
|
||||
cm_fileno(f.get()))
|
||||
.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT, f.get())
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
|
||||
|
||||
auto chain = builder.Start();
|
||||
|
@ -9,6 +9,10 @@
|
||||
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
static std::string getStdin()
|
||||
{
|
||||
char buffer[1024];
|
||||
|
@ -25,6 +25,13 @@ add_CMakeOnly_test(CheckCXXSymbolExists)
|
||||
add_CMakeOnly_test(CheckCXXCompilerFlag)
|
||||
|
||||
add_CMakeOnly_test(CheckLanguage)
|
||||
if (CMake_TEST_HIP)
|
||||
set_property(TEST CMakeOnly.CheckLanguage APPEND PROPERTY LABELS "HIP")
|
||||
add_CMakeOnly_test(CheckLanguageHIPPlatform)
|
||||
set_property(TEST CMakeOnly.CheckLanguageHIPPlatform APPEND PROPERTY LABELS "HIP")
|
||||
add_CMakeOnly_test(CheckLanguageHIPPlatform2)
|
||||
set_property(TEST CMakeOnly.CheckLanguageHIPPlatform2 APPEND PROPERTY LABELS "HIP")
|
||||
endif()
|
||||
|
||||
add_CMakeOnly_test(CheckStructHasMember)
|
||||
|
||||
|
17
Tests/CMakeOnly/CheckLanguageHIPPlatform/CMakeLists.txt
Normal file
17
Tests/CMakeOnly/CheckLanguageHIPPlatform/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
cmake_minimum_required (VERSION 3.28)
|
||||
project(CheckLanguageHIPPlatform NONE)
|
||||
include(CheckLanguage)
|
||||
|
||||
check_language(HIP)
|
||||
|
||||
if(NOT DEFINED CMAKE_HIP_COMPILER)
|
||||
message(FATAL_ERROR "check_language did not set result")
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_HIP_COMPILER)
|
||||
message(FATAL_ERROR "check_language should not fail!")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED CMAKE_HIP_PLATFORM)
|
||||
message(FATAL_ERROR "check_language did not set CMAKE_HIP_PLATFORM!")
|
||||
endif()
|
14
Tests/CMakeOnly/CheckLanguageHIPPlatform2/CMakeLists.txt
Normal file
14
Tests/CMakeOnly/CheckLanguageHIPPlatform2/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
cmake_minimum_required (VERSION 3.28)
|
||||
project(CheckLanguageHIPPlatform2 NONE)
|
||||
include(CheckLanguage)
|
||||
|
||||
set(CMAKE_HIP_PLATFORM "not-a-hip-platform" CACHE STRING "")
|
||||
check_language(HIP)
|
||||
|
||||
if(NOT DEFINED CMAKE_HIP_COMPILER)
|
||||
message(FATAL_ERROR "check_language did not set result")
|
||||
endif()
|
||||
|
||||
if (CMAKE_HIP_COMPILER)
|
||||
message(FATAL_ERROR "check_language should have failed")
|
||||
endif()
|
@ -14,6 +14,7 @@ add_cuda_test_macro(Cuda.MixedStandardLevels5 MixedStandardLevels5)
|
||||
add_cuda_test_macro(Cuda.NotEnabled CudaNotEnabled)
|
||||
add_cuda_test_macro(Cuda.SeparableCompCXXOnly SeparableCompCXXOnly)
|
||||
add_cuda_test_macro(Cuda.StubRPATH StubRPATH)
|
||||
set(Cuda.Toolkit_BUILD_OPTIONS -DHAS_CUPTI:BOOL=${CMake_TEST_CUDA_CUPTI})
|
||||
add_cuda_test_macro(Cuda.Toolkit Toolkit)
|
||||
add_cuda_test_macro(Cuda.IncludePathNoToolkit IncludePathNoToolkit)
|
||||
add_cuda_test_macro(Cuda.SharedRuntimePlusToolkit SharedRuntimePlusToolkit)
|
||||
|
@ -79,6 +79,23 @@ endforeach()
|
||||
add_executable(Toolkit main.cpp)
|
||||
target_link_libraries(Toolkit PRIVATE CUDA::toolkit)
|
||||
|
||||
if(HAS_CUPTI)
|
||||
set(cupti_libs )
|
||||
if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.2)
|
||||
list(APPEND cupti_libs cupti nvperf_target)
|
||||
endif()
|
||||
if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 11.3)
|
||||
list(APPEND cupti_libs pcsamplingutil)
|
||||
endif()
|
||||
foreach (cuda_lib IN LISTS cupti_libs)
|
||||
if(NOT CUDA_${cuda_lib}_LIBRARY)
|
||||
message(FATAL_ERROR "expected CUDAToolkit variable CUDA_${cuda_lib}_LIBRARY not found")
|
||||
endif()
|
||||
if(NOT TARGET CUDA::${cuda_lib})
|
||||
message(FATAL_ERROR "expected CUDAToolkit target CUDA::${cuda_lib} not found")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
# cupti is an optional component of the CUDA toolkit
|
||||
if(TARGET CUDA::cupti)
|
||||
add_executable(cupti cupti.cpp)
|
||||
|
@ -12,6 +12,7 @@ add_cuda_test_macro(CudaOnly.ExportPTX CudaOnlyExportPTX)
|
||||
add_cuda_test_macro(CudaOnly.SharedRuntimePlusToolkit CudaOnlySharedRuntimePlusToolkit)
|
||||
add_cuda_test_macro(CudaOnly.StaticRuntimePlusToolkit CudaOnlyStaticRuntimePlusToolkit)
|
||||
add_cuda_test_macro(CudaOnly.Standard98 CudaOnlyStandard98)
|
||||
set(CudaOnly.Toolkit_BUILD_OPTIONS -DHAS_CUPTI:BOOL=${CMake_TEST_CUDA_CUPTI})
|
||||
add_cuda_test_macro(CudaOnly.Toolkit CudaOnlyToolkit)
|
||||
add_cuda_test_macro(CudaOnly.ToolkitBeforeLang CudaOnlyToolkitBeforeLang)
|
||||
add_cuda_test_macro(CudaOnly.ToolkitMultipleDirs CudaOnlyToolkitMultipleDirs)
|
||||
|
@ -41,7 +41,6 @@ if(CUDAToolkit_VERSION_MAJOR VERSION_LESS 11)
|
||||
list(APPEND cuda_libs nvgraph)
|
||||
endif()
|
||||
|
||||
|
||||
# Verify that all the CUDA:: targets and variables exist
|
||||
foreach (cuda_lib IN LISTS cuda_libs)
|
||||
if(NOT CUDA_${cuda_lib}_LIBRARY)
|
||||
@ -81,5 +80,24 @@ foreach (cuda_lib nvrtc nvToolsExt OpenCL)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(HAS_CUPTI)
|
||||
set(cupti_libs )
|
||||
if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.2)
|
||||
list(APPEND cupti_libs cupti nvperf_target)
|
||||
endif()
|
||||
if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 11.3)
|
||||
list(APPEND cupti_libs pcsamplingutil)
|
||||
endif()
|
||||
|
||||
foreach (cuda_lib IN LISTS cupti_libs)
|
||||
if(NOT CUDA_${cuda_lib}_LIBRARY)
|
||||
message(FATAL_ERROR "expected CUDAToolkit variable CUDA_${cuda_lib}_LIBRARY not found")
|
||||
endif()
|
||||
if(NOT TARGET CUDA::${cuda_lib})
|
||||
message(FATAL_ERROR "expected CUDAToolkit target CUDA::${cuda_lib} not found")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
add_executable(CudaOnlyToolkit main.cu)
|
||||
target_link_libraries(CudaOnlyToolkit PRIVATE CUDA::toolkit)
|
||||
|
@ -16,14 +16,14 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
|
||||
{
|
||||
char* file;
|
||||
char* str;
|
||||
char* srcs;
|
||||
const char* srcs;
|
||||
const char* cstr;
|
||||
char buffer[1024];
|
||||
void* source_file;
|
||||
char* args[2];
|
||||
char* ccArgs[4];
|
||||
char* ccDep[1];
|
||||
char* ccOut[1];
|
||||
const char* ccArgs[4];
|
||||
const char* ccDep[1];
|
||||
const char* ccOut[1];
|
||||
cmLoadedCommandInfo* info = (cmLoadedCommandInfo*)inf;
|
||||
|
||||
cmVTKWrapTclData* cdata =
|
||||
@ -148,7 +148,10 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
|
||||
if (info->CAPI->GetTotalArgumentSize(2, args) != 13) {
|
||||
return 0;
|
||||
}
|
||||
info->CAPI->ExecuteCommand(mf, "SET", 2, args);
|
||||
|
||||
ccArgs[0] = "TEST_EXEC";
|
||||
ccArgs[1] = "TRUE";
|
||||
info->CAPI->ExecuteCommand(mf, "SET", 2, ccArgs);
|
||||
|
||||
/* make sure we can find the source file */
|
||||
if (!info->CAPI->GetSource(mf, argv[1])) {
|
||||
|
@ -16,14 +16,14 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
|
||||
{
|
||||
char* file;
|
||||
char* str;
|
||||
char* srcs;
|
||||
const char* cstr;
|
||||
const char* srcs;
|
||||
char* cstr;
|
||||
char buffer[1024];
|
||||
void* source_file;
|
||||
char* args[2];
|
||||
char* ccArgs[4];
|
||||
char* ccDep[1];
|
||||
char* ccOut[1];
|
||||
const char* ccArgs[4];
|
||||
const char* ccDep[1];
|
||||
const char* ccOut[1];
|
||||
cmLoadedCommandInfo* info = (cmLoadedCommandInfo*)inf;
|
||||
|
||||
cmVTKWrapTclData* cdata =
|
||||
@ -148,7 +148,10 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
|
||||
if (info->CAPI->GetTotalArgumentSize(2, args) != 13) {
|
||||
return 0;
|
||||
}
|
||||
info->CAPI->ExecuteCommand(mf, "SET", 2, args);
|
||||
|
||||
ccArgs[0] = "TEST_EXEC";
|
||||
ccArgs[1] = "TRUE";
|
||||
info->CAPI->ExecuteCommand(mf, "SET", 2, ccArgs);
|
||||
|
||||
/* make sure we can find the source file */
|
||||
if (!info->CAPI->GetSource(mf, argv[1])) {
|
||||
|
11
Tests/QtAutogen/AutogenTimestampDeps/CMakeLists.txt
Normal file
11
Tests/QtAutogen/AutogenTimestampDeps/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
project(AutogenTimestampDeps)
|
||||
include("../AutogenCoreTest.cmake")
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
add_custom_target(ProjectInfo
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UpdateProjectInfo.cmake
|
||||
BYPRODUCTS ${CMAKE_BINARY_DIR}/ProjectInfo.hpp)
|
||||
|
||||
add_subdirectory(src)
|
6
Tests/QtAutogen/AutogenTimestampDeps/ProjectInfo.hpp.in
Normal file
6
Tests/QtAutogen/AutogenTimestampDeps/ProjectInfo.hpp.in
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef PROJECTINFO_HPP
|
||||
#define PROJECTINFO_HPP
|
||||
|
||||
extern int VersionMajor;
|
||||
|
||||
#endif // PROJECTINFO_HPP
|
@ -0,0 +1,2 @@
|
||||
|
||||
configure_file(${CMAKE_CURRENT_LIST_DIR}/../ProjectInfo.hpp.in ${CMAKE_BINARY_DIR}/ProjectInfo.hpp @ONLY)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user