diff options
625 files changed, 9721 insertions, 6578 deletions
diff --git a/.clang-tidy b/.clang-tidy index dc60714..aef99dc 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -15,7 +15,6 @@ modernize-*,\ -modernize-raw-string-literal,\ -modernize-return-braced-init-list,\ -modernize-use-auto,\ --modernize-use-emplace,\ -modernize-use-equals-default,\ -modernize-use-equals-delete,\ -modernize-use-noexcept,\ @@ -32,7 +31,6 @@ readability-*,\ -readability-inconsistent-declaration-parameter-name,\ -readability-named-parameter,\ -readability-redundant-declaration,\ --readability-simplify-boolean-expr,\ " HeaderFilterRegex: 'Source/cm[^/]*\.(h|hxx|cxx)$' CheckOptions: diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 1083036..7e029de 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -2212,6 +2212,8 @@ syn keyword cmakeGeneratorExpressions contained \ DEBUG_MODE \ EXPORT \ FOO_EXTRA_THINGS + \ Fortran_COMPILER_ID + \ Fortran_COMPILER_VERSION \ GENEX_EVAL \ GNU \ IF diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in index 18e0078..823ee3c 100644 --- a/CTestCustom.cmake.in +++ b/CTestCustom.cmake.in @@ -52,6 +52,7 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION "(Lexer|Parser).*warning.*conversion.*may (alter its value|change the sign)" "(Lexer|Parser).*warning.*(statement is unreachable|will never be executed)" "(Lexer|Parser).*warning.*variable.*was set but never used" + "LexerParser.*warning.*empty expression statement has no effect; remove unnecessary" "PGC-W-0095-Type cast required for this conversion.*ProcessUNIX.c" "[Qq]t([Cc]ore|[Gg]ui|[Ww]idgets).*warning.*conversion.*may alter its value" "warning:.*is.*very unsafe.*consider using.*" diff --git a/CompileFlags.cmake b/CompileFlags.cmake index ec9b31b..5d0e144 100644 --- a/CompileFlags.cmake +++ b/CompileFlags.cmake @@ -28,13 +28,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "AIX") endif() endif() -if(CMAKE_SYSTEM_NAME MATCHES "IRIX") - if(NOT CMAKE_COMPILER_IS_GNUCXX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-woff84 -no_auto_include") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-woff15") - endif() -endif() - if(CMAKE_SYSTEM MATCHES "OSF1-V") if(NOT CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -timplicit_local -no_implicit_include ") diff --git a/Help/command/ctest_submit.rst b/Help/command/ctest_submit.rst index 426475c..fba03fd 100644 --- a/Help/command/ctest_submit.rst +++ b/Help/command/ctest_submit.rst @@ -6,6 +6,7 @@ Perform the :ref:`CTest Submit Step` as a :ref:`Dashboard Client`. :: ctest_submit([PARTS <part>...] [FILES <file>...] + [SUBMIT_URL <url>] [HTTPHEADER <header>] [RETRY_COUNT <count>] [RETRY_DELAY <delay>] @@ -39,6 +40,10 @@ The options are: Specify an explicit list of specific files to be submitted. Each individual file must exist at the time of the call. +``SUBMIT_URL <url>`` + The ``http`` or ``https`` URL of the dashboard server to send the submission + to. If not given, the :variable:`CTEST_SUBMIT_URL` variable is used. + ``HTTPHEADER <HTTP-header>`` Specify HTTP header to be included in the request to CDash during submission. This suboption can be repeated several times. @@ -68,6 +73,7 @@ Submit to CDash Upload API :: ctest_submit(CDASH_UPLOAD <file> [CDASH_UPLOAD_TYPE <type>] + [SUBMIT_URL <url>] [HTTPHEADER <header>] [RETRY_COUNT <count>] [RETRY_DELAY <delay>] @@ -80,5 +86,5 @@ with a content hash of the file. If CDash does not already have the file, then it is uploaded. Along with the file, a CDash type string is specified to tell CDash which handler to use to process the data. -This signature accepts the ``HTTPHEADER``, ``RETRY_COUNT``, ``RETRY_DELAY``, -``RETURN_VALUE`` and ``QUIET`` options as described above. +This signature accepts the ``SUBMIT_URL``, ``HTTPHEADER``, ``RETRY_COUNT``, +``RETRY_DELAY``, ``RETURN_VALUE`` and ``QUIET`` options as described above. diff --git a/Help/command/file.rst b/Help/command/file.rst index 6e2a6dd..db4d6fc 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -27,6 +27,7 @@ Synopsis file({`COPY`_ | `INSTALL`_} <file>... DESTINATION <dir> [...]) file(`SIZE`_ <filename> <out-var>) file(`READ_SYMLINK`_ <filename> <out-var>) + file(`CREATE_LINK`_ <file> <new-file> [...]) `Path Conversion`_ file(`RELATIVE_PATH`_ <out-var> <directory> <file>) @@ -368,6 +369,28 @@ could do something like this: set(result "${dir}/${result}") endif() +.. _CREATE_LINK: + +.. code-block:: cmake + + file(CREATE_LINK <file> <new-file> + [RESULT <result>] [COPY_ON_ERROR] [SYMBOLIC]) + +Create a link to ``<file>`` at ``<new-file>``. + +It is a hard link by default. This can be changed to symbolic links by +using ``SYMBOLIC``. The original file needs to exist for hard links. + +The ``<result>`` variable, if specified, gets the status of the operation. +It is set to ``0`` in case of success. Otherwise, it contains the error +generated. In case of failures, if ``RESULT`` is not specified, a fatal error +is emitted. + +Specifying ``COPY_ON_ERROR`` enables copying the file as a fallback if +creating the link fails. + +Overwrites the ``<new-file>`` if it exists. + Path Conversion ^^^^^^^^^^^^^^^ diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 937a930..54d5f68 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -23,9 +23,9 @@ Finds and loads settings from an external project. ``<PackageName>_FOUND`` will be set to indicate whether the package was found. When the package is found package-specific information is provided through variables and :ref:`Imported Targets` documented by the package itself. The -``QUIET`` option disables messages if the package cannot be found. The -``REQUIRED`` option stops processing with an error message if the package -cannot be found. +``QUIET`` option disables informational messages, including those indicating +that the package cannot be found if it is not ``REQUIRED``. The ``REQUIRED`` +option stops processing with an error message if the package cannot be found. A package-specific list of required components may be listed after the ``COMPONENTS`` option (or after the ``REQUIRED`` option if present). @@ -354,6 +354,11 @@ enabled. .. include:: FIND_XXX_ROOT.txt .. include:: FIND_XXX_ORDER.txt +By default the value stored in the result variable will be the path at +which the file is found. The :variable:`CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS` +variable may be set to ``TRUE`` before calling ``find_package`` in order +to resolve symbolic links and store the real path to the file. + Every non-REQUIRED ``find_package`` call can be disabled by setting the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable to ``TRUE``. diff --git a/Help/command/qt_wrap_cpp.rst b/Help/command/qt_wrap_cpp.rst index c04c7a6..ce11c2d 100644 --- a/Help/command/qt_wrap_cpp.rst +++ b/Help/command/qt_wrap_cpp.rst @@ -1,7 +1,16 @@ qt_wrap_cpp ----------- -Create Qt Wrappers. +.. deprecated:: 3.14 + + This command was originally added to support Qt 3 before the + :command:`add_custom_command()` command was sufficiently mature. The + :module:`FindQt4` module provides the ``qt4_wrap_cpp()`` macro, which + should be used instead for Qt 4 projects. For projects using Qt 5 or + later, use the equivalent macro provided by Qt itself (e.g. Qt 5 provides + ``qt5_wrap_cpp()``). + +Manually create Qt Wrappers. .. code-block:: cmake @@ -9,3 +18,6 @@ Create Qt Wrappers. Produces moc files for all the .h files listed in the SourceLists. The moc files will be added to the library using the ``DestName`` source list. + +Consider updating the project to use the :prop_tgt:`AUTOMOC` target property +instead for a more automated way of invoking the ``moc`` tool. diff --git a/Help/command/qt_wrap_ui.rst b/Help/command/qt_wrap_ui.rst index 9a8863d..efbbc54 100644 --- a/Help/command/qt_wrap_ui.rst +++ b/Help/command/qt_wrap_ui.rst @@ -1,7 +1,16 @@ qt_wrap_ui ---------- -Create Qt user interfaces Wrappers. +.. deprecated:: 3.14 + + This command was originally added to support Qt 3 before the + :command:`add_custom_command()` command was sufficiently mature. The + :module:`FindQt4` module provides the ``qt4_wrap_ui()`` macro, which + should be used instead for Qt 4 projects. For projects using Qt 5 or + later, use the equivalent macro provided by Qt itself (e.g. Qt 5 provides + ``qt5_wrap_ui()``). + +Manually create Qt user interfaces Wrappers. .. code-block:: cmake @@ -12,3 +21,6 @@ Produces .h and .cxx files for all the .ui files listed in the ``SourceLists``. The .h files will be added to the library using the ``HeadersDestNamesource`` list. The .cxx files will be added to the library using the ``SourcesDestNamesource`` list. + +Consider updating the project to use the :prop_tgt:`AUTOUIC` target property +instead for a more automated way of invoking the ``uic`` tool. diff --git a/Help/command/set_directory_properties.rst b/Help/command/set_directory_properties.rst index cc71522..f02a8e6 100644 --- a/Help/command/set_directory_properties.rst +++ b/Help/command/set_directory_properties.rst @@ -9,5 +9,7 @@ Set properties of the current directory and subdirectories. Sets properties of the current directory and its subdirectories in key-value pairs. +See also the :command:`set_property(DIRECTORY)` command. + See :ref:`Directory Properties` for the list of properties known to CMake and their individual documentation for the behavior of each property. diff --git a/Help/command/set_property.rst b/Help/command/set_property.rst index 2d270ec..2624b4b 100644 --- a/Help/command/set_property.rst +++ b/Help/command/set_property.rst @@ -24,17 +24,19 @@ It must be one of the following: Scope is unique and does not accept a name. ``DIRECTORY`` - Scope defaults to the current directory but another - directory (already processed by CMake) may be named by full or - relative path. + Scope defaults to the current directory but another directory + (already processed by CMake) may be named by full or relative path. + See also the :command:`set_directory_properties` command. ``TARGET`` Scope may name zero or more existing targets. + See also the :command:`set_target_properties` command. ``SOURCE`` Scope may name zero or more source files. Note that source file properties are visible only to targets added in the same directory (CMakeLists.txt). + See also the :command:`set_source_files_properties` command. ``INSTALL`` Scope may name zero or more installed file paths. @@ -54,6 +56,7 @@ It must be one of the following: ``TEST`` Scope may name zero or more existing tests. + See also the :command:`set_tests_properties` command. ``CACHE`` Scope must name zero or more cache existing entries. diff --git a/Help/command/set_source_files_properties.rst b/Help/command/set_source_files_properties.rst index 8538a1e..91f995c 100644 --- a/Help/command/set_source_files_properties.rst +++ b/Help/command/set_source_files_properties.rst @@ -10,6 +10,10 @@ Source files can have properties that affect how they are built. [prop2 value2 [...]]) Sets properties associated with source files using a key/value paired -list. See :ref:`Source File Properties` for the list of properties known +list. + +See also the :command:`set_property(SOURCE)` command. + +See :ref:`Source File Properties` for the list of properties known to CMake. Source file properties are visible only to targets added in the same directory (CMakeLists.txt). diff --git a/Help/command/set_tests_properties.rst b/Help/command/set_tests_properties.rst index 55fd635..9bc94ae 100644 --- a/Help/command/set_tests_properties.rst +++ b/Help/command/set_tests_properties.rst @@ -10,5 +10,8 @@ Set a property of the tests. Sets a property for the tests. If the test is not found, CMake will report an error. :manual:`Generator expressions <cmake-generator-expressions(7)>` will be -expanded the same as supported by the test's :command:`add_test` call. See -:ref:`Test Properties` for the list of properties known to CMake. +expanded the same as supported by the test's :command:`add_test` call. + +See also the :command:`set_property(TEST)` command. + +See :ref:`Test Properties` for the list of properties known to CMake. diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst index cf9e06f..77f42a1 100644 --- a/Help/command/try_compile.rst +++ b/Help/command/try_compile.rst @@ -168,3 +168,6 @@ then the language standard variables are honored: Their values are used to set the corresponding target properties in the generated project (unless overridden by an explicit option). + +For the :generator:`Green Hills MULTI` generator the GHS toolset and target +system customization cache variables are also propagated into the test project. diff --git a/Help/generator/Green Hills MULTI.rst b/Help/generator/Green Hills MULTI.rst index 1b4960d..bfe671f 100644 --- a/Help/generator/Green Hills MULTI.rst +++ b/Help/generator/Green Hills MULTI.rst @@ -3,49 +3,63 @@ Green Hills MULTI Generates Green Hills MULTI project files (experimental, work-in-progress). +The buildsystem has predetermined build-configuration settings that can be controlled +via the :variable:`CMAKE_BUILD_TYPE` variable. + Customizations that are used to pick toolset and target system: The ``-A <arch>`` can be supplied for setting the target architecture. ``<arch>`` usually is one of "arm", "ppc", "86", etcetera. If the target architecture is not specified then the default architecture of "arm" will be used. -The ``-T <toolset>`` can be supplied for setting the toolset to be used. -All toolsets are expected to be located at ``GHS_TOOLSET_ROOT``. -If the toolset is not specified then the latest toolset will be used. +The ``-T <toolset>`` option can be used to set the directory location of the toolset. +Both absolute and relative paths are valid. Relative paths use ``GHS_TOOLSET_ROOT`` +as the root. If the toolset is not specified then the latest toolset found in +``GHS_TOOLSET_ROOT`` will be used. + +Cache variables that are used for toolset and target system customization: * ``GHS_TARGET_PLATFORM`` -Default to ``integrity``. -Usual values are ``integrity``, ``threadx``, ``uvelosity``, -``velosity``, ``vxworks``, ``standalone``. + | Defaults to ``integrity``. + | Usual values are ``integrity``, ``threadx``, ``uvelosity``, ``velosity``, + ``vxworks``, ``standalone``. * ``GHS_PRIMARY_TARGET`` -Sets ``primaryTarget`` field in project file. -Defaults to ``<arch>_<GHS_TARGET_PLATFORM>.tgt``. + | Sets ``primaryTarget`` entry in project file. + | Defaults to ``<arch>_<GHS_TARGET_PLATFORM>.tgt``. * ``GHS_TOOLSET_ROOT`` -Default to ``C:/ghs``. Root path for ``toolset``. + | Root path for ``toolset`` searches. + | Defaults to ``C:/ghs``. * ``GHS_OS_ROOT`` -Default to ``C:/ghs``. Root path for RTOS searches. + | Root path for RTOS searches. + | Defaults to ``C:/ghs``. * ``GHS_OS_DIR`` -Default to latest platform OS installation at ``GHS_OS_ROOT``. Set this value if -a specific RTOS is to be used. + | Sets ``-os_dir`` entry in project file. + | Defaults to latest platform OS installation at ``GHS_OS_ROOT``. Set this value if + a specific RTOS is to be used. * ``GHS_BSP_NAME`` -Defaults to ``sim<arch>`` if not set by user. + | Sets ``-bsp`` entry in project file. + | Defaults to ``sim<arch>`` for ``integrity`` platforms. Customizations are available through the following cache variables: * ``GHS_CUSTOMIZATION`` * ``GHS_GPJ_MACROS`` +The following properties are available: + +* :prop_tgt:`GHS_INTEGRITY_APP` + .. note:: This generator is deemed experimental as of CMake |release| and is still a work in progress. Future versions of CMake diff --git a/Help/generator/Visual Studio 16 2019.rst b/Help/generator/Visual Studio 16 2019.rst new file mode 100644 index 0000000..6f2bc56 --- /dev/null +++ b/Help/generator/Visual Studio 16 2019.rst @@ -0,0 +1,49 @@ +Visual Studio 16 2019 +--------------------- + +Generates Visual Studio 16 (VS 2019) project files. + +Project Types +^^^^^^^^^^^^^ + +Only Visual C++ and C# projects may be generated. Other types of +projects (JavaScript, Powershell, Python, etc.) are not supported. + +Instance Selection +^^^^^^^^^^^^^^^^^^ + +VS 2019 supports multiple installations on the same machine. +The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a +cache entry containing the absolute path to a Visual Studio instance. +If the value is not specified explicitly by the user or a toolchain file, +CMake queries the Visual Studio Installer to locate VS instances, chooses +one, and sets the variable as a cache entry to hold the value persistently. + +When CMake first chooses an instance, if the ``VS160COMNTOOLS`` environment +variable is set and points to the ``Common7/Tools`` directory within +one of the instances, that instance will be used. Otherwise, if more +than one instance is installed we do not define which one is chosen +by default. + +Platform Selection +^^^^^^^^^^^^^^^^^^ + +The default target platform name (architecture) is that of the host. + +The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps +via the :manual:`cmake(1)` ``-A`` option, to specify a target platform +name (architecture). For example: + +* ``cmake -G "Visual Studio 16 2019" -A Win32`` +* ``cmake -G "Visual Studio 16 2019" -A x64`` +* ``cmake -G "Visual Studio 16 2019" -A ARM`` +* ``cmake -G "Visual Studio 16 2019" -A ARM64`` + +Toolset Selection +^^^^^^^^^^^^^^^^^ + +The ``v142`` toolset that comes with Visual Studio 16 2019 is selected by +default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps +via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. + +.. include:: VS_TOOLSET_HOST_ARCH.txt diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index 4fc484b..a1328f2 100644 --- a/Help/manual/cmake-buildsystem.7.rst +++ b/Help/manual/cmake-buildsystem.7.rst @@ -978,6 +978,7 @@ are: * Built-in properties matching ``COMPATIBLE_INTERFACE_*`` * ``EXPORT_NAME`` * ``IMPORTED`` +* ``MANUALLY_ADDED_DEPENDENCIES`` * ``NAME`` * Properties matching ``IMPORTED_LIBNAME_*`` * Properties matching ``MAP_IMPORTED_CONFIG_*`` diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index ee13e40..a3bc465 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -100,8 +100,6 @@ These commands are available only in CMake projects. /command/link_libraries /command/load_cache /command/project - /command/qt_wrap_cpp - /command/qt_wrap_ui /command/remove_definitions /command/set_source_files_properties /command/set_target_properties @@ -145,9 +143,10 @@ These commands are available only in CTest scripts. Deprecated Commands =================== -These commands are deprecated since CMake version 3.0. -They are available only for backward compatibility. -Do not use them in new code. +These commands are deprecated and are only made available to maintain +backward compatibility. The documentation of each command states the +CMake version in which it was deprecated. Do not use these commands +in new code. .. toctree:: :maxdepth: 1 @@ -161,6 +160,8 @@ Do not use them in new code. /command/load_command /command/make_directory /command/output_required_files + /command/qt_wrap_cpp + /command/qt_wrap_ui /command/remove /command/subdir_depends /command/subdirs diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 63e43e1..7f484a4 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -122,12 +122,19 @@ Variable Queries ``1`` if the CMake-id of the CXX compiler matches ``compiler_id``, otherwise ``0``. See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. +``$<Fortran_COMPILER_ID:compiler_id>`` + ``1`` if the CMake-id of the Fortran compiler matches ``compiler_id``, + otherwise ``0``. + See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. ``$<C_COMPILER_VERSION:version>`` ``1`` if the version of the C compiler matches ``version``, otherwise ``0``. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. ``$<CXX_COMPILER_VERSION:version>`` ``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. +``$<Fortran_COMPILER_VERSION:version>`` + ``1`` if the version of the Fortran compiler matches ``version``, otherwise ``0``. + See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. ``$<TARGET_POLICY:policy>`` ``1`` if the ``policy`` was NEW when the 'head' target was created, else ``0``. If the ``policy`` was not set, the warning message for the policy @@ -339,12 +346,18 @@ Variable Queries ``$<CXX_COMPILER_ID>`` The CMake-id of the CXX compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. +``$<Fortran_COMPILER_ID>`` + The CMake-id of the Fortran compiler used. + See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. ``$<C_COMPILER_VERSION>`` The version of the C compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. ``$<CXX_COMPILER_VERSION>`` The version of the CXX compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. +``$<Fortran_COMPILER_VERSION>`` + The version of the Fortran compiler used. + See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. ``$<COMPILE_LANGUAGE>`` The compile language of source files when evaluating compile options. See :ref:`the related boolean expression diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst index 1de10c4..41f7652 100644 --- a/Help/manual/cmake-generators.7.rst +++ b/Help/manual/cmake-generators.7.rst @@ -87,6 +87,7 @@ Visual Studio Generators /generator/Visual Studio 12 2013 /generator/Visual Studio 14 2015 /generator/Visual Studio 15 2017 + /generator/Visual Studio 16 2019 Other Generators ^^^^^^^^^^^^^^^^ diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 940186a..71a8b00 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -28,6 +28,7 @@ These modules are loaded using the :command:`include` command. /module/CheckFortranCompilerFlag /module/CheckFortranFunctionExists /module/CheckFortranSourceCompiles + /module/CheckFortranSourceRuns /module/CheckFunctionExists /module/CheckIPOSupported /module/CheckIncludeFileCXX diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index df8f12c..e1de134 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -23,6 +23,7 @@ Properties of Global Scope /prop_gbl/AUTORCC_SOURCE_GROUP /prop_gbl/CMAKE_C_KNOWN_FEATURES /prop_gbl/CMAKE_CXX_KNOWN_FEATURES + /prop_gbl/CMAKE_ROLE /prop_gbl/DEBUG_CONFIGURATIONS /prop_gbl/DISABLED_FEATURES /prop_gbl/ENABLED_FEATURES @@ -193,6 +194,7 @@ Properties on Targets /prop_tgt/FRAMEWORK /prop_tgt/FRAMEWORK_VERSION /prop_tgt/GENERATOR_FILE_NAME + /prop_tgt/GHS_INTEGRITY_APP /prop_tgt/GNUtoMS /prop_tgt/HAS_CXX /prop_tgt/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM @@ -204,7 +206,6 @@ Properties on Targets /prop_tgt/IMPORTED_LIBNAME_CONFIG /prop_tgt/IMPORTED_LIBNAME /prop_tgt/IMPORTED_LINK_DEPENDENT_LIBRARIES_CONFIG - /prop_tgt/IMPORTED_LINK_DEPENDENT_LIBRARIES_CONFIG /prop_tgt/IMPORTED_LINK_DEPENDENT_LIBRARIES /prop_tgt/IMPORTED_LINK_INTERFACE_LANGUAGES_CONFIG /prop_tgt/IMPORTED_LINK_INTERFACE_LANGUAGES diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index e464b0c..bd6a58f 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -170,6 +170,7 @@ Variables that Change Behavior /variable/CMAKE_FIND_NO_INSTALL_PREFIX /variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY /variable/CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY + /variable/CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS /variable/CMAKE_FIND_PACKAGE_WARN_NO_MODULE /variable/CMAKE_FIND_ROOT_PATH /variable/CMAKE_FIND_ROOT_PATH_MODE_INCLUDE @@ -482,11 +483,6 @@ Variables for Languages /variable/CMAKE_LANG_FLAGS_RELEASE_INIT /variable/CMAKE_LANG_FLAGS_RELWITHDEBINFO /variable/CMAKE_LANG_FLAGS_RELWITHDEBINFO_INIT - /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_CONFIG - /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG - /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL - /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE - /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO /variable/CMAKE_LANG_IGNORE_EXTENSIONS /variable/CMAKE_LANG_IMPLICIT_INCLUDE_DIRECTORIES /variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES @@ -574,6 +570,7 @@ Variables for CTest /variable/CTEST_RUN_CURRENT_SCRIPT /variable/CTEST_SCP_COMMAND /variable/CTEST_SITE + /variable/CTEST_SUBMIT_URL /variable/CTEST_SOURCE_DIRECTORY /variable/CTEST_SVN_COMMAND /variable/CTEST_SVN_OPTIONS diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 8490e3d..bcf75ac 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -1109,38 +1109,45 @@ Configuration settings include: * :module:`CTest` module variable: ``CTEST_CURL_OPTIONS`` ``DropLocation`` - The path on the dashboard server to send the submission. + Legacy option. When ``SubmitURL`` is not set, it is constructed from + ``DropMethod``, ``DropSiteUser``, ``DropSitePassword``, ``DropSite``, and + ``DropLocation``. * `CTest Script`_ variable: :variable:`CTEST_DROP_LOCATION` * :module:`CTest` module variable: ``DROP_LOCATION`` if set, else ``CTEST_DROP_LOCATION`` ``DropMethod`` - Specify the method by which results should be submitted to the - dashboard server. The value may be ``http`` or ``https``. + Legacy option. When ``SubmitURL`` is not set, it is constructed from + ``DropMethod``, ``DropSiteUser``, ``DropSitePassword``, ``DropSite``, and + ``DropLocation``. * `CTest Script`_ variable: :variable:`CTEST_DROP_METHOD` * :module:`CTest` module variable: ``DROP_METHOD`` if set, else ``CTEST_DROP_METHOD`` ``DropSite`` - The dashboard server name. + Legacy option. When ``SubmitURL`` is not set, it is constructed from + ``DropMethod``, ``DropSiteUser``, ``DropSitePassword``, ``DropSite``, and + ``DropLocation``. * `CTest Script`_ variable: :variable:`CTEST_DROP_SITE` * :module:`CTest` module variable: ``DROP_SITE`` if set, else ``CTEST_DROP_SITE`` ``DropSitePassword`` - The dashboard server login password, if any - (for ``ftp``, ``http``, and ``https``). + Legacy option. When ``SubmitURL`` is not set, it is constructed from + ``DropMethod``, ``DropSiteUser``, ``DropSitePassword``, ``DropSite``, and + ``DropLocation``. * `CTest Script`_ variable: :variable:`CTEST_DROP_SITE_PASSWORD` * :module:`CTest` module variable: ``DROP_SITE_PASSWORD`` if set, else ``CTEST_DROP_SITE_PASWORD`` ``DropSiteUser`` - The dashboard server login user name, if any - (for ``ftp``, ``http``, and ``https``). + Legacy option. When ``SubmitURL`` is not set, it is constructed from + ``DropMethod``, ``DropSiteUser``, ``DropSitePassword``, ``DropSite``, and + ``DropLocation``. * `CTest Script`_ variable: :variable:`CTEST_DROP_SITE_USER` * :module:`CTest` module variable: ``DROP_SITE_USER`` if set, @@ -1166,6 +1173,14 @@ Configuration settings include: * :module:`CTest` module variable: ``SITE``, initialized by the :command:`site_name` command +``SubmitURL`` + The ``http`` or ``https`` URL of the dashboard server to send the submission + to. + + * `CTest Script`_ variable: :variable:`CTEST_SUBMIT_URL` + * :module:`CTest` module variable: ``SUBMIT_URL`` if set, + else ``CTEST_SUBMIT_URL`` + ``TriggerSite`` Legacy option. Not used. diff --git a/Help/module/CheckFortranSourceRuns.rst b/Help/module/CheckFortranSourceRuns.rst new file mode 100644 index 0000000..a1bff70 --- /dev/null +++ b/Help/module/CheckFortranSourceRuns.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CheckFortranSourceRuns.cmake diff --git a/Help/prop_gbl/CMAKE_ROLE.rst b/Help/prop_gbl/CMAKE_ROLE.rst new file mode 100644 index 0000000..27512fa --- /dev/null +++ b/Help/prop_gbl/CMAKE_ROLE.rst @@ -0,0 +1,20 @@ +CMAKE_ROLE +---------- + +Tells what mode the current running script is in. Could be one of several +values: + +``PROJECT`` + Running in project mode (processing a ``CMakeLists.txt`` file). + +``SCRIPT`` + Running in ``-P`` script mode. + +``FIND_PACKAGE`` + Running in ``--find-package`` mode. + +``CTEST`` + Running in CTest script mode. + +``CPACK`` + Running in CPack. diff --git a/Help/prop_tgt/GHS_INTEGRITY_APP.rst b/Help/prop_tgt/GHS_INTEGRITY_APP.rst new file mode 100644 index 0000000..7643038 --- /dev/null +++ b/Help/prop_tgt/GHS_INTEGRITY_APP.rst @@ -0,0 +1,10 @@ +GHS_INTEGRITY_APP +----------------- + +``ON`` / ``OFF`` boolean to determine if an executable target should +be treated as an `Integrity Application`. + +If no value is set and if a `.int` file is added as a source file to the +executable target it will be treated as an `Integrity Application`. + +Supported on :generator:`Green Hills MULTI`. diff --git a/Help/release/dev/ExternalProject-non-cmake-source-subdir.rst b/Help/release/dev/ExternalProject-non-cmake-source-subdir.rst new file mode 100644 index 0000000..29fe2ad --- /dev/null +++ b/Help/release/dev/ExternalProject-non-cmake-source-subdir.rst @@ -0,0 +1,7 @@ +ExternalProject-non-cmake-source-subdir +--------------------------------------- + +* The :module:`ExternalProject` module's ``ExternalProject_Add`` command + learned to apply ``SOURCE_SUBDIR`` when ``BUILD_IN_SOURCE`` is also used. + The ``BUILD_COMMAND`` is run in the given ``SOURCE_SUBDIR`` of the + ``SOURCE_DIR``. diff --git a/Help/release/dev/check-fortran-run.rst b/Help/release/dev/check-fortran-run.rst new file mode 100644 index 0000000..b5f6558 --- /dev/null +++ b/Help/release/dev/check-fortran-run.rst @@ -0,0 +1,6 @@ +check-fortran-run +----------------- + +* A :module:`CheckFortranSourceRuns` module was added to provide a + :command:`check_fortran_source_runs` command to check if a Fortran + source snippet compiles and runs. diff --git a/Help/release/dev/cmake_role-global-property.rst b/Help/release/dev/cmake_role-global-property.rst new file mode 100644 index 0000000..7b1fa0b --- /dev/null +++ b/Help/release/dev/cmake_role-global-property.rst @@ -0,0 +1,6 @@ +cmake_role-global-property +-------------------------- + +* A new global property, :prop_gbl:`CMAKE_ROLE`, was added to allow scripts to + determine whether they're running in project mode, script mode, find-package + mode, CTest, or CPack. diff --git a/Help/release/dev/ctest-submit-url.rst b/Help/release/dev/ctest-submit-url.rst new file mode 100644 index 0000000..f848877 --- /dev/null +++ b/Help/release/dev/ctest-submit-url.rst @@ -0,0 +1,7 @@ +ctest-submit-url +---------------- + +* CTest learned to accept the dashboard server submission URL from a single + variable. See the ``SubmitURL`` setting in :manual:`ctest(1)`, + the :variable:`CTEST_SUBMIT_URL` variable, and the ``SUBMIT_URL`` + argument of the :command:`ctest_submit` command. diff --git a/Help/release/dev/deprecate-policy-old.rst b/Help/release/dev/deprecate-policy-old.rst new file mode 100644 index 0000000..2c99780 --- /dev/null +++ b/Help/release/dev/deprecate-policy-old.rst @@ -0,0 +1,8 @@ +deprecate-policy-old +-------------------- + +* An explicit deprecation diagnostic was added for policies ``CMP0064`` + and ``CMP0065`` (``CMP0063`` and below were already deprecated). + The :manual:`cmake-policies(7)` manual explains that the OLD behaviors + of all policies are deprecated and that projects should port to the + NEW behaviors. diff --git a/Help/release/dev/find-package-resolve-symlinks.rst b/Help/release/dev/find-package-resolve-symlinks.rst new file mode 100644 index 0000000..7adb9fe --- /dev/null +++ b/Help/release/dev/find-package-resolve-symlinks.rst @@ -0,0 +1,6 @@ +find-package-resolve-symlinks +----------------------------- + +* The :command:`find_package` command learned to optionally resolve + symbolic links in the paths to package configuration files. + See the :variable:`CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS` variable. diff --git a/Help/release/dev/fortran-compiler-id.rst b/Help/release/dev/fortran-compiler-id.rst new file mode 100644 index 0000000..1ea3bf9 --- /dev/null +++ b/Help/release/dev/fortran-compiler-id.rst @@ -0,0 +1,5 @@ +Fortran_COMPILER_ID +------------------- + +* The ``$<Fortran_COMPILER_ID:...>`` and ``$<Fortran_COMPILER_VERSION:...>`` + :manual:`generator expressions <cmake-generator-expressions(7)>` were added. diff --git a/Help/release/dev/rel-win7.rst b/Help/release/dev/rel-win7.rst new file mode 100644 index 0000000..f7a745c --- /dev/null +++ b/Help/release/dev/rel-win7.rst @@ -0,0 +1,6 @@ +rel-win7 +-------- + +* Support for running CMake on Windows XP and Windows Vista has been dropped. + The precompiled Windows binaries provided on ``cmake.org`` now require + Windows 7 or higher. diff --git a/Help/release/dev/vs-debug-utility-targets.rst b/Help/release/dev/vs-debug-utility-targets.rst new file mode 100644 index 0000000..02e5262 --- /dev/null +++ b/Help/release/dev/vs-debug-utility-targets.rst @@ -0,0 +1,6 @@ +vs-debug-utility-targets +------------------------ + +* :ref:`Visual Studio Generators` for VS 2010 and above learned + to support the ``VS_DEBUGGER_*`` properties on targets created + via :command:`add_custom_target`. diff --git a/Help/release/dev/vs2019.rst b/Help/release/dev/vs2019.rst new file mode 100644 index 0000000..1ffdeec --- /dev/null +++ b/Help/release/dev/vs2019.rst @@ -0,0 +1,13 @@ +vs2019 +------ + +* The :generator:`Visual Studio 16 2019` generator was added. This is + experimental and based on "Visual Studio 2019 Preview 1.1" because this + version of VS has not been released. + + The VS 2019 generator differs from generators for earlier versions + in that it does not provide variants that specify the target platform + in the generator name. Instead :variable:`CMAKE_GENERATOR_PLATFORM` + must be used, e.g. through the ``-A`` command-line option. Furthermore, + the default target platform (architecture) is now based on the *host* + platform. diff --git a/Help/variable/CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS.rst b/Help/variable/CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS.rst new file mode 100644 index 0000000..dfbde20 --- /dev/null +++ b/Help/variable/CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS.rst @@ -0,0 +1,10 @@ +CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS +----------------------------------- + +Set to ``TRUE`` to tell :command:`find_package` calls to resolve symbolic +links in the value of ``<PackageName>_DIR``. + +This is helpful in use cases where the package search path points at a +proxy directory in which symlinks to the real package locations appear. +This is not enabled by default because there are also common use cases +in which the symlinks should be preserved. diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst index 2264269..033e81c 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst @@ -19,6 +19,7 @@ include: Embarcadero, Borland = Embarcadero (embarcadero.com) G95 = G95 Fortran (g95.org) GNU = GNU Compiler Collection (gcc.gnu.org) + GHS = Green Hills Software (www.ghs.com) HP = Hewlett-Packard Compiler (hp.com) IAR = IAR Systems (iar.com) Intel = Intel Compiler (intel.com) diff --git a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_CONFIG.rst b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_CONFIG.rst deleted file mode 100644 index 8ed1c02..0000000 --- a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_CONFIG.rst +++ /dev/null @@ -1,5 +0,0 @@ -CMAKE_<LANG>_GHS_KERNEL_FLAGS_<CONFIG> --------------------------------------- - -GHS kernel flags for language ``<LANG>`` when building for the ``<CONFIG>`` -configuration. diff --git a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG.rst b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG.rst deleted file mode 100644 index 4fea67a..0000000 --- a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG.rst +++ /dev/null @@ -1,5 +0,0 @@ -CMAKE_<LANG>_GHS_KERNEL_FLAGS_DEBUG ------------------------------------ - -This variable is the ``Debug`` variant of the -:variable:`CMAKE_<LANG>_GHS_KERNEL_FLAGS_<CONFIG>` variable. diff --git a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL.rst b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL.rst deleted file mode 100644 index 31f87f2..0000000 --- a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL.rst +++ /dev/null @@ -1,5 +0,0 @@ -CMAKE_<LANG>_GHS_KERNEL_FLAGS_MINSIZEREL ----------------------------------------- - -This variable is the ``MinSizeRel`` variant of the -:variable:`CMAKE_<LANG>_GHS_KERNEL_FLAGS_<CONFIG>` variable. diff --git a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE.rst b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE.rst deleted file mode 100644 index 1acd198..0000000 --- a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE.rst +++ /dev/null @@ -1,5 +0,0 @@ -CMAKE_<LANG>_GHS_KERNEL_FLAGS_RELEASE -------------------------------------- - -This variable is the ``Release`` variant of the -:variable:`CMAKE_<LANG>_GHS_KERNEL_FLAGS_<CONFIG>` variable. diff --git a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO.rst b/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO.rst deleted file mode 100644 index ac1b6bc..0000000 --- a/Help/variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELWITHDEBINFO.rst +++ /dev/null @@ -1,5 +0,0 @@ -CMAKE_<LANG>_GHS_KERNEL_FLAGS_RELWITHDEBINFO --------------------------------------------- - -This variable is the ``RelWithDebInfo`` variant of the -:variable:`CMAKE_<LANG>_GHS_KERNEL_FLAGS_<CONFIG>` variable. diff --git a/Help/variable/CTEST_SUBMIT_URL.rst b/Help/variable/CTEST_SUBMIT_URL.rst new file mode 100644 index 0000000..7d84da4 --- /dev/null +++ b/Help/variable/CTEST_SUBMIT_URL.rst @@ -0,0 +1,5 @@ +CTEST_SUBMIT_URL +---------------- + +Specify the CTest ``SubmitURL`` setting +in a :manual:`ctest(1)` dashboard client script. diff --git a/Help/variable/GHS-MULTI.rst b/Help/variable/GHS-MULTI.rst index 0f91be8..fe3b17e 100644 --- a/Help/variable/GHS-MULTI.rst +++ b/Help/variable/GHS-MULTI.rst @@ -1,4 +1,4 @@ GHS-MULTI --------- -True when using Green Hills MULTI +``True`` when using :generator:`Green Hills MULTI` generator. diff --git a/Help/variable/MSVC_VERSION.rst b/Help/variable/MSVC_VERSION.rst index 4ef43d8..45df37f 100644 --- a/Help/variable/MSVC_VERSION.rst +++ b/Help/variable/MSVC_VERSION.rst @@ -18,6 +18,7 @@ Known version numbers are:: 1800 = VS 12.0 (v120 toolset) 1900 = VS 14.0 (v140 toolset) 1910-1919 = VS 15.0 (v141 toolset) + 1920-1929 = VS 16.0 (v142 toolset) See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` and :variable:`MSVC_TOOLSET_VERSION` variable. diff --git a/Modules/CMakeBackwardCompatibilityCXX.cmake b/Modules/CMakeBackwardCompatibilityCXX.cmake index 628b541..02744a9 100644 --- a/Modules/CMakeBackwardCompatibilityCXX.cmake +++ b/Modules/CMakeBackwardCompatibilityCXX.cmake @@ -22,9 +22,6 @@ if(NOT CMAKE_SKIP_COMPATIBILITY_TESTS) if(NOT CMAKE_COMPILER_IS_GNUCXX) include(TestCXXAcceptsFlag) set(CMAKE_TRY_ANSI_CXX_FLAGS "") - if(CMAKE_SYSTEM_NAME MATCHES "IRIX") - set(CMAKE_TRY_ANSI_CXX_FLAGS "-LANG:std") - endif() if(CMAKE_SYSTEM_NAME MATCHES "OSF") set(CMAKE_TRY_ANSI_CXX_FLAGS "-std strict_ansi -nopure_cname") endif() diff --git a/Modules/CMakeCompilerABI.h b/Modules/CMakeCompilerABI.h index 6f36b03..45532af 100644 --- a/Modules/CMakeCompilerABI.h +++ b/Modules/CMakeCompilerABI.h @@ -10,16 +10,10 @@ const char info_sizeof_dptr[] = { }; /* Application Binary Interface. */ -#if defined(__sgi) && defined(_ABIO32) -# define ABI_ID "ELF O32" -#elif defined(__sgi) && defined(_ABIN32) -# define ABI_ID "ELF N32" -#elif defined(__sgi) && defined(_ABI64) -# define ABI_ID "ELF 64" /* Check for (some) ARM ABIs. * See e.g. http://wiki.debian.org/ArmEabiPort for some information on this. */ -#elif defined(__GNU__) && defined(__ELF__) && defined(__ARM_EABI__) +#if defined(__GNU__) && defined(__ELF__) && defined(__ARM_EABI__) # define ABI_ID "ELF ARMEABI" #elif defined(__GNU__) && defined(__ELF__) && defined(__ARMEB__) # define ABI_ID "ELF ARM" diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index f2d43b6..4d0c681 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -63,6 +63,7 @@ function(compiler_id_detection outvar lang) Cray TI Fujitsu + GHS ) if (lang STREQUAL C) list(APPEND ordered_compilers @@ -135,9 +136,6 @@ function(compiler_id_detection outvar lang) /* These compilers are either not known or too old to define an identification macro. Try to identify the platform and guess that it is the native compiler. */ -#elif defined(__sgi) -# define ${CID_PREFIX}COMPILER_ID \"MIPSpro\" - #elif defined(__hpux) || defined(__hpua) # define ${CID_PREFIX}COMPILER_ID \"HP\" diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index 1a0d8a6..4f355f3 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -31,6 +31,7 @@ if(NOT CMAKE_C_COMPILER_NAMES) endif() if(${CMAKE_GENERATOR} MATCHES "Visual Studio") +elseif("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI") elseif("${CMAKE_GENERATOR}" MATCHES "Xcode") set(CMAKE_C_COMPILER_XCODE_TYPE sourcecode.c.c) _cmake_find_compiler_path(C) diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index 0a0c37b..96b4209 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -30,6 +30,7 @@ if(NOT CMAKE_CXX_COMPILER_NAMES) endif() if(${CMAKE_GENERATOR} MATCHES "Visual Studio") +elseif("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI") elseif("${CMAKE_GENERATOR}" MATCHES "Xcode") set(CMAKE_CXX_COMPILER_XCODE_TYPE sourcecode.cpp.cpp) _cmake_find_compiler_path(CXX) diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index 604ac27..d88f2ed 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -7,6 +7,7 @@ # code. include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake) +include(CMakeTestCompilerCommon) function(CMAKE_DETERMINE_COMPILER_ABI lang src) if(NOT DEFINED CMAKE_${lang}_ABI_COMPILED) @@ -23,6 +24,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) # from which we might detect implicit link libraries. list(APPEND CMAKE_FLAGS "-DCMAKE_${lang}_STANDARD_LIBRARIES=") endif() + __TestCompiler_setTryCompileTargetType() try_compile(CMAKE_${lang}_ABI_COMPILED ${CMAKE_BINARY_DIR} ${src} CMAKE_FLAGS ${CMAKE_FLAGS} diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 050d3e7..2a0dbd3 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -52,6 +52,13 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) endforeach() endif() + # If the compiler is still unknown, fallback to GHS + if(NOT CMAKE_${lang}_COMPILER_ID AND "${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI") + set(CMAKE_${lang}_COMPILER_ID GHS) + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "The ${lang} compiler identification is falling back to GHS.\n\n") + endif() + # CUDA < 7.5 is missing version macros if(lang STREQUAL "CUDA" AND CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA" @@ -391,6 +398,40 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} separate_arguments(CMAKE_${lang}_XCODE_ARCHS) set(CMAKE_${lang}_XCODE_ARCHS "${CMAKE_${lang}_XCODE_ARCHS}" PARENT_SCOPE) endif() + elseif("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI") + set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR}) + set(id_src "${src}") + if (GHS_PRIMARY_TARGET) + set(ghs_primary_target "${GHS_PRIMARY_TARGET}") + else() + set(ghs_primary_target "${CMAKE_GENERATOR_PLATFORM}_${GHS_TARGET_PLATFORM}.tgt") + endif() + if ("${GHS_TARGET_PLATFORM}" MATCHES "integrity") + set(bsp_name "macro GHS_BSP=${GHS_BSP_NAME}") + set(os_dir "macro GHS_OS=${GHS_OS_DIR}") + endif() + set(command "${CMAKE_MAKE_PROGRAM}" "-commands" "-top" "GHS_default.gpj") + configure_file(${CMAKE_ROOT}/Modules/CompilerId/GHS_default.gpj.in + ${id_dir}/GHS_default.gpj @ONLY) + configure_file(${CMAKE_ROOT}/Modules/CompilerId/GHS_lib.gpj.in + ${id_dir}/GHS_lib.gpj @ONLY) + execute_process(COMMAND ${command} + WORKING_DIRECTORY ${id_dir} + OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT + ERROR_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT + RESULT_VARIABLE CMAKE_${lang}_COMPILER_ID_RESULT + ) + # Match the compiler location line printed out. + set(ghs_toolpath "${CMAKE_MAKE_PROGRAM}") + string(REPLACE "/gbuild.exe" "/" ghs_toolpath ${ghs_toolpath}) + string(REPLACE / "\\\\" ghs_toolpath ${ghs_toolpath}) + if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "(${ghs_toolpath}[^ ]*)") + set(_comp "${CMAKE_MATCH_1}.exe") + if(EXISTS "${_comp}") + file(TO_CMAKE_PATH "${_comp}" _comp) + set(CMAKE_${lang}_COMPILER_ID_TOOL "${_comp}" PARENT_SCOPE) + endif() + endif() else() execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" @@ -523,7 +564,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) file(STRINGS ${file} CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 38 ${CMAKE_${lang}_COMPILER_ID_STRINGS_PARAMETERS} - REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]") + REGEX ".?I.?N.?F.?O.?:.?[A-Za-z0-9_]+\\[[^]]*\\]") set(COMPILER_ID_TWICE) # With the IAR Compiler, some strings are found twice, first time as incomplete # list like "?<Constant "INFO:compiler[IAR]">". Remove the incomplete copies. @@ -531,6 +572,12 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) # In C# binaries, some strings are found more than once. list(REMOVE_DUPLICATES CMAKE_${lang}_COMPILER_ID_STRINGS) foreach(info ${CMAKE_${lang}_COMPILER_ID_STRINGS}) + # The IAR-AVR compiler uses a binary format that places a '6' + # character (0x34) before each character in the string. Strip + # out these characters without removing any legitamate characters. + if("${info}" MATCHES "(.)I.N.F.O.:.") + string(REGEX REPLACE "${CMAKE_MATCH_1}(.)" "\\1" info "${info}") + endif() if("${info}" MATCHES "INFO:compiler\\[([^]\"]*)\\]") if(COMPILER_ID) set(COMPILER_ID_TWICE 1) @@ -544,7 +591,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) set(ARCHITECTURE_ID "${CMAKE_MATCH_1}") endif() if("${info}" MATCHES "INFO:compiler_version\\[([^]\"]*)\\]") - string(REGEX REPLACE "^0+([0-9])" "\\1" COMPILER_VERSION "${CMAKE_MATCH_1}") + string(REGEX REPLACE "^0+([0-9]+)" "\\1" COMPILER_VERSION "${CMAKE_MATCH_1}") string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION "${COMPILER_VERSION}") endif() if("${info}" MATCHES "INFO:compiler_version_internal\\[([^]\"]*)\\]") @@ -596,26 +643,28 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) if(WIN32) # The offset to the PE signature is stored at 0x3c. file(READ ${file} peoffsethex LIMIT 1 OFFSET 60 HEX) - string(SUBSTRING "${peoffsethex}" 0 1 peoffsethex1) - string(SUBSTRING "${peoffsethex}" 1 1 peoffsethex2) - set(peoffsetexpression "${peoffsethex1} * 16 + ${peoffsethex2}") - string(REPLACE "a" "10" peoffsetexpression "${peoffsetexpression}") - string(REPLACE "b" "11" peoffsetexpression "${peoffsetexpression}") - string(REPLACE "c" "12" peoffsetexpression "${peoffsetexpression}") - string(REPLACE "d" "13" peoffsetexpression "${peoffsetexpression}") - string(REPLACE "e" "14" peoffsetexpression "${peoffsetexpression}") - string(REPLACE "f" "15" peoffsetexpression "${peoffsetexpression}") - math(EXPR peoffset "${peoffsetexpression}") - - file(READ ${file} peheader LIMIT 6 OFFSET ${peoffset} HEX) - if(peheader STREQUAL "50450000a201") - set(ARCHITECTURE_ID "SH3") - elseif(peheader STREQUAL "50450000a301") - set(ARCHITECTURE_ID "SH3DSP") - elseif(peheader STREQUAL "50450000a601") - set(ARCHITECTURE_ID "SH4") - elseif(peheader STREQUAL "50450000a801") - set(ARCHITECTURE_ID "SH5") + if(NOT peoffsethex STREQUAL "") + string(SUBSTRING "${peoffsethex}" 0 1 peoffsethex1) + string(SUBSTRING "${peoffsethex}" 1 1 peoffsethex2) + set(peoffsetexpression "${peoffsethex1} * 16 + ${peoffsethex2}") + string(REPLACE "a" "10" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "b" "11" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "c" "12" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "d" "13" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "e" "14" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "f" "15" peoffsetexpression "${peoffsetexpression}") + math(EXPR peoffset "${peoffsetexpression}") + + file(READ ${file} peheader LIMIT 6 OFFSET ${peoffset} HEX) + if(peheader STREQUAL "50450000a201") + set(ARCHITECTURE_ID "SH3") + elseif(peheader STREQUAL "50450000a301") + set(ARCHITECTURE_ID "SH3DSP") + elseif(peheader STREQUAL "50450000a601") + set(ARCHITECTURE_ID "SH4") + elseif(peheader STREQUAL "50450000a801") + set(ARCHITECTURE_ID "SH5") + endif() endif() endif() diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index 600d558..dc208c6 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -13,7 +13,6 @@ # BSD/OS BSD/OS # FreeBSD FreeBSD # HP-UX HP-UX -# IRIX IRIX # Linux Linux # GNU/kFreeBSD GNU/kFreeBSD # NetBSD NetBSD diff --git a/Modules/CMakeFortranCompilerABI.F b/Modules/CMakeFortranCompilerABI.F index b34c284..f4a5489 100644 --- a/Modules/CMakeFortranCompilerABI.F +++ b/Modules/CMakeFortranCompilerABI.F @@ -33,13 +33,7 @@ #if 0 ! Application Binary Interface #endif -#if defined(__sgi) && defined(_ABIO32) - PRINT *, 'INFO:abi[ELF O32]' -#elif defined(__sgi) && defined(_ABIN32) - PRINT *, 'INFO:abi[ELF N32]' -#elif defined(__sgi) && defined(_ABI64) - PRINT *, 'INFO:abi[ELF 64]' -#elif defined(__ELF__) +#if defined(__ELF__) PRINT *, 'INFO:abi[ELF]' #endif PRINT *, 'ABI Detection' diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in index da3d953..5995694 100644 --- a/Modules/CMakeFortranCompilerId.F.in +++ b/Modules/CMakeFortranCompilerId.F.in @@ -105,8 +105,6 @@ # endif #elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) PRINT *, 'INFO:compiler[VisualAge]' -#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) - PRINT *, 'INFO:compiler[MIPSpro]' #elif defined(__hpux) || defined(__hpux__) PRINT *, 'INFO:compiler[HP]' #elif defined(NAGFOR) @@ -114,11 +112,7 @@ #define COMPILER_VERSION_MAJOR DEC(__NAG_COMPILER_RELEASE/10) #define COMPILER_VERSION_MINOR DEC(__NAG_COMPILER_RELEASE % 10) #define COMPILER_VERSION_PATCH DEC(__NAG_COMPILER_BUILD) -#elif 1 -# if 0 -! The above 'elif 1' instead of 'else' is to work around a bug in the -! SGI preprocessor which produces both the __sgi and else blocks. -# endif +#else PRINT *, 'INFO:compiler[]' #endif #if defined(__CRAYXE) || defined(__CRAYXC) @@ -148,8 +142,6 @@ PRINT *, 'INFO:platform[SunOS]' #elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) PRINT *, 'INFO:platform[AIX]' -#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) - PRINT *, 'INFO:platform[IRIX]' #elif defined(__hpux) || defined(__hpux__) PRINT *, 'INFO:platform[HP-UX]' #elif defined(__HAIKU__) @@ -178,11 +170,7 @@ PRINT *, 'INFO:platform[ULTRIX]' #elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) PRINT *, 'INFO:platform[Xenix]' -#elif 1 -# if 0 -! The above 'elif 1' instead of 'else' is to work around a bug in the -! SGI preprocessor which produces both the __sgi and else blocks. -# endif +#else PRINT *, 'INFO:platform[]' #endif #if defined(_WIN32) && (defined(__INTEL_COMPILER) || defined(__ICC)) diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index dd77379..3cb7f24 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -32,9 +32,6 @@ #elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) # define PLATFORM_ID "AIX" -#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) -# define PLATFORM_ID "IRIX" - #elif defined(__hpux) || defined(__hpux__) # define PLATFORM_ID "HP-UX" @@ -94,6 +91,14 @@ # define PLATFORM_ID # endif +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + #else /* unknown platform */ # define PLATFORM_ID @@ -157,6 +162,26 @@ # else /* unknown architecture */ # define ARCHITECTURE_ID "" # endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif #else # define ARCHITECTURE_ID #endif diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake index e34ae75..f74a1c6 100644 --- a/Modules/CMakeTestCCompiler.cmake +++ b/Modules/CMakeTestCCompiler.cmake @@ -22,6 +22,7 @@ unset(CMAKE_C_COMPILER_WORKS CACHE) # any makefiles or projects. if(NOT CMAKE_C_COMPILER_WORKS) PrintTestCompilerStatus("C" "") + __TestCompiler_setTryCompileTargetType() file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c "#ifdef __cplusplus\n" "# error \"The CMAKE_C_COMPILER is set to a C++ compiler\"\n" @@ -41,6 +42,7 @@ if(NOT CMAKE_C_COMPILER_WORKS) set(CMAKE_C_COMPILER_WORKS ${CMAKE_C_COMPILER_WORKS}) unset(CMAKE_C_COMPILER_WORKS CACHE) set(C_TEST_WAS_RUN 1) + __TestCompiler_restoreTryCompileTargetType() endif() if(NOT CMAKE_C_COMPILER_WORKS) diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake index e4d49ae..fe6bd25 100644 --- a/Modules/CMakeTestCXXCompiler.cmake +++ b/Modules/CMakeTestCXXCompiler.cmake @@ -22,6 +22,7 @@ unset(CMAKE_CXX_COMPILER_WORKS CACHE) # any makefiles or projects. if(NOT CMAKE_CXX_COMPILER_WORKS) PrintTestCompilerStatus("CXX" "") + __TestCompiler_setTryCompileTargetType() file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCXXCompiler.cxx "#ifndef __cplusplus\n" "# error \"The CMAKE_CXX_COMPILER is set to a C compiler\"\n" @@ -34,6 +35,7 @@ if(NOT CMAKE_CXX_COMPILER_WORKS) set(CMAKE_CXX_COMPILER_WORKS ${CMAKE_CXX_COMPILER_WORKS}) unset(CMAKE_CXX_COMPILER_WORKS CACHE) set(CXX_TEST_WAS_RUN 1) + __TestCompiler_restoreTryCompileTargetType() endif() if(NOT CMAKE_CXX_COMPILER_WORKS) diff --git a/Modules/CMakeTestCompilerCommon.cmake b/Modules/CMakeTestCompilerCommon.cmake index f76076f..6ee5175 100644 --- a/Modules/CMakeTestCompilerCommon.cmake +++ b/Modules/CMakeTestCompilerCommon.cmake @@ -5,3 +5,23 @@ function(PrintTestCompilerStatus LANG MSG) message(STATUS "Check for working ${LANG} compiler: ${CMAKE_${LANG}_COMPILER}${MSG}") endfunction() + +# if required set the target type if not already explicitly set +macro(__TestCompiler_setTryCompileTargetType) + if(NOT CMAKE_TRY_COMPILE_TARGET_TYPE) + if("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI") + #prefer static libraries to avoid linking issues + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + set(__CMAKE_TEST_COMPILER_TARGET_TYPE_RESTORE 1) + endif() + endif() +endmacro() + +# restore the original value +# -- not necessary if __TestCompiler_setTryCompileTargetType() was used in function scope +macro(__TestCompiler_restoreTryCompileTargetType) + if(__CMAKE_TEST_COMPILER_TARGET_TYPE_RESTORE) + unset(CMAKE_TRY_COMPILE_TARGET_TYPE) + unset(__CMAKE_TEST_COMPILER_TARGET_TYPE_RESTORE) + endif() +endmacro() diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake index 8848bdd..d100704 100644 --- a/Modules/CTest.cmake +++ b/Modules/CTest.cmake @@ -28,10 +28,7 @@ To enable submissions to a CDash server, create a ``CTestConfig.cmake`` file at the top of the project with content such as:: set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") - set(CTEST_DROP_METHOD "http") - set(CTEST_DROP_SITE "my.cdash.org") - set(CTEST_DROP_LOCATION "/submit.php?project=MyProject") - set(CTEST_DROP_SITE_CDASH TRUE) + set(CTEST_SUBMIT_URL "http://my.cdash.org/submit.php?project=MyProject") (the CDash server can provide the file to a project administrator who configures ``MyProject``). Settings in the config file are shared by @@ -89,6 +86,7 @@ if(BUILD_TESTING) if(EXISTS "${PROJECT_SOURCE_DIR}/CTestConfig.cmake") include("${PROJECT_SOURCE_DIR}/CTestConfig.cmake") SET_IF_SET_AND_NOT_SET(NIGHTLY_START_TIME "${CTEST_NIGHTLY_START_TIME}") + SET_IF_SET_AND_NOT_SET(SUBMIT_URL "${CTEST_SUBMIT_URL}") SET_IF_SET_AND_NOT_SET(DROP_METHOD "${CTEST_DROP_METHOD}") SET_IF_SET_AND_NOT_SET(DROP_SITE "${CTEST_DROP_SITE}") SET_IF_SET_AND_NOT_SET(DROP_SITE_USER "${CTEST_DROP_SITE_USER}") @@ -111,6 +109,18 @@ if(BUILD_TESTING) endif() SET_IF_NOT_SET (NIGHTLY_START_TIME "00:00:00 EDT") + if(NOT SUBMIT_URL) + set(SUBMIT_URL "${DROP_METHOD}://") + if(DROP_SITE_USER) + string(APPEND SUBMIT_URL "${DROP_SITE_USER}") + if(DROP_SITE_PASSWORD) + string(APPEND SUBMIT_URL ":${DROP_SITE_PASSWORD}") + endif() + string(APPEND SUBMIT_URL "@") + endif() + string(APPEND SUBMIT_URL "${DROP_SITE}${DROP_SITE_LOCATION}") + endif() + find_program(CVSCOMMAND cvs ) set(CVS_UPDATE_OPTIONS "-d -A -P" CACHE STRING "Options passed to the cvs update command.") diff --git a/Modules/CheckFortranSourceCompiles.cmake b/Modules/CheckFortranSourceCompiles.cmake index b3e83dd..1820407 100644 --- a/Modules/CheckFortranSourceCompiles.cmake +++ b/Modules/CheckFortranSourceCompiles.cmake @@ -26,7 +26,8 @@ Check if given Fortran source compiles and links into an executable. if anything in the output matches any of the specified regular expressions. By default, the test source file will be given a ``.F`` file extension. The - ``SRC_EXT`` option can be used to override this with ``.<extension>`` instead. + ``SRC_EXT`` option can be used to override this with ``.<extension>`` instead-- + ``.F90`` is a typical choice. The underlying check is performed by the :command:`try_compile` command. The compile and link commands can be influenced by setting any of the following diff --git a/Modules/CheckFortranSourceRuns.cmake b/Modules/CheckFortranSourceRuns.cmake new file mode 100644 index 0000000..58d90d7 --- /dev/null +++ b/Modules/CheckFortranSourceRuns.cmake @@ -0,0 +1,158 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +CheckFortranSourceRuns +---------------------- + +Check if given Fortran source compiles and links into an executable and can +subsequently be run. + +.. command:: check_fortran_source_runs + + .. code-block:: cmake + + check_fortran_source_runs(<code> <resultVar> + [SRC_EXT <extension>]) + + Check that the source supplied in ``<code>`` can be compiled as a Fortran source + file, linked as an executable and then run. The ``<code>`` must contain at + least ``program; end program`` statements. If the ``<code>`` could be built and run + successfully, the internal cache variable specified by ``<resultVar>`` will + be set to 1, otherwise it will be set to an value that evaluates to boolean + false (e.g. an empty string or an error message). + + By default, the test source file will be given a ``.F90`` file extension. The + ``SRC_EXT`` option can be used to override this with ``.<extension>`` instead. + + The underlying check is performed by the :command:`try_run` command. The + compile and link commands can be influenced by setting any of the following + variables prior to calling ``check_fortran_source_runs()``: + + ``CMAKE_REQUIRED_FLAGS`` + Additional flags to pass to the compiler. Note that the contents of + :variable:`CMAKE_Fortran_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated + configuration-specific variable are automatically added to the compiler + command before the contents of ``CMAKE_REQUIRED_FLAGS``. + + ``CMAKE_REQUIRED_DEFINITIONS`` + A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form + ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by + ``<resultVar>`` will also be added automatically. + + ``CMAKE_REQUIRED_INCLUDES`` + A :ref:`;-list <CMake Language Lists>` of header search paths to pass to + the compiler. These will be the only header search paths used by + ``try_run()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES` + directory property will be ignored. + + ``CMAKE_REQUIRED_LINK_OPTIONS`` + A :ref:`;-list <CMake Language Lists>` of options to add to the link + command (see :command:`try_run` for further details). + + ``CMAKE_REQUIRED_LIBRARIES`` + A :ref:`;-list <CMake Language Lists>` of libraries to add to the link + command. These can be the name of system libraries or they can be + :ref:`Imported Targets <Imported Targets>` (see :command:`try_run` for + further details). + + ``CMAKE_REQUIRED_QUIET`` + If this variable evaluates to a boolean true value, all status messages + associated with the check will be suppressed. + + The check is only performed once, with the result cached in the variable + named by ``<resultVar>``. Every subsequent CMake run will re-use this cached + value rather than performing the check again, even if the ``<code>`` changes. + In order to force the check to be re-evaluated, the variable named by + ``<resultVar>`` must be manually removed from the cache. + +#]=======================================================================] + +include_guard(GLOBAL) + +macro(CHECK_Fortran_SOURCE_RUNS SOURCE VAR) + if(NOT DEFINED "${VAR}") + set(_SRC_EXT) + set(_key) + foreach(arg ${ARGN}) + if("${arg}" MATCHES "^(SRC_EXT)$") + set(_key "${arg}") + elseif(_key) + list(APPEND _${_key} "${arg}") + else() + message(FATAL_ERROR "Unknown argument:\n ${arg}\n") + endif() + endforeach() + if(NOT _SRC_EXT) + set(_SRC_EXT F90) + endif() + set(MACRO_CHECK_FUNCTION_DEFINITIONS + "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") + if(CMAKE_REQUIRED_LINK_OPTIONS) + set(CHECK_Fortran_SOURCE_COMPILES_ADD_LINK_OPTIONS + LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS}) + else() + set(CHECK_Fortran_SOURCE_COMPILES_ADD_LINK_OPTIONS) + endif() + if(CMAKE_REQUIRED_LIBRARIES) + set(CHECK_Fortran_SOURCE_COMPILES_ADD_LIBRARIES + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + else() + set(CHECK_Fortran_SOURCE_COMPILES_ADD_LIBRARIES) + endif() + if(CMAKE_REQUIRED_INCLUDES) + set(CHECK_Fortran_SOURCE_COMPILES_ADD_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + else() + set(CHECK_Fortran_SOURCE_COMPILES_ADD_INCLUDES) + endif() + file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT}" + "${SOURCE}\n") + + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VAR}") + endif() + try_run(${VAR}_EXITCODE ${VAR}_COMPILED + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT} + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_Fortran_SOURCE_COMPILES_ADD_LINK_OPTIONS} + ${CHECK_Fortran_SOURCE_COMPILES_ADD_LIBRARIES} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} + "${CHECK_Fortran_SOURCE_COMPILES_ADD_INCLUDES}" + COMPILE_OUTPUT_VARIABLE OUTPUT) + + # if it did not compile make the return value fail code of 1 + if(NOT ${VAR}_COMPILED) + set(${VAR}_EXITCODE 1) + endif() + # if the return value was 0 then it worked + if("${${VAR}_EXITCODE}" EQUAL 0) + set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VAR} - Success") + endif() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Performing Fortran SOURCE FILE Test ${VAR} succeeded with the following output:\n" + "${OUTPUT}\n" + "Return value: ${${VAR}}\n" + "Source file was:\n${SOURCE}\n") + else() + if(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN") + set(${VAR} "${${VAR}_EXITCODE}") + else() + set(${VAR} "" CACHE INTERNAL "Test ${VAR}") + endif() + + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VAR} - Failed") + endif() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Performing Fortran SOURCE FILE Test ${VAR} failed with the following output:\n" + "${OUTPUT}\n" + "Return value: ${${VAR}_EXITCODE}\n" + "Source file was:\n${SOURCE}\n") + endif() + endif() +endmacro() diff --git a/Modules/Compiler/GHS-C.cmake b/Modules/Compiler/GHS-C.cmake index c30bdec..a825b0b 100644 --- a/Modules/Compiler/GHS-C.cmake +++ b/Modules/Compiler/GHS-C.cmake @@ -8,23 +8,3 @@ string(APPEND CMAKE_C_FLAGS_DEBUG_INIT " -Odebug -g") string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -Ospace") string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -O") string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -O -g") - -set(CMAKE_C_GHS_KERNEL_FLAGS_DEBUG_INIT "-ldebug ${CMAKE_C_FLAGS_DEBUG_INIT}") -set(CMAKE_C_GHS_KERNEL_FLAGS_MINSIZEREL_INIT "${CMAKE_C_FLAGS_MINSIZEREL_INIT}") -set(CMAKE_C_GHS_KERNEL_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT}") -set(CMAKE_C_GHS_KERNEL_FLAGS_RELWITHDEBINFO_INIT - "-ldebug ${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}") - -if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) - set (CMAKE_C_GHS_KERNEL_FLAGS_DEBUG "${CMAKE_C_GHS_KERNEL_FLAGS_DEBUG_INIT}" - CACHE STRING "Kernel flags used by the compiler during debug builds.") - set (CMAKE_C_GHS_KERNEL_FLAGS_MINSIZEREL - "${CMAKE_C_GHS_KERNEL_FLAGS_MINSIZEREL_INIT}" CACHE STRING - "Kernel flags used by the compiler during release builds for minimum size.") - set (CMAKE_C_GHS_KERNEL_FLAGS_RELEASE - "${CMAKE_C_GHS_KERNEL_FLAGS_RELEASE_INIT}" - CACHE STRING "Kernel flags used by the compiler during release builds.") - set (CMAKE_C_GHS_KERNEL_FLAGS_RELWITHDEBINFO - "${CMAKE_C_GHS_KERNEL_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING - "Kernel flags used by the compiler during release builds with debug info.") -endif() diff --git a/Modules/Compiler/GHS-CXX.cmake b/Modules/Compiler/GHS-CXX.cmake index b3018a7..07b5044 100644 --- a/Modules/Compiler/GHS-CXX.cmake +++ b/Modules/Compiler/GHS-CXX.cmake @@ -8,27 +8,3 @@ string(APPEND CMAKE_CXX_FLAGS_DEBUG_INIT " -Odebug -g") string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -Ospace") string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -O") string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " -O -g") - -set(CMAKE_CXX_GHS_KERNEL_FLAGS_DEBUG_INIT - "-ldebug ${CMAKE_CXX_FLAGS_DEBUG_INIT}") -set(CMAKE_CXX_GHS_KERNEL_FLAGS_MINSIZEREL_INIT - "${CMAKE_CXX_FLAGS_MINSIZEREL_INIT}") -set(CMAKE_CXX_GHS_KERNEL_FLAGS_RELEASE_INIT - "${CMAKE_CXX_FLAGS_RELEASE_INIT}") -set(CMAKE_CXX_GHS_KERNEL_FLAGS_RELWITHDEBINFO_INIT - "-ldebug ${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT}") - -if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) - set (CMAKE_CXX_GHS_KERNEL_FLAGS_DEBUG - "${CMAKE_CXX_GHS_KERNEL_FLAGS_DEBUG_INIT}" - CACHE STRING "Kernel flags used by the compiler during debug builds.") - set (CMAKE_CXX_GHS_KERNEL_FLAGS_MINSIZEREL - "${CMAKE_CXX_GHS_KERNEL_FLAGS_MINSIZEREL_INIT}" CACHE STRING - "Kernel flags used by the compiler during release builds for minimum size.") - set (CMAKE_CXX_GHS_KERNEL_FLAGS_RELEASE - "${CMAKE_CXX_GHS_KERNEL_FLAGS_RELEASE_INIT}" - CACHE STRING "Kernel flags used by the compiler during release builds.") - set (CMAKE_CXX_GHS_KERNEL_FLAGS_RELWITHDEBINFO - "${CMAKE_CXX_GHS_KERNEL_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING - "Kernel flags used by the compiler during release builds with debug info.") -endif() diff --git a/Modules/Compiler/GHS-DetermineCompiler.cmake b/Modules/Compiler/GHS-DetermineCompiler.cmake index 56d24e2..368b375 100644 --- a/Modules/Compiler/GHS-DetermineCompiler.cmake +++ b/Modules/Compiler/GHS-DetermineCompiler.cmake @@ -1,6 +1,9 @@ -set(_compiler_id_pp_test "defined(__INTEGRITY)") +set(_compiler_id_pp_test "defined(__ghs__)") set(_compiler_id_version_compute " -# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__INTEGRITY_MAJOR_VERSION) -# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__INTEGRITY_MINOR_VERSION) -# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__INTEGRITY_PATCH_VERSION)") +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__GHS_VERSION_NUMBER / 100) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__GHS_VERSION_NUMBER / 10 % 10) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__GHS_VERSION_NUMBER % 10) +# endif") diff --git a/Modules/Compiler/GHS.cmake b/Modules/Compiler/GHS.cmake index e6a867d..b41c3eb 100644 --- a/Modules/Compiler/GHS.cmake +++ b/Modules/Compiler/GHS.cmake @@ -3,6 +3,6 @@ if(__COMPILER_GHS) endif() set(__COMPILER_GHS 1) -set(CMAKE_EXECUTABLE_SUFFIX ".as") -set(CMAKE_LIBRARY_PATH_TERMINATOR "\n") -set(CMAKE_LIBRARY_PATH_FLAG " -L") +set(CMAKE_EXECUTABLE_SUFFIX "") +set(CMAKE_LIBRARY_PATH_TERMINATOR "") +set(CMAKE_LIBRARY_PATH_FLAG "") diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake index 2ed8818..b5e61f0 100644 --- a/Modules/Compiler/IAR-C.cmake +++ b/Modules/Compiler/IAR-C.cmake @@ -29,7 +29,19 @@ if("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM") __compiler_check_default_language_standard(C 1.10 90 6.10 99 8.10 11) elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR") + if(NOT CMAKE_C_COMPILER_VERSION) + message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION not detected. This should be automatic.") + endif() + + set(CMAKE_C_EXTENSION_COMPILE_OPTION -e) + + set(CMAKE_C90_STANDARD_COMPILE_OPTION --c89) + set(CMAKE_C90_EXTENSION_COMPILE_OPTION -e) + set(CMAKE_C99_STANDARD_COMPILE_OPTION "") + set(CMAKE_C99_EXTENSION_COMPILE_OPTION -e) + __compiler_iar_AVR(C) + __compiler_check_default_language_standard(C 7.10 99) set(CMAKE_C_OUTPUT_EXTENSION ".r90") if(NOT CMAKE_C_LINK_FLAGS) @@ -43,6 +55,7 @@ elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR") get_filename_component(_compilerDir "${CMAKE_C_COMPILER}" PATH) get_filename_component(_compilerDir "${_compilerDir}" PATH) include_directories("${_compilerDir}/inc" ) + include_directories("${_compilerDir}/inc/Atmel" ) else() message(FATAL_ERROR "CMAKE_C_COMPILER_ARCHITECTURE_ID not detected as \"AVR\" or \"ARM\". This should be automatic.") diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake index 5b783b2..b7076f5 100644 --- a/Modules/Compiler/IAR-CXX.cmake +++ b/Modules/Compiler/IAR-CXX.cmake @@ -38,7 +38,27 @@ if("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM") __compiler_check_default_language_standard(CXX 6.10 98 8.10 14) elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR") + # "embedded C++" --EC++ is probably closest to CXX98 but with no support for: + # Templates, multiple inheritance, virtual inheritance, exceptions, RTTI, C++ style casts, + # Namespaces, the mutable attribute, no STL, any library features related to the above features. + # + # "(extended) embedded C++" --EEC++ Mode but DOES NOT support any normal C++ standard + # probably closest to CXX98 but with no RTTI and no exceptions, and the library + # provided is not in the standard namespace + if(NOT CMAKE_IAR_CXX_FLAG) + if(NOT CMAKE_CXX_COMPILER_VERSION) + message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION not detected. This should be automatic.") + endif() + set(CMAKE_IAR_CXX_FLAG --eec++) + endif() + + set(CMAKE_CXX_EXTENSION_COMPILE_OPTION -e) + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION -e) + __compiler_iar_AVR(CXX) + __compiler_check_default_language_standard(CXX 7.10 98) + set(CMAKE_CXX_OUTPUT_EXTENSION ".r90") if(NOT CMAKE_CXX_LINK_FLAGS) set(CMAKE_CXX_LINK_FLAGS "-Fmotorola") @@ -51,6 +71,7 @@ elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR") get_filename_component(_compilerDir "${CMAKE_C_COMPILER}" PATH) get_filename_component(_compilerDir "${_compilerDir}" PATH) include_directories("${_compilerDir}/inc") + include_directories("${_compilerDir}/inc/Atmel") else() message(FATAL_ERROR "CMAKE_CXX_COMPILER_ARCHITECTURE_ID not detected as \"AVR\" or \"ARM\". This should be automatic." ) diff --git a/Modules/Compiler/IAR-DetermineCompiler.cmake b/Modules/Compiler/IAR-DetermineCompiler.cmake index a1bffeb..43477ac 100644 --- a/Modules/Compiler/IAR-DetermineCompiler.cmake +++ b/Modules/Compiler/IAR-DetermineCompiler.cmake @@ -1,4 +1,4 @@ -# IAR Systems compiler for embedded systems. +# IAR Systems compiler for ARM embedded systems. # http://www.iar.com # http://supp.iar.com/FilesPublic/UPDINFO/004916/arm/doc/EWARM_DevelopmentGuide.ENU.pdf # @@ -9,13 +9,31 @@ # __ICCARM__ An integer that is set to 1 when the code is compiled with the IAR C/C++ Compiler for ARM # __VER__ An integer that identifies the version number of the IAR compiler in use. For example, # version 5.11.3 is returned as 5011003. +# +# IAR Systems Compiler for AVR embedded systems +# http://supp.iar.com/FilesPublic/UPDINFO/007051/ew/doc/EWAVR_CompilerReference.pdf +# +# __IAR_SYSTEMS_ICC__ An integer that identifies the IAR compiler platform. +# __ICCAVR__ An integer that is set to 1 when the code is compiled with the IAR C/C++ Compiler for AVR +# __VER__ An integer that identifies the version number of the IAR compiler in use. +# The value is calculated by (100 * VERSION_MAJOR + VERSION_MINOR). For example the version +# 3.34 is given as 334 +# __SUBVERSION__ An integer that identifies the subversion number of the compiler version number +# for example 3 in 1.2.3.4. THis is used as the patch version, as seen when running iccavr +# from the command line +# set(_compiler_id_pp_test "defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)") set(_compiler_id_version_compute " -# if defined(__VER__) +# if defined(__VER__) && defined(__ICCARM__) # define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@((__VER__) / 1000000) # define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(((__VER__) / 1000) % 1000) # define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@((__VER__) % 1000) # define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && defined(__ICCAVR__) +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@((__VER__) / 100) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@((__VER__) - (((__VER__) / 100)*100)) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__SUBVERSION__) +# define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__IAR_SYSTEMS_ICC__) # endif") diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake index 43243b9..bbcdea2 100644 --- a/Modules/Compiler/IAR.cmake +++ b/Modules/Compiler/IAR.cmake @@ -68,6 +68,27 @@ endmacro() macro(__compiler_iar_AVR lang) set(CMAKE_EXECUTABLE_SUFFIX ".bin") + if (${lang} STREQUAL "C" OR ${lang} STREQUAL "CXX") + + set(CMAKE_${lang}_COMPILE_OBJECT "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") + set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> --preprocess=cnl <PREPROCESSED_SOURCE>") + set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -lAH <ASSEMBLY_SOURCE> -o <OBJECT>.dummy") + + set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-f ") + set(CMAKE_DEPFILE_FLAGS_${lang} "--dependencies=ns <DEPFILE>") + + string(APPEND CMAKE_${lang}_FLAGS_INIT " ") + string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -r") + string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Ohz -DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -Oh -DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -Oh -r -DNDEBUG") + endif() + + set(CMAKE_${lang}_LINK_EXECUTABLE "\"${CMAKE_IAR_LINKER}\" -S <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "\"${CMAKE_IAR_AR}\" <TARGET> <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_CREATE "\"${CMAKE_IAR_AR}\" <TARGET> <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_APPEND "") + set(CMAKE_${lang}_ARCHIVE_FINISH "") set(CMAKE_LIBRARY_PATH_FLAG "-I") diff --git a/Modules/CompilerId/GHS_default.gpj.in b/Modules/CompilerId/GHS_default.gpj.in new file mode 100644 index 0000000..b5cea5c --- /dev/null +++ b/Modules/CompilerId/GHS_default.gpj.in @@ -0,0 +1,8 @@ +#!gbuild +@bsp_name@ +@os_dir@ +primaryTarget=@ghs_primary_target@ +[Project] + {isdefined(GHS_BSP)} -bsp $GHS_BSP + {isdefined(GHS_OS)} -os_dir $GHS_OS +GHS_lib.gpj [Library] diff --git a/Modules/CompilerId/GHS_lib.gpj.in b/Modules/CompilerId/GHS_lib.gpj.in new file mode 100644 index 0000000..149b981 --- /dev/null +++ b/Modules/CompilerId/GHS_lib.gpj.in @@ -0,0 +1,3 @@ +#!gbuild +[Library] +@id_src@ diff --git a/Modules/DartConfiguration.tcl.in b/Modules/DartConfiguration.tcl.in index 24e7b55..e4513b3 100644 --- a/Modules/DartConfiguration.tcl.in +++ b/Modules/DartConfiguration.tcl.in @@ -20,12 +20,7 @@ BuildName: @BUILDNAME@ LabelsForSubprojects: @CTEST_LABELS_FOR_SUBPROJECTS@ # Submission information -DropSite: @DROP_SITE@ -DropLocation: @DROP_LOCATION@ -DropSiteUser: @DROP_SITE_USER@ -DropSitePassword: @DROP_SITE_PASSWORD@ -DropSiteMode: @DROP_SITE_MODE@ -DropMethod: @DROP_METHOD@ +SubmitURL: @SUBMIT_URL@ # Dashboard start time NightlyStartTime: @NIGHTLY_START_TIME@ diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index e763bab..c5d6b45 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -425,7 +425,9 @@ External Project Definition can be used to point to an alternative directory within the source tree to use as the top of the CMake source tree instead. This must be a relative path and it will be interpreted as being relative to - ``SOURCE_DIR``. + ``SOURCE_DIR``. When ``BUILD_IN_SOURCE 1`` is specified, the + ``BUILD_COMMAND`` is used to point to an alternative directory within the + source tree. **Build Step Options:** If the configure step assumed the external project uses CMake as its build @@ -1676,7 +1678,11 @@ function(_ep_set_directories name) endif() if(build_in_source) get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR) - set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}") + if(source_subdir) + set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}/${source_subdir}") + else() + set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}") + endif() endif() # Make the directories at CMake configure time *and* add a custom command diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 98cdf6c..c65ae9e 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -691,6 +691,13 @@ function(__FetchContent_directPopulate contentName) BUILD_COMMAND INSTALL_COMMAND TEST_COMMAND + # We force both of these to be ON since we are always executing serially + # and we want all steps to have access to the terminal in case they + # need input from the command line (e.g. ask for a private key password) + # or they want to provide timely progress. We silently absorb and + # discard these if they are set by the caller. + USES_TERMINAL_DOWNLOAD + USES_TERMINAL_UPDATE ) set(multiValueArgs "") diff --git a/Modules/FetchContent/CMakeLists.cmake.in b/Modules/FetchContent/CMakeLists.cmake.in index 9a7a771..0095b11 100644 --- a/Modules/FetchContent/CMakeLists.cmake.in +++ b/Modules/FetchContent/CMakeLists.cmake.in @@ -18,4 +18,6 @@ ExternalProject_Add(${contentName}-populate BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" + USES_TERMINAL_DOWNLOAD YES + USES_TERMINAL_UPDATE YES ) diff --git a/Modules/FindCURL.cmake b/Modules/FindCURL.cmake index d28dfea..b1989b1 100644 --- a/Modules/FindCURL.cmake +++ b/Modules/FindCURL.cmake @@ -110,12 +110,12 @@ if(CURL_FIND_COMPONENTS) OUTPUT_VARIABLE CURL_CONFIG_FEATURES_STRING ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE "\n" ";" CURL_CONFIG_FEATURES "${CURL_CONFIG_FEATURES_STRING}") + string(REPLACE "\n" ";" CURL_SUPPORTED_FEATURES "${CURL_CONFIG_FEATURES_STRING}") execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --protocols OUTPUT_VARIABLE CURL_CONFIG_PROTOCOLS_STRING ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE "\n" ";" CURL_CONFIG_PROTOCOLS "${CURL_CONFIG_PROTOCOLS_STRING}") + string(REPLACE "\n" ";" CURL_SUPPORTED_PROTOCOLS "${CURL_CONFIG_PROTOCOLS_STRING}") endif() endif() diff --git a/Modules/Platform/GHS-MULTI-Initialize.cmake b/Modules/Platform/GHS-MULTI-Initialize.cmake index 9b384df..25004c6 100644 --- a/Modules/Platform/GHS-MULTI-Initialize.cmake +++ b/Modules/Platform/GHS-MULTI-Initialize.cmake @@ -9,6 +9,9 @@ mark_as_advanced(GHS_OS_ROOT) set(GHS_OS_DIR "NOTFOUND" CACHE PATH "GHS platform OS directory") mark_as_advanced(GHS_OS_DIR) +set(GHS_OS_DIR_OPTION "-os_dir " CACHE STRING "GHS compiler os option") +mark_as_advanced(GHS_OS_DIR) + #set GHS_OS_DIR if not set by user if ( NOT GHS_OS_DIR ) if (EXISTS ${GHS_OS_ROOT}) @@ -23,8 +26,11 @@ if ( NOT GHS_OS_DIR ) endif () #filter based on platform name - if (GHS_TARGET_PLATFORM STREQUAL "integrity") + if (GHS_TARGET_PLATFORM MATCHES "integrity") list(FILTER GHS_CANDIDATE_OS_DIRS INCLUDE REGEX "int[0-9][0-9][0-9][0-9a-z].*") + else() #fall-back for standalone + unset(GHS_CANDIDATE_OS_DIRS) + set(GHS_OS_DIR "IGNORE") endif () if (GHS_CANDIDATE_OS_DIRS) diff --git a/Modules/Platform/IRIX.cmake b/Modules/Platform/IRIX.cmake deleted file mode 100644 index 12b0f37..0000000 --- a/Modules/Platform/IRIX.cmake +++ /dev/null @@ -1,53 +0,0 @@ -set(CMAKE_DL_LIBS "") -set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared -rdata_shared") -set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,") # -rpath -set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP "") # : or empty -if(NOT CMAKE_COMPILER_IS_GNUCXX) - set(CMAKE_CXX_CREATE_STATIC_LIBRARY - "<CMAKE_CXX_COMPILER> -ar -o <TARGET> <OBJECTS>") - set (CMAKE_CXX_FLAGS_INIT "") - set (CMAKE_CXX_FLAGS_DEBUG_INIT "-g") - set (CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-O3 -DNDEBUG") - set (CMAKE_CXX_FLAGS_RELEASE_INIT "-O2 -DNDEBUG") - set (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2") - set (CMAKE_C_FLAGS_INIT "") -endif() -# set flags for gcc support -include(Platform/UnixPaths) - -if(NOT CMAKE_COMPILER_IS_GNUCC) - set (CMAKE_C_CREATE_PREPROCESSED_SOURCE "<CMAKE_C_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") - set (CMAKE_C_CREATE_ASSEMBLY_SOURCE - "<CMAKE_C_COMPILER> <FLAGS> -S <SOURCE>" - "mv `basename \"<SOURCE>\" | sed 's/\\.[^./]*$$//'`.s <ASSEMBLY_SOURCE>" - ) -endif() - -if(NOT CMAKE_COMPILER_IS_GNUCXX) - set (CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") - set (CMAKE_CXX_CREATE_ASSEMBLY_SOURCE - "<CMAKE_CXX_COMPILER> <FLAGS> -S <SOURCE>" - "mv `basename \"<SOURCE>\" | sed 's/\\.[^./]*$$//'`.s <ASSEMBLY_SOURCE>" - ) -endif() - -if(NOT CMAKE_COMPILER_IS_GNUG77) - set (CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE "<CMAKE_Fortran_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") - set (CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE - "<CMAKE_Fortran_COMPILER> <FLAGS> -S <SOURCE>" - "mv `basename \"<SOURCE>\" | sed 's/\\.[^./]*$$//'`.s <ASSEMBLY_SOURCE>" - ) -endif() - -# Initialize C link type selection flags. These flags are used when -# building a shared library, shared module, or executable that links -# to other libraries to select whether to use the static or shared -# versions of the libraries. -foreach(type SHARED_LIBRARY SHARED_MODULE EXE) - set(CMAKE_${type}_LINK_STATIC_C_FLAGS "-Wl,-Bstatic") - set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic") -endforeach() - -# The IRIX linker needs to find transitive shared library dependencies -# in the -L path. -set(CMAKE_LINK_DEPENDENT_LIBRARY_DIRS 1) diff --git a/Modules/Platform/IRIX64.cmake b/Modules/Platform/IRIX64.cmake deleted file mode 100644 index ee9b96e..0000000 --- a/Modules/Platform/IRIX64.cmake +++ /dev/null @@ -1,73 +0,0 @@ -set(CMAKE_DL_LIBS "") -set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared -rdata_shared") -set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,") # -rpath -set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP "") # : or empty -set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,") -if(NOT CMAKE_COMPILER_IS_GNUCC) - # Set default flags init. - set(CMAKE_C_FLAGS_INIT "") - set(CMAKE_CXX_FLAGS_INIT "") - set(CMAKE_Fortran_FLAGS_INIT "") - set(CMAKE_EXE_LINKER_FLAGS_INIT "") - set(CMAKE_SHARED_LINKER_FLAGS_INIT "") - set(CMAKE_MODULE_LINKER_FLAGS_INIT "") - - # If no -o32, -n32, or -64 flag is given, set a reasonable default. - if("$ENV{CFLAGS} $ENV{CXXFLAGS} $ENV{LDFLAGS}" MATCHES "-([no]32|64)") - else() - # Check if this is a 64-bit CMake. - if(CMAKE_FILE_SELF MATCHES "^CMAKE_FILE_SELF$") - exec_program(file ARGS ${CMAKE_COMMAND} OUTPUT_VARIABLE CMAKE_FILE_SELF) - set(CMAKE_FILE_SELF "${CMAKE_FILE_SELF}" CACHE INTERNAL - "Output of file command on ${CMAKE_COMMAND}.") - endif() - - # Set initial flags to match cmake executable. - if(CMAKE_FILE_SELF MATCHES " 64-bit ") - set(CMAKE_C_FLAGS_INIT "-64") - set(CMAKE_CXX_FLAGS_INIT "-64") - set(CMAKE_Fortran_FLAGS_INIT "-64") - set(CMAKE_EXE_LINKER_FLAGS_INIT "-64") - set(CMAKE_SHARED_LINKER_FLAGS_INIT "-64") - set(CMAKE_MODULE_LINKER_FLAGS_INIT "-64") - endif() - endif() - - # Set remaining defaults. - set(CMAKE_CXX_CREATE_STATIC_LIBRARY - "<CMAKE_CXX_COMPILER> -ar -o <TARGET> <OBJECTS>") - set (CMAKE_CXX_FLAGS_DEBUG_INIT "-g") - set (CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-O3 -DNDEBUG") - set (CMAKE_CXX_FLAGS_RELEASE_INIT "-O2 -DNDEBUG") - set (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2") -endif() -include(Platform/UnixPaths) - -if(NOT CMAKE_COMPILER_IS_GNUCC) - set (CMAKE_C_CREATE_PREPROCESSED_SOURCE "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") - set (CMAKE_C_CREATE_ASSEMBLY_SOURCE - "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE>" - "mv `basename \"<SOURCE>\" | sed 's/\\.[^./]*$$//'`.s <ASSEMBLY_SOURCE>" - ) -endif() - -if(NOT CMAKE_COMPILER_IS_GNUCXX) - set (CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") - set (CMAKE_CXX_CREATE_ASSEMBLY_SOURCE - "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE>" - "mv `basename \"<SOURCE>\" | sed 's/\\.[^./]*$$//'`.s <ASSEMBLY_SOURCE>" - ) -endif() - -# Initialize C link type selection flags. These flags are used when -# building a shared library, shared module, or executable that links -# to other libraries to select whether to use the static or shared -# versions of the libraries. -foreach(type SHARED_LIBRARY SHARED_MODULE EXE) - set(CMAKE_${type}_LINK_STATIC_C_FLAGS "-Wl,-Bstatic") - set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic") -endforeach() - -# The IRIX linker needs to find transitive shared library dependencies -# in the -L path. -set(CMAKE_LINK_DEPENDENT_LIBRARY_DIRS 1) diff --git a/Modules/ProcessorCount.cmake b/Modules/ProcessorCount.cmake index 05f56d8..e4b4e53 100644 --- a/Modules/ProcessorCount.cmake +++ b/Modules/ProcessorCount.cmake @@ -12,7 +12,7 @@ Determine the number of processors/cores and save value in ${var} Sets the variable named ${var} to the number of physical cores available on the machine if the information can be determined. Otherwise it is set to 0. Currently this functionality is implemented -for AIX, cygwin, FreeBSD, HPUX, IRIX, Linux, macOS, QNX, Sun and +for AIX, cygwin, FreeBSD, HPUX, Linux, macOS, QNX, Sun and Windows. This function is guaranteed to return a positive integer (>=1) if it @@ -115,22 +115,6 @@ function(ProcessorCount var) endif() if(NOT count) - # IRIX (systems with hinv): - find_program(ProcessorCount_cmd_hinv hinv - PATHS /sbin) - mark_as_advanced(ProcessorCount_cmd_hinv) - if(ProcessorCount_cmd_hinv) - execute_process(COMMAND ${ProcessorCount_cmd_hinv} - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE hinv_output) - string(REGEX MATCHALL "([0-9]+) .* Processors" procs "${hinv_output}") - set(count "${CMAKE_MATCH_1}") - #message("ProcessorCount: trying hinv '${ProcessorCount_cmd_hinv}'") - endif() - endif() - - if(NOT count) # AIX (systems with lsconf): find_program(ProcessorCount_cmd_lsconf lsconf PATHS /usr/sbin) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 91c45bc..9e753e6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -298,6 +298,7 @@ set(SRCS cmMakefileExecutableTargetGenerator.cxx cmMakefileLibraryTargetGenerator.cxx cmMakefileUtilityTargetGenerator.cxx + cmMessageType.h cmMessenger.cxx cmMessenger.h cmMSVC60LinkLineComputer.cxx @@ -696,10 +697,10 @@ if (WIN32) cmGlobalVisualStudio12Generator.cxx cmGlobalVisualStudio14Generator.h cmGlobalVisualStudio14Generator.cxx - cmGlobalVisualStudio15Generator.h - cmGlobalVisualStudio15Generator.cxx cmGlobalVisualStudioGenerator.cxx cmGlobalVisualStudioGenerator.h + cmGlobalVisualStudioVersionedGenerator.h + cmGlobalVisualStudioVersionedGenerator.cxx cmIDEFlagTable.h cmIDEOptions.cxx cmIDEOptions.h diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2c83140..497feed 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 13) -set(CMake_VERSION_PATCH 20190111) +set(CMake_VERSION_PATCH 20190122) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx index d3de02b..4966d09 100644 --- a/Source/CPack/OSXScriptLauncher.cxx +++ b/Source/CPack/OSXScriptLauncher.cxx @@ -46,8 +46,7 @@ int main(int argc, char* argv[]) // get the file system path of the url as a cstring // in an encoding suitable for posix apis - if (CFURLGetFileSystemRepresentation(scriptFileURL, true, path, PATH_MAX) == - false) { + if (!CFURLGetFileSystemRepresentation(scriptFileURL, true, path, PATH_MAX)) { DebugError("CFURLGetFileSystemRepresentation failed"); return 1; } diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index ee1070f..1756218 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -10,6 +10,7 @@ #include "cmWorkingDirectory.h" #include <cstring> +#include <map> #include <ostream> #include <utility> #include <vector> @@ -111,13 +112,15 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( return 0; \ } \ cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat); \ - if (!(archive)) { \ - cmCPackLogger(cmCPackLog::LOG_ERROR, \ - "Problem to create archive <" \ - << (filename) << ">, ERROR = " << (archive).GetError() \ - << std::endl); \ - return 0; \ - } + do { \ + if (!(archive)) { \ + cmCPackLogger(cmCPackLog::LOG_ERROR, \ + "Problem to create archive <" \ + << (filename) << ">, ERROR = " << (archive).GetError() \ + << std::endl); \ + return 0; \ + } \ + } while (false) int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup) { diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 326d26c..be4a18e 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -71,8 +71,8 @@ int cmCPackDragNDropGenerator::InitializeInternal() // Starting with Xcode 4.3, look in "/Applications/Xcode.app" first: // std::vector<std::string> paths; - paths.push_back("/Applications/Xcode.app/Contents/Developer/Tools"); - paths.push_back("/Developer/Tools"); + paths.emplace_back("/Applications/Xcode.app/Contents/Developer/Tools"); + paths.emplace_back("/Developer/Tools"); const std::string hdiutil_path = cmSystemTools::FindProgram("hdiutil", std::vector<std::string>(), false); diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index 9f7b236..9dc9853 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -13,6 +13,7 @@ #include "cmsys/FStream.hxx" +#include <map> #include <utility> #include <vector> @@ -67,7 +68,7 @@ int cmCPackExternalGenerator::PackageFiles() return 0; } - int res = this->MakefileMap->ReadListFile(packageScript); + bool res = this->MakefileMap->ReadListFile(packageScript); if (cmSystemTools::GetErrorOccuredFlag() || !res) { return 0; diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index 2fcd1a8..1e6b118 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -257,13 +257,8 @@ void cmCPackFreeBSDGenerator::write_manifest_fields( static bool ignore_file(const std::string& filename) { struct stat statbuf; - - if (!((stat(filename.c_str(), &statbuf) >= 0) && - ((statbuf.st_mode & S_IFMT) == S_IFREG))) { - return true; - } - // May be other reasons to return false - return false; + return stat(filename.c_str(), &statbuf) < 0 || + (statbuf.st_mode & S_IFMT) != S_IFREG; } // Write the given list of @p files to the manifest stream @p s, diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index acd6650..4728f69 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -18,6 +18,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmVersion.h" #include "cmWorkingDirectory.h" @@ -497,7 +498,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript( tempInstallDirectory.c_str()); this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR", tempInstallDirectory.c_str()); - int res = this->MakefileMap->ReadListFile(installScript.c_str()); + bool res = this->MakefileMap->ReadListFile(installScript); if (cmSystemTools::GetErrorOccuredFlag() || !res) { return 0; } @@ -690,7 +691,7 @@ int cmCPackGenerator::InstallCMakeProject( "- Install component: " << component << std::endl); } - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::CPack); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -850,7 +851,7 @@ int cmCPackGenerator::InstallCMakeProject( mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); } // do installation - int res = mf.ReadListFile(installFile.c_str()); + bool res = mf.ReadListFile(installFile); // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES // to CPack (may be used by generators like CPack RPM or DEB) // in order to transparently handle ABSOLUTE PATH @@ -926,7 +927,7 @@ bool cmCPackGenerator::ReadListFile(const char* moduleName) { bool retval; std::string fullPath = this->MakefileMap->GetModulesFile(moduleName); - retval = this->MakefileMap->ReadListFile(fullPath.c_str()); + retval = this->MakefileMap->ReadListFile(fullPath); // include FATAL_ERROR and ERROR in the return status retval = retval && (!cmSystemTools::GetErrorOccuredFlag()); return retval; @@ -1035,7 +1036,8 @@ int cmCPackGenerator::DoPackage() * may update this during PackageFiles. * (either putting several names or updating the provided one) */ - packageFileNames.push_back(tempPackageFileName ? tempPackageFileName : ""); + packageFileNames.emplace_back(tempPackageFileName ? tempPackageFileName + : ""); toplevel = tempDirectory; { // scope that enables package generators to run internal scripts with // latest CMake policies enabled diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index d02aa5a..4b865ca 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -610,7 +610,7 @@ bool cmCPackNSISGenerator::GetListOfSubdirectories( } } } - dirs.push_back(topdir); + dirs.emplace_back(topdir); return true; } diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index a24dd30..28e0561 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -340,16 +340,16 @@ int cmCPackPackageMakerGenerator::InitializeInternal() // If found, save result in the CPACK_INSTALLER_PROGRAM variable. std::vector<std::string> paths; - paths.push_back("/Applications/Xcode.app/Contents/Applications" - "/PackageMaker.app/Contents/MacOS"); - paths.push_back("/Applications/Utilities" - "/PackageMaker.app/Contents/MacOS"); - paths.push_back("/Applications" - "/PackageMaker.app/Contents/MacOS"); - paths.push_back("/Developer/Applications/Utilities" - "/PackageMaker.app/Contents/MacOS"); - paths.push_back("/Developer/Applications" - "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Applications/Xcode.app/Contents/Applications" + "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Applications/Utilities" + "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Applications" + "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Developer/Applications/Utilities" + "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Developer/Applications" + "/PackageMaker.app/Contents/MacOS"); std::string pkgPath; const char* inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM"); diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index ef0d118..e55ea87 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -6,6 +6,7 @@ #include <sstream> #include <stdio.h> #include <string> +#include <vector> #include "cmCPackGenerator.h" #include "cmCPackLog.h" diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 4e49727..d4c867b 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -24,6 +24,7 @@ #include "cmDocumentationFormatter.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmake.h" @@ -208,7 +209,7 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Read CPack config file: " << cpackConfigFile << std::endl); - cmake cminst(cmake::RoleScript); + cmake cminst(cmake::RoleScript, cmState::CPack); cminst.SetHomeDirectory(""); cminst.SetHomeOutputDirectory(""); cminst.SetProgressCallback(cpackProgressCallback, nullptr); @@ -255,7 +256,7 @@ int main(int argc, char const* const* argv) // paths, so FIND_XXX() commands can be used in scripts std::string systemFile = globalMF.GetModulesFile("CMakeDetermineSystem.cmake"); - if (!globalMF.ReadListFile(systemFile.c_str())) { + if (!globalMF.ReadListFile(systemFile)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Error reading CMakeDetermineSystem.cmake" << std::endl); return 1; @@ -263,7 +264,7 @@ int main(int argc, char const* const* argv) systemFile = globalMF.GetModulesFile("CMakeSystemSpecificInformation.cmake"); - if (!globalMF.ReadListFile(systemFile.c_str())) { + if (!globalMF.ReadListFile(systemFile)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Error reading CMakeSystemSpecificInformation.cmake" << std::endl); @@ -279,7 +280,7 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Read CPack configuration file: " << cpackConfigFile << std::endl); - if (!globalMF.ReadListFile(cpackConfigFile.c_str())) { + if (!globalMF.ReadListFile(cpackConfigFile)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Problem reading CPack config file: \"" << cpackConfigFile << "\"" << std::endl); diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 668a387..312d126 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -6,6 +6,7 @@ #include "cmCTestTestHandler.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmake.h" @@ -163,7 +164,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) return 1; } - cmake cm(cmake::RoleProject); + cmake cm(cmake::RoleProject, cmState::Project); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); std::string cmakeOutString; @@ -231,7 +232,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) // do the build if (this->BuildTargets.empty()) { - this->BuildTargets.push_back(""); + this->BuildTargets.emplace_back(); } for (std::string const& tar : this->BuildTargets) { cmDuration remainingTime = std::chrono::seconds(0); diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 65b4976..32f7496 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -7,6 +7,7 @@ #include "cmCTestGenericHandler.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmake.h" @@ -95,7 +96,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() std::string e = "could not create generator named \""; e += cmakeGeneratorName; e += "\""; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); cmSystemTools::SetFatalErrorOccured(); return nullptr; } diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 539a0ce..d07bd21 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -341,30 +341,34 @@ int cmCTestBuildHandler::ProcessHandler() // warnings and warning exceptions. std::vector<std::string>::size_type cc; for (cc = 0; cmCTestErrorMatches[cc]; cc++) { - this->CustomErrorMatches.push_back(cmCTestErrorMatches[cc]); + this->CustomErrorMatches.emplace_back(cmCTestErrorMatches[cc]); } for (cc = 0; cmCTestErrorExceptions[cc]; cc++) { - this->CustomErrorExceptions.push_back(cmCTestErrorExceptions[cc]); + this->CustomErrorExceptions.emplace_back(cmCTestErrorExceptions[cc]); } for (cc = 0; cmCTestWarningMatches[cc]; cc++) { - this->CustomWarningMatches.push_back(cmCTestWarningMatches[cc]); + this->CustomWarningMatches.emplace_back(cmCTestWarningMatches[cc]); } for (cc = 0; cmCTestWarningExceptions[cc]; cc++) { - this->CustomWarningExceptions.push_back(cmCTestWarningExceptions[cc]); + this->CustomWarningExceptions.emplace_back(cmCTestWarningExceptions[cc]); } // Pre-compile regular expressions objects for all regular expressions #define cmCTestBuildHandlerPopulateRegexVector(strings, regexes) \ - regexes.clear(); \ - cmCTestOptionalLog(this->CTest, DEBUG, \ - this << "Add " #regexes << std::endl, this->Quiet); \ - for (std::string const& s : (strings)) { \ + do { \ + regexes.clear(); \ cmCTestOptionalLog(this->CTest, DEBUG, \ - "Add " #strings ": " << s << std::endl, this->Quiet); \ - (regexes).push_back(s.c_str()); \ - } + this << "Add " #regexes << std::endl, this->Quiet); \ + for (std::string const& s : (strings)) { \ + cmCTestOptionalLog(this->CTest, DEBUG, \ + "Add " #strings ": " << s << std::endl, \ + this->Quiet); \ + (regexes).emplace_back(s); \ + } \ + } while (false) + cmCTestBuildHandlerPopulateRegexVector(this->CustomErrorMatches, this->ErrorMatchRegex); cmCTestBuildHandlerPopulateRegexVector(this->CustomErrorExceptions, @@ -1030,7 +1034,7 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length, } } else { // Otherwise store pre-context for the next error - this->PreContext.push_back(line); + this->PreContext.emplace_back(line); if (this->PreContext.size() > this->MaxPreContext) { this->PreContext.erase(this->PreContext.begin(), this->PreContext.end() - diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 1d9a5f7..6c68f46 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -56,13 +56,12 @@ public: void SetCommand(const char* command) { this->CommandLineStrings.clear(); - this->CommandLineStrings.push_back(command); - ; + this->CommandLineStrings.emplace_back(command); } void AddArgument(const char* arg) { if (arg) { - this->CommandLineStrings.push_back(arg); + this->CommandLineStrings.emplace_back(arg); } } void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; } @@ -317,8 +316,7 @@ int cmCTestCoverageHandler::ProcessHandler() // setup the regex exclude stuff this->CustomCoverageExcludeRegex.clear(); for (std::string const& rex : this->CustomCoverageExclude) { - this->CustomCoverageExcludeRegex.push_back( - cmsys::RegularExpression(rex.c_str())); + this->CustomCoverageExcludeRegex.emplace_back(rex); } if (this->HandleBullseyeCoverage(&cont)) { @@ -1006,7 +1004,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( std::vector<std::string> basecovargs = cmSystemTools::ParseArguments(gcovExtraFlags.c_str()); basecovargs.insert(basecovargs.begin(), gcovCommand); - basecovargs.push_back("-o"); + basecovargs.emplace_back("-o"); // files is a list of *.da and *.gcda files with coverage data in them. // These are binary files that you give as input to gcov so that it will diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index c63694d..57a14ef 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -5,9 +5,9 @@ #include "cmCTest.h" #include "cmCTestGenericHandler.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" -#include "cmake.h" #include <cstring> #include <sstream> @@ -289,7 +289,7 @@ bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg) if (this->Values[k]) { std::ostringstream e; e << "Called with more than one value for " << this->Arguments[k]; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); this->ArgumentDoing = ArgumentDoingError; return true; } diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 6cd1c09..ec3307f 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -15,6 +15,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmProcessOutput.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -145,7 +146,7 @@ void cmCTestLaunch::HandleRealArg(const char* arg) return; } #endif - this->RealArgs.push_back(arg); + this->RealArgs.emplace_back(arg); } void cmCTestLaunch::ComputeFileNames() @@ -533,9 +534,9 @@ void cmCTestLaunch::LoadScrapeRules() // Common compiler warning formats. These are much simpler than the // full log-scraping expressions because we do not need to extract // file and line information. - this->RegexWarning.push_back("(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]"); - this->RegexWarning.push_back("(^|[ :])[Rr][Ee][Mm][Aa][Rr][Kk]"); - this->RegexWarning.push_back("(^|[ :])[Nn][Oo][Tt][Ee]"); + this->RegexWarning.emplace_back("(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]"); + this->RegexWarning.emplace_back("(^|[ :])[Rr][Ee][Mm][Aa][Rr][Kk]"); + this->RegexWarning.emplace_back("(^|[ :])[Nn][Oo][Tt][Ee]"); // Load custom match rules given to us by CTest. this->LoadScrapeRules("Warning", this->RegexWarning); @@ -610,7 +611,7 @@ int cmCTestLaunch::Main(int argc, const char* const argv[]) void cmCTestLaunch::LoadConfig() { - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::CTest); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -618,7 +619,7 @@ void cmCTestLaunch::LoadConfig() cmMakefile mf(&gg, cm.GetCurrentSnapshot()); std::string fname = this->LogDir; fname += "CTestLaunchConfig.cmake"; - if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname.c_str())) { + if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname)) { this->SourceDir = mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); cmSystemTools::ConvertToUnixSlashes(this->SourceDir); } diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 9c9532a..8ba59d3 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -261,8 +261,8 @@ void cmCTestMemCheckHandler::InitializeResultsVectors() }; this->GlobalResults.clear(); for (int i = 0; cmCTestMemCheckResultStrings[i] != nullptr; ++i) { - this->ResultStrings.push_back(cmCTestMemCheckResultStrings[i]); - this->ResultStringsLong.push_back(cmCTestMemCheckResultLongStrings[i]); + this->ResultStrings.emplace_back(cmCTestMemCheckResultStrings[i]); + this->ResultStringsLong.emplace_back(cmCTestMemCheckResultLongStrings[i]); this->GlobalResults.push_back(0); } } @@ -528,11 +528,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() switch (this->MemoryTesterStyle) { case cmCTestMemCheckHandler::VALGRIND: { if (this->MemoryTesterOptions.empty()) { - this->MemoryTesterOptions.push_back("-q"); - this->MemoryTesterOptions.push_back("--tool=memcheck"); - this->MemoryTesterOptions.push_back("--leak-check=yes"); - this->MemoryTesterOptions.push_back("--show-reachable=yes"); - this->MemoryTesterOptions.push_back("--num-callers=50"); + this->MemoryTesterOptions.emplace_back("-q"); + this->MemoryTesterOptions.emplace_back("--tool=memcheck"); + this->MemoryTesterOptions.emplace_back("--leak-check=yes"); + this->MemoryTesterOptions.emplace_back("--show-reachable=yes"); + this->MemoryTesterOptions.emplace_back("--num-callers=50"); } if (!this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile") .empty()) { @@ -586,11 +586,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() std::string dpbdFile = this->CTest->GetBinaryDir() + "/Testing/Temporary/MemoryChecker.??.DPbd"; this->BoundsCheckerDPBDFile = dpbdFile; - this->MemoryTesterDynamicOptions.push_back("/B"); + this->MemoryTesterDynamicOptions.emplace_back("/B"); this->MemoryTesterDynamicOptions.push_back(std::move(dpbdFile)); - this->MemoryTesterDynamicOptions.push_back("/X"); + this->MemoryTesterDynamicOptions.emplace_back("/X"); this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile); - this->MemoryTesterOptions.push_back("/M"); + this->MemoryTesterOptions.emplace_back("/M"); break; } // these are almost the same but the env var used is different @@ -604,8 +604,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() // The MemoryTesterDynamicOptions is setup with the -E env // Then the MemoryTesterEnvironmentVariable gets the // TSAN_OPTIONS string with the log_path in it. - this->MemoryTesterDynamicOptions.push_back("-E"); - this->MemoryTesterDynamicOptions.push_back("env"); + this->MemoryTesterDynamicOptions.emplace_back("-E"); + this->MemoryTesterDynamicOptions.emplace_back("env"); std::string envVar; std::string extraOptions; std::string suppressionsOption; diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 8867323..320647a 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -1039,6 +1039,11 @@ void cmCTestMultiProcessHandler::PrintOutputAsJson() testRun.SetTestProperties(&p); testRun.ComputeArguments(); + // Skip tests not available in this configuration. + if (p.Args.size() >= 2 && p.Args[1] == "NOT_AVAILABLE") { + continue; + } + Json::Value testInfo = DumpCTestInfo(testRun, p, backtraceGraph); tests.append(testInfo); } diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index 511dbd2..c0bdc17 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -307,20 +307,20 @@ void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions) { if (P4Options.empty()) { const char* p4 = this->CommandLineTool.c_str(); - P4Options.push_back(p4); + P4Options.emplace_back(p4); // The CTEST_P4_CLIENT variable sets the P4 client used when issuing // Perforce commands, if it's different from the default one. std::string client = this->CTest->GetCTestConfiguration("P4Client"); if (!client.empty()) { - P4Options.push_back("-c"); + P4Options.emplace_back("-c"); P4Options.push_back(client); } // Set the message language to be English, in case the P4 admin // has localized them - P4Options.push_back("-L"); - P4Options.push_back("en"); + P4Options.emplace_back("-L"); + P4Options.emplace_back("en"); // The CTEST_P4_OPTIONS variable adds additional Perforce command line // options before the main command diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 6c439e9..afde61c 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -521,7 +521,7 @@ private: } else { local_path = path; } - this->SVN->Repositories.emplace_back(local_path.c_str()); + this->SVN->Repositories.emplace_back(local_path); } }; @@ -532,7 +532,7 @@ bool cmCTestSVN::LoadRepositories() } // Info for root repository - this->Repositories.emplace_back(""); + this->Repositories.emplace_back(); this->RootInfo = &(this->Repositories.back()); // Run "svn status" to get the list of external repositories diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h index a467ede..5c8505d 100644 --- a/Source/CTest/cmCTestSVN.h +++ b/Source/CTest/cmCTestSVN.h @@ -41,7 +41,7 @@ private: struct SVNInfo { - SVNInfo(const char* path) + SVNInfo(std::string const& path = std::string()) : LocalPath(path) { } diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 30192c2..f417f53 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -135,7 +135,7 @@ cmCTestScriptHandler::~cmCTestScriptHandler() void cmCTestScriptHandler::AddConfigurationScript(const char* script, bool pscope) { - this->ConfigurationScripts.push_back(script); + this->ConfigurationScripts.emplace_back(script); this->ScriptProcessScope.push_back(pscope); } @@ -280,7 +280,7 @@ void cmCTestScriptHandler::CreateCMake() delete this->GlobalGenerator; delete this->Makefile; } - this->CMake = new cmake(cmake::RoleScript); + this->CMake = new cmake(cmake::RoleScript, cmState::CTest); this->CMake->SetHomeDirectory(""); this->CMake->SetHomeOutputDirectory(""); this->CMake->GetCurrentSnapshot().SetDefaultDefinitions(); @@ -373,7 +373,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) ctest scripting easier. */ std::string systemFile = this->Makefile->GetModulesFile("CTestScriptMode.cmake"); - if (!this->Makefile->ReadListFile(systemFile.c_str()) || + if (!this->Makefile->ReadListFile(systemFile) || cmSystemTools::GetErrorOccuredFlag()) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in read:" << systemFile << "\n"); @@ -388,7 +388,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) } // finally read in the script - if (!this->Makefile->ReadListFile(script.c_str()) || + if (!this->Makefile->ReadListFile(script) || cmSystemTools::GetErrorOccuredFlag()) { // Reset the error flag so that it can run more than // one script with an error when you use ctest_run_script. @@ -450,7 +450,7 @@ int cmCTestScriptHandler::ExtractVariables() updateVar, " specified without specifying CTEST_CVS_COMMAND."); return 12; } - this->ExtraUpdates.push_back(updateVal); + this->ExtraUpdates.emplace_back(updateVal); } } diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 43bd636..00c0610 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -6,8 +6,8 @@ #include "cmCTestGenericHandler.h" #include "cmCTestSubmitHandler.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" #include <sstream> @@ -15,36 +15,28 @@ class cmExecutionStatus; cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() { - const char* ctestDropMethod = - this->Makefile->GetDefinition("CTEST_DROP_METHOD"); - const char* ctestDropSite = this->Makefile->GetDefinition("CTEST_DROP_SITE"); - const char* ctestDropLocation = - this->Makefile->GetDefinition("CTEST_DROP_LOCATION"); - if (!ctestDropMethod) { - ctestDropMethod = "http"; - } + const char* submitURL = !this->SubmitURL.empty() + ? this->SubmitURL.c_str() + : this->Makefile->GetDefinition("CTEST_SUBMIT_URL"); - if (!ctestDropSite) { - // error: CDash requires CTEST_DROP_SITE definition - // in CTestConfig.cmake - } - if (!ctestDropLocation) { - // error: CDash requires CTEST_DROP_LOCATION definition - // in CTestConfig.cmake + if (submitURL) { + this->CTest->SetCTestConfiguration("SubmitURL", submitURL, this->Quiet); + } else { + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropMethod", "CTEST_DROP_METHOD", this->Quiet); + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropSiteUser", "CTEST_DROP_SITE_USER", this->Quiet); + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropSitePassword", "CTEST_DROP_SITE_PASSWORD", + this->Quiet); + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropSite", "CTEST_DROP_SITE", this->Quiet); + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropLocation", "CTEST_DROP_LOCATION", this->Quiet); } - this->CTest->SetCTestConfiguration("DropMethod", ctestDropMethod, - this->Quiet); - this->CTest->SetCTestConfiguration("DropSite", ctestDropSite, this->Quiet); - this->CTest->SetCTestConfiguration("DropLocation", ctestDropLocation, - this->Quiet); this->CTest->SetCTestConfigurationFromCMakeVariable( this->Makefile, "CurlOptions", "CTEST_CURL_OPTIONS", this->Quiet); - this->CTest->SetCTestConfigurationFromCMakeVariable( - this->Makefile, "DropSiteUser", "CTEST_DROP_SITE_USER", this->Quiet); - this->CTest->SetCTestConfigurationFromCMakeVariable( - this->Makefile, "DropSitePassword", "CTEST_DROP_SITE_PASSWORD", - this->Quiet); const char* notesFilesVariable = this->Makefile->GetDefinition("CTEST_NOTES_FILES"); @@ -184,6 +176,11 @@ bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg) return true; } + if (arg == "SUBMIT_URL") { + this->ArgumentDoing = ArgumentDoingSubmitURL; + return true; + } + if (arg == "INTERNAL_TEST_CHECKSUM") { this->InternalTest = true; return true; @@ -203,7 +200,7 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg) } else { std::ostringstream e; e << "Part name \"" << arg << "\" is invalid."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); this->ArgumentDoing = ArgumentDoingError; } return true; @@ -216,7 +213,7 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg) std::ostringstream e; e << "File \"" << arg << "\" does not exist. Cannot submit " << "a non-existent file."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); this->ArgumentDoing = ArgumentDoingError; } return true; @@ -249,6 +246,12 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg) return true; } + if (this->ArgumentDoing == ArgumentDoingSubmitURL) { + this->ArgumentDoing = ArgumentDoingNone; + this->SubmitURL = arg; + return true; + } + // Look for other arguments. return this->Superclass::CheckArgumentValue(arg); } diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h index c4b84ce..0caccd6 100644 --- a/Source/CTest/cmCTestSubmitCommand.h +++ b/Source/CTest/cmCTestSubmitCommand.h @@ -71,6 +71,7 @@ protected: ArgumentDoingCDashUpload, ArgumentDoingCDashUploadType, ArgumentDoingHttpHeader, + ArgumentDoingSubmitURL, ArgumentDoingLast2 }; @@ -85,6 +86,7 @@ protected: std::string CDashUploadFile; std::string CDashUploadType; std::vector<std::string> HttpHeaders; + std::string SubmitURL; }; #endif diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 3042480..5213bd3 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -162,7 +162,6 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( /* In windows, this will init the winsock stuff */ ::curl_global_init(CURL_GLOBAL_ALL); - std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod")); std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions")); std::vector<std::string> args; cmSystemTools::ExpandListArgument(curlopt, args); @@ -495,27 +494,6 @@ void cmCTestSubmitHandler::ParseResponse( } } -void cmCTestSubmitHandler::ConstructCDashURL(std::string& dropMethod, - std::string& url) -{ - dropMethod = this->CTest->GetCTestConfiguration("DropMethod"); - url = dropMethod; - url += "://"; - if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) { - url += this->CTest->GetCTestConfiguration("DropSiteUser"); - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, - this->CTest->GetCTestConfiguration("DropSiteUser").c_str(), this->Quiet); - if (!this->CTest->GetCTestConfiguration("DropSitePassword").empty()) { - url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword"); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, ":******", this->Quiet); - } - url += "@"; - } - url += this->CTest->GetCTestConfiguration("DropSite") + - this->CTest->GetCTestConfiguration("DropLocation"); -} - int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, std::string const& typeString) { @@ -536,16 +514,15 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, curl.SetCurlOptions(args); curl.SetTimeOutSeconds(SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT); curl.SetHttpHeaders(this->HttpHeaders); - std::string dropMethod; - std::string url; - this->ConstructCDashURL(dropMethod, url); + std::string url = this->CTest->GetSubmitURL(); std::string fields; std::string::size_type pos = url.find('?'); if (pos != std::string::npos) { fields = url.substr(pos + 1); url = url.substr(0, pos); } - if (!(dropMethod == "http" || dropMethod == "https")) { + if (!cmHasLiteralPrefix(url, "http://") && + !cmHasLiteralPrefix(url, "https://")) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Only http and https are supported for CDASH_UPLOAD\n"); return -1; @@ -861,7 +838,7 @@ int cmCTestSubmitHandler::ProcessHandler() // Submit Done.xml last if (this->SubmitPart[cmCTest::PartDone]) { - files.push_back("Done.xml"); + files.emplace_back("Done.xml"); } if (ofs) { @@ -872,10 +849,7 @@ int cmCTestSubmitHandler::ProcessHandler() cnt++; } } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - "Submit files (using " - << this->CTest->GetCTestConfiguration("DropMethod") - << ")" << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Submit files\n", this->Quiet); const char* specificTrack = this->CTest->GetSpecificTrack(); if (specificTrack) { @@ -885,72 +859,32 @@ int cmCTestSubmitHandler::ProcessHandler() } this->SetLogFile(&ofs); - std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod")); - - if (dropMethod.empty()) { - dropMethod = "http"; + std::string url = this->CTest->GetSubmitURL(); + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " SubmitURL: " << url << '\n', this->Quiet); + if (!this->SubmitUsingHTTP(buildDirectory + "/Testing/" + + this->CTest->GetCurrentTag(), + files, prefix, url)) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + " Problems when submitting via HTTP\n"); + ofs << " Problems when submitting via HTTP\n"; + return -1; } - - if (dropMethod == "http" || dropMethod == "https") { - std::string url = dropMethod; - url += "://"; - ofs << "Using drop method: " << dropMethod << std::endl; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Using HTTP submit method" << std::endl - << " Drop site:" << url, - this->Quiet); - if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) { - url += this->CTest->GetCTestConfiguration("DropSiteUser"); - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, - this->CTest->GetCTestConfiguration("DropSiteUser").c_str(), - this->Quiet); - if (!this->CTest->GetCTestConfiguration("DropSitePassword").empty()) { - url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword"); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, ":******", - this->Quiet); - } - url += "@"; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "@", this->Quiet); - } - url += this->CTest->GetCTestConfiguration("DropSite") + - this->CTest->GetCTestConfiguration("DropLocation"); + if (this->HasErrors) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Errors occurred during submission.\n"); + ofs << " Errors occurred during submission.\n"; + } else { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - this->CTest->GetCTestConfiguration("DropSite") - << this->CTest->GetCTestConfiguration("DropLocation") + " Submission successful" + << (this->HasWarnings ? ", with warnings." : "") << std::endl, this->Quiet); - if (!this->SubmitUsingHTTP(buildDirectory + "/Testing/" + - this->CTest->GetCurrentTag(), - files, prefix, url)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Problems when submitting via HTTP" << std::endl); - ofs << " Problems when submitting via HTTP" << std::endl; - return -1; - } - if (this->HasErrors) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, - " Errors occurred during " - "submission." - << std::endl); - ofs << " Errors occurred during submission. " << std::endl; - } else { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Submission successful" - << (this->HasWarnings ? ", with warnings." : "") - << std::endl, - this->Quiet); - ofs << " Submission successful" - << (this->HasWarnings ? ", with warnings." : "") << std::endl; - } - - return 0; + ofs << " Submission successful" + << (this->HasWarnings ? ", with warnings." : "") << std::endl; } - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Unknown submission method: \"" << dropMethod << "\"" - << std::endl); - return -1; + return 0; } std::string cmCTestSubmitHandler::GetSubmitResultsPrefix() diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h index 393e826..58f4f97 100644 --- a/Source/CTest/cmCTestSubmitHandler.h +++ b/Source/CTest/cmCTestSubmitHandler.h @@ -48,8 +48,6 @@ public: this->HttpHeaders = v; } - void ConstructCDashURL(std::string& dropMethod, std::string& url); - private: void SetLogFile(std::ostream* ost) { this->LogFile = ost; } diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 9fd2299..cf2652a 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -104,7 +104,7 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args, } fname += "/"; fname += testFilename; - readit = this->Makefile->ReadDependentFile(fname.c_str()); + readit = this->Makefile->ReadDependentFile(fname); } if (!readit) { std::string m = "Could not find include file: "; @@ -170,7 +170,7 @@ bool cmCTestAddSubdirectoryCommand::InitialPass( } fname += "/"; fname += testFilename; - readit = this->Makefile->ReadDependentFile(fname.c_str()); + readit = this->Makefile->ReadDependentFile(fname); } if (!readit) { std::string m = "Could not find include file: "; @@ -1524,7 +1524,7 @@ void cmCTestTestHandler::AddConfigurations( } tempPath = filepath + filename; attempted.push_back(tempPath); - attemptedConfigs.push_back(""); + attemptedConfigs.emplace_back(); if (!ctest->GetConfigType().empty()) { tempPath = filepath; @@ -1547,32 +1547,32 @@ void cmCTestTestHandler::AddConfigurations( tempPath += "Release/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("Release"); + attemptedConfigs.emplace_back("Release"); tempPath = filepath; tempPath += "Debug/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("Debug"); + attemptedConfigs.emplace_back("Debug"); tempPath = filepath; tempPath += "MinSizeRel/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("MinSizeRel"); + attemptedConfigs.emplace_back("MinSizeRel"); tempPath = filepath; tempPath += "RelWithDebInfo/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("RelWithDebInfo"); + attemptedConfigs.emplace_back("RelWithDebInfo"); tempPath = filepath; tempPath += "Deployment/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("Deployment"); + attemptedConfigs.emplace_back("Deployment"); tempPath = filepath; tempPath += "Development/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("Deployment"); + attemptedConfigs.emplace_back("Deployment"); } } @@ -1676,7 +1676,7 @@ void cmCTestTestHandler::GetListOfTests() } cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Constructing a list of tests" << std::endl, this->Quiet); - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::CTest); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx index ec78c1e..2fe2cd3 100644 --- a/Source/CTest/cmCTestUploadCommand.cxx +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -9,8 +9,8 @@ #include "cmCTestGenericHandler.h" #include "cmCTestUploadHandler.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler() { @@ -58,7 +58,7 @@ bool cmCTestUploadCommand::CheckArgumentValue(std::string const& arg) std::ostringstream e; e << "File \"" << arg << "\" does not exist. Cannot submit " << "a non-existent file."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); this->ArgumentDoing = ArgumentDoingError; return false; } diff --git a/Source/CTest/cmParseDelphiCoverage.cxx b/Source/CTest/cmParseDelphiCoverage.cxx index cc81979..d99de06 100644 --- a/Source/CTest/cmParseDelphiCoverage.cxx +++ b/Source/CTest/cmParseDelphiCoverage.cxx @@ -44,7 +44,7 @@ public: // Check that the begin is the first non-space string on the line if ((beginPos == line.find_first_not_of(' ')) && beginPos != std::string::npos) { - beginSet.push_back("begin"); + beginSet.emplace_back("begin"); coverageVector.push_back(-1); continue; } diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx index 18412ba..488d237 100644 --- a/Source/CTest/cmParseMumpsCoverage.cxx +++ b/Source/CTest/cmParseMumpsCoverage.cxx @@ -9,6 +9,7 @@ #include <map> #include <string> #include <utility> +#include <vector> cmParseMumpsCoverage::cmParseMumpsCoverage( cmCTestCoverageHandlerContainer& cont, cmCTest* ctest) diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index c4cf046..7737f65 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -7,7 +7,6 @@ #include "cmCTestTestHandler.h" #include "cmsys/Process.h" -#include <algorithm> #include <fcntl.h> #include <iostream> #include <signal.h> @@ -15,6 +14,7 @@ #if !defined(_WIN32) # include <unistd.h> #endif +#include <utility> #define CM_PROCESS_BUF_SIZE 65536 diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index a3e0717..856723a 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -6,6 +6,7 @@ #include "cmCursesStandardIncludes.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" +#include "cmState.h" #include "cmSystemTools.h" #include "cmake.h" @@ -83,7 +84,7 @@ int main(int argc, char const* const* argv) cmDocumentation doc; doc.addCMakeStandardDocSections(); if (doc.CheckOptions(argc, argv)) { - cmake hcm(cmake::RoleInternal); + cmake hcm(cmake::RoleInternal, cmState::Unknown); hcm.SetHomeDirectory(""); hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); @@ -108,7 +109,7 @@ int main(int argc, char const* const* argv) if (strcmp(argv[j], "-debug") == 0) { debug = true; } else { - args.push_back(argv[j]); + args.emplace_back(argv[j]); } } diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 931797a..55ef375 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -37,11 +37,11 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> const& args, this->AdvancedMode = false; this->NumberOfVisibleEntries = 0; this->OkToGenerate = false; - this->HelpMessage.push_back( + this->HelpMessage.emplace_back( "Welcome to ccmake, curses based user interface for CMake."); - this->HelpMessage.push_back(""); - this->HelpMessage.push_back(s_ConstHelpMessage); - this->CMakeInstance = new cmake(cmake::RoleProject); + this->HelpMessage.emplace_back(); + this->HelpMessage.emplace_back(s_ConstHelpMessage); + this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project); this->CMakeInstance->SetCMakeEditCommand( cmSystemTools::GetCMakeCursesCommand()); @@ -652,7 +652,7 @@ int cmCursesMainForm::Generate() void cmCursesMainForm::AddError(const char* message, const char* /*unused*/) { - this->Errors.push_back(message); + this->Errors.emplace_back(message); } void cmCursesMainForm::RemoveEntry(const char* value) diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx index 6b4fc85..5879912 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.cxx +++ b/Source/LexerParser/cmCommandArgumentLexer.cxx @@ -664,12 +664,14 @@ Modify cmCommandArgumentLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include "cmCommandArgumentParserHelper.h" /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmCommandArgumentParserTokens.h" @@ -2246,3 +2248,5 @@ void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes) BEGIN(ESCAPES); } } + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l index 5927b9e..010d54b 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.in.l +++ b/Source/LexerParser/cmCommandArgumentLexer.in.l @@ -18,12 +18,14 @@ Modify cmCommandArgumentLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include "cmCommandArgumentParserHelper.h" /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmCommandArgumentParserTokens.h" @@ -145,3 +147,5 @@ void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes) BEGIN(ESCAPES); } } + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmDependsJavaLexer.cxx b/Source/LexerParser/cmDependsJavaLexer.cxx index 36cac61..d703e3c 100644 --- a/Source/LexerParser/cmDependsJavaLexer.cxx +++ b/Source/LexerParser/cmDependsJavaLexer.cxx @@ -860,6 +860,8 @@ Modify cmDependsJavaLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include <iostream> #include "cmDependsJavaParserHelper.h" @@ -867,7 +869,7 @@ Modify cmDependsJavaLexer.cxx: /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmDependsJavaParserTokens.h" @@ -2811,3 +2813,7 @@ void yyfree (void * ptr , yyscan_t yyscanner) } #define YYTABLES_NAME "yytables" + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmDependsJavaLexer.in.l b/Source/LexerParser/cmDependsJavaLexer.in.l index 01a0fa3..3dd3c22 100644 --- a/Source/LexerParser/cmDependsJavaLexer.in.l +++ b/Source/LexerParser/cmDependsJavaLexer.in.l @@ -18,6 +18,8 @@ Modify cmDependsJavaLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include <iostream> #include "cmDependsJavaParserHelper.h" @@ -25,7 +27,7 @@ Modify cmDependsJavaLexer.cxx: /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmDependsJavaParserTokens.h" @@ -173,3 +175,7 @@ null { PRIMITIVE; return jp_NULLLITERAL; } } %% + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx index 5400a10..e83afa9 100644 --- a/Source/LexerParser/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -107,7 +107,7 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); #define YYMAXDEPTH 1000000 -#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp); +#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp) #define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval) #define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str)) /* Disable some warnings in the generated code. */ diff --git a/Source/LexerParser/cmDependsJavaParser.y b/Source/LexerParser/cmDependsJavaParser.y index a4e9c5d..d15cffc 100644 --- a/Source/LexerParser/cmDependsJavaParser.y +++ b/Source/LexerParser/cmDependsJavaParser.y @@ -36,7 +36,7 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); #define YYMAXDEPTH 1000000 -#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp); +#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp) #define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval) #define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str)) /* Disable some warnings in the generated code. */ diff --git a/Source/LexerParser/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx index cb24687..72e59b6 100644 --- a/Source/LexerParser/cmExprLexer.cxx +++ b/Source/LexerParser/cmExprLexer.cxx @@ -664,12 +664,14 @@ Modify cmExprLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include "cmExprParserHelper.h" /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmExprParserTokens.h" @@ -2223,3 +2225,7 @@ void yyfree (void * ptr , yyscan_t yyscanner) } #define YYTABLES_NAME "yytables" + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmExprLexer.in.l b/Source/LexerParser/cmExprLexer.in.l index 2197c2a..f8a4224 100644 --- a/Source/LexerParser/cmExprLexer.in.l +++ b/Source/LexerParser/cmExprLexer.in.l @@ -18,12 +18,14 @@ Modify cmExprLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include "cmExprParserHelper.h" /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmExprParserTokens.h" @@ -61,3 +63,7 @@ Modify cmExprLexer.cxx: . { yyextra->UnexpectedChar(yytext[0]); } %% + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx index 82048df..bcda77c 100644 --- a/Source/LexerParser/cmFortranLexer.cxx +++ b/Source/LexerParser/cmFortranLexer.cxx @@ -838,6 +838,8 @@ Modify cmFortranLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #undef YY_NO_UNPUT #define cmFortranLexer_cxx @@ -846,7 +848,7 @@ Modify cmFortranLexer.cxx: /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmFortranParser_Input(yyextra, buf, max_size); } + do { result = cmFortranParser_Input(yyextra, buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmFortranParserTokens.h" @@ -2610,3 +2612,5 @@ YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner) struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return YY_CURRENT_BUFFER; } + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l index b7e837b..3d38a7d 100644 --- a/Source/LexerParser/cmFortranLexer.in.l +++ b/Source/LexerParser/cmFortranLexer.in.l @@ -27,6 +27,8 @@ Modify cmFortranLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #undef YY_NO_UNPUT #define cmFortranLexer_cxx @@ -35,7 +37,7 @@ Modify cmFortranLexer.cxx: /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmFortranParser_Input(yyextra, buf, max_size); } + do { result = cmFortranParser_Input(yyextra, buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmFortranParserTokens.h" @@ -183,3 +185,5 @@ YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner) struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return YY_CURRENT_BUFFER; } + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmListFileLexer.c b/Source/LexerParser/cmListFileLexer.c index eb37337..c726415 100644 --- a/Source/LexerParser/cmListFileLexer.c +++ b/Source/LexerParser/cmListFileLexer.c @@ -805,7 +805,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer); /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } + do { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } while (0) /*--------------------------------------------------------------------------*/ diff --git a/Source/LexerParser/cmListFileLexer.in.l b/Source/LexerParser/cmListFileLexer.in.l index 23c7e49..6a6fb5f 100644 --- a/Source/LexerParser/cmListFileLexer.in.l +++ b/Source/LexerParser/cmListFileLexer.in.l @@ -57,7 +57,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer); /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } + do { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } while (0) /*--------------------------------------------------------------------------*/ %} diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 98cf8b0..b4307bb 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -64,7 +64,7 @@ int main(int argc, char** argv) doc.addCMakeStandardDocSections(); if (argc2 > 1 && doc.CheckOptions(argc2, argv2)) { // Construct and print requested documentation. - cmake hcm(cmake::RoleInternal); + cmake hcm(cmake::RoleInternal, cmState::Unknown); hcm.SetHomeDirectory(""); hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 444a980..72cce9f 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -751,6 +751,7 @@ bool CMakeSetupDialog::setupFirstConfigure() if (dialog.exec() == QDialog::Accepted) { dialog.saveToSettings(); this->CMakeThread->cmakeInstance()->setGenerator(dialog.getGenerator()); + this->CMakeThread->cmakeInstance()->setPlatform(dialog.getPlatform()); this->CMakeThread->cmakeInstance()->setToolset(dialog.getToolset()); QCMakeCacheModel* m = this->CacheValues->cacheModel(); diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx index 88ce7cb..ae5179c 100644 --- a/Source/QtDialog/FirstConfigure.cxx +++ b/Source/QtDialog/FirstConfigure.cxx @@ -16,8 +16,12 @@ StartCompilerSetup::StartCompilerSetup(QWidget* p) this->GeneratorOptions = new QComboBox(this); l->addWidget(this->GeneratorOptions); + // Add the generator platform + this->PlatformFrame = CreatePlatformWidgets(); + l->addWidget(PlatformFrame); + // Add the ability to specify toolset (-T parameter) - ToolsetFrame = CreateToolsetWidgets(); + this->ToolsetFrame = CreateToolsetWidgets(); l->addWidget(ToolsetFrame); l->addSpacing(6); @@ -45,7 +49,7 @@ StartCompilerSetup::StartCompilerSetup(QWidget* p) SLOT(onSelectionChanged(bool))); QObject::connect(this->CompilerSetupOptions[3], SIGNAL(toggled(bool)), this, SLOT(onSelectionChanged(bool))); - QObject::connect(GeneratorOptions, + QObject::connect(this->GeneratorOptions, SIGNAL(currentIndexChanged(QString const&)), this, SLOT(onGeneratorChanged(QString const&))); } @@ -65,6 +69,23 @@ QFrame* StartCompilerSetup::CreateToolsetWidgets() return frame; } +QFrame* StartCompilerSetup::CreatePlatformWidgets() +{ + QFrame* frame = new QFrame(this); + QVBoxLayout* l = new QVBoxLayout(frame); + l->setContentsMargins(0, 0, 0, 0); + + this->PlatformLabel = new QLabel(tr("Optional platform for generator")); + l->addWidget(this->PlatformLabel); + + this->PlatformOptions = new QComboBox(frame); + this->PlatformOptions->setEditable(true); + + l->addWidget(this->PlatformOptions); + + return frame; +} + StartCompilerSetup::~StartCompilerSetup() { } @@ -80,6 +101,26 @@ void StartCompilerSetup::setGenerators( for (it = gens.begin(); it != gens.end(); ++it) { generator_list.append(QString::fromLocal8Bit(it->name.c_str())); + if (it->supportsPlatform) { + this->GeneratorsSupportingPlatform.append( + QString::fromLocal8Bit(it->name.c_str())); + + this + ->GeneratorDefaultPlatform[QString::fromLocal8Bit(it->name.c_str())] = + QString::fromLocal8Bit(it->defaultPlatform.c_str()); + + std::vector<std::string>::const_iterator platformIt = + it->supportedPlatforms.cbegin(); + while (platformIt != it->supportedPlatforms.cend()) { + + this->GeneratorSupportedPlatforms.insert( + QString::fromLocal8Bit(it->name.c_str()), + QString::fromLocal8Bit((*platformIt).c_str())); + + platformIt++; + } + } + if (it->supportsToolset) { this->GeneratorsSupportingToolset.append( QString::fromLocal8Bit(it->name.c_str())); @@ -102,6 +143,11 @@ QString StartCompilerSetup::getGenerator() const return this->GeneratorOptions->currentText(); }; +QString StartCompilerSetup::getPlatform() const +{ + return this->PlatformOptions->currentText(); +}; + QString StartCompilerSetup::getToolset() const { return this->Toolset->text(); @@ -136,6 +182,31 @@ void StartCompilerSetup::onSelectionChanged(bool on) void StartCompilerSetup::onGeneratorChanged(QString const& name) { + // Display the generator platform for the generators supporting it + if (GeneratorsSupportingPlatform.contains(name)) { + + // Change the label title to include the default platform + std::string label = "Optional platform for generator"; + label += "(if empty, generator uses: "; + label += this->GeneratorDefaultPlatform[name].toStdString(); + label += ")"; + this->PlatformLabel->setText(tr(label.c_str())); + + // Regenerate the list of supported platform + this->PlatformOptions->clear(); + QStringList platform_list; + platform_list.append(""); + + QList<QString> platforms = this->GeneratorSupportedPlatforms.values(name); + platform_list.append(platforms); + + this->PlatformOptions->addItems(platform_list); + PlatformFrame->show(); + } else { + PlatformFrame->hide(); + } + + // Display the toolset box for the generators supporting it if (GeneratorsSupportingToolset.contains(name)) { ToolsetFrame->show(); } else { @@ -390,6 +461,11 @@ QString FirstConfigure::getGenerator() const return this->mStartCompilerSetupPage->getGenerator(); } +QString FirstConfigure::getPlatform() const +{ + return this->mStartCompilerSetupPage->getPlatform(); +} + QString FirstConfigure::getToolset() const { return this->mStartCompilerSetupPage->getToolset(); diff --git a/Source/QtDialog/FirstConfigure.h b/Source/QtDialog/FirstConfigure.h index abfa03f..d1db5bf 100644 --- a/Source/QtDialog/FirstConfigure.h +++ b/Source/QtDialog/FirstConfigure.h @@ -35,6 +35,7 @@ public: void setCurrentGenerator(const QString& gen); QString getGenerator() const; QString getToolset() const; + QString getPlatform() const; bool defaultSetup() const; bool compilerSetup() const; @@ -56,10 +57,17 @@ protected: QFrame* ToolsetFrame; QLineEdit* Toolset; QLabel* ToolsetLabel; + QFrame* PlatformFrame; + QComboBox* PlatformOptions; + QLabel* PlatformLabel; QStringList GeneratorsSupportingToolset; + QStringList GeneratorsSupportingPlatform; + QMultiMap<QString, QString> GeneratorSupportedPlatforms; + QMap<QString, QString> GeneratorDefaultPlatform; private: QFrame* CreateToolsetWidgets(); + QFrame* CreatePlatformWidgets(); }; //! the page that gives basic options for native compilers @@ -159,6 +167,7 @@ public: void setGenerators(std::vector<cmake::GeneratorInfo> const& gens); QString getGenerator() const; + QString getPlatform() const; QString getToolset() const; bool defaultSetup() const; diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 0133b88..2eecce6 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -27,7 +27,7 @@ QCMake::QCMake(QObject* p) cmSystemTools::SetStdoutCallback(QCMake::stdoutCallback, this); cmSystemTools::SetStderrCallback(QCMake::stderrCallback, this); - this->CMakeInstance = new cmake(cmake::RoleProject); + this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project); this->CMakeInstance->SetCMakeEditCommand( cmSystemTools::GetCMakeGUICommand()); this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this); @@ -35,7 +35,8 @@ QCMake::QCMake(QObject* p) cmSystemTools::SetInterruptCallback(QCMake::interruptCallback, this); std::vector<cmake::GeneratorInfo> generators; - this->CMakeInstance->GetRegisteredGenerators(generators); + this->CMakeInstance->GetRegisteredGenerators( + generators, /*includeNamesWithPlatform=*/false); std::vector<cmake::GeneratorInfo>::const_iterator it; for (it = generators.begin(); it != generators.end(); ++it) { @@ -74,6 +75,7 @@ void QCMake::setBinaryDirectory(const QString& _dir) cmState* state = this->CMakeInstance->GetState(); this->setGenerator(QString()); this->setToolset(QString()); + this->setPlatform(QString()); if (!this->CMakeInstance->LoadCache( this->BinaryDirectory.toLocal8Bit().data())) { QDir testDir(this->BinaryDirectory); @@ -102,6 +104,12 @@ void QCMake::setBinaryDirectory(const QString& _dir) this->setGenerator(QString::fromLocal8Bit(curGen.c_str())); } + const char* platform = + state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); + if (platform) { + this->setPlatform(QString::fromLocal8Bit(platform)); + } + const char* toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); if (toolset) { this->setToolset(QString::fromLocal8Bit(toolset)); @@ -119,6 +127,14 @@ void QCMake::setGenerator(const QString& gen) } } +void QCMake::setPlatform(const QString& platform) +{ + if (this->Platform != platform) { + this->Platform = platform; + emit this->platformChanged(this->Platform); + } +} + void QCMake::setToolset(const QString& toolset) { if (this->Toolset != toolset) { @@ -140,7 +156,8 @@ void QCMake::configure() this->CMakeInstance->SetGlobalGenerator( this->CMakeInstance->CreateGlobalGenerator( this->Generator.toLocal8Bit().data())); - this->CMakeInstance->SetGeneratorPlatform(""); + this->CMakeInstance->SetGeneratorPlatform( + this->Platform.toLocal8Bit().data()); this->CMakeInstance->SetGeneratorToolset(this->Toolset.toLocal8Bit().data()); this->CMakeInstance->LoadCache(); this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode); diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index 4b3920a..c84da58 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -75,6 +75,8 @@ public slots: /// set the desired generator to use void setGenerator(const QString& generator); /// set the desired generator to use + void setPlatform(const QString& platform); + /// set the desired generator to use void setToolset(const QString& toolset); /// do the configure step void configure(); @@ -155,6 +157,8 @@ signals: void debugOutputChanged(bool); /// signal when the toolset changes void toolsetChanged(const QString& toolset); + /// signal when the platform changes + void platformChanged(const QString& platform); /// signal when open is done void openDone(bool successful); /// signal when open is done @@ -175,6 +179,7 @@ protected: QString SourceDirectory; QString BinaryDirectory; QString Generator; + QString Platform; QString Toolset; std::vector<cmake::GeneratorInfo> AvailableGenerators; QString CMakeExecutable; diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 53f5593..a840f17 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -10,11 +10,11 @@ #include "cmCustomCommandLines.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -361,7 +361,7 @@ bool cmAddCustomCommandCommand::InitialPass( } else { bool issueMessage = true; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0050)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0050) << "\n"; @@ -372,7 +372,7 @@ bool cmAddCustomCommandCommand::InitialPass( case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } @@ -380,7 +380,7 @@ bool cmAddCustomCommandCommand::InitialPass( e << "The SOURCE signatures of add_custom_command are no longer " "supported."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index ddd9b70..8240d3e 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -9,10 +9,10 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -183,19 +183,19 @@ bool cmAddCustomTargetCommand::InitialPass( if (commandLines.empty() && !byproducts.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "BYPRODUCTS may not be specified without any COMMAND"); return true; } if (commandLines.empty() && uses_terminal) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "USES_TERMINAL may not be specified without any COMMAND"); return true; } if (commandLines.empty() && command_expand_lists) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "COMMAND_EXPAND_LISTS may not be specified without any COMMAND"); return true; } diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx index a73b57e..021bd29 100644 --- a/Source/cmAddDependenciesCommand.cxx +++ b/Source/cmAddDependenciesCommand.cxx @@ -5,8 +5,8 @@ #include <sstream> #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -24,7 +24,7 @@ bool cmAddDependenciesCommand::InitialPass( std::ostringstream e; e << "Cannot add target-level dependencies to alias target \"" << target_name << "\".\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } if (cmTarget* target = this->Makefile->FindTargetToUse(target_name)) { std::vector<std::string>::const_iterator s = args.begin(); @@ -40,7 +40,7 @@ bool cmAddDependenciesCommand::InitialPass( << "by the add_executable, add_library, or add_custom_target commands. " << "If you want to add file-level dependencies see the DEPENDS option " << "of the add_custom_target and add_custom_command commands."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } return true; diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index fae8063..5149333 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -7,11 +7,11 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -259,7 +259,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, << (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE") << " option but the target platform does not support dynamic linking. " "Building a STATIC library instead. This may lead to problems."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); type = cmStateEnums::STATIC_LIBRARY; } @@ -275,7 +275,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation( &reason)) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The OBJECT library type may not be used for IMPORTED libraries" + reason + "."); return true; @@ -307,7 +307,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, // A non-imported target may not have UNKNOWN type. if (type == cmStateEnums::UNKNOWN_LIBRARY) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The UNKNOWN library type may be used only for IMPORTED libraries."); return true; } diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 3f2e784..6e5109a 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -135,7 +135,7 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, return; } break; - }; + } #if !defined(_WIN32) || defined(__CYGWIN__) if (archive_read_disk_set_standard_lookup(this->Disk) != ARCHIVE_OK) { this->Error = "archive_read_disk_set_standard_lookup: "; diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 1f9f580..106e7a7 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -5,6 +5,7 @@ #include "cmsys/Directory.hxx" #include <algorithm> #include <stddef.h> +#include <utility> #include "cmAlgorithms.h" #include "cmMakefile.h" diff --git a/Source/cmBreakCommand.cxx b/Source/cmBreakCommand.cxx index 3772c6f..d07898f 100644 --- a/Source/cmBreakCommand.cxx +++ b/Source/cmBreakCommand.cxx @@ -6,8 +6,8 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" -#include "cmake.h" // cmBreakCommand bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, @@ -16,7 +16,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, if (!this->Makefile->IsLoopBlock()) { bool issueMessage = true; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n"; @@ -27,7 +27,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } @@ -35,7 +35,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, e << "A BREAK command was found outside of a proper " "FOREACH or WHILE loop scope."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -46,7 +46,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, if (!args.empty()) { bool issueMessage = true; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n"; @@ -57,14 +57,14 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } if (issueMessage) { e << "The BREAK command does not accept any arguments."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index fd87600..428a0b2 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -6,9 +6,9 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -84,7 +84,7 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args) if (!project_name.empty()) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "Ignoring PROJECT_NAME option because it has no effect."); } diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 8822942..54f08bb 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -10,7 +10,7 @@ #if defined(_WIN32) # include "cmAlgorithms.h" # include "cmGlobalGenerator.h" -# include "cmGlobalVisualStudio15Generator.h" +# include "cmGlobalVisualStudioVersionedGenerator.h" # include "cmSystemTools.h" # include "cmVSSetupHelper.h" # define HAVE_VS_SETUP_HELPER @@ -133,15 +133,31 @@ bool cmCMakeHostSystemInformationCommand::GetValue( // If generating for the VS 15 IDE, use the same instance. cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) { - cmGlobalVisualStudio15Generator* vs15gen = - static_cast<cmGlobalVisualStudio15Generator*>(gg); + cmGlobalVisualStudioVersionedGenerator* vs15gen = + static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); if (vs15gen->GetVSInstance(value)) { return true; } } // Otherwise, find a VS 15 instance ourselves. - cmVSSetupAPIHelper vsSetupAPIHelper; + cmVSSetupAPIHelper vsSetupAPIHelper(15); + if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { + cmSystemTools::ConvertToUnixSlashes(value); + } + } else if (key == "VS_16_DIR") { + // If generating for the VS 16 IDE, use the same instance. + cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 16 ")) { + cmGlobalVisualStudioVersionedGenerator* vs16gen = + static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); + if (vs16gen->GetVSInstance(value)) { + return true; + } + } + + // Otherwise, find a VS 16 instance ourselves. + cmVSSetupAPIHelper vsSetupAPIHelper(16); if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { cmSystemTools::ConvertToUnixSlashes(value); } diff --git a/Source/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx index 2b51976..4218d81 100644 --- a/Source/cmCMakeMinimumRequired.cxx +++ b/Source/cmCMakeMinimumRequired.cxx @@ -6,9 +6,9 @@ #include <stdio.h> #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmVersion.h" -#include "cmake.h" class cmExecutionStatus; @@ -96,7 +96,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, e << "CMake " << version_min << " or higher is required. You are running version " << cmVersion::GetCMakeVersion(); - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -108,7 +108,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, if (required_major < 2 || (required_major == 2 && required_minor < 4)) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0."); this->Makefile->SetPolicyVersion("2.4", version_max); } else { diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx index 3209ea5..ac30e1a 100644 --- a/Source/cmCMakePolicyCommand.cxx +++ b/Source/cmCMakePolicyCommand.cxx @@ -5,10 +5,10 @@ #include <sstream> #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" -#include "cmake.h" class cmExecutionStatus; @@ -146,7 +146,7 @@ bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args) << "The call to cmake_policy(GET " << id << " ...) at which this " << "error appears requests the policy, and this version of CMake " << "requires that the policy be set to NEW before it is checked."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } } diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 1d9621c..8ed43f9 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -181,7 +181,7 @@ void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs, std::vector<std::string> srcs2; int i; for (i = 0; i < numSrcs; ++i) { - srcs2.push_back(srcs[i]); + srcs2.emplace_back(srcs[i]); } cmTarget* tg = mf->AddExecutable(exename, srcs2); if (win32) { @@ -347,7 +347,7 @@ static void addLinkLibrary(cmMakefile* mf, std::string const& target, std::ostringstream e; e << "Attempt to add link library \"" << lib << "\" to target \"" << target << "\" which is not built in this directory."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -362,7 +362,7 @@ static void addLinkLibrary(cmMakefile* mf, std::string const& target, << " may not be linked into another target. " << "One may link only to STATIC or SHARED libraries, or " << "to executables with the ENABLE_EXPORTS property set."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); } t->AddLinkLibrary(*mf, lib, llt); @@ -393,7 +393,7 @@ void CCONV cmAddLibrary(void* arg, const char* libname, int shared, std::vector<std::string> srcs2; int i; for (i = 0; i < numSrcs; ++i) { - srcs2.push_back(srcs[i]); + srcs2.emplace_back(srcs[i]); } mf->AddLibrary( libname, @@ -419,8 +419,7 @@ int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs, lff.Name = name; for (int i = 0; i < numArgs; ++i) { // Assume all arguments are quoted. - lff.Arguments.push_back( - cmListFileArgument(args[i], cmListFileArgument::Quoted, 0)); + lff.Arguments.emplace_back(args[i], cmListFileArgument::Quoted, 0); } cmExecutionStatus status; return mf->ExecuteCommand(lff, status); @@ -436,7 +435,7 @@ void CCONV cmExpandSourceListArguments(void* arg, int numArgs, std::vector<std::string> result; int i; for (i = 0; i < numArgs; ++i) { - result.push_back(args[i]); + result.emplace_back(args[i]); } int resargc = static_cast<int>(result.size()); char** resargv = nullptr; @@ -627,7 +626,7 @@ void CCONV cmSourceFileAddDepend(void* arg, const char* depend) if (cmSourceFile* rsf = sf->RealSourceFile) { rsf->AddDepend(depend); } else { - sf->Depends.push_back(depend); + sf->Depends.emplace_back(depend); } } @@ -647,10 +646,10 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, std::vector<std::string> headerExts; int i; for (i = 0; i < numSourceExtensions; ++i) { - sourceExts.push_back(sourceExtensions[i]); + sourceExts.emplace_back(sourceExtensions[i]); } for (i = 0; i < numHeaderExtensions; ++i) { - headerExts.push_back(headerExtensions[i]); + headerExts.emplace_back(headerExtensions[i]); } // Save the original name given. diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 225c99f..4e2f275 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -429,7 +429,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) } } - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::CTest); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -640,7 +640,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command) " Reading ctest configuration file: " << fname << std::endl, command->ShouldBeQuiet()); - bool readit = mf->ReadDependentFile(fname.c_str()); + bool readit = mf->ReadDependentFile(fname); if (!readit) { std::string m = "Could not find include file: "; m += fname; @@ -1176,12 +1176,12 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, if (strcmp(i, "--build-generator") == 0 && timeout != cmCTest::MaxDuration() && timeout > cmDuration::zero()) { - args.push_back("--test-timeout"); + args.emplace_back("--test-timeout"); std::ostringstream msg; msg << cmDurationTo<unsigned int>(timeout); args.push_back(msg.str()); } - args.push_back(i); + args.emplace_back(i); } } if (log) { @@ -1944,6 +1944,9 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, this->Quiet = true; this->OutputAsJson = true; this->OutputAsJsonVersion = 1; + } else if (format != "human") { + errormsg = "'--show-only=' given unknown value '" + format + "'"; + return false; } } @@ -2469,8 +2472,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) bool erroroc = cmSystemTools::GetErrorOccuredFlag(); cmSystemTools::ResetErrorOccuredFlag(); - if (!mf->ReadListFile(fname.c_str()) || - cmSystemTools::GetErrorOccuredFlag()) { + if (!mf->ReadListFile(fname) || cmSystemTools::GetErrorOccuredFlag()) { cmCTestLog(this, ERROR_MESSAGE, "Problem reading custom configuration: " << fname << std::endl); @@ -2489,15 +2491,13 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) gl.RecurseOn(); gl.FindFiles(rexpr); std::vector<std::string>& files = gl.GetFiles(); - std::vector<std::string>::iterator fileIt; - for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) { + for (const std::string& file : files) { cmCTestLog(this, DEBUG, - "* Read custom CTest configuration file: " << *fileIt + "* Read custom CTest configuration file: " << file << std::endl); - if (!mf->ReadListFile(fileIt->c_str()) || - cmSystemTools::GetErrorOccuredFlag()) { + if (!mf->ReadListFile(file) || cmSystemTools::GetErrorOccuredFlag()) { cmCTestLog(this, ERROR_MESSAGE, - "Problem reading custom configuration: " << *fileIt + "Problem reading custom configuration: " << file << std::endl); } } @@ -2626,6 +2626,32 @@ void cmCTest::SetCTestConfiguration(const char* name, const char* value, this->CTestConfiguration[name] = value; } +std::string cmCTest::GetSubmitURL() +{ + std::string url = this->GetCTestConfiguration("SubmitURL"); + if (url.empty()) { + std::string method = this->GetCTestConfiguration("DropMethod"); + std::string user = this->GetCTestConfiguration("DropSiteUser"); + std::string password = this->GetCTestConfiguration("DropSitePassword"); + std::string site = this->GetCTestConfiguration("DropSite"); + std::string location = this->GetCTestConfiguration("DropLocation"); + + url = method.empty() ? "http" : method; + url += "://"; + if (!user.empty()) { + url += user; + if (!password.empty()) { + url += ':'; + url += password; + } + url += '@'; + } + url += site; + url += location; + } + return url; +} + std::string cmCTest::GetCurrentTag() { return this->CurrentTag; @@ -2690,7 +2716,7 @@ void cmCTest::SetSpecificTrack(const char* track) void cmCTest::AddSubmitFile(Part part, const char* name) { - this->Parts[part].SubmitFiles.push_back(name); + this->Parts[part].SubmitFiles.emplace_back(name); } void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr) @@ -2781,13 +2807,13 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args, if ((res == cmsysProcess_Pipe_STDOUT || res == cmsysProcess_Pipe_STDERR) && this->ExtraVerbose) { processOutput.DecodeText(data, length, strdata); - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } } if (this->ExtraVerbose) { processOutput.DecodeText(std::string(), strdata); if (!strdata.empty()) { - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } } @@ -2853,9 +2879,11 @@ static const char* cmCTestStringLogType[] = { "DEBUG", nullptr }; #define cmCTestLogOutputFileLine(stream) \ - if (this->ShowLineNumbers) { \ - (stream) << std::endl << file << ":" << line << " "; \ - } + do { \ + if (this->ShowLineNumbers) { \ + (stream) << std::endl << file << ":" << line << " "; \ + } \ + } while (false) void cmCTest::InitStreams() { diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 2b40ca3..a82f400 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -176,6 +176,8 @@ public: bool suppress = false); void EmptyCTestConfiguration(); + std::string GetSubmitURL(); + /** * constructor and destructor */ diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 6ccb3a8..e1d312b 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -11,6 +11,7 @@ #include <string> #include "cmGeneratedFileStream.h" +#include "cmMessageType.h" #include "cmMessenger.h" #include "cmState.h" #include "cmSystemTools.h" @@ -478,7 +479,7 @@ void cmCacheManager::OutputNewlineTruncationWarning(std::ostream& fout, std::string message = "Value of "; message += key; message += " contained a newline; truncating"; - messenger->IssueMessage(cmake::WARNING, message); + messenger->IssueMessage(MessageType::WARNING, message); } std::string comment = "WARNING: Value of "; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 27b8599..87bc150 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -8,6 +8,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOrderDirectories.h" #include "cmOutputConverter.h" #include "cmPolicies.h" @@ -30,7 +31,7 @@ Notes about linking on various platforms: ------------------------------------------------------------------------------ -Linux, FreeBSD, macOS, IRIX, Sun, Windows: +Linux, FreeBSD, macOS, Sun, Windows: Linking to libraries using the full path works fine. @@ -522,7 +523,7 @@ bool cmComputeLinkInformation::Compute() "name." ; /* clang-format on */ - this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), + this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), this->Target->GetBacktrace()); } @@ -883,12 +884,12 @@ void cmComputeLinkInformation::AddLinkExtension(const char* e, LinkType type) { if (e && *e) { if (type == LinkStatic) { - this->StaticLinkExtensions.push_back(e); + this->StaticLinkExtensions.emplace_back(e); } if (type == LinkShared) { - this->SharedLinkExtensions.push_back(e); + this->SharedLinkExtensions.emplace_back(e); } - this->LinkExtensions.push_back(e); + this->LinkExtensions.emplace_back(e); } } @@ -1382,7 +1383,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, << " " << item << "\n" << "which is a full-path but not a valid library file name."; /* clang-format on */ - this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), + this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), this->Target->GetBacktrace()); } } @@ -1401,7 +1402,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, << " " << item << "\n" << "which is a full-path but not a valid library file name."; /* clang-format on */ - this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->CMakeInstance->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Target->GetBacktrace()); } break; } @@ -1424,7 +1425,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() "CMP0003-WARNING-GIVEN", "1"); std::ostringstream w; this->PrintLinkPolicyDiagnosis(w); - this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), + this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), this->Target->GetBacktrace()); } case cmPolicies::OLD: @@ -1439,7 +1440,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() std::ostringstream e; e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0003) << "\n"; this->PrintLinkPolicyDiagnosis(e); - this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->CMakeInstance->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Target->GetBacktrace()); return false; } diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index f8ac333..fde9750 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -9,6 +9,7 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSourceFile.h" #include "cmState.h" @@ -217,7 +218,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) depender->GetType() != cmStateEnums::MODULE_LIBRARY && depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Only executables and libraries may reference target objects.", depender->GetBacktrace()); return; @@ -314,7 +315,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, if (!dependee && !linking && (depender->GetType() != cmStateEnums::GLOBAL_TARGET)) { - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; bool issueMessage = false; std::ostringstream e; switch (depender->GetPolicyStatusCMP0046()) { @@ -327,7 +328,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (issueMessage) { cmake* cm = this->GlobalGenerator->GetCMakeInstance(); diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 3b4206f..33b9cf1 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -11,8 +11,10 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmSystemTools.h" +#include "cmake.h" class cmCommand; class cmTest; @@ -81,7 +83,7 @@ cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, bool cmConditionEvaluator::IsTrue( const std::vector<cmExpandedCommandArgument>& args, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { errorString.clear(); @@ -123,7 +125,7 @@ bool cmConditionEvaluator::IsTrue( // now at the end there should only be one argument left if (newArgs.size() != 1) { errorString = "Unknown arguments specified"; - status = cmake::FATAL_ERROR; + status = MessageType::FATAL_ERROR; return false; } @@ -155,7 +157,7 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted( "Since the policy is not set the OLD behavior will be used."; this->Makefile.GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, e.str(), this->Backtrace); + MessageType::AUTHOR_WARNING, e.str(), this->Backtrace); } } @@ -199,7 +201,7 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword, "Since the policy is not set the OLD behavior will be used."; this->Makefile.GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, e.str(), this->Backtrace); + MessageType::AUTHOR_WARNING, e.str(), this->Backtrace); } } @@ -269,7 +271,7 @@ bool cmConditionEvaluator::GetBooleanValueOld( // returns the resulting boolean value bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( cmExpandedCommandArgument& newArg, std::string& errorString, - cmake::MessageType& status, bool oneArg) const + MessageType& status, bool oneArg) const { // Use the policy if it is set. if (this->Policy12Status == cmPolicies::NEW) { @@ -288,7 +290,7 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( errorString = "An argument named \"" + newArg.GetValue() + "\" appears in a conditional statement. " + cmPolicies::GetPolicyWarning(cmPolicies::CMP0012); - status = cmake::AUTHOR_WARNING; + status = MessageType::AUTHOR_WARNING; CM_FALLTHROUGH; case cmPolicies::OLD: return oldResult; @@ -297,7 +299,7 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( errorString = "An argument named \"" + newArg.GetValue() + "\" appears in a conditional statement. " + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0012); - status = cmake::FATAL_ERROR; + status = MessageType::FATAL_ERROR; } case cmPolicies::NEW: break; @@ -362,7 +364,7 @@ void cmConditionEvaluator::HandleBinaryOp(bool value, int& reducible, // level 0 processes parenthetical expressions bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { int reducible; do { @@ -386,7 +388,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, } if (depth) { errorString = "mismatched parenthesis in condition"; - status = cmake::FATAL_ERROR; + status = MessageType::FATAL_ERROR; return false; } // store the reduced args in this vector @@ -419,7 +421,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, //========================================================================= // level one handles most predicates except for NOT bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, - cmake::MessageType&) + MessageType&) { int reducible; do { @@ -485,7 +487,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, "when the policy is set to NEW. " "Since the policy is not set the OLD behavior will be used."; - this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } // is a variable defined if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) { @@ -516,7 +518,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, // level two handles most binary operations except for AND OR bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { int reducible; std::string def_buf; @@ -547,7 +549,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::ostringstream error; error << "Regular expression \"" << rex << "\" cannot compile"; errorString = error.str(); - status = cmake::FATAL_ERROR; + status = MessageType::FATAL_ERROR; return false; } if (regEntry.find(def)) { @@ -682,7 +684,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, "when the policy is set to NEW. " "Since the policy is not set the OLD behavior will be used."; - this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } } @@ -696,7 +698,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, // level 3 handles NOT bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { int reducible; do { @@ -722,7 +724,7 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, // level 4 handles AND OR bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { int reducible; bool lhs; diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index 50f4edc..fc87a2d 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -11,8 +11,8 @@ #include "cmExpandedCommandArgument.h" #include "cmListFileCache.h" +#include "cmMessageType.h" #include "cmPolicies.h" -#include "cmake.h" class cmMakefile; @@ -28,7 +28,7 @@ public: // arguments were valid, and if so, was the response true. If there is // an error, the errorString will be set. bool IsTrue(const std::vector<cmExpandedCommandArgument>& args, - std::string& errorString, cmake::MessageType& status); + std::string& errorString, MessageType& status); private: // Filter the given variable definition based on policy CMP0054. @@ -48,7 +48,7 @@ private: bool GetBooleanValueWithAutoDereference(cmExpandedCommandArgument& newArg, std::string& errorString, - cmake::MessageType& status, + MessageType& status, bool oneArg = false) const; void IncrementArguments(cmArgumentList& newArgs, @@ -66,19 +66,18 @@ private: cmArgumentList::iterator& argP2); bool HandleLevel0(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status); + MessageType& status); - bool HandleLevel1(cmArgumentList& newArgs, std::string&, - cmake::MessageType&); + bool HandleLevel1(cmArgumentList& newArgs, std::string&, MessageType&); bool HandleLevel2(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status); + MessageType& status); bool HandleLevel3(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status); + MessageType& status); bool HandleLevel4(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status); + MessageType& status); cmMakefile& Makefile; cmListFileContext ExecutionContext; diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index 305262d..8224a0f 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -5,8 +5,8 @@ #include <sstream> #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -89,7 +89,7 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args, if (!unknown_args.empty()) { std::string msg = "configure_file called with unknown argument(s):\n"; msg += unknown_args; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); } if (!this->ConfigureFile()) { diff --git a/Source/cmContinueCommand.cxx b/Source/cmContinueCommand.cxx index 2298a05..48f1f41 100644 --- a/Source/cmContinueCommand.cxx +++ b/Source/cmContinueCommand.cxx @@ -4,15 +4,15 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" // cmContinueCommand bool cmContinueCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) { if (!this->Makefile->IsLoopBlock()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "A CONTINUE command was found outside of a " "proper FOREACH or WHILE loop scope."); cmSystemTools::SetFatalErrorOccured(); @@ -22,7 +22,7 @@ bool cmContinueCommand::InitialPass(std::vector<std::string> const& args, status.SetContinueInvoked(); if (!args.empty()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "The CONTINUE command does not accept any " "arguments."); cmSystemTools::SetFatalErrorOccured(); diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index f9b494e..fcb27b4 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -13,6 +13,7 @@ #include "cmExportTryCompileFileGenerator.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmState.h" @@ -56,6 +57,12 @@ static std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = "CMAKE_TRY_COMPILE_PLATFORM_VARIABLES"; static std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED"; +/* GHS Multi platform variables */ +static std::set<std::string> ghs_platform_vars{ + "GHS_TARGET_PLATFORM", "GHS_PRIMARY_TARGET", "GHS_TOOLSET_ROOT", + "GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME" +}; + static void writeProperty(FILE* fout, std::string const& targetName, std::string const& prop, std::string const& value) { @@ -96,7 +103,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, targetType = cmStateEnums::STATIC_LIBRARY; } else { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, std::string("Invalid value '") + tt + "' for " "CMAKE_TRY_COMPILE_TARGET_TYPE. Only " @@ -238,7 +245,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, CM_FALLTHROUGH; default: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Only libraries may be used as try_compile or try_run IMPORTED " "LINK_LIBRARIES. Got " + std::string(tgt->GetName()) + @@ -297,93 +304,95 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else { std::ostringstream m; m << "try_compile given unknown argument \"" << argv[i] << "\"."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m.str()); } } if (didCopyFile && copyFile.empty()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "COPY_FILE must be followed by a file path"); return -1; } if (didCopyFileError && copyFileError.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "COPY_FILE_ERROR must be followed by a variable name"); return -1; } if (didCopyFileError && !didCopyFile) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "COPY_FILE_ERROR may be used only with COPY_FILE"); + MessageType::FATAL_ERROR, + "COPY_FILE_ERROR may be used only with COPY_FILE"); return -1; } if (didOutputVariable && outputVariable.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "OUTPUT_VARIABLE must be followed by a variable name"); return -1; } if (useSources && sources.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "SOURCES must be followed by at least one source file"); return -1; } if (didCStandard && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "C_STANDARD allowed only in source file signature."); + MessageType::FATAL_ERROR, + "C_STANDARD allowed only in source file signature."); return -1; } if (didCxxStandard && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CXX_STANDARD allowed only in source file signature."); return -1; } if (didCudaStandard && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CUDA_STANDARD allowed only in source file signature."); return -1; } if (didCStandardRequired && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "C_STANDARD_REQUIRED allowed only in source file signature."); return -1; } if (didCxxStandardRequired && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CXX_STANDARD_REQUIRED allowed only in source file signature."); return -1; } if (didCudaStandardRequired && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CUDA_STANDARD_REQUIRED allowed only in source file signature."); return -1; } if (didCExtensions && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "C_EXTENSIONS allowed only in source file signature."); return -1; } if (didCxxExtensions && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CXX_EXTENSIONS allowed only in source file signature."); return -1; } if (didCudaExtensions && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CUDA_EXTENSIONS allowed only in source file signature."); return -1; } @@ -397,13 +406,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, // only valid for srcfile signatures if (!compileDefs.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE"); return -1; } if (!copyFile.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "COPY_FILE specified on a srcdir type TRY_COMPILE"); return -1; } @@ -416,7 +425,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::ostringstream e; e << "Attempt at a recursive or nested TRY_COMPILE in directory\n" << " " << this->BinaryDirectory << "\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return -1; } @@ -450,7 +459,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, gg->GetEnabledLanguages(langs); err << cmJoin(langs, " "); err << "\nSee project() command to enable other languages."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, err.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err.str()); return -1; } } @@ -471,7 +480,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, << " " << outFileName << "\n" << cmSystemTools::GetLastSystemError(); /* clang-format on */ - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return -1; } @@ -522,7 +531,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, "(e.g. CMAKE_C_FLAGS_DEBUG) in the test project." ; /* clang-format on */ - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } case cmPolicies::OLD: // OLD behavior is to do nothing. @@ -530,7 +539,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0066)); CM_FALLTHROUGH; case cmPolicies::NEW: { @@ -559,7 +568,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, "in the test project." ; /* clang-format on */ - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } case cmPolicies::OLD: // OLD behavior is to do nothing. @@ -567,7 +576,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0056)); CM_FALLTHROUGH; case cmPolicies::NEW: @@ -606,7 +615,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, tcfg.SetConfig(tcConfig); if (!tcfg.GenerateImportFile()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "could not write export file."); fclose(fout); return -1; @@ -734,7 +743,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0067)); case cmPolicies::NEW: // NEW behavior is to honor the language standard variables. @@ -796,7 +805,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, for (std::string const& vi : this->WarnCMP0067) { w << " " << vi << "\n"; } - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } if (testC) { @@ -866,6 +875,16 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, projectName = "CMAKE_TRY_COMPILE"; } + if (this->Makefile->GetState()->UseGhsMultiIDE()) { + // Forward the GHS variables to the inner project cache. + for (std::string const& var : ghs_platform_vars) { + if (const char* val = this->Makefile->GetDefinition(var)) { + std::string flag = "-D" + var + "=" + val; + cmakeFlags.push_back(std::move(flag)); + } + } + } + bool erroroc = cmSystemTools::GetErrorOccuredFlag(); cmSystemTools::ResetErrorOccuredFlag(); std::string output; @@ -905,7 +924,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, emsg << this->FindErrorMessage.c_str(); } if (copyFileError.empty()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, emsg.str()); return -1; } copyFileErrorMessage = emsg.str(); @@ -1002,12 +1021,12 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName, tmp += config; searchDirs.push_back(std::move(tmp)); } - searchDirs.push_back("/Debug"); + searchDirs.emplace_back("/Debug"); #if defined(__APPLE__) std::string app = "/Debug/" + targetName + ".app"; searchDirs.push_back(std::move(app)); #endif - searchDirs.push_back("/Development"); + searchDirs.emplace_back("/Development"); for (std::string const& sdir : searchDirs) { std::string command = this->BinaryDirectory; diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx index 0482898..0004f66 100644 --- a/Source/cmCurl.cxx +++ b/Source/cmCurl.cxx @@ -14,11 +14,13 @@ #endif #define check_curl_result(result, errstr) \ - if ((result) != CURLE_OK && (result) != CURLE_NOT_BUILT_IN) { \ - e += e.empty() ? "" : "\n"; \ - e += (errstr); \ - e += ::curl_easy_strerror(result); \ - } + do { \ + if ((result) != CURLE_OK && (result) != CURLE_NOT_BUILT_IN) { \ + e += e.empty() ? "" : "\n"; \ + e += (errstr); \ + e += ::curl_easy_strerror(result); \ + } \ + } while (false) std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile) { diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 2acb015..3b3783a 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -13,7 +13,7 @@ #include <string.h> #include <utility> -cmDepends::cmDepends(cmLocalGenerator* lg, const char* targetDir) +cmDepends::cmDepends(cmLocalGenerator* lg, const std::string& targetDir) : LocalGenerator(lg) , TargetDirectory(targetDir) , Dependee(new char[MaxPath]) @@ -65,12 +65,13 @@ bool cmDepends::Finalize(std::ostream& /*unused*/, std::ostream& /*unused*/) return true; } -bool cmDepends::Check(const char* makeFile, const char* internalFile, +bool cmDepends::Check(const std::string& makeFile, + const std::string& internalFile, std::map<std::string, DependencyVector>& validDeps) { // Check whether dependencies must be regenerated. bool okay = true; - cmsys::ifstream fin(internalFile); + cmsys::ifstream fin(internalFile.c_str()); if (!(fin && this->CheckDependencies(fin, internalFile, validDeps))) { // Clear all dependencies so they will be regenerated. this->Clear(makeFile); @@ -81,13 +82,13 @@ bool cmDepends::Check(const char* makeFile, const char* internalFile, return okay; } -void cmDepends::Clear(const char* file) +void cmDepends::Clear(const std::string& file) { // Print verbose output. if (this->Verbose) { std::ostringstream msg; msg << "Clearing dependencies in \"" << file << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } // Write an empty dependency file. @@ -107,7 +108,7 @@ bool cmDepends::WriteDependencies(const std::set<std::string>& /*unused*/, } bool cmDepends::CheckDependencies( - std::istream& internalDepends, const char* internalDependsFileName, + std::istream& internalDepends, const std::string& internalDependsFileName, std::map<std::string, DependencyVector>& validDeps) { // Parse dependencies from the stream. If any dependee is missing @@ -170,7 +171,7 @@ bool cmDepends::CheckDependencies( std::ostringstream msg; msg << "Dependee \"" << dependee << "\" does not exist for depender \"" << depender << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } } else { if (dependerExists) { @@ -187,15 +188,15 @@ bool cmDepends::CheckDependencies( std::ostringstream msg; msg << "Dependee \"" << dependee << "\" is newer than depender \"" << depender << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } } } else { // The dependee exists, but the depender doesn't. Regenerate if the // internalDepends file is older than the dependee. int result = 0; - if ((!this->FileComparison->FileTimeCompare(internalDependsFileName, - dependee, &result) || + if ((!this->FileComparison->FileTimeCompare( + internalDependsFileName.c_str(), dependee, &result) || result < 0)) { // The depends-file is older than the dependee. regenerate = true; @@ -206,7 +207,7 @@ bool cmDepends::CheckDependencies( msg << "Dependee \"" << dependee << "\" is newer than depends file \"" << internalDependsFileName << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } } } diff --git a/Source/cmDepends.h b/Source/cmDepends.h index 705d215..b0b5bb5 100644 --- a/Source/cmDepends.h +++ b/Source/cmDepends.h @@ -29,7 +29,7 @@ class cmDepends public: /** Instances need to know the build directory name and the relative path from the build directory to the target file. */ - cmDepends(cmLocalGenerator* lg = nullptr, const char* targetDir = ""); + cmDepends(cmLocalGenerator* lg = nullptr, const std::string& targetDir = ""); /** Set the local generator for the directory in which we are scanning dependencies. This is not a full local generator; it @@ -41,7 +41,10 @@ public: void SetLanguage(const std::string& lang) { this->Language = lang; } /** Set the target build directory. */ - void SetTargetDirectory(const char* dir) { this->TargetDirectory = dir; } + void SetTargetDirectory(const std::string& dir) + { + this->TargetDirectory = dir; + } /** should this be verbose in its output */ void SetVerbose(bool verb) { this->Verbose = verb; } @@ -61,11 +64,11 @@ public: they must be generated Clear has already been called to wipe out the old dependencies. Dependencies which are still valid will be stored in validDeps. */ - bool Check(const char* makeFile, const char* internalFile, + bool Check(const std::string& makeFile, const std::string& internalFile, std::map<std::string, DependencyVector>& validDeps); /** Clear dependencies for the target file so they will be regenerated. */ - void Clear(const char* file); + void Clear(const std::string& file); /** Set the file comparison object */ void SetFileComparison(cmFileTimeComparison* fc) @@ -85,7 +88,7 @@ protected: // Return false if dependencies must be regenerated and true // otherwise. virtual bool CheckDependencies( - std::istream& internalDepends, const char* internalDependsFileName, + std::istream& internalDepends, const std::string& internalDependsFileName, std::map<std::string, DependencyVector>& validDeps); // Finalize the dependency information for the target. diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 072d116..f6ac4f2 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -24,7 +24,7 @@ cmDependsC::cmDependsC() } cmDependsC::cmDependsC( - cmLocalGenerator* lg, const char* targetDir, const std::string& lang, + cmLocalGenerator* lg, const std::string& targetDir, const std::string& lang, const std::map<std::string, DependencyVector>* validDeps) : cmDepends(lg, targetDir) , ValidDeps(validDeps) @@ -53,8 +53,8 @@ cmDependsC::cmDependsC( } this->IncludeRegexLine.compile(INCLUDE_REGEX_LINE); - this->IncludeRegexScan.compile(scanRegex.c_str()); - this->IncludeRegexComplain.compile(complainRegex.c_str()); + this->IncludeRegexScan.compile(scanRegex); + this->IncludeRegexComplain.compile(complainRegex); this->IncludeRegexLineString = INCLUDE_REGEX_LINE_MARKER INCLUDE_REGEX_LINE; this->IncludeRegexScanString = INCLUDE_REGEX_SCAN_MARKER; this->IncludeRegexScanString += scanRegex; @@ -212,7 +212,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // Scan this file for new dependencies. Pass the directory // containing the file to handle double-quote includes. std::string dir = cmSystemTools::GetFilenamePath(fullName); - this->Scan(fin, dir.c_str(), fullName); + this->Scan(fin, dir, fullName); } else { // Skip file with encoding we do not implement. } @@ -342,7 +342,7 @@ void cmDependsC::WriteCacheFile() const } } -void cmDependsC::Scan(std::istream& is, const char* directory, +void cmDependsC::Scan(std::istream& is, const std::string& directory, const std::string& fullName) { cmIncludeLines* newCacheEntry = new cmIncludeLines; @@ -418,7 +418,7 @@ void cmDependsC::SetupTransforms() sep = "|"; } xform += ")[ \t]*\\(([^),]*)\\)"; - this->IncludeRegexTransform.compile(xform.c_str()); + this->IncludeRegexTransform.compile(xform); // Build a string that encodes all transformation rules and will // change when rules are changed. @@ -460,11 +460,11 @@ void cmDependsC::TransformLine(std::string& line) // Construct the transformed line. std::string newline = this->IncludeRegexTransform.match(1); std::string arg = this->IncludeRegexTransform.match(4); - for (const char* c = tri->second.c_str(); *c; ++c) { - if (*c == '%') { + for (char c : tri->second) { + if (c == '%') { newline += arg; } else { - newline += *c; + newline += c; } } diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index f833888..af2b06e 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -28,7 +28,7 @@ public: /** Checking instances need to know the build directory name and the relative path from the build directory to the target file. */ cmDependsC(); - cmDependsC(cmLocalGenerator* lg, const char* targetDir, + cmDependsC(cmLocalGenerator* lg, const std::string& targetDir, const std::string& lang, const std::map<std::string, DependencyVector>* validDeps); @@ -42,7 +42,7 @@ protected: std::ostream& internalDepends) override; // Method to scan a single file. - void Scan(std::istream& is, const char* directory, + void Scan(std::istream& is, const std::string& directory, const std::string& fullName); // Regular expression to identify C preprocessor include directives. diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index e51f81e..6c5f647 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -7,7 +7,6 @@ #include <iostream> #include <map> #include <stdlib.h> -#include <string.h> #include <utility> #include "cmAlgorithms.h" @@ -54,7 +53,8 @@ public: typedef std::map<std::string, cmFortranSourceInfo> ObjectInfoMap; ObjectInfoMap ObjectInfo; - cmFortranSourceInfo& CreateObjectInfo(const char* obj, const char* src) + cmFortranSourceInfo& CreateObjectInfo(const std::string& obj, + const std::string& src) { std::map<std::string, cmFortranSourceInfo>::iterator i = this->ObjectInfo.find(obj); @@ -121,8 +121,7 @@ bool cmDependsFortran::WriteDependencies(const std::set<std::string>& sources, bool okay = true; for (std::string const& src : sources) { // Get the information object for this source. - cmFortranSourceInfo& info = - this->Internal->CreateObjectInfo(obj.c_str(), src.c_str()); + cmFortranSourceInfo& info = this->Internal->CreateObjectInfo(obj, src); // Create the parser object. The constructor takes info by reference, // so we may look into the resulting objects later. @@ -153,7 +152,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, this->LocateModules(); // Get the directory in which stamp files will be stored. - const char* stamp_dir = this->TargetDirectory.c_str(); + const std::string& stamp_dir = this->TargetDirectory; // Get the directory in which module files will be created. cmMakefile* mf = this->LocalGenerator->GetMakefile(); @@ -167,9 +166,8 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, typedef cmDependsFortranInternals::ObjectInfoMap ObjectInfoMap; ObjectInfoMap const& objInfo = this->Internal->ObjectInfo; for (auto const& i : objInfo) { - if (!this->WriteDependenciesReal(i.first.c_str(), i.second, mod_dir, - stamp_dir, makeDepends, - internalDepends)) { + if (!this->WriteDependenciesReal(i.first, i.second, mod_dir, stamp_dir, + makeDepends, internalDepends)) { return false; } } @@ -256,22 +254,22 @@ void cmDependsFortran::LocateModules() std::string fname = targetDir + "/fortran.internal"; cmsys::ifstream fin(fname.c_str()); if (fin) { - this->MatchRemoteModules(fin, targetDir.c_str()); + this->MatchRemoteModules(fin, targetDir); } } } void cmDependsFortran::MatchLocalModules() { - const char* stampDir = this->TargetDirectory.c_str(); + std::string const& stampDir = this->TargetDirectory; std::set<std::string> const& provides = this->Internal->TargetProvides; for (std::string const& i : provides) { - this->ConsiderModule(i.c_str(), stampDir); + this->ConsiderModule(i, stampDir); } } void cmDependsFortran::MatchRemoteModules(std::istream& fin, - const char* stampDir) + const std::string& stampDir) { std::string line; bool doing_provides = false; @@ -300,7 +298,8 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin, } } -void cmDependsFortran::ConsiderModule(const char* name, const char* stampDir) +void cmDependsFortran::ConsiderModule(const std::string& name, + const std::string& stampDir) { // Locate each required module. typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap; @@ -317,17 +316,17 @@ void cmDependsFortran::ConsiderModule(const char* name, const char* stampDir) } } -bool cmDependsFortran::WriteDependenciesReal(const char* obj, +bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, cmFortranSourceInfo const& info, std::string const& mod_dir, - const char* stamp_dir, + std::string const& stamp_dir, std::ostream& makeDepends, std::ostream& internalDepends) { typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap; // Get the source file for this object. - const char* src = info.Source.c_str(); + std::string const& src = info.Source; // Write the include dependencies to the output stream. std::string binDir = this->LocalGenerator->GetBinaryDirectory(); @@ -502,8 +501,7 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args) cmFortranModuleAppendUpperLower(cmSystemTools::GetFilenameName(mod), mod_upper, mod_lower); if (cmSystemTools::FileExists(mod_upper, true)) { - if (cmDependsFortran::ModulesDiffer(mod_upper.c_str(), stamp.c_str(), - compilerId.c_str())) { + if (cmDependsFortran::ModulesDiffer(mod_upper, stamp, compilerId)) { if (!cmSystemTools::CopyFileAlways(mod_upper, stamp)) { std::cerr << "Error copying Fortran module from \"" << mod_upper << "\" to \"" << stamp << "\".\n"; @@ -513,8 +511,7 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args) return true; } if (cmSystemTools::FileExists(mod_lower, true)) { - if (cmDependsFortran::ModulesDiffer(mod_lower.c_str(), stamp.c_str(), - compilerId.c_str())) { + if (cmDependsFortran::ModulesDiffer(mod_lower, stamp, compilerId)) { if (!cmSystemTools::CopyFileAlways(mod_lower, stamp)) { std::cerr << "Error copying Fortran module from \"" << mod_lower << "\" to \"" << stamp << "\".\n"; @@ -581,9 +578,9 @@ static bool cmFortranStreamsDiffer(std::istream& ifs1, std::istream& ifs2) return true; } -bool cmDependsFortran::ModulesDiffer(const char* modFile, - const char* stampFile, - const char* compilerId) +bool cmDependsFortran::ModulesDiffer(const std::string& modFile, + const std::string& stampFile, + const std::string& compilerId) { /* gnu >= 4.9: @@ -617,16 +614,17 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, * source is compiled twice * -SunPro */ - if (strcmp(compilerId, "SunPro") == 0) { + if (compilerId == "SunPro") { return cmSystemTools::FilesDiffer(modFile, stampFile); } #if defined(_WIN32) || defined(__CYGWIN__) - cmsys::ifstream finModFile(modFile, std::ios::in | std::ios::binary); - cmsys::ifstream finStampFile(stampFile, std::ios::in | std::ios::binary); + cmsys::ifstream finModFile(modFile.c_str(), std::ios::in | std::ios::binary); + cmsys::ifstream finStampFile(stampFile.c_str(), + std::ios::in | std::ios::binary); #else - cmsys::ifstream finModFile(modFile); - cmsys::ifstream finStampFile(stampFile); + cmsys::ifstream finModFile(modFile.c_str()); + cmsys::ifstream finStampFile(stampFile.c_str()); #endif if (!finModFile || !finStampFile) { // At least one of the files does not exist. The modules differ. @@ -641,7 +639,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, * Eat the stream content until all recompile only related changes * are left behind. */ - if (strcmp(compilerId, "GNU") == 0) { + if (compilerId == "GNU") { // GNU Fortran 4.9 and later compress .mod files with gzip // but also do not include a date so we can fall through to // compare them without skipping any prefix. @@ -664,7 +662,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, return true; } } - } else if (strcmp(compilerId, "Intel") == 0) { + } else if (compilerId == "Intel") { const char seq[2] = { '\n', '\0' }; const int seqlen = 2; diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index 5d96dd4..f5f5be2 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -44,8 +44,9 @@ public: /** Determine if a mod file and the corresponding mod.stamp file are representing different module information. */ - static bool ModulesDiffer(const char* modFile, const char* stampFile, - const char* compilerId); + static bool ModulesDiffer(const std::string& modFile, + const std::string& stampFile, + const std::string& compilerId); protected: // Finalize the dependency information for the target. @@ -55,8 +56,8 @@ protected: // Find all the modules required by the target. void LocateModules(); void MatchLocalModules(); - void MatchRemoteModules(std::istream& fin, const char* stampDir); - void ConsiderModule(const char* name, const char* stampDir); + void MatchRemoteModules(std::istream& fin, const std::string& stampDir); + void ConsiderModule(const std::string& name, const std::string& stampDir); bool FindModule(std::string const& name, std::string& module); // Implement writing/checking methods required by superclass. @@ -65,8 +66,10 @@ protected: std::ostream& internalDepends) override; // Actually write the dependencies to the streams. - bool WriteDependenciesReal(const char* obj, cmFortranSourceInfo const& info, - std::string const& mod_dir, const char* stamp_dir, + bool WriteDependenciesReal(std::string const& obj, + cmFortranSourceInfo const& info, + std::string const& mod_dir, + std::string const& stamp_dir, std::ostream& makeDepends, std::ostream& internalDepends); diff --git a/Source/cmDependsJava.cxx b/Source/cmDependsJava.cxx index 29938ba..b44b3a2 100644 --- a/Source/cmDependsJava.cxx +++ b/Source/cmDependsJava.cxx @@ -27,7 +27,8 @@ bool cmDependsJava::WriteDependencies(const std::set<std::string>& sources, } bool cmDependsJava::CheckDependencies( - std::istream& /*internalDepends*/, const char* /*internalDependsFileName*/, + std::istream& /*internalDepends*/, + const std::string& /*internalDependsFileName*/, std::map<std::string, DependencyVector>& /*validDeps*/) { return true; diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h index d070840..1928c51 100644 --- a/Source/cmDependsJava.h +++ b/Source/cmDependsJava.h @@ -33,7 +33,7 @@ protected: const std::string& file, std::ostream& makeDepends, std::ostream& internalDepends) override; bool CheckDependencies( - std::istream& internalDepends, const char* internalDependsFileName, + std::istream& internalDepends, const std::string& internalDependsFileName, std::map<std::string, DependencyVector>& validDeps) override; }; diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx index 02db119..792db48 100644 --- a/Source/cmDependsJavaParserHelper.cxx +++ b/Source/cmDependsJavaParserHelper.cxx @@ -68,7 +68,7 @@ void cmDependsJavaParserHelper::AddClassFound(const char* sclass) return; } } - this->ClassesFound.push_back(sclass); + this->ClassesFound.emplace_back(sclass); } void cmDependsJavaParserHelper::AddPackagesImport(const char* sclass) @@ -78,7 +78,7 @@ void cmDependsJavaParserHelper::AddPackagesImport(const char* sclass) return; } } - this->PackagesImport.push_back(sclass); + this->PackagesImport.emplace_back(sclass); } void cmDependsJavaParserHelper::SafePrintMissing(const char* str, int line, diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx index ce1965d..418d98c 100644 --- a/Source/cmDisallowedCommand.cxx +++ b/Source/cmDisallowedCommand.cxx @@ -3,7 +3,7 @@ #include "cmDisallowedCommand.h" #include "cmMakefile.h" -#include "cmake.h" +#include "cmMessageType.h" class cmExecutionStatus; @@ -12,7 +12,7 @@ bool cmDisallowedCommand::InitialPass(std::vector<std::string> const& args, { switch (this->Makefile->GetPolicyStatus(this->Policy)) { case cmPolicies::WARN: - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(this->Policy)); break; case cmPolicies::OLD: @@ -20,7 +20,7 @@ bool cmDisallowedCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: - this->Makefile->IssueMessage(cmake::FATAL_ERROR, this->Message); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, this->Message); return true; } diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index 2dfba04..6a817b4 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDocumentation.h" -#include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmDocumentationSection.h" #include "cmRST.h" @@ -55,11 +54,6 @@ cmDocumentation::cmDocumentation() this->ShowGenerators = true; } -cmDocumentation::~cmDocumentation() -{ - cmDeleteAll(this->AllSections); -} - bool cmDocumentation::PrintVersion(std::ostream& os) { /* clang-format off */ @@ -145,10 +139,12 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os) } #define GET_OPT_ARGUMENT(target) \ - if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \ - (target) = argv[i + 1]; \ - i = i + 1; \ - }; + do { \ + if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \ + (target) = argv[i + 1]; \ + i = i + 1; \ + }; \ + } while (false) void cmDocumentation::WarnFormFromFilename( cmDocumentation::RequestedHelpItem& request, bool& result) @@ -174,20 +170,16 @@ void cmDocumentation::WarnFormFromFilename( void cmDocumentation::addCommonStandardDocSections() { - cmDocumentationSection* sec; - - sec = new cmDocumentationSection("Options", "OPTIONS"); - sec->Append(cmDocumentationStandardOptions); - this->AllSections["Options"] = sec; + cmDocumentationSection sec{ "Options" }; + sec.Append(cmDocumentationStandardOptions); + this->AllSections.emplace("Options", std::move(sec)); } void cmDocumentation::addCMakeStandardDocSections() { - cmDocumentationSection* sec; - - sec = new cmDocumentationSection("Generators", "GENERATORS"); - sec->Append(cmDocumentationGeneratorsHeader); - this->AllSections["Generators"] = sec; + cmDocumentationSection sec{ "Generators" }; + sec.Append(cmDocumentationGeneratorsHeader); + this->AllSections.emplace("Generators", std::move(sec)); } void cmDocumentation::addCTestStandardDocSections() @@ -199,11 +191,7 @@ void cmDocumentation::addCTestStandardDocSections() void cmDocumentation::addCPackStandardDocSections() { - cmDocumentationSection* sec; - - sec = new cmDocumentationSection("Generators", "GENERATORS"); - sec->Append(cmDocumentationGeneratorsHeader); - this->AllSections["Generators"] = sec; + addCMakeStandardDocSections(); } bool cmDocumentation::CheckOptions(int argc, const char* const* argv, @@ -364,91 +352,59 @@ void cmDocumentation::SetName(const std::string& name) } void cmDocumentation::SetSection(const char* name, - cmDocumentationSection* section) + cmDocumentationSection section) { - if (this->AllSections.find(name) != this->AllSections.end()) { - delete this->AllSections[name]; - } - this->AllSections[name] = section; + this->SectionAtName(name) = std::move(section); } void cmDocumentation::SetSection(const char* name, std::vector<cmDocumentationEntry>& docs) { - cmDocumentationSection* sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - sec->Append(docs); - this->SetSection(name, sec); + cmDocumentationSection sec{ name }; + sec.Append(docs); + this->SetSection(name, std::move(sec)); } void cmDocumentation::SetSection(const char* name, const char* docs[][2]) { - cmDocumentationSection* sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - sec->Append(docs); - this->SetSection(name, sec); + cmDocumentationSection sec{ name }; + sec.Append(docs); + this->SetSection(name, std::move(sec)); } void cmDocumentation::SetSections( - std::map<std::string, cmDocumentationSection*>& sections) + std::map<std::string, cmDocumentationSection> sections) { - for (auto const& s : sections) { - this->SetSection(s.first.c_str(), s.second); + for (auto& s : sections) { + this->SetSection(s.first.c_str(), std::move(s.second)); } } +cmDocumentationSection& cmDocumentation::SectionAtName(const char* name) +{ + return this->AllSections.emplace(name, cmDocumentationSection{ name }) + .first->second; +} void cmDocumentation::PrependSection(const char* name, const char* docs[][2]) { - cmDocumentationSection* sec = nullptr; - if (this->AllSections.find(name) == this->AllSections.end()) { - sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - this->SetSection(name, sec); - } else { - sec = this->AllSections[name]; - } - sec->Prepend(docs); + this->SectionAtName(name).Prepend(docs); } void cmDocumentation::PrependSection(const char* name, std::vector<cmDocumentationEntry>& docs) { - cmDocumentationSection* sec = nullptr; - if (this->AllSections.find(name) == this->AllSections.end()) { - sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - this->SetSection(name, sec); - } else { - sec = this->AllSections[name]; - } - sec->Prepend(docs); + this->SectionAtName(name).Prepend(docs); } void cmDocumentation::AppendSection(const char* name, const char* docs[][2]) { - cmDocumentationSection* sec = nullptr; - if (this->AllSections.find(name) == this->AllSections.end()) { - sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - this->SetSection(name, sec); - } else { - sec = this->AllSections[name]; - } - sec->Append(docs); + this->SectionAtName(name).Append(docs); } void cmDocumentation::AppendSection(const char* name, std::vector<cmDocumentationEntry>& docs) { - cmDocumentationSection* sec = nullptr; - if (this->AllSections.find(name) == this->AllSections.end()) { - sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - this->SetSection(name, sec); - } else { - sec = this->AllSections[name]; - } - sec->Append(docs); + this->SectionAtName(name).Append(docs); } void cmDocumentation::AppendSection(const char* name, @@ -631,11 +587,10 @@ bool cmDocumentation::PrintHelpListPolicies(std::ostream& os) bool cmDocumentation::PrintHelpListGenerators(std::ostream& os) { - std::map<std::string, cmDocumentationSection*>::iterator si; - si = this->AllSections.find("Generators"); + const auto si = this->AllSections.find("Generators"); if (si != this->AllSections.end()) { this->Formatter.SetIndent(" "); - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } return true; } @@ -661,29 +616,27 @@ bool cmDocumentation::PrintHelpListVariables(std::ostream& os) bool cmDocumentation::PrintUsage(std::ostream& os) { - std::map<std::string, cmDocumentationSection*>::iterator si; - si = this->AllSections.find("Usage"); + const auto si = this->AllSections.find("Usage"); if (si != this->AllSections.end()) { - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } return true; } bool cmDocumentation::PrintHelp(std::ostream& os) { - std::map<std::string, cmDocumentationSection*>::iterator si; - si = this->AllSections.find("Usage"); + auto si = this->AllSections.find("Usage"); if (si != this->AllSections.end()) { - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } si = this->AllSections.find("Options"); if (si != this->AllSections.end()) { - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } if (this->ShowGenerators) { si = this->AllSections.find("Generators"); if (si != this->AllSections.end()) { - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } } return true; diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 153bad6..b2ff01a 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -6,13 +6,13 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmDocumentationFormatter.h" +#include "cmDocumentationSection.h" #include <iosfwd> #include <map> #include <string> #include <vector> -class cmDocumentationSection; struct cmDocumentationEntry; /** Class to generate documentation. */ @@ -21,8 +21,6 @@ class cmDocumentation : public cmDocumentationEnums public: cmDocumentation(); - ~cmDocumentation(); - /** * Check command line arguments for documentation options. Returns * true if documentation options are found, and false otherwise. @@ -52,11 +50,11 @@ public: /** Set a section of the documentation. Typical sections include Name, Usage, Description, Options */ - void SetSection(const char* sectionName, cmDocumentationSection* section); + void SetSection(const char* sectionName, cmDocumentationSection section); void SetSection(const char* sectionName, std::vector<cmDocumentationEntry>& docs); void SetSection(const char* sectionName, const char* docs[][2]); - void SetSections(std::map<std::string, cmDocumentationSection*>& sections); + void SetSections(std::map<std::string, cmDocumentationSection> sections); /** Add the documentation to the beginning/end of the section */ void PrependSection(const char* sectionName, const char* docs[][2]); @@ -110,7 +108,8 @@ private: bool ShowGenerators; std::string NameString; - std::map<std::string, cmDocumentationSection*> AllSections; + std::map<std::string, cmDocumentationSection> AllSections; + cmDocumentationSection& SectionAtName(const char* name); std::string CurrentArgument; diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h index d9e8187..7031b52 100644 --- a/Source/cmDocumentationSection.h +++ b/Source/cmDocumentationSection.h @@ -19,7 +19,7 @@ class cmDocumentationSection { public: /** Create a cmSection, with a special name for man-output mode. */ - cmDocumentationSection(const char* name, const char*) + explicit cmDocumentationSection(const char* name) : Name(name) { } diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index e7f8a01..75a7786 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -221,7 +221,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, if (p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) { if (verbose) { processOutput.DecodeText(data, length, strdata); - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } output.append(data, length); } @@ -230,7 +230,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, if (verbose) { processOutput.DecodeText(std::string(), strdata); if (!strdata.empty()) { - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } } @@ -270,7 +270,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, } msg += "\n"; if (verbose) { - cmSystemTools::Stdout(msg.c_str()); + cmSystemTools::Stdout(msg); } output += msg; #else diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index b549776..8c67cdb 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -54,7 +54,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, if (args[i] == "COMMAND") { doing_command = true; command_index = cmds.size(); - cmds.push_back(std::vector<const char*>()); + cmds.emplace_back(); } else if (args[i] == "OUTPUT_VARIABLE") { doing_command = false; if (++i < args.size()) { @@ -249,14 +249,14 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) { if (output_variable.empty()) { processOutput.DecodeText(data, length, strdata, 1); - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } else { cmExecuteProcessCommandAppend(tempOutput, data, length); } } else if (p == cmsysProcess_Pipe_STDERR && !error_quiet) { if (error_variable.empty()) { processOutput.DecodeText(data, length, strdata, 2); - cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + cmSystemTools::Stderr(strdata); } else { cmExecuteProcessCommandAppend(tempError, data, length); } @@ -265,13 +265,13 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, if (!output_quiet && output_variable.empty()) { processOutput.DecodeText(std::string(), strdata, 1); if (!strdata.empty()) { - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } } if (!error_quiet && error_variable.empty()) { processOutput.DecodeText(std::string(), strdata, 2); if (!strdata.empty()) { - cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + cmSystemTools::Stderr(strdata); } } @@ -327,15 +327,15 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, cmsysProcess_GetExitValueByIndex(cp, static_cast<int>(i)); char buf[16]; sprintf(buf, "%d", exitCode); - res.push_back(buf); + res.emplace_back(buf); } break; case kwsysProcess_StateByIndex_Exception: - res.push_back(cmsysProcess_GetExceptionStringByIndex( + res.emplace_back(cmsysProcess_GetExceptionStringByIndex( cp, static_cast<int>(i))); break; case kwsysProcess_StateByIndex_Error: default: - res.push_back("Error getting the child return code"); + res.emplace_back("Error getting the child return code"); break; } } diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index d12ad7f..ced27c9 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -11,11 +11,11 @@ #include "cmGeneratorTarget.h" #include "cmLinkItem.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" cmExportBuildAndroidMKGenerator::cmExportBuildAndroidMKGenerator() { @@ -92,7 +92,7 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( } w << " set to OLD for target " << target->Target->GetName() << ". " << "The export will only work with CMP0022 set to NEW."; - target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } if (!properties.empty()) { os << "LOCAL_CPP_FEATURES := rtti exceptions\n"; diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 024e641..012355b 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -9,6 +9,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -55,7 +56,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) std::ostringstream e; e << "given target \"" << te->GetName() << "\" more than once."; this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e.str(), + MessageType::FATAL_ERROR, e.str(), this->LG->GetMakefile()->GetBacktrace()); return false; } @@ -110,7 +111,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) std::string errorMessage; if (!this->PopulateExportProperties(gte, properties, errorMessage)) { this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, errorMessage, + MessageType::FATAL_ERROR, errorMessage, this->LG->GetMakefile()->GetBacktrace()); return false; } @@ -328,7 +329,8 @@ void cmExportBuildFileGenerator::ComplainAboutMissingTarget( << "consider using the APPEND option with multiple separate calls."; this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e.str(), this->LG->GetMakefile()->GetBacktrace()); + MessageType::FATAL_ERROR, e.str(), + this->LG->GetMakefile()->GetBacktrace()); } std::string cmExportBuildFileGenerator::InstallNameDir( diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 3706a3c..722831a 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -12,10 +12,10 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -279,7 +279,7 @@ void cmExportCommand::ReportRegistryError(std::string const& msg, e << "Windows reported:\n" << " " << cmsys::Encoding::ToNarrow(winmsg); } - this->Makefile->IssueMessage(cmake::WARNING, e.str()); + this->Makefile->IssueMessage(MessageType::WARNING, e.str()); } void cmExportCommand::StorePackageRegistryWin(std::string const& package, @@ -347,7 +347,7 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package, << " " << fname << "\n" << cmSystemTools::GetLastSystemError() << "\n"; /* clang-format on */ - this->Makefile->IssueMessage(cmake::WARNING, e.str()); + this->Makefile->IssueMessage(MessageType::WARNING, e.str()); } } } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index df27c62..c6b66a3 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -9,6 +9,7 @@ #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmProperty.h" @@ -17,7 +18,6 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" -#include "cmake.h" #include "cmsys/FStream.hxx" #include <assert.h> @@ -214,13 +214,13 @@ static bool checkInterfaceDirs(const std::string& prepro, if (genexPos == 0) { continue; } - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; std::ostringstream e; if (genexPos != std::string::npos) { if (prop == "INTERFACE_INCLUDE_DIRECTORIES") { switch (target->GetPolicyStatusCMP0041()) { case cmPolicies::WARN: - messageType = cmake::WARNING; + messageType = MessageType::WARNING; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n"; break; case cmPolicies::OLD: @@ -275,8 +275,8 @@ static bool checkInterfaceDirs(const std::string& prepro, << (inBinary ? "build" : "source") << " tree:\n \"" << (inBinary ? topBinaryDir : topSourceDir) << "\"" << std::endl; - target->GetLocalGenerator()->IssueMessage(cmake::AUTHOR_WARNING, - s.str()); + target->GetLocalGenerator()->IssueMessage( + MessageType::AUTHOR_WARNING, s.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -390,7 +390,7 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( "depend on the configuration, policy values or the link interface " "are " "not supported. Consider using target_include_directories instead."; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -520,7 +520,7 @@ void getCompatibleInterfaceProperties(cmGeneratorTarget* target, e << "Exporting the target \"" << target->GetName() << "\" is not " "allowed since its linker language cannot be determined"; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -727,7 +727,8 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( this->ReplaceInstallPrefix(input); if (!errorString.empty()) { - target->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, errorString); + target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR, + errorString); } } @@ -780,7 +781,7 @@ void cmExportFileGenerator::SetImportLinkInterface( "but also has old-style LINK_INTERFACE_LIBRARIES properties " "populated, but it was exported without the " "EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties"; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 93115b6..3821144 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -4,6 +4,7 @@ #include "cmAlgorithms.h" #include "cmExportSet.h" +#include "cmExportSetMap.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -21,8 +22,6 @@ #include <sstream> #include <utility> -class cmExportSetMap; - cmExportInstallFileGenerator::cmExportInstallFileGenerator( cmInstallExportGenerator* iegen) : IEGen(iegen) diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index e7f3ada..5833631 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -5,6 +5,7 @@ #include "cmsys/RegularExpression.hxx" #include <algorithm> #include <assert.h> +#include <map> #include <sstream> #include <stdio.h> #include <utility> @@ -15,6 +16,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" #include "cmState.h" @@ -133,7 +135,7 @@ void cmExtraEclipseCDT4Generator::Generate() if (!this->GenerateSourceProject && (mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"))) { mf->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT is set to TRUE, " "but this variable is not supported anymore since CMake 2.8.7.\n" "Enable CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT instead."); @@ -141,7 +143,7 @@ void cmExtraEclipseCDT4Generator::Generate() if (cmSystemTools::IsSubDirectory(this->HomeOutputDirectory, this->HomeDirectory)) { - mf->IssueMessage(cmake::WARNING, + mf->IssueMessage(MessageType::WARNING, "The build directory is a subdirectory " "of the source directory.\n" "This is not supported well by Eclipse. It is strongly " @@ -381,7 +383,6 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() xml.StartElement("natures"); xml.Element("nature", "org.eclipse.cdt.make.core.makeNature"); xml.Element("nature", "org.eclipse.cdt.make.core.ScannerConfigNature"); - ; for (std::string const& n : this->Natures) { xml.Element("nature", n); diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 0a1886a..739a177 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -14,6 +14,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -154,7 +155,7 @@ void cmExtraSublimeTextGenerator::CreateNewProjectFile( e << "Could not parse Env Vars specified in " "\"CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS\"" << ", corrupted string " << t; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); } } fout << "\n\t\t}"; diff --git a/Source/cmFileAPICMakeFiles.cxx b/Source/cmFileAPICMakeFiles.cxx index 799a047..5590bc2 100644 --- a/Source/cmFileAPICMakeFiles.cxx +++ b/Source/cmFileAPICMakeFiles.cxx @@ -12,6 +12,7 @@ #include "cm_jsoncpp_value.h" #include <string> +#include <vector> namespace { diff --git a/Source/cmFileAPICache.cxx b/Source/cmFileAPICache.cxx index 074994a..f96bc90 100644 --- a/Source/cmFileAPICache.cxx +++ b/Source/cmFileAPICache.cxx @@ -10,6 +10,7 @@ #include <algorithm> #include <string> +#include <utility> #include <vector> namespace { diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index fc9c1d2..999af54 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -17,6 +17,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <utility> #include <vector> #include "cmAlgorithms.h" @@ -31,6 +32,7 @@ #include "cmInstallType.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" #include "cmTimestamp.h" @@ -183,6 +185,9 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args, if (subCommand == "READ_SYMLINK") { return this->HandleReadSymlinkCommand(args); } + if (subCommand == "CREATE_LINK") { + return this->HandleCreateLinkCommand(args); + } std::string e = "does not recognize sub-command " + subCommand; this->SetError(e); @@ -833,13 +838,13 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, // Generated build system depends on glob results if (!configureDepends && warnConfigureLate) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "CONFIGURE_DEPENDS flag was given after a glob expression was " "already evaluated."); } if (workingMode != cmake::NORMAL_MODE) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CONFIGURE_DEPENDS is invalid for script and find package modes."); return false; } @@ -870,12 +875,12 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, for (cmsys::Glob::Message const& globMessage : globMessages) { if (globMessage.type == cmsys::Glob::cyclicRecursion) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "Cyclic recursion detected while globbing for '" + *i + "':\n" + globMessage.content); } else { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Error has occurred while globbing for '" + *i + "' - " + globMessage.content); shouldExit = true; @@ -924,7 +929,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, // symlinks without being explicitly asked to: warn the author. if (warnFollowedSymlinks) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0009)); } break; @@ -2698,12 +2703,14 @@ private: #endif #define check_curl_result(result, errstr) \ - if (result != CURLE_OK) { \ - std::string e(errstr); \ - e += ::curl_easy_strerror(result); \ - this->SetError(e); \ - return false; \ - } + do { \ + if (result != CURLE_OK) { \ + std::string e(errstr); \ + e += ::curl_easy_strerror(result); \ + this->SetError(e); \ + return false; \ + } \ + } while (false) bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) { @@ -2852,7 +2859,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) // Do not return error for compatibility reason. std::string err = "Unexpected argument: "; err += *i; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, err); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, err); } ++i; } @@ -3168,7 +3175,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) // Do not return error for compatibility reason. std::string err = "Unexpected argument: "; err += *i; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, err); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, err); } ++i; @@ -3426,7 +3433,8 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) // Parse arguments if (args.size() < 2) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "sub-command LOCK requires at least two arguments."); + MessageType::FATAL_ERROR, + "sub-command LOCK requires at least two arguments."); return false; } @@ -3440,7 +3448,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) ++i; const char* merr = "expected FUNCTION, FILE or PROCESS after GUARD"; if (i >= args.size()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, merr); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, merr); return false; } if (args[i] == "FUNCTION") { @@ -3452,7 +3460,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) } else { std::ostringstream e; e << merr << ", but got:\n \"" << args[i] << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -3460,14 +3468,15 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) ++i; if (i >= args.size()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "expected variable name after RESULT_VARIABLE"); + MessageType::FATAL_ERROR, + "expected variable name after RESULT_VARIABLE"); return false; } resultVariable = args[i]; } else if (args[i] == "TIMEOUT") { ++i; if (i >= args.size()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "expected timeout value after TIMEOUT"); return false; } @@ -3476,7 +3485,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) scanned < 0) { std::ostringstream e; e << "TIMEOUT value \"" << args[i] << "\" is not an unsigned integer."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } timeout = static_cast<unsigned long>(scanned); @@ -3484,7 +3493,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) std::ostringstream e; e << "expected DIRECTORY, RELEASE, GUARD, RESULT_VARIABLE or TIMEOUT\n"; e << "but got: \"" << args[i] << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } } @@ -3506,7 +3515,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) std::ostringstream e; e << "directory\n \"" << parentDir << "\"\ncreation failed "; e << "(check permissions)."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -3514,7 +3523,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) if (!file) { std::ostringstream e; e << "file\n \"" << path << "\"\ncreation failed (check permissions)."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -3549,7 +3558,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) if (resultVariable.empty() && !fileLockResult.IsOk()) { std::ostringstream e; e << "error locking file\n \"" << path << "\"\n" << result << "."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -3664,3 +3673,119 @@ bool cmFileCommand::HandleReadSymlinkCommand( return true; } + +bool cmFileCommand::HandleCreateLinkCommand( + std::vector<std::string> const& args) +{ + if (args.size() < 3) { + this->SetError("CREATE_LINK must be called with at least two additional " + "arguments"); + return false; + } + + cmCommandArgumentsHelper argHelper; + cmCommandArgumentGroup group; + + cmCAString linkArg(&argHelper, "CREATE_LINK"); + cmCAString fileArg(&argHelper, nullptr); + cmCAString newFileArg(&argHelper, nullptr); + + cmCAString resultArg(&argHelper, "RESULT", &group); + cmCAEnabler copyOnErrorArg(&argHelper, "COPY_ON_ERROR", &group); + cmCAEnabler symbolicArg(&argHelper, "SYMBOLIC", &group); + + linkArg.Follows(nullptr); + fileArg.Follows(&linkArg); + newFileArg.Follows(&fileArg); + group.Follows(&newFileArg); + + std::vector<std::string> unconsumedArgs; + argHelper.Parse(&args, &unconsumedArgs); + + if (!unconsumedArgs.empty()) { + this->SetError("unknown argument: \"" + unconsumedArgs.front() + '\"'); + return false; + } + + std::string fileName = fileArg.GetString(); + std::string newFileName = newFileArg.GetString(); + + // Output variable for storing the result. + const std::string& resultVar = resultArg.GetString(); + + // The system error message generated in the operation. + std::string result; + + // Check if the paths are distinct. + if (fileName == newFileName) { + result = "CREATE_LINK cannot use same file and newfile"; + if (!resultVar.empty()) { + this->Makefile->AddDefinition(resultVar, result.c_str()); + return true; + } + this->SetError(result); + return false; + } + + // Hard link requires original file to exist. + if (!symbolicArg.IsEnabled() && !cmSystemTools::FileExists(fileName)) { + result = "Cannot hard link \'" + fileName + "\' as it does not exist."; + if (!resultVar.empty()) { + this->Makefile->AddDefinition(resultVar, result.c_str()); + return true; + } + this->SetError(result); + return false; + } + + // Check if the new file already exists and remove it. + if ((cmSystemTools::FileExists(newFileName) || + cmSystemTools::FileIsSymlink(newFileName)) && + !cmSystemTools::RemoveFile(newFileName)) { + std::ostringstream e; + e << "Failed to create link '" << newFileName + << "' because existing path cannot be removed: " + << cmSystemTools::GetLastSystemError() << "\n"; + + if (!resultVar.empty()) { + this->Makefile->AddDefinition(resultVar, e.str().c_str()); + return true; + } + this->SetError(e.str()); + return false; + } + + // Whether the operation completed successfully. + bool completed = false; + + // Check if the command requires a symbolic link. + if (symbolicArg.IsEnabled()) { + completed = cmSystemTools::CreateSymlink(fileName, newFileName, &result); + } else { + completed = cmSystemTools::CreateLink(fileName, newFileName, &result); + } + + // Check if copy-on-error is enabled in the arguments. + if (!completed && copyOnErrorArg.IsEnabled()) { + completed = + cmSystemTools::cmCopyFile(fileName.c_str(), newFileName.c_str()); + if (!completed) { + result = "Copy failed: " + cmSystemTools::GetLastSystemError(); + } + } + + // Check if the operation was successful. + if (completed) { + result = "0"; + } else if (resultVar.empty()) { + // The operation failed and the result is not reported in a variable. + this->SetError(result); + return false; + } + + if (!resultVar.empty()) { + this->Makefile->AddDefinition(resultVar, result.c_str()); + } + + return true; +} diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index fe05c98..12c5115 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -61,6 +61,7 @@ protected: bool HandleLockCommand(std::vector<std::string> const& args); bool HandleSizeCommand(std::vector<std::string> const& args); bool HandleReadSymlinkCommand(std::vector<std::string> const& args); + bool HandleCreateLinkCommand(std::vector<std::string> const& args); private: void AddEvaluationFile(const std::string& inputName, diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 009f0e3..39051b9 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -178,13 +178,13 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) cmSystemTools::ExpandListArgument(rootPath, roots); } if (sysrootCompile) { - roots.push_back(sysrootCompile); + roots.emplace_back(sysrootCompile); } if (sysrootLink) { - roots.push_back(sysrootLink); + roots.emplace_back(sysrootLink); } if (sysroot) { - roots.push_back(sysroot); + roots.emplace_back(sysroot); } for (std::string& r : roots) { cmSystemTools::ConvertToUnixSlashes(r); diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 5a5d036..bcf876d 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -7,6 +7,7 @@ #include <set> #include <stdio.h> #include <string.h> +#include <utility> #include "cmGlobalGenerator.h" #include "cmMakefile.h" diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 3d9cd08..9ae1cb9 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -21,12 +21,12 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSearchPath.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmVersion.h" -#include "cmake.h" #if defined(__HAIKU__) # include <FindDirectory.h> @@ -95,6 +95,7 @@ cmFindPackageCommand::cmFindPackageCommand() this->UseLib32Paths = false; this->UseLib64Paths = false; this->UseLibx32Paths = false; + this->UseRealPath = false; this->PolicyScope = true; this->VersionMajor = 0; this->VersionMinor = 0; @@ -195,6 +196,11 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, this->NoSystemRegistry = true; } + // Check whether we should resolve symlinks when finding packages + if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS")) { + this->UseRealPath = true; + } + // Check if Sorting should be enabled if (const char* so = this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) { @@ -384,7 +390,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, if (this->Version.empty() && this->VersionExact) { this->VersionExact = false; this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, "Ignoring EXACT since no version is requested."); + MessageType::AUTHOR_WARNING, + "Ignoring EXACT since no version is requested."); } if (this->Version.empty() || components.empty()) { @@ -473,7 +480,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0074)); break; case cmPolicies::NEW: { @@ -536,7 +543,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, } aw << "\n" "(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this warning.)"; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str()); } // No find module. Assume the project has a CMake config file. Use @@ -667,7 +674,7 @@ bool cmFindPackageCommand::FindModule(bool& found) case cmPolicies::WARN: { std::ostringstream e; e << cmPolicies::GetPolicyWarning(it->second) << "\n"; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -736,7 +743,8 @@ bool cmFindPackageCommand::HandlePackageMode() // Sanity check. if (fileFound && this->FileFound.empty()) { this->Makefile->IssueMessage( - cmake::INTERNAL_ERROR, "fileFound is true but FileFound is empty!"); + MessageType::INTERNAL_ERROR, + "fileFound is true but FileFound is empty!"); fileFound = false; } } @@ -887,14 +895,15 @@ bool cmFindPackageCommand::HandlePackageMode() } } - this->Makefile->IssueMessage( - this->Required ? cmake::FATAL_ERROR : cmake::WARNING, e.str()); + this->Makefile->IssueMessage(this->Required ? MessageType::FATAL_ERROR + : MessageType::WARNING, + e.str()); if (this->Required) { cmSystemTools::SetFatalErrorOccured(); } if (!aw.str().empty()) { - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str()); } } // output result if in config mode but not in quiet mode @@ -1499,6 +1508,10 @@ bool cmFindPackageCommand::FindConfigFile(std::string const& dir, fprintf(stderr, "Checking file [%s]\n", file.c_str()); } if (cmSystemTools::FileExists(file, true) && this->CheckVersion(file)) { + // Allow resolving symlinks when the config file is found through a link + if (this->UseRealPath) { + file = cmSystemTools::GetRealPath(file); + } return true; } } @@ -1845,7 +1858,7 @@ private: } for (std::string const& n : this->Names) { if (cmsysString_strncasecmp(fname, n.c_str(), n.length()) == 0) { - matches.push_back(fname); + matches.emplace_back(fname); } } } @@ -1904,7 +1917,7 @@ private: for (std::string name : this->Names) { name += this->Extension; if (cmsysString_strcasecmp(fname, name.c_str()) == 0) { - matches.push_back(fname); + matches.emplace_back(fname); } } } @@ -2067,16 +2080,16 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) common.push_back("lib/" + this->LibraryArchitecture); } if (this->UseLib32Paths) { - common.push_back("lib32"); + common.emplace_back("lib32"); } if (this->UseLib64Paths) { - common.push_back("lib64"); + common.emplace_back("lib64"); } if (this->UseLibx32Paths) { - common.push_back("libx32"); + common.emplace_back("libx32"); } - common.push_back("lib"); - common.push_back("share"); + common.emplace_back("lib"); + common.emplace_back("share"); // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/ { diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 05bad49..83d8431 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -178,6 +178,7 @@ private: bool UseLib32Paths; bool UseLib64Paths; bool UseLibx32Paths; + bool UseRealPath; bool PolicyScope; std::string LibraryArchitecture; std::vector<std::string> Names; diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 739c9c0..e359def 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -10,8 +10,8 @@ #include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf) : Makefile(mf) @@ -164,7 +164,7 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args, break; } sprintf(buffer, "%d", cc); - range.push_back(buffer); + range.emplace_back(buffer); if (cc == stop) { break; } @@ -210,7 +210,7 @@ bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args) std::ostringstream e; e << "Unknown argument:\n" << " " << args[i] << "\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return true; } } diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 56eb2bf..61b798b 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -7,6 +7,7 @@ #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" +#include "cmMessageType.h" #include "cmake.h" #include <sstream> @@ -55,7 +56,7 @@ void cmGeneratorExpressionDAGChecker::Initialize() if (CheckResult == DAG && (CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD( - TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(clang-tidy) + TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(*) #undef TEST_TRANSITIVE_PROPERTY_METHOD { std::map<cmGeneratorTarget const*, std::set<std::string>>::const_iterator @@ -99,8 +100,8 @@ void cmGeneratorExpressionDAGChecker::ReportError( << " " << expr << "\n" << "Self reference on target \"" << context->HeadTarget->GetName() << "\".\n"; - context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - parent->Backtrace); + context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), parent->Backtrace); return; } @@ -111,8 +112,8 @@ void cmGeneratorExpressionDAGChecker::ReportError( << " " << expr << "\n" << "Dependency loop found."; /* clang-format on */ - context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - context->Backtrace); + context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), context->Backtrace); } int loopStep = 1; @@ -122,8 +123,8 @@ void cmGeneratorExpressionDAGChecker::ReportError( << " " << (parent->Content ? parent->Content->GetOriginalExpression() : expr) << "\n"; - context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - parent->Backtrace); + context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), parent->Backtrace); parent = parent->Parent; ++loopStep; } diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index e7a55e0..1c33a6e 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -12,10 +12,10 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmSourceFileLocationKind.h" #include "cmSystemTools.h" -#include "cmake.h" cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile( const std::string& input, @@ -48,7 +48,7 @@ void cmGeneratorExpressionEvaluationFile::Generate( << "\" did " "not evaluate to valid content. Got \"" << condResult << "\"."; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } } @@ -77,7 +77,7 @@ void cmGeneratorExpressionEvaluationFile::Generate( "This is generally caused by the content evaluating the " "configuration type, language, or location of object files:\n " << outputFileName; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -137,7 +137,7 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg) if (!fin) { std::ostringstream e; e << "Evaluation file \"" << inputFileName << "\" cannot be read."; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -204,7 +204,7 @@ std::string cmGeneratorExpressionEvaluationFile::FixRelativePath( "undefined behavior will be used." ; /* clang-format on */ - lg->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + lg->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } CM_FALLTHROUGH; case cmPolicies::OLD: diff --git a/Source/cmGeneratorExpressionLexer.cxx b/Source/cmGeneratorExpressionLexer.cxx index 242915d..dd1e243 100644 --- a/Source/cmGeneratorExpressionLexer.cxx +++ b/Source/cmGeneratorExpressionLexer.cxx @@ -20,8 +20,8 @@ std::vector<cmGeneratorExpressionToken> cmGeneratorExpressionLexer::Tokenize( std::vector<cmGeneratorExpressionToken> result; if (input.find('$') == std::string::npos) { - result.push_back(cmGeneratorExpressionToken( - cmGeneratorExpressionToken::Text, input.c_str(), input.size())); + result.emplace_back(cmGeneratorExpressionToken::Text, input.c_str(), + input.size()); return result; } diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index eb3df16..6a3f73d 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -12,6 +12,7 @@ #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmStateTypes.h" @@ -304,7 +305,7 @@ static const struct InListNode : public cmGeneratorExpressionNode << "\nSearch Item:\n \"" << parameters.front() << "\"\nList:\n \"" << parameters[1] << "\"\n"; context->LG->GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, e.str(), context->Backtrace); + MessageType ::AUTHOR_WARNING, e.str(), context->Backtrace); return "0"; } if (values.empty()) { @@ -632,7 +633,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044); context->LG->GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, e.str(), context->Backtrace); + MessageType::AUTHOR_WARNING, e.str(), context->Backtrace); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -691,6 +692,28 @@ static const struct CXXCompilerIdNode : public CompilerIdNode } } cxxCompilerIdNode; +static const struct FortranCompilerIdNode : public CompilerIdNode +{ + FortranCompilerIdNode() {} + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget) { + reportError( + context, content->GetOriginalExpression(), + "$<Fortran_COMPILER_ID> may only be used with binary targets. It may " + "not be used with add_custom_command or add_custom_target."); + return std::string(); + } + return this->EvaluateWithLanguage(parameters, context, content, dagChecker, + "Fortran"); + } +} fortranCompilerIdNode; + struct CompilerVersionNode : public cmGeneratorExpressionNode { CompilerVersionNode() {} @@ -772,6 +795,28 @@ static const struct CxxCompilerVersionNode : public CompilerVersionNode } } cxxCompilerVersionNode; +static const struct FortranCompilerVersionNode : public CompilerVersionNode +{ + FortranCompilerVersionNode() {} + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget) { + reportError( + context, content->GetOriginalExpression(), + "$<Fortran_COMPILER_VERSION> may only be used with binary targets. " + "It may not be used with add_custom_command or add_custom_target."); + return std::string(); + } + return this->EvaluateWithLanguage(parameters, context, content, dagChecker, + "Fortran"); + } +} fortranCompilerVersionNode; + struct PlatformIdNode : public cmGeneratorExpressionNode { PlatformIdNode() {} @@ -1257,7 +1302,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode #define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \ (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) || if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME( - TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(clang-tidy) + TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(*) reportError( context, content->GetOriginalExpression(), "$<TARGET_PROPERTY:...> expression in link libraries " @@ -1654,7 +1699,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode switch (statusForTarget(context->HeadTarget, policy)) { case cmPolicies::WARN: lg->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(policyForString(policy))); CM_FALLTHROUGH; case cmPolicies::REQUIRED_IF_USED: @@ -2023,6 +2068,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( nodeMap["NOT"] = ¬Node; nodeMap["C_COMPILER_ID"] = &cCompilerIdNode; nodeMap["CXX_COMPILER_ID"] = &cxxCompilerIdNode; + nodeMap["Fortran_COMPILER_ID"] = &fortranCompilerIdNode; nodeMap["VERSION_GREATER"] = &versionGreaterNode; nodeMap["VERSION_GREATER_EQUAL"] = &versionGreaterEqNode; nodeMap["VERSION_LESS"] = &versionLessNode; @@ -2030,6 +2076,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( nodeMap["VERSION_EQUAL"] = &versionEqualNode; nodeMap["C_COMPILER_VERSION"] = &cCompilerVersionNode; nodeMap["CXX_COMPILER_VERSION"] = &cxxCompilerVersionNode; + nodeMap["Fortran_COMPILER_VERSION"] = &fortranCompilerVersionNode; nodeMap["PLATFORM_ID"] = &platformIdNode; nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode; nodeMap["CONFIGURATION"] = &configurationNode; @@ -2096,6 +2143,6 @@ void reportError(cmGeneratorExpressionContext* context, << " " << expr << "\n" << result; /* clang-format on */ - context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - context->Backtrace); + context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), context->Backtrace); } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 80d81d5..eb3d4af 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -25,6 +25,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPropertyMap.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" @@ -318,7 +319,7 @@ std::string cmGeneratorTarget::GetOutputName( props.push_back(configUpper + "_OUTPUT_NAME"); } // OUTPUT_NAME - props.push_back("OUTPUT_NAME"); + props.emplace_back("OUTPUT_NAME"); std::string outName; for (std::string const& p : props) { @@ -340,7 +341,7 @@ std::string cmGeneratorTarget::GetOutputName( // An empty map entry indicates we have been called recursively // from the above block. this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.", this->GetBacktrace()); } @@ -354,20 +355,22 @@ void cmGeneratorTarget::ClearSourcesCache() this->Objects.clear(); } -void cmGeneratorTarget::AddSourceCommon(const std::string& src) +void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(lfbt); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src); cge->SetEvaluateForBuildsystem(true); - this->SourceEntries.push_back(new TargetPropertyEntry(std::move(cge))); + this->SourceEntries.insert(before ? this->SourceEntries.begin() + : this->SourceEntries.end(), + new TargetPropertyEntry(std::move(cge))); this->ClearSourcesCache(); } -void cmGeneratorTarget::AddSource(const std::string& src) +void cmGeneratorTarget::AddSource(const std::string& src, bool before) { - this->Target->AddSource(src); - this->AddSourceCommon(src); + this->Target->AddSource(src, before); + this->AddSourceCommon(src, before); } void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs) @@ -386,12 +389,10 @@ void cmGeneratorTarget::AddIncludeDirectory(const std::string& src, cmGeneratorExpression ge(lfbt); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src); cge->SetEvaluateForBuildsystem(true); - // Insert before begin/end - std::vector<TargetPropertyEntry*>::iterator pos = before - ? this->IncludeDirectoriesEntries.begin() - : this->IncludeDirectoriesEntries.end(); this->IncludeDirectoriesEntries.insert( - pos, new TargetPropertyEntry(std::move(cge))); + before ? this->IncludeDirectoriesEntries.begin() + : this->IncludeDirectoriesEntries.end(), + new TargetPropertyEntry(std::move(cge))); } std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends( @@ -435,14 +436,14 @@ static void handleSystemIncludesDep( /* clang-format off */ #define IMPLEMENT_VISIT(KIND) \ - { \ + do { \ KindedSources const& kinded = this->GetKindedSources(config); \ for (SourceAndKind const& s : kinded.Sources) { \ if (s.Kind == KIND) { \ data.push_back(s.Source.Value); \ } \ } \ - } + } while (false) /* clang-format on */ void cmGeneratorTarget::GetObjectSources( @@ -512,7 +513,7 @@ const char* cmGeneratorTarget::GetLinkPIEProperty( case cmPolicies::WARN: { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0083); - this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -559,7 +560,7 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target " << "'" << this->GetName() << "'."; this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace()); + MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace()); this->PolicyReportedCMP0069 = true; } @@ -590,7 +591,7 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, this->PolicyReportedCMP0069 = true; this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, message, this->GetBacktrace()); + MessageType::FATAL_ERROR, message, this->GetBacktrace()); return false; } @@ -924,7 +925,7 @@ static bool processSources( if (fullPath.empty()) { if (!e.empty()) { cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e, tgt->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, e, tgt->GetBacktrace()); } return contextDependent; } @@ -939,7 +940,8 @@ static bool processSources( err << "Found relative path while evaluating sources of \"" << tgt->GetName() << "\":\n \"" << src << "\"\n"; } - tgt->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, err.str()); + tgt->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR, + err.str()); return contextDependent; } src = fullPath; @@ -955,7 +957,7 @@ static bool processSources( } if (!usedSources.empty()) { tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::LOG, + MessageType::LOG, std::string("Used sources for target ") + tgt->GetName() + ":\n" + usedSources, entry->ge->GetBacktrace()); @@ -986,7 +988,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( item.back() == '>') { continue; } - files.push_back(item); + files.emplace_back(item); } } return files; @@ -1129,7 +1131,7 @@ cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources( << "\" use a generator expression that depends on the " "SOURCES themselves."; this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + MessageType::FATAL_ERROR, e.str(), this->GetBacktrace()); static KindedSources empty; return empty; } @@ -1230,7 +1232,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, e << "but may contain only sources that compile, header files, and " "other files that would not affect linking of a normal library."; this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + MessageType::FATAL_ERROR, e.str(), this->GetBacktrace()); } } @@ -1388,7 +1390,7 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall( /* clang-format on */ cmake* cm = this->LocalGenerator->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, w.str(), this->GetBacktrace()); } return have_rpath; @@ -1519,7 +1521,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir( w << " less than 10.5 or because CMake's platform configuration is"; w << " corrupt."; cmake* cm = this->LocalGenerator->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, w.str(), this->GetBacktrace()); } return true; @@ -1819,13 +1821,13 @@ public: if (!item.Target) { if (item.AsStr().find("::") != std::string::npos) { bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; std::ostringstream e; switch (this->Target->GetLocalGenerator()->GetPolicyStatus( cmPolicies::CMP0028)) { case cmPolicies::WARN: { e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n"; - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; } break; case cmPolicies::OLD: noMessage = true; @@ -1928,7 +1930,7 @@ public: } e << "Set the LINKER_LANGUAGE property for this target."; cmake* cm = this->Target->GetLocalGenerator()->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e.str(), + cm->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Target->GetBacktrace()); } return *this->Preferred.begin(); @@ -2053,7 +2055,7 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo( msg += this->GetName(); msg += " which has type "; msg += cmState::GetTargetTypeName(this->GetType()); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return nullptr; } @@ -2239,7 +2241,7 @@ cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target) << "\"\ndepends on the sources of a target it is used in. This " "is a dependency loop and is not allowed."; this->GeneratorTarget->LocalGenerator->IssueMessage( - cmake::FATAL_ERROR, e.str()); + MessageType::FATAL_ERROR, e.str()); return; } if (emitted.insert(sf).second && @@ -2551,14 +2553,14 @@ static void processIncludeDirectories( for (std::string& entryInclude : entryIncludes) { if (fromImported && !cmSystemTools::FileExists(entryInclude)) { std::ostringstream e; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; if (checkCMP0027) { switch (tgt->GetPolicyStatusCMP0027()) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n"; CM_FALLTHROUGH; case cmPolicies::OLD: - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; break; case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: @@ -2584,7 +2586,7 @@ static void processIncludeDirectories( if (!cmSystemTools::FileIsFullPath(entryInclude)) { std::ostringstream e; bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; if (!targetName.empty()) { /* clang-format off */ e << "Target \"" << targetName << "\" contains relative " @@ -2595,7 +2597,7 @@ static void processIncludeDirectories( switch (tgt->GetPolicyStatusCMP0021()) { case cmPolicies::WARN: { e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n"; - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; } break; case cmPolicies::OLD: noMessage = true; @@ -2611,7 +2613,7 @@ static void processIncludeDirectories( } if (!noMessage) { tgt->GetLocalGenerator()->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return; } } @@ -2631,7 +2633,7 @@ static void processIncludeDirectories( } if (!usedIncludes.empty()) { tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::LOG, + MessageType::LOG, std::string("Used includes for target ") + tgt->GetName() + ":\n" + usedIncludes, entry->ge->GetBacktrace()); @@ -2744,7 +2746,7 @@ static void processOptionsInternal( } if (!usedOptions.empty()) { tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::LOG, + MessageType::LOG, std::string("Used ") + logName + std::string(" for target ") + tgt->GetName() + ":\n" + usedOptions, entry->ge->GetBacktrace()); @@ -2946,7 +2948,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( case cmPolicies::WARN: { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043); - this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, + e.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: { @@ -3085,7 +3088,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( return item.find(SHELL) != std::string::npos; }) != linkerOptions.end()) { this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "'SHELL:' prefix is not supported as part of 'LINKER:' arguments.", this->GetBacktrace()); return result; @@ -3219,7 +3222,7 @@ void processLinkDirectories( if (!cmSystemTools::FileIsFullPath(entryDirectory)) { std::ostringstream e; bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; if (!targetName.empty()) { /* clang-format off */ e << "Target \"" << targetName << "\" contains relative " @@ -3230,7 +3233,7 @@ void processLinkDirectories( switch (tgt->GetPolicyStatusCMP0081()) { case cmPolicies::WARN: { e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0081) << "\n"; - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; } break; case cmPolicies::OLD: noMessage = true; @@ -3247,7 +3250,7 @@ void processLinkDirectories( } if (!noMessage) { tgt->GetLocalGenerator()->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return; } } @@ -3257,7 +3260,7 @@ void processLinkDirectories( // in case projects set the LINK_DIRECTORIES property directly. cmSystemTools::ConvertToUnixSlashes(entryDirectory); if (uniqueDirectories.insert(entryDirectory).second) { - directories.push_back(entryDirectory); + directories.emplace_back(entryDirectory); if (debugDirectories) { usedDirectories += " * " + entryDirectory + "\n"; } @@ -3265,7 +3268,7 @@ void processLinkDirectories( } if (!usedDirectories.empty()) { tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::LOG, + MessageType::LOG, std::string("Used link directories for target ") + tgt->GetName() + ":\n" + usedDirectories, entry->ge->GetBacktrace()); @@ -3511,7 +3514,7 @@ std::string cmGeneratorTarget::NormalGetRealName( if (this->IsImported()) { std::string msg = "NormalGetRealName called on imported target: "; msg += this->GetName(); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } if (this->GetType() == cmStateEnums::EXECUTABLE) { @@ -3545,7 +3548,7 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName, if (this->IsImported()) { std::string msg = "GetLibraryNames called on imported target: "; msg += this->GetName(); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return; } @@ -3622,7 +3625,7 @@ void cmGeneratorTarget::GetExecutableNames(std::string& name, if (this->IsImported()) { std::string msg = "GetExecutableNames called on imported target: "; msg += this->GetName(); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } // This versioning is supported only for executables and then only @@ -3835,7 +3838,7 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const } // PDB_NAME - props.push_back("PDB_NAME"); + props.emplace_back("PDB_NAME"); for (std::string const& p : props) { if (const char* outName = this->GetProperty(p)) { @@ -4123,7 +4126,8 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender, "This is not allowed. Only user-defined properties may appear " "listed in the " << propName << " property."; - depender->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str()); + depender->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR, + e.str()); return; } if (emitted.insert(p).second) { @@ -4263,7 +4267,7 @@ void cmGeneratorTarget::CheckPropertyCompatibility( "in a boolean interpretation, a numeric minimum, a numeric maximum " "or a " "string interpretation, but not a mixture."; - this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str()); } } @@ -4863,7 +4867,8 @@ void cmGeneratorTarget::ReportPropertyOrigin( areport += result; areport += "\"):\n" + report; - this->LocalGenerator->GetCMakeInstance()->IssueMessage(cmake::LOG, areport); + this->LocalGenerator->GetCMakeInstance()->IssueMessage(MessageType::LOG, + areport); } void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, @@ -5092,7 +5097,7 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo( msg += this->GetName(); msg += " which has type "; msg += cmState::GetTargetTypeName(this->GetType()); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return nullptr; } @@ -5123,7 +5128,7 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo( // An empty map entry indicates we have been called recursively // from the above block. this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.", this->GetBacktrace()); return nullptr; @@ -5343,7 +5348,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( linkIfaceProp << ":\n" " " << explicitLibraries << "\n"; /* clang-format on */ - this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); this->PolicyWarnedCMP0022 = true; } } @@ -5412,7 +5417,8 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( "Link implementation:\n" " " << oldLibraries << "\n"; /* clang-format on */ - this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, + w.str()); this->PolicyWarnedCMP0022 = true; } } @@ -5720,7 +5726,7 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles( "Config \"" << *it << "\":\n" " " << thisConfigFiles << "\n"; /* clang-format on */ - this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } } @@ -5778,7 +5784,8 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0004) << "\n" << "Target \"" << this->GetName() << "\" links to item \"" << item << "\" which has leading or trailing whitespace."; - cm->IssueMessage(cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), + this->GetBacktrace()); } case cmPolicies::OLD: break; @@ -5787,7 +5794,8 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const e << "Target \"" << this->GetName() << "\" links to item \"" << item << "\" which has leading or trailing whitespace. " << "This is now an error according to policy CMP0004."; - cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, e.str(), + this->GetBacktrace()); } break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: { @@ -5795,7 +5803,8 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0004) << "\n" << "Target \"" << this->GetName() << "\" links to item \"" << item << "\" which has leading or trailing whitespace."; - cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, e.str(), + this->GetBacktrace()); } break; } } @@ -5959,12 +5968,12 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( if (name == this->GetName() || name.empty()) { if (name == this->GetName()) { bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; std::ostringstream e; switch (this->GetPolicyStatusCMP0038()) { case cmPolicies::WARN: { e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0038) << "\n"; - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; } break; case cmPolicies::OLD: noMessage = true; @@ -5979,7 +5988,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( e << "Target \"" << this->GetName() << "\" links to itself."; this->LocalGenerator->GetCMakeInstance()->IssueMessage( messageType, e.str(), this->GetBacktrace()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return; } } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index cfd1df0..d9221f0 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -536,7 +536,7 @@ public: */ void ClearSourcesCache(); - void AddSource(const std::string& src); + void AddSource(const std::string& src, bool before = false); void AddTracedSources(std::vector<std::string> const& srcs); /** @@ -694,7 +694,7 @@ public: const char* GetSourcesProperty() const; private: - void AddSourceCommon(const std::string& src); + void AddSourceCommon(const std::string& src, bool before = false); std::string CreateFortranModuleDirectory( std::string const& working_dir) const; diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index 0d4d653..a92eb71 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -4,9 +4,9 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -76,7 +76,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass( switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0059)) { case cmPolicies::WARN: this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); CM_FALLTHROUGH; case cmPolicies::OLD: diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 1d812bd..039f439 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -8,6 +8,7 @@ #include "cmInstalledFile.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmProperty.h" #include "cmPropertyDefinition.h" @@ -230,7 +231,7 @@ bool cmGetPropertyCommand::HandleDirectoryMode() if (this->PropertyName == "DEFINITIONS") { switch (mf->GetPolicyStatus(cmPolicies::CMP0059)) { case cmPolicies::WARN: - mf->IssueMessage(cmake::AUTHOR_WARNING, + mf->IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); CM_FALLTHROUGH; case cmPolicies::OLD: diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index ec485aa..fc0e9c6 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -6,10 +6,10 @@ #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmTarget.h" #include "cmTargetPropertyComputer.h" -#include "cmake.h" class cmExecutionStatus; class cmMessenger; @@ -52,7 +52,7 @@ bool cmGetTargetPropertyCommand::InitialPass( } else { bool issueMessage = false; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0045)) { case cmPolicies::WARN: issueMessage = true; @@ -63,13 +63,13 @@ bool cmGetTargetPropertyCommand::InitialPass( case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (issueMessage) { e << "get_target_property() called with non-existent target \"" << targetName << "\"."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } diff --git a/Source/cmGhsMultiGpj.cxx b/Source/cmGhsMultiGpj.cxx index f58cfc1..c1f0742 100644 --- a/Source/cmGhsMultiGpj.cxx +++ b/Source/cmGhsMultiGpj.cxx @@ -4,31 +4,34 @@ #include "cmGeneratedFileStream.h" -void GhsMultiGpj::WriteGpjTag(Types const gpjType, - cmGeneratedFileStream* const filestream) +static const char* GHS_TAG[] = { "[INTEGRITY Application]", + "[Library]", + "[Project]", + "[Program]", + "[Reference]", + "[Subproject]" }; + +const char* GhsMultiGpj::GetGpjTag(Types const gpjType) { char const* tag; switch (gpjType) { case INTERGRITY_APPLICATION: - tag = "INTEGRITY Application"; - break; case LIBRARY: - tag = "Library"; - break; case PROJECT: - tag = "Project"; - break; case PROGRAM: - tag = "Program"; - break; case REFERENCE: - tag = "Reference"; - break; case SUBPROJECT: - tag = "Subproject"; + tag = GHS_TAG[gpjType]; break; default: tag = ""; } - *filestream << "[" << tag << "]" << std::endl; + return tag; +} + +void GhsMultiGpj::WriteGpjTag(Types const gpjType, std::ostream& fout) +{ + char const* tag; + tag = GhsMultiGpj::GetGpjTag(gpjType); + fout << tag << std::endl; } diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h index b1eead1..6d59225 100644 --- a/Source/cmGhsMultiGpj.h +++ b/Source/cmGhsMultiGpj.h @@ -4,6 +4,7 @@ #define cmGhsMultiGpj_h #include "cmConfigure.h" // IWYU pragma: keep +#include <iosfwd> class cmGeneratedFileStream; @@ -20,8 +21,9 @@ public: SUBPROJECT }; - static void WriteGpjTag(Types const gpjType, - cmGeneratedFileStream* filestream); + static void WriteGpjTag(Types const gpjType, std::ostream& fout); + + static const char* GetGpjTag(Types const gpjType); }; #endif // ! cmGhsMultiGpjType_h diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 1a25633..19605e4 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGhsMultiTargetGenerator.h" +#include "cmComputeLinkInformation.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGhsMultiGenerator.h" @@ -9,177 +10,128 @@ #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmSourceGroup.h" #include "cmTarget.h" -#include <assert.h> - -std::string const cmGhsMultiTargetGenerator::DDOption("-dynamic"); cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target) : GeneratorTarget(target) , LocalGenerator( static_cast<cmLocalGhsMultiGenerator*>(target->GetLocalGenerator())) , Makefile(target->Target->GetMakefile()) - , TargetGroup(DetermineIfTargetGroup(target)) - , DynamicDownload(false) -{ - this->RelBuildFilePath = this->GetRelBuildFilePath(target); - - this->RelOutputFileName = this->RelBuildFilePath + target->GetName() + ".a"; - - this->RelBuildFileName = this->RelBuildFilePath; - this->RelBuildFileName += this->GetBuildFileName(target); - - std::string absPathToRoot = this->GetAbsPathToRoot(target); - absPathToRoot = this->AddSlashIfNeededToPath(absPathToRoot); - this->AbsBuildFilePath = absPathToRoot + this->RelBuildFilePath; - this->AbsBuildFileName = absPathToRoot + this->RelBuildFileName; - this->AbsOutputFileName = absPathToRoot + this->RelOutputFileName; -} - -cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator() + , Name(target->GetName()) { - cmDeleteAll(this->FolderBuildStreams); -} - -std::string cmGhsMultiTargetGenerator::GetRelBuildFilePath( - const cmGeneratorTarget* target) -{ - std::string output = target->GetEffectiveFolderName(); - cmSystemTools::ConvertToUnixSlashes(output); - if (!output.empty()) { - output += "/"; + // Store the configuration name that is being used + if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { + // Use the build type given by the user. + this->ConfigName = config; + } else { + // No configuration type given. + this->ConfigName.clear(); } - output += target->GetName() + "/"; - return output; -} - -std::string cmGhsMultiTargetGenerator::GetAbsPathToRoot( - const cmGeneratorTarget* target) -{ - return target->GetLocalGenerator()->GetBinaryDirectory(); } -std::string cmGhsMultiTargetGenerator::GetAbsBuildFilePath( - const cmGeneratorTarget* target) -{ - std::string output; - output = cmGhsMultiTargetGenerator::GetAbsPathToRoot(target); - output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output); - output += cmGhsMultiTargetGenerator::GetRelBuildFilePath(target); - return output; -} - -std::string cmGhsMultiTargetGenerator::GetRelBuildFileName( - const cmGeneratorTarget* target) -{ - std::string output; - output = cmGhsMultiTargetGenerator::GetRelBuildFilePath(target); - output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output); - output += cmGhsMultiTargetGenerator::GetBuildFileName(target); - return output; -} - -std::string cmGhsMultiTargetGenerator::GetBuildFileName( - const cmGeneratorTarget* target) -{ - std::string output; - output = target->GetName(); - output += cmGlobalGhsMultiGenerator::FILE_EXTENSION; - return output; -} - -std::string cmGhsMultiTargetGenerator::AddSlashIfNeededToPath( - std::string const& input) +cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator() { - std::string output(input); - if (!cmHasLiteralSuffix(output, "/")) { - output += "/"; - } - return output; } void cmGhsMultiTargetGenerator::Generate() { - std::vector<cmSourceFile*> objectSources = this->GetSources(); - if (!objectSources.empty() && this->IncludeThisTarget()) { - if (!cmSystemTools::FileExists(this->AbsBuildFilePath.c_str())) { - cmSystemTools::MakeDirectory(this->AbsBuildFilePath.c_str()); + // Determine type of target for this project + switch (this->GeneratorTarget->GetType()) { + case cmStateEnums::EXECUTABLE: { + // Get the name of the executable to generate. + std::string targetName; + std::string targetNameImport; + std::string targetNamePDB; + this->GeneratorTarget->GetExecutableNames( + targetName, this->TargetNameReal, targetNameImport, targetNamePDB, + this->ConfigName); + if (cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()) { + this->TagType = GhsMultiGpj::INTERGRITY_APPLICATION; + } else { + this->TagType = GhsMultiGpj::PROGRAM; + } + break; + } + case cmStateEnums::STATIC_LIBRARY: { + std::string targetName; + std::string targetNameSO; + std::string targetNameImport; + std::string targetNamePDB; + this->GeneratorTarget->GetLibraryNames( + targetName, targetNameSO, this->TargetNameReal, targetNameImport, + targetNamePDB, this->ConfigName); + this->TagType = GhsMultiGpj::LIBRARY; + break; + } + case cmStateEnums::SHARED_LIBRARY: { + std::string msg = "add_library(<name> SHARED ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg.c_str()); + return; } - cmGlobalGhsMultiGenerator::Open(std::string(""), this->AbsBuildFileName, - &this->FolderBuildStreams); - cmGlobalGhsMultiGenerator::OpenBuildFileStream( - this->GetFolderBuildStreams()); - std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - if (0 == config.length()) { - config = "RELEASE"; + case cmStateEnums::OBJECT_LIBRARY: { + std::string targetName; + std::string targetNameSO; + std::string targetNameImport; + std::string targetNamePDB; + this->GeneratorTarget->GetLibraryNames( + targetName, targetNameSO, this->TargetNameReal, targetNameImport, + targetNamePDB, this->ConfigName); + this->TagType = GhsMultiGpj::SUBPROJECT; + break; } - const std::string language( - this->GeneratorTarget->GetLinkerLanguage(config)); - config = cmSystemTools::UpperCase(config); - this->DynamicDownload = this->DetermineIfDynamicDownload(config, language); - if (this->DynamicDownload) { - *this->GetFolderBuildStreams() - << "#component integrity_dynamic_download" << std::endl; + case cmStateEnums::MODULE_LIBRARY: { + std::string msg = "add_library(<name> MODULE ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg.c_str()); + return; } - GhsMultiGpj::WriteGpjTag(this->GetGpjTag(), this->GetFolderBuildStreams()); - cmGlobalGhsMultiGenerator::WriteDisclaimer(this->GetFolderBuildStreams()); - - bool const notKernel = this->IsNotKernel(config, language); - this->WriteTypeSpecifics(config, notKernel); - this->SetCompilerFlags(config, language, notKernel); - this->WriteCompilerFlags(config, language); - this->WriteCompilerDefinitions(config, language); - this->WriteIncludes(config, language); - if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - this->WriteTargetLinkLibraries(config, language); + case cmStateEnums::UTILITY: { + std::string msg = "add_custom_target(<name> ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg.c_str()); + return; } - this->WriteCustomCommands(); + default: + return; + } - std::map<const cmSourceFile*, std::string> objectNames = - cmGhsMultiTargetGenerator::GetObjectNames( - &objectSources, this->LocalGenerator, this->GeneratorTarget); + // Tell the global generator the name of the project file + this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", + this->Name.c_str()); + this->GeneratorTarget->Target->SetProperty( + "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType)); - this->WriteSources(objectSources, objectNames); - } + this->GenerateTarget(); } -bool cmGhsMultiTargetGenerator::IncludeThisTarget() +void cmGhsMultiTargetGenerator::GenerateTarget() { - bool output = true; - char const* excludeFromAll = - this->GeneratorTarget->GetProperty("EXCLUDE_FROM_ALL"); - if (NULL != excludeFromAll && '1' == excludeFromAll[0] && - '\0' == excludeFromAll[1]) { - output = false; - } - return output; -} + // Open the filestream in copy-if-different mode. + std::string fname = this->LocalGenerator->GetCurrentBinaryDirectory(); + fname += "/"; + fname += this->Name; + fname += cmGlobalGhsMultiGenerator::FILE_EXTENSION; + cmGeneratedFileStream fout(fname.c_str()); + fout.SetCopyIfDifferent(true); -std::vector<cmSourceFile*> cmGhsMultiTargetGenerator::GetSources() const -{ - std::vector<cmSourceFile*> output; - std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - this->GeneratorTarget->GetSourceFiles(output, config); - return output; -} + this->GetGlobalGenerator()->WriteFileHeader(fout); + GhsMultiGpj::WriteGpjTag(this->TagType, fout); -GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag() const -{ - return cmGhsMultiTargetGenerator::GetGpjTag(this->GeneratorTarget); -} + const std::string language( + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName)); -GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag( - const cmGeneratorTarget* target) -{ - GhsMultiGpj::Types output; - if (cmGhsMultiTargetGenerator::DetermineIfTargetGroup(target)) { - output = GhsMultiGpj::INTERGRITY_APPLICATION; - } else if (target->GetType() == cmStateEnums::STATIC_LIBRARY) { - output = GhsMultiGpj::LIBRARY; - } else { - output = GhsMultiGpj::PROGRAM; - } - return output; + this->WriteTargetSpecifics(fout, this->ConfigName); + this->SetCompilerFlags(this->ConfigName, language); + this->WriteCompilerFlags(fout, this->ConfigName, language); + this->WriteCompilerDefinitions(fout, this->ConfigName, language); + this->WriteIncludes(fout, this->ConfigName, language); + this->WriteTargetLinkLine(fout, this->ConfigName); + this->WriteCustomCommands(fout); + this->WriteSources(fout); + this->WriteReferences(fout); + fout.Close(); } cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator() @@ -189,41 +141,27 @@ cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator() this->LocalGenerator->GetGlobalGenerator()); } -void cmGhsMultiTargetGenerator::WriteTypeSpecifics(const std::string& config, - bool const notKernel) +void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout, + const std::string& config) { - std::string outputDir(this->GetOutputDirectory(config)); - std::string outputFilename(this->GetOutputFilename(config)); - - if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) { - std::string const& static_library_suffix = - this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"); - *this->GetFolderBuildStreams() - << " -o \"" << outputDir << outputFilename << static_library_suffix - << "\"" << std::endl; - } else if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - if (notKernel && !this->IsTargetGroup()) { - *this->GetFolderBuildStreams() << " -relprog" << std::endl; - } - if (this->IsTargetGroup()) { - *this->GetFolderBuildStreams() - << " -o \"" << outputDir << outputFilename << ".elf\"" << std::endl; - *this->GetFolderBuildStreams() - << " :extraOutputFile=\"" << outputDir << outputFilename - << ".elf.ael\"" << std::endl; - } else { - std::string const executable_suffix = - this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX"); - *this->GetFolderBuildStreams() - << " -o \"" << outputDir << outputFilename << executable_suffix - << "\"" << std::endl; - } + std::string outpath; + std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory(); + + if (this->TagType != GhsMultiGpj::SUBPROJECT) { + // set target binary file destination + outpath = this->GeneratorTarget->GetDirectory(config); + outpath = this->LocalGenerator->ConvertToRelativePath(rootpath, outpath); + fout << " :binDirRelative=\"" << outpath << "\"" << std::endl; + fout << " -o \"" << this->TargetNameReal << "\"" << std::endl; } + + // set target object file destination + outpath = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + fout << " :outputDirRelative=\"" << outpath << "\"" << std::endl; } void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, - const std::string& language, - bool const notKernel) + const std::string& language) { std::map<std::string, std::string>::iterator i = this->FlagsByLanguage.find(language); @@ -231,14 +169,9 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, std::string flags; const char* lang = language.c_str(); - if (notKernel) { - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, - lang, config); - } else { - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, - lang + std::string("_GHS_KERNEL"), - config); - } + this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, lang, + config); + this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, lang, config); this->LocalGenerator->AddVisibilityPresetFlags( @@ -281,21 +214,25 @@ std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language, return i->second; } -void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::string const&, +void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::ostream& fout, + std::string const&, const std::string& language) { std::map<std::string, std::string>::iterator flagsByLangI = this->FlagsByLanguage.find(language); if (flagsByLangI != this->FlagsByLanguage.end()) { if (!flagsByLangI->second.empty()) { - *this->GetFolderBuildStreams() - << " " << flagsByLangI->second << std::endl; + std::vector<std::string> ghsCompFlags = + cmSystemTools::ParseArguments(flagsByLangI->second.c_str()); + for (auto& f : ghsCompFlags) { + fout << " " << f << std::endl; + } } } } void cmGhsMultiTargetGenerator::WriteCompilerDefinitions( - const std::string& config, const std::string& language) + std::ostream& fout, const std::string& config, const std::string& language) { std::vector<std::string> compileDefinitions; this->GeneratorTarget->GetCompileDefinitions(compileDefinitions, config, @@ -303,11 +240,12 @@ void cmGhsMultiTargetGenerator::WriteCompilerDefinitions( for (std::vector<std::string>::const_iterator cdI = compileDefinitions.begin(); cdI != compileDefinitions.end(); ++cdI) { - *this->GetFolderBuildStreams() << " -D" << (*cdI) << std::endl; + fout << " -D" << (*cdI) << std::endl; } } -void cmGhsMultiTargetGenerator::WriteIncludes(const std::string& config, +void cmGhsMultiTargetGenerator::WriteIncludes(std::ostream& fout, + const std::string& config, const std::string& language) { std::vector<std::string> includes; @@ -316,80 +254,73 @@ void cmGhsMultiTargetGenerator::WriteIncludes(const std::string& config, for (std::vector<std::string>::const_iterator includes_i = includes.begin(); includes_i != includes.end(); ++includes_i) { - *this->GetFolderBuildStreams() - << " -I\"" << *includes_i << "\"" << std::endl; + fout << " -I\"" << *includes_i << "\"" << std::endl; } } -void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries( - std::string const& config, std::string const& language) +void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, + std::string const& config) { - // library directories - cmTargetDependSet tds = - this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget); - for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end(); - ++tdsI) { - const cmGeneratorTarget* tg = *tdsI; - *this->GetFolderBuildStreams() - << " -L\"" << GetAbsBuildFilePath(tg) << "\"" << std::endl; + if (this->TagType == GhsMultiGpj::INTERGRITY_APPLICATION) { + return; } - // library targets - cmTarget::LinkLibraryVectorType llv = - this->GeneratorTarget->Target->GetOriginalLinkLibraries(); - for (cmTarget::LinkLibraryVectorType::const_iterator llvI = llv.begin(); - llvI != llv.end(); ++llvI) { - std::string libName = llvI->first; - // if it is a user defined target get the full path to the lib - cmTarget* tg(GetGlobalGenerator()->FindTarget(libName)); - if (NULL != tg) { - libName = tg->GetName() + ".a"; - } - *this->GetFolderBuildStreams() - << " -l\"" << libName << "\"" << std::endl; + + std::string linkLibraries; + std::string flags; + std::string linkFlags; + std::string frameworkPath; + std::string linkPath; + + std::unique_ptr<cmLinkLineComputer> linkLineComputer( + this->GetGlobalGenerator()->CreateLinkLineComputer( + this->LocalGenerator, + this->LocalGenerator->GetStateSnapshot().GetDirectory())); + + this->LocalGenerator->GetTargetFlags( + linkLineComputer.get(), config, linkLibraries, flags, linkFlags, + frameworkPath, linkPath, this->GeneratorTarget); + + // write out link options + std::vector<std::string> lopts = + cmSystemTools::ParseArguments(linkFlags.c_str()); + for (auto& l : lopts) { + fout << " " << l << std::endl; } - if (!this->TargetGroup) { - std::string linkLibraries; - std::string flags; - std::string linkFlags; - std::string frameworkPath; - std::string linkPath; - std::string createRule = - this->GeneratorTarget->GetCreateRuleVariable(language, config); - bool useWatcomQuote = - this->Makefile->IsOn(createRule + "_USE_WATCOM_QUOTE"); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( - this->GetGlobalGenerator()->CreateLinkLineComputer( - this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); - linkLineComputer->SetUseWatcomQuote(useWatcomQuote); - - this->LocalGenerator->GetTargetFlags( - linkLineComputer.get(), config, linkLibraries, flags, linkFlags, - frameworkPath, linkPath, this->GeneratorTarget); - linkFlags = cmSystemTools::TrimWhitespace(linkFlags); - - if (!linkPath.empty()) { - linkPath = " " + linkPath.substr(0U, linkPath.size() - 1U); - *this->GetFolderBuildStreams() << linkPath; - } + // write out link search paths + // must be quoted for paths that contain spaces + std::vector<std::string> lpath = + cmSystemTools::ParseArguments(linkPath.c_str()); + for (auto& l : lpath) { + fout << " -L\"" << l << "\"" << std::endl; + } + + // write out link libs + // must be quoted for filepaths that contains spaces + std::string cbd = this->LocalGenerator->GetCurrentBinaryDirectory(); - if (!linkFlags.empty()) { - *this->GetFolderBuildStreams() << " " << linkFlags << std::endl; + std::vector<std::string> llibs = + cmSystemTools::ParseArguments(linkLibraries.c_str()); + for (auto& l : llibs) { + if (l.compare(0, 2, "-l") == 0) { + fout << " \"" << l << "\"" << std::endl; + } else { + std::string rl = cmSystemTools::CollapseCombinedPath(cbd, l); + fout << " -l\"" << rl << "\"" << std::endl; } } } -void cmGhsMultiTargetGenerator::WriteCustomCommands() +void cmGhsMultiTargetGenerator::WriteCustomCommands(std::ostream& fout) { - WriteCustomCommandsHelper(this->GeneratorTarget->GetPreBuildCommands(), + WriteCustomCommandsHelper(fout, this->GeneratorTarget->GetPreBuildCommands(), cmTarget::PRE_BUILD); - WriteCustomCommandsHelper(this->GeneratorTarget->GetPostBuildCommands(), - cmTarget::POST_BUILD); + WriteCustomCommandsHelper( + fout, this->GeneratorTarget->GetPostBuildCommands(), cmTarget::POST_BUILD); } void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( - std::vector<cmCustomCommand> const& commandsSet, + std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet, cmTarget::CustomCommandType const commandType) { for (std::vector<cmCustomCommand>::const_iterator commandsSetI = @@ -400,10 +331,10 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( commandI != commands.end(); ++commandI) { switch (commandType) { case cmTarget::PRE_BUILD: - *this->GetFolderBuildStreams() << " :preexecShellSafe="; + fout << " :preexecShellSafe="; break; case cmTarget::POST_BUILD: - *this->GetFolderBuildStreams() << " :postexecShellSafe="; + fout << " :postexecShellSafe="; break; default: assert("Only pre and post are supported"); @@ -414,242 +345,237 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( std::string subCommandE = this->LocalGenerator->EscapeForShell(*commandLineI, true); if (!command.empty()) { - *this->GetFolderBuildStreams() - << (command.begin() == commandLineI ? "'" : " "); + fout << (command.begin() == commandLineI ? "'" : " "); // Need to double escape backslashes cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\"); } - *this->GetFolderBuildStreams() << subCommandE; + fout << subCommandE; } if (!command.empty()) { - *this->GetFolderBuildStreams() << "'" << std::endl; + fout << "'" << std::endl; } } } } -std::map<const cmSourceFile*, std::string> -cmGhsMultiTargetGenerator::GetObjectNames( - std::vector<cmSourceFile*>* const objectSources, - cmLocalGhsMultiGenerator* const localGhsMultiGenerator, - cmGeneratorTarget* const generatorTarget) +void cmGhsMultiTargetGenerator::WriteSourceProperty(std::ostream& fout, + const cmSourceFile* sf, + std::string propName, + std::string propFlag) { - std::map<std::string, std::vector<cmSourceFile*>> filenameToSource; - std::map<cmSourceFile*, std::string> sourceToFilename; - for (std::vector<cmSourceFile*>::const_iterator sf = objectSources->begin(); - sf != objectSources->end(); ++sf) { - const std::string filename = - cmSystemTools::GetFilenameName((*sf)->GetFullPath()); - const std::string lower_filename = cmSystemTools::LowerCase(filename); - filenameToSource[lower_filename].push_back(*sf); - sourceToFilename[*sf] = lower_filename; - } - - std::vector<cmSourceFile*> duplicateSources; - for (std::map<std::string, std::vector<cmSourceFile*>>::const_iterator - msvSourceI = filenameToSource.begin(); - msvSourceI != filenameToSource.end(); ++msvSourceI) { - if (msvSourceI->second.size() > 1) { - duplicateSources.insert(duplicateSources.end(), - msvSourceI->second.begin(), - msvSourceI->second.end()); + const char* prop = sf->GetProperty(propName); + if (prop) { + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(prop, list); + for (auto& p : list) { + fout << " " << propFlag << p << std::endl; } } - - std::map<const cmSourceFile*, std::string> objectNamesCorrected; - - for (std::vector<cmSourceFile*>::const_iterator sf = - duplicateSources.begin(); - sf != duplicateSources.end(); ++sf) { - std::string const longestObjectDirectory( - cmGhsMultiTargetGenerator::ComputeLongestObjectDirectory( - localGhsMultiGenerator, generatorTarget, *sf)); - std::string objFilenameName = - localGhsMultiGenerator->GetObjectFileNameWithoutTarget( - **sf, longestObjectDirectory); - cmsys::SystemTools::ReplaceString(objFilenameName, "/", "_"); - objectNamesCorrected[*sf] = objFilenameName; - } - - return objectNamesCorrected; } -void cmGhsMultiTargetGenerator::WriteSources( - std::vector<cmSourceFile*> const& objectSources, - std::map<const cmSourceFile*, std::string> const& objectNames) +void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) { - for (const cmSourceFile* sf : objectSources) { - std::vector<cmSourceGroup> sourceGroups(this->Makefile->GetSourceGroups()); - std::string const& sourceFullPath = sf->GetFullPath(); - cmSourceGroup* sourceGroup = - this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups); - std::string sgPath = sourceGroup->GetFullName(); - cmSystemTools::ConvertToUnixSlashes(sgPath); - cmGlobalGhsMultiGenerator::AddFilesUpToPath( - this->GetFolderBuildStreams(), &this->FolderBuildStreams, - this->LocalGenerator->GetBinaryDirectory().c_str(), sgPath, - GhsMultiGpj::SUBPROJECT, this->RelBuildFilePath); - - std::string fullSourcePath(sf->GetFullPath()); - if (sf->GetExtension() == "int" || sf->GetExtension() == "bsp") { - *this->FolderBuildStreams[sgPath] << fullSourcePath << std::endl; - } else { - // WORKAROUND: GHS MULTI needs the path to use backslashes without quotes - // to open files in search as of version 6.1.6 - cmsys::SystemTools::ReplaceString(fullSourcePath, "/", "\\"); - *this->FolderBuildStreams[sgPath] << fullSourcePath << std::endl; - } + /* vector of all sources for this target */ + std::vector<cmSourceFile*> sources; + this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName); - if ("ld" != sf->GetExtension() && "int" != sf->GetExtension() && - "bsp" != sf->GetExtension()) { - this->WriteObjectLangOverride(this->FolderBuildStreams[sgPath], sf); - if (objectNames.end() != objectNames.find(sf)) { - *this->FolderBuildStreams[sgPath] - << " -o \"" << objectNames.find(sf)->second << "\"" << std::endl; - } + /* vector of all groups defined for this target + * -- but the vector is not expanded with sub groups or in any useful order + */ + std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); - this->WriteObjectDir(this->FolderBuildStreams[sgPath], - this->AbsBuildFilePath + sgPath); - } + /* for each source file assign it to its group */ + std::map<std::string, std::vector<cmSourceFile*>> groupFiles; + std::set<std::string> groupNames; + for (auto& sf : sources) { + cmSourceGroup* sourceGroup = + this->Makefile->FindSourceGroup(sf->GetFullPath(), sourceGroups); + std::string gn = sourceGroup->GetFullName(); + groupFiles[gn].push_back(sf); + groupNames.insert(gn); } -} -void cmGhsMultiTargetGenerator::WriteObjectLangOverride( - cmGeneratedFileStream* fileStream, const cmSourceFile* sourceFile) -{ - const char* rawLangProp = sourceFile->GetProperty("LANGUAGE"); - if (NULL != rawLangProp) { - std::string sourceLangProp(rawLangProp); - std::string extension(sourceFile->GetExtension()); - if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) { - *fileStream << " -dotciscxx" << std::endl; + /* list of known groups and the order they are displayed in a project file */ + const std::vector<std::string> standardGroups = { + "Header Files", "Source Files", "CMake Rules", + "Object Files", "Object Libraries", "Resources" + }; + + /* list of groups in the order they are displayed in a project file*/ + std::vector<std::string> groupFilesList(groupFiles.size()); + + /* put the groups in the order they should be listed + * - standard groups first, and then everything else + * in the order used by std::map. + */ + int i = 0; + for (const std::string& gn : standardGroups) { + auto n = groupNames.find(gn); + if (n != groupNames.end()) { + groupFilesList[i] = *n; + i += 1; + groupNames.erase(gn); } } -} -void cmGhsMultiTargetGenerator::WriteObjectDir( - cmGeneratedFileStream* fileStream, std::string const& dir) -{ - std::string workingDir(dir); - cmSystemTools::ConvertToUnixSlashes(workingDir); - if (!workingDir.empty()) { - workingDir += "/"; + { /* catch-all group - is last item */ + std::string gn = ""; + auto n = groupNames.find(gn); + if (n != groupNames.end()) { + groupFilesList.back() = *n; + groupNames.erase(gn); + } } - workingDir += "Objs"; - *fileStream << " -object_dir=\"" << workingDir << "\"" << std::endl; -} -std::string cmGhsMultiTargetGenerator::GetOutputDirectory( - const std::string& config) const -{ - std::string outputDir(AbsBuildFilePath); - - const char* runtimeOutputProp = - this->GeneratorTarget->GetProperty("RUNTIME_OUTPUT_DIRECTORY"); - if (NULL != runtimeOutputProp) { - outputDir = runtimeOutputProp; + for (auto& n : groupNames) { + groupFilesList[i] = n; + i += 1; } - std::string configCapped(cmSystemTools::UpperCase(config)); - const char* runtimeOutputSProp = this->GeneratorTarget->GetProperty( - "RUNTIME_OUTPUT_DIRECTORY_" + configCapped); - if (NULL != runtimeOutputSProp) { - outputDir = runtimeOutputSProp; + /* sort the files within each group */ + for (auto& n : groupFilesList) { + std::sort(groupFiles[n].begin(), groupFiles[n].end(), + [](cmSourceFile* l, cmSourceFile* r) { + return l->GetFullPath() < r->GetFullPath(); + }); } - cmSystemTools::ConvertToUnixSlashes(outputDir); - if (!outputDir.empty()) { - outputDir += "/"; - } + /* list of open project files */ + std::vector<cmGeneratedFileStream*> gfiles; + + /* write files into the proper project file + * -- groups go into main project file + * unless FOLDER property or variable is set. + */ + for (auto& sg : groupFilesList) { + std::ostream* fout; + bool useProjectFile = + cmSystemTools::IsOn( + this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) || + cmSystemTools::IsOn( + this->Makefile->GetDefinition("GHS_NO_SOURCE_GROUP_FILE")); + if (useProjectFile || sg.empty()) { + fout = &fout_proj; + } else { + // Open the filestream in copy-if-different mode. + std::string gname = sg; + cmsys::SystemTools::ReplaceString(gname, "\\", "_"); + std::string lpath = + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + lpath += "/"; + lpath += gname; + lpath += cmGlobalGhsMultiGenerator::FILE_EXTENSION; + std::string fpath = this->LocalGenerator->GetCurrentBinaryDirectory(); + fpath += "/"; + fpath += lpath; + cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath.c_str()); + f->SetCopyIfDifferent(true); + gfiles.push_back(f); + fout = f; + this->GetGlobalGenerator()->WriteFileHeader(*f); + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, *f); + fout_proj << lpath << " "; + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, fout_proj); + } - return outputDir; -} + if (useProjectFile) { + if (sg.empty()) { + *fout << "{comment} Others" << std::endl; + } else { + *fout << "{comment} " << sg << std::endl; + } + } -std::string cmGhsMultiTargetGenerator::GetOutputFilename( - const std::string& config) const -{ - std::string outputFilename(this->GeneratorTarget->GetName()); + /* output rule for each source file */ + for (const cmSourceFile* si : groupFiles[sg]) { - const char* outputNameProp = - this->GeneratorTarget->GetProperty("OUTPUT_NAME"); - if (NULL != outputNameProp) { - outputFilename = outputNameProp; - } + // Convert filename to native system + // WORKAROUND: GHS MULTI 6.1.4 and 6.1.6 are known to need backslash on + // windows when opening some files from the search window. + std::string fname(si->GetFullPath()); + cmSystemTools::ConvertToOutputSlashes(fname); + *fout << fname << std::endl; + + if ("ld" != si->GetExtension() && "int" != si->GetExtension() && + "bsp" != si->GetExtension()) { + this->WriteObjectLangOverride(*fout, si); + } + + this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I"); + this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D"); + this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", ""); - std::string configCapped(cmSystemTools::UpperCase(config)); - const char* outputNameSProp = - this->GeneratorTarget->GetProperty(configCapped + "_OUTPUT_NAME"); - if (NULL != outputNameSProp) { - outputFilename = outputNameSProp; + /* to avoid clutter in the gui only print out the objectName if it has + * been renamed */ + std::string objectName = this->GeneratorTarget->GetObjectName(si); + if (!objectName.empty() && + this->GeneratorTarget->HasExplicitObjectName(si)) { + *fout << " -o " << objectName << std::endl; + } + } } - return outputFilename; + for (cmGeneratedFileStream* f : gfiles) { + f->Close(); + } } -std::string cmGhsMultiTargetGenerator::ComputeLongestObjectDirectory( - cmLocalGhsMultiGenerator const* localGhsMultiGenerator, - cmGeneratorTarget* const generatorTarget, cmSourceFile* const sourceFile) +void cmGhsMultiTargetGenerator::WriteObjectLangOverride( + std::ostream& fout, const cmSourceFile* sourceFile) { - std::string dir_max; - dir_max += - localGhsMultiGenerator->GetMakefile()->GetCurrentBinaryDirectory(); - dir_max += "/"; - dir_max += generatorTarget->Target->GetName(); - dir_max += "/"; - std::vector<cmSourceGroup> sourceGroups( - localGhsMultiGenerator->GetMakefile()->GetSourceGroups()); - std::string const& sourceFullPath = sourceFile->GetFullPath(); - cmSourceGroup* sourceGroup = - localGhsMultiGenerator->GetMakefile()->FindSourceGroup(sourceFullPath, - sourceGroups); - std::string const& sgPath = sourceGroup->GetFullName(); - dir_max += sgPath; - dir_max += "/Objs/libs/"; - dir_max += generatorTarget->Target->GetName(); - dir_max += "/"; - return dir_max; + const char* rawLangProp = sourceFile->GetProperty("LANGUAGE"); + if (NULL != rawLangProp) { + std::string sourceLangProp(rawLangProp); + std::string extension(sourceFile->GetExtension()); + if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) { + fout << " -dotciscxx" << std::endl; + } + } } -bool cmGhsMultiTargetGenerator::IsNotKernel(std::string const& config, - const std::string& language) +void cmGhsMultiTargetGenerator::WriteReferences(std::ostream& fout) { - bool output; - std::vector<std::string> options; - this->GeneratorTarget->GetCompileOptions(options, config, language); - output = - options.end() == std::find(options.begin(), options.end(), "-kernel"); - return output; -} + // This only applies to INTEGRITY Applications + if (this->TagType != GhsMultiGpj::INTERGRITY_APPLICATION) { + return; + } -bool cmGhsMultiTargetGenerator::DetermineIfTargetGroup( - const cmGeneratorTarget* target) -{ - bool output = false; - std::vector<cmSourceFile*> sources; - std::string config = - target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); - target->GetSourceFiles(sources, config); - for (std::vector<cmSourceFile*>::const_iterator sources_i = sources.begin(); - sources.end() != sources_i; ++sources_i) { - if ("int" == (*sources_i)->GetExtension()) { - output = true; - } + // Get the targets that this one depends upon + cmTargetDependSet unordered = + this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget); + cmGlobalGhsMultiGenerator::OrderedTargetDependSet ordered(unordered, + this->Name); + for (auto& t : ordered) { + std::string tname = t->GetName(); + std::string tpath = t->LocalGenerator->GetCurrentBinaryDirectory(); + std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory(); + std::string outpath = + this->LocalGenerator->ConvertToRelativePath(rootpath, tpath) + "/" + + tname + "REF" + cmGlobalGhsMultiGenerator::FILE_EXTENSION; + + fout << outpath; + fout << " "; + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fout); + + // Tell the global generator that a refernce project needs to be created + t->Target->SetProperty("GHS_REFERENCE_PROJECT", "ON"); } - return output; } -bool cmGhsMultiTargetGenerator::DetermineIfDynamicDownload( - std::string const& config, const std::string& language) +bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp(void) { - std::vector<std::string> options; - bool output = false; - this->GeneratorTarget->GetCompileOptions(options, config, language); - for (std::vector<std::string>::const_iterator options_i = options.begin(); - options_i != options.end(); ++options_i) { - std::string option = *options_i; - if (this->DDOption == option) { - output = true; + const char* p = this->GeneratorTarget->GetProperty("ghs_integrity_app"); + if (p) { + return cmSystemTools::IsOn( + this->GeneratorTarget->GetProperty("ghs_integrity_app")); + } else { + std::vector<cmSourceFile*> sources; + this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName); + for (auto& sf : sources) { + if ("int" == sf->GetExtension()) { + return true; + } } + return false; } - return output; } diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h index e936b08..a241cc6 100644 --- a/Source/cmGhsMultiTargetGenerator.h +++ b/Source/cmGhsMultiTargetGenerator.h @@ -24,97 +24,49 @@ public: virtual void Generate(); - bool IncludeThisTarget(); - std::vector<cmSourceFile*> GetSources() const; - GhsMultiGpj::Types GetGpjTag() const; - static GhsMultiGpj::Types GetGpjTag(const cmGeneratorTarget* target); - const char* GetAbsBuildFilePath() const - { - return this->AbsBuildFilePath.c_str(); - } - const char* GetRelBuildFileName() const - { - return this->RelBuildFileName.c_str(); - } - const char* GetAbsBuildFileName() const - { - return this->AbsBuildFileName.c_str(); - } - const char* GetAbsOutputFileName() const - { - return this->AbsOutputFileName.c_str(); - } - - static std::string GetRelBuildFilePath(const cmGeneratorTarget* target); - static std::string GetAbsPathToRoot(const cmGeneratorTarget* target); - static std::string GetAbsBuildFilePath(const cmGeneratorTarget* target); - static std::string GetRelBuildFileName(const cmGeneratorTarget* target); - static std::string GetBuildFileName(const cmGeneratorTarget* target); - static std::string AddSlashIfNeededToPath(std::string const& input); - private: cmGlobalGhsMultiGenerator* GetGlobalGenerator() const; - cmGeneratedFileStream* GetFolderBuildStreams() - { - return this->FolderBuildStreams[""]; - }; - bool IsTargetGroup() const { return this->TargetGroup; } - - void WriteTypeSpecifics(const std::string& config, bool notKernel); - void WriteCompilerFlags(const std::string& config, + + void GenerateTarget(); + + void WriteTargetSpecifics(std::ostream& fout, const std::string& config); + + void WriteCompilerFlags(std::ostream& fout, const std::string& config, const std::string& language); - void WriteCompilerDefinitions(const std::string& config, + void WriteCompilerDefinitions(std::ostream& fout, const std::string& config, const std::string& language); - void SetCompilerFlags(std::string const& config, const std::string& language, - bool const notKernel); + void SetCompilerFlags(std::string const& config, + const std::string& language); + std::string GetDefines(const std::string& langugae, std::string const& config); - void WriteIncludes(const std::string& config, const std::string& language); - void WriteTargetLinkLibraries(std::string const& config, - std::string const& language); - void WriteCustomCommands(); + void WriteIncludes(std::ostream& fout, const std::string& config, + const std::string& language); + void WriteTargetLinkLine(std::ostream& fout, std::string const& config); + void WriteCustomCommands(std::ostream& fout); void WriteCustomCommandsHelper( - std::vector<cmCustomCommand> const& commandsSet, + std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet, cmTarget::CustomCommandType commandType); - void WriteSources( - std::vector<cmSourceFile*> const& objectSources, - std::map<const cmSourceFile*, std::string> const& objectNames); - static std::map<const cmSourceFile*, std::string> GetObjectNames( - std::vector<cmSourceFile*>* objectSources, - cmLocalGhsMultiGenerator* localGhsMultiGenerator, - cmGeneratorTarget* generatorTarget); - static void WriteObjectLangOverride(cmGeneratedFileStream* fileStream, + void WriteSources(std::ostream& fout_proj); + void WriteSourceProperty(std::ostream& fout, const cmSourceFile* sf, + std::string propName, std::string propFlag); + void WriteReferences(std::ostream& fout); + static void WriteObjectLangOverride(std::ostream& fout, const cmSourceFile* sourceFile); - static void WriteObjectDir(cmGeneratedFileStream* fileStream, - std::string const& dir); - std::string GetOutputDirectory(const std::string& config) const; - std::string GetOutputFilename(const std::string& config) const; - static std::string ComputeLongestObjectDirectory( - cmLocalGhsMultiGenerator const* localGhsMultiGenerator, - cmGeneratorTarget* generatorTarget, cmSourceFile* const sourceFile); - - bool IsNotKernel(std::string const& config, const std::string& language); - static bool DetermineIfTargetGroup(const cmGeneratorTarget* target); - bool DetermineIfDynamicDownload(std::string const& config, - const std::string& language); + bool DetermineIfIntegrityApp(void); cmGeneratorTarget* GeneratorTarget; cmLocalGhsMultiGenerator* LocalGenerator; cmMakefile* Makefile; - std::string AbsBuildFilePath; - std::string RelBuildFilePath; - std::string AbsBuildFileName; - std::string RelBuildFileName; - std::string RelOutputFileName; - std::string AbsOutputFileName; - std::map<std::string, cmGeneratedFileStream*> FolderBuildStreams; - bool TargetGroup; - bool DynamicDownload; - static std::string const DDOption; std::map<std::string, std::string> FlagsByLanguage; std::map<std::string, std::string> DefinesByLanguage; + + std::string TargetNameReal; + GhsMultiGpj::Types TagType; + std::string const Name; + std::string ConfigName; /* CMAKE_BUILD_TYPE */ }; #endif // ! cmGhsMultiTargetGenerator_h diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 2389103..56714b1 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -5,6 +5,7 @@ #include "cmDocumentationEntry.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmake.h" diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 47c53e7..2d36315 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -32,6 +32,7 @@ #include "cmLocalGenerator.h" #include "cmMSVC60LinkLineComputer.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmSourceFile.h" @@ -137,7 +138,7 @@ bool cmGlobalGenerator::SetGeneratorInstance(std::string const& i, " " << i << "\n" "was specified."; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -157,7 +158,7 @@ bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p, " " << p << "\n" "was specified."; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -176,7 +177,7 @@ bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, " " << ts << "\n" "was specified."; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -301,7 +302,8 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const for (cmGeneratorTarget* target : targets) { if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || - target->GetType() == cmStateEnums::TargetType::UTILITY) { + target->GetType() == cmStateEnums::TargetType::UTILITY || + cmSystemTools::IsOn(target->GetProperty("ghs_integrity_app"))) { continue; } @@ -319,8 +321,8 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const if (srcs.empty()) { std::ostringstream e; e << "No SOURCES given to target: " << target->GetName(); - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - target->GetBacktrace()); + this->GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, e.str(), target->GetBacktrace()); failed = true; } } @@ -354,7 +356,7 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) std::string setMakeProgram = mf->GetModulesFile(this->FindMakeProgramFile.c_str()); if (!setMakeProgram.empty()) { - mf->ReadListFile(setMakeProgram.c_str()); + mf->ReadListFile(setMakeProgram); } } if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") || @@ -454,7 +456,7 @@ void cmGlobalGenerator::EnableLanguage( e << "Language '" << li << "' is currently being enabled. " "Recursive call not allowed."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return; } @@ -471,7 +473,7 @@ void cmGlobalGenerator::EnableLanguage( std::ostringstream e; e << "The test project needs language " << lang << " which is not enabled."; - this->TryCompileOuterMakefile->IssueMessage(cmake::FATAL_ERROR, + this->TryCompileOuterMakefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return; @@ -521,7 +523,7 @@ void cmGlobalGenerator::EnableLanguage( if (readCMakeSystem) { fpath += "/CMakeSystem.cmake"; if (cmSystemTools::FileExists(fpath)) { - mf->ReadListFile(fpath.c_str()); + mf->ReadListFile(fpath); } } // Load the CMakeDetermineSystem.cmake file and find out @@ -550,12 +552,12 @@ void cmGlobalGenerator::EnableLanguage( #endif // Read the DetermineSystem file std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake"); - mf->ReadListFile(systemFile.c_str()); + mf->ReadListFile(systemFile); // load the CMakeSystem.cmake from the binary directory // this file is configured by the CMakeDetermineSystem.cmake file fpath = rootBin; fpath += "/CMakeSystem.cmake"; - mf->ReadListFile(fpath.c_str()); + mf->ReadListFile(fpath); } if (readCMakeSystem) { @@ -602,7 +604,7 @@ void cmGlobalGenerator::EnableLanguage( // **** Load the system specific initialization if not yet loaded if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INITIALIZE_LOADED")) { fpath = mf->GetModulesFile("CMakeSystemSpecificInitialize.cmake"); - if (!mf->ReadListFile(fpath.c_str())) { + if (!mf->ReadListFile(fpath)) { cmSystemTools::Error("Could not find cmake module file: " "CMakeSystemSpecificInitialize.cmake"); } @@ -634,7 +636,7 @@ void cmGlobalGenerator::EnableLanguage( // version of CMake then try to load the configured file first // to avoid duplicate compiler tests. if (cmSystemTools::FileExists(fpath)) { - if (!mf->ReadListFile(fpath.c_str())) { + if (!mf->ReadListFile(fpath)) { cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); } @@ -661,7 +663,7 @@ void cmGlobalGenerator::EnableLanguage( determineCompiler += "Compiler.cmake"; std::string determineFile = mf->GetModulesFile(determineCompiler.c_str()); - if (!mf->ReadListFile(determineFile.c_str())) { + if (!mf->ReadListFile(determineFile)) { cmSystemTools::Error("Could not find cmake module file: ", determineCompiler.c_str()); } @@ -695,7 +697,7 @@ void cmGlobalGenerator::EnableLanguage( fpath += "/CMake"; fpath += lang; fpath += "Compiler.cmake"; - if (!mf->ReadListFile(fpath.c_str())) { + if (!mf->ReadListFile(fpath)) { cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); } @@ -712,7 +714,7 @@ void cmGlobalGenerator::EnableLanguage( // **** Load the system specific information if not yet loaded if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED")) { fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake"); - if (!mf->ReadListFile(fpath.c_str())) { + if (!mf->ReadListFile(fpath)) { cmSystemTools::Error("Could not find cmake module file: " "CMakeSystemSpecificInformation.cmake"); } @@ -775,7 +777,7 @@ void cmGlobalGenerator::EnableLanguage( if (!this->CMakeInstance->GetIsInTryCompile()) { this->PrintCompilerAdvice(noCompiler, lang, mf->GetDefinition(compilerEnv)); - mf->IssueMessage(cmake::FATAL_ERROR, noCompiler.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, noCompiler.str()); fatalError = true; } } @@ -792,7 +794,7 @@ void cmGlobalGenerator::EnableLanguage( if (informationFile.empty()) { cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); - } else if (!mf->ReadListFile(informationFile.c_str())) { + } else if (!mf->ReadListFile(informationFile)) { cmSystemTools::Error("Could not process cmake module file: ", informationFile.c_str()); } @@ -813,7 +815,7 @@ void cmGlobalGenerator::EnableLanguage( testLang += lang; testLang += "Compiler.cmake"; std::string ifpath = mf->GetModulesFile(testLang.c_str()); - if (!mf->ReadListFile(ifpath.c_str())) { + if (!mf->ReadListFile(ifpath)) { cmSystemTools::Error("Could not find cmake module file: ", testLang.c_str()); } @@ -851,7 +853,7 @@ void cmGlobalGenerator::EnableLanguage( projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME"); projectCompatibility += "Compatibility.cmake"; if (cmSystemTools::FileExists(projectCompatibility)) { - mf->ReadListFile(projectCompatibility.c_str()); + mf->ReadListFile(projectCompatibility); } // Inform any extra generator of the new language. if (this->ExtraGenerator) { @@ -903,7 +905,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( " compiler id \"AppleClang\" to \"Clang\" for compatibility." ; /* clang-format on */ - mf->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } CM_FALLTHROUGH; case cmPolicies::OLD: @@ -913,7 +915,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: mf->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025)); case cmPolicies::NEW: // NEW behavior is to keep AppleClang. @@ -933,7 +935,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( " compiler id \"QCC\" to \"GNU\" for compatibility." ; /* clang-format on */ - mf->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } CM_FALLTHROUGH; case cmPolicies::OLD: @@ -948,7 +950,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: mf->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047)); CM_FALLTHROUGH; case cmPolicies::NEW: @@ -1410,13 +1412,13 @@ void cmGlobalGenerator::Generate() if (!this->GenerateCPackPropertiesFile()) { this->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, "Could not write CPack properties file."); + MessageType::FATAL_ERROR, "Could not write CPack properties file."); } for (auto& buildExpSet : this->BuildExportSets) { if (!buildExpSet.second->GenerateImportFile()) { if (!cmSystemTools::GetErrorOccuredFlag()) { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, "Could not write export file."); } return; @@ -1439,7 +1441,8 @@ void cmGlobalGenerator::Generate() for (std::string const& t : this->CMP0042WarnTargets) { w << " " << t << "\n"; } - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + w.str()); } if (!this->CMP0068WarnTargets.empty()) { @@ -1455,7 +1458,8 @@ void cmGlobalGenerator::Generate() for (std::string const& t : this->CMP0068WarnTargets) { w << " " << t << "\n"; } - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + w.str()); } this->CMakeInstance->UpdateProgress("Generating done", -1); @@ -1758,7 +1762,7 @@ void cmGlobalGenerator::GenerateBuildCommand( bool /*unused*/, int /*unused*/, bool /*unused*/, std::vector<std::string> const& /*unused*/) { - makeCommand.push_back( + makeCommand.emplace_back( "cmGlobalGenerator::GenerateBuildCommand not implemented"); } @@ -2233,7 +2237,7 @@ bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName, if (!tgt) { return true; } - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; std::ostringstream e; bool issueMessage = false; switch (tgt->GetPolicyStatusCMP0037()) { @@ -2247,18 +2251,18 @@ bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } if (issueMessage) { e << "The target name \"" << targetName << "\" is reserved " << reason << "."; - if (messageType == cmake::AUTHOR_WARNING) { + if (messageType == MessageType::AUTHOR_WARNING) { e << " It may result in undefined behavior."; } this->GetCMakeInstance()->IssueMessage(messageType, e.str(), tgt->GetBacktrace()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -2310,12 +2314,12 @@ void cmGlobalGenerator::AddGlobalTarget_Package( singleLine.push_back("./CPackConfig.cmake"); gti.CommandLines.push_back(std::move(singleLine)); if (this->GetPreinstallTargetName()) { - gti.Depends.push_back(this->GetPreinstallTargetName()); + gti.Depends.emplace_back(this->GetPreinstallTargetName()); } else { const char* noPackageAll = mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY"); if (!noPackageAll || cmSystemTools::IsOff(noPackageAll)) { - gti.Depends.push_back(this->GetAllTargetName()); + gti.Depends.emplace_back(this->GetAllTargetName()); } } targets.push_back(std::move(gti)); @@ -2453,7 +2457,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( bool skipInstallRules = mf->IsOn("CMAKE_SKIP_INSTALL_RULES"); if (this->InstallTargetEnabled && skipInstallRules) { this->CMakeInstance->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "CMAKE_SKIP_INSTALL_RULES was enabled even though " "installation rules have been specified", mf->GetBacktrace()); @@ -2480,12 +2484,12 @@ void cmGlobalGenerator::AddGlobalTarget_Install( gti.UsesTerminal = true; cmCustomCommandLine singleLine; if (this->GetPreinstallTargetName()) { - gti.Depends.push_back(this->GetPreinstallTargetName()); + gti.Depends.emplace_back(this->GetPreinstallTargetName()); } else { const char* noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); if (!noall || cmSystemTools::IsOff(noall)) { - gti.Depends.push_back(this->GetAllTargetName()); + gti.Depends.emplace_back(this->GetAllTargetName()); } } if (mf->GetDefinition("CMake_BINARY_DIR") && diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h index 4e3e770..d4f772b 100644 --- a/Source/cmGlobalGeneratorFactory.h +++ b/Source/cmGlobalGeneratorFactory.h @@ -30,13 +30,20 @@ public: virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0; /** Get the names of the current registered generators */ - virtual void GetGenerators(std::vector<std::string>& names) const = 0; + virtual std::vector<std::string> GetGeneratorNames() const = 0; + virtual std::vector<std::string> GetGeneratorNamesWithPlatform() const = 0; /** Determine whether or not this generator supports toolsets */ virtual bool SupportsToolset() const = 0; /** Determine whether or not this generator supports platforms */ virtual bool SupportsPlatform() const = 0; + + /** Get the list of supported platforms name for this generator */ + virtual std::vector<std::string> GetKnownPlatforms() const = 0; + + /** If the generator suports platforms, get its default. */ + virtual std::string GetDefaultPlatformName() const = 0; }; template <class T> @@ -60,9 +67,15 @@ public: } /** Get the names of the current registered generators */ - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(T::GetActualName()); + return names; + } + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + return std::vector<std::string>(); } /** Determine whether or not this generator supports toolsets */ @@ -70,6 +83,15 @@ public: /** Determine whether or not this generator supports platforms */ bool SupportsPlatform() const override { return T::SupportsPlatform(); } + + /** Get the list of supported platforms name for this generator */ + std::vector<std::string> GetKnownPlatforms() const override + { + // default is no platform supported + return std::vector<std::string>(); + } + + std::string GetDefaultPlatformName() const override { return std::string(); } }; #endif diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index a9742c5..557efec 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -11,7 +11,9 @@ #include "cmGhsMultiTargetGenerator.h" #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmVersion.h" +#include "cmake.h" const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj"; const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild.exe"; @@ -19,13 +21,12 @@ const char* cmGlobalGhsMultiGenerator::DEFAULT_TOOLSET_ROOT = "C:/ghs"; cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm) : cmGlobalGenerator(cm) - , OSDirRelative(false) { + cm->GetState()->SetGhsMultiIDE(true); } cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() { - cmDeleteAll(TargetFolderBuildStreams); } cmLocalGenerator* cmGlobalGhsMultiGenerator::CreateLocalGenerator( @@ -41,46 +42,59 @@ void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) "Generates Green Hills MULTI files (experimental, work-in-progress)."; } +void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory( + cmGeneratorTarget* gt) const +{ + // Compute full path to object file directory for this target. + std::string dir; + dir += gt->LocalGenerator->GetCurrentBinaryDirectory(); + dir += "/"; + dir += gt->LocalGenerator->GetTargetDirectory(gt); + dir += "/"; + gt->ObjectDirectory = dir; +} + bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, cmMakefile* mf) { - std::string tsp; /* toolset path */ - std::string tsn = ts; /* toolset name */ + std::string tsp; /* toolset path */ - GetToolset(mf, tsp, tsn); + this->GetToolset(mf, tsp, ts); /* no toolset was found */ - if (tsn.empty()) { + if (tsp.empty()) { return false; } else if (ts.empty()) { std::string message; message = "Green Hills MULTI: -T <toolset> not specified; defaulting to \""; - message += tsn; + message += tsp; message += "\""; cmSystemTools::Message(message.c_str()); - /* store the toolset for later use + /* store the full toolset for later use * -- already done if -T<toolset> was specified */ - mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsn.c_str(), - "Name of generator toolset.", + mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp.c_str(), + "Location of generator toolset.", cmStateEnums::INTERNAL); } /* set the build tool to use */ + std::string gbuild(tsp + ((tsp.back() == '/') ? "" : "/") + + DEFAULT_BUILD_PROGRAM); const char* prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM"); - std::string gbuild(tsp + "/" + tsn + "/" + DEFAULT_BUILD_PROGRAM); /* check if the toolset changed from last generate */ if (prevTool != NULL && (gbuild != prevTool)) { - std::string message = "generator toolset: "; + std::string message = "toolset build tool: "; message += gbuild; - message += "\nDoes not match the toolset used previously: "; + message += "\nDoes not match the previously used build tool: "; message += prevTool; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; cmSystemTools::Error(message.c_str()); + return false; } else { /* store the toolset that is being used for this build */ mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(), @@ -88,25 +102,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, true); } - mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsn.c_str()); - - // FIXME: compiler detection not implemented - // gbuild uses the primaryTarget setting in the top-level project - // file to determine which compiler to use. Because compiler - // detection is not implemented these variables must be - // set to skip past these tests. However cmake will verify that - // the executable pointed to by CMAKE_<LANG>_COMPILER exists. - // To pass this additional check gbuild is used as a place holder for the - // actual compiler. - mf->AddDefinition("CMAKE_C_COMPILER", gbuild.c_str()); - mf->AddDefinition("CMAKE_C_COMPILER_ID_RUN", "TRUE"); - mf->AddDefinition("CMAKE_C_COMPILER_ID", "GHS"); - mf->AddDefinition("CMAKE_C_COMPILER_FORCED", "TRUE"); - - mf->AddDefinition("CMAKE_CXX_COMPILER", gbuild.c_str()); - mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE"); - mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS"); - mf->AddDefinition("CMAKE_CXX_COMPILER_FORCED", "TRUE"); + mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp.c_str()); return true; } @@ -129,6 +125,8 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM"); if (tgtPlatform == nullptr) { + cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not " + "specified; defaulting to \"integrity\""); tgtPlatform = "integrity"; } @@ -159,11 +157,11 @@ bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/) } void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd, - std::string& ts) + const std::string& ts) { const char* ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT"); - if (!ghsRoot) { + if (!ghsRoot || ghsRoot[0] == '\0') { ghsRoot = DEFAULT_TOOLSET_ROOT; } tsd = ghsRoot; @@ -172,129 +170,208 @@ void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd, std::vector<std::string> output; // Use latest? version + if (tsd.back() != '/') { + tsd += "/"; + } cmSystemTools::Glob(tsd, "comp_[^;]+", output); if (output.empty()) { - cmSystemTools::Error("GHS toolset not found in ", tsd.c_str()); - ts = ""; + std::string msg = + "No GHS toolsets found in GHS_TOOLSET_ROOT \"" + tsd + "\"."; + cmSystemTools::Error(msg.c_str()); + tsd = ""; } else { - ts = output.back(); + tsd += output.back(); } } else { - std::string tryPath = tsd + std::string("/") + ts; + std::string tryPath; + /* CollapseCombinedPath will check if ts is an absolute path */ + tryPath = cmSystemTools::CollapseCombinedPath(tsd, ts); if (!cmSystemTools::FileExists(tryPath)) { - cmSystemTools::Error("GHS toolset \"", ts.c_str(), "\" not found in ", - tsd.c_str()); - ts = ""; + std::string msg = "GHS toolset \"" + tryPath + "\" not found."; + cmSystemTools::Error(msg.c_str()); + tsd = ""; + } else { + tsd = tryPath; } } } -void cmGlobalGhsMultiGenerator::OpenBuildFileStream( - std::string const& filepath, cmGeneratedFileStream** filestream) +void cmGlobalGhsMultiGenerator::WriteFileHeader(std::ostream& fout) { - // Get a stream where to generate things. - if (NULL == *filestream) { - *filestream = new cmGeneratedFileStream(filepath.c_str()); - if (NULL != *filestream) { - OpenBuildFileStream(*filestream); - } - } + fout << "#!gbuild" << std::endl; + fout << "#" << std::endl + << "# CMAKE generated file: DO NOT EDIT!" << std::endl + << "# Generated by \"" << this->GetActualName() << "\"" + << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "." + << cmVersion::GetMinorVersion() << std::endl + << "#" << std::endl + << std::endl; } -void cmGlobalGhsMultiGenerator::OpenBuildFileStream( - cmGeneratedFileStream* filestream) +void cmGlobalGhsMultiGenerator::WriteTopLevelProject( + std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators) { - *filestream << "#!gbuild" << std::endl; -} + WriteFileHeader(fout); -void cmGlobalGhsMultiGenerator::OpenBuildFileStream() -{ - // Compute GHS MULTI's build file path. - std::string buildFilePath = - this->GetCMakeInstance()->GetHomeOutputDirectory(); - buildFilePath += "/"; - buildFilePath += "default"; - buildFilePath += FILE_EXTENSION; - - this->Open(std::string(""), buildFilePath, &this->TargetFolderBuildStreams); - OpenBuildFileStream(GetBuildFileStream()); - - char const* osDir = - this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR"); - if (NULL == osDir) { - osDir = ""; - cmSystemTools::Error("GHS_OS_DIR cache variable must be set"); - } else { - this->GetCMakeInstance()->MarkCliAsUsed("GHS_OS_DIR"); - } - std::string fOSDir(this->trimQuotes(osDir)); - std::replace(fOSDir.begin(), fOSDir.end(), '\\', '/'); - if (!fOSDir.empty() && ('c' == fOSDir[0] || 'C' == fOSDir[0])) { - this->OSDirRelative = false; - } else { - this->OSDirRelative = true; + this->WriteMacros(fout); + this->WriteHighLevelDirectives(fout); + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fout); + + fout << "# Top Level Project File" << std::endl; + + // Specify BSP option if supplied by user + // -- not all platforms require this entry in the project file + // integrity platforms require this field; use default if needed + std::string platform; + if (const char* p = + this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM")) { + platform = p; } std::string bspName; - char const* bspCache = - this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME"); - if (bspCache) { + if (char const* bspCache = + this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME")) { bspName = bspCache; this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME"); + } else { + bspName = "IGNORE"; } - if (bspName.empty() || bspName.compare("IGNORE") == 0) { + + if (platform.find("integrity") != std::string::npos && + cmSystemTools::IsOff(bspName.c_str())) { const char* a = this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM"); bspName = "sim"; bspName += (a ? a : ""); } - this->WriteMacros(); - this->WriteHighLevelDirectives(); + if (!cmSystemTools::IsOff(bspName.c_str())) { + fout << " -bsp " << bspName << std::endl; + } + + // Specify OS DIR if supplied by user + // -- not all platforms require this entry in the project file + std::string osDir; + std::string osDirOption; + if (char const* osDirCache = + this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR")) { + osDir = osDirCache; + } + + if (char const* osDirOptionCache = + this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR_OPTION")) { + osDirOption = osDirOptionCache; + } - GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, this->GetBuildFileStream()); - this->WriteDisclaimer(this->GetBuildFileStream()); - *this->GetBuildFileStream() << "# Top Level Project File" << std::endl; - *this->GetBuildFileStream() << " -bsp " << bspName << std::endl; + if (!cmSystemTools::IsOff(osDir.c_str()) || + platform.find("integrity") != std::string::npos) { + std::replace(osDir.begin(), osDir.end(), '\\', '/'); + fout << " " << osDirOption << "\"" << osDir << "\"" << std::endl; + } - this->WriteCompilerOptions(fOSDir); + WriteSubProjects(fout, root, generators); } -void cmGlobalGhsMultiGenerator::CloseBuildFileStream( - cmGeneratedFileStream** filestream) +void cmGlobalGhsMultiGenerator::WriteSubProjects( + std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators) { - if (filestream) { - delete *filestream; - *filestream = NULL; - } else { - cmSystemTools::Error("Build file stream was not open."); + // Collect all targets under this root generator and the transitive + // closure of their dependencies. + TargetDependSet projectTargets; + TargetDependSet originalTargets; + this->GetTargetSets(projectTargets, originalTargets, root, generators); + OrderedTargetDependSet orderedProjectTargets(projectTargets, ""); + + // write out all the sub-projects + std::string rootBinaryDir = root->GetCurrentBinaryDirectory(); + for (cmGeneratorTarget const* target : orderedProjectTargets) { + if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + continue; + } + + const char* projName = target->GetProperty("GENERATOR_FILE_NAME"); + const char* projType = target->GetProperty("GENERATOR_FILE_NAME_EXT"); + if (projName && projType) { + cmLocalGenerator* lg = target->GetLocalGenerator(); + std::string dir = lg->GetCurrentBinaryDirectory(); + dir = root->ConvertToRelativePath(rootBinaryDir, dir.c_str()); + if (dir == ".") { + dir.clear(); + } else { + if (dir.back() != '/') { + dir += "/"; + } + } + + if (cmSystemTools::IsOn(target->GetProperty("EXCLUDE_FROM_ALL"))) { + fout << "{comment} "; + } + std::string projFile = dir + projName + FILE_EXTENSION; + fout << projFile; + fout << " " << projType << std::endl; + + if (cmSystemTools::IsOn(target->GetProperty("GHS_REFERENCE_PROJECT"))) { + // create reference project + std::string fname = dir; + fname += target->GetName(); + fname += "REF"; + fname += FILE_EXTENSION; + + cmGeneratedFileStream fref(fname.c_str()); + fref.SetCopyIfDifferent(true); + + this->WriteFileHeader(fref); + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fref); + fref << " :reference=" << projFile << std::endl; + + fref.Close(); + } + } } } void cmGlobalGhsMultiGenerator::Generate() { + // first do the superclass method this->cmGlobalGenerator::Generate(); - if (!this->LocalGenerators.empty()) { - this->OpenBuildFileStream(); + // output top-level projects + for (auto& it : this->ProjectMap) { + this->OutputTopLevelProject(it.second[0], it.second); + } +} - // Build all the folder build files - for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { - cmLocalGhsMultiGenerator* lg = - static_cast<cmLocalGhsMultiGenerator*>(this->LocalGenerators[i]); - const std::vector<cmGeneratorTarget*>& tgts = lg->GetGeneratorTargets(); - this->UpdateBuildFiles(tgts); - } +void cmGlobalGhsMultiGenerator::OutputTopLevelProject( + cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) +{ + if (generators.empty()) { + return; } - cmDeleteAll(TargetFolderBuildStreams); - this->TargetFolderBuildStreams.clear(); + /* Name top-level projects as filename.top.gpj to avoid name clashes + * with target projects. This avoid the issue where the project has + * the same name as the executable target. + */ + std::string fname = root->GetCurrentBinaryDirectory(); + fname += "/"; + fname += root->GetProjectName(); + fname += ".top"; + fname += FILE_EXTENSION; + + cmGeneratedFileStream fout(fname.c_str()); + fout.SetCopyIfDifferent(true); + + this->WriteTopLevelProject(fout, root, generators); + + fout.Close(); } void cmGlobalGhsMultiGenerator::GenerateBuildCommand( std::vector<std::string>& makeCommand, const std::string& makeProgram, - const std::string& /*projectName*/, const std::string& /*projectDir*/, + const std::string& projectName, const std::string& projectDir, const std::string& targetName, const std::string& /*config*/, bool /*fast*/, int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) { @@ -312,16 +389,34 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand( makeCommand.insert(makeCommand.end(), makeOptions.begin(), makeOptions.end()); + + /* determine which top-project file to use */ + std::string proj = projectName + ".top" + FILE_EXTENSION; + std::vector<std::string> files; + cmSystemTools::Glob(projectDir, ".*\\.top\\.gpj", files); + if (!files.empty()) { + auto p = std::find(files.begin(), files.end(), proj); + if (p == files.end()) { + proj = files.at(0); + } + } + + makeCommand.push_back("-top"); + makeCommand.push_back(proj); if (!targetName.empty()) { if (targetName == "clean") { makeCommand.push_back("-clean"); } else { - makeCommand.push_back(targetName); + if (targetName.compare(targetName.size() - 4, 4, ".gpj") == 0) { + makeCommand.push_back(targetName); + } else { + makeCommand.push_back(targetName + ".gpj"); + } } } } -void cmGlobalGhsMultiGenerator::WriteMacros() +void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout) { char const* ghsGpjMacros = this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS"); @@ -331,12 +426,12 @@ void cmGlobalGhsMultiGenerator::WriteMacros() for (std::vector<std::string>::const_iterator expandedListI = expandedList.begin(); expandedListI != expandedList.end(); ++expandedListI) { - *this->GetBuildFileStream() << "macro " << *expandedListI << std::endl; + fout << "macro " << *expandedListI << std::endl; } } } -void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives() +void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(std::ostream& fout) { /* set primary target */ std::string tgt; @@ -356,183 +451,46 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives() tgt += ".tgt"; } - *this->GetBuildFileStream() << "primaryTarget=" << tgt << std::endl; + fout << "primaryTarget=" << tgt << std::endl; char const* const customization = this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION"); if (NULL != customization && strlen(customization) > 0) { - *this->GetBuildFileStream() - << "customization=" << trimQuotes(customization) << std::endl; + fout << "customization=" << trimQuotes(customization) << std::endl; this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION"); } } -void cmGlobalGhsMultiGenerator::WriteCompilerOptions(std::string const& fOSDir) -{ - *this->GetBuildFileStream() - << " -os_dir=\"" << fOSDir << "\"" << std::endl; -} - -void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream* os) -{ - (*os) << "#" << std::endl - << "# CMAKE generated file: DO NOT EDIT!" << std::endl - << "# Generated by \"" << GetActualName() << "\"" - << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "." - << cmVersion::GetMinorVersion() << std::endl - << "#" << std::endl; -} - -void cmGlobalGhsMultiGenerator::AddFilesUpToPath( - cmGeneratedFileStream* mainBuildFile, - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - char const* homeOutputDirectory, std::string const& path, - GhsMultiGpj::Types projType, std::string const& relPath) +std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str) { - std::string workingPath(path); - cmSystemTools::ConvertToUnixSlashes(workingPath); - std::vector<std::string> splitPath = cmSystemTools::SplitString(workingPath); - std::string workingRelPath(relPath); - cmSystemTools::ConvertToUnixSlashes(workingRelPath); - if (!workingRelPath.empty()) { - workingRelPath += "/"; - } - std::string pathUpTo; - for (std::vector<std::string>::const_iterator splitPathI = splitPath.begin(); - splitPath.end() != splitPathI; ++splitPathI) { - pathUpTo += *splitPathI; - if (targetFolderBuildStreams->end() == - targetFolderBuildStreams->find(pathUpTo)) { - AddFilesUpToPathNewBuildFile( - mainBuildFile, targetFolderBuildStreams, homeOutputDirectory, pathUpTo, - splitPath.begin() == splitPathI, workingRelPath, projType); + std::string result; + result.reserve(str.size()); + for (const char* ch = str.c_str(); *ch != '\0'; ++ch) { + if (*ch != '"') { + result += *ch; } - AddFilesUpToPathAppendNextFile(targetFolderBuildStreams, pathUpTo, - splitPathI, splitPath.end(), projType); - pathUpTo += "/"; - } -} - -void cmGlobalGhsMultiGenerator::Open( - std::string const& mapKeyName, std::string const& fileName, - std::map<std::string, cmGeneratedFileStream*>* fileMap) -{ - if (fileMap->end() == fileMap->find(fileName)) { - cmGeneratedFileStream* temp(new cmGeneratedFileStream); - temp->open(fileName.c_str()); - (*fileMap)[mapKeyName] = temp; - } -} - -void cmGlobalGhsMultiGenerator::AddFilesUpToPathNewBuildFile( - cmGeneratedFileStream* mainBuildFile, - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - char const* homeOutputDirectory, std::string const& pathUpTo, - bool const isFirst, std::string const& relPath, - GhsMultiGpj::Types const projType) -{ - // create folders up to file path - std::string absPath = std::string(homeOutputDirectory) + "/" + relPath; - std::string newPath = absPath + pathUpTo; - if (!cmSystemTools::FileExists(newPath.c_str())) { - cmSystemTools::MakeDirectory(newPath.c_str()); - } - - // Write out to filename for first time - std::string relFilename(GetFileNameFromPath(pathUpTo)); - std::string absFilename = absPath + relFilename; - Open(pathUpTo, absFilename, targetFolderBuildStreams); - OpenBuildFileStream((*targetFolderBuildStreams)[pathUpTo]); - GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]); - WriteDisclaimer((*targetFolderBuildStreams)[pathUpTo]); - - // Add to main build file - if (isFirst) { - *mainBuildFile << relFilename << " "; - GhsMultiGpj::WriteGpjTag(projType, mainBuildFile); - } -} - -void cmGlobalGhsMultiGenerator::AddFilesUpToPathAppendNextFile( - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - std::string const& pathUpTo, - std::vector<std::string>::const_iterator splitPathI, - std::vector<std::string>::const_iterator end, - GhsMultiGpj::Types const projType) -{ - std::vector<std::string>::const_iterator splitPathNextI = splitPathI + 1; - if (end != splitPathNextI && - targetFolderBuildStreams->end() == - targetFolderBuildStreams->find(pathUpTo + "/" + *splitPathNextI)) { - std::string nextFilename(*splitPathNextI); - nextFilename = GetFileNameFromPath(nextFilename); - *(*targetFolderBuildStreams)[pathUpTo] << nextFilename << " "; - GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]); } + return result; } -std::string cmGlobalGhsMultiGenerator::GetFileNameFromPath( - std::string const& path) +bool cmGlobalGhsMultiGenerator::TargetCompare::operator()( + cmGeneratorTarget const* l, cmGeneratorTarget const* r) const { - std::string output(path); - if (!path.empty()) { - cmSystemTools::ConvertToUnixSlashes(output); - std::vector<std::string> splitPath = cmSystemTools::SplitString(output); - output += "/" + splitPath.back() + FILE_EXTENSION; + // Make sure a given named target is ordered first, + // e.g. to set ALL_BUILD as the default active project. + // When the empty string is named this is a no-op. + if (r->GetName() == this->First) { + return false; } - return output; -} - -void cmGlobalGhsMultiGenerator::UpdateBuildFiles( - const std::vector<cmGeneratorTarget*>& tgts) -{ - for (std::vector<cmGeneratorTarget*>::const_iterator tgtsI = tgts.begin(); - tgtsI != tgts.end(); ++tgtsI) { - const cmGeneratorTarget* tgt = *tgtsI; - if (IsTgtForBuild(tgt)) { - std::string folderName = tgt->GetEffectiveFolderName(); - if (this->TargetFolderBuildStreams.end() == - this->TargetFolderBuildStreams.find(folderName)) { - this->AddFilesUpToPath( - GetBuildFileStream(), &this->TargetFolderBuildStreams, - this->GetCMakeInstance()->GetHomeOutputDirectory().c_str(), - folderName, GhsMultiGpj::PROJECT); - } - std::vector<std::string> splitPath = cmSystemTools::SplitString( - cmGhsMultiTargetGenerator::GetRelBuildFileName(tgt)); - std::string foldNameRelBuildFile(*(splitPath.end() - 2) + "/" + - splitPath.back()); - *this->TargetFolderBuildStreams[folderName] << foldNameRelBuildFile - << " "; - GhsMultiGpj::WriteGpjTag(cmGhsMultiTargetGenerator::GetGpjTag(tgt), - this->TargetFolderBuildStreams[folderName]); - } + if (l->GetName() == this->First) { + return true; } + return l->GetName() < r->GetName(); } -bool cmGlobalGhsMultiGenerator::IsTgtForBuild(const cmGeneratorTarget* tgt) +cmGlobalGhsMultiGenerator::OrderedTargetDependSet::OrderedTargetDependSet( + TargetDependSet const& targets, std::string const& first) + : derived(TargetCompare(first)) { - const std::string config = - tgt->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); - std::vector<cmSourceFile*> tgtSources; - tgt->GetSourceFiles(tgtSources, config); - bool tgtInBuild = true; - char const* excludeFromAll = tgt->GetProperty("EXCLUDE_FROM_ALL"); - if (NULL != excludeFromAll && '1' == excludeFromAll[0] && - '\0' == excludeFromAll[1]) { - tgtInBuild = false; - } - return !tgtSources.empty() && tgtInBuild; -} - -std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str) -{ - std::string result; - result.reserve(str.size()); - for (const char* ch = str.c_str(); *ch != '\0'; ++ch) { - if (*ch != '"') { - result += *ch; - } - } - return result; + this->insert(targets.begin(), targets.end()); } diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index a5aff73..9332567 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -13,7 +13,7 @@ class cmGeneratedFileStream; class cmGlobalGhsMultiGenerator : public cmGlobalGenerator { public: - /// The default name of GHS MULTI's build file. Typically: monolith.gpj. + // The default filename extension of GHS MULTI's build files. static const char* FILE_EXTENSION; cmGlobalGhsMultiGenerator(cmake* cm); @@ -63,29 +63,28 @@ public: */ bool FindMakeProgram(cmMakefile* mf) override; - cmGeneratedFileStream* GetBuildFileStream() - { - return this->TargetFolderBuildStreams[""]; - } + void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; - static void OpenBuildFileStream(std::string const& filepath, - cmGeneratedFileStream** filestream); - static void OpenBuildFileStream(cmGeneratedFileStream* filestream); - static void CloseBuildFileStream(cmGeneratedFileStream** filestream); - /// Write the common disclaimer text at the top of each build file. - static void WriteDisclaimer(std::ostream* os); - std::vector<std::string> GetLibDirs() { return this->LibDirs; } - - static void AddFilesUpToPath( - cmGeneratedFileStream* mainBuildFile, - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - char const* homeOutputDirectory, std::string const& path, - GhsMultiGpj::Types projType, std::string const& relPath = ""); - static void Open(std::string const& mapKeyName, std::string const& fileName, - std::map<std::string, cmGeneratedFileStream*>* fileMap); - - static std::string trimQuotes(std::string const& str); - inline bool IsOSDirRelative() { return this->OSDirRelative; } + // Write the common disclaimer text at the top of each build file. + void WriteFileHeader(std::ostream& fout); + + // Target dependency sorting + class TargetSet : public std::set<cmGeneratorTarget const*> + { + }; + class TargetCompare + { + std::string First; + + public: + TargetCompare(std::string const& first) + : First(first) + { + } + bool operator()(cmGeneratorTarget const* l, + cmGeneratorTarget const* r) const; + }; + class OrderedTargetDependSet; protected: void Generate() override; @@ -100,35 +99,35 @@ protected: std::vector<std::string>()) override; private: - void GetToolset(cmMakefile* mf, std::string& tsd, std::string& ts); - void OpenBuildFileStream(); - - void WriteMacros(); - void WriteHighLevelDirectives(); - void WriteCompilerOptions(std::string const& fOSDir); - - static void AddFilesUpToPathNewBuildFile( - cmGeneratedFileStream* mainBuildFile, - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - char const* homeOutputDirectory, std::string const& pathUpTo, bool isFirst, - std::string const& relPath, GhsMultiGpj::Types projType); - static void AddFilesUpToPathAppendNextFile( - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - std::string const& pathUpTo, - std::vector<std::string>::const_iterator splitPathI, - std::vector<std::string>::const_iterator end, GhsMultiGpj::Types projType); - static std::string GetFileNameFromPath(std::string const& path); - void UpdateBuildFiles(const std::vector<cmGeneratorTarget*>& tgts); - bool IsTgtForBuild(const cmGeneratorTarget* tgt); - - std::vector<cmGeneratedFileStream*> TargetSubProjects; - std::map<std::string, cmGeneratedFileStream*> TargetFolderBuildStreams; - - std::vector<std::string> LibDirs; - - bool OSDirRelative; + void GetToolset(cmMakefile* mf, std::string& tsd, const std::string& ts); + + /* top-level project */ + void OutputTopLevelProject(cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators); + void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators); + void WriteMacros(std::ostream& fout); + void WriteHighLevelDirectives(std::ostream& fout); + void WriteSubProjects(std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators); + + std::string trimQuotes(std::string const& str); + static const char* DEFAULT_BUILD_PROGRAM; static const char* DEFAULT_TOOLSET_ROOT; }; +class cmGlobalGhsMultiGenerator::OrderedTargetDependSet + : public std::multiset<cmTargetDepend, + cmGlobalGhsMultiGenerator::TargetCompare> +{ + typedef std::multiset<cmTargetDepend, + cmGlobalGhsMultiGenerator::TargetCompare> + derived; + +public: + typedef cmGlobalGenerator::TargetDependSet TargetDependSet; + OrderedTargetDependSet(TargetDependSet const&, std::string const& first); +}; + #endif diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index 0f41ea1..9c805a8 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -6,6 +6,7 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmake.h" cmGlobalJOMMakefileGenerator::cmGlobalJOMMakefileGenerator(cmake* cm) : cmGlobalUnixMakefileGenerator3(cm) diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx index 3f22382..3c24556 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.cxx +++ b/Source/cmGlobalMSYSMakefileGenerator.cxx @@ -7,6 +7,7 @@ #include "cmDocumentationEntry.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmake.h" diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx index 3c3a5d1d..c6d46e9 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.cxx +++ b/Source/cmGlobalMinGWMakefileGenerator.cxx @@ -6,6 +6,7 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmake.h" cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator(cmake* cm) : cmGlobalUnixMakefileGenerator3(cm) diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index eb66bd1..5235be7 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -6,6 +6,7 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmake.h" cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm) : cmGlobalUnixMakefileGenerator3(cm) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index dcd2585..23dbd76 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -23,6 +23,7 @@ #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmNinjaLinkLineComputer.h" #include "cmOutputConverter.h" #include "cmState.h" @@ -502,7 +503,8 @@ void cmGlobalNinjaGenerator::Generate() msg << "The detected version of Ninja (" << this->NinjaVersion; msg << ") is less than the version of Ninja required by CMake ("; msg << cmGlobalNinjaGenerator::RequiredNinjaVersion() << ")."; - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + msg.str()); return; } this->OpenBuildFileStream(); @@ -548,13 +550,13 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) this->NinjaCommand = ninjaCommand; std::vector<std::string> command; command.push_back(this->NinjaCommand); - command.push_back("--version"); + command.emplace_back("--version"); std::string version; std::string error; if (!cmSystemTools::RunSingleCommand(command, &version, &error, nullptr, nullptr, cmSystemTools::OUTPUT_NONE)) { - mf->IssueMessage(cmake::FATAL_ERROR, + mf->IssueMessage(MessageType::FATAL_ERROR, "Running\n '" + cmJoin(command, "' '") + "'\n" "failed with:\n " + @@ -634,7 +636,7 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const ; /* clang-format on */ } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -679,12 +681,12 @@ void cmGlobalNinjaGenerator::GenerateBuildCommand( makeCommand.push_back(this->SelectMakeProgram(makeProgram)); if (verbose) { - makeCommand.push_back("-v"); + makeCommand.emplace_back("-v"); } if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) && (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) { - makeCommand.push_back("-j"); + makeCommand.emplace_back("-j"); makeCommand.push_back(std::to_string(jobs)); } @@ -692,8 +694,8 @@ void cmGlobalNinjaGenerator::GenerateBuildCommand( makeOptions.end()); if (!targetName.empty()) { if (targetName == "clean") { - makeCommand.push_back("-t"); - makeCommand.push_back("clean"); + makeCommand.emplace_back("-t"); + makeCommand.emplace_back("clean"); } else { makeCommand.push_back(targetName); } @@ -1300,7 +1302,8 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) "options to the custom commands that produce these files." ; /* clang-format on */ - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + w.str()); } } @@ -1428,7 +1431,8 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) << "\n"; msg << "Any pre-check scripts, such as those generated for file(GLOB " "CONFIGURE_DEPENDS), will not be run by Ninja."; - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + msg.str()); } std::sort(implicitDeps.begin(), implicitDeps.end()); @@ -1935,7 +1939,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, } } - cmake cm(cmake::RoleInternal); + cmake cm(cmake::RoleInternal, cmState::Unknown); cm.SetHomeDirectory(dir_top_src); cm.SetHomeOutputDirectory(dir_top_bld); std::unique_ptr<cmGlobalNinjaGenerator> ggd( diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index db72353..52bb046 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -7,6 +7,7 @@ #include <sstream> #include <utility> +#include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -215,7 +216,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() // Just depend on the all target to drive the build. std::vector<std::string> depends; std::vector<std::string> no_commands; - depends.push_back("all"); + depends.emplace_back("all"); // Write the rule. lg->WriteMakeRule(makefileStream, @@ -494,6 +495,7 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( const std::string& targetName, const std::string& /*config*/, bool fast, int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) { + std::unique_ptr<cmMakefile> mfu; cmMakefile* mf; if (!this->Makefiles.empty()) { mf = this->Makefiles[0]; @@ -504,13 +506,14 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( snapshot.GetDirectory().SetCurrentBinary( this->CMakeInstance->GetHomeOutputDirectory()); snapshot.SetDefaultDefinitions(); - mf = new cmMakefile(this, snapshot); + mfu = cm::make_unique<cmMakefile>(this, snapshot); + mf = mfu.get(); } makeCommand.push_back(this->SelectMakeProgram(makeProgram)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back("-j"); + makeCommand.emplace_back("-j"); if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { makeCommand.push_back(std::to_string(jobs)); } @@ -529,9 +532,6 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( cmSystemTools::ConvertToOutputSlashes(tname); makeCommand.push_back(std::move(tname)); } - if (this->Makefiles.empty()) { - delete mf; - } } void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( @@ -542,7 +542,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } // write the target convenience rules @@ -577,7 +577,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), name)); depends.clear(); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name, depends, commands, true); @@ -631,7 +631,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } // for each target Generate the rule files for each target. @@ -740,7 +740,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( } depends.clear(); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } localName = lg->GetRelativeTargetDirectory(gtarget); localName += "/rule"; diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index a6bec4b..dbe582b 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -7,6 +7,7 @@ #include "cmGeneratorTarget.h" #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmVersion.h" #include "cmVisualStudioSlnData.h" @@ -73,15 +74,34 @@ public: "Optional [arch] can be \"Win64\" or \"IA64\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs10generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs10generatorName + std::string(" IA64")); names.push_back(vs10generatorName + std::string(" Win64")); + return names; } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("Itanium"); + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory() @@ -179,7 +199,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( std::ostringstream e; e << this->GetName() << " Windows CE version '" << this->SystemVersion << "' requires CMAKE_GENERATOR_TOOLSET to be set."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -252,7 +272,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( "contains an invalid version specification." ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); // Clear the configured tool-set this->GeneratorToolsetVersion.clear(); @@ -279,7 +299,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( " " << toolsetPath; ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); // Clear the configured tool-set this->GeneratorToolsetVersion.clear(); @@ -333,7 +353,7 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( "that contains a field after the first ',' with no '='." ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } std::string const key = fi->substr(0, pos); @@ -349,7 +369,7 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( "that contains duplicate field key '" << key << "'." ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } if (!this->ProcessGeneratorToolsetField(key, value)) { @@ -363,7 +383,7 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( "that contains invalid field '" << *fi << "'." ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } } @@ -411,12 +431,12 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) std::ostringstream e; e << "CMAKE_SYSTEM_NAME is 'Android' but CMAKE_GENERATOR " << "specifies a platform too: '" << this->GetName() << "'"; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } std::string v = this->GetInstalledNsightTegraVersion(); if (v.empty()) { - mf->IssueMessage(cmake::FATAL_ERROR, + mf->IssueMessage(MessageType::FATAL_ERROR, "CMAKE_SYSTEM_NAME is 'Android' but " "'NVIDIA Nsight Tegra Visual Studio Edition' " "is not installed."); @@ -442,7 +462,7 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf) std::ostringstream e; e << "CMAKE_SYSTEM_NAME is 'WindowsCE' but CMAKE_GENERATOR " << "specifies a platform too: '" << this->GetName() << "'"; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -455,7 +475,7 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsPhone(cmMakefile* mf) { std::ostringstream e; e << this->GetName() << " does not support Windows Phone."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -463,7 +483,7 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsStore(cmMakefile* mf) { std::ostringstream e; e << this->GetName() << " does not support Windows Store."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -524,7 +544,7 @@ void cmGlobalVisualStudio10Generator::Generate() "To avoid this problem CMake must use a full path for this file " "which then triggers the VS 10 property dialog bug."; /* clang-format on */ - lg->IssueMessage(cmake::WARNING, e.str().c_str()); + lg->IssueMessage(MessageType::WARNING, e.str().c_str()); } } @@ -707,7 +727,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) // Prepare the work directory. if (!cmSystemTools::MakeDirectory(wd)) { std::string e = "Failed to make directory:\n " + wd; - mf->IssueMessage(cmake::FATAL_ERROR, e.c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.c_str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -829,7 +849,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) if (ret != 0) { e << "Exit code: " << ret << "\n"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -973,7 +993,7 @@ bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf) << "Install the Microsoft Windows SDK v7.1 to get 64-bit tools:\n" << " http://msdn.microsoft.com/en-us/windows/bb980924.aspx"; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -1032,6 +1052,8 @@ const char* cmGlobalVisualStudio10Generator::GetToolsVersion() const return "14.0"; case cmGlobalVisualStudioGenerator::VS15: return "15.0"; + case cmGlobalVisualStudioGenerator::VS16: + return "16.0"; } return ""; } @@ -1135,14 +1157,32 @@ static cmIDEFlagTable const* cmLoadFlagTableJson( return ret; } +static std::string cmGetFlagTableName(std::string const& toolsetName, + std::string const& table) +{ + return cmSystemTools::GetCMakeRoot() + "/Templates/MSBuild/FlagTables/" + + toolsetName + "_" + table + ".json"; +} + cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( - std::string const& flagTableName, std::string const& table) const + std::string const& optionsName, std::string const& toolsetName, + std::string const& defaultName, std::string const& table) const { cmIDEFlagTable const* ret = nullptr; - std::string filename = cmSystemTools::GetCMakeRoot() + - "/Templates/MSBuild/FlagTables/" + flagTableName + "_" + table + ".json"; - ret = cmLoadFlagTableJson(filename); + std::string filename; + if (!optionsName.empty()) { + filename = cmGetFlagTableName(optionsName, table); + ret = cmLoadFlagTableJson(filename); + } else { + filename = cmGetFlagTableName(toolsetName, table); + if (cmSystemTools::FileExists(filename)) { + ret = cmLoadFlagTableJson(filename); + } else { + filename = cmGetFlagTableName(defaultName, table); + ret = cmLoadFlagTableJson(filename); + } + } if (!ret) { cmMakefile* mf = this->GetCurrentMakefile(); @@ -1152,78 +1192,102 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( e << "JSON flag table \"" << filename << "\" could not be loaded.\n"; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); } return ret; } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const { - std::string flagTableName = this->ToolsetOptions.GetClFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString(), - this->DefaultCLFlagTableName); - - return LoadFlagTable(flagTableName, "CL"); + std::string optionsName = this->ToolsetOptions.GetClFlagTableName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultCLFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "CL"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() const { - std::string flagTableName = this->ToolsetOptions.GetCSharpFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString(), - this->DefaultCSharpFlagTableName); - - return LoadFlagTable(flagTableName, "CSharp"); + std::string optionsName = this->ToolsetOptions.GetCSharpFlagTableName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultCSharpFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const { - std::string flagTableName = this->ToolsetOptions.GetRcFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString(), - this->DefaultRCFlagTableName); - - return LoadFlagTable(flagTableName, "RC"); + std::string optionsName = this->ToolsetOptions.GetRcFlagTableName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultRCFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "RC"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const { - std::string flagTableName = this->ToolsetOptions.GetLibFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString(), - this->DefaultLibFlagTableName); - - return LoadFlagTable(flagTableName, "LIB"); + std::string optionsName = this->ToolsetOptions.GetLibFlagTableName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultLibFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const { - std::string flagTableName = this->ToolsetOptions.GetLinkFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString(), - this->DefaultLinkFlagTableName); - - return LoadFlagTable(flagTableName, "Link"); + std::string optionsName = this->ToolsetOptions.GetLinkFlagTableName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultLinkFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "Link"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const { - return LoadFlagTable(this->DefaultCudaFlagTableName, "Cuda"); + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultCudaFlagTableName); + return LoadFlagTable("", toolsetName, defaultName, "Cuda"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() const { - return LoadFlagTable(this->DefaultCudaHostFlagTableName, "CudaHost"); + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultCudaHostFlagTableName); + return LoadFlagTable("", toolsetName, defaultName, "CudaHost"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { - std::string flagTableName = this->ToolsetOptions.GetMasmFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString(), - this->DefaultMasmFlagTableName); - - return LoadFlagTable(flagTableName, "MASM"); + std::string optionsName = this->ToolsetOptions.GetMasmFlagTableName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultMasmFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const { - return LoadFlagTable(this->DefaultNasmFlagTableName, "NASM"); + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultNasmFlagTableName); + return LoadFlagTable("", toolsetName, defaultName, "NASM"); } diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 7f7c516..7c8918a 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -142,7 +142,9 @@ protected: std::string const& GetMSBuildCommand(); - cmIDEFlagTable const* LoadFlagTable(std::string const& flagTableName, + cmIDEFlagTable const* LoadFlagTable(std::string const& optionsName, + std::string const& toolsetName, + std::string const& defaultName, std::string const& table) const; std::string GeneratorToolset; diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index 07318cf..4eb78ba 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -69,9 +69,16 @@ public: "Optional [arch] can be \"Win64\" or \"ARM\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs11generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs11generatorName + std::string(" ARM")); names.push_back(vs11generatorName + std::string(" Win64")); @@ -80,10 +87,30 @@ public: for (std::string const& i : installedSDKs) { names.push_back(std::string(vs11generatorName) + " " + i); } + + return names; } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + + std::set<std::string> installedSDKs = + cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs(); + for (std::string const& i : installedSDKs) { + platforms.emplace_back(i); + } + + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory() @@ -133,7 +160,7 @@ bool cmGlobalVisualStudio11Generator::InitializeWindowsPhone(cmMakefile* mf) << "Desktop SDK as well as the Windows Phone '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return true; @@ -151,7 +178,7 @@ bool cmGlobalVisualStudio11Generator::InitializeWindowsStore(cmMakefile* mf) << "Desktop SDK as well as the Windows Store '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return true; diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index f9da68c..8b50684 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -58,15 +58,34 @@ public: "Optional [arch] can be \"Win64\" or \"ARM\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs12generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs12generatorName + std::string(" ARM")); names.push_back(vs12generatorName + std::string(" Win64")); + return names; } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory() @@ -129,7 +148,7 @@ bool cmGlobalVisualStudio12Generator::InitializeWindowsPhone(cmMakefile* mf) << "Desktop SDK as well as the Windows Phone '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return true; @@ -149,7 +168,7 @@ bool cmGlobalVisualStudio12Generator::InitializeWindowsStore(cmMakefile* mf) << "Desktop SDK as well as the Windows Store '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return true; diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 8f7dac9..a0a9558 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -58,15 +58,34 @@ public: "Optional [arch] can be \"Win64\" or \"ARM\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs14generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs14generatorName + std::string(" ARM")); names.push_back(vs14generatorName + std::string(" Win64")); + return names; } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory() @@ -126,7 +145,7 @@ bool cmGlobalVisualStudio14Generator::InitializeWindowsStore(cmMakefile* mf) << "Desktop SDK as well as the Windows Store '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { @@ -144,7 +163,7 @@ bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf, std::ostringstream e; e << "Could not find an appropriate version of the Windows 10 SDK" << " installed on this machine"; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } if (!cmSystemTools::VersionCompareEqual(this->WindowsTargetPlatformVersion, diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx deleted file mode 100644 index eb49e87..0000000 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ /dev/null @@ -1,285 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmGlobalVisualStudio15Generator.h" - -#include "cmAlgorithms.h" -#include "cmDocumentationEntry.h" -#include "cmLocalVisualStudio10Generator.h" -#include "cmMakefile.h" -#include "cmVSSetupHelper.h" - -static const char vs15generatorName[] = "Visual Studio 15 2017"; - -// Map generator name without year to name with year. -static const char* cmVS15GenName(const std::string& name, std::string& genName) -{ - if (strncmp(name.c_str(), vs15generatorName, - sizeof(vs15generatorName) - 6) != 0) { - return 0; - } - const char* p = name.c_str() + sizeof(vs15generatorName) - 6; - if (cmHasLiteralPrefix(p, " 2017")) { - p += 5; - } - genName = std::string(vs15generatorName) + p; - return p; -} - -class cmGlobalVisualStudio15Generator::Factory - : public cmGlobalGeneratorFactory -{ -public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override - { - std::string genName; - const char* p = cmVS15GenName(name, genName); - if (!p) { - return 0; - } - if (!*p) { - return new cmGlobalVisualStudio15Generator(cm, genName, ""); - } - if (*p++ != ' ') { - return 0; - } - if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio15Generator(cm, genName, "x64"); - } - if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio15Generator(cm, genName, "ARM"); - } - return 0; - } - - void GetDocumentation(cmDocumentationEntry& entry) const override - { - entry.Name = std::string(vs15generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2017 project files. " - "Optional [arch] can be \"Win64\" or \"ARM\"."; - } - - void GetGenerators(std::vector<std::string>& names) const override - { - names.push_back(vs15generatorName); - names.push_back(vs15generatorName + std::string(" ARM")); - names.push_back(vs15generatorName + std::string(" Win64")); - } - - bool SupportsToolset() const override { return true; } - bool SupportsPlatform() const override { return true; } -}; - -cmGlobalGeneratorFactory* cmGlobalVisualStudio15Generator::NewFactory() -{ - return new Factory; -} - -cmGlobalVisualStudio15Generator::cmGlobalVisualStudio15Generator( - cmake* cm, const std::string& name, - std::string const& platformInGeneratorName) - : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName) -{ - this->ExpressEdition = false; - this->DefaultPlatformToolset = "v141"; - this->DefaultCLFlagTableName = "v141"; - this->DefaultCSharpFlagTableName = "v141"; - this->DefaultLinkFlagTableName = "v141"; - this->Version = VS15; -} - -bool cmGlobalVisualStudio15Generator::MatchesGeneratorName( - const std::string& name) const -{ - std::string genName; - if (cmVS15GenName(name, genName)) { - return genName == this->GetName(); - } - return false; -} - -bool cmGlobalVisualStudio15Generator::SetGeneratorInstance( - std::string const& i, cmMakefile* mf) -{ - if (!i.empty()) { - if (!this->vsSetupAPIHelper.SetVSInstance(i)) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "could not find specified instance of Visual Studio:\n" - " " << i; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } - } - - std::string vsInstance; - if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "could not find any instance of Visual Studio.\n"; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } - - // Save the selected instance persistently. - std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); - if (vsInstance != genInstance) { - this->CMakeInstance->AddCacheEntry( - "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(), - "Generator instance identifier.", cmStateEnums::INTERNAL); - } - - return true; -} - -bool cmGlobalVisualStudio15Generator::GetVSInstance(std::string& dir) const -{ - return vsSetupAPIHelper.GetVSInstanceInfo(dir); -} - -bool cmGlobalVisualStudio15Generator::IsDefaultToolset( - const std::string& version) const -{ - if (version.empty()) { - return true; - } - - std::string vcToolsetVersion; - if (this->vsSetupAPIHelper.GetVCToolsetVersion(vcToolsetVersion)) { - - cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9]+"); - if (regex.find(version) && regex.find(vcToolsetVersion)) { - const auto majorMinorEnd = vcToolsetVersion.find('.', 3); - const auto majorMinor = vcToolsetVersion.substr(0, majorMinorEnd); - return version == majorMinor; - } - } - - return false; -} - -std::string cmGlobalVisualStudio15Generator::GetAuxiliaryToolset() const -{ - const char* version = this->GetPlatformToolsetVersion(); - if (version) { - std::string instancePath; - GetVSInstance(instancePath); - std::stringstream path; - path << instancePath; - path << "/VC/Auxiliary/Build/"; - path << version; - path << "/Microsoft.VCToolsVersion." << version << ".props"; - - std::string toolsetPath = path.str(); - cmSystemTools::ConvertToUnixSlashes(toolsetPath); - return toolsetPath; - } - return {}; -} - -bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf) -{ - // If the Win 8.1 SDK is installed then we can select a SDK matching - // the target Windows version. - if (this->IsWin81SDKInstalled()) { - return cmGlobalVisualStudio14Generator::InitializeWindows(mf); - } - // Otherwise we must choose a Win 10 SDK even if we are not targeting - // Windows 10. - return this->SelectWindows10SDK(mf, false); -} - -bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( - std::string& toolset) const -{ - if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { - if (this->IsWindowsStoreToolsetInstalled() && - this->IsWindowsDesktopToolsetInstalled()) { - toolset = "v141"; // VS 15 uses v141 toolset - return true; - } else { - return false; - } - } - return this->cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( - toolset); -} - -bool cmGlobalVisualStudio15Generator::IsWindowsDesktopToolsetInstalled() const -{ - return vsSetupAPIHelper.IsVS2017Installed(); -} - -bool cmGlobalVisualStudio15Generator::IsWindowsStoreToolsetInstalled() const -{ - return vsSetupAPIHelper.IsWin10SDKInstalled(); -} - -bool cmGlobalVisualStudio15Generator::IsWin81SDKInstalled() const -{ - // Does the VS installer tool know about one? - if (vsSetupAPIHelper.IsWin81SDKInstalled()) { - return true; - } - - // Does the registry know about one (e.g. from VS 2015)? - std::string win81Root; - if (cmSystemTools::ReadRegistryValue( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" - "Windows Kits\\Installed Roots;KitsRoot81", - win81Root, cmSystemTools::KeyWOW64_32) || - cmSystemTools::ReadRegistryValue( - "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" - "Windows Kits\\Installed Roots;KitsRoot81", - win81Root, cmSystemTools::KeyWOW64_32)) { - return cmSystemTools::FileExists(win81Root + "/um/windows.h", true); - } - return false; -} - -std::string cmGlobalVisualStudio15Generator::GetWindows10SDKMaxVersion() const -{ - return std::string(); -} - -std::string cmGlobalVisualStudio15Generator::FindMSBuildCommand() -{ - std::string msbuild; - - // Ask Visual Studio Installer tool. - std::string vs; - if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { - msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe"; - if (cmSystemTools::FileExists(msbuild)) { - return msbuild; - } - } - - msbuild = "MSBuild.exe"; - return msbuild; -} - -std::string cmGlobalVisualStudio15Generator::FindDevEnvCommand() -{ - std::string devenv; - - // Ask Visual Studio Installer tool. - std::string vs; - if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { - devenv = vs + "/Common7/IDE/devenv.com"; - if (cmSystemTools::FileExists(devenv)) { - return devenv; - } - } - - devenv = "devenv.com"; - return devenv; -} diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 8694df2..16796cf 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -6,7 +6,7 @@ #include "cmGeneratorTarget.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" -#include "cmake.h" +#include "cmMessageType.h" cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator( cmake* cm, const std::string& platformName) diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 5855177..cae46e1 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorTarget.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmUuid.h" #include "cmake.h" diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 55284c9..4d165c2 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -7,6 +7,7 @@ #include "cmGeneratorTarget.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmVisualStudioWCEPlatformParser.h" #include "cmake.h" diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index e784595..6e61d26 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -5,8 +5,8 @@ #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmVisualStudioWCEPlatformParser.h" -#include "cmake.h" static const char vs9generatorName[] = "Visual Studio 9 2008"; @@ -59,9 +59,16 @@ public: "Optional [arch] can be \"Win64\" or \"IA64\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs9generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs9generatorName + std::string(" Win64")); names.push_back(vs9generatorName + std::string(" IA64")); cmVisualStudioWCEPlatformParser parser; @@ -71,10 +78,29 @@ public: for (std::string const& i : availablePlatforms) { names.push_back("Visual Studio 9 2008 " + i); } + return names; } bool SupportsToolset() const override { return false; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("Itanium"); + cmVisualStudioWCEPlatformParser parser; + parser.ParseVersion("9.0"); + const std::vector<std::string>& availablePlatforms = + parser.GetAvailablePlatforms(); + for (std::string const& i : availablePlatforms) { + platforms.emplace_back(i); + } + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory() diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index dc8de03..41d961c 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -19,6 +19,7 @@ #include "cmSourceFile.h" #include "cmState.h" #include "cmTarget.h" +#include "cmake.h" cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator( cmake* cm, std::string const& platformInGeneratorName) @@ -86,6 +87,8 @@ const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const return "14.0"; case cmGlobalVisualStudioGenerator::VS15: return "15.0"; + case cmGlobalVisualStudioGenerator::VS16: + return "16.0"; } return ""; } @@ -139,6 +142,15 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout) fout << "# Visual Studio 15\n"; } break; + case cmGlobalVisualStudioGenerator::VS16: + // Visual Studio 16 writes .sln format 12.00 + fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; + if (this->ExpressEdition) { + fout << "# Visual Studio Express 16 for Windows Desktop\n"; + } else { + fout << "# Visual Studio 16\n"; + } + break; } } @@ -512,7 +524,7 @@ std::string cmGlobalVisualStudioGenerator::GetStartupProjectName( return startup; } else { root->GetMakefile()->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "Directory property VS_STARTUP_PROJECT specifies target " "'" + startup + "' that does not exist. Ignoring."); diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index d44f5a5..039191c 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -38,7 +38,8 @@ public: VS12 = 120, /* VS13 = 130 was skipped */ VS14 = 140, - VS15 = 150 + VS15 = 150, + VS16 = 160 }; virtual ~cmGlobalVisualStudioGenerator(); diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx new file mode 100644 index 0000000..31f585c --- /dev/null +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -0,0 +1,486 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmGlobalVisualStudioVersionedGenerator.h" + +#include "cmAlgorithms.h" +#include "cmDocumentationEntry.h" +#include "cmLocalVisualStudio10Generator.h" +#include "cmMakefile.h" +#include "cmVSSetupHelper.h" +#include "cmake.h" + +#if defined(_M_ARM64) +# define HOST_PLATFORM_NAME "ARM64"; +#elif defined(_M_ARM) +# define HOST_PLATFORM_NAME "ARM"; +#elif defined(_M_IA64) +# define HOST_PLATFORM_NAME "Itanium"; +#else +# include "cmsys/SystemInformation.hxx" +#endif + +static std::string VSHostPlatformName() +{ +#ifdef HOST_PLATFORM_NAME + return HOST_PLATFORM_NAME; +#else + cmsys::SystemInformation info; + if (info.Is64Bits()) { + return "x64"; + } else { + return "Win32"; + } +#endif +} + +static unsigned int VSVersionToMajor( + cmGlobalVisualStudioGenerator::VSVersion v) +{ + switch (v) { + case cmGlobalVisualStudioGenerator::VS9: + return 9; + case cmGlobalVisualStudioGenerator::VS10: + return 10; + case cmGlobalVisualStudioGenerator::VS11: + return 11; + case cmGlobalVisualStudioGenerator::VS12: + return 12; + case cmGlobalVisualStudioGenerator::VS14: + return 14; + case cmGlobalVisualStudioGenerator::VS15: + return 15; + case cmGlobalVisualStudioGenerator::VS16: + return 16; + } + return 0; +} + +static const char* VSVersionToToolset( + cmGlobalVisualStudioGenerator::VSVersion v) +{ + switch (v) { + case cmGlobalVisualStudioGenerator::VS9: + return "v90"; + case cmGlobalVisualStudioGenerator::VS10: + return "v100"; + case cmGlobalVisualStudioGenerator::VS11: + return "v110"; + case cmGlobalVisualStudioGenerator::VS12: + return "v120"; + case cmGlobalVisualStudioGenerator::VS14: + return "v140"; + case cmGlobalVisualStudioGenerator::VS15: + return "v141"; + case cmGlobalVisualStudioGenerator::VS16: + // FIXME: VS 2019 Preview 1.1 uses v141 but preview 2 will use v142. + return "v141"; + } + return ""; +} + +static const char vs15generatorName[] = "Visual Studio 15 2017"; + +// Map generator name without year to name with year. +static const char* cmVS15GenName(const std::string& name, std::string& genName) +{ + if (strncmp(name.c_str(), vs15generatorName, + sizeof(vs15generatorName) - 6) != 0) { + return 0; + } + const char* p = name.c_str() + sizeof(vs15generatorName) - 6; + if (cmHasLiteralPrefix(p, " 2017")) { + p += 5; + } + genName = std::string(vs15generatorName) + p; + return p; +} + +class cmGlobalVisualStudioVersionedGenerator::Factory15 + : public cmGlobalGeneratorFactory +{ +public: + cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, + cmake* cm) const override + { + std::string genName; + const char* p = cmVS15GenName(name, genName); + if (!p) { + return 0; + } + if (!*p) { + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, ""); + } + if (*p++ != ' ') { + return 0; + } + if (strcmp(p, "Win64") == 0) { + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "x64"); + } + if (strcmp(p, "ARM") == 0) { + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "ARM"); + } + return 0; + } + + void GetDocumentation(cmDocumentationEntry& entry) const override + { + entry.Name = std::string(vs15generatorName) + " [arch]"; + entry.Brief = "Generates Visual Studio 2017 project files. " + "Optional [arch] can be \"Win64\" or \"ARM\"."; + } + + std::vector<std::string> GetGeneratorNames() const override + { + std::vector<std::string> names; + names.push_back(vs15generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; + names.push_back(vs15generatorName + std::string(" ARM")); + names.push_back(vs15generatorName + std::string(" Win64")); + return names; + } + + bool SupportsToolset() const override { return true; } + bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + platforms.emplace_back("ARM64"); + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } +}; + +cmGlobalGeneratorFactory* +cmGlobalVisualStudioVersionedGenerator::NewFactory15() +{ + return new Factory15; +} + +static const char vs16generatorName[] = "Visual Studio 16 2019"; + +// Map generator name without year to name with year. +static const char* cmVS16GenName(const std::string& name, std::string& genName) +{ + if (strncmp(name.c_str(), vs16generatorName, + sizeof(vs16generatorName) - 6) != 0) { + return 0; + } + const char* p = name.c_str() + sizeof(vs16generatorName) - 6; + if (cmHasLiteralPrefix(p, " 2019")) { + p += 5; + } + genName = std::string(vs16generatorName) + p; + return p; +} + +class cmGlobalVisualStudioVersionedGenerator::Factory16 + : public cmGlobalGeneratorFactory +{ +public: + virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, + cmake* cm) const + { + std::string genName; + const char* p = cmVS16GenName(name, genName); + if (!p) { + return 0; + } + if (!*p) { + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS16, cm, genName, ""); + } + return 0; + } + + virtual void GetDocumentation(cmDocumentationEntry& entry) const + { + entry.Name = std::string(vs16generatorName); + entry.Brief = "Generates Visual Studio 2019 project files. " + "Use -A option to specify architecture."; + } + + std::vector<std::string> GetGeneratorNames() const override + { + std::vector<std::string> names; + names.push_back(vs16generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + return std::vector<std::string>(); + } + + bool SupportsToolset() const override { return true; } + bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + platforms.emplace_back("ARM64"); + return platforms; + } + + std::string GetDefaultPlatformName() const override + { + return VSHostPlatformName(); + } +}; + +cmGlobalGeneratorFactory* +cmGlobalVisualStudioVersionedGenerator::NewFactory16() +{ + return new Factory16; +} + +cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( + VSVersion version, cmake* cm, const std::string& name, + std::string const& platformInGeneratorName) + : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName) + , vsSetupAPIHelper(VSVersionToMajor(version)) +{ + this->Version = version; + this->ExpressEdition = false; + this->DefaultPlatformToolset = VSVersionToToolset(this->Version); + this->DefaultCLFlagTableName = VSVersionToToolset(this->Version); + this->DefaultCSharpFlagTableName = VSVersionToToolset(this->Version); + this->DefaultLinkFlagTableName = VSVersionToToolset(this->Version); + if (this->Version >= cmGlobalVisualStudioGenerator::VS16) { + this->DefaultPlatformName = VSHostPlatformName(); + } +} + +bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( + const std::string& name) const +{ + std::string genName; + switch (this->Version) { + case cmGlobalVisualStudioGenerator::VS9: + case cmGlobalVisualStudioGenerator::VS10: + case cmGlobalVisualStudioGenerator::VS11: + case cmGlobalVisualStudioGenerator::VS12: + case cmGlobalVisualStudioGenerator::VS14: + break; + case cmGlobalVisualStudioGenerator::VS15: + if (cmVS15GenName(name, genName)) { + return genName == this->GetName(); + } + break; + case cmGlobalVisualStudioGenerator::VS16: + if (cmVS16GenName(name, genName)) { + return genName == this->GetName(); + } + break; + } + return false; +} + +bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( + std::string const& i, cmMakefile* mf) +{ + if (!i.empty()) { + if (!this->vsSetupAPIHelper.SetVSInstance(i)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find specified instance of Visual Studio:\n" + " " << i; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + } + + std::string vsInstance; + if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find any instance of Visual Studio.\n"; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + + // Save the selected instance persistently. + std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); + if (vsInstance != genInstance) { + this->CMakeInstance->AddCacheEntry( + "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(), + "Generator instance identifier.", cmStateEnums::INTERNAL); + } + + return true; +} + +bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance( + std::string& dir) const +{ + return vsSetupAPIHelper.GetVSInstanceInfo(dir); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsDefaultToolset( + const std::string& version) const +{ + if (version.empty()) { + return true; + } + + std::string vcToolsetVersion; + if (this->vsSetupAPIHelper.GetVCToolsetVersion(vcToolsetVersion)) { + + cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9]+"); + if (regex.find(version) && regex.find(vcToolsetVersion)) { + const auto majorMinorEnd = vcToolsetVersion.find('.', 3); + const auto majorMinor = vcToolsetVersion.substr(0, majorMinorEnd); + return version == majorMinor; + } + } + + return false; +} + +std::string cmGlobalVisualStudioVersionedGenerator::GetAuxiliaryToolset() const +{ + const char* version = this->GetPlatformToolsetVersion(); + if (version) { + std::string instancePath; + GetVSInstance(instancePath); + std::stringstream path; + path << instancePath; + path << "/VC/Auxiliary/Build/"; + path << version; + path << "/Microsoft.VCToolsVersion." << version << ".props"; + + std::string toolsetPath = path.str(); + cmSystemTools::ConvertToUnixSlashes(toolsetPath); + return toolsetPath; + } + return {}; +} + +bool cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf) +{ + // If the Win 8.1 SDK is installed then we can select a SDK matching + // the target Windows version. + if (this->IsWin81SDKInstalled()) { + return cmGlobalVisualStudio14Generator::InitializeWindows(mf); + } + // Otherwise we must choose a Win 10 SDK even if we are not targeting + // Windows 10. + return this->SelectWindows10SDK(mf, false); +} + +bool cmGlobalVisualStudioVersionedGenerator::SelectWindowsStoreToolset( + std::string& toolset) const +{ + if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { + if (this->IsWindowsStoreToolsetInstalled() && + this->IsWindowsDesktopToolsetInstalled()) { + toolset = VSVersionToToolset(this->Version); + return true; + } else { + return false; + } + } + return this->cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( + toolset); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsWindowsDesktopToolsetInstalled() + const +{ + return vsSetupAPIHelper.IsVSInstalled(); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsWindowsStoreToolsetInstalled() + const +{ + return vsSetupAPIHelper.IsWin10SDKInstalled(); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsWin81SDKInstalled() const +{ + // Does the VS installer tool know about one? + if (vsSetupAPIHelper.IsWin81SDKInstalled()) { + return true; + } + + // Does the registry know about one (e.g. from VS 2015)? + std::string win81Root; + if (cmSystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot81", + win81Root, cmSystemTools::KeyWOW64_32) || + cmSystemTools::ReadRegistryValue( + "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot81", + win81Root, cmSystemTools::KeyWOW64_32)) { + return cmSystemTools::FileExists(win81Root + "/um/windows.h", true); + } + return false; +} + +std::string cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersion() + const +{ + return std::string(); +} + +std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand() +{ + std::string msbuild; + + // Ask Visual Studio Installer tool. + std::string vs; + if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + msbuild = vs + "/MSBuild/Current/Bin/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } + msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } + } + + msbuild = "MSBuild.exe"; + return msbuild; +} + +std::string cmGlobalVisualStudioVersionedGenerator::FindDevEnvCommand() +{ + std::string devenv; + + // Ask Visual Studio Installer tool. + std::string vs; + if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + devenv = vs + "/Common7/IDE/devenv.com"; + if (cmSystemTools::FileExists(devenv)) { + return devenv; + } + } + + devenv = "devenv.com"; + return devenv; +} diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index da85d23..466816b 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -1,7 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio15Generator_h -#define cmGlobalVisualStudio15Generator_h +#ifndef cmGlobalVisualStudioVersionedGenerator_h +#define cmGlobalVisualStudioVersionedGenerator_h #include "cmConfigure.h" // IWYU pragma: keep @@ -14,11 +14,13 @@ class cmGlobalGeneratorFactory; class cmake; -/** \class cmGlobalVisualStudio15Generator */ -class cmGlobalVisualStudio15Generator : public cmGlobalVisualStudio14Generator +/** \class cmGlobalVisualStudioVersionedGenerator */ +class cmGlobalVisualStudioVersionedGenerator + : public cmGlobalVisualStudio14Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static cmGlobalGeneratorFactory* NewFactory15(); + static cmGlobalGeneratorFactory* NewFactory16(); bool MatchesGeneratorName(const std::string& name) const override; @@ -30,8 +32,9 @@ public: std::string GetAuxiliaryToolset() const override; protected: - cmGlobalVisualStudio15Generator(cmake* cm, const std::string& name, - std::string const& platformInGeneratorName); + cmGlobalVisualStudioVersionedGenerator( + VSVersion version, cmake* cm, const std::string& name, + std::string const& platformInGeneratorName); bool InitializeWindows(cmMakefile* mf) override; bool SelectWindowsStoreToolset(std::string& toolset) const override; @@ -53,8 +56,10 @@ protected: std::string FindDevEnvCommand() override; private: - class Factory; - friend class Factory; + class Factory15; + friend class Factory15; + class Factory16; + friend class Factory16; mutable cmVSSetupAPIHelper vsSetupAPIHelper; }; #endif diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 068cf5e..79d77e7 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -21,6 +21,7 @@ #include "cmLocalGenerator.h" #include "cmLocalXCodeGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" @@ -132,13 +133,27 @@ public: cmGlobalXCodeGenerator::GetDocumentation(entry); } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(cmGlobalXCodeGenerator::GetActualName()); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + return std::vector<std::string>(); } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return false; } + + std::vector<std::string> GetKnownPlatforms() const override + { + return std::vector<std::string>(); + } + + std::string GetDefaultPlatformName() const override { return std::string(); } }; cmGlobalXCodeGenerator::cmGlobalXCodeGenerator( @@ -203,7 +218,7 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( unsigned int version_number = 10 * v[0] + v[1]; if (version_number < 30) { - cm->IssueMessage(cmake::FATAL_ERROR, + cm->IssueMessage(MessageType::FATAL_ERROR, "Xcode " + version_string + " not supported."); return nullptr; } @@ -265,7 +280,7 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, " " << ts << "\n" "that was specified."; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } this->GeneratorToolset = ts; @@ -330,14 +345,14 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand( int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) { // now build the test - makeCommand.push_back( + makeCommand.emplace_back( this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand())); - makeCommand.push_back("-project"); + makeCommand.emplace_back("-project"); std::string projectArg = projectName; projectArg += ".xcode"; projectArg += "proj"; - makeCommand.push_back(projectArg); + makeCommand.emplace_back(projectArg); bool clean = false; std::string realTarget = targetName; @@ -346,23 +361,23 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand( realTarget = "ALL_BUILD"; } if (clean) { - makeCommand.push_back("clean"); + makeCommand.emplace_back("clean"); } else { - makeCommand.push_back("build"); + makeCommand.emplace_back("build"); } - makeCommand.push_back("-target"); + makeCommand.emplace_back("-target"); if (!realTarget.empty()) { - makeCommand.push_back(realTarget); + makeCommand.emplace_back(realTarget); } else { - makeCommand.push_back("ALL_BUILD"); + makeCommand.emplace_back("ALL_BUILD"); } - makeCommand.push_back("-configuration"); - makeCommand.push_back(!config.empty() ? config : "Debug"); + makeCommand.emplace_back("-configuration"); + makeCommand.emplace_back(!config.empty() ? config : "Debug"); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back("-jobs"); + makeCommand.emplace_back("-jobs"); if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back(std::to_string(jobs)); + makeCommand.emplace_back(std::to_string(jobs)); } } @@ -776,7 +791,7 @@ public: "specified for source:\n" " " << this->SourceFile->GetFullPath() << "\n"; /* clang-format on */ - this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str()); } return processed; @@ -1052,7 +1067,7 @@ void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen) this->CurrentConfigurationTypes.clear(); this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes); if (this->CurrentConfigurationTypes.empty()) { - this->CurrentConfigurationTypes.push_back(""); + this->CurrentConfigurationTypes.emplace_back(); } } diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index 754fa7d..4b60279 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -13,6 +13,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -172,7 +173,7 @@ cmGraphVizWriter::cmGraphVizWriter(const cmGlobalGenerator* globalGenerator) void cmGraphVizWriter::ReadSettings(const char* settingsFileName, const char* fallbackSettingsFileName) { - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::Unknown); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -198,12 +199,12 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName, std::cout << "Reading GraphViz options file: " << inFileName << std::endl; #define __set_if_set(var, cmakeDefinition) \ - { \ + do { \ const char* value = mf.GetDefinition(cmakeDefinition); \ if (value) { \ (var) = value; \ } \ - } + } while (false) __set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE"); __set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME"); @@ -211,12 +212,12 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName, __set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX"); #define __set_bool_if_set(var, cmakeDefinition) \ - { \ + do { \ const char* value = mf.GetDefinition(cmakeDefinition); \ if (value) { \ (var) = mf.IsOn(cmakeDefinition); \ } \ - } + } while (false) __set_bool_if_set(this->GenerateForExecutables, "GRAPHVIZ_EXECUTABLES"); __set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS"); diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 5d952da..d1f8f58 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -6,6 +6,7 @@ #include "cmExecutionStatus.h" #include "cmExpandedCommandArgument.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmSystemTools.h" #include "cmake.h" @@ -60,7 +61,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, if (this->ElseSeen) { cmListFileBacktrace bt = mf.GetBacktrace(func); mf.GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "A duplicate ELSE command was found inside an IF block.", bt); cmSystemTools::SetFatalErrorOccured(); return true; @@ -79,7 +80,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, if (this->ElseSeen) { cmListFileBacktrace bt = mf.GetBacktrace(func); mf.GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "An ELSEIF command was found after an ELSE command.", bt); cmSystemTools::SetFatalErrorOccured(); return true; @@ -98,7 +99,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, std::vector<cmExpandedCommandArgument> expandedArguments; mf.ExpandArguments(func.Arguments, expandedArguments); - cmake::MessageType messType; + MessageType messType; cmListFileContext conditionContext = cmListFileContext::FromCommandContext( @@ -115,7 +116,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, err += errorString; cmListFileBacktrace bt = mf.GetBacktrace(func); mf.GetCMakeInstance()->IssueMessage(messType, err, bt); - if (messType == cmake::FATAL_ERROR) { + if (messType == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); return true; } @@ -181,7 +182,7 @@ bool cmIfCommand::InvokeInitialPass( std::vector<cmExpandedCommandArgument> expandedArguments; this->Makefile->ExpandArguments(args, expandedArguments); - cmake::MessageType status; + MessageType status; cmConditionEvaluator conditionEvaluator( *(this->Makefile), this->Makefile->GetExecutionContext(), @@ -193,8 +194,8 @@ bool cmIfCommand::InvokeInitialPass( if (!errorString.empty()) { std::string err = "if " + cmIfCommandError(expandedArguments); err += errorString; - if (status == cmake::FATAL_ERROR) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, err); + if (status == MessageType::FATAL_ERROR) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err); cmSystemTools::SetFatalErrorOccured(); return true; } diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index f862578..a67d09e 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -6,9 +6,9 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -58,7 +58,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, } if (fname.empty()) { - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, "include() given empty file name (ignored)."); return true; } @@ -80,7 +80,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, if (gg->IsExportedTargetsFile(fname_abs)) { const char* modal = nullptr; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0024)) { case cmPolicies::WARN: @@ -92,7 +92,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: modal = "may"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { e << "The file\n " << fname_abs @@ -103,7 +103,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, "include() command. Use ALIAS targets instead to refer to targets " "by alternative names.\n"; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -120,8 +120,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, return true; } - bool readit = - this->Makefile->ReadDependentFile(listFile.c_str(), noPolicyScope); + bool readit = this->Makefile->ReadDependentFile(listFile, noPolicyScope); // add the location of the included file if a result variable was given if (!resultVarName.empty()) { diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index caec67d..549a263 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -4,6 +4,7 @@ #include <algorithm> #include <set> +#include <utility> #include "cmGeneratorExpression.h" #include "cmMakefile.h" diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx index c9217d3..b224d09 100644 --- a/Source/cmIncludeExternalMSProjectCommand.cxx +++ b/Source/cmIncludeExternalMSProjectCommand.cxx @@ -8,6 +8,7 @@ # include "cmStateTypes.h" # include "cmSystemTools.h" # include "cmTarget.h" +# include "cmake.h" #endif class cmExecutionStatus; diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 7c8458a..c6f4064 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -23,12 +23,12 @@ #include "cmInstallTargetGenerator.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" -#include "cmake.h" class cmExecutionStatus; @@ -864,7 +864,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) if (gg->IsExportedTargetsFile(file)) { const char* modal = nullptr; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (status) { case cmPolicies::WARN: @@ -876,7 +876,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: modal = "may"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { e << "The file\n " << file @@ -887,7 +887,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) "install() command. Use the install(EXPORT) mechanism " "instead. See the cmake-packages(7) manual for more.\n"; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -1495,7 +1495,7 @@ bool cmInstallCommand::CheckCMP0006(bool& failure) switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) { case cmPolicies::WARN: this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0006)); CM_FALLTHROUGH; case cmPolicies::OLD: @@ -1508,7 +1508,7 @@ bool cmInstallCommand::CheckCMP0006(bool& failure) case cmPolicies::REQUIRED_ALWAYS: failure = true; this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0006)); break; } diff --git a/Source/cmInstallExportAndroidMKGenerator.cxx b/Source/cmInstallExportAndroidMKGenerator.cxx index dd85b88..85b7021 100644 --- a/Source/cmInstallExportAndroidMKGenerator.cxx +++ b/Source/cmInstallExportAndroidMKGenerator.cxx @@ -13,7 +13,7 @@ #include "cmInstallTargetGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmake.h" +#include "cmMessageType.h" cmInstallExportAndroidMKGenerator::cmInstallExportAndroidMKGenerator( cmExportSet* exportSet, const char* destination, diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index d441e41..4cc081c 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -3,6 +3,7 @@ #include "cmInstallExportGenerator.h" #include <algorithm> +#include <map> #include <sstream> #include <utility> diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx index b93debb..12e87c7 100644 --- a/Source/cmInstallScriptGenerator.cxx +++ b/Source/cmInstallScriptGenerator.cxx @@ -7,9 +7,9 @@ #include "cmGeneratorExpression.h" #include "cmLocalGenerator.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmScriptGenerator.h" -#include "cmake.h" cmInstallScriptGenerator::cmInstallScriptGenerator(const char* script, bool code, @@ -39,7 +39,7 @@ void cmInstallScriptGenerator::Compute(cmLocalGenerator* lg) switch (this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0087)) { case cmPolicies::WARN: this->LocalGenerator->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0087)); CM_FALLTHROUGH; case cmPolicies::OLD: diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index ea3d522..86c6a58 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -15,6 +15,7 @@ #include "cmInstallType.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -91,7 +92,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( case cmStateEnums::GLOBAL_TARGET: case cmStateEnums::UNKNOWN_LIBRARY: this->Target->GetLocalGenerator()->IssueMessage( - cmake::INTERNAL_ERROR, + MessageType::INTERNAL_ERROR, "cmInstallTargetGenerator created with non-installable target."); return; } @@ -695,7 +696,7 @@ void cmInstallTargetGenerator::AddChrpathPatchRule( << "Therefore, runtime paths will not be changed when installing. " << "CMAKE_BUILD_WITH_INSTALL_RPATH may be used to work around" " this limitation."; - mf->IssueMessage(cmake::WARNING, msg.str()); + mf->IssueMessage(MessageType::WARNING, msg.str()); } else { // Note: These paths are kept unique to avoid // install_name_tool corruption. diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index 0da6f4f..135fd25 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -14,6 +14,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmProperty.h" +#include "cmPropertyMap.h" #include "cmSourceFile.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -48,7 +49,7 @@ std::vector<std::string> getConfigurations(const cmake* cm) makefiles[0]->GetConfigurations(configurations); if (configurations.empty()) { - configurations.push_back(""); + configurations.emplace_back(); } return configurations; } @@ -291,10 +292,10 @@ static Json::Value DumpSourceFilesList( lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file); for (const auto& include : includes) { - fileData.IncludePathList.push_back( - std::make_pair(include, - target->IsSystemIncludeDirectory( - include, config, fileData.Language))); + fileData.IncludePathList.emplace_back( + include, + target->IsSystemIncludeDirectory(include, config, + fileData.Language)); } } @@ -579,8 +580,8 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, std::vector<std::string> includePathList; lg->GetIncludeDirectories(includePathList, target, lang, config, true); for (std::string const& i : includePathList) { - ld.IncludePathList.push_back( - std::make_pair(i, target->IsSystemIncludeDirectory(i, config, lang))); + ld.IncludePathList.emplace_back( + i, target->IsSystemIncludeDirectory(i, config, lang)); } } diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index 10425fd..7850977 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -7,9 +7,9 @@ #include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -59,7 +59,7 @@ void cmLinkDirectoriesCommand::AddLinkDir( switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0015)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015); - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); break; case cmPolicies::OLD: // OLD behavior does not convert @@ -67,7 +67,7 @@ void cmLinkDirectoriesCommand::AddLinkDir( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0015); - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior converts diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 9b63d24..b826795 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -12,14 +12,15 @@ #include <stdexcept> #include <stdio.h> #include <stdlib.h> // required for atoi +#include <utility> #include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStringReplaceHelper.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -122,7 +123,7 @@ bool cmListCommand::GetList(std::vector<std::string>& list, warn += " List has value = ["; warn += listString; warn += "]."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, warn); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, warn); return true; } case cmPolicies::OLD: @@ -137,7 +138,7 @@ bool cmListCommand::GetList(std::vector<std::string>& list, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0007)); return false; } diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 4689f42..9aa1f32 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -3,11 +3,11 @@ #include "cmListFileCache.h" #include "cmListFileLexer.h" +#include "cmMessageType.h" #include "cmMessenger.h" #include "cmOutputConverter.h" #include "cmState.h" #include "cmSystemTools.h" -#include "cmake.h" #include <assert.h> #include <memory> @@ -66,7 +66,8 @@ cmListFileParser::~cmListFileParser() void cmListFileParser::IssueFileOpenError(const std::string& text) const { - this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, this->Backtrace); + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, + this->Backtrace); } void cmListFileParser::IssueError(const std::string& text) const @@ -76,7 +77,7 @@ void cmListFileParser::IssueError(const std::string& text) const lfc.Line = cmListFileLexer_GetCurrentLine(this->Lexer); cmListFileBacktrace lfbt = this->Backtrace; lfbt = lfbt.Push(lfc); - this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, lfbt); + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, lfbt); cmSystemTools::SetFatalErrorOccured(); } @@ -254,7 +255,7 @@ bool cmListFileParser::ParseFunction(const char* name, long line) lfbt = lfbt.Push(lfc); error << "Parse error. Function missing ending \")\". " << "End of file reached."; - this->Messenger->IssueMessage(cmake::FATAL_ERROR, error.str(), lfbt); + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, error.str(), lfbt); return false; } @@ -279,10 +280,10 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token, << "Argument not separated from preceding token by whitespace."; /* clang-format on */ if (isError) { - this->Messenger->IssueMessage(cmake::FATAL_ERROR, m.str(), lfbt); + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, m.str(), lfbt); return false; } - this->Messenger->IssueMessage(cmake::AUTHOR_WARNING, m.str(), lfbt); + this->Messenger->IssueMessage(MessageType::AUTHOR_WARNING, m.str(), lfbt); return true; } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 8fac039..97e684b 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -165,7 +165,7 @@ cmLocalGenerator::~cmLocalGenerator() cmDeleteAll(this->OwnedImportedGeneratorTargets); } -void cmLocalGenerator::IssueMessage(cmake::MessageType t, +void cmLocalGenerator::IssueMessage(MessageType t, std::string const& text) const { this->GetCMakeInstance()->IssueMessage(t, text, this->DirectoryBacktrace); @@ -190,14 +190,14 @@ void cmLocalGenerator::ComputeObjectMaxPath() w << "CMAKE_OBJECT_PATH_MAX is set to " << pmax << ", which is less than the minimum of 128. " << "The value will be ignored."; - this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } else { std::ostringstream w; w << "CMAKE_OBJECT_PATH_MAX is set to \"" << plen << "\", which fails to parse as a positive integer. " << "The value will be ignored."; - this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } this->ObjectMaxPathViolations.clear(); @@ -565,7 +565,7 @@ void cmLocalGenerator::GenerateInstallRules() "CMAKE_POLICY_WARNING_CMP0082")) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0082) << "\n"; - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } CM_FALLTHROUGH; case cmPolicies::OLD: { @@ -874,7 +874,7 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, "on " "and be depended on by the link implementation." << std::endl; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } } @@ -1387,7 +1387,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( "additional flags may be added to export symbols on all " "executables regardless of their ENABLE_EXPORTS property."; /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } CM_FALLTHROUGH; case cmPolicies::OLD: @@ -1397,7 +1397,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065)); CM_FALLTHROUGH; case cmPolicies::NEW: @@ -1670,7 +1670,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( << (ext ? "(with compiler extensions)" : "") << ", but CMake " "does not know the compile flags to use to enable it."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); } else { std::vector<std::string> optVec; cmSystemTools::ExpandListArgument(opt, optVec); @@ -1684,19 +1684,19 @@ void cmLocalGenerator::AddCompilerRequirementFlag( static std::map<std::string, std::vector<std::string>> langStdMap; if (langStdMap.empty()) { // Maintain sorted order, most recent first. - langStdMap["CXX"].push_back("20"); - langStdMap["CXX"].push_back("17"); - langStdMap["CXX"].push_back("14"); - langStdMap["CXX"].push_back("11"); - langStdMap["CXX"].push_back("98"); + langStdMap["CXX"].emplace_back("20"); + langStdMap["CXX"].emplace_back("17"); + langStdMap["CXX"].emplace_back("14"); + langStdMap["CXX"].emplace_back("11"); + langStdMap["CXX"].emplace_back("98"); - langStdMap["C"].push_back("11"); - langStdMap["C"].push_back("99"); - langStdMap["C"].push_back("90"); + langStdMap["C"].emplace_back("11"); + langStdMap["C"].emplace_back("99"); + langStdMap["C"].emplace_back("90"); - langStdMap["CUDA"].push_back("14"); - langStdMap["CUDA"].push_back("11"); - langStdMap["CUDA"].push_back("98"); + langStdMap["CUDA"].emplace_back("14"); + langStdMap["CUDA"].emplace_back("11"); + langStdMap["CUDA"].emplace_back("98"); } std::string standard(standardProp); @@ -1709,7 +1709,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( std::string e = lang + "_STANDARD is set to invalid value '" + standard + "'"; this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e, target->GetBacktrace()); + MessageType::FATAL_ERROR, e, target->GetBacktrace()); return; } @@ -1719,7 +1719,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( std::string e = "CMAKE_" + lang + "_STANDARD_DEFAULT is set to invalid value '" + std::string(defaultStd) + "'"; - this->IssueMessage(cmake::INTERNAL_ERROR, e); + this->IssueMessage(MessageType::INTERNAL_ERROR, e); return; } @@ -1857,7 +1857,7 @@ void cmLocalGenerator::AddVisibilityPresetFlags( "For compatibility CMake is not honoring them for this target."; /* clang-format on */ target->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, w.str(), target->GetBacktrace()); + MessageType::AUTHOR_WARNING, w.str(), target->GetBacktrace()); } } @@ -1916,7 +1916,7 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared, << flagsVar << " was removed.\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0018); - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -2130,7 +2130,7 @@ void cmLocalGenerator::AppendIncludeDirectories( << sourceFile.GetLocation().GetName() << "\":\n \"" << include << "\"\n"; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -2500,7 +2500,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName( << "cannot be safely placed under this directory. " << "The build may not work correctly."; /* clang-format on */ - this->IssueMessage(cmake::WARNING, m.str()); + this->IssueMessage(MessageType::WARNING, m.str()); } } #else diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 2fa0070..dc54314 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -14,10 +14,10 @@ #include <vector> #include "cmListFileCache.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmStateSnapshot.h" -#include "cmake.h" class cmComputeLinkInformation; class cmCustomCommandGenerator; @@ -28,6 +28,7 @@ class cmMakefile; class cmRulePlaceholderExpander; class cmSourceFile; class cmState; +class cmake; /** \class cmLocalGenerator * \brief Create required build files for a directory. @@ -359,7 +360,7 @@ public: bool IsMinGWMake() const; bool IsNMake() const; - void IssueMessage(cmake::MessageType t, std::string const& text) const; + void IssueMessage(MessageType t, std::string const& text) const; void CreateEvaluationFileOutputs(const std::string& config); void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles); diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index ab6774e..125e8b5 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -7,6 +7,7 @@ #include "cmGhsMultiTargetGenerator.h" #include "cmGlobalGhsMultiGenerator.h" #include "cmMakefile.h" +#include "cmSourceFile.h" cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, cmMakefile* mf) @@ -18,16 +19,82 @@ cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator() { } +std::string cmLocalGhsMultiGenerator::GetTargetDirectory( + cmGeneratorTarget const* target) const +{ + std::string dir; + dir += target->GetName(); + dir += ".dir"; + return dir; +} + +void cmLocalGhsMultiGenerator::GenerateTargetsDepthFirst( + cmGeneratorTarget* target, std::vector<cmGeneratorTarget*>& remaining) +{ + if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + return; + } + // Find this target in the list of remaining targets. + auto it = std::find(remaining.begin(), remaining.end(), target); + if (it == remaining.end()) { + // This target was already handled. + return; + } + // Remove this target from the list of remaining targets because + // we are handling it now. + *it = nullptr; + + cmGhsMultiTargetGenerator tg(target); + tg.Generate(); +} + void cmLocalGhsMultiGenerator::Generate() { - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); + std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets(); + for (auto& t : remaining) { + if (t) { + GenerateTargetsDepthFirst(t, remaining); + } + } +} + +void cmLocalGhsMultiGenerator::ComputeObjectFilenames( + std::map<cmSourceFile const*, std::string>& mapping, + cmGeneratorTarget const* gt) +{ + std::string dir_max; + dir_max += this->GetCurrentBinaryDirectory(); + dir_max += "/"; + dir_max += this->GetTargetDirectory(gt); + dir_max += "/"; + + // Count the number of object files with each name. Note that + // filesystem may not be case sensitive. + std::map<std::string, int> counts; + + for (auto const& si : mapping) { + cmSourceFile const* sf = si.first; + std::string objectNameLower = cmSystemTools::LowerCase( + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())); + objectNameLower += this->GlobalGenerator->GetLanguageOutputExtension(*sf); + counts[objectNameLower] += 1; + } + + // For all source files producing duplicate names we need unique + // object name computation. + for (auto& si : mapping) { + cmSourceFile const* sf = si.first; + std::string objectName = + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()); + objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf); - for (std::vector<cmGeneratorTarget*>::const_iterator l = tgts.begin(); - l != tgts.end(); ++l) { - if ((*l)->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - continue; + if (counts[cmSystemTools::LowerCase(objectName)] > 1) { + const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf); + bool keptSourceExtension; + objectName = this->GetObjectFileNameWithoutTarget(*sf, dir_max, + &keptSourceExtension); + cmsys::SystemTools::ReplaceString(objectName, "/", "_"); } - cmGhsMultiTargetGenerator tg(*l); - tg.Generate(); + si.second = objectName; } } diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h index aa842d7..d5bec42 100644 --- a/Source/cmLocalGhsMultiGenerator.h +++ b/Source/cmLocalGhsMultiGenerator.h @@ -24,6 +24,17 @@ public: * Generate the makefile for this directory. */ virtual void Generate(); + + std::string GetTargetDirectory( + cmGeneratorTarget const* target) const override; + + void ComputeObjectFilenames( + std::map<cmSourceFile const*, std::string>& mapping, + cmGeneratorTarget const* gt = nullptr) override; + +private: + void GenerateTargetsDepthFirst(cmGeneratorTarget* target, + std::vector<cmGeneratorTarget*>& remaining); }; #endif diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 707a1b5..5b9d108 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -318,7 +318,7 @@ void cmLocalUnixMakefileGenerator3::WriteObjectConvenienceRule( // Add a rule to drive the rule below. std::vector<std::string> depends; - depends.push_back(output); + depends.emplace_back(output); std::vector<std::string> no_commands; this->WriteMakeRule(ruleFileStream, nullptr, outNoExt, depends, no_commands, true, true); @@ -685,7 +685,7 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsTop( } // Add a fake suffix to keep HP happy. Must be max 32 chars for SGI make. std::vector<std::string> depends; - depends.push_back(".hpux_make_needs_suffix_list"); + depends.emplace_back(".hpux_make_needs_suffix_list"); this->WriteMakeRule(makefileStream, nullptr, ".SUFFIXES", depends, no_commands, false); if (this->IsWatcomWMake()) { @@ -852,7 +852,7 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepend( const char* nodep = this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY"); if (!nodep || cmSystemTools::IsOff(nodep)) { - depends.push_back(ruleFileName); + depends.emplace_back(ruleFileName); } } @@ -1286,7 +1286,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, std::ostringstream msg; msg << "Dependee \"" << tgtInfo << "\" is newer than depender \"" << internalDependFile << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } needRescanDependInfo = true; } @@ -1307,7 +1307,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, std::ostringstream msg; msg << "Dependee \"" << dirInfoFile << "\" is newer than depender \"" << internalDependFile << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } needRescanDirInfo = true; } @@ -1333,8 +1333,8 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, // dependency vector. This means that in the normal case, when only // few or one file have been edited, then also only this one file is // actually scanned again, instead of all files for this target. - needRescanDependencies = !checker.Check( - dependFile.c_str(), internalDependFile.c_str(), validDependencies); + needRescanDependencies = + !checker.Check(dependFile, internalDependFile, validDependencies); } if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) { @@ -1347,7 +1347,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, cmsysTerminal_Color_ForegroundBold, message.c_str(), true, color); - return this->ScanDependencies(dir.c_str(), validDependencies); + return this->ScanDependencies(dir, validDependencies); } // The dependencies are already up-to-date. @@ -1355,7 +1355,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, } bool cmLocalUnixMakefileGenerator3::ScanDependencies( - const char* targetDir, + const std::string& targetDir, std::map<std::string, cmDepends::DependencyVector>& validDeps) { // Read the directory information file. @@ -1364,8 +1364,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( std::string dirInfoFile = this->GetCurrentBinaryDirectory(); dirInfoFile += cmake::GetCMakeFilesDirectory(); dirInfoFile += "/CMakeDirectoryInformation.cmake"; - if (mf->ReadListFile(dirInfoFile.c_str()) && - !cmSystemTools::GetErrorOccuredFlag()) { + if (mf->ReadListFile(dirInfoFile) && !cmSystemTools::GetErrorOccuredFlag()) { haveDirectoryInfo = true; } @@ -1393,12 +1392,9 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( cmSystemTools::Error("Directory Information file not found"); } - // create the file stream for the depends file - std::string dir = targetDir; - // Open the make depends file. This should be copy-if-different // because the make tool may try to reload it needlessly otherwise. - std::string ruleFileNameFull = dir; + std::string ruleFileNameFull = targetDir; ruleFileNameFull += "/depend.make"; cmGeneratedFileStream ruleFileStream( ruleFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); @@ -1410,7 +1406,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( // Open the cmake dependency tracking file. This should not be // copy-if-different because dependencies are re-scanned when it is // older than the DependInfo.cmake. - std::string internalRuleFileNameFull = dir; + std::string internalRuleFileNameFull = targetDir; internalRuleFileNameFull += "/depend.internal"; cmGeneratedFileStream internalRuleFileStream( internalRuleFileNameFull, false, @@ -1451,7 +1447,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( scanner->SetFileComparison( this->GlobalGenerator->GetCMakeInstance()->GetFileComparison()); scanner->SetLanguage(lang); - scanner->SetTargetDirectory(dir.c_str()); + scanner->SetTargetDirectory(targetDir); scanner->Write(ruleFileStream, internalRuleFileStream); // free the scanner for this language @@ -1489,7 +1485,7 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose) msg << "Deleting primary custom command output \"" << dependee << "\" because another output \"" << depender << "\" does not exist." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } cmSystemTools::RemoveFile(dependee); } @@ -1507,7 +1503,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( // Just depend on the all target to drive the build. std::vector<std::string> depends; std::vector<std::string> no_commands; - depends.push_back("all"); + depends.emplace_back("all"); // Write the rule. this->WriteMakeRule(ruleFileStream, @@ -1571,7 +1567,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( (targetName == "install/strip")) { // Provide a fast install target that does not depend on all // but has the same command. - depends.push_back("preinstall/fast"); + depends.emplace_back("preinstall/fast"); } else { // Just forward to the real target so at least it will work. depends.push_back(targetName); @@ -1593,7 +1589,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( bool regenerate = !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } std::string progressDir = this->GetBinaryDirectory(); @@ -1643,7 +1639,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( depends, commands, true); commands.clear(); depends.clear(); - depends.push_back("clean"); + depends.emplace_back("clean"); this->WriteMakeRule(ruleFileStream, "The main clean target", "clean/fast", depends, commands, true); @@ -1656,10 +1652,10 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( this->Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); if (!noall || cmSystemTools::IsOff(noall)) { // Drive the build before installing. - depends.push_back("all"); + depends.emplace_back("all"); } else if (regenerate) { // At least make sure the build system is up to date. - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } commands.push_back( this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget)); @@ -1720,7 +1716,7 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf, // Clear the implicit dependency makefile. std::string dependFile = dir + "/depend.make"; - clearer.Clear(dependFile.c_str()); + clearer.Clear(dependFile); // Remove the internal dependency check file to force // regeneration. diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index ee6b37b..c0d0e13 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -245,7 +245,7 @@ protected: // Helper methods for dependency updates. bool ScanDependencies( - const char* targetDir, + const std::string& targetDir, std::map<std::string, cmDepends::DependencyVector>& validDeps); void CheckMultipleOutputs(bool verbose); diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index 0c2c64e..d45c335 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -7,6 +7,7 @@ #include "cmMakefile.h" #include "cmVisualStudio10TargetGenerator.h" #include "cmXMLParser.h" +#include "cmake.h" #include "cm_expat.h" diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index fee9dd6..677d033 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmXMLParser.h" diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx index 7294c1c..7368812 100644 --- a/Source/cmMachO.cxx +++ b/Source/cmMachO.cxx @@ -52,10 +52,7 @@ bool peek(cmsys::ifstream& fin, T& v) template <typename T> bool read(cmsys::ifstream& fin, T& v) { - if (!fin.read(reinterpret_cast<char*>(&v), sizeof(T))) { - return false; - } - return true; + return !!fin.read(reinterpret_cast<char*>(&v), sizeof(T)); } // read from the file and fill multiple data structures where @@ -67,10 +64,7 @@ bool read(cmsys::ifstream& fin, std::vector<T>& v) if (v.empty()) { return true; } - if (!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size())) { - return false; - } - return true; + return !!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size()); } } diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 23d93a3..411c0c3 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -94,7 +94,7 @@ bool cmMacroHelperCommand::InvokeInitialPass( char argvName[60]; for (unsigned int j = 0; j < expandedArgs.size(); ++j) { sprintf(argvName, "${ARGV%u}", j); - argVs.push_back(argvName); + argVs.emplace_back(argvName); } // Invoke all the functions that were collected in the block. cmListFileFunction newLFF; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 68a5101..9589b7f 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -30,6 +30,7 @@ #include "cmInstallGenerator.h" // IWYU pragma: keep #include "cmInstallSubdirectoryGenerator.h" #include "cmListFileCache.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" #include "cmState.h" @@ -129,11 +130,11 @@ cmDirectoryId cmMakefile::GetDirectoryId() const return std::string(buf); } -void cmMakefile::IssueMessage(cmake::MessageType t, - std::string const& text) const +void cmMakefile::IssueMessage(MessageType t, std::string const& text) const { if (!this->ExecutionStatusStack.empty()) { - if ((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) { + if ((t == MessageType::FATAL_ERROR) || + (t == MessageType::INTERNAL_ERROR)) { this->ExecutionStatusStack.back()->SetNestedError(); } } @@ -143,7 +144,7 @@ void cmMakefile::IssueMessage(cmake::MessageType t, bool cmMakefile::CheckCMP0037(std::string const& targetName, cmStateEnums::TargetType targetType) const { - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; std::ostringstream e; bool issueMessage = false; switch (this->GetPolicyStatus(cmPolicies::CMP0037)) { @@ -159,7 +160,7 @@ bool cmMakefile::CheckCMP0037(std::string const& targetName, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } if (issueMessage) { @@ -169,7 +170,7 @@ bool cmMakefile::CheckCMP0037(std::string const& targetName, "in undefined behavior."; this->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -198,7 +199,7 @@ void cmMakefile::MaybeWarnCMP0074(std::string const& pkg) << " " << env << "\n"; } w << "For compatibility, CMake is ignoring the variable."; - this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } @@ -381,7 +382,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, // The command invocation requested that we report an error. std::string const error = std::string(lff.Name.Original) + " " + pcmd->GetError(); - this->IssueMessage(cmake::FATAL_ERROR, error); + this->IssueMessage(MessageType::FATAL_ERROR, error); } result = false; if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) { @@ -397,7 +398,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, std::string error = "Unknown CMake command \""; error += lff.Name.Original; error += "\"."; - this->IssueMessage(cmake::FATAL_ERROR, error); + this->IssueMessage(MessageType::FATAL_ERROR, error); result = false; cmSystemTools::SetFatalErrorOccured(); } @@ -509,7 +510,7 @@ void cmMakefile::IncludeScope::EnforceCMP0011() << "affects policy settings. " << "CMake is implying the NO_POLICY_SCOPE option for compatibility, " << "so the effects are applied to the including context."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } break; case cmPolicies::REQUIRED_IF_USED: @@ -521,7 +522,7 @@ void cmMakefile::IncludeScope::EnforceCMP0011() << this->Makefile->GetExecutionFilePath() << "\n" << "affects policy settings, so it requires this policy to be set."; /* clang-format on */ - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } break; case cmPolicies::OLD: case cmPolicies::NEW: @@ -532,7 +533,8 @@ void cmMakefile::IncludeScope::EnforceCMP0011() } } -bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope) +bool cmMakefile::ReadDependentFile(const std::string& filename, + bool noPolicyScope) { this->AddDefinition("CMAKE_PARENT_LIST_FILE", this->GetDefinition("CMAKE_CURRENT_LIST_FILE")); @@ -585,7 +587,7 @@ private: bool ReportError; }; -bool cmMakefile::ReadListFile(const char* filename) +bool cmMakefile::ReadListFile(const std::string& filename) { std::string filenametoread = cmSystemTools::CollapseFullPath( filename, this->GetCurrentSourceDirectory()); @@ -665,7 +667,7 @@ void cmMakefile::EnforceDirectoryLevelRules() const case cmPolicies::WARN: // Warn because the user did not provide a minimum required // version. - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, msg.str(), this->Backtrace); case cmPolicies::OLD: // OLD behavior is to use policy version 2.4 set in @@ -675,8 +677,8 @@ void cmMakefile::EnforceDirectoryLevelRules() const case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: // NEW behavior is to issue an error. - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + msg.str(), this->Backtrace); cmSystemTools::SetFatalErrorOccured(); return; } @@ -764,7 +766,7 @@ void cmMakefile::ConfigureFinalPass() if (oldValue && cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) { this->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "You have set CMAKE_BACKWARDS_COMPATIBILITY to a CMake version less " "than 2.4. This version of CMake only supports backwards compatibility " "with CMake 2.4 or later. For compatibility with older versions please " @@ -785,7 +787,7 @@ void cmMakefile::AddCustomCommandToTarget( cmTargets::iterator ti = this->Targets.find(target); if (ti == this->Targets.end()) { - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; bool issueMessage = false; std::ostringstream e; switch (this->GetPolicyStatus(cmPolicies::CMP0040)) { @@ -798,7 +800,7 @@ void cmMakefile::AddCustomCommandToTarget( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (issueMessage) { @@ -826,7 +828,7 @@ void cmMakefile::AddCustomCommandToTarget( e << "Target \"" << target << "\" is an OBJECT library " "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (t.GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -834,7 +836,7 @@ void cmMakefile::AddCustomCommandToTarget( e << "Target \"" << target << "\" is an INTERFACE library " "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -886,7 +888,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput( if (!cl.empty() && !cl[0].empty() && cl[0][0] == '"') { std::ostringstream e; e << "COMMAND may not contain literal quotes:\n " << cl[0] << "\n"; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return nullptr; } } @@ -1278,7 +1280,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) // This definition has a non-trivial value. switch (this->GetPolicyStatus(cmPolicies::CMP0005)) { case cmPolicies::WARN: - this->IssueMessage(cmake::AUTHOR_WARNING, + this->IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0005)); CM_FALLTHROUGH; case cmPolicies::OLD: @@ -1288,7 +1290,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0005)); return false; case cmPolicies::NEW: @@ -1617,7 +1619,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) << "\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0014); /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); case cmPolicies::OLD: // OLD behavior does not warn. break; @@ -1627,7 +1629,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior prints the error. - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); } return; } @@ -1849,7 +1851,7 @@ void cmMakefile::MaybeWarnUninitialized(std::string const& variable, (sourceFilename && this->IsProjectFile(sourceFilename))) { std::ostringstream msg; msg << "uninitialized variable \'" << variable << "\'"; - this->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, msg.str()); } } } @@ -1868,7 +1870,7 @@ void cmMakefile::LogUnused(const char* reason, const std::string& name) const if (this->CheckSystemVars || this->IsProjectFile(path.c_str())) { std::ostringstream msg; msg << "unused variable (" << reason << ") \'" << name << "\'"; - this->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, msg.str()); } } } @@ -2098,7 +2100,7 @@ void cmMakefile::AddSourceGroup(const std::vector<std::string>& name, if (i == -1) { // group does not exist nor belong to any existing group // add its first component - this->SourceGroups.push_back(cmSourceGroup(name[0], regex)); + this->SourceGroups.emplace_back(name[0], regex); sg = this->GetSourceGroup(currentName); i = 0; // last component found } @@ -2274,8 +2276,8 @@ void cmMakefile::ExpandVariablesCMP0019() << "The following variable evaluations were encountered:\n" << w.str(); /* clang-format on */ - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, m.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + m.str(), this->Backtrace); } } @@ -2494,7 +2496,7 @@ const std::string& cmMakefile::ExpandVariablesInString( const char* filename, long line, bool removeEmpty, bool replaceAt) const { bool compareResults = false; - cmake::MessageType mtype = cmake::LOG; + MessageType mtype = MessageType::LOG; std::string errorstr; std::string original; @@ -2502,7 +2504,7 @@ const std::string& cmMakefile::ExpandVariablesInString( if (atOnly && (!noEscapes || !removeEmpty)) { // This case should never be called. At-only is for // configure-file/string which always does no escapes. - this->IssueMessage(cmake::INTERNAL_ERROR, + this->IssueMessage(MessageType::INTERNAL_ERROR, "ExpandVariablesInString @ONLY called " "on something with escapes."); return source; @@ -2511,7 +2513,7 @@ const std::string& cmMakefile::ExpandVariablesInString( // Variables used in the WARN case. std::string newResult; std::string newErrorstr; - cmake::MessageType newError = cmake::LOG; + MessageType newError = MessageType::LOG; switch (this->GetPolicyStatus(cmPolicies::CMP0053)) { case cmPolicies::WARN: { @@ -2544,8 +2546,8 @@ const std::string& cmMakefile::ExpandVariablesInString( } // If it's an error in either case, just report the error... - if (mtype != cmake::LOG) { - if (mtype == cmake::FATAL_ERROR) { + if (mtype != MessageType::LOG) { + if (mtype == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); } this->IssueMessage(mtype, errorstr); @@ -2584,20 +2586,20 @@ const std::string& cmMakefile::ExpandVariablesInString( msg += "Using the old result for compatibility since the policy is not set."; - this->IssueMessage(cmake::AUTHOR_WARNING, msg); + this->IssueMessage(MessageType::AUTHOR_WARNING, msg); } return source; } -cmake::MessageType cmMakefile::ExpandVariablesInStringOld( +MessageType cmMakefile::ExpandVariablesInStringOld( std::string& errorstr, std::string& source, bool escapeQuotes, bool noEscapes, bool atOnly, const char* filename, long line, bool removeEmpty, bool replaceAt) const { // Fast path strings without any special characters. if (source.find_first_of("$@\\") == std::string::npos) { - return cmake::LOG; + return MessageType::LOG; } // Special-case the @ONLY mode. @@ -2636,7 +2638,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( // Append the rest of the unchanged part of the string. source.append(in); - return cmake::LOG; + return MessageType::LOG; } // This method replaces ${VAR} and @VAR@ where VAR is looked up @@ -2653,7 +2655,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( parser.SetRemoveEmpty(removeEmpty); int res = parser.ParseString(source.c_str(), 0); const char* emsg = parser.GetError(); - cmake::MessageType mtype = cmake::LOG; + MessageType mtype = MessageType::LOG; if (res && !emsg[0]) { source = parser.GetResult(); } else { @@ -2676,7 +2678,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( // parser reported an error message without failing because the // helper implementation is unhappy, which has always reported an // error. - mtype = cmake::FATAL_ERROR; + mtype = MessageType::FATAL_ERROR; if (!res) { // This is a real argument parsing error. Use policy CMP0010 to // decide whether it is an error. @@ -2686,7 +2688,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to just warn and continue. - mtype = cmake::AUTHOR_WARNING; + mtype = MessageType::AUTHOR_WARNING; break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: @@ -2723,7 +2725,7 @@ bool cmMakefile::IsProjectFile(const char* filename) const cmake::GetCMakeFilesDirectory())); } -cmake::MessageType cmMakefile::ExpandVariablesInStringNew( +MessageType cmMakefile::ExpandVariablesInStringNew( std::string& errorstr, std::string& source, bool escapeQuotes, bool noEscapes, bool atOnly, const char* filename, long line, bool replaceAt) const @@ -2740,7 +2742,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( std::vector<t_lookup> openstack; bool error = false; bool done = false; - cmake::MessageType mtype = cmake::LOG; + MessageType mtype = MessageType::LOG; cmState* state = this->GetCMakeInstance()->GetState(); @@ -2819,7 +2821,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( std::string(next, this->cmNamedCurly.end()) + "{} is not supported. Only ${}, $ENV{}, " "and $CACHE{} are allowed."; - mtype = cmake::FATAL_ERROR; + mtype = MessageType::FATAL_ERROR; error = true; } } @@ -2927,7 +2929,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( errorstr += "\') in a variable name: " "'" + result.substr(openstack.back().loc) + "'"; - mtype = cmake::FATAL_ERROR; + mtype = MessageType::FATAL_ERROR; error = true; } break; @@ -2958,7 +2960,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( emsg << "when parsing string\n" << " " << source << "\n"; emsg << errorstr; - mtype = cmake::FATAL_ERROR; + mtype = MessageType::FATAL_ERROR; errorstr = emsg.str(); } else { // Append the rest of the unchanged part of the string. @@ -3052,7 +3054,7 @@ void cmMakefile::PopFunctionBlockerBarrier(bool reportError) << " " << lfc << "\n" << "is not closed."; /* clang-format on */ - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); reportError = false; } } @@ -3205,7 +3207,7 @@ std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker( << " " << closingContext << "\n" << "with mis-matching arguments."; /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } cmFunctionBlocker* b = *pos; this->FunctionBlockers.erase(pos); @@ -3362,7 +3364,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, // use the cmake object instead of calling cmake cmWorkingDirectory workdir(bindir); if (workdir.Failed()) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "Failed to set working directory to " + bindir + " : " + std::strerror(workdir.GetLastResult())); cmSystemTools::SetFatalErrorOccured(); @@ -3373,12 +3375,12 @@ int cmMakefile::TryCompile(const std::string& srcdir, // make sure the same generator is used // use this program as the cmake to be run, it should not // be run that way but the cmake object requires a vailid path - cmake cm(cmake::RoleProject); + cmake cm(cmake::RoleProject, cmState::Project); cm.SetIsInTryCompile(true); cmGlobalGenerator* gg = cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName()); if (!gg) { - this->IssueMessage(cmake::INTERNAL_ERROR, + this->IssueMessage(MessageType::INTERNAL_ERROR, "Global generator '" + this->GetGlobalGenerator()->GetName() + "' could not be created."); @@ -3444,7 +3446,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, cmStateEnums::INTERNAL); } if (cm.Configure() != 0) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "Failed to configure test project build system."); cmSystemTools::SetFatalErrorOccured(); this->IsSourceFileTryCompile = false; @@ -3452,7 +3454,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, } if (cm.Generate() != 0) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "Failed to generate test project build system."); cmSystemTools::SetFatalErrorOccured(); this->IsSourceFileTryCompile = false; @@ -3584,7 +3586,7 @@ std::string cmMakefile::GetModulesFile(const char* filename, << cmPolicies::GetPolicyWarning(cmPolicies::CMP0017); /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -3740,7 +3742,7 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, std::ostringstream e; e << "File starts with a Byte-Order-Mark that is not UTF-8:\n " << sinfile; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return 0; } // rewind to copy BOM to output file @@ -3937,7 +3939,7 @@ void cmMakefile::RaiseScope(const std::string& var, const char* varDef) if (!this->StateSnapshot.RaiseScope(var, varDef)) { std::ostringstream m; m << "Cannot set \"" << var << "\": current scope has no parent."; - this->IssueMessage(cmake::AUTHOR_WARNING, m.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, m.str()); return; } @@ -4022,7 +4024,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, // target names must be globally unique switch (this->GetPolicyStatus(cmPolicies::CMP0002)) { case cmPolicies::WARN: - this->IssueMessage(cmake::AUTHOR_WARNING, + this->IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0002)); CM_FALLTHROUGH; case cmPolicies::OLD: @@ -4030,7 +4032,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0002)); return true; case cmPolicies::NEW: @@ -4109,7 +4111,7 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath, << "to work accidentally and is being allowed for " << "compatibility."; /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior does not warn. @@ -4128,7 +4130,7 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath, << " " << srcPath << "\n" << "Specify a unique binary directory name."; /* clang-format on */ - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); break; } @@ -4213,7 +4215,7 @@ bool cmMakefile::SetPolicy(const char* id, cmPolicies::PolicyStatus status) if (!cmPolicies::GetPolicyID(id, /* out */ pid)) { std::ostringstream e; e << "Policy \"" << id << "\" is not known to this version of CMake."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return this->SetPolicy(pid, status); @@ -4226,14 +4228,18 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, if (status != cmPolicies::NEW && cmPolicies::GetPolicyStatus(id) == cmPolicies::REQUIRED_ALWAYS) { std::string msg = cmPolicies::GetRequiredAlwaysPolicyError(id); - this->IssueMessage(cmake::FATAL_ERROR, msg); + this->IssueMessage(MessageType::FATAL_ERROR, msg); return false; } // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0063) { - this->IssueMessage(cmake::DEPRECATION_WARNING, + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0065 && + !(this->GetCMakeInstance()->GetIsInTryCompile() && + ( + // Policies set by cmCoreTryCompile::TryCompileCode. + id == cmPolicies::CMP0065))) { + this->IssueMessage(MessageType::DEPRECATION_WARNING, cmPolicies::GetPolicyDeprecatedWarning(id)); } @@ -4260,7 +4266,7 @@ void cmMakefile::PushPolicy(bool weak, cmPolicies::PolicyMap const& pm) void cmMakefile::PopPolicy() { if (!this->StateSnapshot.PopPolicy()) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "cmake_policy POP without matching PUSH"); } } @@ -4272,7 +4278,7 @@ void cmMakefile::PopSnapshot(bool reportError) // reject any still-open nested policy scopes with an error. while (!this->StateSnapshot.CanPopPolicyScope()) { if (reportError) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "cmake_policy PUSH without matching POP"); reportError = false; } @@ -4365,7 +4371,7 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Backtrace); } return false; @@ -4412,7 +4418,7 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Backtrace); } return false; @@ -4432,7 +4438,7 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Backtrace); } return nullptr; @@ -4455,7 +4461,7 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Backtrace); } return nullptr; @@ -4480,7 +4486,7 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, std::ostringstream e; e << "CMAKE_C_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " "not fully configured for this compiler."; - this->IssueMessage(cmake::INTERNAL_ERROR, e.str()); + this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); // Return true so the caller does not try to lookup the default standard. return true; } @@ -4490,7 +4496,7 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, e << "The CMAKE_C_STANDARD_DEFAULT variable contains an " "invalid value: \"" << defaultCStandard << "\"."; - this->IssueMessage(cmake::INTERNAL_ERROR, e.str()); + this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); return false; } @@ -4510,7 +4516,7 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, std::ostringstream e; e << "The C_STANDARD property on target \"" << target->GetName() << "\" contained an invalid value: \"" << existingCStandard << "\"."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -4564,7 +4570,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, std::ostringstream e; e << "CMAKE_CXX_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " "not fully configured for this compiler."; - this->IssueMessage(cmake::INTERNAL_ERROR, e.str()); + this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); // Return true so the caller does not try to lookup the default standard. return true; } @@ -4574,7 +4580,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, e << "The CMAKE_CXX_STANDARD_DEFAULT variable contains an " "invalid value: \"" << defaultCxxStandard << "\"."; - this->IssueMessage(cmake::INTERNAL_ERROR, e.str()); + this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); return false; } @@ -4598,7 +4604,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, std::ostringstream e; e << "The CXX_STANDARD property on target \"" << target->GetName() << "\" contained an invalid value: \"" << existingCxxStandard << "\"."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -4678,8 +4684,8 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), this->Backtrace); } return false; } @@ -4699,8 +4705,8 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), this->Backtrace); } return false; } @@ -4777,8 +4783,8 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), this->Backtrace); } return false; } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 1607735..abe2cd1 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -18,13 +18,13 @@ #include "cmAlgorithms.h" #include "cmListFileCache.h" +#include "cmMessageType.h" #include "cmNewLineStyle.h" #include "cmPolicies.h" #include "cmSourceFileLocationKind.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmTarget.h" -#include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cmSourceGroup.h" @@ -46,6 +46,7 @@ class cmState; class cmTest; class cmTestGenerator; class cmVariableWatch; +class cmake; /** A type-safe wrapper for a string representing a directory id. */ class cmDirectoryId @@ -85,11 +86,10 @@ public: cmDirectoryId GetDirectoryId() const; - bool ReadListFile(const char* filename); + bool ReadListFile(const std::string& filename); - bool ReadDependentFile(const char* filename, bool noPolicyScope = true); - - bool ProcessBuildsystemFile(const char* filename); + bool ReadDependentFile(const std::string& filename, + bool noPolicyScope = true); /** * Add a function blocker to this makefile @@ -793,7 +793,7 @@ public: cmMakefile* Makefile; }; - void IssueMessage(cmake::MessageType t, std::string const& text) const; + void IssueMessage(MessageType t, std::string const& text) const; /** Set whether or not to report a CMP0000 violation. */ void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; } @@ -982,15 +982,18 @@ private: friend class BuildsystemFileScope; // CMP0053 == old - cmake::MessageType ExpandVariablesInStringOld( - std::string& errorstr, std::string& source, bool escapeQuotes, - bool noEscapes, bool atOnly, const char* filename, long line, - bool removeEmpty, bool replaceAt) const; + MessageType ExpandVariablesInStringOld(std::string& errorstr, + std::string& source, + bool escapeQuotes, bool noEscapes, + bool atOnly, const char* filename, + long line, bool removeEmpty, + bool replaceAt) const; // CMP0053 == new - cmake::MessageType ExpandVariablesInStringNew( - std::string& errorstr, std::string& source, bool escapeQuotes, - bool noEscapes, bool atOnly, const char* filename, long line, - bool replaceAt) const; + MessageType ExpandVariablesInStringNew(std::string& errorstr, + std::string& source, + bool escapeQuotes, bool noEscapes, + bool atOnly, const char* filename, + long line, bool replaceAt) const; /** * Old version of GetSourceFileWithOutput(const std::string&) kept for * backward-compatibility. It implements a linear search and support diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 846b12c..92eeb2e 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -6,6 +6,7 @@ #include <memory> // IWYU pragma: keep #include <sstream> #include <string> +#include <utility> #include <vector> #include "cmGeneratedFileStream.h" diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 2d2915c..0c2d7b3 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -6,6 +6,7 @@ #include <memory> // IWYU pragma: keep #include <sstream> #include <stddef.h> +#include <utility> #include <vector> #include "cmGeneratedFileStream.h" diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index d1dcd81..1207646 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -816,7 +816,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( lang_has_assembly && this->LocalGenerator->GetCreateAssemblySourceRules(); if (do_preprocess_rules || do_assembly_rules) { std::vector<std::string> force_depends; - force_depends.push_back("cmake_force"); + force_depends.emplace_back("cmake_force"); std::string::size_type dot_pos = relativeObj.rfind('.'); std::string relativeObjBase = relativeObj.substr(0, dot_pos); dot_pos = obj.rfind('.'); diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx index a50e5fc..48b9a27 100644 --- a/Source/cmMathCommand.cxx +++ b/Source/cmMathCommand.cxx @@ -4,8 +4,8 @@ #include "cmExprParserHelper.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cm_kwiml.h" -#include "cmake.h" #include <stdio.h> @@ -104,7 +104,7 @@ bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args) std::string const& w = helper.GetWarning(); if (!w.empty()) { - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w); } this->Makefile->AddDefinition(outputVariable, buffer); diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 5a341bd..4c26c66 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -4,9 +4,9 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmMessenger.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -20,26 +20,26 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, } std::vector<std::string>::const_iterator i = args.begin(); - cmake::MessageType type = cmake::MESSAGE; + MessageType type = MessageType::MESSAGE; bool status = false; bool fatal = false; if (*i == "SEND_ERROR") { - type = cmake::FATAL_ERROR; + type = MessageType::FATAL_ERROR; ++i; } else if (*i == "FATAL_ERROR") { fatal = true; - type = cmake::FATAL_ERROR; + type = MessageType::FATAL_ERROR; ++i; } else if (*i == "WARNING") { - type = cmake::WARNING; + type = MessageType::WARNING; ++i; } else if (*i == "AUTHOR_WARNING") { if (this->Makefile->IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && !this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { fatal = true; - type = cmake::AUTHOR_ERROR; + type = MessageType::AUTHOR_ERROR; } else if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { - type = cmake::AUTHOR_WARNING; + type = MessageType::AUTHOR_WARNING; } else { return true; } @@ -50,10 +50,10 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, } else if (*i == "DEPRECATION") { if (this->Makefile->IsOn("CMAKE_ERROR_DEPRECATED")) { fatal = true; - type = cmake::DEPRECATION_ERROR; + type = MessageType::DEPRECATION_ERROR; } else if ((!this->Makefile->IsSet("CMAKE_WARN_DEPRECATED") || this->Makefile->IsOn("CMAKE_WARN_DEPRECATED"))) { - type = cmake::DEPRECATION_WARNING; + type = MessageType::DEPRECATION_WARNING; } else { return true; } @@ -62,7 +62,7 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, std::string message = cmJoin(cmMakeRange(i, args.end()), std::string()); - if (type != cmake::MESSAGE) { + if (type != MessageType::MESSAGE) { // we've overridden the message type, above, so display it directly cmMessenger* m = this->Makefile->GetMessenger(); m->DisplayMessage(type, message, this->Makefile->GetBacktrace()); diff --git a/Source/cmMessageType.h b/Source/cmMessageType.h new file mode 100644 index 0000000..b57b86b --- /dev/null +++ b/Source/cmMessageType.h @@ -0,0 +1,21 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmMessageType_h +#define cmMessageType_h + +#include "cmConfigure.h" // IWYU pragma: keep + +enum class MessageType +{ + AUTHOR_WARNING, + AUTHOR_ERROR, + FATAL_ERROR, + INTERNAL_ERROR, + MESSAGE, + WARNING, + LOG, + DEPRECATION_ERROR, + DEPRECATION_WARNING +}; + +#endif diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index 880cf4b..3d788f6 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -12,47 +12,47 @@ #include <sstream> -cmake::MessageType cmMessenger::ConvertMessageType(cmake::MessageType t) const +MessageType cmMessenger::ConvertMessageType(MessageType t) const { bool warningsAsErrors; - if (t == cmake::AUTHOR_WARNING || t == cmake::AUTHOR_ERROR) { + if (t == MessageType::AUTHOR_WARNING || t == MessageType::AUTHOR_ERROR) { warningsAsErrors = this->GetDevWarningsAsErrors(); - if (warningsAsErrors && t == cmake::AUTHOR_WARNING) { - t = cmake::AUTHOR_ERROR; - } else if (!warningsAsErrors && t == cmake::AUTHOR_ERROR) { - t = cmake::AUTHOR_WARNING; + if (warningsAsErrors && t == MessageType::AUTHOR_WARNING) { + t = MessageType::AUTHOR_ERROR; + } else if (!warningsAsErrors && t == MessageType::AUTHOR_ERROR) { + t = MessageType::AUTHOR_WARNING; } - } else if (t == cmake::DEPRECATION_WARNING || - t == cmake::DEPRECATION_ERROR) { + } else if (t == MessageType::DEPRECATION_WARNING || + t == MessageType::DEPRECATION_ERROR) { warningsAsErrors = this->GetDeprecatedWarningsAsErrors(); - if (warningsAsErrors && t == cmake::DEPRECATION_WARNING) { - t = cmake::DEPRECATION_ERROR; - } else if (!warningsAsErrors && t == cmake::DEPRECATION_ERROR) { - t = cmake::DEPRECATION_WARNING; + if (warningsAsErrors && t == MessageType::DEPRECATION_WARNING) { + t = MessageType::DEPRECATION_ERROR; + } else if (!warningsAsErrors && t == MessageType::DEPRECATION_ERROR) { + t = MessageType::DEPRECATION_WARNING; } } return t; } -bool cmMessenger::IsMessageTypeVisible(cmake::MessageType t) const +bool cmMessenger::IsMessageTypeVisible(MessageType t) const { bool isVisible = true; - if (t == cmake::DEPRECATION_ERROR) { + if (t == MessageType::DEPRECATION_ERROR) { if (!this->GetDeprecatedWarningsAsErrors()) { isVisible = false; } - } else if (t == cmake::DEPRECATION_WARNING) { + } else if (t == MessageType::DEPRECATION_WARNING) { if (this->GetSuppressDeprecatedWarnings()) { isVisible = false; } - } else if (t == cmake::AUTHOR_ERROR) { + } else if (t == MessageType::AUTHOR_ERROR) { if (!this->GetDevWarningsAsErrors()) { isVisible = false; } - } else if (t == cmake::AUTHOR_WARNING) { + } else if (t == MessageType::AUTHOR_WARNING) { if (this->GetSuppressDevWarnings()) { isVisible = false; } @@ -61,22 +61,22 @@ bool cmMessenger::IsMessageTypeVisible(cmake::MessageType t) const return isVisible; } -static bool printMessagePreamble(cmake::MessageType t, std::ostream& msg) +static bool printMessagePreamble(MessageType t, std::ostream& msg) { // Construct the message header. - if (t == cmake::FATAL_ERROR) { + if (t == MessageType::FATAL_ERROR) { msg << "CMake Error"; - } else if (t == cmake::INTERNAL_ERROR) { + } else if (t == MessageType::INTERNAL_ERROR) { msg << "CMake Internal Error (please report a bug)"; - } else if (t == cmake::LOG) { + } else if (t == MessageType::LOG) { msg << "CMake Debug Log"; - } else if (t == cmake::DEPRECATION_ERROR) { + } else if (t == MessageType::DEPRECATION_ERROR) { msg << "CMake Deprecation Error"; - } else if (t == cmake::DEPRECATION_WARNING) { + } else if (t == MessageType::DEPRECATION_WARNING) { msg << "CMake Deprecation Warning"; - } else if (t == cmake::AUTHOR_WARNING) { + } else if (t == MessageType::AUTHOR_WARNING) { msg << "CMake Warning (dev)"; - } else if (t == cmake::AUTHOR_ERROR) { + } else if (t == MessageType::AUTHOR_ERROR) { msg << "CMake Error (dev)"; } else { msg << "CMake Warning"; @@ -92,13 +92,13 @@ void printMessageText(std::ostream& msg, std::string const& text) formatter.PrintFormatted(msg, text.c_str()); } -void displayMessage(cmake::MessageType t, std::ostringstream& msg) +void displayMessage(MessageType t, std::ostringstream& msg) { // Add a note about warning suppression. - if (t == cmake::AUTHOR_WARNING) { + if (t == MessageType::AUTHOR_WARNING) { msg << "This warning is for project developers. Use -Wno-dev to suppress " "it."; - } else if (t == cmake::AUTHOR_ERROR) { + } else if (t == MessageType::AUTHOR_ERROR) { msg << "This error is for project developers. Use -Wno-error=dev to " "suppress " "it."; @@ -109,7 +109,7 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg) #if defined(CMAKE_BUILD_WITH_CMAKE) // Add a C++ stack trace to internal errors. - if (t == cmake::INTERNAL_ERROR) { + if (t == MessageType::INTERNAL_ERROR) { std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0); if (!stack.empty()) { if (cmHasLiteralPrefix(stack, "WARNING:")) { @@ -121,8 +121,8 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg) #endif // Output the message. - if (t == cmake::FATAL_ERROR || t == cmake::INTERNAL_ERROR || - t == cmake::DEPRECATION_ERROR || t == cmake::AUTHOR_ERROR) { + if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR || + t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) { cmSystemTools::SetErrorOccured(); cmSystemTools::Message(msg.str().c_str(), "Error"); } else { @@ -130,13 +130,13 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg) } } -void cmMessenger::IssueMessage(cmake::MessageType t, const std::string& text, +void cmMessenger::IssueMessage(MessageType t, const std::string& text, const cmListFileBacktrace& backtrace) const { bool force = false; if (!force) { // override the message type, if needed, for warnings and errors - cmake::MessageType override = this->ConvertMessageType(t); + MessageType override = this->ConvertMessageType(t); if (override != t) { t = override; force = true; @@ -149,7 +149,7 @@ void cmMessenger::IssueMessage(cmake::MessageType t, const std::string& text, this->DisplayMessage(t, text, backtrace); } -void cmMessenger::DisplayMessage(cmake::MessageType t, const std::string& text, +void cmMessenger::DisplayMessage(MessageType t, const std::string& text, const cmListFileBacktrace& backtrace) const { std::ostringstream msg; diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h index e947eaa..cf15adf 100644 --- a/Source/cmMessenger.h +++ b/Source/cmMessenger.h @@ -6,7 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmListFileCache.h" -#include "cmake.h" +#include "cmMessageType.h" #include <string> @@ -14,10 +14,10 @@ class cmMessenger { public: void IssueMessage( - cmake::MessageType t, std::string const& text, + MessageType t, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; - void DisplayMessage(cmake::MessageType t, std::string const& text, + void DisplayMessage(MessageType t, std::string const& text, cmListFileBacktrace const& backtrace) const; void SetSuppressDevWarnings(bool suppress) @@ -49,8 +49,8 @@ public: } private: - bool IsMessageTypeVisible(cmake::MessageType t) const; - cmake::MessageType ConvertMessageType(cmake::MessageType t) const; + bool IsMessageTypeVisible(MessageType t) const; + MessageType ConvertMessageType(MessageType t) const; bool SuppressDevWarnings = false; bool SuppressDeprecatedWarnings = false; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 324afbf..8f6a23a 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -9,6 +9,7 @@ #include <memory> // IWYU pragma: keep #include <set> #include <sstream> +#include <utility> #include "cmAlgorithms.h" #include "cmCustomCommandGenerator.h" @@ -376,7 +377,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); linkCmds.insert(linkCmds.begin(), "$PRE_LINK"); - linkCmds.push_back("$POST_BUILD"); + linkCmds.emplace_back("$POST_BUILD"); std::string linkCmd = this->GetLocalGenerator()->BuildCommandLine(linkCmds); @@ -404,7 +405,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) std::vector<std::string> commandLines; commandLines.push_back(cmakeCommand + " -E cmake_symlink_executable $in $out"); - commandLines.push_back("$POST_BUILD"); + commandLines.emplace_back("$POST_BUILD"); this->GetGlobalGenerator()->AddRule( "CMAKE_SYMLINK_EXECUTABLE", @@ -422,7 +423,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) std::vector<std::string> commandLines; commandLines.push_back(cmakeCommand + " -E cmake_symlink_library $in $SONAME $out"); - commandLines.push_back("$POST_BUILD"); + commandLines.emplace_back("$POST_BUILD"); this->GetGlobalGenerator()->AddRule( "CMAKE_SYMLINK_LIBRARY", diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 228c9fb..c959a04 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -10,6 +10,7 @@ #include <map> #include <memory> // IWYU pragma: keep #include <sstream> +#include <utility> #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" @@ -18,6 +19,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalNinjaGenerator.h" +#include "cmListFileCache.h" // for BT #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" @@ -429,6 +431,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) vars.TargetCompilePDB = "$TARGET_COMPILE_PDB"; vars.ObjectDir = "$OBJECT_DIR"; vars.ObjectFileDir = "$OBJECT_FILE_DIR"; + if (lang == "Swift") { + vars.SwiftAuxiliarySources = "$SWIFT_AUXILIARY_SOURCES"; + vars.SwiftModuleName = "$SWIFT_MODULE_NAME"; + } // For some cases we do an explicit preprocessor invocation. bool const explicitPP = this->NeedExplicitPreprocessing(lang); @@ -899,6 +905,22 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["FLAGS"] = this->ComputeFlagsForObject(source, language); vars["DEFINES"] = this->ComputeDefines(source, language); vars["INCLUDES"] = this->ComputeIncludes(source, language); + if (language == "Swift") { + // The swift compiler needs all the sources besides the one being compiled + // in order to do the type checking. List all these "auxiliary" sources. + std::string aux_sources; + cmGeneratorTarget::KindedSources const& sources = + this->GeneratorTarget->GetKindedSources(this->GetConfigName()); + for (cmGeneratorTarget::SourceAndKind const& src : sources.Sources) { + if (src.Source.Value == source) { + continue; + } + aux_sources += " " + this->GetSourceFilePath(src.Source.Value); + } + vars["SWIFT_AUXILIARY_SOURCES"] = aux_sources; + + vars["SWIFT_MODULE_NAME"] = this->GeneratorTarget->GetName(); + } if (!this->NeedDepTypeMSVC(language)) { bool replaceExt(false); diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index 006211d..52f63a3 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -6,12 +6,12 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -81,7 +81,7 @@ bool cmOptionCommand::InitialPass(std::vector<std::string> const& args, "For compatibility with older versions of CMake, option " "is clearing the normal variable '" << args[0] << "'."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } return true; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 7fd7732..961e2b2 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -5,6 +5,7 @@ #include "cmAlgorithms.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmake.h" @@ -475,7 +476,7 @@ void cmOrderDirectories::FindImplicitConflicts() << " libraries in implicit directories:\n" << text << "Some of these libraries may not be found correctly."; this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::WARNING, w.str(), this->Target->GetBacktrace()); + MessageType::WARNING, w.str(), this->Target->GetBacktrace()); } void cmOrderDirectories::OrderDirectories() @@ -544,7 +545,7 @@ void cmOrderDirectories::DiagnoseCycle() } e << "Some of these libraries may not be found correctly."; this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::WARNING, e.str(), this->Target->GetBacktrace()); + MessageType::WARNING, e.str(), this->Target->GetBacktrace()); } bool cmOrderDirectories::IsSameDirectory(std::string const& l, diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index 2d61cc3..796974c 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -9,8 +9,8 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -46,7 +46,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, if (*argIter == "PARSE_ARGV") { if (args.size() != 6) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "PARSE_ARGV must be called with exactly 6 arguments."); cmSystemTools::SetFatalErrorOccured(); return true; @@ -54,7 +54,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, parseFromArgV = true; argIter++; // move past PARSE_ARGV if (!cmSystemTools::StringToULong(argIter->c_str(), &argvStart)) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "PARSE_ARGV index '" + *argIter + "' is not an unsigned integer"); cmSystemTools::SetFatalErrorOccured(); @@ -86,7 +86,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::ExpandListArgument(*argIter++, list); for (std::string const& iter : list) { if (!used_keywords.insert(iter).second) { - this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + iter); + this->GetMakefile()->IssueMessage(MessageType::WARNING, + dup_warning + iter); } options[iter]; // default initialize } @@ -96,7 +97,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::ExpandListArgument(*argIter++, list); for (std::string const& iter : list) { if (!used_keywords.insert(iter).second) { - this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + iter); + this->GetMakefile()->IssueMessage(MessageType::WARNING, + dup_warning + iter); } singleValArgs[iter]; // default initialize } @@ -106,7 +108,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::ExpandListArgument(*argIter++, list); for (std::string const& iter : list) { if (!used_keywords.insert(iter).second) { - this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + iter); + this->GetMakefile()->IssueMessage(MessageType::WARNING, + dup_warning + iter); } multiValArgs[iter]; // default initialize } @@ -131,7 +134,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, std::string argc = this->Makefile->GetSafeDefinition("ARGC"); unsigned long count; if (!cmSystemTools::StringToULong(argc.c_str(), &count)) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "PARSE_ARGV called with ARGC='" + argc + "' that is not an unsigned integer"); cmSystemTools::SetFatalErrorOccured(); @@ -142,13 +145,13 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, argName << "ARGV" << i; const char* arg = this->Makefile->GetDefinition(argName.str()); if (!arg) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "PARSE_ARGV called with " + argName.str() + " not set"); cmSystemTools::SetFatalErrorOccured(); return true; } - list.push_back(arg); + list.emplace_back(arg); } } diff --git a/Source/cmPipeConnection.cxx b/Source/cmPipeConnection.cxx index 3dab2f0..999d6f3 100644 --- a/Source/cmPipeConnection.cxx +++ b/Source/cmPipeConnection.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmPipeConnection.h" -#include <algorithm> +#include <utility> #include "cmServer.h" diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 5caea7d..0a234c5 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -2,11 +2,11 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmVersion.h" -#include "cmake.h" #include <assert.h> #include <ctype.h> @@ -128,7 +128,7 @@ static void DiagnoseAncientPolicies( << "Please either update your CMakeLists.txt files to conform to " << "the new behavior or use an older version of CMake that still " << "supports the old behavior."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); } static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy, @@ -146,7 +146,7 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy, std::ostringstream e; e << defaultVar << " has value \"" << defaultValue << "\" but must be \"OLD\", \"NEW\", or \"\" (empty)."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -167,14 +167,14 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, std::ostringstream e; e << "Invalid policy version value \"" << version_min << "\". " << "A numeric major.minor[.patch[.tweak]] must be given."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } // it is an error if the policy version is less than 2.4 if (minMajor < 2 || (minMajor == 2 && minMinor < 4)) { mf->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0. " "For compatibility with older versions please use any CMake 2.8.x " "release or lower."); @@ -199,7 +199,7 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, << "This is not allowed because the greater version may have new " << "policies not known to this CMake. " << "You may need a newer CMake version to build this project."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -218,7 +218,7 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, std::ostringstream e; e << "Invalid policy max version value \"" << version_max << "\". " << "A numeric major.minor[.patch[.tweak]] must be given."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -232,7 +232,7 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, e << "Policy VERSION range \"" << version_min << "..." << version_max << "\"" << " specifies a larger minimum than maximum."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 8f565c8..2fe9fe8 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -9,10 +9,10 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -90,7 +90,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, if (args[i] == "LANGUAGES") { if (haveLanguages) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "LANGUAGES may be specified at most once."); + MessageType::FATAL_ERROR, + "LANGUAGES may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -105,11 +106,11 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, "keyword: "; msg += cmJoin(languages, ", "); msg += '.'; - this->Makefile->IssueMessage(cmake::WARNING, msg); + this->Makefile->IssueMessage(MessageType::WARNING, msg); } } else if (args[i] == "VERSION") { if (haveVersion) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "VERSION may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; @@ -121,7 +122,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, doing = DoingVersion; missedValueReporter = [this, &resetReporter]() { this->Makefile->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "VERSION keyword not followed by a value or was followed by a " "value that expanded to nothing."); resetReporter(); @@ -129,7 +130,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } else if (args[i] == "DESCRIPTION") { if (haveDescription) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "DESCRIPTION may be specified at most once."); + MessageType::FATAL_ERROR, + "DESCRIPTION may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -140,7 +142,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, doing = DoingDescription; missedValueReporter = [this, &resetReporter]() { this->Makefile->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "DESCRIPTION keyword not followed by a value or was followed " "by a value that expanded to nothing."); resetReporter(); @@ -148,7 +150,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } else if (args[i] == "HOMEPAGE_URL") { if (haveHomepage) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "HOMEPAGE_URL may be specified at most once."); + MessageType::FATAL_ERROR, + "HOMEPAGE_URL may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -156,7 +159,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, doing = DoingHomepage; missedValueReporter = [this, &resetReporter]() { this->Makefile->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "HOMEPAGE_URL keyword not followed by a value or was followed " "by a value that expanded to nothing."); resetReporter(); @@ -188,14 +191,14 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, if ((haveVersion || haveDescription || haveHomepage) && !haveLanguages && !languages.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "project with VERSION, DESCRIPTION or HOMEPAGE_URL must " "use LANGUAGES before language names."); cmSystemTools::SetFatalErrorOccured(); return true; } if (haveLanguages && languages.empty()) { - languages.push_back("NONE"); + languages.emplace_back("NONE"); } cmPolicies::PolicyStatus cmp0048 = @@ -204,7 +207,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, // Set project VERSION variables to given values if (cmp0048 == cmPolicies::OLD || cmp0048 == cmPolicies::WARN) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "VERSION not allowed unless CMP0048 is set to NEW"); cmSystemTools::SetFatalErrorOccured(); return true; @@ -214,7 +217,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, "^([0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[0-9]+)?)?)?)?$"); if (!vx.find(version)) { std::string e = "VERSION \"" + version + "\" format invalid."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -261,22 +264,22 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } else if (cmp0048 != cmPolicies::OLD) { // Set project VERSION variables to empty std::vector<std::string> vv; - vv.push_back("PROJECT_VERSION"); - vv.push_back("PROJECT_VERSION_MAJOR"); - vv.push_back("PROJECT_VERSION_MINOR"); - vv.push_back("PROJECT_VERSION_PATCH"); - vv.push_back("PROJECT_VERSION_TWEAK"); + vv.emplace_back("PROJECT_VERSION"); + vv.emplace_back("PROJECT_VERSION_MAJOR"); + vv.emplace_back("PROJECT_VERSION_MINOR"); + vv.emplace_back("PROJECT_VERSION_PATCH"); + vv.emplace_back("PROJECT_VERSION_TWEAK"); vv.push_back(projectName + "_VERSION"); vv.push_back(projectName + "_VERSION_MAJOR"); vv.push_back(projectName + "_VERSION_MINOR"); vv.push_back(projectName + "_VERSION_PATCH"); vv.push_back(projectName + "_VERSION_TWEAK"); if (this->Makefile->IsRootMakefile()) { - vv.push_back("CMAKE_PROJECT_VERSION"); - vv.push_back("CMAKE_PROJECT_VERSION_MAJOR"); - vv.push_back("CMAKE_PROJECT_VERSION_MINOR"); - vv.push_back("CMAKE_PROJECT_VERSION_PATCH"); - vv.push_back("CMAKE_PROJECT_VERSION_TWEAK"); + vv.emplace_back("CMAKE_PROJECT_VERSION"); + vv.emplace_back("CMAKE_PROJECT_VERSION_MAJOR"); + vv.emplace_back("CMAKE_PROJECT_VERSION_MINOR"); + vv.emplace_back("CMAKE_PROJECT_VERSION_PATCH"); + vv.emplace_back("CMAKE_PROJECT_VERSION_TWEAK"); } std::string vw; for (std::string const& i : vv) { @@ -296,7 +299,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream w; w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0048) << "\nThe following variable(s) would be set to empty:" << vw; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } @@ -312,8 +315,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, if (languages.empty()) { // if no language is specified do c and c++ - languages.push_back("C"); - languages.push_back("CXX"); + languages.emplace_back("C"); + languages.emplace_back("CXX"); } this->Makefile->EnableLanguage(languages, false); std::string extraInclude = "CMAKE_PROJECT_" + projectName + "_INCLUDE"; diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 000529d..653caf7 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -9,6 +9,7 @@ #include <algorithm> #include <iterator> #include <sstream> +#include <utility> // - Static variables @@ -99,6 +100,41 @@ std::string cmQtAutoGen::GeneratorNameUpper(GeneratorT genType) return cmSystemTools::UpperCase(cmQtAutoGen::GeneratorName(genType)); } +std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc) +{ + std::string res; + std::vector<std::string> lst; + if (moc) { + lst.emplace_back("AUTOMOC"); + } + if (uic) { + lst.emplace_back("AUTOUIC"); + } + if (rcc) { + lst.emplace_back("AUTORCC"); + } + switch (lst.size()) { + case 1: + res += lst.at(0); + break; + case 2: + res += lst.at(0); + res += " and "; + res += lst.at(1); + break; + case 3: + res += lst.at(0); + res += ", "; + res += lst.at(1); + res += " and "; + res += lst.at(2); + break; + default: + break; + } + return res; +} + std::string cmQtAutoGen::Quoted(std::string const& text) { static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 4118dc7..96d1946 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -60,6 +60,9 @@ public: /// @brief Returns the generator name in upper case static std::string GeneratorNameUpper(GeneratorT genType); + /// @brief Returns a string with the requested tool names + static std::string Tools(bool moc, bool uic, bool rcc); + /// @brief Returns the string escaped and enclosed in quotes static std::string Quoted(std::string const& text); diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index 678ff14..431c5bc 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -9,6 +9,7 @@ #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -84,16 +85,43 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( // We support Qt4, Qt5 and Qt6 auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target); - bool const validQt = (qtVersion.Major == 4) || - (qtVersion.Major == 5) || (qtVersion.Major == 6); - bool const mocIsValid = moc && (validQt || !mocExec.empty()); - bool const uicIsValid = uic && (validQt || !uicExec.empty()); - bool const rccIsValid = rcc && (validQt || !rccExec.empty()); - + bool const validQt = (qtVersion.first.Major == 4) || + (qtVersion.first.Major == 5) || (qtVersion.first.Major == 6); + + bool const mocAvailable = (validQt || !mocExec.empty()); + bool const uicAvailable = (validQt || !uicExec.empty()); + bool const rccAvailable = (validQt || !rccExec.empty()); + bool const mocIsValid = (moc && mocAvailable); + bool const uicIsValid = (uic && uicAvailable); + bool const rccIsValid = (rcc && rccAvailable); + // Disabled AUTOMOC/UIC/RCC warning + bool const mocDisabled = (moc && !mocAvailable); + bool const uicDisabled = (uic && !uicAvailable); + bool const rccDisabled = (rcc && !rccAvailable); + if (mocDisabled || uicDisabled || rccDisabled) { + std::string msg = "AUTOGEN: No valid Qt version found for target "; + msg += target->GetName(); + msg += ". "; + msg += cmQtAutoGen::Tools(mocDisabled, uicDisabled, rccDisabled); + msg += " disabled. Consider adding:\n"; + { + std::string version = (qtVersion.second == 0) + ? std::string("<QTVERSION>") + : std::to_string(qtVersion.second); + std::string comp = uicDisabled ? "Widgets" : "Core"; + msg += " find_package(Qt"; + msg += version; + msg += " COMPONENTS "; + msg += comp; + msg += ")\n"; + } + msg += "to your CMakeLists.txt file."; + target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); + } if (mocIsValid || uicIsValid || rccIsValid) { // Create autogen target initializer Initializers_.emplace_back(cm::make_unique<cmQtAutoGenInitializer>( - this, target, qtVersion, mocIsValid, uicIsValid, rccIsValid, + this, target, qtVersion.first, mocIsValid, uicIsValid, rccIsValid, globalAutoGenTarget, globalAutoRccTarget)); } } diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index e4d2c82..47f7d73 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -16,6 +16,7 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmProcessOutput.h" @@ -842,7 +843,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() msg += ":\n set_property(SOURCE file.h PROPERTY "; msg += property; msg += " ON)\n"; - makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); + makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); } } } @@ -962,7 +963,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Files provided by the autogen target std::vector<std::string> autogenProvides; if (this->Moc.Enabled) { - this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC); + this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC, true); autogenProvides.push_back(this->Moc.MocsCompilation); } @@ -1231,11 +1232,7 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() } // Write AUTORCC info files - if (this->Rcc.Enabled && !this->SetupWriteRccInfo()) { - return false; - } - - return true; + return !this->Rcc.Enabled || this->SetupWriteRccInfo(); } bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() @@ -1359,7 +1356,8 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() } void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, - GeneratorT genType) + GeneratorT genType, + bool prepend) { // Register source file in makefile cmMakefile* makefile = this->Target->Target->GetMakefile(); @@ -1373,7 +1371,7 @@ void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, AddToSourceGroup(makefile, filename, genType); // Add source file to target - this->Target->AddSource(filename); + this->Target->AddSource(filename, prepend); } static unsigned int CharPtrToInt(const char* const input) @@ -1409,32 +1407,31 @@ static std::vector<cmQtAutoGenInitializer::IntegerVersion> GetKnownQtVersions( return result; } -cmQtAutoGenInitializer::IntegerVersion cmQtAutoGenInitializer::GetQtVersion( - cmGeneratorTarget const* target) +std::pair<cmQtAutoGenInitializer::IntegerVersion, unsigned int> +cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) { - auto knownQtVersions = GetKnownQtVersions(target); - if (knownQtVersions.empty()) { - return cmQtAutoGenInitializer::IntegerVersion(); // No Qt - } + std::pair<IntegerVersion, unsigned int> res( + IntegerVersion(), + CharPtrToInt(target->GetLinkInterfaceDependentStringProperty( + "QT_MAJOR_VERSION", ""))); - // Pick a version from the known versions: - auto targetVersion = CharPtrToInt( - target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")); - - if (targetVersion == 0) { - // No specific version was requested by the target: - // Use highest known Qt version. - return knownQtVersions.at(0); - } - - for (auto it : knownQtVersions) { - if (it.Major == targetVersion) { - return it; + auto knownQtVersions = GetKnownQtVersions(target); + if (!knownQtVersions.empty()) { + if (res.second == 0) { + // No specific version was requested by the target: + // Use highest known Qt version. + res.first = knownQtVersions.at(0); + } else { + // Pick a version from the known versions: + for (auto it : knownQtVersions) { + if (it.Major == res.second) { + res.first = it; + break; + } + } } } - - // Requested version was not found - return cmQtAutoGenInitializer::IntegerVersion(); + return res; } std::pair<bool, std::string> GetQtExecutable( @@ -1486,7 +1483,7 @@ std::pair<bool, std::string> GetQtExecutable( if (cmSystemTools::FileExists(result, true)) { std::vector<std::string> command; command.push_back(result); - command.push_back("-h"); + command.emplace_back("-h"); std::string stdOut; std::string stdErr; int retVal = 0; @@ -1550,9 +1547,9 @@ bool cmQtAutoGenInitializer::GetRccExecutable() if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) { if (stdOut.find("--list") != std::string::npos) { - this->Rcc.ListOptions.push_back("--list"); + this->Rcc.ListOptions.emplace_back("--list"); } else { - this->Rcc.ListOptions.push_back("-list"); + this->Rcc.ListOptions.emplace_back("-list"); } } return true; diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 5cef1b3..eefbaf0 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -11,6 +11,7 @@ #include <ostream> #include <set> #include <string> +#include <utility> #include <vector> class cmGeneratorTarget; @@ -76,7 +77,9 @@ public: }; public: - static IntegerVersion GetQtVersion(cmGeneratorTarget const* target); + /// @return The detected Qt version and the required Qt major version + static std::pair<IntegerVersion, unsigned int> GetQtVersion( + cmGeneratorTarget const* target); cmQtAutoGenInitializer(cmQtAutoGenGlobalInitializer* globalInitializer, cmGeneratorTarget* target, @@ -99,7 +102,8 @@ private: bool SetupWriteAutogenInfo(); bool SetupWriteRccInfo(); - void AddGeneratedSource(std::string const& filename, GeneratorT genType); + void AddGeneratedSource(std::string const& filename, GeneratorT genType, + bool prepend = false); bool GetMocExecutable(); bool GetUicExecutable(); diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 734b2d7..e2d7deb 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -8,12 +8,14 @@ #include "cmAlgorithms.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmake.h" #include <algorithm> +#include <utility> // -- Class methods @@ -52,7 +54,7 @@ void cmQtAutoGenerator::Logger::Info(GeneratorT genType, } { std::lock_guard<std::mutex> lock(Mutex_); - cmSystemTools::Stdout(msg.c_str(), msg.size()); + cmSystemTools::Stdout(msg); } } @@ -76,7 +78,7 @@ void cmQtAutoGenerator::Logger::Warning(GeneratorT genType, msg.push_back('\n'); { std::lock_guard<std::mutex> lock(Mutex_); - cmSystemTools::Stdout(msg.c_str(), msg.size()); + cmSystemTools::Stdout(msg); } } @@ -105,7 +107,7 @@ void cmQtAutoGenerator::Logger::Error(GeneratorT genType, msg.push_back('\n'); { std::lock_guard<std::mutex> lock(Mutex_); - cmSystemTools::Stderr(msg.c_str(), msg.size()); + cmSystemTools::Stderr(msg); } } @@ -147,7 +149,7 @@ void cmQtAutoGenerator::Logger::ErrorCommand( msg.push_back('\n'); { std::lock_guard<std::mutex> lock(Mutex_); - cmSystemTools::Stderr(msg.c_str(), msg.size()); + cmSystemTools::Stderr(msg); } } @@ -685,7 +687,7 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile, bool success = false; { - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::Unknown); cm.SetHomeOutputDirectory(InfoDir()); cm.SetHomeDirectory(InfoDir()); cm.GetCurrentSnapshot().SetDefaultDefinitions(); diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index e6ee85b..068f65c 100644 --- a/Source/cmQtAutoGeneratorMocUic.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -1,19 +1,21 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGeneratorMocUic.h" -#include "cmQtAutoGen.h" #include <algorithm> #include <array> +#include <cstddef> #include <functional> #include <list> #include <memory> +#include <set> #include <sstream> #include <utility> #include "cmAlgorithms.h" #include "cmCryptoHash.h" #include "cmMakefile.h" +#include "cmQtAutoGen.h" #include "cmSystemTools.h" #include "cmake.h" @@ -842,10 +844,10 @@ void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk) wrk.Moc().AllOptions.end()); // Add predefs include if (!wrk.Moc().PredefsFileAbs.empty()) { - cmd.push_back("--include"); + cmd.emplace_back("--include"); cmd.push_back(wrk.Moc().PredefsFileAbs); } - cmd.push_back("-o"); + cmd.emplace_back("-o"); cmd.push_back(BuildFile); cmd.push_back(SourceFile); @@ -961,7 +963,7 @@ void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk) } cmd.insert(cmd.end(), allOpts.begin(), allOpts.end()); } - cmd.push_back("-o"); + cmd.emplace_back("-o"); cmd.push_back(BuildFile); cmd.push_back(SourceFile); @@ -1211,7 +1213,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) }; // -- Read info file - if (!makefile->ReadListFile(InfoFile().c_str())) { + if (!makefile->ReadListFile(InfoFile())) { Log().ErrorFile(GeneratorT::GEN, InfoFile(), "File processing failed"); return false; } @@ -1286,7 +1288,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) std::string& error) { if (!key.empty()) { if (!exp.empty()) { - Moc_.DependFilters.push_back(KeyExpT()); + Moc_.DependFilters.emplace_back(); KeyExpT& filter(Moc_.DependFilters.back()); if (filter.Exp.compile(exp)) { filter.Key = key; @@ -1504,7 +1506,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) } // Append framework includes for (std::string const& path : frameworkPaths) { - Moc_.Includes.push_back("-F"); + Moc_.Includes.emplace_back("-F"); Moc_.Includes.push_back(path); } } diff --git a/Source/cmQtAutoGeneratorMocUic.h b/Source/cmQtAutoGeneratorMocUic.h index edf597c..9ec1def 100644 --- a/Source/cmQtAutoGeneratorMocUic.h +++ b/Source/cmQtAutoGeneratorMocUic.h @@ -11,7 +11,6 @@ #include "cm_uv.h" #include "cmsys/RegularExpression.hxx" -#include <algorithm> #include <condition_variable> #include <cstddef> #include <deque> @@ -21,6 +20,7 @@ #include <set> #include <string> #include <thread> +#include <utility> #include <vector> class cmMakefile; diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx index 29dc7a0..87c8d18 100644 --- a/Source/cmQtAutoGeneratorRcc.cxx +++ b/Source/cmQtAutoGeneratorRcc.cxx @@ -58,7 +58,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile) }; // -- Read info file - if (!makefile->ReadListFile(InfoFile().c_str())) { + if (!makefile->ReadListFile(InfoFile())) { Log().ErrorFile(GeneratorT::RCC, InfoFile(), "File processing failed"); return false; } @@ -603,7 +603,7 @@ bool cmQtAutoGeneratorRcc::GenerateRcc() std::vector<std::string> cmd; cmd.push_back(RccExecutable_); cmd.insert(cmd.end(), Options_.begin(), Options_.end()); - cmd.push_back("-o"); + cmd.emplace_back("-o"); cmd.push_back(RccFileOutput_); cmd.push_back(QrcFile_); // We're done here if the process fails to start diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index f0f92aa..2866a39 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -178,7 +178,7 @@ void cmRST::ProcessLine(std::string const& line) // Record the literal lines to output after whole block. // Ignore the language spec and record the opening line as blank. this->Directive = DirectiveCodeBlock; - this->MarkupLines.push_back(""); + this->MarkupLines.emplace_back(); } else if (this->ReplaceDirective.find(line)) { // Record the replace directive content. this->Directive = DirectiveReplace; @@ -221,7 +221,7 @@ void cmRST::ProcessLine(std::string const& line) // Record the literal lines to output after whole block. this->Markup = MarkupNormal; this->Directive = DirectiveLiteralBlock; - this->MarkupLines.push_back(""); + this->MarkupLines.emplace_back(); this->OutputLine("", false); } // Print non-markup lines. diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index 0dfb797..c3e8ff5 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -162,6 +162,16 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( } } } + if (replaceValues.SwiftAuxiliarySources) { + if (variable == "SWIFT_AUXILIARY_SOURCES") { + return replaceValues.SwiftAuxiliarySources; + } + } + if (replaceValues.SwiftModuleName) { + if (variable == "SWIFT_MODULE_NAME") { + return replaceValues.SwiftModuleName; + } + } if (variable == "TARGET_SONAME" || variable == "SONAME_FLAG" || variable == "TARGET_INSTALLNAME_DIR") { // All these variables depend on TargetSOName diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index a7d8cee..7aa63db 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -58,6 +58,8 @@ public: const char* Includes; const char* DependencyFile; const char* FilterPrefix; + const char* SwiftAuxiliarySources; + const char* SwiftModuleName; }; // Expand rule variables in CMake of the type found in language rules diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index fe0bdc9..f7d3879 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -417,7 +417,7 @@ static void __start_thread(void* arg) auto server = static_cast<cmServerBase*>(arg); std::string error; bool success = server->Serve(&error); - if (!success || error.empty() == false) { + if (!success || !error.empty()) { std::cerr << "Error during serve: " << error << std::endl; } } diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx index 1fc8cf8..5caa019 100644 --- a/Source/cmServerConnection.cxx +++ b/Source/cmServerConnection.cxx @@ -7,13 +7,13 @@ #include "cmServerDictionary.h" #include "cm_uv.h" -#include <algorithm> #ifdef _WIN32 # include "io.h" #else # include <unistd.h> #endif #include <cassert> +#include <utility> cmStdIoConnection::cmStdIoConnection( cmConnectionBufferStrategy* bufferStrategy) diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 6dbfd10..11a3f46 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -130,7 +130,8 @@ bool cmServerProtocol::Activate(cmServer* server, { assert(server); this->m_Server = server; - this->m_CMakeInstance = cm::make_unique<cmake>(cmake::RoleProject); + this->m_CMakeInstance = + cm::make_unique<cmake>(cmake::RoleProject, cmState::Project); const bool result = this->DoActivate(request, errorMessage); if (!result) { this->m_CMakeInstance = nullptr; diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx index 8445b02..9388e7c 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.cxx +++ b/Source/cmSetSourceFilesPropertiesCommand.cxx @@ -53,17 +53,17 @@ bool cmSetSourceFilesPropertiesCommand::RunCommand( for (j = propbeg; j != propend; ++j) { // old style allows for specifier before PROPERTIES keyword if (*j == "ABSTRACT") { - propertyPairs.push_back("ABSTRACT"); - propertyPairs.push_back("1"); + propertyPairs.emplace_back("ABSTRACT"); + propertyPairs.emplace_back("1"); } else if (*j == "WRAP_EXCLUDE") { - propertyPairs.push_back("WRAP_EXCLUDE"); - propertyPairs.push_back("1"); + propertyPairs.emplace_back("WRAP_EXCLUDE"); + propertyPairs.emplace_back("1"); } else if (*j == "GENERATED") { generated = true; - propertyPairs.push_back("GENERATED"); - propertyPairs.push_back("1"); + propertyPairs.emplace_back("GENERATED"); + propertyPairs.emplace_back("1"); } else if (*j == "COMPILE_FLAGS") { - propertyPairs.push_back("COMPILE_FLAGS"); + propertyPairs.emplace_back("COMPILE_FLAGS"); ++j; if (j == propend) { errors = "called with incorrect number of arguments " @@ -72,7 +72,7 @@ bool cmSetSourceFilesPropertiesCommand::RunCommand( } propertyPairs.push_back(*j); } else if (*j == "OBJECT_DEPENDS") { - propertyPairs.push_back("OBJECT_DEPENDS"); + propertyPairs.emplace_back("OBJECT_DEPENDS"); ++j; if (j == propend) { errors = "called with incorrect number of arguments " diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index 7f33b7a..01758ee 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -19,12 +19,12 @@ bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args, return false; } std::vector<std::string> paths; - paths.push_back("/usr/bsd"); - paths.push_back("/usr/sbin"); - paths.push_back("/usr/bin"); - paths.push_back("/bin"); - paths.push_back("/sbin"); - paths.push_back("/usr/local/bin"); + paths.emplace_back("/usr/bsd"); + paths.emplace_back("/usr/sbin"); + paths.emplace_back("/usr/bin"); + paths.emplace_back("/bin"); + paths.emplace_back("/sbin"); + paths.emplace_back("/usr/local/bin"); const char* cacheValue = this->Makefile->GetDefinition(args[0]); if (cacheValue) { diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 5d1f3f0..efc6bb5 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -7,6 +7,7 @@ #include "cmCustomCommand.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmProperty.h" #include "cmState.h" #include "cmSystemTools.h" @@ -179,7 +180,8 @@ bool cmSourceFile::FindFullPath(std::string* error) if (error) { *error = e.str(); } else { - this->Location.GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Location.GetMakefile()->IssueMessage(MessageType::FATAL_ERROR, + e.str()); } this->FindFullPathFailed = true; return false; diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index 90b9123..3dab638 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -5,6 +5,7 @@ #include "cmAlgorithms.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmake.h" @@ -194,7 +195,7 @@ bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc) // This can occur when referencing a source file from a different // directory. This is not yet allowed. this->Makefile->IssueMessage( - cmake::INTERNAL_ERROR, + MessageType::INTERNAL_ERROR, "Matches error: Each side has a directory relative to a different " "location. This can occur when referencing a source file from a " "different directory. This is not yet allowed."); diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index c3df313..34ded38 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -105,7 +105,7 @@ bool addFilesToItsSourceGroups(const std::string& root, tokenizedPath.pop_back(); if (tokenizedPath.empty()) { - tokenizedPath.push_back(""); + tokenizedPath.emplace_back(); } sg = makefile.GetOrCreateSourceGroup(tokenizedPath); @@ -254,16 +254,12 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args, bool cmSourceGroupCommand::checkArgumentsPreconditions( const ParsedArguments& parsedArguments, std::string& errorMsg) const { - if (!checkSingleParameterArgumentPreconditions(kPrefixOptionName, - parsedArguments, errorMsg) || - !checkSingleParameterArgumentPreconditions(kTreeOptionName, - parsedArguments, errorMsg) || - !checkSingleParameterArgumentPreconditions(kRegexOptionName, - parsedArguments, errorMsg)) { - return false; - } - - return true; + return checkSingleParameterArgumentPreconditions( + kPrefixOptionName, parsedArguments, errorMsg) && + checkSingleParameterArgumentPreconditions(kTreeOptionName, parsedArguments, + errorMsg) && + checkSingleParameterArgumentPreconditions(kRegexOptionName, + parsedArguments, errorMsg); } bool cmSourceGroupCommand::processTree(ParsedArguments& parsedArguments, @@ -286,12 +282,8 @@ bool cmSourceGroupCommand::processTree(ParsedArguments& parsedArguments, std::set<std::string> sourceGroupPaths = getSourceGroupFilesPaths(root, filesVector); - if (!addFilesToItsSourceGroups(root, sourceGroupPaths, prefix, - *(this->Makefile), errorMsg)) { - return false; - } - - return true; + return addFilesToItsSourceGroups(root, sourceGroupPaths, prefix, + *(this->Makefile), errorMsg); } bool cmSourceGroupCommand::checkSingleParameterArgumentPreconditions( diff --git a/Source/cmState.cxx b/Source/cmState.cxx index f664000..d4d3df5 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -539,6 +539,9 @@ const char* cmState::GetGlobalProperty(const std::string& prop) std::string langs; langs = cmJoin(this->EnabledLanguages, ";"); this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str()); + } else if (prop == "CMAKE_ROLE") { + std::string mode = this->GetModeString(); + this->SetGlobalProperty("CMAKE_ROLE", mode.c_str()); } #define STRING_LIST_ELEMENT(F) ";" #F if (prop == "CMAKE_C_KNOWN_FEATURES") { @@ -593,6 +596,16 @@ bool cmState::UseWindowsVSIDE() const return this->WindowsVSIDE; } +void cmState::SetGhsMultiIDE(bool ghsMultiIDE) +{ + this->GhsMultiIDE = ghsMultiIDE; +} + +bool cmState::UseGhsMultiIDE() const +{ + return this->GhsMultiIDE; +} + void cmState::SetWatcomWMake(bool watcomWMake) { this->WatcomWMake = watcomWMake; @@ -643,6 +656,40 @@ unsigned int cmState::GetCacheMinorVersion() const return this->CacheManager->GetCacheMinorVersion(); } +cmState::Mode cmState::GetMode() const +{ + return this->CurrentMode; +} + +std::string cmState::GetModeString() const +{ + return ModeToString(this->CurrentMode); +} + +void cmState::SetMode(cmState::Mode mode) +{ + this->CurrentMode = mode; +} + +std::string cmState::ModeToString(cmState::Mode mode) +{ + switch (mode) { + case Project: + return "PROJECT"; + case Script: + return "SCRIPT"; + case FindPackage: + return "FIND_PACKAGE"; + case CTest: + return "CTEST"; + case CPack: + return "CPACK"; + case Unknown: + return "UNKNOWN"; + } + return "UNKNOWN"; +} + std::string const& cmState::GetBinaryDirectory() const { return this->BinaryDirectory; diff --git a/Source/cmState.h b/Source/cmState.h index abe93ed..e447485 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -35,6 +35,16 @@ public: cmState(); ~cmState(); + enum Mode + { + Unknown, + Project, + Script, + FindPackage, + CTest, + CPack, + }; + static const char* GetTargetTypeName(cmStateEnums::TargetType targetType); cmStateSnapshot CreateBaseSnapshot(); @@ -154,6 +164,8 @@ public: bool UseWindowsShell() const; void SetWindowsVSIDE(bool windowsVSIDE); bool UseWindowsVSIDE() const; + void SetGhsMultiIDE(bool ghsMultiIDE); + bool UseGhsMultiIDE() const; void SetWatcomWMake(bool watcomWMake); bool UseWatcomWMake() const; void SetMinGWMake(bool minGWMake); @@ -166,6 +178,12 @@ public: unsigned int GetCacheMajorVersion() const; unsigned int GetCacheMinorVersion() const; + Mode GetMode() const; + std::string GetModeString() const; + void SetMode(Mode mode); + + static std::string ModeToString(Mode mode); + private: friend class cmake; void AddCacheEntry(const std::string& key, const char* value, @@ -206,10 +224,12 @@ private: bool IsGeneratorMultiConfig = false; bool WindowsShell = false; bool WindowsVSIDE = false; + bool GhsMultiIDE = false; bool WatcomWMake = false; bool MinGWMake = false; bool NMake = false; bool MSYSShell = false; + Mode CurrentMode = Unknown; }; #endif diff --git a/Source/cmString.hxx b/Source/cmString.hxx index e5ece52..49bad78 100644 --- a/Source/cmString.hxx +++ b/Source/cmString.hxx @@ -15,6 +15,7 @@ #include <ostream> #include <string> #include <type_traits> +#include <utility> namespace cm { diff --git a/Source/cmStringReplaceHelper.cxx b/Source/cmStringReplaceHelper.cxx index 69b7ced..f50cf58 100644 --- a/Source/cmStringReplaceHelper.cxx +++ b/Source/cmStringReplaceHelper.cxx @@ -85,10 +85,12 @@ void cmStringReplaceHelper::ParseReplaceExpression() auto r = this->ReplaceExpression.find('\\', l); if (r == std::string::npos) { r = this->ReplaceExpression.length(); - this->Replacements.push_back(this->ReplaceExpression.substr(l, r - l)); + this->Replacements.emplace_back( + this->ReplaceExpression.substr(l, r - l)); } else { if (r - l > 0) { - this->Replacements.push_back(this->ReplaceExpression.substr(l, r - l)); + this->Replacements.emplace_back( + this->ReplaceExpression.substr(l, r - l)); } if (r == (this->ReplaceExpression.length() - 1)) { this->ValidReplaceExpression = false; @@ -97,11 +99,11 @@ void cmStringReplaceHelper::ParseReplaceExpression() } if ((this->ReplaceExpression[r + 1] >= '0') && (this->ReplaceExpression[r + 1] <= '9')) { - this->Replacements.push_back(this->ReplaceExpression[r + 1] - '0'); + this->Replacements.emplace_back(this->ReplaceExpression[r + 1] - '0'); } else if (this->ReplaceExpression[r + 1] == 'n') { - this->Replacements.push_back("\n"); + this->Replacements.emplace_back("\n"); } else if (this->ReplaceExpression[r + 1] == '\\') { - this->Replacements.push_back("\\"); + this->Replacements.emplace_back("\\"); } else { this->ValidReplaceExpression = false; std::ostringstream error; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index be65853..9abc5f3 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -302,33 +302,21 @@ void cmSystemTools::SetStderrCallback(OutputCallback f, void* clientData) s_StderrCallbackClientData = clientData; } -void cmSystemTools::Stdout(const char* s) -{ - cmSystemTools::Stdout(s, strlen(s)); -} - -void cmSystemTools::Stderr(const char* s) -{ - cmSystemTools::Stderr(s, strlen(s)); -} - -void cmSystemTools::Stderr(const char* s, size_t length) +void cmSystemTools::Stderr(const std::string& s) { if (s_StderrCallback) { - (*s_StderrCallback)(s, length, s_StderrCallbackClientData); + (*s_StderrCallback)(s.c_str(), s.length(), s_StderrCallbackClientData); } else { - std::cerr.write(s, length); - std::cerr.flush(); + std::cerr << s << std::flush; } } -void cmSystemTools::Stdout(const char* s, size_t length) +void cmSystemTools::Stdout(const std::string& s) { if (s_StdoutCallback) { - (*s_StdoutCallback)(s, length, s_StdoutCallbackClientData); + (*s_StdoutCallback)(s.c_str(), s.length(), s_StdoutCallbackClientData); } else { - std::cout.write(s, length); - std::cout.flush(); + std::cout << s << std::flush; } } @@ -534,7 +522,7 @@ public: void Store(std::vector<std::string>& args) const { for (char** arg = this->ArgV; arg && *arg; ++arg) { - args.push_back(*arg); + args.emplace_back(*arg); } } }; @@ -792,7 +780,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, if (pipe == cmsysProcess_Pipe_STDOUT) { if (outputflag != OUTPUT_NONE) { processOutput.DecodeText(data, length, strdata, 1); - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } if (captureStdOut) { tempStdOut.insert(tempStdOut.end(), data, data + length); @@ -800,7 +788,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, } else if (pipe == cmsysProcess_Pipe_STDERR) { if (outputflag != OUTPUT_NONE) { processOutput.DecodeText(data, length, strdata, 2); - cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + cmSystemTools::Stderr(strdata); } if (captureStdErr) { tempStdErr.insert(tempStdErr.end(), data, data + length); @@ -811,11 +799,11 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, if (outputflag != OUTPUT_NONE) { processOutput.DecodeText(std::string(), strdata, 1); if (!strdata.empty()) { - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } processOutput.DecodeText(std::string(), strdata, 2); if (!strdata.empty()) { - cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + cmSystemTools::Stderr(strdata); } } } @@ -1586,7 +1574,7 @@ std::vector<std::string> cmSystemTools::GetEnvironmentVariables() std::vector<std::string> env; int cc; for (cc = 0; environ[cc]; ++cc) { - env.push_back(environ[cc]); + env.emplace_back(environ[cc]); } return env; } @@ -1899,13 +1887,13 @@ bool extract_tar(const char* outFileName, bool verbose, bool extract) if (verbose) { if (extract) { cmSystemTools::Stdout("x "); - cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str()); + cmSystemTools::Stdout(cm_archive_entry_pathname(entry)); } else { list_item_verbose(stdout, entry); } cmSystemTools::Stdout("\n"); } else if (!extract) { - cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str()); + cmSystemTools::Stdout(cm_archive_entry_pathname(entry)); cmSystemTools::Stdout("\n"); } if (extract) { @@ -3063,7 +3051,7 @@ std::vector<std::string> cmSystemTools::tokenize(const std::string& str, } while (tokend != std::string::npos); if (tokens.empty()) { - tokens.push_back(""); + tokens.emplace_back(); } return tokens; } @@ -3114,7 +3102,8 @@ std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes) } bool cmSystemTools::CreateSymlink(const std::string& origName, - const std::string& newName) + const std::string& newName, + std::string* errorMessage) { uv_fs_t req; int flags = 0; @@ -3128,7 +3117,32 @@ bool cmSystemTools::CreateSymlink(const std::string& origName, if (err) { std::string e = "failed to create symbolic link '" + newName + "': " + uv_strerror(err); - cmSystemTools::Error(e.c_str()); + if (errorMessage) { + *errorMessage = std::move(e); + } else { + cmSystemTools::Error(e.c_str()); + } + return false; + } + + return true; +} + +bool cmSystemTools::CreateLink(const std::string& origName, + const std::string& newName, + std::string* errorMessage) +{ + uv_fs_t req; + int err = + uv_fs_link(nullptr, &req, origName.c_str(), newName.c_str(), nullptr); + if (err) { + std::string e = + "failed to create link '" + newName + "': " + uv_strerror(err); + if (errorMessage) { + *errorMessage = std::move(e); + } else { + cmSystemTools::Error(e.c_str()); + } return false; } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index c0999e7..7a209c6 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -79,13 +79,11 @@ public: typedef void (*OutputCallback)(const char*, size_t length, void*); ///! Send a string to stdout - static void Stdout(const char* s); - static void Stdout(const char* s, size_t length); + static void Stdout(const std::string& s); static void SetStdoutCallback(OutputCallback, void* clientData = nullptr); ///! Send a string to stderr - static void Stderr(const char* s); - static void Stderr(const char* s, size_t length); + static void Stderr(const std::string& s); static void SetStderrCallback(OutputCallback, void* clientData = nullptr); typedef bool (*InterruptCallback)(void*); @@ -528,7 +526,14 @@ public: /** Create a symbolic link if the platform supports it. Returns whether creation succeeded. */ static bool CreateSymlink(const std::string& origName, - const std::string& newName); + const std::string& newName, + std::string* errorMessage = nullptr); + + /** Create a hard link if the platform supports it. Returns whether + creation succeeded. */ + static bool CreateLink(const std::string& origName, + const std::string& newName, + std::string* errorMessage = nullptr); private: static bool s_ForceUnixPaths; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 688f73b..fe48934 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -17,6 +17,7 @@ #include "cmGlobalGenerator.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmMessenger.h" #include "cmOutputConverter.h" #include "cmProperty.h" @@ -99,7 +100,7 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>( bool addContent = false; bool noMessage = true; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (context.GetBottom().GetPolicy(cmPolicies::CMP0051)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n"; @@ -570,7 +571,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s) if (src != s) { std::ostringstream e; bool noMessage = false; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0049)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0049) << "\n"; @@ -581,7 +582,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s) case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (!noMessage) { e << "Legacy variable expansion in source file \"" << s @@ -589,7 +590,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s) << "\". This behavior will be removed in a " "future version of CMake."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return ""; } } @@ -661,7 +662,7 @@ public: } }; -cmSourceFile* cmTarget::AddSource(const std::string& src) +cmSourceFile* cmTarget::AddSource(const std::string& src, bool before) { cmSourceFileLocation sfl(this->Makefile, src, cmSourceFileLocationKind::Known); @@ -670,8 +671,14 @@ cmSourceFile* cmTarget::AddSource(const std::string& src) TargetPropertyEntryFinder(sfl)) == this->Internal->SourceEntries.end()) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->SourceEntries.push_back(src); - this->Internal->SourceBacktraces.push_back(lfbt); + this->Internal->SourceEntries.insert( + before ? this->Internal->SourceEntries.begin() + : this->Internal->SourceEntries.end(), + src); + this->Internal->SourceBacktraces.insert( + before ? this->Internal->SourceBacktraces.begin() + : this->Internal->SourceBacktraces.end(), + lfbt); } if (cmGeneratorExpression::Find(src) != std::string::npos) { return nullptr; @@ -730,7 +737,7 @@ bool cmTarget::PushTLLCommandTrace(TLLSignature signature, } } if (this->TLLCommands.empty() || this->TLLCommands.back().second != lfc) { - this->TLLCommands.push_back(std::make_pair(signature, lfc)); + this->TLLCommands.emplace_back(signature, lfc); } return ret; } @@ -933,40 +940,40 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) if (prop == propMANUALLY_ADDED_DEPENDENCIES) { std::ostringstream e; e << "MANUALLY_ADDED_DEPENDENCIES property is read-only\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propNAME) { std::ostringstream e; e << "NAME property is read-only\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propTYPE) { std::ostringstream e; e << "TYPE property is read-only\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propEXPORT_NAME && this->IsImported()) { std::ostringstream e; e << "EXPORT_NAME property can't be set on imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propSOURCES && this->IsImported()) { std::ostringstream e; e << "SOURCES property can't be set on imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propIMPORTED_GLOBAL && !this->IsImported()) { std::ostringstream e; e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -974,7 +981,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->IncludeDirectoriesEntries.clear(); this->Internal->IncludeDirectoriesBacktraces.clear(); if (value) { - this->Internal->IncludeDirectoriesEntries.push_back(value); + this->Internal->IncludeDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt); } @@ -982,7 +989,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->CompileOptionsEntries.clear(); this->Internal->CompileOptionsBacktraces.clear(); if (value) { - this->Internal->CompileOptionsEntries.push_back(value); + this->Internal->CompileOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileOptionsBacktraces.push_back(lfbt); } @@ -990,7 +997,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->CompileFeaturesEntries.clear(); this->Internal->CompileFeaturesBacktraces.clear(); if (value) { - this->Internal->CompileFeaturesEntries.push_back(value); + this->Internal->CompileFeaturesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileFeaturesBacktraces.push_back(lfbt); } @@ -998,7 +1005,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->CompileDefinitionsEntries.clear(); this->Internal->CompileDefinitionsBacktraces.clear(); if (value) { - this->Internal->CompileDefinitionsEntries.push_back(value); + this->Internal->CompileDefinitionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileDefinitionsBacktraces.push_back(lfbt); } @@ -1006,7 +1013,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->LinkOptionsEntries.clear(); this->Internal->LinkOptionsBacktraces.clear(); if (value) { - this->Internal->LinkOptionsEntries.push_back(value); + this->Internal->LinkOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->LinkOptionsBacktraces.push_back(lfbt); } @@ -1014,7 +1021,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->LinkDirectoriesEntries.clear(); this->Internal->LinkDirectoriesBacktraces.clear(); if (value) { - this->Internal->LinkDirectoriesEntries.push_back(value); + this->Internal->LinkDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->LinkDirectoriesBacktraces.push_back(lfbt); } @@ -1023,7 +1030,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->LinkImplementationPropertyBacktraces.clear(); if (value) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->LinkImplementationPropertyEntries.push_back(value); + this->Internal->LinkImplementationPropertyEntries.emplace_back(value); this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt); } } else if (prop == propSOURCES) { @@ -1031,7 +1038,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->SourceBacktraces.clear(); if (value) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->SourceEntries.push_back(value); + this->Internal->SourceEntries.emplace_back(value); this->Internal->SourceBacktraces.push_back(lfbt); } } else if (prop == propIMPORTED_GLOBAL) { @@ -1039,7 +1046,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) std::ostringstream e; e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } /* no need to change anything if value does not change */ @@ -1056,7 +1063,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT " "targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } else { this->Properties.SetProperty(prop, value); @@ -1074,21 +1081,21 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, if (prop == "NAME") { std::ostringstream e; e << "NAME property is read-only\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == "EXPORT_NAME" && this->IsImported()) { std::ostringstream e; e << "EXPORT_NAME property can't be set on imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == "SOURCES" && this->IsImported()) { std::ostringstream e; e << "SOURCES property can't be set on imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == "IMPORTED_GLOBAL") { @@ -1096,57 +1103,57 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, e << "IMPORTED_GLOBAL property can't be appended, only set on imported " "targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == "INCLUDE_DIRECTORIES") { if (value && *value) { - this->Internal->IncludeDirectoriesEntries.push_back(value); + this->Internal->IncludeDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt); } } else if (prop == "COMPILE_OPTIONS") { if (value && *value) { - this->Internal->CompileOptionsEntries.push_back(value); + this->Internal->CompileOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileOptionsBacktraces.push_back(lfbt); } } else if (prop == "COMPILE_FEATURES") { if (value && *value) { - this->Internal->CompileFeaturesEntries.push_back(value); + this->Internal->CompileFeaturesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileFeaturesBacktraces.push_back(lfbt); } } else if (prop == "COMPILE_DEFINITIONS") { if (value && *value) { - this->Internal->CompileDefinitionsEntries.push_back(value); + this->Internal->CompileDefinitionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileDefinitionsBacktraces.push_back(lfbt); } } else if (prop == "LINK_OPTIONS") { if (value && *value) { - this->Internal->LinkOptionsEntries.push_back(value); + this->Internal->LinkOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->LinkOptionsBacktraces.push_back(lfbt); } } else if (prop == "LINK_DIRECTORIES") { if (value && *value) { - this->Internal->LinkDirectoriesEntries.push_back(value); + this->Internal->LinkDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->LinkDirectoriesBacktraces.push_back(lfbt); } } else if (prop == "LINK_LIBRARIES") { if (value && *value) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->LinkImplementationPropertyEntries.push_back(value); + this->Internal->LinkImplementationPropertyEntries.emplace_back(value); this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt); } } else if (prop == "SOURCES") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->SourceEntries.push_back(value); + this->Internal->SourceEntries.emplace_back(value); this->Internal->SourceBacktraces.push_back(lfbt); } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, prop + " property may not be APPENDed."); } else { this->Properties.AppendProperty(prop, value, asString); @@ -1283,7 +1290,7 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, << "the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG " << "properties accordingly."; } - context->IssueMessage(cmake::FATAL_ERROR, e.str()); + context->IssueMessage(MessageType::FATAL_ERROR, e.str()); } static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, @@ -1305,7 +1312,7 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, "property may contain configuration-sensitive generator-expressions " "which may be used to specify per-configuration rules."; - context->IssueMessage(cmake::FATAL_ERROR, e.str()); + context->IssueMessage(MessageType::FATAL_ERROR, e.str()); } static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, @@ -1319,7 +1326,7 @@ static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, e << "Attempt to promote imported target \"" << target->GetName() << "\" to global scope (by setting IMPORTED_GLOBAL) " "which is not built in this directory."; - context->IssueMessage(cmake::FATAL_ERROR, e.str()); + context->IssueMessage(MessageType::FATAL_ERROR, e.str()); } } @@ -1683,21 +1690,21 @@ bool cmTarget::CheckImportedLibName(std::string const& prop, if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY || !this->IsImported()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, prop + " property may be set only on imported INTERFACE library targets."); return false; } if (!value.empty()) { if (value[0] == '-') { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, prop + " property value\n " + value + "\nmay not start with '-'."); return false; } std::string::size_type bad = value.find_first_of(":/\\;"); if (bad != std::string::npos) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, prop + " property value\n " + value + "\nmay not contain '" + value.substr(bad, 1) + "'."); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 655cefd..24b3742 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -123,7 +123,7 @@ public: void AddSources(std::vector<std::string> const& srcs); void AddTracedSources(std::vector<std::string> const& srcs); cmSourceFile* AddSourceCMP0049(const std::string& src); - cmSourceFile* AddSource(const std::string& src); + cmSourceFile* AddSource(const std::string& src, bool before = false); //* how we identify a library, by name and type typedef std::pair<std::string, cmTargetLinkLibraryType> LibraryID; diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index 4e716dc..c4dc838 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -6,8 +6,8 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -24,7 +24,7 @@ void cmTargetCompileDefinitionsCommand::HandleMissingTarget( e << "Cannot specify compile definitions for target \"" << name << "\" " "which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetCompileDefinitionsCommand::Join( diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx index f58e404..c9e394b 100644 --- a/Source/cmTargetCompileFeaturesCommand.cxx +++ b/Source/cmTargetCompileFeaturesCommand.cxx @@ -6,7 +6,7 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" -#include "cmake.h" +#include "cmMessageType.h" class cmExecutionStatus; class cmTarget; @@ -24,7 +24,7 @@ void cmTargetCompileFeaturesCommand::HandleMissingTarget( e << "Cannot specify compile features for target \"" << name << "\" " "which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetCompileFeaturesCommand::Join( diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index 4df3630..8b4763a 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -7,8 +7,8 @@ #include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -24,7 +24,7 @@ void cmTargetCompileOptionsCommand::HandleMissingTarget( std::ostringstream e; e << "Cannot specify compile options for target \"" << name << "\" which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetCompileOptionsCommand::Join( diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index af142aa..d6918c0 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -8,9 +8,9 @@ #include "cmGeneratorExpression.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -27,7 +27,7 @@ void cmTargetIncludeDirectoriesCommand::HandleMissingTarget( std::ostringstream e; e << "Cannot specify include directories for target \"" << name << "\" which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetIncludeDirectoriesCommand::Join( diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx index bca3e45..269f751 100644 --- a/Source/cmTargetLinkDirectoriesCommand.cxx +++ b/Source/cmTargetLinkDirectoriesCommand.cxx @@ -8,9 +8,9 @@ #include "cmGeneratorExpression.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -26,7 +26,7 @@ void cmTargetLinkDirectoriesCommand::HandleMissingTarget( std::ostringstream e; e << "Cannot specify link directories for target \"" << name << "\" which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetLinkDirectoriesCommand::Join( diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index eebf7a0..5c7b95c 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -8,6 +8,7 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" @@ -51,7 +52,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( } } if (!this->Target) { - cmake::MessageType t = cmake::FATAL_ERROR; // fail by default + MessageType t = MessageType::FATAL_ERROR; // fail by default std::ostringstream e; e << "Cannot specify link libraries for target \"" << args[0] << "\" " << "which is not built by this project."; @@ -60,7 +61,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( if (args.size() < 2) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016)) { case cmPolicies::WARN: - t = cmake::AUTHOR_WARNING; + t = MessageType::AUTHOR_WARNING; // Print the warning. e << "\n" << "CMake does not support this but it used to work accidentally " @@ -69,7 +70,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( << cmPolicies::GetPolicyWarning(cmPolicies::CMP0016); break; case cmPolicies::OLD: // OLD behavior does not warn. - t = cmake::MESSAGE; + t = MessageType::MESSAGE; break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: @@ -81,11 +82,11 @@ bool cmTargetLinkLibrariesCommand::InitialPass( } // Now actually print the message. switch (t) { - case cmake::AUTHOR_WARNING: - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + case MessageType::AUTHOR_WARNING: + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); break; - case cmake::FATAL_ERROR: - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + case MessageType::FATAL_ERROR: + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); break; default: @@ -98,7 +99,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( if (this->Target->GetType() == cmStateEnums::UTILITY) { std::ostringstream e; const char* modal = nullptr; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0039)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0039) << "\n"; @@ -109,13 +110,13 @@ bool cmTargetLinkLibrariesCommand::InitialPass( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: modal = "must"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { e << "Utility target \"" << this->Target->GetName() << "\" " << modal << " not be used as the target of a target_link_libraries call."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -141,7 +142,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState = ProcessingPlainLinkInterface; if (i != 1) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The LINK_INTERFACE_LIBRARIES option must appear as the second " "argument, just after the target name."); return true; @@ -152,7 +153,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingKeywordPublicInterface && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The INTERFACE, PUBLIC or PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -163,7 +164,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingPlainPrivateInterface && this->CurrentProcessingState != ProcessingPlainPublicInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -175,7 +176,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingKeywordPublicInterface && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The INTERFACE, PUBLIC or PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -186,7 +187,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingPlainPublicInterface && this->CurrentProcessingState != ProcessingPlainPrivateInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -198,7 +199,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingKeywordPublicInterface && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The INTERFACE, PUBLIC or PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -258,7 +259,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( std::ostringstream e; e << "The \"" << cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[llt] << "\" argument must be followed by a library."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); } @@ -290,7 +291,7 @@ void cmTargetLinkLibrariesCommand::LinkLibraryTypeSpecifierWarning(int left, << cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[right] << "\" instead of a library name. " << "The first specifier will be ignored."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, @@ -299,7 +300,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "INTERFACE library can only be used with the INTERFACE keyword of " "target_link_libraries"); return false; @@ -307,7 +308,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, if (this->Target->IsImported() && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "IMPORTED library can only be used with the INTERFACE keyword of " "target_link_libraries"); return false; @@ -325,7 +326,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, sig, this->Makefile->GetExecutionContext())) { std::ostringstream e; const char* modal = nullptr; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0023)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n"; @@ -336,7 +337,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: modal = "must"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { @@ -355,7 +356,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, ? cmTarget::PlainTLLSignature : cmTarget::KeywordTLLSignature); this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -408,7 +409,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, << this->Target->GetName() << "\" which is not built in this directory.\n" << "This is allowed only when policy CMP0079 is set to NEW."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -426,7 +427,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, << " may not be linked into another target. One may link only to " "INTERFACE, OBJECT, STATIC or SHARED libraries, or to executables " "with the ENABLE_EXPORTS property set."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } this->Target->AddLinkLibrary(*this->Makefile, lib, libRef, llt); @@ -442,7 +443,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, "which the target was created rather than in this calling " "directory."; /* clang-format on */ - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } // Handle (additional) case where the command was called with PRIVATE / diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx index d6ed5ae..5366486 100644 --- a/Source/cmTargetLinkOptionsCommand.cxx +++ b/Source/cmTargetLinkOptionsCommand.cxx @@ -7,8 +7,8 @@ #include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -23,7 +23,7 @@ void cmTargetLinkOptionsCommand::HandleMissingTarget(const std::string& name) std::ostringstream e; e << "Cannot specify link options for target \"" << name << "\" which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetLinkOptionsCommand::Join( diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index 06ce0b1..d2c3496 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -7,10 +7,10 @@ #include <sstream> #include <unordered_set> +#include "cmMessageType.h" #include "cmMessenger.h" #include "cmPolicies.h" #include "cmStateSnapshot.h" -#include "cmake.h" bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( std::string const& tgtName, cmMessenger* messenger, @@ -18,7 +18,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( { std::ostringstream e; const char* modal = nullptr; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (context.GetBottom().GetPolicy(cmPolicies::CMP0026)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n"; @@ -29,7 +29,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: modal = "may"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { @@ -41,7 +41,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( messenger->IssueMessage(messageType, e.str(), context); } - return messageType != cmake::FATAL_ERROR; + return messageType != MessageType::FATAL_ERROR; } bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( @@ -65,6 +65,7 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( builtIns.insert("EXPORT_NAME"); builtIns.insert("IMPORTED"); builtIns.insert("IMPORTED_GLOBAL"); + builtIns.insert("MANUALLY_ADDED_DEPENDENCIES"); builtIns.insert("NAME"); builtIns.insert("TYPE"); } @@ -100,7 +101,7 @@ bool cmTargetPropertyComputer::PassesWhitelist( e << "INTERFACE_LIBRARY targets may only have whitelisted properties. " "The property \"" << prop << "\" is not allowed."; - messenger->IssueMessage(cmake::FATAL_ERROR, e.str(), context); + messenger->IssueMessage(MessageType::FATAL_ERROR, e.str(), context); return false; } return true; diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index 7429053..11e288f 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -7,10 +7,10 @@ #include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -34,7 +34,7 @@ void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name) e << "Cannot specify sources for target \"" << name << "\" " "which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetSourcesCommand::Join( @@ -99,7 +99,7 @@ std::vector<std::string> cmTargetSourcesCommand::ConvertToAbsoluteContent( case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076)); break; case cmPolicies::NEW: { @@ -117,7 +117,7 @@ std::vector<std::string> cmTargetSourcesCommand::ConvertToAbsoluteContent( e << "A private source from a directory other than that of target \"" << tgt->GetName() << "\" has a relative path."; } - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } return useAbsoluteContent ? absoluteContent : content; diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index e4ced6e..1e2ddc7 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -11,12 +11,11 @@ #include "cmLocalGenerator.h" #include "cmOutputConverter.h" #include "cmProperty.h" +#include "cmPropertyMap.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTest.h" -class cmPropertyMap; - cmTestGenerator::cmTestGenerator( cmTest* test, std::vector<std::string> const& configurations) : cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations) diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx index 3ff84ce..05b3f05 100644 --- a/Source/cmTryCompileCommand.cxx +++ b/Source/cmTryCompileCommand.cxx @@ -3,6 +3,7 @@ #include "cmTryCompileCommand.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmake.h" class cmExecutionStatus; @@ -18,7 +19,7 @@ bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv, if (this->Makefile->GetCMakeInstance()->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The TRY_COMPILE() command is not supported in --find-package mode."); return false; } diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index fafbd24..10a6d9a 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -7,6 +7,7 @@ #include "cmDuration.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -25,7 +26,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, if (this->Makefile->GetCMakeInstance()->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The TRY_RUN() command is not supported in --find-package mode."); return false; } @@ -100,11 +101,11 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, bool captureRunOutput = false; if (!this->OutputVariable.empty()) { captureRunOutput = true; - tryCompile.push_back("OUTPUT_VARIABLE"); + tryCompile.emplace_back("OUTPUT_VARIABLE"); tryCompile.push_back(this->OutputVariable); } if (!this->CompileOutputVariable.empty()) { - tryCompile.push_back("OUTPUT_VARIABLE"); + tryCompile.emplace_back("OUTPUT_VARIABLE"); tryCompile.push_back(this->CompileOutputVariable); } if (!this->RunOutputVariable.empty()) { diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index d80b5a2..9187c29 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -57,8 +57,9 @@ std::string VSInstanceInfo::GetInstallLocation() const return loc; } -cmVSSetupAPIHelper::cmVSSetupAPIHelper() - : setupConfig(NULL) +cmVSSetupAPIHelper::cmVSSetupAPIHelper(unsigned int version) + : Version(version) + , setupConfig(NULL) , setupConfig2(NULL) , setupHelper(NULL) , initializationFailure(false) @@ -88,7 +89,7 @@ bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation) return this->EnumerateAndChooseVSInstance(); } -bool cmVSSetupAPIHelper::IsVS2017Installed() +bool cmVSSetupAPIHelper::IsVSInstalled() { return this->EnumerateAndChooseVSInstance(); } @@ -312,11 +313,11 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() return false; std::string envVSCommonToolsDir; + std::string envVSCommonToolsDirEnvName = + "VS" + std::to_string(this->Version) + "0COMNTOOLS"; - // FIXME: When we support VS versions beyond 2017, the version - // to choose will be passed in by the caller. We need to map that - // to a per-version name of this environment variable. - if (cmSystemTools::GetEnv("VS150COMNTOOLS", envVSCommonToolsDir)) { + if (cmSystemTools::GetEnv(envVSCommonToolsDirEnvName.c_str(), + envVSCommonToolsDir)) { cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir); } @@ -328,8 +329,7 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() return false; } - // FIXME: Add a way for caller to specify other versions. - std::wstring wantVersion = std::to_wstring(15) + L'.'; + std::wstring const wantVersion = std::to_wstring(this->Version) + L'.'; SmartCOMPtr<ISetupInstance> instance; while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index b9cca45..4748a7a 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -120,12 +120,12 @@ struct VSInstanceInfo class cmVSSetupAPIHelper { public: - cmVSSetupAPIHelper(); + cmVSSetupAPIHelper(unsigned int version); ~cmVSSetupAPIHelper(); bool SetVSInstance(std::string const& vsInstallLocation); - bool IsVS2017Installed(); + bool IsVSInstalled(); bool GetVSInstanceInfo(std::string& vsInstallLocation); bool GetVCToolsetVersion(std::string& vsToolsetVersion); bool IsWin10SDKInstalled(); @@ -140,6 +140,8 @@ private: int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances); bool EnumerateAndChooseVSInstance(); + unsigned int Version; + // COM ptrs to query about VS instances SmartCOMPtr<ISetupConfiguration> setupConfig; SmartCOMPtr<ISetupConfiguration2> setupConfig2; diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index e080df1..03e0059 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -7,6 +7,7 @@ #include "cmExecutionStatus.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmVariableWatch.h" #include "cmake.h" @@ -70,7 +71,7 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, msg << "Variable \"" << variable << "\" was accessed using " << accessString << " with value \"" << (newValue ? newValue : "") << "\"."; - makefile->IssueMessage(cmake::LOG, msg.str()); + makefile->IssueMessage(MessageType::LOG, msg.str()); } data->InCallback = false; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index b0e70ff..ac4a4f5 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -6,6 +6,7 @@ #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" #include "cmGeneratedFileStream.h" +#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalVisualStudio10Generator.h" #include "cmLocalVisualStudio10Generator.h" @@ -297,6 +298,11 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( "$(UserRootDir)\\Microsoft.CSharp.$(Platform).user.props" #define VS10_CSharp_TARGETS "$(MSBuildToolsPath)\\Microsoft.CSharp.targets" +#define VS10_CSharp_NETCF_TARGETS \ + "$(MSBuildExtensionsPath)\\Microsoft\\$(TargetFrameworkIdentifier)\\" \ + "$(TargetFrameworkTargetsVersion)\\Microsoft.$(TargetFrameworkIdentifier)" \ + ".CSharp.targets" + void cmVisualStudio10TargetGenerator::Generate() { // do not generate external ms projects @@ -315,8 +321,7 @@ void cmVisualStudio10TargetGenerator::Generate() this->GeneratorTarget->GetName() + "\" is of type STATIC_LIBRARY. This is discouraged (and may be " "disabled in future). Make it a SHARED library instead."; - this->Makefile->IssueMessage(cmake::MessageType::DEPRECATION_WARNING, - message); + this->Makefile->IssueMessage(MessageType::DEPRECATION_WARNING, message); } this->ProjectType = csproj; this->Managed = true; @@ -480,9 +485,31 @@ void cmVisualStudio10TargetGenerator::Generate() targetFrameworkVersion = this->GeneratorTarget->GetProperty( "DOTNET_TARGET_FRAMEWORK_VERSION"); } + if (!targetFrameworkVersion && this->ProjectType == csproj && + this->GlobalGenerator->TargetsWindowsCE() && + this->GlobalGenerator->GetVersion() == + cmGlobalVisualStudioGenerator::VS12) { + // VS12 .NETCF default to .NET framework 3.9 + targetFrameworkVersion = "v3.9"; + } if (targetFrameworkVersion) { e1.Element("TargetFrameworkVersion", targetFrameworkVersion); } + if (this->ProjectType == csproj && + this->GlobalGenerator->TargetsWindowsCE()) { + const char* targetFrameworkId = this->GeneratorTarget->GetProperty( + "VS_TARGET_FRAMEWORK_IDENTIFIER"); + if (!targetFrameworkId) { + targetFrameworkId = "WindowsEmbeddedCompact"; + } + e1.Element("TargetFrameworkIdentifier", targetFrameworkId); + const char* targetFrameworkVer = this->GeneratorTarget->GetProperty( + "VS_TARGET_FRAMEWORKS_TARGET_VERSION"); + if (!targetFrameworkVer) { + targetFrameworkVer = "v8.0"; + } + e1.Element("TargetFrameworkTargetsVersion", targetFrameworkVer); + } } // Disable the project upgrade prompt that is displayed the first time a @@ -638,7 +665,11 @@ void cmVisualStudio10TargetGenerator::Generate() Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS); break; case csproj: - Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS); + if (this->GlobalGenerator->TargetsWindowsCE()) { + Elem(e0, "Import").Attribute("Project", VS10_CSharp_NETCF_TARGETS); + } else { + Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS); + } break; } @@ -1419,6 +1450,14 @@ void cmVisualStudio10TargetGenerator::WriteGroups() groupsUsed.insert(sourceGroup); } + if (cmSourceFile const* srcCMakeLists = + this->LocalGenerator->CreateVCProjBuildRule()) { + std::string const& source = srcCMakeLists->GetFullPath(); + cmSourceGroup* sourceGroup = + this->Makefile->FindSourceGroup(source, sourceGroups); + groupsUsed.insert(sourceGroup); + } + this->AddMissingSourceGroups(groupsUsed, sourceGroups); // Write out group file @@ -2244,6 +2283,58 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( e1.Element("_ProjectFileVersion", "10.0.20506.1"); for (std::string const& config : this->Configurations) { const std::string cond = this->CalcCondition(config); + + if (ttype <= cmStateEnums::UTILITY) { + if (const char* workingDir = this->GeneratorTarget->GetProperty( + "VS_DEBUGGER_WORKING_DIRECTORY")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(workingDir); + std::string genWorkingDir = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond, + genWorkingDir); + } + + if (const char* environment = + this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(environment); + std::string genEnvironment = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond, + genEnvironment); + } + + if (const char* debuggerCommand = + this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) { + + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(debuggerCommand); + std::string genDebuggerCommand = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerCommand", cond, + genDebuggerCommand); + } + + if (const char* commandArguments = this->GeneratorTarget->GetProperty( + "VS_DEBUGGER_COMMAND_ARGUMENTS")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(commandArguments); + std::string genCommandArguments = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond, + genCommandArguments); + } + } + if (ttype >= cmStateEnums::UTILITY) { e1.WritePlatformConfigTag( "IntDir", cond, "$(Platform)\\$(Configuration)\\$(ProjectName)\\"); @@ -2308,55 +2399,6 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( e1.WritePlatformConfigTag("ExcludePath", cond, sdkExcludeDirectories); } - if (const char* workingDir = this->GeneratorTarget->GetProperty( - "VS_DEBUGGER_WORKING_DIRECTORY")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(workingDir); - std::string genWorkingDir = - cge->Evaluate(this->LocalGenerator, config); - - e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond, - genWorkingDir); - } - - if (const char* environment = - this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(environment); - std::string genEnvironment = - cge->Evaluate(this->LocalGenerator, config); - - e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond, - genEnvironment); - } - - if (const char* debuggerCommand = - this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) { - - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(debuggerCommand); - std::string genDebuggerCommand = - cge->Evaluate(this->LocalGenerator, config); - - e1.WritePlatformConfigTag("LocalDebuggerCommand", cond, - genDebuggerCommand); - } - - if (const char* commandArguments = this->GeneratorTarget->GetProperty( - "VS_DEBUGGER_COMMAND_ARGUMENTS")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(commandArguments); - std::string genCommandArguments = - cge->Evaluate(this->LocalGenerator, config); - - e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond, - genCommandArguments); - } - std::string name = cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); e1.WritePlatformConfigTag("TargetName", cond, name); @@ -2551,7 +2593,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( "\" the /clr compiler flag was added manually. " + "Set usage of C++/CLI by setting COMMON_LANGUAGE_RUNTIME " "target property."; - this->Makefile->IssueMessage(cmake::MessageType::WARNING, message); + this->Makefile->IssueMessage(MessageType::WARNING, message); } } if (auto* clr = @@ -2581,6 +2623,10 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } clOptions.AddDefines(targetDefines); + if (this->ProjectType == csproj) { + clOptions.AppendFlag("DefineConstants", targetDefines); + } + // Get includes for this target if (!this->LangForClCompile.empty()) { clOptions.AddIncludes( diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx index f71b8b7..39063ed 100644 --- a/Source/cmVisualStudio10ToolsetOptions.cxx +++ b/Source/cmVisualStudio10ToolsetOptions.cxx @@ -7,8 +7,7 @@ #include "cmVisualStudioGeneratorOptions.h" std::string cmVisualStudio10ToolsetOptions::GetClFlagTableName( - std::string const& name, std::string const& toolset, - std::string const& defaultToolset) const + std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); @@ -23,13 +22,12 @@ std::string cmVisualStudio10ToolsetOptions::GetClFlagTableName( } else if (useToolset == "v100") { return "v10"; } else { - return this->GetToolsetName(name, defaultToolset); + return ""; } } std::string cmVisualStudio10ToolsetOptions::GetCSharpFlagTableName( - std::string const& name, std::string const& toolset, - std::string const& defaultToolset) const + std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); @@ -44,13 +42,12 @@ std::string cmVisualStudio10ToolsetOptions::GetCSharpFlagTableName( } else if (useToolset == "v100") { return "v10"; } else { - return this->GetToolsetName(name, defaultToolset); + return ""; } } std::string cmVisualStudio10ToolsetOptions::GetRcFlagTableName( - std::string const& name, std::string const& toolset, - std::string const& defaultToolset) const + std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); @@ -63,13 +60,12 @@ std::string cmVisualStudio10ToolsetOptions::GetRcFlagTableName( } else if (useToolset == "v100") { return "v10"; } else { - return this->GetToolsetName(name, defaultToolset); + return ""; } } std::string cmVisualStudio10ToolsetOptions::GetLibFlagTableName( - std::string const& name, std::string const& toolset, - std::string const& defaultToolset) const + std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); @@ -82,13 +78,12 @@ std::string cmVisualStudio10ToolsetOptions::GetLibFlagTableName( } else if (useToolset == "v100") { return "v10"; } else { - return this->GetToolsetName(name, defaultToolset); + return ""; } } std::string cmVisualStudio10ToolsetOptions::GetLinkFlagTableName( - std::string const& name, std::string const& toolset, - std::string const& defaultToolset) const + std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); @@ -103,13 +98,12 @@ std::string cmVisualStudio10ToolsetOptions::GetLinkFlagTableName( } else if (useToolset == "v100") { return "v10"; } else { - return this->GetToolsetName(name, defaultToolset); + return ""; } } std::string cmVisualStudio10ToolsetOptions::GetMasmFlagTableName( - std::string const& name, std::string const& toolset, - std::string const& defaultToolset) const + std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); @@ -122,7 +116,7 @@ std::string cmVisualStudio10ToolsetOptions::GetMasmFlagTableName( } else if (useToolset == "v100") { return "v10"; } else { - return this->GetToolsetName(name, defaultToolset); + return ""; } } diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h index 43946f0..875a35b 100644 --- a/Source/cmVisualStudio10ToolsetOptions.h +++ b/Source/cmVisualStudio10ToolsetOptions.h @@ -16,25 +16,17 @@ class cmVisualStudio10ToolsetOptions { public: std::string GetClFlagTableName(std::string const& name, - std::string const& toolset, - std::string const& defaultToolset) const; + std::string const& toolset) const; std::string GetCSharpFlagTableName(std::string const& name, - std::string const& toolset, - std::string const& defaultToolset) const; + std::string const& toolset) const; std::string GetRcFlagTableName(std::string const& name, - std::string const& toolset, - std::string const& defaultToolset) const; + std::string const& toolset) const; std::string GetLibFlagTableName(std::string const& name, - std::string const& toolset, - std::string const& defaultToolset) const; + std::string const& toolset) const; std::string GetLinkFlagTableName(std::string const& name, - std::string const& toolset, - std::string const& defaultToolset) const; + std::string const& toolset) const; std::string GetMasmFlagTableName(std::string const& name, - std::string const& toolset, - std::string const& defaultToolset) const; - -private: + std::string const& toolset) const; std::string GetToolsetName(std::string const& name, std::string const& toolset) const; }; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index afe9230..5c3e533 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -70,6 +70,7 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() case cmGlobalVisualStudioGenerator::VS12: case cmGlobalVisualStudioGenerator::VS14: case cmGlobalVisualStudioGenerator::VS15: + case cmGlobalVisualStudioGenerator::VS16: // by default VS puts <ExceptionHandling></ExceptionHandling> empty // for a project, to make our projects look the same put a new line // and space over for the closing </ExceptionHandling> as the default diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 9d43d19..a01fa6f 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -6,8 +6,8 @@ #include "cmExecutionStatus.h" #include "cmExpandedCommandArgument.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" #include <memory> // IWYU pragma: keep @@ -45,7 +45,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, std::vector<cmExpandedCommandArgument> expandedArguments; mf.ExpandArguments(this->Args, expandedArguments); - cmake::MessageType messageType; + MessageType messageType; cmListFileContext execContext = this->GetStartingContext(); @@ -72,7 +72,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, err += errorString; err += ")."; mf.IssueMessage(messageType, err); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); return true; } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index e1bae34..b44c325 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -55,8 +55,8 @@ # include "cmGlobalVisualStudio11Generator.h" # include "cmGlobalVisualStudio12Generator.h" # include "cmGlobalVisualStudio14Generator.h" -# include "cmGlobalVisualStudio15Generator.h" # include "cmGlobalVisualStudio9Generator.h" +# include "cmGlobalVisualStudioVersionedGenerator.h" # include "cmVSSetupHelper.h" # define CMAKE_HAVE_VS_GENERATORS @@ -126,7 +126,7 @@ void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, cm->MarkCliAsUsed(variable); } -cmake::cmake(Role role) +cmake::cmake(Role role, cmState::Mode mode) { this->Trace = false; this->TraceExpand = false; @@ -140,6 +140,7 @@ cmake::cmake(Role role) this->FileComparison = new cmFileTimeComparison; this->State = new cmState; + this->State->SetMode(mode); this->CurrentSnapshot = this->State->CreateBaseSnapshot(); this->Messenger = new cmMessenger; @@ -178,31 +179,31 @@ cmake::cmake(Role role) // these are used to find files when the extension // is not given // The "c" extension MUST precede the "C" extension. - this->SourceFileExtensions.push_back("c"); - this->SourceFileExtensions.push_back("C"); - - this->SourceFileExtensions.push_back("c++"); - this->SourceFileExtensions.push_back("cc"); - this->SourceFileExtensions.push_back("cpp"); - this->SourceFileExtensions.push_back("cxx"); - this->SourceFileExtensions.push_back("cu"); - this->SourceFileExtensions.push_back("m"); - this->SourceFileExtensions.push_back("M"); - this->SourceFileExtensions.push_back("mm"); + this->SourceFileExtensions.emplace_back("c"); + this->SourceFileExtensions.emplace_back("C"); + + this->SourceFileExtensions.emplace_back("c++"); + this->SourceFileExtensions.emplace_back("cc"); + this->SourceFileExtensions.emplace_back("cpp"); + this->SourceFileExtensions.emplace_back("cxx"); + this->SourceFileExtensions.emplace_back("cu"); + this->SourceFileExtensions.emplace_back("m"); + this->SourceFileExtensions.emplace_back("M"); + this->SourceFileExtensions.emplace_back("mm"); std::copy(this->SourceFileExtensions.begin(), this->SourceFileExtensions.end(), std::inserter(this->SourceFileExtensionsSet, this->SourceFileExtensionsSet.end())); - this->HeaderFileExtensions.push_back("h"); - this->HeaderFileExtensions.push_back("hh"); - this->HeaderFileExtensions.push_back("h++"); - this->HeaderFileExtensions.push_back("hm"); - this->HeaderFileExtensions.push_back("hpp"); - this->HeaderFileExtensions.push_back("hxx"); - this->HeaderFileExtensions.push_back("in"); - this->HeaderFileExtensions.push_back("txx"); + this->HeaderFileExtensions.emplace_back("h"); + this->HeaderFileExtensions.emplace_back("hh"); + this->HeaderFileExtensions.emplace_back("h++"); + this->HeaderFileExtensions.emplace_back("hm"); + this->HeaderFileExtensions.emplace_back("hpp"); + this->HeaderFileExtensions.emplace_back("hxx"); + this->HeaderFileExtensions.emplace_back("in"); + this->HeaderFileExtensions.emplace_back("txx"); std::copy(this->HeaderFileExtensions.begin(), this->HeaderFileExtensions.end(), @@ -532,7 +533,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) mf->SetArgcArgv(args); std::string systemFile = mf->GetModulesFile("CMakeFindPackageMode.cmake"); - mf->ReadListFile(systemFile.c_str()); + mf->ReadListFile(systemFile); std::string language = mf->GetSafeDefinition("LANGUAGE"); std::string mode = mf->GetSafeDefinition("MODE"); @@ -610,16 +611,13 @@ bool cmake::FindPackage(const std::vector<std::string>& args) } // Parse the args -void cmake::SetArgs(const std::vector<std::string>& args, - bool directoriesSetBefore) +void cmake::SetArgs(const std::vector<std::string>& args) { - bool directoriesSet = directoriesSetBefore; bool haveToolset = false; bool havePlatform = false; for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; if (arg.find("-H", 0) == 0 || arg.find("-S", 0) == 0) { - directoriesSet = true; std::string path = arg.substr(2); if (path.empty()) { ++i; @@ -640,7 +638,6 @@ void cmake::SetArgs(const std::vector<std::string>& args, } else if (arg.find("-O", 0) == 0) { // There is no local generate anymore. Ignore -O option. } else if (arg.find("-B", 0) == 0) { - directoriesSet = true; std::string path = arg.substr(2); if (path.empty()) { ++i; @@ -802,16 +799,27 @@ void cmake::SetArgs(const std::vector<std::string>& args, this->SetGlobalGenerator(gen); } } - // no option assume it is the path to the source + // no option assume it is the path to the source or an existing build else { - directoriesSet = true; this->SetDirectoriesFromFile(arg.c_str()); } } - if (!directoriesSet) { - this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory()); + + const bool haveSourceDir = !this->GetHomeDirectory().empty(); + const bool haveBinaryDir = !this->GetHomeOutputDirectory().empty(); + + if (this->CurrentWorkingMode == cmake::NORMAL_MODE && !haveSourceDir && + !haveBinaryDir) { + cmSystemTools::Error("No source or binary directory provided"); + return; + } + + if (!haveSourceDir) { this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory()); } + if (!haveBinaryDir) { + this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory()); + } } void cmake::SetDirectoriesFromFile(const char* arg) @@ -951,17 +959,25 @@ void cmake::AddDefaultExtraGenerators() #endif } -void cmake::GetRegisteredGenerators( - std::vector<GeneratorInfo>& generators) const +void cmake::GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, + bool includeNamesWithPlatform) const { for (cmGlobalGeneratorFactory* gen : this->Generators) { - std::vector<std::string> names; - gen->GetGenerators(names); + std::vector<std::string> names = gen->GetGeneratorNames(); + + if (includeNamesWithPlatform) { + std::vector<std::string> namesWithPlatform = + gen->GetGeneratorNamesWithPlatform(); + names.insert(names.end(), namesWithPlatform.begin(), + namesWithPlatform.end()); + } for (std::string const& name : names) { GeneratorInfo info; info.supportsToolset = gen->SupportsToolset(); info.supportsPlatform = gen->SupportsPlatform(); + info.supportedPlatforms = gen->GetKnownPlatforms(); + info.defaultPlatform = gen->GetDefaultPlatformName(); info.name = name; info.baseName = name; info.isAlias = false; @@ -1538,8 +1554,9 @@ void cmake::CreateDefaultGlobalGenerator() "\\Setup\\VC;ProductDir", // ";InstallDir" // }; - cmVSSetupAPIHelper vsSetupAPIHelper; - if (vsSetupAPIHelper.IsVS2017Installed()) { + if (cmVSSetupAPIHelper(16).IsVSInstalled()) { + found = "Visual Studio 16 2019"; + } else if (cmVSSetupAPIHelper(15).IsVSInstalled()) { found = "Visual Studio 15 2017"; } else { for (VSVersionedGenerator const* g = cm::cbegin(vsGenerators); @@ -1793,7 +1810,10 @@ void cmake::AddDefaultGenerators() { #if defined(_WIN32) && !defined(__CYGWIN__) # if !defined(CMAKE_BOOT_MINGW) - this->Generators.push_back(cmGlobalVisualStudio15Generator::NewFactory()); + this->Generators.push_back( + cmGlobalVisualStudioVersionedGenerator::NewFactory16()); + this->Generators.push_back( + cmGlobalVisualStudioVersionedGenerator::NewFactory15()); this->Generators.push_back(cmGlobalVisualStudio14Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio12Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio11Generator::NewFactory()); @@ -1994,7 +2014,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake no build system arguments\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2005,26 +2025,27 @@ int cmake::CheckBuildSystem() std::ostringstream msg; msg << "Re-run cmake missing file: " << this->CheckBuildSystemArgument << "\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } // Read the rerun check file and use it to decide whether to do the // global generate. - cmake cm(RoleScript); // Actually, all we need is the `set` command. + // Actually, all we need is the `set` command. + cmake cm(RoleScript, cmState::Unknown); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); cmGlobalGenerator gg(&cm); cmMakefile mf(&gg, cm.GetCurrentSnapshot()); - if (!mf.ReadListFile(this->CheckBuildSystemArgument.c_str()) || + if (!mf.ReadListFile(this->CheckBuildSystemArgument) || cmSystemTools::GetErrorOccuredFlag()) { if (verbose) { std::ostringstream msg; msg << "Re-run cmake error reading : " << this->CheckBuildSystemArgument << "\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } // There was an error reading the file. Just rerun. return 1; @@ -2058,7 +2079,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake, missing byproduct: " << p << "\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2079,7 +2100,7 @@ int cmake::CheckBuildSystem() std::ostringstream msg; msg << "Re-run cmake no CMAKE_MAKEFILE_DEPENDS " "or CMAKE_MAKEFILE_OUTPUTS :\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2098,7 +2119,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake: build system dependency is missing\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2118,7 +2139,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake: build system output is missing\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2134,7 +2155,7 @@ int cmake::CheckBuildSystem() std::ostringstream msg; msg << "Re-run cmake file: " << out_oldest << " older than: " << dep_newest << "\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2454,7 +2475,7 @@ static bool cmakeCheckStampList(const char* stampList, bool verbose) return true; } -void cmake::IssueMessage(cmake::MessageType t, std::string const& text, +void cmake::IssueMessage(MessageType t, std::string const& text, cmListFileBacktrace const& backtrace) const { this->Messenger->IssueMessage(t, text, backtrace); @@ -2472,7 +2493,7 @@ std::vector<std::string> cmake::GetDebugConfigs() } // If no configurations were specified, use a default list. if (configs.empty()) { - configs.push_back("DEBUG"); + configs.emplace_back("DEBUG"); } return configs; } @@ -2681,7 +2702,7 @@ void cmake::RunCheckForUnusedVariables() } } if (haveUnused) { - this->IssueMessage(cmake::WARNING, msg.str()); + this->IssueMessage(MessageType::WARNING, msg.str()); } #endif } diff --git a/Source/cmake.h b/Source/cmake.h index d00acc7..38d0c62 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -14,6 +14,8 @@ #include "cmInstalledFile.h" #include "cmListFileCache.h" +#include "cmMessageType.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" @@ -28,7 +30,6 @@ class cmGlobalGenerator; class cmGlobalGeneratorFactory; class cmMakefile; class cmMessenger; -class cmState; class cmVariableWatch; struct cmDocumentationEntry; @@ -68,19 +69,6 @@ public: RoleProject // all commands }; - enum MessageType - { - AUTHOR_WARNING, - AUTHOR_ERROR, - FATAL_ERROR, - INTERNAL_ERROR, - MESSAGE, - WARNING, - LOG, - DEPRECATION_ERROR, - DEPRECATION_WARNING - }; - enum DiagLevel { DIAG_IGNORE, @@ -116,6 +104,8 @@ public: std::string extraName; bool supportsToolset; bool supportsPlatform; + std::vector<std::string> supportedPlatforms; + std::string defaultPlatform; bool isAlias; }; @@ -125,7 +115,7 @@ public: static const int DEFAULT_BUILD_PARALLEL_LEVEL = 0; /// Default constructor - cmake(Role role); + cmake(Role role, cmState::Mode mode); /// Destructor ~cmake(); @@ -208,7 +198,8 @@ public: void SetGlobalGenerator(cmGlobalGenerator*); ///! Get the names of the current registered generators - void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators) const; + void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, + bool includeNamesWithPlatform = true) const; ///! Set the name of the selected generator-specific instance. void SetGeneratorInstance(std::string const& instance) @@ -277,8 +268,7 @@ public: int GetSystemInformation(std::vector<std::string>&); ///! Parse command line arguments - void SetArgs(const std::vector<std::string>&, - bool directoriesSetBefore = false); + void SetArgs(const std::vector<std::string>& args); ///! Is this cmake running as a result of a TRY_COMPILE command bool GetIsInTryCompile() const; @@ -434,7 +424,7 @@ public: /** Display a message to the user. */ void IssueMessage( - cmake::MessageType t, std::string const& text, + MessageType t, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; ///! run the --build option @@ -550,13 +540,13 @@ private: * Convert a message type between a warning and an error, based on the state * of the error output CMake variables, in the cache. */ - cmake::MessageType ConvertMessageType(cmake::MessageType t) const; + MessageType ConvertMessageType(MessageType t) const; /* * Check if messages of this type should be output, based on the state of the * warning and error output CMake variables, in the cache. */ - bool IsMessageTypeVisible(cmake::MessageType t) const; + bool IsMessageTypeVisible(MessageType t) const; }; #define CMAKE_STANDARD_OPTIONS_TABLE \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 75dabde..5a04eab 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -106,7 +106,7 @@ static int do_command(int ac, char const* const* av) { std::vector<std::string> args; args.reserve(ac - 1); - args.push_back(av[0]); + args.emplace_back(av[0]); args.insert(args.end(), av + 2, av + ac); return cmcmd::ExecuteCMakeCommand(args); } @@ -217,7 +217,7 @@ int do_cmake(int ac, char const* const* av) doc.addCMakeStandardDocSections(); if (doc.CheckOptions(ac, av)) { // Construct and print requested documentation. - cmake hcm(cmake::RoleInternal); + cmake hcm(cmake::RoleInternal, cmState::Unknown); hcm.SetHomeDirectory(""); hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); @@ -285,21 +285,21 @@ int do_cmake(int ac, char const* const* av) } else if (cmHasLiteralPrefix(av[i], "-P")) { if (i == ac - 1) { cmSystemTools::Error("No script specified for argument -P"); - } else { - workingMode = cmake::SCRIPT_MODE; - args.push_back(av[i]); - i++; - args.push_back(av[i]); + return 1; } + workingMode = cmake::SCRIPT_MODE; + args.emplace_back(av[i]); + i++; + args.emplace_back(av[i]); } else if (cmHasLiteralPrefix(av[i], "--find-package")) { workingMode = cmake::FIND_PACKAGE_MODE; - args.push_back(av[i]); + args.emplace_back(av[i]); } else { - args.push_back(av[i]); + args.emplace_back(av[i]); } } if (sysinfo) { - cmake cm(cmake::RoleProject); + cmake cm(cmake::RoleProject, cmState::Project); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); int ret = cm.GetSystemInformation(args); @@ -307,7 +307,19 @@ int do_cmake(int ac, char const* const* av) } cmake::Role const role = workingMode == cmake::SCRIPT_MODE ? cmake::RoleScript : cmake::RoleProject; - cmake cm(role); + cmState::Mode mode = cmState::Unknown; + switch (workingMode) { + case cmake::NORMAL_MODE: + mode = cmState::Project; + break; + case cmake::SCRIPT_MODE: + mode = cmState::Script; + break; + case cmake::FIND_PACKAGE_MODE: + mode = cmState::FindPackage; + break; + } + cmake cm(role, mode); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); @@ -374,7 +386,7 @@ static int do_build(int ac, char const* const* av) Doing doing = DoingDir; for (int i = 2; i < ac; ++i) { if (doing == DoingNative) { - nativeOptions.push_back(av[i]); + nativeOptions.emplace_back(av[i]); } else if ((strcmp(av[i], "-j") == 0) || (strcmp(av[i], "--parallel") == 0)) { jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL; @@ -463,7 +475,7 @@ static int do_build(int ac, char const* const* av) return 1; } - cmake cm(cmake::RoleInternal); + cmake cm(cmake::RoleInternal, cmState::Unknown); cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); cm.SetProgressCallback(cmakemainProgressCallback, &cm); return cm.Build(jobs, dir, target, config, nativeOptions, clean); @@ -501,7 +513,7 @@ static int do_open(int ac, char const* const* av) return 1; } - cmake cm(cmake::RoleInternal); + cmake cm(cmake::RoleInternal, cmState::Unknown); cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); cm.SetProgressCallback(cmakemainProgressCallback, &cm); return cm.Open(dir, false) ? 0 : 1; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 930ced9..26f7509 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -9,6 +9,7 @@ #include "cmMakefile.h" #include "cmQtAutoGeneratorMocUic.h" #include "cmQtAutoGeneratorRcc.h" +#include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" @@ -44,6 +45,7 @@ #include <stdlib.h> #include <string.h> #include <time.h> +#include <utility> class cmConnection; @@ -199,7 +201,7 @@ static int HandleTidy(const std::string& runCmd, const std::string& sourceFile, std::vector<std::string> tidy_cmd; cmSystemTools::ExpandListArgument(runCmd, tidy_cmd, true); tidy_cmd.push_back(sourceFile); - tidy_cmd.push_back("--"); + tidy_cmd.emplace_back("--"); tidy_cmd.insert(tidy_cmd.end(), orig_cmd.begin(), orig_cmd.end()); // Run the tidy command line. Capture its stdout and hide its stderr. @@ -226,9 +228,9 @@ static int HandleLWYU(const std::string& runCmd, // Construct the ldd -r -u (link what you use lwyu) command line // ldd -u -r lwuy target std::vector<std::string> lwyu_cmd; - lwyu_cmd.push_back("ldd"); - lwyu_cmd.push_back("-u"); - lwyu_cmd.push_back("-r"); + lwyu_cmd.emplace_back("ldd"); + lwyu_cmd.emplace_back("-u"); + lwyu_cmd.emplace_back("-r"); lwyu_cmd.push_back(runCmd); // Run the ldd -u -r command line. @@ -270,9 +272,12 @@ static int HandleCppLint(const std::string& runCmd, << "\n"; return 1; } - std::cerr << "Warning: cpplint diagnostics:\n"; - // Output the output from cpplint to stderr - std::cerr << stdOut; + if (!stdOut.empty()) { + std::cerr << "Warning: cpplint diagnostics:\n"; + // Output the output from cpplint to stderr + std::cerr << stdOut; + } + // always return 0 so the build can continue as cpplint returns non-zero // for any warning return 0; @@ -717,7 +722,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) std::cerr << "-E capabilities accepts no additional arguments\n"; return 1; } - cmake cm(cmake::RoleInternal); + cmake cm(cmake::RoleInternal, cmState::Unknown); #if defined(CMAKE_BUILD_WITH_CMAKE) std::cout << cm.ReportCapabilities(true); #else @@ -894,7 +899,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) const bool verbose = isCMakeVerbose(); // Create a cmake object instance to process dependencies. - cmake cm(cmake::RoleScript); // All we need is the `set` command. + // All we need is the `set` command. + cmake cm(cmake::RoleScript, cmState::Unknown); std::string gen; std::string homeDir; std::string startDir; @@ -1017,7 +1023,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) std::string config; if (args.size() > 3) { config = args[3]; - }; + } return autoGen.Run(infoFile, config) ? 0 : 1; } #endif @@ -1481,7 +1487,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string>& args) break; default: break; - }; + } } // Free the process instance. @@ -1727,7 +1733,7 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg, } if (this->LinkGeneratesManifest) { - this->LinkCommand.push_back("/MANIFEST"); + this->LinkCommand.emplace_back("/MANIFEST"); this->LinkCommand.push_back("/MANIFESTFILE:" + this->LinkerManifestFile); } @@ -1875,8 +1881,8 @@ int cmVSLink::RunMT(std::string const& out, bool notify) { std::vector<std::string> mtCommand; mtCommand.push_back(this->MtPath.empty() ? "mt" : this->MtPath); - mtCommand.push_back("/nologo"); - mtCommand.push_back("/manifest"); + mtCommand.emplace_back("/nologo"); + mtCommand.emplace_back("/manifest"); if (this->LinkGeneratesManifest) { mtCommand.push_back(this->LinkerManifestFile); } @@ -1886,7 +1892,7 @@ int cmVSLink::RunMT(std::string const& out, bool notify) if (notify) { // Add an undocumented option that enables a special return // code to notify us when the manifest is modified. - mtCommand.push_back("/notify_update"); + mtCommand.emplace_back("/notify_update"); } int mtRet = 0; if (!RunCommand("MT", mtCommand, this->Verbose, FORMAT_HEX, &mtRet, diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 8ba126f..4a2531a 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -208,7 +208,7 @@ int main(int argc, char const* const* argv) std::vector<std::string> args; args.reserve(argc); for (int i = 0; i < argc; ++i) { - args.push_back(argv[i]); + args.emplace_back(argv[i]); } // run ctest std::string output; diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 094c2ee..f65690b 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -1162,7 +1162,7 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, case KWSYSPE_PIPE_STDERR: wd->PipeId = kwsysProcess_Pipe_STDERR; break; - }; + } return 1; } } else if (n < 0 && errno == EAGAIN) { diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx index ef87436..15f9c02 100644 --- a/Source/kwsys/testCommandLineArguments.cxx +++ b/Source/kwsys/testCommandLineArguments.cxx @@ -165,25 +165,26 @@ int testCommandLineArguments(int argc, char* argv[]) } size_t cc; #define CompareTwoLists(list1, list_valid, lsize) \ - if (list1.size() != lsize) { \ - std::cerr << "Problem setting " #list1 ". Size is: " << list1.size() \ - << " should be: " << lsize << std::endl; \ - res = 1; \ - } else { \ - std::cout << #list1 " argument set:"; \ - for (cc = 0; cc < lsize; ++cc) { \ - std::cout << " " << list1[cc]; \ - if (!CompareTwoItemsOnList(list1[cc], list_valid[cc])) { \ - std::cerr << "Problem setting " #list1 ". Value of " << cc \ - << " is: [" << list1[cc] << "] <> [" << list_valid[cc] \ - << "]" << std::endl; \ - res = 1; \ - break; \ + do { \ + if (list1.size() != lsize) { \ + std::cerr << "Problem setting " #list1 ". Size is: " << list1.size() \ + << " should be: " << lsize << std::endl; \ + res = 1; \ + } else { \ + std::cout << #list1 " argument set:"; \ + for (cc = 0; cc < lsize; ++cc) { \ + std::cout << " " << list1[cc]; \ + if (!CompareTwoItemsOnList(list1[cc], list_valid[cc])) { \ + std::cerr << "Problem setting " #list1 ". Value of " << cc \ + << " is: [" << list1[cc] << "] <> [" << list_valid[cc] \ + << "]" << std::endl; \ + res = 1; \ + break; \ + } \ } \ + std::cout << std::endl; \ } \ - std::cout << std::endl; \ - } - + } while (0) CompareTwoLists(numbers_argument, valid_numbers, 10); CompareTwoLists(doubles_argument, valid_doubles, 3); CompareTwoLists(bools_argument, valid_bools, 3); diff --git a/Tests/CMakeLib/testString.cxx b/Tests/CMakeLib/testString.cxx index 2aa1459..af5e41e 100644 --- a/Tests/CMakeLib/testString.cxx +++ b/Tests/CMakeLib/testString.cxx @@ -16,10 +16,12 @@ #include <utility> #define ASSERT_TRUE(x) \ - if (!(x)) { \ - std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \ - return false; \ - } + do { \ + if (!(x)) { \ + std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \ + return false; \ + } \ + } while (false) static bool testConstructDefault() { @@ -144,7 +146,6 @@ static bool testConstructFromCStr() { std::cout << "testConstructFromCStr()\n"; return testFromCStr(cstr); - ; } static bool testAssignFromCStr() @@ -153,7 +154,6 @@ static bool testAssignFromCStr() cm::String str; str = cstr; return testFromCStr(str); - ; } static const std::string stdstr = "abc"; diff --git a/Tests/CMakeLib/testSystemTools.cxx b/Tests/CMakeLib/testSystemTools.cxx index 623ad28..96a4819 100644 --- a/Tests/CMakeLib/testSystemTools.cxx +++ b/Tests/CMakeLib/testSystemTools.cxx @@ -16,11 +16,13 @@ failed = 1 #define cmAssert(exp, m) \ - if ((exp)) { \ - cmPassed(m); \ - } else { \ - cmFailed(m); \ - } + do { \ + if ((exp)) { \ + cmPassed(m); \ + } else { \ + cmFailed(m); \ + } \ + } while (false) int testSystemTools(int /*unused*/, char* /*unused*/ []) { diff --git a/Tests/CMakeLib/testUVRAII.cxx b/Tests/CMakeLib/testUVRAII.cxx index e165ff7..1c1da76 100644 --- a/Tests/CMakeLib/testUVRAII.cxx +++ b/Tests/CMakeLib/testUVRAII.cxx @@ -1,9 +1,9 @@ #include "cmUVHandlePtr.h" -#include <algorithm> #include <chrono> #include <iostream> #include <thread> +#include <utility> #include "cm_uv.h" diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 803e5f0..86f4c56 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -436,6 +436,9 @@ if(BUILD_TESTING) ADD_TEST_MACRO(PolicyScope PolicyScope) ADD_TEST_MACRO(EmptyLibrary EmptyLibrary) ADD_TEST_MACRO(CompileDefinitions CompileDefinitions) + if(CMAKE_Fortran_COMPILER) + set(CompileOptions_BUILD_OPTIONS -DTEST_FORTRAN=1) + endif() ADD_TEST_MACRO(CompileOptions CompileOptions) ADD_TEST_MACRO(CompatibleInterface CompatibleInterface) ADD_TEST_MACRO(AliasTarget AliasTarget) @@ -597,7 +600,6 @@ if(BUILD_TESTING) else() if (CMAKE_CXX_COMPILER_ID MATCHES "PGI" OR CMAKE_CXX_COMPILER_ID MATCHES "PathScale" - OR CMAKE_SYSTEM_NAME MATCHES "IRIX64" OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") set(run_pic_test 0) else() @@ -1363,18 +1365,18 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Targets") if(Qt5Widgets_FOUND AND NOT Qt5Widgets_VERSION VERSION_LESS 5.1.0) - add_test(Qt4And5Automoc ${CMAKE_CTEST_COMMAND} + add_test(Qt4And5AutomocForward ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/Qt4And5Automoc" - "${CMake_BINARY_DIR}/Tests/Qt4And5Automoc" + "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocForward" ${build_generator_args} --build-project Qt4And5Automoc - --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4And5Automoc" + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocForward" --force-new-ctest-process --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -V ) - list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4And5Automoc") + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocForward") add_test(Qt4And5AutomocReverse ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/Qt4And5Automoc" @@ -1636,6 +1638,18 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdir") + add_test(NAME ExternalProjectSourceSubdirNotCMake + COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/ExternalProjectSourceSubdirNotCMake" + "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdirNotCMake" + ${build_generator_args} + --build-project ExternalProjectSourceSubdirNotCMake + --force-new-ctest-process + --build-options ${build_options} + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdirNotCMake") + add_test(ExternalProjectLocal ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/ExternalProjectLocal" @@ -2261,32 +2275,104 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release endif() if (CMake_TEST_GreenHillsMULTI) - macro(add_test_GhsMulti name primaryTarget bspName) - add_test(NAME GhsMulti.${name} COMMAND ${CMAKE_CTEST_COMMAND} - --build-and-test - "${CMake_SOURCE_DIR}/Tests/GhsMulti" - "${CMake_BINARY_DIR}/Tests/GhsMulti/${name}" - --build-generator "Green Hills MULTI" - --build-project ReturnNum - --build-config $<CONFIGURATION> - --build-options -DGHS_PRIMARY_TARGET=${primaryTarget} - -DGHS_BSP_NAME=${bspName} - ) - endmacro () - add_test_GhsMulti("arm_integrity_simarm" "arm_integrity.tgt" "simarm") - add_test_GhsMulti("arm64_integrity_simarm" "arm64_integrity.tgt" "simarm") - add_test(NAME GhsMulti.duplicate_source_filenames + macro(add_test_GhsMulti test_name test_dir bin_sub_dir build_opts) + separate_arguments(_ghs_build_opts UNIX_COMMAND ${build_opts}) + separate_arguments(_ghs_toolset_extra UNIX_COMMAND ${ghs_toolset_extra}) + if(${ARGC} GREATER 4) + set(_ghs_test_command --test-command ${ARGN}) + endif() + if(ghs_config_name STREQUAL "__default__") + set(_ghs_test_name "${test_name}") + else() + set(_ghs_test_name "${ghs_config_name}.${test_name}") + endif() + add_test(NAME GhsMulti.${_ghs_test_name} COMMAND ${CMAKE_CTEST_COMMAND} --build-and-test - "${CMake_SOURCE_DIR}/Tests/GhsMultiDuplicateSourceFilenames" - "${CMake_BINARY_DIR}/Tests/GhsMultiDuplicateSourceFilenames" + "${CMake_SOURCE_DIR}/Tests/GhsMulti/${test_dir}" + "${CMake_BINARY_DIR}/Tests/GhsMulti/${ghs_config_name}/${test_dir}/${bin_sub_dir}" --build-generator "Green Hills MULTI" - --build-project ReturnNum + --build-project test --build-config $<CONFIGURATION> - --build-options -DGHS_PRIMARY_TARGET=arm_integrity.tgt - -DGHS_BSP_NAME="simarm" + --build-options ${ghs_target_arch} ${ghs_toolset_name} ${ghs_toolset_root} ${ghs_target_platform} + ${ghs_os_root} ${ghs_os_dir} ${ghs_bsp_name} ${_ghs_build_opts} ${_ghs_toolset_extra} + ${_ghs_test_command} ) - endif () + unset(_ghs_build_opts) + unset(_ghs_toolset_extra) + unset(_ghs_test_command) + unset(_ghs_test_name) + endmacro() + macro(add_test_GhsMulti_rename_install test_name) + add_test_GhsMulti( ${test_name} GhsMultiRenameInstall ${test_name} + "-DCMAKE_INSTALL_PREFIX=. -DRUN_TEST=${test_name}" ${CMAKE_CMAKE_COMMAND} -P ./cmake_install.cmake) + endmacro() + #unset ghs config variables + unset(ghs_config_name) + unset(ghs_target_arch) + unset(ghs_toolset_root) + unset(ghs_toolset_name) + unset(ghs_os_root) + unset(ghs_os_dir) + unset(ghs_target_platform) + unset(ghs_bsp_name) + unset(ghs_toolset_extra) + if(NOT CMake_TEST_GreenHillsMULTI_config) + #if list of config settings not defined then just run once as default + set(CMake_TEST_GreenHillsMULTI_config "__default__") + endif() + foreach(ghs_file IN LISTS CMake_TEST_GreenHillsMULTI_config) + # source GHS tools config file + if(NOT ghs_file STREQUAL "__default__") + if(IS_ABSOLUTE ${ghs_file}) + include(${ghs_file}) + else() + include(${CMAKE_BINARY_DIR}/${ghs_file}) + endif() + endif() + if(NOT ghs_config_name) + set(ghs_config_name "__default__") + endif() + # test integrity build + if (NOT ghs_skip_integrity AND (NOT ghs_target_platform OR ghs_target_platform MATCHES "integrity")) + add_test_GhsMulti(integrityDDInt GhsMultiIntegrity/GhsMultiIntegrityDDInt "" "") + add_test_GhsMulti(integrityMonolith GhsMultiIntegrity/GhsMultiIntegrityMonolith "" "") + add_test_GhsMulti(integrityDD GhsMultiIntegrity/GhsMultiIntegrityDD "" "") + endif() + add_test_GhsMulti(duplicate_source_filenames GhsMultiDuplicateSourceFilenames "" "") + add_test_GhsMulti_rename_install(SINGLE_EXEC) + add_test_GhsMulti_rename_install(SINGLE_EXEC_RENAMED) + add_test_GhsMulti_rename_install(EXEC_AND_LIB) + add_test_GhsMulti(multiple_source_groups GhsMultiSrcGroups Default "") + add_test_GhsMulti(multiple_source_groups_folders GhsMultiSrcGroups PropFolders "-DTEST_PROP=ON") + add_test_GhsMulti(multiple_source_groups_all_folders GhsMultiSrcGroups AllFolders "-DGHS_NO_SOURCE_GROUP_FILE=ON") + add_test_GhsMulti(unsupported_targets GhsMultiUnsupportedTargets "" "") + add_test_GhsMulti(object_library GhsMultiObjectLibrary "" "") + add_test_GhsMulti(exclude GhsMultiExclude "" "" + ${CMAKE_CMAKE_COMMAND} -P ${CMake_SOURCE_DIR}/Tests/GhsMulti/GhsMultiExclude/verify.cmake) + add_test_GhsMulti(interface GhsMultiInterface "" "") + add_test_GhsMulti(transitive_link_test GhsMultiLinkTest TransitiveLink "-DRUN_TEST=NO_FLAGS") + add_test_GhsMulti(flags_link_test GhsMultiLinkTest FlagsCheck "-DRUN_TEST=CHECK_FLAGS") + add_test_GhsMulti(sub_link_test GhsMultiLinkTestSub "" "") + add_test_GhsMulti(multiple_projects GhsMultiMultipleProjects "" "" + ${CMAKE_CMAKE_COMMAND} -P ${CMake_SOURCE_DIR}/Tests/GhsMulti/GhsMultiMultipleProjects/verify.cmake) + add_test_GhsMulti(compiler_options_none GhsMultiCompilerOptions None "-DRUN_TEST=RELEASE_FLAGS -DRUN_TEST_BUILD_TYPE=\"\"") + add_test_GhsMulti(compiler_options_kernel GhsMultiCompilerOptions Kernel "-DRUN_TEST=KERNEL_FLAGS -DRUN_TEST_BUILD_TYPE=DEBUG") + add_test_GhsMulti(try_compile_copy GhsMultiCopyFile "" "") + add_test_GhsMulti(ghs_platform GhsMultiPlatform "" "") + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/GhsMulti/${ghs_config_name}") + #unset ghs config variables + unset(ghs_config_name) + unset(ghs_target_arch) + unset(ghs_toolset_root) + unset(ghs_toolset_name) + unset(ghs_os_root) + unset(ghs_os_dir) + unset(ghs_target_platform) + unset(ghs_bsp_name) + unset(ghs_toolset_extra) + endforeach() + endif() if(tegra AND NOT "${CMake_SOURCE_DIR};${CMake_BINARY_DIR}" MATCHES " ") macro(add_test_VSNsightTegra name generator) diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index 9157c76..f01e616 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -415,78 +415,6 @@ set(hp_f90_64_dirs "/usr/lib/hpux64;/opt/langtools/lib/hpux64") list(APPEND platforms hp_f90_64) #----------------------------------------------------------------------------- -# IRIX - -# cc -o32 dummy.c -v -set(irix64_cc_o32_text "/usr/lib/ld -elf -_SYSTYPE_SVR4 -require_dynamic_link _rld_new_interface -no_unresolved -Wx,-G 0 -o32 -mips2 -call_shared -g0 -KPIC -L/usr/lib/ -nocount /usr/lib/crt1.o -count dummy.o -nocount -lc /usr/lib/crtn.o") -set(irix64_cc_o32_libs "c") -set(irix64_cc_o32_dirs "/usr/lib") -list(APPEND platforms irix64_cc_o32) - -# cc -n32 dummy.c -v -set(irix64_cc_n32_text "/usr/lib32/cmplrs/ld32 -call_shared -no_unresolved -transitive_link -elf -_SYSTYPE_SVR4 -show -mips4 -n32 -L/usr/lib32/mips4/r10000 -L/usr/lib32/mips4 -L/usr/lib32 /usr/lib32/mips4/crt1.o dummy.o -dont_warn_unused -Bdynamic -lc /usr/lib32/mips4/crtn.o -warn_unused") -set(irix64_cc_n32_libs "c") -set(irix64_cc_n32_dirs "/usr/lib32/mips4/r10000;/usr/lib32/mips4;/usr/lib32") -list(APPEND platforms irix64_cc_n32) - -# cc -64 dummy.c -v -set(irix64_cc_64_text "/usr/lib32/cmplrs/ld64 -call_shared -no_unresolved -transitive_link -elf -_SYSTYPE_SVR4 -show -mips4 -64 -L/usr/lib64/mips4/r10000 -L/usr/lib64/mips4 -L/usr/lib64 /usr/lib64/mips4/crt1.o dummy.o -dont_warn_unused -Bdynamic -lc /usr/lib64/mips4/crtn.o -warn_unused") -set(irix64_cc_64_libs "c") -set(irix64_cc_64_dirs "/usr/lib64/mips4/r10000;/usr/lib64/mips4;/usr/lib64") -list(APPEND platforms irix64_cc_64) - -# CC -o32 dummy.cxx -v -set(irix64_CC_o32_text "/usr/lib/ld -elf -cxx -woff 134 -_SYSTYPE_SVR4 -require_dynamic_link _rld_new_interface -no_unresolved -Wx,-G 0 -o32 -mips2 -call_shared -g0 -KPIC -L/usr/lib/ -nocount /usr/lib/crt1.o /usr/lib/c++init.o -count dummy.o -nocount -dont_warn_unused -lC -warn_unused -lc /usr/lib/crtn.o") -set(irix64_CC_o32_libs "C;c") -set(irix64_CC_o32_dirs "/usr/lib") -list(APPEND platforms irix64_CC_o32) - -# CC -n32 dummy.cxx -v -set(irix64_CC_n32_text "/usr/lib32/cmplrs/ld32 -call_shared -init _main -fini _fini -no_unresolved -transitive_link -demangle -elf -_SYSTYPE_SVR4 -LANG:std -show -mips4 -n32 -L/usr/lib32/mips4/r10000 -L/usr/lib32/mips4 -L/usr/lib32 -cxx -woff 134 /usr/lib32/mips4/crt1.o /usr/lib32/c++init.o dummy.o -dont_warn_unused -lCsup -lC -lCio -Bdynamic -lc /usr/lib32/mips4/crtn.o -warn_unused") -set(irix64_CC_n32_libs "Csup;C;Cio;c") -set(irix64_CC_n32_dirs "/usr/lib32/mips4/r10000;/usr/lib32/mips4;/usr/lib32") -list(APPEND platforms irix64_CC_n32) - -# CC -64 dummy.cxx -v -set(irix64_CC_64_text "/usr/lib32/cmplrs/ld64 -call_shared -init _main -fini _fini -no_unresolved -transitive_link -demangle -elf -_SYSTYPE_SVR4 -LANG:std -show -mips4 -64 -L/usr/lib64/mips4/r10000 -L/usr/lib64/mips4 -L/usr/lib64 -cxx -woff 134 /usr/lib64/mips4/crt1.o /usr/lib64/c++init.o dummy.o -dont_warn_unused -lCsup -lC -lCio -Bdynamic -lc /usr/lib64/mips4/crtn.o -warn_unused") -set(irix64_CC_64_libs "Csup;C;Cio;c") -set(irix64_CC_64_dirs "/usr/lib64/mips4/r10000;/usr/lib64/mips4;/usr/lib64") -list(APPEND platforms irix64_CC_64) - -# f77 -o32 dummy.f -v -set(irix64_f77_o32_text "/usr/lib/ld -elf -_SYSTYPE_SVR4 -require_dynamic_link _rld_new_interface -no_unresolved -Wx,-G 0 -o32 -mips2 -call_shared -g0 -KPIC -L/usr/lib/ -nocount /usr/lib/crt1.o -count dummy.o -nocount -lftn -lm -lc /usr/lib/crtn.o") -set(irix64_f77_o32_libs "ftn;m;c") -set(irix64_f77_o32_dirs "/usr/lib") -list(APPEND platforms irix64_f77_o32) - -# f77 -n32 dummy.f -v -set(irix64_f77_n32_text "/usr/lib32/cmplrs/ld32 -call_shared -no_unresolved -transitive_link -elf -_SYSTYPE_SVR4 -show -mips4 -n32 -L/usr/lib32/mips4/r10000 -L/usr/lib32/mips4 -L/usr/lib32 /usr/lib32/mips4/crt1.o dummy.o -dont_warn_unused -lftn -lm -Bdynamic -lc /usr/lib32/mips4/crtn.o -warn_unused") -set(irix64_f77_n32_libs "ftn;m;c") -set(irix64_f77_n32_dirs "/usr/lib32/mips4/r10000;/usr/lib32/mips4;/usr/lib32") -list(APPEND platforms irix64_f77_n32) - -# f77 -64 dummy.f -v -set(irix64_f77_64_text "/usr/lib32/cmplrs/ld64 -call_shared -no_unresolved -transitive_link -elf -_SYSTYPE_SVR4 -show -mips4 -64 -L/usr/lib64/mips4/r10000 -L/usr/lib64/mips4 -L/usr/lib64 /usr/lib64/mips4/crt1.o dummy.o -dont_warn_unused -lftn -lm -Bdynamic -lc /usr/lib64/mips4/crtn.o -warn_unused") -set(irix64_f77_64_libs "ftn;m;c") -set(irix64_f77_64_dirs "/usr/lib64/mips4/r10000;/usr/lib64/mips4;/usr/lib64") -list(APPEND platforms irix64_f77_64) - -# f90 -o32 dummy.f -v -#f90 ERROR: specified abi -o32 not supported. - -# f90 -n32 dummy.f -v -set(irix64_f90_n32_text "/usr/lib32/cmplrs/ld32 -call_shared -no_unresolved -transitive_link -elf -_SYSTYPE_SVR4 -show -mips4 -n32 -L/usr/lib32/mips4/r10000 -L/usr/lib32/mips4 -L/usr/lib32 /usr/lib32/mips4/crt1.o dummy.o -dont_warn_unused -lfortran -lffio -lftn -lm -Bdynamic -lc /usr/lib32/mips4/crtn.o -warn_unused") -set(irix64_f90_n32_libs "fortran;ffio;ftn;m;c") -set(irix64_f90_n32_dirs "/usr/lib32/mips4/r10000;/usr/lib32/mips4;/usr/lib32") -list(APPEND platforms irix64_f90_n32) - -# f90 -64 dummy.f -v -set(irix64_f90_64_text "/usr/lib32/cmplrs/ld64 -call_shared -no_unresolved -transitive_link -elf -_SYSTYPE_SVR4 -show -mips4 -64 -L/usr/lib64/mips4/r10000 -L/usr/lib64/mips4 -L/usr/lib64 /usr/lib64/mips4/crt1.o dummy.o -dont_warn_unused -lfortran -lffio -lftn -lm -Bdynamic -lc /usr/lib64/mips4/crtn.o -warn_unused") -set(irix64_f90_64_libs "fortran;ffio;ftn;m;c") -set(irix64_f90_64_dirs "/usr/lib64/mips4/r10000;/usr/lib64/mips4;/usr/lib64") -list(APPEND platforms irix64_f90_64) - -#----------------------------------------------------------------------------- # Cygwin # gcc dummy.c -v diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt index c9f1710..15a993c 100644 --- a/Tests/CompileOptions/CMakeLists.txt +++ b/Tests/CompileOptions/CMakeLists.txt @@ -4,6 +4,10 @@ project(CompileOptions) add_library(testlib other.cpp) +if(TEST_FORTRAN) + enable_language(Fortran) +endif() + add_executable(CompileOptions main.cpp) macro(get_compiler_test_genex lst lang) @@ -13,6 +17,9 @@ endmacro() get_compiler_test_genex(c_tests C) get_compiler_test_genex(cxx_tests CXX) +if(TEST_FORTRAN) + get_compiler_test_genex(fortran_tests Fortran) +endif() set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS "-DTEST_DEFINE" @@ -21,6 +28,7 @@ set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS "SHELL:" # produces no options ${c_tests} ${cxx_tests} + ${fortran_tests} ) if(BORLAND OR WATCOM) # these compilers do not support separate -D flags @@ -54,3 +62,12 @@ target_compile_definitions(CompileOptions "EXPECTED_C_COMPILER_VERSION=\"${CMAKE_C_COMPILER_VERSION}\"" "EXPECTED_CXX_COMPILER_VERSION=\"${CMAKE_CXX_COMPILER_VERSION}\"" ) + +if(TEST_FORTRAN) + # Definitions for the C++ code to test the values + target_compile_definitions(CompileOptions + PRIVATE + "TEST_FORTRAN" + "EXPECTED_Fortran_COMPILER_VERSION=\"${CMAKE_Fortran_COMPILER_VERSION}\"" + ) +endif() diff --git a/Tests/CompileOptions/main.cpp b/Tests/CompileOptions/main.cpp index 1379940..d94a169 100644 --- a/Tests/CompileOptions/main.cpp +++ b/Tests/CompileOptions/main.cpp @@ -47,10 +47,17 @@ int main() #endif && strcmp(EXPECTED_C_COMPILER_VERSION, TEST_C_COMPILER_VERSION) == 0 && - strcmp(EXPECTED_CXX_COMPILER_VERSION, TEST_CXX_COMPILER_VERSION) == - 0 && - TEST_C_COMPILER_VERSION_EQUALITY == 1 && - TEST_CXX_COMPILER_VERSION_EQUALITY == 1) + strcmp(EXPECTED_CXX_COMPILER_VERSION, TEST_CXX_COMPILER_VERSION) == 0 +#ifdef TEST_FORTRAN + && strcmp(EXPECTED_Fortran_COMPILER_VERSION, + TEST_Fortran_COMPILER_VERSION) == 0 +#endif + && TEST_C_COMPILER_VERSION_EQUALITY == 1 && + TEST_CXX_COMPILER_VERSION_EQUALITY == 1 +#ifdef TEST_FORTRAN + && TEST_Fortran_COMPILER_VERSION_EQUALITY == 1 +#endif + ) ? 0 : 1; } diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 67fcc02..811fff3 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -332,7 +332,6 @@ if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") else() if (CMAKE_CXX_COMPILER_ID MATCHES "PGI" OR CMAKE_CXX_COMPILER_ID MATCHES "PathScale" - OR CMAKE_SYSTEM_NAME MATCHES "IRIX64" OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") set(run_pic_test 0) else() diff --git a/Tests/ExternalProjectSourceSubdirNotCMake/CMakeLists.txt b/Tests/ExternalProjectSourceSubdirNotCMake/CMakeLists.txt new file mode 100644 index 0000000..f64df1a --- /dev/null +++ b/Tests/ExternalProjectSourceSubdirNotCMake/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.6) +project(ExternalProjectSourceSubdirNotCMake NONE) +include(ExternalProject) + +find_program(MAKE_EXECUTABLE + NAMES gmake make) + +if (NOT MAKE_EXECUTABLE) + message("No `make` executable found; skipping") + return () +endif () + +ExternalProject_Add(Example + SOURCE_SUBDIR subdir + BUILD_IN_SOURCE 1 + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Example + CONFIGURE_COMMAND "" + BUILD_COMMAND "${MAKE_EXECUTABLE}" + INSTALL_COMMAND "" + ) diff --git a/Tests/ExternalProjectSourceSubdirNotCMake/Example/subdir/Makefile b/Tests/ExternalProjectSourceSubdirNotCMake/Example/subdir/Makefile new file mode 100644 index 0000000..cab3b8f --- /dev/null +++ b/Tests/ExternalProjectSourceSubdirNotCMake/Example/subdir/Makefile @@ -0,0 +1,2 @@ +all: + echo "complete" diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt index 6a80df5..f8b36c5 100644 --- a/Tests/FindPackageTest/CMakeLists.txt +++ b/Tests/FindPackageTest/CMakeLists.txt @@ -188,6 +188,37 @@ find_package(ArchC 3.1 EXACT NAMES zot) find_package(ArchD 4.0 EXACT NAMES zot) unset(CMAKE_LIBRARY_ARCHITECTURE) +# Test find_package() with CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS enabled +if(UNIX) + # Create ./symlink pointing back here. + execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink + . "${CMAKE_CURRENT_SOURCE_DIR}/symlink") + # Make find_package search through the symlink + set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/symlink") + + # First, test the default behavior where symlinks are preserved. + set(SetFoundResolved_DIR "") + find_package(SetFoundResolved) + # The result must preserve the /symlink/ path. + set(SetFoundResolved_EXPECTED "${CMAKE_CURRENT_SOURCE_DIR}/symlink/cmake") + if(NOT "${SetFoundResolved_DIR}" STREQUAL "${SetFoundResolved_EXPECTED}") + message(SEND_ERROR "SetFoundResolved_DIR set by find_package() is set to \"${SetFoundResolved_DIR}\" (expected \"${SetFoundResolved_EXPECTED}\")") + endif() + + # Resolve symlinks when finding the package. + set(CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS TRUE) + set(SetFoundResolved_DIR "") + find_package(SetFoundResolved) + # ./symlink points back here so it should be gone when resolved. + set(SetFoundResolved_EXPECTED "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + if(NOT "${SetFoundResolved_DIR}" STREQUAL "${SetFoundResolved_EXPECTED}") + message(SEND_ERROR "SetFoundResolved_DIR set by find_package() is set to \"${SetFoundResolved_DIR}\" (expected \"${SetFoundResolved_EXPECTED}\")") + endif() + # Cleanup. + unset(CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS) + file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/symlink") +endif() + # Test <PackageName>_DIR environment variable. # We erase the main prefix path to ensure the env var is used. set(CMAKE_PREFIX_PATH) diff --git a/Tests/FindPackageTest/cmake/SetFoundResolvedConfig.cmake b/Tests/FindPackageTest/cmake/SetFoundResolvedConfig.cmake new file mode 100644 index 0000000..b2cf87c --- /dev/null +++ b/Tests/FindPackageTest/cmake/SetFoundResolvedConfig.cmake @@ -0,0 +1 @@ +set(SetFoundResolved_DIR "${CMAKE_CURRENT_LIST_DIR}") diff --git a/Tests/FortranOnly/CMakeLists.txt b/Tests/FortranOnly/CMakeLists.txt index 59e6d59..77f6041 100644 --- a/Tests/FortranOnly/CMakeLists.txt +++ b/Tests/FortranOnly/CMakeLists.txt @@ -70,8 +70,15 @@ if(NOT CMAKE_Fortran_COMPILER_ID STREQUAL XL) include(CheckFortranCompilerFlag) CHECK_Fortran_COMPILER_FLAG(-_this_is_not_a_flag_ Fortran_BOGUS_FLAG) if (Fortran_BOGUS_FLAG) - message (SEND_ERROR "CHECK_Fortran_COMPILER_FLAG() succeeded, but should have failed") - endif () + message(SEND_ERROR "CHECK_Fortran_COMPILER_FLAG() succeeded, but should have failed") + endif() + + unset(Fortran_RUN_FLAG CACHE) + include(CheckFortranSourceRuns) + check_fortran_source_runs("program a; end program" Fortran_RUN_FLAG SRC_EXT F90) + if(NOT Fortran_RUN_FLAG) + message(SEND_ERROR "CHECK_Fortran_SOURCE_RUNS() failed") + endif() endif() # Test generation of preprocessed sources. diff --git a/Tests/GhsMulti/CMakeLists.txt b/Tests/GhsMulti/CMakeLists.txt deleted file mode 100644 index 6e15ba9..0000000 --- a/Tests/GhsMulti/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(ReturnNum) - -add_subdirectory(ReturnNum) diff --git a/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt b/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt new file mode 100644 index 0000000..4a3f5c2 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt @@ -0,0 +1,92 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +message("Copy project") +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt.in + ${CMAKE_CURRENT_BINARY_DIR}/src/CMakeLists.txt COPYONLY) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test.c + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/src +) + +message("Building project") +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +try_compile(RESULT + ${CMAKE_CURRENT_BINARY_DIR}/build + ${CMAKE_CURRENT_BINARY_DIR}/src + test + CMAKE_FLAGS + -DRUN_TEST=${RUN_TEST} + -DCMAKE_BUILD_TYPE=${RUN_TEST_BUILD_TYPE} + OUTPUT_VARIABLE OUTPUT) + +message("Output from build:\n${OUTPUT}") +if (RUN_TEST STREQUAL "RELEASE_FLAGS") + find_file (fileName test_none.gpj + ${CMAKE_CURRENT_BINARY_DIR}/build + ${CMAKE_CURRENT_BINARY_DIR}/build/test_none + ) + message("Parsing project file: ${fileName}") + file(STRINGS ${fileName} fileText) + set(opt "-unexpected_release_option") + string(FIND "${fileText}" "${opt}" opt_found) + if ( NOT opt_found EQUAL -1 ) + message(SEND_ERROR "Release option found: ${opt}") + endif() +else() + unset(fileName CACHE) + find_file (fileName K1.gpj + ${CMAKE_CURRENT_BINARY_DIR}/build + ${CMAKE_CURRENT_BINARY_DIR}/build/K1 + ) + message("Parsing project file: ${fileName}") + file(STRINGS ${fileName} fileText) + set(opt "-required-debug-option") + string(FIND "${fileText}" "${opt}" opt_found) + if ( opt_found EQUAL -1 ) + message(SEND_ERROR "Missing debug option: ${opt}") + endif() + + unset(fileName CACHE) + find_file (fileName K2.gpj + ${CMAKE_CURRENT_BINARY_DIR}/build + ${CMAKE_CURRENT_BINARY_DIR}/build/K2 + ) + message("Parsing project file: ${fileName}") + file(STRINGS ${fileName} fileText) + set(opt "-required-debug-option") + string(FIND "${fileText}" "${opt}" opt_found) + if ( opt_found EQUAL -1 ) + message(SEND_ERROR "Missing debug option: ${opt}") + endif() + + unset(fileName CACHE) + find_file (fileName K3.gpj + ${CMAKE_CURRENT_BINARY_DIR}/build + ${CMAKE_CURRENT_BINARY_DIR}/build/K3 + ) + message("Parsing project file: ${fileName}") + file(STRINGS ${fileName} fileText) + set(opt "-required-debug-option") + string(FIND "${fileText}" "${opt}" opt_found) + if ( opt_found EQUAL -1 ) + message(SEND_ERROR "Missing debug option: ${opt}") + endif() + + unset(fileName CACHE) + find_file (fileName K4.gpj + ${CMAKE_CURRENT_BINARY_DIR}/build + ${CMAKE_CURRENT_BINARY_DIR}/build/K4 + ) + message("Parsing project file: ${fileName}") + file(STRINGS ${fileName} fileText) + set(opt "-required-debug-option") + string(FIND "${fileText}" "${opt}" opt_found) + if ( opt_found EQUAL -1 ) + message(SEND_ERROR "Missing debug option: ${opt}") + endif() +endif() diff --git a/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt.in b/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt.in new file mode 100644 index 0000000..fc24d90 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt.in @@ -0,0 +1,32 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +if(CMAKE_C_COMPILER_ID STREQUAL "GHS") + add_link_options("-non_shared") +endif() + +if(RUN_TEST STREQUAL "RELEASE_FLAGS") + #RELEASE flags used when CMAKE_BUILD_TYPE is undefined + string(APPEND CMAKE_C_FLAGS_RELEASE " -unexpected_release_option") + add_executable(test_none test.c) +endif() + +if(RUN_TEST STREQUAL "KERNEL_FLAGS") + #DEBUG flag missing when -kernel is added as a compile option + string(APPEND CMAKE_C_FLAGS_DEBUG " -required-debug-option") + + add_executable(K1 test.c) + + add_executable(K2 test.c) + target_compile_options(K2 PRIVATE -kernel) + + add_executable(K3 test.c) + target_compile_options(K3 PRIVATE -kernel=fast) + + add_executable(K4 test.c) + target_link_options(K4 PRIVATE -kernel) +endif() diff --git a/Tests/GhsMulti/GhsMultiCompilerOptions/test.c b/Tests/GhsMulti/GhsMultiCompilerOptions/test.c new file mode 100644 index 0000000..95f2e8e --- /dev/null +++ b/Tests/GhsMulti/GhsMultiCompilerOptions/test.c @@ -0,0 +1,4 @@ +int main(void) +{ + return -1; +} diff --git a/Tests/GhsMulti/GhsMultiCopyFile/CMakeLists.txt b/Tests/GhsMulti/GhsMultiCopyFile/CMakeLists.txt new file mode 100644 index 0000000..d6d007d --- /dev/null +++ b/Tests/GhsMulti/GhsMultiCopyFile/CMakeLists.txt @@ -0,0 +1,30 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +try_compile(RESULT + ${CMAKE_CURRENT_BINARY_DIR}/build + ${CMAKE_CURRENT_SOURCE_DIR}/test.c + OUTPUT_VARIABLE OUTPUT + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/test_library" +) + +message(STATUS "Output from build:\n${OUTPUT}") + +if(NOT RESULT) + message(SEND_ERROR "try_compile() failed") +endif() + +if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/test_library") + if (IS_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test_library") + message(SEND_ERROR "library is folder !") + else() + message(STATUS "library seems okay") + endif() +else() + message(SEND_ERROR "library is not found !") +endif() diff --git a/Tests/GhsMulti/GhsMultiCopyFile/test.c b/Tests/GhsMulti/GhsMultiCopyFile/test.c new file mode 100644 index 0000000..5c657b5 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiCopyFile/test.c @@ -0,0 +1,4 @@ +int lib(int x) +{ + return -x; +} diff --git a/Tests/GhsMultiDuplicateSourceFilenames/CMakeLists.txt b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/CMakeLists.txt index 82a014b..a1f152f 100644 --- a/Tests/GhsMultiDuplicateSourceFilenames/CMakeLists.txt +++ b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/CMakeLists.txt @@ -1,15 +1,17 @@ cmake_minimum_required(VERSION 3.5) -project(demo C) +project(test C) add_library(libdemo test.c + testCase.c subfolder_test.c subfolder_test_0.c "subfolder/test.c" + subfolder/testcase.c ) add_executable(demo main.c) target_link_libraries(demo libdemo) -if(GHSMULTI) - target_compile_options(demo PUBLIC "-non_shared") +if(CMAKE_C_COMPILER_ID STREQUAL "GHS") + target_link_options(demo PRIVATE "-non_shared") endif() diff --git a/Tests/GhsMultiDuplicateSourceFilenames/main.c b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/main.c index d5b7914..d4ef7bb 100644 --- a/Tests/GhsMultiDuplicateSourceFilenames/main.c +++ b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/main.c @@ -2,6 +2,8 @@ int test_a(void); int test_b(void); int test_c(void); int test_d(void); +int test_e(void); +int test_f(void); int main(int argc, char* argv[]) { @@ -9,5 +11,7 @@ int main(int argc, char* argv[]) test_b(); test_c(); test_d(); + test_e(); + test_f(); return 0; } diff --git a/Tests/GhsMultiDuplicateSourceFilenames/subfolder/test.c b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/subfolder/test.c index e1e1759..5d857dd 100644 --- a/Tests/GhsMultiDuplicateSourceFilenames/subfolder/test.c +++ b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/subfolder/test.c @@ -1,4 +1,3 @@ - int test_b() { return 2; diff --git a/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/subfolder/testcase.c b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/subfolder/testcase.c new file mode 100644 index 0000000..66ee6f3 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/subfolder/testcase.c @@ -0,0 +1,4 @@ +int test_f() +{ + return 1; +} diff --git a/Tests/GhsMultiDuplicateSourceFilenames/subfolder_test.c b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/subfolder_test.c index c552e6a..83589ba 100644 --- a/Tests/GhsMultiDuplicateSourceFilenames/subfolder_test.c +++ b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/subfolder_test.c @@ -1,4 +1,3 @@ - int test_c() { return 1; diff --git a/Tests/GhsMultiDuplicateSourceFilenames/subfolder_test_0.c b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/subfolder_test_0.c index 170b33d..82f9a52 100644 --- a/Tests/GhsMultiDuplicateSourceFilenames/subfolder_test_0.c +++ b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/subfolder_test_0.c @@ -1,4 +1,3 @@ - int test_d() { return 1; diff --git a/Tests/GhsMultiDuplicateSourceFilenames/test.c b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/test.c index 5ffcbdf..feba80e 100644 --- a/Tests/GhsMultiDuplicateSourceFilenames/test.c +++ b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/test.c @@ -1,4 +1,3 @@ - int test_a() { return 1; diff --git a/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/testCase.c b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/testCase.c new file mode 100644 index 0000000..943c19d --- /dev/null +++ b/Tests/GhsMulti/GhsMultiDuplicateSourceFilenames/testCase.c @@ -0,0 +1,4 @@ +int test_e() +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiExclude/CMakeLists.txt b/Tests/GhsMulti/GhsMultiExclude/CMakeLists.txt new file mode 100644 index 0000000..0448cf2 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiExclude/CMakeLists.txt @@ -0,0 +1,17 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +if(CMAKE_C_COMPILER_ID STREQUAL "GHS") + add_link_options("-non_shared") +endif() + +add_library(lib1 lib1.c) +set_target_properties( lib1 PROPERTIES EXCLUDE_FROM_ALL yes ) + +add_library(lib2 EXCLUDE_FROM_ALL lib1.c) + +add_executable(exe1 exe1.c) diff --git a/Tests/GhsMulti/GhsMultiExclude/exe1.c b/Tests/GhsMulti/GhsMultiExclude/exe1.c new file mode 100644 index 0000000..8488f4e --- /dev/null +++ b/Tests/GhsMulti/GhsMultiExclude/exe1.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/GhsMulti/GhsMultiExclude/lib1.c b/Tests/GhsMulti/GhsMultiExclude/lib1.c new file mode 100644 index 0000000..b35e9cc --- /dev/null +++ b/Tests/GhsMulti/GhsMultiExclude/lib1.c @@ -0,0 +1,4 @@ +int func(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiExclude/verify.cmake b/Tests/GhsMulti/GhsMultiExclude/verify.cmake new file mode 100644 index 0000000..0467b5a --- /dev/null +++ b/Tests/GhsMulti/GhsMultiExclude/verify.cmake @@ -0,0 +1,54 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#test project was generated +unset(fileName CACHE) +find_file (fileName lib1.gpj + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/lib1 + ) + +if (fileName) + message("Found target lib1: ${fileName}") +else() + message(SEND_ERROR "Could not find target lib1: ${fileName}") +endif() + +#test project was built +unset(fileName CACHE) +find_file (fileName lib1.a + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/lib1 + ) + +if (fileName) + message(SEND_ERROR "Found target lib1: ${fileName}") +else() + message("Could not find target lib1: ${fileName}") +endif() + +#test project was generated +unset(fileName CACHE) +find_file (fileName lib2.gpj + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/lib2 + ) + +if (fileName) + message("Found target lib2 ${fileName}") +else() + message(SEND_ERROR "Could not find target lib2: ${fileName}") +endif() + +#test project was built +unset(fileName CACHE) +find_file (fileName lib2.a + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/lib2 + ) + +if (fileName) + message(SEND_ERROR "Found target lib2: ${fileName}") +else() + message("Could not find target lib2: ${fileName}") +endif() diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDD/CMakeLists.txt b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDD/CMakeLists.txt new file mode 100644 index 0000000..d4cbf04 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDD/CMakeLists.txt @@ -0,0 +1,19 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +add_link_options("-non_shared") + +# create virtual AS +add_executable(vas exe.c) +target_link_libraries(vas lib) +add_library(lib func.c) + +# create dynamic download INTEGRITY application +add_executable(dynamic) +set_target_properties(dynamic PROPERTIES ghs_integrity_app ON) +target_compile_options(dynamic PRIVATE -dynamic) +add_dependencies(dynamic vas) diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDD/exe.c b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDD/exe.c new file mode 100644 index 0000000..29ad70a --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDD/exe.c @@ -0,0 +1,5 @@ +extern int func(void); +int main(void) +{ + return func(); +} diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDD/func.c b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDD/func.c new file mode 100644 index 0000000..b35e9cc --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDD/func.c @@ -0,0 +1,4 @@ +int func(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/ReturnNum/App/CMakeLists.txt b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/App/CMakeLists.txt index 2adbd4e..e431217 100644 --- a/Tests/GhsMulti/ReturnNum/App/CMakeLists.txt +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/App/CMakeLists.txt @@ -1,4 +1,4 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../Lib) add_executable(App Main.c) +target_include_directories(App PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../Lib) target_link_libraries(App Lib) target_compile_options(App PUBLIC "-non_shared") diff --git a/Tests/GhsMulti/ReturnNum/App/Main.c b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/App/Main.c index db8d658..db8d658 100644 --- a/Tests/GhsMulti/ReturnNum/App/Main.c +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/App/Main.c diff --git a/Tests/GhsMulti/ReturnNum/CMakeLists.txt b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/CMakeLists.txt index 7bcc5f9..92254e6 100644 --- a/Tests/GhsMulti/ReturnNum/CMakeLists.txt +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/CMakeLists.txt @@ -1,3 +1,6 @@ +cmake_minimum_required(VERSION 3.1) +project(test) + add_subdirectory(App) add_subdirectory(Int) add_subdirectory(Lib) diff --git a/Tests/GhsMulti/ReturnNum/Int/AppDD.int b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Int/AppDD.int index 9e22b5e..5035d58 100644 --- a/Tests/GhsMulti/ReturnNum/Int/AppDD.int +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Int/AppDD.int @@ -7,6 +7,6 @@ Kernel EndKernel AddressSpace App - Filename "App/App.as" + Filename "App/App" Language C EndAddressSpace diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Int/CMakeLists.txt b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Int/CMakeLists.txt new file mode 100644 index 0000000..d173c01 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Int/CMakeLists.txt @@ -0,0 +1 @@ +add_executable(AppDD AppDD.int) diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Lib/CMakeLists.txt b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Lib/CMakeLists.txt new file mode 100644 index 0000000..00e0f59 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Lib/CMakeLists.txt @@ -0,0 +1 @@ +add_library(Lib HelperFun.c HelperFun.h) diff --git a/Tests/GhsMulti/ReturnNum/Lib/HelperFun.c b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Lib/HelperFun.c index 61922bb..61922bb 100644 --- a/Tests/GhsMulti/ReturnNum/Lib/HelperFun.c +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Lib/HelperFun.c diff --git a/Tests/GhsMulti/ReturnNum/Lib/HelperFun.h b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Lib/HelperFun.h index 00971b0..00971b0 100644 --- a/Tests/GhsMulti/ReturnNum/Lib/HelperFun.h +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityDDInt/Lib/HelperFun.h diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/CMakeLists.txt b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/CMakeLists.txt new file mode 100644 index 0000000..c5db155 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/CMakeLists.txt @@ -0,0 +1,20 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +add_link_options("-non_shared") + +project(test C) + +# create virtual AS +add_executable(vas exe.c) +target_link_libraries(vas lib) +add_library(lib func.c) + +# create kernel +add_executable(kernel kernel.c) +target_link_options(kernel PRIVATE -kernel) + +# create monolith INTEGRITY application +add_executable(monolith test.int) diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/exe.c b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/exe.c new file mode 100644 index 0000000..29ad70a --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/exe.c @@ -0,0 +1,5 @@ +extern int func(void); +int main(void) +{ + return func(); +} diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/func.c b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/func.c new file mode 100644 index 0000000..c302418 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/func.c @@ -0,0 +1,5 @@ + +int func(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/kernel.c b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/kernel.c new file mode 100644 index 0000000..d1bce33 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/kernel.c @@ -0,0 +1,15 @@ +#include "INTEGRITY.h" +#include "boottable.h" + +void main() +{ + Exit(0); +} + +/* This global table will be filled in during the Integrate phase with */ +/* information about the AddressSpaces, Tasks, and Objects that are to be */ +/* created. If you do not plan to use Integrate, you may omit this file from + */ +/* the kernel, and the boot table code will then not be included. */ + +GlobalTable TheGlobalTable = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; diff --git a/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/test.int b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/test.int new file mode 100644 index 0000000..361793a --- /dev/null +++ b/Tests/GhsMulti/GhsMultiIntegrity/GhsMultiIntegrityMonolith/test.int @@ -0,0 +1,8 @@ +Kernel + Filename kernel +EndKernel + +AddressSpace App + Filename vas + Language C +EndAddressSpace diff --git a/Tests/GhsMulti/GhsMultiInterface/CMakeLists.txt b/Tests/GhsMulti/GhsMultiInterface/CMakeLists.txt new file mode 100644 index 0000000..fa0dce0 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiInterface/CMakeLists.txt @@ -0,0 +1,8 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +add_library(iface INTERFACE) diff --git a/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt b/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt new file mode 100644 index 0000000..da80b51 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt @@ -0,0 +1,92 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +message("Copy project") +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt.in + ${CMAKE_CURRENT_BINARY_DIR}/link_src/CMakeLists.txt COPYONLY) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/exe1.c + ${CMAKE_CURRENT_SOURCE_DIR}/exe1.h + ${CMAKE_CURRENT_SOURCE_DIR}/func2.c + ${CMAKE_CURRENT_SOURCE_DIR}/func3.c + ${CMAKE_CURRENT_SOURCE_DIR}/func4.c + ${CMAKE_CURRENT_SOURCE_DIR}/func5.c + ${CMAKE_CURRENT_SOURCE_DIR}/func6.c + ${CMAKE_CURRENT_SOURCE_DIR}/func7.c + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/link_src +) + +message("Building project") +try_compile(RESULT + ${CMAKE_CURRENT_BINARY_DIR}/link_build + ${CMAKE_CURRENT_BINARY_DIR}/link_src + test + CMAKE_FLAGS + -DRUN_TEST=${RUN_TEST} + -DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS} + OUTPUT_VARIABLE OUTPUT) + +message("Output from build:\n${OUTPUT}") +if (RUN_TEST STREQUAL "NO_FLAGS") + if(NOT RESULT) + message(SEND_ERROR "Could not build test project (1)!") + endif() +else() + unset(fileName CACHE) + find_file(fileName exe1.gpj + ${CMAKE_CURRENT_BINARY_DIR}/link_build + ${CMAKE_CURRENT_BINARY_DIR}/link_build/exe1 + ) + message("Parsing project file: ${fileName}") + file(STRINGS ${fileName} fileText) + set(expected_flags + -add-link-options1 -add-link-options2 + link_directories_used1 link_directories_used2 "c:/absolute" + link_libraries_used1 link_libraries_used2 + -lcsl1 csl2 + -clinkexe1 -clinkexe2 + -special-lib2-public-link) + foreach(opt IN LISTS expected_flags) + string(FIND "${fileText}" "${opt}" opt_found) + if ( opt_found EQUAL -1 ) + message(SEND_ERROR "Could not find: ${opt}") + endif() + endforeach() + + unset(fileName CACHE) + find_file (fileName lib1.gpj + ${CMAKE_CURRENT_BINARY_DIR}/link_build + ${CMAKE_CURRENT_BINARY_DIR}/link_build/lib1 + ) + message("Parsing project file: ${fileName}") + file(STRINGS ${fileName} fileText) + set(expected_flags + -clinkexeA1 -clinkexeA2 + -static-lib-flags1 -static-lib-flags2) + foreach(opt IN LISTS expected_flags) + string(FIND "${fileText}" "${opt}" opt_found) + if (opt_found EQUAL -1) + message(SEND_ERROR "Could not find: ${opt}") + endif() + endforeach() + + unset(fileName CACHE) + find_file (fileName lib2.gpj + ${CMAKE_CURRENT_BINARY_DIR}/link_build + ${CMAKE_CURRENT_BINARY_DIR}/link_build/lib2 + ) + message("Parsing project file: ${fileName}") + file(STRINGS ${fileName} fileText) + set(expected_flags + -clinkexeA1 -clinkexeA2) + foreach(opt IN LISTS expected_flags) + string(FIND "${fileText}" "${opt}" opt_found) + if ( opt_found EQUAL -1 ) + message(SEND_ERROR "Could not find: ${opt}") + endif() + endforeach() +endif() diff --git a/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt.in b/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt.in new file mode 100644 index 0000000..58c2115 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt.in @@ -0,0 +1,43 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +if(CMAKE_C_COMPILER_ID STREQUAL "GHS") + add_link_options("-non_shared") +endif() + +if(RUN_TEST STREQUAL "CHECK_FLAGS") + add_link_options(-add-link-options1 -add-link-options2) + link_directories(link_directories_used1 link_directories_used2 "c:/absolute") + link_libraries(link_libraries_used1 link_libraries_used2 ) + set( CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} -lcsl1 csl2" ) + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -clinkexe1 -clinkexe2") +endif() + +add_executable(exe1 exe1.c) +target_link_libraries(exe1 lib1) + +if(RUN_TEST STREQUAL "CHECK_FLAGS") + set_property(TARGET exe1 APPEND_STRING PROPERTY LINK_FLAGS "--link-flag-prop1 --link-flag-prop2") + set_property(TARGET exe1 APPEND PROPERTY LINK_OPTIONS --link-opt-prop1 --link-opt-prop2) +endif() + +if(RUN_TEST STREQUAL "CHECK_FLAGS") + set(CMAKE_STATIC_LINKER_FLAGS ${CMAKE_STATIC_LINKER_FLAGS} "-clinkexeA1 -clinkexeA2") +endif() + +add_library(lib1 STATIC func2.c func3.c func4.c) +target_link_libraries(lib1 lib2) + +if(RUN_TEST STREQUAL "CHECK_FLAGS") + set_property(TARGET lib1 APPEND_STRING PROPERTY STATIC_LIBRARY_FLAGS "-static-lib-flags1 -static-lib-flags2") +endif() + +add_library(lib2 STATIC func5.c func6.c func7.c) + +if(RUN_TEST STREQUAL "CHECK_FLAGS") + target_link_options(lib2 PUBLIC -special-lib2-public-link) +endif() diff --git a/Tests/GhsMulti/GhsMultiLinkTest/exe1.c b/Tests/GhsMulti/GhsMultiLinkTest/exe1.c new file mode 100644 index 0000000..f21c126 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/exe1.c @@ -0,0 +1,6 @@ +#include "exe1.h" + +int main(void) +{ + return func2a() + func3a() + func4a() + func5a() + func6a() + func7a(); +} diff --git a/Tests/GhsMulti/GhsMultiLinkTest/exe1.h b/Tests/GhsMulti/GhsMultiLinkTest/exe1.h new file mode 100644 index 0000000..e2b1725 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/exe1.h @@ -0,0 +1,6 @@ +extern int func2a(void); +extern int func3a(void); +extern int func4a(void); +extern int func5a(void); +extern int func6a(void); +extern int func7a(void); diff --git a/Tests/GhsMulti/GhsMultiLinkTest/func2.c b/Tests/GhsMulti/GhsMultiLinkTest/func2.c new file mode 100644 index 0000000..8f66fba --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/func2.c @@ -0,0 +1,4 @@ +int func2a(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTest/func3.c b/Tests/GhsMulti/GhsMultiLinkTest/func3.c new file mode 100644 index 0000000..57c7a6f --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/func3.c @@ -0,0 +1,4 @@ +int func3a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTest/func4.c b/Tests/GhsMulti/GhsMultiLinkTest/func4.c new file mode 100644 index 0000000..109fd7b --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/func4.c @@ -0,0 +1,4 @@ +int func4a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTest/func5.c b/Tests/GhsMulti/GhsMultiLinkTest/func5.c new file mode 100644 index 0000000..f28a705 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/func5.c @@ -0,0 +1,4 @@ +int func5a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTest/func6.c b/Tests/GhsMulti/GhsMultiLinkTest/func6.c new file mode 100644 index 0000000..bf77406 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/func6.c @@ -0,0 +1,4 @@ +int func6a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTest/func7.c b/Tests/GhsMulti/GhsMultiLinkTest/func7.c new file mode 100644 index 0000000..6a4a9a1 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTest/func7.c @@ -0,0 +1,4 @@ +int func7a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/CMakeLists.txt b/Tests/GhsMulti/GhsMultiLinkTestSub/CMakeLists.txt new file mode 100644 index 0000000..145dac0 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/CMakeLists.txt @@ -0,0 +1,9 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +add_subdirectory(sub_exe) +add_subdirectory(sub_lib) diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_exe/CMakeLists.txt b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_exe/CMakeLists.txt new file mode 100644 index 0000000..f49e33d --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_exe/CMakeLists.txt @@ -0,0 +1,12 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +add_executable(exe1 exe1.c) +target_link_libraries(exe1 lib1) +if(CMAKE_C_COMPILER_ID STREQUAL "GHS") + target_link_options(exe1 PRIVATE "-non_shared") +endif() diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_exe/exe1.c b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_exe/exe1.c new file mode 100644 index 0000000..f21c126 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_exe/exe1.c @@ -0,0 +1,6 @@ +#include "exe1.h" + +int main(void) +{ + return func2a() + func3a() + func4a() + func5a() + func6a() + func7a(); +} diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_exe/exe1.h b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_exe/exe1.h new file mode 100644 index 0000000..e2b1725 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_exe/exe1.h @@ -0,0 +1,6 @@ +extern int func2a(void); +extern int func3a(void); +extern int func4a(void); +extern int func5a(void); +extern int func6a(void); +extern int func7a(void); diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/CMakeLists.txt b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/CMakeLists.txt new file mode 100644 index 0000000..9039730 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/CMakeLists.txt @@ -0,0 +1,7 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +add_library(lib1 STATIC func2.c func3.c func4.c) +target_link_libraries(lib1 lib2) + +add_library(lib2 STATIC func5.c func6.c func7.c) diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func2.c b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func2.c new file mode 100644 index 0000000..8f66fba --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func2.c @@ -0,0 +1,4 @@ +int func2a(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func3.c b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func3.c new file mode 100644 index 0000000..57c7a6f --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func3.c @@ -0,0 +1,4 @@ +int func3a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func4.c b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func4.c new file mode 100644 index 0000000..109fd7b --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func4.c @@ -0,0 +1,4 @@ +int func4a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func5.c b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func5.c new file mode 100644 index 0000000..f28a705 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func5.c @@ -0,0 +1,4 @@ +int func5a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func6.c b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func6.c new file mode 100644 index 0000000..bf77406 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func6.c @@ -0,0 +1,4 @@ +int func6a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func7.c b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func7.c new file mode 100644 index 0000000..6a4a9a1 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiLinkTestSub/sub_lib/func7.c @@ -0,0 +1,4 @@ +int func7a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/CMakeLists.txt b/Tests/GhsMulti/GhsMultiMultipleProjects/CMakeLists.txt new file mode 100644 index 0000000..9e077a9 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/CMakeLists.txt @@ -0,0 +1,17 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +if(CMAKE_C_COMPILER_ID STREQUAL "GHS") + add_link_options("-non_shared") +endif() + +add_library(lib1 lib1.c) +add_executable(exe1 exe1.c) +target_link_libraries(exe1 lib1) + +add_subdirectory(sub) +add_subdirectory(sub2 examples EXCLUDE_FROM_ALL) diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/exe1.c b/Tests/GhsMulti/GhsMultiMultipleProjects/exe1.c new file mode 100644 index 0000000..b9cdd61 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/exe1.c @@ -0,0 +1,5 @@ +extern int lib1_func(void); +int main(void) +{ + return lib1_func(); +} diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/lib1.c b/Tests/GhsMulti/GhsMultiMultipleProjects/lib1.c new file mode 100644 index 0000000..5100945 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/lib1.c @@ -0,0 +1,4 @@ +int lib1_func(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/sub/CMakeLists.txt b/Tests/GhsMulti/GhsMultiMultipleProjects/sub/CMakeLists.txt new file mode 100644 index 0000000..0d83bc3 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/sub/CMakeLists.txt @@ -0,0 +1,10 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test2 C) + +add_library(lib2 lib2.c) +add_executable(exe2 exe2.c) +target_link_libraries(exe2 lib1 lib2) diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/sub/exe2.c b/Tests/GhsMulti/GhsMultiMultipleProjects/sub/exe2.c new file mode 100644 index 0000000..9238cf3 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/sub/exe2.c @@ -0,0 +1,6 @@ +extern int func(void); +extern int lib1_func(void); +int main(void) +{ + return func() + lib1_func(); +} diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/sub/lib2.c b/Tests/GhsMulti/GhsMultiMultipleProjects/sub/lib2.c new file mode 100644 index 0000000..b35e9cc --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/sub/lib2.c @@ -0,0 +1,4 @@ +int func(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/sub2/CMakeLists.txt b/Tests/GhsMulti/GhsMultiMultipleProjects/sub2/CMakeLists.txt new file mode 100644 index 0000000..e42e7fb --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/sub2/CMakeLists.txt @@ -0,0 +1,10 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test3 C) + +add_library(lib3 lib3.c) +add_executable(exe3 exe3.c) +target_link_libraries(exe3 lib1 lib3) diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/sub2/exe3.c b/Tests/GhsMulti/GhsMultiMultipleProjects/sub2/exe3.c new file mode 100644 index 0000000..9238cf3 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/sub2/exe3.c @@ -0,0 +1,6 @@ +extern int func(void); +extern int lib1_func(void); +int main(void) +{ + return func() + lib1_func(); +} diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/sub2/lib3.c b/Tests/GhsMulti/GhsMultiMultipleProjects/sub2/lib3.c new file mode 100644 index 0000000..b35e9cc --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/sub2/lib3.c @@ -0,0 +1,4 @@ +int func(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/verify.cmake b/Tests/GhsMulti/GhsMultiMultipleProjects/verify.cmake new file mode 100644 index 0000000..3855215 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/verify.cmake @@ -0,0 +1,58 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#test project was generated +unset(fileName CACHE) +find_file(fileName lib3.gpj + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/lib3 + ${CMAKE_CURRENT_BINARY_DIR}/examples + ) + +if (fileName) + message("Found target lib3: ${fileName}") +else() + message(SEND_ERROR "Could not find target lib3: ${fileName}") +endif() + +#test project was generated +unset(fileName CACHE) +find_file (fileName exe3.gpj + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/exe3 + ${CMAKE_CURRENT_BINARY_DIR}/examples + ) + +if (fileName) + message("Found target exe3: ${fileName}") +else() + message(SEND_ERROR "Could not find target exe3: ${fileName}") +endif() + +#test project was not built +unset(fileName CACHE) +find_file (fileName lib3.a + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/lib3 + ${CMAKE_CURRENT_BINARY_DIR}/examples + ) + +if (fileName) + message(SEND_ERROR "Found target lib3: ${fileName}") +else() + message("Could not find target lib3: ${fileName}") +endif() + +unset(fileName CACHE) +find_file (fileName NAMES exe3.as exe3 + HINTS + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/exe3 + ${CMAKE_CURRENT_BINARY_DIR}/examples + ) + +if (fileName) + message(SEND_ERROR "Found target exe3: ${fileName}") +else() + message("Could not find target exe3: ${fileName}") +endif() diff --git a/Tests/GhsMulti/GhsMultiObjectLibrary/CMakeLists.txt b/Tests/GhsMulti/GhsMultiObjectLibrary/CMakeLists.txt new file mode 100644 index 0000000..a025814 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiObjectLibrary/CMakeLists.txt @@ -0,0 +1,13 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +add_library(obj1 OBJECT testObj.c testObj.h sub/testObj.c testObj2.c) + +add_executable(exe1 exe.c $<TARGET_OBJECTS:obj1>) +if(CMAKE_C_COMPILER_ID STREQUAL "GHS") + target_link_options(exe1 PRIVATE "-non_shared") +endif() diff --git a/Tests/GhsMulti/GhsMultiObjectLibrary/exe.c b/Tests/GhsMulti/GhsMultiObjectLibrary/exe.c new file mode 100644 index 0000000..c2c5a19 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiObjectLibrary/exe.c @@ -0,0 +1,8 @@ +extern int funcOBJ(void); +extern int funcOBJ2(void); +extern int funcOBJs(void); + +int main(void) +{ + return funcOBJ() + funcOBJ2() + funcOBJs(); +} diff --git a/Tests/GhsMulti/GhsMultiObjectLibrary/sub/testOBJ.c b/Tests/GhsMulti/GhsMultiObjectLibrary/sub/testOBJ.c new file mode 100644 index 0000000..5228ef2 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiObjectLibrary/sub/testOBJ.c @@ -0,0 +1,4 @@ +int funcOBJs(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiObjectLibrary/testOBJ.c b/Tests/GhsMulti/GhsMultiObjectLibrary/testOBJ.c new file mode 100644 index 0000000..ec6f2c3 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiObjectLibrary/testOBJ.c @@ -0,0 +1,4 @@ +int funcOBJ(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiObjectLibrary/testOBJ.h b/Tests/GhsMulti/GhsMultiObjectLibrary/testOBJ.h new file mode 100644 index 0000000..9aef431 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiObjectLibrary/testOBJ.h @@ -0,0 +1 @@ +extern int funcOBJ(void); diff --git a/Tests/GhsMulti/GhsMultiObjectLibrary/testOBJ2.c b/Tests/GhsMulti/GhsMultiObjectLibrary/testOBJ2.c new file mode 100644 index 0000000..b6a9b93 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiObjectLibrary/testOBJ2.c @@ -0,0 +1,4 @@ +int funcOBJ2(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiPlatform/CMakeLists.txt b/Tests/GhsMulti/GhsMultiPlatform/CMakeLists.txt new file mode 100644 index 0000000..b177887 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiPlatform/CMakeLists.txt @@ -0,0 +1,34 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test) + +message("PLATFORM_ID = ${PLATFORM_ID}") + +message("CMAKE_C_COMPILER = ${CMAKE_C_COMPILER}") +message("CMAKE_C_COMPILER_ID = ${CMAKE_C_COMPILER_ID}") +message("CMAKE_C_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION}") +message("CMAKE_C_COMPILER_VERSION_INTERNAL = ${CMAKE_C_COMPILER_VERSION_INTERNAL}") +message("CMAKE_C_PLATFORM_ID = ${CMAKE_C_PLATFORM_ID}") +message("CMAKE_C_COMPILER_ARCHITECTURE_ID = ${CMAKE_C_COMPILER_ARCHITECTURE_ID}") +message("CMAKE_C_COMPILER_ABI = ${CMAKE_C_COMPILER_ABI}") +message("CMAKE_C_STANDARD_COMPUTED_DEFAULT = ${CMAKE_C_STANDARD_COMPUTED_DEFAULT}") + +message("CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}") +message("CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}") +message("CMAKE_CXX_COMPILER_VERSION = ${CMAKE_CXX_COMPILER_VERSION}") +message("CMAKE_CXX_COMPILER_VERSION_INTERNAL = ${CMAKE_CXX_COMPILER_VERSION_INTERNAL}") +message("CMAKE_CXX_PLATFORM_ID = ${CMAKE_CXX_PLATFORM_ID}") +message("CMAKE_CXX_COMPILER_ARCHITECTURE_ID = ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}") +message("CMAKE_CXX_COMPILER_ABI = ${CMAKE_CXX_COMPILER_ABI}") +message("CMAKE_CXX_STANDARD_COMPUTED_DEFAULT = ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}") + +if(CMAKE_C_COMPILER AND NOT CMAKE_C_COMPILER_ID STREQUAL "GHS") + message(FATAL_ERROR "CMAKE_C_COMPILER_ID != GHS") +endif() + +if(CMAKE_CXX_COMPILER AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "GHS") + message(FATAL_ERROR "CMAKE_CXX_COMPILER_ID != GHS") +endif() diff --git a/Tests/GhsMulti/GhsMultiPlatform/file1.c b/Tests/GhsMulti/GhsMultiPlatform/file1.c new file mode 100644 index 0000000..4132aa4 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiPlatform/file1.c @@ -0,0 +1,4 @@ +int main(void) +{ + return -42; +} diff --git a/Tests/GhsMulti/GhsMultiRenameInstall/CMakeLists.txt b/Tests/GhsMulti/GhsMultiRenameInstall/CMakeLists.txt new file mode 100644 index 0000000..f5792b4 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiRenameInstall/CMakeLists.txt @@ -0,0 +1,42 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +set(targets_to_install "") + +if(CMAKE_C_COMPILER_ID STREQUAL "GHS") + add_link_options("-non_shared") +endif() + +if(RUN_TEST STREQUAL "SINGLE_EXEC") + add_executable(exe1 exe.c) + set(targets_to_install ${targets_to_install} exe1) +endif() + +if(RUN_TEST STREQUAL "SINGLE_EXEC_RENAMED") + set(name new_name) + add_executable(exe1 exe.c) + set_property(TARGET exe1 PROPERTY RUNTIME_OUTPUT_DIRECTORY ${name}_bin_$<CONFIG>) + set_property(TARGET exe1 PROPERTY OUTPUT_NAME ${name}_$<CONFIG>) + set_property(TARGET exe1 PROPERTY SUFFIX .bin) + set(targets_to_install ${targets_to_install} exe1) +endif() + +if(RUN_TEST STREQUAL "EXEC_AND_LIB") + add_library(lib1 lib1.c) + set_property(TARGET lib1 PROPERTY ARCHIVE_OUTPUT_DIRECTORY forced-$<CONFIG>) + set_property(TARGET lib1 PROPERTY SUFFIX .LL) + set_property(TARGET lib1 PROPERTY OUTPUT_NAME lib1_$<CONFIG>) + + add_executable(exe1 exe1.c) + target_link_libraries(exe1 lib1) + set(targets_to_install ${targets_to_install} exe1 lib1) +endif() + +install(TARGETS ${targets_to_install} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static) diff --git a/Tests/GhsMulti/GhsMultiRenameInstall/exe.c b/Tests/GhsMulti/GhsMultiRenameInstall/exe.c new file mode 100644 index 0000000..8488f4e --- /dev/null +++ b/Tests/GhsMulti/GhsMultiRenameInstall/exe.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/GhsMulti/GhsMultiRenameInstall/exe1.c b/Tests/GhsMulti/GhsMultiRenameInstall/exe1.c new file mode 100644 index 0000000..29ad70a --- /dev/null +++ b/Tests/GhsMulti/GhsMultiRenameInstall/exe1.c @@ -0,0 +1,5 @@ +extern int func(void); +int main(void) +{ + return func(); +} diff --git a/Tests/GhsMulti/GhsMultiRenameInstall/lib1.c b/Tests/GhsMulti/GhsMultiRenameInstall/lib1.c new file mode 100644 index 0000000..b35e9cc --- /dev/null +++ b/Tests/GhsMulti/GhsMultiRenameInstall/lib1.c @@ -0,0 +1,4 @@ +int func(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/Atest3.c b/Tests/GhsMulti/GhsMultiSrcGroups/Atest3.c new file mode 100644 index 0000000..9c9c1d9 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/Atest3.c @@ -0,0 +1,4 @@ +int funcA3a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/CMakeLists.txt b/Tests/GhsMulti/GhsMultiSrcGroups/CMakeLists.txt new file mode 100644 index 0000000..93a1afc --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/CMakeLists.txt @@ -0,0 +1,45 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +#set(CMAKE_FOLDER ON) +add_executable(groups + test1.c + test1.h + test2a.c + test4.c + test5.c + test6.c + test7.c + standard.h + testOBJ.c + testOBJ.h + sub/testOBJ.c + sub/testOBJ.h + textfile.txt + textfile2.txt + test3.c + Atest3.c +# object.o + resource.pdf + cmake.rule + s5.h + s2.h + s4.h + standard.h + ) + +if(TEST_PROP) + set_target_properties(groups PROPERTIES GHS_NO_SOURCE_GROUP_FILE ON) +endif() +if(CMAKE_C_COMPILER_ID MATCHES "GHS") + target_link_options(groups PRIVATE "-non_shared") +endif() +source_group( gC FILES sub/testOBJ.h testOBJ.c testOBJ.h sub/testOBJ.c ) +source_group( gA FILES test1.c test1.h) +source_group( gB test[65].c ) +source_group( gC\\gD FILES test7.c ) +source_group( docs FILES textfile.txt ) diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/cmake.rule b/Tests/GhsMulti/GhsMultiSrcGroups/cmake.rule new file mode 100644 index 0000000..c6cac69 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/cmake.rule @@ -0,0 +1 @@ +empty diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/object.o b/Tests/GhsMulti/GhsMultiSrcGroups/object.o new file mode 100644 index 0000000..c6cac69 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/object.o @@ -0,0 +1 @@ +empty diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/resource.pdf b/Tests/GhsMulti/GhsMultiSrcGroups/resource.pdf new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/resource.pdf diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/s2.h b/Tests/GhsMulti/GhsMultiSrcGroups/s2.h new file mode 100644 index 0000000..e2b1725 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/s2.h @@ -0,0 +1,6 @@ +extern int func2a(void); +extern int func3a(void); +extern int func4a(void); +extern int func5a(void); +extern int func6a(void); +extern int func7a(void); diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/s4.h b/Tests/GhsMulti/GhsMultiSrcGroups/s4.h new file mode 100644 index 0000000..e2b1725 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/s4.h @@ -0,0 +1,6 @@ +extern int func2a(void); +extern int func3a(void); +extern int func4a(void); +extern int func5a(void); +extern int func6a(void); +extern int func7a(void); diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/s5.h b/Tests/GhsMulti/GhsMultiSrcGroups/s5.h new file mode 100644 index 0000000..e2b1725 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/s5.h @@ -0,0 +1,6 @@ +extern int func2a(void); +extern int func3a(void); +extern int func4a(void); +extern int func5a(void); +extern int func6a(void); +extern int func7a(void); diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/standard.h b/Tests/GhsMulti/GhsMultiSrcGroups/standard.h new file mode 100644 index 0000000..2773a55 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/standard.h @@ -0,0 +1 @@ +#define somthing diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/sub/testOBJ.c b/Tests/GhsMulti/GhsMultiSrcGroups/sub/testOBJ.c new file mode 100644 index 0000000..90ea9b9 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/sub/testOBJ.c @@ -0,0 +1,6 @@ +#include "testOBJ.h" + +int funcOBJsub(void) +{ + return func2a() + func3a() + func4a() + func5a() + func6a() + func7a(); +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/sub/testOBJ.h b/Tests/GhsMulti/GhsMultiSrcGroups/sub/testOBJ.h new file mode 100644 index 0000000..e2b1725 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/sub/testOBJ.h @@ -0,0 +1,6 @@ +extern int func2a(void); +extern int func3a(void); +extern int func4a(void); +extern int func5a(void); +extern int func6a(void); +extern int func7a(void); diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/test1.c b/Tests/GhsMulti/GhsMultiSrcGroups/test1.c new file mode 100644 index 0000000..94f818a --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/test1.c @@ -0,0 +1,6 @@ +#include "test1.h" + +int main(void) +{ + return func2a() + func3a() + func4a() + func5a() + func6a() + func7a(); +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/test1.h b/Tests/GhsMulti/GhsMultiSrcGroups/test1.h new file mode 100644 index 0000000..e2b1725 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/test1.h @@ -0,0 +1,6 @@ +extern int func2a(void); +extern int func3a(void); +extern int func4a(void); +extern int func5a(void); +extern int func6a(void); +extern int func7a(void); diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/test2a.c b/Tests/GhsMulti/GhsMultiSrcGroups/test2a.c new file mode 100644 index 0000000..8f66fba --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/test2a.c @@ -0,0 +1,4 @@ +int func2a(void) +{ + return 2; +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/test3.c b/Tests/GhsMulti/GhsMultiSrcGroups/test3.c new file mode 100644 index 0000000..57c7a6f --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/test3.c @@ -0,0 +1,4 @@ +int func3a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/test3.h b/Tests/GhsMulti/GhsMultiSrcGroups/test3.h new file mode 100644 index 0000000..2773a55 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/test3.h @@ -0,0 +1 @@ +#define somthing diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/test4.c b/Tests/GhsMulti/GhsMultiSrcGroups/test4.c new file mode 100644 index 0000000..109fd7b --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/test4.c @@ -0,0 +1,4 @@ +int func4a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/test5.c b/Tests/GhsMulti/GhsMultiSrcGroups/test5.c new file mode 100644 index 0000000..f28a705 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/test5.c @@ -0,0 +1,4 @@ +int func5a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/test6.c b/Tests/GhsMulti/GhsMultiSrcGroups/test6.c new file mode 100644 index 0000000..bf77406 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/test6.c @@ -0,0 +1,4 @@ +int func6a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/test7.c b/Tests/GhsMulti/GhsMultiSrcGroups/test7.c new file mode 100644 index 0000000..6a4a9a1 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/test7.c @@ -0,0 +1,4 @@ +int func7a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/testOBJ.c b/Tests/GhsMulti/GhsMultiSrcGroups/testOBJ.c new file mode 100644 index 0000000..e86e2a4 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/testOBJ.c @@ -0,0 +1,11 @@ +extern int func2a(void); +extern int func3a(void); +extern int func4a(void); +extern int func5a(void); +extern int func6a(void); +extern int func7a(void); + +int funcOBJ(void) +{ + return func2a() + func3a() + func4a() + func5a() + func6a() + func7a(); +} diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/testOBJ.h b/Tests/GhsMulti/GhsMultiSrcGroups/testOBJ.h new file mode 100644 index 0000000..e2b1725 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/testOBJ.h @@ -0,0 +1,6 @@ +extern int func2a(void); +extern int func3a(void); +extern int func4a(void); +extern int func5a(void); +extern int func6a(void); +extern int func7a(void); diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/textfile.txt b/Tests/GhsMulti/GhsMultiSrcGroups/textfile.txt new file mode 100644 index 0000000..48cdce8 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/textfile.txt @@ -0,0 +1 @@ +placeholder diff --git a/Tests/GhsMulti/GhsMultiSrcGroups/textfile2.txt b/Tests/GhsMulti/GhsMultiSrcGroups/textfile2.txt new file mode 100644 index 0000000..48cdce8 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiSrcGroups/textfile2.txt @@ -0,0 +1 @@ +placeholder diff --git a/Tests/GhsMulti/GhsMultiUnsupportedTargets/CMakeLists.txt b/Tests/GhsMulti/GhsMultiUnsupportedTargets/CMakeLists.txt new file mode 100644 index 0000000..ed3094b --- /dev/null +++ b/Tests/GhsMulti/GhsMultiUnsupportedTargets/CMakeLists.txt @@ -0,0 +1,12 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(test C) + +add_custom_target(testTarget ALL echo this is a test) + +add_library(sharedLib SHARED file.c) + +add_library(moduleLib MODULE file.c) diff --git a/Tests/GhsMulti/GhsMultiUnsupportedTargets/file.c b/Tests/GhsMulti/GhsMultiUnsupportedTargets/file.c new file mode 100644 index 0000000..6a4a9a1 --- /dev/null +++ b/Tests/GhsMulti/GhsMultiUnsupportedTargets/file.c @@ -0,0 +1,4 @@ +int func7a(void) +{ + return 1; +} diff --git a/Tests/GhsMulti/ReturnNum/Int/CMakeLists.txt b/Tests/GhsMulti/ReturnNum/Int/CMakeLists.txt deleted file mode 100644 index 44c5de1..0000000 --- a/Tests/GhsMulti/ReturnNum/Int/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_executable(AppDD AppDD.int Default.bsp) diff --git a/Tests/GhsMulti/ReturnNum/Int/Default.bsp b/Tests/GhsMulti/ReturnNum/Int/Default.bsp deleted file mode 100644 index 224ec29..0000000 --- a/Tests/GhsMulti/ReturnNum/Int/Default.bsp +++ /dev/null @@ -1,35 +0,0 @@ -# Target description File for the Integrate utility for use with the -# INTEGRITY real-time operating system by Green Hills Software. -# Before editing this file, refer to your Integrate documentation. -# default.bsp is appropriate for INTEGRITY applications which are -# fully linked with the kernel (for RAM or ROM) or dynamically downloaded. -# -# MinimumAddress must match the value of .ramend in the linker directives -# file used for the KernelSpace program - see default.ld for more info. -# The MaximumAddress used here allows memory mappings to be specified -# for up to the 16 MB mark in RAM. Intex will not permit programs -# that require more memory for its mappings. If the board has less -# memory, this number can be reduced by the user. - -Target - MinimumAddress .ramend - MaximumAddress .ramlimit - Clock StandardTick - EndClock - Clock HighResTimer - EndClock - IODevice "SerialDev0" - InitialKernelObjects 200 - DefaultStartIt false - DefaultMaxPriority 255 - DefaultPriority 127 - DefaultWeight 1 - DefaultMaxWeight 255 - DefaultHeapSize 0x10000 - LastVirtualAddress 0x3fffffff - PageSize 0x1000 - ArchitectedPageSize 0x1000 - ArchitectedPageSize 0x10000 - ArchitectedPageSize 0x100000 - DefaultMemoryRegionSize 0x20000 -EndTarget diff --git a/Tests/GhsMulti/ReturnNum/Lib/CMakeLists.txt b/Tests/GhsMulti/ReturnNum/Lib/CMakeLists.txt deleted file mode 100644 index 9c822da..0000000 --- a/Tests/GhsMulti/ReturnNum/Lib/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_library(Lib HelperFun.c HelperFun.h)
\ No newline at end of file diff --git a/Tests/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt index 3db210a..6aae09a 100644 --- a/Tests/InterfaceLibrary/CMakeLists.txt +++ b/Tests/InterfaceLibrary/CMakeLists.txt @@ -31,6 +31,7 @@ add_library(item_real STATIC item.cpp) add_library(item_iface INTERFACE IMPORTED) set_property(TARGET item_iface PROPERTY IMPORTED_LIBNAME item_real) add_dependencies(item_iface item_real) +get_property(item_iface_dependencies TARGET item_iface PROPERTY MANUALLY_ADDED_DEPENDENCIES) link_directories(${CMAKE_CURRENT_BINARY_DIR}) add_executable(InterfaceLibrary definetestexe.cpp) diff --git a/Tests/RunCMake/Autogen/CMakeLists.txt b/Tests/RunCMake/Autogen/CMakeLists.txt new file mode 100644 index 0000000..9a66cde --- /dev/null +++ b/Tests/RunCMake/Autogen/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.13) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Autogen/NoQt-stderr.txt b/Tests/RunCMake/Autogen/NoQt-stderr.txt new file mode 100644 index 0000000..1c6660a --- /dev/null +++ b/Tests/RunCMake/Autogen/NoQt-stderr.txt @@ -0,0 +1,8 @@ +^CMake Warning \(dev\) in CMakeLists.txt: + AUTOGEN: No valid Qt version found for target main. AUTOMOC, AUTOUIC and + AUTORCC disabled. Consider adding: + + find_package\(Qt<QTVERSION> COMPONENTS Widgets\) + + to your CMakeLists.txt file. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/Autogen/NoQt.cmake b/Tests/RunCMake/Autogen/NoQt.cmake new file mode 100644 index 0000000..b2d375a --- /dev/null +++ b/Tests/RunCMake/Autogen/NoQt.cmake @@ -0,0 +1,6 @@ +enable_language(CXX) + +add_executable(main empty.cpp) +set_property(TARGET main PROPERTY AUTOMOC 1) +set_property(TARGET main PROPERTY AUTORCC 1) +set_property(TARGET main PROPERTY AUTOUIC 1) diff --git a/Tests/RunCMake/Autogen/RunCMakeTest.cmake b/Tests/RunCMake/Autogen/RunCMakeTest.cmake new file mode 100644 index 0000000..e52f28d --- /dev/null +++ b/Tests/RunCMake/Autogen/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(NoQt) diff --git a/Tests/RunCMake/Autogen/empty.cpp b/Tests/RunCMake/Autogen/empty.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/Autogen/empty.cpp diff --git a/Tests/RunCMake/CMP0064/CMP0064-OLD-stderr.txt b/Tests/RunCMake/CMP0064/CMP0064-OLD-stderr.txt new file mode 100644 index 0000000..987a503 --- /dev/null +++ b/Tests/RunCMake/CMP0064/CMP0064-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0064-OLD.cmake:1 \(cmake_policy\): + The OLD behavior for policy CMP0064 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 5afa242..c8653b4 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -150,10 +150,12 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) endif() add_RunCMake_test(AndroidTestUtilities) +add_RunCMake_test(Autogen) add_RunCMake_test(BuildDepends) if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja") add_RunCMake_test(Byproducts) endif() +add_RunCMake_test(CMakeRoleGlobalProperty) if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja") add_RunCMake_test(CompilerChange) endif() @@ -334,7 +336,7 @@ if (GTK2_FOUND) endif() if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") - add_RunCMake_test(include_external_msproject) + add_RunCMake_test(include_external_msproject -DVS_PLATFORM_NAME=${CMAKE_VS_PLATFORM_NAME}) if("${CMAKE_GENERATOR}" MATCHES "Visual Studio (9|10)" AND NOT CMAKE_VS_DEVENV_COMMAND) set(NO_USE_FOLDERS 1) endif() diff --git a/Tests/RunCMake/CMakeRoleGlobalProperty/BuildAndTest/CMakeLists.txt b/Tests/RunCMake/CMakeRoleGlobalProperty/BuildAndTest/CMakeLists.txt new file mode 100644 index 0000000..332b023 --- /dev/null +++ b/Tests/RunCMake/CMakeRoleGlobalProperty/BuildAndTest/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.12) +project(CMakeRoleGlobalPropertyBuildAndTest NONE) +include(CTest) + +get_property(role GLOBAL PROPERTY CMAKE_ROLE) +if(NOT role STREQUAL "PROJECT") + message(SEND_ERROR "CMAKE_ROLE property is \"${role}\", should be \"PROJECT\"") +endif() + +add_test(NAME RunCMakeVersion COMMAND "${CMAKE_COMMAND}" --version) diff --git a/Tests/RunCMake/CMakeRoleGlobalProperty/CMakeLists.txt b/Tests/RunCMake/CMakeRoleGlobalProperty/CMakeLists.txt new file mode 100644 index 0000000..44025d3 --- /dev/null +++ b/Tests/RunCMake/CMakeRoleGlobalProperty/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.12) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMakeRoleGlobalProperty/CMakeLists.txt.in b/Tests/RunCMake/CMakeRoleGlobalProperty/CMakeLists.txt.in new file mode 100644 index 0000000..bb8f9c1 --- /dev/null +++ b/Tests/RunCMake/CMakeRoleGlobalProperty/CMakeLists.txt.in @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.12) +project(CMakeRoleGlobalProperty@CASE_NAME@ NONE) +include(CTest) +add_test(NAME RunCMakeVersion COMMAND "${CMAKE_COMMAND}" --version) diff --git a/Tests/RunCMake/CMakeRoleGlobalProperty/FindDummyPackage.cmake b/Tests/RunCMake/CMakeRoleGlobalProperty/FindDummyPackage.cmake new file mode 100644 index 0000000..8299042 --- /dev/null +++ b/Tests/RunCMake/CMakeRoleGlobalProperty/FindDummyPackage.cmake @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.12) + +get_property(role GLOBAL PROPERTY CMAKE_ROLE) +if(NOT role STREQUAL "FIND_PACKAGE") + message(SEND_ERROR "CMAKE_ROLE property is \"${role}\", should be \"FIND_PACKAGE\"") +endif() + +set(DummyPackage_FOUND 1) diff --git a/Tests/RunCMake/CMakeRoleGlobalProperty/Project.cmake b/Tests/RunCMake/CMakeRoleGlobalProperty/Project.cmake new file mode 100644 index 0000000..c0b6a48 --- /dev/null +++ b/Tests/RunCMake/CMakeRoleGlobalProperty/Project.cmake @@ -0,0 +1,6 @@ +get_property(role GLOBAL PROPERTY CMAKE_ROLE) +if(NOT role STREQUAL "PROJECT") + message(SEND_ERROR "CMAKE_ROLE property is \"${role}\", should be \"PROJECT\"") +endif() + +add_subdirectory(sub) diff --git a/Tests/RunCMake/CMakeRoleGlobalProperty/RunCMakeTest.cmake b/Tests/RunCMake/CMakeRoleGlobalProperty/RunCMakeTest.cmake new file mode 100644 index 0000000..3cbd51d --- /dev/null +++ b/Tests/RunCMake/CMakeRoleGlobalProperty/RunCMakeTest.cmake @@ -0,0 +1,14 @@ +include(RunCMake) +include(RunCTest) + +run_cmake(Project) +run_cmake_command(Script "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_LIST_DIR}/Script.cmake") +run_cmake_command(FindPackage "${CMAKE_COMMAND}" --find-package -DNAME=DummyPackage -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}") +run_ctest(CTest) +run_cmake_command(BuildAndTest "${CMAKE_CTEST_COMMAND}" + --build-and-test + "${RunCMake_SOURCE_DIR}/BuildAndTest" + "${RunCMake_BINARY_DIR}/BuildAndTest-build" + --build-project CMakeRoleGlobalPropertyBuildAndTest + --build-generator "${RunCMake_GENERATOR}" + ) diff --git a/Tests/RunCMake/CMakeRoleGlobalProperty/Script.cmake b/Tests/RunCMake/CMakeRoleGlobalProperty/Script.cmake new file mode 100644 index 0000000..371edbc --- /dev/null +++ b/Tests/RunCMake/CMakeRoleGlobalProperty/Script.cmake @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.12) + +get_property(role GLOBAL PROPERTY CMAKE_ROLE) +if(NOT role STREQUAL "SCRIPT") + message(SEND_ERROR "CMAKE_ROLE property is \"${role}\", should be \"SCRIPT\"") +endif() diff --git a/Tests/RunCMake/CMakeRoleGlobalProperty/sub/CMakeLists.txt b/Tests/RunCMake/CMakeRoleGlobalProperty/sub/CMakeLists.txt new file mode 100644 index 0000000..8ecf671 --- /dev/null +++ b/Tests/RunCMake/CMakeRoleGlobalProperty/sub/CMakeLists.txt @@ -0,0 +1,4 @@ +get_property(role GLOBAL PROPERTY CMAKE_ROLE) +if(NOT role STREQUAL "PROJECT") + message(SEND_ERROR "CMAKE_ROLE property is \"${role}\", should be \"PROJECT\"") +endif() diff --git a/Tests/RunCMake/CMakeRoleGlobalProperty/test.cmake.in b/Tests/RunCMake/CMakeRoleGlobalProperty/test.cmake.in new file mode 100644 index 0000000..4e2c085 --- /dev/null +++ b/Tests/RunCMake/CMakeRoleGlobalProperty/test.cmake.in @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.12) +set(CTEST_RUN_CURRENT_SCRIPT 0) + +get_property(role GLOBAL PROPERTY CMAKE_ROLE) +if(NOT role STREQUAL "CTEST") + message(SEND_ERROR "CMAKE_ROLE property is \"${role}\", should be \"CTEST\"") +endif() diff --git a/Tests/RunCMake/CPack/tests/EXTERNAL/create_package.cmake b/Tests/RunCMake/CPack/tests/EXTERNAL/create_package.cmake index 2d7f993..6f7c4c2 100644 --- a/Tests/RunCMake/CPack/tests/EXTERNAL/create_package.cmake +++ b/Tests/RunCMake/CPack/tests/EXTERNAL/create_package.cmake @@ -1,5 +1,10 @@ message("This script could run an external packaging tool") +get_property(role GLOBAL PROPERTY CMAKE_ROLE) +if(NOT role STREQUAL "CPACK") + message(SEND_ERROR "CMAKE_ROLE property is \"${role}\", should be \"CPACK\"") +endif() + function(expect_variable VAR) if(NOT ${VAR}) message(FATAL_ERROR "${VAR} is unexpectedly not set") diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake index cae14b1..d524f41 100644 --- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -174,12 +174,15 @@ function(run_TestStdin) endfunction() run_TestStdin() -function(ShowAsJson_check_python v) +function(show_only_json_check_python v) + if(RunCMake_TEST_FAILED OR NOT PYTHON_EXECUTABLE) + return() + endif() set(json_file "${RunCMake_TEST_BINARY_DIR}/ctest.json") file(WRITE "${json_file}" "${actual_stdout}") set(actual_stdout "" PARENT_SCOPE) execute_process( - COMMAND ${PYTHON_EXECUTABLE} "${RunCMake_SOURCE_DIR}/ShowAsJson${v}-check.py" "${json_file}" + COMMAND ${PYTHON_EXECUTABLE} "${RunCMake_SOURCE_DIR}/show-only_json-v${v}_check.py" "${json_file}" RESULT_VARIABLE result OUTPUT_VARIABLE output ERROR_VARIABLE output @@ -190,15 +193,18 @@ function(ShowAsJson_check_python v) endif() endfunction() -function(run_ShowAsJson) - set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ShowAsJson) +function(run_ShowOnly) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ShowOnly) set(RunCMake_TEST_NO_CLEAN 1) file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" " - add_test(ShowAsJson \"${CMAKE_COMMAND}\" -E echo) - set_tests_properties(ShowAsJson PROPERTIES WILL_FAIL true _BACKTRACE_TRIPLES \"file1;1;add_test;file0;;\") + add_test(ShowOnly \"${CMAKE_COMMAND}\" -E echo) + set_tests_properties(ShowOnly PROPERTIES WILL_FAIL true _BACKTRACE_TRIPLES \"file1;1;add_test;file0;;\") + add_test(ShowOnlyNotAvailable NOT_AVAILABLE) ") - run_cmake_command(ShowAsJsonVersionOne ${CMAKE_CTEST_COMMAND} --show-only=json-v1) + run_cmake_command(show-only_human ${CMAKE_CTEST_COMMAND} --show-only=human) + run_cmake_command(show-only_bad ${CMAKE_CTEST_COMMAND} --show-only=bad) + run_cmake_command(show-only_json-v1 ${CMAKE_CTEST_COMMAND} --show-only=json-v1) endfunction() -run_ShowAsJson() +run_ShowOnly() diff --git a/Tests/RunCMake/CTestCommandLine/show-only_bad-result.txt b/Tests/RunCMake/CTestCommandLine/show-only_bad-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/show-only_bad-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestCommandLine/show-only_bad-stderr.txt b/Tests/RunCMake/CTestCommandLine/show-only_bad-stderr.txt new file mode 100644 index 0000000..cc55ab3 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/show-only_bad-stderr.txt @@ -0,0 +1 @@ +^CMake Error: '--show-only=' given unknown value 'bad'$ diff --git a/Tests/RunCMake/CTestCommandLine/show-only_human-stdout.txt b/Tests/RunCMake/CTestCommandLine/show-only_human-stdout.txt new file mode 100644 index 0000000..1332149 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/show-only_human-stdout.txt @@ -0,0 +1 @@ +Test #1: ShowOnly diff --git a/Tests/RunCMake/CTestCommandLine/show-only_json-v1-check.cmake b/Tests/RunCMake/CTestCommandLine/show-only_json-v1-check.cmake new file mode 100644 index 0000000..f9234f8 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/show-only_json-v1-check.cmake @@ -0,0 +1 @@ +show_only_json_check_python(1) diff --git a/Tests/RunCMake/CTestCommandLine/ShowAsJson1-check.py b/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py index d794e7d..4dff90c 100644 --- a/Tests/RunCMake/CTestCommandLine/ShowAsJson1-check.py +++ b/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py @@ -1,4 +1,4 @@ -from ShowAsJson_check import * +from show_only_json_check import * def check_kind(k): assert is_string(k) @@ -77,7 +77,7 @@ def check_workingdir_property(p): assert is_string(p["name"]) assert is_string(p["value"]) assert p["name"] == "WORKING_DIRECTORY" - assert p["value"].endswith("Tests/RunCMake/CTestCommandLine/ShowAsJson") + assert p["value"].endswith("Tests/RunCMake/CTestCommandLine/ShowOnly") def check_properties(p): assert is_list(p) @@ -95,7 +95,7 @@ def check_tests(t): assert test["backtrace"] == 1 check_command(test["command"]) assert is_string(test["name"]) - assert test["name"] == "ShowAsJson" + assert test["name"] == "ShowOnly" check_properties(test["properties"]) assert is_dict(ctest_json) diff --git a/Tests/RunCMake/CTestCommandLine/ShowAsJson_check.py b/Tests/RunCMake/CTestCommandLine/show_only_json_check.py index 493c9e5..493c9e5 100644 --- a/Tests/RunCMake/CTestCommandLine/ShowAsJson_check.py +++ b/Tests/RunCMake/CTestCommandLine/show_only_json_check.py diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 4cd34de..0e04ad1 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -4,17 +4,17 @@ include(RunCMake) run_cmake_command(NoArgs ${CMAKE_COMMAND}) run_cmake_command(Wizard ${CMAKE_COMMAND} -i) -run_cmake_command(C-no-arg ${CMAKE_COMMAND} -C) -run_cmake_command(C-no-file ${CMAKE_COMMAND} -C nosuchcachefile.txt) -run_cmake_command(Cno-file ${CMAKE_COMMAND} -Cnosuchcachefile.txt) +run_cmake_command(C-no-arg ${CMAKE_COMMAND} -B DummyBuildDir -C) +run_cmake_command(C-no-file ${CMAKE_COMMAND} -B DummyBuildDir -C nosuchcachefile.txt) +run_cmake_command(Cno-file ${CMAKE_COMMAND} -B DummyBuildDir -Cnosuchcachefile.txt) run_cmake_command(cache-no-file ${CMAKE_COMMAND} nosuchsubdir/CMakeCache.txt) run_cmake_command(lists-no-file ${CMAKE_COMMAND} nosuchsubdir/CMakeLists.txt) -run_cmake_command(D-no-arg ${CMAKE_COMMAND} -D) -run_cmake_command(D-no-src ${CMAKE_COMMAND} -D VAR=VALUE) -run_cmake_command(Dno-src ${CMAKE_COMMAND} -DVAR=VALUE) -run_cmake_command(U-no-arg ${CMAKE_COMMAND} -U) -run_cmake_command(U-no-src ${CMAKE_COMMAND} -U VAR) -run_cmake_command(Uno-src ${CMAKE_COMMAND} -UVAR) +run_cmake_command(D-no-arg ${CMAKE_COMMAND} -B DummyBuildDir -D) +run_cmake_command(D-no-src ${CMAKE_COMMAND} -B DummyBuildDir -D VAR=VALUE) +run_cmake_command(Dno-src ${CMAKE_COMMAND} -B DummyBuildDir -DVAR=VALUE) +run_cmake_command(U-no-arg ${CMAKE_COMMAND} -B DummyBuildDir -U) +run_cmake_command(U-no-src ${CMAKE_COMMAND} -B DummyBuildDir -U VAR) +run_cmake_command(Uno-src ${CMAKE_COMMAND} -B DummyBuildDir -UVAR) run_cmake_command(E-no-arg ${CMAKE_COMMAND} -E) run_cmake_command(E_capabilities ${CMAKE_COMMAND} -E capabilities) run_cmake_command(E_capabilities-arg ${CMAKE_COMMAND} -E capabilities --extra-arg) @@ -34,8 +34,8 @@ run_cmake_command(E___run_co_compile-bad-iwyu ${CMAKE_COMMAND} -E __run_co_compi run_cmake_command(E___run_co_compile-no--- ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist command-does-not-exist) run_cmake_command(E___run_co_compile-no-cc ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist --) -run_cmake_command(G_no-arg ${CMAKE_COMMAND} -G) -run_cmake_command(G_bad-arg ${CMAKE_COMMAND} -G NoSuchGenerator) +run_cmake_command(G_no-arg ${CMAKE_COMMAND} -B DummyBuildDir -G) +run_cmake_command(G_bad-arg ${CMAKE_COMMAND} -B DummyBuildDir -G NoSuchGenerator) run_cmake_command(P_no-arg ${CMAKE_COMMAND} -P) run_cmake_command(P_no-file ${CMAKE_COMMAND} -P nosuchscriptfile.cmake) @@ -61,6 +61,7 @@ function(run_ExplicitDirs) file(REMOVE_RECURSE "${binary_dir}") file(MAKE_DIRECTORY "${binary_dir}") + run_cmake_command(no-S-B ${CMAKE_COMMAND} -DFOO=BAR) run_cmake_command(S-arg ${CMAKE_COMMAND} -S ${source_dir} ${binary_dir}) run_cmake_command(S-arg-reverse-order ${CMAKE_COMMAND} ${binary_dir} -S${source_dir} ) run_cmake_command(S-no-arg ${CMAKE_COMMAND} -S ) @@ -330,9 +331,9 @@ set(RunCMake_TEST_OPTIONS -Wdev -Wno-dev) run_cmake(Wno-dev) unset(RunCMake_TEST_OPTIONS) -run_cmake_command(W_bad-arg1 ${CMAKE_COMMAND} -W) -run_cmake_command(W_bad-arg2 ${CMAKE_COMMAND} -Wno-) -run_cmake_command(W_bad-arg3 ${CMAKE_COMMAND} -Werror=) +run_cmake_command(W_bad-arg1 ${CMAKE_COMMAND} -B DummyBuildDir -W) +run_cmake_command(W_bad-arg2 ${CMAKE_COMMAND} -B DummyBuildDir -Wno-) +run_cmake_command(W_bad-arg3 ${CMAKE_COMMAND} -B DummyBuildDir -Werror=) set(RunCMake_TEST_OPTIONS --debug-output) run_cmake(debug-output) diff --git a/Tests/RunCMake/CommandLine/no-S-B-result.txt b/Tests/RunCMake/CommandLine/no-S-B-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/no-S-B-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/no-S-B-stderr.txt b/Tests/RunCMake/CommandLine/no-S-B-stderr.txt new file mode 100644 index 0000000..7a94307 --- /dev/null +++ b/Tests/RunCMake/CommandLine/no-S-B-stderr.txt @@ -0,0 +1 @@ +CMake Error: No source or binary directory provided diff --git a/Tests/RunCMake/FetchContent/CMakeLists.txt b/Tests/RunCMake/FetchContent/CMakeLists.txt index d3137f6..3cc2e43 100644 --- a/Tests/RunCMake/FetchContent/CMakeLists.txt +++ b/Tests/RunCMake/FetchContent/CMakeLists.txt @@ -1,3 +1,7 @@ cmake_minimum_required(VERSION 3.9) project(${RunCMake_TEST} NONE) + +# Tests assume no previous downloads in the output directory +file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/_deps) + include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake index 621fb8b..9c1ab66 100644 --- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake +++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake @@ -10,6 +10,7 @@ run_cmake(SameGenerator) run_cmake(VarDefinitions) run_cmake(GetProperties) run_cmake(DirOverrides) +run_cmake(UsesTerminalOverride) # We need to pass through CMAKE_GENERATOR and CMAKE_MAKE_PROGRAM # to ensure the test can run on machines where the build tool diff --git a/Tests/RunCMake/FetchContent/UsesTerminalOverride-stdout.txt b/Tests/RunCMake/FetchContent/UsesTerminalOverride-stdout.txt new file mode 100644 index 0000000..3718d64 --- /dev/null +++ b/Tests/RunCMake/FetchContent/UsesTerminalOverride-stdout.txt @@ -0,0 +1,2 @@ +Logged from t1 download step ++.*Logged from t2 download step diff --git a/Tests/RunCMake/FetchContent/UsesTerminalOverride.cmake b/Tests/RunCMake/FetchContent/UsesTerminalOverride.cmake new file mode 100644 index 0000000..99d9719 --- /dev/null +++ b/Tests/RunCMake/FetchContent/UsesTerminalOverride.cmake @@ -0,0 +1,17 @@ +include(FetchContent) + +set(FETCHCONTENT_QUIET NO) + +FetchContent_Declare( + t1 + DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Logged from t1 download step" + USES_TERMINAL_DOWNLOAD NO + +) +FetchContent_Populate(t1) + +FetchContent_Populate( + t2 + DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Logged from t2 download step" + USES_TERMINAL_DOWNLOAD NO +) diff --git a/Tests/RunCMake/FindBoost/RunCMakeTest.cmake b/Tests/RunCMake/FindBoost/RunCMakeTest.cmake index 5d0577b..eef350c 100644 --- a/Tests/RunCMake/FindBoost/RunCMakeTest.cmake +++ b/Tests/RunCMake/FindBoost/RunCMakeTest.cmake @@ -1,4 +1,5 @@ include(RunCMake) +unset(ENV{Boost_ROOT}) run_cmake(CMakePackage) run_cmake(NoCXX) diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID-result.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID-stderr.txt new file mode 100644 index 0000000..fc13248 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at NonValidTarget-Fortran_COMPILER_ID.cmake:1 \(add_custom_command\): + Error evaluating generator expression: + + \$<Fortran_COMPILER_ID> + + \$<Fortran_COMPILER_ID> may only be used with binary targets. It may not be + used with add_custom_command or add_custom_target. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID.cmake new file mode 100644 index 0000000..88a0bfb --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_ID.cmake @@ -0,0 +1,4 @@ +add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c" + COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<Fortran_COMPILER_ID>.c" +) +add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c") diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION-result.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION-stderr.txt new file mode 100644 index 0000000..f8a4120 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at NonValidTarget-Fortran_COMPILER_VERSION.cmake:1 \(add_custom_command\): + Error evaluating generator expression: + + \$<Fortran_COMPILER_VERSION> + + \$<Fortran_COMPILER_VERSION> may only be used with binary targets. It may + not be used with add_custom_command or add_custom_target. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION.cmake new file mode 100644 index 0000000..34a4884 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-Fortran_COMPILER_VERSION.cmake @@ -0,0 +1,4 @@ +add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c" + COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<Fortran_COMPILER_VERSION>.c" +) +add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c") diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake index 013117e..8a5604c 100644 --- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake @@ -15,8 +15,10 @@ run_cmake(BadSHELL_PATH) run_cmake(CMP0044-WARN) run_cmake(NonValidTarget-C_COMPILER_ID) run_cmake(NonValidTarget-CXX_COMPILER_ID) +run_cmake(NonValidTarget-Fortran_COMPILER_ID) run_cmake(NonValidTarget-C_COMPILER_VERSION) run_cmake(NonValidTarget-CXX_COMPILER_VERSION) +run_cmake(NonValidTarget-Fortran_COMPILER_VERSION) run_cmake(NonValidTarget-TARGET_BUNDLE_DIR) run_cmake(NonValidTarget-TARGET_BUNDLE_CONTENT_DIR) run_cmake(NonValidTarget-TARGET_PROPERTY) diff --git a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake index 27250cb..27ede06 100644 --- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake @@ -3,7 +3,7 @@ include(RunCMake) set(RunCMake_GENERATOR_PLATFORM "") run_cmake(NoPlatform) -if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[01245])( 20[0-9][0-9])?$") +if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[012456])( 20[0-9][0-9])?$") set(RunCMake_GENERATOR_PLATFORM "x64") run_cmake(x64Platform) else() @@ -17,7 +17,7 @@ set(RunCMake_TEST_OPTIONS -A "Extra Platform") run_cmake(TwoPlatforms) unset(RunCMake_TEST_OPTIONS) -if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[01245])( 20[0-9][0-9])?$") +if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[012456])( 20[0-9][0-9])?$") set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestPlatform-toolchain.cmake) run_cmake(TestPlatformToolchain) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index d1738a0..ccf58b4 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -3,7 +3,7 @@ include(RunCMake) set(RunCMake_GENERATOR_TOOLSET "") run_cmake(NoToolset) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset") run_cmake(TestToolset) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,cuda=Test Cuda") @@ -12,7 +12,7 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") run_cmake(TestToolsetCudaOnly) set(RunCMake_GENERATOR_TOOLSET "cuda=Test Cuda") run_cmake(TestToolsetCudaOnly) - if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[245]") + if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[2456]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(TestToolsetHostArchBoth) set(RunCMake_GENERATOR_TOOLSET ",host=x64") @@ -25,7 +25,7 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") run_cmake(BadToolsetHostArch) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x64") run_cmake(BadToolsetHostArchTwice) - if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 15") + if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[56]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version") run_cmake(TestToolsetVersionBoth) set(RunCMake_GENERATOR_TOOLSET ",version=Test Toolset Version") @@ -59,7 +59,7 @@ set(RunCMake_TEST_OPTIONS -T "Extra Toolset") run_cmake(TwoToolsets) unset(RunCMake_TEST_OPTIONS) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode") +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]|Xcode") set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestToolset-toolchain.cmake) run_cmake(TestToolsetToolchain) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index db375ae..7c1ed4e 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -1,6 +1,7 @@ include(RunCMake) run_cmake(ExplicitCMakeLists) +run_cmake(SourceGroupCMakeLists) run_cmake(VsConfigurationType) run_cmake(VsTargetsFileReferences) @@ -13,5 +14,6 @@ run_cmake(VsCSharpCustomTags) run_cmake(VsCSharpReferenceProps) run_cmake(VsCSharpWithoutSources) run_cmake(VsCSharpDeployFiles) +run_cmake(VSCSharpDefines) run_cmake(VsSdkDirectories) run_cmake(VsGlobals) diff --git a/Tests/RunCMake/VS10Project/SourceGroupCMakeLists-check.cmake b/Tests/RunCMake/VS10Project/SourceGroupCMakeLists-check.cmake new file mode 100644 index 0000000..c2a94bb --- /dev/null +++ b/Tests/RunCMake/VS10Project/SourceGroupCMakeLists-check.cmake @@ -0,0 +1,33 @@ +set(vcFiltersFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj.filters") +if(NOT EXISTS "${vcFiltersFile}") + set(RunCMake_TEST_FAILED "Filters file ${vcFiltersFile} does not exist.") + return() +endif() + +set(foundFileFilter 0) +set(foundFilter 0) +file(STRINGS "${vcFiltersFile}" lines) +foreach(line IN LISTS lines) + if(line MATCHES "<Filter>CMakeListsSourceGroup</Filter>") + set(rule "${CMAKE_MATCH_1}") + if(foundFileFilter) + set(RunCMake_TEST_FAILED "Multiple files listed with filter for CMakeListsSourceGroup.") + return() + endif() + set(foundFileFilter 1) + endif() + if(line MATCHES "<Filter.*Include=\"CMakeListsSourceGroup\"") + set(rule "${CMAKE_MATCH_1}") + if(foundFilter) + set(RunCMake_TEST_FAILED "Multiple copies of CMakeListsSourceGroup filter listed.") + return() + endif() + set(foundFilter 1) + endif() +endforeach() +if(NOT foundFileFilter) + set(RunCMake_TEST_FAILED "File filter for CMakeListsSourceGroup not found.") +endif() +if(NOT foundFilter) + set(RunCMake_TEST_FAILED "Filter CMakeListsSourceGroup not found.") +endif() diff --git a/Tests/RunCMake/VS10Project/SourceGroupCMakeLists.cmake b/Tests/RunCMake/VS10Project/SourceGroupCMakeLists.cmake new file mode 100644 index 0000000..4ad87ec --- /dev/null +++ b/Tests/RunCMake/VS10Project/SourceGroupCMakeLists.cmake @@ -0,0 +1,3 @@ +set(CMAKE_CONFIGURATION_TYPES Debug) +add_custom_target(foo) +source_group("CMakeListsSourceGroup" FILES CMakeLists.txt) diff --git a/Tests/RunCMake/VS10Project/VsCSharpDefines-check.cmake b/Tests/RunCMake/VS10Project/VsCSharpDefines-check.cmake new file mode 100644 index 0000000..152bf9c --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpDefines-check.cmake @@ -0,0 +1,64 @@ +# +# Check C# VS project for required elements. +# +set(csProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj") +if(NOT EXISTS "${csProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${csProjectFile} does not exist.") + return() +endif() + + +set(inDebug FALSE) +set(inRelease FALSE) +set(debugOK FALSE) +set(releaseOK FALSE) + + +file(STRINGS "${csProjectFile}" lines) +foreach(line IN LISTS lines) + #message(STATUS ${line}) + if(line MATCHES "^ *<PropertyGroup .*Debug\\|(Win32|x64).*") + set(inDebug TRUE) + elseif(line MATCHES "^ *<PropertyGroup .*Release\\|(Win32|x64).*") + set(inRelease TRUE) + elseif(line MATCHES "^ *</PropertyGroup> *$") + set(inRelease FALSE) + set(inDebug FALSE) + elseif(inDebug AND + (line MATCHES "^ *<DefineConstants>.*MY_FOO_DEFINE.*</DefineConstants> *$") AND + (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_DEBUG.*</DefineConstants> *$") AND + (line MATCHES "^ *<DefineConstants>.*MY_BAR_ASSIGNMENT=bar.*</DefineConstants> *$") AND + (NOT (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_RELEASE.*</DefineConstants> *$")) + ) + set(debugOK TRUE) + elseif(inRelease AND + (line MATCHES "^ *<DefineConstants>.*MY_FOO_DEFINE.*</DefineConstants> *$") AND + (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_RELEASE.*</DefineConstants> *$") AND + (line MATCHES "^ *<DefineConstants>.*MY_BAR_ASSIGNMENT=bar.*</DefineConstants> *$") AND + (NOT (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_DEBUG.*</DefineConstants> *$")) + ) + set(releaseOK TRUE) + endif() +endforeach() + +function(print_csprojfile) + file(STRINGS "${csProjectFile}" lines) + foreach(line IN LISTS lines) + message(STATUS ${line}) + endforeach() +endfunction() + + +if(NOT debugOK) + message(STATUS "Failed to set Debug configuration defines correctly.") + set(RunCMake_TEST_FAILED "Failed to set Debug configuration defines correctly.") + print_csprojfile() + return() +endif() + +if(NOT releaseOK) + message(STATUS "Failed to set Release configuration defines correctly.") + set(RunCMake_TEST_FAILED "Failed to set Release configuration defines correctly.") + print_csprojfile() + return() +endif() diff --git a/Tests/RunCMake/VS10Project/VsCSharpDefines.cmake b/Tests/RunCMake/VS10Project/VsCSharpDefines.cmake new file mode 100644 index 0000000..62c19c5 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpDefines.cmake @@ -0,0 +1,18 @@ +enable_language(CSharp) + +add_library(foo SHARED + foo.cs) + +set_target_properties(foo PROPERTIES + LINKER_LANGUAGE CSharp) + + +# Issue 18698 +target_compile_definitions( + foo + PUBLIC + MY_FOO_DEFINE + "MY_BAR_ASSIGNMENT=bar" + $<$<CONFIG:Debug>:DEFINE_ONLY_FOR_DEBUG> + $<$<CONFIG:Release>:DEFINE_ONLY_FOR_RELEASE> +) diff --git a/Tests/RunCMake/VS10Project/VsDebuggerCommand-check.cmake b/Tests/RunCMake/VS10Project/VsDebuggerCommand-check.cmake index 440f9f2..00288d4 100644 --- a/Tests/RunCMake/VS10Project/VsDebuggerCommand-check.cmake +++ b/Tests/RunCMake/VS10Project/VsDebuggerCommand-check.cmake @@ -1,22 +1,24 @@ -set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") -if(NOT EXISTS "${vcProjectFile}") - set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") - return() -endif() +foreach(target foo bar) + set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${target}.vcxproj") + if(NOT EXISTS "${vcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") + return() + endif() -set(debuggerCommandSet FALSE) + set(debuggerCommandSet FALSE) -file(STRINGS "${vcProjectFile}" lines) -foreach(line IN LISTS lines) - if(line MATCHES "^ *<LocalDebuggerCommand[^>]*>([^<>]+)</LocalDebuggerCommand>$") - if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-command foo") - message(STATUS "foo.vcxproj has debugger command set") - set(debuggerCommandSet TRUE) + file(STRINGS "${vcProjectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<LocalDebuggerCommand[^>]*>([^<>]+)</LocalDebuggerCommand>$") + if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-command foo") + message(STATUS "${target}.vcxproj has debugger command set") + set(debuggerCommandSet TRUE) + endif() endif() + endforeach() + + if(NOT debuggerCommandSet) + set(RunCMake_TEST_FAILED "LocalDebuggerCommand not found or not set correctly.") + return() endif() endforeach() - -if(NOT debuggerCommandSet) - set(RunCMake_TEST_FAILED "LocalDebuggerCommand not found or not set correctly.") - return() -endif() diff --git a/Tests/RunCMake/VS10Project/VsDebuggerCommand.cmake b/Tests/RunCMake/VS10Project/VsDebuggerCommand.cmake index 5dcb6d1..54f9154 100644 --- a/Tests/RunCMake/VS10Project/VsDebuggerCommand.cmake +++ b/Tests/RunCMake/VS10Project/VsDebuggerCommand.cmake @@ -1,5 +1,6 @@ enable_language(CXX) add_library(foo foo.cpp) +add_custom_target(bar) -set_target_properties(foo PROPERTIES +set_target_properties(foo bar PROPERTIES VS_DEBUGGER_COMMAND "my-debugger-command $<TARGET_PROPERTY:foo,NAME>") diff --git a/Tests/RunCMake/VS10Project/VsDebuggerCommandArguments-check.cmake b/Tests/RunCMake/VS10Project/VsDebuggerCommandArguments-check.cmake index b2e0a43..87555d1 100644 --- a/Tests/RunCMake/VS10Project/VsDebuggerCommandArguments-check.cmake +++ b/Tests/RunCMake/VS10Project/VsDebuggerCommandArguments-check.cmake @@ -1,22 +1,24 @@ -set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") -if(NOT EXISTS "${vcProjectFile}") - set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") - return() -endif() +foreach(target foo bar) + set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${target}.vcxproj") + if(NOT EXISTS "${vcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") + return() + endif() -set(debuggerCommandArgumentsSet FALSE) + set(debuggerCommandArgumentsSet FALSE) -file(STRINGS "${vcProjectFile}" lines) -foreach(line IN LISTS lines) - if(line MATCHES "^ *<LocalDebuggerCommandArguments[^>]*>([^<>]+)</LocalDebuggerCommandArguments>$") - if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-command-arguments foo") - message(STATUS "foo.vcxproj has debugger command arguments set") - set(debuggerCommandArgumentsSet TRUE) + file(STRINGS "${vcProjectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<LocalDebuggerCommandArguments[^>]*>([^<>]+)</LocalDebuggerCommandArguments>$") + if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-command-arguments foo") + message(STATUS "${target}.vcxproj has debugger command arguments set") + set(debuggerCommandArgumentsSet TRUE) + endif() endif() + endforeach() + + if(NOT debuggerCommandArgumentsSet) + set(RunCMake_TEST_FAILED "LocalDebuggerCommandArguments not found or not set correctly.") + return() endif() endforeach() - -if(NOT debuggerCommandArgumentsSet) - set(RunCMake_TEST_FAILED "LocalDebuggerCommandArguments not found or not set correctly.") - return() -endif() diff --git a/Tests/RunCMake/VS10Project/VsDebuggerCommandArguments.cmake b/Tests/RunCMake/VS10Project/VsDebuggerCommandArguments.cmake index aa87cdc..1f7d0be 100644 --- a/Tests/RunCMake/VS10Project/VsDebuggerCommandArguments.cmake +++ b/Tests/RunCMake/VS10Project/VsDebuggerCommandArguments.cmake @@ -1,5 +1,6 @@ enable_language(CXX) add_library(foo foo.cpp) +add_custom_target(bar) -set_target_properties(foo PROPERTIES +set_target_properties(foo bar PROPERTIES VS_DEBUGGER_COMMAND_ARGUMENTS "my-debugger-command-arguments $<TARGET_PROPERTY:foo,NAME>") diff --git a/Tests/RunCMake/VS10Project/VsDebuggerEnvironment-check.cmake b/Tests/RunCMake/VS10Project/VsDebuggerEnvironment-check.cmake index 2427ad4..fee121a 100644 --- a/Tests/RunCMake/VS10Project/VsDebuggerEnvironment-check.cmake +++ b/Tests/RunCMake/VS10Project/VsDebuggerEnvironment-check.cmake @@ -1,22 +1,24 @@ -set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") -if(NOT EXISTS "${vcProjectFile}") - set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") - return() -endif() +foreach(target foo bar) + set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${target}.vcxproj") + if(NOT EXISTS "${vcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") + return() + endif() -set(debuggerEnvironmentSet FALSE) + set(debuggerEnvironmentSet FALSE) -file(STRINGS "${vcProjectFile}" lines) -foreach(line IN LISTS lines) - if(line MATCHES "^ *<LocalDebuggerEnvironment[^>]*>([^<>]+)</LocalDebuggerEnvironment>$") - if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-environment foo") - message(STATUS "foo.vcxproj has debugger environment set") - set(debuggerEnvironmentSet TRUE) + file(STRINGS "${vcProjectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<LocalDebuggerEnvironment[^>]*>([^<>]+)</LocalDebuggerEnvironment>$") + if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-environment foo") + message(STATUS "${target}.vcxproj has debugger environment set") + set(debuggerEnvironmentSet TRUE) + endif() endif() + endforeach() + + if(NOT debuggerEnvironmentSet) + set(RunCMake_TEST_FAILED "LocalDebuggerEnvironment not found or not set correctly.") + return() endif() endforeach() - -if(NOT debuggerEnvironmentSet) - set(RunCMake_TEST_FAILED "LocalDebuggerEnvironment not found or not set correctly.") - return() -endif() diff --git a/Tests/RunCMake/VS10Project/VsDebuggerEnvironment.cmake b/Tests/RunCMake/VS10Project/VsDebuggerEnvironment.cmake index d5bec4c..c594f35 100644 --- a/Tests/RunCMake/VS10Project/VsDebuggerEnvironment.cmake +++ b/Tests/RunCMake/VS10Project/VsDebuggerEnvironment.cmake @@ -1,5 +1,6 @@ enable_language(CXX) add_library(foo foo.cpp) +add_custom_target(bar) -set_target_properties(foo PROPERTIES +set_target_properties(foo bar PROPERTIES VS_DEBUGGER_ENVIRONMENT "my-debugger-environment $<TARGET_PROPERTY:foo,NAME>") diff --git a/Tests/RunCMake/VS10Project/VsDebuggerWorkingDir-check.cmake b/Tests/RunCMake/VS10Project/VsDebuggerWorkingDir-check.cmake index 6a142f8..9d3f2a8 100644 --- a/Tests/RunCMake/VS10Project/VsDebuggerWorkingDir-check.cmake +++ b/Tests/RunCMake/VS10Project/VsDebuggerWorkingDir-check.cmake @@ -1,22 +1,24 @@ -set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") -if(NOT EXISTS "${vcProjectFile}") - set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") - return() -endif() +foreach(target foo bar) + set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${target}.vcxproj") + if(NOT EXISTS "${vcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") + return() + endif() -set(debuggerWorkDirSet FALSE) + set(debuggerWorkDirSet FALSE) -file(STRINGS "${vcProjectFile}" lines) -foreach(line IN LISTS lines) - if(line MATCHES "^ *<LocalDebuggerWorkingDirectory[^>]*>([^<>]+)</LocalDebuggerWorkingDirectory>$") - if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-directory foo") - message(STATUS "foo.vcxproj has debugger working dir set") - set(debuggerWorkDirSet TRUE) + file(STRINGS "${vcProjectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<LocalDebuggerWorkingDirectory[^>]*>([^<>]+)</LocalDebuggerWorkingDirectory>$") + if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-directory foo") + message(STATUS "${target}.vcxproj has debugger working dir set") + set(debuggerWorkDirSet TRUE) + endif() endif() + endforeach() + + if(NOT debuggerWorkDirSet) + set(RunCMake_TEST_FAILED "LocalDebuggerWorkingDirectory not found or not set correctly.") + return() endif() endforeach() - -if(NOT debuggerWorkDirSet) - set(RunCMake_TEST_FAILED "LocalDebuggerWorkingDirectory not found or not set correctly.") - return() -endif() diff --git a/Tests/RunCMake/VS10Project/VsDebuggerWorkingDir.cmake b/Tests/RunCMake/VS10Project/VsDebuggerWorkingDir.cmake index 36daed0..69ed85c 100644 --- a/Tests/RunCMake/VS10Project/VsDebuggerWorkingDir.cmake +++ b/Tests/RunCMake/VS10Project/VsDebuggerWorkingDir.cmake @@ -1,5 +1,6 @@ enable_language(CXX) add_library(foo foo.cpp) +add_custom_target(bar) -set_target_properties(foo PROPERTIES +set_target_properties(foo bar PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "my-debugger-directory $<TARGET_PROPERTY:foo,NAME>") diff --git a/Tests/RunCMake/VS10ProjectWinCE/RunCMakeTest.cmake b/Tests/RunCMake/VS10ProjectWinCE/RunCMakeTest.cmake index b35ee90..2c9067f 100644 --- a/Tests/RunCMake/VS10ProjectWinCE/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10ProjectWinCE/RunCMakeTest.cmake @@ -6,3 +6,4 @@ set(RunCMake_GENERATOR_INSTANCE "") set(RunCMake_TEST_OPTIONS -DCMAKE_SYSTEM_NAME=WindowsCE ) run_cmake(VsCEDebuggerDeploy) +run_cmake(VSCSharpCFProject) diff --git a/Tests/RunCMake/VS10ProjectWinCE/VsCSharpCFProject-check.cmake b/Tests/RunCMake/VS10ProjectWinCE/VsCSharpCFProject-check.cmake new file mode 100644 index 0000000..618896e --- /dev/null +++ b/Tests/RunCMake/VS10ProjectWinCE/VsCSharpCFProject-check.cmake @@ -0,0 +1,54 @@ +# +# Check C# Compact Framework project for required elements. +# +set(csProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj") +if(NOT EXISTS "${csProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${csProjectFile} does not exist.") + return() +endif() + +if( NOT ${CMAKE_SYSTEM_NAME} STREQUAL "WindowsCE" ) + set(RunCMake_TEST_FAILED "Test only valid for WindowsCE") + return() +endif() + +set(FoundTargetFrameworkTargetsVersion FALSE) +set(FoundDotNetFrameworkVersion FALSE) +set(FoundTargetFrameworkIdentifier FALSE) +set(FoundCFTargetsImport FALSE) + + +file(STRINGS "${csProjectFile}" lines) +foreach(line IN LISTS lines) + #message(STATUS ${line}) + if(line MATCHES "^ *<TargetFrameworkIdentifier>WindowsEmbeddedCompact</TargetFrameworkIdentifier> *$") + set(FoundTargetFrameworkIdentifier TRUE) + elseif(line MATCHES " *<TargetFrameworkVersion>v3.9</TargetFrameworkVersion> *$") + set(FoundDotNetFrameworkVersion TRUE) + elseif(line MATCHES " *<TargetFrameworkTargetsVersion>v8.0</TargetFrameworkTargetsVersion> *$") + set(FoundTargetFrameworkTargetsVersion TRUE) + elseif( line MATCHES " *<Import Project=\"\\$\\(MSBuildExtensionsPath\\)\\\\Microsoft\\\\\\$\\(TargetFrameworkIdentifier\\)\\\\\\$\\(TargetFrameworkTargetsVersion\\)\\\\Microsoft\\.\\$\\(TargetFrameworkIdentifier\\)\\.CSharp\\.targets\" */> *" ) + set(FoundCFTargetsImport TRUE) + endif() +endforeach() + + +if(NOT FoundTargetFrameworkTargetsVersion) + set(RunCMake_TEST_FAILED "TargetFrameworkIdentifier not found or not set correctly.") + return() +endif() + +if(NOT FoundDotNetFrameworkVersion) + set(RunCMake_TEST_FAILED "TargetFrameworkVersion not found or not set correctly.") + return() +endif() + +if(NOT FoundTargetFrameworkIdentifier) + set(RunCMake_TEST_FAILED "TargetFrameworkTargetsVersion not found or not set correctly.") + return() +endif() + +if(NOT FoundCFTargetsImport) + set(RunCMake_TEST_FAILED "Import of Compact Framework targets file not found or not set correctly.") + return() +endif() diff --git a/Tests/RunCMake/VS10ProjectWinCE/VsCSharpCFProject.cmake b/Tests/RunCMake/VS10ProjectWinCE/VsCSharpCFProject.cmake new file mode 100644 index 0000000..fb2acbb --- /dev/null +++ b/Tests/RunCMake/VS10ProjectWinCE/VsCSharpCFProject.cmake @@ -0,0 +1,8 @@ +enable_language(CSharp) + +add_library(foo SHARED foo.cs ) + +set_target_properties(foo + PROPERTIES + DOTNET_TARGET_FRAMEWORK_VERSION "v3.9" +) diff --git a/Tests/RunCMake/ctest_submit/FailDrop-http-stdout.txt b/Tests/RunCMake/ctest_submit/FailDrop-http-stdout.txt index c7f35c5..c9111b0 100644 --- a/Tests/RunCMake/ctest_submit/FailDrop-http-stdout.txt +++ b/Tests/RunCMake/ctest_submit/FailDrop-http-stdout.txt @@ -1,3 +1,2 @@ -Submit files \(using http\) - Using HTTP submit method - Drop site:http:// +Submit files + SubmitURL: http://-no-site- diff --git a/Tests/RunCMake/ctest_submit/FailDrop-https-stdout.txt b/Tests/RunCMake/ctest_submit/FailDrop-https-stdout.txt index 19f8234..2c67eb9 100644 --- a/Tests/RunCMake/ctest_submit/FailDrop-https-stdout.txt +++ b/Tests/RunCMake/ctest_submit/FailDrop-https-stdout.txt @@ -1,3 +1,2 @@ -Submit files \(using https\) - Using HTTP submit method - Drop site:https:// +Submit files + SubmitURL: https://-no-site- diff --git a/Tests/RunCMake/file/CREATE_LINK-COPY_ON_ERROR.cmake b/Tests/RunCMake/file/CREATE_LINK-COPY_ON_ERROR.cmake new file mode 100644 index 0000000..777ef4e --- /dev/null +++ b/Tests/RunCMake/file/CREATE_LINK-COPY_ON_ERROR.cmake @@ -0,0 +1,11 @@ +# Use COPY_ON_ERROR to handle the case where the source and destination +# directory are on different devices. Cross-device links are not permitted +# and the following command falls back to copying the file if link fails. +file(CREATE_LINK + ${CMAKE_CURRENT_LIST_FILE} TestCreateLink.cmake + RESULT result + COPY_ON_ERROR + ) +if(NOT result STREQUAL "0") + message(SEND_ERROR "COPY_ON_ERROR failed: '${result}'") +endif() diff --git a/Tests/RunCMake/file/CREATE_LINK-SYMBOLIC-noexist.cmake b/Tests/RunCMake/file/CREATE_LINK-SYMBOLIC-noexist.cmake new file mode 100644 index 0000000..61aaf38 --- /dev/null +++ b/Tests/RunCMake/file/CREATE_LINK-SYMBOLIC-noexist.cmake @@ -0,0 +1,4 @@ +file(CREATE_LINK does_not_exist.txt TestSymLink.txt RESULT sym_result SYMBOLIC) +if(NOT sym_result STREQUAL "0") + message("Symlink fail: ${sym_result}") +endif() diff --git a/Tests/RunCMake/file/CREATE_LINK-SYMBOLIC.cmake b/Tests/RunCMake/file/CREATE_LINK-SYMBOLIC.cmake new file mode 100644 index 0000000..77b899c --- /dev/null +++ b/Tests/RunCMake/file/CREATE_LINK-SYMBOLIC.cmake @@ -0,0 +1,4 @@ +file(CREATE_LINK ${CMAKE_CURRENT_LIST_FILE} TestSymLink.cmake RESULT sym_result SYMBOLIC) +if(NOT sym_result STREQUAL "0") + message(SEND_ERROR "Symlink result='${sym_result}'") +endif() diff --git a/Tests/RunCMake/file/CREATE_LINK-noarg-result.txt b/Tests/RunCMake/file/CREATE_LINK-noarg-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/CREATE_LINK-noarg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/CREATE_LINK-noarg-stderr.txt b/Tests/RunCMake/file/CREATE_LINK-noarg-stderr.txt new file mode 100644 index 0000000..12494f8 --- /dev/null +++ b/Tests/RunCMake/file/CREATE_LINK-noarg-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at CREATE_LINK-noarg\.cmake:[0-9]+ \(file\): + file CREATE_LINK must be called with at least two additional arguments +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/file/CREATE_LINK-noarg.cmake b/Tests/RunCMake/file/CREATE_LINK-noarg.cmake new file mode 100644 index 0000000..65002fa --- /dev/null +++ b/Tests/RunCMake/file/CREATE_LINK-noarg.cmake @@ -0,0 +1 @@ +file(CREATE_LINK ${CMAKE_CURRENT_LIST_FILE}) diff --git a/Tests/RunCMake/file/CREATE_LINK-noexist-stderr.txt b/Tests/RunCMake/file/CREATE_LINK-noexist-stderr.txt new file mode 100644 index 0000000..97eee4f --- /dev/null +++ b/Tests/RunCMake/file/CREATE_LINK-noexist-stderr.txt @@ -0,0 +1 @@ +Hard link error: Cannot hard link 'does_not_exist.txt' as it does not exist. diff --git a/Tests/RunCMake/file/CREATE_LINK-noexist.cmake b/Tests/RunCMake/file/CREATE_LINK-noexist.cmake new file mode 100644 index 0000000..5ee2580 --- /dev/null +++ b/Tests/RunCMake/file/CREATE_LINK-noexist.cmake @@ -0,0 +1,4 @@ +file(CREATE_LINK does_not_exist.txt TestLink.txt RESULT result) +if(NOT result STREQUAL "0") + message("Hard link error: ${result}") +endif() diff --git a/Tests/RunCMake/file/CREATE_LINK.cmake b/Tests/RunCMake/file/CREATE_LINK.cmake new file mode 100644 index 0000000..ca61646 --- /dev/null +++ b/Tests/RunCMake/file/CREATE_LINK.cmake @@ -0,0 +1,11 @@ +# start with a file in the same directory to avoid cross-device links +set(test_file ${CMAKE_CURRENT_BINARY_DIR}/CreateLinkTest.txt) +file(TOUCH ${test_file}) + +file(CREATE_LINK + ${test_file} ${CMAKE_CURRENT_BINARY_DIR}/TestCreateLink.txt + RESULT result + ) +if(NOT result STREQUAL "0") + message(SEND_ERROR "Hard link result='${result}'") +endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index b872824..128e8f3 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -1,5 +1,9 @@ include(RunCMake) +run_cmake(CREATE_LINK) +run_cmake(CREATE_LINK-COPY_ON_ERROR) +run_cmake(CREATE_LINK-noarg) +run_cmake(CREATE_LINK-noexist) run_cmake(DOWNLOAD-hash-mismatch) run_cmake(DOWNLOAD-unused-argument) run_cmake(DOWNLOAD-httpheader-not-set) @@ -53,6 +57,8 @@ run_cmake_command(GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE.cmake) if(NOT WIN32 OR CYGWIN) + run_cmake(CREATE_LINK-SYMBOLIC) + run_cmake(CREATE_LINK-SYMBOLIC-noexist) run_cmake(GLOB_RECURSE-cyclic-recursion) run_cmake(INSTALL-SYMLINK) run_cmake(READ_SYMLINK) diff --git a/Tests/RunCMake/find_package/PackageRoot/ResolvedConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/ResolvedConfig.cmake new file mode 100644 index 0000000..4496a05 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRoot/ResolvedConfig.cmake @@ -0,0 +1 @@ +set(Resolved_DIR "${CMAKE_CURRENT_LIST_DIR}") diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index e9f3558..066523e 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -26,3 +26,6 @@ run_cmake(WrongVersionConfig) run_cmake(CMP0084-OLD) run_cmake(CMP0084-WARN) run_cmake(CMP0084-NEW) +if(UNIX) + run_cmake(SetFoundResolved) +endif() diff --git a/Tests/RunCMake/find_package/SetFoundResolved-stderr.txt b/Tests/RunCMake/find_package/SetFoundResolved-stderr.txt new file mode 100644 index 0000000..ea94be5 --- /dev/null +++ b/Tests/RunCMake/find_package/SetFoundResolved-stderr.txt @@ -0,0 +1,10 @@ +CMake Warning at SetFoundResolved.cmake:10 \(message\): + .*/Tests/RunCMake/find_package/symlink +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) + + +CMake Warning at SetFoundResolved.cmake:15 \(message\): + .*/Tests/RunCMake/find_package/PackageRoot +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/find_package/SetFoundResolved.cmake b/Tests/RunCMake/find_package/SetFoundResolved.cmake new file mode 100644 index 0000000..8d56513 --- /dev/null +++ b/Tests/RunCMake/find_package/SetFoundResolved.cmake @@ -0,0 +1,17 @@ +# Create ./symlink pointing back here. +execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink + PackageRoot "${CMAKE_CURRENT_SOURCE_DIR}/symlink") + +# Make find_package search through the symlink. +set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/symlink") + +# Test preservation of symlinks. +find_package(Resolved) +message(WARNING "${Resolved_DIR}") + +# Test resolving symlinks. +set(CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS ON) +find_package(Resolved) +message(WARNING "${Resolved_DIR}") + +file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/symlink") diff --git a/Tests/RunCMake/include_external_msproject/check_utils.cmake b/Tests/RunCMake/include_external_msproject/check_utils.cmake index e9e9cac..0a2ba63 100644 --- a/Tests/RunCMake/include_external_msproject/check_utils.cmake +++ b/Tests/RunCMake/include_external_msproject/check_utils.cmake @@ -100,6 +100,8 @@ function(check_project test name guid type platform imported_release_config_name set(platform "${RunCMake_GENERATOR_PLATFORM}") elseif("${RunCMake_GENERATOR}" MATCHES "Win64") set(platform "x64") + elseif(VS_PLATFORM_NAME) + set(platform "${VS_PLATFORM_NAME}") else() set(platform "Win32") endif() diff --git a/Tests/SubDirSpaces/CMakeLists.txt b/Tests/SubDirSpaces/CMakeLists.txt index 40c265e..0d45db8 100644 --- a/Tests/SubDirSpaces/CMakeLists.txt +++ b/Tests/SubDirSpaces/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 2.6) project(SUBDIR) # Some systems do not seem to support rpath with spaces. -if(CMAKE_SYSTEM_NAME MATCHES "IRIX|QNX") +if(CMAKE_SYSTEM_NAME MATCHES "QNX") set(CMAKE_SKIP_BUILD_RPATH 1) endif() diff --git a/Tests/VSExternalInclude/CMakeLists.txt b/Tests/VSExternalInclude/CMakeLists.txt index 7465243..8ca7252 100644 --- a/Tests/VSExternalInclude/CMakeLists.txt +++ b/Tests/VSExternalInclude/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 2.6) project(VSExternalInclude) -if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[01245]") +if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[012456]") set(PROJECT_EXT vcxproj) else() set(PROJECT_EXT vcproj) @@ -55,7 +55,7 @@ add_dependencies(VSExternalInclude lib2) # and the sln file can no longer be the only source # of that depend. So, for VS 10 make the executable # depend on lib1 and lib2 -if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[01245]") +if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[012456]") add_dependencies(VSExternalInclude lib1) endif() diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index c5231bb..482a08d 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -55,6 +55,9 @@ # HACK: iwyu wrongly thinks that <system_error> is needed for std::hash { symbol: [ "std::hash", private, "<functional>", public ] }, + # HACK: iwyu thinks we use a libstdc++ private type + { symbol: [ "__gnu_cxx::size_t", private, "<cstddef>", public ] }, + # __decay_and_strip is used internally in the C++11 standard library. # IWYU does not classify it as internal and suggests to add <type_traits>. # To ignore it, we simply map it to a file that is included anyway. @@ -94,7 +97,7 @@ { include: [ "<json/writer.h>", private, "\"cm_jsoncpp_writer.h\"", public ] }, { include: [ "<rhash.h>", private, "\"cm_rhash.h\"", public ] }, { include: [ "<uv.h>", private, "\"cm_uv.h\"", public ] }, - { include: [ "@<uv-.+\\.h>", private, "\"cm_uv.h\"", public ] }, + { include: [ "@<uv[/-].+\\.h>", private, "\"cm_uv.h\"", public ] }, { include: [ "<kwiml/abi.h>", private, "\"cm_kwiml.h\"", public ] }, { include: [ "<kwiml/int.h>", private, "\"cm_kwiml.h\"", public ] }, { include: [ "<zconf.h>", private, "\"cm_zlib.h\"", public ] }, @@ -111,7 +114,7 @@ { include: [ "\"cmjsoncpp/include/json/writer.h\"", private, "\"cm_jsoncpp_writer.h\"", public ] }, { include: [ "\"cmlibrhash/librhash/rhash.h\"", private, "\"cm_rhash.h\"", public ] }, { include: [ "\"cmlibuv/include/uv.h\"", private, "\"cm_uv.h\"", public ] }, - { include: [ "@\"cmlibuv/include/uv-.+\\.h\"", private, "\"cm_uv.h\"", public ] }, + { include: [ "@\"cmlibuv/include/uv/.+\\.h\"", private, "\"cm_uv.h\"", public ] }, { include: [ "\"KWIML/include/kwiml/abi.h\"", private, "\"cm_kwiml.h\"", public ] }, { include: [ "\"KWIML/include/kwiml/int.h\"", private, "\"cm_kwiml.h\"", public ] }, { include: [ "\"cmzlib/cm_zlib_mangle.h\"", private, "\"cm_zlib.h\"", public ] }, diff --git a/Utilities/Release/win32_release.cmake b/Utilities/Release/win32_release.cmake index 2e817d9..c03c665 100644 --- a/Utilities/Release/win32_release.cmake +++ b/Utilities/Release/win32_release.cmake @@ -25,13 +25,13 @@ BUILD_QtDialog:BOOL=TRUE CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3 CMAKE_C_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG CMAKE_CXX_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG -CMAKE_EXE_LINKER_FLAGS:STRING=-machine:x86 -subsystem:console,5.01 +CMAKE_EXE_LINKER_FLAGS:STRING=-machine:x86 -subsystem:console,6.01 CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES:STRING=${qt_win_libs} CMAKE_PREFIX_PATH:STRING=${qt_prefix} CMake_TEST_Qt4:BOOL=OFF CMake_TEST_Qt5:BOOL=OFF ") -set(ppflags "-D_WIN32_WINNT=0x501 -DNTDDI_VERSION=0x05010000 -D_USING_V110_SDK71_") +set(ppflags "-D_WIN32_WINNT=0x601 -DNTDDI_VERSION=0x06010000 -D_USING_V110_SDK71_") set(CFLAGS "${ppflags}") set(CXXFLAGS "${ppflags}") set(ENV ". ~/rel/env32") diff --git a/Utilities/Release/win64_release.cmake b/Utilities/Release/win64_release.cmake index 33af830..8417206 100644 --- a/Utilities/Release/win64_release.cmake +++ b/Utilities/Release/win64_release.cmake @@ -25,13 +25,13 @@ BUILD_QtDialog:BOOL=TRUE CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3 CMAKE_C_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG CMAKE_CXX_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG -CMAKE_EXE_LINKER_FLAGS:STRING=-machine:x64 -subsystem:console,5.02 +CMAKE_EXE_LINKER_FLAGS:STRING=-machine:x64 -subsystem:console,6.01 CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES:STRING=${qt_win_libs} CMAKE_PREFIX_PATH:STRING=${qt_prefix} CMake_TEST_Qt4:BOOL=OFF CMake_TEST_Qt5:BOOL=OFF ") -set(ppflags "-D_WIN32_WINNT=0x502 -DNTDDI_VERSION=0x05020000 -D_USING_V110_SDK71_") +set(ppflags "-D_WIN32_WINNT=0x601 -DNTDDI_VERSION=0x06010000 -D_USING_V110_SDK71_") set(CFLAGS "${ppflags}") set(CXXFLAGS "${ppflags}") set(ENV ". ~/rel/env64") diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt index 9ae7aa3..1c96497 100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@ -29,7 +29,7 @@ set(DISABLED_THREADSAFE OFF CACHE INTERNAL "Curl can use thread-safe functions") set(ENABLE_ARES OFF CACHE INTERNAL "No curl c-ares support") set(ENABLE_CURLDEBUG OFF CACHE INTERNAL "No curl TrackMemory features") set(ENABLE_DEBUG OFF CACHE INTERNAL "No curl debug features") -set(ENABLE_IPV6 OFF CACHE INTERNAL "No curl IPv6 support") +set(ENABLE_IPV6 ON CACHE INTERNAL "Enable curl IPv6 support detection") set(ENABLE_MANUAL OFF CACHE INTERNAL "No curl built-in manual") set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS lookup") set(ENABLE_UNIX_SOCKETS OFF CACHE INTERNAL "No curl Unix domain sockets support") diff --git a/Utilities/cmliblzma/liblzma/simple/x86.c b/Utilities/cmliblzma/liblzma/simple/x86.c index 23d0c42..b38cebf 100644 --- a/Utilities/cmliblzma/liblzma/simple/x86.c +++ b/Utilities/cmliblzma/liblzma/simple/x86.c @@ -97,7 +97,7 @@ x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder, if (!Test86MSByte(b)) break; - src = dest ^ ((1u << (32 - i * 8)) - 1); + src = dest ^ ((1ull << (32 - i * 8)) - 1); } buffer[buffer_pos + 4] diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index a503041..a62c516 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -14,16 +14,21 @@ set(uv_libraries ${CMAKE_THREAD_LIBS_INIT}) set(uv_includes include src) set(uv_headers include/uv.h - include/uv-errno.h - include/uv-threadpool.h - include/uv-version.h + include/uv/errno.h + include/uv/threadpool.h + include/uv/version.h ) set(uv_sources src/fs-poll.c src/heap-inl.h + src/idna.c + src/idna.h src/inet.c src/queue.h + src/strscpy.c + src/strscpy.h src/threadpool.c + src/timer.c src/uv-common.c src/uv-common.h src/uv-data-getter-setters.c @@ -45,7 +50,7 @@ if(WIN32) _WIN32_WINNT=0x0600 ) list(APPEND uv_headers - include/uv-win.h + include/uv/win.h include/tree.h ) list(APPEND uv_sources @@ -67,7 +72,6 @@ if(WIN32) src/win/poll.c src/win/process-stdio.c src/win/process.c - src/win/req.c src/win/req-inl.h src/win/signal.c src/win/snprintf.c @@ -75,7 +79,6 @@ if(WIN32) src/win/stream-inl.h src/win/tcp.c src/win/thread.c - src/win/timer.c src/win/tty.c src/win/udp.c src/win/util.c @@ -89,7 +92,7 @@ else() src/unix ) list(APPEND uv_headers - include/uv-unix.h + include/uv/unix.h ) list(APPEND uv_sources src/unix/async.c @@ -110,7 +113,6 @@ else() src/unix/stream.c src/unix/tcp.c src/unix/thread.c - src/unix/timer.c src/unix/tty.c src/unix/udp.c ) @@ -121,7 +123,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX") perfstat ) list(APPEND uv_headers - include/uv-aix.h + include/uv/aix.h ) list(APPEND uv_defines _ALL_SOURCE @@ -139,7 +141,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN") list(APPEND uv_libraries ) list(APPEND uv_headers - include/uv-posix.h + include/uv/posix.h ) list(APPEND uv_defines ) @@ -158,8 +160,7 @@ endif() if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") list(APPEND uv_headers - include/uv-darwin.h - include/pthread-barrier.h + include/uv/darwin.h ) list(APPEND uv_defines _DARWIN_USE_64_BIT_INODE=1 @@ -178,7 +179,7 @@ endif() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") list(APPEND uv_libraries dl rt) list(APPEND uv_headers - include/uv-linux.h + include/uv/linux.h ) list(APPEND uv_defines _GNU_SOURCE) list(APPEND uv_sources @@ -198,10 +199,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") kvm ) list(APPEND uv_headers - include/uv-bsd.h + include/uv/bsd.h ) list(APPEND uv_sources src/unix/bsd-ifaddrs.c + src/unix/bsd-proctitle.c src/unix/freebsd.c src/unix/kqueue.c src/unix/posix-hrtime.c @@ -214,10 +216,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "kFreeBSD") kvm ) list(APPEND uv_headers - include/uv-bsd.h + include/uv/bsd.h ) list(APPEND uv_sources src/unix/bsd-ifaddrs.c + src/unix/bsd-proctitle.c src/unix/freebsd.c src/unix/kqueue.c src/unix/posix-hrtime.c @@ -229,10 +232,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") kvm ) list(APPEND uv_headers - include/uv-bsd.h + include/uv/bsd.h ) list(APPEND uv_sources src/unix/bsd-ifaddrs.c + src/unix/bsd-proctitle.c src/unix/netbsd.c src/unix/kqueue.c src/unix/posix-hrtime.c @@ -244,10 +248,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") kvm ) list(APPEND uv_headers - include/uv-bsd.h + include/uv/bsd.h ) list(APPEND uv_sources src/unix/bsd-ifaddrs.c + src/unix/bsd-proctitle.c src/unix/openbsd.c src/unix/kqueue.c src/unix/posix-hrtime.c @@ -263,7 +268,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") rt ) list(APPEND uv_headers - include/uv-sunos.h + include/uv/sunos.h ) list(APPEND uv_defines __EXTENSIONS__ diff --git a/Utilities/cmlibuv/include/pthread-barrier.h b/Utilities/cmlibuv/include/pthread-barrier.h deleted file mode 100644 index 07db9b8a..0000000 --- a/Utilities/cmlibuv/include/pthread-barrier.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (c) 2016, Kari Tristan Helgason <kthelgason@gmail.com> - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#ifndef _UV_PTHREAD_BARRIER_ -#define _UV_PTHREAD_BARRIER_ -#include <errno.h> -#include <pthread.h> -#if !defined(__MVS__) -#include <semaphore.h> /* sem_t */ -#endif - -#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 -#define UV__PTHREAD_BARRIER_FALLBACK 1 - -/* - * To maintain ABI compatibility with - * libuv v1.x struct is padded according - * to target platform - */ -#if defined(__ANDROID__) -# define UV_BARRIER_STRUCT_PADDING \ - sizeof(pthread_mutex_t) + \ - sizeof(pthread_cond_t) + \ - sizeof(unsigned int) - \ - sizeof(void *) -#elif defined(__APPLE__) -# define UV_BARRIER_STRUCT_PADDING \ - sizeof(pthread_mutex_t) + \ - 2 * sizeof(sem_t) + \ - 2 * sizeof(unsigned int) - \ - sizeof(void *) -#else -# define UV_BARRIER_STRUCT_PADDING 0 -#endif - -typedef struct { - pthread_mutex_t mutex; - pthread_cond_t cond; - unsigned threshold; - unsigned in; - unsigned out; -} _uv_barrier; - -typedef struct { - _uv_barrier* b; - char _pad[UV_BARRIER_STRUCT_PADDING]; -} pthread_barrier_t; - -int pthread_barrier_init(pthread_barrier_t* barrier, - const void* barrier_attr, - unsigned count); - -int pthread_barrier_wait(pthread_barrier_t* barrier); -int pthread_barrier_destroy(pthread_barrier_t *barrier); - -#endif /* _UV_PTHREAD_BARRIER_ */ diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h index 74fa00d..e6dc736 100644 --- a/Utilities/cmlibuv/include/uv.h +++ b/Utilities/cmlibuv/include/uv.h @@ -49,21 +49,21 @@ extern "C" { # define UV_EXTERN /* nothing */ #endif -#include "uv-errno.h" -#include "uv-version.h" +#include "uv/errno.h" +#include "uv/version.h" #include <stddef.h> #include <stdio.h> #if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" +# include "uv/stdint-msvc2008.h" #else # include <stdint.h> #endif #if defined(_WIN32) -# include "uv-win.h" +# include "uv/win.h" #else -# include "uv-unix.h" +# include "uv/unix.h" #endif /* Expand this list if necessary. */ @@ -146,6 +146,7 @@ extern "C" { XX(EHOSTDOWN, "host is down") \ XX(EREMOTEIO, "remote I/O error") \ XX(ENOTTY, "inappropriate ioctl for device") \ + XX(EFTYPE, "inappropriate file type or format") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \ @@ -237,6 +238,7 @@ typedef struct uv_cpu_info_s uv_cpu_info_t; typedef struct uv_interface_address_s uv_interface_address_t; typedef struct uv_dirent_s uv_dirent_t; typedef struct uv_passwd_s uv_passwd_t; +typedef struct uv_utsname_s uv_utsname_t; typedef enum { UV_LOOP_BLOCK_SIGNAL @@ -373,7 +375,10 @@ typedef enum { UV_EXTERN int uv_translate_sys_error(int sys_errno); UV_EXTERN const char* uv_strerror(int err); +UV_EXTERN char* uv_strerror_r(int err, char* buf, size_t buflen); + UV_EXTERN const char* uv_err_name(int err); +UV_EXTERN char* uv_err_name_r(int err, char* buf, size_t buflen); #define UV_REQ_FIELDS \ @@ -507,7 +512,7 @@ UV_EXTERN int uv_try_write(uv_stream_t* handle, struct uv_write_s { UV_REQ_FIELDS uv_write_cb cb; - uv_stream_t* send_handle; + uv_stream_t* send_handle; /* TODO: make private and unix-only in v2.x. */ uv_stream_t* handle; UV_WRITE_PRIVATE_FIELDS }; @@ -869,7 +874,13 @@ typedef enum { * flags may be specified to create a duplex data stream. */ UV_READABLE_PIPE = 0x10, - UV_WRITABLE_PIPE = 0x20 + UV_WRITABLE_PIPE = 0x20, + + /* + * Open the child pipe handle in overlapped mode on Windows. + * On Unix it is silently ignored. + */ + UV_OVERLAPPED_PIPE = 0x40 } uv_stdio_flags; typedef struct uv_stdio_container_s { @@ -970,11 +981,22 @@ enum uv_process_flags { */ UV_PROCESS_DETACHED = (1 << 3), /* + * Hide the subprocess window that would normally be created. This option is + * only meaningful on Windows systems. On Unix it is silently ignored. + */ + UV_PROCESS_WINDOWS_HIDE = (1 << 4), + /* * Hide the subprocess console window that would normally be created. This * option is only meaningful on Windows systems. On Unix it is silently * ignored. */ - UV_PROCESS_WINDOWS_HIDE = (1 << 4) + UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5), + /* + * Hide the subprocess GUI window that would normally be created. This + * option is only meaningful on Windows systems. On Unix it is silently + * ignored. + */ + UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6) }; /* @@ -1014,16 +1036,18 @@ UV_EXTERN int uv_queue_work(uv_loop_t* loop, UV_EXTERN int uv_cancel(uv_req_t* req); +struct uv_cpu_times_s { + uint64_t user; + uint64_t nice; + uint64_t sys; + uint64_t idle; + uint64_t irq; +}; + struct uv_cpu_info_s { char* model; int speed; - struct uv_cpu_times_s { - uint64_t user; - uint64_t nice; - uint64_t sys; - uint64_t idle; - uint64_t irq; - } cpu_times; + struct uv_cpu_times_s cpu_times; }; struct uv_interface_address_s { @@ -1048,6 +1072,16 @@ struct uv_passwd_s { char* homedir; }; +struct uv_utsname_s { + char sysname[256]; + char release[256]; + char version[256]; + char machine[256]; + /* This struct does not contain the nodename and domainname fields present in + the utsname type. domainname is a GNU extension. Both fields are referred + to as meaningless in the docs. */ +}; + typedef enum { UV_DIRENT_UNKNOWN, UV_DIRENT_FILE, @@ -1070,6 +1104,7 @@ UV_EXTERN int uv_set_process_title(const char* title); UV_EXTERN int uv_resident_set_memory(size_t* rss); UV_EXTERN int uv_uptime(double* uptime); UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd); +UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd); typedef struct { long tv_sec; @@ -1104,6 +1139,16 @@ UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd); UV_EXTERN uv_pid_t uv_os_getpid(void); UV_EXTERN uv_pid_t uv_os_getppid(void); +#define UV_PRIORITY_LOW 19 +#define UV_PRIORITY_BELOW_NORMAL 10 +#define UV_PRIORITY_NORMAL 0 +#define UV_PRIORITY_ABOVE_NORMAL -7 +#define UV_PRIORITY_HIGH -14 +#define UV_PRIORITY_HIGHEST -20 + +UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority); +UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority); + UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count); UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count); UV_EXTERN int uv_cpumask_size(void); @@ -1119,6 +1164,8 @@ UV_EXTERN int uv_os_unsetenv(const char* name); UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size); +UV_EXTERN int uv_os_uname(uv_utsname_t* buffer); + typedef enum { UV_FS_UNKNOWN = -1, @@ -1151,7 +1198,8 @@ typedef enum { UV_FS_CHOWN, UV_FS_FCHOWN, UV_FS_REALPATH, - UV_FS_COPYFILE + UV_FS_COPYFILE, + UV_FS_LCHOWN } uv_fs_type; /* uv_fs_t is a subclass of uv_req_t. */ @@ -1354,6 +1402,12 @@ UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); +UV_EXTERN int uv_fs_lchown(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_uid_t uid, + uv_gid_t gid, + uv_fs_cb cb); enum uv_fs_event { diff --git a/Utilities/cmlibuv/include/uv-aix.h b/Utilities/cmlibuv/include/uv/aix.h index 7dc992f..7dc992f 100644 --- a/Utilities/cmlibuv/include/uv-aix.h +++ b/Utilities/cmlibuv/include/uv/aix.h diff --git a/Utilities/cmlibuv/include/android-ifaddrs.h b/Utilities/cmlibuv/include/uv/android-ifaddrs.h index 9cd19fe..9cd19fe 100644 --- a/Utilities/cmlibuv/include/android-ifaddrs.h +++ b/Utilities/cmlibuv/include/uv/android-ifaddrs.h diff --git a/Utilities/cmlibuv/include/uv-bsd.h b/Utilities/cmlibuv/include/uv/bsd.h index 2d72b3d..2d72b3d 100644 --- a/Utilities/cmlibuv/include/uv-bsd.h +++ b/Utilities/cmlibuv/include/uv/bsd.h diff --git a/Utilities/cmlibuv/include/uv-darwin.h b/Utilities/cmlibuv/include/uv/darwin.h index d226415..d226415 100644 --- a/Utilities/cmlibuv/include/uv-darwin.h +++ b/Utilities/cmlibuv/include/uv/darwin.h diff --git a/Utilities/cmlibuv/include/uv-errno.h b/Utilities/cmlibuv/include/uv/errno.h index aa4d450..8eeb95d 100644 --- a/Utilities/cmlibuv/include/uv-errno.h +++ b/Utilities/cmlibuv/include/uv/errno.h @@ -433,5 +433,11 @@ # define UV__ENOTTY (-4029) #endif +#if defined(EFTYPE) && !defined(_WIN32) +# define UV__EFTYPE UV__ERR(EFTYPE) +#else +# define UV__EFTYPE (-4028) +#endif + #endif /* UV_ERRNO_H_ */ diff --git a/Utilities/cmlibuv/include/uv-linux.h b/Utilities/cmlibuv/include/uv/linux.h index 9b38405..9b38405 100644 --- a/Utilities/cmlibuv/include/uv-linux.h +++ b/Utilities/cmlibuv/include/uv/linux.h diff --git a/Utilities/cmlibuv/include/uv-os390.h b/Utilities/cmlibuv/include/uv/os390.h index 0267d74..0267d74 100644 --- a/Utilities/cmlibuv/include/uv-os390.h +++ b/Utilities/cmlibuv/include/uv/os390.h diff --git a/Utilities/cmlibuv/include/uv-posix.h b/Utilities/cmlibuv/include/uv/posix.h index 9a96634..9a96634 100644 --- a/Utilities/cmlibuv/include/uv-posix.h +++ b/Utilities/cmlibuv/include/uv/posix.h diff --git a/Utilities/cmlibuv/include/stdint-msvc2008.h b/Utilities/cmlibuv/include/uv/stdint-msvc2008.h index d02608a..d02608a 100644 --- a/Utilities/cmlibuv/include/stdint-msvc2008.h +++ b/Utilities/cmlibuv/include/uv/stdint-msvc2008.h diff --git a/Utilities/cmlibuv/include/uv-sunos.h b/Utilities/cmlibuv/include/uv/sunos.h index 0421664..0421664 100644 --- a/Utilities/cmlibuv/include/uv-sunos.h +++ b/Utilities/cmlibuv/include/uv/sunos.h diff --git a/Utilities/cmlibuv/include/uv-threadpool.h b/Utilities/cmlibuv/include/uv/threadpool.h index 9708ebd..9708ebd 100644 --- a/Utilities/cmlibuv/include/uv-threadpool.h +++ b/Utilities/cmlibuv/include/uv/threadpool.h diff --git a/Utilities/cmlibuv/include/tree.h b/Utilities/cmlibuv/include/uv/tree.h index f936416..f936416 100644 --- a/Utilities/cmlibuv/include/tree.h +++ b/Utilities/cmlibuv/include/uv/tree.h diff --git a/Utilities/cmlibuv/include/uv-unix.h b/Utilities/cmlibuv/include/uv/unix.h index 455674d..3c1b363 100644 --- a/Utilities/cmlibuv/include/uv-unix.h +++ b/Utilities/cmlibuv/include/uv/unix.h @@ -42,34 +42,32 @@ #include <pthread.h> #include <signal.h> -#include "uv-threadpool.h" +#include "threadpool.h" #ifdef CMAKE_BOOTSTRAP -# include "uv-posix.h" +# include "posix.h" #elif defined(__linux__) -# include "uv-linux.h" +# include "linux.h" #elif defined (__MVS__) -# include "uv-os390.h" +# include "os390.h" #elif defined(__PASE__) -# include "uv-posix.h" +# include "posix.h" #elif defined(_AIX) -# include "uv-aix.h" +# include "aix.h" #elif defined(__sun) -# include "uv-sunos.h" +# include "sunos.h" #elif defined(__APPLE__) -# include "uv-darwin.h" +# include "darwin.h" #elif defined(__DragonFly__) || \ defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) -# include "uv-bsd.h" +# include "bsd.h" #elif defined(__CYGWIN__) || defined(__MSYS__) -# include "uv-posix.h" -#endif - -#ifndef PTHREAD_BARRIER_SERIAL_THREAD -# include "pthread-barrier.h" +# include "posix.h" +#elif defined(__GNU__) +# include "posix.h" #endif #ifndef NI_MAXHOST @@ -149,9 +147,30 @@ typedef pthread_rwlock_t uv_rwlock_t; typedef UV_PLATFORM_SEM_T uv_sem_t; typedef pthread_cond_t uv_cond_t; typedef pthread_key_t uv_key_t; + +/* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */ +#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) +/* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */ +struct _uv_barrier { + uv_mutex_t mutex; + uv_cond_t cond; + unsigned threshold; + unsigned in; + unsigned out; +}; + +typedef struct { + struct _uv_barrier* b; +# if defined(PTHREAD_BARRIER_SERIAL_THREAD) + /* TODO(bnoordhuis) Remove padding in v2. */ + char pad[sizeof(pthread_barrier_t) - sizeof(struct _uv_barrier*)]; +# endif +} uv_barrier_t; +#else typedef pthread_barrier_t uv_barrier_t; #endif +#endif /* Platform-specific definitions for uv_spawn support. */ typedef gid_t uv_gid_t; diff --git a/Utilities/cmlibuv/include/uv-version.h b/Utilities/cmlibuv/include/uv/version.h index 06c6711..abc140a 100644 --- a/Utilities/cmlibuv/include/uv-version.h +++ b/Utilities/cmlibuv/include/uv/version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 20 -#define UV_VERSION_PATCH 3 +#define UV_VERSION_MINOR 24 +#define UV_VERSION_PATCH 2 #define UV_VERSION_IS_RELEASE 0 #define UV_VERSION_SUFFIX "dev" diff --git a/Utilities/cmlibuv/include/uv-win.h b/Utilities/cmlibuv/include/uv/win.h index 6486aab..f3d3809 100644 --- a/Utilities/cmlibuv/include/uv-win.h +++ b/Utilities/cmlibuv/include/uv/win.h @@ -25,6 +25,7 @@ #if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) typedef intptr_t ssize_t; +# define SSIZE_MAX INTPTR_MAX # define _SSIZE_T_ # define _SSIZE_T_DEFINED #endif @@ -59,7 +60,7 @@ typedef struct pollfd { #endif #include "tree.h" -#include "uv-threadpool.h" +#include "threadpool.h" #define MAX_PIPENAME_LEN 256 @@ -86,8 +87,16 @@ typedef struct pollfd { #define SIGKILL 9 #define SIGWINCH 28 -/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many */ -/* unix-like platforms. However MinGW doesn't define it, so we do. */ +/* Redefine NSIG to take SIGWINCH into consideration */ +#if defined(NSIG) && NSIG <= SIGWINCH +# undef NSIG +#endif +#ifndef NSIG +# define NSIG SIGWINCH + 1 +#endif + +/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many unix-like + * platforms. However MinGW doesn't define it, so we do. */ #ifndef SIGABRT_COMPAT # define SIGABRT_COMPAT 6 #endif @@ -255,7 +264,7 @@ typedef union { CRITICAL_SECTION waiters_count_lock; HANDLE signal_event; HANDLE broadcast_event; - } fallback; + } unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */ } uv_cond_t; typedef union { @@ -319,8 +328,6 @@ typedef struct { char* errmsg; } uv_lib_t; -RB_HEAD(uv_timer_tree_s, uv_timer_s); - #define UV_LOOP_PRIVATE_FIELDS \ /* The loop's I/O completion port */ \ HANDLE iocp; \ @@ -332,8 +339,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); uv_req_t* pending_reqs_tail; \ /* Head of a single-linked list of closed handles */ \ uv_handle_t* endgame_handles; \ - /* The head of the timers tree */ \ - struct uv_timer_tree_s timers; \ + /* TODO(bnoordhuis) Stop heap-allocating |timer_heap| in libuv v2.x. */ \ + void* timer_heap; \ /* Lists of active loop (prepare / check / idle) watchers */ \ uv_prepare_t* prepare_handles; \ uv_check_t* check_handles; \ @@ -379,10 +386,10 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); } u; \ struct uv_req_s* next_req; -#define UV_WRITE_PRIVATE_FIELDS \ - int ipc_header; \ - uv_buf_t write_buffer; \ - HANDLE event_handle; \ +#define UV_WRITE_PRIVATE_FIELDS \ + int coalesced; \ + uv_buf_t write_buffer; \ + HANDLE event_handle; \ HANDLE wait_handle; #define UV_CONNECT_PRIVATE_FIELDS \ @@ -470,16 +477,17 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); #define uv_pipe_connection_fields \ uv_timer_t* eof_timer; \ - uv_write_t ipc_header_write_req; \ - int ipc_pid; \ - uint64_t remaining_ipc_rawdata_bytes; \ - struct { \ - void* queue[2]; \ - int queue_len; \ - } pending_ipc_info; \ + uv_write_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \ + DWORD ipc_remote_pid; \ + union { \ + uint32_t payload_remaining; \ + uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \ + } ipc_data_frame; \ + void* ipc_xfer_queue[2]; \ + int ipc_xfer_queue_length; \ uv_write_t* non_overlapped_writes_tail; \ - uv_mutex_t readfile_mutex; \ - volatile HANDLE readfile_thread; + CRITICAL_SECTION readfile_thread_lock; \ + volatile HANDLE readfile_thread_handle; #define UV_PIPE_PRIVATE_FIELDS \ HANDLE handle; \ @@ -489,8 +497,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); struct { uv_pipe_connection_fields } conn; \ } pipe; -/* TODO: put the parser states in an union - TTY handles are always */ -/* half-duplex so read-state can safely overlap write-state. */ +/* TODO: put the parser states in an union - TTY handles are always half-duplex + * so read-state can safely overlap write-state. */ #define UV_TTY_PRIVATE_FIELDS \ HANDLE handle; \ union { \ @@ -539,8 +547,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); unsigned char events; #define UV_TIMER_PRIVATE_FIELDS \ - RB_ENTRY(uv_timer_s) tree_entry; \ - uint64_t due; \ + void* heap_node[3]; \ + int unused; \ + uint64_t timeout; \ uint64_t repeat; \ uint64_t start_id; \ uv_timer_cb timer_cb; diff --git a/Utilities/cmlibuv/src/fs-poll.c b/Utilities/cmlibuv/src/fs-poll.c index ee73d5a..6c82dfc 100644 --- a/Utilities/cmlibuv/src/fs-poll.c +++ b/Utilities/cmlibuv/src/fs-poll.c @@ -83,7 +83,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle, if (err < 0) goto error; - ctx->timer_handle.flags |= UV__HANDLE_INTERNAL; + ctx->timer_handle.flags |= UV_HANDLE_INTERNAL; uv__handle_unref(&ctx->timer_handle); err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb); @@ -248,7 +248,7 @@ static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) { #include "win/handle-inl.h" void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); + assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); uv__handle_close(handle); } diff --git a/Utilities/cmlibuv/src/idna.c b/Utilities/cmlibuv/src/idna.c new file mode 100644 index 0000000..13ffac6 --- /dev/null +++ b/Utilities/cmlibuv/src/idna.c @@ -0,0 +1,291 @@ +/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Derived from https://github.com/bnoordhuis/punycode + * but updated to support IDNA 2008. + */ + +#include "uv.h" +#include "idna.h" +#include <string.h> + +static unsigned uv__utf8_decode1_slow(const char** p, + const char* pe, + unsigned a) { + unsigned b; + unsigned c; + unsigned d; + unsigned min; + + if (a > 0xF7) + return -1; + + switch (*p - pe) { + default: + if (a > 0xEF) { + min = 0x10000; + a = a & 7; + b = (unsigned char) *(*p)++; + c = (unsigned char) *(*p)++; + d = (unsigned char) *(*p)++; + break; + } + /* Fall through. */ + case 2: + if (a > 0xDF) { + min = 0x800; + b = 0x80 | (a & 15); + c = (unsigned char) *(*p)++; + d = (unsigned char) *(*p)++; + a = 0; + break; + } + /* Fall through. */ + case 1: + if (a > 0xBF) { + min = 0x80; + b = 0x80; + c = 0x80 | (a & 31); + d = (unsigned char) *(*p)++; + a = 0; + break; + } + return -1; /* Invalid continuation byte. */ + } + + if (0x80 != (0xC0 & (b ^ c ^ d))) + return -1; /* Invalid sequence. */ + + b &= 63; + c &= 63; + d &= 63; + a = (a << 18) | (b << 12) | (c << 6) | d; + + if (a < min) + return -1; /* Overlong sequence. */ + + if (a > 0x10FFFF) + return -1; /* Four-byte sequence > U+10FFFF. */ + + if (a >= 0xD800 && a <= 0xDFFF) + return -1; /* Surrogate pair. */ + + return a; +} + +unsigned uv__utf8_decode1(const char** p, const char* pe) { + unsigned a; + + a = (unsigned char) *(*p)++; + + if (a < 128) + return a; /* ASCII, common case. */ + + return uv__utf8_decode1_slow(p, pe, a); +} + +#define foreach_codepoint(c, p, pe) \ + for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;) + +static int uv__idna_toascii_label(const char* s, const char* se, + char** d, char* de) { + static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789"; + const char* ss; + unsigned c; + unsigned h; + unsigned k; + unsigned n; + unsigned m; + unsigned q; + unsigned t; + unsigned x; + unsigned y; + unsigned bias; + unsigned delta; + unsigned todo; + int first; + + h = 0; + ss = s; + todo = 0; + + foreach_codepoint(c, &s, se) { + if (c < 128) + h++; + else if (c == (unsigned) -1) + return UV_EINVAL; + else + todo++; + } + + if (todo > 0) { + if (*d < de) *(*d)++ = 'x'; + if (*d < de) *(*d)++ = 'n'; + if (*d < de) *(*d)++ = '-'; + if (*d < de) *(*d)++ = '-'; + } + + x = 0; + s = ss; + foreach_codepoint(c, &s, se) { + if (c > 127) + continue; + + if (*d < de) + *(*d)++ = c; + + if (++x == h) + break; /* Visited all ASCII characters. */ + } + + if (todo == 0) + return h; + + /* Only write separator when we've written ASCII characters first. */ + if (h > 0) + if (*d < de) + *(*d)++ = '-'; + + n = 128; + bias = 72; + delta = 0; + first = 1; + + while (todo > 0) { + m = -1; + s = ss; + foreach_codepoint(c, &s, se) + if (c >= n) + if (c < m) + m = c; + + x = m - n; + y = h + 1; + + if (x > ~delta / y) + return UV_E2BIG; /* Overflow. */ + + delta += x * y; + n = m; + + s = ss; + foreach_codepoint(c, &s, se) { + if (c < n) + if (++delta == 0) + return UV_E2BIG; /* Overflow. */ + + if (c != n) + continue; + + for (k = 36, q = delta; /* empty */; k += 36) { + t = 1; + + if (k > bias) + t = k - bias; + + if (t > 26) + t = 26; + + if (q < t) + break; + + /* TODO(bnoordhuis) Since 1 <= t <= 26 and therefore + * 10 <= y <= 35, we can optimize the long division + * into a table-based reciprocal multiplication. + */ + x = q - t; + y = 36 - t; /* 10 <= y <= 35 since 1 <= t <= 26. */ + q = x / y; + t = t + x % y; /* 1 <= t <= 35 because of y. */ + + if (*d < de) + *(*d)++ = alphabet[t]; + } + + if (*d < de) + *(*d)++ = alphabet[q]; + + delta /= 2; + + if (first) { + delta /= 350; + first = 0; + } + + /* No overflow check is needed because |delta| was just + * divided by 2 and |delta+delta >= delta + delta/h|. + */ + h++; + delta += delta / h; + + for (bias = 0; delta > 35 * 26 / 2; bias += 36) + delta /= 35; + + bias += 36 * delta / (delta + 38); + delta = 0; + todo--; + } + + delta++; + n++; + } + + return 0; +} + +#undef foreach_codepoint + +long uv__idna_toascii(const char* s, const char* se, char* d, char* de) { + const char* si; + const char* st; + unsigned c; + char* ds; + int rc; + + ds = d; + + for (si = s; si < se; /* empty */) { + st = si; + c = uv__utf8_decode1(&si, se); + + if (c != '.') + if (c != 0x3002) /* 。 */ + if (c != 0xFF0E) /* . */ + if (c != 0xFF61) /* 。 */ + continue; + + rc = uv__idna_toascii_label(s, st, &d, de); + + if (rc < 0) + return rc; + + if (d < de) + *d++ = '.'; + + s = si; + } + + if (s < se) { + rc = uv__idna_toascii_label(s, se, &d, de); + + if (rc < 0) + return rc; + } + + if (d < de) + *d++ = '\0'; + + return d - ds; /* Number of bytes written. */ +} diff --git a/Utilities/cmlibuv/src/idna.h b/Utilities/cmlibuv/src/idna.h new file mode 100644 index 0000000..8e0c592 --- /dev/null +++ b/Utilities/cmlibuv/src/idna.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef UV_SRC_IDNA_H_ +#define UV_SRC_IDNA_H_ + +/* Decode a single codepoint. Returns the codepoint or UINT32_MAX on error. + * |p| is updated on success _and_ error, i.e., bad multi-byte sequences are + * skipped in their entirety, not just the first bad byte. + */ +unsigned uv__utf8_decode1(const char** p, const char* pe); + +/* Convert a UTF-8 domain name to IDNA 2008 / Punycode. A return value >= 0 + * is the number of bytes written to |d|, including the trailing nul byte. + * A return value < 0 is a libuv error code. |s| and |d| can not overlap. + */ +long uv__idna_toascii(const char* s, const char* se, char* d, char* de); + +#endif /* UV_SRC_IDNA_H_ */ diff --git a/Utilities/cmlibuv/src/inet.c b/Utilities/cmlibuv/src/inet.c index 7c75e43..58238dc 100644 --- a/Utilities/cmlibuv/src/inet.c +++ b/Utilities/cmlibuv/src/inet.c @@ -22,7 +22,7 @@ #include <string.h> #if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" +# include "uv/stdint-msvc2008.h" #else # include <stdint.h> #endif @@ -59,8 +59,7 @@ static int inet_ntop4(const unsigned char *src, char *dst, size_t size) { if (l <= 0 || (size_t) l >= size) { return UV_ENOSPC; } - strncpy(dst, tmp, size); - dst[size - 1] = '\0'; + uv__strscpy(dst, tmp, size); return 0; } @@ -142,14 +141,8 @@ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) { if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words)) *tp++ = ':'; *tp++ = '\0'; - - /* - * Check for overflow, copy, and we're done. - */ - if ((size_t)(tp - tmp) > size) { + if (UV_E2BIG == uv__strscpy(dst, tmp, size)) return UV_ENOSPC; - } - strcpy(dst, tmp); return 0; } diff --git a/Utilities/cmlibuv/src/strscpy.c b/Utilities/cmlibuv/src/strscpy.c new file mode 100644 index 0000000..2a2bdce --- /dev/null +++ b/Utilities/cmlibuv/src/strscpy.c @@ -0,0 +1,17 @@ +#include "strscpy.h" +#include <limits.h> /* SSIZE_MAX */ + +ssize_t uv__strscpy(char* d, const char* s, size_t n) { + size_t i; + + for (i = 0; i < n; i++) + if ('\0' == (d[i] = s[i])) + return i > SSIZE_MAX ? UV_E2BIG : (ssize_t) i; + + if (i == 0) + return 0; + + d[--i] = '\0'; + + return UV_E2BIG; +} diff --git a/Utilities/cmlibuv/src/strscpy.h b/Utilities/cmlibuv/src/strscpy.h new file mode 100644 index 0000000..fbe0a39 --- /dev/null +++ b/Utilities/cmlibuv/src/strscpy.h @@ -0,0 +1,18 @@ +#ifndef UV_STRSCPY_H_ +#define UV_STRSCPY_H_ + +/* Include uv.h for its definitions of size_t and ssize_t. + * size_t can be obtained directly from <stddef.h> but ssize_t requires + * some hoop jumping on Windows that I didn't want to duplicate here. + */ +#include "uv.h" + +/* Copies up to |n-1| bytes from |d| to |s| and always zero-terminates + * the result, except when |n==0|. Returns the number of bytes copied + * or UV_E2BIG if |d| is too small. + * + * See https://www.kernel.org/doc/htmldocs/kernel-api/API-strscpy.html + */ +ssize_t uv__strscpy(char* d, const char* s, size_t n); + +#endif /* UV_STRSCPY_H_ */ diff --git a/Utilities/cmlibuv/src/threadpool.c b/Utilities/cmlibuv/src/threadpool.c index 413d1c2..4258933 100644 --- a/Utilities/cmlibuv/src/threadpool.c +++ b/Utilities/cmlibuv/src/threadpool.c @@ -33,12 +33,18 @@ static uv_once_t once = UV_ONCE_INIT; static uv_cond_t cond; static uv_mutex_t mutex; static unsigned int idle_threads; +static unsigned int slow_io_work_running; static unsigned int nthreads; static uv_thread_t* threads; static uv_thread_t default_threads[4]; static QUEUE exit_message; static QUEUE wq; +static QUEUE run_slow_work_message; +static QUEUE slow_io_pending_wq; +static unsigned int slow_work_thread_threshold(void) { + return (nthreads + 1) / 2; +} static void uv__cancelled(struct uv__work* w) { abort(); @@ -51,34 +57,67 @@ static void uv__cancelled(struct uv__work* w) { static void worker(void* arg) { struct uv__work* w; QUEUE* q; + int is_slow_work; uv_sem_post((uv_sem_t*) arg); arg = NULL; + uv_mutex_lock(&mutex); for (;;) { - uv_mutex_lock(&mutex); - - while (QUEUE_EMPTY(&wq)) { + /* `mutex` should always be locked at this point. */ + + /* Keep waiting while either no work is present or only slow I/O + and we're at the threshold for that. */ + while (QUEUE_EMPTY(&wq) || + (QUEUE_HEAD(&wq) == &run_slow_work_message && + QUEUE_NEXT(&run_slow_work_message) == &wq && + slow_io_work_running >= slow_work_thread_threshold())) { idle_threads += 1; uv_cond_wait(&cond, &mutex); idle_threads -= 1; } q = QUEUE_HEAD(&wq); - - if (q == &exit_message) + if (q == &exit_message) { uv_cond_signal(&cond); - else { + uv_mutex_unlock(&mutex); + break; + } + + QUEUE_REMOVE(q); + QUEUE_INIT(q); /* Signal uv_cancel() that the work req is executing. */ + + is_slow_work = 0; + if (q == &run_slow_work_message) { + /* If we're at the slow I/O threshold, re-schedule until after all + other work in the queue is done. */ + if (slow_io_work_running >= slow_work_thread_threshold()) { + QUEUE_INSERT_TAIL(&wq, q); + continue; + } + + /* If we encountered a request to run slow I/O work but there is none + to run, that means it's cancelled => Start over. */ + if (QUEUE_EMPTY(&slow_io_pending_wq)) + continue; + + is_slow_work = 1; + slow_io_work_running++; + + q = QUEUE_HEAD(&slow_io_pending_wq); QUEUE_REMOVE(q); - QUEUE_INIT(q); /* Signal uv_cancel() that the work req is - executing. */ + QUEUE_INIT(q); + + /* If there is more slow I/O work, schedule it to be run as well. */ + if (!QUEUE_EMPTY(&slow_io_pending_wq)) { + QUEUE_INSERT_TAIL(&wq, &run_slow_work_message); + if (idle_threads > 0) + uv_cond_signal(&cond); + } } uv_mutex_unlock(&mutex); - if (q == &exit_message) - break; - w = QUEUE_DATA(q, struct uv__work, wq); w->work(w); @@ -88,12 +127,32 @@ static void worker(void* arg) { QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq); uv_async_send(&w->loop->wq_async); uv_mutex_unlock(&w->loop->wq_mutex); + + /* Lock `mutex` since that is expected at the start of the next + * iteration. */ + uv_mutex_lock(&mutex); + if (is_slow_work) { + /* `slow_io_work_running` is protected by `mutex`. */ + slow_io_work_running--; + } } } -static void post(QUEUE* q) { +static void post(QUEUE* q, enum uv__work_kind kind) { uv_mutex_lock(&mutex); + if (kind == UV__WORK_SLOW_IO) { + /* Insert into a separate queue. */ + QUEUE_INSERT_TAIL(&slow_io_pending_wq, q); + if (!QUEUE_EMPTY(&run_slow_work_message)) { + /* Running slow I/O tasks is already scheduled => Nothing to do here. + The worker that runs said other task will schedule this one as well. */ + uv_mutex_unlock(&mutex); + return; + } + q = &run_slow_work_message; + } + QUEUE_INSERT_TAIL(&wq, q); if (idle_threads > 0) uv_cond_signal(&cond); @@ -108,7 +167,7 @@ UV_DESTRUCTOR(static void cleanup(void)) { if (nthreads == 0) return; - post(&exit_message); + post(&exit_message, UV__WORK_CPU); for (i = 0; i < nthreads; i++) if (uv_thread_join(threads + i)) @@ -156,6 +215,8 @@ static void init_threads(void) { abort(); QUEUE_INIT(&wq); + QUEUE_INIT(&slow_io_pending_wq); + QUEUE_INIT(&run_slow_work_message); if (uv_sem_init(&sem, 0)) abort(); @@ -194,13 +255,14 @@ static void init_once(void) { void uv__work_submit(uv_loop_t* loop, struct uv__work* w, + enum uv__work_kind kind, void (*work)(struct uv__work* w), void (*done)(struct uv__work* w, int status)) { uv_once(&once, init_once); w->loop = loop; w->work = work; w->done = done; - post(&w->wq); + post(&w->wq, kind); } @@ -284,7 +346,11 @@ int uv_queue_work(uv_loop_t* loop, req->loop = loop; req->work_cb = work_cb; req->after_work_cb = after_work_cb; - uv__work_submit(loop, &req->work_req, uv__queue_work, uv__queue_done); + uv__work_submit(loop, + &req->work_req, + UV__WORK_CPU, + uv__queue_work, + uv__queue_done); return 0; } diff --git a/Utilities/cmlibuv/src/unix/timer.c b/Utilities/cmlibuv/src/timer.c index 54dabfe..dd78bcb 100644 --- a/Utilities/cmlibuv/src/unix/timer.c +++ b/Utilities/cmlibuv/src/timer.c @@ -19,13 +19,22 @@ */ #include "uv.h" -#include "internal.h" +#include "uv-common.h" #include "heap-inl.h" #include <assert.h> #include <limits.h> +static struct heap *timer_heap(const uv_loop_t* loop) { +#ifdef _WIN32 + return (struct heap*) loop->timer_heap; +#else + return (struct heap*) &loop->timer_heap; +#endif +} + + static int timer_less_than(const struct heap_node* ha, const struct heap_node* hb) { const uv_timer_t* a; @@ -81,7 +90,7 @@ int uv_timer_start(uv_timer_t* handle, /* start_id is the second index to be compared in uv__timer_cmp() */ handle->start_id = handle->loop->timer_counter++; - heap_insert((struct heap*) &handle->loop->timer_heap, + heap_insert(timer_heap(handle->loop), (struct heap_node*) &handle->heap_node, timer_less_than); uv__handle_start(handle); @@ -94,7 +103,7 @@ int uv_timer_stop(uv_timer_t* handle) { if (!uv__is_active(handle)) return 0; - heap_remove((struct heap*) &handle->loop->timer_heap, + heap_remove(timer_heap(handle->loop), (struct heap_node*) &handle->heap_node, timer_less_than); uv__handle_stop(handle); @@ -131,7 +140,7 @@ int uv__next_timeout(const uv_loop_t* loop) { const uv_timer_t* handle; uint64_t diff; - heap_node = heap_min((const struct heap*) &loop->timer_heap); + heap_node = heap_min(timer_heap(loop)); if (heap_node == NULL) return -1; /* block indefinitely */ @@ -143,7 +152,7 @@ int uv__next_timeout(const uv_loop_t* loop) { if (diff > INT_MAX) diff = INT_MAX; - return diff; + return (int) diff; } @@ -152,7 +161,7 @@ void uv__run_timers(uv_loop_t* loop) { uv_timer_t* handle; for (;;) { - heap_node = heap_min((struct heap*) &loop->timer_heap); + heap_node = heap_min(timer_heap(loop)); if (heap_node == NULL) break; diff --git a/Utilities/cmlibuv/src/unix/aix-common.c b/Utilities/cmlibuv/src/unix/aix-common.c index 9c11c5d..e9697e9 100644 --- a/Utilities/cmlibuv/src/unix/aix-common.c +++ b/Utilities/cmlibuv/src/unix/aix-common.c @@ -166,8 +166,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { } -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { uv_interface_address_t* address; int sockfd, inet6, size = 1; struct ifconf ifc; @@ -175,6 +174,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, struct sockaddr_dl* sa_addr; *count = 0; + *addresses = NULL; if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { return UV__ERR(errno); @@ -217,6 +217,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, (*count)++; } + if (*count == 0) { + uv__close(sockfd); + return 0; + } + /* Alloc the return interface structs */ *addresses = uv__malloc(*count * sizeof(uv_interface_address_t)); if (!(*addresses)) { @@ -290,3 +295,4 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses, uv__free(addresses); } + diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c index 92de814..337e58e 100644 --- a/Utilities/cmlibuv/src/unix/aix.c +++ b/Utilities/cmlibuv/src/unix/aix.c @@ -358,19 +358,15 @@ void uv_loadavg(double avg[3]) { #ifdef HAVE_SYS_AHAFS_EVPRODS_H -static char *uv__rawname(char *cp) { - static char rawbuf[FILENAME_MAX+1]; - char *dp = rindex(cp, '/'); +static char* uv__rawname(const char* cp, char (*dst)[FILENAME_MAX+1]) { + char* dp; + dp = rindex(cp, '/'); if (dp == 0) return 0; - *dp = 0; - strcpy(rawbuf, cp); - *dp = '/'; - strcat(rawbuf, "/r"); - strcat(rawbuf, dp+1); - return rawbuf; + snprintf(*dst, sizeof(*dst), "%.*s/r%s", (int) (dp - cp), cp, dp + 1); + return *dst; } @@ -399,6 +395,7 @@ static int uv__path_is_a_directory(char* filename) { * Returns 0 if AHAFS is mounted, or an error code < 0 on failure */ static int uv__is_ahafs_mounted(void){ + char rawbuf[FILENAME_MAX+1]; int rv, i = 2; struct vmount *p; int size_multiplier = 10; @@ -432,7 +429,7 @@ static int uv__is_ahafs_mounted(void){ obj = vmt2dataptr(vmt, VMT_OBJECT); /* device */ stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */ - if (EQ(obj, dev) || EQ(uv__rawname(obj), dev) || EQ(stub, dev)) { + if (EQ(obj, dev) || EQ(uv__rawname(obj, &rawbuf), dev) || EQ(stub, dev)) { uv__free(p); /* Found a match */ return 0; } @@ -453,7 +450,8 @@ static int uv__makedir_p(const char *dir) { size_t len; int err; - snprintf(tmp, sizeof(tmp),"%s",dir); + /* TODO(bnoordhuis) Check uv__strscpy() return value. */ + uv__strscpy(tmp, dir, sizeof(tmp)); len = strlen(tmp); if (tmp[len - 1] == '/') tmp[len - 1] = 0; @@ -557,7 +555,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) { sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1"); rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1); - if (rc < 0) + if (rc < 0 && errno != EBUSY) return UV__ERR(errno); return 0; @@ -702,9 +700,9 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int else p++; } - strncpy(fname, p, sizeof(fname) - 1); - /* Just in case */ - fname[sizeof(fname) - 1] = '\0'; + + /* TODO(bnoordhuis) Check uv__strscpy() return value. */ + uv__strscpy(fname, p, sizeof(fname)); handle->cb(handle, fname, events, 0); } @@ -730,12 +728,19 @@ int uv_fs_event_start(uv_fs_event_t* handle, char cwd[PATH_MAX]; char absolute_path[PATH_MAX]; char readlink_cwd[PATH_MAX]; + struct timeval zt; + fd_set pollfd; /* Figure out whether filename is absolute or not */ - if (filename[0] == '/') { + if (filename[0] == '\0') { + /* Missing a pathname */ + return UV_ENOENT; + } + else if (filename[0] == '/') { /* We have absolute pathname */ - snprintf(absolute_path, sizeof(absolute_path), "%s", filename); + /* TODO(bnoordhuis) Check uv__strscpy() return value. */ + uv__strscpy(absolute_path, filename, sizeof(absolute_path)); } else { /* We have a relative pathname, compose the absolute pathname */ snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid()); @@ -769,6 +774,15 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv__io_start(handle->loop, &handle->event_watcher, POLLIN); + /* AHAFS wants someone to poll for it to start mointoring. + * so kick-start it so that we don't miss an event in the + * eventuality of an event that occurs in the current loop. */ + do { + memset(&zt, 0, sizeof(zt)); + FD_ZERO(&pollfd); + FD_SET(fd, &pollfd); + rc = select(fd + 1, &pollfd, NULL, NULL, &zt); + } while (rc == -1 && errno == EINTR); return 0; #else return UV_ENOSYS; @@ -886,16 +900,20 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { size_t len; - len = strlen(process_argv[0]); if (buffer == NULL || size == 0) return UV_EINVAL; - else if (size <= len) - return UV_ENOBUFS; uv_once(&process_title_mutex_once, init_process_title_mutex_once); uv_mutex_lock(&process_title_mutex); - memcpy(buffer, process_argv[0], len + 1); + len = strlen(process_argv[0]); + if (size <= len) { + uv_mutex_unlock(&process_title_mutex); + return UV_ENOBUFS; + } + + memcpy(buffer, process_argv[0], len); + buffer[len] = '\0'; uv_mutex_unlock(&process_title_mutex); @@ -982,7 +1000,8 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { return UV_ENOMEM; } - strcpy(cpu_id.name, FIRST_CPU); + /* TODO(bnoordhuis) Check uv__strscpy() return value. */ + uv__strscpy(cpu_id.name, FIRST_CPU, sizeof(cpu_id.name)); result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus); if (result == -1) { uv__free(ps_cpus); diff --git a/Utilities/cmlibuv/src/unix/android-ifaddrs.c b/Utilities/cmlibuv/src/unix/android-ifaddrs.c index bf30b14..99fb25a 100644 --- a/Utilities/cmlibuv/src/unix/android-ifaddrs.c +++ b/Utilities/cmlibuv/src/unix/android-ifaddrs.c @@ -23,7 +23,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "android-ifaddrs.h" +#include "uv/android-ifaddrs.h" #include "uv-common.h" #include <string.h> diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c index 0d02154..3c2253f 100644 --- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c +++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c @@ -52,13 +52,10 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { */ if (ent->ifa_addr->sa_family == AF_LINK) return 1; -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) if (ent->ifa_addr->sa_family != PF_INET && ent->ifa_addr->sa_family != PF_INET6) return 1; -#elif defined(__OpenBSD__) - if (ent->ifa_addr->sa_family != PF_INET) - return 1; #endif return 0; } @@ -69,11 +66,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { uv_interface_address_t* address; int i; + *count = 0; + *addresses = NULL; + if (getifaddrs(&addrs) != 0) return UV__ERR(errno); - *count = 0; - /* Count the number of interfaces */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) @@ -81,6 +79,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { (*count)++; } + if (*count == 0) { + freeifaddrs(addrs); + return 0; + } + *addresses = uv__malloc(*count * sizeof(**addresses)); if (*addresses == NULL) { @@ -121,15 +124,17 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address = *addresses; for (i = 0; i < *count; i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { #if defined(__CYGWIN__) || defined(__MSYS__) - memset(address->phys_addr, 0, sizeof(address->phys_addr)); + memset(address->phys_addr, 0, sizeof(address->phys_addr)); #else + if (strcmp(address->name, ent->ifa_name) == 0) { struct sockaddr_dl* sa_addr; sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); -#endif + } else { + memset(address->phys_addr, 0, sizeof(address->phys_addr)); } +#endif address++; } } diff --git a/Utilities/cmlibuv/src/unix/bsd-proctitle.c b/Utilities/cmlibuv/src/unix/bsd-proctitle.c new file mode 100644 index 0000000..0ce47c8 --- /dev/null +++ b/Utilities/cmlibuv/src/unix/bsd-proctitle.c @@ -0,0 +1,93 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include <sys/types.h> +#include <unistd.h> + + +static uv_mutex_t process_title_mutex; +static uv_once_t process_title_mutex_once = UV_ONCE_INIT; +static char* process_title; + + +static void init_process_title_mutex_once(void) { + if (uv_mutex_init(&process_title_mutex)) + abort(); +} + + +char** uv_setup_args(int argc, char** argv) { + process_title = argc > 0 ? uv__strdup(argv[0]) : NULL; + return argv; +} + + +int uv_set_process_title(const char* title) { + char* new_title; + + new_title = uv__strdup(title); + if (new_title == NULL) + return UV_ENOMEM; + + uv_once(&process_title_mutex_once, init_process_title_mutex_once); + uv_mutex_lock(&process_title_mutex); + + uv__free(process_title); + process_title = new_title; + setproctitle("%s", title); + + uv_mutex_unlock(&process_title_mutex); + + return 0; +} + + +int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return UV_EINVAL; + + uv_once(&process_title_mutex_once, init_process_title_mutex_once); + uv_mutex_lock(&process_title_mutex); + + if (process_title != NULL) { + len = strlen(process_title) + 1; + + if (size < len) { + uv_mutex_unlock(&process_title_mutex); + return UV_ENOBUFS; + } + + memcpy(buffer, process_title, len); + } else { + len = 0; + } + + uv_mutex_unlock(&process_title_mutex); + + buffer[len] = '\0'; + + return 0; +} diff --git a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c index 4f32d03..309ec79 100644 --- a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c +++ b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c @@ -46,6 +46,7 @@ void uv__async_stop(uv_loop_t* loop) { } void uv__work_submit(uv_loop_t* loop, struct uv__work* w, + enum uv__work_kind kind, void (*work)(struct uv__work* w), void (*done)(struct uv__work* w, int status)) { abort(); diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c index a357ef3..a8d6adb 100644 --- a/Utilities/cmlibuv/src/unix/core.c +++ b/Utilities/cmlibuv/src/unix/core.c @@ -41,6 +41,7 @@ #include <sys/resource.h> /* getrusage */ #include <pwd.h> #include <sched.h> +#include <sys/utsname.h> #ifdef __sun # include <netdb.h> /* MAXHOSTNAMELEN on Solaris */ @@ -119,7 +120,7 @@ uint64_t uv_hrtime(void) { void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { assert(!uv__is_closing(handle)); - handle->flags |= UV_CLOSING; + handle->flags |= UV_HANDLE_CLOSING; handle->close_cb = close_cb; switch (handle->type) { @@ -177,8 +178,8 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { case UV_SIGNAL: uv__signal_close((uv_signal_t*) handle); - /* Signal handles may not be closed immediately. The signal code will */ - /* itself close uv__make_close_pending whenever appropriate. */ + /* Signal handles may not be closed immediately. The signal code will + * itself close uv__make_close_pending whenever appropriate. */ return; default: @@ -217,8 +218,8 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { } void uv__make_close_pending(uv_handle_t* handle) { - assert(handle->flags & UV_CLOSING); - assert(!(handle->flags & UV_CLOSED)); + assert(handle->flags & UV_HANDLE_CLOSING); + assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->next_closing = handle->loop->closing_handles; handle->loop->closing_handles = handle; } @@ -244,15 +245,17 @@ int uv__getiovmax(void) { static void uv__finish_close(uv_handle_t* handle) { - /* Note: while the handle is in the UV_CLOSING state now, it's still possible - * for it to be active in the sense that uv__is_active() returns true. + /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still + * possible for it to be active in the sense that uv__is_active() returns + * true. + * * A good example is when the user calls uv_shutdown(), immediately followed * by uv_close(). The handle is considered active at this point because the * completion of the shutdown req is still pending. */ - assert(handle->flags & UV_CLOSING); - assert(!(handle->flags & UV_CLOSED)); - handle->flags |= UV_CLOSED; + assert(handle->flags & UV_HANDLE_CLOSING); + assert(!(handle->flags & UV_HANDLE_CLOSED)); + handle->flags |= UV_HANDLE_CLOSED; switch (handle->type) { case UV_PREPARE: @@ -637,27 +640,6 @@ int uv__cloexec_fcntl(int fd, int set) { } -/* This function is not execve-safe, there is a race window - * between the call to dup() and fcntl(FD_CLOEXEC). - */ -int uv__dup(int fd) { - int err; - - fd = dup(fd); - - if (fd == -1) - return UV__ERR(errno); - - err = uv__cloexec(fd, 1); - if (err) { - uv__close(fd); - return err; - } - - return fd; -} - - ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { struct cmsghdr* cmsg; ssize_t rc; @@ -930,6 +912,11 @@ int uv__io_active(const uv__io_t* w, unsigned int events) { } +int uv__fd_exists(uv_loop_t* loop, int fd) { + return (unsigned) fd < loop->nwatchers && loop->watchers[fd] != NULL; +} + + int uv_getrusage(uv_rusage_t* rusage) { struct rusage usage; @@ -1343,6 +1330,9 @@ uv_os_fd_t uv_get_osfhandle(int fd) { return fd; } +int uv_open_osfhandle(uv_os_fd_t os_fd) { + return os_fd; +} uv_pid_t uv_os_getpid(void) { return getpid(); @@ -1352,3 +1342,87 @@ uv_pid_t uv_os_getpid(void) { uv_pid_t uv_os_getppid(void) { return getppid(); } + + +int uv_os_getpriority(uv_pid_t pid, int* priority) { + int r; + + if (priority == NULL) + return UV_EINVAL; + + errno = 0; + r = getpriority(PRIO_PROCESS, (int) pid); + + if (r == -1 && errno != 0) + return UV__ERR(errno); + + *priority = r; + return 0; +} + + +int uv_os_setpriority(uv_pid_t pid, int priority) { + if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW) + return UV_EINVAL; + + if (setpriority(PRIO_PROCESS, (int) pid, priority) != 0) + return UV__ERR(errno); + + return 0; +} + + +int uv_os_uname(uv_utsname_t* buffer) { + struct utsname buf; + int r; + + if (buffer == NULL) + return UV_EINVAL; + + if (uname(&buf) == -1) { + r = UV__ERR(errno); + goto error; + } + + r = uv__strscpy(buffer->sysname, buf.sysname, sizeof(buffer->sysname)); + if (r == UV_E2BIG) + goto error; + +#ifdef _AIX + r = snprintf(buffer->release, + sizeof(buffer->release), + "%s.%s", + buf.version, + buf.release); + if (r >= sizeof(buffer->release)) { + r = UV_E2BIG; + goto error; + } +#else + r = uv__strscpy(buffer->release, buf.release, sizeof(buffer->release)); + if (r == UV_E2BIG) + goto error; +#endif + + r = uv__strscpy(buffer->version, buf.version, sizeof(buffer->version)); + if (r == UV_E2BIG) + goto error; + +#if defined(_AIX) || defined(__PASE__) + r = uv__strscpy(buffer->machine, "ppc64", sizeof(buffer->machine)); +#else + r = uv__strscpy(buffer->machine, buf.machine, sizeof(buffer->machine)); +#endif + + if (r == UV_E2BIG) + goto error; + + return 0; + +error: + buffer->sysname[0] = '\0'; + buffer->release[0] = '\0'; + buffer->version[0] = '\0'; + buffer->machine[0] = '\0'; + return r; +} diff --git a/Utilities/cmlibuv/src/unix/cygwin.c b/Utilities/cmlibuv/src/unix/cygwin.c index 9fe4093..9da20e2 100644 --- a/Utilities/cmlibuv/src/unix/cygwin.c +++ b/Utilities/cmlibuv/src/unix/cygwin.c @@ -38,7 +38,7 @@ int uv_uptime(double* uptime) { int uv_resident_set_memory(size_t* rss) { /* FIXME: read /proc/meminfo? */ *rss = 0; - return UV_ENOSYS; + return 0; } int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { diff --git a/Utilities/cmlibuv/src/unix/darwin-proctitle.c b/Utilities/cmlibuv/src/unix/darwin-proctitle.c index dabde22..e505bdd 100644 --- a/Utilities/cmlibuv/src/unix/darwin-proctitle.c +++ b/Utilities/cmlibuv/src/unix/darwin-proctitle.c @@ -33,61 +33,56 @@ # include <ApplicationServices/ApplicationServices.h> #endif +#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) -static int uv__pthread_setname_np(const char* name) { - int (*dynamic_pthread_setname_np)(const char* name); - char namebuf[64]; /* MAXTHREADNAMESIZE */ - int err; - - /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */ - *(void **)(&dynamic_pthread_setname_np) = - dlsym(RTLD_DEFAULT, "pthread_setname_np"); - - if (dynamic_pthread_setname_np == NULL) - return UV_ENOSYS; - - strncpy(namebuf, name, sizeof(namebuf) - 1); - namebuf[sizeof(namebuf) - 1] = '\0'; - err = dynamic_pthread_setname_np(namebuf); - if (err) - return UV__ERR(err); +static int (*dynamic_pthread_setname_np)(const char* name); +#if !TARGET_OS_IPHONE +static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, + const char*, + CFStringEncoding); +static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); +static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); +static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); +static CFTypeRef (*pLSGetCurrentApplicationASN)(void); +static OSStatus (*pLSSetApplicationInformationItem)(int, + CFTypeRef, + CFStringRef, + CFStringRef, + CFDictionaryRef*); +static void* application_services_handle; +static void* core_foundation_handle; +static CFBundleRef launch_services_bundle; +static CFStringRef* display_name_key; +static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); +static CFBundleRef (*pCFBundleGetMainBundle)(void); +static CFBundleRef hi_services_bundle; +static OSStatus (*pSetApplicationIsDaemon)(int); +static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); +static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, + void*); + + +UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) { + if (core_foundation_handle != NULL) { + dlclose(core_foundation_handle); + core_foundation_handle = NULL; + } - return 0; + if (application_services_handle != NULL) { + dlclose(application_services_handle); + application_services_handle = NULL; + } } +#endif /* !TARGET_OS_IPHONE */ -int uv__set_process_title(const char* title) { -#if TARGET_OS_IPHONE - return uv__pthread_setname_np(title); -#else - CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, - const char*, - CFStringEncoding); - CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); - void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); - void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); - CFTypeRef (*pLSGetCurrentApplicationASN)(void); - OSStatus (*pLSSetApplicationInformationItem)(int, - CFTypeRef, - CFStringRef, - CFStringRef, - CFDictionaryRef*); - void* application_services_handle; - void* core_foundation_handle; - CFBundleRef launch_services_bundle; - CFStringRef* display_name_key; - CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); - CFBundleRef (*pCFBundleGetMainBundle)(void); - CFBundleRef hi_services_bundle; - OSStatus (*pSetApplicationIsDaemon)(int); - CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); - void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, - void*); - CFTypeRef asn; - int err; - - err = UV_ENOENT; +void uv__set_process_title_platform_init(void) { + /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */ + *(void **)(&dynamic_pthread_setname_np) = + dlsym(RTLD_DEFAULT, "pthread_setname_np"); + +#if !TARGET_OS_IPHONE application_services_handle = dlopen("/System/Library/Frameworks/" "ApplicationServices.framework/" "Versions/A/ApplicationServices", @@ -116,8 +111,6 @@ int uv__set_process_title(const char* title) { goto out; } -#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) - launch_services_bundle = pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices")); @@ -148,13 +141,14 @@ int uv__set_process_title(const char* title) { "CFBundleGetInfoDictionary"); *(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle, "CFBundleGetMainBundle"); + if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) goto out; /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */ hi_services_bundle = pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices")); - err = UV_ENOENT; + if (hi_services_bundle == NULL) goto out; @@ -168,42 +162,37 @@ int uv__set_process_title(const char* title) { pCFBundleGetFunctionPointerForName( launch_services_bundle, S("_LSSetApplicationLaunchServicesServerConnectionStatus")); + if (pSetApplicationIsDaemon == NULL || pLSApplicationCheckIn == NULL || pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) { goto out; } - if (pSetApplicationIsDaemon(1) != noErr) - goto out; - - pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); - - /* Check into process manager?! */ - pLSApplicationCheckIn(-2, - pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); - - asn = pLSGetCurrentApplicationASN(); - - err = UV_EINVAL; - if (pLSSetApplicationInformationItem(-2, /* Magic value. */ - asn, - *display_name_key, - S(title), - NULL) != noErr) { - goto out; - } - - uv__pthread_setname_np(title); /* Don't care if it fails. */ - err = 0; + return; out: - if (core_foundation_handle != NULL) - dlclose(core_foundation_handle); + uv__set_process_title_platform_fini(); +#endif /* !TARGET_OS_IPHONE */ +} - if (application_services_handle != NULL) - dlclose(application_services_handle); - return err; +void uv__set_process_title(const char* title) { +#if !TARGET_OS_IPHONE + if (core_foundation_handle != NULL && pSetApplicationIsDaemon(1) != noErr) { + CFTypeRef asn; + pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); + pLSApplicationCheckIn(/* Magic value */ -2, + pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); + asn = pLSGetCurrentApplicationASN(); + pLSSetApplicationInformationItem(/* Magic value */ -2, asn, + *display_name_key, S(title), NULL); + } #endif /* !TARGET_OS_IPHONE */ + + if (dynamic_pthread_setname_np != NULL) { + char namebuf[64]; /* MAXTHREADNAMESIZE */ + uv__strscpy(namebuf, title, sizeof(namebuf)); + dynamic_pthread_setname_np(namebuf); + } } diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c index 70ccb13..0f729cf 100644 --- a/Utilities/cmlibuv/src/unix/freebsd.c +++ b/Utilities/cmlibuv/src/unix/freebsd.c @@ -47,15 +47,6 @@ # define CP_INTR 4 #endif -static uv_mutex_t process_title_mutex; -static uv_once_t process_title_mutex_once = UV_ONCE_INIT; -static char *process_title; - - -static void init_process_title_mutex_once(void) { - uv_mutex_init(&process_title_mutex); -} - int uv__platform_loop_init(uv_loop_t* loop) { return uv__kqueue_init(loop); @@ -159,76 +150,6 @@ void uv_loadavg(double avg[3]) { } -char** uv_setup_args(int argc, char** argv) { - process_title = argc ? uv__strdup(argv[0]) : NULL; - return argv; -} - - -int uv_set_process_title(const char* title) { - int oid[4]; - char* new_title; - - new_title = uv__strdup(title); - - uv_once(&process_title_mutex_once, init_process_title_mutex_once); - uv_mutex_lock(&process_title_mutex); - - if (process_title == NULL) { - uv_mutex_unlock(&process_title_mutex); - return UV_ENOMEM; - } - - uv__free(process_title); - process_title = new_title; - - oid[0] = CTL_KERN; - oid[1] = KERN_PROC; - oid[2] = KERN_PROC_ARGS; - oid[3] = getpid(); - - sysctl(oid, - ARRAY_SIZE(oid), - NULL, - NULL, - process_title, - strlen(process_title) + 1); - - uv_mutex_unlock(&process_title_mutex); - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - size_t len; - - if (buffer == NULL || size == 0) - return UV_EINVAL; - - uv_once(&process_title_mutex_once, init_process_title_mutex_once); - uv_mutex_lock(&process_title_mutex); - - if (process_title) { - len = strlen(process_title) + 1; - - if (size < len) { - uv_mutex_unlock(&process_title_mutex); - return UV_ENOBUFS; - } - - memcpy(buffer, process_title, len); - } else { - len = 0; - } - - uv_mutex_unlock(&process_title_mutex); - - buffer[len] = '\0'; - - return 0; -} - int uv_resident_set_memory(size_t* rss) { struct kinfo_proc kinfo; size_t page_size; diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c index a6cc6db..bffc956 100644 --- a/Utilities/cmlibuv/src/unix/fs.c +++ b/Utilities/cmlibuv/src/unix/fs.c @@ -43,7 +43,6 @@ #include <pthread.h> #include <unistd.h> #include <fcntl.h> -#include <utime.h> #include <poll.h> #if defined(__DragonFly__) || \ @@ -62,11 +61,20 @@ #if defined(__APPLE__) # include <copyfile.h> +# include <sys/sysctl.h> #elif defined(__linux__) && !defined(FICLONE) # include <sys/ioctl.h> # define FICLONE _IOW(0x94, 9, int) #endif +#if defined(_AIX) && !defined(_AIX71) +# include <utime.h> +#endif + +#if defined(_AIX) && _XOPEN_SOURCE <= 600 +extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */ +#endif + #define INIT(subtype) \ do { \ if (req == NULL) \ @@ -120,7 +128,11 @@ do { \ if (cb != NULL) { \ uv__req_register(loop, req); \ - uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \ + uv__work_submit(loop, \ + &req->work_req, \ + UV__WORK_FAST_IO, \ + uv__fs_work, \ + uv__fs_done); \ return 0; \ } \ else { \ @@ -143,7 +155,7 @@ static ssize_t uv__fs_fsync(uv_fs_t* req) { int r; r = fcntl(req->file, F_FULLFSYNC); - if (r != 0 && errno == ENOTTY) + if (r != 0) r = fsync(req->file); return r; #else @@ -165,59 +177,17 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { static ssize_t uv__fs_futime(uv_fs_t* req) { -#if defined(__linux__) +#if defined(__linux__) \ + || defined(_AIX71) /* utimesat() has nanosecond resolution but we stick to microseconds * for the sake of consistency with other platforms. */ - static int no_utimesat; struct timespec ts[2]; - struct timeval tv[2]; - char path[sizeof("/proc/self/fd/") + 3 * sizeof(int)]; - int r; - - if (no_utimesat) - goto skip; - ts[0].tv_sec = req->atime; ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; ts[1].tv_sec = req->mtime; ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; - - r = uv__utimesat(req->file, NULL, ts, 0); - if (r == 0) - return r; - - if (errno != ENOSYS) - return r; - - no_utimesat = 1; - -skip: - - tv[0].tv_sec = req->atime; - tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; - tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; - snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file); - - r = utimes(path, tv); - if (r == 0) - return r; - - switch (errno) { - case ENOENT: - if (fcntl(req->file, F_GETFL) == -1 && errno == EBADF) - break; - /* Fall through. */ - - case EACCES: - case ENOTDIR: - errno = ENOSYS; - break; - } - - return r; - + return futimens(req->file, ts); #elif defined(__APPLE__) \ || defined(__DragonFly__) \ || defined(__FreeBSD__) \ @@ -235,13 +205,6 @@ skip: # else return futimes(req->file, tv); # endif -#elif defined(_AIX71) - struct timespec ts[2]; - ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; - ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; - return futimens(req->file, ts); #elif defined(__MVS__) attrib_t atr; memset(&atr, 0, sizeof(atr)); @@ -314,17 +277,13 @@ static ssize_t uv__fs_read(uv_fs_t* req) { #if defined(__linux__) static int no_preadv; #endif + unsigned int iovmax; ssize_t result; -#if defined(_AIX) - struct stat buf; - if(fstat(req->file, &buf)) - return -1; - if(S_ISDIR(buf.st_mode)) { - errno = EISDIR; - return -1; - } -#endif /* defined(_AIX) */ + iovmax = uv__getiovmax(); + if (req->nbufs > iovmax) + req->nbufs = iovmax; + if (req->off < 0) { if (req->nbufs == 1) result = read(req->file, req->bufs[0].base, req->bufs[0].len); @@ -343,25 +302,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) { if (no_preadv) retry: # endif { - off_t nread; - size_t index; - - nread = 0; - index = 0; - result = 1; - do { - if (req->bufs[index].len > 0) { - result = pread(req->file, - req->bufs[index].base, - req->bufs[index].len, - req->off + nread); - if (result > 0) - nread += result; - } - index++; - } while (index < req->nbufs && result > 0); - if (nread > 0) - result = nread; + result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off); } # if defined(__linux__) else { @@ -379,6 +320,13 @@ static ssize_t uv__fs_read(uv_fs_t* req) { } done: + /* Early cleanup of bufs allocation, since we're done with it. */ + if (req->bufs != req->bufsml) + uv__free(req->bufs); + + req->bufs = NULL; + req->nbufs = 0; + return result; } @@ -446,8 +394,10 @@ static ssize_t uv__fs_pathmax_size(const char* path) { } static ssize_t uv__fs_readlink(uv_fs_t* req) { + ssize_t maxlen; ssize_t len; char* buf; + char* newbuf; #if defined(UV__FS_PATH_MAX_FALLBACK) /* We may not have a real PATH_MAX. Read size of link. */ @@ -461,17 +411,17 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { return -1; } - len = st.st_size; + maxlen = st.st_size; /* According to readlink(2) lstat can report st_size == 0 for some symlinks, such as those in /proc or /sys. */ - if (len == 0) - len = uv__fs_pathmax_size(req->path); + if (maxlen == 0) + maxlen = uv__fs_pathmax_size(req->path); #else - len = uv__fs_pathmax_size(req->path); + maxlen = uv__fs_pathmax_size(req->path); #endif - buf = uv__malloc(len + 1); + buf = uv__malloc(maxlen); if (buf == NULL) { errno = ENOMEM; @@ -479,17 +429,28 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { } #if defined(__MVS__) - len = os390_readlink(req->path, buf, len); + len = os390_readlink(req->path, buf, maxlen); #else - len = readlink(req->path, buf, len); + len = readlink(req->path, buf, maxlen); #endif - if (len == -1) { uv__free(buf); return -1; } + /* Uncommon case: resize to make room for the trailing nul byte. */ + if (len == maxlen) { + newbuf = uv__realloc(buf, len + 1); + + if (newbuf == NULL) { + uv__free(buf); + return -1; + } + + buf = newbuf; + } + buf[len] = '\0'; req->ptr = buf; @@ -739,10 +700,48 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { static ssize_t uv__fs_utime(uv_fs_t* req) { +#if defined(__linux__) \ + || defined(_AIX71) \ + || defined(__sun) + /* utimesat() has nanosecond resolution but we stick to microseconds + * for the sake of consistency with other platforms. + */ + struct timespec ts[2]; + ts[0].tv_sec = req->atime; + ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; + ts[1].tv_sec = req->mtime; + ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; + return utimensat(AT_FDCWD, req->path, ts, 0); +#elif defined(__APPLE__) \ + || defined(__DragonFly__) \ + || defined(__FreeBSD__) \ + || defined(__FreeBSD_kernel__) \ + || defined(__NetBSD__) \ + || defined(__OpenBSD__) + struct timeval tv[2]; + tv[0].tv_sec = req->atime; + tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; + tv[1].tv_sec = req->mtime; + tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; + return utimes(req->path, tv); +#elif defined(_AIX) \ + && !defined(_AIX71) struct utimbuf buf; buf.actime = req->atime; buf.modtime = req->mtime; - return utime(req->path, &buf); /* TODO use utimes() where available */ + return utime(req->path, &buf); +#elif defined(__MVS__) + attrib_t atr; + memset(&atr, 0, sizeof(atr)); + atr.att_mtimechg = 1; + atr.att_atimechg = 1; + atr.att_mtime = req->mtime; + atr.att_atime = req->atime; + return __lchattr((char*) req->path, &atr, sizeof(atr)); +#else + errno = ENOSYS; + return -1; +#endif } @@ -780,25 +779,7 @@ static ssize_t uv__fs_write(uv_fs_t* req) { if (no_pwritev) retry: # endif { - off_t written; - size_t index; - - written = 0; - index = 0; - r = 0; - do { - if (req->bufs[index].len > 0) { - r = pwrite(req->file, - req->bufs[index].base, - req->bufs[index].len, - req->off + written); - if (r > 0) - written += r; - } - index++; - } while (index < req->nbufs && r >= 0); - if (written > 0) - r = written; + r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off); } # if defined(__linux__) else { @@ -827,26 +808,41 @@ done: static ssize_t uv__fs_copyfile(uv_fs_t* req) { #if defined(__APPLE__) && !TARGET_OS_IPHONE /* On macOS, use the native copyfile(3). */ + static int can_clone; copyfile_flags_t flags; + char buf[64]; + size_t len; + int major; flags = COPYFILE_ALL; if (req->flags & UV_FS_COPYFILE_EXCL) flags |= COPYFILE_EXCL; -#ifdef COPYFILE_CLONE - if (req->flags & UV_FS_COPYFILE_FICLONE) - flags |= COPYFILE_CLONE; -#endif - + /* Check OS version. Cloning is only supported on macOS >= 10.12. */ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { -#ifdef COPYFILE_CLONE_FORCE - flags |= COPYFILE_CLONE_FORCE; -#else - return UV_ENOSYS; -#endif + if (can_clone == 0) { + len = sizeof(buf); + if (sysctlbyname("kern.osrelease", buf, &len, NULL, 0)) + return UV__ERR(errno); + + if (1 != sscanf(buf, "%d", &major)) + abort(); + + can_clone = -1 + 2 * (major >= 16); /* macOS >= 10.12 */ + } + + if (can_clone < 0) + return UV_ENOSYS; } + /* copyfile() simply ignores COPYFILE_CLONE if it's not supported. */ + if (req->flags & UV_FS_COPYFILE_FICLONE) + flags |= 1 << 24; /* COPYFILE_CLONE */ + + if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) + flags |= 1 << 25; /* COPYFILE_CLONE_FORCE */ + return copyfile(req->path, req->new_path, NULL, flags); #else uv_fs_t fs_req; @@ -906,9 +902,11 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { /* If an error occurred that the sendfile fallback also won't handle, or this is a force clone then exit. Otherwise, fall through to try using sendfile(). */ - if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) || - req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { - err = -errno; + if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) { + err = UV__ERR(errno); + goto out; + } else if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { + err = UV_ENOTSUP; goto out; } } else { @@ -968,7 +966,11 @@ out: } } - return result; + if (result == 0) + return 0; + + errno = UV__ERR(result); + return -1; #endif } @@ -1084,9 +1086,21 @@ static int uv__fs_fstat(int fd, uv_stat_t *buf) { return ret; } +static size_t uv__fs_buf_offset(uv_buf_t* bufs, size_t size) { + size_t offset; + /* Figure out which bufs are done */ + for (offset = 0; size > 0 && bufs[offset].len <= size; ++offset) + size -= bufs[offset].len; + + /* Fix a partial read/write */ + if (size > 0) { + bufs[offset].base += size; + bufs[offset].len -= size; + } + return offset; +} -typedef ssize_t (*uv__fs_buf_iter_processor)(uv_fs_t* req); -static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process) { +static ssize_t uv__fs_write_all(uv_fs_t* req) { unsigned int iovmax; unsigned int nbufs; uv_buf_t* bufs; @@ -1103,7 +1117,10 @@ static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process) if (req->nbufs > iovmax) req->nbufs = iovmax; - result = process(req); + do + result = uv__fs_write(req); + while (result < 0 && errno == EINTR); + if (result <= 0) { if (total == 0) total = result; @@ -1113,14 +1130,12 @@ static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process) if (req->off >= 0) req->off += result; + req->nbufs = uv__fs_buf_offset(req->bufs, result); req->bufs += req->nbufs; nbufs -= req->nbufs; total += result; } - if (errno == EINTR && total == -1) - return total; - if (bufs != req->bufsml) uv__free(bufs); @@ -1137,7 +1152,8 @@ static void uv__fs_work(struct uv__work* w) { ssize_t r; req = container_of(w, uv_fs_t, work_req); - retry_on_eintr = !(req->fs_type == UV_FS_CLOSE); + retry_on_eintr = !(req->fs_type == UV_FS_CLOSE || + req->fs_type == UV_FS_READ); do { errno = 0; @@ -1155,6 +1171,7 @@ static void uv__fs_work(struct uv__work* w) { X(COPYFILE, uv__fs_copyfile(req)); X(FCHMOD, fchmod(req->file, req->mode)); X(FCHOWN, fchown(req->file, req->uid, req->gid)); + X(LCHOWN, lchown(req->path, req->uid, req->gid)); X(FDATASYNC, uv__fs_fdatasync(req)); X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); X(FSYNC, uv__fs_fsync(req)); @@ -1165,7 +1182,7 @@ static void uv__fs_work(struct uv__work* w) { X(MKDIR, mkdir(req->path, req->mode)); X(MKDTEMP, uv__fs_mkdtemp(req)); X(OPEN, uv__fs_open(req)); - X(READ, uv__fs_buf_iter(req, uv__fs_read)); + X(READ, uv__fs_read(req)); X(SCANDIR, uv__fs_scandir(req)); X(READLINK, uv__fs_readlink(req)); X(REALPATH, uv__fs_realpath(req)); @@ -1176,7 +1193,7 @@ static void uv__fs_work(struct uv__work* w) { X(SYMLINK, symlink(req->path, req->new_path)); X(UNLINK, unlink(req->path)); X(UTIME, uv__fs_utime(req)); - X(WRITE, uv__fs_buf_iter(req, uv__fs_write)); + X(WRITE, uv__fs_write_all(req)); default: abort(); } #undef X @@ -1281,6 +1298,20 @@ int uv_fs_fchown(uv_loop_t* loop, } +int uv_fs_lchown(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_uid_t uid, + uv_gid_t gid, + uv_fs_cb cb) { + INIT(LCHOWN); + PATH; + req->uid = uid; + req->gid = gid; + POST; +} + + int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { INIT(FDATASYNC); req->file = file; diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c index 47d8024..c430562 100644 --- a/Utilities/cmlibuv/src/unix/fsevents.c +++ b/Utilities/cmlibuv/src/unix/fsevents.c @@ -255,42 +255,55 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, path = paths[i]; len = strlen(path); + if (handle->realpath_len == 0) + continue; /* This should be unreachable */ + /* Filter out paths that are outside handle's request */ - if (strncmp(path, handle->realpath, handle->realpath_len) != 0) + if (len < handle->realpath_len) + continue; + + if (handle->realpath_len != len && + path[handle->realpath_len] != '/') + /* Make sure that realpath actually named a directory, + * or that we matched the whole string */ continue; - if (handle->realpath_len > 1 || *handle->realpath != '/') { + if (memcmp(path, handle->realpath, handle->realpath_len) != 0) + continue; + + if (!(handle->realpath_len == 1 && handle->realpath[0] == '/')) { + /* Remove common prefix, unless the watched folder is "/" */ path += handle->realpath_len; len -= handle->realpath_len; - /* Skip forward slash */ - if (*path != '\0') { + /* Ignore events with path equal to directory itself */ + if (len <= 1 && (flags & kFSEventStreamEventFlagItemIsDir)) + continue; + + if (len == 0) { + /* Since we're using fsevents to watch the file itself, + * realpath == path, and we now need to get the basename of the file back + * (for commonality with other codepaths and platforms). */ + while (len < handle->realpath_len && path[-1] != '/') { + path--; + len++; + } + /* Created and Removed seem to be always set, but don't make sense */ + flags &= ~kFSEventsRenamed; + } else { + /* Skip forward slash */ path++; len--; } } -#ifdef MAC_OS_X_VERSION_10_7 - /* Ignore events with path equal to directory itself */ - if (len == 0) - continue; -#else - if (len == 0 && (flags & kFSEventStreamEventFlagItemIsDir)) - continue; -#endif /* MAC_OS_X_VERSION_10_7 */ - /* Do not emit events from subdirectories (without option set) */ - if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != 0) { + if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != '\0') { pos = strchr(path + 1, '/'); if (pos != NULL) continue; } -#ifndef MAC_OS_X_VERSION_10_7 - path = ""; - len = 0; -#endif /* MAC_OS_X_VERSION_10_7 */ - event = uv__malloc(sizeof(*event) + len); if (event == NULL) break; @@ -299,22 +312,11 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, memcpy(event->path, path, len + 1); event->events = UV_RENAME; -#ifdef MAC_OS_X_VERSION_10_7 - if (0 != (flags & kFSEventsModified) && - 0 == (flags & kFSEventsRenamed)) { - event->events = UV_CHANGE; - } -#else - if (0 != (flags & kFSEventsModified) && - 0 != (flags & kFSEventStreamEventFlagItemIsDir) && - 0 == (flags & kFSEventStreamEventFlagItemRenamed)) { - event->events = UV_CHANGE; - } - if (0 == (flags & kFSEventStreamEventFlagItemIsDir) && - 0 == (flags & kFSEventStreamEventFlagItemRenamed)) { - event->events = UV_CHANGE; + if (0 == (flags & kFSEventsRenamed)) { + if (0 != (flags & kFSEventsModified) || + 0 == (flags & kFSEventStreamEventFlagItemIsDir)) + event->events = UV_CHANGE; } -#endif /* MAC_OS_X_VERSION_10_7 */ QUEUE_INSERT_TAIL(&head, &event->member); } @@ -836,7 +838,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { handle->cf_cb->data = handle; uv_async_init(handle->loop, handle->cf_cb, uv__fsevents_cb); - handle->cf_cb->flags |= UV__HANDLE_INTERNAL; + handle->cf_cb->flags |= UV_HANDLE_INTERNAL; uv_unref((uv_handle_t*) handle->cf_cb); err = uv_mutex_init(&handle->cf_mutex); diff --git a/Utilities/cmlibuv/src/unix/getaddrinfo.c b/Utilities/cmlibuv/src/unix/getaddrinfo.c index 10e8afd..6d23fbe 100644 --- a/Utilities/cmlibuv/src/unix/getaddrinfo.c +++ b/Utilities/cmlibuv/src/unix/getaddrinfo.c @@ -27,6 +27,7 @@ #include "uv.h" #include "internal.h" +#include "idna.h" #include <errno.h> #include <stddef.h> /* NULL */ @@ -141,15 +142,34 @@ int uv_getaddrinfo(uv_loop_t* loop, const char* hostname, const char* service, const struct addrinfo* hints) { + char hostname_ascii[256]; size_t hostname_len; size_t service_len; size_t hints_len; size_t len; char* buf; + long rc; if (req == NULL || (hostname == NULL && service == NULL)) return UV_EINVAL; + /* FIXME(bnoordhuis) IDNA does not seem to work z/OS, + * probably because it uses EBCDIC rather than ASCII. + */ +#ifdef __MVS__ + (void) &hostname_ascii; +#else + if (hostname != NULL) { + rc = uv__idna_toascii(hostname, + hostname + strlen(hostname), + hostname_ascii, + hostname_ascii + sizeof(hostname_ascii)); + if (rc < 0) + return rc; + hostname = hostname_ascii; + } +#endif + hostname_len = hostname ? strlen(hostname) + 1 : 0; service_len = service ? strlen(service) + 1 : 0; hints_len = hints ? sizeof(*hints) : 0; @@ -186,6 +206,7 @@ int uv_getaddrinfo(uv_loop_t* loop, if (cb) { uv__work_submit(loop, &req->work_req, + UV__WORK_SLOW_IO, uv__getaddrinfo_work, uv__getaddrinfo_done); return 0; diff --git a/Utilities/cmlibuv/src/unix/getnameinfo.c b/Utilities/cmlibuv/src/unix/getnameinfo.c index d9e6f79..b695081 100644 --- a/Utilities/cmlibuv/src/unix/getnameinfo.c +++ b/Utilities/cmlibuv/src/unix/getnameinfo.c @@ -109,6 +109,7 @@ int uv_getnameinfo(uv_loop_t* loop, if (getnameinfo_cb) { uv__work_submit(loop, &req->work_req, + UV__WORK_SLOW_IO, uv__getnameinfo_work, uv__getnameinfo_done); return 0; diff --git a/Utilities/cmlibuv/src/unix/ibmi.c b/Utilities/cmlibuv/src/unix/ibmi.c index 02e90fb..13fed6c 100644 --- a/Utilities/cmlibuv/src/unix/ibmi.c +++ b/Utilities/cmlibuv/src/unix/ibmi.c @@ -72,7 +72,8 @@ void uv_loadavg(double avg[3]) { int uv_resident_set_memory(size_t* rss) { - return UV_ENOSYS; + *rss = 0; + return 0; } diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h index 89c6eb1..48fe6e8 100644 --- a/Utilities/cmlibuv/src/unix/internal.h +++ b/Utilities/cmlibuv/src/unix/internal.h @@ -137,26 +137,6 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t; -/* handle flags */ -enum { - UV_CLOSING = 0x01, /* uv_close() called but not finished. */ - UV_CLOSED = 0x02, /* close(2) finished. */ - UV_STREAM_READING = 0x04, /* uv_read_start() called. */ - UV_STREAM_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */ - UV_STREAM_SHUT = 0x10, /* Write side closed. */ - UV_STREAM_READABLE = 0x20, /* The stream is readable */ - UV_STREAM_WRITABLE = 0x40, /* The stream is writable */ - UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */ - UV_STREAM_READ_PARTIAL = 0x100, /* read(2) read less than requested. */ - UV_STREAM_READ_EOF = 0x200, /* read(2) read EOF. */ - UV_TCP_NODELAY = 0x400, /* Disable Nagle. */ - UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */ - UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */ - UV_HANDLE_IPV6 = 0x10000, /* Handle is bound to a IPv6 socket. */ - UV_UDP_PROCESSING = 0x20000, /* Handle is running the send callback queue. */ - UV_HANDLE_BOUND = 0x40000 /* Handle is bound to an address and port */ -}; - /* loop flags */ enum { UV_LOOP_BLOCK_SIGPROF = 1 @@ -215,7 +195,6 @@ int uv__nonblock_fcntl(int fd, int set); int uv__close(int fd); /* preserves errno */ int uv__close_nocheckstdio(int fd); int uv__socket(int domain, int type, int protocol); -int uv__dup(int fd); ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags); void uv__make_close_pending(uv_handle_t* handle); int uv__getiovmax(void); @@ -229,6 +208,7 @@ int uv__io_active(const uv__io_t* w, unsigned int events); int uv__io_check_fd(uv_loop_t* loop, int fd); void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */ int uv__io_fork(uv_loop_t* loop); +int uv__fd_exists(uv_loop_t* loop, int fd); /* async */ void uv__async_stop(uv_loop_t* loop); @@ -261,10 +241,6 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay); /* pipe */ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); -/* timer */ -void uv__run_timers(uv_loop_t* loop); -int uv__next_timeout(const uv_loop_t* loop); - /* signal */ void uv__signal_close(uv_signal_t* handle); void uv__signal_global_once_init(void); @@ -289,7 +265,6 @@ void uv__prepare_close(uv_prepare_t* handle); void uv__process_close(uv_process_t* handle); void uv__stream_close(uv_stream_t* handle); void uv__tcp_close(uv_tcp_t* handle); -void uv__timer_close(uv_timer_t* handle); void uv__udp_close(uv_udp_t* handle); void uv__udp_finish_close(uv_udp_t* handle); uv_handle_type uv__handle_type(int fd); @@ -319,24 +294,6 @@ int uv__fsevents_init(uv_fs_event_t* handle); int uv__fsevents_close(uv_fs_event_t* handle); void uv__fsevents_loop_delete(uv_loop_t* loop); -/* OSX < 10.7 has no file events, polyfill them */ -#ifndef MAC_OS_X_VERSION_10_7 - -static const int kFSEventStreamCreateFlagFileEvents = 0x00000010; -static const int kFSEventStreamEventFlagItemCreated = 0x00000100; -static const int kFSEventStreamEventFlagItemRemoved = 0x00000200; -static const int kFSEventStreamEventFlagItemInodeMetaMod = 0x00000400; -static const int kFSEventStreamEventFlagItemRenamed = 0x00000800; -static const int kFSEventStreamEventFlagItemModified = 0x00001000; -static const int kFSEventStreamEventFlagItemFinderInfoMod = 0x00002000; -static const int kFSEventStreamEventFlagItemChangeOwner = 0x00004000; -static const int kFSEventStreamEventFlagItemXattrMod = 0x00008000; -static const int kFSEventStreamEventFlagItemIsFile = 0x00010000; -static const int kFSEventStreamEventFlagItemIsDir = 0x00020000; -static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000; - -#endif /* __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 */ - #endif /* defined(__APPLE__) */ UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) { diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c index a30fd73..c24f96e 100644 --- a/Utilities/cmlibuv/src/unix/kqueue.c +++ b/Utilities/cmlibuv/src/unix/kqueue.c @@ -261,8 +261,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w = loop->watchers[fd]; if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. */ - /* TODO batch up */ + /* File descriptor that we've stopped watching, disarm it. + * TODO: batch up. */ struct kevent events[1]; EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); @@ -452,49 +452,48 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, const char* path, unsigned int flags) { -#if defined(__APPLE__) - struct stat statbuf; -#endif /* defined(__APPLE__) */ int fd; if (uv__is_active(handle)) return UV_EINVAL; - /* TODO open asynchronously - but how do we report back errors? */ - fd = open(path, O_RDONLY); - if (fd == -1) - return UV__ERR(errno); - - uv__handle_start(handle); - uv__io_init(&handle->event_watcher, uv__fs_event, fd); - handle->path = uv__strdup(path); - handle->cb = cb; - #if defined(__APPLE__) - if (uv__has_forked_with_cfrunloop) - goto fallback; - /* Nullify field to perform checks later */ handle->cf_cb = NULL; handle->realpath = NULL; handle->realpath_len = 0; handle->cf_flags = flags; - if (fstat(fd, &statbuf)) - goto fallback; - /* FSEvents works only with directories */ - if (!(statbuf.st_mode & S_IFDIR)) - goto fallback; - - /* The fallback fd is no longer needed */ - uv__close(fd); - handle->event_watcher.fd = -1; - - return uv__fsevents_init(handle); - -fallback: + if (!uv__has_forked_with_cfrunloop) { + int r; + /* The fallback fd is not used */ + handle->event_watcher.fd = -1; + handle->path = uv__strdup(path); + if (handle->path == NULL) + return UV_ENOMEM; + handle->cb = cb; + r = uv__fsevents_init(handle); + if (r == 0) { + uv__handle_start(handle); + } else { + uv__free(handle->path); + handle->path = NULL; + } + return r; + } #endif /* defined(__APPLE__) */ + /* TODO open asynchronously - but how do we report back errors? */ + fd = open(path, O_RDONLY); + if (fd == -1) + return UV__ERR(errno); + + handle->path = uv__strdup(path); + if (handle->path == NULL) + return UV_ENOMEM; + handle->cb = cb; + uv__handle_start(handle); + uv__io_init(&handle->event_watcher, uv__fs_event, fd); uv__io_start(handle->loop, &handle->event_watcher, POLLIN); return 0; @@ -502,29 +501,29 @@ fallback: int uv_fs_event_stop(uv_fs_event_t* handle) { + int r; + r = 0; + if (!uv__is_active(handle)) return 0; uv__handle_stop(handle); #if defined(__APPLE__) - if (uv__has_forked_with_cfrunloop || uv__fsevents_close(handle)) -#endif /* defined(__APPLE__) */ - { - uv__io_close(handle->loop, &handle->event_watcher); - } - - uv__free(handle->path); - handle->path = NULL; + if (!uv__has_forked_with_cfrunloop) + r = uv__fsevents_close(handle); +#endif if (handle->event_watcher.fd != -1) { - /* When FSEvents is used, we don't use the event_watcher's fd under certain - * confitions. (see uv_fs_event_start) */ + uv__io_close(handle->loop, &handle->event_watcher); uv__close(handle->event_watcher.fd); handle->event_watcher.fd = -1; } - return 0; + uv__free(handle->path); + handle->path = NULL; + + return r; } diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c index b63c25f..3341b94 100644 --- a/Utilities/cmlibuv/src/unix/linux-core.c +++ b/Utilities/cmlibuv/src/unix/linux-core.c @@ -20,7 +20,7 @@ /* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their * EPOLL* counterparts. We use the POLL* variants in this file because that - * is what libuv uses elsewhere and it avoids a dependency on <sys/epoll.h>. + * is what libuv uses elsewhere. */ #include "uv.h" @@ -34,6 +34,7 @@ #include <errno.h> #include <net/if.h> +#include <sys/epoll.h> #include <sys/param.h> #include <sys/prctl.h> #include <sys/sysinfo.h> @@ -51,7 +52,7 @@ #ifdef HAVE_IFADDRS_H # if defined(__ANDROID__) -# include "android-ifaddrs.h" +# include "uv/android-ifaddrs.h" # else # include <ifaddrs.h> # endif @@ -84,13 +85,13 @@ static unsigned long read_cpufreq(unsigned int cpunum); int uv__platform_loop_init(uv_loop_t* loop) { int fd; - fd = uv__epoll_create1(UV__EPOLL_CLOEXEC); + fd = epoll_create1(EPOLL_CLOEXEC); /* epoll_create1() can fail either because it's not implemented (old kernel) * or because it doesn't understand the EPOLL_CLOEXEC flag. */ if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) { - fd = uv__epoll_create(256); + fd = epoll_create(256); if (fd != -1) uv__cloexec(fd, 1); @@ -134,20 +135,20 @@ void uv__platform_loop_delete(uv_loop_t* loop) { void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct uv__epoll_event* events; - struct uv__epoll_event dummy; + struct epoll_event* events; + struct epoll_event dummy; uintptr_t i; uintptr_t nfds; assert(loop->watchers != NULL); - events = (struct uv__epoll_event*) loop->watchers[loop->nwatchers]; + events = (struct epoll_event*) loop->watchers[loop->nwatchers]; nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; if (events != NULL) /* Invalidate events with same file descriptor */ for (i = 0; i < nfds; i++) - if ((int) events[i].data == fd) - events[i].data = -1; + if (events[i].data.fd == fd) + events[i].data.fd = -1; /* Remove the file descriptor from the epoll. * This avoids a problem where the same file description remains open @@ -160,25 +161,26 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings. */ memset(&dummy, 0, sizeof(dummy)); - uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &dummy); + epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy); } } int uv__io_check_fd(uv_loop_t* loop, int fd) { - struct uv__epoll_event e; + struct epoll_event e; int rc; + memset(&e, 0, sizeof(e)); e.events = POLLIN; - e.data = -1; + e.data.fd = -1; rc = 0; - if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e)) + if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e)) if (errno != EEXIST) rc = UV__ERR(errno); if (rc == 0) - if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e)) + if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e)) abort(); return rc; @@ -195,16 +197,14 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { * that being the largest value I have seen in the wild (and only once.) */ static const int max_safe_timeout = 1789569; - static int no_epoll_pwait; - static int no_epoll_wait; - struct uv__epoll_event events[1024]; - struct uv__epoll_event* pe; - struct uv__epoll_event e; + struct epoll_event events[1024]; + struct epoll_event* pe; + struct epoll_event e; int real_timeout; QUEUE* q; uv__io_t* w; sigset_t sigset; - uint64_t sigmask; + sigset_t* psigset; uint64_t base; int have_signals; int nevents; @@ -219,6 +219,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { return; } + memset(&e, 0, sizeof(e)); + while (!QUEUE_EMPTY(&loop->watcher_queue)) { q = QUEUE_HEAD(&loop->watcher_queue); QUEUE_REMOVE(q); @@ -230,35 +232,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { assert(w->fd < (int) loop->nwatchers); e.events = w->pevents; - e.data = w->fd; + e.data.fd = w->fd; if (w->events == 0) - op = UV__EPOLL_CTL_ADD; + op = EPOLL_CTL_ADD; else - op = UV__EPOLL_CTL_MOD; + op = EPOLL_CTL_MOD; /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching * events, skip the syscall and squelch the events after epoll_wait(). */ - if (uv__epoll_ctl(loop->backend_fd, op, w->fd, &e)) { + if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) { if (errno != EEXIST) abort(); - assert(op == UV__EPOLL_CTL_ADD); + assert(op == EPOLL_CTL_ADD); /* We've reactivated a file descriptor that's been watched before. */ - if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_MOD, w->fd, &e)) + if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e)) abort(); } w->events = w->pevents; } - sigmask = 0; + psigset = NULL; if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { sigemptyset(&sigset); sigaddset(&sigset, SIGPROF); - sigmask |= 1 << (SIGPROF - 1); + psigset = &sigset; } assert(timeout >= -1); @@ -273,30 +275,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) timeout = max_safe_timeout; - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) - abort(); - - if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) { - nfds = uv__epoll_pwait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout, - sigmask); - if (nfds == -1 && errno == ENOSYS) - no_epoll_pwait = 1; - } else { - nfds = uv__epoll_wait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout); - if (nfds == -1 && errno == ENOSYS) - no_epoll_wait = 1; - } - - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) - abort(); + nfds = epoll_pwait(loop->backend_fd, + events, + ARRAY_SIZE(events), + timeout, + psigset); /* Update loop->time unconditionally. It's tempting to skip the update when * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the @@ -317,12 +300,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } if (nfds == -1) { - if (errno == ENOSYS) { - /* epoll_wait() or epoll_pwait() failed, try the other system call. */ - assert(no_epoll_wait == 0 || no_epoll_pwait == 0); - continue; - } - if (errno != EINTR) abort(); @@ -344,7 +321,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; for (i = 0; i < nfds; i++) { pe = events + i; - fd = pe->data; + fd = pe->data.fd; /* Skip invalidated events, see uv__platform_invalidate_fd */ if (fd == -1) @@ -361,7 +338,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { * Ignore all errors because we may be racing with another thread * when the file descriptor is closed. */ - uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, pe); + epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe); continue; } @@ -388,7 +365,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { * free when we switch over to edge-triggered I/O. */ if (pe->events == POLLERR || pe->events == POLLHUP) - pe->events |= w->pevents & (POLLIN | POLLOUT | UV__POLLPRI); + pe->events |= + w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); if (pe->events != 0) { /* Run signal watchers last. This also affects child process watchers @@ -851,9 +829,10 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { return !exclude_type; } -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { #ifndef HAVE_IFADDRS_H + *count = 0; + *addresses = NULL; return UV_ENOSYS; #else struct ifaddrs *addrs, *ent; @@ -861,12 +840,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int i; struct sockaddr_ll *sll; - if (getifaddrs(&addrs)) - return UV__ERR(errno); - *count = 0; *addresses = NULL; + if (getifaddrs(&addrs)) + return UV__ERR(errno); + /* Count the number of interfaces */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) @@ -875,8 +854,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, (*count)++; } - if (*count == 0) + if (*count == 0) { + freeifaddrs(addrs); return 0; + } *addresses = uv__malloc(*count * sizeof(**addresses)); if (!(*addresses)) { @@ -920,6 +901,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, if (strcmp(address->name, ent->ifa_name) == 0) { sll = (struct sockaddr_ll*)ent->ifa_addr; memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr)); + } else { + memset(address->phys_addr, 0, sizeof(address->phys_addr)); } address++; } diff --git a/Utilities/cmlibuv/src/unix/linux-inotify.c b/Utilities/cmlibuv/src/unix/linux-inotify.c index bcad630..9b26202 100644 --- a/Utilities/cmlibuv/src/unix/linux-inotify.c +++ b/Utilities/cmlibuv/src/unix/linux-inotify.c @@ -19,7 +19,7 @@ */ #include "uv.h" -#include "tree.h" +#include "uv/tree.h" #include "internal.h" #include <stdint.h> @@ -278,6 +278,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, const char* path, unsigned int flags) { struct watcher_list* w; + size_t len; int events; int err; int wd; @@ -306,12 +307,13 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (w) goto no_insert; - w = uv__malloc(sizeof(*w) + strlen(path) + 1); + len = strlen(path) + 1; + w = uv__malloc(sizeof(*w) + len); if (w == NULL) return UV_ENOMEM; w->wd = wd; - w->path = strcpy((char*)(w + 1), path); + w->path = memcpy(w + 1, path, len); QUEUE_INIT(&w->watchers); w->iterating = 0; RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); diff --git a/Utilities/cmlibuv/src/unix/linux-syscalls.c b/Utilities/cmlibuv/src/unix/linux-syscalls.c index 89998de..bfd7544 100644 --- a/Utilities/cmlibuv/src/unix/linux-syscalls.c +++ b/Utilities/cmlibuv/src/unix/linux-syscalls.c @@ -77,56 +77,6 @@ # endif #endif /* __NR_eventfd2 */ -#ifndef __NR_epoll_create -# if defined(__x86_64__) -# define __NR_epoll_create 213 -# elif defined(__i386__) -# define __NR_epoll_create 254 -# elif defined(__arm__) -# define __NR_epoll_create (UV_SYSCALL_BASE + 250) -# endif -#endif /* __NR_epoll_create */ - -#ifndef __NR_epoll_create1 -# if defined(__x86_64__) -# define __NR_epoll_create1 291 -# elif defined(__i386__) -# define __NR_epoll_create1 329 -# elif defined(__arm__) -# define __NR_epoll_create1 (UV_SYSCALL_BASE + 357) -# endif -#endif /* __NR_epoll_create1 */ - -#ifndef __NR_epoll_ctl -# if defined(__x86_64__) -# define __NR_epoll_ctl 233 /* used to be 214 */ -# elif defined(__i386__) -# define __NR_epoll_ctl 255 -# elif defined(__arm__) -# define __NR_epoll_ctl (UV_SYSCALL_BASE + 251) -# endif -#endif /* __NR_epoll_ctl */ - -#ifndef __NR_epoll_wait -# if defined(__x86_64__) -# define __NR_epoll_wait 232 /* used to be 215 */ -# elif defined(__i386__) -# define __NR_epoll_wait 256 -# elif defined(__arm__) -# define __NR_epoll_wait (UV_SYSCALL_BASE + 252) -# endif -#endif /* __NR_epoll_wait */ - -#ifndef __NR_epoll_pwait -# if defined(__x86_64__) -# define __NR_epoll_pwait 281 -# elif defined(__i386__) -# define __NR_epoll_pwait 319 -# elif defined(__arm__) -# define __NR_epoll_pwait (UV_SYSCALL_BASE + 346) -# endif -#endif /* __NR_epoll_pwait */ - #ifndef __NR_inotify_init # if defined(__x86_64__) # define __NR_inotify_init 253 @@ -285,76 +235,6 @@ int uv__eventfd2(unsigned int count, int flags) { } -int uv__epoll_create(int size) { -#if defined(__NR_epoll_create) - return syscall(__NR_epoll_create, size); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_create1(int flags) { -#if defined(__NR_epoll_create1) - return syscall(__NR_epoll_create1, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event* events) { -#if defined(__NR_epoll_ctl) - return syscall(__NR_epoll_ctl, epfd, op, fd, events); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_wait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout) { -#if defined(__NR_epoll_wait) - int result; - result = syscall(__NR_epoll_wait, epfd, events, nevents, timeout); -#if MSAN_ACTIVE - if (result > 0) - __msan_unpoison(events, sizeof(events[0]) * result); -#endif - return result; -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_pwait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout, - uint64_t sigmask) { -#if defined(__NR_epoll_pwait) - int result; - result = syscall(__NR_epoll_pwait, - epfd, - events, - nevents, - timeout, - &sigmask, - sizeof(sigmask)); -#if MSAN_ACTIVE - if (result > 0) - __msan_unpoison(events, sizeof(events[0]) * result); -#endif - return result; -#else - return errno = ENOSYS, -1; -#endif -} - - int uv__inotify_init(void) { #if defined(__NR_inotify_init) return syscall(__NR_inotify_init); @@ -431,19 +311,6 @@ int uv__recvmmsg(int fd, } -int uv__utimesat(int dirfd, - const char* path, - const struct timespec times[2], - int flags) -{ -#if defined(__NR_utimensat) - return syscall(__NR_utimensat, dirfd, path, times, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { #if defined(__NR_preadv) return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); diff --git a/Utilities/cmlibuv/src/unix/linux-syscalls.h b/Utilities/cmlibuv/src/unix/linux-syscalls.h index 4c095e9..3dfd329 100644 --- a/Utilities/cmlibuv/src/unix/linux-syscalls.h +++ b/Utilities/cmlibuv/src/unix/linux-syscalls.h @@ -66,12 +66,6 @@ # define UV__SOCK_NONBLOCK UV__O_NONBLOCK #endif -/* epoll flags */ -#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC -#define UV__EPOLL_CTL_ADD 1 -#define UV__EPOLL_CTL_DEL 2 -#define UV__EPOLL_CTL_MOD 3 - /* inotify flags */ #define UV__IN_ACCESS 0x001 #define UV__IN_MODIFY 0x002 @@ -86,18 +80,6 @@ #define UV__IN_DELETE_SELF 0x400 #define UV__IN_MOVE_SELF 0x800 -#if defined(__x86_64__) -struct uv__epoll_event { - uint32_t events; - uint64_t data; -} __attribute__((packed)); -#else -struct uv__epoll_event { - uint32_t events; - uint64_t data; -}; -#endif - struct uv__inotify_event { int32_t wd; uint32_t mask; @@ -113,18 +95,6 @@ struct uv__mmsghdr { int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags); int uv__eventfd(unsigned int count); -int uv__epoll_create(int size); -int uv__epoll_create1(int flags); -int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event *ev); -int uv__epoll_wait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout); -int uv__epoll_pwait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout, - uint64_t sigmask); int uv__eventfd2(unsigned int count, int flags); int uv__inotify_init(void); int uv__inotify_init1(int flags); @@ -140,10 +110,6 @@ int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen, unsigned int flags); -int uv__utimesat(int dirfd, - const char* path, - const struct timespec times[2], - int flags); ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset); ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset); int uv__dup3(int oldfd, int newfd, int flags); diff --git a/Utilities/cmlibuv/src/unix/loop.c b/Utilities/cmlibuv/src/unix/loop.c index 99ead6c..c2a03d7 100644 --- a/Utilities/cmlibuv/src/unix/loop.c +++ b/Utilities/cmlibuv/src/unix/loop.c @@ -20,7 +20,7 @@ */ #include "uv.h" -#include "tree.h" +#include "uv/tree.h" #include "internal.h" #include "heap-inl.h" #include <stdlib.h> @@ -74,7 +74,7 @@ int uv_loop_init(uv_loop_t* loop) { goto fail_signal_init; uv__handle_unref(&loop->child_watcher); - loop->child_watcher.flags |= UV__HANDLE_INTERNAL; + loop->child_watcher.flags |= UV_HANDLE_INTERNAL; QUEUE_INIT(&loop->process_handles); err = uv_rwlock_init(&loop->cloexec_lock); @@ -90,7 +90,7 @@ int uv_loop_init(uv_loop_t* loop) { goto fail_async_init; uv__handle_unref(&loop->wq_async); - loop->wq_async.flags |= UV__HANDLE_INTERNAL; + loop->wq_async.flags |= UV_HANDLE_INTERNAL; return 0; diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c index 2605c11..a2a4e52 100644 --- a/Utilities/cmlibuv/src/unix/netbsd.c +++ b/Utilities/cmlibuv/src/unix/netbsd.c @@ -40,15 +40,6 @@ #include <unistd.h> #include <time.h> -static uv_mutex_t process_title_mutex; -static uv_once_t process_title_mutex_once = UV_ONCE_INIT; -static char *process_title; - - -static void init_process_title_mutex_once(void) { - uv_mutex_init(&process_title_mutex); -} - int uv__platform_loop_init(uv_loop_t* loop) { return uv__kqueue_init(loop); @@ -96,7 +87,8 @@ int uv_exepath(char* buffer, size_t* size) { /* Copy string from the intermediate buffer to outer one with appropriate * length. */ - strlcpy(buffer, int_buf, *size); + /* TODO(bnoordhuis) Check uv__strscpy() return value. */ + uv__strscpy(buffer, int_buf, *size); /* Set new size. */ *size = strlen(buffer); @@ -134,65 +126,6 @@ uint64_t uv_get_total_memory(void) { } -char** uv_setup_args(int argc, char** argv) { - process_title = argc ? uv__strdup(argv[0]) : NULL; - return argv; -} - - -int uv_set_process_title(const char* title) { - char* new_title; - - new_title = uv__strdup(title); - - uv_once(&process_title_mutex_once, init_process_title_mutex_once); - uv_mutex_lock(&process_title_mutex); - - if (process_title == NULL) { - uv_mutex_unlock(&process_title_mutex); - return UV_ENOMEM; - } - - uv__free(process_title); - process_title = new_title; - setproctitle("%s", title); - - uv_mutex_unlock(&process_title_mutex); - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - size_t len; - - if (buffer == NULL || size == 0) - return UV_EINVAL; - - uv_once(&process_title_mutex_once, init_process_title_mutex_once); - uv_mutex_lock(&process_title_mutex); - - if (process_title) { - len = strlen(process_title) + 1; - - if (size < len) { - uv_mutex_unlock(&process_title_mutex); - return UV_ENOBUFS; - } - - memcpy(buffer, process_title, len); - } else { - len = 0; - } - - uv_mutex_unlock(&process_title_mutex); - - buffer[len] = '\0'; - - return 0; -} - - int uv_resident_set_memory(size_t* rss) { kvm_t *kd = NULL; struct kinfo_proc2 *kinfo = NULL; diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c index ce937cd..bffb58b 100644 --- a/Utilities/cmlibuv/src/unix/openbsd.c +++ b/Utilities/cmlibuv/src/unix/openbsd.c @@ -36,16 +36,6 @@ #include <unistd.h> -static uv_mutex_t process_title_mutex; -static uv_once_t process_title_mutex_once = UV_ONCE_INIT; -static char *process_title; - - -static void init_process_title_mutex_once(void) { - uv_mutex_init(&process_title_mutex); -} - - int uv__platform_loop_init(uv_loop_t* loop) { return uv__kqueue_init(loop); } @@ -146,65 +136,6 @@ uint64_t uv_get_total_memory(void) { } -char** uv_setup_args(int argc, char** argv) { - process_title = argc ? uv__strdup(argv[0]) : NULL; - return argv; -} - - -int uv_set_process_title(const char* title) { - char* new_title; - - new_title = uv__strdup(title); - - uv_once(&process_title_mutex_once, init_process_title_mutex_once); - uv_mutex_lock(&process_title_mutex); - - if (process_title == NULL) { - uv_mutex_unlock(&process_title_mutex); - return UV_ENOMEM; - } - - uv__free(process_title); - process_title = new_title; - setproctitle("%s", title); - - uv_mutex_unlock(&process_title_mutex); - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - size_t len; - - if (buffer == NULL || size == 0) - return UV_EINVAL; - - uv_once(&process_title_mutex_once, init_process_title_mutex_once); - uv_mutex_lock(&process_title_mutex); - - if (process_title) { - len = strlen(process_title) + 1; - - if (size < len) { - uv_mutex_unlock(&process_title_mutex); - return UV_ENOBUFS; - } - - memcpy(buffer, process_title, len); - } else { - len = 0; - } - - uv_mutex_unlock(&process_title_mutex); - - buffer[len] = '\0'; - - return 0; -} - - int uv_resident_set_memory(size_t* rss) { struct kinfo_proc kinfo; size_t page_size = getpagesize(); diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c index a5dd344..1040d66 100644 --- a/Utilities/cmlibuv/src/unix/os390-syscalls.c +++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c @@ -141,7 +141,7 @@ static void init_message_queue(uv__os390_epoll* lst) { } msg; /* initialize message queue */ - lst->msg_queue = msgget(IPC_PRIVATE, 0622 | IPC_CREAT); + lst->msg_queue = msgget(IPC_PRIVATE, 0600 | IPC_CREAT); if (lst->msg_queue == -1) abort(); @@ -255,12 +255,13 @@ int epoll_ctl(uv__os390_epoll* lst, lst->items[fd].events = event->events; lst->items[fd].revents = 0; } else if (op == EPOLL_CTL_MOD) { - if (fd >= lst->size || lst->items[fd].fd == -1) { + if (fd >= lst->size - 1 || lst->items[fd].fd == -1) { uv_mutex_unlock(&global_epoll_lock); errno = ENOENT; return -1; } lst->items[fd].events = event->events; + lst->items[fd].revents = 0; } else abort(); @@ -275,8 +276,9 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, struct pollfd* pfds; int pollret; int reventcount; + int nevents; - size = _SET_FDS_MSGS(size, 1, lst->size - 1); + _SET_FDS_MSGS(size, 1, lst->size - 1); pfds = lst->items; pollret = poll(pfds, size, timeout); if (pollret <= 0) @@ -285,19 +287,28 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, pollret = _NFDS(pollret) + _NMSGS(pollret); reventcount = 0; + nevents = 0; for (int i = 0; i < lst->size && i < maxevents && reventcount < pollret; ++i) { struct epoll_event ev; + struct pollfd* pfd; - if (pfds[i].fd == -1 || pfds[i].revents == 0) + pfd = &pfds[i]; + if (pfd->fd == -1 || pfd->revents == 0) continue; - ev.fd = pfds[i].fd; - ev.events = pfds[i].revents; - events[reventcount++] = ev; + ev.fd = pfd->fd; + ev.events = pfd->revents; + if (pfd->revents & POLLIN && pfd->revents & POLLOUT) + reventcount += 2; + else if (pfd->revents & (POLLIN | POLLOUT)) + ++reventcount; + + pfd->revents = 0; + events[nevents++] = ev; } - return reventcount; + return nevents; } @@ -493,7 +504,7 @@ ssize_t os390_readlink(const char* path, char* buf, size_t len) { size_t strnlen(const char* str, size_t maxlen) { - void* p = memchr(str, 0, maxlen); + char* p = memchr(str, 0, maxlen); if (p == NULL) return maxlen; else diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.h b/Utilities/cmlibuv/src/unix/os390-syscalls.h index 6e34a88..ea59910 100644 --- a/Utilities/cmlibuv/src/unix/os390-syscalls.h +++ b/Utilities/cmlibuv/src/unix/os390-syscalls.h @@ -36,10 +36,6 @@ #define MAX_ITEMS_PER_EPOLL 1024 #define UV__O_CLOEXEC 0x80000 -#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC -#define UV__EPOLL_CTL_ADD EPOLL_CTL_ADD -#define UV__EPOLL_CTL_DEL EPOLL_CTL_DEL -#define UV__EPOLL_CTL_MOD EPOLL_CTL_MOD struct epoll_event { int events; diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c index f766b39..dc146e3 100644 --- a/Utilities/cmlibuv/src/unix/os390.c +++ b/Utilities/cmlibuv/src/unix/os390.c @@ -229,15 +229,15 @@ static int getexe(const int pid, char* buf, size_t len) { assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A'); /* Get the offset from the lowest 3 bytes */ - Output_path = (char*)(&Output_buf) + - (Output_buf.Output_data.offsetPath & 0x00FFFFFF); + Output_path = (struct Output_path_type*) ((char*) (&Output_buf) + + (Output_buf.Output_data.offsetPath & 0x00FFFFFF)); if (Output_path->len >= len) { errno = ENOBUFS; return -1; } - strncpy(buf, Output_path->path, len); + uv__strscpy(buf, Output_path->path, len); return 0; } @@ -357,13 +357,11 @@ uint64_t uv_get_total_memory(void) { int uv_resident_set_memory(size_t* rss) { - char* psa; char* ascb; char* rax; size_t nframes; - psa = PSA_PTR; - ascb = *(char* __ptr32 *)(psa + PSAAOLD); + ascb = *(char* __ptr32 *)(PSA_PTR + PSAAOLD); rax = *(char* __ptr32 *)(ascb + ASCBRSME); nframes = *(unsigned int*)(rax + RAXFMCT); @@ -512,7 +510,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses, /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0; - + memset(address->phys_addr, 0, sizeof(address->phys_addr)); address++; } @@ -531,12 +529,14 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { struct ifreq* p; int count_v6; + *count = 0; + *addresses = NULL; + /* get the ipv6 addresses first */ uv_interface_address_t* addresses_v6; uv__interface_addresses_v6(&addresses_v6, &count_v6); /* now get the ipv4 addresses */ - *count = 0; /* Assume maximum buffer size allowable */ maxsize = 16384; @@ -578,6 +578,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { (*count)++; } + if (*count == 0) { + uv__close(sockfd); + return 0; + } + /* Alloc the return interface structs */ *addresses = uv__malloc((*count + count_v6) * sizeof(uv_interface_address_t)); @@ -624,6 +629,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { } address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; + memset(address->phys_addr, 0, sizeof(address->phys_addr)); address++; } @@ -662,7 +668,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { /* Remove the file descriptor from the epoll. */ if (loop->ep != NULL) - epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy); + epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, &dummy); } @@ -751,7 +757,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { memcpy(reg_struct.__rfis_rftok, handle->rfis_rftok, sizeof(handle->rfis_rftok)); - /* + /* * This call will take "/" as the path argument in case we * don't care to supply the correct path. The system will simply * ignore it. @@ -838,9 +844,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { e.fd = w->fd; if (w->events == 0) - op = UV__EPOLL_CTL_ADD; + op = EPOLL_CTL_ADD; else - op = UV__EPOLL_CTL_MOD; + op = EPOLL_CTL_MOD; /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching * events, skip the syscall and squelch the events after epoll_wait(). @@ -849,10 +855,10 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { if (errno != EEXIST) abort(); - assert(op == UV__EPOLL_CTL_ADD); + assert(op == EPOLL_CTL_ADD); /* We've reactivated a file descriptor that's been watched before. */ - if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e)) + if (epoll_ctl(loop->ep, EPOLL_CTL_MOD, w->fd, &e)) abort(); } @@ -934,7 +940,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { * Ignore all errors because we may be racing with another thread * when the file descriptor is closed. */ - epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe); + epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, pe); continue; } @@ -987,7 +993,7 @@ void uv__set_process_title(const char* title) { } int uv__io_fork(uv_loop_t* loop) { - /* + /* Nullify the msg queue but don't close it because it is still being used by the parent. */ diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c index 42846b9..9657bc9 100644 --- a/Utilities/cmlibuv/src/unix/pipe.c +++ b/Utilities/cmlibuv/src/unix/pipe.c @@ -64,8 +64,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { sockfd = err; memset(&saddr, 0, sizeof saddr); - strncpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path) - 1); - saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0'; + uv__strscpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path)); saddr.sun_family = AF_UNIX; if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) { @@ -130,7 +129,20 @@ void uv__pipe_close(uv_pipe_t* handle) { int uv_pipe_open(uv_pipe_t* handle, uv_file fd) { + int flags; + int mode; int err; + flags = 0; + + if (uv__fd_exists(handle->loop, fd)) + return UV_EEXIST; + + do + mode = fcntl(fd, F_GETFL); + while (mode == -1 && errno == EINTR); + + if (mode == -1) + return UV__ERR(errno); /* according to docs, must be EBADF */ err = uv__nonblock(fd, 1); if (err) @@ -142,9 +154,13 @@ int uv_pipe_open(uv_pipe_t* handle, uv_file fd) { return err; #endif /* defined(__APPLE__) */ - return uv__stream_open((uv_stream_t*)handle, - fd, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + mode &= O_ACCMODE; + if (mode != O_WRONLY) + flags |= UV_HANDLE_READABLE; + if (mode != O_RDONLY) + flags |= UV_HANDLE_WRITABLE; + + return uv__stream_open((uv_stream_t*)handle, fd, flags); } @@ -167,8 +183,7 @@ void uv_pipe_connect(uv_connect_t* req, } memset(&saddr, 0, sizeof saddr); - strncpy(saddr.sun_path, name, sizeof(saddr.sun_path) - 1); - saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0'; + uv__strscpy(saddr.sun_path, name, sizeof(saddr.sun_path)); saddr.sun_family = AF_UNIX; do { @@ -194,7 +209,7 @@ void uv_pipe_connect(uv_connect_t* req, if (new_sock) { err = uv__stream_open((uv_stream_t*)handle, uv__stream_fd(handle), - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); } if (err == 0) diff --git a/Utilities/cmlibuv/src/unix/poll.c b/Utilities/cmlibuv/src/unix/poll.c index f3b0bf4..3d5022b 100644 --- a/Utilities/cmlibuv/src/unix/poll.c +++ b/Utilities/cmlibuv/src/unix/poll.c @@ -68,6 +68,9 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { int err; + if (uv__fd_exists(loop, fd)) + return UV_EEXIST; + err = uv__io_check_fd(loop, fd); if (err) return err; diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c index 1bded8d..e9579f5 100644 --- a/Utilities/cmlibuv/src/unix/process.c +++ b/Utilities/cmlibuv/src/unix/process.c @@ -250,9 +250,9 @@ static int uv__process_open_stream(uv_stdio_container_t* container, flags = 0; if (container->flags & UV_WRITABLE_PIPE) - flags |= UV_STREAM_READABLE; + flags |= UV_HANDLE_READABLE; if (container->flags & UV_READABLE_PIPE) - flags |= UV_STREAM_WRITABLE; + flags |= UV_HANDLE_WRITABLE; return uv__stream_open(container->data.stream, pipefds[0], flags); } @@ -334,7 +334,7 @@ static void uv__process_child_init(const uv_process_options_t* options, use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR); close_fd = use_fd; - if (use_fd == -1) { + if (use_fd < 0) { uv__write_int(error_fd, UV__ERR(errno)); _exit(127); } diff --git a/Utilities/cmlibuv/src/unix/proctitle.c b/Utilities/cmlibuv/src/unix/proctitle.c index 1a8c7a7..a5ce203 100644 --- a/Utilities/cmlibuv/src/unix/proctitle.c +++ b/Utilities/cmlibuv/src/unix/proctitle.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include <string.h> +extern void uv__set_process_title_platform_init(void); extern void uv__set_process_title(const char* title); static uv_mutex_t process_title_mutex; @@ -38,6 +39,9 @@ static struct { static void init_process_title_mutex_once(void) { uv_mutex_init(&process_title_mutex); +#ifdef __APPLE__ + uv__set_process_title_platform_init(); +#endif } diff --git a/Utilities/cmlibuv/src/unix/signal.c b/Utilities/cmlibuv/src/unix/signal.c index b9d0a56..01aa55f 100644 --- a/Utilities/cmlibuv/src/unix/signal.c +++ b/Utilities/cmlibuv/src/unix/signal.c @@ -54,8 +54,7 @@ static void uv__signal_unregister_handler(int signum); static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT; static struct uv__signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree); -static int uv__signal_lock_pipefd[2]; - +static int uv__signal_lock_pipefd[2] = { -1, -1 }; RB_GENERATE_STATIC(uv__signal_tree_s, uv_signal_s, tree_entry, @@ -64,7 +63,7 @@ RB_GENERATE_STATIC(uv__signal_tree_s, static void uv__signal_global_reinit(void); static void uv__signal_global_init(void) { - if (!uv__signal_lock_pipefd[0]) + if (uv__signal_lock_pipefd[0] == -1) /* pthread_atfork can register before and after handlers, one * for each child. This only registers one for the child. That * state is both persistent and cumulative, so if we keep doing @@ -74,15 +73,11 @@ static void uv__signal_global_init(void) { if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit)) abort(); - if (uv__make_pipe(uv__signal_lock_pipefd, 0)) - abort(); - - if (uv__signal_unlock()) - abort(); + uv__signal_global_reinit(); } -static void uv__signal_global_reinit(void) { +UV_DESTRUCTOR(static void uv__signal_global_fini(void)) { /* We can only use signal-safe functions here. * That includes read/write and close, fortunately. * We do all of this directly here instead of resetting @@ -90,11 +85,26 @@ static void uv__signal_global_reinit(void) { * uv__signal_global_once_init is only called from uv_loop_init * and this needs to function in existing loops. */ - uv__close(uv__signal_lock_pipefd[0]); - uv__signal_lock_pipefd[0] = -1; - uv__close(uv__signal_lock_pipefd[1]); - uv__signal_lock_pipefd[1] = -1; - uv__signal_global_init(); + if (uv__signal_lock_pipefd[0] != -1) { + uv__close(uv__signal_lock_pipefd[0]); + uv__signal_lock_pipefd[0] = -1; + } + + if (uv__signal_lock_pipefd[1] != -1) { + uv__close(uv__signal_lock_pipefd[1]); + uv__signal_lock_pipefd[1] = -1; + } +} + + +static void uv__signal_global_reinit(void) { + uv__signal_global_fini(); + + if (uv__make_pipe(uv__signal_lock_pipefd, 0)) + abort(); + + if (uv__signal_unlock()) + abort(); } @@ -103,7 +113,6 @@ void uv__signal_global_once_init(void) { } - static int uv__signal_lock(void) { int r; char data; @@ -387,7 +396,7 @@ static int uv__signal_start(uv_signal_t* handle, */ first_handle = uv__signal_first_handle(signum); if (first_handle == NULL || - (!oneshot && (first_handle->flags & UV__SIGNAL_ONE_SHOT))) { + (!oneshot && (first_handle->flags & UV_SIGNAL_ONE_SHOT))) { err = uv__signal_register_handler(signum, oneshot); if (err) { /* Registering the signal handler failed. Must be an invalid signal. */ @@ -398,7 +407,7 @@ static int uv__signal_start(uv_signal_t* handle, handle->signum = signum; if (oneshot) - handle->flags |= UV__SIGNAL_ONE_SHOT; + handle->flags |= UV_SIGNAL_ONE_SHOT; RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle); @@ -455,20 +464,20 @@ static void uv__signal_event(uv_loop_t* loop, handle = msg->handle; if (msg->signum == handle->signum) { - assert(!(handle->flags & UV_CLOSING)); + assert(!(handle->flags & UV_HANDLE_CLOSING)); handle->signal_cb(handle, handle->signum); } handle->dispatched_signals++; - if (handle->flags & UV__SIGNAL_ONE_SHOT) + if (handle->flags & UV_SIGNAL_ONE_SHOT) uv__signal_stop(handle); /* If uv_close was called while there were caught signals that were not * yet dispatched, the uv__finish_close was deferred. Make close pending * now if this has happened. */ - if ((handle->flags & UV_CLOSING) && + if ((handle->flags & UV_HANDLE_CLOSING) && (handle->caught_signals == handle->dispatched_signals)) { uv__make_close_pending((uv_handle_t*) handle); } @@ -496,11 +505,11 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { if (w1->signum < w2->signum) return -1; if (w1->signum > w2->signum) return 1; - /* Handlers without UV__SIGNAL_ONE_SHOT set will come first, so if the first + /* Handlers without UV_SIGNAL_ONE_SHOT set will come first, so if the first * handler returned is a one-shot handler, the rest will be too. */ - f1 = w1->flags & UV__SIGNAL_ONE_SHOT; - f2 = w2->flags & UV__SIGNAL_ONE_SHOT; + f1 = w1->flags & UV_SIGNAL_ONE_SHOT; + f2 = w2->flags & UV_SIGNAL_ONE_SHOT; if (f1 < f2) return -1; if (f1 > f2) return 1; @@ -549,8 +558,8 @@ static void uv__signal_stop(uv_signal_t* handle) { if (first_handle == NULL) { uv__signal_unregister_handler(handle->signum); } else { - rem_oneshot = handle->flags & UV__SIGNAL_ONE_SHOT; - first_oneshot = first_handle->flags & UV__SIGNAL_ONE_SHOT; + rem_oneshot = handle->flags & UV_SIGNAL_ONE_SHOT; + first_oneshot = first_handle->flags & UV_SIGNAL_ONE_SHOT; if (first_oneshot && !rem_oneshot) { ret = uv__signal_register_handler(handle->signum, 1); assert(ret == 0); diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c index 9bdd1c5..4b9123f 100644 --- a/Utilities/cmlibuv/src/unix/stream.c +++ b/Utilities/cmlibuv/src/unix/stream.c @@ -58,11 +58,19 @@ struct uv__stream_select_s { fd_set* swrite; size_t swrite_sz; }; -# define WRITE_RETRY_ON_ERROR(send_handle) \ + +/* Due to a possible kernel bug at least in OS X 10.10 "Yosemite", + * EPROTOTYPE can be returned while trying to write to a socket that is + * shutting down. If we retry the write, we should get the expected EPIPE + * instead. + */ +# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR || errno == EPROTOTYPE) +# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \ (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \ - (errno == EMSGSIZE && send_handle)) + (errno == EMSGSIZE && send_handle != NULL)) #else -# define WRITE_RETRY_ON_ERROR(send_handle) \ +# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR) +# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \ (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS) #endif /* defined(__APPLE__) */ @@ -220,7 +228,7 @@ static void uv__stream_osx_select(void* arg) { uv_sem_wait(&s->async_sem); /* Should be processed at this stage */ - assert((s->events == 0) || (stream->flags & UV_CLOSING)); + assert((s->events == 0) || (stream->flags & UV_HANDLE_CLOSING)); } } } @@ -248,7 +256,7 @@ static void uv__stream_osx_select_cb(uv_async_t* handle) { if ((events & POLLOUT) && uv__io_active(&stream->io_watcher, POLLOUT)) uv__stream_io(stream->loop, &stream->io_watcher, POLLOUT); - if (stream->flags & UV_CLOSING) + if (stream->flags & UV_HANDLE_CLOSING) return; /* NOTE: It is important to do it here, otherwise `select()` might be called @@ -342,7 +350,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { if (err) goto failed_async_init; - s->async.flags |= UV__HANDLE_INTERNAL; + s->async.flags |= UV_HANDLE_INTERNAL; uv__handle_unref(&s->async); err = uv_sem_init(&s->close_sem, 0); @@ -407,12 +415,14 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { stream->flags |= flags; if (stream->type == UV_TCP) { - if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1)) + if ((stream->flags & UV_HANDLE_TCP_NODELAY) && uv__tcp_nodelay(fd, 1)) return UV__ERR(errno); /* TODO Use delay the user passed in. */ - if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60)) + if ((stream->flags & UV_HANDLE_TCP_KEEPALIVE) && + uv__tcp_keepalive(fd, 1, 60)) { return UV__ERR(errno); + } } #if defined(__APPLE__) @@ -447,7 +457,7 @@ void uv__stream_flush_write_queue(uv_stream_t* stream, int error) { void uv__stream_destroy(uv_stream_t* stream) { assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT)); - assert(stream->flags & UV_CLOSED); + assert(stream->flags & UV_HANDLE_CLOSED); if (stream->connect_req) { uv__req_unregister(stream->loop, stream->connect_req); @@ -522,7 +532,7 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { stream = container_of(w, uv_stream_t, io_watcher); assert(events & POLLIN); assert(stream->accepted_fd == -1); - assert(!(stream->flags & UV_CLOSING)); + assert(!(stream->flags & UV_HANDLE_CLOSING)); uv__io_start(stream->loop, &stream->io_watcher, POLLIN); @@ -565,7 +575,8 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { return; } - if (stream->type == UV_TCP && (stream->flags & UV_TCP_SINGLE_ACCEPT)) { + if (stream->type == UV_TCP && + (stream->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) { /* Give other processes a chance to accept connections. */ struct timespec timeout = { 0, 1 }; nanosleep(&timeout, NULL); @@ -590,7 +601,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) { case UV_TCP: err = uv__stream_open(client, server->accepted_fd, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); if (err) { /* TODO handle error */ uv__close(server->accepted_fd); @@ -674,14 +685,14 @@ static void uv__drain(uv_stream_t* stream) { uv__stream_osx_interrupt_select(stream); /* Shutdown? */ - if ((stream->flags & UV_STREAM_SHUTTING) && - !(stream->flags & UV_CLOSING) && - !(stream->flags & UV_STREAM_SHUT)) { + if ((stream->flags & UV_HANDLE_SHUTTING) && + !(stream->flags & UV_HANDLE_CLOSING) && + !(stream->flags & UV_HANDLE_SHUT)) { assert(stream->shutdown_req); req = stream->shutdown_req; stream->shutdown_req = NULL; - stream->flags &= ~UV_STREAM_SHUTTING; + stream->flags &= ~UV_HANDLE_SHUTTING; uv__req_unregister(stream->loop, req); err = 0; @@ -689,7 +700,7 @@ static void uv__drain(uv_stream_t* stream) { err = UV__ERR(errno); if (err == 0) - stream->flags |= UV_STREAM_SHUT; + stream->flags |= UV_HANDLE_SHUT; if (req->cb != NULL) req->cb(req, err); @@ -697,6 +708,14 @@ static void uv__drain(uv_stream_t* stream) { } +static ssize_t uv__writev(int fd, struct iovec* vec, size_t n) { + if (n == 1) + return write(fd, vec->iov_base, vec->iov_len); + else + return writev(fd, vec, n); +} + + static size_t uv__write_req_size(uv_write_t* req) { size_t size; @@ -709,6 +728,37 @@ static size_t uv__write_req_size(uv_write_t* req) { } +/* Returns 1 if all write request data has been written, or 0 if there is still + * more data to write. + * + * Note: the return value only says something about the *current* request. + * There may still be other write requests sitting in the queue. + */ +static int uv__write_req_update(uv_stream_t* stream, + uv_write_t* req, + size_t n) { + uv_buf_t* buf; + size_t len; + + assert(n <= stream->write_queue_size); + stream->write_queue_size -= n; + + buf = req->bufs + req->write_index; + + while (n > 0) { + len = n < buf->len ? n : buf->len; + buf->base += len; + buf->len -= len; + buf += (buf->len == 0); /* Advance to next buffer if this one is empty. */ + n -= len; + } + + req->write_index = buf - req->bufs; + + return req->write_index == req->nbufs; +} + + static void uv__write_req_finish(uv_write_t* req) { uv_stream_t* stream = req->handle; @@ -829,102 +879,32 @@ start: *pi = fd_to_send; } - do { + do n = sendmsg(uv__stream_fd(stream), &msg, 0); - } -#if defined(__APPLE__) - /* - * Due to a possible kernel bug at least in OS X 10.10 "Yosemite", - * EPROTOTYPE can be returned while trying to write to a socket that is - * shutting down. If we retry the write, we should get the expected EPIPE - * instead. - */ - while (n == -1 && (errno == EINTR || errno == EPROTOTYPE)); -#else - while (n == -1 && errno == EINTR); -#endif - } else { - do { - if (iovcnt == 1) { - n = write(uv__stream_fd(stream), iov[0].iov_base, iov[0].iov_len); - } else { - n = writev(uv__stream_fd(stream), iov, iovcnt); - } - } -#if defined(__APPLE__) - /* - * Due to a possible kernel bug at least in OS X 10.10 "Yosemite", - * EPROTOTYPE can be returned while trying to write to a socket that is - * shutting down. If we retry the write, we should get the expected EPIPE - * instead. - */ - while (n == -1 && (errno == EINTR || errno == EPROTOTYPE)); -#else - while (n == -1 && errno == EINTR); -#endif - } + while (n == -1 && RETRY_ON_WRITE_ERROR(errno)); - if (n < 0) { - if (!WRITE_RETRY_ON_ERROR(req->send_handle)) { - err = UV__ERR(errno); - goto error; - } else if (stream->flags & UV_STREAM_BLOCKING) { - /* If this is a blocking stream, try again. */ - goto start; - } + /* Ensure the handle isn't sent again in case this is a partial write. */ + if (n >= 0) + req->send_handle = NULL; } else { - /* Successful write */ - - while (n >= 0) { - uv_buf_t* buf = &(req->bufs[req->write_index]); - size_t len = buf->len; - - assert(req->write_index < req->nbufs); - - if ((size_t)n < len) { - buf->base += n; - buf->len -= n; - stream->write_queue_size -= n; - n = 0; - - /* There is more to write. */ - if (stream->flags & UV_STREAM_BLOCKING) { - /* - * If we're blocking then we should not be enabling the write - * watcher - instead we need to try again. - */ - goto start; - } else { - /* Break loop and ensure the watcher is pending. */ - break; - } - - } else { - /* Finished writing the buf at index req->write_index. */ - req->write_index++; - - assert((size_t)n >= len); - n -= len; - - assert(stream->write_queue_size >= len); - stream->write_queue_size -= len; + do + n = uv__writev(uv__stream_fd(stream), iov, iovcnt); + while (n == -1 && RETRY_ON_WRITE_ERROR(errno)); + } - if (req->write_index == req->nbufs) { - /* Then we're done! */ - assert(n == 0); - uv__write_req_finish(req); - /* TODO: start trying to write the next request. */ - return; - } - } - } + if (n == -1 && !IS_TRANSIENT_WRITE_ERROR(errno, req->send_handle)) { + err = UV__ERR(errno); + goto error; } - /* Either we've counted n down to zero or we've got EAGAIN. */ - assert(n == 0 || n == -1); + if (n > 0 && uv__write_req_update(stream, req, n)) { + uv__write_req_finish(req); + return; /* TODO(bnoordhuis) Start trying to write the next request. */ + } - /* Only non-blocking streams should use the write_watcher. */ - assert(!(stream->flags & UV_STREAM_BLOCKING)); + /* If this is a blocking stream, try again. */ + if (stream->flags & UV_HANDLE_BLOCKING_WRITES) + goto start; /* We're not done. */ uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); @@ -947,10 +927,16 @@ error: static void uv__write_callbacks(uv_stream_t* stream) { uv_write_t* req; QUEUE* q; + QUEUE pq; + + if (QUEUE_EMPTY(&stream->write_completed_queue)) + return; + + QUEUE_MOVE(&stream->write_completed_queue, &pq); - while (!QUEUE_EMPTY(&stream->write_completed_queue)) { + while (!QUEUE_EMPTY(&pq)) { /* Pop a req off write_completed_queue. */ - q = QUEUE_HEAD(&stream->write_completed_queue); + q = QUEUE_HEAD(&pq); req = QUEUE_DATA(q, uv_write_t, queue); QUEUE_REMOVE(q); uv__req_unregister(stream->loop, req); @@ -966,8 +952,6 @@ static void uv__write_callbacks(uv_stream_t* stream) { if (req->cb) req->cb(req, req->error); } - - assert(QUEUE_EMPTY(&stream->write_completed_queue)); } @@ -1015,13 +999,13 @@ uv_handle_type uv__handle_type(int fd) { static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { - stream->flags |= UV_STREAM_READ_EOF; + stream->flags |= UV_HANDLE_READ_EOF; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); stream->read_cb(stream, UV_EOF, buf); - stream->flags &= ~UV_STREAM_READING; + stream->flags &= ~UV_HANDLE_READING; } @@ -1121,6 +1105,7 @@ static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) { #ifdef __clang__ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wgnu-folding-constant" +# pragma clang diagnostic ignored "-Wvla-extension" #endif static void uv__read(uv_stream_t* stream) { @@ -1132,7 +1117,7 @@ static void uv__read(uv_stream_t* stream) { int err; int is_ipc; - stream->flags &= ~UV_STREAM_READ_PARTIAL; + stream->flags &= ~UV_HANDLE_READ_PARTIAL; /* Prevent loop starvation when the data comes in as fast as (or faster than) * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O. @@ -1141,11 +1126,11 @@ static void uv__read(uv_stream_t* stream) { is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc; - /* XXX: Maybe instead of having UV_STREAM_READING we just test if + /* XXX: Maybe instead of having UV_HANDLE_READING we just test if * tcp->read_cb is NULL or not? */ while (stream->read_cb - && (stream->flags & UV_STREAM_READING) + && (stream->flags & UV_HANDLE_READING) && (count-- > 0)) { assert(stream->alloc_cb != NULL); @@ -1186,7 +1171,7 @@ static void uv__read(uv_stream_t* stream) { /* Error */ if (errno == EAGAIN || errno == EWOULDBLOCK) { /* Wait for the next one. */ - if (stream->flags & UV_STREAM_READING) { + if (stream->flags & UV_HANDLE_READING) { uv__io_start(stream->loop, &stream->io_watcher, POLLIN); uv__stream_osx_interrupt_select(stream); } @@ -1199,8 +1184,8 @@ static void uv__read(uv_stream_t* stream) { } else { /* Error. User should call uv_close(). */ stream->read_cb(stream, UV__ERR(errno), &buf); - if (stream->flags & UV_STREAM_READING) { - stream->flags &= ~UV_STREAM_READING; + if (stream->flags & UV_HANDLE_READING) { + stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); @@ -1250,7 +1235,7 @@ static void uv__read(uv_stream_t* stream) { /* Return if we didn't fill the buffer, there is no more data to read. */ if (nread < buflen) { - stream->flags |= UV_STREAM_READ_PARTIAL; + stream->flags |= UV_HANDLE_READ_PARTIAL; return; } } @@ -1271,9 +1256,9 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { stream->type == UV_TTY || stream->type == UV_NAMED_PIPE); - if (!(stream->flags & UV_STREAM_WRITABLE) || - stream->flags & UV_STREAM_SHUT || - stream->flags & UV_STREAM_SHUTTING || + if (!(stream->flags & UV_HANDLE_WRITABLE) || + stream->flags & UV_HANDLE_SHUT || + stream->flags & UV_HANDLE_SHUTTING || uv__is_closing(stream)) { return UV_ENOTCONN; } @@ -1285,7 +1270,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { req->handle = stream; req->cb = cb; stream->shutdown_req = req; - stream->flags |= UV_STREAM_SHUTTING; + stream->flags |= UV_HANDLE_SHUTTING; uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); @@ -1302,7 +1287,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || stream->type == UV_TTY); - assert(!(stream->flags & UV_CLOSING)); + assert(!(stream->flags & UV_HANDLE_CLOSING)); if (stream->connect_req) { uv__stream_connect(stream); @@ -1311,7 +1296,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { assert(uv__stream_fd(stream) >= 0); - /* Ignore POLLHUP here. Even it it's set, there may still be data to read. */ + /* Ignore POLLHUP here. Even if it's set, there may still be data to read. */ if (events & (POLLIN | POLLERR | POLLHUP)) uv__read(stream); @@ -1325,9 +1310,9 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { * report the EOF yet because there is still data to read. */ if ((events & POLLHUP) && - (stream->flags & UV_STREAM_READING) && - (stream->flags & UV_STREAM_READ_PARTIAL) && - !(stream->flags & UV_STREAM_READ_EOF)) { + (stream->flags & UV_HANDLE_READING) && + (stream->flags & UV_HANDLE_READ_PARTIAL) && + !(stream->flags & UV_HANDLE_READ_EOF)) { uv_buf_t buf = { NULL, 0 }; uv__stream_eof(stream, &buf); } @@ -1417,7 +1402,7 @@ int uv_write2(uv_write_t* req, if (uv__stream_fd(stream) < 0) return UV_EBADF; - if (!(stream->flags & UV_STREAM_WRITABLE)) + if (!(stream->flags & UV_HANDLE_WRITABLE)) return -EPIPE; if (send_handle) { @@ -1487,7 +1472,7 @@ int uv_write2(uv_write_t* req, * if this assert fires then somehow the blocking stream isn't being * sufficiently flushed in uv__write. */ - assert(!(stream->flags & UV_STREAM_BLOCKING)); + assert(!(stream->flags & UV_HANDLE_BLOCKING_WRITES)); uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); } @@ -1568,16 +1553,16 @@ int uv_read_start(uv_stream_t* stream, assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || stream->type == UV_TTY); - if (stream->flags & UV_CLOSING) + if (stream->flags & UV_HANDLE_CLOSING) return UV_EINVAL; - if (!(stream->flags & UV_STREAM_READABLE)) + if (!(stream->flags & UV_HANDLE_READABLE)) return -ENOTCONN; - /* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just + /* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just * expresses the desired state of the user. */ - stream->flags |= UV_STREAM_READING; + stream->flags |= UV_HANDLE_READING; /* TODO: try to do the read inline? */ /* TODO: keep track of tcp state. If we've gotten a EOF then we should @@ -1598,10 +1583,10 @@ int uv_read_start(uv_stream_t* stream, int uv_read_stop(uv_stream_t* stream) { - if (!(stream->flags & UV_STREAM_READING)) + if (!(stream->flags & UV_HANDLE_READING)) return 0; - stream->flags &= ~UV_STREAM_READING; + stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); @@ -1614,12 +1599,12 @@ int uv_read_stop(uv_stream_t* stream) { int uv_is_readable(const uv_stream_t* stream) { - return !!(stream->flags & UV_STREAM_READABLE); + return !!(stream->flags & UV_HANDLE_READABLE); } int uv_is_writable(const uv_stream_t* stream) { - return !!(stream->flags & UV_STREAM_WRITABLE); + return !!(stream->flags & UV_HANDLE_WRITABLE); } @@ -1668,6 +1653,7 @@ void uv__stream_close(uv_stream_t* handle) { uv__io_close(handle->loop, &handle->io_watcher); uv_read_stop(handle); uv__handle_stop(handle); + handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); if (handle->io_watcher.fd != -1) { /* Don't close stdio file descriptors. Nothing good comes from it. */ diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c index b92888e..aac6504 100644 --- a/Utilities/cmlibuv/src/unix/sunos.c +++ b/Utilities/cmlibuv/src/unix/sunos.c @@ -696,6 +696,8 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { #ifdef SUNOS_NO_IFADDRS int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + *count = 0; + *addresses = NULL; return UV_ENOSYS; } #else /* SUNOS_NO_IFADDRS */ @@ -709,13 +711,14 @@ static int uv__set_phys_addr(uv_interface_address_t* address, struct sockaddr_dl* sa_addr; int sockfd; - int i; + size_t i; struct arpreq arpreq; /* This appears to only work as root */ sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); for (i = 0; i < sizeof(address->phys_addr); i++) { + /* Check that all bytes of phys_addr are zero. */ if (address->phys_addr[i] != 0) return 0; } @@ -762,11 +765,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { struct ifaddrs* addrs; struct ifaddrs* ent; + *count = 0; + *addresses = NULL; + if (getifaddrs(&addrs)) return UV__ERR(errno); - *count = 0; - /* Count the number of interfaces */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { if (uv__ifaddr_exclude(ent)) @@ -774,6 +778,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { (*count)++; } + if (*count == 0) { + freeifaddrs(addrs); + return 0; + } + *addresses = uv__malloc(*count * sizeof(**addresses)); if (!(*addresses)) { freeifaddrs(addrs); diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c index 9a46793..2982851 100644 --- a/Utilities/cmlibuv/src/unix/tcp.c +++ b/Utilities/cmlibuv/src/unix/tcp.c @@ -216,7 +216,7 @@ int uv__tcp_connect(uv_connect_t* req, err = maybe_new_socket(handle, addr->sa_family, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); if (err) return err; @@ -263,13 +263,16 @@ int uv__tcp_connect(uv_connect_t* req, int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { int err; + if (uv__fd_exists(handle->loop, sock)) + return UV_EEXIST; + err = uv__nonblock(sock, 1); if (err) return err; return uv__stream_open((uv_stream_t*)handle, sock, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); } @@ -331,7 +334,7 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { } if (single_accept) - tcp->flags |= UV_TCP_SINGLE_ACCEPT; + tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; flags = 0; #if defined(__MVS__) @@ -398,9 +401,9 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int on) { } if (on) - handle->flags |= UV_TCP_NODELAY; + handle->flags |= UV_HANDLE_TCP_NODELAY; else - handle->flags &= ~UV_TCP_NODELAY; + handle->flags &= ~UV_HANDLE_TCP_NODELAY; return 0; } @@ -416,9 +419,9 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) { } if (on) - handle->flags |= UV_TCP_KEEPALIVE; + handle->flags |= UV_HANDLE_TCP_KEEPALIVE; else - handle->flags &= ~UV_TCP_KEEPALIVE; + handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE; /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge * uv_tcp_t with an int that's almost never used... @@ -430,9 +433,9 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) { int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { if (enable) - handle->flags &= ~UV_TCP_SINGLE_ACCEPT; + handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT; else - handle->flags |= UV_TCP_SINGLE_ACCEPT; + handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; return 0; } diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c index 303bc6e..2900470 100644 --- a/Utilities/cmlibuv/src/unix/thread.c +++ b/Utilities/cmlibuv/src/unix/thread.c @@ -44,108 +44,119 @@ #undef NANOSEC #define NANOSEC ((uint64_t) 1e9) +#if defined(PTHREAD_BARRIER_SERIAL_THREAD) +STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t)); +#endif -#if defined(UV__PTHREAD_BARRIER_FALLBACK) -/* TODO: support barrier_attr */ -int pthread_barrier_init(pthread_barrier_t* barrier, - const void* barrier_attr, - unsigned count) { +/* Note: guard clauses should match uv_barrier_t's in include/uv/uv-unix.h. */ +#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) +int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { + struct _uv_barrier* b; int rc; - _uv_barrier* b; if (barrier == NULL || count == 0) - return EINVAL; - - if (barrier_attr != NULL) - return ENOTSUP; + return UV_EINVAL; b = uv__malloc(sizeof(*b)); if (b == NULL) - return ENOMEM; + return UV_ENOMEM; b->in = 0; b->out = 0; b->threshold = count; - if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0) + rc = uv_mutex_init(&b->mutex); + if (rc != 0) goto error2; - if ((rc = pthread_cond_init(&b->cond, NULL)) != 0) + + rc = uv_cond_init(&b->cond); + if (rc != 0) goto error; barrier->b = b; return 0; error: - pthread_mutex_destroy(&b->mutex); + uv_mutex_destroy(&b->mutex); error2: uv__free(b); return rc; } -int pthread_barrier_wait(pthread_barrier_t* barrier) { - int rc; - _uv_barrier* b; + +int uv_barrier_wait(uv_barrier_t* barrier) { + struct _uv_barrier* b; + int last; if (barrier == NULL || barrier->b == NULL) - return EINVAL; + return UV_EINVAL; b = barrier->b; - /* Lock the mutex*/ - if ((rc = pthread_mutex_lock(&b->mutex)) != 0) - return rc; + uv_mutex_lock(&b->mutex); - /* Increment the count. If this is the first thread to reach the threshold, - wake up waiters, unlock the mutex, then return - PTHREAD_BARRIER_SERIAL_THREAD. */ if (++b->in == b->threshold) { b->in = 0; - b->out = b->threshold - 1; - rc = pthread_cond_signal(&b->cond); - assert(rc == 0); - - pthread_mutex_unlock(&b->mutex); - return PTHREAD_BARRIER_SERIAL_THREAD; + b->out = b->threshold; + uv_cond_signal(&b->cond); + } else { + do + uv_cond_wait(&b->cond, &b->mutex); + while (b->in != 0); } - /* Otherwise, wait for other threads until in is set to 0, - then return 0 to indicate this is not the first thread. */ - do { - if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0) - break; - } while (b->in != 0); - - /* mark thread exit */ - b->out--; - pthread_cond_signal(&b->cond); - pthread_mutex_unlock(&b->mutex); - return rc; + + last = (--b->out == 0); + if (!last) + uv_cond_signal(&b->cond); /* Not needed for last thread. */ + + uv_mutex_unlock(&b->mutex); + return last; } -int pthread_barrier_destroy(pthread_barrier_t* barrier) { - int rc; - _uv_barrier* b; - if (barrier == NULL || barrier->b == NULL) - return EINVAL; +void uv_barrier_destroy(uv_barrier_t* barrier) { + struct _uv_barrier* b; b = barrier->b; + uv_mutex_lock(&b->mutex); - if ((rc = pthread_mutex_lock(&b->mutex)) != 0) - return rc; + assert(b->in == 0); + assert(b->out == 0); - if (b->in > 0 || b->out > 0) - rc = EBUSY; - - pthread_mutex_unlock(&b->mutex); + if (b->in != 0 || b->out != 0) + abort(); - if (rc) - return rc; + uv_mutex_unlock(&b->mutex); + uv_mutex_destroy(&b->mutex); + uv_cond_destroy(&b->cond); - pthread_cond_destroy(&b->cond); - pthread_mutex_destroy(&b->mutex); uv__free(barrier->b); barrier->b = NULL; - return 0; } + +#else + +int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { + return UV__ERR(pthread_barrier_init(barrier, NULL, count)); +} + + +int uv_barrier_wait(uv_barrier_t* barrier) { + int rc; + + rc = pthread_barrier_wait(barrier); + if (rc != 0) + if (rc != PTHREAD_BARRIER_SERIAL_THREAD) + abort(); + + return rc == PTHREAD_BARRIER_SERIAL_THREAD; +} + + +void uv_barrier_destroy(uv_barrier_t* barrier) { + if (pthread_barrier_destroy(barrier)) + abort(); +} + #endif @@ -771,25 +782,6 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { } -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - return UV__ERR(pthread_barrier_init(barrier, NULL, count)); -} - - -void uv_barrier_destroy(uv_barrier_t* barrier) { - if (pthread_barrier_destroy(barrier)) - abort(); -} - - -int uv_barrier_wait(uv_barrier_t* barrier) { - int r = pthread_barrier_wait(barrier); - if (r && r != PTHREAD_BARRIER_SERIAL_THREAD) - abort(); - return r == PTHREAD_BARRIER_SERIAL_THREAD; -} - - int uv_key_create(uv_key_t* key) { return UV__ERR(pthread_key_create(key, NULL)); } diff --git a/Utilities/cmlibuv/src/unix/tty.c b/Utilities/cmlibuv/src/unix/tty.c index e8ea302..b8bc283 100644 --- a/Utilities/cmlibuv/src/unix/tty.c +++ b/Utilities/cmlibuv/src/unix/tty.c @@ -92,13 +92,15 @@ static int uv__tty_is_slave(const int fd) { return result; } -int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { +int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) { uv_handle_type type; int flags = 0; int newfd = -1; int r; int saved_flags; + int mode; char path[256]; + (void)unused; /* deprecated parameter is no longer needed */ /* File descriptors that refer to files cannot be monitored with epoll. * That restriction also applies to character devices like /dev/random @@ -108,6 +110,15 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { if (type == UV_FILE || type == UV_UNKNOWN_HANDLE) return UV_EINVAL; + /* Save the fd flags in case we need to restore them due to an error. */ + do + saved_flags = fcntl(fd, F_GETFL); + while (saved_flags == -1 && errno == EINTR); + + if (saved_flags == -1) + return UV__ERR(errno); + mode = saved_flags & O_ACCMODE; + /* Reopen the file descriptor when it refers to a tty. This lets us put the * tty in non-blocking mode without affecting other processes that share it * with us. @@ -125,14 +136,14 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { * slave device. */ if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0) - r = uv__open_cloexec(path, O_RDWR); + r = uv__open_cloexec(path, mode); else r = -1; if (r < 0) { /* fallback to using blocking writes */ - if (!readable) - flags |= UV_STREAM_BLOCKING; + if (mode != O_RDONLY) + flags |= UV_HANDLE_BLOCKING_WRITES; goto skip; } @@ -151,22 +162,6 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { fd = newfd; } -#if defined(__APPLE__) - /* Save the fd flags in case we need to restore them due to an error. */ - do - saved_flags = fcntl(fd, F_GETFL); - while (saved_flags == -1 && errno == EINTR); - - if (saved_flags == -1) { - if (newfd != -1) - uv__close(newfd); - return UV__ERR(errno); - } -#endif - - /* Pacify the compiler. */ - (void) &saved_flags; - skip: uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); @@ -174,7 +169,7 @@ skip: * the handle queue, since it was added by uv__handle_init in uv_stream_init. */ - if (!(flags & UV_STREAM_BLOCKING)) + if (!(flags & UV_HANDLE_BLOCKING_WRITES)) uv__nonblock(fd, 1); #if defined(__APPLE__) @@ -191,10 +186,10 @@ skip: } #endif - if (readable) - flags |= UV_STREAM_READABLE; - else - flags |= UV_STREAM_WRITABLE; + if (mode != O_WRONLY) + flags |= UV_HANDLE_READABLE; + if (mode != O_RDONLY) + flags |= UV_HANDLE_WRITABLE; uv__stream_open((uv_stream_t*) tty, fd, flags); tty->mode = UV_TTY_MODE_NORMAL; diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c index 74d613b..ec337ec 100644 --- a/Utilities/cmlibuv/src/unix/udp.c +++ b/Utilities/cmlibuv/src/unix/udp.c @@ -92,8 +92,8 @@ static void uv__udp_run_completed(uv_udp_t* handle) { uv_udp_send_t* req; QUEUE* q; - assert(!(handle->flags & UV_UDP_PROCESSING)); - handle->flags |= UV_UDP_PROCESSING; + assert(!(handle->flags & UV_HANDLE_UDP_PROCESSING)); + handle->flags |= UV_HANDLE_UDP_PROCESSING; while (!QUEUE_EMPTY(&handle->write_completed_queue)) { q = QUEUE_HEAD(&handle->write_completed_queue); @@ -128,7 +128,7 @@ static void uv__udp_run_completed(uv_udp_t* handle) { uv__handle_stop(handle); } - handle->flags &= ~UV_UDP_PROCESSING; + handle->flags &= ~UV_HANDLE_UDP_PROCESSING; } @@ -427,7 +427,7 @@ int uv__udp_send(uv_udp_send_t* req, QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue); uv__handle_start(handle); - if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) { + if (empty_queue && !(handle->flags & UV_HANDLE_UDP_PROCESSING)) { uv__udp_sendmsg(handle); /* `uv__udp_sendmsg` may not be able to do non-blocking write straight @@ -624,6 +624,9 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { if (handle->io_watcher.fd != -1) return UV_EBUSY; + if (uv__fd_exists(handle->loop, sock)) + return UV_EEXIST; + err = uv__nonblock(sock, 1); if (err) return err; @@ -757,14 +760,16 @@ int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { * IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case, * and use the general uv__setsockopt_maybe_char call otherwise. */ -#if defined(__sun) || defined(_AIX) || defined(__MVS__) +#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \ + defined(__MVS__) if (handle->flags & UV_HANDLE_IPV6) return uv__setsockopt(handle, IP_MULTICAST_TTL, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); -#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */ +#endif /* defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \ + defined(__MVS__) */ return uv__setsockopt_maybe_char(handle, IP_MULTICAST_TTL, @@ -780,14 +785,16 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { * IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case, * and use the general uv__setsockopt_maybe_char call otherwise. */ -#if defined(__sun) || defined(_AIX) || defined(__MVS__) +#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \ + defined(__MVS__) if (handle->flags & UV_HANDLE_IPV6) return uv__setsockopt(handle, IP_MULTICAST_LOOP, IPV6_MULTICAST_LOOP, &on, sizeof(on)); -#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */ +#endif /* defined(__sun) || defined(_AIX) ||defined(__OpenBSD__) || + defined(__MVS__) */ return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c index 15dec08..907ebf2 100644 --- a/Utilities/cmlibuv/src/uv-common.c +++ b/Utilities/cmlibuv/src/uv-common.c @@ -72,7 +72,9 @@ char* uv__strndup(const char* s, size_t n) { } void* uv__malloc(size_t size) { - return uv__allocator.local_malloc(size); + if (size > 0) + return uv__allocator.local_malloc(size); + return NULL; } void uv__free(void* ptr) { @@ -91,7 +93,10 @@ void* uv__calloc(size_t count, size_t size) { } void* uv__realloc(void* ptr, size_t size) { - return uv__allocator.local_realloc(ptr, size); + if (size > 0) + return uv__allocator.local_realloc(ptr, size); + uv__free(ptr); + return NULL; } int uv_replace_allocator(uv_malloc_func malloc_func, @@ -155,6 +160,18 @@ static const char* uv__unknown_err_code(int err) { return copy != NULL ? copy : "Unknown system error"; } +#define UV_ERR_NAME_GEN_R(name, _) \ +case UV_## name: \ + uv__strscpy(buf, #name, buflen); break; +char* uv_err_name_r(int err, char* buf, size_t buflen) { + switch (err) { + UV_ERRNO_MAP(UV_ERR_NAME_GEN_R) + default: snprintf(buf, buflen, "Unknown system error %d", err); + } + return buf; +} +#undef UV_ERR_NAME_GEN_R + #define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name; const char* uv_err_name(int err) { @@ -166,6 +183,19 @@ const char* uv_err_name(int err) { #undef UV_ERR_NAME_GEN +#define UV_STRERROR_GEN_R(name, msg) \ +case UV_ ## name: \ + snprintf(buf, buflen, "%s", msg); break; +char* uv_strerror_r(int err, char* buf, size_t buflen) { + switch (err) { + UV_ERRNO_MAP(UV_STRERROR_GEN_R) + default: snprintf(buf, buflen, "Unknown system error %d", err); + } + return buf; +} +#undef UV_STRERROR_GEN_R + + #define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg; const char* uv_strerror(int err) { switch (err) { @@ -359,7 +389,7 @@ void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { QUEUE_REMOVE(q); QUEUE_INSERT_TAIL(&loop->handle_queue, q); - if (h->flags & UV__HANDLE_INTERNAL) continue; + if (h->flags & UV_HANDLE_INTERNAL) continue; walk_cb(h, arg); } } @@ -388,9 +418,9 @@ static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) { fprintf(stream, "[%c%c%c] %-8s %p\n", - "R-"[!(h->flags & UV__HANDLE_REF)], - "A-"[!(h->flags & UV__HANDLE_ACTIVE)], - "I-"[!(h->flags & UV__HANDLE_INTERNAL)], + "R-"[!(h->flags & UV_HANDLE_REF)], + "A-"[!(h->flags & UV_HANDLE_ACTIVE)], + "I-"[!(h->flags & UV_HANDLE_INTERNAL)], type, (void*)h); } @@ -634,7 +664,7 @@ int uv_loop_close(uv_loop_t* loop) { QUEUE_FOREACH(q, &loop->handle_queue) { h = QUEUE_DATA(q, uv_handle_t, handle_queue); - if (!(h->flags & UV__HANDLE_INTERNAL)) + if (!(h->flags & UV_HANDLE_INTERNAL)) return UV_EBUSY; } diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h index c497d01..15ac4d0 100644 --- a/Utilities/cmlibuv/src/uv-common.h +++ b/Utilities/cmlibuv/src/uv-common.h @@ -32,14 +32,15 @@ #include <stddef.h> #if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" +# include "uv/stdint-msvc2008.h" #else # include <stdint.h> #endif #include "uv.h" -#include "tree.h" +#include "uv/tree.h" #include "queue.h" +#include "strscpy.h" #if EDOM > 0 # define UV__ERR(x) (-(x)) @@ -59,22 +60,67 @@ extern int snprintf(char*, size_t, const char*, ...); #define STATIC_ASSERT(expr) \ void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)]) -#ifndef _WIN32 +/* Handle flags. Some flags are specific to Windows or UNIX. */ enum { - UV__SIGNAL_ONE_SHOT = 0x80000, /* On signal reception remove sighandler */ - UV__HANDLE_INTERNAL = 0x8000, - UV__HANDLE_ACTIVE = 0x4000, - UV__HANDLE_REF = 0x2000, - UV__HANDLE_CLOSING = 0 /* no-op on unix */ + /* Used by all handles. */ + UV_HANDLE_CLOSING = 0x00000001, + UV_HANDLE_CLOSED = 0x00000002, + UV_HANDLE_ACTIVE = 0x00000004, + UV_HANDLE_REF = 0x00000008, + UV_HANDLE_INTERNAL = 0x00000010, + UV_HANDLE_ENDGAME_QUEUED = 0x00000020, + + /* Used by streams. */ + UV_HANDLE_LISTENING = 0x00000040, + UV_HANDLE_CONNECTION = 0x00000080, + UV_HANDLE_SHUTTING = 0x00000100, + UV_HANDLE_SHUT = 0x00000200, + UV_HANDLE_READ_PARTIAL = 0x00000400, + UV_HANDLE_READ_EOF = 0x00000800, + + /* Used by streams and UDP handles. */ + UV_HANDLE_READING = 0x00001000, + UV_HANDLE_BOUND = 0x00002000, + UV_HANDLE_READABLE = 0x00004000, + UV_HANDLE_WRITABLE = 0x00008000, + UV_HANDLE_READ_PENDING = 0x00010000, + UV_HANDLE_SYNC_BYPASS_IOCP = 0x00020000, + UV_HANDLE_ZERO_READ = 0x00040000, + UV_HANDLE_EMULATE_IOCP = 0x00080000, + UV_HANDLE_BLOCKING_WRITES = 0x00100000, + UV_HANDLE_CANCELLATION_PENDING = 0x00200000, + + /* Used by uv_tcp_t and uv_udp_t handles */ + UV_HANDLE_IPV6 = 0x00400000, + + /* Only used by uv_tcp_t handles. */ + UV_HANDLE_TCP_NODELAY = 0x01000000, + UV_HANDLE_TCP_KEEPALIVE = 0x02000000, + UV_HANDLE_TCP_SINGLE_ACCEPT = 0x04000000, + UV_HANDLE_TCP_ACCEPT_STATE_CHANGING = 0x08000000, + UV_HANDLE_TCP_SOCKET_CLOSED = 0x10000000, + UV_HANDLE_SHARED_TCP_SOCKET = 0x20000000, + + /* Only used by uv_udp_t handles. */ + UV_HANDLE_UDP_PROCESSING = 0x01000000, + + /* Only used by uv_pipe_t handles. */ + UV_HANDLE_NON_OVERLAPPED_PIPE = 0x01000000, + UV_HANDLE_PIPESERVER = 0x02000000, + + /* Only used by uv_tty_t handles. */ + UV_HANDLE_TTY_READABLE = 0x01000000, + UV_HANDLE_TTY_RAW = 0x02000000, + UV_HANDLE_TTY_SAVED_POSITION = 0x04000000, + UV_HANDLE_TTY_SAVED_ATTRIBUTES = 0x08000000, + + /* Only used by uv_signal_t handles. */ + UV_SIGNAL_ONE_SHOT_DISPATCHED = 0x01000000, + UV_SIGNAL_ONE_SHOT = 0x02000000, + + /* Only used by uv_poll_t handles. */ + UV_HANDLE_POLL_SLOW = 0x01000000 }; -#else -# define UV__SIGNAL_ONE_SHOT_DISPATCHED 0x200 -# define UV__SIGNAL_ONE_SHOT 0x100 -# define UV__HANDLE_INTERNAL 0x80 -# define UV__HANDLE_ACTIVE 0x40 -# define UV__HANDLE_REF 0x20 -# define UV__HANDLE_CLOSING 0x01 -#endif int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); @@ -119,8 +165,15 @@ void uv__fs_poll_close(uv_fs_poll_t* handle); int uv__getaddrinfo_translate_error(int sys_err); /* EAI_* error. */ +enum uv__work_kind { + UV__WORK_CPU, + UV__WORK_FAST_IO, + UV__WORK_SLOW_IO +}; + void uv__work_submit(uv_loop_t* loop, struct uv__work *w, + enum uv__work_kind kind, void (*work)(struct uv__work *w), void (*done)(struct uv__work *w, int status)); @@ -132,6 +185,10 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); void uv__fs_scandir_cleanup(uv_fs_t* req); +int uv__next_timeout(const uv_loop_t* loop); +void uv__run_timers(uv_loop_t* loop); +void uv__timer_close(uv_timer_t* handle); + #define uv__has_active_reqs(loop) \ ((loop)->active_reqs.count > 0) @@ -164,49 +221,47 @@ void uv__fs_scandir_cleanup(uv_fs_t* req); while (0) #define uv__is_active(h) \ - (((h)->flags & UV__HANDLE_ACTIVE) != 0) + (((h)->flags & UV_HANDLE_ACTIVE) != 0) #define uv__is_closing(h) \ - (((h)->flags & (UV_CLOSING | UV_CLOSED)) != 0) + (((h)->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED)) != 0) #define uv__handle_start(h) \ do { \ - assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) break; \ - (h)->flags |= UV__HANDLE_ACTIVE; \ - if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_add(h); \ + if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break; \ + (h)->flags |= UV_HANDLE_ACTIVE; \ + if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_add(h); \ } \ while (0) #define uv__handle_stop(h) \ do { \ - assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \ - if (((h)->flags & UV__HANDLE_ACTIVE) == 0) break; \ - (h)->flags &= ~UV__HANDLE_ACTIVE; \ - if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_rm(h); \ + if (((h)->flags & UV_HANDLE_ACTIVE) == 0) break; \ + (h)->flags &= ~UV_HANDLE_ACTIVE; \ + if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_rm(h); \ } \ while (0) #define uv__handle_ref(h) \ do { \ - if (((h)->flags & UV__HANDLE_REF) != 0) break; \ - (h)->flags |= UV__HANDLE_REF; \ - if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \ + if (((h)->flags & UV_HANDLE_REF) != 0) break; \ + (h)->flags |= UV_HANDLE_REF; \ + if (((h)->flags & UV_HANDLE_CLOSING) != 0) break; \ + if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \ } \ while (0) #define uv__handle_unref(h) \ do { \ - if (((h)->flags & UV__HANDLE_REF) == 0) break; \ - (h)->flags &= ~UV__HANDLE_REF; \ - if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \ + if (((h)->flags & UV_HANDLE_REF) == 0) break; \ + (h)->flags &= ~UV_HANDLE_REF; \ + if (((h)->flags & UV_HANDLE_CLOSING) != 0) break; \ + if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \ } \ while (0) #define uv__has_ref(h) \ - (((h)->flags & UV__HANDLE_REF) != 0) + (((h)->flags & UV_HANDLE_REF) != 0) #if defined(_WIN32) # define uv__handle_platform_init(h) ((h)->u.fd = -1) @@ -218,7 +273,7 @@ void uv__fs_scandir_cleanup(uv_fs_t* req); do { \ (h)->loop = (loop_); \ (h)->type = (type_); \ - (h)->flags = UV__HANDLE_REF; /* Ref the loop when active. */ \ + (h)->flags = UV_HANDLE_REF; /* Ref the loop when active. */ \ QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \ uv__handle_platform_init(h); \ } \ diff --git a/Utilities/cmlibuv/src/uv-data-getter-setters.c b/Utilities/cmlibuv/src/uv-data-getter-setters.c index 533e4a2..b7fcd4a 100644 --- a/Utilities/cmlibuv/src/uv-data-getter-setters.c +++ b/Utilities/cmlibuv/src/uv-data-getter-setters.c @@ -3,11 +3,11 @@ const char* uv_handle_type_name(uv_handle_type type) { switch (type) { #define XX(uc,lc) case UV_##uc: return #lc; - UV_HANDLE_TYPE_MAP(XX) + UV_HANDLE_TYPE_MAP(XX) #undef XX - case UV_FILE: return "file"; - case UV_HANDLE_TYPE_MAX: - case UV_UNKNOWN_HANDLE: return NULL; + case UV_FILE: return "file"; + case UV_HANDLE_TYPE_MAX: + case UV_UNKNOWN_HANDLE: return NULL; } return NULL; } @@ -31,10 +31,12 @@ void uv_handle_set_data(uv_handle_t* handle, void* data) { const char* uv_req_type_name(uv_req_type type) { switch (type) { #define XX(uc,lc) case UV_##uc: return #lc; - UV_REQ_TYPE_MAP(XX) + UV_REQ_TYPE_MAP(XX) #undef XX - case UV_REQ_TYPE_MAX: - case UV_UNKNOWN_REQ: return NULL; + case UV_REQ_TYPE_MAX: + case UV_UNKNOWN_REQ: + default: /* UV_REQ_TYPE_PRIVATE */ + return NULL; } return NULL; } diff --git a/Utilities/cmlibuv/src/win/async.c b/Utilities/cmlibuv/src/win/async.c index 0b636ed..d787f66 100644 --- a/Utilities/cmlibuv/src/win/async.c +++ b/Utilities/cmlibuv/src/win/async.c @@ -29,7 +29,7 @@ void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && !handle->async_sent) { assert(!(handle->flags & UV_HANDLE_CLOSED)); uv__handle_close(handle); @@ -71,9 +71,9 @@ int uv_async_send(uv_async_t* handle) { return -1; } - /* The user should make sure never to call uv_async_send to a closing */ - /* or closed handle. */ - assert(!(handle->flags & UV__HANDLE_CLOSING)); + /* The user should make sure never to call uv_async_send to a closing or + * closed handle. */ + assert(!(handle->flags & UV_HANDLE_CLOSING)); if (!uv__atomic_exchange_set(&handle->async_sent)) { POST_COMPLETION_FOR_REQ(loop, &handle->async_req); @@ -90,7 +90,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, handle->async_sent = 0; - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { uv_want_endgame(loop, (uv_handle_t*)handle); } else if (handle->async_cb != NULL) { handle->async_cb(handle); diff --git a/Utilities/cmlibuv/src/win/atomicops-inl.h b/Utilities/cmlibuv/src/win/atomicops-inl.h index 6d8126f..52713cf 100644 --- a/Utilities/cmlibuv/src/win/atomicops-inl.h +++ b/Utilities/cmlibuv/src/win/atomicops-inl.h @@ -29,10 +29,10 @@ /* Atomic set operation on char */ #ifdef _MSC_VER /* MSVC */ -/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less */ -/* efficient than InterlockedExchange, but InterlockedExchange8 does not */ -/* exist, and interlocked operations on larger targets might require the */ -/* target to be aligned. */ +/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less + * efficient than InterlockedExchange, but InterlockedExchange8 does not exist, + * and interlocked operations on larger targets might require the target to be + * aligned. */ #pragma intrinsic(_InterlockedOr8) static char INLINE uv__atomic_exchange_set(char volatile* target) { diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c index b8aad11..58309c6 100644 --- a/Utilities/cmlibuv/src/win/core.c +++ b/Utilities/cmlibuv/src/win/core.c @@ -33,6 +33,7 @@ #include "internal.h" #include "queue.h" #include "handle-inl.h" +#include "heap-inl.h" #include "req-inl.h" /* uv_once initialization guards */ @@ -221,6 +222,7 @@ static void uv_init(void) { int uv_loop_init(uv_loop_t* loop) { + struct heap* timer_heap; int err; /* Initialize libuv itself first */ @@ -246,7 +248,13 @@ int uv_loop_init(uv_loop_t* loop) { loop->endgame_handles = NULL; - RB_INIT(&loop->timers); + loop->timer_heap = timer_heap = uv__malloc(sizeof(*timer_heap)); + if (timer_heap == NULL) { + err = UV_ENOMEM; + goto fail_timers_alloc; + } + + heap_init(timer_heap); loop->check_handles = NULL; loop->prepare_handles = NULL; @@ -273,7 +281,7 @@ int uv_loop_init(uv_loop_t* loop) { goto fail_async_init; uv__handle_unref(&loop->wq_async); - loop->wq_async.flags |= UV__HANDLE_INTERNAL; + loop->wq_async.flags |= UV_HANDLE_INTERNAL; err = uv__loops_add(loop); if (err) @@ -285,6 +293,10 @@ fail_async_init: uv_mutex_destroy(&loop->wq_mutex); fail_mutex_init: + uv__free(timer_heap); + loop->timer_heap = NULL; + +fail_timers_alloc: CloseHandle(loop->iocp); loop->iocp = INVALID_HANDLE_VALUE; @@ -292,6 +304,13 @@ fail_mutex_init: } +void uv_update_time(uv_loop_t* loop) { + uint64_t new_time = uv__hrtime(1000); + assert(new_time >= loop->time); + loop->time = new_time; +} + + void uv__once_init(void) { uv_once(&uv_init_guard_, uv_init); } @@ -320,6 +339,9 @@ void uv__loop_close(uv_loop_t* loop) { uv_mutex_unlock(&loop->wq_mutex); uv_mutex_destroy(&loop->wq_mutex); + uv__free(loop->timer_heap); + loop->timer_heap = NULL; + CloseHandle(loop->iocp); } @@ -359,7 +381,7 @@ int uv_backend_timeout(const uv_loop_t* loop) { } -static void uv_poll(uv_loop_t* loop, DWORD timeout) { +static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { DWORD bytes; ULONG_PTR key; OVERLAPPED* overlapped; @@ -410,7 +432,7 @@ static void uv_poll(uv_loop_t* loop, DWORD timeout) { } -static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) { +static void uv__poll(uv_loop_t* loop, DWORD timeout) { BOOL success; uv_req_t* req; OVERLAPPED_ENTRY overlappeds[128]; @@ -422,12 +444,12 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) { timeout_time = loop->time + timeout; for (repeat = 0; ; repeat++) { - success = pGetQueuedCompletionStatusEx(loop->iocp, - overlappeds, - ARRAY_SIZE(overlappeds), - &count, - timeout, - FALSE); + success = GetQueuedCompletionStatusEx(loop->iocp, + overlappeds, + ARRAY_SIZE(overlappeds), + &count, + timeout, + FALSE); if (success) { for (i = 0; i < count; i++) { @@ -485,12 +507,6 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { DWORD timeout; int r; int ran_pending; - void (*poll)(uv_loop_t* loop, DWORD timeout); - - if (pGetQueuedCompletionStatusEx) - poll = &uv_poll_ex; - else - poll = &uv_poll; r = uv__loop_alive(loop); if (!r) @@ -498,7 +514,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { while (r != 0 && loop->stop_flag == 0) { uv_update_time(loop); - uv_process_timers(loop); + uv__run_timers(loop); ran_pending = uv_process_reqs(loop); uv_idle_invoke(loop); @@ -508,7 +524,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) timeout = uv_backend_timeout(loop); - (*poll)(loop, timeout); + if (pGetQueuedCompletionStatusEx) + uv__poll(loop, timeout); + else + uv__poll_wine(loop, timeout); + uv_check_invoke(loop); uv_process_endgames(loop); @@ -522,7 +542,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from * the check. */ - uv_process_timers(loop); + uv__run_timers(loop); } r = uv__loop_alive(loop); diff --git a/Utilities/cmlibuv/src/win/dl.c b/Utilities/cmlibuv/src/win/dl.c index 97ac1c1..676be4d 100644 --- a/Utilities/cmlibuv/src/win/dl.c +++ b/Utilities/cmlibuv/src/win/dl.c @@ -64,7 +64,8 @@ void uv_dlclose(uv_lib_t* lib) { int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) { - *ptr = (void*) GetProcAddress(lib->handle, name); + /* Cast though integer to suppress pedantic warning about forbidden cast. */ + *ptr = (void*)(uintptr_t) GetProcAddress(lib->handle, name); return uv__dlerror(lib, "", *ptr ? 0 : GetLastError()); } @@ -75,8 +76,9 @@ const char* uv_dlerror(const uv_lib_t* lib) { static void uv__format_fallback_error(uv_lib_t* lib, int errorno){ - DWORD_PTR args[1] = { (DWORD_PTR) errorno }; - LPSTR fallback_error = "error: %1!d!"; + static const CHAR fallback_error[] = "error: %1!d!"; + DWORD_PTR args[1]; + args[0] = (DWORD_PTR) errorno; FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY | @@ -107,7 +109,8 @@ static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno) { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPSTR) &lib->errmsg, 0, NULL); - if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { + if (!res && (GetLastError() == ERROR_MUI_FILE_NOT_FOUND || + GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND)) { res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, diff --git a/Utilities/cmlibuv/src/win/error.c b/Utilities/cmlibuv/src/win/error.c index 9b03bfe..24924ba 100644 --- a/Utilities/cmlibuv/src/win/error.c +++ b/Utilities/cmlibuv/src/win/error.c @@ -46,8 +46,8 @@ void uv_fatal_error(const int errorno, const char* syscall) { errmsg = "Unknown error"; } - /* FormatMessage messages include a newline character already, */ - /* so don't add another. */ + /* FormatMessage messages include a newline character already, so don't add + * another. */ if (syscall) { fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg); } else { diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c index 14c9af9..acf8e11 100644 --- a/Utilities/cmlibuv/src/win/fs-event.c +++ b/Utilities/cmlibuv/src/win/fs-event.c @@ -83,7 +83,7 @@ static void uv_relative_path(const WCHAR* filename, static int uv_split_path(const WCHAR* filename, WCHAR** dir, WCHAR** file) { size_t len, i; - + if (filename == NULL) { if (dir != NULL) *dir = NULL; @@ -215,11 +215,11 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv__free(long_path); long_path = NULL; } - } - if (long_path) { - uv__free(pathw); - pathw = long_path; + if (long_path) { + uv__free(pathw); + pathw = long_path; + } } dir_to_watch = pathw; @@ -230,8 +230,11 @@ int uv_fs_event_start(uv_fs_event_t* handle, */ /* Convert to short path. */ - short_path = short_path_buffer; - if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) { + if (GetShortPathNameW(pathw, + short_path_buffer, + ARRAY_SIZE(short_path_buffer))) { + short_path = short_path_buffer; + } else { short_path = NULL; } @@ -419,7 +422,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, * - We are not active, just ignore the callback */ if (!uv__is_active(handle)) { - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { uv_want_endgame(loop, (uv_handle_t*) handle); } return; @@ -543,7 +546,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, } offset = file_info->NextEntryOffset; - } while (offset && !(handle->flags & UV__HANDLE_CLOSING)); + } while (offset && !(handle->flags & UV_HANDLE_CLOSING)); } else { handle->cb(handle, NULL, UV_CHANGE, 0); } @@ -552,7 +555,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, handle->cb(handle, NULL, 0, uv_translate_sys_error(err)); } - if (!(handle->flags & UV__HANDLE_CLOSING)) { + if (!(handle->flags & UV_HANDLE_CLOSING)) { uv_fs_event_queue_readdirchanges(loop, handle); } else { uv_want_endgame(loop, (uv_handle_t*)handle); @@ -573,7 +576,7 @@ void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) { void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) { - if ((handle->flags & UV__HANDLE_CLOSING) && !handle->req_pending) { + if ((handle->flags & UV_HANDLE_CLOSING) && !handle->req_pending) { assert(!(handle->flags & UV_HANDLE_CLOSED)); if (handle->buffer) { diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c index 30b87ac..65d936b 100644 --- a/Utilities/cmlibuv/src/win/fs.c +++ b/Utilities/cmlibuv/src/win/fs.c @@ -55,7 +55,11 @@ do { \ if (cb != NULL) { \ uv__req_register(loop, req); \ - uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \ + uv__work_submit(loop, \ + &req->work_req, \ + UV__WORK_FAST_IO, \ + uv__fs_work, \ + uv__fs_done); \ return 0; \ } else { \ uv__fs_work(&req->work_req); \ @@ -92,14 +96,17 @@ return; \ } +#define MILLIONu (1000U * 1000U) +#define BILLIONu (1000U * 1000U * 1000U) + #define FILETIME_TO_UINT(filetime) \ - (*((uint64_t*) &(filetime)) - 116444736000000000ULL) + (*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu) #define FILETIME_TO_TIME_T(filetime) \ - (FILETIME_TO_UINT(filetime) / 10000000ULL) + (FILETIME_TO_UINT(filetime) / (10u * MILLIONu)) #define FILETIME_TO_TIME_NS(filetime, secs) \ - ((FILETIME_TO_UINT(filetime) - (secs * 10000000ULL)) * 100) + ((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U) #define FILETIME_TO_TIMESPEC(ts, filetime) \ do { \ @@ -109,8 +116,8 @@ #define TIME_T_TO_FILETIME(time, filetime_ptr) \ do { \ - uint64_t bigtime = ((uint64_t) ((time) * 10000000ULL)) + \ - 116444736000000000ULL; \ + uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) + \ + (uint64_t) 116444736 * BILLIONu; \ (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \ (filetime_ptr)->dwHighDateTime = bigtime >> 32; \ } while(0) @@ -326,12 +333,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR); - /* Real symlinks can contain pretty much everything, but the only thing */ - /* we really care about is undoing the implicit conversion to an NT */ - /* namespaced path that CreateSymbolicLink will perform on absolute */ - /* paths. If the path is win32-namespaced then the user must have */ - /* explicitly made it so, and we better just return the unmodified */ - /* reparse data. */ + /* Real symlinks can contain pretty much everything, but the only thing we + * really care about is undoing the implicit conversion to an NT namespaced + * path that CreateSymbolicLink will perform on absolute paths. If the path + * is win32-namespaced then the user must have explicitly made it so, and + * we better just return the unmodified reparse data. */ if (w_target_len >= 4 && w_target[0] == L'\\' && w_target[1] == L'?' && @@ -352,8 +358,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, (w_target[5] == L'N' || w_target[5] == L'n') && (w_target[6] == L'C' || w_target[6] == L'c') && w_target[7] == L'\\') { - /* \??\UNC\<server>\<share>\ - make sure the final path looks like */ - /* \\<server>\<share>\ */ + /* \??\UNC\<server>\<share>\ - make sure the final path looks like + * \\<server>\<share>\ */ w_target += 6; w_target[0] = L'\\'; w_target_len -= 6; @@ -368,11 +374,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR); - /* Only treat junctions that look like \??\<drive>:\ as symlink. */ - /* Junctions can also be used as mount points, like \??\Volume{<guid>}, */ - /* but that's confusing for programs since they wouldn't be able to */ - /* actually understand such a path when returned by uv_readlink(). */ - /* UNC paths are never valid for junctions so we don't care about them. */ + /* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions + * can also be used as mount points, like \??\Volume{<guid>}, but that's + * confusing for programs since they wouldn't be able to actually + * understand such a path when returned by uv_readlink(). UNC paths are + * never valid for junctions so we don't care about them. */ if (!(w_target_len >= 6 && w_target[0] == L'\\' && w_target[1] == L'?' && @@ -409,8 +415,8 @@ void fs__open(uv_fs_t* req) { int fd, current_umask; int flags = req->fs.info.file_flags; - /* Obtain the active umask. umask() never fails and returns the previous */ - /* umask. */ + /* Obtain the active umask. umask() never fails and returns the previous + * umask. */ current_umask = umask(0); umask(current_umask); @@ -502,6 +508,33 @@ void fs__open(uv_fs_t* req) { } if (flags & UV_FS_O_DIRECT) { + /* + * FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually exclusive. + * Windows returns 87, ERROR_INVALID_PARAMETER if these are combined. + * + * FILE_APPEND_DATA is included in FILE_GENERIC_WRITE: + * + * FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE | + * FILE_WRITE_DATA | + * FILE_WRITE_ATTRIBUTES | + * FILE_WRITE_EA | + * FILE_APPEND_DATA | + * SYNCHRONIZE + * + * Note: Appends are also permitted by FILE_WRITE_DATA. + * + * In order for direct writes and direct appends to succeed, we therefore + * exclude FILE_APPEND_DATA if FILE_WRITE_DATA is specified, and otherwise + * fail if the user's sole permission is a direct append, since this + * particular combination is invalid. + */ + if (access & FILE_APPEND_DATA) { + if (access & FILE_WRITE_DATA) { + access &= ~FILE_APPEND_DATA; + } else { + goto einval; + } + } attributes |= FILE_FLAG_NO_BUFFERING; } @@ -530,8 +563,8 @@ void fs__open(uv_fs_t* req) { DWORD error = GetLastError(); if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) && !(flags & UV_FS_O_EXCL)) { - /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was */ - /* specified, it means the path referred to a directory. */ + /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was + * specified, it means the path referred to a directory. */ SET_REQ_UV_ERROR(req, UV_EISDIR, error); } else { SET_REQ_WIN32_ERROR(req, GetLastError()); @@ -756,9 +789,9 @@ void fs__unlink(uv_fs_t* req) { } if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - /* Do not allow deletion of directories, unless it is a symlink. When */ - /* the path refers to a non-symlink directory, report EPERM as mandated */ - /* by POSIX.1. */ + /* Do not allow deletion of directories, unless it is a symlink. When the + * path refers to a non-symlink directory, report EPERM as mandated by + * POSIX.1. */ /* Check if it is a reparse point. If it's not, it's a normal directory. */ if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { @@ -767,8 +800,8 @@ void fs__unlink(uv_fs_t* req) { return; } - /* Read the reparse point and check if it is a valid symlink. */ - /* If not, don't unlink. */ + /* Read the reparse point and check if it is a valid symlink. If not, don't + * unlink. */ if (fs__readlink_handle(handle, NULL, NULL) < 0) { DWORD error = GetLastError(); if (error == ERROR_SYMLINK_NOT_SUPPORTED) @@ -783,9 +816,8 @@ void fs__unlink(uv_fs_t* req) { /* Remove read-only attribute */ FILE_BASIC_INFORMATION basic = { 0 }; - basic.FileAttributes = info.dwFileAttributes - & ~(FILE_ATTRIBUTE_READONLY) - | FILE_ATTRIBUTE_ARCHIVE; + basic.FileAttributes = (info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY) | + FILE_ATTRIBUTE_ARCHIVE; status = pNtSetInformationFile(handle, &iosb, @@ -1196,7 +1228,7 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf, /* st_blocks contains the on-disk allocation size in 512-byte units. */ statbuf->st_blocks = - file_info.StandardInformation.AllocationSize.QuadPart >> 9ULL; + (uint64_t) file_info.StandardInformation.AllocationSize.QuadPart >> 9; statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks; @@ -1490,6 +1522,7 @@ static void fs__chmod(uv_fs_t* req) { static void fs__fchmod(uv_fs_t* req) { int fd = req->file.fd; + int clear_archive_flag; HANDLE handle; NTSTATUS nt_status; IO_STATUS_BLOCK io_status; @@ -1497,7 +1530,11 @@ static void fs__fchmod(uv_fs_t* req) { VERIFY_FD(fd, req); - handle = uv__get_osfhandle(fd); + handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0); + if (handle == INVALID_HANDLE_VALUE) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } nt_status = pNtQueryInformationFile(handle, &io_status, @@ -1507,7 +1544,27 @@ static void fs__fchmod(uv_fs_t* req) { if (!NT_SUCCESS(nt_status)) { SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); - return; + goto fchmod_cleanup; + } + + /* Test if the Archive attribute is cleared */ + if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) { + /* Set Archive flag, otherwise setting or clearing the read-only + flag will not work */ + file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE; + nt_status = pNtSetInformationFile(handle, + &io_status, + &file_info, + sizeof file_info, + FileBasicInformation); + if (!NT_SUCCESS(nt_status)) { + SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); + goto fchmod_cleanup; + } + /* Remeber to clear the flag later on */ + clear_archive_flag = 1; + } else { + clear_archive_flag = 0; } if (req->fs.info.mode & _S_IWRITE) { @@ -1524,10 +1581,28 @@ static void fs__fchmod(uv_fs_t* req) { if (!NT_SUCCESS(nt_status)) { SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); - return; + goto fchmod_cleanup; + } + + if (clear_archive_flag) { + file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE; + if (file_info.FileAttributes == 0) { + file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL; + } + nt_status = pNtSetInformationFile(handle, + &io_status, + &file_info, + sizeof file_info, + FileBasicInformation); + if (!NT_SUCCESS(nt_status)) { + SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); + goto fchmod_cleanup; + } } SET_REQ_SUCCESS(req); +fchmod_cleanup: + CloseHandle(handle); } @@ -1787,17 +1862,13 @@ static void fs__symlink(uv_fs_t* req) { fs__create_junction(req, pathw, new_pathw); return; } - if (!pCreateSymbolicLinkW) { - SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); - return; - } if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR) flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag; else flags = uv__file_symlink_usermode_flag; - if (pCreateSymbolicLinkW(new_pathw, pathw, flags)) { + if (CreateSymbolicLinkW(new_pathw, pathw, flags)) { SET_REQ_RESULT(req, 0); return; } @@ -1848,13 +1919,13 @@ static void fs__readlink(uv_fs_t* req) { } -static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { +static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { int r; DWORD w_realpath_len; WCHAR* w_realpath_ptr = NULL; WCHAR* w_realpath_buf; - w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS); + w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS); if (w_realpath_len == 0) { return -1; } @@ -1866,10 +1937,8 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { } w_realpath_ptr = w_realpath_buf; - if (pGetFinalPathNameByHandleW(handle, - w_realpath_ptr, - w_realpath_len, - VOLUME_NAME_DOS) == 0) { + if (GetFinalPathNameByHandleW( + handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) { uv__free(w_realpath_buf); SetLastError(ERROR_INVALID_HANDLE); return -1; @@ -1901,11 +1970,6 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { static void fs__realpath(uv_fs_t* req) { HANDLE handle; - if (!pGetFinalPathNameByHandleW) { - SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); - return; - } - handle = CreateFileW(req->file.pathw, 0, 0, @@ -1940,6 +2004,10 @@ static void fs__fchown(uv_fs_t* req) { } +static void fs__lchown(uv_fs_t* req) { + req->result = 0; +} + static void uv__fs_work(struct uv__work* w) { uv_fs_t* req; @@ -1977,6 +2045,7 @@ static void uv__fs_work(struct uv__work* w) { XX(REALPATH, realpath) XX(CHOWN, chown) XX(FCHOWN, fchown); + XX(LCHOWN, lchown); default: assert(!"bad uv_fs_type"); } @@ -2262,6 +2331,19 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid, } +int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, + uv_gid_t gid, uv_fs_cb cb) { + int err; + + INIT(UV_FS_LCHOWN); + err = fs__capture_path(req, path, NULL, cb != NULL); + if (err) { + return uv_translate_sys_error(err); + } + POST; +} + + int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c index 5adc766..dfab860 100644 --- a/Utilities/cmlibuv/src/win/getaddrinfo.c +++ b/Utilities/cmlibuv/src/win/getaddrinfo.c @@ -24,6 +24,7 @@ #include "uv.h" #include "internal.h" #include "req-inl.h" +#include "idna.h" /* EAI_* constants. */ #include <winsock2.h> @@ -71,8 +72,8 @@ int uv__getaddrinfo_translate_error(int sys_err) { #endif -/* adjust size value to be multiple of 4. Use to keep pointer aligned */ -/* Do we need different versions of this for different architectures? */ +/* Adjust size value to be multiple of 4. Use to keep pointer aligned. + * Do we need different versions of this for different architectures? */ #define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2) #ifndef NDIS_IF_MAX_STRING_SIZE @@ -124,8 +125,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) { } if (req->retcode == 0) { - /* convert addrinfoW to addrinfo */ - /* first calculate required length */ + /* Convert addrinfoW to addrinfo. First calculate required length. */ addrinfow_ptr = req->addrinfow; while (addrinfow_ptr != NULL) { addrinfo_len += addrinfo_struct_len + @@ -260,11 +260,13 @@ int uv_getaddrinfo(uv_loop_t* loop, const char* node, const char* service, const struct addrinfo* hints) { + char hostname_ascii[256]; int nodesize = 0; int servicesize = 0; int hintssize = 0; char* alloc_ptr = NULL; int err; + long rc; if (req == NULL || (node == NULL && service == NULL)) { return UV_EINVAL; @@ -278,12 +280,19 @@ int uv_getaddrinfo(uv_loop_t* loop, /* calculate required memory size for all input values */ if (node != NULL) { - nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, node, -1, NULL, 0) * - sizeof(WCHAR)); + rc = uv__idna_toascii(node, + node + strlen(node), + hostname_ascii, + hostname_ascii + sizeof(hostname_ascii)); + if (rc < 0) + return rc; + nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii, + -1, NULL, 0) * sizeof(WCHAR)); if (nodesize == 0) { err = GetLastError(); goto error; } + node = hostname_ascii; } if (service != NULL) { @@ -313,8 +322,8 @@ int uv_getaddrinfo(uv_loop_t* loop, /* save alloc_ptr now so we can free if error */ req->alloc = (void*)alloc_ptr; - /* convert node string to UTF16 into allocated memory and save pointer in */ - /* the request. */ + /* Convert node string to UTF16 into allocated memory and save pointer in the + * request. */ if (node != NULL) { req->node = (WCHAR*)alloc_ptr; if (MultiByteToWideChar(CP_UTF8, @@ -331,8 +340,8 @@ int uv_getaddrinfo(uv_loop_t* loop, req->node = NULL; } - /* convert service string to UTF16 into allocated memory and save pointer */ - /* in the req. */ + /* Convert service string to UTF16 into allocated memory and save pointer in + * the req. */ if (service != NULL) { req->service = (WCHAR*)alloc_ptr; if (MultiByteToWideChar(CP_UTF8, @@ -369,6 +378,7 @@ int uv_getaddrinfo(uv_loop_t* loop, if (getaddrinfo_cb) { uv__work_submit(loop, &req->work_req, + UV__WORK_SLOW_IO, uv__getaddrinfo_work, uv__getaddrinfo_done); return 0; @@ -392,21 +402,15 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) { DWORD bufsize; int r; - uv__once_init(); - if (buffer == NULL || size == NULL || *size == 0) return UV_EINVAL; - if (pConvertInterfaceIndexToLuid == NULL) - return UV_ENOSYS; - r = pConvertInterfaceIndexToLuid(ifindex, &luid); + r = ConvertInterfaceIndexToLuid(ifindex, &luid); if (r != 0) return uv_translate_sys_error(r); - if (pConvertInterfaceLuidToNameW == NULL) - return UV_ENOSYS; - r = pConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname)); + r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname)); if (r != 0) return uv_translate_sys_error(r); diff --git a/Utilities/cmlibuv/src/win/getnameinfo.c b/Utilities/cmlibuv/src/win/getnameinfo.c index 9f10cd2..b377338 100644 --- a/Utilities/cmlibuv/src/win/getnameinfo.c +++ b/Utilities/cmlibuv/src/win/getnameinfo.c @@ -42,7 +42,7 @@ static void uv__getnameinfo_work(struct uv__work* w) { uv_getnameinfo_t* req; WCHAR host[NI_MAXHOST]; WCHAR service[NI_MAXSERV]; - int ret = 0; + int ret; req = container_of(w, uv_getnameinfo_t, work_req); if (GetNameInfoW((struct sockaddr*)&req->storage, @@ -53,27 +53,34 @@ static void uv__getnameinfo_work(struct uv__work* w) { ARRAY_SIZE(service), req->flags)) { ret = WSAGetLastError(); + req->retcode = uv__getaddrinfo_translate_error(ret); + return; + } + + ret = WideCharToMultiByte(CP_UTF8, + 0, + host, + -1, + req->host, + sizeof(req->host), + NULL, + NULL); + if (ret == 0) { + req->retcode = uv_translate_sys_error(GetLastError()); + return; + } + + ret = WideCharToMultiByte(CP_UTF8, + 0, + service, + -1, + req->service, + sizeof(req->service), + NULL, + NULL); + if (ret == 0) { + req->retcode = uv_translate_sys_error(GetLastError()); } - req->retcode = uv__getaddrinfo_translate_error(ret); - - /* convert results to UTF-8 */ - WideCharToMultiByte(CP_UTF8, - 0, - host, - -1, - req->host, - sizeof(req->host), - NULL, - NULL); - - WideCharToMultiByte(CP_UTF8, - 0, - service, - -1, - req->service, - sizeof(req->service), - NULL, - NULL); } @@ -138,6 +145,7 @@ int uv_getnameinfo(uv_loop_t* loop, if (getnameinfo_cb) { uv__work_submit(loop, &req->work_req, + UV__WORK_SLOW_IO, uv__getnameinfo_work, uv__getnameinfo_done); return 0; diff --git a/Utilities/cmlibuv/src/win/handle-inl.h b/Utilities/cmlibuv/src/win/handle-inl.h index 8d0334c..82c657d 100644 --- a/Utilities/cmlibuv/src/win/handle-inl.h +++ b/Utilities/cmlibuv/src/win/handle-inl.h @@ -32,7 +32,7 @@ #define DECREASE_ACTIVE_COUNT(loop, handle) \ do { \ if (--(handle)->activecnt == 0 && \ - !((handle)->flags & UV__HANDLE_CLOSING)) { \ + !((handle)->flags & UV_HANDLE_CLOSING)) { \ uv__handle_stop((handle)); \ } \ assert((handle)->activecnt >= 0); \ @@ -53,7 +53,7 @@ assert(handle->reqs_pending > 0); \ handle->reqs_pending--; \ \ - if (handle->flags & UV__HANDLE_CLOSING && \ + if (handle->flags & UV_HANDLE_CLOSING && \ handle->reqs_pending == 0) { \ uv_want_endgame(loop, (uv_handle_t*)handle); \ } \ @@ -62,14 +62,14 @@ #define uv__handle_closing(handle) \ do { \ - assert(!((handle)->flags & UV__HANDLE_CLOSING)); \ + assert(!((handle)->flags & UV_HANDLE_CLOSING)); \ \ - if (!(((handle)->flags & UV__HANDLE_ACTIVE) && \ - ((handle)->flags & UV__HANDLE_REF))) \ + if (!(((handle)->flags & UV_HANDLE_ACTIVE) && \ + ((handle)->flags & UV_HANDLE_REF))) \ uv__active_handle_add((uv_handle_t*) (handle)); \ \ - (handle)->flags |= UV__HANDLE_CLOSING; \ - (handle)->flags &= ~UV__HANDLE_ACTIVE; \ + (handle)->flags |= UV_HANDLE_CLOSING; \ + (handle)->flags &= ~UV_HANDLE_ACTIVE; \ } while (0) @@ -126,7 +126,8 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) { break; case UV_TIMER: - uv_timer_endgame(loop, (uv_timer_t*) handle); + uv__timer_close((uv_timer_t*) handle); + uv__handle_close(handle); break; case UV_PREPARE: @@ -164,10 +165,10 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) { INLINE static HANDLE uv__get_osfhandle(int fd) { - /* _get_osfhandle() raises an assert in debug builds if the FD is invalid. */ - /* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE */ - /* for invalid FDs in release builds (or if you let the assert continue). */ - /* So this wrapper function disables asserts when calling _get_osfhandle. */ + /* _get_osfhandle() raises an assert in debug builds if the FD is invalid. + * But it also correctly checks the FD and returns INVALID_HANDLE_VALUE for + * invalid FDs in release builds (or if you let the assert continue). So this + * wrapper function disables asserts when calling _get_osfhandle. */ HANDLE handle; UV_BEGIN_DISABLE_CRT_ASSERT(); diff --git a/Utilities/cmlibuv/src/win/handle.c b/Utilities/cmlibuv/src/win/handle.c index 3915070..9d76c3f 100644 --- a/Utilities/cmlibuv/src/win/handle.c +++ b/Utilities/cmlibuv/src/win/handle.c @@ -59,15 +59,15 @@ uv_handle_type uv_guess_handle(uv_file file) { int uv_is_active(const uv_handle_t* handle) { - return (handle->flags & UV__HANDLE_ACTIVE) && - !(handle->flags & UV__HANDLE_CLOSING); + return (handle->flags & UV_HANDLE_ACTIVE) && + !(handle->flags & UV_HANDLE_CLOSING); } void uv_close(uv_handle_t* handle, uv_close_cb cb) { uv_loop_t* loop = handle->loop; - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { assert(0); return; } @@ -150,10 +150,14 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) { int uv_is_closing(const uv_handle_t* handle) { - return !!(handle->flags & (UV__HANDLE_CLOSING | UV_HANDLE_CLOSED)); + return !!(handle->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED)); } uv_os_fd_t uv_get_osfhandle(int fd) { return uv__get_osfhandle(fd); } + +int uv_open_osfhandle(uv_os_fd_t os_fd) { + return _open_osfhandle((intptr_t) os_fd, 0); +} diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h index 849bc82..206ab5f 100644 --- a/Utilities/cmlibuv/src/win/internal.h +++ b/Utilities/cmlibuv/src/win/internal.h @@ -29,7 +29,7 @@ #include "uv.h" #include "../uv-common.h" -#include "tree.h" +#include "uv/tree.h" #include "winapi.h" #include "winsock.h" @@ -62,77 +62,19 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled; #endif /* - * Handles - * (also see handle-inl.h) - */ - -/* Used by all handles. */ -#define UV_HANDLE_CLOSED 0x00000002 -#define UV_HANDLE_ENDGAME_QUEUED 0x00000008 - -/* uv-common.h: #define UV__HANDLE_CLOSING 0x00000001 */ -/* uv-common.h: #define UV__HANDLE_ACTIVE 0x00000040 */ -/* uv-common.h: #define UV__HANDLE_REF 0x00000020 */ -/* uv-common.h: #define UV_HANDLE_INTERNAL 0x00000080 */ - -/* Used by streams and UDP handles. */ -#define UV_HANDLE_READING 0x00000100 -#define UV_HANDLE_BOUND 0x00000200 -#define UV_HANDLE_LISTENING 0x00000800 -#define UV_HANDLE_CONNECTION 0x00001000 -#define UV_HANDLE_READABLE 0x00008000 -#define UV_HANDLE_WRITABLE 0x00010000 -#define UV_HANDLE_READ_PENDING 0x00020000 -#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00040000 -#define UV_HANDLE_ZERO_READ 0x00080000 -#define UV_HANDLE_EMULATE_IOCP 0x00100000 -#define UV_HANDLE_BLOCKING_WRITES 0x00200000 -#define UV_HANDLE_CANCELLATION_PENDING 0x00400000 - -/* Used by uv_tcp_t and uv_udp_t handles */ -#define UV_HANDLE_IPV6 0x01000000 - -/* Only used by uv_tcp_t handles. */ -#define UV_HANDLE_TCP_NODELAY 0x02000000 -#define UV_HANDLE_TCP_KEEPALIVE 0x04000000 -#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000 -#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000 -#define UV_HANDLE_TCP_SOCKET_CLOSED 0x20000000 -#define UV_HANDLE_SHARED_TCP_SOCKET 0x40000000 - -/* Only used by uv_pipe_t handles. */ -#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000 -#define UV_HANDLE_PIPESERVER 0x02000000 -#define UV_HANDLE_PIPE_READ_CANCELABLE 0x04000000 - -/* Only used by uv_tty_t handles. */ -#define UV_HANDLE_TTY_READABLE 0x01000000 -#define UV_HANDLE_TTY_RAW 0x02000000 -#define UV_HANDLE_TTY_SAVED_POSITION 0x04000000 -#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x08000000 - -/* Only used by uv_poll_t handles. */ -#define UV_HANDLE_POLL_SLOW 0x02000000 - - -/* - * Requests: see req-inl.h - */ - - -/* - * Streams: see stream-inl.h - */ - - -/* * TCP */ +typedef enum { + UV__IPC_SOCKET_XFER_NONE = 0, + UV__IPC_SOCKET_XFER_TCP_CONNECTION, + UV__IPC_SOCKET_XFER_TCP_SERVER +} uv__ipc_socket_xfer_type_t; + typedef struct { WSAPROTOCOL_INFOW socket_info; - int delayed_error; -} uv__ipc_socket_info_ex; + uint32_t delayed_error; +} uv__ipc_socket_xfer_info_t; int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb); int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client); @@ -154,11 +96,13 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp); void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle); -int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, - int tcp_connection); - -int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, - LPWSAPROTOCOL_INFOW protocol_info); +int uv__tcp_xfer_export(uv_tcp_t* handle, + int pid, + uv__ipc_socket_xfer_type_t* xfer_type, + uv__ipc_socket_xfer_info_t* xfer_info); +int uv__tcp_xfer_import(uv_tcp_t* tcp, + uv__ipc_socket_xfer_type_t xfer_type, + uv__ipc_socket_xfer_info_t* xfer_info); /* @@ -182,14 +126,14 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client); int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb); -int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); -int uv_pipe_write2(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle, - uv_write_cb cb); -void uv__pipe_pause_read(uv_pipe_t* handle); -void uv__pipe_unpause_read(uv_pipe_t* handle); -void uv__pipe_stop_read(uv_pipe_t* handle); +void uv__pipe_read_stop(uv_pipe_t* handle); +int uv__pipe_write(uv_loop_t* loop, + uv_write_t* req, + uv_pipe_t* handle, + const uv_buf_t bufs[], + size_t nbufs, + uv_stream_t* send_handle, + uv_write_cb cb); void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, uv_req_t* req); @@ -252,15 +196,6 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle); /* - * Timers - */ -void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle); - -DWORD uv__next_timeout(const uv_loop_t* loop); -void uv_process_timers(uv_loop_t* loop); - - -/* * Loop watchers */ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle); @@ -336,7 +271,6 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle); void uv__util_init(void); uint64_t uv__hrtime(double scale); -int uv_current_pid(void); __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall); int uv__getpwuid_r(uv_passwd_t* pwd); int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8); diff --git a/Utilities/cmlibuv/src/win/loop-watcher.c b/Utilities/cmlibuv/src/win/loop-watcher.c index 20e4509..ad7fbea 100644 --- a/Utilities/cmlibuv/src/win/loop-watcher.c +++ b/Utilities/cmlibuv/src/win/loop-watcher.c @@ -27,7 +27,7 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->flags |= UV_HANDLE_CLOSED; uv__handle_close(handle); diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c index 83ee4f9..277f649 100644 --- a/Utilities/cmlibuv/src/win/pipe.c +++ b/Utilities/cmlibuv/src/win/pipe.c @@ -21,39 +21,28 @@ #include <assert.h> #include <io.h> -#include <string.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> -#include "uv.h" -#include "internal.h" #include "handle-inl.h" -#include "stream-inl.h" +#include "internal.h" #include "req-inl.h" +#include "stream-inl.h" +#include "uv-common.h" +#include "uv.h" #include <aclapi.h> #include <accctrl.h> -typedef struct uv__ipc_queue_item_s uv__ipc_queue_item_t; - -struct uv__ipc_queue_item_s { - /* - * NOTE: It is important for socket_info_ex to be the first field, - * because we will we assigning it to the pending_ipc_info.socket_info - */ - uv__ipc_socket_info_ex socket_info_ex; - QUEUE member; - int tcp_connection; -}; - /* A zero-size buffer for use by uv_pipe_read */ static char uv_zero_[] = ""; /* Null uv_buf_t */ static const uv_buf_t uv_null_buf_ = { 0, NULL }; -/* The timeout that the pipe will wait for the remote end to write data */ -/* when the local ends wants to shut it down. */ +/* The timeout that the pipe will wait for the remote end to write data when + * the local ends wants to shut it down. */ static const int64_t eof_timeout = 50; /* ms */ static const int default_pending_pipe_instances = 4; @@ -62,22 +51,44 @@ static const int default_pending_pipe_instances = 4; static char pipe_prefix[] = "\\\\?\\pipe"; static const int pipe_prefix_len = sizeof(pipe_prefix) - 1; -/* IPC protocol flags. */ -#define UV_IPC_RAW_DATA 0x0001 -#define UV_IPC_TCP_SERVER 0x0002 -#define UV_IPC_TCP_CONNECTION 0x0004 +/* IPC incoming xfer queue item. */ +typedef struct { + uv__ipc_socket_xfer_type_t xfer_type; + uv__ipc_socket_xfer_info_t xfer_info; + QUEUE member; +} uv__ipc_xfer_queue_item_t; + +/* IPC frame header flags. */ +/* clang-format off */ +enum { + UV__IPC_FRAME_HAS_DATA = 0x01, + UV__IPC_FRAME_HAS_SOCKET_XFER = 0x02, + UV__IPC_FRAME_XFER_IS_TCP_CONNECTION = 0x04, + /* These are combinations of the flags above. */ + UV__IPC_FRAME_XFER_FLAGS = 0x06, + UV__IPC_FRAME_VALID_FLAGS = 0x07 +}; +/* clang-format on */ /* IPC frame header. */ typedef struct { - int flags; - uint64_t raw_data_length; -} uv_ipc_frame_header_t; - -/* IPC frame, which contains an imported TCP socket stream. */ + uint32_t flags; + uint32_t reserved1; /* Ignored. */ + uint32_t data_length; /* Must be zero if there is no data. */ + uint32_t reserved2; /* Must be zero. */ +} uv__ipc_frame_header_t; + +/* To implement the IPC protocol correctly, these structures must have exactly + * the right size. */ +STATIC_ASSERT(sizeof(uv__ipc_frame_header_t) == 16); +STATIC_ASSERT(sizeof(uv__ipc_socket_xfer_info_t) == 632); + +/* Coalesced write request. */ typedef struct { - uv_ipc_frame_header_t header; - uv__ipc_socket_info_ex socket_info_ex; -} uv_ipc_frame_uv_stream; + uv_write_t req; /* Internal heap-allocated write request. */ + uv_write_t* user_req; /* Pointer to user-specified uv_write_t. */ +} uv__coalesced_write_t; + static void eof_timer_init(uv_pipe_t* pipe); static void eof_timer_start(uv_pipe_t* pipe); @@ -98,15 +109,12 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { handle->reqs_pending = 0; handle->handle = INVALID_HANDLE_VALUE; handle->name = NULL; - handle->pipe.conn.ipc_pid = 0; - handle->pipe.conn.remaining_ipc_rawdata_bytes = 0; - QUEUE_INIT(&handle->pipe.conn.pending_ipc_info.queue); - handle->pipe.conn.pending_ipc_info.queue_len = 0; + handle->pipe.conn.ipc_remote_pid = 0; + handle->pipe.conn.ipc_data_frame.payload_remaining = 0; + QUEUE_INIT(&handle->pipe.conn.ipc_xfer_queue); + handle->pipe.conn.ipc_xfer_queue_length = 0; handle->ipc = ipc; handle->pipe.conn.non_overlapped_writes_tail = NULL; - handle->pipe.conn.readfile_thread = NULL; - - UV_REQ_INIT(&handle->pipe.conn.ipc_header_write_req, UV_UNKNOWN_REQ); return 0; } @@ -117,10 +125,9 @@ static void uv_pipe_connection_init(uv_pipe_t* handle) { handle->read_req.data = handle; handle->pipe.conn.eof_timer = NULL; assert(!(handle->flags & UV_HANDLE_PIPESERVER)); - if (pCancelSynchronousIo && - handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - uv_mutex_init(&handle->pipe.conn.readfile_mutex); - handle->flags |= UV_HANDLE_PIPE_READ_CANCELABLE; + if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { + handle->pipe.conn.readfile_thread_handle = NULL; + InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock); } } @@ -347,12 +354,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_PIPE_LOCAL_INFORMATION pipe_info; - uv__ipc_queue_item_t* item; - - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - handle->flags &= ~UV_HANDLE_PIPE_READ_CANCELABLE; - uv_mutex_destroy(&handle->pipe.conn.readfile_mutex); - } + uv__ipc_xfer_queue_item_t* xfer_queue_item; if ((handle->flags & UV_HANDLE_CONNECTION) && handle->stream.conn.shutdown_req != NULL && @@ -362,7 +364,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { /* Clear the shutdown_req field so we don't go here again. */ handle->stream.conn.shutdown_req = NULL; - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { UNREGISTER_HANDLE_REQ(loop, handle, req); /* Already closing. Cancel the shutdown. */ @@ -423,33 +425,33 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { } } - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); if (handle->flags & UV_HANDLE_CONNECTION) { /* Free pending sockets */ - while (!QUEUE_EMPTY(&handle->pipe.conn.pending_ipc_info.queue)) { + while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) { QUEUE* q; SOCKET socket; - q = QUEUE_HEAD(&handle->pipe.conn.pending_ipc_info.queue); + q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue); QUEUE_REMOVE(q); - item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); + xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member); /* Materialize socket and close it */ socket = WSASocketW(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, - &item->socket_info_ex.socket_info, + &xfer_queue_item->xfer_info.socket_info, 0, WSA_FLAG_OVERLAPPED); - uv__free(item); + uv__free(xfer_queue_item); if (socket != INVALID_SOCKET) closesocket(socket); } - handle->pipe.conn.pending_ipc_info.queue_len = 0; + handle->pipe.conn.ipc_xfer_queue_length = 0; if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { @@ -461,6 +463,9 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { handle->read_req.event_handle = NULL; } } + + if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) + DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock); } if (handle->flags & UV_HANDLE_PIPESERVER) { @@ -595,8 +600,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { loop = handle->loop; assert(loop); - /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. */ - /* We wait for the pipe to become available with WaitNamedPipe. */ + /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait + * for the pipe to become available with WaitNamedPipe. */ while (WaitNamedPipeW(handle->name, 30000)) { /* The pipe is now available, try to connect. */ pipeHandle = open_named_pipe(handle->name, &duplex_flags); @@ -706,55 +711,68 @@ error: } -void uv__pipe_pause_read(uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - /* Pause the ReadFile task briefly, to work - around the Windows kernel bug that causes - any access to a NamedPipe to deadlock if - any process has called ReadFile */ - HANDLE h; - uv_mutex_lock(&handle->pipe.conn.readfile_mutex); - h = handle->pipe.conn.readfile_thread; - while (h) { - /* spinlock: we expect this to finish quickly, - or we are probably about to deadlock anyways - (in the kernel), so it doesn't matter */ - pCancelSynchronousIo(h); - SwitchToThread(); /* yield thread control briefly */ - h = handle->pipe.conn.readfile_thread; - } - } -} +void uv__pipe_interrupt_read(uv_pipe_t* handle) { + BOOL r; + + if (!(handle->flags & UV_HANDLE_READ_PENDING)) + return; /* No pending reads. */ + if (handle->flags & UV_HANDLE_CANCELLATION_PENDING) + return; /* Already cancelled. */ + if (handle->handle == INVALID_HANDLE_VALUE) + return; /* Pipe handle closed. */ + if (!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)) { + /* Cancel asynchronous read. */ + r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped); + assert(r || GetLastError() == ERROR_NOT_FOUND); -void uv__pipe_unpause_read(uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - uv_mutex_unlock(&handle->pipe.conn.readfile_mutex); + } else { + /* Cancel synchronous read (which is happening in the thread pool). */ + HANDLE thread; + volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle; + + EnterCriticalSection(&handle->pipe.conn.readfile_thread_lock); + + thread = *thread_ptr; + if (thread == NULL) { + /* The thread pool thread has not yet reached the point of blocking, we + * can pre-empt it by setting thread_handle to INVALID_HANDLE_VALUE. */ + *thread_ptr = INVALID_HANDLE_VALUE; + + } else { + /* Spin until the thread has acknowledged (by setting the thread to + * INVALID_HANDLE_VALUE) that it is past the point of blocking. */ + while (thread != INVALID_HANDLE_VALUE) { + r = CancelSynchronousIo(thread); + assert(r || GetLastError() == ERROR_NOT_FOUND); + SwitchToThread(); /* Yield thread. */ + thread = *thread_ptr; + } + } + + LeaveCriticalSection(&handle->pipe.conn.readfile_thread_lock); } + + /* Set flag to indicate that read has been cancelled. */ + handle->flags |= UV_HANDLE_CANCELLATION_PENDING; } -void uv__pipe_stop_read(uv_pipe_t* handle) { - if (pCancelIoEx && - !(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) && - !(handle->flags & UV_HANDLE_EMULATE_IOCP) && - handle->flags & UV_HANDLE_READING && - handle->read_req.type == UV_READ) { - pCancelIoEx(handle->handle, &handle->read_req.u.io.overlapped); - } +void uv__pipe_read_stop(uv_pipe_t* handle) { handle->flags &= ~UV_HANDLE_READING; - uv__pipe_pause_read((uv_pipe_t*)handle); - uv__pipe_unpause_read((uv_pipe_t*)handle); + DECREASE_ACTIVE_COUNT(handle->loop, handle); + + uv__pipe_interrupt_read(handle); } -/* Cleans up uv_pipe_t (server or connection) and all resources associated */ -/* with it. */ +/* Cleans up uv_pipe_t (server or connection) and all resources associated with + * it. */ void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) { int i; HANDLE pipeHandle; - uv__pipe_stop_read(handle); + uv__pipe_interrupt_read(handle); if (handle->name) { uv__free(handle->name); @@ -864,23 +882,22 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { uv_pipe_t* pipe_client; uv_pipe_accept_t* req; QUEUE* q; - uv__ipc_queue_item_t* item; + uv__ipc_xfer_queue_item_t* item; int err; if (server->ipc) { - if (QUEUE_EMPTY(&server->pipe.conn.pending_ipc_info.queue)) { + if (QUEUE_EMPTY(&server->pipe.conn.ipc_xfer_queue)) { /* No valid pending sockets. */ return WSAEWOULDBLOCK; } - q = QUEUE_HEAD(&server->pipe.conn.pending_ipc_info.queue); + q = QUEUE_HEAD(&server->pipe.conn.ipc_xfer_queue); QUEUE_REMOVE(q); - server->pipe.conn.pending_ipc_info.queue_len--; - item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); + server->pipe.conn.ipc_xfer_queue_length--; + item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member); - err = uv_tcp_import((uv_tcp_t*)client, - &item->socket_info_ex, - item->tcp_connection); + err = uv__tcp_xfer_import( + (uv_tcp_t*) client, item->xfer_type, &item->xfer_info); if (err != 0) return err; @@ -889,8 +906,8 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { } else { pipe_client = (uv_pipe_t*)client; - /* Find a connection instance that has been connected, but not yet */ - /* accepted. */ + /* Find a connection instance that has been connected, but not yet + * accepted. */ req = server->pipe.serv.pending_accepts; if (!req) { @@ -908,7 +925,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { req->next_pending = NULL; req->pipeHandle = INVALID_HANDLE_VALUE; - if (!(server->flags & UV__HANDLE_CLOSING)) { + if (!(server->flags & UV_HANDLE_CLOSING)) { uv_pipe_queue_accept(loop, server, req, FALSE); } } @@ -953,74 +970,75 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { } -static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) { - int result; - DWORD bytes; - uv_read_t* req = (uv_read_t*) parameter; +static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* arg) { + uv_read_t* req = (uv_read_t*) arg; uv_pipe_t* handle = (uv_pipe_t*) req->data; uv_loop_t* loop = handle->loop; - HANDLE hThread = NULL; + volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle; + CRITICAL_SECTION* lock = &handle->pipe.conn.readfile_thread_lock; + HANDLE thread; + DWORD bytes; DWORD err; - uv_mutex_t *m = &handle->pipe.conn.readfile_mutex; - assert(req != NULL); assert(req->type == UV_READ); assert(handle->type == UV_NAMED_PIPE); - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - uv_mutex_lock(m); /* mutex controls *setting* of readfile_thread */ - if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &hThread, - 0, FALSE, DUPLICATE_SAME_ACCESS)) { - handle->pipe.conn.readfile_thread = hThread; - } else { - hThread = NULL; - } - uv_mutex_unlock(m); + err = 0; + + /* Create a handle to the current thread. */ + if (!DuplicateHandle(GetCurrentProcess(), + GetCurrentThread(), + GetCurrentProcess(), + &thread, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + err = GetLastError(); + goto out1; } -restart_readfile: - if (handle->flags & UV_HANDLE_READING) { - result = ReadFile(handle->handle, - &uv_zero_, - 0, - &bytes, - NULL); - if (!result) { - err = GetLastError(); - if (err == ERROR_OPERATION_ABORTED && - handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - if (handle->flags & UV_HANDLE_READING) { - /* just a brief break to do something else */ - handle->pipe.conn.readfile_thread = NULL; - /* resume after it is finished */ - uv_mutex_lock(m); - handle->pipe.conn.readfile_thread = hThread; - uv_mutex_unlock(m); - goto restart_readfile; - } else { - result = 1; /* successfully stopped reading */ - } - } - } + + /* The lock needs to be held when thread handle is modified. */ + EnterCriticalSection(lock); + if (*thread_ptr == INVALID_HANDLE_VALUE) { + /* uv__pipe_interrupt_read() cancelled reading before we got here. */ + err = ERROR_OPERATION_ABORTED; } else { - result = 1; /* successfully aborted read before it even started */ - } - if (hThread) { - assert(hThread == handle->pipe.conn.readfile_thread); - /* mutex does not control clearing readfile_thread */ - handle->pipe.conn.readfile_thread = NULL; - uv_mutex_lock(m); - /* only when we hold the mutex lock is it safe to - open or close the handle */ - CloseHandle(hThread); - uv_mutex_unlock(m); + /* Let main thread know which worker thread is doing the blocking read. */ + assert(*thread_ptr == NULL); + *thread_ptr = thread; } + LeaveCriticalSection(lock); - if (!result) { - SET_REQ_ERROR(req, err); - } + if (err) + goto out2; + + /* Block the thread until data is available on the pipe, or the read is + * cancelled. */ + if (!ReadFile(handle->handle, &uv_zero_, 0, &bytes, NULL)) + err = GetLastError(); + + /* Let the main thread know the worker is past the point of blocking. */ + assert(thread == *thread_ptr); + *thread_ptr = INVALID_HANDLE_VALUE; + + /* Briefly acquire the mutex. Since the main thread holds the lock while it + * is spinning trying to cancel this thread's I/O, we will block here until + * it stops doing that. */ + EnterCriticalSection(lock); + LeaveCriticalSection(lock); +out2: + /* Close the handle to the current thread. */ + CloseHandle(thread); + +out1: + /* Set request status and post a completion record to the IOCP. */ + if (err) + SET_REQ_ERROR(req, err); + else + SET_REQ_SUCCESS(req); POST_COMPLETION_FOR_REQ(loop, req); + return 0; } @@ -1102,6 +1120,7 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { req = &handle->read_req; if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { + handle->pipe.conn.readfile_thread_handle = NULL; /* Reset cancellation. */ if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc, req, WT_EXECUTELONGFUNCTION)) { @@ -1169,8 +1188,8 @@ int uv_pipe_read_start(uv_pipe_t* handle, handle->read_cb = read_cb; handle->alloc_cb = alloc_cb; - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ + /* If reading was stopped and then started again, there could still be a read + * request pending. */ if (!(handle->flags & UV_HANDLE_READ_PENDING)) uv_pipe_queue_read(loop, handle); @@ -1226,154 +1245,110 @@ static void uv_queue_non_overlapped_write(uv_pipe_t* handle) { } -static int uv_pipe_write_impl(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - int err; - int result; - uv_tcp_t* tcp_send_handle; - uv_write_t* ipc_header_req = NULL; - uv_ipc_frame_uv_stream ipc_frame; +static int uv__build_coalesced_write_req(uv_write_t* user_req, + const uv_buf_t bufs[], + size_t nbufs, + uv_write_t** req_out, + uv_buf_t* write_buf_out) { + /* Pack into a single heap-allocated buffer: + * (a) a uv_write_t structure where libuv stores the actual state. + * (b) a pointer to the original uv_write_t. + * (c) data from all `bufs` entries. + */ + char* heap_buffer; + size_t heap_buffer_length, heap_buffer_offset; + uv__coalesced_write_t* coalesced_write_req; /* (a) + (b) */ + char* data_start; /* (c) */ + size_t data_length; + unsigned int i; + + /* Compute combined size of all combined buffers from `bufs`. */ + data_length = 0; + for (i = 0; i < nbufs; i++) + data_length += bufs[i].len; + + /* The total combined size of data buffers should not exceed UINT32_MAX, + * because WriteFile() won't accept buffers larger than that. */ + if (data_length > UINT32_MAX) + return WSAENOBUFS; /* Maps to UV_ENOBUFS. */ + + /* Compute heap buffer size. */ + heap_buffer_length = sizeof *coalesced_write_req + /* (a) + (b) */ + data_length; /* (c) */ + + /* Allocate buffer. */ + heap_buffer = uv__malloc(heap_buffer_length); + if (heap_buffer == NULL) + return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */ + + /* Copy uv_write_t information to the buffer. */ + coalesced_write_req = (uv__coalesced_write_t*) heap_buffer; + coalesced_write_req->req = *user_req; /* copy (a) */ + coalesced_write_req->req.coalesced = 1; + coalesced_write_req->user_req = user_req; /* copy (b) */ + heap_buffer_offset = sizeof *coalesced_write_req; /* offset (a) + (b) */ + + /* Copy data buffers to the heap buffer. */ + data_start = &heap_buffer[heap_buffer_offset]; + for (i = 0; i < nbufs; i++) { + memcpy(&heap_buffer[heap_buffer_offset], + bufs[i].base, + bufs[i].len); /* copy (c) */ + heap_buffer_offset += bufs[i].len; /* offset (c) */ + } + assert(heap_buffer_offset == heap_buffer_length); + + /* Set out arguments and return. */ + *req_out = &coalesced_write_req->req; + *write_buf_out = uv_buf_init(data_start, (unsigned int) data_length); + return 0; +} - if (nbufs != 1 && (nbufs != 0 || !send_handle)) { - return ERROR_NOT_SUPPORTED; - } - /* Only TCP handles are supported for sharing. */ - if (send_handle && ((send_handle->type != UV_TCP) || - (!(send_handle->flags & UV_HANDLE_BOUND) && - !(send_handle->flags & UV_HANDLE_CONNECTION)))) { - return ERROR_NOT_SUPPORTED; - } +static int uv__pipe_write_data(uv_loop_t* loop, + uv_write_t* req, + uv_pipe_t* handle, + const uv_buf_t bufs[], + size_t nbufs, + uv_write_cb cb, + int copy_always) { + int err; + int result; + uv_buf_t write_buf; assert(handle->handle != INVALID_HANDLE_VALUE); UV_REQ_INIT(req, UV_WRITE); req->handle = (uv_stream_t*) handle; + req->send_handle = NULL; req->cb = cb; - req->ipc_header = 0; + /* Private fields. */ + req->coalesced = 0; req->event_handle = NULL; req->wait_handle = INVALID_HANDLE_VALUE; memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - - if (handle->ipc) { - assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - ipc_frame.header.flags = 0; - - /* Use the IPC framing protocol. */ - if (send_handle) { - tcp_send_handle = (uv_tcp_t*)send_handle; - - if (handle->pipe.conn.ipc_pid == 0) { - handle->pipe.conn.ipc_pid = uv_current_pid(); - } - - err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid, - &ipc_frame.socket_info_ex.socket_info); - if (err) { - return err; - } - - ipc_frame.socket_info_ex.delayed_error = tcp_send_handle->delayed_error; - - ipc_frame.header.flags |= UV_IPC_TCP_SERVER; - - if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) { - ipc_frame.header.flags |= UV_IPC_TCP_CONNECTION; - } - } - - if (nbufs == 1) { - ipc_frame.header.flags |= UV_IPC_RAW_DATA; - ipc_frame.header.raw_data_length = bufs[0].len; - } - - /* - * Use the provided req if we're only doing a single write. - * If we're doing multiple writes, use ipc_header_write_req to do - * the first write, and then use the provided req for the second write. - */ - if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { - ipc_header_req = req; - } else { - /* - * Try to use the preallocated write req if it's available. - * Otherwise allocate a new one. - */ - if (handle->pipe.conn.ipc_header_write_req.type != UV_WRITE) { - ipc_header_req = (uv_write_t*)&handle->pipe.conn.ipc_header_write_req; - } else { - ipc_header_req = (uv_write_t*)uv__malloc(sizeof(uv_write_t)); - if (!ipc_header_req) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - } - - UV_REQ_INIT(ipc_header_req, UV_WRITE); - ipc_header_req->handle = (uv_stream_t*) handle; - ipc_header_req->cb = NULL; - ipc_header_req->ipc_header = 1; - } - - /* Write the header or the whole frame. */ - memset(&ipc_header_req->u.io.overlapped, 0, - sizeof(ipc_header_req->u.io.overlapped)); - - /* Using overlapped IO, but wait for completion before returning. - This write is blocking because ipc_frame is on stack. */ - ipc_header_req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); - if (!ipc_header_req->u.io.overlapped.hEvent) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - - result = WriteFile(handle->handle, - &ipc_frame, - ipc_frame.header.flags & UV_IPC_TCP_SERVER ? - sizeof(ipc_frame) : sizeof(ipc_frame.header), - NULL, - &ipc_header_req->u.io.overlapped); - if (!result && GetLastError() != ERROR_IO_PENDING) { - err = GetLastError(); - CloseHandle(ipc_header_req->u.io.overlapped.hEvent); + req->write_buffer = uv_null_buf_; + + if (nbufs == 0) { + /* Write empty buffer. */ + write_buf = uv_null_buf_; + } else if (nbufs == 1 && !copy_always) { + /* Write directly from bufs[0]. */ + write_buf = bufs[0]; + } else { + /* Coalesce all `bufs` into one big buffer. This also creates a new + * write-request structure that replaces the old one. */ + err = uv__build_coalesced_write_req(req, bufs, nbufs, &req, &write_buf); + if (err != 0) return err; - } - - if (!result) { - /* Request not completed immediately. Wait for it.*/ - if (WaitForSingleObject(ipc_header_req->u.io.overlapped.hEvent, INFINITE) != - WAIT_OBJECT_0) { - err = GetLastError(); - CloseHandle(ipc_header_req->u.io.overlapped.hEvent); - return err; - } - } - ipc_header_req->u.io.queued_bytes = 0; - CloseHandle(ipc_header_req->u.io.overlapped.hEvent); - ipc_header_req->u.io.overlapped.hEvent = NULL; - - REGISTER_HANDLE_REQ(loop, handle, ipc_header_req); - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - - /* If we don't have any raw data to write - we're done. */ - if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { - return 0; - } } if ((handle->flags & (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) == (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) { DWORD bytes; - result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, - &bytes, - NULL); + result = + WriteFile(handle->handle, write_buf.base, write_buf.len, &bytes, NULL); if (!result) { err = GetLastError(); @@ -1389,14 +1364,14 @@ static int uv_pipe_write_impl(uv_loop_t* loop, POST_COMPLETION_FOR_REQ(loop, req); return 0; } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - req->write_buffer = bufs[0]; + req->write_buffer = write_buf; uv_insert_non_overlapped_write_req(handle, req); if (handle->stream.conn.write_reqs_pending == 0) { uv_queue_non_overlapped_write(handle); } /* Request queued by the kernel. */ - req->u.io.queued_bytes = bufs[0].len; + req->u.io.queued_bytes = write_buf.len; handle->write_queue_size += req->u.io.queued_bytes; } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) { /* Using overlapped IO, but wait for completion before returning */ @@ -1406,8 +1381,8 @@ static int uv_pipe_write_impl(uv_loop_t* loop, } result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, + write_buf.base, + write_buf.len, NULL, &req->u.io.overlapped); @@ -1422,13 +1397,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop, req->u.io.queued_bytes = 0; } else { /* Request queued by the kernel. */ - req->u.io.queued_bytes = bufs[0].len; + req->u.io.queued_bytes = write_buf.len; handle->write_queue_size += req->u.io.queued_bytes; if (WaitForSingleObject(req->u.io.overlapped.hEvent, INFINITE) != WAIT_OBJECT_0) { err = GetLastError(); CloseHandle(req->u.io.overlapped.hEvent); - return uv_translate_sys_error(err); + return err; } } CloseHandle(req->u.io.overlapped.hEvent); @@ -1439,8 +1414,8 @@ static int uv_pipe_write_impl(uv_loop_t* loop, return 0; } else { result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, + write_buf.base, + write_buf.len, NULL, &req->u.io.overlapped); @@ -1453,7 +1428,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, req->u.io.queued_bytes = 0; } else { /* Request queued by the kernel. */ - req->u.io.queued_bytes = bufs[0].len; + req->u.io.queued_bytes = write_buf.len; handle->write_queue_size += req->u.io.queued_bytes; } @@ -1478,35 +1453,143 @@ static int uv_pipe_write_impl(uv_loop_t* loop, } -int uv_pipe_write(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, NULL, cb); +static DWORD uv__pipe_get_ipc_remote_pid(uv_pipe_t* handle) { + DWORD* pid = &handle->pipe.conn.ipc_remote_pid; + + /* If the both ends of the IPC pipe are owned by the same process, + * the remote end pid may not yet be set. If so, do it here. + * TODO: this is weird; it'd probably better to use a handshake. */ + if (*pid == 0) + *pid = GetCurrentProcessId(); + + return *pid; +} + + +int uv__pipe_write_ipc(uv_loop_t* loop, + uv_write_t* req, + uv_pipe_t* handle, + const uv_buf_t data_bufs[], + size_t data_buf_count, + uv_stream_t* send_handle, + uv_write_cb cb) { + uv_buf_t stack_bufs[6]; + uv_buf_t* bufs; + size_t buf_count, buf_index; + uv__ipc_frame_header_t frame_header; + uv__ipc_socket_xfer_type_t xfer_type = UV__IPC_SOCKET_XFER_NONE; + uv__ipc_socket_xfer_info_t xfer_info; + uint64_t data_length; + size_t i; + int err; + + /* Compute the combined size of data buffers. */ + data_length = 0; + for (i = 0; i < data_buf_count; i++) + data_length += data_bufs[i].len; + if (data_length > UINT32_MAX) + return WSAENOBUFS; /* Maps to UV_ENOBUFS. */ + + /* Prepare the frame's socket xfer payload. */ + if (send_handle != NULL) { + uv_tcp_t* send_tcp_handle = (uv_tcp_t*) send_handle; + + /* Verify that `send_handle` it is indeed a tcp handle. */ + if (send_tcp_handle->type != UV_TCP) + return ERROR_NOT_SUPPORTED; + + /* Export the tcp handle. */ + err = uv__tcp_xfer_export(send_tcp_handle, + uv__pipe_get_ipc_remote_pid(handle), + &xfer_type, + &xfer_info); + if (err != 0) + return err; + } + + /* Compute the number of uv_buf_t's required. */ + buf_count = 1 + data_buf_count; /* Frame header and data buffers. */ + if (send_handle != NULL) + buf_count += 1; /* One extra for the socket xfer information. */ + + /* Use the on-stack buffer array if it is big enough; otherwise allocate + * space for it on the heap. */ + if (buf_count < ARRAY_SIZE(stack_bufs)) { + /* Use on-stack buffer array. */ + bufs = stack_bufs; + } else { + /* Use heap-allocated buffer array. */ + bufs = uv__calloc(buf_count, sizeof(uv_buf_t)); + if (bufs == NULL) + return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */ + } + buf_index = 0; + + /* Initialize frame header and add it to the buffers list. */ + memset(&frame_header, 0, sizeof frame_header); + bufs[buf_index++] = uv_buf_init((char*) &frame_header, sizeof frame_header); + + if (send_handle != NULL) { + /* Add frame header flags. */ + switch (xfer_type) { + case UV__IPC_SOCKET_XFER_TCP_CONNECTION: + frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER | + UV__IPC_FRAME_XFER_IS_TCP_CONNECTION; + break; + case UV__IPC_SOCKET_XFER_TCP_SERVER: + frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER; + break; + default: + assert(0); /* Unreachable. */ + } + /* Add xfer info buffer. */ + bufs[buf_index++] = uv_buf_init((char*) &xfer_info, sizeof xfer_info); + } + + if (data_length > 0) { + /* Update frame header. */ + frame_header.flags |= UV__IPC_FRAME_HAS_DATA; + frame_header.data_length = (uint32_t) data_length; + /* Add data buffers to buffers list. */ + for (i = 0; i < data_buf_count; i++) + bufs[buf_index++] = data_bufs[i]; + } + + /* Write buffers. We set the `always_copy` flag, so it is not a problem that + * some of the written data lives on the stack. */ + err = uv__pipe_write_data(loop, req, handle, bufs, buf_count, cb, 1); + + /* If we had to heap-allocate the bufs array, free it now. */ + if (bufs != stack_bufs) { + uv__free(bufs); + } + + return err; } -int uv_pipe_write2(uv_loop_t* loop, +int uv__pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, const uv_buf_t bufs[], - unsigned int nbufs, + size_t nbufs, uv_stream_t* send_handle, uv_write_cb cb) { - if (!handle->ipc) { - return WSAEINVAL; + if (handle->ipc) { + /* IPC pipe write: use framing protocol. */ + return uv__pipe_write_ipc(loop, req, handle, bufs, nbufs, send_handle, cb); + } else { + /* Non-IPC pipe write: put data on the wire directly. */ + assert(send_handle == NULL); + return uv__pipe_write_data(loop, req, handle, bufs, nbufs, cb, 0); } - - return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, send_handle, cb); } static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, uv_buf_t buf) { - /* If there is an eof timer running, we don't need it any more, */ - /* so discard it. */ + /* If there is an eof timer running, we don't need it any more, so discard + * it. */ eof_timer_destroy(handle); handle->flags &= ~UV_HANDLE_READABLE; @@ -1518,8 +1601,8 @@ static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, uv_buf_t buf) { - /* If there is an eof timer running, we don't need it any more, */ - /* so discard it. */ + /* If there is an eof timer running, we don't need it any more, so discard + * it. */ eof_timer_destroy(handle); uv_read_stop((uv_stream_t*) handle); @@ -1530,10 +1613,7 @@ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, int error, uv_buf_t buf) { - if (error == ERROR_OPERATION_ABORTED) { - /* do nothing (equivalent to EINTR) */ - } - else if (error == ERROR_BROKEN_PIPE) { + if (error == ERROR_BROKEN_PIPE) { uv_pipe_read_eof(loop, handle, buf); } else { uv_pipe_read_error(loop, handle, error, buf); @@ -1541,152 +1621,228 @@ static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, } -void uv__pipe_insert_pending_socket(uv_pipe_t* handle, - uv__ipc_socket_info_ex* info, - int tcp_connection) { - uv__ipc_queue_item_t* item; +static void uv__pipe_queue_ipc_xfer_info( + uv_pipe_t* handle, + uv__ipc_socket_xfer_type_t xfer_type, + uv__ipc_socket_xfer_info_t* xfer_info) { + uv__ipc_xfer_queue_item_t* item; - item = (uv__ipc_queue_item_t*) uv__malloc(sizeof(*item)); + item = (uv__ipc_xfer_queue_item_t*) uv__malloc(sizeof(*item)); if (item == NULL) uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - memcpy(&item->socket_info_ex, info, sizeof(item->socket_info_ex)); - item->tcp_connection = tcp_connection; - QUEUE_INSERT_TAIL(&handle->pipe.conn.pending_ipc_info.queue, &item->member); - handle->pipe.conn.pending_ipc_info.queue_len++; + item->xfer_type = xfer_type; + item->xfer_info = *xfer_info; + + QUEUE_INSERT_TAIL(&handle->pipe.conn.ipc_xfer_queue, &item->member); + handle->pipe.conn.ipc_xfer_queue_length++; +} + + +/* Read an exact number of bytes from a pipe. If an error or end-of-file is + * encountered before the requested number of bytes are read, an error is + * returned. */ +static int uv__pipe_read_exactly(HANDLE h, void* buffer, DWORD count) { + DWORD bytes_read, bytes_read_now; + + bytes_read = 0; + while (bytes_read < count) { + if (!ReadFile(h, + (char*) buffer + bytes_read, + count - bytes_read, + &bytes_read_now, + NULL)) { + return GetLastError(); + } + + bytes_read += bytes_read_now; + } + + assert(bytes_read == count); + return 0; } -void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* req) { - DWORD bytes, avail; +static DWORD uv__pipe_read_data(uv_loop_t* loop, + uv_pipe_t* handle, + DWORD suggested_bytes, + DWORD max_bytes) { + DWORD bytes_read; uv_buf_t buf; - uv_ipc_frame_uv_stream ipc_frame; + /* Ask the user for a buffer to read data into. */ + buf = uv_buf_init(NULL, 0); + handle->alloc_cb((uv_handle_t*) handle, suggested_bytes, &buf); + if (buf.base == NULL || buf.len == 0) { + handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); + return 0; /* Break out of read loop. */ + } + + /* Ensure we read at most the smaller of: + * (a) the length of the user-allocated buffer. + * (b) the maximum data length as specified by the `max_bytes` argument. + */ + if (max_bytes > buf.len) + max_bytes = buf.len; + + /* Read into the user buffer. */ + if (!ReadFile(handle->handle, buf.base, max_bytes, &bytes_read, NULL)) { + uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf); + return 0; /* Break out of read loop. */ + } + + /* Call the read callback. */ + handle->read_cb((uv_stream_t*) handle, bytes_read, &buf); + + return bytes_read; +} + + +static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) { + uint32_t* data_remaining = &handle->pipe.conn.ipc_data_frame.payload_remaining; + int err; + + if (*data_remaining > 0) { + /* Read frame data payload. */ + DWORD bytes_read = + uv__pipe_read_data(loop, handle, *data_remaining, *data_remaining); + *data_remaining -= bytes_read; + return bytes_read; + + } else { + /* Start of a new IPC frame. */ + uv__ipc_frame_header_t frame_header; + uint32_t xfer_flags; + uv__ipc_socket_xfer_type_t xfer_type; + uv__ipc_socket_xfer_info_t xfer_info; + + /* Read the IPC frame header. */ + err = uv__pipe_read_exactly( + handle->handle, &frame_header, sizeof frame_header); + if (err) + goto error; + + /* Validate that flags are valid. */ + if ((frame_header.flags & ~UV__IPC_FRAME_VALID_FLAGS) != 0) + goto invalid; + /* Validate that reserved2 is zero. */ + if (frame_header.reserved2 != 0) + goto invalid; + + /* Parse xfer flags. */ + xfer_flags = frame_header.flags & UV__IPC_FRAME_XFER_FLAGS; + if (xfer_flags & UV__IPC_FRAME_HAS_SOCKET_XFER) { + /* Socket coming -- determine the type. */ + xfer_type = xfer_flags & UV__IPC_FRAME_XFER_IS_TCP_CONNECTION + ? UV__IPC_SOCKET_XFER_TCP_CONNECTION + : UV__IPC_SOCKET_XFER_TCP_SERVER; + } else if (xfer_flags == 0) { + /* No socket. */ + xfer_type = UV__IPC_SOCKET_XFER_NONE; + } else { + /* Invalid flags. */ + goto invalid; + } + + /* Parse data frame information. */ + if (frame_header.flags & UV__IPC_FRAME_HAS_DATA) { + *data_remaining = frame_header.data_length; + } else if (frame_header.data_length != 0) { + /* Data length greater than zero but data flag not set -- invalid. */ + goto invalid; + } + + /* If no socket xfer info follows, return here. Data will be read in a + * subsequent invocation of uv__pipe_read_ipc(). */ + if (xfer_type == UV__IPC_SOCKET_XFER_NONE) + return sizeof frame_header; /* Number of bytes read. */ + + /* Read transferred socket information. */ + err = uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info); + if (err) + goto error; + + /* Store the pending socket info. */ + uv__pipe_queue_ipc_xfer_info(handle, xfer_type, &xfer_info); + + /* Return number of bytes read. */ + return sizeof frame_header + sizeof xfer_info; + } + +invalid: + /* Invalid frame. */ + err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */ + +error: + uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_); + return 0; /* Break out of read loop. */ +} + + +void uv_process_pipe_read_req(uv_loop_t* loop, + uv_pipe_t* handle, + uv_req_t* req) { assert(handle->type == UV_NAMED_PIPE); - handle->flags &= ~UV_HANDLE_READ_PENDING; + handle->flags &= ~(UV_HANDLE_READ_PENDING | UV_HANDLE_CANCELLATION_PENDING); + DECREASE_PENDING_REQ_COUNT(handle); eof_timer_stop(handle); - if (!REQ_SUCCESS(req)) { - /* An error occurred doing the 0-read. */ - if (handle->flags & UV_HANDLE_READING) { - uv_pipe_read_error_or_eof(loop, - handle, - GET_REQ_ERROR(req), - uv_null_buf_); - } - } else { - /* Do non-blocking reads until the buffer is empty */ - while (handle->flags & UV_HANDLE_READING) { - if (!PeekNamedPipe(handle->handle, - NULL, - 0, - NULL, - &avail, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); - break; - } + /* At this point, we're done with bookkeeping. If the user has stopped + * reading the pipe in the meantime, there is nothing left to do, since there + * is no callback that we can call. */ + if (!(handle->flags & UV_HANDLE_READING)) + return; - if (avail == 0) { - /* There is nothing to read after all. */ - break; - } + if (!REQ_SUCCESS(req)) { + /* An error occurred doing the zero-read. */ + DWORD err = GET_REQ_ERROR(req); - if (handle->ipc) { - /* Use the IPC framing protocol to read the incoming data. */ - if (handle->pipe.conn.remaining_ipc_rawdata_bytes == 0) { - /* We're reading a new frame. First, read the header. */ - assert(avail >= sizeof(ipc_frame.header)); - - if (!ReadFile(handle->handle, - &ipc_frame.header, - sizeof(ipc_frame.header), - &bytes, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), - uv_null_buf_); - break; - } - - assert(bytes == sizeof(ipc_frame.header)); - assert(ipc_frame.header.flags <= (UV_IPC_TCP_SERVER | UV_IPC_RAW_DATA | - UV_IPC_TCP_CONNECTION)); - - if (ipc_frame.header.flags & UV_IPC_TCP_SERVER) { - assert(avail - sizeof(ipc_frame.header) >= - sizeof(ipc_frame.socket_info_ex)); - - /* Read the TCP socket info. */ - if (!ReadFile(handle->handle, - &ipc_frame.socket_info_ex, - sizeof(ipc_frame) - sizeof(ipc_frame.header), - &bytes, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), - uv_null_buf_); - break; - } - - assert(bytes == sizeof(ipc_frame) - sizeof(ipc_frame.header)); - - /* Store the pending socket info. */ - uv__pipe_insert_pending_socket( - handle, - &ipc_frame.socket_info_ex, - ipc_frame.header.flags & UV_IPC_TCP_CONNECTION); - } - - if (ipc_frame.header.flags & UV_IPC_RAW_DATA) { - handle->pipe.conn.remaining_ipc_rawdata_bytes = - ipc_frame.header.raw_data_length; - continue; - } - } else { - avail = min(avail, (DWORD)handle->pipe.conn.remaining_ipc_rawdata_bytes); - } - } + /* If the read was cancelled by uv__pipe_interrupt_read(), the request may + * indicate an ERROR_OPERATION_ABORTED error. This error isn't relevant to + * the user; we'll start a new zero-read at the end of this function. */ + if (err != ERROR_OPERATION_ABORTED) + uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_); - buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, avail, &buf); - if (buf.base == NULL || buf.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); + } else { + /* The zero-read completed without error, indicating there is data + * available in the kernel buffer. */ + DWORD avail; + + /* Get the number of bytes available. */ + avail = 0; + if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL)) + uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); + + /* Read until we've either read all the bytes available, or the 'reading' + * flag is cleared. */ + while (avail > 0 && handle->flags & UV_HANDLE_READING) { + /* Depending on the type of pipe, read either IPC frames or raw data. */ + DWORD bytes_read = + handle->ipc ? uv__pipe_read_ipc(loop, handle) + : uv__pipe_read_data(loop, handle, avail, (DWORD) -1); + + /* If no bytes were read, treat this as an indication that an error + * occurred, and break out of the read loop. */ + if (bytes_read == 0) break; - } - assert(buf.base != NULL); - - if (ReadFile(handle->handle, - buf.base, - min(buf.len, avail), - &bytes, - NULL)) { - /* Successful read */ - if (handle->ipc) { - assert(handle->pipe.conn.remaining_ipc_rawdata_bytes >= bytes); - handle->pipe.conn.remaining_ipc_rawdata_bytes = - handle->pipe.conn.remaining_ipc_rawdata_bytes - bytes; - } - handle->read_cb((uv_stream_t*)handle, bytes, &buf); - /* Read again only if bytes == buf.len */ - if (bytes <= buf.len) { - break; - } - } else { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf); + /* It is possible that more bytes were read than we thought were + * available. To prevent `avail` from underflowing, break out of the loop + * if this is the case. */ + if (bytes_read > avail) break; - } - } - /* Post another 0-read if still reading and not closing. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_pipe_queue_read(loop, handle); + /* Recompute the number of bytes available. */ + avail -= bytes_read; } } - DECREASE_PENDING_REQ_COUNT(handle); + /* Start another zero-read request if necessary. */ + if ((handle->flags & UV_HANDLE_READING) && + !(handle->flags & UV_HANDLE_READ_PENDING)) { + uv_pipe_queue_read(loop, handle); + } } @@ -1712,17 +1868,19 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, } } - if (req->ipc_header) { - if (req == &handle->pipe.conn.ipc_header_write_req) { - req->type = UV_UNKNOWN_REQ; - } else { - uv__free(req); - } - } else { - if (req->cb) { - err = GET_REQ_ERROR(req); - req->cb(req, uv_translate_sys_error(err)); - } + err = GET_REQ_ERROR(req); + + /* If this was a coalesced write, extract pointer to the user_provided + * uv_write_t structure so we can pass the expected pointer to the callback, + * then free the heap-allocated write req. */ + if (req->coalesced) { + uv__coalesced_write_t* coalesced_write = + container_of(req, uv__coalesced_write_t, req); + req = coalesced_write->user_req; + uv__free(coalesced_write); + } + if (req->cb) { + req->cb(req, uv_translate_sys_error(err)); } handle->stream.conn.write_reqs_pending--; @@ -1748,7 +1906,7 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, assert(handle->type == UV_NAMED_PIPE); - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */ assert(req->pipeHandle == INVALID_HANDLE_VALUE); DECREASE_PENDING_REQ_COUNT(handle); @@ -1768,7 +1926,7 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, CloseHandle(req->pipeHandle); req->pipeHandle = INVALID_HANDLE_VALUE; } - if (!(handle->flags & UV__HANDLE_CLOSING)) { + if (!(handle->flags & UV_HANDLE_CLOSING)) { uv_pipe_queue_accept(loop, handle, req, FALSE); } } @@ -1806,19 +1964,19 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, UNREGISTER_HANDLE_REQ(loop, handle, req); if (handle->flags & UV_HANDLE_READABLE) { - /* Initialize and optionally start the eof timer. Only do this if the */ - /* pipe is readable and we haven't seen EOF come in ourselves. */ + /* Initialize and optionally start the eof timer. Only do this if the pipe + * is readable and we haven't seen EOF come in ourselves. */ eof_timer_init(handle); - /* If reading start the timer right now. */ - /* Otherwise uv_pipe_queue_read will start it. */ + /* If reading start the timer right now. Otherwise uv_pipe_queue_read will + * start it. */ if (handle->flags & UV_HANDLE_READ_PENDING) { eof_timer_start(handle); } } else { - /* This pipe is not readable. We can just close it to let the other end */ - /* know that we're done writing. */ + /* This pipe is not readable. We can just close it to let the other end + * know that we're done writing. */ close_pipe(handle); } @@ -1869,17 +2027,16 @@ static void eof_timer_cb(uv_timer_t* timer) { assert(pipe->type == UV_NAMED_PIPE); - /* This should always be true, since we start the timer only */ - /* in uv_pipe_queue_read after successfully calling ReadFile, */ - /* or in uv_process_pipe_shutdown_req if a read is pending, */ - /* and we always immediately stop the timer in */ - /* uv_process_pipe_read_req. */ + /* This should always be true, since we start the timer only in + * uv_pipe_queue_read after successfully calling ReadFile, or in + * uv_process_pipe_shutdown_req if a read is pending, and we always + * immediately stop the timer in uv_process_pipe_read_req. */ assert(pipe->flags & UV_HANDLE_READ_PENDING); - /* If there are many packets coming off the iocp then the timer callback */ - /* may be called before the read request is coming off the queue. */ - /* Therefore we check here if the read request has completed but will */ - /* be processed later. */ + /* If there are many packets coming off the iocp then the timer callback may + * be called before the read request is coming off the queue. Therefore we + * check here if the read request has completed but will be processed later. + */ if ((pipe->flags & UV_HANDLE_READ_PENDING) && HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) { return; @@ -1888,12 +2045,12 @@ static void eof_timer_cb(uv_timer_t* timer) { /* Force both ends off the pipe. */ close_pipe(pipe); - /* Stop reading, so the pending read that is going to fail will */ - /* not be reported to the user. */ + /* Stop reading, so the pending read that is going to fail will not be + * reported to the user. */ uv_read_stop((uv_stream_t*) pipe); - /* Report the eof and update flags. This will get reported even if the */ - /* user stopped reading in the meantime. TODO: is that okay? */ + /* Report the eof and update flags. This will get reported even if the user + * stopped reading in the meantime. TODO: is that okay? */ uv_pipe_read_eof(loop, pipe, uv_null_buf_); } @@ -1980,8 +2137,8 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { if (pipe->ipc) { assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - pipe->pipe.conn.ipc_pid = uv_os_getppid(); - assert(pipe->pipe.conn.ipc_pid != -1); + pipe->pipe.conn.ipc_remote_pid = uv_os_getppid(); + assert(pipe->pipe.conn.ipc_remote_pid != (DWORD) -1); } return 0; } @@ -2006,7 +2163,15 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) return UV_EINVAL; } - uv__pipe_pause_read((uv_pipe_t*)handle); /* cast away const warning */ + /* NtQueryInformationFile will block if another thread is performing a + * blocking operation on the queried handle. If the pipe handle is + * synchronous, there may be a worker thread currently calling ReadFile() on + * the pipe handle, which could cause a deadlock. To avoid this, interrupt + * the read. */ + if (handle->flags & UV_HANDLE_CONNECTION && + handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { + uv__pipe_interrupt_read((uv_pipe_t*) handle); /* cast away const warning */ + } nt_status = pNtQueryInformationFile(handle->handle, &io_status, @@ -2097,7 +2262,6 @@ error: uv__free(name_info); cleanup: - uv__pipe_unpause_read((uv_pipe_t*)handle); /* cast away const warning */ return err; } @@ -2105,7 +2269,7 @@ cleanup: int uv_pipe_pending_count(uv_pipe_t* handle) { if (!handle->ipc) return 0; - return handle->pipe.conn.pending_ipc_info.queue_len; + return handle->pipe.conn.ipc_xfer_queue_length; } @@ -2138,14 +2302,14 @@ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { if (!handle->ipc) return UV_UNKNOWN_HANDLE; - if (handle->pipe.conn.pending_ipc_info.queue_len == 0) + if (handle->pipe.conn.ipc_xfer_queue_length == 0) return UV_UNKNOWN_HANDLE; else return UV_TCP; } int uv_pipe_chmod(uv_pipe_t* handle, int mode) { - SID_IDENTIFIER_AUTHORITY sid_world = SECURITY_WORLD_SID_AUTHORITY; + SID_IDENTIFIER_AUTHORITY sid_world = { SECURITY_WORLD_SID_AUTHORITY }; PACL old_dacl, new_dacl; PSECURITY_DESCRIPTOR sd; EXPLICIT_ACCESS ea; @@ -2180,7 +2344,7 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) { error = GetLastError(); goto clean_sid; } - + memset(&ea, 0, sizeof(EXPLICIT_ACCESS)); if (mode & UV_READABLE) ea.grfAccessPermissions |= GENERIC_READ | FILE_WRITE_ATTRIBUTES; diff --git a/Utilities/cmlibuv/src/win/poll.c b/Utilities/cmlibuv/src/win/poll.c index a648ba7..3c66786 100644 --- a/Utilities/cmlibuv/src/win/poll.c +++ b/Utilities/cmlibuv/src/win/poll.c @@ -75,7 +75,7 @@ static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) { static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { uv_req_t* req; AFD_POLL_INFO* afd_poll_info; - DWORD result; + int result; /* Find a yet unsubmitted req to submit. */ if (handle->submitted_events_1 == 0) { @@ -91,16 +91,16 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { handle->mask_events_1 = handle->events; handle->mask_events_2 = 0; } else { - /* Just wait until there's an unsubmitted req. */ - /* This will happen almost immediately as one of the 2 outstanding */ - /* requests is about to return. When this happens, */ - /* uv__fast_poll_process_poll_req will be called, and the pending */ - /* events, if needed, will be processed in a subsequent request. */ + /* Just wait until there's an unsubmitted req. This will happen almost + * immediately as one of the 2 outstanding requests is about to return. + * When this happens, uv__fast_poll_process_poll_req will be called, and + * the pending events, if needed, will be processed in a subsequent + * request. */ return; } - /* Setting Exclusive to TRUE makes the other poll request return if there */ - /* is any. */ + /* Setting Exclusive to TRUE makes the other poll request return if there is + * any. */ afd_poll_info->Exclusive = TRUE; afd_poll_info->NumberOfHandles = 1; afd_poll_info->Timeout.QuadPart = INT64_MAX; @@ -136,7 +136,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) { AFD_POLL_INFO afd_poll_info; - DWORD result; + int result; afd_poll_info.Exclusive = TRUE; afd_poll_info.NumberOfHandles = 1; @@ -218,7 +218,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, if ((handle->events & ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) { uv__fast_poll_submit_poll_req(loop, handle); - } else if ((handle->flags & UV__HANDLE_CLOSING) && + } else if ((handle->flags & UV_HANDLE_CLOSING) && handle->submitted_events_1 == 0 && handle->submitted_events_2 == 0) { uv_want_endgame(loop, (uv_handle_t*) handle); @@ -228,7 +228,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { assert(handle->type == UV_POLL); - assert(!(handle->flags & UV__HANDLE_CLOSING)); + assert(!(handle->flags & UV_HANDLE_CLOSING)); assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); handle->events = events; @@ -257,8 +257,8 @@ static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) { uv_want_endgame(loop, (uv_handle_t*) handle); return 0; } else { - /* Cancel outstanding poll requests by executing another, unique poll */ - /* request that forces the outstanding ones to return. */ + /* Cancel outstanding poll requests by executing another, unique poll + * request that forces the outstanding ones to return. */ return uv__fast_poll_cancel_poll_req(loop, handle); } } @@ -316,9 +316,8 @@ static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop, return INVALID_SOCKET; } - /* If we didn't (try) to create a peer socket yet, try to make one. Don't */ - /* try again if the peer socket creation failed earlier for the same */ - /* protocol. */ + /* If we didn't (try) to create a peer socket yet, try to make one. Don't try + * again if the peer socket creation failed earlier for the same protocol. */ peer_socket = loop->poll_peer_sockets[index]; if (peer_socket == 0) { peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info); @@ -357,8 +356,8 @@ static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) { efds.fd_count = 0; } - /* Make the select() time out after 3 minutes. If select() hangs because */ - /* the user closed the socket, we will at least not hang indefinitely. */ + /* Make the select() time out after 3 minutes. If select() hangs because the + * user closed the socket, we will at least not hang indefinitely. */ timeout.tv_sec = 3 * 60; timeout.tv_usec = 0; @@ -462,7 +461,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, if ((handle->events & ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) { uv__slow_poll_submit_poll_req(loop, handle); - } else if ((handle->flags & UV__HANDLE_CLOSING) && + } else if ((handle->flags & UV_HANDLE_CLOSING) && handle->submitted_events_1 == 0 && handle->submitted_events_2 == 0) { uv_want_endgame(loop, (uv_handle_t*) handle); @@ -472,7 +471,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { assert(handle->type == UV_POLL); - assert(!(handle->flags & UV__HANDLE_CLOSING)); + assert(!(handle->flags & UV_HANDLE_CLOSING)); assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0); handle->events = events; @@ -522,10 +521,10 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) return uv_translate_sys_error(WSAGetLastError()); - /* Try to obtain a base handle for the socket. This increases this chances */ - /* that we find an AFD handle and are able to use the fast poll mechanism. */ - /* This will always fail on windows XP/2k3, since they don't support the */ - /* SIO_BASE_HANDLE ioctl. */ +/* Try to obtain a base handle for the socket. This increases this chances that + * we find an AFD handle and are able to use the fast poll mechanism. This will + * always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE + * ioctl. */ #ifndef NDEBUG base_socket = INVALID_SOCKET; #endif @@ -557,9 +556,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, return uv_translate_sys_error(WSAGetLastError()); } - /* Get the peer socket that is needed to enable fast poll. If the returned */ - /* value is NULL, the protocol is not implemented by MSAFD and we'll have */ - /* to use slow mode. */ + /* Get the peer socket that is needed to enable fast poll. If the returned + * value is NULL, the protocol is not implemented by MSAFD and we'll have to + * use slow mode. */ peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info); if (peer_socket != INVALID_SOCKET) { @@ -634,7 +633,7 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) { void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); + assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); assert(handle->submitted_events_1 == 0); diff --git a/Utilities/cmlibuv/src/win/process-stdio.c b/Utilities/cmlibuv/src/win/process-stdio.c index 032e309..355d618 100644 --- a/Utilities/cmlibuv/src/win/process-stdio.c +++ b/Utilities/cmlibuv/src/win/process-stdio.c @@ -103,12 +103,12 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop, DWORD client_access = 0; HANDLE child_pipe = INVALID_HANDLE_VALUE; int err; + int overlap; if (flags & UV_READABLE_PIPE) { - /* The server needs inbound access too, otherwise CreateNamedPipe() */ - /* won't give us the FILE_READ_ATTRIBUTES permission. We need that to */ - /* probe the state of the write buffer when we're trying to shutdown */ - /* the pipe. */ + /* The server needs inbound access too, otherwise CreateNamedPipe() won't + * give us the FILE_READ_ATTRIBUTES permission. We need that to probe the + * state of the write buffer when we're trying to shutdown the pipe. */ server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND; client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES; } @@ -131,12 +131,13 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop, sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; + overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE); child_pipe = CreateFileA(pipe_name, client_access, 0, &sa, OPEN_EXISTING, - server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0, + overlap ? FILE_FLAG_OVERLAPPED : 0, NULL); if (child_pipe == INVALID_HANDLE_VALUE) { err = GetLastError(); @@ -159,8 +160,8 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop, } #endif - /* Do a blocking ConnectNamedPipe. This should not block because we have */ - /* both ends of the pipe created. */ + /* Do a blocking ConnectNamedPipe. This should not block because we have both + * ends of the pipe created. */ if (!ConnectNamedPipe(server_pipe->handle, NULL)) { if (GetLastError() != ERROR_PIPE_CONNECTED) { err = GetLastError(); @@ -194,11 +195,11 @@ static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) { HANDLE current_process; - /* _get_osfhandle will sometimes return -2 in case of an error. This seems */ - /* to happen when fd <= 2 and the process' corresponding stdio handle is */ - /* set to NULL. Unfortunately DuplicateHandle will happily duplicate */ - /* (HANDLE) -2, so this situation goes unnoticed until someone tries to */ - /* use the duplicate. Therefore we filter out known-invalid handles here. */ + /* _get_osfhandle will sometimes return -2 in case of an error. This seems to + * happen when fd <= 2 and the process' corresponding stdio handle is set to + * NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so + * this situation goes unnoticed until someone tries to use the duplicate. + * Therefore we filter out known-invalid handles here. */ if (handle == INVALID_HANDLE_VALUE || handle == NULL || handle == (HANDLE) -2) { @@ -284,8 +285,8 @@ int uv__stdio_create(uv_loop_t* loop, return ERROR_OUTOFMEMORY; } - /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */ - /* clean up on failure. */ + /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean + * up on failure. */ CHILD_STDIO_COUNT(buffer) = count; for (i = 0; i < count; i++) { CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; @@ -303,12 +304,12 @@ int uv__stdio_create(uv_loop_t* loop, switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM)) { case UV_IGNORE: - /* Starting a process with no stdin/stout/stderr can confuse it. */ - /* So no matter what the user specified, we make sure the first */ - /* three FDs are always open in their typical modes, e.g. stdin */ - /* be readable and stdout/err should be writable. For FDs > 2, don't */ - /* do anything - all handles in the stdio buffer are initialized with */ - /* INVALID_HANDLE_VALUE, which should be okay. */ + /* Starting a process with no stdin/stout/stderr can confuse it. So no + * matter what the user specified, we make sure the first three FDs are + * always open in their typical modes, e. g. stdin be readable and + * stdout/err should be writable. For FDs > 2, don't do anything - all + * handles in the stdio buffer are initialized with. + * INVALID_HANDLE_VALUE, which should be okay. */ if (i <= 2) { DWORD access = (i == 0) ? FILE_GENERIC_READ : FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES; @@ -323,14 +324,14 @@ int uv__stdio_create(uv_loop_t* loop, break; case UV_CREATE_PIPE: { - /* Create a pair of two connected pipe ends; one end is turned into */ - /* an uv_pipe_t for use by the parent. The other one is given to */ - /* the child. */ + /* Create a pair of two connected pipe ends; one end is turned into an + * uv_pipe_t for use by the parent. The other one is given to the + * child. */ uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream; HANDLE child_pipe = INVALID_HANDLE_VALUE; - /* Create a new, connected pipe pair. stdio[i].stream should point */ - /* to an uninitialized, but not connected pipe handle. */ + /* Create a new, connected pipe pair. stdio[i]. stream should point to + * an uninitialized, but not connected pipe handle. */ assert(fdopt.data.stream->type == UV_NAMED_PIPE); assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION)); assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER)); @@ -354,8 +355,8 @@ int uv__stdio_create(uv_loop_t* loop, /* Make an inheritable duplicate of the handle. */ err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle); if (err) { - /* If fdopt.data.fd is not valid and fd fd <= 2, then ignore the */ - /* error. */ + /* If fdopt. data. fd is not valid and fd <= 2, then ignore the + * error. */ if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) { CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; @@ -418,8 +419,8 @@ int uv__stdio_create(uv_loop_t* loop, if (stream_handle == NULL || stream_handle == INVALID_HANDLE_VALUE) { - /* The handle is already closed, or not yet created, or the */ - /* stream type is not supported. */ + /* The handle is already closed, or not yet created, or the stream + * type is not supported. */ err = ERROR_NOT_SUPPORTED; goto error; } diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c index 25cfe87..24037b3 100644 --- a/Utilities/cmlibuv/src/win/process.c +++ b/Utilities/cmlibuv/src/win/process.c @@ -360,8 +360,8 @@ static WCHAR* search_path(const WCHAR *file, return NULL; } - /* Find the start of the filename so we can split the directory from the */ - /* name. */ + /* Find the start of the filename so we can split the directory from the + * name. */ for (file_name_start = (WCHAR*)file + file_len; file_name_start > file && file_name_start[-1] != L'\\' @@ -556,8 +556,8 @@ int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) { arg_count++; } - /* Adjust for potential quotes. Also assume the worst-case scenario */ - /* that every character needs escaping, so we need twice as much space. */ + /* Adjust for potential quotes. Also assume the worst-case scenario that + * every character needs escaping, so we need twice as much space. */ dst_len = dst_len * 2 + arg_count * 2; /* Allocate buffer for the final command line. */ @@ -739,7 +739,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { } } *ptr_copy = NULL; - assert(env_len == ptr - dst_copy); + assert(env_len == (size_t) (ptr - dst_copy)); /* sort our (UTF-16) copy */ qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp); @@ -799,7 +799,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { var_size = GetEnvironmentVariableW(required_vars[i].wide, ptr, (int) (env_len - (ptr - dst))); - if (var_size != len-1) { /* race condition? */ + if (var_size != (DWORD) (len - 1)) { /* TODO: handle race condition? */ uv_fatal_error(GetLastError(), "GetEnvironmentVariableW"); } } @@ -815,7 +815,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { } /* Terminate with an extra NULL. */ - assert(env_len == (ptr - dst)); + assert(env_len == (size_t) (ptr - dst)); *ptr = L'\0'; uv__free(dst_copy); @@ -831,8 +831,13 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { */ static WCHAR* find_path(WCHAR *env) { for (; env != NULL && *env != 0; env += wcslen(env) + 1) { - if (wcsncmp(env, L"PATH=", 5) == 0) + if ((env[0] == L'P' || env[0] == L'p') && + (env[1] == L'A' || env[1] == L'a') && + (env[2] == L'T' || env[2] == L't') && + (env[3] == L'H' || env[3] == L'h') && + (env[4] == L'=')) { return &env[5]; + } } return NULL; @@ -865,9 +870,9 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { assert(handle->exit_cb_pending); handle->exit_cb_pending = 0; - /* If we're closing, don't call the exit callback. Just schedule a close */ - /* callback now. */ - if (handle->flags & UV__HANDLE_CLOSING) { + /* If we're closing, don't call the exit callback. Just schedule a close + * callback now. */ + if (handle->flags & UV_HANDLE_CLOSING) { uv_want_endgame(loop, (uv_handle_t*) handle); return; } @@ -878,14 +883,14 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { handle->wait_handle = INVALID_HANDLE_VALUE; } - /* Set the handle to inactive: no callbacks will be made after the exit */ - /* callback.*/ + /* Set the handle to inactive: no callbacks will be made after the exit + * callback. */ uv__handle_stop(handle); if (GetExitCodeProcess(handle->process_handle, &status)) { exit_code = status; } else { - /* Unable to to obtain the exit code. This should never happen. */ + /* Unable to obtain the exit code. This should never happen. */ exit_code = uv_translate_sys_error(GetLastError()); } @@ -900,8 +905,8 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) { uv__handle_closing(handle); if (handle->wait_handle != INVALID_HANDLE_VALUE) { - /* This blocks until either the wait was cancelled, or the callback has */ - /* completed. */ + /* This blocks until either the wait was cancelled, or the callback has + * completed. */ BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE); if (!r) { /* This should never happen, and if it happens, we can't recover... */ @@ -919,7 +924,7 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) { void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) { assert(!handle->exit_cb_pending); - assert(handle->flags & UV__HANDLE_CLOSING); + assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); /* Clean-up the process handle. */ @@ -965,6 +970,8 @@ int uv_spawn(uv_loop_t* loop, UV_PROCESS_SETGID | UV_PROCESS_SETUID | UV_PROCESS_WINDOWS_HIDE | + UV_PROCESS_WINDOWS_HIDE_CONSOLE | + UV_PROCESS_WINDOWS_HIDE_GUI | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); err = uv_utf8_to_utf16_alloc(options->file, &application); @@ -1066,7 +1073,8 @@ int uv_spawn(uv_loop_t* loop, process_flags = CREATE_UNICODE_ENVIRONMENT; - if (options->flags & UV_PROCESS_WINDOWS_HIDE) { + if ((options->flags & UV_PROCESS_WINDOWS_HIDE_CONSOLE) || + (options->flags & UV_PROCESS_WINDOWS_HIDE)) { /* Avoid creating console window if stdio is not inherited. */ for (i = 0; i < options->stdio_count; i++) { if (options->stdio[i].flags & UV_INHERIT_FD) @@ -1074,7 +1082,9 @@ int uv_spawn(uv_loop_t* loop, if (i == options->stdio_count - 1) process_flags |= CREATE_NO_WINDOW; } - + } + if ((options->flags & UV_PROCESS_WINDOWS_HIDE_GUI) || + (options->flags & UV_PROCESS_WINDOWS_HIDE)) { /* Use SW_HIDE to avoid any potential process window. */ startup.wShowWindow = SW_HIDE; } else { @@ -1160,14 +1170,13 @@ int uv_spawn(uv_loop_t* loop, } } - /* Spawn succeeded */ - /* Beyond this point, failure is reported asynchronously. */ + /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */ process->process_handle = info.hProcess; process->pid = info.dwProcessId; - /* If the process isn't spawned as detached, assign to the global job */ - /* object so windows will kill it when the parent process dies. */ + /* If the process isn't spawned as detached, assign to the global job object + * so windows will kill it when the parent process dies. */ if (!(options->flags & UV_PROCESS_DETACHED)) { uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle); @@ -1194,7 +1203,8 @@ int uv_spawn(uv_loop_t* loop, if (fdopt->flags & UV_CREATE_PIPE && fdopt->data.stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) fdopt->data.stream)->ipc) { - ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId; + ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_remote_pid = + info.dwProcessId; } } @@ -1210,8 +1220,8 @@ int uv_spawn(uv_loop_t* loop, assert(!err); - /* Make the handle active. It will remain active until the exit callback */ - /* is made or the handle is closed, whichever happens first. */ + /* Make the handle active. It will remain active until the exit callback is + * made or the handle is closed, whichever happens first. */ uv__handle_start(process); /* Cleanup, whether we succeeded or failed. */ @@ -1242,16 +1252,16 @@ static int uv__kill(HANDLE process_handle, int signum) { case SIGTERM: case SIGKILL: case SIGINT: { - /* Unconditionally terminate the process. On Windows, killed processes */ - /* normally return 1. */ + /* Unconditionally terminate the process. On Windows, killed processes + * normally return 1. */ DWORD status; int err; if (TerminateProcess(process_handle, 1)) return 0; - /* If the process already exited before TerminateProcess was called, */ - /* TerminateProcess will fail with ERROR_ACCESS_DENIED. */ + /* If the process already exited before TerminateProcess was called,. + * TerminateProcess will fail with ERROR_ACCESS_DENIED. */ err = GetLastError(); if (err == ERROR_ACCESS_DENIED && GetExitCodeProcess(process_handle, &status) && diff --git a/Utilities/cmlibuv/src/win/req.c b/Utilities/cmlibuv/src/win/req.c deleted file mode 100644 index 111cc5e..0000000 --- a/Utilities/cmlibuv/src/win/req.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include <assert.h> - -#include "uv.h" -#include "internal.h" diff --git a/Utilities/cmlibuv/src/win/signal.c b/Utilities/cmlibuv/src/win/signal.c index a174da1..276dc60 100644 --- a/Utilities/cmlibuv/src/win/signal.c +++ b/Utilities/cmlibuv/src/win/signal.c @@ -47,13 +47,13 @@ void uv_signals_init(void) { static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { - /* Compare signums first so all watchers with the same signnum end up */ - /* adjacent. */ + /* Compare signums first so all watchers with the same signnum end up + * adjacent. */ if (w1->signum < w2->signum) return -1; if (w1->signum > w2->signum) return 1; - /* Sort by loop pointer, so we can easily look up the first item after */ - /* { .signum = x, .loop = NULL } */ + /* Sort by loop pointer, so we can easily look up the first item after + * { .signum = x, .loop = NULL }. */ if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1; if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1; @@ -90,7 +90,7 @@ int uv__signal_dispatch(int signum) { unsigned long previous = InterlockedExchange( (volatile LONG*) &handle->pending_signum, signum); - if (handle->flags & UV__SIGNAL_ONE_SHOT_DISPATCHED) + if (handle->flags & UV_SIGNAL_ONE_SHOT_DISPATCHED) continue; if (!previous) { @@ -98,8 +98,8 @@ int uv__signal_dispatch(int signum) { } dispatched = 1; - if (handle->flags & UV__SIGNAL_ONE_SHOT) - handle->flags |= UV__SIGNAL_ONE_SHOT_DISPATCHED; + if (handle->flags & UV_SIGNAL_ONE_SHOT) + handle->flags |= UV_SIGNAL_ONE_SHOT_DISPATCHED; } LeaveCriticalSection(&uv__signal_lock); @@ -118,10 +118,10 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) { case CTRL_CLOSE_EVENT: if (uv__signal_dispatch(SIGHUP)) { - /* Windows will terminate the process after the control handler */ - /* returns. After that it will just terminate our process. Therefore */ - /* block the signal handler so the main loop has some time to pick */ - /* up the signal and do something for a few seconds. */ + /* Windows will terminate the process after the control handler + * returns. After that it will just terminate our process. Therefore + * block the signal handler so the main loop has some time to pick up + * the signal and do something for a few seconds. */ Sleep(INFINITE); return TRUE; } @@ -129,8 +129,8 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) { case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: - /* These signals are only sent to services. Services have their own */ - /* notification mechanism, so there's no point in handling these. */ + /* These signals are only sent to services. Services have their own + * notification mechanism, so there's no point in handling these. */ default: /* We don't handle these. */ @@ -190,13 +190,13 @@ int uv__signal_start(uv_signal_t* handle, int signum, int oneshot) { /* Test for invalid signal values. */ - if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG)) + if (signum <= 0 || signum >= NSIG) return UV_EINVAL; - /* Short circuit: if the signal watcher is already watching {signum} don't */ - /* go through the process of deregistering and registering the handler. */ - /* Additionally, this avoids pending signals getting lost in the (small) */ - /* time frame that handle->signum == 0. */ + /* Short circuit: if the signal watcher is already watching {signum} don't go + * through the process of deregistering and registering the handler. + * Additionally, this avoids pending signals getting lost in the (small) time + * frame that handle->signum == 0. */ if (signum == handle->signum) { handle->signal_cb = signal_cb; return 0; @@ -213,7 +213,7 @@ int uv__signal_start(uv_signal_t* handle, handle->signum = signum; if (oneshot) - handle->flags |= UV__SIGNAL_ONE_SHOT; + handle->flags |= UV_SIGNAL_ONE_SHOT; RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle); @@ -237,16 +237,16 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, (volatile LONG*) &handle->pending_signum, 0); assert(dispatched_signum != 0); - /* Check if the pending signal equals the signum that we are watching for. */ - /* These can get out of sync when the handler is stopped and restarted */ - /* while the signal_req is pending. */ + /* Check if the pending signal equals the signum that we are watching for. + * These can get out of sync when the handler is stopped and restarted while + * the signal_req is pending. */ if (dispatched_signum == handle->signum) handle->signal_cb(handle, dispatched_signum); - if (handle->flags & UV__SIGNAL_ONE_SHOT) + if (handle->flags & UV_SIGNAL_ONE_SHOT) uv_signal_stop(handle); - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { /* When it is closing, it must be stopped at this point. */ assert(handle->signum == 0); uv_want_endgame(loop, (uv_handle_t*) handle); @@ -265,7 +265,7 @@ void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) { void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); + assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); assert(handle->signum == 0); diff --git a/Utilities/cmlibuv/src/win/stream.c b/Utilities/cmlibuv/src/win/stream.c index 13cbfdc..7656627 100644 --- a/Utilities/cmlibuv/src/win/stream.c +++ b/Utilities/cmlibuv/src/win/stream.c @@ -105,12 +105,10 @@ int uv_read_stop(uv_stream_t* handle) { err = 0; if (handle->type == UV_TTY) { err = uv_tty_read_stop((uv_tty_t*) handle); + } else if (handle->type == UV_NAMED_PIPE) { + uv__pipe_read_stop((uv_pipe_t*) handle); } else { - if (handle->type == UV_NAMED_PIPE) { - uv__pipe_stop_read((uv_pipe_t*) handle); - } else { - handle->flags &= ~UV_HANDLE_READING; - } + handle->flags &= ~UV_HANDLE_READING; DECREASE_ACTIVE_COUNT(handle->loop, handle); } @@ -136,7 +134,8 @@ int uv_write(uv_write_t* req, err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb); break; case UV_NAMED_PIPE: - err = uv_pipe_write(loop, req, (uv_pipe_t*) handle, bufs, nbufs, cb); + err = uv__pipe_write( + loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb); break; case UV_TTY: err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb); @@ -158,25 +157,18 @@ int uv_write2(uv_write_t* req, uv_loop_t* loop = handle->loop; int err; - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; + if (send_handle == NULL) { + return uv_write(req, handle, bufs, nbufs, cb); } - err = ERROR_INVALID_PARAMETER; - switch (handle->type) { - case UV_NAMED_PIPE: - err = uv_pipe_write2(loop, - req, - (uv_pipe_t*) handle, - bufs, - nbufs, - send_handle, - cb); - break; - default: - assert(0); + if (handle->type != UV_NAMED_PIPE || !((uv_pipe_t*) handle)->ipc) { + return UV_EINVAL; + } else if (!(handle->flags & UV_HANDLE_WRITABLE)) { + return UV_EPIPE; } + err = uv__pipe_write( + loop, req, (uv_pipe_t*) handle, bufs, nbufs, send_handle, cb); return uv_translate_sys_error(err); } @@ -184,7 +176,7 @@ int uv_write2(uv_write_t* req, int uv_try_write(uv_stream_t* stream, const uv_buf_t bufs[], unsigned int nbufs) { - if (stream->flags & UV__HANDLE_CLOSING) + if (stream->flags & UV_HANDLE_CLOSING) return UV_EBADF; if (!(stream->flags & UV_HANDLE_WRITABLE)) return UV_EPIPE; diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c index 39c1ff0..3ce5548 100644 --- a/Utilities/cmlibuv/src/win/tcp.c +++ b/Utilities/cmlibuv/src/win/tcp.c @@ -99,8 +99,8 @@ static int uv_tcp_set_socket(uv_loop_t* loop, if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) return GetLastError(); - /* Associate it with the I/O completion port. */ - /* Use uv_handle_t pointer as completion key. */ + /* Associate it with the I/O completion port. Use uv_handle_t pointer as + * completion key. */ if (CreateIoCompletionPort((HANDLE)socket, loop->iocp, (ULONG_PTR)socket, @@ -118,15 +118,12 @@ static int uv_tcp_set_socket(uv_loop_t* loop, non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4; } - if (pSetFileCompletionNotificationModes && - !(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) { - if (pSetFileCompletionNotificationModes((HANDLE) socket, - FILE_SKIP_SET_EVENT_ON_HANDLE | - FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { - handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; - } else if (GetLastError() != ERROR_INVALID_FUNCTION) { + if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) { + UCHAR sfcnm_flags = + FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS; + if (!SetFileCompletionNotificationModes((HANDLE) socket, sfcnm_flags)) return GetLastError(); - } + handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; } if (handle->flags & UV_HANDLE_TCP_NODELAY) { @@ -220,7 +217,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req); err = 0; - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { err = ERROR_OPERATION_ABORTED; } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) { err = WSAGetLastError(); @@ -236,7 +233,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { return; } - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); @@ -326,9 +323,9 @@ static int uv_tcp_try_bind(uv_tcp_t* handle, on = (flags & UV_TCP_IPV6ONLY) != 0; - /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ - /* available, or when run on XP/2003 which have no support for dualstack */ - /* sockets. For now we're silently ignoring the error. */ + /* TODO: how to handle errors? This may fail if there is no ipv4 stack + * available, or when run on XP/2003 which have no support for dualstack + * sockets. For now we're silently ignoring the error. */ setsockopt(handle->socket, IPPROTO_IPV6, IPV6_V6ONLY, @@ -626,9 +623,9 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { uv_tcp_queue_accept(handle, req); } - /* Initialize other unused requests too, because uv_tcp_endgame */ - /* doesn't know how how many requests were initialized, so it will */ - /* try to clean up {uv_simultaneous_server_accepts} requests. */ + /* Initialize other unused requests too, because uv_tcp_endgame doesn't + * know how many requests were initialized, so it will try to clean up + * {uv_simultaneous_server_accepts} requests. */ for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) { req = &handle->tcp.serv.accept_reqs[i]; UV_REQ_INIT(req, UV_ACCEPT); @@ -683,7 +680,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { req->next_pending = NULL; req->accept_socket = INVALID_SOCKET; - if (!(server->flags & UV__HANDLE_CLOSING)) { + if (!(server->flags & UV_HANDLE_CLOSING)) { /* Check if we're in a middle of changing the number of pending accepts. */ if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) { uv_tcp_queue_accept(server, req); @@ -721,8 +718,8 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, handle->alloc_cb = alloc_cb; INCREASE_ACTIVE_COUNT(loop, handle); - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ + /* If reading was stopped and then started again, there could still be a read + * request pending. */ if (!(handle->flags & UV_HANDLE_READ_PENDING)) { if (handle->flags & UV_HANDLE_EMULATE_IOCP && !handle->read_req.event_handle) { @@ -948,6 +945,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req) { DWORD bytes, flags, err; uv_buf_t buf; + int count; assert(handle->type == UV_TCP); @@ -965,8 +963,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, err = GET_REQ_SOCK_ERROR(req); if (err == WSAECONNABORTED) { - /* - * Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix. + /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix. */ err = WSAECONNRESET; } @@ -1003,7 +1000,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, } /* Do nonblocking reads until the buffer is empty */ - while (handle->flags & UV_HANDLE_READING) { + count = 32; + while ((handle->flags & UV_HANDLE_READING) && (count-- > 0)) { buf = uv_buf_init(NULL, 0); handle->alloc_cb((uv_handle_t*) handle, 65536, &buf); if (buf.base == NULL || buf.len == 0) { @@ -1046,8 +1044,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, DECREASE_ACTIVE_COUNT(loop, handle); if (err == WSAECONNABORTED) { - /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with */ - /* Unix. */ + /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with + * Unix. */ err = WSAECONNRESET; } @@ -1119,10 +1117,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, assert(handle->type == UV_TCP); - /* If handle->accepted_socket is not a valid socket, then */ - /* uv_queue_accept must have failed. This is a serious error. We stop */ - /* accepting connections and report this error to the connection */ - /* callback. */ + /* If handle->accepted_socket is not a valid socket, then uv_queue_accept + * must have failed. This is a serious error. We stop accepting connections + * and report this error to the connection callback. */ if (req->accept_socket == INVALID_SOCKET) { if (handle->flags & UV_HANDLE_LISTENING) { handle->flags &= ~UV_HANDLE_LISTENING; @@ -1147,9 +1144,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, handle->stream.serv.connection_cb((uv_stream_t*)handle, 0); } } else { - /* Error related to accepted socket is ignored because the server */ - /* socket may still be healthy. If the server socket is broken */ - /* uv_queue_accept will detect it. */ + /* Error related to accepted socket is ignored because the server socket + * may still be healthy. If the server socket is broken uv_queue_accept + * will detect it. */ closesocket(req->accept_socket); req->accept_socket = INVALID_SOCKET; if (handle->flags & UV_HANDLE_LISTENING) { @@ -1171,7 +1168,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, err = 0; if (REQ_SUCCESS(req)) { - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { /* use UV_ECANCELED for consistency with Unix */ err = ERROR_OPERATION_ABORTED; } else if (setsockopt(handle->socket, @@ -1194,40 +1191,76 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, } -int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, - int tcp_connection) { +int uv__tcp_xfer_export(uv_tcp_t* handle, + int target_pid, + uv__ipc_socket_xfer_type_t* xfer_type, + uv__ipc_socket_xfer_info_t* xfer_info) { + if (handle->flags & UV_HANDLE_CONNECTION) { + *xfer_type = UV__IPC_SOCKET_XFER_TCP_CONNECTION; + } else { + *xfer_type = UV__IPC_SOCKET_XFER_TCP_SERVER; + /* We're about to share the socket with another process. Because this is a + * listening socket, we assume that the other process will be accepting + * connections on it. Thus, before sharing the socket with another process, + * we call listen here in the parent process. */ + if (!(handle->flags & UV_HANDLE_LISTENING)) { + if (!(handle->flags & UV_HANDLE_BOUND)) { + return ERROR_NOT_SUPPORTED; + } + if (handle->delayed_error == 0 && + listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { + handle->delayed_error = WSAGetLastError(); + } + } + } + + if (WSADuplicateSocketW(handle->socket, target_pid, &xfer_info->socket_info)) + return WSAGetLastError(); + xfer_info->delayed_error = handle->delayed_error; + + /* Mark the local copy of the handle as 'shared' so we behave in a way that's + * friendly to the process(es) that we share the socket with. */ + handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET; + + return 0; +} + + +int uv__tcp_xfer_import(uv_tcp_t* tcp, + uv__ipc_socket_xfer_type_t xfer_type, + uv__ipc_socket_xfer_info_t* xfer_info) { int err; - SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - &socket_info_ex->socket_info, - 0, - WSA_FLAG_OVERLAPPED); + SOCKET socket; + + assert(xfer_type == UV__IPC_SOCKET_XFER_TCP_SERVER || + xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION); + + socket = WSASocketW(FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + &xfer_info->socket_info, + 0, + WSA_FLAG_OVERLAPPED); if (socket == INVALID_SOCKET) { return WSAGetLastError(); } - err = uv_tcp_set_socket(tcp->loop, - tcp, - socket, - socket_info_ex->socket_info.iAddressFamily, - 1); + err = uv_tcp_set_socket( + tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1); if (err) { closesocket(socket); return err; } - if (tcp_connection) { + tcp->delayed_error = xfer_info->delayed_error; + tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET; + + if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) { uv_connection_init((uv_stream_t*)tcp); tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } - tcp->flags |= UV_HANDLE_BOUND; - tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET; - - tcp->delayed_error = socket_info_ex->delayed_error; - tcp->loop->active_tcp_streams++; return 0; } @@ -1273,39 +1306,6 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { } -int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, - LPWSAPROTOCOL_INFOW protocol_info) { - if (!(handle->flags & UV_HANDLE_CONNECTION)) { - /* - * We're about to share the socket with another process. Because - * this is a listening socket, we assume that the other process will - * be accepting connections on it. So, before sharing the socket - * with another process, we call listen here in the parent process. - */ - - if (!(handle->flags & UV_HANDLE_LISTENING)) { - if (!(handle->flags & UV_HANDLE_BOUND)) { - return ERROR_INVALID_PARAMETER; - } - - if (!(handle->delayed_error)) { - if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { - handle->delayed_error = WSAGetLastError(); - } - } - } - } - - if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) { - return WSAGetLastError(); - } - - handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET; - - return 0; -} - - int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { if (handle->flags & UV_HANDLE_CONNECTION) { return UV_EINVAL; @@ -1346,8 +1346,8 @@ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) { non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : uv_tcp_non_ifs_lsp_ipv4; - /* If there are non-ifs LSPs then try to obtain a base handle for the */ - /* socket. This will always fail on Windows XP/3k. */ + /* If there are non-ifs LSPs then try to obtain a base handle for the socket. + * This will always fail on Windows XP/3k. */ if (non_ifs_lsp) { DWORD bytes; if (WSAIoctl(socket, @@ -1379,38 +1379,37 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { int close_socket = 1; if (tcp->flags & UV_HANDLE_READ_PENDING) { - /* In order for winsock to do a graceful close there must not be any */ - /* any pending reads, or the socket must be shut down for writing */ + /* In order for winsock to do a graceful close there must not be any any + * pending reads, or the socket must be shut down for writing */ if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) { /* Just do shutdown on non-shared sockets, which ensures graceful close. */ shutdown(tcp->socket, SD_SEND); } else if (uv_tcp_try_cancel_io(tcp) == 0) { - /* In case of a shared socket, we try to cancel all outstanding I/O, */ - /* If that works, don't close the socket yet - wait for the read req to */ - /* return and close the socket in uv_tcp_endgame. */ + /* In case of a shared socket, we try to cancel all outstanding I/O,. If + * that works, don't close the socket yet - wait for the read req to + * return and close the socket in uv_tcp_endgame. */ close_socket = 0; } else { - /* When cancelling isn't possible - which could happen when an LSP is */ - /* present on an old Windows version, we will have to close the socket */ - /* with a read pending. That is not nice because trailing sent bytes */ - /* may not make it to the other side. */ + /* When cancelling isn't possible - which could happen when an LSP is + * present on an old Windows version, we will have to close the socket + * with a read pending. That is not nice because trailing sent bytes may + * not make it to the other side. */ } } else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) && tcp->tcp.serv.accept_reqs != NULL) { - /* Under normal circumstances closesocket() will ensure that all pending */ - /* accept reqs are canceled. However, when the socket is shared the */ - /* presence of another reference to the socket in another process will */ - /* keep the accept reqs going, so we have to ensure that these are */ - /* canceled. */ + /* Under normal circumstances closesocket() will ensure that all pending + * accept reqs are canceled. However, when the socket is shared the + * presence of another reference to the socket in another process will keep + * the accept reqs going, so we have to ensure that these are canceled. */ if (uv_tcp_try_cancel_io(tcp) != 0) { - /* When cancellation is not possible, there is another option: we can */ - /* close the incoming sockets, which will also cancel the accept */ - /* operations. However this is not cool because we might inadvertently */ - /* close a socket that just accepted a new connection, which will */ - /* cause the connection to be aborted. */ + /* When cancellation is not possible, there is another option: we can + * close the incoming sockets, which will also cancel the accept + * operations. However this is not cool because we might inadvertently + * close a socket that just accepted a new connection, which will cause + * the connection to be aborted. */ unsigned int i; for (i = 0; i < uv_simultaneous_server_accepts; i++) { uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i]; diff --git a/Utilities/cmlibuv/src/win/thread.c b/Utilities/cmlibuv/src/win/thread.c index 9eaad77..fd4b7c9 100644 --- a/Utilities/cmlibuv/src/win/thread.c +++ b/Utilities/cmlibuv/src/win/thread.c @@ -23,29 +23,15 @@ #include <limits.h> #include <stdlib.h> +#if defined(__MINGW64_VERSION_MAJOR) +/* MemoryBarrier expands to __mm_mfence in some cases (x86+sse2), which may + * require this header in some versions of mingw64. */ +#include <intrin.h> +#endif + #include "uv.h" #include "internal.h" - -#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL) - -static int uv_cond_fallback_init(uv_cond_t* cond); -static void uv_cond_fallback_destroy(uv_cond_t* cond); -static void uv_cond_fallback_signal(uv_cond_t* cond); -static void uv_cond_fallback_broadcast(uv_cond_t* cond); -static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex); -static int uv_cond_fallback_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout); - -static int uv_cond_condvar_init(uv_cond_t* cond); -static void uv_cond_condvar_destroy(uv_cond_t* cond); -static void uv_cond_condvar_signal(uv_cond_t* cond); -static void uv_cond_condvar_broadcast(uv_cond_t* cond); -static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex); -static int uv_cond_condvar_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout); - - static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) { DWORD result; HANDLE existing_event, created_event; @@ -69,8 +55,8 @@ static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) { guard->ran = 1; } else { - /* We lost the race. Destroy the event we created and wait for the */ - /* existing one to become signaled. */ + /* We lost the race. Destroy the event we created and wait for the existing + * one to become signaled. */ CloseHandle(created_event); result = WaitForSingleObject(existing_event, INFINITE); assert(result == WAIT_OBJECT_0); @@ -138,7 +124,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { ctx->arg = arg; /* Create the thread in suspended state so we have a chance to pass - * its own creation handle to it */ + * its own creation handle to it */ thread = (HANDLE) _beginthreadex(NULL, 0, uv__thread_start, @@ -377,220 +363,35 @@ int uv_sem_trywait(uv_sem_t* sem) { } -/* This condition variable implementation is based on the SetEvent solution - * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html - * We could not use the SignalObjectAndWait solution (section 3.4) because - * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and - * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs. - */ - -static int uv_cond_fallback_init(uv_cond_t* cond) { - int err; - - /* Initialize the count to 0. */ - cond->fallback.waiters_count = 0; - - InitializeCriticalSection(&cond->fallback.waiters_count_lock); - - /* Create an auto-reset event. */ - cond->fallback.signal_event = CreateEvent(NULL, /* no security */ - FALSE, /* auto-reset event */ - FALSE, /* non-signaled initially */ - NULL); /* unnamed */ - if (!cond->fallback.signal_event) { - err = GetLastError(); - goto error2; - } - - /* Create a manual-reset event. */ - cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */ - TRUE, /* manual-reset */ - FALSE, /* non-signaled */ - NULL); /* unnamed */ - if (!cond->fallback.broadcast_event) { - err = GetLastError(); - goto error; - } - - return 0; - -error: - CloseHandle(cond->fallback.signal_event); -error2: - DeleteCriticalSection(&cond->fallback.waiters_count_lock); - return uv_translate_sys_error(err); -} - - -static int uv_cond_condvar_init(uv_cond_t* cond) { - pInitializeConditionVariable(&cond->cond_var); - return 0; -} - - int uv_cond_init(uv_cond_t* cond) { - uv__once_init(); - - if (HAVE_CONDVAR_API()) - return uv_cond_condvar_init(cond); - else - return uv_cond_fallback_init(cond); -} - - -static void uv_cond_fallback_destroy(uv_cond_t* cond) { - if (!CloseHandle(cond->fallback.broadcast_event)) - abort(); - if (!CloseHandle(cond->fallback.signal_event)) - abort(); - DeleteCriticalSection(&cond->fallback.waiters_count_lock); -} - - -static void uv_cond_condvar_destroy(uv_cond_t* cond) { - /* nothing to do */ + InitializeConditionVariable(&cond->cond_var); + return 0; } void uv_cond_destroy(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_destroy(cond); - else - uv_cond_fallback_destroy(cond); -} - - -static void uv_cond_fallback_signal(uv_cond_t* cond) { - int have_waiters; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - have_waiters = cond->fallback.waiters_count > 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - if (have_waiters) - SetEvent(cond->fallback.signal_event); -} - - -static void uv_cond_condvar_signal(uv_cond_t* cond) { - pWakeConditionVariable(&cond->cond_var); + /* nothing to do */ + (void) &cond; } void uv_cond_signal(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_signal(cond); - else - uv_cond_fallback_signal(cond); -} - - -static void uv_cond_fallback_broadcast(uv_cond_t* cond) { - int have_waiters; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - have_waiters = cond->fallback.waiters_count > 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - if (have_waiters) - SetEvent(cond->fallback.broadcast_event); -} - - -static void uv_cond_condvar_broadcast(uv_cond_t* cond) { - pWakeAllConditionVariable(&cond->cond_var); + WakeConditionVariable(&cond->cond_var); } void uv_cond_broadcast(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_broadcast(cond); - else - uv_cond_fallback_broadcast(cond); -} - - -static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, - DWORD dwMilliseconds) { - DWORD result; - int last_waiter; - HANDLE handles[2] = { - cond->fallback.signal_event, - cond->fallback.broadcast_event - }; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - cond->fallback.waiters_count++; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - /* It's ok to release the <mutex> here since Win32 manual-reset events */ - /* maintain state when used with <SetEvent>. This avoids the "lost wakeup" */ - /* bug. */ - uv_mutex_unlock(mutex); - - /* Wait for either event to become signaled due to <uv_cond_signal> being */ - /* called or <uv_cond_broadcast> being called. */ - result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds); - - EnterCriticalSection(&cond->fallback.waiters_count_lock); - cond->fallback.waiters_count--; - last_waiter = result == WAIT_OBJECT_0 + 1 - && cond->fallback.waiters_count == 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - /* Some thread called <pthread_cond_broadcast>. */ - if (last_waiter) { - /* We're the last waiter to be notified or to stop waiting, so reset the */ - /* the manual-reset event. */ - ResetEvent(cond->fallback.broadcast_event); - } - - /* Reacquire the <mutex>. */ - uv_mutex_lock(mutex); - - if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1) - return 0; - - if (result == WAIT_TIMEOUT) - return UV_ETIMEDOUT; - - abort(); - return -1; /* Satisfy the compiler. */ -} - - -static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (uv_cond_wait_helper(cond, mutex, INFINITE)) - abort(); -} - - -static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE)) - abort(); + WakeAllConditionVariable(&cond->cond_var); } void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_wait(cond, mutex); - else - uv_cond_fallback_wait(cond, mutex); -} - - -static int uv_cond_fallback_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout) { - return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6)); + if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE)) + abort(); } - -static int uv_cond_condvar_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout) { - if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6))) +int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { + if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6))) return 0; if (GetLastError() != ERROR_TIMEOUT) abort(); @@ -598,15 +399,6 @@ static int uv_cond_condvar_timedwait(uv_cond_t* cond, } -int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, - uint64_t timeout) { - if (HAVE_CONDVAR_API()) - return uv_cond_condvar_timedwait(cond, mutex, timeout); - else - return uv_cond_fallback_timedwait(cond, mutex, timeout); -} - - int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { int err; diff --git a/Utilities/cmlibuv/src/win/timer.c b/Utilities/cmlibuv/src/win/timer.c deleted file mode 100644 index 7e006fe..0000000 --- a/Utilities/cmlibuv/src/win/timer.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include <assert.h> -#include <limits.h> - -#include "uv.h" -#include "internal.h" -#include "tree.h" -#include "handle-inl.h" - - -/* The number of milliseconds in one second. */ -#define UV__MILLISEC 1000 - - -void uv_update_time(uv_loop_t* loop) { - uint64_t new_time = uv__hrtime(UV__MILLISEC); - assert(new_time >= loop->time); - loop->time = new_time; -} - - -static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) { - if (a->due < b->due) - return -1; - if (a->due > b->due) - return 1; - /* - * compare start_id when both has the same due. start_id is - * allocated with loop->timer_counter in uv_timer_start(). - */ - if (a->start_id < b->start_id) - return -1; - if (a->start_id > b->start_id) - return 1; - return 0; -} - - -RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare) - - -int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_TIMER); - handle->timer_cb = NULL; - handle->repeat = 0; - - return 0; -} - - -void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -static uint64_t get_clamped_due_time(uint64_t loop_time, uint64_t timeout) { - uint64_t clamped_timeout; - - clamped_timeout = loop_time + timeout; - if (clamped_timeout < timeout) - clamped_timeout = (uint64_t) -1; - - return clamped_timeout; -} - - -int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout, - uint64_t repeat) { - uv_loop_t* loop = handle->loop; - uv_timer_t* old; - - if (timer_cb == NULL) - return UV_EINVAL; - - if (uv__is_active(handle)) - uv_timer_stop(handle); - - handle->timer_cb = timer_cb; - handle->due = get_clamped_due_time(loop->time, timeout); - handle->repeat = repeat; - uv__handle_start(handle); - - /* start_id is the second index to be compared in uv__timer_cmp() */ - handle->start_id = handle->loop->timer_counter++; - - old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle); - assert(old == NULL); - - return 0; -} - - -int uv_timer_stop(uv_timer_t* handle) { - uv_loop_t* loop = handle->loop; - - if (!uv__is_active(handle)) - return 0; - - RB_REMOVE(uv_timer_tree_s, &loop->timers, handle); - uv__handle_stop(handle); - - return 0; -} - - -int uv_timer_again(uv_timer_t* handle) { - /* If timer_cb is NULL that means that the timer was never started. */ - if (!handle->timer_cb) { - return UV_EINVAL; - } - - if (handle->repeat) { - uv_timer_stop(handle); - uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat); - } - - return 0; -} - - -void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) { - assert(handle->type == UV_TIMER); - handle->repeat = repeat; -} - - -uint64_t uv_timer_get_repeat(const uv_timer_t* handle) { - assert(handle->type == UV_TIMER); - return handle->repeat; -} - - -DWORD uv__next_timeout(const uv_loop_t* loop) { - uv_timer_t* timer; - int64_t delta; - - /* Check if there are any running timers - * Need to cast away const first, since RB_MIN doesn't know what we are - * going to do with this return value, it can't be marked const - */ - timer = RB_MIN(uv_timer_tree_s, &((uv_loop_t*)loop)->timers); - if (timer) { - delta = timer->due - loop->time; - if (delta >= UINT_MAX - 1) { - /* A timeout value of UINT_MAX means infinite, so that's no good. */ - return UINT_MAX - 1; - } else if (delta < 0) { - /* Negative timeout values are not allowed */ - return 0; - } else { - return (DWORD)delta; - } - } else { - /* No timers */ - return INFINITE; - } -} - - -void uv_process_timers(uv_loop_t* loop) { - uv_timer_t* timer; - - /* Call timer callbacks */ - for (timer = RB_MIN(uv_timer_tree_s, &loop->timers); - timer != NULL && timer->due <= loop->time; - timer = RB_MIN(uv_timer_tree_s, &loop->timers)) { - - uv_timer_stop(timer); - uv_timer_again(timer); - timer->timer_cb((uv_timer_t*) timer); - } -} diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c index ecf7bc9..f38e9a8 100644 --- a/Utilities/cmlibuv/src/win/tty.c +++ b/Utilities/cmlibuv/src/win/tty.c @@ -25,7 +25,7 @@ #include <stdlib.h> #if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" +# include "uv/stdint-msvc2008.h" #else # include <stdint.h> #endif @@ -164,7 +164,7 @@ void uv_console_init(void) { OPEN_EXISTING, 0, 0); - if (uv__tty_console_handle != NULL) { + if (uv__tty_console_handle != INVALID_HANDLE_VALUE) { QueueUserWorkItem(uv__tty_console_resize_message_loop_thread, NULL, WT_EXECUTELONGFUNCTION); @@ -172,9 +172,12 @@ void uv_console_init(void) { } -int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { +int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) { + BOOL readable; + DWORD NumberOfEvents; HANDLE handle; CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; + (void)unused; uv__once_init(); handle = (HANDLE) uv__get_osfhandle(fd); @@ -199,14 +202,15 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { fd = -1; } + readable = GetNumberOfConsoleInputEvents(handle, &NumberOfEvents); if (!readable) { /* Obtain the screen buffer info with the output handle. */ if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) { return uv_translate_sys_error(GetLastError()); } - /* Obtain the the tty_output_lock because the virtual window state is */ - /* shared between all uv_tty_t handles. */ + /* Obtain the tty_output_lock because the virtual window state is shared + * between all uv_tty_t handles. */ uv_sem_wait(&uv_tty_output_lock); if (uv__vterm_state == UV_UNCHECKED) @@ -356,6 +360,8 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { } } else { was_reading = 0; + alloc_cb = NULL; + read_cb = NULL; } uv_sem_wait(&uv_tty_output_lock); @@ -382,12 +388,6 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { } -int uv_is_tty(uv_file file) { - DWORD result; - return GetConsoleMode((HANDLE) _get_osfhandle(file), &result) != 0; -} - - int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { CONSOLE_SCREEN_BUFFER_INFO info; @@ -484,8 +484,8 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { bytes = MAX_INPUT_BUFFER_LENGTH; } - /* At last, unicode! */ - /* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */ + /* At last, unicode! One utf-16 codeunit never takes more than 3 utf-8 + * codeunits to encode. */ chars = bytes / 3; status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS); @@ -620,10 +620,10 @@ static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl, } switch (code) { - /* These mappings are the same as Cygwin's. Unmodified and alt-modified */ - /* keypad keys comply with linux console, modifiers comply with xterm */ - /* modifier usage. F1..f12 and shift-f1..f10 comply with linux console, */ - /* f6..f12 with and without modifiers comply with rxvt. */ + /* These mappings are the same as Cygwin's. Unmodified and alt-modified + * keypad keys comply with linux console, modifiers comply with xterm + * modifier usage. F1. f12 and shift-f1. f10 comply with linux console, f6. + * f12 with and without modifiers comply with rxvt. */ VK_CASE(VK_INSERT, "[2~", "[2;2~", "[2;5~", "[2;6~") VK_CASE(VK_END, "[4~", "[4;2~", "[4;5~", "[4;6~") VK_CASE(VK_DOWN, "[B", "[1;2B", "[1;5B", "[1;6B") @@ -706,8 +706,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, goto out; } - /* Windows sends a lot of events that we're not interested in, so buf */ - /* will be allocated on demand, when there's actually something to emit. */ + /* Windows sends a lot of events that we're not interested in, so buf will be + * allocated on demand, when there's actually something to emit. */ buf = uv_null_buf_; buf_used = 0; @@ -733,16 +733,17 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, continue; } - /* Ignore keyup events, unless the left alt key was held and a valid */ - /* unicode character was emitted. */ - if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) || - KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) { + /* Ignore keyup events, unless the left alt key was held and a valid + * unicode character was emitted. */ + if (!KEV.bKeyDown && + KEV.wVirtualKeyCode != VK_MENU && + KEV.uChar.UnicodeChar != 0) { continue; } - /* Ignore keypresses to numpad number keys if the left alt is held */ - /* because the user is composing a character, or windows simulating */ - /* this. */ + /* Ignore keypresses to numpad number keys if the left alt is held + * because the user is composing a character, or windows simulating this. + */ if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) && !(KEV.dwControlKeyState & ENHANCED_KEY) && (KEV.wVirtualKeyCode == VK_INSERT || @@ -779,8 +780,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, continue; } - /* Prefix with \u033 if alt was held, but alt was not used as part */ - /* a compose sequence. */ + /* Prefix with \u033 if alt was held, but alt was not used as part a + * compose sequence. */ if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) && !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) { @@ -793,8 +794,9 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, if (KEV.uChar.UnicodeChar >= 0xDC00 && KEV.uChar.UnicodeChar < 0xE000) { /* UTF-16 surrogate pair */ - WCHAR utf16_buffer[2] = { handle->tty.rd.last_utf16_high_surrogate, - KEV.uChar.UnicodeChar}; + WCHAR utf16_buffer[2]; + utf16_buffer[0] = handle->tty.rd.last_utf16_high_surrogate; + utf16_buffer[1] = KEV.uChar.UnicodeChar; char_len = WideCharToMultiByte(CP_UTF8, 0, utf16_buffer, @@ -818,8 +820,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, /* Whatever happened, the last character wasn't a high surrogate. */ handle->tty.rd.last_utf16_high_surrogate = 0; - /* If the utf16 character(s) couldn't be converted something must */ - /* be wrong. */ + /* If the utf16 character(s) couldn't be converted something must be + * wrong. */ if (!char_len) { handle->flags &= ~UV_HANDLE_READING; DECREASE_ACTIVE_COUNT(loop, handle); @@ -943,21 +945,15 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle, handle->read_cb((uv_stream_t*) handle, uv_translate_sys_error(GET_REQ_ERROR(req)), &buf); - } else { - /* The read was cancelled, or whatever we don't care */ - handle->read_cb((uv_stream_t*) handle, 0, &buf); } - } else { - if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) { - /* Read successful */ - /* TODO: read unicode, convert to utf-8 */ + if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING) && + req->u.io.overlapped.InternalHigh != 0) { + /* Read successful. TODO: read unicode, convert to utf-8 */ DWORD bytes = req->u.io.overlapped.InternalHigh; handle->read_cb((uv_stream_t*) handle, bytes, &buf); - } else { - handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING; - handle->read_cb((uv_stream_t*) handle, 0, &buf); } + handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING; } /* Wait for more input events. */ @@ -975,9 +971,9 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, assert(handle->type == UV_TTY); assert(handle->flags & UV_HANDLE_TTY_READABLE); - /* If the read_line_buffer member is zero, it must have been an raw read. */ - /* Otherwise it was a line-buffered read. */ - /* FIXME: This is quite obscure. Use a flag or something. */ + /* If the read_line_buffer member is zero, it must have been an raw read. + * Otherwise it was a line-buffered read. FIXME: This is quite obscure. Use a + * flag or something. */ if (handle->tty.rd.read_line_buffer.len == 0) { uv_process_tty_read_raw_req(loop, handle, req); } else { @@ -999,14 +995,14 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, handle->read_cb = read_cb; handle->alloc_cb = alloc_cb; - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ + /* If reading was stopped and then started again, there could still be a read + * request pending. */ if (handle->flags & UV_HANDLE_READ_PENDING) { return 0; } - /* Maybe the user stopped reading half-way while processing key events. */ - /* Short-circuit if this could be the case. */ + /* Maybe the user stopped reading half-way while processing key events. + * Short-circuit if this could be the case. */ if (handle->tty.rd.last_key_len > 0) { SET_REQ_SUCCESS(&handle->read_req); uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req); @@ -1033,9 +1029,10 @@ int uv_tty_read_stop(uv_tty_t* handle) { return 0; if (handle->flags & UV_HANDLE_TTY_RAW) { - /* Cancel raw read */ - /* Write some bullshit event to force the console wait to return. */ + /* Cancel raw read. Write some bullshit event to force the console wait to + * return. */ memset(&record, 0, sizeof record); + record.EventType = FOCUS_EVENT; if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) { return GetLastError(); } @@ -1116,8 +1113,8 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) { uv_tty_virtual_offset = info->dwCursorPosition.Y; } else if (uv_tty_virtual_offset < info->dwCursorPosition.Y - uv_tty_virtual_height + 1) { - /* If suddenly find the cursor outside of the virtual window, it must */ - /* have somehow scrolled. Update the virtual window offset. */ + /* If suddenly find the cursor outside of the virtual window, it must have + * somehow scrolled. Update the virtual window offset. */ uv_tty_virtual_offset = info->dwCursorPosition.Y - uv_tty_virtual_height + 1; } @@ -1304,8 +1301,8 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, x2 = 0; x2r = 1; } else { - /* Clear to end of row. We pretend the console is 65536 characters wide, */ - /* uv_tty_make_real_coord will clip it to the actual console width. */ + /* Clear to end of row. We pretend the console is 65536 characters wide, + * uv_tty_make_real_coord will clip it to the actual console width. */ x2 = 0xffff; x2r = 0; } @@ -1613,8 +1610,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, const uv_buf_t bufs[], unsigned int nbufs, DWORD* error) { - /* We can only write 8k characters at a time. Windows can't handle */ - /* much more characters in a single console write anyway. */ + /* We can only write 8k characters at a time. Windows can't handle much more + * characters in a single console write anyway. */ WCHAR utf16_buf[MAX_CONSOLE_CHAR]; WCHAR* utf16_buffer; DWORD utf16_buf_used = 0; @@ -1650,9 +1647,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, unsigned char previous_eol = handle->tty.wr.previous_eol; unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state; - /* Store the error here. If we encounter an error, stop trying to do i/o */ - /* but keep parsing the buffer so we leave the parser in a consistent */ - /* state. */ + /* Store the error here. If we encounter an error, stop trying to do i/o but + * keep parsing the buffer so we leave the parser in a consistent state. */ *error = ERROR_SUCCESS; utf16_buffer = utf16_buf; @@ -1700,9 +1696,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle, for (j = 0; j < buf.len; j++) { unsigned char c = buf.base[j]; - /* Run the character through the utf8 decoder We happily accept non */ - /* shortest form encodings and invalid code points - there's no real */ - /* harm that can be done. */ + /* Run the character through the utf8 decoder We happily accept non + * shortest form encodings and invalid code points - there's no real harm + * that can be done. */ if (utf8_bytes_left == 0) { /* Read utf-8 start byte */ DWORD first_zero_bit; @@ -1742,8 +1738,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, /* Start byte where continuation was expected. */ utf8_bytes_left = 0; utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - /* Patch buf offset so this character will be parsed again as a */ - /* start byte. */ + /* Patch buf offset so this character will be parsed again as a start + * byte. */ j--; } @@ -1776,8 +1772,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case '_': case 'P': case ']': - /* Not supported, but we'll have to parse until we see a stop */ - /* code, e.g. ESC \ or BEL. */ + /* Not supported, but we'll have to parse until we see a stop code, + * e. g. ESC \ or BEL. */ ansi_parser_state = ANSI_ST_CONTROL; continue; @@ -1859,8 +1855,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle, continue; } else { - /* If ANSI_IN_ARG is not set, add another argument and */ - /* default it to 0. */ + /* If ANSI_IN_ARG is not set, add another argument and default it + * to 0. */ + /* Check for too many arguments */ if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { ansi_parser_state |= ANSI_IGNORE; @@ -1874,9 +1871,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle, } else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) && handle->tty.wr.ansi_csi_argc == 0) { - /* Ignores '?' if it is the first character after CSI[ */ - /* This is an extension character from the VT100 codeset */ - /* that is supported and used by most ANSI terminals today. */ + /* Ignores '?' if it is the first character after CSI[. This is an + * extension character from the VT100 codeset that is supported and + * used by most ANSI terminals today. */ continue; } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' && @@ -2006,8 +2003,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, continue; } else { - /* We don't support commands that use private mode characters or */ - /* intermediaries. Ignore the rest of the sequence. */ + /* We don't support commands that use private mode characters or + * intermediaries. Ignore the rest of the sequence. */ ansi_parser_state |= ANSI_IGNORE; continue; } @@ -2020,8 +2017,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, } } else if (ansi_parser_state & ANSI_ST_CONTROL) { - /* Unsupported control code */ - /* Ignore everything until we see BEL or ESC \ */ + /* Unsupported control code. + * Ignore everything until we see `BEL` or `ESC \`. */ if (ansi_parser_state & ANSI_IN_STRING) { if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) { if (utf8_codepoint == '"') { @@ -2055,9 +2052,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle, abort(); } - /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */ - /* windows console doesn't really support UTF-16, so just emit the */ - /* replacement character. */ + /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the windows + * console doesn't really support UTF-16, so just emit the replacement + * character. */ if (utf8_codepoint > 0xffff) { utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; } @@ -2071,10 +2068,10 @@ static int uv_tty_write_bufs(uv_tty_t* handle, utf16_buf[utf16_buf_used++] = L'\r'; utf16_buf[utf16_buf_used++] = L'\n'; } else if (utf8_codepoint == 0x0d && previous_eol == 0x0a) { - /* \n was followed by \r; do not print the \r, since */ - /* the source was either \r\n\r (so the second \r is */ - /* redundant) or was \n\r (so the \n was processed */ - /* by the last case and an \r automatically inserted). */ + /* \n was followed by \r; do not print the \r, since the source was + * either \r\n\r (so the second \r is redundant) or was \n\r (so the + * \n was processed by the last case and an \r automatically + * inserted). */ } else { /* \r without \n; print \r as-is. */ ENSURE_BUFFER_SPACE(1); @@ -2182,14 +2179,14 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, void uv_tty_close(uv_tty_t* handle) { assert(handle->u.fd == -1 || handle->u.fd > 2); + if (handle->flags & UV_HANDLE_READING) + uv_tty_read_stop(handle); + if (handle->u.fd == -1) CloseHandle(handle->handle); else close(handle->u.fd); - if (handle->flags & UV_HANDLE_READING) - uv_tty_read_stop(handle); - handle->u.fd = -1; handle->handle = INVALID_HANDLE_VALUE; handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); @@ -2209,7 +2206,7 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { /* TTY shutdown is really just a no-op */ if (handle->stream.conn.shutdown_req->cb) { - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED); } else { handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0); @@ -2222,10 +2219,10 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { return; } - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { - /* The wait handle used for raw reading should be unregistered when the */ - /* wait callback runs. */ + /* The wait handle used for raw reading should be unregistered when the + * wait callback runs. */ assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || handle->tty.rd.read_raw_wait == NULL); diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c index cd1d0e0..37df849 100644 --- a/Utilities/cmlibuv/src/win/udp.c +++ b/Utilities/cmlibuv/src/win/udp.c @@ -74,8 +74,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, return GetLastError(); } - /* Associate it with the I/O completion port. */ - /* Use uv_handle_t pointer as completion key. */ + /* Associate it with the I/O completion port. Use uv_handle_t pointer as + * completion key. */ if (CreateIoCompletionPort((HANDLE)socket, loop->iocp, (ULONG_PTR)socket, @@ -83,31 +83,28 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, return GetLastError(); } - if (pSetFileCompletionNotificationModes) { - /* All known Windows that support SetFileCompletionNotificationModes */ - /* have a bug that makes it impossible to use this function in */ - /* conjunction with datagram sockets. We can work around that but only */ - /* if the user is using the default UDP driver (AFD) and has no other */ - /* LSPs stacked on top. Here we check whether that is the case. */ - opt_len = (int) sizeof info; - if (getsockopt(socket, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &info, - &opt_len) == SOCKET_ERROR) { - return GetLastError(); - } + /* All known Windows that support SetFileCompletionNotificationModes have a + * bug that makes it impossible to use this function in conjunction with + * datagram sockets. We can work around that but only if the user is using + * the default UDP driver (AFD) and has no other. LSPs stacked on top. Here + * we check whether that is the case. */ + opt_len = (int) sizeof info; + if (getsockopt( + socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) == + SOCKET_ERROR) { + return GetLastError(); + } - if (info.ProtocolChain.ChainLen == 1) { - if (pSetFileCompletionNotificationModes((HANDLE)socket, - FILE_SKIP_SET_EVENT_ON_HANDLE | - FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { - handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; - handle->func_wsarecv = uv_wsarecv_workaround; - handle->func_wsarecvfrom = uv_wsarecvfrom_workaround; - } else if (GetLastError() != ERROR_INVALID_FUNCTION) { - return GetLastError(); - } + if (info.ProtocolChain.ChainLen == 1) { + if (SetFileCompletionNotificationModes( + (HANDLE) socket, + FILE_SKIP_SET_EVENT_ON_HANDLE | + FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { + handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; + handle->func_wsarecv = uv_wsarecv_workaround; + handle->func_wsarecvfrom = uv_wsarecvfrom_workaround; + } else if (GetLastError() != ERROR_INVALID_FUNCTION) { + return GetLastError(); } } @@ -191,7 +188,7 @@ void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) { void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); uv__handle_close(handle); @@ -245,12 +242,12 @@ static int uv_udp_maybe_bind(uv_udp_t* handle, handle->flags |= UV_HANDLE_IPV6; if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { - /* On windows IPV6ONLY is on by default. */ - /* If the user doesn't specify it libuv turns it off. */ + /* On windows IPV6ONLY is on by default. If the user doesn't specify it + * libuv turns it off. */ - /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ - /* available, or when run on XP/2003 which have no support for dualstack */ - /* sockets. For now we're silently ignoring the error. */ + /* TODO: how to handle errors? This may fail if there is no ipv4 stack + * available, or when run on XP/2003 which have no support for dualstack + * sockets. For now we're silently ignoring the error. */ setsockopt(handle->socket, IPPROTO_IPV6, IPV6_V6ONLY, @@ -369,7 +366,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, int err; if (handle->flags & UV_HANDLE_READING) { - return WSAEALREADY; + return UV_EALREADY; } err = uv_udp_maybe_bind(handle, @@ -377,7 +374,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, sizeof(uv_addr_ip4_any_), 0); if (err) - return err; + return uv_translate_sys_error(err); handle->flags |= UV_HANDLE_READING; INCREASE_ACTIVE_COUNT(loop, handle); @@ -386,8 +383,8 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, handle->recv_cb = recv_cb; handle->alloc_cb = alloc_cb; - /* If reading was stopped and then started again, there could still be a */ - /* recv request pending. */ + /* If reading was stopped and then started again, there could still be a recv + * request pending. */ if (!(handle->flags & UV_HANDLE_READ_PENDING)) uv_udp_queue_recv(loop, handle); @@ -467,19 +464,19 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, if (!REQ_SUCCESS(req)) { DWORD err = GET_REQ_SOCK_ERROR(req); if (err == WSAEMSGSIZE) { - /* Not a real error, it just indicates that the received packet */ - /* was bigger than the receive buffer. */ + /* Not a real error, it just indicates that the received packet was + * bigger than the receive buffer. */ } else if (err == WSAECONNRESET || err == WSAENETRESET) { - /* A previous sendto operation failed; ignore this error. If */ - /* zero-reading we need to call WSARecv/WSARecvFrom _without_ the */ - /* MSG_PEEK flag to clear out the error queue. For nonzero reads, */ - /* immediately queue a new receive. */ + /* A previous sendto operation failed; ignore this error. If zero-reading + * we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to + * clear out the error queue. For nonzero reads, immediately queue a new + * receive. */ if (!(handle->flags & UV_HANDLE_ZERO_READ)) { goto done; } } else { - /* A real error occurred. Report the error to the user only if we're */ - /* currently reading. */ + /* A real error occurred. Report the error to the user only if we're + * currently reading. */ if (handle->flags & UV_HANDLE_READING) { uv_udp_recv_stop(handle); buf = (handle->flags & UV_HANDLE_ZERO_READ) ? @@ -503,8 +500,8 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, struct sockaddr_storage from; int from_len; - /* Do a nonblocking receive */ - /* TODO: try to read multiple datagrams at once. FIONREAD maybe? */ + /* Do a nonblocking receive. + * TODO: try to read multiple datagrams at once. FIONREAD maybe? */ buf = uv_buf_init(NULL, 0); handle->alloc_cb((uv_handle_t*) handle, 65536, &buf); if (buf.base == NULL || buf.len == 0) { @@ -741,7 +738,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) return UV_EINVAL; } - if (!(handle->flags & UV_HANDLE_BOUND)) + if (handle->socket == INVALID_SOCKET) return UV_EBADF; if (addr_st.ss_family == AF_INET) { @@ -772,7 +769,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) int uv_udp_set_broadcast(uv_udp_t* handle, int value) { BOOL optval = (BOOL) value; - if (!(handle->flags & UV_HANDLE_BOUND)) + if (handle->socket == INVALID_SOCKET) return UV_EBADF; if (setsockopt(handle->socket, @@ -818,7 +815,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { return UV_EINVAL; \ } \ \ - if (!(handle->flags & UV_HANDLE_BOUND)) \ + if (handle->socket == INVALID_SOCKET) \ return UV_EBADF; \ \ if (!(handle->flags & UV_HANDLE_IPV6)) { \ diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c index 49b5bc7..9237891 100644 --- a/Utilities/cmlibuv/src/win/util.c +++ b/Utilities/cmlibuv/src/win/util.c @@ -74,10 +74,6 @@ static char *process_title; static CRITICAL_SECTION process_title_lock; -/* Cached copy of the process id, written once. */ -static DWORD current_pid = 0; - - /* Interval (in seconds) of the high-resolution clock. */ static double hrtime_interval_ = 0; @@ -149,8 +145,8 @@ int uv_exepath(char* buffer, size_t* size_ptr) { uv__free(utf16_buffer); - /* utf8_len *does* include the terminating null at this point, but the */ - /* returned size shouldn't. */ + /* utf8_len *does* include the terminating null at this point, but the + * returned size shouldn't. */ *size_ptr = utf8_len - 1; return 0; @@ -173,16 +169,16 @@ int uv_cwd(char* buffer, size_t* size) { if (utf16_len == 0) { return uv_translate_sys_error(GetLastError()); } else if (utf16_len > MAX_PATH) { - /* This should be impossible; however the CRT has a code path to deal */ - /* with this scenario, so I added a check anyway. */ + /* This should be impossible; however the CRT has a code path to deal with + * this scenario, so I added a check anyway. */ return UV_EIO; } /* utf16_len contains the length, *not* including the terminating null. */ utf16_buffer[utf16_len] = L'\0'; - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed.*/ + /* The returned directory should not have a trailing slash, unless it points + * at a drive root, like c:\. Remove it if needed. */ if (utf16_buffer[utf16_len - 1] == L'\\' && !(utf16_len == 3 && utf16_buffer[1] == L':')) { utf16_len--; @@ -239,9 +235,9 @@ int uv_chdir(const char* dir) { utf16_buffer, MAX_PATH) == 0) { DWORD error = GetLastError(); - /* The maximum length of the current working directory is 260 chars, */ - /* including terminating null. If it doesn't fit, the path name must be */ - /* too long. */ + /* The maximum length of the current working directory is 260 chars, + * including terminating null. If it doesn't fit, the path name must be too + * long. */ if (error == ERROR_INSUFFICIENT_BUFFER) { return UV_ENAMETOOLONG; } else { @@ -253,9 +249,9 @@ int uv_chdir(const char* dir) { return uv_translate_sys_error(GetLastError()); } - /* Windows stores the drive-local path in an "hidden" environment variable, */ - /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */ - /* update this, so we'll have to do it. */ + /* Windows stores the drive-local path in an "hidden" environment variable, + * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update + * this, so we'll have to do it. */ utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer); if (utf16_len == 0) { return uv_translate_sys_error(GetLastError()); @@ -263,8 +259,8 @@ int uv_chdir(const char* dir) { return UV_EIO; } - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed. */ + /* The returned directory should not have a trailing slash, unless it points + * at a drive root, like c:\. Remove it if needed. */ if (utf16_buffer[utf16_len - 1] == L'\\' && !(utf16_len == 3 && utf16_buffer[1] == L':')) { utf16_len--; @@ -272,8 +268,8 @@ int uv_chdir(const char* dir) { } if (utf16_len < 2 || utf16_buffer[1] != L':') { - /* Doesn't look like a drive letter could be there - probably an UNC */ - /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */ + /* Doesn't look like a drive letter could be there - probably an UNC path. + * TODO: Need to handle win32 namespaces like \\?\C:\ ? */ drive_letter = 0; } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') { drive_letter = utf16_buffer[0]; @@ -359,14 +355,6 @@ uv_pid_t uv_os_getppid(void) { } -int uv_current_pid(void) { - if (current_pid == 0) { - current_pid = GetCurrentProcessId(); - } - return current_pid; -} - - char** uv_setup_args(int argc, char** argv) { return argv; } @@ -828,6 +816,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, int is_vista_or_greater; ULONG flags; + *addresses_ptr = NULL; + *count_ptr = 0; + is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0); if (is_vista_or_greater) { flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | @@ -842,17 +833,17 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, } - /* Fetch the size of the adapters reported by windows, and then get the */ - /* list itself. */ + /* Fetch the size of the adapters reported by windows, and then get the list + * itself. */ win_address_buf_size = 0; win_address_buf = NULL; for (;;) { ULONG r; - /* If win_address_buf is 0, then GetAdaptersAddresses will fail with */ - /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */ - /* win_address_buf_size. */ + /* If win_address_buf is 0, then GetAdaptersAddresses will fail with. + * ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in + * win_address_buf_size. */ r = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, @@ -866,8 +857,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, switch (r) { case ERROR_BUFFER_OVERFLOW: - /* This happens when win_address_buf is NULL or too small to hold */ - /* all adapters. */ + /* This happens when win_address_buf is NULL or too small to hold all + * adapters. */ win_address_buf = uv__malloc(win_address_buf_size); if (win_address_buf == NULL) return UV_ENOMEM; @@ -901,15 +892,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, return UV_ENOBUFS; default: - /* Other (unspecified) errors can happen, but we don't have any */ - /* special meaning for them. */ + /* Other (unspecified) errors can happen, but we don't have any special + * meaning for them. */ assert(r != ERROR_SUCCESS); return uv_translate_sys_error(r); } } - /* Count the number of enabled interfaces and compute how much space is */ - /* needed to store their info. */ + /* Count the number of enabled interfaces and compute how much space is + * needed to store their info. */ count = 0; uv_address_buf_size = 0; @@ -919,9 +910,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, IP_ADAPTER_UNICAST_ADDRESS* unicast_address; int name_size; - /* Interfaces that are not 'up' should not be reported. Also skip */ - /* interfaces that have no associated unicast address, as to avoid */ - /* allocating space for the name for this interface. */ + /* Interfaces that are not 'up' should not be reported. Also skip + * interfaces that have no associated unicast address, as to avoid + * allocating space for the name for this interface. */ if (adapter->OperStatus != IfOperStatusUp || adapter->FirstUnicastAddress == NULL) continue; @@ -941,8 +932,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, } uv_address_buf_size += name_size; - /* Count the number of addresses associated with this interface, and */ - /* compute the size. */ + /* Count the number of addresses associated with this interface, and + * compute the size. */ for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) adapter->FirstUnicastAddress; unicast_address != NULL; @@ -959,8 +950,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, return UV_ENOMEM; } - /* Compute the start of the uv_interface_address_t array, and the place in */ - /* the buffer where the interface names will be stored. */ + /* Compute the start of the uv_interface_address_t array, and the place in + * the buffer where the interface names will be stored. */ uv_address = uv_address_buf; name_buf = (char*) (uv_address_buf + count); @@ -1199,8 +1190,8 @@ int uv_os_tmpdir(char* buffer, size_t* size) { return UV_EIO; } - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed.*/ + /* The returned directory should not have a trailing slash, unless it points + * at a drive root, like c:\. Remove it if needed. */ if (path[len - 1] == L'\\' && !(len == 3 && path[1] == L':')) { len--; @@ -1542,3 +1533,214 @@ int uv_os_gethostname(char* buffer, size_t* size) { *size = len; return 0; } + + +static int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) { + int r; + + if (pid == 0) + *handle = GetCurrentProcess(); + else + *handle = OpenProcess(access, FALSE, pid); + + if (*handle == NULL) { + r = GetLastError(); + + if (r == ERROR_INVALID_PARAMETER) + return UV_ESRCH; + else + return uv_translate_sys_error(r); + } + + return 0; +} + + +int uv_os_getpriority(uv_pid_t pid, int* priority) { + HANDLE handle; + int r; + + if (priority == NULL) + return UV_EINVAL; + + r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle); + + if (r != 0) + return r; + + r = GetPriorityClass(handle); + + if (r == 0) { + r = uv_translate_sys_error(GetLastError()); + } else { + /* Map Windows priority classes to Unix nice values. */ + if (r == REALTIME_PRIORITY_CLASS) + *priority = UV_PRIORITY_HIGHEST; + else if (r == HIGH_PRIORITY_CLASS) + *priority = UV_PRIORITY_HIGH; + else if (r == ABOVE_NORMAL_PRIORITY_CLASS) + *priority = UV_PRIORITY_ABOVE_NORMAL; + else if (r == NORMAL_PRIORITY_CLASS) + *priority = UV_PRIORITY_NORMAL; + else if (r == BELOW_NORMAL_PRIORITY_CLASS) + *priority = UV_PRIORITY_BELOW_NORMAL; + else /* IDLE_PRIORITY_CLASS */ + *priority = UV_PRIORITY_LOW; + + r = 0; + } + + CloseHandle(handle); + return r; +} + + +int uv_os_setpriority(uv_pid_t pid, int priority) { + HANDLE handle; + int priority_class; + int r; + + /* Map Unix nice values to Windows priority classes. */ + if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW) + return UV_EINVAL; + else if (priority < UV_PRIORITY_HIGH) + priority_class = REALTIME_PRIORITY_CLASS; + else if (priority < UV_PRIORITY_ABOVE_NORMAL) + priority_class = HIGH_PRIORITY_CLASS; + else if (priority < UV_PRIORITY_NORMAL) + priority_class = ABOVE_NORMAL_PRIORITY_CLASS; + else if (priority < UV_PRIORITY_BELOW_NORMAL) + priority_class = NORMAL_PRIORITY_CLASS; + else if (priority < UV_PRIORITY_LOW) + priority_class = BELOW_NORMAL_PRIORITY_CLASS; + else + priority_class = IDLE_PRIORITY_CLASS; + + r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle); + + if (r != 0) + return r; + + if (SetPriorityClass(handle, priority_class) == 0) + r = uv_translate_sys_error(GetLastError()); + + CloseHandle(handle); + return r; +} + + +int uv_os_uname(uv_utsname_t* buffer) { + /* Implementation loosely based on + https://github.com/gagern/gnulib/blob/master/lib/uname.c */ + OSVERSIONINFOW os_info; + SYSTEM_INFO system_info; + int processor_level; + int r; + + if (buffer == NULL) + return UV_EINVAL; + + uv__once_init(); + os_info.dwOSVersionInfoSize = sizeof(os_info); + os_info.szCSDVersion[0] = L'\0'; + + /* Try calling RtlGetVersion(), and fall back to the deprecated GetVersionEx() + if RtlGetVersion() is not available. */ + if (pRtlGetVersion) { + pRtlGetVersion(&os_info); + } else { + /* Silence GetVersionEx() deprecation warning. */ + #pragma warning(suppress : 4996) + if (GetVersionExW(&os_info) == 0) { + r = uv_translate_sys_error(GetLastError()); + goto error; + } + } + + /* Populate the version field. */ + if (WideCharToMultiByte(CP_UTF8, + 0, + os_info.szCSDVersion, + -1, + buffer->version, + sizeof(buffer->version), + NULL, + NULL) == 0) { + r = uv_translate_sys_error(GetLastError()); + goto error; + } + + /* Populate the sysname field. */ +#ifdef __MINGW32__ + r = snprintf(buffer->sysname, + sizeof(buffer->sysname), + "MINGW32_NT-%u.%u", + (unsigned int) os_info.dwMajorVersion, + (unsigned int) os_info.dwMinorVersion); + assert(r < sizeof(buffer->sysname)); +#else + uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname)); +#endif + + /* Populate the release field. */ + r = snprintf(buffer->release, + sizeof(buffer->release), + "%d.%d.%d", + (unsigned int) os_info.dwMajorVersion, + (unsigned int) os_info.dwMinorVersion, + (unsigned int) os_info.dwBuildNumber); + assert(r < sizeof(buffer->release)); + + /* Populate the machine field. */ + GetSystemInfo(&system_info); + + switch (system_info.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_AMD64: + uv__strscpy(buffer->machine, "x86_64", sizeof(buffer->machine)); + break; + case PROCESSOR_ARCHITECTURE_IA64: + uv__strscpy(buffer->machine, "ia64", sizeof(buffer->machine)); + break; + case PROCESSOR_ARCHITECTURE_INTEL: + uv__strscpy(buffer->machine, "i386", sizeof(buffer->machine)); + + if (system_info.wProcessorLevel > 3) { + processor_level = system_info.wProcessorLevel < 6 ? + system_info.wProcessorLevel : 6; + buffer->machine[1] = '0' + processor_level; + } + + break; + case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: + uv__strscpy(buffer->machine, "i686", sizeof(buffer->machine)); + break; + case PROCESSOR_ARCHITECTURE_MIPS: + uv__strscpy(buffer->machine, "mips", sizeof(buffer->machine)); + break; + case PROCESSOR_ARCHITECTURE_ALPHA: + case PROCESSOR_ARCHITECTURE_ALPHA64: + uv__strscpy(buffer->machine, "alpha", sizeof(buffer->machine)); + break; + case PROCESSOR_ARCHITECTURE_PPC: + uv__strscpy(buffer->machine, "powerpc", sizeof(buffer->machine)); + break; + case PROCESSOR_ARCHITECTURE_SHX: + uv__strscpy(buffer->machine, "sh", sizeof(buffer->machine)); + break; + case PROCESSOR_ARCHITECTURE_ARM: + uv__strscpy(buffer->machine, "arm", sizeof(buffer->machine)); + break; + default: + uv__strscpy(buffer->machine, "unknown", sizeof(buffer->machine)); + break; + } + + return 0; + +error: + buffer->sysname[0] = '\0'; + buffer->release[0] = '\0'; + buffer->version[0] = '\0'; + buffer->machine[0] = '\0'; + return r; +} diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c index c330786..fbbbcee 100644 --- a/Utilities/cmlibuv/src/win/winapi.c +++ b/Utilities/cmlibuv/src/win/winapi.c @@ -26,6 +26,7 @@ /* Ntdll function pointers */ +sRtlGetVersion pRtlGetVersion; sRtlNtStatusToDosError pRtlNtStatusToDosError; sNtDeviceIoControlFile pNtDeviceIoControlFile; sNtQueryInformationFile pNtQueryInformationFile; @@ -34,20 +35,8 @@ sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; sNtQueryDirectoryFile pNtQueryDirectoryFile; sNtQuerySystemInformation pNtQuerySystemInformation; - /* Kernel32 function pointers */ sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; -sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; -sCreateSymbolicLinkW pCreateSymbolicLinkW; -sCancelIoEx pCancelIoEx; -sInitializeConditionVariable pInitializeConditionVariable; -sSleepConditionVariableCS pSleepConditionVariableCS; -sSleepConditionVariableSRW pSleepConditionVariableSRW; -sWakeAllConditionVariable pWakeAllConditionVariable; -sWakeConditionVariable pWakeConditionVariable; -sCancelSynchronousIo pCancelSynchronousIo; -sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; - /* Powrprof.dll function pointer */ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; @@ -55,22 +44,21 @@ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; /* User32.dll function pointer */ sSetWinEventHook pSetWinEventHook; -/* iphlpapi.dll function pointer */ -sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid = NULL; -sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW = NULL; void uv_winapi_init(void) { HMODULE ntdll_module; - HMODULE kernel32_module; HMODULE powrprof_module; HMODULE user32_module; - HMODULE iphlpapi_module; + HMODULE kernel32_module; ntdll_module = GetModuleHandleA("ntdll.dll"); if (ntdll_module == NULL) { uv_fatal_error(GetLastError(), "GetModuleHandleA"); } + pRtlGetVersion = (sRtlGetVersion) GetProcAddress(ntdll_module, + "RtlGetVersion"); + pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress( ntdll_module, "RtlNtStatusToDosError"); @@ -127,37 +115,6 @@ void uv_winapi_init(void) { kernel32_module, "GetQueuedCompletionStatusEx"); - pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes) - GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes"); - - pCreateSymbolicLinkW = (sCreateSymbolicLinkW) - GetProcAddress(kernel32_module, "CreateSymbolicLinkW"); - - pCancelIoEx = (sCancelIoEx) - GetProcAddress(kernel32_module, "CancelIoEx"); - - pInitializeConditionVariable = (sInitializeConditionVariable) - GetProcAddress(kernel32_module, "InitializeConditionVariable"); - - pSleepConditionVariableCS = (sSleepConditionVariableCS) - GetProcAddress(kernel32_module, "SleepConditionVariableCS"); - - pSleepConditionVariableSRW = (sSleepConditionVariableSRW) - GetProcAddress(kernel32_module, "SleepConditionVariableSRW"); - - pWakeAllConditionVariable = (sWakeAllConditionVariable) - GetProcAddress(kernel32_module, "WakeAllConditionVariable"); - - pWakeConditionVariable = (sWakeConditionVariable) - GetProcAddress(kernel32_module, "WakeConditionVariable"); - - pCancelSynchronousIo = (sCancelSynchronousIo) - GetProcAddress(kernel32_module, "CancelSynchronousIo"); - - pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW) - GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW"); - - powrprof_module = LoadLibraryA("powrprof.dll"); if (powrprof_module != NULL) { pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification) @@ -170,11 +127,4 @@ void uv_winapi_init(void) { GetProcAddress(user32_module, "SetWinEventHook"); } - iphlpapi_module = LoadLibraryA("iphlpapi.dll"); - if (iphlpapi_module != NULL) { - pConvertInterfaceIndexToLuid = (sConvertInterfaceIndexToLuid) - GetProcAddress(iphlpapi_module, "ConvertInterfaceIndexToLuid"); - pConvertInterfaceLuidToNameW = (sConvertInterfaceLuidToNameW) - GetProcAddress(iphlpapi_module, "ConvertInterfaceLuidToNameW"); - } } diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h index ae384b7..1e49b57 100644 --- a/Utilities/cmlibuv/src/win/winapi.h +++ b/Utilities/cmlibuv/src/win/winapi.h @@ -4076,8 +4076,8 @@ # define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L) #endif -/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the */ -/* DDK got it wrong! */ +/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the DDK + * got it wrong! */ #ifdef NTSTATUS_FROM_WIN32 # undef NTSTATUS_FROM_WIN32 #endif @@ -4109,6 +4109,9 @@ #endif /* from winternl.h */ +#if !defined(__UNICODE_STRING_DEFINED) && defined(__MINGW32_) +#define __UNICODE_STRING_DEFINED +#endif typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; @@ -4524,6 +4527,9 @@ typedef VOID (NTAPI *PIO_APC_ROUTINE) PIO_STATUS_BLOCK IoStatusBlock, ULONG Reserved); +typedef NTSTATUS (NTAPI *sRtlGetVersion) + (PRTL_OSVERSIONINFOW lpVersionInformation); + typedef ULONG (NTAPI *sRtlNtStatusToDosError) (NTSTATUS Status); @@ -4659,48 +4665,6 @@ typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx) DWORD dwMilliseconds, BOOL fAlertable); -typedef BOOL (WINAPI* sSetFileCompletionNotificationModes) - (HANDLE FileHandle, - UCHAR Flags); - -typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW) - (LPCWSTR lpSymlinkFileName, - LPCWSTR lpTargetFileName, - DWORD dwFlags); - -typedef BOOL (WINAPI* sCancelIoEx) - (HANDLE hFile, - LPOVERLAPPED lpOverlapped); - -typedef VOID (WINAPI* sInitializeConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI* sSleepConditionVariableCS) - (PCONDITION_VARIABLE ConditionVariable, - PCRITICAL_SECTION CriticalSection, - DWORD dwMilliseconds); - -typedef BOOL (WINAPI* sSleepConditionVariableSRW) - (PCONDITION_VARIABLE ConditionVariable, - PSRWLOCK SRWLock, - DWORD dwMilliseconds, - ULONG Flags); - -typedef VOID (WINAPI* sWakeAllConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef VOID (WINAPI* sWakeConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI* sCancelSynchronousIo) - (HANDLE hThread); - -typedef DWORD (WINAPI* sGetFinalPathNameByHandleW) - (HANDLE hFile, - LPWSTR lpszFilePath, - DWORD cchFilePath, - DWORD dwFlags); - /* from powerbase.h */ #ifndef DEVICE_NOTIFY_CALLBACK # define DEVICE_NOTIFY_CALLBACK 2 @@ -4755,6 +4719,7 @@ typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook) /* Ntdll function pointers */ +extern sRtlGetVersion pRtlGetVersion; extern sRtlNtStatusToDosError pRtlNtStatusToDosError; extern sNtDeviceIoControlFile pNtDeviceIoControlFile; extern sNtQueryInformationFile pNtQueryInformationFile; @@ -4763,20 +4728,8 @@ extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; extern sNtQueryDirectoryFile pNtQueryDirectoryFile; extern sNtQuerySystemInformation pNtQuerySystemInformation; - /* Kernel32 function pointers */ extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; -extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; -extern sCreateSymbolicLinkW pCreateSymbolicLinkW; -extern sCancelIoEx pCancelIoEx; -extern sInitializeConditionVariable pInitializeConditionVariable; -extern sSleepConditionVariableCS pSleepConditionVariableCS; -extern sSleepConditionVariableSRW pSleepConditionVariableSRW; -extern sWakeAllConditionVariable pWakeAllConditionVariable; -extern sWakeConditionVariable pWakeConditionVariable; -extern sCancelSynchronousIo pCancelSynchronousIo; -extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; - /* Powrprof.dll function pointer */ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; @@ -4784,19 +4737,4 @@ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotifi /* User32.dll function pointer */ extern sSetWinEventHook pSetWinEventHook; -/* iphlpapi.dll function pointer */ -union _NET_LUID_LH; -typedef DWORD (WINAPI *sConvertInterfaceIndexToLuid)( - ULONG InterfaceIndex, - union _NET_LUID_LH *InterfaceLuid); - -typedef DWORD (WINAPI *sConvertInterfaceLuidToNameW)( - const union _NET_LUID_LH *InterfaceLuid, - PWSTR InterfaceName, - size_t Length); - -extern sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid; -extern sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW; - - #endif /* UV_WIN_WINAPI_H_ */ diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c index 8418895..5e7da2a 100644 --- a/Utilities/cmlibuv/src/win/winsock.c +++ b/Utilities/cmlibuv/src/win/winsock.c @@ -256,8 +256,8 @@ int uv_ntstatus_to_winsock_error(NTSTATUS status) { default: if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) && (status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) { - /* It's a windows error that has been previously mapped to an */ - /* ntstatus code. */ + /* It's a windows error that has been previously mapped to an ntstatus + * code. */ return (DWORD) (status & 0xffff); } else { /* The default fallback for unmappable ntstatus codes. */ @@ -519,8 +519,8 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, sizeof *info_out); if (overlapped == NULL) { - /* If this is a blocking operation, wait for the event to become */ - /* signaled, and then grab the real status from the io status block. */ + /* If this is a blocking operation, wait for the event to become signaled, + * and then grab the real status from the io status block. */ if (status == STATUS_PENDING) { DWORD r = WaitForSingleObject(event, INFINITE); @@ -491,8 +491,11 @@ KWSYS_FILES="\ if ${cmake_system_mingw}; then LIBUV_C_SOURCES="\ src/fs-poll.c \ + src/idna.c src/inet.c \ src/threadpool.c \ + src/strscpy.c \ + src/timer.c \ src/uv-common.c \ src/win/async.c \ src/win/core.c \ @@ -509,12 +512,10 @@ if ${cmake_system_mingw}; then src/win/poll.c \ src/win/process-stdio.c \ src/win/process.c \ - src/win/req.c \ src/win/signal.c \ src/win/stream.c \ src/win/tcp.c \ src/win/thread.c \ - src/win/timer.c \ src/win/tty.c \ src/win/udp.c \ src/win/util.c \ @@ -523,6 +524,8 @@ if ${cmake_system_mingw}; then " else LIBUV_C_SOURCES="\ + src/strscpy.c \ + src/timer.c \ src/uv-common.c \ src/unix/cmake-bootstrap.c \ src/unix/core.c \ @@ -537,7 +540,6 @@ else src/unix/process.c \ src/unix/signal.c \ src/unix/stream.c \ - src/unix/timer.c \ " fi |