---
-# This configuration requires clang-format 3.8 or higher.
+# This configuration requires clang-format version 6.0 exactly.
BasedOnStyle: Mozilla
AlignOperands: false
-AlwaysBreakAfterReturnType: None
+AllowShortFunctionsOnASingleLine: InlineOnly
AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterStruct: true
+ AfterUnion: true
+BreakBeforeBraces: Custom
ColumnLimit: 79
+IndentPPDirectives: AfterHash
+SortUsingDeclarations: false
+SpaceAfterTemplateKeyword: true
...
message(FATAL_ERROR "CMake_RUN_IWYU is ON but include-what-you-use is not found!")
endif()
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
- "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp;-w")
+ "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp;-w;-DCMAKE_IWYU")
endif()
#---------------------------------------------------------------------
# Use curses?
if (UNIX)
- # there is a bug in the Syllable libraries which makes linking ccmake fail, Alex
- if(NOT CMAKE_SYSTEM_NAME MATCHES syllable)
- set(CURSES_NEED_NCURSES TRUE)
- find_package(Curses QUIET)
- if (CURSES_LIBRARY)
- option(BUILD_CursesDialog "Build the CMake Curses Dialog ccmake" ON)
- else ()
- message("Curses libraries were not found. Curses GUI for CMake will not be built.")
- set(BUILD_CursesDialog 0)
- endif ()
- else()
- set(BUILD_CursesDialog 0)
+ if(NOT DEFINED BUILD_CursesDialog)
+ include(${CMake_SOURCE_DIR}/Source/Checks/Curses.cmake)
+ option(BUILD_CursesDialog "Build the CMake Curses Dialog ccmake" "${CMakeCheckCurses_COMPILED}")
endif()
else ()
set(BUILD_CursesDialog 0)
endif ()
if(BUILD_CursesDialog)
+ set(CURSES_NEED_NCURSES TRUE)
+ find_package(Curses)
+ if(NOT CURSES_FOUND)
+ message(WARNING
+ "'ccmake' will not be built because Curses was not found.\n"
+ "Turn off BUILD_CursesDialog to suppress this message."
+ )
+ set(BUILD_CursesDialog 0)
+ endif()
+ endif()
+ if(BUILD_CursesDialog)
if(NOT CMAKE_USE_SYSTEM_FORM)
add_subdirectory(Source/CursesDialog/form)
elseif(NOT CURSES_FORM_LIBRARY)
#. Base all new work on the upstream ``master`` branch.
Base work on the upstream ``release`` branch only if it fixes a
regression or bug in a feature new to that release.
+ If in doubt, prefer ``master``. Reviewers may simply ask for
+ a rebase if deemed appropriate in particular cases.
#. Create commits making incremental, distinct, logically complete changes
with appropriate `commit messages`_.
#. Push a topic branch to a personal repository fork on GitLab.
#. Create a GitLab Merge Request targeting the upstream ``master`` branch
(even if the change is intended for merge to the ``release`` branch).
+ Check the box to allow edits from maintainers.
The merge request will enter the `CMake Review Process`_ for consideration.
if (CMAKE_ANSI_CFLAGS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}")
endif ()
+
+# Allow per-translation-unit parallel builds when using MSVC
+if(CMAKE_GENERATOR MATCHES "Visual Studio" AND
+ (CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel" OR
+ CMAKE_CXX_COMPILER_ID MATCHES "MSVC|Intel"))
+
+ set(CMake_MSVC_PARALLEL ON CACHE STRING "\
+Enables /MP flag for parallel builds using MSVC. Specify an \
+integer value to control the number of threads used (Only \
+works on some older versions of Visual Studio). Setting to \
+ON lets the toolchain decide how many threads to use. Set to \
+OFF to disable /MP completely." )
+
+ if(CMake_MSVC_PARALLEL)
+ if(CMake_MSVC_PARALLEL GREATER 0)
+ string(APPEND CMAKE_C_FLAGS " /MP${CMake_MSVC_PARALLEL}")
+ string(APPEND CMAKE_CXX_FLAGS " /MP${CMake_MSVC_PARALLEL}")
+ else()
+ string(APPEND CMAKE_C_FLAGS " /MP")
+ string(APPEND CMAKE_CXX_FLAGS " /MP")
+ endif()
+ endif()
+endif()
* Nikita Krupen'ko <krnekit@gmail.com>
* NVIDIA Corporation <www.nvidia.com>
* OpenGamma Ltd. <opengamma.com>
+* Patrick Stotko <stotko@cs.uni-bonn.de>
* Per Øyvind Karlsen <peroyvind@mandriva.org>
* Peter Collingbourne <peter@pcc.me.uk>
* Petr Gotthard <gotthard@honeywell.com>
--- /dev/null
+The final set of compile options used for a target is constructed by
+accumulating options from the current target and the usage requirements of
+it dependencies. The set of options is de-duplicated to avoid repetition.
+While beneficial for individual options, the de-duplication step can break
+up option groups. For example, ``-D A -D B`` becomes ``-D A B``. One may
+specify a group of options using shell-like quoting along with a ``SHELL:``
+prefix. The ``SHELL:`` prefix is dropped and the rest of the option string
+is parsed using the :command:`separate_arguments` ``UNIX_COMMAND`` mode.
+For example, ``"SHELL:-D A" "SHELL:-D B"`` becomes ``-D A -D B``.
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[DOC "cache documentation string"]
[NO_DEFAULT_PATH]
+ [NO_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
added to the search.
If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| replace::
+ |prefix_XXX_SUBDIR| for each ``<prefix>`` in ``PackageName_ROOT`` if called
+ from within a find module
+
.. |CMAKE_PREFIX_PATH_XXX_SUBDIR| replace::
|prefix_XXX_SUBDIR| for each ``<prefix>`` in :variable:`CMAKE_PREFIX_PATH`
|prefix_XXX_SUBDIR| for each ``<prefix>`` in
:variable:`CMAKE_SYSTEM_PREFIX_PATH`
-1. Search paths specified in cmake-specific cache variables.
+1. If called from within a find module, search prefix paths unique to the
+ current package being found. Specifically look in the ``PackageName_ROOT``
+ CMake and environment variables. The package root variables are maintained
+ as a stack so if called from nested find modules, root paths from the
+ parent's find module will be searched after paths from the current module,
+ i.e. ``CurrentPackage_ROOT``, ``ENV{CurrentPackage_ROOT}``,
+ ``ParentPackage_ROOT``, ``ENV{ParentPackage_ROOT}``, etc.
+ This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed.
+ See policy :policy:`CMP0074`.
+
+ * |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX|
+
+2. Search paths specified in cmake-specific cache variables.
These are intended to be used on the command line with a ``-DVAR=value``.
The values are interpreted as :ref:`;-lists <CMake Language Lists>`.
This can be skipped if ``NO_CMAKE_PATH`` is passed.
* |CMAKE_XXX_PATH|
* |CMAKE_XXX_MAC_PATH|
-2. Search paths specified in cmake-specific environment variables.
+3. Search paths specified in cmake-specific environment variables.
These are intended to be set in the user's shell configuration,
and therefore use the host's native path separator
(``;`` on Windows and ``:`` on UNIX).
* |CMAKE_XXX_PATH|
* |CMAKE_XXX_MAC_PATH|
-3. Search the paths specified by the ``HINTS`` option.
+4. Search the paths specified by the ``HINTS`` option.
These should be paths computed by system introspection, such as a
hint provided by the location of another item already found.
Hard-coded guesses should be specified with the ``PATHS`` option.
-4. Search the standard system environment variables.
+5. Search the standard system environment variables.
This can be skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is an argument.
* |SYSTEM_ENVIRONMENT_PATH_XXX|
-5. Search cmake variables defined in the Platform files
+6. Search cmake variables defined in the Platform files
for the current system. This can be skipped if ``NO_CMAKE_SYSTEM_PATH``
is passed.
* |CMAKE_SYSTEM_XXX_PATH|
* |CMAKE_SYSTEM_XXX_MAC_PATH|
-6. Search the paths specified by the PATHS option
+7. Search the paths specified by the PATHS option
or in the short-hand version of the command.
These are typically hard-coded guesses.
--- /dev/null
+add_compile_definitions
+-----------------------
+
+Adds preprocessor definitions to the compilation of source files.
+
+::
+
+ add_compile_definitions(<definition> ...)
+
+Adds preprocessor definitions to the compiler command line for targets in the
+current directory and below (whether added before or after this command is
+invoked). See documentation of the :prop_dir:`directory <COMPILE_DEFINITIONS>`
+and :prop_tgt:`target <COMPILE_DEFINITIONS>` ``COMPILE_DEFINITIONS`` properties.
+
+Definitions are specified using the syntax ``VAR`` or ``VAR=value``.
+Function-style definitions are not supported. CMake will automatically
+escape the value correctly for the native build system (note that CMake
+language syntax may require escapes to specify some values).
+
+Arguments to ``add_compile_definitions`` may use "generator expressions" with
+the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. See the :manual:`cmake-buildsystem(7)`
+manual for more on defining buildsystem properties.
This command can be used to add any options, but alternative commands
exist to add preprocessor definitions (:command:`target_compile_definitions`
-and :command:`add_definitions`) or include directories
+and :command:`add_compile_definitions`) or include directories
(:command:`target_include_directories` and :command:`include_directories`).
Arguments to ``add_compile_options`` may use "generator expressions" with
the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
+
+.. include:: COMPILE_OPTIONS_SHELL.txt
of the following is specified:
``PRE_BUILD``
- Run before any other rules are executed within the target.
- This is supported only on Visual Studio 8 or later.
- For all other generators ``PRE_BUILD`` will be treated as
- ``PRE_LINK``.
+ On :ref:`Visual Studio Generators`, run before any other rules are
+ executed within the target.
+ On other generators, run just before ``PRE_LINK`` commands.
``PRE_LINK``
Run after sources have been compiled but before linking the binary
or running the librarian or archiver tool of a static library.
Adds definitions to the compiler command line for targets in the current
directory and below (whether added before or after this command is invoked).
This command can be used to add any flags, but it is intended to add
-preprocessor definitions (see the :command:`add_compile_options` command
-to add other flags).
+preprocessor definitions.
+
+.. note::
+
+ This command has been superseded by alternatives:
+
+ * Use :command:`add_compile_definitions` to add preprocessor definitions.
+ * Use :command:`include_directories` to add include directories.
+ * Use :command:`add_compile_options` to add other options.
+
Flags beginning in -D or /D that look like preprocessor definitions are
automatically added to the :prop_dir:`COMPILE_DEFINITIONS` directory
property for the current directory. Definitions with non-trivial values
begin in ``IMPORTED_`` and ``INTERFACE_``. The most important such
property is :prop_tgt:`IMPORTED_LOCATION` (and its per-configuration
variant :prop_tgt:`IMPORTED_LOCATION_<CONFIG>`) which specifies the
-location of the main library file on disk. See documentation of the
-``IMPORTED_*`` and ``INTERFACE_*`` properties for more information.
+location of the main library file on disk. Or, for object libraries,
+:prop_tgt:`IMPORTED_OBJECTS` (and :prop_tgt:`IMPORTED_OBJECTS_<CONFIG>`)
+specifies the locations of object files on disk.
+See documentation of the ``IMPORTED_*`` and ``INTERFACE_*`` properties
+for more information.
Object Libraries
^^^^^^^^^^^^^^^^
may contain only sources that compile, header files, and other files
that would not affect linking of a normal library (e.g. ``.txt``).
They may contain custom commands generating such sources, but not
-``PRE_BUILD``, ``PRE_LINK``, or ``POST_BUILD`` commands. Object libraries
-cannot be linked. Some native build systems (such as Xcode) may not like
-targets that have only object files, so consider adding at least one real
-source file to any target that references ``$<TARGET_OBJECTS:objlib>``.
+``PRE_BUILD``, ``PRE_LINK``, or ``POST_BUILD`` commands. Some native build
+systems (such as Xcode) may not like targets that have only object files, so
+consider adding at least one real source file to any target that references
+``$<TARGET_OBJECTS:objlib>``.
Alias Libraries
^^^^^^^^^^^^^^^
``IS_64BIT`` One if processor is 64Bit
``HAS_FPU`` One if processor has floating point unit
``HAS_MMX`` One if processor supports MMX instructions
-``HAS_MMX_PLUS`` One if porcessor supports Ext. MMX instructions
-``HAS_SSE`` One if porcessor supports SSE instructions
-``HAS_SSE2`` One if porcessor supports SSE2 instructions
-``HAS_SSE_FP`` One if porcessor supports SSE FP instructions
-``HAS_SSE_MMX`` One if porcessor supports SSE MMX instructions
-``HAS_AMD_3DNOW`` One if porcessor supports 3DNow instructions
-``HAS_AMD_3DNOW_PLUS`` One if porcessor supports 3DNow+ instructions
+``HAS_MMX_PLUS`` One if processor supports Ext. MMX instructions
+``HAS_SSE`` One if processor supports SSE instructions
+``HAS_SSE2`` One if processor supports SSE2 instructions
+``HAS_SSE_FP`` One if processor supports SSE FP instructions
+``HAS_SSE_MMX`` One if processor supports SSE MMX instructions
+``HAS_AMD_3DNOW`` One if processor supports 3DNow instructions
+``HAS_AMD_3DNOW_PLUS`` One if processor supports 3DNow+ instructions
``HAS_IA64`` One if IA64 processor emulating x86
``HAS_SERIAL_NUMBER`` One if processor has serial number
``PROCESSOR_SERIAL_NUMBER`` Processor serial number
Set the minimum required version of cmake for a project and
update `Policy Settings`_ to match the version given::
- cmake_minimum_required(VERSION major.minor[.patch[.tweak]]
- [FATAL_ERROR])
+ cmake_minimum_required(VERSION <min>[...<max>] [FATAL_ERROR])
-If the current version of CMake is lower than that required it will
-stop processing the project and report an error.
+``<min>`` and the optional ``<max>`` are each CMake versions of the form
+``major.minor[.patch[.tweak]]``, and the ``...`` is literal.
+
+If the running version of CMake is lower than the ``<min>`` required
+version it will stop processing the project and report an error.
+The optional ``<max>`` version, if specified, must be at least the
+``<min>`` version and affects policy settings as described below.
+If the running version of CMake is older than 3.12, the extra ``...``
+dots will be seen as version component separators, resulting in the
+``...<max>`` part being ignored and preserving the pre-3.12 behavior
+of basing policies on ``<min>``.
The ``FATAL_ERROR`` option is accepted but ignored by CMake 2.6 and
higher. It should be specified so CMake versions 2.4 and lower fail
The ``cmake_minimum_required(VERSION)`` command implicitly invokes the
:command:`cmake_policy(VERSION)` command to specify that the current
-project code is written for the given version of CMake.
-All policies introduced in the specified version or earlier will be
-set to use NEW behavior. All policies introduced after the specified
-version will be unset. This effectively requests behavior preferred
+project code is written for the given range of CMake versions.
+All policies known to the running version of CMake and introduced
+in the ``<min>`` (or ``<max>``, if specified) version or earlier will
+be set to use ``NEW`` behavior. All policies introduced in later
+versions will be unset. This effectively requests behavior preferred
as of a given CMake version and tells newer CMake versions to warn
about their new policies.
-When a version higher than 2.4 is specified the command implicitly
-invokes::
+When a ``<min>`` version higher than 2.4 is specified the command
+implicitly invokes::
- cmake_policy(VERSION major[.minor[.patch[.tweak]]])
+ cmake_policy(VERSION <min>[...<max>])
-which sets the cmake policy version level to the version specified.
-When version 2.4 or lower is given the command implicitly invokes::
+which sets CMake policies based on the range of versions specified.
+When a ``<min>`` version 2.4 or lower is given the command implicitly
+invokes::
- cmake_policy(VERSION 2.4)
+ cmake_policy(VERSION 2.4[...<max>])
which enables compatibility features for CMake 2.4 and lower.
behavior. While setting policies individually is supported, we
encourage projects to set policies based on CMake versions::
- cmake_policy(VERSION major.minor[.patch[.tweak]])
-
-Specify that the current CMake code is written for the given
-version of CMake. All policies introduced in the specified version or
-earlier will be set to use ``NEW`` behavior. All policies introduced
-after the specified version will be unset (unless the
+ cmake_policy(VERSION <min>[...<max>])
+
+``<min>`` and the optional ``<max>`` are each CMake versions of the form
+``major.minor[.patch[.tweak]]``, and the ``...`` is literal. The ``<min>``
+version must be at least ``2.4`` and at most the running version of CMake.
+The ``<max>`` version, if specified, must be at least the ``<min>`` version
+but may exceed the running version of CMake. If the running version of
+CMake is older than 3.12, the extra ``...`` dots will be seen as version
+component separators, resulting in the ``...<max>`` part being ignored and
+preserving the pre-3.12 behavior of basing policies on ``<min>``.
+
+This specifies that the current CMake code is written for the given
+range of CMake versions. All policies known to the running version of CMake
+and introduced in the ``<min>`` (or ``<max>``, if specified) version
+or earlier will be set to use ``NEW`` behavior. All policies
+introduced in later versions will be unset (unless the
:variable:`CMAKE_POLICY_DEFAULT_CMP<NNNN>` variable sets a default).
This effectively requests behavior preferred as of a given CMake
version and tells newer CMake versions to warn about their new policies.
-The policy version specified must be at least 2.4 or the command will
-report an error.
Note that the :command:`cmake_minimum_required(VERSION)`
command implicitly calls ``cmake_policy(VERSION)`` too.
::
- ctest_start(Model [TRACK <track>] [APPEND] [source [binary]] [QUIET])
+ ctest_start(<model> [<source> [<binary>]] [TRACK <track>] [QUIET])
+
+ ctest_start([<model> [<source> [<binary>]]] [TRACK <track>] APPEND [QUIET])
Starts the testing for a given model. The command should be called
-after the binary directory is initialized. If the 'source' and
-'binary' directory are not specified, it reads the
-:variable:`CTEST_SOURCE_DIRECTORY` and :variable:`CTEST_BINARY_DIRECTORY`.
-If the track is
-specified, the submissions will go to the specified track. If APPEND
-is used, the existing TAG is used rather than creating a new one based
-on the current time stamp. If ``QUIET`` is used, CTest will suppress any
-non-error messages that it otherwise would have printed to the console.
-
-If the :variable:`CTEST_CHECKOUT_COMMAND` variable
-(or the :variable:`CTEST_CVS_CHECKOUT` variable)
-is set, its content is treated as command-line. The command is
-invoked with the current working directory set to the parent of the source
-directory, even if the source directory already exists. This can be used
-to create the source tree from a version control repository.
+after the binary directory is initialized.
+
+The parameters are as follows:
+
+``<model>``
+ Set the dashboard model. Must be one of ``Experimental``, ``Continuous``, or
+ ``Nightly``. This parameter is required unless ``APPEND`` is specified.
+
+``<source>``
+ Set the source directory. If not specified, the value of
+ :variable:`CTEST_SOURCE_DIRECTORY` is used instead.
+
+``<binary>``
+ Set the binary directory. If not specified, the value of
+ :variable:`CTEST_BINARY_DIRECTORY` is used instead.
+
+``TRACK <track>``
+ If ``TRACK`` is used, the submissions will go to the specified track on the
+ CDash server. If no ``TRACK`` is specified, the name of the model is used by
+ default.
+
+``APPEND``
+ If ``APPEND`` is used, the existing ``TAG`` is used rather than creating a new
+ one based on the current time stamp. If you use ``APPEND``, you can omit the
+ ``<model>`` and ``TRACK <track>`` parameters, because they will be read from
+ the generated ``TAG`` file. For example:
+
+ .. code-block:: cmake
+
+ ctest_start(Experimental TRACK TrackExperimental)
+
+ Later, in another ``ctest -S`` script:
+
+ .. code-block:: cmake
+
+ ctest_start(APPEND)
+
+ When the second script runs ``ctest_start(APPEND)``, it will read the
+ ``Experimental`` model and ``TrackExperimental`` track from the ``TAG`` file
+ generated by the first ``ctest_start()`` command. Please note that if you
+ call ``ctest_start(APPEND)`` and specify a different model or track than
+ in the first ``ctest_start()`` command, a warning will be issued, and the
+ new model and track will be used.
+
+``QUIET``
+ If ``QUIET`` is used, CTest will suppress any non-error messages that it
+ otherwise would have printed to the console.
+
+The parameters for ``ctest_start()`` can be issued in any order, with the
+exception that ``<model>``, ``<source>``, and ``<binary>`` have to appear
+in that order with respect to each other. The following are all valid and
+equivalent:
+
+.. code-block:: cmake
+
+ ctest_start(Experimental path/to/source path/to/binary TRACK SomeTrack QUIET APPEND)
+
+ ctest_start(TRACK SomeTrack Experimental QUIET path/to/source APPEND path/to/binary)
+
+ ctest_start(APPEND QUIET Experimental path/to/source TRACK SomeTrack path/to/binary)
+
+However, for the sake of readability, it is recommended that you order your
+parameters in the order listed at the top of this page.
+
+If the :variable:`CTEST_CHECKOUT_COMMAND` variable (or the
+:variable:`CTEST_CVS_CHECKOUT` variable) is set, its content is treated as
+command-line. The command is invoked with the current working directory set
+to the parent of the source directory, even if the source directory already
+exists. This can be used to create the source tree from a version control
+repository.
[QUIET])
This second signature is used to upload files to CDash via the CDash
-file upload API. The api first sends a request to upload to CDash along
+file upload API. The API first sends a request to upload to CDash along
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.
The required ``PROPERTY`` option is immediately followed by the name of
the property being defined.
-If the ``INHERITED`` option then the :command:`get_property` command will
-chain up to the next higher scope when the requested property is not set
-in the scope given to the command. ``DIRECTORY`` scope chains to
-``GLOBAL``. ``TARGET``, ``SOURCE``, and ``TEST`` chain to ``DIRECTORY``.
+If the ``INHERITED`` option is given, then the :command:`get_property` command
+will chain up to the next higher scope when the requested property is not set
+in the scope given to the command.
+
+* ``DIRECTORY`` scope chains to its parent directory's scope, continuing the
+ walk up parent directories until a directory has the property set or there
+ are no more parents. If still not found at the top level directory, it
+ chains to the ``GLOBAL`` scope.
+* ``TARGET``, ``SOURCE`` and ``TEST`` properties chain to ``DIRECTORY`` scope,
+ including further chaining up the directories, etc. as needed.
+
+Note that this scope chaining behavior only applies to calls to
+:command:`get_property`, :command:`get_directory_property`,
+:command:`get_target_property`, :command:`get_source_file_property` and
+:command:`get_test_property`. There is no inheriting behavior when *setting*
+properties, so using ``APPEND`` or ``APPEND_STRING`` with the
+:command:`set_property` command will not consider inherited values when working
+out the contents to append to.
The ``BRIEF_DOCS`` and ``FULL_DOCS`` options are followed by strings to be
associated with the property as its brief and full documentation.
but a target to which it links is not included the behavior is
unspecified.
+.. note::
+
+ :ref:`Object Libraries` under :generator:`Xcode` have special handling if
+ multiple architectures are listed in :variable:`CMAKE_OSX_ARCHITECTURES`.
+ In this case they will be exported as :ref:`Interface Libraries` with
+ no object files available to clients. This is sufficient to satisfy
+ transitive usage requirements of other targets that link to the
+ object libraries in their implementation.
+
::
export(PACKAGE <name>)
File manipulation command.
-------------------------------------------------------------------------------
+Synopsis
+^^^^^^^^
-::
+.. parsed-literal::
- file(WRITE <filename> <content>...)
- file(APPEND <filename> <content>...)
+ `Reading`_
+ file(`READ`_ <filename> <out-var> [...])
+ file(`STRINGS`_ <filename> <out-var> [...])
+ file(`\<HASH\> <HASH_>`_ <filename> <out-var>)
+ file(`TIMESTAMP`_ <filename> <out-var> [...])
-Write ``<content>`` into a file called ``<filename>``. If the file does
-not exist, it will be created. If the file already exists, ``WRITE``
-mode will overwrite it and ``APPEND`` mode will append to the end.
-Any directories in the path specified by ``<filename>`` that do not
-exist will be created.
+ `Writing`_
+ file({`WRITE`_ | `APPEND`_} <filename> <content>...)
+ file({`TOUCH`_ | `TOUCH_NOCREATE`_} [<file>...])
+ file(`GENERATE`_ OUTPUT <output-file> [...])
-If the file is a build input, use the :command:`configure_file` command
-to update the file only when its content changes.
+ `Filesystem`_
+ file({`GLOB`_ | `GLOB_RECURSE`_} <out-var> [...] [<globbing-expr>...])
+ file(`RENAME`_ <oldname> <newname>)
+ file({`REMOVE`_ | `REMOVE_RECURSE`_ } [<files>...])
+ file(`MAKE_DIRECTORY`_ [<dir>...])
+ file({`COPY`_ | `INSTALL`_} <file>... DESTINATION <dir> [...])
+
+ `Path Conversion`_
+ file(`RELATIVE_PATH`_ <out-var> <directory> <file>)
+ file({`TO_CMAKE_PATH`_ | `TO_NATIVE_PATH`_} <path> <out-var>)
+
+ `Transfer`_
+ file(`DOWNLOAD`_ <url> <file> [...])
+ file(`UPLOAD`_ <file> <url> [...])
+
+ `Locking`_
+ file(`LOCK`_ <path> [...])
+
+Reading
+^^^^^^^
-------------------------------------------------------------------------------
+.. _READ:
::
read at most ``<max-in>`` bytes. The ``HEX`` option causes data to
be converted to a hexadecimal representation (useful for binary data).
-------------------------------------------------------------------------------
+.. _STRINGS:
::
stores a list in the variable ``myfile`` in which each item is a line
from the input file.
-------------------------------------------------------------------------------
+.. _HASH:
::
are those listed by the :ref:`string(\<HASH\>) <Supported Hash Algorithms>`
command.
-------------------------------------------------------------------------------
+.. _TIMESTAMP:
+
+::
+
+ file(TIMESTAMP <filename> <variable> [<format>] [UTC])
+
+Compute a string representation of the modification time of ``<filename>``
+and store it in ``<variable>``. Should the command be unable to obtain a
+timestamp variable will be set to the empty string ("").
+
+See the :command:`string(TIMESTAMP)` command for documentation of
+the ``<format>`` and ``UTC`` options.
+
+Writing
+^^^^^^^
+
+.. _WRITE:
+.. _APPEND:
+
+::
+
+ file(WRITE <filename> <content>...)
+ file(APPEND <filename> <content>...)
+
+Write ``<content>`` into a file called ``<filename>``. If the file does
+not exist, it will be created. If the file already exists, ``WRITE``
+mode will overwrite it and ``APPEND`` mode will append to the end.
+Any directories in the path specified by ``<filename>`` that do not
+exist will be created.
+
+If the file is a build input, use the :command:`configure_file` command
+to update the file only when its content changes.
+
+.. _TOUCH:
+.. _TOUCH_NOCREATE:
+
+::
+
+ file(TOUCH [<files>...])
+ file(TOUCH_NOCREATE [<files>...])
+
+Create a file with no content if it does not yet exist. If the file already
+exists, its access and/or modification will be updated to the time when the
+function call is executed.
+
+Use TOUCH_NOCREATE to touch a file if it exists but not create it. If a file
+does not exist it will be silently ignored.
+
+With TOUCH and TOUCH_NOCREATE the contents of an existing file will not be
+modified.
+
+.. _GENERATE:
+
+::
+
+ file(GENERATE OUTPUT output-file
+ <INPUT input-file|CONTENT content>
+ [CONDITION expression])
+
+Generate an output file for each build configuration supported by the current
+:manual:`CMake Generator <cmake-generators(7)>`. Evaluate
+:manual:`generator expressions <cmake-generator-expressions(7)>`
+from the input content to produce the output content. The options are:
+
+``CONDITION <condition>``
+ Generate the output file for a particular configuration only if
+ the condition is true. The condition must be either ``0`` or ``1``
+ after evaluating generator expressions.
+
+``CONTENT <content>``
+ Use the content given explicitly as input.
+
+``INPUT <input-file>``
+ Use the content from a given file as input.
+ A relative path is treated with respect to the value of
+ :variable:`CMAKE_CURRENT_SOURCE_DIR`. See policy :policy:`CMP0070`.
+
+``OUTPUT <output-file>``
+ Specify the output file name to generate. Use generator expressions
+ such as ``$<CONFIG>`` to specify a configuration-specific output file
+ name. Multiple configurations may generate the same output file only
+ if the generated content is identical. Otherwise, the ``<output-file>``
+ must evaluate to an unique name for each configuration.
+ A relative path (after evaluating generator expressions) is treated
+ with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
+ See policy :policy:`CMP0070`.
+
+Exactly one ``CONTENT`` or ``INPUT`` option must be given. A specific
+``OUTPUT`` file may be named by at most one invocation of ``file(GENERATE)``.
+Generated files are modified and their timestamp updated on subsequent cmake
+runs only if their content is changed.
+
+Note also that ``file(GENERATE)`` does not create the output file until the
+generation phase. The output file will not yet have been written when the
+``file(GENERATE)`` command returns, it is written only after processing all
+of a project's ``CMakeLists.txt`` files.
+
+Filesystem
+^^^^^^^^^^
+
+.. _GLOB:
+.. _GLOB_RECURSE:
::
file(GLOB <variable>
- [LIST_DIRECTORIES true|false] [RELATIVE <path>]
+ [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
[<globbing-expressions>...])
file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS]
- [LIST_DIRECTORIES true|false] [RELATIVE <path>]
+ [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
[<globbing-expressions>...])
Generate a list of files that match the ``<globbing-expressions>`` and
specified, the results will be returned as relative paths to the given
path. The results will be ordered lexicographically.
+If the ``CONFIGURE_DEPENDS`` flag is specified, CMake will add logic
+to the main build system check target to rerun the flagged ``GLOB`` commands
+at build time. If any of the outputs change, CMake will regenerate the build
+system.
+
By default ``GLOB`` lists directories - directories are omitted in result if
``LIST_DIRECTORIES`` is set to false.
your source tree. If no CMakeLists.txt file changes when a source is
added or removed then the generated build system cannot know when to
ask CMake to regenerate.
+ The ``CONFIGURE_DEPENDS`` flag may not work reliably on all generators, or if
+ a new generator is added in the future that cannot support it, projects using
+ it will be stuck. Even if ``CONFIGURE_DEPENDS`` works reliably, there is
+ still a cost to perform the check on every rebuild.
Examples of globbing expressions include::
/dir/*.py - match all python files in /dir and subdirectories
-------------------------------------------------------------------------------
+.. _RENAME:
::
Move a file or directory within a filesystem from ``<oldname>`` to
``<newname>``, replacing the destination atomically.
-------------------------------------------------------------------------------
+.. _REMOVE:
+.. _REMOVE_RECURSE:
::
files and directories, also non-empty directories. No error is emitted if a
given file does not exist.
-------------------------------------------------------------------------------
+.. _MAKE_DIRECTORY:
::
Create the given directories and their parents as needed.
-------------------------------------------------------------------------------
+.. _COPY:
+.. _INSTALL:
+
+::
+
+ file(<COPY|INSTALL> <files>... DESTINATION <dir>
+ [FILE_PERMISSIONS <permissions>...]
+ [DIRECTORY_PERMISSIONS <permissions>...]
+ [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
+ [FILES_MATCHING]
+ [[PATTERN <pattern> | REGEX <regex>]
+ [EXCLUDE] [PERMISSIONS <permissions>...]] [...])
+
+The ``COPY`` signature copies files, directories, and symlinks to a
+destination folder. Relative input paths are evaluated with respect
+to the current source directory, and a relative destination is
+evaluated with respect to the current build directory. Copying
+preserves input file timestamps, and optimizes out a file if it exists
+at the destination with the same timestamp. Copying preserves input
+permissions unless explicit permissions or ``NO_SOURCE_PERMISSIONS``
+are given (default is ``USE_SOURCE_PERMISSIONS``).
+
+See the :command:`install(DIRECTORY)` command for documentation of
+permissions, ``FILES_MATCHING``, ``PATTERN``, ``REGEX``, and
+``EXCLUDE`` options. Copying directories preserves the structure
+of their content even if options are used to select a subset of
+files.
+
+The ``INSTALL`` signature differs slightly from ``COPY``: it prints
+status messages (subject to the :variable:`CMAKE_INSTALL_MESSAGE` variable),
+and ``NO_SOURCE_PERMISSIONS`` is default.
+Installation scripts generated by the :command:`install` command
+use this signature (with some undocumented options for internal use).
+
+Path Conversion
+^^^^^^^^^^^^^^^
+
+.. _RELATIVE_PATH:
::
Compute the relative path from a ``<directory>`` to a ``<file>`` and
store it in the ``<variable>``.
-------------------------------------------------------------------------------
+.. _TO_CMAKE_PATH:
+.. _TO_NATIVE_PATH:
::
Always use double quotes around the ``<path>`` to be sure it is treated
as a single argument to this command.
-------------------------------------------------------------------------------
+Transfer
+^^^^^^^^
+
+.. _DOWNLOAD:
+.. _UPLOAD:
::
If neither ``TLS`` option is given CMake will check variables
``CMAKE_TLS_VERIFY`` and ``CMAKE_TLS_CAINFO``, respectively.
-------------------------------------------------------------------------------
-
-::
-
- file(TIMESTAMP <filename> <variable> [<format>] [UTC])
-
-Compute a string representation of the modification time of ``<filename>``
-and store it in ``<variable>``. Should the command be unable to obtain a
-timestamp variable will be set to the empty string ("").
-
-See the :command:`string(TIMESTAMP)` command for documentation of
-the ``<format>`` and ``UTC`` options.
-
-------------------------------------------------------------------------------
-
-::
-
- file(GENERATE OUTPUT output-file
- <INPUT input-file|CONTENT content>
- [CONDITION expression])
-
-Generate an output file for each build configuration supported by the current
-:manual:`CMake Generator <cmake-generators(7)>`. Evaluate
-:manual:`generator expressions <cmake-generator-expressions(7)>`
-from the input content to produce the output content. The options are:
-
-``CONDITION <condition>``
- Generate the output file for a particular configuration only if
- the condition is true. The condition must be either ``0`` or ``1``
- after evaluating generator expressions.
-
-``CONTENT <content>``
- Use the content given explicitly as input.
-
-``INPUT <input-file>``
- Use the content from a given file as input.
- A relative path is treated with respect to the value of
- :variable:`CMAKE_CURRENT_SOURCE_DIR`. See policy :policy:`CMP0070`.
-
-``OUTPUT <output-file>``
- Specify the output file name to generate. Use generator expressions
- such as ``$<CONFIG>`` to specify a configuration-specific output file
- name. Multiple configurations may generate the same output file only
- if the generated content is identical. Otherwise, the ``<output-file>``
- must evaluate to an unique name for each configuration.
- A relative path (after evaluating generator expressions) is treated
- with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
- See policy :policy:`CMP0070`.
-
-Exactly one ``CONTENT`` or ``INPUT`` option must be given. A specific
-``OUTPUT`` file may be named by at most one invocation of ``file(GENERATE)``.
-Generated files are modified and their timestamp updated on subsequent cmake
-runs only if their content is changed.
-
-Note also that ``file(GENERATE)`` does not create the output file until the
-generation phase. The output file will not yet have been written when the
-``file(GENERATE)`` command returns, it is written only after processing all
-of a project's ``CMakeLists.txt`` files.
-
-------------------------------------------------------------------------------
-
-::
-
- file(<COPY|INSTALL> <files>... DESTINATION <dir>
- [FILE_PERMISSIONS <permissions>...]
- [DIRECTORY_PERMISSIONS <permissions>...]
- [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
- [FILES_MATCHING]
- [[PATTERN <pattern> | REGEX <regex>]
- [EXCLUDE] [PERMISSIONS <permissions>...]] [...])
-
-The ``COPY`` signature copies files, directories, and symlinks to a
-destination folder. Relative input paths are evaluated with respect
-to the current source directory, and a relative destination is
-evaluated with respect to the current build directory. Copying
-preserves input file timestamps, and optimizes out a file if it exists
-at the destination with the same timestamp. Copying preserves input
-permissions unless explicit permissions or ``NO_SOURCE_PERMISSIONS``
-are given (default is ``USE_SOURCE_PERMISSIONS``).
-
-See the :command:`install(DIRECTORY)` command for documentation of
-permissions, ``FILES_MATCHING``, ``PATTERN``, ``REGEX``, and
-``EXCLUDE`` options. Copying directories preserves the structure
-of their content even if options are used to select a subset of
-files.
-
-The ``INSTALL`` signature differs slightly from ``COPY``: it prints
-status messages (subject to the :variable:`CMAKE_INSTALL_MESSAGE` variable),
-and ``NO_SOURCE_PERMISSIONS`` is default.
-Installation scripts generated by the :command:`install` command
-use this signature (with some undocumented options for internal use).
+Locking
+^^^^^^^
-------------------------------------------------------------------------------
+.. _LOCK:
::
.. |prefix_XXX_SUBDIR| replace:: ``<prefix>/include``
.. |entry_XXX_SUBDIR| replace:: ``<entry>/include``
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+ ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
+ is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_PREFIX_PATH_XXX| replace::
``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
is set, and |CMAKE_PREFIX_PATH_XXX_SUBDIR|
.. |prefix_XXX_SUBDIR| replace:: ``<prefix>/lib``
.. |entry_XXX_SUBDIR| replace:: ``<entry>/lib``
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+ ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set,
+ and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_PREFIX_PATH_XXX| replace::
``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set,
and |CMAKE_PREFIX_PATH_XXX_SUBDIR|
[PATHS path1 [path2 ... ]]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[NO_DEFAULT_PATH]
+ [NO_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
<prefix>/(cmake|CMake)/ (W)
<prefix>/<name>*/ (W)
<prefix>/<name>*/(cmake|CMake)/ (W)
- <prefix>/(lib/<arch>|lib|share)/cmake/<name>*/ (U)
- <prefix>/(lib/<arch>|lib|share)/<name>*/ (U)
- <prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (U)
- <prefix>/<name>*/(lib/<arch>|lib|share)/cmake/<name>*/ (W/U)
- <prefix>/<name>*/(lib/<arch>|lib|share)/<name>*/ (W/U)
- <prefix>/<name>*/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (W/U)
+ <prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/ (U)
+ <prefix>/(lib/<arch>|lib*|share)/<name>*/ (U)
+ <prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (U)
+ <prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/ (W/U)
+ <prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/ (W/U)
+ <prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (W/U)
On systems supporting OS X Frameworks and Application Bundles the
following directories are searched for frameworks or bundles
In all cases the ``<name>`` is treated as case-insensitive and corresponds
to any of the names specified (``<package>`` or names given by ``NAMES``).
+
Paths with ``lib/<arch>`` are enabled if the
-:variable:`CMAKE_LIBRARY_ARCHITECTURE` variable is set. If ``PATH_SUFFIXES``
-is specified the suffixes are appended to each (W) or (U) directory entry
-one-by-one.
+:variable:`CMAKE_LIBRARY_ARCHITECTURE` variable is set. ``lib*`` includes one
+or more of the values ``lib64``, ``lib32``, ``libx32`` or ``lib`` (searched in
+that order).
+
+* Paths with ``lib64`` are searched on 64 bit platforms if the
+ :prop_gbl:`FIND_LIBRARY_USE_LIB64_PATHS` property is set to ``TRUE``.
+* Paths with ``lib32`` are searched on 32 bit platforms if the
+ :prop_gbl:`FIND_LIBRARY_USE_LIB32_PATHS` property is set to ``TRUE``.
+* Paths with ``libx32`` are searched on platforms using the x32 ABI
+ if the :prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS` property is set to ``TRUE``.
+* The ``lib`` path is always searched.
+
+If ``PATH_SUFFIXES`` is specified, the suffixes are appended to each
+(W) or (U) directory entry one-by-one.
This set of directories is intended to work in cooperation with
projects that provide configuration files in their installation trees.
steps. If ``NO_DEFAULT_PATH`` is specified all ``NO_*`` options are
enabled.
-1. Search paths specified in cmake-specific cache variables. These
+1. Search paths specified in the ``PackageName_ROOT`` CMake and environment
+ variables. The package root variables are maintained as a stack so if
+ called from within a find module, root paths from the parent's find
+ module will also be searched after paths for the current package.
+ This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed.
+ See policy :policy:`CMP0074`.
+
+2. Search paths specified in cmake-specific cache variables. These
are intended to be used on the command line with a ``-DVAR=value``.
The values are interpreted as :ref:`;-lists <CMake Language Lists>`.
This can be skipped if ``NO_CMAKE_PATH`` is passed::
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
-2. Search paths specified in cmake-specific environment variables.
+3. Search paths specified in cmake-specific environment variables.
These are intended to be set in the user's shell configuration,
and therefore use the host's native path separator
(``;`` on Windows and ``:`` on UNIX).
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
-3. Search paths specified by the ``HINTS`` option. These should be paths
+4. Search paths specified by the ``HINTS`` option. These should be paths
computed by system introspection, such as a hint provided by the
location of another item already found. Hard-coded guesses should
be specified with the ``PATHS`` option.
-4. Search the standard system environment variables. This can be
+5. Search the standard system environment variables. This can be
skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed. Path entries
ending in ``/bin`` or ``/sbin`` are automatically converted to their
parent directories::
PATH
-5. Search paths stored in the CMake :ref:`User Package Registry`.
+6. Search paths stored in the CMake :ref:`User Package Registry`.
This can be skipped if ``NO_CMAKE_PACKAGE_REGISTRY`` is passed or by
setting the :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`
to ``TRUE``.
See the :manual:`cmake-packages(7)` manual for details on the user
package registry.
-6. Search cmake variables defined in the Platform files for the
+7. Search cmake variables defined in the Platform files for the
current system. This can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is
passed::
CMAKE_SYSTEM_FRAMEWORK_PATH
CMAKE_SYSTEM_APPBUNDLE_PATH
-7. Search paths stored in the CMake :ref:`System Package Registry`.
+8. Search paths stored in the CMake :ref:`System Package Registry`.
This can be skipped if ``NO_CMAKE_SYSTEM_PACKAGE_REGISTRY`` is passed
or by setting the
:variable:`CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY` to ``TRUE``.
See the :manual:`cmake-packages(7)` manual for details on the system
package registry.
-8. Search paths specified by the ``PATHS`` option. These are typically
+9. Search paths specified by the ``PATHS`` option. These are typically
hard-coded guesses.
.. |FIND_XXX| replace:: find_package
.. |prefix_XXX_SUBDIR| replace:: ``<prefix>/include``
.. |entry_XXX_SUBDIR| replace:: ``<entry>/include``
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+ ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
+ is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_PREFIX_PATH_XXX| replace::
``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
is set, and |CMAKE_PREFIX_PATH_XXX_SUBDIR|
.. |prefix_XXX_SUBDIR| replace:: ``<prefix>/[s]bin``
.. |entry_XXX_SUBDIR| replace:: ``<entry>/[s]bin``
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+ |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_PREFIX_PATH_XXX| replace::
|CMAKE_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_PROGRAM_PATH`
get_directory_property(<variable> [DIRECTORY <dir>] <prop-name>)
-Store a property of directory scope in the named variable. If the
-property is not defined the empty-string is returned. The ``DIRECTORY``
-argument specifies another directory from which to retrieve the
-property value. The specified directory must have already been
-traversed by CMake.
+Store a property of directory scope in the named ``<variable>``.
+The ``DIRECTORY`` argument specifies another directory from which
+to retrieve the property value instead of the current directory.
+The specified directory must have already been traversed by CMake.
+
+If the property is not defined for the nominated directory scope,
+an empty string is returned. In the case of ``INHERITED`` properties,
+if the property is not found for the nominated directory scope,
+the search will chain to a parent scope as described for the
+:command:`define_property` command.
::
provided, the default base directory will be
:variable:`CMAKE_CURRENT_SOURCE_DIR`.
-Paths are returned with forward slashes and have no trailing slahes. If the
+Paths are returned with forward slashes and have no trailing slashes. If the
optional ``CACHE`` argument is specified, the result variable is added to the
cache.
The required ``PROPERTY`` option is immediately followed by the name of
the property to get. If the property is not set an empty value is
-returned. If the ``SET`` option is given the variable is set to a boolean
+returned, although some properties support inheriting from a parent scope
+if defined to behave that way (see :command:`define_property`).
+
+If the ``SET`` option is given the variable is set to a boolean
value indicating whether the property has been set. If the ``DEFINED``
option is given the variable is set to a boolean value indicating
whether the property has been defined such as with the
get_source_file_property(VAR file property)
Get a property from a source file. The value of the property is
-stored in the variable ``VAR``. If the property is not found, ``VAR``
-will be set to "NOTFOUND". Use :command:`set_source_files_properties`
-to set property values. Source file properties usually control how the
-file is built. One property that is always there is :prop_sf:`LOCATION`
+stored in the variable ``VAR``. If the source property is not found, the
+behavior depends on whether it has been defined to be an ``INHERITED`` property
+or not (see :command:`define_property`). Non-inherited properties will set
+``VAR`` to "NOTFOUND", whereas inherited properties will search the relevant
+parent scope as described for the :command:`define_property` command and
+if still unable to find the property, ``VAR`` will be set to an empty string.
+
+Use :command:`set_source_files_properties` to set property values. Source
+file properties usually control how the file is built. One property that is
+always there is :prop_sf:`LOCATION`.
See also the more general :command:`get_property` command.
get_target_property(VAR target property)
Get a property from a target. The value of the property is stored in
-the variable ``VAR``. If the property is not found, ``VAR`` will be set to
-"NOTFOUND". Use :command:`set_target_properties` to set property values.
+the variable ``VAR``. If the target property is not found, the behavior
+depends on whether it has been defined to be an ``INHERITED`` property
+or not (see :command:`define_property`). Non-inherited properties will
+set ``VAR`` to "NOTFOUND", whereas inherited properties will search the
+relevant parent scope as described for the :command:`define_property`
+command and if still unable to find the property, ``VAR`` will be set to
+an empty string.
+
+Use :command:`set_target_properties` to set target property values.
Properties are usually used to control how a target is built, but some
query the target instead. This command can get properties for any
target so far created. The targets do not need to be in the current
get_test_property(test property VAR)
Get a property from the test. The value of the property is stored in
-the variable ``VAR``. If the test or property is not found, ``VAR`` will
-be set to "NOTFOUND". For a list of standard properties you can type
-``cmake --help-property-list``.
+the variable ``VAR``. If the test property is not found, the behavior
+depends on whether it has been defined to be an ``INHERITED`` property
+or not (see :command:`define_property`). Non-inherited properties will
+set ``VAR`` to "NOTFOUND", whereas inherited properties will search the
+relevant parent scope as described for the :command:`define_property`
+command and if still unable to find the property, ``VAR`` will be set to
+an empty string.
+
+For a list of standard properties you can type ``cmake --help-property-list``.
See also the more general :command:`get_property` command.
install
-------
-.. only:: html
+Specify rules to run at install time.
- .. contents::
+Synopsis
+^^^^^^^^
-Specify rules to run at install time.
+.. parsed-literal::
+
+ install(`TARGETS`_ <target>... [...])
+ install({`FILES`_ | `PROGRAMS`_} <file>... DESTINATION <dir> [...])
+ install(`DIRECTORY`_ <dir>... DESTINATION <dir> [...])
+ install(`SCRIPT`_ <file> [...])
+ install(`CODE`_ <code> [...])
+ install(`EXPORT`_ <export-name> DESTINATION <dir> [...])
Introduction
^^^^^^^^^^^^
Installing Targets
^^^^^^^^^^^^^^^^^^
+.. _TARGETS:
+
::
install(TARGETS targets... [EXPORT <export-name>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
+ [NAMELINK_COMPONENT <component>]
[OPTIONAL] [EXCLUDE_FROM_ALL]
[NAMELINK_ONLY|NAMELINK_SKIP]
] [...]
)
The ``TARGETS`` form specifies rules for installing targets from a
-project. There are six kinds of target files that may be installed:
-``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``OBJECTS``, ``FRAMEWORK``, and
-``BUNDLE``. Executables are treated as ``RUNTIME`` targets, except that
-those marked with the ``MACOSX_BUNDLE`` property are treated as ``BUNDLE``
-targets on OS X. Static libraries are treated as ``ARCHIVE`` targets,
-except that those marked with the ``FRAMEWORK`` property are treated
-as ``FRAMEWORK`` targets on OS X.
-Module libraries are always treated as ``LIBRARY`` targets.
-For non-DLL platforms shared libraries are treated as ``LIBRARY``
-targets, except that those marked with the ``FRAMEWORK`` property are
-treated as ``FRAMEWORK`` targets on OS X. For DLL platforms the DLL
-part of a shared library is treated as a ``RUNTIME`` target and the
-corresponding import library is treated as an ``ARCHIVE`` target.
-All Windows-based systems including Cygwin are DLL platforms. Object
-libraries are always treated as ``OBJECTS`` targets.
-The ``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``OBJECTS``, and ``FRAMEWORK``
-arguments change the type of target to which the subsequent properties
-apply. If none is given the installation properties apply to all target
-types. If only one is given then only targets of that type will be
-installed (which can be used to install just a DLL or just an import
-library).
-
-The ``PRIVATE_HEADER``, ``PUBLIC_HEADER``, and ``RESOURCE`` arguments
-cause subsequent properties to be applied to installing a ``FRAMEWORK``
-shared library target's associated files on non-Apple platforms. Rules
-defined by these arguments are ignored on Apple platforms because the
-associated files are installed into the appropriate locations inside
-the framework folder. See documentation of the
-:prop_tgt:`PRIVATE_HEADER`, :prop_tgt:`PUBLIC_HEADER`, and
-:prop_tgt:`RESOURCE` target properties for details.
-
-Either ``NAMELINK_ONLY`` or ``NAMELINK_SKIP`` may be specified as a
-``LIBRARY`` option. On some platforms a versioned shared library
-has a symbolic link such as::
-
- lib<name>.so -> lib<name>.so.1
-
-where ``lib<name>.so.1`` is the soname of the library and ``lib<name>.so``
-is a "namelink" allowing linkers to find the library when given
-``-l<name>``. The ``NAMELINK_ONLY`` option causes installation of only the
-namelink when a library target is installed. The ``NAMELINK_SKIP`` option
-causes installation of library files other than the namelink when a
-library target is installed. When neither option is given both
-portions are installed. On platforms where versioned shared libraries
-do not have namelinks or when a library is not versioned the
-``NAMELINK_SKIP`` option installs the library and the ``NAMELINK_ONLY``
-option installs nothing. See the :prop_tgt:`VERSION` and
-:prop_tgt:`SOVERSION` target properties for details on creating versioned
-shared libraries.
-
-The ``INCLUDES DESTINATION`` specifies a list of directories
-which will be added to the :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`
-target property of the ``<targets>`` when exported by the
-:command:`install(EXPORT)` command. If a relative path is
-specified, it is treated as relative to the ``$<INSTALL_PREFIX>``.
-This is independent of the rest of the argument groups and does
-not actually install anything.
+project. There are several kinds of target files that may be installed:
+
+``ARCHIVE``
+ Static libraries are treated as ``ARCHIVE`` targets, except those
+ marked with the ``FRAMEWORK`` property on OS X (see ``FRAMEWORK``
+ below.) For DLL platforms (all Windows-based systems including
+ Cygwin), the DLL import library is treated as an ``ARCHIVE`` target.
+
+``LIBRARY``
+ Module libraries are always treated as ``LIBRARY`` targets. For non-
+ DLL platforms shared libraries are treated as ``LIBRARY`` targets,
+ except those marked with the ``FRAMEWORK`` property on OS X (see
+ ``FRAMEWORK`` below.)
+
+``RUNTIME``
+ Executables are treated as ``RUNTIME`` objects, except those marked
+ with the ``MACOSX_BUNDLE`` property on OS X (see ``BUNDLE`` below.)
+ For DLL platforms (all Windows-based systems including Cygwin), the
+ DLL part of a shared library is treated as a ``RUNTIME`` target.
+
+``OBJECTS``
+ Object libraries (a simple group of object files) are always treated
+ as ``OBJECTS`` targets.
+
+``FRAMEWORK``
+ Both static and shared libraries marked with the ``FRAMEWORK``
+ property are treated as ``FRAMEWORK`` targets on OS X.
+
+``BUNDLE``
+ Executables marked with the ``MACOSX_BUNDLE`` property are treated as
+ ``BUNDLE`` targets on OS X.
+
+``PUBLIC_HEADER``
+ Any ``PUBLIC_HEADER`` files associated with a library are installed in
+ the destination specified by the ``PUBLIC_HEADER`` argument on non-Apple
+ platforms. Rules defined by this argument are ignored for ``FRAMEWORK``
+ libraries on Apple platforms because the associated files are installed
+ into the appropriate locations inside the framework folder. See
+ :prop_tgt:`PUBLIC_HEADER` for details.
+
+``PRIVATE_HEADER``
+ Similar to ``PUBLIC_HEADER``, but for ``PRIVATE_HEADER`` files. See
+ :prop_tgt:`PRIVATE_HEADER` for details.
+
+``RESOURCE``
+ Similar to ``PUBLIC_HEADER`` and ``PRIVATE_HEADER``, but for
+ ``RESOURCE`` files. See :prop_tgt:`RESOURCE` for details.
+
+For each of these arguments given, the arguments following them only apply
+to the target or file type specified in the argument. If none is given, the
+installation properties apply to all target types. If only one is given then
+only targets of that type will be installed (which can be used to install
+just a DLL or just an import library.)
+
+In addition to the common options listed above, each target can accept
+the following additional arguments:
+
+``NAMELINK_COMPONENT``
+ On some platforms a versioned shared library has a symbolic link such
+ as::
+
+ lib<name>.so -> lib<name>.so.1
+
+ where ``lib<name>.so.1`` is the soname of the library and ``lib<name>.so``
+ is a "namelink" allowing linkers to find the library when given
+ ``-l<name>``. The ``NAMELINK_COMPONENT`` option is similar to the
+ ``COMPONENT`` option, but it changes the installation component of a shared
+ library namelink if one is generated. If not specified, this defaults to the
+ value of ``COMPONENT``. It is an error to use this parameter outside of a
+ ``LIBRARY`` block.
+
+ Consider the following example:
+
+ .. code-block:: cmake
+
+ install(TARGETS mylib
+ LIBRARY
+ DESTINATION lib
+ COMPONENT Libraries
+ NAMELINK_COMPONENT Development
+ PUBLIC_HEADER
+ DESTINATION include
+ COMPONENT Development
+ )
+
+ In this scenario, if you choose to install only the ``Development``
+ component, both the headers and namelink will be installed without the
+ library. (If you don't also install the ``Libraries`` component, the
+ namelink will be a dangling symlink, and projects that link to the library
+ will have build errors.) If you install only the ``Libraries`` component,
+ only the library will be installed, without the headers and namelink.
+
+ This option is typically used for package managers that have separate
+ runtime and development packages. For example, on Debian systems, the
+ library is expected to be in the runtime package, and the headers and
+ namelink are expected to be in the development package.
+
+ See the :prop_tgt:`VERSION` and :prop_tgt:`SOVERSION` target properties for
+ details on creating versioned shared libraries.
+
+``NAMELINK_ONLY``
+ This option causes the installation of only the namelink when a library
+ target is installed. On platforms where versioned shared libraries do not
+ have namelinks or when a library is not versioned, the ``NAMELINK_ONLY``
+ option installs nothing. It is an error to use this parameter outside of a
+ ``LIBRARY`` block.
+
+ When ``NAMELINK_ONLY`` is given, either ``NAMELINK_COMPONENT`` or
+ ``COMPONENT`` may be used to specify the installation component of the
+ namelink, but ``COMPONENT`` should generally be preferred.
+
+``NAMELINK_SKIP``
+ Similar to ``NAMELINK_ONLY``, but it has the opposite effect: it causes the
+ installation of library files other than the namelink when a library target
+ is installed. When neither ``NAMELINK_ONLY`` or ``NAMELINK_SKIP`` are given,
+ both portions are installed. On platforms where versioned shared libraries
+ do not have symlinks or when a library is not versioned, ``NAMELINK_SKIP``
+ installs the library. It is an error to use this parameter outside of a
+ ``LIBRARY`` block.
+
+ If ``NAMELINK_SKIP`` is specified, ``NAMELINK_COMPONENT`` has no effect. It
+ is not recommended to use ``NAMELINK_SKIP`` in conjunction with
+ ``NAMELINK_COMPONENT``.
+
+The ``install(TARGETS)`` command can also accept the following options at the
+top level:
+
+``EXPORT``
+ This option associates the installed target files with an export called
+ ``<export-name>``. It must appear before any target options. To actually
+ install the export file itself, call ``install(EXPORT)``, documented below.
+
+``INCLUDES DESTINATION``
+ This option specifies a list of directories which will be added to the
+ :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` target property of the
+ ``<targets>`` when exported by the :command:`install(EXPORT)` command. If a
+ relative path is specified, it is treated as relative to the
+ ``$<INSTALL_PREFIX>``.
One or more groups of properties may be specified in a single call to
the ``TARGETS`` form of this command. A target may be installed more than
``/some/full/path`` and its import library will be installed to
``<prefix>/lib/static`` and ``/some/full/path``.
-The ``EXPORT`` option associates the installed target files with an
-export called ``<export-name>``. It must appear before any ``RUNTIME``,
-``LIBRARY``, ``ARCHIVE``, or ``OBJECTS`` options. To actually install the
-export file itself, call ``install(EXPORT)``, documented below.
+:ref:`Interface Libraries` may be listed among the targets to install.
+They install no artifacts but will be included in an associated ``EXPORT``.
+If :ref:`Object Libraries` are listed but given no destination for their
+object files, they will be exported as :ref:`Interface Libraries`.
+This is sufficient to satisfy transitive usage requirements of other
+targets that link to the object libraries in their implementation.
Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property
set to ``TRUE`` has undefined behavior.
Installing Files
^^^^^^^^^^^^^^^^
+.. _FILES:
+.. _PROGRAMS:
+
::
install(<FILES|PROGRAMS> files... DESTINATION <dir>
Installing Directories
^^^^^^^^^^^^^^^^^^^^^^
+.. _DIRECTORY:
+
::
install(DIRECTORY dirs... DESTINATION <dir>
Custom Installation Logic
^^^^^^^^^^^^^^^^^^^^^^^^^
+.. _CODE:
+.. _SCRIPT:
+
::
install([[SCRIPT <file>] [CODE <code>]]
Installing Exports
^^^^^^^^^^^^^^^^^^
+.. _EXPORT:
+
::
install(EXPORT <export-name> DESTINATION <dir>
[NAMESPACE <namespace>] [[FILE <name>.cmake]|
- [EXPORT_ANDROID_MK <name>.mk]]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[EXPORT_LINK_INTERFACE_LIBRARIES]
[COMPONENT <component>]
[EXCLUDE_FROM_ALL])
+ install(EXPORT_ANDROID_MK <export-name> DESTINATION <dir> [...])
The ``EXPORT`` form generates and installs a CMake file containing code to
import targets from the installation tree into another project.
configurations. The ``EXPORT_LINK_INTERFACE_LIBRARIES`` keyword, if
present, causes the contents of the properties matching
``(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?`` to be exported, when
-policy :policy:`CMP0022` is ``NEW``. If a ``COMPONENT`` option is
-specified that does not match that given to the targets associated with
-``<export-name>`` the behavior is undefined. If a library target is
-included in the export but a target to which it links is not included
-the behavior is unspecified.
-
-In addition to cmake language files, the ``EXPORT_ANDROID_MK`` option maybe
-used to specify an export to the android ndk build system. The Android
+policy :policy:`CMP0022` is ``NEW``.
+
+When a ``COMPONENT`` option is given, the listed ``<component>`` implicitly
+depends on all components mentioned in the export set. The exported
+``<name>.cmake`` file will require each of the exported components to be
+present in order for dependent projects to build properly. For example, a
+project may define components ``Runtime`` and ``Development``, with shared
+libraries going into the ``Runtime`` component and static libraries and
+headers going into the ``Development`` component. The export set would also
+typically be part of the ``Development`` component, but it would export
+targets from both the ``Runtime`` and ``Development`` components. Therefore,
+the ``Runtime`` component would need to be installed if the ``Development``
+component was installed, but not vice versa. If the ``Development`` component
+was installed without the ``Runtime`` component, dependent projects that try
+to link against it would have build errors. Package managers, such as APT and
+RPM, typically handle this by listing the ``Runtime`` component as a dependency
+of the ``Development`` component in the package metadata, ensuring that the
+library is always installed if the headers and CMake export file are present.
+
+In addition to cmake language files, the ``EXPORT_ANDROID_MK`` mode maybe
+used to specify an export to the android ndk build system. This mode
+accepts the same options as the normal export mode. The Android
NDK supports the use of prebuilt libraries, both static and shared. This
allows cmake to build the libraries of a project and make them available
to an ndk build system complete with transitive dependencies, include flags
will install the executable myexe to ``<prefix>/bin`` and code to import
it in the file ``<prefix>/lib/myproj/myproj.cmake`` and
-``<prefix>/lib/share/ndk-modules/Android.mk``. An outside project
+``<prefix>/share/ndk-modules/Android.mk``. An outside project
may load this file with the include command and reference the ``myexe``
executable from the installation tree using the imported target name
``mp_myexe`` as if the target were built in its own tree.
those generated by :command:`install_targets`,
:command:`install_files`, and :command:`install_programs` commands
is not defined.
+
+Generated Installation Script
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``install()`` command generates a file, ``cmake_install.cmake``, inside
+the build directory, which is used internally by the generated install target
+and by CPack. You can also invoke this script manually with ``cmake -P``. This
+script accepts several variables:
+
+``COMPONENT``
+ Set this variable to install only a single CPack component as opposed to all
+ of them. For example, if you only want to install the ``Development``
+ component, run ``cmake -DCOMPONENT=Development -P cmake_install.cmake``.
+
+``BUILD_TYPE``
+ Set this variable to change the build type if you are using a multi-config
+ generator. For example, to install with the ``Debug`` configuration, run
+ ``cmake -DBUILD_TYPE=Debug -P cmake_install.cmake``.
+
+``DESTDIR``
+ This is an environment variable rather than a CMake variable. It allows you
+ to change the installation prefix on UNIX systems. See :envvar:`DESTDIR` for
+ details.
List operations.
+Synopsis
+^^^^^^^^
+
+.. parsed-literal::
+
+ `Reading`_
+ list(`LENGTH`_ <list> <out-var>)
+ list(`GET`_ <list> <element index> [<index> ...] <out-var>)
+ list(`JOIN`_ <list> <glue> <out-var>)
+ list(`SUBLIST`_ <list> <begin> <length> <out-var>)
+
+ `Search`_
+ list(`FIND`_ <list> <value> <out-var>)
+
+ `Modification`_
+ list(`APPEND`_ <list> [<element>...])
+ list(`FILTER`_ <list> {INCLUDE | EXCLUDE} REGEX <regex>)
+ list(`INSERT`_ <list> <index> [<element>...])
+ list(`REMOVE_ITEM`_ <list> <value>...)
+ list(`REMOVE_AT`_ <list> <index>...)
+ list(`REMOVE_DUPLICATES`_ <list>)
+ list(`TRANSFORM`_ <list> <ACTION> [...])
+
+ `Ordering`_
+ list(`REVERSE`_ <list>)
+ list(`SORT`_ <list>)
+
+Introduction
+^^^^^^^^^^^^
+
+The list subcommands ``APPEND``, ``INSERT``, ``FILTER``, ``REMOVE_AT``,
+``REMOVE_ITEM``, ``REMOVE_DUPLICATES``, ``REVERSE`` and ``SORT`` may create
+new values for the list within the current CMake variable scope. Similar to
+the :command:`set` command, the LIST command creates new variable values in
+the current scope, even if the list itself is actually defined in a parent
+scope. To propagate the results of these operations upwards, use
+:command:`set` with ``PARENT_SCOPE``, :command:`set` with
+``CACHE INTERNAL``, or some other means of value propagation.
+
+.. note::
+
+ A list in cmake is a ``;`` separated group of strings. To create a
+ list the set command can be used. For example, ``set(var a b c d e)``
+ creates a list with ``a;b;c;d;e``, and ``set(var "a b c d e")`` creates a
+ string or a list with one item in it. (Note macro arguments are not
+ variables, and therefore cannot be used in LIST commands.)
+
+.. note::
+
+ When specifying index values, if ``<element index>`` is 0 or greater, it
+ is indexed from the beginning of the list, with 0 representing the
+ first list element. If ``<element index>`` is -1 or lesser, it is indexed
+ from the end of the list, with -1 representing the last list element.
+ Be careful when counting with negative indices: they do not start from
+ 0. -0 is equivalent to 0, the first list element.
+
+Reading
+^^^^^^^
+
+.. _LENGTH:
+
::
list(LENGTH <list> <output variable>)
- list(GET <list> <element index> [<element index> ...]
- <output variable>)
+
+Returns the list's length.
+
+.. _GET:
+
+::
+
+ list(GET <list> <element index> [<element index> ...] <output variable>)
+
+Returns the list of elements specified by indices from the list.
+
+.. _JOIN:
+
+::
+
+ list(JOIN <list> <glue> <output variable>)
+
+Returns a string joining all list's elements using the glue string.
+To join multiple strings, which are not part of a list, use ``JOIN`` operator
+from :command:`string` command.
+
+.. _SUBLIST:
+
+::
+
+ list(SUBLIST <list> <begin> <length> <output variable>)
+
+Returns a sublist of the given list.
+If ``<length>`` is 0, an empty list will be returned.
+If ``<length>`` is -1 or the list is smaller than ``<begin>+<length>`` then
+the remaining elements of the list starting at ``<begin>`` will be returned.
+
+Search
+^^^^^^
+
+.. _FIND:
+
+::
+
+ list(FIND <list> <value> <output variable>)
+
+Returns the index of the element specified in the list or -1
+if it wasn't found.
+
+Modification
+^^^^^^^^^^^^
+
+.. _APPEND:
+
+::
+
list(APPEND <list> [<element> ...])
+
+Appends elements to the list.
+
+.. _FILTER:
+
+::
+
list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)
- list(FIND <list> <value> <output variable>)
+
+Includes or removes items from the list that match the mode's pattern.
+In ``REGEX`` mode, items will be matched against the given regular expression.
+
+For more information on regular expressions see also the
+:command:`string` command.
+
+.. _INSERT:
+
+::
+
list(INSERT <list> <element_index> <element> [<element> ...])
+
+Inserts elements to the list to the specified location.
+
+.. _REMOVE_ITEM:
+
+::
+
list(REMOVE_ITEM <list> <value> [<value> ...])
+
+Removes the given items from the list.
+
+.. _REMOVE_AT:
+
+::
+
list(REMOVE_AT <list> <index> [<index> ...])
+
+Removes items at given indices from the list.
+
+.. _REMOVE_DUPLICATES:
+
+::
+
list(REMOVE_DUPLICATES <list>)
- list(REVERSE <list>)
- list(SORT <list>)
-``LENGTH`` will return a given list's length.
+Removes duplicated items in the list.
-``GET`` will return list of elements specified by indices from the list.
+.. _TRANSFORM:
-``APPEND`` will append elements to the list.
+::
-``FILTER`` will include or remove items from the list that match the
-mode's pattern.
-In ``REGEX`` mode, items will be matched against the given regular expression.
-For more information on regular expressions see also the :command:`string`
-command.
+ list(TRANSFORM <list> <ACTION> [<SELECTOR>]
+ [OUTPUT_VARIABLE <output variable>])
-``FIND`` will return the index of the element specified in the list or -1
-if it wasn't found.
+Transforms the list by applying an action to all or, by specifying a
+``<SELECTOR>``, to the selected elements of the list, storing result in-place
+or in the specified output variable.
-``INSERT`` will insert elements to the list to the specified location.
+.. note::
-``REMOVE_AT`` and ``REMOVE_ITEM`` will remove items from the list. The
-difference is that ``REMOVE_ITEM`` will remove the given items, while
-``REMOVE_AT`` will remove the items at the given indices.
+ ``TRANSFORM`` sub-command does not change the number of elements of the
+ list. If a ``<SELECTOR>`` is specified, only some elements will be changed,
+ the other ones will remain same as before the transformation.
-``REMOVE_DUPLICATES`` will remove duplicated items in the list.
+``<ACTION>`` specify the action to apply to the elements of list.
+The actions have exactly the same semantics as sub-commands of
+:command:`string` command.
-``REVERSE`` reverses the contents of the list in-place.
+The ``<ACTION>`` may be one of:
-``SORT`` sorts the list in-place alphabetically.
+``APPEND``, ``PREPEND``: Append, prepend specified value to each element of
+the list. ::
+
+ list(TRANSFORM <list> <APPEND|PREPEND> <value> ...)
+
+``TOUPPER``, ``TOLOWER``: Convert each element of the list to upper, lower
+characters. ::
+
+ list(TRANSFORM <list> <TOLOWER|TOUPPER> ...)
+
+``STRIP``: Remove leading and trailing spaces from each element of the
+list. ::
+
+ list(TRANSFORM <list> STRIP ...)
+
+``GENEX_STRIP``: Strip any
+:manual:`generator expressions <cmake-generator-expressions(7)>` from each
+element of the list. ::
+
+ list(TRANSFORM <list> GENEX_STRIP ...)
+
+``REPLACE``: Match the regular expression as many times as possible and
+substitute the replacement expression for the match for each element
+of the list
+(Same semantic as ``REGEX REPLACE`` from :command:`string` command). ::
+
+ list(TRANSFORM <list> REPLACE <regular_expression>
+ <replace_expression> ...)
+
+``<SELECTOR>`` select which elements of the list will be transformed. Only one
+type of selector can be specified at a time.
+
+The ``<SELECTOR>`` may be one of:
+
+``AT``: Specify a list of indexes. ::
+
+ list(TRANSFORM <list> <ACTION> AT <index> [<index> ...] ...)
+
+``FOR``: Specify a range with, optionally, an increment used to iterate over
+the range. ::
+
+ list(TRANSFORM <list> <ACTION> FOR <start> <stop> [<step>] ...)
+
+``REGEX``: Specify a regular expression. Only elements matching the regular
+expression will be transformed. ::
+
+ list(TRANSFORM <list> <ACTION> REGEX <regular_expression> ...)
+
+
+Ordering
+^^^^^^^^
+
+.. _REVERSE:
+
+::
+
+ list(REVERSE <list>)
+
+Reverses the contents of the list in-place.
+
+.. _SORT:
+
+::
+
+ list(SORT <list>)
-The list subcommands ``APPEND``, ``INSERT``, ``FILTER``, ``REMOVE_AT``,
-``REMOVE_ITEM``, ``REMOVE_DUPLICATES``, ``REVERSE`` and ``SORT`` may create new
-values for the list within the current CMake variable scope. Similar to the
-:command:`set` command, the LIST command creates new variable values in the
-current scope, even if the list itself is actually defined in a parent
-scope. To propagate the results of these operations upwards, use
-:command:`set` with ``PARENT_SCOPE``, :command:`set` with
-``CACHE INTERNAL``, or some other means of value propagation.
-NOTES: A list in cmake is a ``;`` separated group of strings. To create a
-list the set command can be used. For example, ``set(var a b c d e)``
-creates a list with ``a;b;c;d;e``, and ``set(var "a b c d e")`` creates a
-string or a list with one item in it. (Note macro arguments are not
-variables, and therefore cannot be used in LIST commands.)
-
-When specifying index values, if ``<element index>`` is 0 or greater, it
-is indexed from the beginning of the list, with 0 representing the
-first list element. If ``<element index>`` is -1 or lesser, it is indexed
-from the end of the list, with -1 representing the last list element.
-Be careful when counting with negative indices: they do not start from
-0. -0 is equivalent to 0, the first list element.
+Sorts the list in-place alphabetically.
project
-------
-Set a name, version, and enable languages for the entire project.
+Sets project details such as name, version, etc. and enables languages.
.. code-block:: cmake
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[DESCRIPTION <project-description-string>]
+ [HOMEPAGE_URL <url-string>]
[LANGUAGES <language-name>...])
Sets the name of the project and stores the name in the
Variables corresponding to unspecified versions are set to the empty string
(if policy :policy:`CMP0048` is set to ``NEW``).
-If optional ``DESCRIPTION`` is given, then additional :variable:`PROJECT_DESCRIPTION`
-variable will be set to its argument. The argument must be a string with short
-description of the project (only a few words).
+If the optional ``DESCRIPTION`` is given, then :variable:`PROJECT_DESCRIPTION`
+and :variable:`<PROJECT-NAME>_DESCRIPTION` will be set to its argument.
+The description is expected to be a relatively short string, usually no more
+than a few words.
+
+The optional ``HOMEPAGE_URL`` sets the analogous variables
+:variable:`PROJECT_HOMEPAGE_URL` and :variable:`<PROJECT-NAME>_HOMEPAGE_URL`.
+When this option is given, the URL provided should be the canonical home for
+the project.
+
+Note that the description and homepage URL may be used as defaults for
+things like packaging meta-data, documentation, etc.
Optionally you can specify which languages your project supports.
Example languages include ``C``, ``CXX`` (i.e. C++), ``CUDA``,
literal, direct call to the :command:`project` command; loading one
through the :command:`include` command is not sufficient. If no such
call exists CMake will implicitly add one to the top that enables the
-default languages (``C`` and ``CXX``).
+default languages (``C`` and ``CXX``). The name of the project set in
+the top level ``CMakeLists.txt`` file is available from the
+:variable:`CMAKE_PROJECT_NAME` variable, its description from
+:variable:`CMAKE_PROJECT_DESCRIPTION`, its homepage URL from
+:variable:`CMAKE_PROJECT_HOMEPAGE_URL` and its version from
+:variable:`CMAKE_PROJECT_VERSION`.
.. note::
Call the :command:`cmake_minimum_required` command at the beginning
The required ``PROPERTY`` option is immediately followed by the name of
the property to set. Remaining arguments are used to compose the
-property value in the form of a semicolon-separated list. If the
-``APPEND`` option is given the list is appended to any existing property
-value. If the ``APPEND_STRING`` option is given the string is append to any
-existing property value as string, i.e. it results in a longer string
-and not a list of strings.
+property value in the form of a semicolon-separated list.
+
+If the ``APPEND`` option is given the list is appended to any existing
+property value. If the ``APPEND_STRING`` option is given the string is
+appended to any existing property value as string, i.e. it results in a
+longer string and not a list of strings. When using ``APPEND`` or
+``APPEND_STRING`` with a property defined to support ``INHERITED``
+behavior (see :command:`define_property`), no inheriting occurs when
+finding the initial value to append to. If the property is not already
+directly set in the nominated scope, the command will behave as though
+``APPEND`` or ``APPEND_STRING`` had not been given.
See the :manual:`cmake-properties(7)` manual for a list of properties
in each scope.
PROPERTIES prop1 value1
prop2 value2 ...)
-Set properties on a target. The syntax for the command is to list all
-the files you want to change, and then provide the values you want to
+Set properties on targets. The syntax for the command is to list all
+the targets you want to change, and then provide the values you want to
set next. You can use any prop value pair you want and extract it
later with the :command:`get_property` or :command:`get_target_property`
command.
+See also the :command:`set_property(TARGET)` command.
+
See :ref:`Target Properties` for the list of properties known to CMake.
string
------
-.. only:: html
-
- .. contents::
-
String operations.
+Synopsis
+^^^^^^^^
+
+.. parsed-literal::
+
+ `Search and Replace`_
+ string(`FIND`_ <string> <substring> <out-var> [...])
+ string(`REPLACE`_ <match-string> <replace-string> <out-var> <input>...)
+
+ `Regular Expressions`_
+ string(`REGEX MATCH`_ <match-regex> <out-var> <input>...)
+ string(`REGEX MATCHALL`_ <match-regex> <out-var> <input>...)
+ string(`REGEX REPLACE`_ <match-regex> <replace-expr> <out-var> <input>...)
+
+ `Manipulation`_
+ string(`APPEND`_ <string-var> [<input>...])
+ string(`PREPEND`_ <string-var> [<input>...])
+ string(`CONCAT`_ <out-var> [<input>...])
+ string(`JOIN`_ <glue> <out-var> [<input>...])
+ string(`TOLOWER`_ <string1> <out-var>)
+ string(`TOUPPER`_ <string1> <out-var>)
+ string(`LENGTH`_ <string> <out-var>)
+ string(`SUBSTRING`_ <string> <begin> <length> <out-var>)
+ string(`STRIP`_ <string> <out-var>)
+ string(`GENEX_STRIP`_ <string> <out-var>)
+
+ `Comparison`_
+ string(`COMPARE`_ <op> <string1> <string2> <out-var>)
+
+ `Hashing`_
+ string(`\<HASH\> <HASH_>`_ <out-var> <input>)
+
+ `Generation`_
+ string(`ASCII`_ <number>... <out-var>)
+ string(`CONFIGURE`_ <string1> <out-var> [...])
+ string(`MAKE_C_IDENTIFIER`_ <string> <out-var>)
+ string(`RANDOM`_ [<option>...] <out-var>)
+ string(`TIMESTAMP`_ <out-var> [<format string>] [UTC])
+ string(`UUID`_ <out-var> ...)
+
Search and Replace
^^^^^^^^^^^^^^^^^^
-FIND
-""""
+.. _FIND:
::
search for the position of the last occurrence of the specified
substring. If the substring is not found, a position of -1 is returned.
-REPLACE
-"""""""
+.. _REPLACE:
::
Regular Expressions
^^^^^^^^^^^^^^^^^^^
-REGEX MATCH
-"""""""""""
+.. _`REGEX MATCH`:
::
Match the regular expression once and store the match in the output variable.
All ``<input>`` arguments are concatenated before matching.
-REGEX MATCHALL
-""""""""""""""
+.. _`REGEX MATCHALL`:
::
in the output variable as a list.
All ``<input>`` arguments are concatenated before matching.
-REGEX REPLACE
-"""""""""""""
+.. _`REGEX REPLACE`:
::
Manipulation
^^^^^^^^^^^^
-APPEND
-""""""
+.. _APPEND:
::
Append all the input arguments to the string.
-PREPEND
-"""""""
+.. _PREPEND:
::
Prepend all the input arguments to the string.
-CONCAT
-""""""
+.. _CONCAT:
::
Concatenate all the input arguments together and store
the result in the named output variable.
-TOLOWER
-"""""""
+.. _JOIN:
+
+::
+
+ string(JOIN <glue> <output variable> [<input>...])
+
+Join all the input arguments together using the glue
+string and store the result in the named output variable.
+
+To join list's elements, use preferably the ``JOIN`` operator
+from :command:`list` command. This allows for the elements to have
+special characters like ``;`` in them.
+
+.. _TOLOWER:
::
Convert string to lower characters.
-TOUPPER
-"""""""
+.. _TOUPPER:
::
Convert string to upper characters.
-LENGTH
-""""""
+.. _LENGTH:
::
Store in an output variable a given string's length.
-SUBSTRING
-"""""""""
+.. _SUBSTRING:
::
CMake 3.1 and below reported an error if length pointed past
the end of string.
-STRIP
-"""""
+.. _STRIP:
::
Store in an output variable a substring of a given string with leading and
trailing spaces removed.
-GENEX_STRIP
-"""""""""""
+.. _GENEX_STRIP:
::
Comparison
^^^^^^^^^^
+.. _COMPARE:
+
::
string(COMPARE LESS <string1> <string2> <output variable>)
Hashing
^^^^^^^
+.. _`HASH`:
+
::
string(<HASH> <output variable> <input>)
Generation
^^^^^^^^^^
-ASCII
-"""""
+.. _ASCII:
::
Convert all numbers into corresponding ASCII characters.
-CONFIGURE
-"""""""""
+.. _CONFIGURE:
::
Transform a string like :command:`configure_file` transforms a file.
-RANDOM
-""""""
+.. _MAKE_C_IDENTIFIER:
+
+::
+
+ string(MAKE_C_IDENTIFIER <input string> <output variable>)
+
+Convert each non-alphanumeric character in the ``<input string>`` to an
+underscore and store the result in the ``<output variable>``. If the first
+character of the string is a digit, an underscore will also be prepended to
+the result.
+
+.. _RANDOM:
::
If an integer ``RANDOM_SEED`` is given, its value will be used to seed the
random number generator.
-TIMESTAMP
-"""""""""
+.. _TIMESTAMP:
::
%Y-%m-%dT%H:%M:%S for local time.
%Y-%m-%dT%H:%M:%SZ for UTC.
-
-::
-
- string(MAKE_C_IDENTIFIER <input string> <output variable>)
-
-Write a string which can be used as an identifier in C.
-
.. note::
If the ``SOURCE_DATE_EPOCH`` environment variable is set,
its value will be used instead of the current time.
See https://reproducible-builds.org/specs/source-date-epoch/ for details.
-UUID
-""""
+.. _UUID:
::
string(UUID <output variable> NAMESPACE <namespace> NAME <name>
TYPE <MD5|SHA1> [UPPER])
-Create a univerally unique identifier (aka GUID) as per RFC4122
+Create a universally unique identifier (aka GUID) as per RFC4122
based on the hash of the combined values of ``<namespace>``
(which itself has to be a valid UUID) and ``<name>``.
The hash algorithm can be either ``MD5`` (Version 3 UUID) or
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
+
+Any leading ``-D`` on an item will be removed. Empty items are ignored.
+For example, the following are all equivalent:
+
+.. code-block:: cmake
+
+ target_compile_definitions(foo PUBLIC FOO)
+ target_compile_definitions(foo PUBLIC -DFOO) # -D removed
+ target_compile_definitions(foo PUBLIC "" FOO) # "" ignored
+ target_compile_definitions(foo PUBLIC -D FOO) # -D becomes "", then ignored
This command can be used to add any options, but
alternative commands exist to add preprocessor definitions
-(:command:`target_compile_definitions` and :command:`add_definitions`) or
-include directories (:command:`target_include_directories` and
+(:command:`target_compile_definitions` and :command:`add_compile_definitions`)
+or include directories (:command:`target_include_directories` and
:command:`include_directories`). See documentation of the
:prop_dir:`directory <COMPILE_OPTIONS>` and
:prop_tgt:`target <COMPILE_OPTIONS>` ``COMPILE_OPTIONS`` properties.
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
+
+.. include:: COMPILE_OPTIONS_SHELL.txt
``general`` (or without any keyword) are treated as if specified for both
``debug`` and ``optimized``.
+Linking Object Libraries
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+:ref:`Object Libraries` may be used as the ``<target>`` (first) argument
+of ``target_link_libraries`` to specify dependencies of their sources
+on other libraries. For example, the code
+
+.. code-block:: cmake
+
+ add_library(A SHARED a.c)
+ target_compile_definitions(A PUBLIC A)
+
+ add_library(obj OBJECT obj.c)
+ target_compile_definitions(obj PUBLIC OBJ)
+ target_link_libraries(obj PUBLIC A)
+
+compiles ``obj.c`` with ``-DA -DOBJ`` and establishes usage requirements
+for ``obj`` that propagate to its dependents.
+
+Normal libraries and executables may link to :ref:`Object Libraries`
+to get their objects and usage requirements. Continuing the above
+example, the code
+
+.. code-block:: cmake
+
+ add_library(B SHARED b.c)
+ target_link_libraries(B PUBLIC obj)
+
+compiles ``b.c`` with ``-DA -DOBJ``, creates shared library ``B``
+with object files from ``b.c`` and ``obj.c``, and links ``B`` to ``A``.
+Furthermore, the code
+
+.. code-block:: cmake
+
+ add_executable(main main.c)
+ target_link_libraries(main B)
+
+compiles ``main.c`` with ``-DA -DOBJ`` and links executable ``main``
+to ``B`` and ``A``. The object library's usage requirements are
+propagated transitively through ``B``, but its object files are not.
+
+:ref:`Object Libraries` may "link" to other object libraries to get
+usage requirements, but since they do not have a link step nothing
+is done with their object files. Continuing from the above example,
+the code:
+
+.. code-block:: cmake
+
+ add_library(obj2 OBJECT obj2.c)
+ target_link_libraries(obj2 PUBLIC obj)
+
+ add_executable(main2 main2.c)
+ target_link_libraries(main2 obj2)
+
+compiles ``obj2.c`` with ``-DA -DOBJ``, creates executable ``main2``
+with object files from ``main2.c`` and ``obj2.c``, and links ``main2``
+to ``A``.
+
+In other words, when :ref:`Object Libraries` appear in a target's
+:prop_tgt:`INTERFACE_LINK_LIBRARIES` property they will be
+treated as :ref:`Interface Libraries`, but when they appear in
+a target's :prop_tgt:`LINK_LIBRARIES` property their object files
+will be included in the link too.
+
Cyclic Dependencies of Static Libraries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
branch in the constructed merge commit message.
Additionally, ``Do: merge`` extracts configuration from trailing lines
-in the MR description:
+in the MR description (the following have no effect if used in a MR
+comment instead):
* ``Topic-rename: <topic>``: substitute ``<topic>`` for the name of
the MR topic branch in the constructed merge commit message.
- The ``-t`` option overrides this.
+ It is also used in merge commits constructed by ``Do: stage``.
+ The ``-t`` option to a ``Do: merge`` command overrides any topic
+ rename set in the MR description.
.. _`CMake GitLab Project Masters`: https://gitlab.kitware.com/cmake/cmake/settings/members
C++ Code Style
==============
-We use `clang-format`_ version **3.8** to define our style for C++ code in
+We use `clang-format`_ version **6.0** to define our style for C++ code in
the CMake source tree. See the `.clang-format`_ configuration file for our
style settings. Use the `Utilities/Scripts/clang-format.bash`_ script to
format source code. It automatically runs ``clang-format`` on the set of
--- /dev/null
+CMAKE_BUILD_PARALLEL_LEVEL
+--------------------------
+
+Specifies the maximum number of concurrent processes to use when building
+using the ``cmake --build`` command line
+:ref:`Build Tool Mode <Build Tool Mode>`.
+
+If this variable is defined empty the native build tool's default number is
+used.
--- /dev/null
+DESTDIR
+-------
+
+On UNIX one can use the ``DESTDIR`` mechanism in order to relocate the
+whole installation. ``DESTDIR`` means DESTination DIRectory. It is
+commonly used by makefile users in order to install software at
+non-default location. It is usually invoked like this:
+
+::
+
+ make DESTDIR=/home/john install
+
+which will install the concerned software using the installation
+prefix, e.g. ``/usr/local`` prepended with the ``DESTDIR`` value which
+finally gives ``/home/john/usr/local``.
+
+WARNING: ``DESTDIR`` may not be used on Windows because installation
+prefix usually contains a drive letter like in ``C:/Program Files``
+which cannot be prepended with some other prefix.
Visual Studio 8 2005
--------------------
-Deprecated. Generates Visual Studio 8 2005 project files.
-
-.. note::
- This generator is deprecated and will be removed in a future version
- of CMake. It will still be possible to build with VS 8 2005 tools
- using the :generator:`Visual Studio 10 2010` (or above) generator
- with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v80``, or by
- using the :generator:`NMake Makefiles` generator.
-
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set
-to specify a target platform name.
-
-For compatibility with CMake versions prior to 3.1, one may specify
-a target platform name optionally at the end of this generator name:
-
-``Visual Studio 8 2005 Win64``
- Specify target platform ``x64``.
-
-``Visual Studio 8 2005 <WinCE-SDK>``
- Specify target platform matching a Windows CE SDK name.
+Removed. This once generated Visual Studio 8 2005 project files, but
+the generator has been removed since CMake 3.12. It is still possible to
+build with VS 2005 tools using the :generator:`NMake Makefiles` generator.
/manual/cmake-commands.7
/manual/cmake-compile-features.7
/manual/cmake-developer.7
+ /manual/cmake-env-variables.7
/manual/cmake-generator-expressions.7
/manual/cmake-generators.7
/manual/cmake-language.7
- /manual/cmake-server.7
/manual/cmake-modules.7
/manual/cmake-packages.7
/manual/cmake-policies.7
/manual/cmake-properties.7
/manual/cmake-qt.7
+ /manual/cmake-server.7
/manual/cmake-toolchains.7
/manual/cmake-variables.7
- /manual/cmake-env-variables.7
.. only:: html or text
The primary starting point for learning about CMake.
-Frequently Asked Questions
- https://cmake.org/Wiki/CMake_FAQ
-
- A Wiki is provided containing answers to frequently asked questions.
-
-Online Documentation
+Online Documentation and Community Resources
https://cmake.org/documentation
- Links to available documentation may be found on this web page.
+ Links to available documentation and community resources may be
+ found on this web page.
Mailing List
https://cmake.org/mailing-lists
cache-format file.
``-D <var>:<type>=<value>, -D <var>=<value>``
- Create a cmake cache entry.
+ Create or update a cmake cache entry.
When cmake is first run in an empty build tree, it creates a
CMakeCache.txt file and populates it with customizable settings for
.. parsed-literal::
- ccmake [<options>] (<path-to-source> | <path-to-existing-build>)
+ ccmake [<options>] {<path-to-source> | <path-to-existing-build>}
Description
===========
Object Libraries
^^^^^^^^^^^^^^^^
-The ``OBJECT`` library type is also not linked to. It defines a non-archival
-collection of object files resulting from compiling the given source files.
-The object files collection can be used as source inputs to other targets:
+The ``OBJECT`` library type defines a non-archival collection of object files
+resulting from compiling the given source files. The object files collection
+may be used as source inputs to other targets:
.. code-block:: cmake
add_executable(test_exe $<TARGET_OBJECTS:archive> test.cpp)
-``OBJECT`` libraries may not be used in the right hand side of
-:command:`target_link_libraries`. They also may not be used as the ``TARGET``
-in a use of the :command:`add_custom_command(TARGET)` command signature. They
-may be installed, and will be exported as an INTERFACE library.
+The link (or archiving) step of those other targets will use the object
+files collection in addition to those from their own sources.
-Although object libraries may not be named directly in calls to
-the :command:`target_link_libraries` command, they can be "linked"
-indirectly by using an :ref:`Interface Library <Interface Libraries>`
-whose :prop_tgt:`INTERFACE_SOURCES` target property is set to name
-``$<TARGET_OBJECTS:objlib>``.
+Alternatively, object libraries may be linked into other targets:
-Although object libraries may not be used as the ``TARGET``
-in a use of the :command:`add_custom_command(TARGET)` command signature,
-the list of objects can be used by :command:`add_custom_command(OUTPUT)` or
-:command:`file(GENERATE)` by using ``$<TARGET_OBJECTS:objlib>``.
+.. code-block:: cmake
+
+ add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)
+
+ add_library(archiveExtras STATIC extras.cpp)
+ target_link_libraries(archiveExtras PUBLIC archive)
+
+ add_executable(test_exe test.cpp)
+ target_link_libraries(test_exe archive)
+
+The link (or archiving) step of those other targets will use the object
+files from object libraries that are *directly* linked. Additionally,
+usage requirements of the object libraries will be honored when compiling
+sources in those other targets. Furthermore, those usage requirements
+will propagate transitively to dependents of those other targets.
+Object libraries may not be used as the ``TARGET`` in a use of the
+:command:`add_custom_command(TARGET)` command signature. However,
+the list of objects can be used by :command:`add_custom_command(OUTPUT)`
+or :command:`file(GENERATE)` by using ``$<TARGET_OBJECTS:objlib>``.
Build Specification and Usage Requirements
==========================================
The :command:`target_include_directories`,
:command:`target_compile_definitions` and
:command:`target_compile_options` commands have an effect on only one
-target at a time. The commands :command:`add_definitions`,
+target at a time. The commands :command:`add_compile_definitions`,
:command:`add_compile_options` and :command:`include_directories` have
a similar function, but operate at directory scope instead of target
scope for convenience.
.. toctree::
:maxdepth: 1
+ /command/add_compile_definitions
/command/add_compile_options
/command/add_custom_command
/command/add_custom_target
the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
versions specified for each:
-* ``AppleClang``: Apple Clang for Xcode versions 4.4 though 6.2.
-* ``Clang``: Clang compiler versions 2.9 through 3.4.
-* ``GNU``: GNU compiler versions 4.4 through 5.0.
+* ``AppleClang``: Apple Clang for Xcode versions 4.4 though 9.2.
+* ``Clang``: Clang compiler versions 2.9 through 6.0.
+* ``GNU``: GNU compiler versions 4.4 through 8.0.
* ``MSVC``: Microsoft Visual Studio versions 2010 through 2017.
* ``SunPro``: Oracle SolarisStudio versions 12.4 through 12.6.
* ``Intel``: Intel compiler versions 12.1 through 17.0.
versions specified for each:
* all compilers and versions listed above for C++.
-* ``GNU``: GNU compiler versions 3.4 through 5.0.
+* ``GNU``: GNU compiler versions 3.4 through 8.0.
CMake is currently aware of the :prop_tgt:`C++ standards <CXX_STANDARD>` and
their associated meta-features (e.g. ``cxx_std_11``) available from the
versions specified for each:
* all compilers and versions listed above with only meta-features for C++.
+* ``TI``: Texas Instruments compiler.
CMake is currently aware of the :prop_tgt:`CUDA standards <CUDA_STANDARD>`
from the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
versions specified for each:
-* ``NVIDIA``: NVIDIA nvcc compiler 7.5 though 8.0.
+* ``NVIDIA``: NVIDIA nvcc compiler 7.5 though 9.1.
+.. _`CMake Developer Standard Variable Names`:
+
Standard Variable Names
^^^^^^^^^^^^^^^^^^^^^^^
endif()
The ``RELEASE`` variant should be listed first in the property
-so that that variant is chosen if the user uses a configuration which is
+so that the variant is chosen if the user uses a configuration which is
not an exact match for any listed ``IMPORTED_CONFIGURATIONS``.
Most of the cache variables should be hidden in the ``ccmake`` interface unless
.. toctree::
:maxdepth: 1
+ /envvar/CMAKE_BUILD_PARALLEL_LEVEL
/envvar/CMAKE_CONFIG_TYPE
/envvar/CMAKE_MSVCIDE_RUN_PATH
/envvar/CMAKE_OSX_ARCHITECTURES
+ /envvar/DESTDIR
/envvar/LDFLAGS
/envvar/MACOSX_DEPLOYMENT_TARGET
``1`` if ``a`` is STREQUAL ``b``, else ``0``
``$<EQUAL:a,b>``
``1`` if ``a`` is EQUAL ``b`` in a numeric comparison, else ``0``
+``$<IN_LIST:a,b>``
+ ``1`` if ``a`` is IN_LIST ``b``, else ``0``
+``$<TARGET_EXISTS:tgt>``
+ ``1`` if ``tgt`` is an existed target name, else ``0``.
``$<CONFIG:cfg>``
``1`` if config is ``cfg``, else ``0``. This is a case-insensitive comparison.
The mapping in :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by
Marks ``...`` as being the name of a target. This is required if exporting
targets to multiple dependent export sets. The ``...`` must be a literal
name of a target- it may not contain generator expressions.
+``$<TARGET_NAME_IF_EXISTS:...>``
+ Expands to the ``...`` if the given target exists, an empty string
+ otherwise.
``$<LINK_ONLY:...>``
Content of ``...`` except when evaluated in a link interface while
propagating :ref:`Target Usage Requirements`, in which case it is the
``$<UPPER_CASE:...>``
Content of ``...`` converted to upper case.
``$<MAKE_C_IDENTIFIER:...>``
- Content of ``...`` converted to a C identifier.
+ Content of ``...`` converted to a C identifier. The conversion follows the
+ same behavior as :command:`string(MAKE_C_IDENTIFIER)`.
``$<TARGET_OBJECTS:objLib>``
List of objects resulting from build of ``objLib``. ``objLib`` must be an
object of type ``OBJECT_LIBRARY``.
Content of ``...`` converted to shell path style. For example, slashes are
converted to backslashes in Windows shells and drive letters are converted
to posix paths in MSYS shells. The ``...`` must be an absolute path.
+``$<GENEX_EVAL:...>``
+ Content of ``...`` evaluated as a generator expression in the current
+ context. This enables consumption of generator expressions
+ whose evaluation results itself in generator expressions.
+``$<TARGET_GENEX_EVAL:tgt,...>``
+ Content of ``...`` evaluated as a generator expression in the context of
+ ``tgt`` target. This enables consumption of custom target properties that
+ themselves contain generator expressions.
+
+ Having the capability to evaluate generator expressions is very useful when
+ you want to manage custom properties supporting generator expressions.
+ For example:
+
+ .. code-block:: cmake
+
+ add_library(foo ...)
+
+ set_property(TARGET foo PROPERTY
+ CUSTOM_KEYS $<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>
+ )
+
+ add_custom_target(printFooKeys
+ COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_PROPERTY:foo,CUSTOM_KEYS>
+ )
+
+ This naive implementation of the ``printFooKeys`` custom command is wrong
+ because ``CUSTOM_KEYS`` target property is not evaluated and the content
+ is passed as is (i.e. ``$<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>``).
+
+ To have the expected result (i.e. ``FOO_EXTRA_THINGS`` if config is
+ ``Debug``), it is required to evaluate the output of
+ ``$<TARGET_PROPERTY:foo,CUSTOM_KEYS>``:
+
+ .. code-block:: cmake
+
+ add_custom_target(printFooKeys
+ COMMAND ${CMAKE_COMMAND} -E
+ echo $<TARGET_GENEX_EVAL:foo,$<TARGET_PROPERTY:foo,CUSTOM_KEYS>>
+ )
.. parsed-literal::
cmake-gui [<options>]
- cmake-gui [<options>] (<path-to-source> | <path-to-existing-build>)
+ cmake-gui [<options>] {<path-to-source> | <path-to-existing-build>}
Description
===========
/module/CPackIFW
/module/CPackIFWConfigureFile
/module/CPackNSIS
+ /module/CPackNuGet
/module/CPackPackageMaker
/module/CPackProductBuild
/module/CPackRPM
/module/FindMPEG2
/module/FindMPEG
/module/FindMPI
+ /module/FindODBC
/module/FindOpenACC
/module/FindOpenAL
/module/FindOpenCL
/module/FindPostgreSQL
/module/FindProducer
/module/FindProtobuf
+ /module/FindPython
+ /module/FindPython2
+ /module/FindPython3
/module/FindPythonInterp
/module/FindPythonLibs
/module/FindQt3
to determine whether to report an error on use of deprecated macros or
functions.
+Policies Introduced by CMake 3.12
+=================================
+
+.. toctree::
+ :maxdepth: 1
+
+ CMP0075: Include file check macros honor CMAKE_REQUIRED_LIBRARIES. </policy/CMP0075>
+ CMP0074: find_package uses PackageName_ROOT variables. </policy/CMP0074>
+ CMP0073: Do not produce legacy _LIB_DEPENDS cache entries. </policy/CMP0073>
+
Policies Introduced by CMake 3.11
=================================
/prop_gbl/JOB_POOLS
/prop_gbl/PREDEFINED_TARGETS_FOLDER
/prop_gbl/ECLIPSE_EXTRA_NATURES
+ /prop_gbl/ECLIPSE_EXTRA_CPROJECT_CONTENTS
/prop_gbl/REPORT_UNDEFINED_PROPERTIES
/prop_gbl/RULE_LAUNCH_COMPILE
/prop_gbl/RULE_LAUNCH_CUSTOM
/prop_dir/RULE_LAUNCH_LINK
/prop_dir/SOURCE_DIR
/prop_dir/SUBDIRECTORIES
+ /prop_dir/TESTS
/prop_dir/TEST_INCLUDE_FILES
/prop_dir/VARIABLES
/prop_dir/VS_GLOBAL_SECTION_POST_section
/prop_tgt/C_EXTENSIONS
/prop_tgt/C_STANDARD
/prop_tgt/C_STANDARD_REQUIRED
+ /prop_tgt/COMMON_LANGUAGE_RUNTIME
/prop_tgt/COMPATIBLE_INTERFACE_BOOL
/prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MAX
/prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MIN
/prop_tgt/DEBUG_POSTFIX
/prop_tgt/DEFINE_SYMBOL
/prop_tgt/DEPLOYMENT_REMOTE_DIRECTORY
+ /prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION
/prop_tgt/EchoString
/prop_tgt/ENABLE_EXPORTS
/prop_tgt/EXCLUDE_FROM_ALL
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD
/prop_tgt/EXPORT_NAME
+ /prop_tgt/EXPORT_PROPERTIES
/prop_tgt/FOLDER
/prop_tgt/Fortran_FORMAT
/prop_tgt/Fortran_MODULE_DIRECTORY
/prop_tgt/GNUtoMS
/prop_tgt/HAS_CXX
/prop_tgt/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
+ /prop_tgt/IMPORTED_COMMON_LANGUAGE_RUNTIME
/prop_tgt/IMPORTED_CONFIGURATIONS
/prop_tgt/IMPORTED_GLOBAL
/prop_tgt/IMPORTED_IMPLIB_CONFIG
/prop_tgt/VISIBILITY_INLINES_HIDDEN
/prop_tgt/VS_CONFIGURATION_TYPE
/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY
+ /prop_tgt/VS_DEBUGGER_COMMAND
/prop_tgt/VS_DESKTOP_EXTENSIONS_VERSION
/prop_tgt/VS_DOTNET_REFERENCE_refname
/prop_tgt/VS_DOTNET_REFERENCEPROP_refname_TAG_tagname
/prop_test/LABELS
/prop_test/MEASUREMENT
/prop_test/PASS_REGULAR_EXPRESSION
+ /prop_test/PROCESSOR_AFFINITY
/prop_test/PROCESSORS
/prop_test/REQUIRED_FILES
/prop_test/RESOURCE_LOCK
/prop_sf/VS_SHADER_ENTRYPOINT
/prop_sf/VS_SHADER_FLAGS
/prop_sf/VS_SHADER_MODEL
+ /prop_sf/VS_SHADER_OBJECT_FILE_NAME
/prop_sf/VS_SHADER_OUTPUT_HEADER_FILE
/prop_sf/VS_SHADER_TYPE
/prop_sf/VS_SHADER_VARIABLE_NAME
Start :manual:`cmake(1)` in the server command mode, supplying the path to
the build directory to process::
- cmake -E server (--debug|--pipe <NAMED_PIPE>)
+ cmake -E server (--debug|--pipe=<NAMED_PIPE>)
The server will communicate using stdin/stdout (with the ``--debug`` parameter)
-or using a named pipe (with the ``--pipe <NAMED_PIPE>`` parameter).
+or using a named pipe (with the ``--pipe=<NAMED_PIPE>`` parameter). Note
+that "named pipe" refers to a local domain socket on Unix and to a named pipe
+on Windows.
When connecting to the server (via named pipe or by starting it in ``--debug``
mode), the server will reply with a hello message::
/variable/CMAKE_CURRENT_SOURCE_DIR
/variable/CMAKE_DIRECTORY_LABELS
/variable/CMAKE_DL_LIBS
+ /variable/CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION
/variable/CMAKE_EDIT_COMMAND
/variable/CMAKE_EXECUTABLE_SUFFIX
/variable/CMAKE_EXTRA_GENERATOR
/variable/CMAKE_PARENT_LIST_FILE
/variable/CMAKE_PATCH_VERSION
/variable/CMAKE_PROJECT_DESCRIPTION
+ /variable/CMAKE_PROJECT_HOMEPAGE_URL
/variable/CMAKE_PROJECT_NAME
+ /variable/CMAKE_PROJECT_VERSION
+ /variable/CMAKE_PROJECT_VERSION_MAJOR
+ /variable/CMAKE_PROJECT_VERSION_MINOR
+ /variable/CMAKE_PROJECT_VERSION_PATCH
+ /variable/CMAKE_PROJECT_VERSION_TWEAK
/variable/CMAKE_RANLIB
/variable/CMAKE_ROOT
/variable/CMAKE_SCRIPT_MODE_FILE
/variable/CMAKE_VS_PLATFORM_TOOLSET
/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA
/variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
+ /variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION
/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
/variable/CMAKE_XCODE_GENERATE_SCHEME
/variable/CMAKE_XCODE_PLATFORM_TOOLSET
/variable/PROJECT-NAME_BINARY_DIR
+ /variable/PROJECT-NAME_DESCRIPTION
+ /variable/PROJECT-NAME_HOMEPAGE_URL
/variable/PROJECT-NAME_SOURCE_DIR
/variable/PROJECT-NAME_VERSION
/variable/PROJECT-NAME_VERSION_MAJOR
/variable/PROJECT-NAME_VERSION_TWEAK
/variable/PROJECT_BINARY_DIR
/variable/PROJECT_DESCRIPTION
+ /variable/PROJECT_HOMEPAGE_URL
/variable/PROJECT_NAME
/variable/PROJECT_SOURCE_DIR
/variable/PROJECT_VERSION
/variable/CMAKE_STAGING_PREFIX
/variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS
/variable/CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE
+ /variable/CMAKE_SUPPRESS_REGENERATION
/variable/CMAKE_SYSROOT
/variable/CMAKE_SYSROOT_COMPILE
/variable/CMAKE_SYSROOT_LINK
/variable/MSVC80
/variable/MSVC90
/variable/MSVC_IDE
+ /variable/MSVC_TOOLSET_VERSION
/variable/MSVC_VERSION
/variable/UNIX
/variable/WIN32
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT
/variable/CMAKE_EXE_LINKER_FLAGS_INIT
+ /variable/CMAKE_FOLDER
/variable/CMAKE_Fortran_FORMAT
/variable/CMAKE_Fortran_MODULE_DIRECTORY
/variable/CMAKE_GNUtoMS
/variable/CMAKE_VISIBILITY_INLINES_HIDDEN
/variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD
/variable/CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD
+ /variable/CMAKE_VS_SDK_EXCLUDE_DIRECTORIES
+ /variable/CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES
+ /variable/CMAKE_VS_SDK_INCLUDE_DIRECTORIES
+ /variable/CMAKE_VS_SDK_LIBRARY_DIRECTORIES
+ /variable/CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES
+ /variable/CMAKE_VS_SDK_REFERENCE_DIRECTORIES
+ /variable/CMAKE_VS_SDK_SOURCE_DIRECTORIES
/variable/CMAKE_WIN32_EXECUTABLE
/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute
.. parsed-literal::
- cmake [<options>] (<path-to-source> | <path-to-existing-build>)
- cmake [(-D <var>=<value>)...] -P <cmake-script-file>
+ cmake [<options>] {<path-to-source> | <path-to-existing-build>}
+ cmake [{-D <var>=<value>}...] -P <cmake-script-file>
cmake --build <dir> [<options>...] [-- <build-tool-options>...]
cmake --open <dir>
cmake -E <command> [<options>...]
``--build <dir>``
Project binary directory to be built. This is required and must be first.
+``-j [<jobs>], --parallel [<jobs>]``
+ The maximum number of concurrent processes to use when building.
+ If ``<jobs>`` is omitted the native build tool's default number is used.
+
+ The :envvar:`CMAKE_BUILD_PARALLEL_LEVEL` environment variable, if set,
+ specifies a default parallel level when this option is not given.
+
``--target <tgt>``
Build ``<tgt>`` instead of default targets. May only be specified once.
.. parsed-literal::
- cpack -G <generator> [<options>]
+ cpack [<options>]
Description
===========
-The "cpack" executable is the CMake packaging program.
-CMake-generated build trees created for projects that use the
-INSTALL_* commands have packaging support. This program will generate
-the package.
-
-CMake is a cross-platform build system generator. Projects specify
-their build process with platform-independent CMake listfiles included
-in each directory of a source tree with the name CMakeLists.txt.
-Users build a project by using CMake to generate a build system for a
-native tool on their platform.
+The ``cpack`` executable is the CMake packaging program.
+CMake projects use :command:`install` commands to define the contents of
+packages which can be generated in various formats by this tool.
+The :module:`CPack` module greatly simplifies the creation of the input file
+used by ``cpack``, allowing most aspects of the packaging configuration to be
+controlled directly from the CMake project's own ``CMakeLists.txt`` files.
Options
=======
-``-G <generator>``
- Use the specified generator to generate package.
-
- CPack may support multiple native packaging systems on certain
- platforms. A generator is responsible for generating input files
- for particular system and invoking that systems. Possible generator
- names are specified in the Generators section.
+``-G <generators>``
+ ``<generators>`` is a :ref:`semicolon-separated list <CMake Language Lists>`
+ of generator names. ``cpack`` will iterate through this list and produce
+ package(s) in that generator's format according to the details provided in
+ the ``CPackConfig.cmake`` configuration file. A generator is responsible for
+ generating the required inputs for a particular package system and invoking
+ that system's package creation tools. Possible generator names are specified
+ in the :manual:`Generators <cmake-generators(7)>` section of the manual and
+ the ``--help`` option lists the generators supported for the target platform.
+ If this option is not given, the :variable:`CPACK_GENERATOR` variable
+ determines the default set of generators that will be used.
``-C <Configuration>``
- Specify the project configuration
-
- This option specifies the configuration that the project was build
- with, for example 'Debug', 'Release'.
+ Specify the project configuration to be packaged (e.g. ``Debug``,
+ ``Release``, etc.). When the CMake project uses a multi-configuration
+ generator such as Xcode or Visual Studio, this option is needed to tell
+ ``cpack`` which built executables to include in the package.
``-D <var>=<value>``
- Set a CPack variable.
-
- Set a variable that can be used by the generator.
+ Set a CPack variable. This will override any value set for ``<var>`` in the
+ input file read by ``cpack``.
-``--config <config file>``
- Specify the config file.
-
- Specify the config file to use to create the package. By default
- CPackConfig.cmake in the current directory will be used.
+``--config <configFile>``
+ Specify the configuration file read by ``cpack`` to provide the packaging
+ details. By default, ``CPackConfig.cmake`` in the current directory will
+ be used.
``--verbose,-V``
- enable verbose output
-
- Run cpack with verbose output.
+ Run ``cpack`` with verbose output. This can be used to show more details
+ from the package generation tools and is suitable for project developers.
``--debug``
- enable debug output (for CPack developers)
-
- Run cpack with debug output (for CPack developers).
+ Run ``cpack`` with debug output. This option is intended mainly for the
+ developers of ``cpack`` itself and is not normally needed by project
+ developers.
``--trace``
- Put underlying cmake scripts in trace mode.
+ Put the underlying cmake scripts in trace mode.
``--trace-expand``
- Put underlying cmake scripts in expanded trace mode.
-
-``-P <package name>``
- override/define CPACK_PACKAGE_NAME
-
- If the package name is not specified on cpack command line
- thenCPack.cmake defines it as CMAKE_PROJECT_NAME
-
-``-R <package version>``
- override/define CPACK_PACKAGE_VERSION
-
- If version is not specified on cpack command line thenCPack.cmake
- defines it from CPACK_PACKAGE_VERSION_[MAJOR|MINOR|PATCH]look into
- CPack.cmake for detail
-
-``-B <package directory>``
- override/define CPACK_PACKAGE_DIRECTORY
-
- The directory where CPack will be doing its packaging work.The
- resulting package will be found there. Inside this directoryCPack
- creates '_CPack_Packages' sub-directory which is theCPack temporary
- directory.
-
-``--vendor <vendor name>``
- override/define CPACK_PACKAGE_VENDOR
-
- If vendor is not specified on cpack command line (or inside
- CMakeLists.txt) thenCPack.cmake defines it with a default value
+ Put the underlying cmake scripts in expanded trace mode.
+
+``-P <packageName>``
+ Override/define the value of the :variable:`CPACK_PACKAGE_NAME` variable used
+ for packaging. Any value set for this variable in the ``CPackConfig.cmake``
+ file will then be ignored.
+
+``-R <packageVersion>``
+ Override/define the value of the :variable:`CPACK_PACKAGE_VERSION`
+ variable used for packaging. It will override a value set in the
+ ``CPackConfig.cmake`` file or one automatically computed from
+ :variable:`CPACK_PACKAGE_VERSION_MAJOR`,
+ :variable:`CPACK_PACKAGE_VERSION_MINOR` and
+ :variable:`CPACK_PACKAGE_VERSION_PATCH`.
+
+``-B <packageDirectory>``
+ Override/define :variable:`CPACK_PACKAGE_DIRECTORY`, which controls the
+ directory where CPack will perform its packaging work. The resultant
+ package(s) will be created at this location by default and a
+ ``_CPack_Packages`` subdirectory will also be created below this directory to
+ use as a working area during package creation.
+
+``--vendor <vendorName>``
+ Override/define :variable:`CPACK_PACKAGE_VENDOR`.
.. include:: OPTIONS_HELP.txt
ctest [<options>]
ctest <path-to-source> <path-to-build> --build-generator <generator>
[<options>...] [-- <build-options>...] [--test-command <test>]
- ctest (-D <dashboard> | -M <model> -T <action> | -S <script> | -SP <script>)
+ ctest {-D <dashboard> | -M <model> -T <action> | -S <script> | -SP <script>}
[-- <dashboard-options>...]
Description
Build and Test Mode
===================
-CTest provides a command-line signature to to configure (i.e. run cmake on),
-build, and or execute a test::
+CTest provides a command-line signature to configure (i.e. run cmake on),
+build, and/or execute a test::
ctest --build-and-test <path-to-source> <path-to-build>
- --build-generator <generator> [<options>...] [-- <build-options>...]
- [--test-command <test>]
+ --build-generator <generator>
+ [<options>...]
+ [--build-options <opts>...]
+ [--test-command <command> [<args>...]]
The configure and test steps are optional. The arguments to this command line
-are the source and binary directories. The ``--build-generator`` option *must*
+are the source and binary directories. The ``--build-generator`` option *must*
be provided to use ``--build-and-test``. If ``--test-command`` is specified
then that will be run after the build is complete. Other options that affect
this mode include:
should be used. e.g. Debug/Release/etc.
``--build-options``
- Add extra options to the build step.
-
- This option must be the last option with the exception of
- ``--test-command``
+ Additional options for configuring the build (i.e. for CMake, not for
+ the build tool). Note that if this is specified, the ``--build-options``
+ keyword and its arguments must be the last option given on the command
+ line, with the possible exception of ``--test-command``.
``--test-command``
- The test to run with the ``--build-and-test`` option.
+ The command to run as the test step with the ``--build-and-test`` option.
+ All arguments following this keyword will be assumed to be part of the
+ test command line, so it must be the last option given.
``--test-timeout``
The time limit in seconds
--- /dev/null
+.. cmake-module:: ../../Modules/CPackNuGet.cmake
--- /dev/null
+.. cmake-module:: ../../Modules/FindODBC.cmake
--- /dev/null
+.. cmake-module:: ../../Modules/FindPython.cmake
--- /dev/null
+.. cmake-module:: ../../Modules/FindPython2.cmake
--- /dev/null
+.. cmake-module:: ../../Modules/FindPython3.cmake
--- /dev/null
+CMP0073
+-------
+
+Do not produce legacy ``_LIB_DEPENDS`` cache entries.
+
+Ancient CMake versions once used ``<tgt>_LIB_DEPENDS`` cache entries to
+propagate library link dependencies. This has long been done by other
+means, leaving the :command:`export_library_dependencies` command as the
+only user of these values. That command has long been disallowed by
+policy :policy:`CMP0033`, but the ``<tgt>_LIB_DEPENDS`` cache entries
+were left for compatibility with possible non-standard uses by projects.
+
+CMake 3.12 and above now prefer to not produce these cache entries
+at all. This policy provides compatibility with projects that have
+not been updated to avoid using them.
+
+The ``OLD`` behavior for this policy is to set ``<tgt>_LIB_DEPENDS`` cache
+entries. The ``NEW`` behavior for this policy is to not set them.
+
+This policy was introduced in CMake version 3.12. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike most policies, CMake version |release| does *not* warn
+when this policy is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
--- /dev/null
+CMP0074
+-------
+
+:command:`find_package` uses ``PackageName_ROOT`` variables.
+
+In CMake 3.12 and above the ``find_package(PackageName)`` command now searches
+a prefix specified by a ``PackageName_ROOT`` CMake or environment variable.
+Package roots are maintained as a stack so nested calls to all ``find_*``
+commands inside find modules also search the roots as prefixes. This policy
+provides compatibility with projects that have not been updated to avoid using
+``PackageName_ROOT`` variables for other purposes.
+
+The ``OLD`` behavior for this policy is to ignore ``PackageName_ROOT``
+variables. The ``NEW`` behavior for this policy is to use ``PackageName_ROOT``
+variables.
+
+This policy was introduced in CMake version 3.12. CMake version
+|release| warns when the policy is not set and uses ``OLD`` behavior.
+Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
+explicitly.
+
+.. include:: DEPRECATED.txt
--- /dev/null
+CMP0075
+-------
+
+Include file check macros honor ``CMAKE_REQUIRED_LIBRARIES``.
+
+In CMake 3.12 and above, the
+
+* ``check_include_file`` macro in the :module:`CheckIncludeFile` module, the
+* ``check_include_file_cxx`` macro in the
+ :module:`CheckIncludeFileCXX` module, and the
+* ``check_include_files`` macro in the :module:`CheckIncludeFiles` module
+
+now prefer to link the check executable to the libraries listed in the
+``CMAKE_REQUIRED_LIBRARIES`` variable. This policy provides compatibility
+with projects that have not been updated to expect this behavior.
+
+The ``OLD`` behavior for this policy is to ignore ``CMAKE_REQUIRED_LIBRARIES``
+in the include file check macros. The ``NEW`` behavior of this policy is to
+honor ``CMAKE_REQUIRED_LIBRARIES`` in the include file check macros.
+
+This policy was introduced in CMake version 3.12. CMake version
+|release| warns when the policy is not set and uses ``OLD`` behavior.
+Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
+explicitly.
+
+.. include:: DEPRECATED.txt
Preprocessor definitions for compiling a directory's sources.
This property specifies the list of options given so far to the
-:command:`add_definitions` command.
+:command:`add_compile_definitions` (or :command:`add_definitions`) command.
The ``COMPILE_DEFINITIONS`` property may be set to a semicolon-separated
list of preprocessor definitions using the syntax ``VAR`` or ``VAR=value``.
--- /dev/null
+TESTS
+-----
+
+List of tests.
+
+This read-only property holds a :ref:`;-list <CMake Language Lists>` of tests
+defined so far by the :command:`add_test` command.
solution global section. Whitespace around key and value is ignored.
List elements which do not contain an equal sign are skipped.
-This property only works for Visual Studio 8 and above; it is ignored
+This property only works for Visual Studio 9 and above; it is ignored
on other generators. The property only applies when set on a
directory whose CMakeLists.txt contains a project() command.
solution global section. Whitespace around key and value is ignored.
List elements which do not contain an equal sign are skipped.
-This property only works for Visual Studio 8 and above; it is ignored
+This property only works for Visual Studio 9 and above; it is ignored
on other generators. The property only applies when set on a
directory whose CMakeLists.txt contains a project() command.
``cxx_std_17``
Compiler mode is aware of C++ 17.
+``cxx_std_20``
+ Compiler mode is aware of C++ 20.
+
``cxx_aggregate_default_initializers``
Aggregate default initializers, as defined in N3605_.
--- /dev/null
+ECLIPSE_EXTRA_CPROJECT_CONTENTS
+-------------------------------
+
+Additional contents to be inserted into the generated Eclipse cproject file.
+
+The cproject file defines the CDT specific information. Some third party IDE's
+are based on Eclipse with the addition of other information specific to that IDE.
+Through this property, it is possible to add this additional contents to
+the generated project.
+It is expected to contain valid XML.
+
+Also see the :prop_gbl:`ECLIPSE_EXTRA_NATURES` property.
Eclipse projects specify language plugins by using natures. This property
should be set to the unique identifier for a nature (which looks like a Java
package name).
+
+Also see the :prop_gbl:`ECLIPSE_EXTRA_CPROJECT_CONTENTS` property.
--- /dev/null
+VS_SHADER_OBJECT_FILE_NAME
+--------------------------
+
+Specifies a file name for the compiled shader object file for an ``.hlsl``
+source file. This adds the ``-Fo`` flag to the command line for the FxCompiler
+tool.
----------
Set to specify how many process slots this test requires.
+If not set, the default is ``1`` processor.
Denotes the number of processors that this test will require. This is
typically used for MPI tests, and should be used in conjunction with
subproject summaries in the command line output of :manual:`ctest(1)`. The wall
clock time for the test run will be multiplied by this property to give a
better idea of how much cpu resource CTest allocated for the test.
+
+See also the :prop_test:`PROCESSOR_AFFINITY` test property.
--- /dev/null
+PROCESSOR_AFFINITY
+------------------
+
+Set to a true value to ask CTest to launch the test process with CPU affinity
+for a fixed set of processors. If enabled and supported for the current
+platform, CTest will choose a set of processors to place in the CPU affinity
+mask when launching the test process. The number of processors in the set is
+determined by the :prop_test:`PROCESSORS` test property or the number of
+processors available to CTest, whichever is smaller. The set of processors
+chosen will be disjoint from the processors assigned to other concurrently
+running tests that also have the ``PROCESSOR_AFFINITY`` property enabled.
The directory from which the test executable will be called.
-If this is not set it is called from the directory the test executable
-is located in.
+If this is not set, the test will be run with the working directory set to the
+binary directory associated with where the test was created (i.e. the
+:variable:`CMAKE_CURRENT_BINARY_DIR` for where :command:`add_test` was
+called).
Example
^^^^^^^
-In this case the the ``Q_OBJECT`` macro is hidden inside an other macro
-called ``CUSTOM_MACRO``. To let CMake know that source files, that contain
-``CUSTOM_MACRO``, need to be ``moc`` processed, we call::
+In this case the ``Q_OBJECT`` macro is hidden inside another macro
+called ``CUSTOM_MACRO``. To let CMake know that source files that contain
+``CUSTOM_MACRO`` need to be ``moc`` processed, we call::
set_property(TARGET tgt APPEND PROPERTY AUTOMOC_MACRO_NAMES "CUSTOM_MACRO")
--- /dev/null
+COMMON_LANGUAGE_RUNTIME
+-----------------------
+
+By setting this target property, the target is configured to build with
+``C++/CLI`` support.
+
+The Visual Studio generator defines the ``clr`` parameter depending on
+the value of ``COMMON_LANGUAGE_RUNTIME``:
+
+* property not set: native C++ (i.e. default)
+* property set but empty: mixed unmanaged/managed C++
+* property set to any non empty value: managed C++
+
+Supported values: ``""``, ``"pure"``, ``"safe"``
+
+This property is only evaluated :ref:`Visual Studio Generators` for
+VS 2010 and above.
+
+To be able to build managed C++ targets with VS 2017 and above the component
+``C++/CLI support`` must be installed, which may not be done by default.
+
+See also :prop_tgt:`IMPORTED_COMMON_LANGUAGE_RUNTIME`
have no notion of a standard level, such as Microsoft Visual C++ before
2015 Update 3, this has no effect.
-Supported values are ``98``, ``11``, ``14``, and ``17``.
+Supported values are ``98``, ``11``, ``14``, ``17``, and ``20``.
If the value requested does not result in a compile flag being added for
the compiler in use, a previous standard flag will be added instead. This
Set the WinCE project ``RemoteDirectory`` in ``DeploymentTool`` and
``RemoteExecutable`` in ``DebuggerTool`` in ``.vcproj`` files generated
-by the :generator:`Visual Studio 9 2008` and :generator:`Visual Studio 8 2005`
-generators. This is useful when you want to debug on remote WinCE device.
+by the :generator:`Visual Studio 9 2008` generator.
+This is useful when you want to debug on remote WinCE device.
For example:
.. code-block:: cmake
--- /dev/null
+DOTNET_TARGET_FRAMEWORK_VERSION
+-------------------------------
+
+Specify the .NET target framework version.
+
+Used to specify the .NET target framework version for C++/CLI. For
+example, "v4.5".
+
+This property is only evaluated for :ref:`Visual Studio Generators`
+VS 2010 and above.
+
+Can be initialized for all targets using the variable
+:variable:`CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION`.
--- /dev/null
+EXPORT_PROPERTIES
+-----------------
+
+List additional properties to export for a target.
+
+This property contains a list of property names that should be exported by
+the :command:`install(EXPORT)` and :command:`export` commands. By default
+only a limited number of properties are exported. This property can be used
+to additionally export other properties as well.
+
+Properties starting with ``INTERFACE_`` or ``IMPORTED_`` are not allowed as
+they are reserved for internal CMake use.
+
+Properties containing generator expressions are also not allowed.
will appear next to each other in a folder of that name. To nest
folders, use FOLDER values such as 'GUI/Dialogs' with '/' characters
separating folder levels.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_FOLDER` if it is set when a target is created.
--- /dev/null
+IMPORTED_COMMON_LANGUAGE_RUNTIME
+--------------------------------
+
+Property to define if the target uses ``C++/CLI``.
+
+Ignored for non-imported targets.
+
+See also the :prop_tgt:`COMMON_LANGUAGE_RUNTIME` target property.
INSTALL_NAME_DIR is a string specifying the directory portion of the
"install_name" field of shared libraries on Mac OSX to use in the
installed targets.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_INSTALL_NAME_DIR` if it is set when a target is
+created.
generated by the linker for an executable or shared library target.
This property specifies the directory into which the MS debug symbols
-will be placed by the linker. This property is initialized by the
-value of the :variable:`CMAKE_PDB_OUTPUT_DIRECTORY` variable if it is
+will be placed by the linker. The property value may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+Multi-configuration generators append a per-configuration
+subdirectory to the specified directory unless a generator expression
+is used.
+
+This property is initialized by the value of the
+:variable:`CMAKE_PDB_OUTPUT_DIRECTORY` variable if it is
set when a target is created.
.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY`
:variable:`CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG>` variable if it is
set when a target is created.
+Contents of ``PDB_OUTPUT_DIRECTORY_<CONFIG>`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>`
.. include:: PDB_NOTE.txt
This read-only property can be used to test the type of the given
target. It will be one of STATIC_LIBRARY, MODULE_LIBRARY,
-SHARED_LIBRARY, INTERFACE_LIBRARY, EXECUTABLE or one of the internal
-target types.
+SHARED_LIBRARY, OBJECT_LIBRARY, INTERFACE_LIBRARY, EXECUTABLE or one
+of the internal target types.
--- /dev/null
+VS_DEBUGGER_COMMAND
+-------------------
+
+Sets the local debugger command for Visual Studio C++ targets.
+This is defined in ``<LocalDebuggerCommand>`` in the Visual Studio
+project file.
+
+This property only works for Visual Studio 2010 and above;
+it is ignored on other generators.
Sets the local debugger working directory for Visual Studio C++ targets.
This is defined in ``<LocalDebuggerWorkingDirectory>`` in the Visual Studio
project file.
+
+This property only works for Visual Studio 2010 and above;
+it is ignored on other generators.
Used to specify the .NET target framework version for C++/CLI. For
example, "v4.5".
+
+This property is deprecated and should not be used anymore. Use
+:prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` instead.
option to change the ``boost`` prefix on library names.
* The :module:`FindBoost` module learned to control search
- for libraies with the ``g`` tag (for MS debug runtime) with
+ for libraries with the ``g`` tag (for MS debug runtime) with
a new ``Boost_USE_DEBUG_RUNTIME`` option. It is ``ON`` by
default to preserve existing behavior.
--- /dev/null
+CMake 3.12 Release Notes
+************************
+
+.. only:: html
+
+ .. contents::
+
+Changes made since CMake 3.11 include the following.
+
+New Features
+============
+
+Generators
+----------
+
+* The :ref:`Visual Studio Generators` for VS 2017 learned to support a
+ ``version=14.##`` option in the :variable:`CMAKE_GENERATOR_TOOLSET`
+ value (e.g. via the :manual:`cmake(1)` ``-T`` option) to specify a
+ toolset version number.
+
+Command-Line
+------------
+
+* The :manual:`cmake(1)` :ref:`Build Tool Mode` (``cmake --build``) gained
+ ``--parallel [<jobs>]`` and ``-j [<jobs>]`` options to specify a parallel
+ build level. They map to corresponding options of the native build tool.
+
+Commands
+--------
+
+* The :command:`add_compile_definitions` command was added to set preprocessor
+ definitions at directory level. This supersedes :command:`add_definitions`.
+
+* The :command:`cmake_minimum_required` and :command:`cmake_policy(VERSION)`
+ commands now accept a version range using the form ``<min>[...<max>]``.
+ The ``<min>`` version is required but policies are set based on the
+ older of the running CMake version and the version specified by
+ ``<max>``. This allows projects to specify a range of versions
+ for which they have been updated and avoid explicit policy settings.
+
+* The :command:`file(GLOB)` and :command:`file(GLOB_RECURSE)` commands
+ learned a new flag ``CONFIGURE_DEPENDS`` which enables expression of
+ build system dependency on globbed directory's contents.
+
+* The :command:`file(TOUCH)` and :command:`file(TOUCH_NOCREATE)` commands
+ were added to expose ``TOUCH`` functionality without having to use
+ CMake's command-line tool mode with :command:`execute_process`.
+
+* The :command:`find_package` command now searches a prefix specified by
+ a ``PackageName_ROOT`` CMake or environment variable. Package roots are
+ maintained as a stack so nested calls to all ``find_*`` commands inside
+ find modules also search the roots as prefixes.
+ See policy :policy:`CMP0074`.
+
+* The :command:`install` command learned an optional ``NAMELINK_COMPONENT``
+ parameter, which allows you to change the component for a shared library's
+ namelink. If none is specified, the value of ``COMPONENT`` is used by
+ default.
+
+* The :command:`list` command learned a ``JOIN`` sub-command
+ to concatenate list's elements separated by a glue string.
+
+* The :command:`list` command learned a ``SUBLIST`` sub-command
+ to get a sublist of the list.
+
+* The :command:`list` command learned a ``TRANSFORM`` sub-command
+ to apply various string transformation to list's elements.
+
+* The :command:`project` command learned an optional ``HOMEPAGE_URL``
+ parameter which has the effect of setting variables like
+ :variable:`PROJECT_HOMEPAGE_URL`, :variable:`<PROJECT-NAME>_HOMEPAGE_URL`
+ and :variable:`CMAKE_PROJECT_HOMEPAGE_URL`.
+
+* The :command:`string` command learned a ``JOIN`` sub-command
+ to concatenate input strings separated by a glue string.
+
+* :command:`target_compile_options` and :command:`add_compile_options`
+ commands gained a ``SHELL:`` prefix to specify a group of related
+ options using shell-like quoting.
+
+* The :command:`target_link_libraries` command now supports
+ :ref:`Object Libraries`. Linking to an object library uses its object
+ files in direct dependents and also propagates usage requirements.
+
+Variables
+---------
+
+* The :variable:`CMAKE_FOLDER` variable was added to initialize the
+ :prop_tgt:`FOLDER` property on all targets.
+
+* The :variable:`CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION` variable
+ was defined to initialize all
+ :prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` target properties.
+
+* ``CMAKE_PROJECT_VERSION*`` variables have been introduced:
+
+ - :variable:`CMAKE_PROJECT_VERSION`
+ - :variable:`CMAKE_PROJECT_VERSION_MAJOR`
+ - :variable:`CMAKE_PROJECT_VERSION_MINOR`
+ - :variable:`CMAKE_PROJECT_VERSION_PATCH`
+ - :variable:`CMAKE_PROJECT_VERSION_TWEAK`
+
+* The :variable:`CMAKE_SUPPRESS_REGENERATION` variable was extended to
+ support the :generator:`Ninja` and :ref:`Makefile Generators`.
+ It is also now documented.
+
+* ``CMAKE_VS_SDK_*_DIRECTORIES`` variables were defined to tell
+ :ref:`Visual Studio Generators` for VS 2010 and above how to populate
+ fields in ``.vcxproj`` files that specify SDK directories. The
+ variables are:
+
+ - :variable:`CMAKE_VS_SDK_EXCLUDE_DIRECTORIES`
+ - :variable:`CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES`
+ - :variable:`CMAKE_VS_SDK_INCLUDE_DIRECTORIES`
+ - :variable:`CMAKE_VS_SDK_LIBRARY_DIRECTORIES`
+ - :variable:`CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES`
+ - :variable:`CMAKE_VS_SDK_REFERENCE_DIRECTORIES`
+ - :variable:`CMAKE_VS_SDK_SOURCE_DIRECTORIES`
+
+* A :variable:`MSVC_TOOLSET_VERSION` variable was added to provide the
+ MSVC toolset version associated with the current MSVC compiler version
+ in :variable:`MSVC_VERSION`.
+
+Properties
+----------
+
+* The :prop_tgt:`COMMON_LANGUAGE_RUNTIME` target property was introduced
+ to configure the use of managed C++ for :ref:`Visual Studio Generators`
+ for VS 2010 and above.
+ A corresponding :prop_tgt:`IMPORTED_COMMON_LANGUAGE_RUNTIME` target
+ property was added to support ``C++/CLI`` for imported targets.
+
+* The :prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` target property
+ was introduced as replacement for
+ :prop_tgt:`VS_DOTNET_TARGET_FRAMEWORK_VERSION`, which is considered
+ deprecated now.
+
+* An :prop_tgt:`EXPORT_PROPERTIES` target property was added to specify a
+ custom list of target properties to include in targets exported by the
+ :command:`install(EXPORT)` and :command:`export` commands.
+
+* The :prop_tgt:`PDB_OUTPUT_DIRECTORY` property learned to support
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+* A :prop_dir:`TESTS` directory property was added to hold the list of
+ tests defined by the :command:`add_test` command.
+
+* A :prop_tgt:`VS_DEBUGGER_COMMAND` target property was created to set the
+ debugging command line with :ref:`Visual Studio Generators` for VS 2010
+ and above.
+
+* HLSL source file properties :prop_sf:`VS_SHADER_DISABLE_OPTIMIZATIONS`
+ and :prop_sf:`VS_SHADER_ENABLE_DEBUG` gained support for generator
+ expressions.
+
+* HLSL source file property :prop_sf:`VS_SHADER_OBJECT_FILE_NAME` has been
+ added to the :ref:`Visual Studio Generators` for VS 2010 and above.
+ The property specifies the file name of the compiled shader object.
+
+Modules
+-------
+
+* The :module:`FindALSA` module now provides imported targets.
+
+* The :module:`FindCURL` module now provides imported targets.
+
+* The :module:`FindJPEG` module now provides imported targets.
+
+* The :module:`FindLibXml2` module now provides imported targets.
+
+* The :module:`FindMatlab` module now supports the Matlab Runtime
+ Compiler (MCR) for compiling and linking matlab extensions.
+
+* A :module:`FindODBC` module was added to find an Open Database Connectivity
+ (ODBC) library.
+
+* The :module:`FindPkgConfig` module has learned to export the found
+ libraries with full path for direct consumption with the
+ :command:`target_link_libraries` command.
+
+* New :module:`FindPython3` and :module:`FindPython2` modules, as well as
+ a new :module:`FindPython` module, have been added to provide a new way
+ to locate python environments.
+
+* The :module:`UseSWIG` module gained a whole refresh and is now more
+ consistent with standard CMake commands to generate libraries and is
+ fully configurable through properties.
+
+* The :module:`UseSWIG` module learned to manage multiple behaviors through
+ ``UseSWIG_MODULE_VERSION`` variable to ensure legacy support as well as more
+ robust handling of ``SWIG`` advanced features (like ``%template``).
+
+* The :module:`UseSWIG` module learned to support CSHARP variant
+ wrapper files.
+
+* The :module:`WriteCompilerDetectionHeader` module gained a ``BARE_FEATURES``
+ option to add a compatibility define for the exact keyword of a new language
+ feature.
+
+Generator Expressions
+---------------------
+
+* A new ``$<GENEX_EVAL:...>`` and ``$<TARGET_GENEX_EVAL:target,...>``
+ :manual:`generator expression <cmake-generator-expressions(7)>`
+ has been added to enable consumption of generator expressions whose
+ evaluation results itself in generator expressions.
+
+* A new ``$<IN_LIST:...>``
+ :manual:`generator expression <cmake-generator-expressions(7)>`
+ has been added.
+
+* A new ``$<TARGET_EXISTS:...>``
+ :manual:`generator expression <cmake-generator-expressions(7)>`
+ has been added.
+
+* A new ``$<TARGET_NAME_IF_EXISTS:...>``
+ :manual:`generator expression <cmake-generator-expressions(7)>`
+ has been added.
+
+CTest
+-----
+
+* The :command:`ctest_start` command has been reworked so that you can simply
+ call ``ctest_start(APPEND)`` and it will read all the needed information from
+ the TAG file. The argument parsing has also been relaxed so that the order of
+ the arguments is less significant.
+
+* A :prop_test:`PROCESSOR_AFFINITY` test property was added to request
+ that CTest run a test with CPU affinity for a set of processors
+ disjoint from other concurrently running tests with the property set.
+
+CPack
+-----
+
+* The :module:`CPack` module now uses variables
+ :variable:`CMAKE_PROJECT_VERSION_MAJOR`,
+ :variable:`CMAKE_PROJECT_VERSION_MINOR` and
+ :variable:`CMAKE_PROJECT_VERSION_PATCH`
+ to initialize corresponding CPack variables.
+
+* :manual:`cpack(1)` gained basic support for `NuGet`_.
+ See the :module:`CPackNuGet` module.
+
+.. _NuGet: https://docs.microsoft.com/en-us/nuget/what-is-nuget
+
+Other
+-----
+
+* The :manual:`Compile Features <cmake-compile-features(7)>` functionality
+ is now aware of C++ 20. No specific features are yet enumerated besides
+ the ``cxx_std_20`` meta-feature.
+
+* The :manual:`Compile Features <cmake-compile-features(7)>` functionality
+ is now aware of the availability of C features in MSVC since VS 2010.
+
+* The :manual:`Compile Features <cmake-compile-features(7)>` functionality
+ is now aware of C language standards supported by Texas Instruments C
+ compilers.
+
+Deprecated and Removed Features
+===============================
+
+* The :generator:`Visual Studio 8 2005` generator has been removed.
+
+* CMake no longer produces ``<tgt>_LIB_DEPENDS`` cache entries
+ for library targets. See policy :policy:`CMP0073`.
+
+Other Changes
+=============
+
+* Include flags for directories marked as ``SYSTEM`` are now moved after
+ non-system directories. The ``-isystem`` flag does this automatically,
+ so moving them explicitly to the end makes the behavior consistent on
+ compilers that do not have any ``-isystem`` flag.
+
+* Fortran dependency scanning now supports dependencies implied by
+ `Fortran Submodules`_.
+
+* The existence and functionality of the file
+ ``${CMAKE_BINARY_DIR}/cmake_install.cmake`` has now been documented in the
+ :command:`install` documentation so that external packaging software can take
+ advantage of CPack-style component installs.
+
+* The :module:`CheckIncludeFile` module ``check_include_file`` macro
+ learned to honor the ``CMAKE_REQUIRED_LIBRARIES`` variable.
+ See policy :policy:`CMP0075`.
+
+* The :module:`CheckIncludeFileCXX` module ``check_include_file_cxx`` macro
+ learned to honor the ``CMAKE_REQUIRED_LIBRARIES`` variable.
+ See policy :policy:`CMP0075`.
+
+* The :module:`CheckIncludeFiles` module ``check_include_files`` macro
+ learned to honor the ``CMAKE_REQUIRED_LIBRARIES`` variable.
+ See policy :policy:`CMP0075`.
+
+* The :manual:`cmake(1)` ``-E copy_directory`` tool now fails when the
+ source directory does not exist. Previously it succeeded by creating
+ an empty destination directory.
+
+* The :module:`UseSWIG` module :command:`swig_add_library` command
+ (and legacy ``swig_add_module`` command) now set the prefix of
+ Java modules to ``""`` for MINGW, MSYS, and CYGWIN environments.
+
+.. _`Fortran Submodules`: http://fortranwiki.org/fortran/show/Submodules
.. toctree::
:maxdepth: 1
+ 3.12 <3.12>
3.11 <3.11>
3.10 <3.10>
3.9 <3.9>
::
- $(ConfigurationName) = Visual Studio 8, 9
+ $(ConfigurationName) = Visual Studio 9
$(Configuration) = Visual Studio 10
$(CONFIGURATION) = Xcode
. = Make-based tools
--- /dev/null
+CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION
+-------------------------------------
+
+Default value for :prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION`
+property of targets.
+
+This variable is used to initialize the
+:prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` property on all
+targets. See that target property for additional information.
+
+Setting ``CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION`` may be necessary
+when working with ``C#`` and newer .NET framework versions to
+avoid referencing errors with the ``ALL_BUILD`` CMake target.
+
+This variable is only evaluated for :ref:`Visual Studio Generators`
+VS 2010 and above.
--- /dev/null
+CMAKE_FOLDER
+------------
+
+Set the folder name. Use to organize targets in an IDE.
+
+This variable is used to initialize the :prop_tgt:`FOLDER` property on all the
+targets. See that target property for additional information.
Supported by VS 2013 and above.
See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE`
variable.
+
+``version=<version>``
+ Specify the toolset version to use. Supported by VS 2017
+ and above with the specified toolset installed.
+ See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_VERSION` variable.
CMAKE_HOST_SYSTEM
-----------------
-Composit Name of OS CMake is being run on.
+Composite Name of OS CMake is being run on.
This variable is the composite of :variable:`CMAKE_HOST_SYSTEM_NAME` and
:variable:`CMAKE_HOST_SYSTEM_VERSION`, e.g.
project might choose its own default.
On UNIX one can use the ``DESTDIR`` mechanism in order to relocate the
-whole installation. ``DESTDIR`` means DESTination DIRectory. It is
-commonly used by makefile users in order to install software at
-non-default location. It is usually invoked like this:
-
-::
-
- make DESTDIR=/home/john install
-
-which will install the concerned software using the installation
-prefix, e.g. ``/usr/local`` prepended with the ``DESTDIR`` value which
-finally gives ``/home/john/usr/local``.
-
-WARNING: ``DESTDIR`` may not be used on Windows because installation
-prefix usually contains a drive letter like in ``C:/Program Files``
-which cannot be prepended with some other prefix.
+whole installation. See :envvar:`DESTDIR` for more information.
The installation prefix is also added to :variable:`CMAKE_SYSTEM_PREFIX_PATH`
so that :command:`find_package`, :command:`find_program`,
CMAKE_<LANG>_CLANG_TIDY
-----------------------
-Default value for :prop_tgt:`<LANG>_CLANG_TIDY` target property.
+Default value for :prop_tgt:`<LANG>_CLANG_TIDY` target property
+when ``<LANG>`` is ``C`` or ``CXX``.
+
This variable is used to initialize the property on each target as it is
-created. This is done only when ``<LANG>`` is ``C`` or ``CXX``.
+created. For example:
+
+.. code-block:: cmake
+
+ set(CMAKE_CXX_CLANG_TIDY clang-tidy checks=-*,readability-*)
+ add_executable(foo foo.cxx)
Flags for all build types.
``<LANG>`` flags used regardless of the value of :variable:`CMAKE_BUILD_TYPE`.
+
+This is initialized for each language from environment variables:
+
+* ``CMAKE_C_FLAGS``:
+ Initialized by the :envvar:`CFLAGS` environment variable.
+* ``CMAKE_CXX_FLAGS``:
+ Initialized by the :envvar:`CXXFLAGS` environment variable.
+* ``CMAKE_CUDA_FLAGS``:
+ Initialized by the :envvar:`CUDAFLAGS` environment variable.
+* ``CMAKE_Fortran_FLAGS``:
+ Initialized by the :envvar:`FFLAGS` environment variable.
language. CMake automatically detects these directories for each
language and reports the results in this variable.
-When a library in one of these directories is given by full path to
-:command:`target_link_libraries` CMake will generate the ``-l<name>`` form on
-link lines to ensure the linker searches its implicit directories for the
-library. Note that some toolchains read implicit directories from an
-environment variable such as ``LIBRARY_PATH`` so keep its value consistent
-when operating in a given build tree.
+Some toolchains read implicit directories from an environment variable such as
+``LIBRARY_PATH``. If using such an environment variable, keep its value
+consistent when operating in a given build tree because CMake saves the value
+detected when first creating a build tree.
+
+If policy :policy:`CMP0060` is not set to ``NEW``, then when a library in one
+of these directories is given by full path to :command:`target_link_libraries`
+CMake will generate the ``-l<name>`` form on link lines for historical
+purposes.
CMAKE_MINIMUM_REQUIRED_VERSION
------------------------------
-Version specified to :command:`cmake_minimum_required` command
-
-Variable containing the ``VERSION`` component specified in the
-:command:`cmake_minimum_required` command.
+The ``<min>`` version of CMake given to the most recent call to the
+:command:`cmake_minimum_required(VERSION)` command.
-----------------
:ref:`;-list <CMake Language Lists>` of directories specifying a search path
-for CMake modules to be loaded by the the :command:`include` or
+for CMake modules to be loaded by the :command:`include` or
:command:`find_package` commands before checking the default modules that come
with CMake. By default it is empty, it is intended to be set by the project.
Target specific architectures for OS X and iOS.
This variable is used to initialize the :prop_tgt:`OSX_ARCHITECTURES`
-property on each target as it is creaed. See that target property
+property on each target as it is created. See that target property
for additional information.
.. include:: CMAKE_OSX_VARIABLE.txt
CMAKE_PROJECT_DESCRIPTION
-------------------------
-The description of the current project.
+The description of the top level project.
-This specifies description of the current project from the closest inherited
-:command:`project` command.
+This variable holds the description of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. In the event that
+the top level CMakeLists.txt contains multiple :command:`project` calls,
+the most recently called one from that top level CMakeLists.txt will determine
+the value that ``CMAKE_PROJECT_DESCRIPTION`` contains. For example, consider
+the following top level CMakeLists.txt:
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.0)
+ project(First DESCRIPTION "I am First")
+ project(Second DESCRIPTION "I am Second")
+ add_subdirectory(sub)
+ project(Third DESCRIPTION "I am Third")
+
+And ``sub/CMakeLists.txt`` with the following contents:
+
+.. code-block:: cmake
+
+ project(SubProj DESCRIPTION "I am SubProj")
+ message("CMAKE_PROJECT_DESCRIPTION = ${CMAKE_PROJECT_DESCRIPTION}")
+
+The most recently seen :command:`project` command from the top level
+CMakeLists.txt would be ``project(Second ...)``, so this will print::
+
+ CMAKE_PROJECT_DESCRIPTION = I am Second
+
+To obtain the description from the most recent call to :command:`project` in
+the current directory scope or above, see the :variable:`PROJECT_DESCRIPTION`
+variable.
--- /dev/null
+CMAKE_PROJECT_HOMEPAGE_URL
+--------------------------
+
+The homepage URL of the top level project.
+
+This variable holds the homepage URL of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. In the event that
+the top level CMakeLists.txt contains multiple :command:`project` calls,
+the most recently called one from that top level CMakeLists.txt will determine
+the value that ``CMAKE_PROJECT_HOMEPAGE_URL`` contains. For example, consider
+the following top level CMakeLists.txt:
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.0)
+ project(First HOMEPAGE_URL "http://first.example.com")
+ project(Second HOMEPAGE_URL "http://second.example.com")
+ add_subdirectory(sub)
+ project(Third HOMEPAGE_URL "http://third.example.com")
+
+And ``sub/CMakeLists.txt`` with the following contents:
+
+.. code-block:: cmake
+
+ project(SubProj HOMEPAGE_URL "http://subproj.example.com")
+ message("CMAKE_PROJECT_HOMEPAGE_URL = ${CMAKE_PROJECT_HOMEPAGE_URL}")
+
+The most recently seen :command:`project` command from the top level
+CMakeLists.txt would be ``project(Second ...)``, so this will print::
+
+ CMAKE_PROJECT_HOMEPAGE_URL = http://second.example.com
+
+To obtain the homepage URL from the most recent call to :command:`project` in
+the current directory scope or above, see the :variable:`PROJECT_HOMEPAGE_URL`
+variable.
CMAKE_PROJECT_NAME
------------------
-The name of the current project.
+The name of the top level project.
-This specifies name of the current project from the closest inherited
-:command:`project` command.
+This variable holds the name of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. In the event that
+the top level CMakeLists.txt contains multiple :command:`project` calls,
+the most recently called one from that top level CMakeLists.txt will determine
+the name that ``CMAKE_PROJECT_NAME`` contains. For example, consider
+the following top level CMakeLists.txt:
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.0)
+ project(First)
+ project(Second)
+ add_subdirectory(sub)
+ project(Third)
+
+And ``sub/CMakeLists.txt`` with the following contents:
+
+.. code-block:: cmake
+
+ project(SubProj)
+ message("CMAKE_PROJECT_NAME = ${CMAKE_PROJECT_NAME}")
+
+The most recently seen :command:`project` command from the top level
+CMakeLists.txt would be ``project(Second)``, so this will print::
+
+ CMAKE_PROJECT_NAME = Second
+
+To obtain the name from the most recent call to :command:`project` in
+the current directory scope or above, see the :variable:`PROJECT_NAME`
+variable.
--- /dev/null
+CMAKE_PROJECT_VERSION
+---------------------
+
+The version of the top level project.
+
+This variable holds the version of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. In the event that
+the top level CMakeLists.txt contains multiple :command:`project` calls,
+the most recently called one from that top level CMakeLists.txt will determine
+the value that ``CMAKE_PROJECT_VERSION`` contains. For example, consider
+the following top level CMakeLists.txt:
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.0)
+ project(First VERSION 1.2.3)
+ project(Second VERSION 3.4.5)
+ add_subdirectory(sub)
+ project(Third VERSION 6.7.8)
+
+And ``sub/CMakeLists.txt`` with the following contents:
+
+.. code-block:: cmake
+
+ project(SubProj VERSION 1)
+ message("CMAKE_PROJECT_VERSION = ${CMAKE_PROJECT_VERSION}")
+
+The most recently seen :command:`project` command from the top level
+CMakeLists.txt would be ``project(Second ...)``, so this will print::
+
+ CMAKE_PROJECT_VERSION = 3.4.5
+
+To obtain the version from the most recent call to :command:`project` in
+the current directory scope or above, see the :variable:`PROJECT_VERSION`
+variable.
--- /dev/null
+CMAKE_PROJECT_VERSION_MAJOR
+---------------------------
+
+The major version of the top level project.
+
+This variable holds the major version of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. Please see
+:variable:`CMAKE_PROJECT_VERSION` documentation for the behavior when
+multiple :command:`project` commands are used in the sources.
--- /dev/null
+CMAKE_PROJECT_VERSION_MINOR
+---------------------------
+
+The minor version of the top level project.
+
+This variable holds the minor version of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. Please see
+:variable:`CMAKE_PROJECT_VERSION` documentation for the behavior when
+multiple :command:`project` commands are used in the sources.
--- /dev/null
+CMAKE_PROJECT_VERSION_PATCH
+---------------------------
+
+The patch version of the top level project.
+
+This variable holds the patch version of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. Please see
+:variable:`CMAKE_PROJECT_VERSION` documentation for the behavior when
+multiple :command:`project` commands are used in the sources.
--- /dev/null
+CMAKE_PROJECT_VERSION_TWEAK
+---------------------------
+
+The tweak version of the top level project.
+
+This variable holds the tweak version of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. Please see
+:variable:`CMAKE_PROJECT_VERSION` documentation for the behavior when
+multiple :command:`project` commands are used in the sources.
--- /dev/null
+CMAKE_SUPPRESS_REGENERATION
+---------------------------
+
+If CMAKE_SUPPRESS_REGENERATION is ``OFF``, which is default, then CMake adds a
+special target on which all other targets depend that checks the build system
+and optionally re-runs CMake to regenerate the build system when the target
+specification source changes.
+
+If this variable evaluates to ``ON`` at the end of the top-level
+``CMakeLists.txt`` file, CMake will not add the regeneration target to the
+build system or perform any build system checks.
CMAKE_VS_DEVENV_COMMAND
-----------------------
-The generators for :generator:`Visual Studio 8 2005` and above set this
+The generators for :generator:`Visual Studio 9 2008` and above set this
variable to the ``devenv.com`` command installed with the corresponding
Visual Studio version. Note that this variable may be empty on
Visual Studio Express editions because they do not provide this tool.
CMAKE_VS_INTEL_Fortran_PROJECT_VERSION
--------------------------------------
-When generating for :generator:`Visual Studio 8 2005` or greater with the Intel
+When generating for :generator:`Visual Studio 9 2008` or greater with the Intel
Fortran plugin installed, this specifies the ``.vfproj`` project file format
version. This is intended for internal use by CMake and should not be
used by project code.
--- /dev/null
+CMAKE_VS_PLATFORM_TOOLSET_VERSION
+---------------------------------
+
+Visual Studio Platform Toolset version.
+
+The :ref:`Visual Studio Generators` for VS 2017 and above allow to
+select minor versions of the same toolset. The toolset version number
+may be specified by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of
+the form ``version=14.11``. If none is specified CMake will choose a default
+toolset. The value may be empty if no minor version was selected and the
+default is used.
--- /dev/null
+CMAKE_VS_SDK_EXCLUDE_DIRECTORIES
+--------------------------------
+
+This variable allows to override Visual Studio default Exclude Directories.
--- /dev/null
+CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES
+-----------------------------------
+
+This variable allows to override Visual Studio default Executable Directories.
--- /dev/null
+CMAKE_VS_SDK_INCLUDE_DIRECTORIES
+--------------------------------
+
+This variable allows to override Visual Studio default Include Directories.
--- /dev/null
+CMAKE_VS_SDK_LIBRARY_DIRECTORIES
+--------------------------------
+
+This variable allows to override Visual Studio default Library Directories.
--- /dev/null
+CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES
+--------------------------------------
+
+This variable allows to override Visual Studio default Library WinRT
+Directories.
--- /dev/null
+CMAKE_VS_SDK_REFERENCE_DIRECTORIES
+----------------------------------
+
+This variable allows to override Visual Studio default Reference Directories.
--- /dev/null
+CMAKE_VS_SDK_SOURCE_DIRECTORIES
+-------------------------------
+
+This variable allows to override Visual Studio default Source Directories.
--- /dev/null
+MSVC_TOOLSET_VERSION
+--------------------
+
+The toolset version of Microsoft Visual C/C++ being used if any.
+If MSVC-like is being used, this variable is set based on the version
+of the compiler as given by the :variable:`MSVC_VERSION` variable.
+
+Known toolset version numbers are::
+
+ 80 = VS 2005 (8.0)
+ 90 = VS 2008 (9.0)
+ 100 = VS 2010 (10.0)
+ 110 = VS 2012 (11.0)
+ 120 = VS 2013 (12.0)
+ 140 = VS 2015 (14.0)
+ 141 = VS 2017 (15.0)
+
+Compiler versions newer than those known to CMake will be reported
+as the latest known toolset version.
+
+See also the :variable:`MSVC_VERSION` variable.
1900 = VS 14.0 (v140 toolset)
1910-1919 = VS 15.0 (v141 toolset)
-See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` and
+:variable:`MSVC_TOOLSET_VERSION` variable.
--- /dev/null
+<PROJECT-NAME>_DESCRIPTION
+--------------------------
+
+Value given to the ``DESCRIPTION`` option of the most recent call to the
+:command:`project` command with project name ``<PROJECT-NAME>``, if any.
--- /dev/null
+<PROJECT-NAME>_HOMEPAGE_URL
+---------------------------
+
+Value given to the ``HOMEPAGE_URL`` option of the most recent call to the
+:command:`project` command with project name ``<PROJECT-NAME>``, if any.
Short project description given to the project command.
-This is the description given to the most recent :command:`project` command.
+This is the description given to the most recently called :command:`project`
+command in the current directory scope or above. To obtain the description
+of the top level project, see the :variable:`CMAKE_PROJECT_DESCRIPTION`
+variable.
--- /dev/null
+PROJECT_HOMEPAGE_URL
+--------------------
+
+The homepage URL of the project.
+
+This is the homepage URL given to the most recently called :command:`project`
+command in the current directory scope or above. To obtain the homepage URL
+of the top level project, see the :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
+variable.
Name of the project given to the project command.
-This is the name given to the most recent :command:`project` command.
+This is the name given to the most recently called :command:`project`
+command in the current directory scope or above. To obtain the name of
+the top level project, see the :variable:`CMAKE_PROJECT_NAME` variable.
endif()
if(CMAKE_SYSTEM_PROCESSOR)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}-ASM${ASM_DIALECT}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}-ASM${ASM_DIALECT}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
if(NOT _INCLUDED_FILE)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
endif()
endif()
-include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}-ASM${ASM_DIALECT} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}-ASM${ASM_DIALECT} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
if(NOT _INCLUDED_FILE)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL)
endif()
# This should be included before the _INIT variables are
set(CMAKE_C_SIMULATE_VERSION "@CMAKE_C_SIMULATE_VERSION@")
@_SET_CMAKE_C_COMPILER_ARCHITECTURE_ID@
@SET_MSVC_C_ARCHITECTURE_ID@
-@SET_CMAKE_XCODE_CURRENT_ARCH@
+@SET_CMAKE_XCODE_ARCHS@
set(CMAKE_AR "@CMAKE_AR@")
set(CMAKE_C_COMPILER_AR "@CMAKE_C_COMPILER_AR@")
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
#ifdef __cplusplus
-#error "A C++ compiler has been selected for C."
+# error "A C++ compiler has been selected for C."
#endif
#ifdef __CLASSIC_C__
-#define const
+# define const
#endif
#include "CMakeCompilerABI.h"
# load a hardware specific file, mostly useful for embedded compilers
if(CMAKE_SYSTEM_PROCESSOR)
if(CMAKE_C_COMPILER_ID)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_C_COMPILER_ID}-C-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_C_COMPILER_ID}-C-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
endif()
if (NOT _INCLUDED_FILE)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
endif ()
endif()
# load the system- and compiler specific files
if(CMAKE_C_COMPILER_ID)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_C_COMPILER_ID}-C
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_C_COMPILER_ID}-C
OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
endif()
if (NOT _INCLUDED_FILE)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}
OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
endif ()
set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX")
set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX")
+set(CMAKE_CUDA_COMPILER_LOADED 1)
set(CMAKE_CUDA_COMPILER_ID_RUN 1)
set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu)
set(CMAKE_CUDA_LINKER_PREFERENCE 15)
#ifndef __CUDACC__
-#error "A C or C++ compiler has been selected for CUDA"
+# error "A C or C++ compiler has been selected for CUDA"
#endif
#include "CMakeCompilerABI.h"
@CMAKE_CUDA_COMPILER_ID_ERROR_FOR_TEST@
const char* info_language_dialect_default = "INFO" ":" "dialect_default["
-#if __cplusplus > 201402L
+#if __cplusplus > 201703L
+ "20"
+#elif __cplusplus >= 201703L
"17"
#elif __cplusplus >= 201402L
"14"
if(CMAKE_CUDA_COMPILER_ID)
# load a hardware specific file, mostly useful for embedded compilers
if(CMAKE_SYSTEM_PROCESSOR)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CUDA_COMPILER_ID}-CUDA-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_CUDA_COMPILER_ID}-CUDA-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
endif()
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CUDA_COMPILER_ID}-CUDA OPTIONAL)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_CUDA_COMPILER_ID}-CUDA OPTIONAL)
endif()
# compile a cu file into an executable
if(NOT CMAKE_CUDA_LINK_EXECUTABLE)
set(CMAKE_CUDA_LINK_EXECUTABLE
- "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
+ "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
endif()
if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0")
set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
endif()
+# Add implicit host link directories that contain device libraries
+# to the device link line.
+set(__IMPLICT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+if(__IMPLICT_DLINK_DIRS)
+ list(REMOVE_ITEM __IMPLICT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
+endif()
+set(__IMPLICT_DLINK_FLAGS )
+foreach(dir ${__IMPLICT_DLINK_DIRS})
+ if(EXISTS "${dir}/libcublas_device.a")
+ string(APPEND __IMPLICT_DLINK_FLAGS " -L\"${dir}\"")
+ endif()
+endforeach()
+unset(__IMPLICT_DLINK_DIRS)
#These are used when linking relocatable (dc) cuda code
if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY)
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+ "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
endif()
if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE)
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+ "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
endif()
unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
+unset(__IMPLICT_DLINK_FLAGS)
set(CMAKE_CUDA_INFORMATION_LOADED 1)
set(CMAKE_CXX11_COMPILE_FEATURES "@CMAKE_CXX11_COMPILE_FEATURES@")
set(CMAKE_CXX14_COMPILE_FEATURES "@CMAKE_CXX14_COMPILE_FEATURES@")
set(CMAKE_CXX17_COMPILE_FEATURES "@CMAKE_CXX17_COMPILE_FEATURES@")
+set(CMAKE_CXX20_COMPILE_FEATURES "@CMAKE_CXX20_COMPILE_FEATURES@")
set(CMAKE_CXX_PLATFORM_ID "@CMAKE_CXX_PLATFORM_ID@")
set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@")
set(CMAKE_CXX_SIMULATE_VERSION "@CMAKE_CXX_SIMULATE_VERSION@")
@_SET_CMAKE_CXX_COMPILER_ARCHITECTURE_ID@
@SET_MSVC_CXX_ARCHITECTURE_ID@
-@SET_CMAKE_XCODE_CURRENT_ARCH@
+@SET_CMAKE_XCODE_ARCHS@
set(CMAKE_AR "@CMAKE_AR@")
set(CMAKE_CXX_COMPILER_AR "@CMAKE_CXX_COMPILER_AR@")
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
#ifndef __cplusplus
-#error "A C compiler has been selected for C++."
+# error "A C compiler has been selected for C++."
#endif
#include "CMakeCompilerABI.h"
#endif
const char* info_language_dialect_default = "INFO" ":" "dialect_default["
-#if CXX_STD > 201402L
+#if CXX_STD > 201703L
+ "20"
+#elif CXX_STD >= 201703L
"17"
#elif CXX_STD >= 201402L
"14"
# load a hardware specific file, mostly useful for embedded compilers
if(CMAKE_SYSTEM_PROCESSOR)
if(CMAKE_CXX_COMPILER_ID)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
endif()
if (NOT _INCLUDED_FILE)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
endif ()
endif()
# load the system- and compiler specific files
if(CMAKE_CXX_COMPILER_ID)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
endif()
if (NOT _INCLUDED_FILE)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL
RESULT_VARIABLE _INCLUDED_FILE)
endif ()
/* Size of a pointer-to-data in bytes. */
#define SIZEOF_DPTR (sizeof(void*))
const char info_sizeof_dptr[] = {
+ /* clang-format off */
'I', 'N', 'F', 'O', ':', 's', 'i', 'z', 'e', 'o', 'f', '_', 'd', 'p', 't',
'r', '[', ('0' + ((SIZEOF_DPTR / 10) % 10)), ('0' + (SIZEOF_DPTR % 10)), ']',
'\0'
- /* clang-format needs this comment to break after the opening brace */
+ /* clang-format on */
};
/* Application Binary Interface. */
#if defined(__sgi) && defined(_ABIO32)
-#define ABI_ID "ELF O32"
+# define ABI_ID "ELF O32"
#elif defined(__sgi) && defined(_ABIN32)
-#define ABI_ID "ELF N32"
+# define ABI_ID "ELF N32"
#elif defined(__sgi) && defined(_ABI64)
-#define ABI_ID "ELF 64"
+# 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__)
-#define ABI_ID "ELF ARMEABI"
+# define ABI_ID "ELF ARMEABI"
#elif defined(__GNU__) && defined(__ELF__) && defined(__ARMEB__)
-#define ABI_ID "ELF ARM"
+# define ABI_ID "ELF ARM"
#elif defined(__GNU__) && defined(__ELF__) && defined(__ARMEL__)
-#define ABI_ID "ELF ARM"
+# define ABI_ID "ELF ARM"
#elif defined(__linux__) && defined(__ELF__) && defined(__amd64__) && \
defined(__ILP32__)
-#define ABI_ID "ELF X32"
+# define ABI_ID "ELF X32"
#elif defined(__ELF__)
-#define ABI_ID "ELF"
+# define ABI_ID "ELF"
#endif
#if defined(ABI_ID)
"set(MSVC_C_ARCHITECTURE_ID ${MSVC_C_ARCHITECTURE_ID})")
endif()
-if(CMAKE_C_XCODE_CURRENT_ARCH)
- set(SET_CMAKE_XCODE_CURRENT_ARCH
- "set(CMAKE_XCODE_CURRENT_ARCH ${CMAKE_C_XCODE_CURRENT_ARCH})")
+if(CMAKE_C_XCODE_ARCHS)
+ set(SET_CMAKE_XCODE_ARCHS
+ "set(CMAKE_XCODE_ARCHS \"${CMAKE_C_XCODE_ARCHS}\")")
endif()
# configure variables set in this file for fast reload later on
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-if(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
+if(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
message(FATAL_ERROR
"C# is currently only supported for Microsoft Visual Studio 2010 and later.")
endif()
if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR
("${CMAKE_GENERATOR}" MATCHES "Ninja") OR
- ("${CMAKE_GENERATOR}" MATCHES "Visual Studio (1|[89][0-9])") ) )
+ ("${CMAKE_GENERATOR}" MATCHES "Visual Studio (1|[9][0-9])") ) )
message(FATAL_ERROR "CUDA language not currently supported by \"${CMAKE_GENERATOR}\" generator")
endif()
endif()
#Allow the user to specify a host compiler
-set(CMAKE_CUDA_HOST_COMPILER "" CACHE FILEPATH "Host compiler to be used by nvcc")
if(NOT $ENV{CUDAHOSTCXX} STREQUAL "")
get_filename_component(CMAKE_CUDA_HOST_COMPILER $ENV{CUDAHOSTCXX} PROGRAM)
if(NOT EXISTS ${CMAKE_CUDA_HOST_COMPILER})
"set(MSVC_CXX_ARCHITECTURE_ID ${MSVC_CXX_ARCHITECTURE_ID})")
endif()
-if(CMAKE_CXX_XCODE_CURRENT_ARCH)
- set(SET_CMAKE_XCODE_CURRENT_ARCH
- "set(CMAKE_XCODE_CURRENT_ARCH ${CMAKE_CXX_XCODE_CURRENT_ARCH})")
+if(CMAKE_CXX_XCODE_ARCHS)
+ set(SET_CMAKE_XCODE_ARCHS
+ "set(CMAKE_XCODE_ARCHS \"${CMAKE_CXX_XCODE_ARCHS}\")")
endif()
# configure all variables set in this file
set(CMAKE_CXX11_COMPILE_FEATURES)
set(CMAKE_CXX14_COMPILE_FEATURES)
set(CMAKE_CXX17_COMPILE_FEATURES)
+ set(CMAKE_CXX20_COMPILE_FEATURES)
include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
return()
endif()
+ if (CMAKE_CXX17_COMPILE_FEATURES AND CMAKE_CXX20_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX17_COMPILE_FEATURES})
+ endif()
if (CMAKE_CXX14_COMPILE_FEATURES AND CMAKE_CXX17_COMPILE_FEATURES)
list(REMOVE_ITEM CMAKE_CXX17_COMPILE_FEATURES ${CMAKE_CXX14_COMPILE_FEATURES})
endif()
${CMAKE_CXX11_COMPILE_FEATURES}
${CMAKE_CXX14_COMPILE_FEATURES}
${CMAKE_CXX17_COMPILE_FEATURES}
+ ${CMAKE_CXX20_COMPILE_FEATURES}
)
endif()
set(CMAKE_CXX11_COMPILE_FEATURES ${CMAKE_CXX11_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CXX14_COMPILE_FEATURES ${CMAKE_CXX14_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CXX17_COMPILE_FEATURES ${CMAKE_CXX17_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES} PARENT_SCOPE)
message(STATUS "Detecting ${lang} compile features - done")
endif()
endforeach()
endif()
+ # CUDA < 7.5 is missing version macros
+ if(lang STREQUAL "CUDA"
+ AND CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA"
+ AND NOT CMAKE_${lang}_COMPILER_VERSION)
+ execute_process(
+ COMMAND "${CMAKE_${lang}_COMPILER}"
+ --version
+ OUTPUT_VARIABLE output ERROR_VARIABLE output
+ RESULT_VARIABLE result
+ TIMEOUT 10
+ )
+ if(output MATCHES [=[ V([0-9]+)\.([0-9]+)\.([0-9]+)]=])
+ set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
+ endif()
+ endif()
+
if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU")
execute_process(
COMMAND "${CMAKE_${lang}_COMPILER}"
set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "${CMAKE_${lang}_COMPILER_ARCHITECTURE_ID}" PARENT_SCOPE)
set(MSVC_${lang}_ARCHITECTURE_ID "${MSVC_${lang}_ARCHITECTURE_ID}"
PARENT_SCOPE)
- set(CMAKE_${lang}_XCODE_CURRENT_ARCH "${CMAKE_${lang}_XCODE_CURRENT_ARCH}" PARENT_SCOPE)
+ set(CMAKE_${lang}_XCODE_ARCHS "${CMAKE_${lang}_XCODE_ARCHS}" PARENT_SCOPE)
set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX}" PARENT_SCOPE)
set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}" PARENT_SCOPE)
set(CMAKE_${lang}_COMPILER_VERSION_INTERNAL "${CMAKE_${lang}_COMPILER_VERSION_INTERNAL}" PARENT_SCOPE)
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "Intel")
set(id_cl icl.exe)
endif()
+ if(CMAKE_VS_PLATFORM_TOOLSET_VERSION)
+ set(id_toolset_version_props "<Import Project=\"${CMAKE_GENERATOR_INSTANCE}\\VC\\Auxiliary\\Build\\${CMAKE_VS_PLATFORM_TOOLSET_VERSION}\\Microsoft.VCToolsVersion.${CMAKE_VS_PLATFORM_TOOLSET_VERSION}.props\" />")
+ endif()
endif()
else()
set(id_toolset "")
+ set(id_toolset_version_props "")
endif()
if(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE)
set(id_PreferredToolArchitecture "<PreferredToolArchitecture>${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}</PreferredToolArchitecture>")
endif()
endif()
endif()
- if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "CURRENT_ARCH=([^%\r\n]+)[\r\n]")
- set(CMAKE_${lang}_XCODE_CURRENT_ARCH "${CMAKE_MATCH_1}" PARENT_SCOPE)
+ if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "ARCHS=([^%\r\n]+)[\r\n]")
+ set(CMAKE_${lang}_XCODE_ARCHS "${CMAKE_MATCH_1}")
+ separate_arguments(CMAKE_${lang}_XCODE_ARCHS)
+ set(CMAKE_${lang}_XCODE_ARCHS "${CMAKE_${lang}_XCODE_ARCHS}" PARENT_SCOPE)
endif()
else()
execute_process(
# The order is 95 or newer compilers first, then 90,
# then 77 or older compilers, gnu is always last in the group,
# so if you paid for a compiler it is picked by default.
- set(CMAKE_Fortran_COMPILER_LIST
- ftn
- ifort ifc af95 af90 efc f95 pathf2003 pathf95 pgf95 pgfortran lf95 xlf95
- fort flang gfortran gfortran-4 g95 f90 pathf90 pgf90 xlf90 epcf90 fort77
- frt pgf77 xlf fl32 af77 g77 f77 nag
- )
+ if(CMAKE_HOST_WIN32)
+ set(CMAKE_Fortran_COMPILER_LIST
+ ifort pgf95 pgfortran lf95 fort
+ flang gfortran gfortran-4 g95 f90 pgf90
+ pgf77 g77 f77 nag
+ )
+ else()
+ set(CMAKE_Fortran_COMPILER_LIST
+ ftn
+ ifort ifc efc pgf95 pgfortran lf95 xlf95 fort
+ flang gfortran gfortran-4 g95 f90 pgf90
+ frt pgf77 xlf g77 f77 nag
+ )
+ endif()
# Vendor-specific compiler names.
set(_Fortran_COMPILER_NAMES_GNU gfortran gfortran-4 g95 g77)
# on UNIX, cygwin and mingw
+if(CMAKE_LINKER)
+ # we only get here if CMAKE_LINKER was specified using -D or a pre-made CMakeCache.txt
+ # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
+ # find the linker in the PATH if necessary
+ get_filename_component(_CMAKE_USER_LINKER_PATH "${CMAKE_LINKER}" PATH)
+ if(NOT _CMAKE_USER_LINKER_PATH)
+ find_program(CMAKE_LINKER_WITH_PATH NAMES ${CMAKE_LINKER} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+ if(CMAKE_LINKER_WITH_PATH)
+ set(CMAKE_LINKER ${CMAKE_LINKER_WITH_PATH})
+ get_property(_CMAKE_LINKER_CACHED CACHE CMAKE_LINKER PROPERTY TYPE)
+ if(_CMAKE_LINKER_CACHED)
+ set(CMAKE_LINKER "${CMAKE_LINKER}" CACHE STRING "Default Linker" FORCE)
+ endif()
+ unset(_CMAKE_LINKER_CACHED)
+ endif()
+ unset(CMAKE_LINKER_WITH_PATH CACHE)
+ endif()
+endif()
+
# if it's the MS C/CXX compiler, search for link
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC"
OR "x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xMSVC"
set(CMAKE_${LANGUAGE}_OSX_DEPLOYMENT_TARGET_FLAG "")
endif()
+include(CMakeSystemSpecificInitialize)
+
# Also load the system specific file, which sets up e.g. the search paths.
# This makes the FIND_XXX() calls work much better
include(CMakeSystemSpecificInformation)
set(MINGW 1)
endif()
set(CMAKE_Fortran_COMPILER_ID_RUN 1)
-set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;f77;F77;f90;F90;for;For;FOR;f95;F95)
+set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95)
set(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_Fortran_LINKER_PREFERENCE 20)
if(UNIX)
set(CMAKE_BASE_NAME g77)
endif()
if(CMAKE_Fortran_COMPILER_ID)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_Fortran_COMPILER_ID}-Fortran OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_Fortran_COMPILER_ID}-Fortran OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
endif()
if (NOT _INCLUDED_FILE)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL
RESULT_VARIABLE _INCLUDED_FILE)
endif ()
macro(__cmake_include_compiler_wrapper lang)
set(_INCLUDED_WRAPPER_FILE 0)
if (CMAKE_${lang}_COMPILER_ID)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_${lang}_COMPILER_WRAPPER}-${CMAKE_${lang}_COMPILER_ID}-${lang} OPTIONAL RESULT_VARIABLE _INCLUDED_WRAPPER_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_${lang}_COMPILER_WRAPPER}-${CMAKE_${lang}_COMPILER_ID}-${lang} OPTIONAL RESULT_VARIABLE _INCLUDED_WRAPPER_FILE)
endif()
if (NOT _INCLUDED_WRAPPER_FILE)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_${lang}_COMPILER_WRAPPER}-${lang} OPTIONAL RESULT_VARIABLE _INCLUDED_WRAPPER_FILE)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_${lang}_COMPILER_WRAPPER}-${lang} OPTIONAL RESULT_VARIABLE _INCLUDED_WRAPPER_FILE)
endif ()
# No platform - wrapper - lang information so maybe there's just wrapper - lang information
# into the ``FooConfig.cmake`` file.
#
# ``check_required_components(<package_name>)`` should be called at the end of
-# the ``FooConfig.cmake`` file if the package supports components. This macro
-# checks whether all requested, non-optional components have been found, and if
-# this is not the case, sets the ``Foo_FOUND`` variable to ``FALSE``, so that
-# the package is considered to be not found. It does that by testing the
-# ``Foo_<Component>_FOUND`` variables for all requested required components.
-# When using the ``NO_CHECK_REQUIRED_COMPONENTS_MACRO`` option, this macro is
-# not generated into the ``FooConfig.cmake`` file.
+# the ``FooConfig.cmake`` file. This macro checks whether all requested,
+# non-optional components have been found, and if this is not the case, sets
+# the ``Foo_FOUND`` variable to ``FALSE``, so that the package is considered to
+# be not found. It does that by testing the ``Foo_<Component>_FOUND``
+# variables for all requested required components. This macro should be
+# called even if the package doesn't provide any components to make sure
+# users are not specifying components erroneously. When using the
+# ``NO_CHECK_REQUIRED_COMPONENTS_MACRO`` option, this macro is not generated
+# into the ``FooConfig.cmake`` file.
#
# For an example see below the documentation for
# :command:`write_basic_package_version_file()`.
if(CMAKE_Swift_COMPILER_ID)
# load a hardware specific file, mostly useful for embedded compilers
if(CMAKE_SYSTEM_PROCESSOR)
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_Swift_COMPILER_ID}-Swift-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_Swift_COMPILER_ID}-Swift-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
endif()
- include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_Swift_COMPILER_ID}-Swift OPTIONAL)
+ include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_Swift_COMPILER_ID}-Swift OPTIONAL)
endif()
# for most systems a module is the same as a shared library
# This file is included by cmGlobalGenerator::EnableLanguage.
# It is included before the compiler has been determined.
+# The CMAKE_EFFECTIVE_SYSTEM_NAME is used to load compiler and compiler
+# wrapper configuration files. By default it equals to CMAKE_SYSTEM_NAME
+# but could be overridden in the ${CMAKE_SYSTEM_NAME}-Initialize files.
+#
+# It is useful to share the same aforementioned configuration files and
+# avoids duplicating them in case of tightly related platforms.
+#
+# An example are the platforms supported by Xcode (macOS, iOS, tvOS,
+# and watchOS). For all of those the CMAKE_EFFECTIVE_SYSTEM_NAME is
+# set to Apple which results in using
+# Platform/Apple-AppleClang-CXX.cmake for the Apple C++ compiler.
+set(CMAKE_EFFECTIVE_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}")
+
include(Platform/${CMAKE_SYSTEM_NAME}-Initialize OPTIONAL)
set(CMAKE_SYSTEM_SPECIFIC_INITIALIZE_LOADED 1)
set(test_compile_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCSharpCompiler.cs")
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected C# compiler can actually compile
+# determine that the selected C# compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
unset(CMAKE_CUDA_COMPILER_WORKS CACHE)
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected cuda compiler can actually compile
+# determine that the selected cuda compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
unset(CMAKE_CXX_COMPILER_WORKS CACHE)
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected C++ compiler can actually compile
+# determine that the selected C++ compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
unset(CMAKE_Fortran_COMPILER_WORKS CACHE)
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected Fortran compiler can actually compile
+# determine that the selected Fortran compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected Fortran compiler can actually compile
+# determine that the selected Fortran compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected RC compiler can actually compile
+# determine that the selected RC compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
unset(CMAKE_Swift_COMPILER_WORKS CACHE)
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected C++ compiler can actually compile
+# determine that the selected C++ compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
+ <metadata>
+ <!-- Required elements-->
+ <id>@CPACK_NUGET_PACKAGE_NAME@</id>
+ <version>@CPACK_NUGET_PACKAGE_VERSION@</version>
+ <description>@CPACK_NUGET_PACKAGE_DESCRIPTION@</description>
+ <authors>@CPACK_NUGET_PACKAGE_AUTHORS@</authors>
+
+ <!-- Optional elements -->
+ @_CPACK_NUGET_TITLE_TAG@
+ @_CPACK_NUGET_OWNERS_TAG@
+ @_CPACK_NUGET_PROJECTURL_TAG@
+ @_CPACK_NUGET_LICENSEURL_TAG@
+ @_CPACK_NUGET_ICONURL_TAG@
+ @_CPACK_NUGET_REQUIRELICENSEACCEPTANCE_TAG@
+ @_CPACK_NUGET_SUMMARY_TAG@
+ @_CPACK_NUGET_RELEASENOTES_TAG@
+ @_CPACK_NUGET_COPYRIGHT_TAG@
+ @_CPACK_NUGET_TAGS_TAG@
+ @_CPACK_NUGET_DEPENDENCIES_TAG@
+ </metadata>
+ @_CPACK_NUGET_FILES_TAG@
+</package>
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#.rst:
-# CPack
-# -----
-#
-# Build binary and source package installers.
-#
-# Variables common to all CPack generators
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# The
-# CPack module generates binary and source installers in a variety of
-# formats using the cpack program. Inclusion of the CPack module adds
-# two new targets to the resulting makefiles, package and
-# package_source, which build the binary and source installers,
-# respectively. The generated binary installers contain everything
-# installed via CMake's INSTALL command (and the deprecated
-# INSTALL_FILES, INSTALL_PROGRAMS, and INSTALL_TARGETS commands).
-#
-# For certain kinds of binary installers (including the graphical
-# installers on Mac OS X and Windows), CPack generates installers that
-# allow users to select individual application components to install.
-# See CPackComponent module for that.
-#
-# The CPACK_GENERATOR variable has different meanings in different
-# contexts. In your CMakeLists.txt file, CPACK_GENERATOR is a *list of
-# generators*: when run with no other arguments, CPack will iterate over
-# that list and produce one package for each generator. In a
-# CPACK_PROJECT_CONFIG_FILE, though, CPACK_GENERATOR is a *string naming
-# a single generator*. If you need per-cpack- generator logic to
-# control *other* cpack settings, then you need a
-# CPACK_PROJECT_CONFIG_FILE.
-#
-# The CMake source tree itself contains a CPACK_PROJECT_CONFIG_FILE.
-# See the top level file CMakeCPackOptions.cmake.in for an example.
-#
-# If set, the CPACK_PROJECT_CONFIG_FILE is included automatically on a
-# per-generator basis. It only need contain overrides.
-#
-# Here's how it works:
-#
-# * cpack runs
-# * it includes CPackConfig.cmake
-# * it iterates over the generators listed in that file's
-# CPACK_GENERATOR list variable (unless told to use just a
-# specific one via -G on the command line...)
-# * foreach generator, it then
-#
-# - sets CPACK_GENERATOR to the one currently being iterated
-# - includes the CPACK_PROJECT_CONFIG_FILE
-# - produces the package for that generator
-#
-# This is the key: For each generator listed in CPACK_GENERATOR in
-# CPackConfig.cmake, cpack will *reset* CPACK_GENERATOR internally to
-# *the one currently being used* and then include the
-# CPACK_PROJECT_CONFIG_FILE.
-#
-# Before including this CPack module in your CMakeLists.txt file, there
-# are a variety of variables that can be set to customize the resulting
-# installers. The most commonly-used variables are:
-#
-# .. variable:: CPACK_PACKAGE_NAME
-#
-# The name of the package (or application). If not specified, defaults to
-# the project name.
-#
-# .. variable:: CPACK_PACKAGE_VENDOR
-#
-# The name of the package vendor. (e.g., "Kitware"). Default is "Humanity".
-#
-# .. variable:: CPACK_PACKAGE_DIRECTORY
-#
-# The directory in which CPack is doing its packaging. If it is not set
-# then this will default (internally) to the build dir. This variable may
-# be defined in CPack config file or from the cpack command line option
-# "-B". If set the command line option override the value found in the
-# config file.
-#
-# .. variable:: CPACK_PACKAGE_VERSION_MAJOR
-#
-# Package major Version. Default value is 0.
-#
-# .. variable:: CPACK_PACKAGE_VERSION_MINOR
-#
-# Package minor Version. Default value is 1.
-#
-# .. variable:: CPACK_PACKAGE_VERSION_PATCH
-#
-# Package patch Version. Default value is 1.
-#
-# .. variable:: CPACK_PACKAGE_DESCRIPTION_FILE
-#
-# A text file used to describe the project. Used, for example, the
-# introduction screen of a CPack-generated Windows installer to describe
-# the project.
-#
-# .. variable:: CPACK_PACKAGE_DESCRIPTION_SUMMARY
-#
-# Short description of the project (only a few words). Default value is::
-#
-# ${PROJECT_DESCRIPTION}
-#
-# if DESCRIPTION has given to the project() call or
-# CMake generated string with PROJECT_NAME otherwise.
-#
-# .. variable:: CPACK_PACKAGE_FILE_NAME
-#
-# The name of the package file to generate, not including the
-# extension. For example, cmake-2.6.1-Linux-i686. The default value is::
-#
-# ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}.
-#
-# .. variable:: CPACK_PACKAGE_INSTALL_DIRECTORY
-#
-# Installation directory on the target system. This may be used by some
-# CPack generators like NSIS to create an installation directory e.g.,
-# "CMake 2.5" below the installation prefix. All installed element will be
-# put inside this directory.
-#
-# .. variable:: CPACK_PACKAGE_ICON
-#
-# A branding image that will be displayed inside the installer (used by GUI
-# installers).
-#
-# .. variable:: CPACK_PACKAGE_CHECKSUM
-#
-# An algorithm that will be used to generate additional file with checksum
-# of the package. Output file name will be::
-#
-# ${CPACK_PACKAGE_FILE_NAME}.${CPACK_PACKAGE_CHECKSUM}
-#
-# Supported algorithms are those listed by the
-# :ref:`string(\<HASH\>) <Supported Hash Algorithms>`
-# command.
-#
-# .. variable:: CPACK_PROJECT_CONFIG_FILE
-#
-# CPack-time project CPack configuration file. This file included at cpack
-# time, once per generator after CPack has set CPACK_GENERATOR to the
-# actual generator being used. It allows per-generator setting of CPACK_*
-# variables at cpack time.
-#
-# .. variable:: CPACK_RESOURCE_FILE_LICENSE
-#
-# License to be embedded in the installer. It will typically be displayed
-# to the user by the produced installer (often with an explicit "Accept"
-# button, for graphical installers) prior to installation. This license
-# file is NOT added to installed file but is used by some CPack generators
-# like NSIS. If you want to install a license file (may be the same as this
-# one) along with your project you must add an appropriate CMake INSTALL
-# command in your CMakeLists.txt.
-#
-# .. variable:: CPACK_RESOURCE_FILE_README
-#
-# ReadMe file to be embedded in the installer. It typically describes in
-# some detail the purpose of the project during the installation. Not all
-# CPack generators uses this file.
-#
-# .. variable:: CPACK_RESOURCE_FILE_WELCOME
-#
-# Welcome file to be embedded in the installer. It welcomes users to this
-# installer. Typically used in the graphical installers on Windows and Mac
-# OS X.
-#
-# .. variable:: CPACK_MONOLITHIC_INSTALL
-#
-# Disables the component-based installation mechanism. When set the
-# component specification is ignored and all installed items are put in a
-# single "MONOLITHIC" package. Some CPack generators do monolithic
-# packaging by default and may be asked to do component packaging by
-# setting CPACK_<GENNAME>_COMPONENT_INSTALL to 1/TRUE.
-#
-# .. variable:: CPACK_GENERATOR
-#
-# List of CPack generators to use. If not specified, CPack will create a
-# set of options CPACK_BINARY_<GENNAME> (e.g., CPACK_BINARY_NSIS) allowing
-# the user to enable/disable individual generators. This variable may be
-# used on the command line as well as in::
-#
-# cpack -D CPACK_GENERATOR="ZIP;TGZ" /path/to/build/tree
-#
-# .. variable:: CPACK_OUTPUT_CONFIG_FILE
-#
-# The name of the CPack binary configuration file. This file is the CPack
-# configuration generated by the CPack module for binary
-# installers. Defaults to CPackConfig.cmake.
-#
-# .. variable:: CPACK_PACKAGE_EXECUTABLES
-#
-# Lists each of the executables and associated text label to be used to
-# create Start Menu shortcuts. For example, setting this to the list
-# ccmake;CMake will create a shortcut named "CMake" that will execute the
-# installed executable ccmake. Not all CPack generators use it (at least
-# NSIS, WIX and OSXX11 do).
-#
-# .. variable:: CPACK_STRIP_FILES
-#
-# List of files to be stripped. Starting with CMake 2.6.0 CPACK_STRIP_FILES
-# will be a boolean variable which enables stripping of all files (a list
-# of files evaluates to TRUE in CMake, so this change is compatible).
-#
-# .. variable:: CPACK_VERBATIM_VARIABLES
-#
-# If set to TRUE, values of variables prefixed with CPACK_ will be escaped
-# before being written to the configuration files, so that the cpack program
-# receives them exactly as they were specified. If not, characters like quotes
-# and backslashes can cause parsing errors or alter the value received by the
-# cpack program. Defaults to FALSE for backwards compatibility.
-#
-# * Mandatory : NO
-# * Default : FALSE
-#
-# The following CPack variables are specific to source packages, and
-# will not affect binary packages:
-#
-# .. variable:: CPACK_SOURCE_PACKAGE_FILE_NAME
-#
-# The name of the source package. For example cmake-2.6.1.
-#
-# .. variable:: CPACK_SOURCE_STRIP_FILES
-#
-# List of files in the source tree that will be stripped. Starting with
-# CMake 2.6.0 CPACK_SOURCE_STRIP_FILES will be a boolean variable which
-# enables stripping of all files (a list of files evaluates to TRUE in
-# CMake, so this change is compatible).
-#
-# .. variable:: CPACK_SOURCE_GENERATOR
-#
-# List of generators used for the source packages. As with CPACK_GENERATOR,
-# if this is not specified then CPack will create a set of options (e.g.,
-# CPACK_SOURCE_ZIP) allowing users to select which packages will be
-# generated.
-#
-# .. variable:: CPACK_SOURCE_OUTPUT_CONFIG_FILE
-#
-# The name of the CPack source configuration file. This file is the CPack
-# configuration generated by the CPack module for source
-# installers. Defaults to CPackSourceConfig.cmake.
-#
-# .. variable:: CPACK_SOURCE_IGNORE_FILES
-#
-# Pattern of files in the source tree that won't be packaged when building
-# a source package. This is a list of regular expression patterns (that
-# must be properly escaped), e.g.,
-# /CVS/;/\\.svn/;\\.swp$;\\.#;/#;.*~;cscope.*
-#
-# The following variables are for advanced uses of CPack:
-#
-# .. variable:: CPACK_CMAKE_GENERATOR
-#
-# What CMake generator should be used if the project is CMake
-# project. Defaults to the value of CMAKE_GENERATOR few users will want to
-# change this setting.
-#
-# .. variable:: CPACK_INSTALL_CMAKE_PROJECTS
-#
-# List of four values that specify what project to install. The four values
-# are: Build directory, Project Name, Project Component, Directory. If
-# omitted, CPack will build an installer that installs everything.
-#
-# .. variable:: CPACK_SYSTEM_NAME
-#
-# System name, defaults to the value of ${CMAKE_SYSTEM_NAME}, except on
-# Windows where it will be "win32" or "win64".
-#
-# .. variable:: CPACK_PACKAGE_VERSION
-#
-# Package full version, used internally. By default, this is built from
-# CPACK_PACKAGE_VERSION_MAJOR, CPACK_PACKAGE_VERSION_MINOR, and
-# CPACK_PACKAGE_VERSION_PATCH.
-#
-# .. variable:: CPACK_TOPLEVEL_TAG
-#
-# Directory for the installed files.
-#
-# .. variable:: CPACK_INSTALL_COMMANDS
-#
-# Extra commands to install components.
-#
-# .. variable:: CPACK_INSTALLED_DIRECTORIES
-#
-# Extra directories to install.
-#
-# .. variable:: CPACK_PACKAGE_INSTALL_REGISTRY_KEY
-#
-# Registry key used when installing this project. This is only used by
-# installer for Windows. The default value is based on the installation
-# directory.
-#
-# .. variable:: CPACK_CREATE_DESKTOP_LINKS
-#
-# List of desktop links to create.
-# Each desktop link requires a corresponding start menu shortcut
-# as created by :variable:`CPACK_PACKAGE_EXECUTABLES`.
+#[=======================================================================[.rst:
+CPack
+-----
+
+Build binary and source package installers.
+
+Variables common to all CPack generators
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CPack module generates binary and source installers in a variety of
+formats using the cpack program. Inclusion of the CPack module adds
+two new build targets, ``package`` and ``package_source``, which build
+the binary and source installers respectively. The generated binary
+installers contain everything installed via CMake's :command:`install`
+command (and the deprecated :command:`install_files`,
+:command:`install_programs` and :command:`install_targets` commands).
+
+For certain kinds of binary installers (including the graphical
+installers on Mac OS X and Windows), CPack generates installers that
+allow users to select individual application components to install.
+See :module:`CPackComponent` module for further details.
+
+The :variable:`CPACK_GENERATOR` variable has different meanings in different
+contexts. In a ``CMakeLists.txt`` file, :variable:`CPACK_GENERATOR` is a
+*list of generators*: and when :manual:`cpack <cpack(1)>` is run with no other
+arguments, it will iterate over that list and produce one package for each
+generator. In a :variable:`CPACK_PROJECT_CONFIG_FILE`,
+:variable:`CPACK_GENERATOR` is a *string naming a single generator*. If you
+need per-cpack-generator logic to control *other* cpack settings, then you
+need a :variable:`CPACK_PROJECT_CONFIG_FILE`.
+
+The CMake source tree itself contains a :variable:`CPACK_PROJECT_CONFIG_FILE`.
+See the top level file ``CMakeCPackOptions.cmake.in`` for an example.
+
+If set, the :variable:`CPACK_PROJECT_CONFIG_FILE` is included automatically
+on a per-generator basis. It only need contain overrides.
+
+Here's how it works:
+
+* :manual:`cpack <cpack(1)>` runs
+* it includes ``CPackConfig.cmake``
+* it iterates over the generators given by the ``-G`` command line option,
+ or if no such option was specified, over the list of generators given by
+ the :variable:`CPACK_GENERATOR` variable set in the ``CPackConfig.cmake``
+ input file.
+* foreach generator, it then
+
+ - sets :variable:`CPACK_GENERATOR` to the one currently being iterated
+ - includes the :variable:`CPACK_PROJECT_CONFIG_FILE`
+ - produces the package for that generator
+
+This is the key: For each generator listed in :variable:`CPACK_GENERATOR` in
+``CPackConfig.cmake``, cpack will *reset* :variable:`CPACK_GENERATOR`
+internally to *the one currently being used* and then include the
+:variable:`CPACK_PROJECT_CONFIG_FILE`.
+
+Before including this CPack module in your ``CMakeLists.txt`` file, there
+are a variety of variables that can be set to customize the resulting
+installers. The most commonly-used variables are:
+
+.. variable:: CPACK_PACKAGE_NAME
+
+ The name of the package (or application). If not specified, it defaults to
+ the project name.
+
+.. variable:: CPACK_PACKAGE_VENDOR
+
+ The name of the package vendor. (e.g., "Kitware"). The default is "Humanity".
+
+.. variable:: CPACK_PACKAGE_DIRECTORY
+
+ The directory in which CPack is doing its packaging. If it is not set
+ then this will default (internally) to the build dir. This variable may
+ be defined in a CPack config file or from the :manual:`cpack <cpack(1)>`
+ command line option ``-B``. If set, the command line option overrides the
+ value found in the config file.
+
+.. variable:: CPACK_PACKAGE_VERSION_MAJOR
+
+ Package major version. This variable will always be set, but its default
+ value depends on whether or not version details were given to the
+ :command:`project` command in the top level CMakeLists.txt file. If version
+ details were given, the default value will be
+ :variable:`CMAKE_PROJECT_VERSION_MAJOR`. If no version details were given,
+ a default version of 0.1.1 will be assumed, leading to
+ ``CPACK_PACKAGE_VERSION_MAJOR`` having a default value of 0.
+
+.. variable:: CPACK_PACKAGE_VERSION_MINOR
+
+ Package minor version. The default value is determined based on whether or
+ not version details were given to the :command:`project` command in the top
+ level CMakeLists.txt file. If version details were given, the default
+ value will be :variable:`CMAKE_PROJECT_VERSION_MINOR`, but if no minor
+ version component was specified then ``CPACK_PACKAGE_VERSION_MINOR`` will be
+ left unset. If no project version was given at all, a default version of
+ 0.1.1 will be assumed, leading to ``CPACK_PACKAGE_VERSION_MINOR`` having a
+ default value of 1.
+
+.. variable:: CPACK_PACKAGE_VERSION_PATCH
+
+ Package patch version. The default value is determined based on whether or
+ not version details were given to the :command:`project` command in the top
+ level CMakeLists.txt file. If version details were given, the default
+ value will be :variable:`CMAKE_PROJECT_VERSION_PATCH`, but if no patch
+ version component was specified then ``CPACK_PACKAGE_VERSION_PATCH`` will be
+ left unset. If no project version was given at all, a default version of
+ 0.1.1 will be assumed, leading to ``CPACK_PACKAGE_VERSION_PATCH`` having a
+ default value of 1.
+
+.. variable:: CPACK_PACKAGE_DESCRIPTION
+
+ A description of the project, used in places such as the introduction
+ screen of CPack-generated Windows installers. If not set, the value of
+ this variable is populated from the file named by
+ :variable:`CPACK_PACKAGE_DESCRIPTION_FILE`.
+
+.. variable:: CPACK_PACKAGE_DESCRIPTION_FILE
+
+ A text file used to describe the project when
+ :variable:`CPACK_PACKAGE_DESCRIPTION` is not explicitly set. The default
+ value for ``CPACK_PACKAGE_DESCRIPTION_FILE`` points to a built-in template
+ file ``Templates/CPack.GenericDescription.txt``.
+
+.. variable:: CPACK_PACKAGE_DESCRIPTION_SUMMARY
+
+ Short description of the project (only a few words). If the
+ :variable:`CMAKE_PROJECT_DESCRIPTION` variable is set, it is used as the
+ default value, otherwise the default will be a string generated by CMake
+ based on :variable:`CMAKE_PROJECT_NAME`.
+
+.. variable:: CPACK_PACKAGE_HOMEPAGE_URL
+
+ Project homepage URL. The default value is taken from the
+ :variable:`CMAKE_PROJECT_HOMEPAGE_URL` variable, which is set by the top
+ level :command:`project` command, or else the default will be empty if no
+ URL was provided to :command:`project`.
+
+.. variable:: CPACK_PACKAGE_FILE_NAME
+
+ The name of the package file to generate, not including the
+ extension. For example, ``cmake-2.6.1-Linux-i686``. The default value
+ is::
+
+ ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}
+
+.. variable:: CPACK_PACKAGE_INSTALL_DIRECTORY
+
+ Installation directory on the target system. This may be used by some
+ CPack generators like NSIS to create an installation directory e.g.,
+ "CMake 2.5" below the installation prefix. All installed elements will be
+ put inside this directory.
+
+.. variable:: CPACK_PACKAGE_ICON
+
+ A branding image that will be displayed inside the installer (used by GUI
+ installers).
+
+.. variable:: CPACK_PACKAGE_CHECKSUM
+
+ An algorithm that will be used to generate an additional file with the
+ checksum of the package. The output file name will be::
+
+ ${CPACK_PACKAGE_FILE_NAME}.${CPACK_PACKAGE_CHECKSUM}
+
+ Supported algorithms are those listed by the
+ :ref:`string(\<HASH\>) <Supported Hash Algorithms>` command.
+
+.. variable:: CPACK_PROJECT_CONFIG_FILE
+
+ CPack-time project CPack configuration file. This file is included at cpack
+ time, once per generator after CPack has set :variable:`CPACK_GENERATOR`
+ to the actual generator being used. It allows per-generator setting of
+ ``CPACK_*`` variables at cpack time.
+
+.. variable:: CPACK_RESOURCE_FILE_LICENSE
+
+ License to be embedded in the installer. It will typically be displayed
+ to the user by the produced installer (often with an explicit "Accept"
+ button, for graphical installers) prior to installation. This license
+ file is NOT added to the installed files but is used by some CPack generators
+ like NSIS. If you want to install a license file (may be the same as this
+ one) along with your project, you must add an appropriate CMake
+ :command:`install` command in your ``CMakeLists.txt``.
+
+.. variable:: CPACK_RESOURCE_FILE_README
+
+ ReadMe file to be embedded in the installer. It typically describes in
+ some detail the purpose of the project during the installation. Not all
+ CPack generators use this file.
+
+.. variable:: CPACK_RESOURCE_FILE_WELCOME
+
+ Welcome file to be embedded in the installer. It welcomes users to this
+ installer. Typically used in the graphical installers on Windows and Mac
+ OS X.
+
+.. variable:: CPACK_MONOLITHIC_INSTALL
+
+ Disables the component-based installation mechanism. When set, the
+ component specification is ignored and all installed items are put in a
+ single "MONOLITHIC" package. Some CPack generators do monolithic
+ packaging by default and may be asked to do component packaging by
+ setting ``CPACK_<GENNAME>_COMPONENT_INSTALL`` to ``TRUE``.
+
+.. variable:: CPACK_GENERATOR
+
+ List of CPack generators to use. If not specified, CPack will create a
+ set of options following the naming pattern
+ :variable:`CPACK_BINARY_<GENNAME>` (e.g. ``CPACK_BINARY_NSIS``) allowing
+ the user to enable/disable individual generators. If the ``-G`` option is
+ given on the :manual:`cpack <cpack(1)>` command line, it will override this
+ variable and any ``CPACK_BINARY_<GENNAME>`` options.
+
+.. variable:: CPACK_OUTPUT_CONFIG_FILE
+
+ The name of the CPack binary configuration file. This file is the CPack
+ configuration generated by the CPack module for binary installers.
+ Defaults to ``CPackConfig.cmake``.
+
+.. variable:: CPACK_PACKAGE_EXECUTABLES
+
+ Lists each of the executables and associated text label to be used to
+ create Start Menu shortcuts. For example, setting this to the list
+ ``ccmake;CMake`` will create a shortcut named "CMake" that will execute the
+ installed executable ``ccmake``. Not all CPack generators use it (at least
+ NSIS, WIX and OSXX11 do).
+
+.. variable:: CPACK_STRIP_FILES
+
+ List of files to be stripped. Starting with CMake 2.6.0,
+ ``CPACK_STRIP_FILES`` will be a boolean variable which enables
+ stripping of all files (a list of files evaluates to ``TRUE`` in CMake,
+ so this change is compatible).
+
+.. variable:: CPACK_VERBATIM_VARIABLES
+
+ If set to ``TRUE``, values of variables prefixed with ``CPACK_`` will be
+ escaped before being written to the configuration files, so that the cpack
+ program receives them exactly as they were specified. If not, characters
+ like quotes and backslashes can cause parsing errors or alter the value
+ received by the cpack program. Defaults to ``FALSE`` for backwards
+ compatibility.
+
+The following CPack variables are specific to source packages, and
+will not affect binary packages:
+
+.. variable:: CPACK_SOURCE_PACKAGE_FILE_NAME
+
+ The name of the source package. For example ``cmake-2.6.1``.
+
+.. variable:: CPACK_SOURCE_STRIP_FILES
+
+ List of files in the source tree that will be stripped. Starting with
+ CMake 2.6.0, ``CPACK_SOURCE_STRIP_FILES`` will be a boolean
+ variable which enables stripping of all files (a list of files evaluates
+ to ``TRUE`` in CMake, so this change is compatible).
+
+.. variable:: CPACK_SOURCE_GENERATOR
+
+ List of generators used for the source packages. As with
+ :variable:`CPACK_GENERATOR`, if this is not specified then CPack will
+ create a set of options (e.g. ``CPACK_SOURCE_ZIP``) allowing
+ users to select which packages will be generated.
+
+.. variable:: CPACK_SOURCE_OUTPUT_CONFIG_FILE
+
+ The name of the CPack source configuration file. This file is the CPack
+ configuration generated by the CPack module for source installers.
+ Defaults to ``CPackSourceConfig.cmake``.
+
+.. variable:: CPACK_SOURCE_IGNORE_FILES
+
+ Pattern of files in the source tree that won't be packaged when building
+ a source package. This is a list of regular expression patterns (that
+ must be properly escaped), e.g.,
+ ``/CVS/;/\\.svn/;\\.swp$;\\.#;/#;.*~;cscope.*``
+
+The following variables are for advanced uses of CPack:
+
+.. variable:: CPACK_CMAKE_GENERATOR
+
+ What CMake generator should be used if the project is a CMake
+ project. Defaults to the value of :variable:`CMAKE_GENERATOR`. Few users
+ will want to change this setting.
+
+.. variable:: CPACK_INSTALL_CMAKE_PROJECTS
+
+ List of four values that specify what project to install. The four values
+ are: Build directory, Project Name, Project Component, Directory. If
+ omitted, CPack will build an installer that installs everything.
+
+.. variable:: CPACK_SYSTEM_NAME
+
+ System name, defaults to the value of :variable:`CMAKE_SYSTEM_NAME`,
+ except on Windows where it will be ``win32`` or ``win64``.
+
+.. variable:: CPACK_PACKAGE_VERSION
+
+ Package full version, used internally. By default, this is built from
+ :variable:`CPACK_PACKAGE_VERSION_MAJOR`,
+ :variable:`CPACK_PACKAGE_VERSION_MINOR`, and
+ :variable:`CPACK_PACKAGE_VERSION_PATCH`.
+
+.. variable:: CPACK_TOPLEVEL_TAG
+
+ Directory for the installed files.
+
+.. variable:: CPACK_INSTALL_COMMANDS
+
+ Extra commands to install components.
+
+.. variable:: CPACK_INSTALLED_DIRECTORIES
+
+ Extra directories to install.
+
+.. variable:: CPACK_PACKAGE_INSTALL_REGISTRY_KEY
+
+ Registry key used when installing this project. This is only used by
+ installers for Windows. The default value is based on the installation
+ directory.
+
+.. variable:: CPACK_CREATE_DESKTOP_LINKS
+
+ List of desktop links to create. Each desktop link requires a
+ corresponding start menu shortcut as created by
+ :variable:`CPACK_PACKAGE_EXECUTABLES`.
+
+.. variable:: CPACK_BINARY_<GENNAME>
+
+ CPack generated options for binary generators. The ``CPack.cmake`` module
+ generates (when :variable:`CPACK_GENERATOR` is not set) a set of CMake
+ options (see CMake :command:`option` command) which may then be used to
+ select the CPack generator(s) to be used when building the ``package``
+ target or when running :manual:`cpack <cpack(1)>` without the ``-G`` option.
+
+#]=======================================================================]
# Define this var in order to avoid (or warn) concerning multiple inclusion
if(CPack_CMake_INCLUDED)
# Set the package name
_cpack_set_default(CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}")
-_cpack_set_default(CPACK_PACKAGE_VERSION_MAJOR "0")
-_cpack_set_default(CPACK_PACKAGE_VERSION_MINOR "1")
-_cpack_set_default(CPACK_PACKAGE_VERSION_PATCH "1")
-_cpack_set_default(CPACK_PACKAGE_VERSION
- "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
+if(CMAKE_PROJECT_VERSION_MAJOR)
+ _cpack_set_default(CPACK_PACKAGE_VERSION_MAJOR "${CMAKE_PROJECT_VERSION_MAJOR}")
+ if(CMAKE_PROJECT_VERSION_MINOR)
+ _cpack_set_default(CPACK_PACKAGE_VERSION_MINOR "${CMAKE_PROJECT_VERSION_MINOR}")
+ if(CMAKE_PROJECT_VERSION_PATCH)
+ _cpack_set_default(CPACK_PACKAGE_VERSION_PATCH "${CMAKE_PROJECT_VERSION_PATCH}")
+ _cpack_set_default(CPACK_PACKAGE_VERSION
+ "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
+ else()
+ _cpack_set_default(CPACK_PACKAGE_VERSION
+ "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}")
+ endif()
+ else()
+ _cpack_set_default(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}")
+ endif()
+else()
+ _cpack_set_default(CPACK_PACKAGE_VERSION_MAJOR "0")
+ _cpack_set_default(CPACK_PACKAGE_VERSION_MINOR "1")
+ _cpack_set_default(CPACK_PACKAGE_VERSION_PATCH "1")
+ _cpack_set_default(CPACK_PACKAGE_VERSION
+ "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
+endif()
_cpack_set_default(CPACK_PACKAGE_VENDOR "Humanity")
if(CMAKE_PROJECT_DESCRIPTION)
_cpack_set_default(CPACK_PACKAGE_DESCRIPTION_SUMMARY
_cpack_set_default(CPACK_PACKAGE_DESCRIPTION_SUMMARY
"${CMAKE_PROJECT_NAME} built using CMake")
endif()
+if(CMAKE_PROJECT_HOMEPAGE_URL)
+ _cpack_set_default(CPACK_PACKAGE_HOMEPAGE_URL
+ "${CMAKE_PROJECT_HOMEPAGE_URL}")
+endif()
_cpack_set_default(CPACK_PACKAGE_DESCRIPTION_FILE
"${CMAKE_ROOT}/Templates/CPack.GenericDescription.txt")
endif()
endmacro()
-#.rst:
-# .. variable:: CPACK_BINARY_<GENNAME>
-#
-# CPack generated options for binary generators. The CPack.cmake module
-# generates (when CPACK_GENERATOR is not set) a set of CMake options (see
-# CMake option command) which may then be used to select the CPack
-# generator(s) to be used when launching the package target.
-#
-# Provide options to choose generators we might check here if the required
-# tools for the generates exist and set the defaults according to the results
+# Provide options to choose generators we might check here if the required
+# tools for the generators exist and set the defaults according to the
+# results.
if(NOT CPACK_GENERATOR)
if(UNIX)
if(CYGWIN)
option(CPACK_BINARY_TXZ "Enable to build TXZ packages" OFF)
endif()
else()
- option(CPACK_BINARY_7Z "Enable to build 7-Zip packages" OFF)
- option(CPACK_BINARY_NSIS "Enable to build NSIS packages" ON)
- option(CPACK_BINARY_WIX "Enable to build WiX packages" OFF)
- option(CPACK_BINARY_ZIP "Enable to build ZIP packages" OFF)
+ option(CPACK_BINARY_7Z "Enable to build 7-Zip packages" OFF)
+ option(CPACK_BINARY_NSIS "Enable to build NSIS packages" ON)
+ option(CPACK_BINARY_NUGET "Enable to build NuGet packages" OFF)
+ option(CPACK_BINARY_WIX "Enable to build WiX packages" OFF)
+ option(CPACK_BINARY_ZIP "Enable to build ZIP packages" OFF)
endif()
option(CPACK_BINARY_IFW "Enable to build IFW packages" OFF)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_FREEBSD FREEBSD)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_IFW IFW)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NSIS NSIS)
+ cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NUGET NuGet)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_OSXX11 OSXX11)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PACKAGEMAKER PackageMaker)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PRODUCTBUILD productbuild)
CPACK_BINARY_FREEBSD
CPACK_BINARY_IFW
CPACK_BINARY_NSIS
+ CPACK_BINARY_NUGET
CPACK_BINARY_OSXX11
CPACK_BINARY_PACKAGEMAKER
CPACK_BINARY_PRODUCTBUILD
# Here are some CPackDeb wiki resources that are here for historic reasons and
# are no longer maintained but may still prove useful:
#
-# - https://cmake.org/Wiki/CMake:CPackConfiguration
-# - https://cmake.org/Wiki/CMake:CPackPackageGenerators#DEB_.28UNIX_only.29
+# - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/Configuration
+# - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/PackageGenerators#deb-unix-only
#
# List of CPackDEB specific variables:
#
# upstream documentation or information may be found.
#
# * Mandatory : NO
-# * Default : -
+# * Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
#
# .. note::
#
# You may need set :variable:`CMAKE_INSTALL_RPATH` to an appropriate value
# if you use this feature, because if you don't :code:`dpkg-shlibdeps`
# may fail to find your own shared libs.
-# See https://cmake.org/Wiki/CMake_RPATH_handling.
+# See https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling
#
# .. variable:: CPACK_DEBIAN_PACKAGE_DEBUG
#
endif()
endif()
+ # Homepage: (optional)
+ if(NOT CPACK_DEBIAN_PACKAGE_HOMEPAGE AND CMAKE_PROJECT_HOMEPAGE_URL)
+ set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CMAKE_PROJECT_HOMEPAGE_URL}")
+ endif()
+
# Section: (recommended)
if(NOT CPACK_DEBIAN_PACKAGE_SECTION)
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
"CPACK_DEBIAN_FILE_NAME")
if(CPACK_DEBIAN_FILE_NAME)
if(CPACK_DEBIAN_FILE_NAME STREQUAL "DEB-DEFAULT")
- # Patch package file name to be in corrent debian format:
+ # Patch package file name to be in correct debian format:
# <foo>_<VersionNumber>-<DebianRevisionNumber>_<DebianArchitecture>.deb
set(CPACK_OUTPUT_FILE_NAME
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
* Mandatory: YES
* Default:
- - :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
+ - :variable:`CMAKE_PROJECT_HOMEPAGE_URL`, or if that is not set,
+ :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
for Debian packaging, so we may as well re-use it).
.. variable:: CPACK_FREEBSD_PACKAGE_LICENSE
# There's really only one homepage for a project, so
# re-use the Debian setting if it's there.
_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_WWW"
+ "CMAKE_PROJECT_HOMEPAGE_URL"
"CPACK_DEBIAN_PACKAGE_HOMEPAGE"
"_cpack_freebsd_fallback_www"
)
# .. variable:: CPACK_NSIS_MENU_LINKS
#
# Specify links in [application] menu. This should contain a list of pair
-# "link" "link name". The link may be an URL or a path relative to
+# "link" "link name". The link may be a URL or a path relative to
# installation prefix. Like::
#
# set(CPACK_NSIS_MENU_LINKS
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CPackNuGet
+----------
+
+When build a NuGet package there is no direct way to control an output
+filename due a lack of the corresponding CLI option of NuGet, so there
+is no ``CPACK_NUGET_PACKAGE_FILENAME`` variable. To form the output filename
+NuGet uses the package name and the version according to its built-in rules.
+
+Also, be aware that including a top level directory
+(``CPACK_INCLUDE_TOPLEVEL_DIRECTORY``) is ignored by this generator.
+
+
+Variables specific to CPack NuGet generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+CPackNuGet may be used to create NuGet packages using :module:`CPack`.
+CPackNuGet is a :module:`CPack` generator thus it uses the ``CPACK_XXX``
+variables used by :module:`CPack`.
+
+CPackNuGet has specific features which are controlled by the specifics
+:code:`CPACK_NUGET_XXX` variables. In the "one per group" mode
+(see :variable:`CPACK_COMPONENTS_GROUPING`), ``<compName>`` placeholder
+in the variables below would contain a group name (uppercased and turned into
+a "C" identifier).
+
+List of CPackNuGet specific variables:
+
+.. variable:: CPACK_NUGET_COMPONENT_INSTALL
+
+ Enable component packaging for CPackNuGet
+
+ * Mandatory : NO
+ * Default : OFF
+
+.. variable:: CPACK_NUGET_PACKAGE_NAME
+ CPACK_NUGET_<compName>_PACKAGE_NAME
+
+ The NUGET package name.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_NAME`
+
+.. variable:: CPACK_NUGET_PACKAGE_VERSION
+ CPACK_NUGET_<compName>_PACKAGE_VERSION
+
+ The NuGet package version.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_VERSION`
+
+.. variable:: CPACK_NUGET_PACKAGE_DESCRIPTION
+ CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION
+
+ A long description of the package for UI display.
+
+ * Mandatory : YES
+ * Default :
+ - :variable:`CPACK_COMPONENT_<compName>_DESCRIPTION`,
+ - ``CPACK_COMPONENT_GROUP_<groupName>_DESCRIPTION``,
+ - :variable:`CPACK_PACKAGE_DESCRIPTION`
+
+.. variable:: CPACK_NUGET_PACKAGE_AUTHORS
+ CPACK_NUGET_<compName>_PACKAGE_AUTHORS
+
+ A comma-separated list of packages authors, matching the profile names
+ on nuget.org_. These are displayed in the NuGet Gallery on
+ nuget.org_ and are used to cross-reference packages by the same
+ authors.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_VENDOR`
+
+.. variable:: CPACK_NUGET_PACKAGE_TITLE
+ CPACK_NUGET_<compName>_PACKAGE_TITLE
+
+ A human-friendly title of the package, typically used in UI displays
+ as on nuget.org_ and the Package Manager in Visual Studio. If not
+ specified, the package ID is used.
+
+ * Mandatory : NO
+ * Default :
+ - :variable:`CPACK_COMPONENT_<compName>_DISPLAY_NAME`,
+ - ``CPACK_COMPONENT_GROUP_<groupName>_DISPLAY_NAME``
+
+.. variable:: CPACK_NUGET_PACKAGE_OWNERS
+ CPACK_NUGET_<compName>_PACKAGE_OWNERS
+
+ A comma-separated list of the package creators using profile names
+ on nuget.org_. This is often the same list as in authors,
+ and is ignored when uploading the package to nuget.org_.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_HOMEPAGE_URL
+ CPACK_NUGET_<compName>_PACKAGE_HOMEPAGE_URL
+
+ A URL for the package's home page, often shown in UI displays as well
+ as nuget.org_.
+
+ * Mandatory : NO
+ * Default : :variable:`CPACK_PACKAGE_HOMEPAGE_URL`
+
+.. variable:: CPACK_NUGET_PACKAGE_LICENSEURL
+ CPACK_NUGET_<compName>_PACKAGE_LICENSEURL
+
+ A URL for the package's license, often shown in UI displays as well
+ as nuget.org_.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_ICONURL
+ CPACK_NUGET_<compName>_PACKAGE_ICONURL
+
+ A URL for a 64x64 image with transparency background to use as the
+ icon for the package in UI display.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DESCRIPTION_SUMMARY
+ CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION_SUMMARY
+
+ A short description of the package for UI display. If omitted, a
+ truncated version of description is used.
+
+ * Mandatory : NO
+ * Default : :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
+
+.. variable:: CPACK_NUGET_PACKAGE_RELEASE_NOTES
+ CPACK_NUGET_<compName>_PACKAGE_RELEASE_NOTES
+
+ A description of the changes made in this release of the package,
+ often used in UI like the Updates tab of the Visual Studio Package
+ Manager in place of the package description.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_COPYRIGHT
+ CPACK_NUGET_<compName>_PACKAGE_COPYRIGHT
+
+ Copyright details for the package.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_TAGS
+ CPACK_NUGET_<compName>_PACKAGE_TAGS
+
+ A space-delimited list of tags and keywords that describe the
+ package and aid discoverability of packages through search and
+ filtering.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DEPENDENCIES
+ CPACK_NUGET_<compName>_PACKAGE_DEPENDENCIES
+
+ A list of package dependencies.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DEPENDENCIES_<dependency>_VERSION
+ CPACK_NUGET_<compName>_PACKAGE_DEPENDENCIES_<dependency>_VERSION
+
+ A `version specification`_ for the particular dependency, where
+ ``<dependency>`` is an item of the dependency list (see above)
+ transformed with ``MAKE_C_IDENTIFIER`` function of :command:`string`
+ command.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DEBUG
+
+ Enable debug messages while executing ``CPackNuGet.cmake``.
+
+ * Mandatory : NO
+ * Default : OFF
+
+
+.. _nuget.org: http://nuget.org
+.. _version specification: https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
+
+.. NuGet spec docs https://docs.microsoft.com/en-us/nuget/reference/nuspec
+
+#]=======================================================================]
+
+# Author: Alex Turbov
+
+if(CMAKE_BINARY_DIR)
+ message(FATAL_ERROR "CPackNuGet.cmake may only be used by CPack internally.")
+endif()
+
+function(_cpack_nuget_debug)
+ if(CPACK_NUGET_PACKAGE_DEBUG)
+ message("CPackNuGet:Debug: " ${ARGN})
+ endif()
+endfunction()
+
+function(_cpack_nuget_debug_var NAME)
+ if(CPACK_NUGET_PACKAGE_DEBUG)
+ message("CPackNuGet:Debug: ${NAME}=`${${NAME}}`")
+ endif()
+endfunction()
+
+function(_cpack_nuget_variable_fallback OUTPUT_VAR_NAME NUGET_VAR_NAME)
+ if(ARGN)
+ list(JOIN ARGN "`, `" _va_args)
+ set(_va_args ", ARGN: `${_va_args}`")
+ endif()
+ _cpack_nuget_debug(
+ "_cpack_nuget_variable_fallback: "
+ "OUTPUT_VAR_NAME=`${OUTPUT_VAR_NAME}`, "
+ "NUGET_VAR_NAME=`${NUGET_VAR_NAME}`"
+ "${_va_args}"
+ )
+
+ set(_options USE_CDATA)
+ set(_one_value_args LIST_GLUE)
+ set(_multi_value_args FALLBACK_VARS)
+ cmake_parse_arguments(PARSE_ARGV 0 _args "${_options}" "${_one_value_args}" "${_multi_value_args}")
+
+ if(CPACK_NUGET_PACKAGE_COMPONENT)
+ string(
+ TOUPPER "${CPACK_NUGET_PACKAGE_COMPONENT}"
+ CPACK_NUGET_PACKAGE_COMPONENT_UPPER
+ )
+ endif()
+
+ if(CPACK_NUGET_PACKAGE_COMPONENT
+ AND CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_PACKAGE_${NUGET_VAR_NAME}
+ )
+ set(
+ _result
+ "${CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_PACKAGE_${NUGET_VAR_NAME}}"
+ )
+ _cpack_nuget_debug(
+ " CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_PACKAGE_${NUGET_VAR_NAME}: "
+ "OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`"
+ )
+
+ elseif(CPACK_NUGET_PACKAGE_COMPONENT_UPPER
+ AND CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_${NUGET_VAR_NAME}
+ )
+ set(
+ _result
+ "${CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_${NUGET_VAR_NAME}}"
+ )
+ _cpack_nuget_debug(
+ " CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_${NUGET_VAR_NAME}: "
+ "OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`"
+ )
+
+ elseif(CPACK_NUGET_PACKAGE_${NUGET_VAR_NAME})
+ set(_result "${CPACK_NUGET_PACKAGE_${NUGET_VAR_NAME}}")
+ _cpack_nuget_debug(
+ " CPACK_NUGET_PACKAGE_${NUGET_VAR_NAME}: "
+ "OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`"
+ )
+
+ else()
+ foreach(_var IN LISTS _args_FALLBACK_VARS)
+ _cpack_nuget_debug(" Fallback: ${_var} ...")
+ if(${_var})
+ _cpack_nuget_debug(" ${_var}=`${${_var}}`")
+ set(_result "${${_var}}")
+ _cpack_nuget_debug(
+ " ${_var}: OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`"
+ )
+ break()
+ endif()
+ endforeach()
+ endif()
+
+ if(_result)
+ if(_args_USE_CDATA)
+ set(_value_before "<![CDATA[")
+ set(_value_after "]]>")
+ endif()
+
+ list(LENGTH _result _result_len)
+ if(_result_len GREATER 1 AND _args_LIST_GLUE)
+ list(JOIN _result "${_args_LIST_GLUE}" _result)
+ endif()
+
+ set(${OUTPUT_VAR_NAME} "${_value_before}${_result}${_value_after}" PARENT_SCOPE)
+ endif()
+
+endfunction()
+
+function(_cpack_nuget_variable_fallback_and_wrap_into_element ELEMENT NUGET_VAR_NAME)
+ set(_options)
+ set(_one_value_args)
+ set(_multi_value_args FALLBACK_VARS)
+ cmake_parse_arguments(PARSE_ARGV 0 _args "${_options}" "${_one_value_args}" "${_multi_value_args}")
+
+ _cpack_nuget_variable_fallback(_value ${NUGET_VAR_NAME} ${ARGN} USE_CDATA)
+
+ if(_value)
+ string(TOUPPER "${ELEMENT}" _ELEMENT_UP)
+ set(
+ _CPACK_NUGET_${_ELEMENT_UP}_TAG
+ "<${ELEMENT}>${_value}</${ELEMENT}>"
+ PARENT_SCOPE
+ )
+ endif()
+endfunction()
+
+# Print some debug info
+_cpack_nuget_debug("---[CPack NuGet Input Variables]---")
+_cpack_nuget_debug_var(CPACK_PACKAGE_NAME)
+_cpack_nuget_debug_var(CPACK_PACKAGE_VERSION)
+_cpack_nuget_debug_var(CPACK_TOPLEVEL_TAG)
+_cpack_nuget_debug_var(CPACK_TOPLEVEL_DIRECTORY)
+_cpack_nuget_debug_var(CPACK_TEMPORARY_DIRECTORY)
+_cpack_nuget_debug_var(CPACK_NUGET_GROUPS)
+if(CPACK_NUGET_GROUPS)
+ foreach(_group IN LISTS CPACK_NUGET_GROUPS)
+ string(MAKE_C_IDENTIFIER "${_group}" _group_up)
+ string(TOUPPER "${_group_up}" _group_up)
+ _cpack_nuget_debug_var(CPACK_NUGET_${_group_up}_GROUP_COMPONENTS)
+ endforeach()
+endif()
+_cpack_nuget_debug_var(CPACK_NUGET_COMPONENTS)
+_cpack_nuget_debug_var(CPACK_NUGET_ALL_IN_ONE)
+_cpack_nuget_debug_var(CPACK_NUGET_ORDINAL_MONOLITIC)
+_cpack_nuget_debug("-----------------------------------")
+
+function(_cpack_nuget_render_spec)
+ # Make a variable w/ upper-cased component name
+ if(CPACK_NUGET_PACKAGE_COMPONENT)
+ string(TOUPPER "${CPACK_NUGET_PACKAGE_COMPONENT}" CPACK_NUGET_PACKAGE_COMPONENT_UPPER)
+ endif()
+
+ # Set mandatory variables (not wrapped into XML elements)
+ # https://docs.microsoft.com/en-us/nuget/reference/nuspec#required-metadata-elements
+ if(CPACK_NUGET_PACKAGE_COMPONENT)
+ if(CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME)
+ set(
+ CPACK_NUGET_PACKAGE_NAME
+ "${CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME}"
+ )
+ elseif(NOT CPACK_NUGET_PACKAGE_COMPONENT STREQUAL "Unspecified")
+ set(
+ CPACK_NUGET_PACKAGE_NAME
+ "${CPACK_PACKAGE_NAME}.${CPACK_NUGET_PACKAGE_COMPONENT}"
+ )
+ else()
+ set(CPACK_NUGET_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
+ endif()
+ elseif(NOT CPACK_NUGET_PACKAGE_NAME)
+ set(CPACK_NUGET_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
+ endif()
+
+ _cpack_nuget_variable_fallback(
+ CPACK_NUGET_PACKAGE_VERSION VERSION
+ FALLBACK_VARS
+ CPACK_PACKAGE_VERSION
+ )
+ _cpack_nuget_variable_fallback(
+ CPACK_NUGET_PACKAGE_DESCRIPTION DESCRIPTION
+ FALLBACK_VARS
+ CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT}_DESCRIPTION
+ CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DESCRIPTION
+ CPACK_COMPONENT_GROUP_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DESCRIPTION
+ CPACK_PACKAGE_DESCRIPTION
+ USE_CDATA
+ )
+ _cpack_nuget_variable_fallback(
+ CPACK_NUGET_PACKAGE_AUTHORS AUTHORS
+ FALLBACK_VARS
+ CPACK_PACKAGE_VENDOR
+ USE_CDATA
+ LIST_GLUE ","
+ )
+
+ # Set optional variables (wrapped into XML elements)
+ # https://docs.microsoft.com/en-us/nuget/reference/nuspec#optional-metadata-elements
+ _cpack_nuget_variable_fallback_and_wrap_into_element(
+ title
+ TITLE
+ FALLBACK_VARS
+ CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT}_DISPLAY_NAME
+ CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DISPLAY_NAME
+ CPACK_COMPONENT_GROUP_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DISPLAY_NAME
+ )
+ _cpack_nuget_variable_fallback_and_wrap_into_element(owners OWNERS LIST_GLUE ",")
+ _cpack_nuget_variable_fallback_and_wrap_into_element(
+ projectUrl
+ HOMEPAGE_URL
+ FALLBACK_VARS
+ CPACK_PACKAGE_HOMEPAGE_URL
+ )
+ _cpack_nuget_variable_fallback_and_wrap_into_element(licenseUrl LICENSEURL)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(iconUrl ICONURL)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(
+ summary DESCRIPTION_SUMMARY
+ FALLBACK_VARS
+ CPACK_PACKAGE_DESCRIPTION_SUMMARY
+ )
+ if(CPACK_NUGET_PACKAGE_REQUIRE_LICENSE_ACCEPTANCE)
+ set(
+ _CPACK_NUGET_REQUIRELICENSEACCEPTANCE_TAG
+ "<requireLicenseAcceptance>true</requireLicenseAcceptance>"
+ )
+ endif()
+ _cpack_nuget_variable_fallback_and_wrap_into_element(releaseNotes RELEASE_NOTES)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(copyright COPYRIGHT)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(tags TAGS LIST_GLUE " ")
+
+ # Handle dependencies
+ _cpack_nuget_variable_fallback(_deps DEPENDENCIES)
+ set(_collected_deps)
+ foreach(_dep IN LISTS _deps)
+ _cpack_nuget_debug(" checking dependency `${_dep}`")
+
+ string(MAKE_C_IDENTIFIER "${_dep}" _dep_id)
+
+ _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep_id}_VERSION)
+
+ if(NOT _ver)
+ string(TOUPPER "${_dep_id}" _dep_id)
+ _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep_id}_VERSION)
+ endif()
+
+ if(_ver)
+ _cpack_nuget_debug(" got `${_dep}` dependency version ${_ver}")
+ list(APPEND _collected_deps "<dependency id=\"${_dep}\" version=\"${_ver}\" />")
+ endif()
+ endforeach()
+
+ # Render deps into the variable
+ if(_collected_deps)
+ set(_CPACK_NUGET_DEPENDENCIES_TAG "<dependencies>\n")
+ foreach(_line IN LISTS _collected_deps)
+ string(
+ APPEND _CPACK_NUGET_DEPENDENCIES_TAG
+ " ${_line}\n"
+ )
+ endforeach()
+ string(APPEND _CPACK_NUGET_DEPENDENCIES_TAG " </dependencies>")
+ endif()
+
+ # Render the spec file
+ # NOTE The spec filename doesn't matter. Being included into a package,
+ # NuGet will name it properly.
+ _cpack_nuget_debug("Rendering `${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec` file...")
+ configure_file(
+ "${CMAKE_CURRENT_LIST_DIR}/CPack.NuGet.nuspec.in"
+ "${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec"
+ @ONLY
+ )
+endfunction()
+
+function(_cpack_nuget_make_files_tag)
+ set(_files)
+ foreach(_comp IN LISTS ARGN)
+ string(APPEND _files " <file src=\"${_comp}\\**\" target=\".\" />\n")
+ endforeach()
+ set(_CPACK_NUGET_FILES_TAG "<files>\n${_files} </files>" PARENT_SCOPE)
+endfunction()
+
+find_program(NUGET_EXECUTABLE NuGet)
+_cpack_nuget_debug_var(NUGET_EXECUTABLE)
+if(NOT NUGET_EXECUTABLE)
+ message(FATAL_ERROR "NuGet executable not found")
+endif()
+
+# Add details for debug run
+if(CPACK_NUGET_PACKAGE_DEBUG)
+ list(APPEND CPACK_NUGET_PACK_ADDITIONAL_OPTIONS "-Verbosity" "detailed")
+endif()
+
+# Case one: ordinal all-in-one package
+if(CPACK_NUGET_ORDINAL_MONOLITIC)
+ # This variable `CPACK_NUGET_ALL_IN_ONE` set by C++ code:
+ # Meaning to pack all installed files into a single package
+ _cpack_nuget_debug("---[Making an ordinal monolitic package]---")
+ _cpack_nuget_render_spec()
+ execute_process(
+ COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ )
+
+elseif(CPACK_NUGET_ALL_IN_ONE)
+ # This variable `CPACK_NUGET_ALL_IN_ONE` set by C++ code:
+ # Meaning to pack all installed components into a single package
+ _cpack_nuget_debug("---[Making a monolitic package from installed components]---")
+
+ # Prepare the `files` element which include files from several components
+ _cpack_nuget_make_files_tag(${CPACK_NUGET_COMPONENTS})
+ _cpack_nuget_render_spec()
+ execute_process(
+ COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ )
+
+else()
+ # Is there any grouped component?
+ if(CPACK_NUGET_GROUPS)
+ _cpack_nuget_debug("---[Making grouped component(s) package(s)]---")
+ foreach(_group IN LISTS CPACK_NUGET_GROUPS)
+ _cpack_nuget_debug("Starting to make the package for group `${_group}`")
+ string(MAKE_C_IDENTIFIER "${_group}" _group_up)
+ string(TOUPPER "${_group_up}" _group_up)
+
+ # Render a spec file which includes all components in the current group
+ unset(_CPACK_NUGET_FILES_TAG)
+ _cpack_nuget_make_files_tag(${CPACK_NUGET_${_group_up}_GROUP_COMPONENTS})
+ # Temporary set `CPACK_NUGET_PACKAGE_COMPONENT` to the group name
+ # to properly collect various per group settings
+ set(CPACK_NUGET_PACKAGE_COMPONENT ${_group})
+ _cpack_nuget_render_spec()
+ unset(CPACK_NUGET_PACKAGE_COMPONENT)
+ execute_process(
+ COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ )
+ endforeach()
+ endif()
+ # Is there any single component package needed?
+ if(CPACK_NUGET_COMPONENTS)
+ _cpack_nuget_debug("---[Making single-component(s) package(s)]---")
+ foreach(_comp IN LISTS CPACK_NUGET_COMPONENTS)
+ _cpack_nuget_debug("Starting to make the package for component `${_comp}`")
+ # Render a spec file which includes only given component
+ unset(_CPACK_NUGET_FILES_TAG)
+ _cpack_nuget_make_files_tag(${_comp})
+ # Temporary set `CPACK_NUGET_PACKAGE_COMPONENT` to the current
+ # component name to properly collect various per group settings
+ set(CPACK_NUGET_PACKAGE_COMPONENT ${_comp})
+ _cpack_nuget_render_spec()
+ unset(CPACK_NUGET_PACKAGE_COMPONENT)
+ execute_process(
+ COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ )
+ endforeach()
+ endif()
+endif()
+
+file(GLOB_RECURSE GEN_CPACK_OUTPUT_FILES "${CPACK_TEMPORARY_DIRECTORY}/*.nupkg")
+if(NOT GEN_CPACK_OUTPUT_FILES)
+ message(FATAL_ERROR "NuGet package was not generated at `${CPACK_TEMPORARY_DIRECTORY}`!")
+endif()
+
+_cpack_nuget_debug("Generated files: ${GEN_CPACK_OUTPUT_FILES}")
# Specify a specific keychain to search for the signing identity.
#
#
+# .. variable:: CPACK_PREFLIGHT_<COMP>_SCRIPT
+#
+# Full path to a file that will be used as the ``preinstall`` script for the
+# named ``<COMP>`` component's package, where ``<COMP>`` is the uppercased
+# component name. No ``preinstall`` script is added if this variable is not
+# defined for a given component.
+#
+#
+# .. variable:: CPACK_POSTFLIGHT_<COMP>_SCRIPT
+#
+# Full path to a file that will be used as the ``postinstall`` script for the
+# named ``<COMP>`` component's package, where ``<COMP>`` is the uppercased
+# component name. No ``postinstall`` script is added if this variable is not
+# defined for a given component.
+#
+#
# .. variable:: CPACK_PRODUCTBUILD_RESOURCES_DIR
#
# If specified the productbuild generator copies files from this directory
# Here are some CPackRPM wiki resources that are here for historic reasons and
# are no longer maintained but may still prove useful:
#
-# - https://cmake.org/Wiki/CMake:CPackConfiguration
-# - https://cmake.org/Wiki/CMake:CPackPackageGenerators#RPM_.28Unix_Only.29
+# - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/Configuration
+# - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/PackageGenerators#rpm-unix-only
#
# List of CPackRPM specific variables:
#
# The projects URL.
#
# * Mandatory : NO
-# * Default : -
+# * Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
#
# .. variable:: CPACK_RPM_PACKAGE_DESCRIPTION
# CPACK_RPM_<component>_PACKAGE_DESCRIPTION
#
# .. variable:: CPACK_RPM_SPEC_INSTALL_POST
#
-# Deprecated - use :variable:`CPACK_RPM_POST_INSTALL_SCRIPT_FILE` instead.
+# Deprecated - use :variable:`CPACK_RPM_SPEC_MORE_DEFINE` instead.
#
# * Mandatory : NO
# * Default : -
# * Deprecated: YES
#
-# This way of specifying post-install script is deprecated, use
-# :variable:`CPACK_RPM_POST_INSTALL_SCRIPT_FILE`.
-# May be used to set an RPM post-install command inside the spec file.
-# For example setting it to ``/bin/true`` may be used to prevent
-# rpmbuild to strip binaries.
+# May be used to override the ``__spec_install_post`` section within the
+# generated spec file. This affects the install step during package creation,
+# not during package installation. For adding operations to be performed
+# during package installation, use
+# :variable:`CPACK_RPM_POST_INSTALL_SCRIPT_FILE` instead.
#
# .. variable:: CPACK_RPM_SPEC_MORE_DEFINE
#
# * Mandatory : NO
# * Default : -
#
-# May be used to add any ``%define`` lines to the generated spec file.
+# May be used to add any ``%define`` lines to the generated spec file. An
+# example of its use is to prevent stripping of executables (but note that
+# this may also disable other default post install processing)::
+#
+# set(CPACK_RPM_SPEC_MORE_DEFINE "%define __spec_install_post /bin/true")
#
# .. variable:: CPACK_RPM_PACKAGE_DEBUG
#
# variable while usually using :variable:`CPACK_INSTALLED_DIRECTORIES` variable
# to provide directory containing CMakeLists.txt and source files.
#
-# For CMake projects SRPM package would be product by executing:
+# For CMake projects SRPM package would be produced by executing::
#
-# ``cpack -G RPM --config ./CPackSourceConfig.cmake``
+# cpack -G RPM --config ./CPackSourceConfig.cmake
#
# .. note::
#
#
# Once the SRPM package is generated it can be used to generate binary packages
# by creating a directory structure for rpm generation and executing rpmbuild
-# tool:
+# tool::
#
-# ``mkdir -p build_dir/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}``
-# ``rpmbuild --define "_topdir <path_to_build_dir>" --rebuild <SRPM_file_name>``
+# mkdir -p build_dir/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
+# rpmbuild --define "_topdir <path_to_build_dir>" --rebuild <SRPM_file_name>
#
# Generated packages will be located in build_dir/RPMS directory or its sub
# directories.
endif()
endif()
+ if(NOT CPACK_RPM_PACKAGE_URL AND CMAKE_PROJECT_HOMEPAGE_URL)
+ set(CPACK_RPM_PACKAGE_URL "${CMAKE_PROJECT_HOMEPAGE_URL}")
+ endif()
+
# CPACK_RPM_PACKAGE_NAME (mandatory)
if(NOT CPACK_RPM_PACKAGE_NAME)
string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_RPM_PACKAGE_NAME)
endif()
if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER})
- # Prefix can be replaced by Prefixes but the old version stil works so we'll ignore it for now
+ # Prefix can be replaced by Prefixes but the old version still works so we'll ignore it for now
# Requires* is a special case because it gets transformed to Requires(pre/post/preun/postun)
# Auto* is a special case because the tags can not be queried by querytags rpmbuild flag
set(special_case_tags_ PREFIX REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN AUTOPROV AUTOREQ AUTOREQPROV)
option(BUILD_TESTING "Build the testing tree." ON)
# function to turn generator name into a version string
-# like vs8 vs9
+# like vs9 or vs10
function(GET_VS_VERSION_STRING generator var)
string(REGEX REPLACE "Visual Studio ([0-9][0-9]?)($|.*)" "\\1"
NUMBER "${generator}")
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
-DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
"${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
- COMPILE_OUTPUT_VARIABLE OUTPUT)
+ COMPILE_OUTPUT_VARIABLE OUTPUT
+ RUN_OUTPUT_VARIABLE RUN_OUTPUT)
# if it did not compile make the return value fail code of 1
if(NOT ${VAR}_COMPILED)
set(${VAR}_EXITCODE 1)
message(STATUS "Performing Test ${VAR} - Success")
endif()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
- "Performing C SOURCE FILE Test ${VAR} succeeded with the following output:\n"
+ "Performing C SOURCE FILE Test ${VAR} succeeded with the following compile output:\n"
"${OUTPUT}\n"
+ "...and run output:\n"
+ "${RUN_OUTPUT}\n"
"Return value: ${${VAR}}\n"
"Source file was:\n${SOURCE}\n")
else()
message(STATUS "Performing Test ${VAR} - Failed")
endif()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
+ "Performing C SOURCE FILE Test ${VAR} failed with the following compile output:\n"
"${OUTPUT}\n"
+ "...and run output:\n"
+ "${RUN_OUTPUT}\n"
"Return value: ${${VAR}_EXITCODE}\n"
"Source file was:\n${SOURCE}\n")
#ifdef CHECK_FUNCTION_EXISTS
-#ifdef __cplusplus
+# ifdef __cplusplus
extern "C"
-#endif
+# endif
char
CHECK_FUNCTION_EXISTS(void);
-#ifdef __CLASSIC_C__
+# ifdef __CLASSIC_C__
int main()
{
int ac;
char* av[];
-#else
+# else
int main(int ac, char* av[])
{
-#endif
+# endif
CHECK_FUNCTION_EXISTS();
if (ac > 1000) {
return *av[0];
#else /* CHECK_FUNCTION_EXISTS */
-#error "CHECK_FUNCTION_EXISTS has to specify the function"
+# error "CHECK_FUNCTION_EXISTS has to specify the function"
#endif /* CHECK_FUNCTION_EXISTS */
# list of macros to define (-DFOO=bar)
# ``CMAKE_REQUIRED_INCLUDES``
# list of include directories
+# ``CMAKE_REQUIRED_LIBRARIES``
+# A list of libraries to link. See policy :policy:`CMP0075`.
# ``CMAKE_REQUIRED_QUIET``
# execute quietly without messages
#
string(APPEND CMAKE_C_FLAGS " ${ARGV2}")
endif()
+ set(_CIF_LINK_LIBRARIES "")
+ if(CMAKE_REQUIRED_LIBRARIES)
+ cmake_policy(GET CMP0075 _CIF_CMP0075
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
+ if("x${_CIF_CMP0075}x" STREQUAL "xNEWx")
+ set(_CIF_LINK_LIBRARIES LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ elseif("x${_CIF_CMP0075}x" STREQUAL "xOLDx")
+ elseif(NOT _CIF_CMP0075_WARNED)
+ set(_CIF_CMP0075_WARNED 1)
+ message(AUTHOR_WARNING
+ "Policy CMP0075 is not set: Include file check macros honor CMAKE_REQUIRED_LIBRARIES. "
+ "Run \"cmake --help-policy CMP0075\" for policy details. "
+ "Use the cmake_policy command to set the policy and suppress this warning."
+ "\n"
+ "CMAKE_REQUIRED_LIBRARIES is set to:\n"
+ " ${CMAKE_REQUIRED_LIBRARIES}\n"
+ "For compatibility with CMake 3.11 and below this check is ignoring it."
+ )
+ endif()
+ unset(_CIF_CMP0075)
+ endif()
+
try_compile(${VARIABLE}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ ${_CIF_LINK_LIBRARIES}
CMAKE_FLAGS
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_INCLUDE_FILE_FLAGS}
"${CHECK_INCLUDE_FILE_C_INCLUDE_DIRS}"
OUTPUT_VARIABLE OUTPUT)
+ unset(_CIF_LINK_LIBRARIES)
if(${ARGC} EQUAL 3)
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS_SAVE})
# list of macros to define (-DFOO=bar)
# ``CMAKE_REQUIRED_INCLUDES``
# list of include directories
+# ``CMAKE_REQUIRED_LIBRARIES``
+# A list of libraries to link. See policy :policy:`CMP0075`.
# ``CMAKE_REQUIRED_QUIET``
# execute quietly without messages
#
string(APPEND CMAKE_CXX_FLAGS " ${ARGV2}")
endif()
+ set(_CIF_LINK_LIBRARIES "")
+ if(CMAKE_REQUIRED_LIBRARIES)
+ cmake_policy(GET CMP0075 _CIF_CMP0075
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
+ if("x${_CIF_CMP0075}x" STREQUAL "xNEWx")
+ set(_CIF_LINK_LIBRARIES LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ elseif("x${_CIF_CMP0075}x" STREQUAL "xOLDx")
+ elseif(NOT _CIF_CMP0075_WARNED)
+ set(_CIF_CMP0075_WARNED 1)
+ message(AUTHOR_WARNING
+ "Policy CMP0075 is not set: Include file check macros honor CMAKE_REQUIRED_LIBRARIES. "
+ "Run \"cmake --help-policy CMP0075\" for policy details. "
+ "Use the cmake_policy command to set the policy and suppress this warning."
+ "\n"
+ "CMAKE_REQUIRED_LIBRARIES is set to:\n"
+ " ${CMAKE_REQUIRED_LIBRARIES}\n"
+ "For compatibility with CMake 3.11 and below this check is ignoring it."
+ )
+ endif()
+ unset(_CIF_CMP0075)
+ endif()
+
try_compile(${VARIABLE}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ ${_CIF_LINK_LIBRARIES}
CMAKE_FLAGS
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_INCLUDE_FILE_FLAGS}
"${CHECK_INCLUDE_FILE_CXX_INCLUDE_DIRS}"
OUTPUT_VARIABLE OUTPUT)
+ unset(_CIF_LINK_LIBRARIES)
if(${ARGC} EQUAL 3)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS_SAVE})
# list of macros to define (-DFOO=bar)
# ``CMAKE_REQUIRED_INCLUDES``
# list of include directories
+# ``CMAKE_REQUIRED_LIBRARIES``
+# A list of libraries to link. See policy :policy:`CMP0075`.
# ``CMAKE_REQUIRED_QUIET``
# execute quietly without messages
#
set(_description "include file ${_INCLUDE}")
endif()
+ set(_CIF_LINK_LIBRARIES "")
+ if(CMAKE_REQUIRED_LIBRARIES)
+ cmake_policy(GET CMP0075 _CIF_CMP0075
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
+ if("x${_CIF_CMP0075}x" STREQUAL "xNEWx")
+ set(_CIF_LINK_LIBRARIES LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ elseif("x${_CIF_CMP0075}x" STREQUAL "xOLDx")
+ elseif(NOT _CIF_CMP0075_WARNED)
+ set(_CIF_CMP0075_WARNED 1)
+ message(AUTHOR_WARNING
+ "Policy CMP0075 is not set: Include file check macros honor CMAKE_REQUIRED_LIBRARIES. "
+ "Run \"cmake --help-policy CMP0075\" for policy details. "
+ "Use the cmake_policy command to set the policy and suppress this warning."
+ "\n"
+ "CMAKE_REQUIRED_LIBRARIES is set to:\n"
+ " ${CMAKE_REQUIRED_LIBRARIES}\n"
+ "For compatibility with CMake 3.11 and below this check is ignoring it."
+ )
+ endif()
+ unset(_CIF_CMP0075)
+ endif()
+
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Looking for ${_description}")
endif()
${CMAKE_BINARY_DIR}
${src}
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ ${_CIF_LINK_LIBRARIES}
CMAKE_FLAGS
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_INCLUDE_FILES_FLAGS}
"${CHECK_INCLUDE_FILES_INCLUDE_DIRS}"
OUTPUT_VARIABLE OUTPUT)
+ unset(_CIF_LINK_LIBRARIES)
if(${VARIABLE})
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Looking for ${_description} - found")
include_guard(GLOBAL)
+cmake_policy(PUSH)
+cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
+
macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE)
if(CMAKE_C_COMPILER_LOADED)
__CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" "${SYMBOL}" "${FILES}" "${VARIABLE}" )
endif()
endif()
endmacro()
+
+cmake_policy(POP)
extern int CHECK_VARIABLE_EXISTS;
-#ifdef __CLASSIC_C__
+# ifdef __CLASSIC_C__
int main()
{
int ac;
char* av[];
-#else
+# else
int main(int ac, char* av[])
{
-#endif
+# endif
if (ac > 1000) {
return *av[0];
}
#else /* CHECK_VARIABLE_EXISTS */
-#error "CHECK_VARIABLE_EXISTS has to specify the variable"
+# error "CHECK_VARIABLE_EXISTS has to specify the variable"
#endif /* CHECK_VARIABLE_EXISTS */
# Define to allow compile features to be automatically determined
macro(cmake_record_cxx_compile_features)
set(_result 0)
+ if(_result EQUAL 0 AND DEFINED CMAKE_CXX20_STANDARD_COMPILE_OPTION)
+ _record_compiler_features_cxx(20)
+ endif()
if(_result EQUAL 0 AND DEFINED CMAKE_CXX17_STANDARD_COMPILE_OPTION)
_record_compiler_features_cxx(17)
endif()
set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=gnu++1y")
endif()
- if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
+ set(_clang_version_std17 5.0)
+ if(CMAKE_SYSTEM_NAME STREQUAL "Android")
+ set(_clang_version_std17 6.0)
+ endif()
+
+ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}")
+ set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17")
+ set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17")
+ elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++1z")
set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
endif()
+
+ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}")
+ set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++2a")
+ set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a")
+ endif()
+
+ unset(_clang_version_std17)
+
+ __compiler_check_default_language_standard(CXX 2.1 98)
+elseif(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 3.9
+ AND CMAKE_CXX_SIMULATE_VERSION VERSION_GREATER_EQUAL 19.0)
+ # This version of clang-cl and the MSVC version it simulates have
+ # support for -std: flags.
+ set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "")
+ set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "")
+ set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std:c++14")
+ set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std:c++14")
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0)
+ set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std:c++17")
+ set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std:c++17")
+ set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std:c++latest")
+ set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std:c++latest")
+ else()
+ set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std:c++latest")
+ set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std:c++latest")
+ endif()
+
+ __compiler_check_default_language_standard(CXX 3.9 14)
else()
- # clang-cl does not know these options because it behaves like cl.exe
+ # This version of clang-cl, or the MSVC version it simulates, does not have
+ # language standards. Set these options as empty strings so the feature
+ # test infrastructure can at least check to see if they are defined.
set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "")
set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "")
set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "")
set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "")
set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "")
-endif()
+ set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "")
-if(NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
- __compiler_check_default_language_standard(CXX 2.1 98)
-else()
+ # There is no meaningful default for this
set(CMAKE_CXX_STANDARD_DEFAULT "")
+
+ # There are no compiler modes so we only need to test features once.
+ # Override the default macro for this special case. Pretend that
+ # all language standards are available so that at least compilation
+ # can be attempted.
+ macro(cmake_record_cxx_compile_features)
+ list(APPEND CMAKE_CXX_COMPILE_FEATURES
+ cxx_std_98
+ cxx_std_11
+ cxx_std_14
+ cxx_std_17
+ cxx_std_20
+ )
+ _record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES)
+ endmacro()
endif()
set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=gnu++1y")
endif()
-if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1)
+if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
+ set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17")
+ set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17")
+elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1)
set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++1z")
set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
endif()
+if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
+ set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++2a")
+ set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a")
+endif()
+
__compiler_check_default_language_standard(CXX 3.4 98 6.0 14)
"\"${CMAKE_${lang}_COMPILER_RANLIB}\" <TARGET>"
)
endif()
+
+ set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
endmacro()
if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15.0.0)
set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
- # todo: there is no gnu11 value supported; figure out what to do
- set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=c11")
+ set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
endif()
if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0)
unset(DETECT_BUGGY_ICC15)
set(Intel17_CXX14 "__INTEL_COMPILER >= 1700 && ${DETECT_CXX14}")
-set(_cmake_feature_test_cxx_relaxed_constexpr "__cpp_constexpr >= 201304 || (${Intel17_CXX14} && !defined(_MSC_VER))")
+set(_cmake_feature_test_cxx_relaxed_constexpr "__cpp_constexpr >= 201304 || (${Intel17_CXX14} && __INTEL_COMPILER != 1800 && !defined(_MSC_VER))")
set(Intel16_CXX14 "__INTEL_COMPILER >= 1600 && ${DETECT_CXX14}")
set(_cmake_feature_test_cxx_aggregate_default_initializers "${Intel16_CXX14}")
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0.0)
set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17")
- # todo: there is no gnu++17 value supported; figure out what to do
- set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=c++17")
+ set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17")
endif()
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0.2)
set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14")
- # todo: there is no gnu++14 value supported; figure out what to do
- set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=c++14")
elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0.0)
set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++1y")
- # todo: there is no gnu++14 value supported; figure out what to do
- set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=c++1y")
+ endif()
+
+ # Intel 15.0.2 accepts c++14 instead of c++1y, but not gnu++14
+ # instead of gnu++1y. Intel 17.0.0 accepts gnu++14 too.
+ if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0)
+ set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14")
+ elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0.0)
+ set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=gnu++1y")
endif()
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0)
--- /dev/null
+set(_cmake_oldestSupported "_MSC_VER >= 1600")
+
+# Not yet supported:
+#set(_cmake_feature_test_c_static_assert "")
+#set(_cmake_feature_test_c_restrict "")
+
+set(_cmake_feature_test_c_variadic_macros "${_cmake_oldestSupported}")
+set(_cmake_feature_test_c_function_prototypes "${_cmake_oldestSupported}")
--- /dev/null
+# MSVC has no specific options to set C language standards, but set them as
+# empty strings anyways so the feature test infrastructure can at least check
+# to see if they are defined.
+set(CMAKE_C90_STANDARD_COMPILE_OPTION "")
+set(CMAKE_C90_EXTENSION_COMPILE_OPTION "")
+set(CMAKE_C99_STANDARD_COMPILE_OPTION "")
+set(CMAKE_C99_EXTENSION_COMPILE_OPTION "")
+set(CMAKE_C11_STANDARD_COMPILE_OPTION "")
+set(CMAKE_C11_EXTENSION_COMPILE_OPTION "")
+
+# There is no meaningful default for this
+set(CMAKE_C_STANDARD_DEFAULT "")
+
+# There are no C compiler modes so we only need to test features once.
+# Override the default macro for this special case. Pretend that
+# all language standards are available so that at least compilation
+# can be attempted.
+macro(cmake_record_c_compile_features)
+ list(APPEND CMAKE_C_COMPILE_FEATURES
+ c_std_90
+ c_std_99
+ c_std_11
+ )
+ _record_compiler_features(C "" CMAKE_C_COMPILE_FEATURES)
+endmacro()
set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std:c++latest")
set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std:c++latest")
endif()
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.12.25835)
+ set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std:c++latest")
+ set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std:c++latest")
+ endif()
__compiler_check_default_language_standard(CXX 19.0 14)
# for meta-features for C++14 and above. Override the default macro
# to avoid doing unnecessary work.
macro(cmake_record_cxx_compile_features)
+ if (DEFINED CMAKE_CXX20_STANDARD_COMPILE_OPTION)
+ list(APPEND CMAKE_CXX20_COMPILE_FEATURES cxx_std_20)
+ endif()
+ # The main cmake_record_cxx_compile_features macro makes all
+ # these conditional on CMAKE_CXX##_STANDARD_COMPILE_OPTION,
+ # but we can skip the conditions because we set them above.
list(APPEND CMAKE_CXX17_COMPILE_FEATURES cxx_std_17)
list(APPEND CMAKE_CXX14_COMPILE_FEATURES cxx_std_14)
list(APPEND CMAKE_CXX98_COMPILE_FEATURES cxx_std_11) # no flag needed for 11
set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "")
set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "")
set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "")
+ set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "")
# There is no meaningful default for this
set(CMAKE_CXX_STANDARD_DEFAULT "")
cxx_std_11
cxx_std_14
cxx_std_17
+ cxx_std_20
)
_record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES)
endmacro()
set(_compiler_id_pp_test "defined(__NVCC__)")
set(_compiler_id_version_compute "
-# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__CUDACC_VER_MAJOR__)
-# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__CUDACC_VER_MINOR__)
-# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__CUDACC_VER_BUILD__)
+# if defined(__CUDACC_VER_MAJOR__)
+# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__CUDACC_VER_MAJOR__)
+# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__CUDACC_VER_MINOR__)
+# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__CUDACC_VER_BUILD__)
+# endif
# if defined(_MSC_VER)
/* _MSC_VER = VVRR */
# define @PREFIX@SIMULATE_VERSION_MAJOR @MACRO_DEC@(_MSC_VER / 100)
set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE NO)
set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+ set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-Wp,-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
+
unset(CMAKE_${lang}_COMPILE_OPTIONS_IPO)
unset(CMAKE_${lang}_ARCHIVE_CREATE_IPO)
unset(CMAKE_${lang}_ARCHIVE_APPEND_IPO)
string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -xO3 -DNDEBUG")
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -g -xO2 -DNDEBUG")
+set(CMAKE_DEPFILE_FLAGS_C "-xMD -xMF <DEPFILE>")
+
# 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
string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -xO3 -DNDEBUG")
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " -g -xO2 -DNDEBUG")
+set(CMAKE_DEPFILE_FLAGS_CXX "-xMD -xMF <DEPFILE>")
+
# 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
set(CMAKE_LINK_LIBRARY_FLAG "--library=")
set(CMAKE_INCLUDE_FLAG_C "--include_path=")
+set(CMAKE_C90_STANDARD_COMPILE_OPTION "--c89")
+set(CMAKE_C90_EXTENSION_COMPILE_OPTION "--c89 --relaxed_ansi")
+
+set(CMAKE_C99_STANDARD_COMPILE_OPTION "--c99")
+set(CMAKE_C99_EXTENSION_COMPILE_OPTION "--c99 --relaxed_ansi")
+
set(CMAKE_DEPFILE_FLAGS_C "--preproc_with_compile --preproc_dependency=<DEPFILE>")
set(CMAKE_C_CREATE_ASSEMBLY_SOURCE "<CMAKE_C_COMPILER> --compile_only --skip_assembler --c_file=<SOURCE> <DEFINES> <INCLUDES> <FLAGS> --output_file=<ASSEMBLY_SOURCE>")
set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-MF <DEPFILE> -qmakedep=gcc")
+
# CMAKE_XL_CreateExportList is part of the AIX XL compilers but not the linux ones.
# If we found the tool, we'll use it to create exports, otherwise stick with the regular
# create shared library compile line.
@id_WindowsTargetPlatformVersion@
@id_WindowsSDKDesktopARMSupport@
</PropertyGroup>
+ @id_toolset_version_props@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
@id_PreferredToolArchitecture@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "echo \"GCC_VERSION=$GCC_VERSION\" ; echo \"CURRENT_ARCH=$CURRENT_ARCH\"";
+ shellScript = "echo \"GCC_VERSION=$GCC_VERSION\" ; echo \"ARCHS=$ARCHS\"";
showEnvVarsInLog = 0;
};
2C18F0B515DC1DCE00593670 = {
if(file_up_to_date)
# Touch the file to convince the build system it is up to date.
- execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${file}")
+ file(TOUCH "${file}")
else()
_ExternalData_link_or_copy("${obj}" "${file}")
endif()
#
# Find the alsa libraries (asound)
#
-# ::
+# IMPORTED Targets
+# ^^^^^^^^^^^^^^^^
#
-# This module defines the following variables:
-# ALSA_FOUND - True if ALSA_INCLUDE_DIR & ALSA_LIBRARY are found
-# ALSA_LIBRARIES - Set when ALSA_LIBRARY is found
-# ALSA_INCLUDE_DIRS - Set when ALSA_INCLUDE_DIR is found
+# This module defines :prop_tgt:`IMPORTED` target ``ALSA::ALSA``, if
+# ALSA has been found.
#
+# Result Variables
+# ^^^^^^^^^^^^^^^^
#
+# This module defines the following variables:
#
-# ::
+# ``ALSA_FOUND``
+# True if ALSA_INCLUDE_DIR & ALSA_LIBRARY are found
#
-# ALSA_INCLUDE_DIR - where to find asoundlib.h, etc.
-# ALSA_LIBRARY - the asound library
-# ALSA_VERSION_STRING - the version of alsa found (since CMake 2.8.8)
+# ``ALSA_LIBRARIES``
+# List of libraries when using ALSA.
+#
+# ``ALSA_INCLUDE_DIRS``
+# Where to find the ALSA headers.
+#
+# Cache variables
+# ^^^^^^^^^^^^^^^
+#
+# The following cache variables may also be set:
+#
+# ``ALSA_INCLUDE_DIR``
+# the ALSA include directory
+#
+# ``ALSA_LIBRARY``
+# the absolute path of the asound library
find_path(ALSA_INCLUDE_DIR NAMES alsa/asoundlib.h
DOC "The ALSA (asound) include directory"
if(ALSA_FOUND)
set( ALSA_LIBRARIES ${ALSA_LIBRARY} )
set( ALSA_INCLUDE_DIRS ${ALSA_INCLUDE_DIR} )
+ if(NOT TARGET ALSA::ALSA)
+ add_library(ALSA::ALSA UNKNOWN IMPORTED)
+ set_target_properties(ALSA::ALSA PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ALSA_INCLUDE_DIRS}")
+ set_property(TARGET ALSA::ALSA APPEND PROPERTY IMPORTED_LOCATION "${ALSA_LIBRARY}")
+ endif()
endif()
mark_as_advanced(ALSA_INCLUDE_DIR ALSA_LIBRARY)
if(BLA_PREFER_PKGCONFIG)
find_package(PkgConfig)
- pkg_check_modules(PKGC_BLAS IMPORTED_TARGET blas)
+ pkg_check_modules(PKGC_BLAS blas)
if(PKGC_BLAS_FOUND)
- # FIXME: We should not interpret the INTERFACE_LINK_LIBRARIES property
- # because it could have generator expressions and such. This is a
- # workaround for pkg_check_modules not providing a first-class way to
- # get the list of libraries.
- get_property(BLAS_LIBRARIES TARGET PkgConfig::PKGC_BLAS PROPERTY INTERFACE_LINK_LIBRARIES)
- find_package_handle_standard_args(BLAS
- REQUIRED_VARS BLAS_LIBRARIES
- VERSION_VAR PKGC_BLAS_VERSION)
+ set(BLAS_LIBRARIES "${PKGC_BLAS_LINK_LIBRARIES}")
return()
endif()
endif()
#
# This module defines the following variables:
#
-# ::
+# ``BZIP2_FOUND``
+# system has BZip2
+# ``BZIP2_INCLUDE_DIRS``
+# the BZip2 include directories
+# ``BZIP2_LIBRARIES``
+# Link these to use BZip2
+# ``BZIP2_NEED_PREFIX``
+# this is set if the functions are prefixed with ``BZ2_``
+# ``BZIP2_VERSION_STRING``
+# the version of BZip2 found
#
-# BZIP2_FOUND - system has BZip2
-# BZIP2_INCLUDE_DIR - the BZip2 include directory
-# BZIP2_LIBRARIES - Link these to use BZip2
-# BZIP2_NEED_PREFIX - this is set if the functions are prefixed with BZ2_
-# BZIP2_VERSION_STRING - the version of BZip2 found (since CMake 2.8.8)
+# Cache variables
+# ^^^^^^^^^^^^^^^
+#
+# The following cache variables may also be set:
+#
+# ``BZIP2_INCLUDE_DIR``
+# the BZip2 include directory
set(_BZIP2_PATHS PATHS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Bzip2;InstallPath]"
VERSION_VAR BZIP2_VERSION_STRING)
if (BZIP2_FOUND)
+ set(BZIP2_INCLUDE_DIRS ${BZIP2_INCLUDE_DIR})
include(${CMAKE_CURRENT_LIST_DIR}/CheckSymbolExists.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake)
cmake_push_check_state()
elseif (GHSMULTI)
set(_boost_COMPILER "-ghs")
elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
- if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10)
+ if(MSVC_TOOLSET_VERSION GREATER_EQUAL 141)
set(_boost_COMPILER "-vc141;-vc140")
- elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19)
- set(_boost_COMPILER "-vc140")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18)
- set(_boost_COMPILER "-vc120")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17)
- set(_boost_COMPILER "-vc110")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
- set(_boost_COMPILER "-vc100")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
- set(_boost_COMPILER "-vc90")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
- set(_boost_COMPILER "-vc80")
+ elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 80)
+ set(_boost_COMPILER "-vc${MSVC_TOOLSET_VERSION}")
elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10)
set(_boost_COMPILER "-vc71")
elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13) # Good luck!
set(_Boost_TIMER_DEPENDENCIES chrono system)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
+ elseif(NOT Boost_VERSION VERSION_LESS 106700 AND Boost_VERSION VERSION_LESS 106800)
+ set(_Boost_CHRONO_DEPENDENCIES system)
+ set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time)
+ set(_Boost_COROUTINE_DEPENDENCIES context system)
+ set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time)
+ set(_Boost_FILESYSTEM_DEPENDENCIES system)
+ set(_Boost_IOSTREAMS_DEPENDENCIES regex)
+ set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic)
+ set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
+ set(_Boost_MPI_DEPENDENCIES serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
+ set(_Boost_NUMPY_DEPENDENCIES python${component_python_version})
+ set(_Boost_RANDOM_DEPENDENCIES system)
+ set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
+ set(_Boost_TIMER_DEPENDENCIES chrono system)
+ set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
+ set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
else()
- if(NOT Boost_VERSION VERSION_LESS 106700)
+ if(NOT Boost_VERSION VERSION_LESS 106800)
set(_Boost_CHRONO_DEPENDENCIES system)
set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time)
+ set(_Boost_CONTRACT_DEPENDENCIES thread chrono system date_time)
set(_Boost_COROUTINE_DEPENDENCIES context system)
set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time)
set(_Boost_FILESYSTEM_DEPENDENCIES system)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
endif()
- if(NOT Boost_VERSION VERSION_LESS 106800)
+ if(NOT Boost_VERSION VERSION_LESS 106900)
message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
endif()
endif()
set(_Boost_ATOMIC_HEADERS "boost/atomic.hpp")
set(_Boost_CHRONO_HEADERS "boost/chrono.hpp")
set(_Boost_CONTAINER_HEADERS "boost/container/container_fwd.hpp")
- set(_Boost_CONTEXT_HEADERS "boost/context/all.hpp")
+ set(_Boost_CONTRACT_HEADERS "boost/contract.hpp")
+ set(_Boost_CONTEXT_HEADERS "boost/context/detail/fcontext.hpp")
set(_Boost_COROUTINE_HEADERS "boost/coroutine/all.hpp")
set(_Boost_DATE_TIME_HEADERS "boost/date_time/date.hpp")
set(_Boost_EXCEPTION_HEADERS "boost/exception/exception.hpp")
else()
set(_arch_suffix 32)
endif()
- if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10)
+ if(MSVC_TOOLSET_VERSION GREATER_EQUAL 141)
list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.1)
list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0)
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19)
- list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0)
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18)
- list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-12.0)
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17)
- list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-11.0)
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
- list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-10.0)
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
- list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-9.0)
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
- list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-8.0)
+ elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 80)
+ math(EXPR _toolset_major_version "${MSVC_TOOLSET_VERSION} / 10")
+ list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-${_toolset_major_version}.0)
endif()
set(${componentlibvar} ${${componentlibvar}} PARENT_SCOPE)
endif()
# _Boost_COMPONENT_HEADERS. See the instructions at the top of
# _Boost_COMPONENT_DEPENDENCIES.
set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS}
- "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65"
+ "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65"
"1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60"
"1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55"
"1.54.0" "1.54" "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51"
# -- Same as CUDA_ADD_EXECUTABLE except that a library is created.
#
# CUDA_BUILD_CLEAN_TARGET()
-# -- Creates a convience target that deletes all the dependency files
+# -- Creates a convenience target that deletes all the dependency files
# generated. You should make clean after running this target to ensure the
# dependency files get regenerated.
#
set(c_compiler_realpath "")
endif()
set(CUDA_HOST_COMPILER "${c_compiler_realpath}" CACHE FILEPATH "Host side compiler used by NVCC")
+ elseif(MSVC AND "${CMAKE_C_COMPILER}" MATCHES "clcache|sccache")
+ # NVCC does not think it will work if it is passed clcache.exe or sccache.exe
+ # as the host compiler, which means that builds with CC=cl.exe won't work.
+ # Best to just feed it whatever the actual cl.exe is as the host compiler.
+ set(CUDA_HOST_COMPILER "cl.exe" CACHE FILEPATH "Host side compiler used by NVCC")
else()
set(CUDA_HOST_COMPILER "${CMAKE_C_COMPILER}"
CACHE FILEPATH "Host side compiler used by NVCC")
endif()
# Propagate the host flags to the host compiler via -Xcompiler
-option(CUDA_PROPAGATE_HOST_FLAGS "Propage C/CXX_FLAGS and friends to the host compiler via -Xcompile" ON)
+option(CUDA_PROPAGATE_HOST_FLAGS "Propagate C/CXX_FLAGS and friends to the host compiler via -Xcompile" ON)
# Enable CUDA_SEPARABLE_COMPILATION
option(CUDA_SEPARABLE_COMPILATION "Compile CUDA objects with separable compilation enabled. Requires CUDA 5.0+" OFF)
# CUDA_NVCC_EXECUTABLE
-cuda_find_host_program(CUDA_NVCC_EXECUTABLE
- NAMES nvcc
- PATHS "${CUDA_TOOLKIT_ROOT_DIR}"
- ENV CUDA_PATH
- ENV CUDA_BIN_PATH
- PATH_SUFFIXES bin bin64
- NO_DEFAULT_PATH
- )
-# Search default search paths, after we search our own set of paths.
-cuda_find_host_program(CUDA_NVCC_EXECUTABLE nvcc)
+if(DEFINED ENV{CUDA_NVCC_EXECUTABLE})
+ set(CUDA_NVCC_EXECUTABLE "$ENV{CUDA_NVCC_EXECUTABLE}" CACHE FILEPATH "The CUDA compiler")
+else()
+ cuda_find_host_program(CUDA_NVCC_EXECUTABLE
+ NAMES nvcc
+ PATHS "${CUDA_TOOLKIT_ROOT_DIR}"
+ ENV CUDA_PATH
+ ENV CUDA_BIN_PATH
+ PATH_SUFFIXES bin bin64
+ NO_DEFAULT_PATH
+ )
+ # Search default search paths, after we search our own set of paths.
+ cuda_find_host_program(CUDA_NVCC_EXECUTABLE nvcc)
+endif()
mark_as_advanced(CUDA_NVCC_EXECUTABLE)
if(CUDA_NVCC_EXECUTABLE AND NOT CUDA_VERSION)
# Bring in the dependencies. Creates a variable CUDA_NVCC_DEPEND #######
cuda_include_nvcc_dependencies(${cmake_dependency_file})
- # Convience string for output ###########################################
+ # Convenience string for output #########################################
if(CUDA_BUILD_EMULATION)
set(cuda_build_type "Emulation")
else()
###############################################################################
###############################################################################
macro(CUDA_BUILD_CLEAN_TARGET)
- # Call this after you add all your CUDA targets, and you will get a convience
- # target. You should also make clean after running this target to get the
- # build system to generate all the code again.
+ # Call this after you add all your CUDA targets, and you will get a
+ # convenience target. You should also make clean after running this target
+ # to get the build system to generate all the code again.
set(cuda_clean_target_name clean_cuda_depends)
if (CMAKE_GENERATOR MATCHES "Visual Studio")
# More info on CUDA architectures: https://en.wikipedia.org/wiki/CUDA
#
+if(CMAKE_CUDA_COMPILER_LOADED) # CUDA as a language
+ if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
+ set(CUDA_VERSION "${CMAKE_CUDA_COMPILER_VERSION}")
+ endif()
+endif()
+
+# See: https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-feature-list
+
# This list will be used for CUDA_ARCH_NAME = All option
set(CUDA_KNOWN_GPU_ARCHITECTURES "Fermi" "Kepler" "Maxwell")
# This list will be used for CUDA_ARCH_NAME = Common option (enabled by default)
set(CUDA_COMMON_GPU_ARCHITECTURES "3.0" "3.5" "5.0")
-if (CUDA_VERSION VERSION_GREATER "6.5")
+if(CUDA_VERSION VERSION_LESS "7.0")
+ set(CUDA_LIMIT_GPU_ARCHITECTURE "5.2")
+endif()
+
+# This list is used to filter CUDA archs when autodetecting
+set(CUDA_ALL_GPU_ARCHITECTURES "3.0" "3.2" "3.5" "5.0")
+
+if(CUDA_VERSION VERSION_GREATER_EQUAL "7.0")
list(APPEND CUDA_KNOWN_GPU_ARCHITECTURES "Kepler+Tegra" "Kepler+Tesla" "Maxwell+Tegra")
list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "5.2")
-endif ()
-if (CUDA_VERSION VERSION_GREATER "7.5")
+ if(CUDA_VERSION VERSION_LESS "8.0")
+ list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "5.2+PTX")
+ set(CUDA_LIMIT_GPU_ARCHITECTURE "6.0")
+ endif()
+endif()
+
+if(CUDA_VERSION VERSION_GREATER_EQUAL "8.0")
list(APPEND CUDA_KNOWN_GPU_ARCHITECTURES "Pascal")
list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "6.0" "6.1")
-else()
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "5.2+PTX")
+ list(APPEND CUDA_ALL_GPU_ARCHITECTURES "6.0" "6.1" "6.2")
+
+ if(CUDA_VERSION VERSION_LESS "9.0")
+ list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "6.1+PTX")
+ set(CUDA_LIMIT_GPU_ARCHITECTURE "7.0")
+ endif()
endif ()
-if (CUDA_VERSION VERSION_GREATER "8.5")
+if(CUDA_VERSION VERSION_GREATER_EQUAL "9.0")
list(APPEND CUDA_KNOWN_GPU_ARCHITECTURES "Volta")
list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "7.0" "7.0+PTX")
-else()
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "6.1+PTX")
+
+ if(CUDA_VERSION VERSION_LESS "10.0")
+ set(CUDA_LIMIT_GPU_ARCHITECTURE "8.0")
+ endif()
endif()
################################################################################################
#
function(CUDA_DETECT_INSTALLED_GPUS OUT_VARIABLE)
if(NOT CUDA_GPU_DETECT_OUTPUT)
- set(file ${PROJECT_BINARY_DIR}/detect_cuda_compute_capabilities.cpp)
+ if(CMAKE_CUDA_COMPILER_LOADED) # CUDA as a language
+ set(file "${PROJECT_BINARY_DIR}/detect_cuda_compute_capabilities.cu")
+ else()
+ set(file "${PROJECT_BINARY_DIR}/detect_cuda_compute_capabilities.cpp")
+ endif()
file(WRITE ${file} ""
"#include <cuda_runtime.h>\n"
" return 0;\n"
"}\n")
- try_run(run_result compile_result ${PROJECT_BINARY_DIR} ${file}
- CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CUDA_INCLUDE_DIRS}"
- LINK_LIBRARIES ${CUDA_LIBRARIES}
- RUN_OUTPUT_VARIABLE compute_capabilities)
+ if(CMAKE_CUDA_COMPILER_LOADED) # CUDA as a language
+ try_run(run_result compile_result ${PROJECT_BINARY_DIR} ${file}
+ RUN_OUTPUT_VARIABLE compute_capabilities)
+ else()
+ try_run(run_result compile_result ${PROJECT_BINARY_DIR} ${file}
+ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CUDA_INCLUDE_DIRS}"
+ LINK_LIBRARIES ${CUDA_LIBRARIES}
+ RUN_OUTPUT_VARIABLE compute_capabilities)
+ endif()
if(run_result EQUAL 0)
string(REPLACE "2.1" "2.1(2.0)" compute_capabilities "${compute_capabilities}")
message(STATUS "Automatic GPU detection failed. Building for common architectures.")
set(${OUT_VARIABLE} ${CUDA_COMMON_GPU_ARCHITECTURES} PARENT_SCOPE)
else()
- set(${OUT_VARIABLE} ${CUDA_GPU_DETECT_OUTPUT} PARENT_SCOPE)
+ # Filter based on CUDA version supported archs
+ set(CUDA_GPU_DETECT_OUTPUT_FILTERED "")
+ separate_arguments(CUDA_GPU_DETECT_OUTPUT)
+ foreach(ITEM IN ITEMS ${CUDA_GPU_DETECT_OUTPUT})
+ if(CUDA_LIMIT_GPU_ARCHITECTURE AND ITEM VERSION_GREATER_EQUAL CUDA_LIMIT_GPU_ARCHITECTURE)
+ list(GET CUDA_COMMON_GPU_ARCHITECTURES -1 NEWITEM)
+ string(APPEND CUDA_GPU_DETECT_OUTPUT_FILTERED " ${NEWITEM}")
+ else()
+ string(APPEND CUDA_GPU_DETECT_OUTPUT_FILTERED " ${ITEM}")
+ endif()
+ endforeach()
+
+ set(${OUT_VARIABLE} ${CUDA_GPU_DETECT_OUTPUT_FILTERED} PARENT_SCOPE)
endif()
endfunction()
# FindCURL
# --------
#
-# Find curl
-#
# Find the native CURL headers and libraries.
#
-# ::
+# IMPORTED Targets
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines :prop_tgt:`IMPORTED` target ``CURL::libcurl``, if
+# curl has been found.
+#
+# Result Variables
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines the following variables:
#
-# CURL_INCLUDE_DIRS - where to find curl/curl.h, etc.
-# CURL_LIBRARIES - List of libraries when using curl.
-# CURL_FOUND - True if curl found.
-# CURL_VERSION_STRING - the version of curl found (since CMake 2.8.8)
+# ``CURL_FOUND``
+# True if curl found.
+#
+# ``CURL_INCLUDE_DIRS``
+# where to find curl/curl.h, etc.
+#
+# ``CURL_LIBRARIES``
+# List of libraries when using curl.
+#
+# ``CURL_VERSION_STRING``
+# The version of curl found.
# Look for the header file.
find_path(CURL_INCLUDE_DIR NAMES curl/curl.h)
if(CURL_FOUND)
set(CURL_LIBRARIES ${CURL_LIBRARY})
set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
+
+ if(NOT TARGET CURL::libcurl)
+ add_library(CURL::libcurl UNKNOWN IMPORTED)
+ set_target_properties(CURL::libcurl PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}")
+ set_property(TARGET CURL::libcurl APPEND PROPERTY IMPORTED_LOCATION "${CURL_LIBRARY}")
+ endif()
endif()
set(CXXTEST_TESTGEN_ARGS --error-printer)
endif()
-find_package(PythonInterp QUIET)
+find_package(Python QUIET)
find_package(Perl QUIET)
find_path(CXXTEST_INCLUDE_DIR cxxtest/TestSuite.h)
find_program(CXXTEST_PERL_TESTGEN_EXECUTABLE cxxtestgen.pl
PATHS ${CXXTEST_INCLUDE_DIR})
-if(PYTHONINTERP_FOUND OR PERL_FOUND)
+if(PYTHON_FOUND OR PERL_FOUND)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
- if(PYTHONINTERP_FOUND AND (CXXTEST_USE_PYTHON OR NOT PERL_FOUND OR NOT DEFINED CXXTEST_USE_PYTHON))
+ if(PYTHON_FOUND AND (CXXTEST_USE_PYTHON OR NOT PERL_FOUND OR NOT DEFINED CXXTEST_USE_PYTHON))
set(CXXTEST_TESTGEN_EXECUTABLE ${CXXTEST_PYTHON_TESTGEN_EXECUTABLE})
execute_process(COMMAND ${CXXTEST_PYTHON_TESTGEN_EXECUTABLE} --version
OUTPUT_VARIABLE _CXXTEST_OUT ERROR_VARIABLE _CXXTEST_OUT RESULT_VARIABLE _CXXTEST_RESULT)
if(_CXXTEST_RESULT EQUAL 0)
set(CXXTEST_TESTGEN_INTERPRETER "")
else()
- set(CXXTEST_TESTGEN_INTERPRETER ${PYTHON_EXECUTABLE})
+ set(CXXTEST_TESTGEN_INTERPRETER ${Python_EXECUTABLE})
endif()
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CxxTest DEFAULT_MSG
CXXTEST_INCLUDE_DIR CXXTEST_PYTHON_TESTGEN_EXECUTABLE)
# Compatibility: This variable is deprecated
set(DCMTK_INCLUDE_DIR ${DCMTK_INCLUDE_DIRS})
-include(FindPackageHandleStandardArgs)
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(DCMTK
REQUIRED_VARS ${DCMTK_INCLUDE_DIR_NAMES} DCMTK_LIBRARIES
FAIL_MESSAGE "Please set DCMTK_DIR and re-run configure")
# Workaround bug in packaging of DCMTK 3.6.0 on Debian.
# See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=637687
if(DCMTK_FOUND AND UNIX AND NOT APPLE)
- include(CheckCXXSourceCompiles)
+ include(${CMAKE_CURRENT_LIST_DIR}/CheckIncludeFiles.cmake)
set(CMAKE_REQUIRED_FLAGS )
set(CMAKE_REQUIRED_DEFINITIONS )
set(CMAKE_REQUIRED_INCLUDES ${DCMTK_INCLUDE_DIRS})
set(CMAKE_REQUIRED_LIBRARIES ${DCMTK_LIBRARIES})
set(CMAKE_REQUIRED_QUIET ${DCMTK_FIND_QUIETLY})
- check_cxx_source_compiles("#include <dcmtk/config/osconfig.h>\n#include <dcmtk/ofstd/ofstream.h>\nint main(int,char*[]){return 0;}"
- DCMTK_HAVE_CONFIG_H_OPTIONAL
- )
+ check_include_files("dcmtk/config/osconfig.h;dcmtk/ofstd/ofstream.h" DCMTK_HAVE_CONFIG_H_OPTIONAL LANGUAGE CXX)
if(NOT DCMTK_HAVE_CONFIG_H_OPTIONAL)
set(DCMTK_DEFINITIONS "HAVE_CONFIG_H")
endif()
endif()
-
-if(NOT DCMTK_FIND_QUIETLY)
- message(STATUS "Trying to find DCMTK relying on FindDCMTK.cmake - ok")
-endif()
doxygen_add_docs(targetName
[filesOrDirs...]
+ [ALL]
[WORKING_DIRECTORY dir]
[COMMENT comment])
the :command:`add_custom_target` command used to create the custom target
internally.
+ If ALL is set, the target will be added to the default build target.
+
The contents of the generated ``Doxyfile`` can be customized by setting CMake
variables before calling ``doxygen_add_docs()``. Any variable with a name of
the form ``DOXYGEN_<tag>`` will have its value substituted for the
endfunction()
function(doxygen_add_docs targetName)
- set(_options)
+ set(_options ALL)
set(_one_value_args WORKING_DIRECTORY COMMENT)
set(_multi_value_args)
cmake_parse_arguments(_args
set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.${targetName}")
configure_file("${_doxyfile_template}" "${_target_doxyfile}")
+ unset(_all)
+ if(${_args_ALL})
+ set(_all ALL)
+ endif()
+
# Add the target
- add_custom_target( ${targetName} VERBATIM
+ add_custom_target( ${targetName} ${_all} VERBATIM
COMMAND ${CMAKE_COMMAND} -E make_directory ${_original_doxygen_output_dir}
COMMAND "${DOXYGEN_EXECUTABLE}" "${_target_doxyfile}"
WORKING_DIRECTORY "${_args_WORKING_DIRECTORY}"
if(GDAL_CONFIG)
exec_program(${GDAL_CONFIG} ARGS --libs OUTPUT_VARIABLE GDAL_CONFIG_LIBS)
+
if(GDAL_CONFIG_LIBS)
- string(REGEX MATCHALL "-l[^ ]+" _gdal_dashl ${GDAL_CONFIG_LIBS})
- string(REPLACE "-l" "" _gdal_lib "${_gdal_dashl}")
- string(REGEX MATCHALL "-L[^ ]+" _gdal_dashL ${GDAL_CONFIG_LIBS})
- string(REPLACE "-L" "" _gdal_libpath "${_gdal_dashL}")
+ # treat the output as a command line and split it up
+ separate_arguments(args NATIVE_COMMAND "${GDAL_CONFIG_LIBS}")
+
+ # only consider libraries whose name matches this pattern
+ set(name_pattern "[gG][dD][aA][lL]")
+
+ # consider each entry as a possible library path, name, or parent directory
+ foreach(arg IN LISTS args)
+ # library name
+ if("${arg}" MATCHES "^-l(.*)$")
+ set(lib "${CMAKE_MATCH_1}")
+
+ # only consider libraries whose name matches the expected pattern
+ if("${lib}" MATCHES "${name_pattern}")
+ list(APPEND _gdal_lib "${lib}")
+ endif()
+ # library search path
+ elseif("${arg}" MATCHES "^-L(.*)$")
+ list(APPEND _gdal_libpath "${CMAKE_MATCH_1}")
+ # assume this is a full path to a library
+ elseif(IS_ABSOLUTE "${arg}" AND EXISTS "${arg}")
+ # extract the file name
+ get_filename_component(lib "${arg}" NAME)
+
+ # only consider libraries whose name matches the expected pattern
+ if(NOT "${lib}" MATCHES "${name_pattern}")
+ continue()
+ endif()
+
+ # extract the file directory
+ get_filename_component(dir "${arg}" DIRECTORY)
+
+ # remove library prefixes/suffixes
+ string(REGEX REPLACE "^(${CMAKE_SHARED_LIBRARY_PREFIX}|${CMAKE_STATIC_LIBRARY_PREFIX})" "" lib "${lib}")
+ string(REGEX REPLACE "(${CMAKE_SHARED_LIBRARY_SUFFIX}|${CMAKE_STATIC_LIBRARY_SUFFIX})$" "" lib "${lib}")
+
+ # use the file name and directory as hints
+ list(APPEND _gdal_libpath "${dir}")
+ list(APPEND _gdal_lib "${lib}")
+ endif()
+ endforeach()
endif()
endif()
endif()
if(_expand_vc AND MSVC)
# Add vc80/vc90/vc100 midfixes
- if(MSVC_VERSION EQUAL 1400)
- set(_library ${_library}-vc80)
- elseif(MSVC_VERSION EQUAL 1500)
- set(_library ${_library}-vc90)
- elseif(MSVC_VERSION EQUAL 1600)
- set(_library ${_library}-vc100)
- elseif(MSVC_VERSION EQUAL 1700)
+ if(MSVC_TOOLSET_VERSION LESS 110)
+ set(_library ${_library}-vc${MSVC_TOOLSET_VERSION})
+ else()
# Up to gtkmm-win 2.22.0-2 there are no vc110 libraries but vc100 can be used
set(_library ${_library}-vc100)
endif()
unset(vcvers)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
- if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10)
+ if(MSVC_TOOLSET_VERSION GREATER_EQUAL 141)
set(vcvers "141;140")
- elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19)
- set(vcvers "140")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18)
- set(vcvers "120")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17)
- set(vcvers "110")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
- set(vcvers "100")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
- set(vcvers "90")
+ elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 100)
+ set(vcvers "${MSVC_TOOLSET_VERSION}")
+ elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 90)
+ set(vcvers "${MSVC_TOOLSET_VERSION}")
set(vcyear "2008")
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
- set(vcvers "80")
+ elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 80)
+ set(vcvers "${MSVC_TOOLSET_VERSION}")
set(vcyear "2005")
else() # Unknown version
set(vcvers Unknown)
PATH_SUFFIXES
ImageMagick ImageMagick-6 ImageMagick-7
DOC "Path to the ImageMagick arch-independent include dir."
+ NO_DEFAULT_PATH
)
find_path(ImageMagick_${component}_ARCH_INCLUDE_DIR
NAMES magick/magick-baseconfig.h
PATH_SUFFIXES
ImageMagick ImageMagick-6 ImageMagick-7
DOC "Path to the ImageMagick arch-specific include dir."
+ NO_DEFAULT_PATH
)
find_library(ImageMagick_${component}_LIBRARY
NAMES ${ARGN}
PATHS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/lib"
DOC "Path to the ImageMagick Magick++ library."
+ NO_DEFAULT_PATH
)
# old version have only indep dir
# FindJPEG
# --------
#
-# Find JPEG
+# Find the JPEG library (libjpeg)
#
-# Find the native JPEG includes and library This module defines
+# Imported targets
+# ^^^^^^^^^^^^^^^^
#
-# ::
+# This module defines the following :prop_tgt:`IMPORTED` targets:
#
-# JPEG_INCLUDE_DIR, where to find jpeglib.h, etc.
-# JPEG_LIBRARIES, the libraries needed to use JPEG.
-# JPEG_FOUND, If false, do not try to use JPEG.
+# ``JPEG::JPEG``
+# The JPEG library, if found.
#
-# also defined, but not for general use are
+# Result variables
+# ^^^^^^^^^^^^^^^^
#
-# ::
+# This module will set the following variables in your project:
#
-# JPEG_LIBRARY, where to find the JPEG library.
+# ``JPEG_FOUND``
+# If false, do not try to use JPEG.
+# ``JPEG_INCLUDE_DIRS``
+# where to find jpeglib.h, etc.
+# ``JPEG_LIBRARIES``
+# the libraries needed to use JPEG.
+# ``JPEG_VERSION``
+# the version of the JPEG library found
+#
+# Cache variables
+# ^^^^^^^^^^^^^^^
+#
+# The following cache variables may also be set:
+#
+# ``JPEG_INCLUDE_DIRS``
+# where to find jpeglib.h, etc.
+# ``JPEG_LIBRARY_RELEASE``
+# where to find the JPEG library (optimized).
+# ``JPEG_LIBRARY_DEBUG``
+# where to find the JPEG library (debug).
+#
+# Obsolete variables
+# ^^^^^^^^^^^^^^^^^^
+#
+# ``JPEG_INCLUDE_DIR``
+# where to find jpeglib.h, etc. (same as JPEG_INCLUDE_DIRS)
+# ``JPEG_LIBRARY``
+# where to find the JPEG library.
find_path(JPEG_INCLUDE_DIR jpeglib.h)
-set(JPEG_NAMES ${JPEG_NAMES} jpeg libjpeg)
-find_library(JPEG_LIBRARY NAMES ${JPEG_NAMES} )
+set(jpeg_names ${JPEG_NAMES} jpeg jpeg-static libjpeg libjpeg-static)
+foreach(name ${jpeg_names})
+ list(APPEND jpeg_names_debug "${name}d")
+endforeach()
+
+if(NOT JPEG_LIBRARY)
+ find_library(JPEG_LIBRARY_RELEASE NAMES ${jpeg_names})
+ find_library(JPEG_LIBRARY_DEBUG NAMES ${jpeg_names_debug})
+ include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+ select_library_configurations(JPEG)
+ mark_as_advanced(JPEG_LIBRARY_RELEASE JPEG_LIBRARY_DEBUG)
+endif()
+unset(jpeg_names)
+unset(jpeg_names_debug)
+
+if(JPEG_INCLUDE_DIR AND EXISTS "${JPEG_INCLUDE_DIR}/jpeglib.h")
+ file(STRINGS "${JPEG_INCLUDE_DIR}/jpeglib.h"
+ jpeg_lib_version REGEX "^#define[\t ]+JPEG_LIB_VERSION[\t ]+.*")
+
+ if (NOT jpeg_lib_version)
+ # libjpeg-turbo sticks JPEG_LIB_VERSION in jconfig.h
+ find_path(jconfig_dir jconfig.h)
+ if (jconfig_dir)
+ file(STRINGS "${jconfig_dir}/jconfig.h"
+ jpeg_lib_version REGEX "^#define[\t ]+JPEG_LIB_VERSION[\t ]+.*")
+ endif()
+ unset(jconfig_dir)
+ endif()
+
+ string(REGEX REPLACE "^#define[\t ]+JPEG_LIB_VERSION[\t ]+([0-9]+).*"
+ "\\1" JPEG_VERSION "${jpeg_lib_version}")
+ unset(jpeg_lib_version)
+endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(JPEG DEFAULT_MSG JPEG_LIBRARY JPEG_INCLUDE_DIR)
+find_package_handle_standard_args(JPEG
+ REQUIRED_VARS JPEG_LIBRARY JPEG_INCLUDE_DIR
+ VERSION_VAR JPEG_VERSION)
if(JPEG_FOUND)
set(JPEG_LIBRARIES ${JPEG_LIBRARY})
-endif()
+ set(JPEG_INCLUDE_DIRS "${JPEG_INCLUDE_DIR}")
-# Deprecated declarations.
-set (NATIVE_JPEG_INCLUDE_PATH ${JPEG_INCLUDE_DIR} )
-if(JPEG_LIBRARY)
- get_filename_component (NATIVE_JPEG_LIB_PATH ${JPEG_LIBRARY} PATH)
+ if(NOT TARGET JPEG::JPEG)
+ add_library(JPEG::JPEG UNKNOWN IMPORTED)
+ if(JPEG_INCLUDE_DIRS)
+ set_target_properties(JPEG::JPEG PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${JPEG_INCLUDE_DIRS}")
+ endif()
+ if(EXISTS "${JPEG_LIBRARY}")
+ set_target_properties(JPEG::JPEG PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_LOCATION "${JPEG_LIBRARY}")
+ endif()
+ if(EXISTS "${JPEG_LIBRARY_RELEASE}")
+ set_property(TARGET JPEG::JPEG APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS RELEASE)
+ set_target_properties(JPEG::JPEG PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+ IMPORTED_LOCATION_RELEASE "${JPEG_LIBRARY_RELEASE}")
+ endif()
+ if(EXISTS "${JPEG_LIBRARY_DEBUG}")
+ set_property(TARGET JPEG::JPEG APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS DEBUG)
+ set_target_properties(JPEG::JPEG PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+ IMPORTED_LOCATION_DEBUG "${JPEG_LIBRARY_DEBUG}")
+ endif()
+ endif()
endif()
-mark_as_advanced(JPEG_LIBRARY JPEG_INCLUDE_DIR )
+mark_as_advanced(JPEG_LIBRARY JPEG_INCLUDE_DIR)
# ::
#
# Runtime = User just want to execute some Java byte-compiled
-# Development = Development tools (java, javac, javah and javadoc), includes Runtime component
+# Development = Development tools (java, javac, javah, jar and javadoc), includes Runtime component
# IdlJ = idl compiler for Java
# JarSigner = signer tool for jar
#
endif()
elseif(component STREQUAL "Development")
list(APPEND _JAVA_REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAVAC_EXECUTABLE
- Java_JAVADOC_EXECUTABLE)
+ Java_JAR_EXECUTABLE Java_JAVADOC_EXECUTABLE)
if(Java_VERSION VERSION_LESS "10")
list(APPEND _JAVA_REQUIRED_VARS Java_JAVAH_EXECUTABLE)
if(Java_JAVA_EXECUTABLE AND Java_JAVAC_EXECUTABLE
- AND Java_JAVAH_EXECUTABLE AND Java_JAVADOC_EXECUTABLE)
+ AND Java_JAVAH_EXECUTABLE AND Java_JAR_EXECUTABLE AND Java_JAVADOC_EXECUTABLE)
set(Java_Development_FOUND TRUE)
endif()
else()
if(Java_JAVA_EXECUTABLE AND Java_JAVAC_EXECUTABLE
- AND Java_JAVADOC_EXECUTABLE)
+ AND Java_JAR_EXECUTABLE AND Java_JAVADOC_EXECUTABLE)
set(Java_Development_FOUND TRUE)
endif()
endif()
#
# Find the XML processing library (libxml2).
#
+# IMPORTED Targets
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines :prop_tgt:`IMPORTED` target ``LibXml2::LibXml2``, if
+# libxml2 has been found.
+#
# Result variables
# ^^^^^^^^^^^^^^^^
#
VERSION_VAR LIBXML2_VERSION_STRING)
mark_as_advanced(LIBXML2_INCLUDE_DIR LIBXML2_LIBRARY LIBXML2_XMLLINT_EXECUTABLE)
+
+if(LibXml2_FOUND AND NOT TARGET LibXml2::LibXml2)
+ add_library(LibXml2::LibXml2 UNKNOWN IMPORTED)
+ set_target_properties(LibXml2::LibXml2 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBXML2_INCLUDE_DIRS}")
+ set_property(TARGET LibXml2::LibXml2 APPEND PROPERTY IMPORTED_LOCATION "${LIBXML2_LIBRARY}")
+endif()
# This is because, the lua location is not standardized and may exist in
# locations other than lua/
+cmake_policy(PUSH) # Policies apply to functions at definition-time
+cmake_policy(SET CMP0012 NEW) # For while(TRUE)
+
unset(_lua_include_subdirs)
unset(_lua_library_names)
unset(_lua_append_versions)
+set(_lua_additional_paths
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt)
# this is a function only to have all the variables inside go away automatically
-function(_lua_set_version_vars)
+function(_lua_get_versions)
set(LUA_VERSIONS5 5.3 5.2 5.1 5.0)
if (Lua_FIND_VERSION_EXACT)
list(APPEND _lua_append_versions ${subver})
endif ()
endforeach ()
+ # New version -> Search for it (heuristic only! Defines in include might have changed)
+ if (NOT _lua_append_versions)
+ set(_lua_append_versions ${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR})
+ endif()
endif ()
endif ()
else ()
set(_lua_append_versions ${LUA_VERSIONS5})
endif ()
- list(APPEND _lua_include_subdirs "include/lua" "include")
+ if (LUA_Debug)
+ message(STATUS "Considering following Lua versions: ${_lua_append_versions}")
+ endif()
+
+ set(_lua_append_versions "${_lua_append_versions}" PARENT_SCOPE)
+endfunction()
+
+function(_lua_set_version_vars)
+ set(_lua_include_subdirs_raw "lua")
foreach (ver IN LISTS _lua_append_versions)
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)$" _ver "${ver}")
- list(APPEND _lua_include_subdirs
- include/lua${CMAKE_MATCH_1}${CMAKE_MATCH_2}
- include/lua${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
- include/lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
+ list(APPEND _lua_include_subdirs_raw
+ lua${CMAKE_MATCH_1}${CMAKE_MATCH_2}
+ lua${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
+ lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
)
endforeach ()
+ # Prepend "include/" to each path directly after the path
+ set(_lua_include_subdirs "include")
+ foreach (dir IN LISTS _lua_include_subdirs_raw)
+ list(APPEND _lua_include_subdirs "${dir}" "include/${dir}")
+ endforeach ()
+
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
- set(_lua_append_versions "${_lua_append_versions}" PARENT_SCOPE)
endfunction(_lua_set_version_vars)
-function(_lua_check_header_version _hdr_file)
+function(_lua_get_header_version)
+ unset(LUA_VERSION_STRING PARENT_SCOPE)
+ set(_hdr_file "${LUA_INCLUDE_DIR}/lua.h")
+
+ if (NOT EXISTS "${_hdr_file}")
+ return()
+ endif ()
+
# At least 5.[012] have different ways to express the version
# so all of them need to be tested. Lua 5.2 defines LUA_VERSION
# and LUA_RELEASE as joined by the C preprocessor, so avoid those.
return()
endif ()
endforeach ()
-endfunction(_lua_check_header_version)
-
-_lua_set_version_vars()
-
-if (LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h")
- _lua_check_header_version("${LUA_INCLUDE_DIR}/lua.h")
-endif ()
-
-if (NOT LUA_VERSION_STRING)
- foreach (subdir IN LISTS _lua_include_subdirs)
- unset(LUA_INCLUDE_PREFIX CACHE)
- find_path(LUA_INCLUDE_PREFIX ${subdir}/lua.h
- HINTS
- ENV LUA_DIR
- PATHS
- ~/Library/Frameworks
- /Library/Frameworks
- /sw # Fink
- /opt/local # DarwinPorts
- /opt/csw # Blastwave
- /opt
- )
- if (LUA_INCLUDE_PREFIX)
- _lua_check_header_version("${LUA_INCLUDE_PREFIX}/${subdir}/lua.h")
- if (LUA_VERSION_STRING)
- set(LUA_INCLUDE_DIR "${LUA_INCLUDE_PREFIX}/${subdir}")
+endfunction(_lua_get_header_version)
+
+function(_lua_find_header)
+ _lua_set_version_vars()
+
+ # Initialize as local variable
+ set(CMAKE_IGNORE_PATH ${CMAKE_IGNORE_PATH})
+ while (TRUE)
+ # Find the next header to test. Check each possible subdir in order
+ # This prefers e.g. higher versions as they are earlier in the list
+ # It is also consistent with previous versions of FindLua
+ foreach (subdir IN LISTS _lua_include_subdirs)
+ find_path(LUA_INCLUDE_DIR lua.h
+ HINTS
+ ENV LUA_DIR
+ PATH_SUFFIXES ${subdir}
+ PATHS ${_lua_additional_paths}
+ )
+ if (LUA_INCLUDE_DIR)
break()
- endif ()
- endif ()
- endforeach ()
-endif ()
-unset(_lua_include_subdirs)
+ endif()
+ endforeach()
+ # Did not found header -> Fail
+ if (NOT LUA_INCLUDE_DIR)
+ return()
+ endif()
+ _lua_get_header_version()
+ # Found accepted version -> Ok
+ if (LUA_VERSION_STRING)
+ if (LUA_Debug)
+ message(STATUS "Found suitable version ${LUA_VERSION_STRING} in ${LUA_INCLUDE_DIR}/lua.h")
+ endif()
+ return()
+ endif()
+ # Found wrong version -> Ignore this path and retry
+ if (LUA_Debug)
+ message(STATUS "Ignoring unsuitable version in ${LUA_INCLUDE_DIR}")
+ endif()
+ list(APPEND CMAKE_IGNORE_PATH "${LUA_INCLUDE_DIR}")
+ unset(LUA_INCLUDE_DIR CACHE)
+ unset(LUA_INCLUDE_DIR)
+ unset(LUA_INCLUDE_DIR PARENT_SCOPE)
+ endwhile ()
+endfunction()
+
+_lua_get_versions()
+_lua_find_header()
+_lua_get_header_version()
unset(_lua_append_versions)
if (LUA_VERSION_STRING)
HINTS
ENV LUA_DIR
PATH_SUFFIXES lib
- PATHS
- ~/Library/Frameworks
- /Library/Frameworks
- /sw
- /opt/local
- /opt/csw
- /opt
+ PATHS ${_lua_additional_paths}
)
unset(_lua_library_names)
VERSION_VAR LUA_VERSION_STRING)
mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARY LUA_MATH_LIBRARY)
+
+cmake_policy(POP)
# Ensure that no error output might be passed upwards.
if(NOT WRAPPER_RETURN EQUAL 0)
unset(WRAPPER_OUTPUT)
+ else()
+ # Strip leading whitespace
+ string(REGEX REPLACE "^ +" "" WRAPPER_OUTPUT "${WRAPPER_OUTPUT}")
endif()
set(${OUTPUT_VARIABLE} "${WRAPPER_OUTPUT}" PARENT_SCOPE)
set(${RESULT_VARIABLE} "${WRAPPER_RETURN}" PARENT_SCOPE)
# or shared libraries if there aren't any import libraries in use on the system.
# Note that we do not consider CMAKE_<TYPE>_LIBRARY_PREFIX intentionally here: The linker will for a given file
# decide how to link it based on file type, not based on a prefix like 'lib'.
- set(_MPI_LIB_NAME_REGEX "[^\" ]+${CMAKE_STATIC_LIBRARY_SUFFIX}|\"[^\"]+${CMAKE_STATIC_LIBRARY_SUFFIX}\"")
+ set(_MPI_LIB_SUFFIX_REGEX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
if(DEFINED CMAKE_IMPORT_LIBRARY_SUFFIX)
if(NOT ("${CMAKE_IMPORT_LIBRARY_SUFFIX}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}"))
- string(APPEND _MPI_LIB_NAME_REGEX "[^\" ]+${CMAKE_IMPORT_LIBRARY_SUFFIX}|\"[^\"]+${CMAKE_IMPORT_LIBRARY_SUFFIX}\"")
+ string(APPEND _MPI_SUFFIX_REGEX "|${CMAKE_IMPORT_LIBRARY_SUFFIX}")
endif()
else()
- string(APPEND _MPI_LIB_NAME_REGEX "[^\" ]+${CMAKE_SHARED_LIBRARY_SUFFIX}|\"[^\"]+${CMAKE_SHARED_LIBRARY_SUFFIX}\"")
+ string(APPEND _MPI_LIB_SUFFIX_REGEX "|${CMAKE_SHARED_LIBRARY_SUFFIX}")
endif()
+ set(_MPI_LIB_NAME_REGEX "(([^\" ]+(${_MPI_LIB_SUFFIX_REGEX}))|(\"[^\"]+(${_MPI_LIB_SUFFIX_REGEX})\"))( +|$)")
string(REPLACE "." "\\." _MPI_LIB_NAME_REGEX "${_MPI_LIB_NAME_REGEX}")
- string(REGEX MATCHALL "(^| )(${_MPI_LIB_NAME_REGEX})" MPI_LIBNAMES "${MPI_LINK_CMDLINE}")
+ string(REGEX MATCHALL "${_MPI_LIB_NAME_REGEX}" MPI_LIBNAMES "${MPI_LINK_CMDLINE}")
foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES)
- string(REGEX REPLACE "^ " "" _MPI_LIB_NAME "${_MPI_LIB_NAME}")
- string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}")
+ string(REGEX REPLACE "^ +\"?|\"? +$" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}")
get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY)
if(NOT "${_MPI_LIB_PATH}" STREQUAL "")
list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}")
#include <mpi.h>
#ifdef __cplusplus
-#include <cstdio>
+# include <cstdio>
#else
-#include <stdio.h>
+# include <stdio.h>
#endif
int main(int argc, char* argv[])
#include <mpi.h>
#ifdef __cplusplus
-#include <cstdio>
+# include <cstdio>
#else
-#include <stdio.h>
+# include <stdio.h>
#endif
#if defined(MPI_VERSION) && defined(MPI_SUBVERSION)
int main(int argc, char* argv[])
{
#if defined(MPI_VERSION) && defined(MPI_SUBVERSION)
-#ifdef __cplusplus
+# ifdef __cplusplus
std::puts(mpiver_str);
-#else
+# else
puts(mpiver_str);
-#endif
+# endif
#endif
#ifdef TEST_MPI_MPICXX
MPI::MPI_Init(&argc, &argv);
# FindMatlab
# ----------
#
-# Finds Matlab installations and provides Matlab tools and libraries to cmake.
+# Finds Matlab or Matlab Compiler Runtime (MCR) and provides Matlab tools,
+# libraries and compilers to CMake.
#
-# This package first intention is to find the libraries associated with Matlab
-# in order to be able to build Matlab extensions (mex files). It can also be
-# used:
+# This package primary purpose is to find the libraries associated with Matlab
+# or the MCR in order to be able to build Matlab extensions (mex files). It
+# can also be used:
#
-# * run specific commands in Matlab
-# * declare Matlab unit test
-# * retrieve various information from Matlab (mex extensions, versions and
+# * to run specific commands in Matlab in case Matlab is available
+# * for declaring Matlab unit test
+# * to retrieve various information from Matlab (mex extensions, versions and
# release queries, ...)
#
# The module supports the following components:
#
-# * ``MX_LIBRARY``, ``ENG_LIBRARY`` and ``MAT_LIBRARY``: respectively the MX,
-# ENG and MAT libraries of Matlab
-# * ``MAIN_PROGRAM`` the Matlab binary program.
+# * ``MX_LIBRARY``, ``ENG_LIBRARY`` and ``MAT_LIBRARY``: respectively the ``MX``,
+# ``ENG`` and ``MAT`` libraries of Matlab
+# * ``MAIN_PROGRAM`` the Matlab binary program. Note that this component is not
+# available on the MCR version, and will yield an error if the MCR is found
+# instead of the regular Matlab installation.
# * ``MEX_COMPILER`` the MEX compiler.
# * ``SIMULINK`` the Simulink environment.
#
# **version**, which should not be confused with the Matlab *release* name
# (eg. `R2014`).
# The :command:`matlab_get_version_from_release_name` and
-# :command:`matlab_get_release_name_from_version` allow a mapping
-# from the release name to the version.
+# :command:`matlab_get_release_name_from_version` provide a mapping
+# between the release name and the version.
#
# The variable :variable:`Matlab_ROOT_DIR` may be specified in order to give
# the path of the desired Matlab version. Otherwise, the behaviour is platform
# specific:
#
-# * Windows: The installed versions of Matlab are retrieved from the
+# * Windows: The installed versions of Matlab/MCR are retrieved from the
# Windows registry
-# * OS X: The installed versions of Matlab are given by the MATLAB
-# paths in ``/Application``. If no such application is found, it falls back
-# to the one that might be accessible from the PATH.
-# * Unix: The desired Matlab should be accessible from the PATH.
+# * OS X: The installed versions of Matlab/MCR are given by the MATLAB
+# default installation paths in ``/Application``. If no such application is
+# found, it falls back to the one that might be accessible from the ``PATH``.
+# * Unix: The desired Matlab should be accessible from the ``PATH``. This does
+# not work for MCR installation and :variable:`Matlab_ROOT_DIR` should be
+# specified on this platform.
#
# Additional information is provided when :variable:`MATLAB_FIND_DEBUG` is set.
-# When a Matlab binary is found automatically and the ``MATLAB_VERSION``
-# is not given, the version is queried from Matlab directly.
-# On Windows, it can make a window running Matlab appear.
+# When a Matlab/MCR installation is found automatically and the ``MATLAB_VERSION``
+# is not given, the version is queried from Matlab directly (on Windows this
+# may pop up a Matlab window) or from the MCR installation.
#
# The mapping of the release names and the version of Matlab is performed by
# defining pairs (name, version). The variable
# parses the registry for all Matlab versions. Available on Windows only.
# The part of the registry parsed is dependent on the host processor
# :command:`matlab_get_all_valid_matlab_roots_from_registry`
-# returns all the possible Matlab paths, according to a previously
+# returns all the possible Matlab or MCR paths, according to a previously
# given list. Only the existing/accessible paths are kept. This is mainly
# useful for the searching all possible Matlab installation.
# :command:`matlab_get_mex_suffix`
# returns the suffix to be used for the mex files
# (platform/architecture dependent)
# :command:`matlab_get_version_from_matlab_run`
-# returns the version of Matlab, given the full directory of the Matlab
-# program.
+# returns the version of Matlab/MCR, given the full directory of the Matlab/MCR
+# installation path.
#
#
# Known issues
set(_FindMatlab_SELF_DIR "${CMAKE_CURRENT_LIST_DIR}")
-include(FindPackageHandleStandardArgs)
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
include(CheckCXXCompilerFlag)
include(CheckCCompilerFlag)
# .. command:: matlab_get_version_from_release_name
#
# Returns the version of Matlab (17.58) from a release name (R2017k)
-macro (matlab_get_version_from_release_name release_name version_name)
+macro(matlab_get_version_from_release_name release_name version_name)
string(REGEX MATCHALL "${release_name}=([0-9]+\\.?[0-9]*)" _matched ${MATLAB_VERSIONS_MAPPING})
if(NOT _matched STREQUAL "")
set(${version_name} ${CMAKE_MATCH_1})
else()
- message(WARNING "The release name ${release_name} is not registered")
+ message(WARNING "[MATLAB] The release name ${release_name} is not registered")
endif()
unset(_matched)
# .. command:: matlab_get_release_name_from_version
#
# Returns the release name (R2017k) from the version of Matlab (17.58)
-macro (matlab_get_release_name_from_version version release_name)
+macro(matlab_get_release_name_from_version version release_name)
set(${release_name} "")
foreach(_var IN LISTS MATLAB_VERSIONS_MAPPING)
unset(_var)
unset(_matched)
if(${release_name} STREQUAL "")
- message(WARNING "The version ${version} is not registered")
+ message(WARNING "[MATLAB] The version ${version} is not registered")
endif()
endmacro()
# installed. The found versions are returned in `matlab_versions`.
# Set `win64` to `TRUE` if the 64 bit version of Matlab should be looked for
# The returned list contains all versions under
-# ``HKLM\\SOFTWARE\\Mathworks\\MATLAB`` or an empty list in case an error
-# occurred (or nothing found).
+# ``HKLM\\SOFTWARE\\Mathworks\\MATLAB`` and
+# ``HKLM\\SOFTWARE\\Mathworks\\MATLAB Runtime`` or an empty list in case an
+# error occurred (or nothing found).
#
# .. note::
#
function(matlab_extract_all_installed_versions_from_registry win64 matlab_versions)
if(NOT CMAKE_HOST_WIN32)
- message(FATAL_ERROR "This macro can only be called by a windows host (call to reg.exe")
+ message(FATAL_ERROR "[MATLAB] This macro can only be called by a windows host (call to reg.exe)")
endif()
-
if(${win64} AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "64")
set(APPEND_REG "/reg:64")
else()
set(APPEND_REG "/reg:32")
endif()
- # /reg:64 should be added on 64 bits capable OSs in order to enable the
- # redirection of 64 bits applications
- execute_process(
- COMMAND reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Mathworks\\MATLAB /f * /k ${APPEND_REG}
- RESULT_VARIABLE resultMatlab
- OUTPUT_VARIABLE varMatlab
- ERROR_VARIABLE errMatlab
- INPUT_FILE NUL
- )
+ set(matlabs_from_registry)
+ foreach(_installation_type IN ITEMS "MATLAB" "MATLAB Runtime")
- set(matlabs_from_registry)
- if(${resultMatlab} EQUAL 0)
+ # /reg:64 should be added on 64 bits capable OSs in order to enable the
+ # redirection of 64 bits applications
+ execute_process(
+ COMMAND reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Mathworks\\${_installation_type} /f * /k ${APPEND_REG}
+ RESULT_VARIABLE resultMatlab
+ OUTPUT_VARIABLE varMatlab
+ ERROR_VARIABLE errMatlab
+ INPUT_FILE NUL
+ )
- string(
- REGEX MATCHALL "MATLAB\\\\([0-9]+(\\.[0-9]+)?)"
- matlab_versions_regex ${varMatlab})
- foreach(match IN LISTS matlab_versions_regex)
- string(
- REGEX MATCH "MATLAB\\\\(([0-9]+)(\\.([0-9]+))?)"
- current_match ${match})
+ if(${resultMatlab} EQUAL 0)
- set(_matlab_current_version ${CMAKE_MATCH_1})
- set(current_matlab_version_major ${CMAKE_MATCH_2})
- set(current_matlab_version_minor ${CMAKE_MATCH_4})
- if(NOT current_matlab_version_minor)
- set(current_matlab_version_minor "0")
- endif()
+ string(
+ REGEX MATCHALL "MATLAB\\\\([0-9]+(\\.[0-9]+)?)"
+ matlab_versions_regex ${varMatlab})
+
+ foreach(match IN LISTS matlab_versions_regex)
+ string(
+ REGEX MATCH "MATLAB\\\\(([0-9]+)(\\.([0-9]+))?)"
+ current_match ${match})
+
+ set(_matlab_current_version ${CMAKE_MATCH_1})
+ set(current_matlab_version_major ${CMAKE_MATCH_2})
+ set(current_matlab_version_minor ${CMAKE_MATCH_4})
+ if(NOT current_matlab_version_minor)
+ set(current_matlab_version_minor "0")
+ endif()
- list(APPEND matlabs_from_registry ${_matlab_current_version})
- unset(_matlab_current_version)
- endforeach(match)
+ list(APPEND matlabs_from_registry ${_matlab_current_version})
+ unset(_matlab_current_version)
+ endforeach()
- endif()
+ endif()
+ endforeach()
if(matlabs_from_registry)
list(REMOVE_DUPLICATES matlabs_from_registry)
# list(APPEND matlab_supported_versions MATLAB_ADDITIONAL_VERSIONS)
# endif()
-
# we order from more recent to older
if(matlab_supported_versions)
list(REMOVE_DUPLICATES matlab_supported_versions)
list(REVERSE matlab_supported_versions)
endif()
-
set(${matlab_versions} ${matlab_supported_versions})
-
-
endmacro()
#.rst:
# .. command:: matlab_get_all_valid_matlab_roots_from_registry
#
-# Populates the Matlab root with valid versions of Matlab.
-# The returned matlab_roots is organized in pairs
-# ``(version_number,matlab_root_path)``.
+# Populates the Matlab root with valid versions of Matlab or
+# Matlab Runtime (MCR).
+# The returned matlab_roots is organized in triplets
+# ``(type,version_number,matlab_root_path)``, where ``type``
+# indicates either ``MATLAB`` or ``MCR``.
#
# ::
#
# matlab_roots)
#
# ``matlab_versions``
-# the versions of each of the Matlab installations
+# the versions of each of the Matlab or MCR installations
# ``matlab_roots``
-# the location of each of the Matlab installations
+# the location of each of the Matlab or MCR installations
function(matlab_get_all_valid_matlab_roots_from_registry matlab_versions matlab_roots)
# The matlab_versions comes either from
# extract_matlab_versions_from_registry_brute_force or
# matlab_extract_all_installed_versions_from_registry.
-
set(_matlab_roots_list )
+ # check for Matlab installations
foreach(_matlab_current_version ${matlab_versions})
get_filename_component(
current_MATLAB_ROOT
ABSOLUTE)
if(EXISTS ${current_MATLAB_ROOT})
- list(APPEND _matlab_roots_list ${_matlab_current_version} ${current_MATLAB_ROOT})
+ list(APPEND _matlab_roots_list "MATLAB" ${_matlab_current_version} ${current_MATLAB_ROOT})
+ endif()
+
+ endforeach()
+
+ # Check for MCR installations
+ foreach(_matlab_current_version ${matlab_versions})
+ get_filename_component(
+ current_MATLAB_ROOT
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB Runtime\\${_matlab_current_version};MATLABROOT]"
+ ABSOLUTE)
+
+ # remove the dot
+ string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}")
+
+ if(EXISTS ${current_MATLAB_ROOT})
+ list(APPEND _matlab_roots_list "MCR" ${_matlab_current_version} "${current_MATLAB_ROOT}/v${_matlab_current_version_without_dot}")
endif()
- endforeach(_matlab_current_version)
- unset(_matlab_current_version)
+ endforeach()
set(${matlab_roots} ${_matlab_roots_list} PARENT_SCOPE)
- unset(_matlab_roots_list)
endfunction()
#.rst:
# mex_suffix)
#
# ``matlab_root``
-# the root of the Matlab installation
+# the root of the Matlab/MCR installation
# ``mex_suffix``
# the variable name in which the suffix will be returned.
function(matlab_get_mex_suffix matlab_root mex_suffix)
)
endif()
endforeach(current_mexext_suffix)
-
+ if(MATLAB_FIND_DEBUG)
+ message(STATUS "[MATLAB] Determining mex files extensions from '${matlab_root}/bin' with program '${Matlab_MEXEXTENSIONS_PROG}'")
+ endif()
# the program has been found?
if((NOT Matlab_MEXEXTENSIONS_PROG) OR (NOT EXISTS ${Matlab_MEXEXTENSIONS_PROG}))
set(devnull INPUT_FILE NUL)
endif()
+ # this is the preferred way. If this does not work properly (eg. MCR on Windows), then we use our own knowledge
execute_process(
COMMAND ${Matlab_MEXEXTENSIONS_PROG}
OUTPUT_VARIABLE _matlab_mex_extension
+ #RESULT_VARIABLE _matlab_mex_extension_call
ERROR_VARIABLE _matlab_mex_extension_error
${devnull})
- string(STRIP ${_matlab_mex_extension} _matlab_mex_extension)
+
+ if(NOT "${_matlab_mex_extension_error}" STREQUAL "")
+ if(WIN32)
+ # this is only for intel architecture
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(_matlab_mex_extension "mexw64")
+ else()
+ set(_matlab_mex_extension "mexw32")
+ endif()
+ endif()
+ endif()
+
+ string(STRIP "${_matlab_mex_extension}" _matlab_mex_extension)
+ if(MATLAB_FIND_DEBUG)
+ message(STATUS "[MATLAB] '${Matlab_MEXEXTENSIONS_PROG}' : returned '${_matlab_mex_extension_call}', determined extension '${_matlab_mex_extension}' and error string is '${_matlab_mex_extension_error}'")
+ endif()
unset(Matlab_MEXEXTENSIONS_PROG CACHE)
set(${mex_suffix} ${_matlab_mex_extension} PARENT_SCOPE)
# .. command:: matlab_get_version_from_matlab_run
#
# This function runs Matlab program specified on arguments and extracts its
-# version.
+# version. If the path provided for the Matlab installation points to an MCR
+# installation, the version is extracted from the installed files.
#
# ::
#
set(${matlab_list_versions} "" PARENT_SCOPE)
-
if(MATLAB_FIND_DEBUG)
message(STATUS "[MATLAB] Determining the version of Matlab from ${matlab_binary_program}")
endif()
# .. command:: matlab_add_unit_test
#
# Adds a Matlab unit test to the test set of cmake/ctest.
-# This command requires the component ``MAIN_PROGRAM``.
+# This command requires the component ``MAIN_PROGRAM`` and hence is not
+# available for an MCR installation.
+#
# The unit test uses the Matlab unittest framework (default, available
# starting Matlab 2013b+) except if the option ``NO_UNITTEST_FRAMEWORK``
# is given.
TARGET ${${prefix}_NAME}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${${prefix}_DOCUMENTATION} $<TARGET_FILE_DIR:${${prefix}_NAME}>/${output_name}.m
- COMMENT "Copy ${${prefix}_NAME} documentation file into the output folder"
+ COMMENT "[MATLAB] Copy ${${prefix}_NAME} documentation file into the output folder"
)
endif() # documentation
# (internal)
# Used to get the version of matlab, using caching. This basically transforms the
# output of the root list, with possible unknown version, to a version
-#
-function(_Matlab_get_version_from_root matlab_root matlab_known_version matlab_final_version)
+# This can possibly run Matlab for extracting the version.
+function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_version matlab_final_version)
- # if the version is not trivial, we query matlab for that
+ # if the version is not trivial, we query matlab (if not MCR) for that
# we keep track of the location of matlab that induced this version
#if(NOT DEFINED Matlab_PROG_VERSION_STRING_AUTO_DETECT)
# set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version")
return()
endif()
- #
- set(_matlab_current_program ${Matlab_MAIN_PROGRAM})
-
- # do we already have a matlab program?
- if(NOT _matlab_current_program)
-
- set(_find_matlab_options)
- if(matlab_root AND EXISTS ${matlab_root})
- set(_find_matlab_options PATHS ${matlab_root} ${matlab_root}/bin NO_DEFAULT_PATH)
+ if("${matlab_or_mcr}" STREQUAL "UNKNOWN")
+ if(MATLAB_FIND_DEBUG)
+ message(WARNING "[MATLAB] Determining Matlab or MCR")
endif()
- find_program(
- _matlab_current_program
- matlab
- ${_find_matlab_options}
- DOC "Matlab main program"
- )
- endif()
+ if(EXISTS "${matlab_root}/appdata/version.xml")
+ # we inspect the application version.xml file that contains the product information
+ file(STRINGS "${matlab_root}/appdata/version.xml" productinfo_string NEWLINE_CONSUME)
+ string(REGEX MATCH "<installedProductData.*displayedString=\"([a-zA-Z ]+)\".*/>"
+ product_reg_match
+ ${productinfo_string}
+ )
+
+ # default fallback to Matlab
+ set(matlab_or_mcr "MATLAB")
+ if(NOT "${CMAKE_MATCH_1}" STREQUAL "")
+ string(TOLOWER "${CMAKE_MATCH_1}" product_reg_match)
+
+ if("${product_reg_match}" STREQUAL "matlab runtime")
+ set(matlab_or_mcr "MCR")
+ endif()
+ endif()
+ endif()
- if(NOT _matlab_current_program OR NOT EXISTS ${_matlab_current_program})
- # if not found, clear the dependent variables
if(MATLAB_FIND_DEBUG)
- message(WARNING "[MATLAB] Cannot find the main matlab program under ${matlab_root}")
+ message(WARNING "[MATLAB] '${matlab_root}' contains the '${matlab_or_mcr}'")
endif()
- set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
- set(Matlab_VERSION_STRING_INTERNAL "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
- unset(_matlab_current_program)
- unset(_matlab_current_program CACHE)
- return()
endif()
- # full real path for path comparison
- get_filename_component(_matlab_main_real_path_tmp "${_matlab_current_program}" REALPATH)
- unset(_matlab_current_program)
- unset(_matlab_current_program CACHE)
+ # UNKNOWN is the default behaviour in case we
+ # - have an erroneous matlab_root
+ # - have an initial 'UNKNOWN'
+ if("${matlab_or_mcr}" STREQUAL "MATLAB" OR "${matlab_or_mcr}" STREQUAL "UNKNOWN")
+ # MATLAB versions
+ set(_matlab_current_program ${Matlab_MAIN_PROGRAM})
- # is it the same as the previous one?
- if(_matlab_main_real_path_tmp STREQUAL Matlab_PROG_VERSION_STRING_AUTO_DETECT)
- set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE)
- return()
- endif()
+ # do we already have a matlab program?
+ if(NOT _matlab_current_program)
- # update the location of the program
- set(Matlab_PROG_VERSION_STRING_AUTO_DETECT ${_matlab_main_real_path_tmp} CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
+ set(_find_matlab_options)
+ if(matlab_root AND EXISTS ${matlab_root})
+ set(_find_matlab_options PATHS ${matlab_root} ${matlab_root}/bin NO_DEFAULT_PATH)
+ endif()
- set(matlab_list_of_all_versions)
- matlab_get_version_from_matlab_run("${Matlab_PROG_VERSION_STRING_AUTO_DETECT}" matlab_list_of_all_versions)
+ find_program(
+ _matlab_current_program
+ matlab
+ ${_find_matlab_options}
+ DOC "Matlab main program"
+ )
+ endif()
- list(LENGTH matlab_list_of_all_versions list_of_all_versions_length)
- if(${list_of_all_versions_length} GREATER 0)
- list(GET matlab_list_of_all_versions 0 _matlab_version_tmp)
- else()
- set(_matlab_version_tmp "unknown")
- endif()
+ if(NOT _matlab_current_program OR NOT EXISTS ${_matlab_current_program})
+ # if not found, clear the dependent variables
+ if(MATLAB_FIND_DEBUG)
+ message(WARNING "[MATLAB] Cannot find the main matlab program under ${matlab_root}")
+ endif()
+ set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
+ set(Matlab_VERSION_STRING_INTERNAL "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
+ unset(_matlab_current_program)
+ unset(_matlab_current_program CACHE)
+ return()
+ endif()
- # set the version into the cache
- set(Matlab_VERSION_STRING_INTERNAL ${_matlab_version_tmp} CACHE INTERNAL "Matlab version (automatically determined)" FORCE)
+ # full real path for path comparison
+ get_filename_component(_matlab_main_real_path_tmp "${_matlab_current_program}" REALPATH)
+ unset(_matlab_current_program)
+ unset(_matlab_current_program CACHE)
- # warning, just in case several versions found (should not happen)
- if((${list_of_all_versions_length} GREATER 1) AND MATLAB_FIND_DEBUG)
- message(WARNING "[MATLAB] Found several versions, taking the first one (versions found ${matlab_list_of_all_versions})")
- endif()
+ # is it the same as the previous one?
+ if(_matlab_main_real_path_tmp STREQUAL Matlab_PROG_VERSION_STRING_AUTO_DETECT)
+ set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE)
+ return()
+ endif()
- # return the updated value
- set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE)
+ # update the location of the program
+ set(Matlab_PROG_VERSION_STRING_AUTO_DETECT
+ ${_matlab_main_real_path_tmp}
+ CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
-endfunction()
+ set(matlab_list_of_all_versions)
+ matlab_get_version_from_matlab_run("${Matlab_PROG_VERSION_STRING_AUTO_DETECT}" matlab_list_of_all_versions)
+ list(LENGTH matlab_list_of_all_versions list_of_all_versions_length)
+ if(${list_of_all_versions_length} GREATER 0)
+ list(GET matlab_list_of_all_versions 0 _matlab_version_tmp)
+ else()
+ set(_matlab_version_tmp "unknown")
+ endif()
+ # set the version into the cache
+ set(Matlab_VERSION_STRING_INTERNAL ${_matlab_version_tmp} CACHE INTERNAL "Matlab version (automatically determined)" FORCE)
+ # warning, just in case several versions found (should not happen)
+ if((${list_of_all_versions_length} GREATER 1) AND MATLAB_FIND_DEBUG)
+ message(WARNING "[MATLAB] Found several versions, taking the first one (versions found ${matlab_list_of_all_versions})")
+ endif()
+ # return the updated value
+ set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE)
+ else()
+ # MCR
+ # we cannot run anything in order to extract the version. We assume that the file
+ # VersionInfo.xml exists under the MatlabRoot, we look for it and extract the version from there
+ set(_matlab_version_tmp "unknown")
+ file(STRINGS "${matlab_root}/VersionInfo.xml" versioninfo_string NEWLINE_CONSUME)
+ # parses "<version>9.2.0.538062</version>"
+ string(REGEX MATCH "<version>(.*)</version>"
+ version_reg_match
+ ${versioninfo_string}
+ )
+
+ if(NOT "${version_reg_match}" STREQUAL "")
+ if("${CMAKE_MATCH_1}" MATCHES "(([0-9])\\.([0-9]))[\\.0-9]*")
+ set(_matlab_version_tmp "${CMAKE_MATCH_1}")
+ endif()
+ endif()
+ set(${matlab_final_version} "${_matlab_version_tmp}" PARENT_SCOPE)
+ set(Matlab_VERSION_STRING_INTERNAL
+ "${_matlab_version_tmp}"
+ CACHE INTERNAL "Matlab (MCR) version (automatically determined)"
+ FORCE)
+ endif() # Matlab or MCR
+endfunction()
-# ###################################
-# Exploring the possible Matlab_ROOTS
-# this variable will get all Matlab installations found in the current system.
-set(_matlab_possible_roots)
+# Utility function for finding Matlab or MCR on Win32
+function(_Matlab_find_instances_win32 matlab_roots)
+ # On WIN32, we look for Matlab installation in the registry
+ # if unsuccessful, we look for all known revision and filter the existing
+ # ones.
+ # testing if we are able to extract the needed information from the registry
+ set(_matlab_versions_from_registry)
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(_matlab_win64 ON)
+ else()
+ set(_matlab_win64 OFF)
+ endif()
-if(Matlab_ROOT_DIR)
- # if the user specifies a possible root, we keep this one
+ matlab_extract_all_installed_versions_from_registry(_matlab_win64 _matlab_versions_from_registry)
- if(NOT EXISTS ${Matlab_ROOT_DIR})
- # if Matlab_ROOT_DIR specified but erroneous
+ # the returned list is empty, doing the search on all known versions
+ if(NOT _matlab_versions_from_registry)
if(MATLAB_FIND_DEBUG)
- message(WARNING "[MATLAB] the specified path for Matlab_ROOT_DIR does not exist (${Matlab_ROOT_DIR})")
- endif()
- else()
- # NOTFOUND indicates the code below to search for the version automatically
- if("${Matlab_VERSION_STRING_INTERNAL}" STREQUAL "")
- list(APPEND _matlab_possible_roots "NOTFOUND" ${Matlab_ROOT_DIR}) # empty version
- else()
- list(APPEND _matlab_possible_roots ${Matlab_VERSION_STRING_INTERNAL} ${Matlab_ROOT_DIR}) # cached version
+ message(STATUS "[MATLAB] Search for Matlab from the registry unsuccessful, testing all supported versions")
endif()
+ extract_matlab_versions_from_registry_brute_force(_matlab_versions_from_registry)
endif()
+ # filtering the results with the registry keys
+ matlab_get_all_valid_matlab_roots_from_registry("${_matlab_versions_from_registry}" _matlab_possible_roots)
+ unset(_matlab_versions_from_registry)
-else()
-
- # if the user does not specify the possible installation root, we look for
- # one installation using the appropriate heuristics
+ set(_matlab_versions_from_registry)
+ matlab_extract_all_installed_versions_from_registry(CMAKE_CL_64 _matlab_versions_from_registry)
- if(WIN32)
+ # the returned list is empty, doing the search on all known versions
+ if(NOT _matlab_versions_from_registry)
+ if(MATLAB_FIND_DEBUG)
+ message(STATUS "[MATLAB] Search for Matlab from the registry unsuccessful, testing all supported versions")
+ endif()
+ extract_matlab_versions_from_registry_brute_force(_matlab_versions_from_registry)
+ endif()
- # On WIN32, we look for Matlab installation in the registry
- # if unsuccessful, we look for all known revision and filter the existing
- # ones.
+ # filtering the results with the registry keys
+ matlab_get_all_valid_matlab_roots_from_registry("${_matlab_versions_from_registry}" _matlab_possible_roots)
+ set(${matlab_roots} ${_matlab_possible_roots} PARENT_SCOPE)
- # testing if we are able to extract the needed information from the registry
- set(_matlab_versions_from_registry)
+endfunction()
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- set(_matlab_win64 ON)
- else()
- set(_matlab_win64 OFF)
- endif()
+# Utility function for finding Matlab or MCR on OSX
+function(_Matlab_find_instances_osx matlab_roots)
- matlab_extract_all_installed_versions_from_registry(_matlab_win64 _matlab_versions_from_registry)
+ set(_matlab_possible_roots)
+ # on mac, we look for the /Application paths
+ # this corresponds to the behaviour on Windows. On Linux, we do not have
+ # any other guess.
+ matlab_get_supported_releases(_matlab_releases)
+ if(MATLAB_FIND_DEBUG)
+ message(STATUS "[MATLAB] Matlab supported versions ${_matlab_releases}. If more version should be supported "
+ "the variable MATLAB_ADDITIONAL_VERSIONS can be set according to the documentation")
+ endif()
- # the returned list is empty, doing the search on all known versions
- if(NOT _matlab_versions_from_registry)
+ foreach(_matlab_current_release IN LISTS _matlab_releases)
+ matlab_get_version_from_release_name("${_matlab_current_release}" _matlab_current_version)
+ string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}")
+ set(_matlab_base_path "/Applications/MATLAB_${_matlab_current_release}.app")
+ # Check Matlab, has precedence over MCR
+ if(EXISTS ${_matlab_base_path})
if(MATLAB_FIND_DEBUG)
- message(STATUS "[MATLAB] Search for Matlab from the registry unsuccessful, testing all supported versions")
+ message(STATUS "[MATLAB] Found version ${_matlab_current_release} (${_matlab_current_version}) in ${_matlab_base_path}")
endif()
-
- extract_matlab_versions_from_registry_brute_force(_matlab_versions_from_registry)
+ list(APPEND _matlab_possible_roots "MATLAB" ${_matlab_current_version} ${_matlab_base_path})
endif()
- # filtering the results with the registry keys
- matlab_get_all_valid_matlab_roots_from_registry("${_matlab_versions_from_registry}" _matlab_possible_roots)
- unset(_matlab_versions_from_registry)
-
- elseif(APPLE)
-
- # on mac, we look for the /Application paths
- # this corresponds to the behaviour on Windows. On Linux, we do not have
- # any other guess.
- matlab_get_supported_releases(_matlab_releases)
- if(MATLAB_FIND_DEBUG)
- message(STATUS "[MATLAB] Matlab supported versions ${_matlab_releases}. If more version should be supported "
- "the variable MATLAB_ADDITIONAL_VERSIONS can be set according to the documentation")
- endif()
-
- foreach(_matlab_current_release IN LISTS _matlab_releases)
- set(_matlab_full_string "/Applications/MATLAB_${_matlab_current_release}.app")
- if(EXISTS ${_matlab_full_string})
- set(_matlab_current_version)
- matlab_get_version_from_release_name("${_matlab_current_release}" _matlab_current_version)
- if(MATLAB_FIND_DEBUG)
- message(STATUS "[MATLAB] Found version ${_matlab_current_release} (${_matlab_current_version}) in ${_matlab_full_string}")
- endif()
- list(APPEND _matlab_possible_roots ${_matlab_current_version} ${_matlab_full_string})
- unset(_matlab_current_version)
+ # Checks MCR
+ set(_mcr_path "/Applications/MATLAB/MATLAB_Runtime/v${_matlab_current_version_without_dot}")
+ if(EXISTS "${_mcr_path}")
+ if(MATLAB_FIND_DEBUG)
+ message(STATUS "[MATLAB] Found MCR version ${_matlab_current_release} (${_matlab_current_version}) in ${_mcr_path}")
endif()
+ list(APPEND _matlab_possible_roots "MCR" ${_matlab_current_version} ${_mcr_path})
+ endif()
- unset(_matlab_full_string)
- endforeach(_matlab_current_release)
-
- unset(_matlab_current_release)
- unset(_matlab_releases)
-
- endif()
-
-endif()
-
+ endforeach()
+ set(${matlab_roots} ${_matlab_possible_roots} PARENT_SCOPE)
+endfunction()
-list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots)
-if(_numbers_of_matlab_roots EQUAL 0)
- # if we have not found anything, we fall back on the PATH
+# Utility function for finding Matlab or MCR from the PATH
+function(_Matlab_find_instances_from_path matlab_roots)
+ set(_matlab_possible_roots)
# At this point, we have no other choice than trying to find it from PATH.
- # If set by the user, this won't change
+ # If set by the user, this wont change
find_program(
_matlab_main_tmp
NAMES matlab)
-
if(_matlab_main_tmp)
# we then populate the list of roots, with empty version
if(MATLAB_FIND_DEBUG)
get_filename_component(_matlab_current_location "${_matlab_current_location}" DIRECTORY)
get_filename_component(_matlab_current_location "${_matlab_current_location}" DIRECTORY) # Matlab should be in bin
- list(APPEND _matlab_possible_roots "NOTFOUND" ${_matlab_current_location})
+ # We found the Matlab program
+ list(APPEND _matlab_possible_roots "MATLAB" "NOTFOUND" ${_matlab_current_location})
+
+ # we remove this from the CACHE
+ unset(_matlab_main_tmp CACHE)
+ else()
+ find_program(
+ _matlab_mex_tmp
+ NAMES mex)
+ if(_matlab_mex_tmp)
+ # we then populate the list of roots, with empty version
+ if(MATLAB_FIND_DEBUG)
+ message(STATUS "[MATLAB] mex compiler found from PATH: ${_matlab_mex_tmp}")
+ endif()
+
+ # resolve symlinks
+ get_filename_component(_mex_current_location "${_matlab_mex_tmp}" REALPATH)
+
+ # get the directory (the command below has to be run twice)
+ # this will be the matlab root
+ get_filename_component(_mex_current_location "${_mex_current_location}" DIRECTORY)
+ get_filename_component(_mex_current_location "${_mex_current_location}" DIRECTORY) # Matlab Runtime mex compiler should be in bin
+
+ # We found the Matlab program
+ list(APPEND _matlab_possible_roots "MCR" "NOTFOUND" ${_mex_current_location})
+
+ unset(_matlab_mex_tmp CACHE)
+ else()
+ if(MATLAB_FIND_DEBUG)
+ message(STATUS "[MATLAB] mex compiler not found")
+ endif()
+ endif()
- unset(_matlab_current_location)
endif()
- unset(_matlab_main_tmp CACHE)
-endif()
+ set(${matlab_roots} ${_matlab_possible_roots} PARENT_SCOPE)
+endfunction()
+# ###################################
+# Exploring the possible Matlab_ROOTS
+# this variable will get all Matlab installations found in the current system.
+set(_matlab_possible_roots)
+
+if(Matlab_ROOT_DIR)
+ # if the user specifies a possible root, we keep this one
+
+ if(NOT EXISTS "${Matlab_ROOT_DIR}")
+ # if Matlab_ROOT_DIR specified but erroneous
+ if(MATLAB_FIND_DEBUG)
+ message(WARNING "[MATLAB] the specified path for Matlab_ROOT_DIR does not exist (${Matlab_ROOT_DIR})")
+ endif()
+ else()
+ # NOTFOUND indicates the code below to search for the version automatically
+ if("${Matlab_VERSION_STRING_INTERNAL}" STREQUAL "")
+ list(APPEND _matlab_possible_roots "UNKNOWN" "NOTFOUND" ${Matlab_ROOT_DIR}) # empty version, empty MCR/Matlab indication
+ else()
+ list(APPEND _matlab_possible_roots "UNKNOWN" ${Matlab_VERSION_STRING_INTERNAL} ${Matlab_ROOT_DIR}) # cached version
+ endif()
+ endif()
+else()
+
+ # if the user does not specify the possible installation root, we look for
+ # one installation using the appropriate heuristics.
+ # There is apparently no standard way on Linux.
+ if(WIN32)
+ _Matlab_find_instances_win32(_matlab_possible_roots_win32)
+ list(APPEND _matlab_possible_roots ${_matlab_possible_roots_win32})
+ elseif(APPLE)
+ _Matlab_find_instances_osx(_matlab_possible_roots_osx)
+ list(APPEND _matlab_possible_roots ${_matlab_possible_roots_osx})
+ endif()
+endif()
+
+
+list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots)
+if(_numbers_of_matlab_roots EQUAL 0)
+ # if we have not found anything, we fall back on the PATH
+ _Matlab_find_instances_from_path(_matlab_possible_roots)
+endif()
if(MATLAB_FIND_DEBUG)
# take the first possible Matlab root
list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots)
set(Matlab_VERSION_STRING "NOTFOUND")
+set(Matlab_Or_MCR "UNKNOWN")
if(_numbers_of_matlab_roots GREATER 0)
- list(GET _matlab_possible_roots 0 Matlab_VERSION_STRING)
- list(GET _matlab_possible_roots 1 Matlab_ROOT_DIR)
+ list(GET _matlab_possible_roots 0 Matlab_Or_MCR)
+ list(GET _matlab_possible_roots 1 Matlab_VERSION_STRING)
+ list(GET _matlab_possible_roots 2 Matlab_ROOT_DIR)
# adding a warning in case of ambiguity
- if(_numbers_of_matlab_roots GREATER 2 AND MATLAB_FIND_DEBUG)
+ if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG)
message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})."
" If this is not the desired behaviour, provide the -DMatlab_ROOT_DIR=... on the command line")
endif()
# Fix the version, in case this one is NOTFOUND
_Matlab_get_version_from_root(
"${Matlab_ROOT_DIR}"
+ "${Matlab_Or_MCR}"
${Matlab_VERSION_STRING}
Matlab_VERSION_STRING
)
-
-
-
if(MATLAB_FIND_DEBUG)
message(STATUS "[MATLAB] Current version is ${Matlab_VERSION_STRING} located ${Matlab_ROOT_DIR}")
endif()
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindODBC
+--------
+
+Find an Open Database Connectivity (ODBC) include directory and library.
+
+On Windows, when building with Visual Studio, this module assumes the ODBC
+library is provided by the available Windows SDK.
+
+On Unix, this module allows to search for ODBC library provided by
+unixODBC or iODBC implementations of ODBC API.
+This module reads hint about location of the config program:
+
+.. variable:: ODBC_CONFIG
+
+ Location of odbc_config or iodbc-config program
+
+Otherwise, this module tries to find the config program,
+first from unixODBC, then from iODBC.
+If no config program found, this module searches for ODBC header
+and library in list of known locations.
+
+Imported targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :prop_tgt:`IMPORTED` targets:
+
+.. variable:: ODBC::ODBC
+
+ Imported target for using the ODBC library, if found.
+
+Result variables
+^^^^^^^^^^^^^^^^
+
+.. variable:: ODBC_FOUND
+
+ Set to true if ODBC library found, otherwise false or undefined.
+
+.. variable:: ODBC_INCLUDE_DIRS
+
+ Paths to include directories listed in one variable for use by ODBC client.
+ May be empty on Windows, where the include directory corresponding to the
+ expected Windows SDK is already available in the compilation environment.
+
+.. variable:: ODBC_LIBRARIES
+
+ Paths to libraries to linked against to use ODBC.
+ May just a library name on Windows, where the library directory corresponding
+ to the expected Windows SDK is already available in the compilation environment.
+
+.. variable:: ODBC_CONFIG
+
+ Path to unixODBC or iODBC config program, if found or specified.
+
+Cache variables
+^^^^^^^^^^^^^^^
+
+For users who wish to edit and control the module behavior, this module
+reads hints about search locations from the following variables:
+
+.. variable:: ODBC_INCLUDE_DIR
+
+ Path to ODBC include directory with ``sql.h`` header.
+
+.. variable:: ODBC_LIBRARY
+
+ Path to ODBC library to be linked.
+
+These variables should not be used directly by project code.
+
+Limitations
+^^^^^^^^^^^
+
+On Windows, this module does not search for iODBC.
+On Unix, there is no way to prefer unixODBC over iODBC, or vice versa,
+other than providing the config program location using the ``ODBC_CONFIG``.
+This module does not allow to search for a specific ODBC driver.
+
+#]=======================================================================]
+
+# Define lists used internally
+set(_odbc_include_paths)
+set(_odbc_lib_paths)
+set(_odbc_lib_names)
+set(_odbc_required_libs_names)
+
+### Try Windows Kits ##########################################################
+if(WIN32)
+ # List names of ODBC libraries on Windows
+ set(ODBC_LIBRARY odbc32.lib)
+ set(_odbc_lib_names odbc32;)
+
+ # List additional libraries required to use ODBC library
+ if(MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Intel")
+ set(_odbc_required_libs_names odbccp32;ws2_32)
+ elseif(MINGW)
+ set(_odbc_required_libs_names odbccp32)
+ endif()
+endif()
+
+### Try unixODBC or iODBC config program ######################################
+if (UNIX)
+ find_program(ODBC_CONFIG
+ NAMES odbc_config iodbc-config
+ DOC "Path to unixODBC or iODBC config program")
+ mark_as_advanced(ODBC_CONFIG)
+endif()
+
+if (UNIX AND ODBC_CONFIG)
+ # unixODBC and iODBC accept unified command line options
+ execute_process(COMMAND ${ODBC_CONFIG} --cflags
+ OUTPUT_VARIABLE _cflags OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${ODBC_CONFIG} --libs
+ OUTPUT_VARIABLE _libs OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ # Collect paths of include directories from CFLAGS
+ separate_arguments(_cflags NATIVE_COMMAND "${_cflags}")
+ foreach(arg IN LISTS _cflags)
+ if("${arg}" MATCHES "^-I(.*)$")
+ list(APPEND _odbc_include_paths "${CMAKE_MATCH_1}")
+ endif()
+ endforeach()
+ unset(_cflags)
+
+ # Collect paths of library names and directories from LIBS
+ separate_arguments(_libs NATIVE_COMMAND "${_libs}")
+ foreach(arg IN LISTS _libs)
+ if("${arg}" MATCHES "^-L(.*)$")
+ list(APPEND _odbc_lib_paths "${CMAKE_MATCH_1}")
+ elseif("${arg}" MATCHES "^-l(.*)$")
+ set(_lib_name ${CMAKE_MATCH_1})
+ string(REGEX MATCH "odbc" _is_odbc ${_lib_name})
+ if(_is_odbc)
+ list(APPEND _odbc_lib_names ${_lib_name})
+ else()
+ list(APPEND _odbc_required_libs_names ${_lib_name})
+ endif()
+ unset(_lib_name)
+ endif()
+ endforeach()
+ unset(_libs)
+endif()
+
+### Try unixODBC or iODBC in include/lib filesystems ##########################
+if (UNIX AND NOT ODBC_CONFIG)
+ # List names of both ODBC libraries, unixODBC and iODBC
+ set(_odbc_lib_names odbc;iodbc;unixodbc;)
+endif()
+
+### Find include directories ##################################################
+find_path(ODBC_INCLUDE_DIR
+ NAMES sql.h
+ PATHS ${_odbc_include_paths})
+
+if(NOT ODBC_INCLUDE_DIR AND WIN32)
+ set(ODBC_INCLUDE_DIR "")
+endif()
+
+### Find libraries ############################################################
+if(NOT ODBC_LIBRARY)
+ find_library(ODBC_LIBRARY
+ NAMES ${_odbc_lib_names}
+ PATHS ${_odbc_lib_paths}
+ PATH_SUFFIXES odbc)
+
+ foreach(_lib IN LISTS _odbc_required_libs_names)
+ find_library(_lib_path
+ NAMES ${_lib}
+ PATHS ${_odbc_lib_paths} # system parths or collected from ODBC_CONFIG
+ PATH_SUFFIXES odbc)
+ if(_lib_path)
+ list(APPEND _odbc_required_libs_paths ${_lib_path})
+ endif()
+ unset(_lib_path CACHE)
+ endforeach()
+endif()
+
+# Unset internal lists as no longer used
+unset(_odbc_include_paths)
+unset(_odbc_lib_paths)
+unset(_odbc_lib_names)
+unset(_odbc_required_libs_names)
+
+### Set result variables ######################################################
+set(_odbc_required_vars ODBC_LIBRARY)
+if(NOT WIN32)
+ list(APPEND _odbc_required_vars ODBC_INCLUDE_DIR)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(ODBC DEFAULT_MSG ${_odbc_required_vars})
+
+unset(_odbc_required_vars)
+
+mark_as_advanced(ODBC_LIBRARY ODBC_INCLUDE_DIR)
+
+set(ODBC_INCLUDE_DIRS ${ODBC_INCLUDE_DIR})
+list(APPEND ODBC_LIBRARIES ${ODBC_LIBRARY})
+list(APPEND ODBC_LIBRARIES ${_odbc_required_libs_paths})
+
+### Import targets ############################################################
+if(ODBC_FOUND)
+ if(NOT TARGET ODBC::ODBC)
+ if(IS_ABSOLUTE "${ODBC_LIBRARY}")
+ add_library(ODBC::ODBC UNKNOWN IMPORTED)
+ set_target_properties(ODBC::ODBC PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_LOCATION "${ODBC_LIBRARY}")
+ else()
+ add_library(ODBC::ODBC INTERFACE IMPORTED)
+ set_target_properties(ODBC::ODBC PROPERTIES
+ IMPORTED_LIBNAME "${ODBC_LIBRARY}")
+ endif()
+ set_target_properties(ODBC::ODBC PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${ODBC_INCLUDE_DIR}")
+
+ if(_odbc_required_libs_paths)
+ set_property(TARGET ODBC::ODBC APPEND PROPERTY
+ INTERFACE_LINK_LIBRARIES "${_odbc_required_libs_paths}")
+ endif()
+ endif()
+endif()
+
+unset(_odbc_required_libs_paths)
find_path(OPENAL_INCLUDE_DIR al.h
HINTS
ENV OPENALDIR
- PATH_SUFFIXES include/AL include/OpenAL include
+ PATH_SUFFIXES include/AL include/OpenAL include AL OpenAL
PATHS
~/Library/Frameworks
/Library/Frameworks
set(OMP_FLAG_GNU "-fopenmp")
set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp")
+ set(OMP_FLAG_AppleClang "-Xclang -fopenmp")
set(OMP_FLAG_HP "+Oopenmp")
if(WIN32)
set(OMP_FLAG_Intel "-Qopenmp")
#include <omp.h>
int main() {
#ifdef _OPENMP
+ omp_get_max_threads();
return 0;
#else
breaks_on_purpose
set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
endfunction()
-include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseImplicitLinkInfo.cmake)
function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
_OPENMP_FLAG_CANDIDATES("${LANG}")
set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
endif()
break()
+ elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang"
+ AND CMAKE_${LANG}_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0")
+
+ # Check for separate OpenMP library on AppleClang 7+
+ find_library(OpenMP_libomp_LIBRARY
+ NAMES omp gomp iomp5
+ HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
+ )
+ mark_as_advanced(OpenMP_libomp_LIBRARY)
+
+ if(OpenMP_libomp_LIBRARY)
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+ LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+ )
+ if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+ set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
+ set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
+ break()
+ endif()
+ endif()
endif()
set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
unset(_OpenMP_MIN_VERSION)
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+
foreach(LANG IN LISTS OpenMP_FINDLIST)
if(CMAKE_${LANG}_COMPILER_LOADED)
if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS)
_OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}")
endif()
- include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-
set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY})
set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED})
set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION})
#
# Find the OpenSSL encryption library.
#
+# Optional COMPONENTS
+# ^^^^^^^^^^^^^^^^^^^
+#
+# This module supports two optional COMPONENTS: ``Crypto`` and ``SSL``. Both
+# components have associated imported targets, as described below.
+#
# Imported Targets
# ^^^^^^^^^^^^^^^^
#
# This module will set the following variables in your project:
#
# ``OPENSSL_FOUND``
-# System has the OpenSSL library.
+# System has the OpenSSL library. If no components are requested it only
+# requires the crypto library.
# ``OPENSSL_INCLUDE_DIR``
# The OpenSSL include directory.
# ``OPENSSL_CRYPTO_LIBRARY``
endif ()
endif ()
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-
set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} )
-if (OPENSSL_VERSION)
- find_package_handle_standard_args(OpenSSL
- REQUIRED_VARS
- #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request?
- OPENSSL_CRYPTO_LIBRARY
- OPENSSL_INCLUDE_DIR
- VERSION_VAR
- OPENSSL_VERSION
- FAIL_MESSAGE
- "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
- )
-else ()
- find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
- #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request?
+foreach(_comp IN LISTS OpenSSL_FIND_COMPONENTS)
+ if(_comp STREQUAL "Crypto")
+ if(EXISTS "${OPENSSL_INCLUDE_DIR}" AND
+ (EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
+ EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
+ EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
+ )
+ set(OpenSSL_${_comp}_FOUND TRUE)
+ else()
+ set(OpenSSL_${_comp}_FOUND FALSE)
+ endif()
+ elseif(_comp STREQUAL "SSL")
+ if(EXISTS "${OPENSSL_INCLUDE_DIR}" AND
+ (EXISTS "${OPENSSL_SSL_LIBRARY}" OR
+ EXISTS "${SSL_EAY_LIBRARY_DEBUG}" OR
+ EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
+ )
+ set(OpenSSL_${_comp}_FOUND TRUE)
+ else()
+ set(OpenSSL_${_comp}_FOUND FALSE)
+ endif()
+ else()
+ message(WARNING "${_comp} is not a valid OpenSSL component")
+ set(OpenSSL_${_comp}_FOUND FALSE)
+ endif()
+endforeach()
+unset(_comp)
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(OpenSSL
+ REQUIRED_VARS
OPENSSL_CRYPTO_LIBRARY
OPENSSL_INCLUDE_DIR
- )
-endif ()
+ VERSION_VAR
+ OPENSSL_VERSION
+ HANDLE_COMPONENTS
+ FAIL_MESSAGE
+ "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
+)
mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)
IMPORTED_LOCATION_DEBUG "${LIB_EAY_LIBRARY_DEBUG}")
endif()
endif()
+
if(NOT TARGET OpenSSL::SSL AND
(EXISTS "${OPENSSL_SSL_LIBRARY}" OR
EXISTS "${SSL_EAY_LIBRARY_DEBUG}" OR
NAME)
set(PERL_POSSIBLE_BIN_PATHS ${PERL_POSSIBLE_BIN_PATHS}
"C:/Perl/bin"
+ "C:/Strawberry/perl/bin"
[HKEY_LOCAL_MACHINE\\SOFTWARE\\ActiveState\\ActivePerl\\${ActivePerl_CurrentVersion}]/bin
)
endif()
# scan the LDFLAGS returned by pkg-config for library directories and
# libraries, figure out the absolute paths of that libraries in the
-# given directories, and create an imported target from them
-function(_pkg_create_imp_target _prefix _no_cmake_path _no_cmake_environment_path)
+# given directories
+function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path)
unset(_libs)
unset(_find_opts)
unset(_search_paths)
foreach (flag IN LISTS ${_prefix}_LDFLAGS)
if (flag MATCHES "^-L(.*)")
- # only look into the given paths from now on
list(APPEND _search_paths ${CMAKE_MATCH_1})
- set(_find_opts HINTS ${_search_paths} NO_DEFAULT_PATH)
continue()
endif()
if (flag MATCHES "^-l(.*)")
continue()
endif()
+ if(_search_paths)
+ # Firstly search in -L paths
+ find_library(pkgcfg_lib_${_prefix}_${_pkg_search}
+ NAMES ${_pkg_search}
+ HINTS ${_search_paths} NO_DEFAULT_PATH)
+ endif()
find_library(pkgcfg_lib_${_prefix}_${_pkg_search}
NAMES ${_pkg_search}
${_find_opts})
list(APPEND _libs "${pkgcfg_lib_${_prefix}_${_pkg_search}}")
endforeach()
+ set(${_prefix}_LINK_LIBRARIES "${_libs}" PARENT_SCOPE)
+endfunction()
+
+# create an imported target from all the information returned by pkg-config
+function(_pkg_create_imp_target _prefix)
# only create the target if it is linkable, i.e. no executables
if (NOT TARGET PkgConfig::${_prefix}
- AND ( ${_prefix}_INCLUDE_DIRS OR _libs OR ${_prefix}_CFLAGS_OTHER ))
+ AND ( ${_prefix}_INCLUDE_DIRS OR ${_prefix}_LINK_LIBRARIES OR ${_prefix}_CFLAGS_OTHER ))
add_library(PkgConfig::${_prefix} INTERFACE IMPORTED)
if(${_prefix}_INCLUDE_DIRS)
set_property(TARGET PkgConfig::${_prefix} PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${${_prefix}_INCLUDE_DIRS}")
endif()
- if(_libs)
+ if(${_prefix}_LINK_LIBRARIES)
set_property(TARGET PkgConfig::${_prefix} PROPERTY
- INTERFACE_LINK_LIBRARIES "${_libs}")
+ INTERFACE_LINK_LIBRARIES "${${_prefix}_LINK_LIBRARIES}")
endif()
if(${_prefix}_CFLAGS_OTHER)
set_property(TARGET PkgConfig::${_prefix} PROPERTY
endif()
endfunction()
+# recalculate the dynamic output
+# this is a macro and not a function so the result of _pkg_find_libs is automatically propagated
+macro(_pkg_recalculate _prefix _no_cmake_path _no_cmake_environment_path _imp_target)
+ _pkg_find_libs(${_prefix} ${_no_cmake_path} ${_no_cmake_environment_path})
+ if(${_imp_target})
+ _pkg_create_imp_target(${_prefix})
+ endif()
+endmacro()
+
###
macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _prefix)
_pkgconfig_unset(${_prefix}_FOUND)
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS "" --cflags )
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER "" --cflags-only-other )
- if (_imp_target)
- _pkg_create_imp_target("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path})
- endif()
+ _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target})
endif()
if(NOT "${_extra_paths}" STREQUAL "")
<XXX>_FOUND ... set to 1 if module(s) exist
<XXX>_LIBRARIES ... only the libraries (without the '-l')
+ <XXX>_LINK_LIBRARIES ... the libraries and their absolute paths
<XXX>_LIBRARY_DIRS ... the paths of the libraries (without the '-L')
<XXX>_LDFLAGS ... all required linker flags
<XXX>_LDFLAGS_OTHER ... all other linker flags
if (${_prefix}_FOUND)
_pkgconfig_set(__pkg_config_arguments_${_prefix} "${_module0};${ARGN}")
endif()
- elseif (${_prefix}_FOUND AND ${_imp_target})
- _pkg_create_imp_target("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path})
+ else()
+ if (${_prefix}_FOUND)
+ _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target})
+ endif()
endif()
endmacro()
endif()
_pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
- elseif (${_prefix}_FOUND AND ${_imp_target})
- _pkg_create_imp_target("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path})
+ elseif (${_prefix}_FOUND)
+ _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target})
endif()
endmacro()
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindPython
+----------
+
+Find Python interpreter, compiler and development environment (include
+directories and libraries).
+
+Three components are supported:
+
+* ``Interpreter``: search for Python interpreter.
+* ``Compiler``: search for Python compiler. Only offered by IronPython.
+* ``Development``: search for development artifacts (include directories and
+ libraries).
+
+If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed.
+
+To ensure consistent versions between components ``Interpreter``, ``Compiler``
+and ``Development``, specify all components at the same time::
+
+ find_package (Python COMPONENTS Interpreter Development)
+
+This module looks preferably for version 3 of Python. If not found, version 2
+is searched.
+To manage concurrent versions 3 and 2 of Python, use :module:`FindPython3` and
+:module:`FindPython2` modules rather than this one.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+``Python::Interpreter``
+ Python interpreter. Target defined if component ``Interpreter`` is found.
+``Python::Compiler``
+ Python compiler. Target defined if component ``Compiler`` is found.
+``Python::Python``
+ Python library. Target defined if component ``Development`` is found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module will set the following variables in your project
+(see :ref:`Standard Variable Names <CMake Developer Standard Variable Names>`):
+
+``Python_FOUND``
+ System has the Python requested components.
+``Python_Interpreter_FOUND``
+ System has the Python interpreter.
+``Python_EXECUTABLE``
+ Path to the Python interpreter.
+``Python_INTERPRETER_ID``
+ A short string unique to the interpreter. Possible values include:
+ * Python
+ * ActivePython
+ * Anaconda
+ * Canopy
+ * IronPython
+``Python_STDLIB``
+ Standard platform independent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)``.
+``Python_STDARCH``
+ Standard platform dependent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)``.
+``Python_SITELIB``
+ Third-party platform independent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)``.
+``Python_SITEARCH``
+ Third-party platform dependent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``.
+``Python_Compiler_FOUND``
+ System has the Python compiler.
+``Python_COMPILER``
+ Path to the Python compiler. Only offered by IronPython.
+``Python_COMPILER_ID``
+ A short string unique to the compiler. Possible values include:
+ * IronPython
+``Python_Development_FOUND``
+ System has the Python development artifacts.
+``Python_INCLUDE_DIRS``
+ The Python include directories.
+``Python_LIBRARIES``
+ The Python libraries.
+``Python_LIBRARY_DIRS``
+ The Python library directories.
+``Python_RUNTIME_LIBRARY_DIRS``
+ The Python runtime library directories.
+``Python_VERSION``
+ Python version.
+``Python_VERSION_MAJOR``
+ Python major version.
+``Python_VERSION_MINOR``
+ Python minor version.
+``Python_VERSION_PATCH``
+ Python patch version.
+
+Hints
+^^^^^
+
+``Python_ROOT_DIR``
+ Define the root directory of a Python installation.
+
+``Python_USE_STATIC_LIBS``
+ * If not defined, search for shared libraries and static libraries in that
+ order.
+ * If set to TRUE, search **only** for static libraries.
+ * If set to FALSE, search **only** for shared libraries.
+
+Commands
+^^^^^^^^
+
+This module defines the command ``Python_add_library`` which have the same
+semantic as :command:`add_library` but take care of Python module naming rules
+(only applied if library is of type ``MODULE``) and add dependency to target
+``Python::Python``::
+
+ Python_add_library (my_module MODULE src1.cpp)
+
+If library type is not specified, ``MODULE`` is assumed.
+#]=======================================================================]
+
+
+set (_PYTHON_PREFIX Python)
+
+if (DEFINED Python_FIND_VERSION)
+ set (_Python_REQUIRED_VERSION_MAJOR ${Python_FIND_VERSION_MAJOR})
+
+ include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake)
+else()
+ # iterate over versions in quiet and NOT required modes to avoid multiple
+ # "Found" messages and prematurally failure.
+ set (_Python_QUIETLY ${Python_FIND_QUIETLY})
+ set (_Python_REQUIRED ${Python_FIND_REQUIRED})
+ set (Python_FIND_QUIETLY TRUE)
+ set (Python_FIND_REQUIRED FALSE)
+
+ set (_Python_REQUIRED_VERSIONS 3 2)
+ set (_Python_REQUIRED_VERSION_LAST 2)
+
+ foreach (_Python_REQUIRED_VERSION_MAJOR IN LISTS _Python_REQUIRED_VERSIONS)
+ set (Python_FIND_VERSION ${_Python_REQUIRED_VERSION_MAJOR})
+ include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake)
+ if (Python_FOUND OR
+ _Python_REQUIRED_VERSION_MAJOR EQUAL _Python_REQUIRED_VERSION_LAST)
+ break()
+ endif()
+ # clean-up some CACHE variables to ensure look-up restart from scratch
+ foreach (_Python_ITEM IN LISTS _Python_CACHED_VARS)
+ unset (${_Python_ITEM} CACHE)
+ endforeach()
+ endforeach()
+
+ unset (Python_FIND_VERSION)
+
+ set (Python_FIND_QUIETLY ${_Python_QUIETLY})
+ set (Python_FIND_REQUIRED ${_Python_REQUIRED})
+ if (Python_FIND_REQUIRED OR NOT Python_FIND_QUIETLY)
+ # call again validation command to get "Found" or error message
+ find_package_handle_standard_args (Python HANDLE_COMPONENTS
+ REQUIRED_VARS ${_Python_REQUIRED_VARS}
+ VERSION_VAR Python_VERSION)
+ endif()
+endif()
+
+if (COMMAND __Python_add_library)
+ macro (Python_add_library)
+ __Python_add_library (Python ${ARGV})
+ endmacro()
+endif()
+
+unset (_PYTHON_PREFIX)
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#
+# This file is a "template" file used by various FindPython modules.
+#
+
+cmake_policy (VERSION 3.7)
+
+#
+# Initial configuration
+#
+if (NOT DEFINED _PYTHON_PREFIX)
+ message (FATAL_ERROR "FindPython: INTERNAL ERROR")
+endif()
+if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+ message (FATAL_ERROR "FindPython: INTERNAL ERROR")
+endif()
+if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 3)
+ set(_${_PYTHON_PREFIX}_VERSIONS 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 2)
+ set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
+else()
+ message (FATAL_ERROR "FindPython: INTERNAL ERROR")
+endif()
+
+
+#
+# helper commands
+#
+macro (_PYTHON_DISPLAY_FAILURE _PYTHON_MSG)
+ if (${_PYTHON_PREFIX}_FIND_REQUIRED)
+ message (FATAL_ERROR "${_PYTHON_MSG}")
+ else()
+ if (NOT ${_PYTHON_PREFIX}_FIND_QUIETLY)
+ message(STATUS "${_PYTHON_MSG}")
+ endif ()
+ endif()
+
+ set (${_PYTHON_PREFIX}_FOUND FALSE)
+ string (TOUPPER "${_PYTHON_PREFIX}" _${_PYTHON_PREFIX}_UPPER_PREFIX)
+ set (${_PYTHON_UPPER_PREFIX}_FOUND FALSE)
+ return()
+endmacro()
+
+
+function (_PYTHON_GET_FRAMEWORKS _PYTHON_PGF_FRAMEWORK_PATHS _PYTHON_VERSION)
+ set (_PYTHON_FRAMEWORK_PATHS)
+ foreach (_PYTHON_FRAMEWORK IN LISTS Python_FRAMEWORKS)
+ list (APPEND _PYTHON_FRAMEWORK_PATHS
+ "${_PYTHON_FRAMEWORK}/Versions/${_PYTHON_VERSION}")
+ endforeach()
+ set (${_PYTHON_PGF_FRAMEWORK_PATHS} ${_PYTHON_FRAMEWORK_PATHS} PARENT_SCOPE)
+endfunction()
+
+
+function (_PYTHON_VALIDATE_INTERPRETER)
+ if (NOT ${_PYTHON_PREFIX}_EXECUTABLE)
+ return()
+ endif()
+
+ if (${_PYTHON_PREFIX}_EXECUTABLE MATCHES "python${CMAKE_EXECUTABLE_SUFFIX}$")
+ # executable found do not have version in name
+ # ensure major version is OK
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+ "import sys; sys.stdout.write(str(sys.version_info[0]))"
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE version
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+ # interpreter not usable or has wrong major version
+ set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
+ return()
+ endif()
+ endif()
+
+ if (CMAKE_SIZEOF_VOID_P AND "Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+ AND NOT CMAKE_CROSSCOMPILING)
+ # In this case, interpreter must have same architecture as environment
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+ "import sys, struct; sys.stdout.write(str(struct.calcsize(\"P\")))"
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE size
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P)
+ # interpreter not usable or has wrong architecture
+ set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
+ return()
+ endif()
+ endif()
+endfunction()
+
+
+function (_PYTHON_FIND_RUNTIME_LIBRARY _PYTHON_LIB)
+ string (REPLACE "_RUNTIME" "" _PYTHON_LIB "${_PYTHON_LIB}")
+ # look at runtime part on systems supporting it
+ if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR
+ (CMAKE_SYSTEM_NAME MATCHES "MSYS|CYGWIN"
+ AND ${_PYTHON_LIB} MATCHES "${CMAKE_IMPORT_LIBRARY_SUFFIX}$"))
+ set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})
+ # MSYS has a special syntax for runtime libraries
+ if (CMAKE_SYSTEM_NAME MATCHES "MSYS")
+ list (APPEND CMAKE_FIND_LIBRARY_PREFIXES "msys-")
+ endif()
+ find_library (${ARGV})
+ endif()
+endfunction()
+
+
+function (_PYTHON_SET_LIBRARY_DIRS _PYTHON_SLD_RESULT)
+ unset (_PYTHON_DIRS)
+ set (_PYTHON_LIBS ${ARGV})
+ list (REMOVE_AT _PYTHON_LIBS 0)
+ foreach (_PYTHON_LIB IN LISTS _PYTHON_LIBS)
+ if (${_PYTHON_LIB})
+ get_filename_component (_PYTHON_DIR "${${_PYTHON_LIB}}" DIRECTORY)
+ list (APPEND _PYTHON_DIRS "${_PYTHON_DIR}")
+ endif()
+ endforeach()
+ if (_PYTHON_DIRS)
+ list (REMOVE_DUPLICATES _PYTHON_DIRS)
+ endif()
+ set (${_PYTHON_SLD_RESULT} ${_PYTHON_DIRS} PARENT_SCOPE)
+endfunction()
+
+
+# If major version is specified, it must be the same as internal major version
+if (DEFINED ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR
+ AND NOT ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+ _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Wrong major version specified is \"${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}\", but expected major version is \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"")
+endif()
+
+
+# handle components
+if (NOT ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+ set (${_PYTHON_PREFIX}_FIND_COMPONENTS Interpreter)
+ set (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter TRUE)
+endif()
+foreach (_${_PYTHON_PREFIX}_COMPONENT IN LISTS ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+ set (${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_FOUND FALSE)
+endforeach()
+unset (_${_PYTHON_PREFIX}_FIND_VERSIONS)
+
+# Set versions to search
+## default: search any version
+set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSIONS})
+
+if (${_PYTHON_PREFIX}_FIND_VERSION_COUNT GREATER 1)
+ if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT)
+ set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}.${${_PYTHON_PREFIX}_FIND_VERSION_MINOR})
+ else()
+ unset (_${_PYTHON_PREFIX}_FIND_VERSIONS)
+ # add all compatible versions
+ foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_VERSIONS)
+ if (_${_PYTHON_PREFIX}_VERSION VERSION_GREATER_EQUAL ${_PYTHON_PREFIX}_FIND_VERSION)
+ list (APPEND _${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSION})
+ endif()
+ endforeach()
+ endif()
+endif()
+
+# Anaconda distribution: define which architectures can be used
+if (CMAKE_SIZEOF_VOID_P)
+ # In this case, search only for 64bit or 32bit
+ math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
+ set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH})
+else()
+ # architecture unknown, search for both 64bit and 32bit
+ set (_${_PYTHON_PREFIX}_ARCH 64)
+ set (_${_PYTHON_PREFIX}_ARCH2 32)
+endif()
+
+# IronPython support
+if (CMAKE_SIZEOF_VOID_P)
+ # In this case, search only for 64bit or 32bit
+ math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
+ set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy${_${_PYTHON_PREFIX}_ARCH} ipy)
+else()
+ # architecture unknown, search for natural interpreter
+ set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy)
+endif()
+
+# Apple frameworks handling
+include (${CMAKE_CURRENT_LIST_DIR}/../CMakeFindFrameworks.cmake)
+cmake_find_frameworks (Python)
+
+# Save CMAKE_FIND_FRAMEWORK
+if (DEFINED CMAKE_FIND_FRAMEWORK)
+ set (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
+else()
+ unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
+endif()
+# To avoid picking up the system elements pre-maturely.
+set (CMAKE_FIND_FRAMEWORK LAST)
+
+
+unset (${_PYTHON_PREFIX}_VERSION_MAJOR)
+unset (${_PYTHON_PREFIX}_VERSION_MINOR)
+unset (${_PYTHON_PREFIX}_VERSION_PATCH)
+
+unset (_${_PYTHON_PREFIX}_REQUIRED_VARS)
+unset (_${_PYTHON_PREFIX}_CACHED_VARS)
+
+
+# first step, search for the interpreter
+if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+ if (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter)
+ list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_EXECUTABLE)
+ list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_EXECUTABLE)
+ endif()
+
+ set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
+
+ # look-up for various versions and locations
+ foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
+ string (REPLACE "." "" _${_PYTHON_PREFIX}_VERSION_NO_DOTS ${_${_PYTHON_PREFIX}_VERSION})
+
+ _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
+
+ # try using HINTS
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION}
+ NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ PATH_SUFFIXES bin
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ # try using registry
+ if (WIN32)
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION} python
+ ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+ NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ PATH_SUFFIXES bin
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+ # try in standard paths
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION})
+
+ _python_validate_interpreter ()
+ if (${_PYTHON_PREFIX}_EXECUTABLE)
+ break()
+ endif()
+ endforeach()
+
+ # try more generic names
+ if (NOT ${_PYTHON_PREFIX}_EXECUTABLE)
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${${_PYTHON_PREFIX}_VERSION_MAJOR} python
+ ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATH_SUFFIXES bin)
+
+ _python_validate_interpreter ()
+ endif()
+
+ # retrieve exact version of executable found
+ if (${_PYTHON_PREFIX}_EXECUTABLE)
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+ "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))"
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE ${_PYTHON_PREFIX}_VERSION
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (NOT _${_PYTHON_PREFIX}_RESULT)
+ string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${${_PYTHON_PREFIX}_VERSION}")
+ list (GET _${_PYTHON_PREFIX}_VERSIONS 0 ${_PYTHON_PREFIX}_VERSION_MAJOR)
+ list (GET _${_PYTHON_PREFIX}_VERSIONS 1 ${_PYTHON_PREFIX}_VERSION_MINOR)
+ list (GET _${_PYTHON_PREFIX}_VERSIONS 2 ${_PYTHON_PREFIX}_VERSION_PATCH)
+ else()
+ # Interpreter is not usable
+ set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
+ unset (${_PYTHON_PREFIX}_VERSION)
+ endif()
+ endif()
+
+ if (${_PYTHON_PREFIX}_EXECUTABLE
+ AND ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+ set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE)
+ # Use interpreter version for future searches to ensure consistency
+ set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
+ endif()
+
+ if (${_PYTHON_PREFIX}_Interpreter_FOUND)
+ # retrieve interpreter identity
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -V
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID
+ ERROR_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID)
+ if (NOT _${_PYTHON_PREFIX}_RESULT)
+ if (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Anaconda")
+ set (${_PYTHON_PREFIX}_INTERPRETER_ID "Anaconda")
+ elseif (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Enthought")
+ set (${_PYTHON_PREFIX}_INTERPRETER_ID "Canopy")
+ else()
+ string (REGEX REPLACE "^([^ ]+).*" "\\1" ${_PYTHON_PREFIX}_INTERPRETER_ID "${${_PYTHON_PREFIX}_INTERPRETER_ID}")
+ if (${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "Python")
+ # try to get a more precise ID
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.copyright)"
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE ${_PYTHON_PREFIX}_COPYRIGHT
+ ERROR_QUIET)
+ if (${_PYTHON_PREFIX}_COPYRIGHT MATCHES "ActiveState")
+ set (${_PYTHON_PREFIX}_INTERPRETER_ID "ActivePython")
+ endif()
+ endif()
+ endif()
+ else()
+ set (${_PYTHON_PREFIX}_INTERPRETER_ID Python)
+ endif()
+ else()
+ unset (${_PYTHON_PREFIX}_INTERPRETER_ID)
+ endif()
+
+ # retrieve various package installation directories
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig;sys.stdout.write(';'.join([sysconfig.get_python_lib(plat_specific=False,standard_lib=True),sysconfig.get_python_lib(plat_specific=True,standard_lib=True),sysconfig.get_python_lib(plat_specific=False,standard_lib=False),sysconfig.get_python_lib(plat_specific=True,standard_lib=False)]))"
+
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE _${_PYTHON_PREFIX}_LIBPATHS
+ ERROR_QUIET)
+ if (NOT _${_PYTHON_PREFIX}_RESULT)
+ list (GET _${_PYTHON_PREFIX}_LIBPATHS 0 ${_PYTHON_PREFIX}_STDLIB)
+ list (GET _${_PYTHON_PREFIX}_LIBPATHS 1 ${_PYTHON_PREFIX}_STDARCH)
+ list (GET _${_PYTHON_PREFIX}_LIBPATHS 2 ${_PYTHON_PREFIX}_SITELIB)
+ list (GET _${_PYTHON_PREFIX}_LIBPATHS 3 ${_PYTHON_PREFIX}_SITEARCH)
+ else()
+ unset (${_PYTHON_PREFIX}_STDLIB)
+ unset (${_PYTHON_PREFIX}_STDARCH)
+ unset (${_PYTHON_PREFIX}_SITELIB)
+ unset (${_PYTHON_PREFIX}_SITEARCH)
+ endif()
+
+ mark_as_advanced (${_PYTHON_PREFIX}_EXECUTABLE)
+endif()
+
+
+# second step, search for compiler (IronPython)
+if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+ if (${_PYTHON_PREFIX}_FIND_REQUIRED_Compiler)
+ list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_COMPILER)
+ list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_COMPILER)
+ endif()
+
+ # IronPython specific artifacts
+ # If IronPython interpreter is found, use its path
+ unset (_${_PYTHON_PREFIX}_IRON_ROOT)
+ if (${_PYTHON_PREFIX}_Interpreter_FOUND AND ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython")
+ get_filename_component (_${_PYTHON_PREFIX}_IRON_ROOT "${${_PYTHON_PREFIX}_EXECUTABLE}" DIRECTORY)
+ endif()
+
+ # try using root dir and registry
+ foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
+ find_program (${_PYTHON_PREFIX}_COMPILER
+ NAMES ipyc
+ HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ if (${_PYTHON_PREFIX}_COMPILER)
+ break()
+ endif()
+ endforeach()
+ # try in standard paths
+ find_program (${_PYTHON_PREFIX}_COMPILER
+ NAMES ipyc)
+
+ if (${_PYTHON_PREFIX}_COMPILER)
+ # retrieve python environment version from compiler
+ set (_${_PYTHON_PREFIX}_VERSION_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir")
+ file (WRITE "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))\n")
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py"
+ WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}"
+ OUTPUT_QUIET
+ ERROR_QUIET)
+ execute_process (COMMAND "${_${_PYTHON_PREFIX}_VERSION_DIR}/version"
+ WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}"
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE _${_PYTHON_PREFIX}_VERSION
+ ERROR_QUIET)
+ if (NOT _${_PYTHON_PREFIX}_RESULT)
+ string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${_${_PYTHON_PREFIX}_VERSION}")
+ list (GET _${_PYTHON_PREFIX}_VERSIONS 0 _${_PYTHON_PREFIX}_VERSION_MAJOR)
+ list (GET _${_PYTHON_PREFIX}_VERSIONS 1 _${_PYTHON_PREFIX}_VERSION_MINOR)
+ list (GET _${_PYTHON_PREFIX}_VERSIONS 2 _${_PYTHON_PREFIX}_VERSION_PATCH)
+
+ if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND)
+ # set public version information
+ set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION})
+ set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR})
+ set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR})
+ set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH})
+ endif()
+ else()
+ # compiler not usable
+ set (${_PYTHON_PREFIX}_COMPILER ${_PYTHON_PREFIX}_COMPILER-NOTFOUND CACHE INTERNAL "" FORCE)
+ endif()
+ file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}")
+ endif()
+
+ if (${_PYTHON_PREFIX}_COMPILER)
+ if (${_PYTHON_PREFIX}_Interpreter_FOUND)
+ # Compiler must be compatible with interpreter
+ if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
+ set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE)
+ endif()
+ elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+ set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE)
+ # Use compiler version for future searches to ensure consistency
+ set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
+ endif()
+ endif()
+
+ if (${_PYTHON_PREFIX}_Compiler_FOUND)
+ set (${_PYTHON_PREFIX}_COMPILER_ID IronPython)
+ else()
+ unset (${_PYTHON_PREFIX}_COMPILER_ID)
+ endif()
+
+ mark_as_advanced (${_PYTHON_PREFIX}_COMPILER)
+endif()
+
+
+# third step, search for the development artifacts
+## Development environment is not compatible with IronPython interpreter
+if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+ AND NOT ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython")
+ if (${_PYTHON_PREFIX}_FIND_REQUIRED_Development)
+ list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_LIBRARY
+ ${_PYTHON_PREFIX}_INCLUDE_DIR)
+ list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_LIBRARY
+ ${_PYTHON_PREFIX}_LIBRARY_RELEASE
+ ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
+ ${_PYTHON_PREFIX}_LIBRARY_DEBUG
+ ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG
+ ${_PYTHON_PREFIX}_INCLUDE_DIR)
+ endif()
+
+ # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
+ unset (_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES)
+ if (DEFINED ${_PYTHON_PREFIX}_USE_STATIC_LIBS AND NOT WIN32)
+ set(_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ if(${_PYTHON_PREFIX}_USE_STATIC_LIBS)
+ set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
+ else()
+ list (REMOVE_ITEM CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
+ endif()
+ else()
+ endif()
+
+ # if python interpreter is found, use its location and version to ensure consistency
+ # between interpreter and development environment
+ unset (_${_PYTHON_PREFIX}_PREFIX)
+ if (${_PYTHON_PREFIX}_Interpreter_FOUND)
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+ "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.PREFIX)"
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PREFIX
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (_${_PYTHON_PREFIX}_RESULT)
+ unset (_${_PYTHON_PREFIX}_PREFIX)
+ endif()
+ endif()
+ set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
+
+ foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
+ string (REPLACE "." "" _${_PYTHON_PREFIX}_VERSION_NO_DOTS ${_${_PYTHON_PREFIX}_VERSION})
+
+ # try to use pythonX.Y-config tool
+ set (_${_PYTHON_PREFIX}_CONFIG_NAMES)
+ if (DEFINED CMAKE_LIBRARY_ARCHITECTURE)
+ set (_${_PYTHON_PREFIX}_CONFIG_NAMES "${CMAKE_LIBRARY_ARCHITECTURE}-python${_${_PYTHON_PREFIX}_VERSION}-config")
+ endif()
+ list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES "python${_${_PYTHON_PREFIX}_VERSION}-config")
+ find_program (_${_PYTHON_PREFIX}_CONFIG
+ NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES}
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATH_SUFFIXES bin)
+ unset (_${_PYTHON_PREFIX}_CONFIG_NAMES)
+
+ if (NOT _${_PYTHON_PREFIX}_CONFIG)
+ continue()
+ endif()
+
+ # retrieve root install directory
+ execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --prefix
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PREFIX
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (_${_PYTHON_PREFIX}_RESULT)
+ # python-config is not usable
+ unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
+ continue()
+ endif()
+ set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
+
+ # retrieve library
+ execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (NOT _${_PYTHON_PREFIX}_RESULT)
+ # retrieve library directory
+ string (REGEX MATCHALL "-L[^ ]+" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_FLAGS}")
+ string (REPLACE "-L" "" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_LIB_DIRS}")
+ list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_DIRS)
+ # retrieve library name
+ string (REGEX MATCHALL "-lpython[^ ]+" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_FLAGS}")
+ string (REPLACE "-l" "" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_LIB_NAMES}")
+ list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_NAMES)
+
+ find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
+ NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
+ NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_HINTS} ${_${_PYTHON_PREFIX}_LIB_DIRS}
+ PATH_SUFFIXES lib
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ # retrieve runtime library
+ if (${_PYTHON_PREFIX}_LIBRARY_RELEASE)
+ get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
+ _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
+ NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
+ NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_PATH} ${_${_PYTHON_PREFIX}_HINTS}
+ PATH_SUFFIXES bin
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+ endif()
+
+ # retrieve include directory
+ execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --includes
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (NOT _${_PYTHON_PREFIX}_RESULT)
+ # retrieve include directory
+ string (REGEX MATCHALL "-I[^ ]+" _${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_FLAGS}")
+ string (REPLACE "-I" "" _${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIRS}")
+ list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_INCLUDE_DIRS)
+
+ find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
+ NAMES Python.h
+ HINTS ${_${_PYTHON_PREFIX}_INCLUDE_DIRS}
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+
+ if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_INCLUDE_DIR)
+ break()
+ endif()
+ endforeach()
+
+ # Rely on HINTS and standard paths if config tool failed to locate artifacts
+ if (NOT (${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG) OR NOT ${_PYTHON_PREFIX}_INCLUDE_DIR)
+ foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
+ string (REPLACE "." "" _${_PYTHON_PREFIX}_VERSION_NO_DOTS ${_${_PYTHON_PREFIX}_VERSION})
+
+ _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
+
+ # search first in known locations
+ find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}
+ python${_${_PYTHON_PREFIX}_VERSION}mu
+ python${_${_PYTHON_PREFIX}_VERSION}m
+ python${_${_PYTHON_PREFIX}_VERSION}u
+ python${_${_PYTHON_PREFIX}_VERSION}
+ NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}u
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ # search in all default paths
+ find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}
+ python${_${_PYTHON_PREFIX}_VERSION}mu
+ python${_${_PYTHON_PREFIX}_VERSION}m
+ python${_${_PYTHON_PREFIX}_VERSION}u
+ python${_${_PYTHON_PREFIX}_VERSION}
+ NAMES_PER_DIR
+ PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}u
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config)
+ # retrieve runtime library
+ if (${_PYTHON_PREFIX}_LIBRARY_RELEASE)
+ get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
+ _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}
+ python${_${_PYTHON_PREFIX}_VERSION}mu
+ python${_${_PYTHON_PREFIX}_VERSION}m
+ python${_${_PYTHON_PREFIX}_VERSION}u
+ python${_${_PYTHON_PREFIX}_VERSION}
+ NAMES_PER_DIR
+ HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ PATH_SUFFIXES bin)
+ endif()
+
+ if (WIN32)
+ # search for debug library
+ if (${_PYTHON_PREFIX}_LIBRARY_RELEASE)
+ # use library location as a hint
+ get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
+ find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
+ NAMES_PER_DIR
+ HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
+ NO_DEFAULT_PATH)
+ else()
+ # search first in known locations
+ find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
+ NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ PATH_SUFFIXES lib libs
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ # search in all default paths
+ find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
+ NAMES_PER_DIR
+ PATH_SUFFIXES lib libs)
+ endif()
+ if (${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+ get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}" DIRECTORY)
+ _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
+ NAMES_PER_DIR
+ HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ PATH_SUFFIXES bin)
+ endif()
+ endif()
+
+ # Don't search for include dir until library location is known
+ if (${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+ unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS)
+ foreach (_${_PYTHON_PREFIX}_LIB IN ITEMS ${_PYTHON_PREFIX}_LIBRARY_RELEASE ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+ if (${_${_PYTHON_PREFIX}_LIB})
+ # Use the library's install prefix as a hint
+ if (${_${_PYTHON_PREFIX}_LIB} MATCHES "^(.+/Frameworks/Python.framework/Versions/[0-9.]+)")
+ list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}")
+ elseif (${_${_PYTHON_PREFIX}_LIB} MATCHES "^(.+)/lib(64|32)?/python[0-9.]+/config")
+ list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}")
+ elseif (DEFINED CMAKE_LIBRARY_ARCHITECTURE AND ${_${_PYTHON_PREFIX}_LIB} MATCHES "^(.+)/lib/${CMAKE_LIBRARY_ARCHITECTURE}")
+ list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}")
+ else()
+ # assume library is in a directory under root
+ get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${${_${_PYTHON_PREFIX}_LIB}}" DIRECTORY)
+ get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${_${_PYTHON_PREFIX}_PREFIX}" DIRECTORY)
+ list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${_${_PYTHON_PREFIX}_PREFIX}")
+ endif()
+ endif()
+ endforeach()
+ list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_INCLUDE_HINTS)
+
+ find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
+ NAMES Python.h
+ HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ PATH_SUFFIXES include/python${_${_PYTHON_PREFIX}_VERSION}mu
+ include/python${_${_PYTHON_PREFIX}_VERSION}m
+ include/python${_${_PYTHON_PREFIX}_VERSION}u
+ include/python${_${_PYTHON_PREFIX}_VERSION}
+ include
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+
+ if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG) AND ${_PYTHON_PREFIX}_INCLUDE_DIR)
+ break()
+ endif()
+ endforeach()
+
+ # search header file in standard locations
+ find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
+ NAMES Python.h)
+ endif()
+
+ if (${_PYTHON_PREFIX}_INCLUDE_DIR)
+ # retrieve version from header file
+ file (STRINGS "${${_PYTHON_PREFIX}_INCLUDE_DIR}/patchlevel.h" _${_PYTHON_PREFIX}_VERSION
+ REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"")
+ string (REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1"
+ _${_PYTHON_PREFIX}_VERSION "${_${_PYTHON_PREFIX}_VERSION}")
+ string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${_${_PYTHON_PREFIX}_VERSION}")
+ list (GET _${_PYTHON_PREFIX}_VERSIONS 0 _${_PYTHON_PREFIX}_VERSION_MAJOR)
+ list (GET _${_PYTHON_PREFIX}_VERSIONS 1 _${_PYTHON_PREFIX}_VERSION_MINOR)
+ list (GET _${_PYTHON_PREFIX}_VERSIONS 2 _${_PYTHON_PREFIX}_VERSION_PATCH)
+
+ if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT ${_PYTHON_PREFIX}_Compiler_FOUND)
+ # set public version information
+ set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION})
+ set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR})
+ set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR})
+ set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH})
+ endif()
+ endif()
+
+ # define public variables
+ include (${CMAKE_CURRENT_LIST_DIR}/../SelectLibraryConfigurations.cmake)
+ select_library_configurations (${_PYTHON_PREFIX})
+ if (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE)
+ set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}")
+ elseif (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
+ set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}")
+ else()
+ set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "$${_PYTHON_PREFIX}_RUNTIME_LIBRARY-NOTFOUND")
+ endif()
+
+ _python_set_library_dirs (${_PYTHON_PREFIX}_LIBRARY_DIRS
+ ${_PYTHON_PREFIX}_LIBRARY_RELEASE ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+ if (UNIX)
+ if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
+ OR ${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$")
+ set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS ${${_PYTHON_PREFIX}_LIBRARY_DIRS})
+ endif()
+ else()
+ _python_set_library_dirs (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS
+ ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
+ endif()
+
+ set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${${_PYTHON_PREFIX}_INCLUDE_DIR}")
+
+ mark_as_advanced (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
+ ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG
+ ${_PYTHON_PREFIX}_INCLUDE_DIR)
+
+ if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+ AND ${_PYTHON_PREFIX}_INCLUDE_DIR)
+ if (${_PYTHON_PREFIX}_Interpreter_FOUND OR ${_PYTHON_PREFIX}_Compiler_FOUND)
+ # development environment must be compatible with interpreter/compiler
+ if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
+ set (${_PYTHON_PREFIX}_Development_FOUND TRUE)
+ endif()
+ elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+ set (${_PYTHON_PREFIX}_Development_FOUND TRUE)
+ endif()
+ endif()
+
+ # Restore the original find library ordering
+ if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES)
+ set (CMAKE_FIND_LIBRARY_SUFFIXES ${_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES})
+ endif()
+endif()
+
+# final validation
+if (${_PYTHON_PREFIX}_VERSION_MAJOR AND
+ NOT ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+ _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Found unsuitable major version \"${${_PYTHON_PREFIX}_VERSION_MAJOR}\", but required major version is exact version \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"")
+endif()
+
+include (${CMAKE_CURRENT_LIST_DIR}/../FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args (${_PYTHON_PREFIX}
+ REQUIRED_VARS ${_${_PYTHON_PREFIX}_REQUIRED_VARS}
+ VERSION_VAR ${_PYTHON_PREFIX}_VERSION
+ HANDLE_COMPONENTS)
+
+# Create imported targets and helper functions
+if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+ AND ${_PYTHON_PREFIX}_Interpreter_FOUND
+ AND NOT TARGET ${_PYTHON_PREFIX}::Interpreter)
+ add_executable (${_PYTHON_PREFIX}::Interpreter IMPORTED)
+ set_property (TARGET ${_PYTHON_PREFIX}::Interpreter
+ PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_EXECUTABLE}")
+endif()
+
+if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+ AND ${_PYTHON_PREFIX}_Compiler_FOUND
+ AND NOT TARGET ${_PYTHON_PREFIX}::Compiler)
+ add_executable (${_PYTHON_PREFIX}::Compiler IMPORTED)
+ set_property (TARGET ${_PYTHON_PREFIX}::Compiler
+ PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_COMPILER}")
+endif()
+
+if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+ AND ${_PYTHON_PREFIX}_Development_FOUND AND NOT TARGET ${_PYTHON_PREFIX}::Python)
+
+ if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
+ OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
+ OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
+ set (_${_PYTHON_PREFIX}_LIBRARY_TYPE SHARED)
+ else()
+ set (_${_PYTHON_PREFIX}_LIBRARY_TYPE STATIC)
+ endif()
+
+ add_library (${_PYTHON_PREFIX}::Python ${_${_PYTHON_PREFIX}_LIBRARY_TYPE} IMPORTED)
+
+ set_property (TARGET ${_PYTHON_PREFIX}::Python
+ PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIR}")
+
+ if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE)
+ OR (${_PYTHON_PREFIX}_LIBRARY_DEBUG AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG))
+ # System manage shared libraries in two parts: import and runtime
+ if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+ set_property (TARGET ${_PYTHON_PREFIX}::Python PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
+ set_target_properties (${_PYTHON_PREFIX}::Python
+ PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+ IMPORTED_IMPLIB_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}"
+ IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}")
+ set_target_properties (${_PYTHON_PREFIX}::Python
+ PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+ IMPORTED_IMPLIB_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}"
+ IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}")
+ else()
+ set_target_properties (${_PYTHON_PREFIX}::Python
+ PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_IMPLIB "${${_PYTHON_PREFIX}_LIBRARY}"
+ IMPORTED_LOCATION "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY}")
+ endif()
+ else()
+ if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+ set_property (TARGET ${_PYTHON_PREFIX}::Python PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
+ set_target_properties (${_PYTHON_PREFIX}::Python
+ PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+ IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
+ set_target_properties (${_PYTHON_PREFIX}::Python
+ PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+ IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}")
+ else()
+ set_target_properties (${_PYTHON_PREFIX}::Python
+ PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_LOCATION "${${_PYTHON_PREFIX}_LIBRARY}")
+ endif()
+ endif()
+
+ if (_${_PYTHON_PREFIX}_CONFIG AND _${_PYTHON_PREFIX}_LIBRARY_TYPE STREQUAL "STATIC")
+ # extend link information with dependent libraries
+ execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (NOT _${_PYTHON_PREFIX}_RESULT)
+ string (REGEX MATCHALL "-[Ll][^ ]+" _${_PYTHON_PREFIX}_LINK_LIBRARIES "${_${_PYTHON_PREFIX}_FLAGS}")
+ # remove elements relative to python library itself
+ list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-lpython")
+ foreach (_${_PYTHON_PREFIX}_DIR IN LISTS ${_PYTHON_PREFIX}_LIBRARY_DIRS)
+ list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-L${${_PYTHON_PREFIX}_DIR}")
+ endforeach()
+ set_property (TARGET ${_PYTHON_PREFIX}::Python
+ PROPERTY INTERFACE_LINK_LIBRARIES ${_${_PYTHON_PREFIX}_LINK_LIBRARIES})
+ endif()
+ endif()
+
+ #
+ # PYTHON_ADD_LIBRARY (<name> [STATIC|SHARED|MODULE] src1 src2 ... srcN)
+ # It is used to build modules for python.
+ #
+ function (__${_PYTHON_PREFIX}_ADD_LIBRARY prefix name)
+ cmake_parse_arguments (PARSE_ARGV 2 PYTHON_ADD_LIBRARY
+ "STATIC;SHARED;MODULE" "" "")
+
+ unset (type)
+ if (NOT (PYTHON_ADD_LIBRARY_STATIC
+ OR PYTHON_ADD_LIBRARY_SHARED
+ OR PYTHON_ADD_LIBRARY_MODULE))
+ set (type MODULE)
+ endif()
+ add_library (${name} ${type} ${ARGN})
+ target_link_libraries (${name} PRIVATE ${prefix}::Python)
+
+ # customize library name to follow module name rules
+ get_property (type TARGET ${name} PROPERTY TYPE)
+ if (type STREQUAL "MODULE_LIBRARY")
+ set_property (TARGET ${name} PROPERTY PREFIX "")
+ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ set_property (TARGET ${name} PROPERTY SUFFIX ".pyd")
+ endif()
+ endif()
+ endfunction()
+endif()
+
+# final clean-up
+
+# Restore CMAKE_FIND_FRAMEWORK
+if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
+ set (CMAKE_FIND_FRAMEWORK ${_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK})
+ unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
+else()
+ unset (CMAKE_FIND_FRAMEWORK)
+endif()
+
+unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindPython2
+-----------
+
+Find Python 2 interpreter, compiler and development environment (include
+directories and libraries).
+
+Three components are supported:
+
+* ``Interpreter``: search for Python 2 interpreter
+* ``Compiler``: search for Python 2 compiler. Only offered by IronPython.
+* ``Development``: search for development artifacts (include directories and
+ libraries)
+
+If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed.
+
+To ensure consistent versions between components ``Interpreter``, ``Compiler``
+and ``Development``, specify all components at the same time::
+
+ find_package (Python2 COMPONENTS Interpreter Development)
+
+This module looks only for version 2 of Python. This module can be used
+concurrently with :module:`FindPython3` module to use both Python versions.
+
+The :module:`FindPython` module can be used if Python version does not matter
+for you.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+``Python2::Interpreter``
+ Python 2 interpreter. Target defined if component ``Interpreter`` is found.
+``Python2::Compiler``
+ Python 2 compiler. Target defined if component ``Compiler`` is found.
+``Python2::Python``
+ Python 2 library. Target defined if component ``Development`` is found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module will set the following variables in your project
+(see :ref:`Standard Variable Names <CMake Developer Standard Variable Names>`):
+
+``Python2_FOUND``
+ System has the Python 2 requested components.
+``Python2_Interpreter_FOUND``
+ System has the Python 2 interpreter.
+``Python2_EXECUTABLE``
+ Path to the Python 2 interpreter.
+``Python2_INTERPRETER_ID``
+ A short string unique to the interpreter. Possible values include:
+ * Python
+ * ActivePython
+ * Anaconda
+ * Canopy
+ * IronPython
+``Python2_STDLIB``
+ Standard platform independent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)``.
+``Python2_STDARCH``
+ Standard platform dependent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)``.
+``Python2_SITELIB``
+ Third-party platform independent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)``.
+``Python2_SITEARCH``
+ Third-party platform dependent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``.
+``Python2_Compiler_FOUND``
+ System has the Python 2 compiler.
+``Python2_COMPILER``
+ Path to the Python 2 compiler. Only offered by IronPython.
+``Python2_COMPILER_ID``
+ A short string unique to the compiler. Possible values include:
+ * IronPython
+``Python2_Development_FOUND``
+ System has the Python 2 development artifacts.
+``Python2_INCLUDE_DIRS``
+ The Python 2 include directories.
+``Python2_LIBRARIES``
+ The Python 2 libraries.
+``Python2_LIBRARY_DIRS``
+ The Python 2 library directories.
+``Python2_RUNTIME_LIBRARY_DIRS``
+ The Python 2 runtime library directories.
+``Python2_VERSION``
+ Python 2 version.
+``Python2_VERSION_MAJOR``
+ Python 2 major version.
+``Python2_VERSION_MINOR``
+ Python 2 minor version.
+``Python2_VERSION_PATCH``
+ Python 2 patch version.
+
+Hints
+^^^^^
+
+``Python2_ROOT_DIR``
+ Define the root directory of a Python 2 installation.
+
+``Python2_USE_STATIC_LIBS``
+ * If not defined, search for shared libraries and static libraries in that
+ order.
+ * If set to TRUE, search **only** for static libraries.
+ * If set to FALSE, search **only** for shared libraries.
+
+Commands
+^^^^^^^^
+
+This module defines the command ``Python2_add_library`` which have the same
+semantic as :command:`add_library` but take care of Python module naming rules
+(only applied if library is of type ``MODULE``) and add dependency to target
+``Python2::Python``::
+
+ Python2_add_library (my_module MODULE src1.cpp)
+
+If library type is not specified, ``MODULE`` is assumed.
+#]=======================================================================]
+
+
+set (_PYTHON_PREFIX Python2)
+
+set (_Python2_REQUIRED_VERSION_MAJOR 2)
+
+include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake)
+
+if (COMMAND __Python2_add_library)
+ macro (Python2_add_library)
+ __Python2_add_library (Python2 ${ARGV})
+ endmacro()
+endif()
+
+unset (_PYTHON_PREFIX)
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindPython3
+-----------
+
+Find Python 3 interpreter, compiler and development environment (include
+directories and libraries).
+
+Three components are supported:
+
+* ``Interpreter``: search for Python 3 interpreter
+* ``Compiler``: search for Python 3 compiler. Only offered by IronPython.
+* ``Development``: search for development artifacts (include directories and
+ libraries)
+
+If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed.
+
+To ensure consistent versions between components ``Interpreter``, ``Compiler``
+and ``Development``, specify all components at the same time::
+
+ find_package (Python3 COMPONENTS Interpreter Development)
+
+This module looks only for version 3 of Python. This module can be used
+concurrently with :module:`FindPython2` module to use both Python versions.
+
+The :module:`FindPython` module can be used if Python version does not matter
+for you.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+``Python3::Interpreter``
+ Python 3 interpreter. Target defined if component ``Interpreter`` is found.
+``Python3::Compiler``
+ Python 3 compiler. Target defined if component ``Compiler`` is found.
+``Python3::Python``
+ Python 3 library. Target defined if component ``Development`` is found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module will set the following variables in your project
+(see :ref:`Standard Variable Names <CMake Developer Standard Variable Names>`):
+
+``Python3_FOUND``
+ System has the Python 3 requested components.
+``Python3_Interpreter_FOUND``
+ System has the Python 3 interpreter.
+``Python3_EXECUTABLE``
+ Path to the Python 3 interpreter.
+``Python3_INTERPRETER_ID``
+ A short string unique to the interpreter. Possible values include:
+ * Python
+ * ActivePython
+ * Anaconda
+ * Canopy
+ * IronPython
+``Python3_STDLIB``
+ Standard platform independent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)``.
+``Python3_STDARCH``
+ Standard platform dependent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)``.
+``Python3_SITELIB``
+ Third-party platform independent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)``.
+``Python3_SITEARCH``
+ Third-party platform dependent installation directory.
+
+ Information returned by
+ ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``.
+``Python3_Compiler_FOUND``
+ System has the Python 3 compiler.
+``Python3_COMPILER``
+ Path to the Python 3 compiler. Only offered by IronPython.
+``Python3_COMPILER_ID``
+ A short string unique to the compiler. Possible values include:
+ * IronPython
+``Python3_Development_FOUND``
+ System has the Python 3 development artifacts.
+``Python3_INCLUDE_DIRS``
+ The Python 3 include directories.
+``Python3_LIBRARIES``
+ The Python 3 libraries.
+``Python3_LIBRARY_DIRS``
+ The Python 3 library directories.
+``Python3_RUNTIME_LIBRARY_DIRS``
+ The Python 3 runtime library directories.
+``Python3_VERSION``
+ Python 3 version.
+``Python3_VERSION_MAJOR``
+ Python 3 major version.
+``Python3_VERSION_MINOR``
+ Python 3 minor version.
+``Python3_VERSION_PATCH``
+ Python 3 patch version.
+
+Hints
+^^^^^
+
+``Python3_ROOT_DIR``
+ Define the root directory of a Python 3 installation.
+
+``Python3_USE_STATIC_LIBS``
+ * If not defined, search for shared libraries and static libraries in that
+ order.
+ * If set to TRUE, search **only** for static libraries.
+ * If set to FALSE, search **only** for shared libraries.
+
+Commands
+^^^^^^^^
+
+This module defines the command ``Python3_add_library`` which have the same
+semantic as :command:`add_library` but take care of Python module naming rules
+(only applied if library is of type ``MODULE``) and add dependency to target
+``Python3::Python``::
+
+ Python3_add_library (my_module MODULE src1.cpp)
+
+If library type is not specified, ``MODULE`` is assumed.
+#]=======================================================================]
+
+
+set (_PYTHON_PREFIX Python3)
+
+set (_Python3_REQUIRED_VERSION_MAJOR 3)
+
+include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake)
+
+if (COMMAND __Python3_add_library)
+ macro (Python3_add_library)
+ __Python3_add_library (Python3 ${ARGV})
+ endmacro()
+endif()
+
+unset (_PYTHON_PREFIX)
#
# Find python interpreter
#
+# .. deprecated:: 3.12
+#
+# Use :module:`FindPython3`, :module:`FindPython2` or :module:`FindPython` instead.
+#
# This module finds if Python interpreter is installed and determines
# where the executables are. This code sets the following variables:
#
set(_PYTHON1_VERSIONS 1.6 1.5)
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
-set(_PYTHON3_VERSIONS 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+set(_PYTHON3_VERSIONS 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
if(PythonInterp_FIND_VERSION)
if(PythonInterp_FIND_VERSION_COUNT GREATER 1)
#
# Find python libraries
#
+# .. deprecated:: 3.12
+#
+# Use :module:`FindPython3`, :module:`FindPython2` or :module:`FindPython` instead.
+#
# This module finds if Python is installed and determines where the
# include files and libraries are. It also determines what the name of
# the library is. This code sets the following variables:
set(_PYTHON1_VERSIONS 1.6 1.5)
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
-set(_PYTHON3_VERSIONS 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+set(_PYTHON3_VERSIONS 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
if(PythonLibs_FIND_VERSION)
if(PythonLibs_FIND_VERSION_COUNT GREATER 1)
if(NOT WIN32)
string(REPLACE ":" ";" qt_mkspecs_dirs "${qt_mkspecs_dirs}")
endif()
- set(qt_cross_paths)
- foreach(qt_cross_path ${CMAKE_FIND_ROOT_PATH})
- set(qt_cross_paths ${qt_cross_paths} "${qt_cross_path}/mkspecs")
- endforeach()
- set(QT_MKSPECS_DIR NOTFOUND)
+
find_path(QT_MKSPECS_DIR NAMES qconfig.pri
- HINTS ${qt_cross_paths} ${qt_mkspecs_dirs}
- DOC "The location of the Qt mkspecs containing qconfig.pri"
- NO_CMAKE_FIND_ROOT_PATH)
+ HINTS ${qt_mkspecs_dirs}
+ PATH_SUFFIXES mkspecs share/qt4/mkspecs
+ DOC "The location of the Qt mkspecs containing qconfig.pri")
endif()
if(EXISTS "${QT_MKSPECS_DIR}/qconfig.pri")
# ask qmake for the plugins directory
if (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR OR QT_QMAKE_CHANGED)
_qt4_query_qmake(QT_INSTALL_PLUGINS qt_plugins_dir)
- set(QT_PLUGINS_DIR NOTFOUND)
- foreach(qt_cross_path ${CMAKE_FIND_ROOT_PATH})
- set(qt_cross_paths ${qt_cross_paths} "${qt_cross_path}/plugins")
- endforeach()
- find_path(QT_PLUGINS_DIR NAMES accessible imageformats sqldrivers codecs designer
- HINTS ${qt_cross_paths} ${qt_plugins_dir}
- DOC "The location of the Qt plugins"
- NO_CMAKE_FIND_ROOT_PATH)
+ if(CMAKE_CROSSCOMPILING OR NOT qt_plugins_dir)
+ find_path(QT_PLUGINS_DIR
+ NAMES accessible bearer codecs designer graphicssystems iconengines imageformats inputmethods qmltooling script sqldrivers
+ HINTS ${qt_plugins_dir}
+ PATH_SUFFIXES plugins lib/qt4/plugins
+ DOC "The location of the Qt plugins")
+ else()
+ set(QT_PLUGINS_DIR ${qt_plugins_dir} CACHE PATH "The location of the Qt plugins")
+ endif()
endif ()
# ask qmake for the translations directory
# ask qmake for the imports directory
if (QT_LIBRARY_DIR AND NOT QT_IMPORTS_DIR OR QT_QMAKE_CHANGED)
_qt4_query_qmake(QT_INSTALL_IMPORTS qt_imports_dir)
- if(qt_imports_dir)
- set(QT_IMPORTS_DIR NOTFOUND)
- foreach(qt_cross_path ${CMAKE_FIND_ROOT_PATH})
- set(qt_cross_paths ${qt_cross_paths} "${qt_cross_path}/imports")
- endforeach()
+ if(CMAKE_CROSSCOMPILING OR NOT qt_imports_dir)
find_path(QT_IMPORTS_DIR NAMES Qt
- HINTS ${qt_cross_paths} ${qt_imports_dir}
- DOC "The location of the Qt imports"
- NO_CMAKE_FIND_ROOT_PATH
- NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- mark_as_advanced(QT_IMPORTS_DIR)
+ HINTS ${qt_imports_dir}
+ PATH_SUFFIXES imports lib/qt4/imports
+ DOC "The location of the Qt imports")
+ else()
+ set(QT_IMPORTS_DIR ${qt_imports_dir} CACHE PATH "The location of the Qt imports")
endif()
endif ()
set(Vulkan_LIBRARIES ${Vulkan_LIBRARY})
set(Vulkan_INCLUDE_DIRS ${Vulkan_INCLUDE_DIR})
-include(FindPackageHandleStandardArgs)
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(Vulkan
DEFAULT_MSG
Vulkan_LIBRARY Vulkan_INCLUDE_DIR)
# Allow ZLIB_LIBRARY to be set manually, as the location of the zlib library
if(NOT ZLIB_LIBRARY)
foreach(search ${_ZLIB_SEARCHES})
- find_library(ZLIB_LIBRARY_RELEASE NAMES ${ZLIB_NAMES} ${${search}} PATH_SUFFIXES lib)
- find_library(ZLIB_LIBRARY_DEBUG NAMES ${ZLIB_NAMES_DEBUG} ${${search}} PATH_SUFFIXES lib)
+ find_library(ZLIB_LIBRARY_RELEASE NAMES ${ZLIB_NAMES} NAMES_PER_DIR ${${search}} PATH_SUFFIXES lib)
+ find_library(ZLIB_LIBRARY_DEBUG NAMES ${ZLIB_NAMES_DEBUG} NAMES_PER_DIR ${${search}} PATH_SUFFIXES lib)
endforeach()
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
set(_WX_TOOL gcc)
elseif(MSVC)
set(_WX_TOOL vc)
- if(MSVC_VERSION EQUAL 1910)
- set(_WX_TOOLVER 141)
- elseif(MSVC_VERSION EQUAL 1900)
- set(_WX_TOOLVER 140)
- elseif(MSVC_VERSION EQUAL 1800)
- set(_WX_TOOLVER 120)
- elseif(MSVC_VERSION EQUAL 1700)
- set(_WX_TOOLVER 110)
- elseif(MSVC_VERSION EQUAL 1600)
- set(_WX_TOOLVER 100)
- elseif(MSVC_VERSION EQUAL 1500)
- set(_WX_TOOLVER 90)
- endif()
+ set(_WX_TOOLVER ${MSVC_TOOLSET_VERSION})
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_WX_ARCH _x64)
endif()
# extract linkdirs (-L) for rpath (i.e., LINK_DIRECTORIES)
string(REGEX MATCHALL "-L[^;]+"
wxWidgets_LIBRARY_DIRS "${wxWidgets_LIBRARIES}")
- string(REPLACE "-L" ""
+ string(REGEX REPLACE "-L([^;]+)" "\\1"
wxWidgets_LIBRARY_DIRS "${wxWidgets_LIBRARY_DIRS}")
DBG_MSG_V("wxWidgets_LIBRARIES=${wxWidgets_LIBRARIES}")
set(wxWidgets_INCLUDE_DIRS ${_tmp_path})
separate_arguments(wxWidgets_INCLUDE_DIRS)
list(REMOVE_ITEM wxWidgets_INCLUDE_DIRS "")
+
+ set(_tmp_path "")
+ foreach(_path ${wxWidgets_LIBRARY_DIRS})
+ execute_process(
+ COMMAND cygpath -w ${_path}
+ OUTPUT_VARIABLE _native_path
+ RESULT_VARIABLE _retv
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET
+ )
+ if(_retv EQUAL 0)
+ file(TO_CMAKE_PATH ${_native_path} _native_path)
+ DBG_MSG_V("Path ${_path} converted to ${_native_path}")
+ string(APPEND _tmp_path " ${_native_path}")
+ endif()
+ endforeach()
+ DBG_MSG("Setting wxWidgets_LIBRARY_DIRS = ${_tmp_path}")
+ set(wxWidgets_LIBRARY_DIRS ${_tmp_path})
+ separate_arguments(wxWidgets_LIBRARY_DIRS)
+ list(REMOVE_ITEM wxWidgets_LIBRARY_DIRS "")
endif()
unset(_cygpath_exe CACHE)
endif()
# Check if a specific version was requested by find_package().
if(wxWidgets_FOUND)
- find_file(_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH)
- dbg_msg("_filename: ${_filename}")
+ unset(_wx_filename)
+ find_file(_wx_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH)
+ dbg_msg("_wx_filename: ${_wx_filename}")
- if(NOT _filename)
+ if(NOT _wx_filename)
message(FATAL_ERROR "wxWidgets wx/version.h file not found in ${wxWidgets_INCLUDE_DIRS}.")
endif()
- file(READ ${_filename} _wx_version_h)
+ file(READ "${_wx_filename}" _wx_version_h)
+ unset(_wx_filename CACHE)
string(REGEX REPLACE "^(.*\n)?#define +wxMAJOR_VERSION +([0-9]+).*"
"\\2" wxWidgets_VERSION_MAJOR "${_wx_version_h}" )
# :prop_tgt:`CXX_VISIBILITY_PRESET <<LANG>_VISIBILITY_PRESET>` and
# :prop_tgt:`VISIBILITY_INLINES_HIDDEN` instead.
+include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
# TODO: Install this macro separately?
)
endmacro()
+# TODO: Install this macro separately?
+macro(_check_c_compiler_attribute _ATTRIBUTE _RESULT)
+ check_c_source_compiles("${_ATTRIBUTE} int somefunc() { return 0; }
+ int main() { return somefunc();}" ${_RESULT}
+ )
+endmacro()
+
macro(_test_compiler_hidden_visibility)
if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.2")
AND NOT CMAKE_CXX_COMPILER_ID MATCHES XL
AND NOT CMAKE_CXX_COMPILER_ID MATCHES PGI
AND NOT CMAKE_CXX_COMPILER_ID MATCHES Watcom)
- check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
- check_cxx_compiler_flag(-fvisibility-inlines-hidden
- COMPILER_HAS_HIDDEN_INLINE_VISIBILITY)
+ if (CMAKE_CXX_COMPILER_LOADED)
+ check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
+ check_cxx_compiler_flag(-fvisibility-inlines-hidden
+ COMPILER_HAS_HIDDEN_INLINE_VISIBILITY)
+ else()
+ check_c_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
+ check_c_compiler_flag(-fvisibility-inlines-hidden
+ COMPILER_HAS_HIDDEN_INLINE_VISIBILITY)
+ endif()
endif()
endmacro()
set(COMPILER_HAS_DEPRECATED "" CACHE INTERNAL
"Compiler support for a deprecated attribute")
else()
- _check_cxx_compiler_attribute("__attribute__((__deprecated__))"
- COMPILER_HAS_DEPRECATED_ATTR)
- if(COMPILER_HAS_DEPRECATED_ATTR)
- set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}"
- CACHE INTERNAL "Compiler support for a deprecated attribute")
+ if (CMAKE_CXX_COMPILER_LOADED)
+ _check_cxx_compiler_attribute("__attribute__((__deprecated__))"
+ COMPILER_HAS_DEPRECATED_ATTR)
+ if(COMPILER_HAS_DEPRECATED_ATTR)
+ set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}"
+ CACHE INTERNAL "Compiler support for a deprecated attribute")
+ else()
+ _check_cxx_compiler_attribute("__declspec(deprecated)"
+ COMPILER_HAS_DEPRECATED)
+ endif()
else()
- _check_cxx_compiler_attribute("__declspec(deprecated)"
- COMPILER_HAS_DEPRECATED)
+ _check_c_compiler_attribute("__attribute__((__deprecated__))"
+ COMPILER_HAS_DEPRECATED_ATTR)
+ if(COMPILER_HAS_DEPRECATED_ATTR)
+ set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}"
+ CACHE INTERNAL "Compiler support for a deprecated attribute")
+ else()
+ _check_c_compiler_attribute("__declspec(deprecated)"
+ COMPILER_HAS_DEPRECATED)
+ endif()
+
endif()
endif()
endmacro()
)
endif()
- if(MSVC_VERSION EQUAL 1400)
- set(MSVC_REDIST_NAME VC80)
-
+ if(MSVC_TOOLSET_VERSION EQUAL 80)
# Find the runtime library redistribution directory.
get_filename_component(msvc_install_dir
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0;InstallDir]" ABSOLUTE)
endif()
endif()
- if(MSVC_VERSION EQUAL 1500)
- set(MSVC_REDIST_NAME VC90)
-
+ if(MSVC_TOOLSET_VERSION EQUAL 90)
# Find the runtime library redistribution directory.
get_filename_component(msvc_install_dir
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0;InstallDir]" ABSOLUTE)
endif()
set(MSVC_REDIST_NAME "")
- set(_MSVCRT_DLL_VERSION "")
- set(_MSVCRT_IDE_VERSION "")
+ set(_MSVC_DLL_VERSION "")
+ set(_MSVC_IDE_VERSION "")
if(MSVC_VERSION GREATER_EQUAL 2000)
message(WARNING "MSVC ${MSVC_VERSION} not yet supported.")
- elseif(MSVC_VERSION GREATER_EQUAL 1911)
- set(MSVC_REDIST_NAME VC141)
- set(_MSVCRT_DLL_VERSION 140)
- set(_MSVCRT_IDE_VERSION 15)
- elseif(MSVC_VERSION EQUAL 1910)
- set(MSVC_REDIST_NAME VC150)
- set(_MSVCRT_DLL_VERSION 140)
- set(_MSVCRT_IDE_VERSION 15)
- elseif(MSVC_VERSION EQUAL 1900)
- set(MSVC_REDIST_NAME VC140)
- set(_MSVCRT_DLL_VERSION 140)
- set(_MSVCRT_IDE_VERSION 14)
- elseif(MSVC_VERSION EQUAL 1800)
- set(MSVC_REDIST_NAME VC120)
- set(_MSVCRT_DLL_VERSION 120)
- set(_MSVCRT_IDE_VERSION 12)
- elseif(MSVC_VERSION EQUAL 1700)
- set(MSVC_REDIST_NAME VC110)
- set(_MSVCRT_DLL_VERSION 110)
- set(_MSVCRT_IDE_VERSION 11)
- elseif(MSVC_VERSION EQUAL 1600)
- set(MSVC_REDIST_NAME VC100)
- set(_MSVCRT_DLL_VERSION 100)
- set(_MSVCRT_IDE_VERSION 10)
+ elseif(MSVC_TOOLSET_VERSION)
+ set(MSVC_REDIST_NAME VC${MSVC_TOOLSET_VERSION})
+ if(MSVC_VERSION EQUAL 1910)
+ # VS2017 named this differently prior to update 3.
+ set(MSVC_REDIST_NAME VC150)
+ endif()
+
+ math(EXPR _MSVC_DLL_VERSION "${MSVC_TOOLSET_VERSION} / 10 * 10")
+
+ if(MSVC_TOOLSET_VERSION EQUAL 141)
+ set(_MSVC_IDE_VERSION 15)
+ else()
+ math(EXPR _MSVC_IDE_VERSION "${MSVC_TOOLSET_VERSION} / 10")
+ endif()
+ endif()
+
+ set(_MSVCRT_DLL_VERSION "")
+ set(_MSVCRT_IDE_VERSION "")
+ if(_MSVC_IDE_VERSION GREATER_EQUAL 10)
+ set(_MSVCRT_DLL_VERSION "${_MSVC_DLL_VERSION}")
+ set(_MSVCRT_IDE_VERSION "${_MSVC_IDE_VERSION}")
endif()
if(_MSVCRT_DLL_VERSION)
set(_MFC_DLL_VERSION "")
set(_MFC_IDE_VERSION "")
- if(MSVC_VERSION GREATER_EQUAL 2000)
- # Version not yet supported.
- elseif(MSVC_VERSION GREATER_EQUAL 1910)
- set(_MFC_DLL_VERSION 140)
- set(_MFC_IDE_VERSION 15)
- elseif(MSVC_VERSION EQUAL 1900)
- set(_MFC_DLL_VERSION 140)
- set(_MFC_IDE_VERSION 14)
- elseif(MSVC_VERSION EQUAL 1800)
- set(_MFC_DLL_VERSION 120)
- set(_MFC_IDE_VERSION 12)
- elseif(MSVC_VERSION EQUAL 1700)
- set(_MFC_DLL_VERSION 110)
- set(_MFC_IDE_VERSION 11)
- elseif(MSVC_VERSION EQUAL 1600)
- set(_MFC_DLL_VERSION 100)
- set(_MFC_IDE_VERSION 10)
+ if(_MSVC_IDE_VERSION GREATER_EQUAL 10)
+ set(_MFC_DLL_VERSION ${_MSVC_DLL_VERSION})
+ set(_MFC_IDE_VERSION ${_MSVC_IDE_VERSION})
endif()
if(_MFC_DLL_VERSION)
# MSVC 8 was the first version with OpenMP
# Furthermore, there is no debug version of this
if(CMAKE_INSTALL_OPENMP_LIBRARIES AND _IRSL_HAVE_MSVC)
- set(_MSOMP_DLL_VERSION "")
- set(_MSOMP_IDE_VERSION "")
- if(MSVC_VERSION GREATER_EQUAL 2000)
- # Version not yet supported.
- elseif(MSVC_VERSION GREATER_EQUAL 1910)
- set(_MSOMP_DLL_VERSION 140)
- set(_MSOMP_IDE_VERSION 15)
- elseif(MSVC_VERSION EQUAL 1900)
- set(_MSOMP_DLL_VERSION 140)
- set(_MSOMP_IDE_VERSION 14)
- elseif(MSVC_VERSION EQUAL 1800)
- set(_MSOMP_DLL_VERSION 120)
- set(_MSOMP_IDE_VERSION 12)
- elseif(MSVC_VERSION EQUAL 1700)
- set(_MSOMP_DLL_VERSION 110)
- set(_MSOMP_IDE_VERSION 11)
- elseif(MSVC_VERSION EQUAL 1600)
- set(_MSOMP_DLL_VERSION 100)
- set(_MSOMP_IDE_VERSION 10)
- elseif(MSVC_VERSION EQUAL 1500)
- set(_MSOMP_DLL_VERSION 90)
- set(_MSOMP_IDE_VERSION 9)
- elseif(MSVC_VERSION EQUAL 1400)
- set(_MSOMP_DLL_VERSION 80)
- set(_MSOMP_IDE_VERSION 8)
- endif()
+ set(_MSOMP_DLL_VERSION ${_MSVC_DLL_VERSION})
+ set(_MSOMP_IDE_VERSION ${_MSVC_IDE_VERSION})
if(_MSOMP_DLL_VERSION)
set(v "${_MSOMP_DLL_VERSION}")
if(no_unittest_framework)
- set(unittest_to_run "try, ${unittest_file_to_run_name}, catch err, disp('An exception has been thrown during the execution'), disp(err), disp(err.stack), exit(1), end, exit(0)")
+ set(unittest_to_run "${unittest_file_to_run_name}")
endif()
+set(command_to_run "try, ${unittest_to_run}, catch err, disp('An exception has been thrown during the execution'), disp(err), disp(err.stack), exit(1), end, exit(0)")
set(Matlab_SCRIPT_TO_RUN
- "addpath(${concat_string}); ${cmd_to_run_before_test}; ${unittest_to_run}"
+ "addpath(${concat_string}); ${cmd_to_run_before_test}; ${command_to_run}"
)
# if the working directory is not specified then default
# to the output_directory because the log file will go there
include(Platform/Android-Clang)
__android_compiler_clang(CXX)
+if(_ANDROID_STL_NOSTDLIBXX)
+ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 6)
+ string(APPEND CMAKE_CXX_STANDARD_LIBRARIES " -nostdlib++")
+ else()
+ string(APPEND CMAKE_CXX_STANDARD_LIBRARIES " -nodefaultlibs -lgcc -lc -lm -ldl")
+ endif()
+endif()
else()
# https://developer.android.com/ndk/guides/application_mk.html
# Default is the oldest ARM ABI.
- set(CMAKE_ANDROID_ARCH_ABI "armeabi")
+
+ # Lookup the available ABIs among all toolchains.
+ set(_ANDROID_ABIS "")
+ file(GLOB _ANDROID_CONFIG_MKS
+ "${CMAKE_ANDROID_NDK}/build/core/toolchains/*/config.mk"
+ "${CMAKE_ANDROID_NDK}/toolchains/*/config.mk"
+ )
+ foreach(config_mk IN LISTS _ANDROID_CONFIG_MKS)
+ file(STRINGS "${config_mk}" _ANDROID_TOOL_ABIS REGEX "^TOOLCHAIN_ABIS :=")
+ string(REPLACE "TOOLCHAIN_ABIS :=" "" _ANDROID_TOOL_ABIS "${_ANDROID_TOOL_ABIS}")
+ separate_arguments(_ANDROID_TOOL_ABIS UNIX_COMMAND "${_ANDROID_TOOL_ABIS}")
+ list(APPEND _ANDROID_ABIS ${_ANDROID_TOOL_ABIS})
+ unset(_ANDROID_TOOL_ABIS)
+ endforeach()
+ unset(_ANDROID_CONFIG_MKS)
+
+ # Choose the oldest among the available arm ABIs.
+ if(_ANDROID_ABIS)
+ list(REMOVE_DUPLICATES _ANDROID_ABIS)
+ cmake_policy(PUSH)
+ cmake_policy(SET CMP0057 NEW)
+ foreach(abi armeabi armeabi-v7a arm64-v8a)
+ if("${abi}" IN_LIST _ANDROID_ABIS)
+ set(CMAKE_ANDROID_ARCH_ABI "${abi}")
+ break()
+ endif()
+ endforeach()
+ cmake_policy(POP)
+ endif()
+ unset(_ANDROID_ABIS)
+
+ if(NOT CMAKE_ANDROID_ARCH_ABI)
+ set(CMAKE_ANDROID_ARCH_ABI "armeabi")
+ endif()
endif()
endif()
set(CMAKE_ANDROID_ARCH "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_ARCH}")
include(Platform/Android-GNU)
__android_compiler_gnu(CXX)
+if(_ANDROID_STL_NOSTDLIBXX)
+ string(APPEND CMAKE_CXX_STANDARD_LIBRARIES " -nodefaultlibs -lgcc -lc -lm -ldl")
+endif()
# <ndk>/sources/cxx-stl/llvm-libc++/Android.mk
set(_ANDROID_STL_RTTI 1)
set(_ANDROID_STL_EXCEPTIONS 1)
+set(_ANDROID_STL_NOSTDLIBXX 1)
macro(__android_stl_cxx lang filename)
# Add the include directory.
if(EXISTS "${CMAKE_ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libcxx/include/cstddef")
# <ndk>/sources/cxx-stl/gabi++/Android.mk
set(_ANDROID_STL_RTTI 1)
set(_ANDROID_STL_EXCEPTIONS 1)
+set(_ANDROID_STL_NOSTDLIBXX 1)
macro(__android_stl_gabixx lang filename)
__android_stl_inc(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/gabi++/include" 1)
__android_stl_lib(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${CMAKE_ANDROID_ARCH_ABI}/${filename}" 1)
# <ndk>/sources/cxx-stl/gnu-libstdc++/Android.mk
set(_ANDROID_STL_RTTI 1)
set(_ANDROID_STL_EXCEPTIONS 1)
+set(_ANDROID_STL_NOSTDLIBXX 1)
macro(__android_stl_gnustl lang filename)
__android_stl_inc(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${CMAKE_${lang}_ANDROID_TOOLCHAIN_VERSION}/include" 1)
__android_stl_inc(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${CMAKE_${lang}_ANDROID_TOOLCHAIN_VERSION}/libs/${CMAKE_ANDROID_ARCH_ABI}/include" 1)
+set(_ANDROID_STL_NOSTDLIBXX 1)
macro(__android_stl lang)
endmacro()
# <ndk>/sources/cxx-stl/stlport/Android.mk
set(_ANDROID_STL_RTTI 1)
set(_ANDROID_STL_EXCEPTIONS 1)
+set(_ANDROID_STL_NOSTDLIBXX 0)
macro(__android_stl_stlport lang filename)
__android_stl_inc(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/stlport/stlport" 1)
__android_stl_lib(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/stlport/libs/${CMAKE_ANDROID_ARCH_ABI}/${filename}" 1)
# <ndk>/android-ndk-r11c/sources/cxx-stl/system/Android.mk
set(_ANDROID_STL_RTTI 0)
set(_ANDROID_STL_EXCEPTIONS 0)
+set(_ANDROID_STL_NOSTDLIBXX 0)
macro(__android_stl lang)
__android_stl_inc(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/system/include" 1)
endmacro()
-include(Platform/Darwin-Clang-C)
+include(Platform/Apple-Clang-C)
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.2)
set(CMAKE_C_SYSTEM_FRAMEWORK_SEARCH_FLAG "-iframework ")
else()
-include(Platform/Darwin-Clang-CXX)
+include(Platform/Apple-Clang-CXX)
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2)
set(CMAKE_CXX_SYSTEM_FRAMEWORK_SEARCH_FLAG "-iframework ")
else()
--- /dev/null
+include(Platform/Apple-Clang)
+__apple_compiler_clang(C)
--- /dev/null
+include(Platform/Apple-Clang)
+__apple_compiler_clang(CXX)
# This module is shared by multiple languages; use include blocker.
-if(__DARWIN_COMPILER_CLANG)
- return()
-endif()
-set(__DARWIN_COMPILER_CLANG 1)
+include_guard()
-macro(__darwin_compiler_clang lang)
+macro(__apple_compiler_clang lang)
set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names")
set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names")
-include(Platform/Darwin-GNU)
-__darwin_compiler_gnu(C)
+include(Platform/Apple-GNU)
+__apple_compiler_gnu(C)
cmake_gnu_set_sysroot_flag(C)
cmake_gnu_set_osx_deployment_target_flag(C)
-include(Platform/Darwin-GNU)
-__darwin_compiler_gnu(CXX)
+include(Platform/Apple-GNU)
+__apple_compiler_gnu(CXX)
cmake_gnu_set_sysroot_flag(CXX)
cmake_gnu_set_osx_deployment_target_flag(CXX)
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-include(Platform/Darwin-GNU)
-__darwin_compiler_gnu(Fortran)
+include(Platform/Apple-GNU)
+__apple_compiler_gnu(Fortran)
cmake_gnu_set_sysroot_flag(Fortran)
cmake_gnu_set_osx_deployment_target_flag(Fortran)
# This module is shared by multiple languages; use include blocker.
-if(__DARWIN_COMPILER_GNU)
- return()
-endif()
-set(__DARWIN_COMPILER_GNU 1)
+include_guard()
-macro(__darwin_compiler_gnu lang)
+macro(__apple_compiler_gnu lang)
set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output
# GNU does not have -shared on OS X
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names")
--- /dev/null
+include(Platform/Apple-Intel)
+__apple_compiler_intel(C)
--- /dev/null
+include(Platform/Apple-Intel)
+__apple_compiler_intel(CXX)
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-include(Platform/Darwin-Intel)
-__darwin_compiler_intel(Fortran)
+include(Platform/Apple-Intel)
+__apple_compiler_intel(Fortran)
set(CMAKE_Fortran_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
set(CMAKE_Fortran_OSX_CURRENT_VERSION_FLAG "-current_version ")
# This module is shared by multiple languages; use include blocker.
-if(__DARWIN_COMPILER_INTEL)
- return()
-endif()
-set(__DARWIN_COMPILER_INTEL 1)
+include_guard()
-macro(__darwin_compiler_intel lang)
+macro(__apple_compiler_intel lang)
set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names")
set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names")
--- /dev/null
+include(Platform/Apple-PGI)
+__apple_compiler_pgi(C)
--- /dev/null
+include(Platform/Apple-PGI)
+__apple_compiler_pgi(CXX)
--- /dev/null
+include(Platform/Apple-PGI)
+__apple_compiler_pgi(Fortran)
# file Copyright.txt or https://cmake.org/licensing for details.
# This module is shared by multiple languages; use include blocker.
-if(__DARWIN_COMPILER_PGI)
- return()
-endif()
-set(__DARWIN_COMPILER_PGI 1)
+include_guard()
-macro(__darwin_compiler_pgi lang)
+macro(__apple_compiler_pgi lang)
set(CMAKE_${lang}_OSX_COMPATIBILITY_VERSION_FLAG "-Wl,-compatibility_version,")
set(CMAKE_${lang}_OSX_CURRENT_VERSION_FLAG "-Wl,-current_version,")
set(CMAKE_SHARED_LIBRARY_SONAME_${lang}_FLAG "-Wl,-install_name")
--- /dev/null
+include(Platform/Apple-XL-C)
--- /dev/null
+include(Platform/Apple-XL-CXX)
+++ /dev/null
-include(Platform/Darwin-Clang)
-__darwin_compiler_clang(C)
+++ /dev/null
-include(Platform/Darwin-Clang)
-__darwin_compiler_clang(CXX)
set(CMAKE_OSX_ARCHITECTURES "$ENV{CMAKE_OSX_ARCHITECTURES}" CACHE STRING
"Build architectures for OSX")
+# macOS, iOS, tvOS, and watchOS should lookup compilers from
+# Platform/Apple-${CMAKE_CXX_COMPILER_ID}-<LANG>
+set(CMAKE_EFFECTIVE_SYSTEM_NAME "Apple")
+
#----------------------------------------------------------------------------
# _CURRENT_OSX_VERSION - as a two-component string: 10.5, 10.6, ...
#
+++ /dev/null
-include(Platform/Darwin-Intel)
-__darwin_compiler_intel(C)
+++ /dev/null
-include(Platform/Darwin-Intel)
-__darwin_compiler_intel(CXX)
+++ /dev/null
-include(Platform/Darwin-PGI)
-__darwin_compiler_pgi(C)
+++ /dev/null
-include(Platform/Darwin-PGI)
-__darwin_compiler_pgi(CXX)
+++ /dev/null
-include(Platform/Darwin-PGI)
-__darwin_compiler_pgi(Fortran)
+++ /dev/null
-include(Platform/Darwin-XL-C)
+++ /dev/null
-include(Platform/Darwin-XL-CXX)
# We pass this for historical reasons. Projects may have
# executables that use dlopen but do not set ENABLE_EXPORTS.
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
- set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
endmacro()
message(FATAL_ERROR "MSVC compiler version not detected properly: ${_compiler_version}")
endif()
+ if(MSVC_VERSION GREATER_EQUAL 1910)
+ # VS 2017 or greater
+ set(MSVC_TOOLSET_VERSION 141)
+ elseif(MSVC_VERSION EQUAL 1900)
+ # VS 2015
+ set(MSVC_TOOLSET_VERSION 140)
+ elseif(MSVC_VERSION EQUAL 1800)
+ # VS 2013
+ set(MSVC_TOOLSET_VERSION 120)
+ elseif(MSVC_VERSION EQUAL 1700)
+ # VS 2012
+ set(MSVC_TOOLSET_VERSION 110)
+ elseif(MSVC_VERSION EQUAL 1600)
+ # VS 2010
+ set(MSVC_TOOLSET_VERSION 100)
+ elseif(MSVC_VERSION EQUAL 1500)
+ # VS 2008
+ set(MSVC_TOOLSET_VERSION 90)
+ elseif(MSVC_VERSION EQUAL 1400)
+ # VS 2005
+ set(MSVC_TOOLSET_VERSION 80)
+ else()
+ # We don't support MSVC_TOOLSET_VERSION for earlier compiler.
+ endif()
+
set(MSVC10)
set(MSVC11)
set(MSVC12)
set(CMAKE_${lang}_LINK_EXECUTABLE
"${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
+ if("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xMSVC")
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "/GL")
+ set(CMAKE_${lang}_LINK_OPTIONS_IPO "/INCREMENTAL:NO" "/LTCG")
+ string(REPLACE "<LINK_FLAGS> " "/LTCG <LINK_FLAGS> "
+ CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO "${CMAKE_${lang}_CREATE_STATIC_LIBRARY}")
+ elseif("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xClang" OR
+ "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xFlang")
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+
+ # '-flto=thin' available since Clang 3.9 and Xcode 8
+ # * http://clang.llvm.org/docs/ThinLTO.html#clang-llvm
+ # * https://trac.macports.org/wiki/XcodeVersionInfo
+ set(_CMAKE_LTO_THIN TRUE)
+ if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.9)
+ set(_CMAKE_LTO_THIN FALSE)
+ endif()
+
+ if(_CMAKE_LTO_THIN)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin")
+ else()
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto")
+ endif()
+ endif()
+
if("x${lang}" STREQUAL "xC" OR
"x${lang}" STREQUAL "xCXX")
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
string(APPEND __IMPLICT_LINKS " \"${lib}\"")
endforeach()
set(CMAKE_CUDA_LINK_EXECUTABLE
- "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
+ "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
set(_CMAKE_VS_LINK_DLL "<CMAKE_COMMAND> -E vs_link_dll --intdir=<OBJECT_DIR> --manifests <MANIFESTS> -- ")
set(_CMAKE_VS_LINK_EXE "<CMAKE_COMMAND> -E vs_link_exe --intdir=<OBJECT_DIR> --manifests <MANIFESTS> -- ")
set(CMAKE_CUDA_CREATE_STATIC_LIBRARY "<CMAKE_LINKER> /lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
set(CMAKE_CUDA_LINKER_SUPPORTS_PDB ON)
set(CMAKE_CUDA_LINK_EXECUTABLE
- "${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}")
+ "${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}")
unset(_CMAKE_VS_LINK_EXE)
unset(_CMAKE_VS_LINK_EXE)
set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
endif()
+# Add implicit host link directories that contain device libraries
+# to the device link line.
+set(__IMPLICT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+if(__IMPLICT_DLINK_DIRS)
+ list(REMOVE_ITEM __IMPLICT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
+endif()
+set(__IMPLICT_DLINK_FLAGS )
+foreach(dir ${__IMPLICT_DLINK_DIRS})
+ if(EXISTS "${dir}/cublas_device.lib")
+ string(APPEND __IMPLICT_DLINK_FLAGS " -L\"${dir}\"")
+ endif()
+endforeach()
+unset(__IMPLICT_DLINK_DIRS)
+
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
+unset(__IMPLICT_DLINK_FLAGS)
string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}")
set(CMAKE_CREATE_WIN32_EXE /winapp)
set(CMAKE_CREATE_CONSOLE_EXE )
-if(CMAKE_GENERATOR MATCHES "Visual Studio 8")
- set (CMAKE_NO_BUILD_TYPE 1)
-endif()
# does the compiler support pdbtype and is it the newer compiler
set(CMAKE_BUILD_TYPE_INIT Debug)
# TEST_BIG_ENDIAN(VARIABLE)
# VARIABLE - variable to store the result to
+include(CheckTypeSize)
+
macro(TEST_BIG_ENDIAN VARIABLE)
if(NOT DEFINED HAVE_${VARIABLE})
message(STATUS "Check if the system is big endian")
message(FATAL_ERROR "TEST_BIG_ENDIAN needs either C or CXX language enabled")
endif()
- include(CheckTypeSize)
-
CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT LANGUAGE ${_test_language})
if(CMAKE_SIZEOF_UNSIGNED_SHORT EQUAL 2)
message(STATUS "Using unsigned short")
# The default OUTPUT_DIR can also be changed by setting the variable
# CMAKE_JAVA_TARGET_OUTPUT_DIR.
#
-# Optionaly, using option GENERATE_NATIVE_HEADERS, native header files can be generated
+# Optionally, using option GENERATE_NATIVE_HEADERS, native header files can be generated
# for methods declared as native. These files provide the connective glue that allow your
# Java and C code to interact. An INTERFACE target will be created for an easy usage
# of generated files. Sub-option DESTINATION can be used to specify output directory for
UseSWIG
-------
-Defines the following macros for use with SWIG:
+This file provides support for ``SWIG``. It is assumed that :module:`FindSWIG`
+module has already been loaded.
+
+Defines the following command for use with ``SWIG``:
.. command:: swig_add_library
swig_add_library(<name>
[TYPE <SHARED|MODULE|STATIC|USE_BUILD_SHARED_LIBS>]
LANGUAGE <language>
+ [NO_PROXY]
+ [OUTPUT_DIR <directory>]
+ [OUTFILE_DIR <directory>]
SOURCES <file>...
- )
-
- The variable ``SWIG_MODULE_<name>_REAL_NAME`` will be set to the name
- of the swig module target library.
+ )
+
+ Targets created with the ``swig_add_library`` command have the same
+ capabilities as targets created with the :command:`add_library` command, so
+ those targets can be used with any command expecting a target (e.g.
+ :command:`target_link_libraries`).
+
+ .. note::
+
+ The variable ``SWIG_MODULE_<name>_REAL_NAME`` will be set to the name
+ of the swig module target library. This variable is useless if variable
+ ``UseSWIG_TARGET_NAME_PREFERENCE`` is set to ``STANDARD``.
+
+ .. note::
+
+ For multi-config generators, this module does not support
+ configuration-specific files generated by ``SWIG``. All build
+ configurations must result in the same generated source file.
+
+ ``TYPE``
+ ``SHARED``, ``MODULE`` and ``STATIC`` have the same semantic as for the
+ :command:`add_library` command. If ``USE_BUILD_SHARED_LIBS`` is specified,
+ the library type will be ``STATIC`` or ``SHARED`` based on whether the
+ current value of the :variable:`BUILD_SHARED_LIBS` variable is ``ON``. If
+ no type is specified, ``MODULE`` will be used.
+
+ ``LANGUAGE``
+ Specify the target language.
+
+ ``NO_PROXY``
+ Prevent the generation of the wrapper layer (swig ``-noproxy`` option).
+
+ ``OUTPUT_DIR``
+ Specify where to write the language specific files (swig ``-outdir``
+ option). If not given, the ``CMAKE_SWIG_OUTDIR`` variable will be used.
+ If neither is specified, the default depends on the value of the
+ ``UseSWIG_MODULE_VERSION`` variable as follows:
+
+ * If ``UseSWIG_MODULE_VERSION`` is 1 or is undefined, output is written to
+ the :variable:`CMAKE_CURRENT_BINARY_DIR` directory.
+ * If ``UseSWIG_MODULE_VERSION`` is 2, a dedicated directory will be used.
+ The path of this directory can be retrieved from the
+ ``SWIG_SUPPORT_FILES_DIRECTORY`` target property.
+
+ ``OUTFILE_DIR``
+ Specify an output directory name where the generated source file will be
+ placed (swig -o option). If not specified, the ``SWIG_OUTFILE_DIR`` variable
+ will be used. If neither is specified, ``OUTPUT_DIR`` or
+ ``CMAKE_SWIG_OUTDIR`` is used instead.
+
+ ``SOURCES``
+ List of sources for the library. Files with extension ``.i`` will be
+ identified as sources for the ``SWIG`` tool. Other files will be handled in
+ the standard way.
+
+ .. note::
+
+ If ``UseSWIG_MODULE_VERSION`` is set to 2, it is **strongly** recommended
+ to use a dedicated directory unique to the target when either the
+ ``OUTPUT_DIR`` option or the ``CMAKE_SWIG_OUTDIR`` variable are specified.
+ The output directory contents are erased as part of the target build, so
+ to prevent interference between targets or losing other important files,
+ each target should have its own dedicated output directory.
.. command:: swig_link_libraries
Link libraries to swig module::
- swig_link_libraries(<name> [ libraries ])
+ swig_link_libraries(<name> <item>...)
+
+ This command has same capabilities as :command:`target_link_libraries`
+ command.
+
+ .. note::
-Source file properties on module files can be set before the invocation
-of the ``swig_add_library`` macro to specify special behavior of SWIG:
+ If variable ``UseSWIG_TARGET_NAME_PREFERENCE`` is set to ``STANDARD``, this
+ command is deprecated and :command:`target_link_libraries` command must be
+ used instead.
+
+Source file properties on module files **must** be set before the invocation
+of the ``swig_add_library`` command to specify special behavior of SWIG and
+ensure generated files will receive the required settings.
``CPLUSPLUS``
Call SWIG in c++ mode. For example:
set_property(SOURCE mymod.i PROPERTY CPLUSPLUS ON)
swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
-``SWIG_FLAGS``
- Add custom flags to the SWIG executable.
+``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS`` and ``COMPILE_OPTIONS``
+ Add custom flags to SWIG compiler and have same semantic as properties
+ :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
+ :prop_sf:`COMPILE_OPTIONS`.
+
+``GENERATED_INCLUDE_DIRECTORIES``, ``GENERATED_COMPILE_DEFINITIONS`` and ``GENERATED_COMPILE_OPTIONS``
+ Add custom flags to the C/C++ generated source. They will fill, respectively,
+ properties :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
+ :prop_sf:`COMPILE_OPTIONS` of generated C/C++ file.
+``DEPENDS``
+ Specify additional dependencies to the source file.
``SWIG_MODULE_NAME``
Specify the actual import name of the module in the target language.
set_property(SOURCE mymod.i PROPERTY SWIG_MODULE_NAME mymod_realname)
-Some variables can be set to specify special behavior of SWIG:
+Target library properties can be set to apply same configuration to all SWIG
+input files.
+
+``SWIG_INCLUDE_DIRECTORIES``, ``SWIG_COMPILE_DEFINITIONS`` and ``SWIG_COMPILE_OPTIONS``
+ These properties will be applied to all SWIG input files and have same
+ semantic as target properties :prop_tgt:`INCLUDE_DIRECTORIES`,
+ :prop_tgt:`COMPILE_DEFINITIONS` and :prop_tgt:`COMPILE_OPTIONS`.
+
+ .. code-block:: cmake
+
+ set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
+ swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
+ set_property(TARGET mymod PROPERTY SWIG_COMPILE_DEFINITIONS MY_DEF1 MY_DEF2)
+ set_property(TARGET mymod PROPERTY SWIG_COMPILE_OPTIONS -bla -blb)
+
+``SWIG_GENERATED_INCLUDE_DIRECTORIES``, ``SWIG_GENERATED_COMPILE_DEFINITIONS`` and ``SWIG_GENERATED_COMPILE_OPTIONS``
+ These properties will populate, respectively, properties
+ :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
+ :prop_sf:`COMPILE_FLAGS` of all generated C/C++ files.
+
+``SWIG_DEPENDS``
+ Add dependencies to all SWIG input files.
+
+The following target properties are output properties and can be used to get
+information about support files generated by ``SWIG`` interface compilation.
+
+``SWIG_SUPPORT_FILES``
+ This output property list of wrapper files generated during SWIG compilation.
+
+ .. code-block:: cmake
+
+ set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
+ swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
+ get_property(support_files TARGET mymod PROPERTY SWIG_SUPPORT_FILES)
+
+ .. note::
+
+ Only most principal support files are listed. In case some advanced
+ features of ``SWIG`` are used (for example ``%template``), associated
+ support files may not be listed. Prefer to use the
+ ``SWIG_SUPPORT_FILES_DIRECTORY`` property to handle support files.
+
+``SWIG_SUPPORT_FILES_DIRECTORY``
+ This output property specifies the directory where support files will be
+ generated.
+
+Some variables can be set to customize the behavior of ``swig_add_library``
+as well as ``SWIG``:
+
+``UseSWIG_TARGET_NAME_PREFERENCE``
+ Specify target name strategy.
+
+ * Set to ``LEGACY`` or undefined: legacy strategy is applied. Variable
+ ``SWIG_MODULE_<name>_REAL_NAME`` must be used to get real target name.
+ * Set to ``STANDARD``: target name matches specified name.
+
+``UseSWIG_MODULE_VERSION``
+ Specify different behaviors for ``UseSWIG`` module.
+
+ * Set to 1 or undefined: Legacy behavior is applied.
+ * Set to 2: A new strategy is applied regarding support files: the output
+ directory of support files is erased before ``SWIG`` interface compilation.
``CMAKE_SWIG_FLAGS``
Add flags to all swig calls.
Specify extra dependencies for the generated module for ``<name>``.
#]=======================================================================]
+
+cmake_policy (VERSION 3.12)
+
set(SWIG_CXX_EXTENSION "cxx")
set(SWIG_EXTRA_LIBRARIES "")
set(SWIG_PYTHON_EXTRA_FILE_EXTENSIONS ".py")
set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
+set(SWIG_CSHARP_EXTRA_FILE_EXTENSIONS ".cs" "PINVOKE.cs")
+
+##
+## PRIVATE functions
+##
+function (__SWIG_COMPUTE_TIMESTAMP name language infile workingdir __timestamp)
+ get_filename_component(filename "${infile}" NAME_WE)
+ set(${__timestamp}
+ "${workingdir}/${filename}${language}.stamp" PARENT_SCOPE)
+ # get_filename_component(filename "${infile}" ABSOLUTE)
+ # string(UUID uuid NAMESPACE 9735D882-D2F8-4E1D-88C9-A0A4F1F6ECA4
+ # NAME ${name}-${language}-${filename} TYPE SHA1)
+ # set(${__timestamp} "${workingdir}/${uuid}.stamp" PARENT_SCOPE)
+endfunction()
#
# For given swig module initialize variables associated with it
#
macro(SWIG_MODULE_INITIALIZE name language)
- string(TOUPPER "${language}" swig_uppercase_language)
- string(TOLOWER "${language}" swig_lowercase_language)
- set(SWIG_MODULE_${name}_LANGUAGE "${swig_uppercase_language}")
- set(SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${swig_lowercase_language}")
+ string(TOUPPER "${language}" SWIG_MODULE_${name}_LANGUAGE)
+ string(TOLOWER "${language}" SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG)
- set(SWIG_MODULE_${name}_REAL_NAME "${name}")
- if (";${CMAKE_SWIG_FLAGS};" MATCHES ";-noproxy;")
+ set(SWIG_MODULE_${name}_EXTRA_FLAGS)
+ if (NOT DEFINED SWIG_MODULE_${name}_NOPROXY)
+ set (SWIG_MODULE_${name}_NOPROXY FALSE)
+ endif()
+ if ("-noproxy" IN_LIST CMAKE_SWIG_FLAGS)
set (SWIG_MODULE_${name}_NOPROXY TRUE)
endif ()
- if("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xUNKNOWN")
+
+ if (SWIG_MODULE_${name}_NOPROXY AND NOT "-noproxy" IN_LIST CMAKE_SWIG_FLAGS)
+ list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-noproxy")
+ endif()
+ if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "UNKNOWN")
message(FATAL_ERROR "SWIG Error: Language \"${language}\" not found")
- elseif("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xPYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY)
- # swig will produce a module.py containing an 'import _modulename' statement,
- # which implies having a corresponding _modulename.so (*NIX), _modulename.pyd (Win32),
- # unless the -noproxy flag is used
- set(SWIG_MODULE_${name}_REAL_NAME "_${name}")
- elseif("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xPERL")
- set(SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
+ elseif(SWIG_MODULE_${name}_LANGUAGE STREQUAL "PERL")
+ list(APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
endif()
endmacro()
# will be generated. This is internal swig macro.
#
-macro(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
- set(${outfiles} "")
- get_source_file_property(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename
- ${infile} SWIG_MODULE_NAME)
- if(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND")
+function(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
+ set(files)
+ get_source_file_property(module_basename
+ "${infile}" SWIG_MODULE_NAME)
+ if(NOT module_basename)
# try to get module name from "%module foo" syntax
- if ( EXISTS ${infile} )
- file ( STRINGS ${infile} _MODULE_NAME REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" )
+ if ( EXISTS "${infile}" )
+ file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" )
endif ()
- if ( _MODULE_NAME )
- string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" _MODULE_NAME "${_MODULE_NAME}" )
- set(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${_MODULE_NAME}")
+ if ( module_basename )
+ string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
else ()
# try to get module name from "%module (options=...) foo" syntax
- if ( EXISTS ${infile} )
- file ( STRINGS ${infile} _MODULE_NAME REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" )
+ if ( EXISTS "${infile}" )
+ file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" )
endif ()
- if ( _MODULE_NAME )
- string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" _MODULE_NAME "${_MODULE_NAME}" )
- set(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${_MODULE_NAME}")
+ if ( module_basename )
+ string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
else ()
# fallback to file basename
- get_filename_component(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename ${infile} NAME_WE)
+ get_filename_component(module_basename "${infile}" NAME_WE)
endif ()
endif ()
endif()
foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSIONS})
- set(extra_file "${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}${it}")
- list(APPEND ${outfiles} ${extra_file})
- # Treat extra outputs as plain files regardless of language.
- set_property(SOURCE "${extra_file}" PROPERTY LANGUAGE "")
+ set(extra_file "${generatedpath}/${module_basename}${it}")
+ if (extra_file MATCHES "\\.cs$")
+ set_source_files_properties(${extra_file} PROPERTIES LANGUAGE "CSharp")
+ else()
+ # Treat extra outputs as plain files regardless of language.
+ set_source_files_properties(${extra_file} PROPERTIES LANGUAGE "")
+ endif()
+ list(APPEND files "${extra_file}")
endforeach()
-endmacro()
+
+ set (${outfiles} ${files} PARENT_SCOPE)
+endfunction()
#
# Take swig (*.i) file and add proper custom commands for it
#
-macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
- set(swig_full_infile ${infile})
+function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
get_filename_component(swig_source_file_name_we "${infile}" NAME_WE)
- get_source_file_property(swig_source_file_generated ${infile} GENERATED)
- get_source_file_property(swig_source_file_cplusplus ${infile} CPLUSPLUS)
- get_source_file_property(swig_source_file_flags ${infile} SWIG_FLAGS)
- if("${swig_source_file_flags}" STREQUAL "NOTFOUND")
- set(swig_source_file_flags "")
- endif()
- get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE)
+ get_source_file_property(swig_source_file_cplusplus "${infile}" CPLUSPLUS)
# If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir
if(CMAKE_SWIG_OUTDIR)
- set(swig_outdir ${CMAKE_SWIG_OUTDIR})
+ set(outdir ${CMAKE_SWIG_OUTDIR})
else()
- set(swig_outdir ${CMAKE_CURRENT_BINARY_DIR})
+ set(outdir ${CMAKE_CURRENT_BINARY_DIR})
endif()
if(SWIG_OUTFILE_DIR)
- set(swig_outfile_dir ${SWIG_OUTFILE_DIR})
+ set(outfiledir ${SWIG_OUTFILE_DIR})
+ else()
+ set(outfiledir ${outdir})
+ endif()
+
+ if(SWIG_WORKING_DIR)
+ set (workingdir "${SWIG_WORKING_DIR}")
else()
- set(swig_outfile_dir ${swig_outdir})
+ set(workingdir "${outdir}")
endif()
+ if(SWIG_TARGET_NAME)
+ set(target_name ${SWIG_TARGET_NAME})
+ else()
+ set(target_name ${name})
+ endif()
+
+ set (swig_source_file_flags ${CMAKE_SWIG_FLAGS})
+ # handle various swig compile flags properties
+ get_source_file_property (include_directories "${infile}" INCLUDE_DIRECTORIES)
+ if (include_directories)
+ list (APPEND swig_source_file_flags "$<$<BOOL:${include_directories}>:-I$<JOIN:${include_directories},$<SEMICOLON>-I>>")
+ endif()
+ set (property "$<TARGET_PROPERTY:${target_name},SWIG_INCLUDE_DIRECTORIES>")
+ list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:$<TARGET_GENEX_EVAL:${target_name},${property}>,$<SEMICOLON>-I>>")
+
+ set (property "$<TARGET_PROPERTY:${target_name},SWIG_COMPILE_DEFINITIONS>")
+ list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-D$<JOIN:$<TARGET_GENEX_EVAL:${target_name},${property}>,$<SEMICOLON>-D>>")
+ get_source_file_property (compile_definitions "${infile}" COMPILE_DEFINITIONS)
+ if (compile_definitions)
+ list (APPEND swig_source_file_flags "$<$<BOOL:${compile_definitions}>:-D$<JOIN:${compile_definitions},$<SEMICOLON>-D>>")
+ endif()
+
+ list (APPEND swig_source_file_flags "$<TARGET_GENEX_EVAL:${target_name},$<TARGET_PROPERTY:${target_name},SWIG_COMPILE_OPTIONS>>")
+ get_source_file_property (compile_options "${infile}" COMPILE_OPTIONS)
+ if (compile_options)
+ list (APPEND swig_source_file_flags ${compile_options})
+ endif()
+
+ # legacy support
+ get_source_file_property (swig_flags "${infile}" SWIG_FLAGS)
+ if (swig_flags)
+ list (APPEND swig_source_file_flags ${swig_flags})
+ endif()
+
+ get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE)
+
if (NOT SWIG_MODULE_${name}_NOPROXY)
SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE}
swig_extra_generated_files
- "${swig_outdir}"
+ "${outdir}"
"${swig_source_file_fullname}")
endif()
set(swig_generated_file_fullname
- "${swig_outfile_dir}/${swig_source_file_name_we}")
+ "${outfiledir}/${swig_source_file_name_we}")
# add the language into the name of the file (i.e. TCL_wrap)
# this allows for the same .i file to be wrapped into different languages
string(APPEND swig_generated_file_fullname
".c")
endif()
- #message("Full path to source file: ${swig_source_file_fullname}")
- #message("Full path to the output file: ${swig_generated_file_fullname}")
- get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
- list(REMOVE_DUPLICATES cmake_include_directories)
- set(swig_include_dirs)
- foreach(it ${cmake_include_directories})
- set(swig_include_dirs ${swig_include_dirs} "-I${it}")
- endforeach()
+ get_directory_property (cmake_include_directories INCLUDE_DIRECTORIES)
+ list (REMOVE_DUPLICATES cmake_include_directories)
+ set (swig_include_dirs)
+ if (cmake_include_directories)
+ set (swig_include_dirs "$<$<BOOL:${cmake_include_directories}>:-I$<JOIN:${cmake_include_directories},$<SEMICOLON>-I>>")
+ endif()
set(swig_special_flags)
# default is c, so add c++ flag if it is c++
if(swig_source_file_cplusplus)
- set(swig_special_flags ${swig_special_flags} "-c++")
+ list (APPEND swig_special_flags "-c++")
endif()
- if("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xCSHARP")
- if(NOT ";${swig_source_file_flags};${CMAKE_SWIG_FLAGS};" MATCHES ";-dllimport;")
+
+ set (swig_extra_flags)
+ if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "CSHARP")
+ if(NOT ("-dllimport" IN_LIST swig_source_file_flags OR "-dllimport" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS))
# This makes sure that the name used in the generated DllImport
# matches the library name created by CMake
- set(SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport;${name}")
+ list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport" "${name}")
endif()
endif()
- set(swig_extra_flags)
- if(SWIG_MODULE_${name}_EXTRA_FLAGS)
- set(swig_extra_flags ${swig_extra_flags} ${SWIG_MODULE_${name}_EXTRA_FLAGS})
+ list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS})
+
+ # dependencies
+ set (swig_dependencies ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${target_name},SWIG_DEPENDS>)
+ get_source_file_property(file_depends "${infile}" DEPENDS)
+ if (file_depends)
+ list (APPEND swig_dependencies ${file_depends})
+ endif()
+
+ if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
+ # as part of custom command, start by removing old generated files
+ # to ensure obsolete files do not stay
+ set (swig_cleanup_command COMMAND "${CMAKE_COMMAND}" -E remove_directory "${outdir}")
+ else()
+ unset (swig_cleanup_command)
endif()
+
# IMPLICIT_DEPENDS below can not handle situations where a dependent file is
# removed. We need an extra step with timestamp and custom target, see #16830
# As this is needed only for Makefile generator do it conditionally
if(CMAKE_GENERATOR MATCHES "Make")
- get_filename_component(swig_generated_timestamp
- "${swig_generated_file_fullname}" NAME_WE)
- set(swig_gen_target gen_${name}_${swig_generated_timestamp})
- set(swig_generated_timestamp
- "${swig_outdir}/${swig_generated_timestamp}.stamp")
- set(swig_custom_output ${swig_generated_timestamp})
+ __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE}
+ "${infile}" "${workingdir}" swig_generated_timestamp)
+ set(swig_custom_output "${swig_generated_timestamp}")
set(swig_custom_products
BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files})
set(swig_timestamp_command
- COMMAND ${CMAKE_COMMAND} -E touch ${swig_generated_timestamp})
+ COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}")
else()
set(swig_custom_output
"${swig_generated_file_fullname}" ${swig_extra_generated_files})
add_custom_command(
OUTPUT ${swig_custom_output}
${swig_custom_products}
- # Let's create the ${swig_outdir} at execution time, in case dir contains $(OutDir)
- COMMAND ${CMAKE_COMMAND} -E make_directory ${swig_outdir}
+ ${swig_cleanup_command}
+ # Let's create the ${outdir} at execution time, in case dir contains $(OutDir)
+ COMMAND "${CMAKE_COMMAND}" -E make_directory ${outdir} ${outfiledir}
${swig_timestamp_command}
- COMMAND "${SWIG_EXECUTABLE}"
- ARGS "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
- ${swig_source_file_flags}
- ${CMAKE_SWIG_FLAGS}
- -outdir ${swig_outdir}
+ COMMAND "${CMAKE_COMMAND}" -E env "SWIG_LIB=${SWIG_DIR}" "${SWIG_EXECUTABLE}"
+ "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
+ "${swig_source_file_flags}"
+ -outdir "${outdir}"
${swig_special_flags}
${swig_extra_flags}
- ${swig_include_dirs}
+ "${swig_include_dirs}"
-o "${swig_generated_file_fullname}"
"${swig_source_file_fullname}"
MAIN_DEPENDENCY "${swig_source_file_fullname}"
- DEPENDS ${SWIG_MODULE_${name}_EXTRA_DEPS}
+ DEPENDS ${swig_dependencies}
IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
- COMMENT "Swig source")
- if(CMAKE_GENERATOR MATCHES "Make")
- add_custom_target(${swig_gen_target} DEPENDS ${swig_generated_timestamp})
- endif()
- unset(swig_generated_timestamp)
- unset(swig_custom_output)
- unset(swig_custom_products)
- unset(swig_timestamp_command)
+ COMMENT "Swig source"
+ COMMAND_EXPAND_LISTS)
set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files}
PROPERTIES GENERATED 1)
- set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files})
-endmacro()
+
+ ## add all properties for generated file to various properties
+ get_property (include_directories SOURCE "${infile}" PROPERTY GENERATED_INCLUDE_DIRECTORIES)
+ set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY INCLUDE_DIRECTORIES ${include_directories} $<TARGET_GENEX_EVAL:${target_name},$<TARGET_PROPERTY:${target_name},SWIG_GENERATED_INCLUDE_DIRECTORIES>>)
+
+ get_property (compile_definitions SOURCE "${infile}" PROPERTY GENERATED_COMPILE_DEFINITIONS)
+ set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_DEFINITIONS $<TARGET_GENEX_EVAL:${target_name},$<TARGET_PROPERTY:${target_name},SWIG_GENERATED_COMPILE_DEFINITIONS>> ${compile_definitions})
+
+ get_property (compile_options SOURCE "${infile}" PROPERTY GENERATED_COMPILE_OPTIONS)
+ set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_OPTIONS $<TARGET_GENEX_EVAL:${target_name},$<TARGET_PROPERTY:${target_name},SWIG_GENERATED_COMPILE_OPTIONS>> ${compile_options})
+
+ set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files} PARENT_SCOPE)
+
+ # legacy support
+ set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
+endfunction()
#
# Create Swig module
endmacro()
-macro(SWIG_ADD_LIBRARY name)
- set(options "")
+function(SWIG_ADD_LIBRARY name)
+ set(options NO_PROXY)
set(oneValueArgs LANGUAGE
- TYPE)
+ TYPE
+ OUTPUT_DIR
+ OUTFILE_DIR)
set(multiValueArgs SOURCES)
cmake_parse_arguments(_SAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ if (_SAM_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "SWIG_ADD_LIBRARY: ${_SAM_UNPARSED_ARGUMENTS}: unexpected arguments")
+ endif()
+
if(NOT DEFINED _SAM_LANGUAGE)
message(FATAL_ERROR "SWIG_ADD_LIBRARY: Missing LANGUAGE argument")
endif()
if(NOT DEFINED _SAM_TYPE)
set(_SAM_TYPE MODULE)
- elseif("${_SAM_TYPE}" STREQUAL "USE_BUILD_SHARED_LIBS")
+ elseif(_SAM_TYPE STREQUAL "USE_BUILD_SHARED_LIBS")
unset(_SAM_TYPE)
endif()
+ if (NOT DEFINED UseSWIG_TARGET_NAME_PREFERENCE)
+ set (UseSWIG_TARGET_NAME_PREFERENCE LEGACY)
+ elseif (NOT UseSWIG_TARGET_NAME_PREFERENCE MATCHES "^(LEGACY|STANDARD)$")
+ message (FATAL_ERROR "UseSWIG_TARGET_NAME_PREFERENCE: ${UseSWIG_TARGET_NAME_PREFERENCE}: invalid value. 'LEGACY' or 'STANDARD' is expected.")
+ endif()
+
+ if (NOT DEFINED UseSWIG_MODULE_VERSION)
+ set (UseSWIG_MODULE_VERSION 1)
+ elseif (NOT UseSWIG_MODULE_VERSION MATCHES "^(1|2)$")
+ message (FATAL_ERROR "UseSWIG_MODULE_VERSION: ${UseSWIG_MODULE_VERSION}: invalid value. 1 or 2 is expected.")
+ endif()
+
+ set (SWIG_MODULE_${name}_NOPROXY ${_SAM_NO_PROXY})
swig_module_initialize(${name} ${_SAM_LANGUAGE})
- set(swig_dot_i_sources)
- set(swig_other_sources)
- foreach(it ${_SAM_SOURCES})
- if(${it} MATCHES "\\.i$")
- set(swig_dot_i_sources ${swig_dot_i_sources} "${it}")
+ # compute real target name.
+ if (UseSWIG_TARGET_NAME_PREFERENCE STREQUAL "LEGACY" AND
+ SWIG_MODULE_${name}_LANGUAGE STREQUAL "PYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY)
+ # swig will produce a module.py containing an 'import _modulename' statement,
+ # which implies having a corresponding _modulename.so (*NIX), _modulename.pyd (Win32),
+ # unless the -noproxy flag is used
+ set(target_name "_${name}")
+ else()
+ set(target_name "${name}")
+ endif()
+
+ if (TARGET ${target_name})
+ # a target with same name is already defined.
+ # call NOW add_library command to raise the most useful error message
+ add_library(${target_name})
+ return()
+ endif()
+
+ set (workingdir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${target_name}.dir")
+ # set special variable to pass extra information to command SWIG_ADD_SOURCE_TO_MODULE
+ # which cannot be changed due to legacy compatibility
+ set (SWIG_WORKING_DIR "${workingdir}")
+ set (SWIG_TARGET_NAME "${target_name}")
+
+ set (outputdir "${_SAM_OUTPUT_DIR}")
+ if (NOT _SAM_OUTPUT_DIR)
+ if (CMAKE_SWIG_OUTDIR)
+ set (outputdir "${CMAKE_SWIG_OUTDIR}")
else()
- set(swig_other_sources ${swig_other_sources} "${it}")
+ if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
+ set (outputdir "${workingdir}/${_SAM_LANGUAGE}.files")
+ else()
+ set (outputdir "${CMAKE_CURRENT_BINARY_DIR}")
+ endif()
endif()
- endforeach()
+ endif()
+
+ set (outfiledir "${_SAM_OUTFILE_DIR}")
+ if(NOT _SAM_OUTFILE_DIR)
+ if (SWIG_OUTFILE_DIR)
+ set (outfiledir "${SWIG_OUTFILE_DIR}")
+ else()
+ if (_SAM_OUTPUT_DIR OR CMAKE_SWIG_OUTDIR)
+ set (outfiledir "${outputdir}")
+ else()
+ set (outfiledir "${workingdir}")
+ endif()
+ endif()
+ endif()
+ # set again, locally, predefined variables to ensure compatibility
+ # with command SWIG_ADD_SOURCE_TO_MODULE
+ set(CMAKE_SWIG_OUTDIR "${outputdir}")
+ set(SWIG_OUTFILE_DIR "${outfiledir}")
+
+ set(swig_dot_i_sources ${_SAM_SOURCES})
+ list(FILTER swig_dot_i_sources INCLUDE REGEX "\\.i$")
+ if (NOT swig_dot_i_sources)
+ message(FATAL_ERROR "SWIG_ADD_LIBRARY: no SWIG interface files specified")
+ endif()
+ set(swig_other_sources ${_SAM_SOURCES})
+ list(REMOVE_ITEM swig_other_sources ${swig_dot_i_sources})
set(swig_generated_sources)
- set(swig_generated_targets)
- foreach(it ${swig_dot_i_sources})
- SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source ${it})
- set(swig_generated_sources ${swig_generated_sources} "${swig_generated_source}")
- list(APPEND swig_generated_targets "${swig_gen_target}")
+ set(swig_generated_timestamps)
+ foreach(swig_it IN LISTS swig_dot_i_sources)
+ SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source "${swig_it}")
+ list (APPEND swig_generated_sources "${swig_generated_source}")
+ if(CMAKE_GENERATOR MATCHES "Make")
+ __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE} "${swig_it}"
+ "${workingdir}" swig_timestamp)
+ list (APPEND swig_generated_timestamps "${swig_timestamp}")
+ endif()
endforeach()
- get_directory_property(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
- set_directory_properties(PROPERTIES
- ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources}")
- add_library(${SWIG_MODULE_${name}_REAL_NAME}
+ set_property (DIRECTORY APPEND PROPERTY
+ ADDITIONAL_MAKE_CLEAN_FILES ${swig_generated_sources} ${swig_generated_timestamps})
+ if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
+ set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${outputdir}")
+ endif()
+
+ add_library(${target_name}
${_SAM_TYPE}
${swig_generated_sources}
${swig_other_sources})
if(CMAKE_GENERATOR MATCHES "Make")
# see IMPLICIT_DEPENDS above
- add_dependencies(${SWIG_MODULE_${name}_REAL_NAME} ${swig_generated_targets})
+ add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps})
+ add_dependencies(${target_name} ${name}_swig_compilation)
endif()
- if("${_SAM_TYPE}" STREQUAL "MODULE")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES NO_SONAME ON)
+ if(_SAM_TYPE STREQUAL "MODULE")
+ set_target_properties(${target_name} PROPERTIES NO_SONAME ON)
endif()
string(TOLOWER "${_SAM_LANGUAGE}" swig_lowercase_language)
- if ("${swig_lowercase_language}" STREQUAL "octave")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".oct")
- elseif ("${swig_lowercase_language}" STREQUAL "go")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
- elseif ("${swig_lowercase_language}" STREQUAL "java")
+ if (swig_lowercase_language STREQUAL "octave")
+ set_target_properties(${target_name} PROPERTIES PREFIX "")
+ set_target_properties(${target_name} PROPERTIES SUFFIX ".oct")
+ elseif (swig_lowercase_language STREQUAL "go")
+ set_target_properties(${target_name} PROPERTIES PREFIX "")
+ elseif (swig_lowercase_language STREQUAL "java")
+ # In java you want:
+ # System.loadLibrary("LIBRARY");
+ # then JNI will look for a library whose name is platform dependent, namely
+ # MacOS : libLIBRARY.jnilib
+ # Windows: LIBRARY.dll
+ # Linux : libLIBRARY.so
if (APPLE)
- # In java you want:
- # System.loadLibrary("LIBRARY");
- # then JNI will look for a library whose name is platform dependent, namely
- # MacOS : libLIBRARY.jnilib
- # Windows: LIBRARY.dll
- # Linux : libLIBRARY.so
- set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".jnilib")
- endif ()
- elseif ("${swig_lowercase_language}" STREQUAL "lua")
- if("${_SAM_TYPE}" STREQUAL "MODULE")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+ set_target_properties (${target_name} PROPERTIES SUFFIX ".jnilib")
+ endif()
+ if ((WIN32 AND MINGW) OR CYGWIN OR CMAKE_SYSTEM_NAME STREQUAL MSYS)
+ set_target_properties(${target_name} PROPERTIES PREFIX "")
+ endif()
+ elseif (swig_lowercase_language STREQUAL "lua")
+ if(_SAM_TYPE STREQUAL "MODULE")
+ set_target_properties(${target_name} PROPERTIES PREFIX "")
+ endif()
+ elseif (swig_lowercase_language STREQUAL "python")
+ if (UseSWIG_TARGET_NAME_PREFERENCE STREQUAL "STANDARD" AND NOT SWIG_MODULE_${name}_NOPROXY)
+ # swig will produce a module.py containing an 'import _modulename' statement,
+ # which implies having a corresponding _modulename.so (*NIX), _modulename.pyd (Win32),
+ # unless the -noproxy flag is used
+ set_target_properties(${target_name} PROPERTIES PREFIX "_")
+ else()
+ set_target_properties(${target_name} PROPERTIES PREFIX "")
endif()
- elseif ("${swig_lowercase_language}" STREQUAL "python")
- # this is only needed for the python case where a _modulename.so is generated
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
# Python extension modules on Windows must have the extension ".pyd"
# instead of ".dll" as of Python 2.5. Older python versions do support
# this suffix.
# .pyd is now the only filename extension that will be searched for.
# </quote>
if(WIN32 AND NOT CYGWIN)
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".pyd")
+ set_target_properties(${target_name} PROPERTIES SUFFIX ".pyd")
endif()
- elseif ("${swig_lowercase_language}" STREQUAL "r")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
- elseif ("${swig_lowercase_language}" STREQUAL "ruby")
+ elseif (swig_lowercase_language STREQUAL "r")
+ set_target_properties(${target_name} PROPERTIES PREFIX "")
+ elseif (swig_lowercase_language STREQUAL "ruby")
# In ruby you want:
# require 'LIBRARY'
# then ruby will look for a library whose name is platform dependent, namely
# MacOS : LIBRARY.bundle
# Windows: LIBRARY.dll
# Linux : LIBRARY.so
- set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+ set_target_properties (${target_name} PROPERTIES PREFIX "")
if (APPLE)
- set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".bundle")
+ set_target_properties (${target_name} PROPERTIES SUFFIX ".bundle")
+ endif ()
+ elseif (swig_lowercase_language STREQUAL "perl")
+ # assume empty prefix because we expect the module to be dynamically loaded
+ set_target_properties (${target_name} PROPERTIES PREFIX "")
+ if (APPLE)
+ set_target_properties (${target_name} PROPERTIES SUFFIX ".dylib")
endif ()
else()
# assume empty prefix because we expect the module to be dynamically loaded
- set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+ set_target_properties (${target_name} PROPERTIES PREFIX "")
endif ()
-endmacro()
+
+ # target property SWIG_SUPPORT_FILES_DIRECTORY specify output directory of support files
+ set_property (TARGET ${target_name} PROPERTY SWIG_SUPPORT_FILES_DIRECTORY "${outputdir}")
+ # target property SWIG_SUPPORT_FILES lists principal proxy support files
+ if (NOT SWIG_MODULE_${name}_NOPROXY)
+ string(TOUPPER "${_SAM_LANGUAGE}" swig_uppercase_language)
+ set(swig_all_support_files)
+ foreach (swig_it IN LISTS SWIG_${swig_uppercase_language}_EXTRA_FILE_EXTENSIONS)
+ set (swig_support_files ${swig_generated_sources})
+ list (FILTER swig_support_files INCLUDE REGEX ".*${swig_it}$")
+ list(APPEND swig_all_support_files ${swig_support_files})
+ endforeach()
+ if (swig_all_support_files)
+ list(REMOVE_DUPLICATES swig_all_support_files)
+ endif()
+ set_property (TARGET ${target_name} PROPERTY SWIG_SUPPORT_FILES ${swig_all_support_files})
+ endif()
+
+ # to ensure legacy behavior, export some variables
+ set (SWIG_MODULE_${name}_LANGUAGE "${SWIG_MODULE_${name}_LANGUAGE}" PARENT_SCOPE)
+ set (SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" PARENT_SCOPE)
+ set (SWIG_MODULE_${name}_REAL_NAME "${target_name}" PARENT_SCOPE)
+ set (SWIG_MODULE_${name}_NOPROXY "${SWIG_MODULE_${name}_NOPROXY}" PARENT_SCOPE)
+ set (SWIG_MODULE_${name}_EXTRA_FLAGS "${SWIG_MODULE_${name}_EXTRA_FLAGS}" PARENT_SCOPE)
+ # the last one is a bit crazy but it is documented, so...
+ # NOTA: works as expected if only ONE input file is specified
+ set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
+endfunction()
#
# Like TARGET_LINK_LIBRARIES but for swig modules
#
-macro(SWIG_LINK_LIBRARIES name)
- if(SWIG_MODULE_${name}_REAL_NAME)
- target_link_libraries(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN})
+function(SWIG_LINK_LIBRARIES name)
+ if (UseSWIG_TARGET_NAME_PREFERENCE STREQUAL "STANDARD")
+ message(DEPRECATION "SWIG_LINK_LIBRARIES is deprecated. Use TARGET_LINK_LIBRARIES instead.")
+ target_link_libraries(${name} ${ARGN})
else()
- message(SEND_ERROR "Cannot find Swig library \"${name}\".")
+ if(SWIG_MODULE_${name}_REAL_NAME)
+ target_link_libraries(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN})
+ else()
+ message(SEND_ERROR "Cannot find Swig library \"${name}\".")
+ endif()
endif()
-endmacro()
+endfunction()
# [OUTPUT_FILES_VAR <output_files_var> OUTPUT_DIR <output_dir>]
# COMPILERS <compiler> [...]
# FEATURES <feature> [...]
+# [BARE_FEATURES <feature> [...]]
# [VERSION <version>]
# [PROLOG <prolog>]
# [EPILOG <epilog>]
# See the :manual:`cmake-compile-features(7)` manual for information on
# compile features.
#
+# ``BARE_FEATURES`` will define the compatibility macros with the name used in
+# newer versions of the language standard, so the code can use the new feature
+# name unconditionally.
+#
# ``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` cause
# the module to generate conditions that treat unknown compilers as simply
# lacking all features. Without these options the default behavior is to
-# generate a ``#error`` for unknown compilers.
+# generate a ``#error`` for unknown compilers and versions.
#
# Feature Test Macros
# ===================
# ``ClimbingStats_CONSTEXPR`` macro will expand to ``constexpr``
# if ``cxx_constexpr`` is supported.
#
-# The following features generate corresponding symbol defines:
+# If ``BARE_FEATURES cxx_final`` was given as argument the ``final`` keyword
+# will be defined for old compilers, too.
+#
+# The following features generate corresponding symbol defines and if they
+# are available as ``BARE_FEATURES``:
#
-# ========================== =================================== =================
-# Feature Define Symbol
-# ========================== =================================== =================
-# ``c_restrict`` ``<PREFIX>_RESTRICT`` ``restrict``
-# ``cxx_constexpr`` ``<PREFIX>_CONSTEXPR`` ``constexpr``
+# ========================== =================================== ================= ======
+# Feature Define Symbol bare
+# ========================== =================================== ================= ======
+# ``c_restrict`` ``<PREFIX>_RESTRICT`` ``restrict`` yes
+# ``cxx_constexpr`` ``<PREFIX>_CONSTEXPR`` ``constexpr`` yes
# ``cxx_deleted_functions`` ``<PREFIX>_DELETED_FUNCTION`` ``= delete``
# ``cxx_extern_templates`` ``<PREFIX>_EXTERN_TEMPLATE`` ``extern``
-# ``cxx_final`` ``<PREFIX>_FINAL`` ``final``
-# ``cxx_noexcept`` ``<PREFIX>_NOEXCEPT`` ``noexcept``
+# ``cxx_final`` ``<PREFIX>_FINAL`` ``final`` yes
+# ``cxx_noexcept`` ``<PREFIX>_NOEXCEPT`` ``noexcept`` yes
# ``cxx_noexcept`` ``<PREFIX>_NOEXCEPT_EXPR(X)`` ``noexcept(X)``
-# ``cxx_override`` ``<PREFIX>_OVERRIDE`` ``override``
-# ========================== =================================== =================
+# ``cxx_override`` ``<PREFIX>_OVERRIDE`` ``override`` yes
+# ========================== =================================== ================= ======
#
# Compatibility Implementation Macros
# ===================================
# decorator or a compiler-specific decorator such as ``__alignof__``
# used by GNU compilers.
#
-# ============================= ================================ =====================
-# Feature Define Symbol
-# ============================= ================================ =====================
+# ============================= ================================ ===================== ======
+# Feature Define Symbol bare
+# ============================= ================================ ===================== ======
# ``cxx_alignas`` ``<PREFIX>_ALIGNAS`` ``alignas``
# ``cxx_alignof`` ``<PREFIX>_ALIGNOF`` ``alignof``
-# ``cxx_nullptr`` ``<PREFIX>_NULLPTR`` ``nullptr``
+# ``cxx_nullptr`` ``<PREFIX>_NULLPTR`` ``nullptr`` yes
# ``cxx_static_assert`` ``<PREFIX>_STATIC_ASSERT`` ``static_assert``
# ``cxx_static_assert`` ``<PREFIX>_STATIC_ASSERT_MSG`` ``static_assert``
# ``cxx_attribute_deprecated`` ``<PREFIX>_DEPRECATED`` ``[[deprecated]]``
# ``cxx_attribute_deprecated`` ``<PREFIX>_DEPRECATED_MSG`` ``[[deprecated]]``
# ``cxx_thread_local`` ``<PREFIX>_THREAD_LOCAL`` ``thread_local``
-# ============================= ================================ =====================
+# ============================= ================================ ===================== ======
#
# A use-case which arises with such deprecation macros is the deprecation
# of an entire library. In that case, all public API in the library may
endif()
endmacro()
+macro(_simplebaredefine FEATURE_NAME FEATURE_STRING FEATURE_DEFAULT_STRING)
+ if (feature STREQUAL "${FEATURE_NAME}")
+ string(APPEND file_content "
+# if !(defined(${def_name}) && ${def_name})
+# define ${FEATURE_STRING} ${FEATURE_DEFAULT_STRING}
+# endif
+\n")
+ endif()
+endmacro()
+
+function(_check_feature_lists C_FEATURE_VAR CXX_FEATURE_VAR)
+ foreach(feature ${ARGN})
+ if (feature MATCHES "^c_std_")
+ # ignored
+ elseif (feature MATCHES "^cxx_std_")
+ # ignored
+ elseif (feature MATCHES "^cxx_")
+ list(APPEND _langs CXX)
+ list(APPEND ${CXX_FEATURE_VAR} ${feature})
+ elseif (feature MATCHES "^c_")
+ list(APPEND _langs C)
+ list(APPEND ${C_FEATURE_VAR} ${feature})
+ else()
+ message(FATAL_ERROR "Unsupported feature ${feature}.")
+ endif()
+ endforeach()
+ set(${C_FEATURE_VAR} ${${C_FEATURE_VAR}} PARENT_SCOPE)
+ set(${CXX_FEATURE_VAR} ${${CXX_FEATURE_VAR}} PARENT_SCOPE)
+ set(_langs ${_langs} PARENT_SCOPE)
+endfunction()
+
function(write_compiler_detection_header
file_keyword file_arg
prefix_keyword prefix_arg
endif()
set(options ALLOW_UNKNOWN_COMPILERS ALLOW_UNKNOWN_COMPILER_VERSIONS)
set(oneValueArgs VERSION EPILOG PROLOG OUTPUT_FILES_VAR OUTPUT_DIR)
- set(multiValueArgs COMPILERS FEATURES)
+ set(multiValueArgs COMPILERS FEATURES BARE_FEATURES)
cmake_parse_arguments(_WCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT _WCD_COMPILERS)
message(FATAL_ERROR "Invalid arguments. write_compiler_detection_header requires at least one compiler.")
endif()
- if (NOT _WCD_FEATURES)
+ if (NOT _WCD_FEATURES AND NOT _WCD_BARE_FEATURES)
message(FATAL_ERROR "Invalid arguments. write_compiler_detection_header requires at least one feature.")
endif()
)\n")
endif()
- foreach(feature ${_WCD_FEATURES})
- if (feature MATCHES "^c_std_")
- # ignored
- elseif (feature MATCHES "^cxx_std_")
- # ignored
- elseif (feature MATCHES "^cxx_")
- list(APPEND _langs CXX)
- list(APPEND CXX_features ${feature})
- elseif (feature MATCHES "^c_")
- list(APPEND _langs C)
- list(APPEND C_features ${feature})
- else()
- message(FATAL_ERROR "Unsupported feature ${feature}.")
- endif()
- endforeach()
+ _check_feature_lists(C_features CXX_features ${_WCD_FEATURES})
+ _check_feature_lists(C_bare_features CXX_bare_features ${_WCD_BARE_FEATURES})
list(REMOVE_DUPLICATES _langs)
if(_WCD_OUTPUT_FILES_VAR)
# endif
\n")
endif()
- _simpledefine(cxx_nullptr NULLPTR nullptr 0)
+ if (feature STREQUAL cxx_nullptr)
+ set(def_value "${prefix_arg}_NULLPTR")
+ string(APPEND file_content "
+# if defined(${def_name}) && ${def_name}
+# define ${def_value} nullptr
+# elif ${prefix_arg}_COMPILER_IS_GNU
+# define ${def_value} __null
+# else
+# define ${def_value} 0
+# endif
+\n")
+ endif()
if (feature STREQUAL cxx_thread_local)
set(def_value "${prefix_arg}_THREAD_LOCAL")
string(APPEND file_content "
endif()
endforeach()
+ foreach(feature ${${_lang}_bare_features})
+ string(TOUPPER ${feature} feature_upper)
+ set(feature_PP "COMPILER_${feature_upper}")
+ set(def_name ${prefix_arg}_${feature_PP})
+ _simplebaredefine(c_restrict restrict "")
+ _simplebaredefine(cxx_constexpr constexpr "")
+ _simplebaredefine(cxx_final final "")
+ _simplebaredefine(cxx_override override "")
+ if (feature STREQUAL cxx_nullptr)
+ set(def_value "nullptr")
+ string(APPEND file_content "
+# if !(defined(${def_name}) && ${def_name})
+# if ${prefix_arg}_COMPILER_IS_GNU
+# define ${def_value} __null
+# else
+# define ${def_value} 0
+# endif
+# endif
+\n")
+ endif()
+ _simplebaredefine(cxx_noexcept noexcept "")
+ endforeach()
+
string(APPEND file_content "#endif\n")
endforeach()
See the "Find Modules" section of the cmake-developer(7) manual page.
For more information about how to contribute modules to CMake, see this page:
-https://cmake.org/Wiki/CMake:Module_Maintainers
+https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/dev/Module-Maintainers
if(BEOS)
set(CMAKE_BIN_DIR_DEFAULT "bin") # HAIKU
set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # HAIKU
- set(CMAKE_MAN_DIR_DEFAULT "documentation/man") # HAIKU
set(CMAKE_DOC_DIR_DEFAULT "documentation/doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # HAIKU
+ set(CMAKE_INFO_DIR_DEFAULT "documentation/info") # HAIKU
+ set(CMAKE_MAN_DIR_DEFAULT "documentation/man") # HAIKU
set(CMAKE_XDGDATA_DIR_DEFAULT "share") # HAIKU
elseif(CYGWIN)
set(CMAKE_BIN_DIR_DEFAULT "bin") # CYGWIN
set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION}") # CYGWIN
set(CMAKE_DOC_DIR_DEFAULT "share/doc/cmake-${CMake_VERSION}") # CYGWIN
+ set(CMAKE_INFO_DIR_DEFAULT "share/info") # CYGWIN
set(CMAKE_MAN_DIR_DEFAULT "share/man") # CYGWIN
set(CMAKE_XDGDATA_DIR_DEFAULT "share") # CYGWIN
else()
set(CMAKE_BIN_DIR_DEFAULT "bin") # OTHER
set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # OTHER
set(CMAKE_DOC_DIR_DEFAULT "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # OTHER
+ set(CMAKE_INFO_DIR_DEFAULT "info") # OTHER
set(CMAKE_MAN_DIR_DEFAULT "man") # OTHER
set(CMAKE_XDGDATA_DIR_DEFAULT "share") # OTHER
endif()
set(CMAKE_BIN_DIR_DESC "bin")
set(CMAKE_DATA_DIR_DESC "data")
set(CMAKE_DOC_DIR_DESC "docs")
+set(CMAKE_INFO_DIR_DESC "Info manual")
set(CMAKE_MAN_DIR_DESC "man pages")
set(CMAKE_XDGDATA_DIR_DESC "XDG specific files")
CMAKE_BIN_DIR
CMAKE_DATA_DIR
CMAKE_DOC_DIR
+ CMAKE_INFO_DIR
CMAKE_MAN_DIR
CMAKE_XDGDATA_DIR
)
LexerParser/cmListFileLexer.c
LexerParser/cmListFileLexer.in.l
+ cmAffinity.cxx
+ cmAffinity.h
cmArchiveWrite.cxx
cmBase32.cxx
cmCacheManager.cxx
cmGlobalGeneratorFactory.h
cmGlobalUnixMakefileGenerator3.cxx
cmGlobalUnixMakefileGenerator3.h
+ cmGlobVerificationManager.cxx
+ cmGlobVerificationManager.h
cmGraphAdjacencyList.h
cmGraphVizWriter.cxx
cmGraphVizWriter.h
cmCommand.h
cmCommands.cxx
cmCommands.h
+ cmAddCompileDefinitionsCommand.cxx
+ cmAddCompileDefinitionsCommand.h
cmAddCompileOptionsCommand.cxx
cmAddCompileOptionsCommand.h
cmAddCustomCommandCommand.cxx
cmSiteNameCommand.h
cmSourceGroupCommand.cxx
cmSourceGroupCommand.h
+ cmStringReplaceHelper.cxx
cmStringCommand.cxx
cmStringCommand.h
cmSubdirCommand.cxx
CPack/cmCPackGenerator.cxx
CPack/cmCPackLog.cxx
CPack/cmCPackNSISGenerator.cxx
+ CPack/cmCPackNuGetGenerator.cxx
CPack/cmCPackSTGZGenerator.cxx
CPack/cmCPackTGZGenerator.cxx
CPack/cmCPackTXZGenerator.cxx
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
-set(CMake_VERSION_MINOR 11)
-set(CMake_VERSION_PATCH 4)
+set(CMake_VERSION_MINOR 12)
+set(CMake_VERSION_PATCH 0)
#set(CMake_VERSION_RC 0)
# components in the RC file are 16-bit integers so we may have to
# split the patch component.
if(CMake_VERSION_PATCH MATCHES "^([0-9]+)([0-9][0-9][0-9][0-9])$")
- set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMAKE_MATCH_1},${CMAKE_MATCH_2})
+ set(CMake_RCVERSION_YEAR "${CMAKE_MATCH_1}")
+ set(CMake_RCVERSION_MONTH_DAY "${CMAKE_MATCH_2}")
+ string(REGEX REPLACE "^0+" "" CMake_RCVERSION_MONTH_DAY "${CMake_RCVERSION_MONTH_DAY}")
+ set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_RCVERSION_YEAR},${CMake_RCVERSION_MONTH_DAY})
+ unset(CMake_RCVERSION_MONTH_DAY)
+ unset(CMake_RCVERSION_YEAR)
else()
set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH})
endif()
ifwCmd += " --repository " + rd;
}
} else {
- cmCPackIFWLogger(WARNING, "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
+ cmCPackIFWLogger(WARNING,
+ "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
<< "variable is set, but content will be skipped, "
<< "because this feature available only since "
<< "QtIFW 3.1. Please update your QtIFW instance."
ofs << "# Run command: " << ifwCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackIFWLogger(ERROR, "Problem running IFW command: "
+ cmCPackIFWLogger(ERROR,
+ "Problem running IFW command: "
<< ifwCmd << std::endl
<< "Please check " << ifwTmpFile << " for errors"
<< std::endl);
if (!this->Repository.RepositoryUpdate.empty() &&
!this->Repository.PatchUpdatesXml()) {
- cmCPackIFWLogger(WARNING, "Problem patch IFW \"Updates\" "
+ cmCPackIFWLogger(WARNING,
+ "Problem patch IFW \"Updates\" "
<< "file: "
<< this->toplevel + "/repository/Updates.xml"
<< std::endl);
}
- cmCPackIFWLogger(OUTPUT, "- repository: " << this->toplevel
- << "/repository generated"
- << std::endl);
+ cmCPackIFWLogger(OUTPUT,
+ "- repository: " << this->toplevel
+ << "/repository generated" << std::endl);
}
// Run binary creator
ifwCmd += " --repository " + rd;
}
} else {
- cmCPackIFWLogger(WARNING, "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
+ cmCPackIFWLogger(WARNING,
+ "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
<< "variable is set, but content will be skipped, "
<< "because this feature available only since "
<< "QtIFW 3.1. Please update your QtIFW instance."
ofs << "# Run command: " << ifwCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackIFWLogger(ERROR, "Problem running IFW command: "
+ cmCPackIFWLogger(ERROR,
+ "Problem running IFW command: "
<< ifwCmd << std::endl
<< "Please check " << ifwTmpFile << " for errors"
<< std::endl);
}
if (this->BinCreator.empty()) {
- cmCPackIFWLogger(ERROR, "Cannot find QtIFW compiler \"binarycreator\": "
- "likely it is not installed, or not in your PATH"
+ cmCPackIFWLogger(ERROR,
+ "Cannot find QtIFW compiler \"binarycreator\": "
+ "likely it is not installed, or not in your PATH"
<< std::endl);
return 0;
}
}
} else {
this->Packages.erase(name);
- cmCPackIFWLogger(ERROR, "Cannot configure package \""
+ cmCPackIFWLogger(ERROR,
+ "Cannot configure package \""
<< name << "\" for component \"" << component->Name
<< "\"" << std::endl);
}
this->BinaryPackages.insert(package);
} else {
this->Packages.erase(name);
- cmCPackIFWLogger(ERROR, "Cannot configure package \""
+ cmCPackIFWLogger(ERROR,
+ "Cannot configure package \""
<< name << "\" for component group \"" << group->Name
<< "\"" << std::endl);
}
} else {
this->Repositories.erase(repositoryName);
repository = nullptr;
- cmCPackIFWLogger(WARNING, "Invalid repository \""
+ cmCPackIFWLogger(WARNING,
+ "Invalid repository \""
<< repositoryName << "\""
<< " configuration. Repository will be skipped."
<< std::endl);
*
* http://qt-project.org/doc/qtinstallerframework/index.html
*/
-class cmCPackIFWGenerator : public cmCPackGenerator, public cmCPackIFWCommon
+class cmCPackIFWGenerator
+ : public cmCPackGenerator
+ , public cmCPackIFWCommon
{
public:
cmCPackTypeMacro(cmCPackIFWGenerator, cmCPackGenerator);
const std::string& optionName, const std::string& optionValue)
{
cmCPackIFWLogger(
- WARNING, "Option "
+ WARNING,
+ "Option "
<< optionName << " is set to \"" << optionValue
<< "\" but will be skipped because the specified file does not exist."
<< std::endl);
if (this->WizardStyle != "Modern" && this->WizardStyle != "Aero" &&
this->WizardStyle != "Mac" && this->WizardStyle != "Classic") {
cmCPackIFWLogger(
- WARNING, "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \""
+ WARNING,
+ "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \""
<< option << "\". Expected values are: Modern, Aero, Mac, Classic."
<< std::endl);
}
cmsys::SystemTools::CopyFileIfDifferent(this->Resources[i], path);
resources.push_back(std::move(name));
} else {
- cmCPackIFWLogger(WARNING, "Can't copy resources from \""
+ cmCPackIFWLogger(WARNING,
+ "Can't copy resources from \""
<< this->Resources[i]
<< "\". Resource will be skipped." << std::endl);
}
this->RequiresAdminRights.clear();
}
-// Defaul configuration (all in one package)
+// Default configuration (all in one package)
int cmCPackIFWPackage::ConfigureFromOptions()
{
- // Restore defaul configuration
+ // Restore default configuration
this->DefaultConfiguration();
// Name
return 0;
}
- // Restore defaul configuration
+ // Restore default configuration
this->DefaultConfiguration();
std::string prefix = "CPACK_IFW_COMPONENT_" +
if (const char* option = this->GetOption(prefix + "PRIORITY")) {
this->SortingPriority = option;
cmCPackIFWLogger(
- WARNING, "The \"PRIORITY\" option is set "
+ WARNING,
+ "The \"PRIORITY\" option is set "
<< "for component \"" << component->Name << "\", but there option is "
<< "deprecated. Please use \"SORTING_PRIORITY\" option instead."
<< std::endl);
return 0;
}
- // Restore defaul configuration
+ // Restore default configuration
this->DefaultConfiguration();
std::string prefix = "CPACK_IFW_COMPONENT_GROUP_" +
if (const char* option = this->GetOption(prefix + "PRIORITY")) {
this->SortingPriority = option;
cmCPackIFWLogger(
- WARNING, "The \"PRIORITY\" option is set "
+ WARNING,
+ "The \"PRIORITY\" option is set "
<< "for component group \"" << group->Name
<< "\", but there option is "
<< "deprecated. Please use \"SORTING_PRIORITY\" option instead."
#include <vector>
#ifdef __CYGWIN__
-#include <sys/cygwin.h>
+# include <sys/cygwin.h>
std::string CMakeToWixPath(const std::string& cygpath)
{
std::vector<char> winpath_chars;
#include "cmsys/SystemTools.hxx"
#ifdef _WIN32
-#include <rpc.h> // for GUID generation (windows only)
+# include <rpc.h> // for GUID generation (windows only)
#else
-#include <uuid/uuid.h> // for GUID generation (libuuid)
+# include <uuid/uuid.h> // for GUID generation (libuuid)
#endif
#include "cmCMakeToWixPath.h"
{
std::string logFileName = this->CPackTopLevel + "/wix.log";
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Running WiX command: " << command
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Running WiX command: " << command << std::endl);
std::string output;
logFile.close();
if (!status || returnValue) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running WiX candle. "
- "Please check '"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running WiX candle. "
+ "Please check '"
<< logFileName << "' for errors." << std::endl);
return false;
int cmCPackWIXGenerator::PackageFiles()
{
if (!PackageFilesImpl() || cmSystemTools::GetErrorOccuredFlag()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Fatal WiX Generator Error"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Fatal WiX Generator Error" << std::endl);
return false;
}
bool cmCPackWIXGenerator::InitializeWiXConfiguration()
{
if (!ReadListFile("CPackWIX.cmake")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while executing CPackWIX.cmake"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while executing CPackWIX.cmake" << std::endl);
return false;
}
std::string guid = GenerateGUID();
SetOption("CPACK_WIX_UPGRADE_GUID", guid.c_str());
- cmCPackLogger(
- cmCPackLog::LOG_WARNING, "CPACK_WIX_UPGRADE_GUID implicitly set to "
- << guid << " . "
- "Please refer to the documentation on how and why "
- "you might want to set this explicitly."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPACK_WIX_UPGRADE_GUID implicitly set to "
+ << guid
+ << " . "
+ "Please refer to the documentation on how and why "
+ "you might want to set this explicitly."
+ << std::endl);
}
if (!RequireOption("CPACK_TOPLEVEL_DIRECTORY", this->CPackTopLevel)) {
includeFile.AddAttribute("Id", "FindInstallLocation");
includeFile.AddAttribute("Root", "HKLM");
includeFile.AddAttribute(
- "Key", "Software\\Microsoft\\Windows\\"
- "CurrentVersion\\Uninstall\\[WIX_UPGRADE_DETECTED]");
+ "Key",
+ "Software\\Microsoft\\Windows\\"
+ "CurrentVersion\\Uninstall\\[WIX_UPGRADE_DETECTED]");
includeFile.AddAttribute("Name", "InstallLocation");
includeFile.AddAttribute("Type", "raw");
includeFile.EndElement("RegistrySearch");
std::string mainSourceFilePath = this->CPackTopLevel + "/main.wxs";
if (!ConfigureFile(wixTemplate.c_str(), mainSourceFilePath.c_str())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed creating '"
- << mainSourceFilePath << "'' from template." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed creating '" << mainSourceFilePath
+ << "'' from template." << std::endl);
return false;
}
return true;
} else {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Required variable "
- << name << " not set" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Required variable " << name << " not set" << std::endl);
return false;
}
void cmWIXAccessControlList::ReportError(std::string const& entry,
std::string const& message)
{
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed processing ACL entry '"
- << entry << "': " << message << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed processing ACL entry '" << entry << "': " << message
+ << std::endl);
}
bool cmWIXAccessControlList::IsBooleanAttribute(std::string const& name)
{
cmWIXPatchParser parser(Fragments, Logger);
if (!parser.ParseFile(patchFilePath.c_str())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed parsing XML patch file: '"
- << patchFilePath << "'" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed parsing XML patch file: '" << patchFilePath << "'"
+ << std::endl);
return false;
}
cmWIXSourceWriter::~cmWIXSourceWriter()
{
if (Elements.size() > 1) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, Elements.size() - 1
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ Elements.size() - 1
<< " WiX elements were still open when closing '"
<< SourceFilename << "'" << std::endl);
return;
}
if (Elements.back() != name) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "WiX element <"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "WiX element <"
<< Elements.back() << "> can not be closed by </" << name
<< "> in '" << SourceFilename << "'" << std::endl);
return;
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
+#include <cstring>
#include <ostream>
#include <utility>
#include <vector>
this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1");
return this->Superclass::InitializeInternal();
}
+
int cmCPackArchiveGenerator::addOneComponentToArchive(
cmArchiveWrite& archive, cmCPackComponent* component)
{
localToplevel += "/" + component->Name;
// Change to local toplevel
cmWorkingDirectory workdir(localToplevel);
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << localToplevel << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ return 0;
+ }
std::string filePrefix;
if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME");
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file: " << rp << std::endl);
archive.Add(rp, 0, nullptr, false);
if (!archive) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "ERROR while packaging files: "
- << archive.GetError() << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "ERROR while packaging files: " << archive.GetError()
+ << std::endl);
return 0;
}
}
} \
cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat); \
if (!(archive)) { \
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem to create archive < " \
+ cmCPackLogger(cmCPackLog::LOG_ERROR, \
+ "Problem to create archive < " \
<< (filename) << ">. ERROR =" << (archive).GetError() \
<< std::endl); \
return 0; \
// Does the component belong to a group?
if (comp.second.Group == nullptr) {
cmCPackLogger(
- cmCPackLog::LOG_VERBOSE, "Component <"
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
<< comp.second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
// CASE 3 : NON COMPONENT package.
DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive);
cmWorkingDirectory workdir(toplevel);
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << toplevel << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ return 0;
+ }
for (std::string const& file : files) {
// Get the relative path to the file
std::string rp = cmSystemTools::RelativePath(toplevel, file);
archive.Add(rp, 0, nullptr, false);
if (!archive) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem while adding file< "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem while adding file< "
<< file << "> to archive <" << packageFileNames[0]
<< "> .ERROR =" << archive.GetError() << std::endl);
return 0;
"codesign", std::vector<std::string>(), false);
if (codesign_path.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate codesign command"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot locate codesign command" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_CODESIGN", codesign_path.c_str());
? this->GetOption("CPACK_BUNDLE_NAME")
: "";
if (cpack_bundle_name.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_BUNDLE_NAME must be set." << std::endl);
return 0;
}
? this->GetOption("CPACK_BUNDLE_PLIST")
: "";
if (cpack_bundle_plist.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_PLIST must be set."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_BUNDLE_PLIST must be set." << std::endl);
return 0;
}
? this->GetOption("CPACK_BUNDLE_ICON")
: "";
if (cpack_bundle_icon.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_ICON must be set."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_BUNDLE_ICON must be set." << std::endl);
return 0;
}
return 0;
}
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Application has been codesigned"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Application has been codesigned" << std::endl);
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
(this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS")
? "with entitlement sandboxing"
// system tools because it is not implemented robustly enough to move
// files across directories.
#ifdef _WIN32
-#include "cm_sys_stat.h"
-#include <windows.h>
+# include "cm_sys_stat.h"
+# include <windows.h>
#endif
cmCPackCygwinSourceGenerator::cmCPackCygwinSourceGenerator()
if (!cmSystemTools::CopyFileAlways(
this->GetOption("CPACK_CYGWIN_PATCH_FILE"),
this->GetOption("CPACK_TOPLEVEL_DIRECTORY"))) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "problem copying: ["
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "problem copying: ["
<< this->GetOption("CPACK_CYGWIN_PATCH_FILE") << "]\nto\n["
<< this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
return 0;
if (!cmSystemTools::CopyFileAlways(
this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"),
this->GetOption("CPACK_TOPLEVEL_DIRECTORY"))) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "problem copying: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "problem copying: "
<< this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT") << "\nto\n"
<< this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
return 0;
outerTarFile += "-";
const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
if (!patch) {
- cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER"
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPACK_CYGWIN_PATCH_NUMBER"
<< " not specified, defaulting to 1\n");
patch = "1";
}
this->OutputExtension = "-";
const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
if (!patch) {
- cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER"
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPACK_CYGWIN_PATCH_NUMBER"
<< " not specified, defaulting to 1\n");
patch = "1";
}
this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
component_path.c_str());
if (!this->ReadListFile("CPackDeb.cmake")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackDeb.cmake"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackDeb.cmake" << std::endl);
retval = 0;
return retval;
}
// Does the component belong to a group?
if (comp.second.Group == nullptr) {
cmCPackLogger(
- cmCPackLog::LOG_VERBOSE, "Component <"
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
<< comp.second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
component_path.c_str());
}
if (!this->ReadListFile("CPackDeb.cmake")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackDeb.cmake"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackDeb.cmake" << std::endl);
retval = 0;
return retval;
}
cmGeneratedFileStream fileStream_data_tar;
fileStream_data_tar.Open(filename_data_tar.c_str(), false, true);
if (!fileStream_data_tar) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error opening the file \""
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the file \""
<< filename_data_tar << "\" for writing" << std::endl);
return 0;
}
// e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would
// give /usr and /opt
size_t topLevelLength = strGenWDIR.length();
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "WDIR: \""
- << strGenWDIR << "\", length = " << topLevelLength
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "WDIR: \"" << strGenWDIR << "\", length = " << topLevelLength
+ << std::endl);
std::set<std::string> orderedFiles;
// we have to reconstruct the parent folders as well
}
for (std::string const& file : orderedFiles) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "FILEIT: \"" << file << "\""
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "FILEIT: \"" << file << "\"" << std::endl);
std::string::size_type slashPos = file.find('/', topLevelLength + 1);
std::string relativeDir =
file.substr(topLevelLength, slashPos - topLevelLength);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "RELATIVEDIR: \""
- << relativeDir << "\"" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "RELATIVEDIR: \"" << relativeDir << "\"" << std::endl);
#ifdef WIN32
std::string mode_t_adt_filename = file + ":cmake_mode_t";
// do not recurse because the loop will do it
if (!data_tar.Add(file, topLevelLength, ".", false)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem adding file to tar:"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem adding file to tar:"
<< std::endl
<< "#top level directory: " << strGenWDIR << std::endl
<< "#file: " << file << std::endl
std::string output =
cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5);
if (output.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem computing the md5 of "
- << file << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem computing the md5 of " << file << std::endl);
}
output += " " + file + "\n";
cmGeneratedFileStream fileStream_control_tar;
fileStream_control_tar.Open(filename_control_tar.c_str(), false, true);
if (!fileStream_control_tar) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error opening the file \""
- << filename_control_tar << "\" for writing"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the file \"" << filename_control_tar
+ << "\" for writing"
+ << std::endl);
return 0;
}
cmArchiveWrite control_tar(fileStream_control_tar,
// adds control and md5sums
if (!control_tar.Add(md5filename, strGenWDIR.length(), ".") ||
!control_tar.Add(strGenWDIR + "/control", strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding file to tar:"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
<< std::endl
<< "#top level directory: " << strGenWDIR << std::endl
<< "#file: \"control\" or \"md5sums\"" << std::endl
// adds generated shlibs file
if (gen_shibs) {
if (!control_tar.Add(shlibsfilename, strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding file to tar:"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
<< std::endl
<< "#top level directory: " << strGenWDIR << std::endl
<< "#file: \"shlibs\"" << std::endl
if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST")) {
control_tar.SetPermissions(permission755);
if (!control_tar.Add(postinst, strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding file to tar:"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
<< std::endl
<< "#top level directory: " << strGenWDIR << std::endl
<< "#file: \"postinst\"" << std::endl
if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM")) {
control_tar.SetPermissions(permission755);
if (!control_tar.Add(postrm, strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding file to tar:"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
<< std::endl
<< "#top level directory: " << strGenWDIR << std::endl
<< "#file: \"postinst\"" << std::endl
cmGeneratedFileStream debStream;
debStream.Open(outputPath.c_str(), false, true);
cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd");
+
+ // uid/gid should be the one of the root user, and this root user has
+ // always uid/gid equal to 0.
+ deb.SetUIDAndGID(0u, 0u);
+ deb.SetUNAMEAndGNAME("root", "root");
+
if (!deb.Add(tlDir + "debian-binary", tlDir.length()) ||
!deb.Add(tlDir + "control.tar.gz", tlDir.length()) ||
!deb.Add(tlDir + "data.tar" + compression_suffix, tlDir.length())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error creating debian package:"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error creating debian package:"
<< std::endl
<< "#top level directory: " << outputDir << std::endl
<< "#file: " << outputName << std::endl
// For the old LocaleStringToLangAndRegionCodes() function, to convert
// to the old Script Manager RegionCode values needed for the 'LPic' data
// structure used for generating multi-lingual SLAs.
-#include <CoreServices/CoreServices.h>
+# include <CoreServices/CoreServices.h>
#endif
static const char* SLAHeader =
const std::string hdiutil_path =
cmSystemTools::FindProgram("hdiutil", std::vector<std::string>(), false);
if (hdiutil_path.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate hdiutil command"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot locate hdiutil command" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str());
const std::string setfile_path =
cmSystemTools::FindProgram("SetFile", paths, false);
if (setfile_path.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate SetFile command"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot locate SetFile command" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path.c_str());
const std::string rez_path = cmSystemTools::FindProgram("Rez", paths, false);
if (rez_path.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate Rez command"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot locate Rez command" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path.c_str());
return 0;
}
if (!cmSystemTools::FileExists(slaDirectory, false)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_DMG_SLA_DIR does not exist"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_DMG_SLA_DIR does not exist" << std::endl);
return 0;
}
for (auto const& language : languages) {
std::string license = slaDirectory + "/" + language + ".license.txt";
if (!singleLicense && !cmSystemTools::FileExists(license)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Missing license file "
- << language << ".license.txt" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Missing license file " << language << ".license.txt"
+ << std::endl);
return 0;
}
std::string menu = slaDirectory + "/" + language + ".menu.txt";
if (!cmSystemTools::FileExists(menu)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Missing menu file "
- << language << ".menu.txt" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Missing menu file " << language << ".menu.txt"
+ << std::endl);
return 0;
}
}
{
if (!cmSystemTools::CopyFileIfDifferent(source.str().c_str(),
target.str().c_str())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error copying "
- << source.str() << " to " << target.str() << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error copying " << source.str() << " to " << target.str()
+ << std::endl);
return false;
}
this->GeneratorVerbose, cmDuration::zero());
if (!result || exit_code) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error executing: " << command.str()
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error executing: " << command.str() << std::endl);
return false;
}
std::ostringstream dummy_padding;
dummy_padding << staging.str() << "/.dummy-padding-file";
if (!this->CreateEmptyFile(dummy_padding, 1048576)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error creating dummy padding file."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error creating dummy padding file." << std::endl);
return 0;
}
std::ostringstream dummy_padding;
dummy_padding << temp_mount << "/.dummy-padding-file";
if (!cmSystemTools::RemoveFile(dummy_padding.str())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error removing dummy padding file."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error removing dummy padding file." << std::endl);
had_error = true;
}
CFLocaleCreateCanonicalLanguageIdentifierFromString(
nullptr, language_cfstring);
if (!iso_language) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, languages[i]
- << " is not a recognized language" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ languages[i] << " is not a recognized language"
+ << std::endl);
}
char iso_language_cstr[65];
CFStringGetCString(iso_language, iso_language_cstr,
ofs.Close();
if (have_write_license_error) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error writing license file to SLA."
- << std::endl
- << error << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error writing license file to SLA." << std::endl
+ << error
+ << std::endl);
return 0;
}
embed_sla_command << "\"" << temp_image << "\"";
if (!this->RunCommand(embed_sla_command, &error)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding SLA." << std::endl
- << error
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding SLA." << std::endl
+ << error << std::endl);
return 0;
}
std::string convert_error;
if (!this->RunCommand(final_image_command, &convert_error)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error compressing disk image."
- << std::endl
- << convert_error << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error compressing disk image." << std::endl
+ << convert_error
+ << std::endl);
return 0;
}
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cstring>
#include <memory> // IWYU pragma: keep
#include <utility>
#include "cmake.h"
#if defined(__HAIKU__)
-#include <FindDirectory.h>
-#include <StorageDefs.h>
+# include <FindDirectory.h>
+# include <StorageDefs.h>
#endif
cmCPackGenerator::cmCPackGenerator()
// checks CPACK_SET_DESTDIR support
if (IsOn("CPACK_SET_DESTDIR")) {
if (SETDESTDIR_UNSUPPORTED == SupportsSetDestdir()) {
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "CPACK_SET_DESTDIR is set to ON but the '"
- << Name << "' generator does NOT support it." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_SET_DESTDIR is set to ON but the '"
+ << Name << "' generator does NOT support it."
+ << std::endl);
return 0;
}
if (SETDESTDIR_SHOULD_NOT_BE_USED == SupportsSetDestdir()) {
std::string outName = pfname;
tempDirectory += "/" + outName;
if (!this->GetOutputExtension()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "No output extension specified"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "No output extension specified" << std::endl);
return 0;
}
outName += this->GetOutputExtension();
"Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl);
const char* descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
if (descFileName) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: " << descFileName
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Look for: " << descFileName << std::endl);
if (!cmSystemTools::FileExists(descFileName)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot find description file name: ["
const char* algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM");
if (algoSignature) {
if (!cmCryptoHash::New(algoSignature)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot recognize algorithm: "
- << algoSignature << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot recognize algorithm: " << algoSignature
+ << std::endl);
return 0;
}
}
cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
for (const auto& arg : items) {
if (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Invalid permission value '"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Invalid permission value '"
<< arg
<< "'."
" CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
ofs << "# Run command: " << ic << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem running install command: "
- << ic << std::endl
- << "Please check " << tmpFile << " for errors" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running install command: "
+ << ic << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return 0;
}
}
}
std::string filePath = tempDir;
filePath += "/" + subdir + "/" + cmSystemTools::RelativePath(top, gf);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy file: "
- << inFile << " -> " << filePath << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Copy file: " << inFile << " -> " << filePath
+ << std::endl);
/* If the file is a symlink we will have to re-create it */
if (cmSystemTools::FileIsSymlink(inFile)) {
std::string targetFile;
filePath.c_str()) &&
cmSystemTools::CopyFileTime(inFile.c_str(),
filePath.c_str()))) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying file: "
- << inFile << " -> " << filePath << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying file: " << inFile << " -> "
+ << filePath << std::endl);
return 0;
}
}
std::string curDir = cmSystemTools::GetCurrentWorkingDirectory();
std::string goToDir = tempDir;
goToDir += "/" + subdir;
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Change dir to: " << goToDir
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Change dir to: " << goToDir << std::endl);
cmWorkingDirectory workdir(goToDir);
- for (auto const& symlinked : symlinkedFiles) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Will create a symlink: "
- << symlinked.second << "--> " << symlinked.first
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << goToDir << " : "
+ << std::strerror(workdir.GetLastResult())
<< std::endl);
+ return 0;
+ }
+ for (auto const& symlinked : symlinkedFiles) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Will create a symlink: " << symlinked.second << "--> "
+ << symlinked.first
+ << std::endl);
// make sure directory exists for symlink
std::string destDir =
cmSystemTools::GetFilenamePath(symlinked.second);
if (!destDir.empty() &&
!cmSystemTools::MakeDirectory(destDir, default_dir_mode)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create dir: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot create dir: "
<< destDir << "\nTrying to create symlink: "
<< symlinked.second << "--> " << symlinked.first
<< std::endl);
}
if (!cmSystemTools::CreateSymlink(symlinked.first,
symlinked.second)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create symlink: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot create symlink: "
<< symlinked.second << "--> " << symlinked.first
<< std::endl);
return 0;
}
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Going back to: " << curDir
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Going back to: " << curDir << std::endl);
}
}
}
{
const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPT");
if (cmakeScripts && *cmakeScripts) {
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install scripts: " << cmakeScripts
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install scripts: " << cmakeScripts << std::endl);
std::vector<std::string> cmakeScriptsVector;
cmSystemTools::ExpandListArgument(cmakeScripts, cmakeScriptsVector);
for (std::string const& installScript : cmakeScriptsVector) {
preinstall, buildConfig, "", false);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Install command: " << buildCommand << std::endl);
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Run preinstall target for: "
- << installProjectName << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Run preinstall target for: " << installProjectName
+ << std::endl);
std::string output;
int retVal = 1;
bool resB = cmSystemTools::RunSingleCommand(
<< "# Directory: " << installDirectory << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem running install command: "
- << buildCommand << std::endl
- << "Please check " << tmpFile << " for errors" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running install command: "
+ << buildCommand << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return 0;
}
}
std::string tempInstallDirectory = baseTempInstallDirectory;
installComponent = component;
if (componentInstall) {
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install component: "
- << installComponent << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install component: " << installComponent
+ << std::endl);
}
cmake cm(cmake::RoleScript);
*/
cmSystemTools::PutEnv(std::string("DESTDIR=") +
tempInstallDirectory);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Creating directory: '"
- << dir << "'" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Creating directory: '" << dir << "'" << std::endl);
if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) {
cmCPackLogger(
localFileName =
localFileName.substr(localFileName.find_first_not_of('/'));
Components[installComponent].Files.push_back(localFileName);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file <"
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Adding file <"
<< localFileName << "> to component <"
<< installComponent << ">" << std::endl);
}
this->MakefileMap->RemoveDefinition(op);
return;
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, this->GetNameOfClass()
- << "::SetOption(" << op << ", " << value << ")"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ this->GetNameOfClass() << "::SetOption(" << op << ", " << value
+ << ")" << std::endl);
this->MakefileMap->AddDefinition(op, value);
}
int cmCPackGenerator::DoPackage()
{
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package using " << this->Name
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "Create package using " << this->Name << std::endl);
// Prepare CPack internal name and check
// values for many CPACK_xxx vars
const char* toplevelDirectory =
this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
if (cmSystemTools::FileExists(toplevelDirectory)) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove toplevel directory: "
- << toplevelDirectory << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Remove toplevel directory: " << toplevelDirectory
+ << std::endl);
if (!cmSystemTools::RepeatedRemoveDirectory(toplevelDirectory)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem removing toplevel directory: "
}
}
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "About to install project "
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "About to install project " << std::endl);
if (!this->InstallProject()) {
return 0;
}
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package" << std::endl);
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Package files to: "
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Package files to: "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)")
<< std::endl);
if (cmSystemTools::FileExists(tempPackageFileName)) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove old package file"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Remove old package file" << std::endl);
cmSystemTools::RemoveFile(tempPackageFileName);
}
if (cmSystemTools::IsOn(
{ // scope that enables package generators to run internal scripts with
// latest CMake policies enabled
cmMakefile::ScopePushPop pp{ this->MakefileMap };
- this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion());
+ this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion(),
+ std::string());
if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem compressing the directory" << std::endl);
return 0;
}
}
* - the initially provided name may have changed
* (because the specific generator did 'normalize' it)
*/
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Copying final package(s) ["
- << packageFileNames.size() << "]:" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Copying final package(s) [" << packageFileNames.size()
+ << "]:" << std::endl);
/* now copy package one by one */
for (std::string const& pkgFileName : packageFileNames) {
std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
tempPackageFileName = pkgFileName.c_str();
tmpPF += "/" + filename;
const char* packageFileName = tmpPF.c_str();
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy final package(s): "
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Copy final package(s): "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)")
<< " to " << (packageFileName ? packageFileName : "(NULL)")
<< std::endl);
if (!cmSystemTools::CopyFileIfDifferent(tempPackageFileName,
packageFileName)) {
cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem copying the package: "
+ cmCPackLog::LOG_ERROR,
+ "Problem copying the package: "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to "
<< (packageFileName ? packageFileName : "(NULL)") << std::endl);
return 0;
}
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- package: "
- << packageFileName << " generated." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- package: " << packageFileName << " generated."
+ << std::endl);
/* Generate checksum file */
if (crypto) {
hashFile += "." + cmSystemTools::LowerCase(algo);
cmsys::ofstream outF(hashFile.c_str());
if (!outF) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create checksum file: "
- << hashFile << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot create checksum file: " << hashFile
+ << std::endl);
return 0;
}
outF << crypto->HashFile(packageFileName) << " " << filename << "\n";
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- checksum file: "
- << hashFile << " generated." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- checksum file: " << hashFile << " generated."
+ << std::endl);
}
}
const char* cmCPackGenerator::GetPackagingInstallPrefix()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "GetPackagingInstallPrefix: '"
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "GetPackagingInstallPrefix: '"
<< this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'"
<< std::endl);
std::string cmCPackGenerator::FindTemplate(const char* name)
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for template: "
- << (name ? name : "(NULL)") << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Look for template: " << (name ? name : "(NULL)")
+ << std::endl);
std::string ffile = this->MakefileMap->GetModulesFile(name);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Found template: " << ffile
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Found template: " << ffile << std::endl);
return ffile;
}
}
if (!groupingType.empty()) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "["
- << this->Name << "]"
- << " requested component grouping = " << groupingType
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "[" << this->Name << "]"
+ << " requested component grouping = " << groupingType
+ << std::endl);
if (groupingType == "ALL_COMPONENTS_IN_ONE") {
method = ONE_PACKAGE;
} else if (groupingType == "IGNORE") {
method = ONE_PACKAGE_PER_GROUP;
} else {
cmCPackLogger(
- cmCPackLog::LOG_WARNING, "["
- << this->Name << "]"
- << " requested component grouping type <" << groupingType
- << "> UNKNOWN not in (ALL_COMPONENTS_IN_ONE,IGNORE,ONE_PER_GROUP)"
- << std::endl);
+ cmCPackLog::LOG_WARNING,
+ "[" << this->Name << "]"
+ << " requested component grouping type <" << groupingType
+ << "> UNKNOWN not in (ALL_COMPONENTS_IN_ONE,IGNORE,ONE_PER_GROUP)"
+ << std::endl);
}
}
method = ONE_PACKAGE_PER_COMPONENT;
}
cmCPackLogger(
- cmCPackLog::LOG_WARNING, "["
- << this->Name << "]"
- << " One package per component group requested, "
- << "but NO component groups exist: Ignoring component group."
- << std::endl);
+ cmCPackLog::LOG_WARNING,
+ "[" << this->Name << "]"
+ << " One package per component group requested, "
+ << "but NO component groups exist: Ignoring component group."
+ << std::endl);
}
// if user specified packaging method, override the default packaging method
const char* method_names[] = { "ALL_COMPONENTS_IN_ONE", "IGNORE_GROUPS",
"ONE_PER_GROUP" };
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "["
- << this->Name << "]"
- << " requested component grouping = "
- << method_names[componentPackageMethod] << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "[" << this->Name << "]"
+ << " requested component grouping = "
+ << method_names[componentPackageMethod] << std::endl);
return 1;
}
bool cmCPackGenerator::WantsComponentInstallation() const
{
- return (!IsOn("CPACK_MONOLITHIC_INSTALL") && SupportsComponentInstallation()
+ return (!IsOn("CPACK_MONOLITHIC_INSTALL") &&
+ SupportsComponentInstallation()
// check that we have at least one group or component
&& (!this->ComponentGroups.empty() || !this->Components.empty()));
}
#include "cmAlgorithms.h"
#include "cmCPack7zGenerator.h"
#ifdef HAVE_FREEBSD_PKG
-#include "cmCPackFreeBSDGenerator.h"
+# include "cmCPackFreeBSDGenerator.h"
#endif
#include "cmCPackDebGenerator.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmCPackNSISGenerator.h"
+#include "cmCPackNuGetGenerator.h"
#include "cmCPackSTGZGenerator.h"
#include "cmCPackTGZGenerator.h"
#include "cmCPackTXZGenerator.h"
#include "cmCPackZIPGenerator.h"
#ifdef __APPLE__
-#include "cmCPackBundleGenerator.h"
-#include "cmCPackDragNDropGenerator.h"
-#include "cmCPackOSXX11Generator.h"
-#include "cmCPackPackageMakerGenerator.h"
-#include "cmCPackProductBuildGenerator.h"
+# include "cmCPackBundleGenerator.h"
+# include "cmCPackDragNDropGenerator.h"
+# include "cmCPackOSXX11Generator.h"
+# include "cmCPackPackageMakerGenerator.h"
+# include "cmCPackProductBuildGenerator.h"
#endif
#ifdef __CYGWIN__
-#include "cmCPackCygwinBinaryGenerator.h"
-#include "cmCPackCygwinSourceGenerator.h"
+# include "cmCPackCygwinBinaryGenerator.h"
+# include "cmCPackCygwinSourceGenerator.h"
#endif
#if !defined(_WIN32) && !defined(__QNXNTO__) && !defined(__BEOS__) && \
!defined(__HAIKU__)
-#include "cmCPackRPMGenerator.h"
+# include "cmCPackRPMGenerator.h"
#endif
#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
-#include "WiX/cmCPackWIXGenerator.h"
+# include "WiX/cmCPackWIXGenerator.h"
#endif
cmCPackGeneratorFactory::cmCPackGeneratorFactory()
this->RegisterGenerator("DEB", "Debian packages",
cmCPackDebGenerator::CreateGenerator);
}
+ if (cmCPackNuGetGenerator::CanGenerate()) {
+ this->RegisterGenerator("NuGet", "NuGet packages",
+ cmCPackNuGetGenerator::CreateGenerator);
+ }
#ifdef __APPLE__
if (cmCPackDragNDropGenerator::CanGenerate()) {
this->RegisterGenerator("DragNDrop", "Mac OSX Drag And Drop",
bool SetLogOutputFile(const char* fname);
//! Set the various prefixes for the logging. SetPrefix sets the generic
- // prefix that overwrittes missing ones.
+ // prefix that overwrites missing ones.
void SetPrefix(std::string const& pfx) { this->Prefix = pfx; }
void SetOutputPrefix(std::string const& pfx) { this->OutputPrefix = pfx; }
void SetVerbosePrefix(std::string const& pfx) { this->VerbosePrefix = pfx; }
/* NSIS uses different command line syntax on Windows and others */
#ifdef _WIN32
-#define NSIS_OPT "/"
+# define NSIS_OPT "/"
#else
-#define NSIS_OPT "-"
+# define NSIS_OPT "-"
#endif
cmCPackNSISGenerator::cmCPackNSISGenerator(bool nsis64)
str << " Delete \"" << outputDir << "\\" << fileN << "\"" << std::endl;
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Files: " << str.str()
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Uninstall Files: " << str.str() << std::endl);
this->SetOptionIfNotSet("CPACK_NSIS_DELETE_FILES", str.str().c_str());
std::vector<std::string> dirs;
this->GetListOfSubdirectories(toplevel.c_str(), dirs);
this->Components[componentName].Directories.push_back(std::move(fileN));
}
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Dirs: " << dstr.str()
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Uninstall Dirs: " << dstr.str() << std::endl);
this->SetOptionIfNotSet("CPACK_NSIS_DELETE_DIRECTORIES", dstr.str().c_str());
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << nsisInFileName << " to " << nsisFileName << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Configure file: " << nsisInFileName << " to " << nsisFileName
+ << std::endl);
if (this->IsSet("CPACK_NSIS_MUI_ICON") ||
this->IsSet("CPACK_NSIS_MUI_UNIICON")) {
std::string installerIconCode;
ofs << "# Run command: " << nsisCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running NSIS command: "
- << nsisCmd << std::endl
- << "Please check " << tmpFile << " for errors"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running NSIS command: " << nsisCmd << std::endl
+ << "Please check "
+ << tmpFile << " for errors"
+ << std::endl);
return 0;
}
return 1;
this->SetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", nullptr);
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackNSISGenerator::Initialize()"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "cmCPackNSISGenerator::Initialize()" << std::endl);
std::vector<std::string> path;
std::string nsisPath;
bool gotRegValue = false;
#ifdef _WIN32
if (Nsis64) {
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode",
- nsisPath, cmsys::SystemTools::KeyWOW64_64)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath,
+ cmsys::SystemTools::KeyWOW64_64)) {
gotRegValue = true;
}
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
- cmsys::SystemTools::KeyWOW64_64)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
+ cmsys::SystemTools::KeyWOW64_64)) {
gotRegValue = true;
}
}
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode",
- nsisPath, cmsys::SystemTools::KeyWOW64_32)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath,
+ cmsys::SystemTools::KeyWOW64_32)) {
gotRegValue = true;
}
if (!gotRegValue &&
"HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath)) {
gotRegValue = true;
}
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
- cmsys::SystemTools::KeyWOW64_32)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
+ cmsys::SystemTools::KeyWOW64_32)) {
gotRegValue = true;
}
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath)) {
gotRegValue = true;
}
}
std::string nsisCmd = "\"" + nsisPath + "\" " NSIS_OPT "VERSION";
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Test NSIS version: " << nsisCmd
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Test NSIS version: " << nsisCmd << std::endl);
std::string output;
int retVal = 1;
bool resS = cmSystemTools::RunSingleCommand(
ofs << "# Run command: " << nsisCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem checking NSIS version with command: "
- << nsisCmd << std::endl
- << "Please check " << tmpFile << " for errors" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem checking NSIS version with command: "
+ << nsisCmd << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return 0;
}
if (versionRex.find(output)) {
double nsisVersion = atof(versionRex.match(1).c_str());
double minNSISVersion = 2.09;
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: " << nsisVersion
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "NSIS Version: " << nsisVersion << std::endl);
if (nsisVersion < minNSISVersion) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPack requires NSIS Version 2.09 or greater. "
}
if (versionRexCVS.find(output)) {
// No version check for NSIS cvs build
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: CVS "
- << versionRexCVS.match(1) << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "NSIS Version: CVS " << versionRexCVS.match(1) << std::endl);
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath.c_str());
this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLES_DIRECTORY", "bin");
this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY");
std::vector<std::string> cpackPackageDesktopLinksVector;
if (cpackPackageDeskTopLinks) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "CPACK_CREATE_DESKTOP_LINKS: "
- << cpackPackageDeskTopLinks << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "CPACK_CREATE_DESKTOP_LINKS: " << cpackPackageDeskTopLinks
+ << std::endl);
cmSystemTools::ExpandListArgument(cpackPackageDeskTopLinks,
cpackPackageDesktopLinksVector);
"CPACK_CREATE_DESKTOP_LINKS: " << cpdl << std::endl);
}
} else {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "CPACK_CREATE_DESKTOP_LINKS: "
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "CPACK_CREATE_DESKTOP_LINKS: "
<< "not set" << std::endl);
}
std::ostringstream deleteStr;
if (cpackPackageExecutables) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: "
- << cpackPackageExecutables << "." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "The cpackPackageExecutables: " << cpackPackageExecutables
+ << "." << std::endl);
std::vector<std::string> cpackPackageExecutablesVector;
cmSystemTools::ExpandListArgument(cpackPackageExecutables,
cpackPackageExecutablesVector);
<< std::endl);
if (cmSystemTools::FileExists(archiveFile, true)) {
if (!cmSystemTools::RemoveFile(archiveFile)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Unable to remove archive file "
- << archiveFile << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Unable to remove archive file " << archiveFile
+ << std::endl);
return "";
}
}
this->ReadListFile("CPackZIP.cmake");
if (!this->IsSet("ZIP_EXECUTABLE")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Unable to find ZIP program"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Unable to find ZIP program" << std::endl);
return "";
}
}
ofs << "# Run command: " << cmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running zip command: "
- << cmd << std::endl
- << "Please check " << tmpFile << " for errors"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running zip command: " << cmd << std::endl
+ << "Please check "
+ << tmpFile << " for errors"
+ << std::endl);
return "";
}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackNuGetGenerator.h"
+
+#include "cmAlgorithms.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+#include "cmSystemTools.h"
+
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+bool cmCPackNuGetGenerator::SupportsComponentInstallation() const
+{
+ return IsOn("CPACK_NUGET_COMPONENT_INSTALL");
+}
+
+int cmCPackNuGetGenerator::PackageFiles()
+{
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << toplevel << std::endl);
+
+ /* Reset package file name list it will be populated after the
+ * `CPackNuGet.cmake` run */
+ packageFileNames.clear();
+
+ /* Are we in the component packaging case */
+ if (WantsComponentInstallation()) {
+ if (componentPackageMethod == ONE_PACKAGE) {
+ // CASE 1 : COMPONENT ALL-IN-ONE package
+ // Meaning that all per-component pre-installed files
+ // goes into the single package.
+ this->SetOption("CPACK_NUGET_ALL_IN_ONE", "TRUE");
+ SetupGroupComponentVariables(true);
+ } else {
+ // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
+ // There will be 1 package for each component group
+ // however one may require to ignore component group and
+ // in this case you'll get 1 package for each component.
+ SetupGroupComponentVariables(componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
+ }
+ } else {
+ // CASE 3 : NON COMPONENT package.
+ this->SetOption("CPACK_NUGET_ORDINAL_MONOLITIC", "TRUE");
+ }
+
+ auto retval = this->ReadListFile("CPackNuGet.cmake");
+ if (retval) {
+ AddGeneratedPackageNames();
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackNuGet.cmake" << std::endl);
+ }
+
+ return retval;
+}
+
+void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup)
+{
+ // The default behavior is to have one package by component group
+ // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
+ if (!ignoreGroup) {
+ std::vector<std::string> groups;
+ for (auto const& compG : this->ComponentGroups) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compG.first << std::endl);
+ groups.push_back(compG.first);
+ auto compGUp =
+ cmSystemTools::UpperCase(cmSystemTools::MakeCidentifier(compG.first));
+
+ // Collect components for this group
+ std::vector<std::string> components;
+ std::transform(begin(compG.second.Components),
+ end(compG.second.Components),
+ std::back_inserter(components),
+ [](cmCPackComponent const* comp) { return comp->Name; });
+ this->SetOption("CPACK_NUGET_" + compGUp + "_GROUP_COMPONENTS",
+ cmJoin(components, ";").c_str());
+ }
+ if (!groups.empty()) {
+ this->SetOption("CPACK_NUGET_GROUPS", cmJoin(groups, ";").c_str());
+ }
+
+ // Handle Orphan components (components not belonging to any groups)
+ std::vector<std::string> components;
+ for (auto const& comp : this->Components) {
+ // Does the component belong to a group?
+ if (comp.second.Group == nullptr) {
+ cmCPackLogger(
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
+ << comp.second.Name
+ << "> does not belong to any group, package it separately."
+ << std::endl);
+ components.push_back(comp.first);
+ }
+ }
+ if (!components.empty()) {
+ this->SetOption("CPACK_NUGET_COMPONENTS",
+ cmJoin(components, ";").c_str());
+ }
+
+ } else {
+ std::vector<std::string> components;
+ components.reserve(this->Components.size());
+ std::transform(begin(this->Components), end(this->Components),
+ std::back_inserter(components),
+ [](std::pair<std::string, cmCPackComponent> const& comp) {
+ return comp.first;
+ });
+ this->SetOption("CPACK_NUGET_COMPONENTS", cmJoin(components, ";").c_str());
+ }
+}
+
+void cmCPackNuGetGenerator::AddGeneratedPackageNames()
+{
+ const char* const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES");
+ if (!files_list) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Error while execution CPackNuGet.cmake: No NuGet package has generated"
+ << std::endl);
+ return;
+ }
+ // add the generated packages to package file names list
+ std::string fileNames{ files_list };
+ const char sep = ';';
+ std::string::size_type pos1 = 0;
+ std::string::size_type pos2 = fileNames.find(sep, pos1 + 1);
+ while (pos2 != std::string::npos) {
+ packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+ pos1 = pos2 + 1;
+ pos2 = fileNames.find(sep, pos1 + 1);
+ }
+ packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackNuGetGenerator_h
+#define cmCPackNuGetGenerator_h
+
+#include "cmCPackGenerator.h"
+
+/** \class cmCPackNuGetGenerator
+ * \brief A generator for RPM packages
+ */
+class cmCPackNuGetGenerator : public cmCPackGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackNuGetGenerator, cmCPackGenerator);
+
+ // NOTE In fact, it is possible to have NuGet not only for Windows...
+ // https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools
+ static bool CanGenerate() { return true; }
+
+protected:
+ bool SupportsComponentInstallation() const override;
+ int PackageFiles() override;
+
+ const char* GetOutputExtension() override { return ".nupkg"; }
+ bool SupportsAbsoluteDestination() const override { return false; }
+ /**
+ * The method used to prepare variables when component
+ * install is used.
+ */
+ void SetupGroupComponentVariables(bool ignoreGroup);
+ /**
+ * Populate \c packageFileNames vector of built packages.
+ */
+ void AddGeneratedPackageNames();
+};
+
+#endif
const char* cpackPackageExecutables =
this->GetOption("CPACK_PACKAGE_EXECUTABLES");
if (cpackPackageExecutables) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: "
- << cpackPackageExecutables << "." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "The cpackPackageExecutables: " << cpackPackageExecutables
+ << "." << std::endl);
std::ostringstream str;
std::ostringstream deleteStr;
std::vector<std::string> cpackPackageExecutablesVector;
if (iconFile) {
std::string iconFileName = cmsys::SystemTools::GetFilenameName(iconFile);
if (!cmSystemTools::FileExists(iconFile)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find icon file: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find icon file: "
<< iconFile
<< ". Please check CPACK_PACKAGE_ICON setting."
<< std::endl);
!this->CopyResourcePlistFile("OSXScriptLauncher", appdir,
this->GetOption("CPACK_PACKAGE_FILE_NAME"),
true)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying the resource files" << std::endl);
return 0;
}
dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
<< "\" create -ov -fs HFS+ -format UDZO -srcfolder \""
<< diskImageDirectory << "\" \"" << packageFileNames[0] << "\"";
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Compress disk image using command: "
- << dmgCmd.str() << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Compress disk image using command: " << dmgCmd.str()
+ << std::endl);
// since we get random dashboard failures with this one
// try running it more than once
int retVal = 1;
ofs << "# Run command: " << dmgCmd.str() << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running hdiutil command: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running hdiutil command: "
<< dmgCmd.str() << std::endl
<< "Please check " << tmpFile << " for errors"
<< std::endl);
int cmCPackOSXX11Generator::InitializeInternal()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackOSXX11Generator::Initialize()"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "cmCPackOSXX11Generator::Initialize()" << std::endl);
std::vector<std::string> path;
std::string pkgPath = cmSystemTools::FindProgram("hdiutil", path, false);
if (pkgPath.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find hdiutil compiler"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find hdiutil compiler" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
destFileName += "/";
destFileName += outputFileName;
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << inFileName << " to " << destFileName << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Configure file: " << inFileName << " to " << destFileName
+ << std::endl);
this->ConfigureFile(inFileName.c_str(), destFileName.c_str(), copyOnly);
return true;
}
int cmCPackPKGGenerator::InitializeInternal()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackPKGGenerator::Initialize()"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "cmCPackPKGGenerator::Initialize()" << std::endl);
return this->Superclass::InitializeInternal();
}
std::string distributionTemplate =
this->FindTemplate("CPack.distribution.dist.in");
if (distributionTemplate.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find input file: "
- << distributionTemplate << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find input file: " << distributionTemplate
+ << std::endl);
return;
}
std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname;
const char* inFileName = this->GetOption(cpackVar);
if (!inFileName) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: "
- << cpackVar.c_str()
- << " not specified. It should point to "
- << (!name.empty() ? name : "<empty>") << ".rtf, " << name
- << ".html, or " << name << ".txt file" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPack option: " << cpackVar.c_str()
+ << " not specified. It should point to "
+ << (!name.empty() ? name : "<empty>")
+ << ".rtf, " << name << ".html, or " << name
+ << ".txt file" << std::endl);
return false;
}
if (!cmSystemTools::FileExists(inFileName)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find "
- << (!name.empty() ? name : "<empty>")
- << " resource file: " << inFileName << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find " << (!name.empty() ? name : "<empty>")
+ << " resource file: " << inFileName
+ << std::endl);
return false;
}
std::string ext = cmSystemTools::GetFilenameLastExtension(inFileName);
if (ext != ".rtfd" && ext != ".rtf" && ext != ".html" && ext != ".txt") {
cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Bad file extension specified: "
+ cmCPackLog::LOG_ERROR,
+ "Bad file extension specified: "
<< ext
<< ". Currently only .rtfd, .rtf, .html, and .txt files allowed."
<< std::endl);
destFileName += "/";
destFileName += outName;
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << inFileName << " to " << destFileName << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Configure file: " << inFileName << " to " << destFileName
+ << std::endl);
this->ConfigureFile(inFileName.c_str(), destFileName.c_str());
return true;
}
!this->CopyCreateResourceFile("Welcome", resDir) ||
!this->CopyResourcePlistFile("Info.plist") ||
!this->CopyResourcePlistFile("Description.plist")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying the resource files" << std::endl);
return 0;
}
ofs << "# Run command: " << dmgCmd.str() << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running hdiutil command: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running hdiutil command: "
<< dmgCmd.str() << std::endl
<< "Please check " << tmpFile << " for errors"
<< std::endl);
} else {
pkgPath = cmSystemTools::FindProgram("PackageMaker", paths, false);
if (pkgPath.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find PackageMaker compiler"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find PackageMaker compiler" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str());
}
this->PackageMakerVersion = atof(rexVersion.match(1).c_str());
if (this->PackageMakerVersion < 1.0) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Require PackageMaker 1.0 or higher"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Require PackageMaker 1.0 or higher" << std::endl);
return 0;
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "PackageMaker version is: "
- << this->PackageMakerVersion << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "PackageMaker version is: " << this->PackageMakerVersion
+ << std::endl);
// Determine the package compatibility version. If it wasn't
// specified by the user, we define it based on which features the
std::vector<std::string> no_paths;
pkgPath = cmSystemTools::FindProgram("hdiutil", no_paths, false);
if (pkgPath.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find hdiutil compiler"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find hdiutil compiler" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
bool res = cmSystemTools::RunSingleCommand(
command, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
cmDuration::zero());
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running package maker"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Done running package maker" << std::endl);
if (!res || retVal) {
cmGeneratedFileStream ofs(tmpFile.c_str());
ofs << "# Run command: " << command << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem running PackageMaker command: "
- << command << std::endl
- << "Please check " << tmpFile << " for errors" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running PackageMaker command: "
+ << command << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return false;
}
// sometimes the command finishes but the directory is not yet
const char* packageFile, const char* packageDir,
const cmCPackComponent& component)
{
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Building component package: "
- << packageFile << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Building component package: " << packageFile
+ << std::endl);
// The command that will be used to run PackageMaker
std::ostringstream pkgCmd;
this->GetOption("CPACK_PRODUCTBUILD_RESOURCES_DIR");
if (!cmSystemTools::CopyADirectory(userResDir, resDir)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying the resource files" << std::endl);
return 0;
}
}
std::string program =
cmSystemTools::FindProgram("pkgbuild", no_paths, false);
if (program.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find pkgbuild executable"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find pkgbuild executable" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_PKGBUILD", program.c_str());
program = cmSystemTools::FindProgram("productbuild", no_paths, false);
if (program.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find productbuild executable"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find productbuild executable" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_PRODUCTBUILD", program.c_str());
packageFile += '/';
packageFile += packageFileName;
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Building component package: "
- << packageFile << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Building component package: " << packageFile
+ << std::endl);
const char* comp_name = component ? component->Name.c_str() : nullptr;
this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
component_path.c_str());
if (!this->ReadListFile("CPackRPM.cmake")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackRPM.cmake" << std::endl);
retval = 0;
}
}
if (shouldSet) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Setting "
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Setting "
<< "CPACK_RPM_DEBUGINFO_PACKAGE because "
<< "CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE is set but "
<< " none of the "
continue;
}
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
- << compGIt->first << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compGIt->first
+ << std::endl);
retval &= PackageOnePack(initialTopLevel, compGIt->first);
}
// Handle Orphan components (components not belonging to any groups)
}
cmCPackLogger(
- cmCPackLog::LOG_VERBOSE, "Component <"
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
<< compIt->second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
} else if (mainCompIt != this->Components.end()) {
retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
} else {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_RPM_MAIN_COMPONENT set"
<< " to non existing component.\n");
retval = 0;
}
if (mainCompIt != this->Components.end()) {
retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
} else {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_RPM_MAIN_COMPONENT set"
<< " to non existing component.\n");
retval = 0;
}
std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
for (compGIt = this->ComponentGroups.begin();
compGIt != this->ComponentGroups.end(); ++compGIt) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
- << compGIt->first << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compGIt->first
+ << std::endl);
retval &= PackageOnePack(initialTopLevel, compGIt->first);
}
// Handle Orphan components (components not belonging to any groups)
// Does the component belong to a group?
if (compIt->second.Group == nullptr) {
cmCPackLogger(
- cmCPackLog::LOG_VERBOSE, "Component <"
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
<< compIt->second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
}
} else {
cmCPackLogger(
- cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT not set but"
+ cmCPackLog::LOG_ERROR,
+ "CPACK_RPM_MAIN_COMPONENT not set but"
<< " it is mandatory with CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE"
<< " being set.\n");
retval = 0;
if (this->ReadListFile("CPackRPM.cmake")) {
AddGeneratedPackageNames();
} else {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackRPM.cmake" << std::endl);
retval = 0;
}
S_IRGRP | S_IWGRP | S_IXGRP |
S_IROTH | S_IWOTH | S_IXOTH
#endif
- );
+ );
}
return retval;
}
++ptr;
}
counter++;
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Number of lines: " << counter
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Number of lines: " << counter << std::endl);
char buffer[1024];
sprintf(buffer, "%d", counter);
cmSystemTools::ReplaceString(res, headerLengthTag, buffer);
#include <vector>
#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmsys/ConsoleBuf.hxx"
+# include "cmsys/ConsoleBuf.hxx"
#endif
#include "cmCPackGenerator.h"
};
static const char* cmDocumentationUsage[][2] = {
- { nullptr, " cpack -G <generator> [options]" },
+ // clang-format off
+ { nullptr, " cpack [options]" },
{ nullptr, nullptr }
+ // clang-format on
};
static const char* cmDocumentationOptions[][2] = {
- { "-G <generator>", "Use the specified generator to generate package." },
+ { "-G <generators>", "Override/define CPACK_GENERATOR" },
{ "-C <Configuration>", "Specify the project configuration" },
{ "-D <var>=<value>", "Set a CPack variable." },
- { "--config <config file>", "Specify the config file." },
- { "--verbose,-V", "enable verbose output" },
+ { "--config <configFile>", "Specify the config file." },
+ { "--verbose,-V", "Enable verbose output" },
{ "--trace", "Put underlying cmake scripts in trace mode." },
{ "--trace-expand", "Put underlying cmake scripts in expanded trace mode." },
- { "--debug", "enable debug output (for CPack developers)" },
- { "-P <package name>", "override/define CPACK_PACKAGE_NAME" },
- { "-R <package version>", "override/define CPACK_PACKAGE_VERSION" },
- { "-B <package directory>", "override/define CPACK_PACKAGE_DIRECTORY" },
- { "--vendor <vendor name>", "override/define CPACK_PACKAGE_VENDOR" },
+ { "--debug", "Enable debug output (for CPack developers)" },
+ { "-P <packageName>", "Override/define CPACK_PACKAGE_NAME" },
+ { "-R <packageVersion>", "Override/define CPACK_PACKAGE_VERSION" },
+ { "-B <packageDirectory>", "Override/define CPACK_PACKAGE_DIRECTORY" },
+ { "--vendor <vendorName>", "Override/define CPACK_PACKAGE_VENDOR" },
{ nullptr, nullptr }
};
std::string key = value.substr(0, pos);
value = value.c_str() + pos + 1;
def->Map[key] = value;
- cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG, "Set CPack variable: "
- << key << " to \"" << value << "\"" << std::endl);
+ cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG,
+ "Set CPack variable: " << key << " to \"" << value << "\""
+ << std::endl);
return 1;
}
}
const char* genList = globalMF.GetDefinition("CPACK_GENERATOR");
if (!genList) {
- cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack generator not specified"
- << std::endl);
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "CPack generator not specified" << std::endl);
} else {
std::vector<std::string> generatorsVector;
cmSystemTools::ExpandListArgument(genList, generatorsVector);
}
if (parsed) {
const char* projName = mf->GetDefinition("CPACK_PACKAGE_NAME");
- cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Use generator: "
- << cpackGenerator->GetNameOfClass() << std::endl);
+ cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
+ "Use generator: " << cpackGenerator->GetNameOfClass()
+ << std::endl);
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"For project: " << projName << std::endl);
{
this->OldRevision = this->LoadInfo();
this->Log << "Revision before update: " << this->OldRevision << "\n";
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of repository is: " << this->OldRevision
+ << "\n");
this->PriorRev.Rev = this->OldRevision;
return true;
}
{
this->NewRevision = this->LoadInfo();
this->Log << "Revision after update: " << this->NewRevision << "\n";
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of repository is: " << this->NewRevision
+ << "\n");
this->Log << "URL = " << this->URL << "\n";
return true;
}
-class cmCTestBZR::LogParser : public cmCTestVC::OutputLogger,
- private cmXMLParser
+class cmCTestBZR::LogParser
+ : public cmCTestVC::OutputLogger
+ , private cmXMLParser
{
public:
LogParser(cmCTestBZR* bzr, const char* prefix)
#include "cmsys/Process.h"
#include <chrono>
+#include <cstring>
#include <ratio>
#include <stdlib.h>
cmSystemTools::MakeDirectory(this->BinaryDir);
}
cmWorkingDirectory workdir(this->BinaryDir);
+ if (workdir.Failed()) {
+ auto msg = "Failed to change working directory to " + this->BinaryDir +
+ " : " + std::strerror(workdir.GetLastResult()) + "\n";
+ if (outstring) {
+ *outstring = msg;
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, msg);
+ }
+ return 1;
+ }
if (this->BuildNoCMake) {
// Make the generator available for the Build call below.
config = "Debug";
}
int retVal = cm.GetGlobalGenerator()->Build(
- this->SourceDir, this->BinaryDir, this->BuildProject, tar, output,
- this->BuildMakeProgram, config, !this->BuildNoClean, false, false,
- remainingTime);
+ cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir,
+ this->BuildProject, tar, output, this->BuildMakeProgram, config,
+ !this->BuildNoClean, false, false, remainingTime);
out << output;
// if the build failed then return
if (retVal) {
// run the test from the this->BuildRunDir if set
if (!this->BuildRunDir.empty()) {
out << "Run test in directory: " << this->BuildRunDir << "\n";
- cmSystemTools::ChangeDirectory(this->BuildRunDir);
+ if (!workdir.SetDirectory(this->BuildRunDir)) {
+ out << "Failed to change working directory : "
+ << std::strerror(workdir.GetLastResult()) << "\n";
+ if (outstring) {
+ *outstring = out.str();
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, out.str());
+ }
+ return 1;
+ }
}
out << "Running test command: \"" << fullPath << "\"";
for (std::string const& testCommandArg : this->TestCommandArgs) {
this->ErrorWarningFileLineRegex.push_back(std::move(r));
} else {
cmCTestLog(
- this->CTest, ERROR_MESSAGE, "Problem Compiling regular expression: "
+ this->CTest, ERROR_MESSAGE,
+ "Problem Compiling regular expression: "
<< cmCTestWarningErrorFileLine[entry].RegularExpressionString
<< std::endl);
}
cmGeneratedFileStream ofs;
auto elapsed_time_start = std::chrono::steady_clock::now();
if (!this->StartLogFile("Build", ofs)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build log file"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create build log file" << std::endl);
}
// Create lists of regular expression strings for errors, error exceptions,
this->CustomWarningExceptions.push_back(cmCTestWarningExceptions[cc]);
}
-// Pre-compile regular expressions objects for all regular expressions
+ // Pre-compile regular expressions objects for all regular expressions
#define cmCTestBuildHandlerPopulateRegexVector(strings, regexes) \
regexes.clear(); \
// Generate XML output
cmGeneratedFileStream xofs;
if (!this->StartResultingXML(cmCTest::PartBuild, "Build", xofs)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build XML file"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create build XML file" << std::endl);
return -1;
}
cmXMLWriter xml(xofs);
this->GenerateXMLFooter(xml, elapsed_build_time);
if (res != cmsysProcess_State_Exited || retVal || this->TotalErrors > 0) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error(s) when building project"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error(s) when building project" << std::endl);
}
// Display message about number of errors and warnings
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " "
- << this->TotalErrors
- << (this->TotalErrors >= this->MaxErrors ? " or more" : "")
- << " Compiler errors" << std::endl);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " "
- << this->TotalWarnings
- << (this->TotalWarnings >= this->MaxWarnings ? " or more" : "")
- << " Compiler warnings" << std::endl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " " << this->TotalErrors
+ << (this->TotalErrors >= this->MaxErrors ? " or more" : "")
+ << " Compiler errors" << std::endl);
+ cmCTestLog(
+ this->CTest, HANDLER_OUTPUT,
+ " " << this->TotalWarnings
+ << (this->TotalWarnings >= this->MaxWarnings ? " or more" : "")
+ << " Compiler warnings" << std::endl);
return retVal;
}
}
argv.push_back(nullptr);
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command:",
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Run command:", this->Quiet);
for (char const* arg : argv) {
if (!arg) {
break;
cmProcessOutput processOutput(encoding);
std::string strdata;
cmCTestOptionalLog(
- this->CTest, HANDLER_PROGRESS_OUTPUT, " Each symbol represents "
+ this->CTest, HANDLER_PROGRESS_OUTPUT,
+ " Each symbol represents "
<< tick_len << " bytes of output." << std::endl
<< (this->UseCTestLaunch
? ""
&this->BuildProcessingQueue);
this->ProcessBuffer(nullptr, 0, tick, tick_len, ofs,
&this->BuildProcessingErrorQueue);
- cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size of output: "
+ cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT,
+ " Size of output: "
<< ((this->BuildOutputLogSize + 512) / 1024) << "K"
<< std::endl,
this->Quiet);
errorwarning.Error = true;
this->ErrorsAndWarnings.push_back(std::move(errorwarning));
this->TotalErrors++;
- cmCTestLog(this->CTest, ERROR_MESSAGE, "There was an error: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "There was an error: " << cmsysProcess_GetErrorString(cp)
+ << std::endl);
}
cmsysProcess_Delete(cp);
this->LastTickChar, this->Quiet);
tickDisplayed = true;
if (tick % tick_line_len == 0 && tick > 0) {
- cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size: "
+ cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT,
+ " Size: "
<< ((this->BuildOutputLogSize + 512) / 1024) << "K"
<< std::endl
<< " ",
for (cmsys::RegularExpression& rx : this->ErrorExceptionRegex) {
if (rx.find(data)) {
errorLine = 0;
- cmCTestOptionalLog(this->CTest, DEBUG, " Not an error Line: "
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Not an error Line: "
<< data << " (matches: "
<< this->CustomErrorExceptions[wrxCnt] << ")"
<< std::endl,
for (cmsys::RegularExpression& rx : this->WarningMatchRegex) {
if (rx.find(data)) {
warningLine = 1;
- cmCTestOptionalLog(this->CTest, DEBUG, " Warning Line: "
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Warning Line: "
<< data << " (matches: "
<< this->CustomWarningMatches[wrxCnt] << ")"
<< std::endl,
for (cmsys::RegularExpression& rx : this->WarningExceptionRegex) {
if (rx.find(data)) {
warningLine = 0;
- cmCTestOptionalLog(this->CTest, DEBUG, " Not a warning Line: "
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Not a warning Line: "
<< data << " (matches: "
<< this->CustomWarningExceptions[wrxCnt] << ")"
<< std::endl,
bool ProcessLine() override
{
- if (this->Line == ("======================================="
- "======================================")) {
+ if (this->Line ==
+ ("======================================="
+ "======================================")) {
// This line ends the revision list.
if (this->Section == SectionRevisions) {
this->FinishRevision();
if (!this->CTest->GetShowOnly()) {
cmGeneratedFileStream os;
if (!this->StartResultingXML(cmCTest::PartConfigure, "Configure", os)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open configure file"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open configure file" << std::endl);
return 1;
}
std::string start_time = this->CTest->CurrentTime();
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <chrono>
+#include <cstring>
#include <iomanip>
#include <iterator>
#include <sstream>
for (cmsys::RegularExpression& rx : this->CustomCoverageExcludeRegex) {
if (rx.find(file)) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " File "
- << file << " is excluded in CTestCustom.ctest"
- << std::endl;
- , this->Quiet);
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " File " << file << " is excluded in CTestCustom.ctest" << std::endl;
+ , this->Quiet);
return false;
}
}
if (!this->StartResultingXML(cmCTest::PartCoverage, "Coverage",
covSumFile)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open coverage summary file."
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open coverage summary file." << std::endl);
return -1;
}
covSumFile.setf(std::ios::fixed, std::ios::floatfield);
this->Quiet);
file_count++;
if (file_count % 50 == 0) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " processed: "
- << file_count << " out of "
- << cont.TotalCoverage.size() << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " processed: " << file_count << " out of "
+ << cont.TotalCoverage.size()
+ << std::endl,
this->Quiet);
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet);
}
float cper = 0;
float cmet = 0;
if (tested + untested > 0) {
- cper = (100 * SAFEDIV(static_cast<float>(tested),
- static_cast<float>(tested + untested)));
+ cper = (100 *
+ SAFEDIV(static_cast<float>(tested),
+ static_cast<float>(tested + untested)));
cmet = (SAFEDIV(static_cast<float>(tested + 10),
static_cast<float>(tested + untested + 10)));
}
covSumXML.EndElement(); // Coverage
this->CTest->EndXML(covSumXML);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, ""
- << std::endl
- << "\tCovered LOC: " << total_tested << std::endl
- << "\tNot covered LOC: " << total_untested << std::endl
- << "\tTotal LOC: " << total_lines << std::endl
- << "\tPercentage Coverage: "
- << std::setiosflags(std::ios::fixed) << std::setprecision(2)
- << (percent_coverage) << "%" << std::endl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ "" << std::endl
+ << "\tCovered LOC: " << total_tested << std::endl
+ << "\tNot covered LOC: " << total_untested << std::endl
+ << "\tTotal LOC: " << total_lines << std::endl
+ << "\tPercentage Coverage: "
+ << std::setiosflags(std::ios::fixed) << std::setprecision(2)
+ << (percent_coverage) << "%" << std::endl);
ofs << "\tCovered LOC: " << total_tested << std::endl
<< "\tNot covered LOC: " << total_untested << std::endl
// Compare file names: fnc(fn1) == fnc(fn2) // fnc == file name compare
//
#ifdef _WIN32
-#define fnc(s) cmSystemTools::LowerCase(s)
+# define fnc(s) cmSystemTools::LowerCase(s)
#else
-#define fnc(s) s
+# define fnc(s) s
#endif
bool IsFileInDir(const std::string& infile, const std::string& indir)
std::string gcovCommand =
this->CTest->GetCTestConfiguration("CoverageCommand");
if (gcovCommand.empty()) {
- cmCTestLog(this->CTest, WARNING, "Could not find gcov." << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Could not find gcov." << std::endl, this->Quiet);
return 0;
}
std::string gcovExtraFlags =
std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
std::string tempDir = testingDir + "/CoverageInfo";
- cmSystemTools::MakeDirectory(tempDir);
+ if (!cmSystemTools::MakeDirectory(tempDir)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to make directory: " << tempDir << std::endl);
+ cont->Error++;
+ return 0;
+ }
cmWorkingDirectory workdir(tempDir);
int gcovStyle = 0;
continue;
}
if (retVal != 0) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Coverage command returned: "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Coverage command returned: "
<< retVal << " while processing: " << f << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Command produced error: " << cont->Error << std::endl);
gcovStyle = 1;
}
if (gcovStyle != 1) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e1"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e1" << std::endl);
cont->Error++;
break;
}
gcovStyle = 1;
}
if (gcovStyle != 1) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e2"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e2" << std::endl);
cont->Error++;
break;
}
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e3"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e3" << std::endl);
cont->Error++;
break;
}
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e4"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e4" << std::endl);
cont->Error++;
break;
}
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e5"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e5" << std::endl);
cont->Error++;
break;
}
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e6"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e6" << std::endl);
cont->Error++;
break;
}
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e7"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e7" << std::endl);
cont->Error++;
break;
}
- cmCTestOptionalLog(this->CTest, WARNING, "Warning: Cannot open file: "
- << st2re5.match(1) << std::endl,
+ cmCTestOptionalLog(this->CTest, WARNING,
+ "Warning: Cannot open file: " << st2re5.match(1)
+ << std::endl,
this->Quiet);
} else if (st2re6.find(line.c_str())) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e8"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e8" << std::endl);
cont->Error++;
break;
}
- cmCTestOptionalLog(this->CTest, WARNING, "Warning: File: "
- << st2re6.match(1) << " is newer than "
- << st2re6.match(2) << std::endl,
+ cmCTestOptionalLog(this->CTest, WARNING,
+ "Warning: File: " << st2re6.match(1)
+ << " is newer than "
+ << st2re6.match(2) << std::endl,
this->Quiet);
} else {
// gcov 4.7 can have output lines saying "No executable lines" and
// "Removing 'filename.gcov'"... Don't log those as "errors."
if (line != "No executable lines" &&
!cmSystemTools::StringStartsWith(line.c_str(), "Removing ")) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output line: ["
- << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output line: [" << line << "]"
+ << std::endl);
cont->Error++;
// abort();
}
this->Quiet);
std::string fileDir = cmSystemTools::GetFilenamePath(f);
cmWorkingDirectory workdir(fileDir);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to change working directory to "
+ << fileDir << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ cont->Error++;
+ continue;
+ }
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Current coverage dir: " << fileDir << std::endl,
continue;
}
if (retVal != 0) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Coverage command returned: "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Coverage command returned: "
<< retVal << " while processing: " << f << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Command produced error: " << cont->Error << std::endl);
gl.RecurseThroughSymlinksOff();
std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory");
cmWorkingDirectory workdir(buildDir);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to change working directory to " << buildDir
+ << std::endl);
+ return false;
+ }
// Run profmerge to merge all *.dyn files into dpi files
if (!cmSystemTools::RunSingleCommand("profmerge")) {
"run covbr: " << std::endl, this->Quiet);
if (!this->RunBullseyeCommand(cont, "covbr", nullptr, outputFile)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "error running covbr for."
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error running covbr for."
<< "\n");
return -1;
}
cmXMLWriter xml(covSumFile);
if (!this->StartResultingXML(cmCTest::PartCoverage, "Coverage",
covSumFile)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open coverage summary file."
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open coverage summary file." << std::endl);
return 0;
}
this->CTest->StartXML(xml, this->AppendXML);
}
// should be at the end now
if (pos != std::string::npos) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing input : "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error parsing input : "
<< inputLine << " last pos not npos = " << pos << "\n");
}
return true;
#include "cmCTestCurl.h"
#include "cmCTest.h"
+#include "cmCurl.h"
#include "cmSystemTools.h"
#include <ostream>
if (!this->Curl) {
return false;
}
+ cmCurlSetCAInfo(this->Curl);
if (this->VerifyPeerOff) {
curl_easy_setopt(this->Curl, CURLOPT_SSL_VERIFYPEER, 0);
}
::curl_slist_append(nullptr, "Content-Type: text/xml");
// Add any additional headers that the user specified.
for (std::string const& h : this->HttpHeaders) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestOptionalLog(this->CTest, DEBUG,
" Add HTTP Header: \"" << h << "\"" << std::endl,
this->Quiet);
headers = ::curl_slist_append(headers, h.c_str());
"Curl debug: [" << curlDebug << "]\n", this->Quiet);
}
if (response.empty()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "No response from server.\n"
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "No response from server.\n"
<< curlDebug);
return false;
}
std::string const& fields, std::string& response)
{
response.clear();
- cmCTestOptionalLog(this->CTest, DEBUG, "HttpRequest\n"
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "HttpRequest\n"
<< "url: " << url << "\n"
<< "fields " << fields << "\n",
this->Quiet);
struct curl_slist* headers = nullptr;
if (!this->HttpHeaders.empty()) {
for (std::string const& h : this->HttpHeaders) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestOptionalLog(this->CTest, DEBUG,
" Add HTTP Header: \"" << h << "\"" << std::endl,
this->Quiet);
headers = ::curl_slist_append(headers, h.c_str());
public:
cmCTestCurl(cmCTest*);
~cmCTestCurl();
- bool UploadFile(std::string const& url, std::string const& file,
+ bool UploadFile(std::string const& local_file, std::string const& url,
std::string const& fields, std::string& response);
bool HttpRequest(std::string const& url, std::string const& fields,
std::string& response);
bool cmCTestGIT::NoteOldRevision()
{
this->OldRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of repository is: " << this->OldRevision
+ << "\n");
this->PriorRev.Rev = this->OldRevision;
return true;
}
bool cmCTestGIT::NoteNewRevision()
{
this->NewRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of repository is: " << this->NewRevision
+ << "\n");
return true;
}
}
if (!this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(), ostr.str(),
xofs, true)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create resulting XML file: "
- << ostr.str() << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create resulting XML file: " << ostr.str()
+ << std::endl);
return false;
}
this->CTest->AddSubmitFile(part, ostr.str().c_str());
{
public:
/**
- * If verbose then more informaiton is printed out
+ * If verbose then more information is printed out
*/
void SetVerbose(bool val)
{
bool cmCTestHG::NoteOldRevision()
{
this->OldRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of repository is: " << this->OldRevision
+ << "\n");
this->PriorRev.Rev = this->OldRevision;
return true;
}
bool cmCTestHG::NoteNewRevision()
{
this->NewRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of repository is: " << this->NewRevision
+ << "\n");
return true;
}
return this->RunUpdateCommand(&hg_update[0], &out, &err);
}
-class cmCTestHG::LogParser : public cmCTestVC::OutputLogger,
- private cmXMLParser
+class cmCTestHG::LogParser
+ : public cmCTestVC::OutputLogger
+ , private cmXMLParser
{
public:
LogParser(cmCTestHG* hg, const char* prefix)
this->InitializeParser();
}
~LogParser() override { this->CleanupParser(); }
+
private:
cmCTestHG* HG;
#include "cmWorkingDirectory.h"
#include "cmake.h"
+#include <cstring>
#include <sstream>
#include <stdlib.h>
"BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(),
this->Quiet);
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "CTEST_BINARY_DIRECTORY not set"
- << std::endl;);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "CTEST_BINARY_DIRECTORY not set" << std::endl;);
}
}
if (this->Values[ct_SOURCE]) {
- cmCTestLog(this->CTest, DEBUG, "Set source directory to: "
- << this->Values[ct_SOURCE] << std::endl);
+ cmCTestLog(this->CTest, DEBUG,
+ "Set source directory to: " << this->Values[ct_SOURCE]
+ << std::endl);
this->CTest->SetCTestConfiguration(
"SourceDirectory",
cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
cmCTestGenericHandler* handler = this->InitializeHandler();
if (!handler) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot instantiate test handler "
- << this->GetName() << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot instantiate test handler " << this->GetName()
+ << std::endl);
if (capureCMakeError) {
this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
"-1");
}
cmWorkingDirectory workdir(
this->CTest->GetCTestConfiguration("BuildDirectory"));
+ if (workdir.Failed()) {
+ this->SetError("failed to change directory to " +
+ this->CTest->GetCTestConfiguration("BuildDirectory") +
+ " : " + std::strerror(workdir.GetLastResult()));
+ if (capureCMakeError) {
+ this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
+ "-1");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ this->GetName() << " " << this->GetError() << "\n");
+ // return success because failure is recorded in CAPTURE_CMAKE_ERROR
+ return true;
+ }
+ return false;
+ }
+
int res = handler->ProcessHandler();
if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) {
std::ostringstream str;
return true;
}
this->Values[k] = arg.c_str();
- cmCTestLog(this->CTest, DEBUG, "Set " << this->Arguments[k] << " to "
- << arg << "\n");
+ cmCTestLog(this->CTest, DEBUG,
+ "Set " << this->Arguments[k] << " to " << arg << "\n");
return true;
}
return false;
#include "cmake.h"
#ifdef _WIN32
-#include <fcntl.h> // for _O_BINARY
-#include <io.h> // for _setmode
-#include <stdio.h> // for std{out,err} and fileno
+# include <fcntl.h> // for _O_BINARY
+# include <io.h> // for _setmode
+# include <stdio.h> // for std{out,err} and fileno
#endif
cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv)
// Use cmGeneratedFileStream to atomically create the report file.
cmGeneratedFileStream fxml(logXML.c_str());
cmXMLWriter xml(fxml, 2);
- xml.StartElement("Failure");
- xml.Attribute("type", this->IsError() ? "Error" : "Warning");
- this->WriteXMLAction(xml);
- this->WriteXMLCommand(xml);
- this->WriteXMLResult(xml);
- this->WriteXMLLabels(xml);
- xml.EndElement(); // Failure
+ cmXMLElement e2(xml, "Failure");
+ e2.Attribute("type", this->IsError() ? "Error" : "Warning");
+ this->WriteXMLAction(e2);
+ this->WriteXMLCommand(e2);
+ this->WriteXMLResult(e2);
+ this->WriteXMLLabels(e2);
}
-void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLAction(cmXMLElement& e2)
{
- xml.Comment("Meta-information about the build action");
- xml.StartElement("Action");
+ e2.Comment("Meta-information about the build action");
+ cmXMLElement e3(e2, "Action");
// TargetName
if (!this->OptionTargetName.empty()) {
- xml.Element("TargetName", this->OptionTargetName);
+ e3.Element("TargetName", this->OptionTargetName);
}
// Language
if (!this->OptionLanguage.empty()) {
- xml.Element("Language", this->OptionLanguage);
+ e3.Element("Language", this->OptionLanguage);
}
// SourceFile
source = cmSystemTools::RelativePath(this->SourceDir, source);
}
- xml.Element("SourceFile", source);
+ e3.Element("SourceFile", source);
}
// OutputFile
if (!this->OptionOutput.empty()) {
- xml.Element("OutputFile", this->OptionOutput);
+ e3.Element("OutputFile", this->OptionOutput);
}
// OutputType
outputType = "object file";
}
if (outputType) {
- xml.Element("OutputType", outputType);
+ e3.Element("OutputType", outputType);
}
-
- xml.EndElement(); // Action
}
-void cmCTestLaunch::WriteXMLCommand(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLCommand(cmXMLElement& e2)
{
- xml.Comment("Details of command");
- xml.StartElement("Command");
+ e2.Comment("Details of command");
+ cmXMLElement e3(e2, "Command");
if (!this->CWD.empty()) {
- xml.Element("WorkingDirectory", this->CWD);
+ e3.Element("WorkingDirectory", this->CWD);
}
for (std::string const& realArg : this->RealArgs) {
- xml.Element("Argument", realArg);
+ e3.Element("Argument", realArg);
}
- xml.EndElement(); // Command
}
-void cmCTestLaunch::WriteXMLResult(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLResult(cmXMLElement& e2)
{
- xml.Comment("Result of command");
- xml.StartElement("Result");
+ e2.Comment("Result of command");
+ cmXMLElement e3(e2, "Result");
// StdOut
- xml.StartElement("StdOut");
- this->DumpFileToXML(xml, this->LogOut);
- xml.EndElement(); // StdOut
+ this->DumpFileToXML(e3, "StdOut", this->LogOut);
// StdErr
- xml.StartElement("StdErr");
- this->DumpFileToXML(xml, this->LogErr);
- xml.EndElement(); // StdErr
+ this->DumpFileToXML(e3, "StdErr", this->LogErr);
// ExitCondition
- xml.StartElement("ExitCondition");
+ cmXMLElement e4(e3, "ExitCondition");
cmsysProcess* cp = this->Process;
switch (cmsysProcess_GetState(cp)) {
case cmsysProcess_State_Starting:
- xml.Content("No process has been executed");
+ e4.Content("No process has been executed");
break;
case cmsysProcess_State_Executing:
- xml.Content("The process is still executing");
+ e4.Content("The process is still executing");
break;
case cmsysProcess_State_Disowned:
- xml.Content("Disowned");
+ e4.Content("Disowned");
break;
case cmsysProcess_State_Killed:
- xml.Content("Killed by parent");
+ e4.Content("Killed by parent");
break;
case cmsysProcess_State_Expired:
- xml.Content("Killed when timeout expired");
+ e4.Content("Killed when timeout expired");
break;
case cmsysProcess_State_Exited:
- xml.Content(this->ExitCode);
+ e4.Content(this->ExitCode);
break;
case cmsysProcess_State_Exception:
- xml.Content("Terminated abnormally: ");
- xml.Content(cmsysProcess_GetExceptionString(cp));
+ e4.Content("Terminated abnormally: ");
+ e4.Content(cmsysProcess_GetExceptionString(cp));
break;
case cmsysProcess_State_Error:
- xml.Content("Error administrating child process: ");
- xml.Content(cmsysProcess_GetErrorString(cp));
+ e4.Content("Error administrating child process: ");
+ e4.Content(cmsysProcess_GetErrorString(cp));
break;
- };
- xml.EndElement(); // ExitCondition
-
- xml.EndElement(); // Result
+ }
}
-void cmCTestLaunch::WriteXMLLabels(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLLabels(cmXMLElement& e2)
{
this->LoadLabels();
if (!this->Labels.empty()) {
- xml.Comment("Interested parties");
- xml.StartElement("Labels");
+ e2.Comment("Interested parties");
+ cmXMLElement e3(e2, "Labels");
for (std::string const& label : this->Labels) {
- xml.Element("Label", label);
+ e3.Element("Label", label);
}
- xml.EndElement(); // Labels
}
}
-void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml, std::string const& fname)
+void cmCTestLaunch::DumpFileToXML(cmXMLElement& e3, const char* tag,
+ std::string const& fname)
{
cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
std::string line;
const char* sep = "";
+ cmXMLElement e4(e3, tag);
while (cmSystemTools::GetLineFromStream(fin, line)) {
if (MatchesFilterPrefix(line)) {
continue;
} else if (this->Match(line, this->RegexWarning)) {
line = "[CTest: warning matched] " + line;
}
- xml.Content(sep);
- xml.Content(line);
+ e4.Content(sep);
+ e4.Content(line);
sep = "\n";
}
}
#include <string>
#include <vector>
-class cmXMLWriter;
+class cmXMLElement;
/** \class cmCTestLaunch
* \brief Launcher for make rules to report results for ctest
// Methods to generate the xml fragment.
void WriteXML();
- void WriteXMLAction(cmXMLWriter& xml);
- void WriteXMLCommand(cmXMLWriter& xml);
- void WriteXMLResult(cmXMLWriter& xml);
- void WriteXMLLabels(cmXMLWriter& xml);
- void DumpFileToXML(cmXMLWriter& xml, std::string const& fname);
+ void WriteXMLAction(cmXMLElement&);
+ void WriteXMLCommand(cmXMLElement&);
+ void WriteXMLResult(cmXMLElement&);
+ void WriteXMLLabels(cmXMLElement&);
+ void DumpFileToXML(cmXMLElement&, const char* tag, std::string const& fname);
// Configuration
void LoadConfig();
static void xmlReportError(int line, const char* msg, void* data)
{
cmCTest* ctest = static_cast<cmCTest*>(data);
- cmCTestLog(ctest, ERROR_MESSAGE, "Error parsing XML in stream at line "
- << line << ": " << msg << std::endl);
+ cmCTestLog(ctest, ERROR_MESSAGE,
+ "Error parsing XML in stream at line " << line << ": " << msg
+ << std::endl);
}
// parse the xml file containing the results of last BoundsChecker run
const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
std::string outname = result.Name + " ";
outname.resize(maxTestNameWidth + 4, '.');
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, cc + 1
- << "/" << total << " MemCheck: #"
- << result.TestCount << ": " << outname
- << " Defects: " << memoryErrors << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ cc + 1 << "/" << total << " MemCheck: #"
+ << result.TestCount << ": " << outname
+ << " Defects: " << memoryErrors << std::endl,
this->Quiet);
}
xml.StartElement("Log");
}
}
if (cc == this->ResultStrings.size()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown Purify memory fault: "
- << pfW.match(1) << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown Purify memory fault: " << pfW.match(1)
+ << std::endl);
ostr << "*** Unknown Purify memory fault: " << pfW.match(1)
<< std::endl;
}
break; // stop the copy of output if we are full
}
}
- cmCTestOptionalLog(
- this->CTest, DEBUG, "End test (elapsed: "
- << cmDurationTo<unsigned int>(std::chrono::steady_clock::now() - sttime)
- << "s)" << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "End test (elapsed: "
+ << cmDurationTo<unsigned int>(
+ std::chrono::steady_clock::now() - sttime)
+ << "s)" << std::endl,
+ this->Quiet);
log = ostr.str();
this->DefectCount += defects;
return defects == 0;
results[err]++;
defects++;
}
- cmCTestOptionalLog(
- this->CTest, DEBUG, "End test (elapsed: "
- << cmDurationTo<unsigned int>(std::chrono::steady_clock::now() - sttime)
- << "s)" << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "End test (elapsed: "
+ << cmDurationTo<unsigned int>(
+ std::chrono::steady_clock::now() - sttime)
+ << "s)" << std::endl,
+ this->Quiet);
if (defects) {
// only put the output of Bounds Checker if there were
// errors or leaks detected
//! Parse Valgrind/Purify/Bounds Checker result out of the output
// string. After running, log holds the output and results hold the
- // different memmory errors.
+ // different memory errors.
bool ProcessMemCheckOutput(const std::string& str, std::string& log,
std::vector<int>& results);
bool ProcessMemCheckValgrindOutput(const std::string& str, std::string& log,
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMultiProcessHandler.h"
+#include "cmAffinity.h"
#include "cmCTest.h"
#include "cmCTestRunTest.h"
#include "cmCTestScriptHandler.h"
#include <algorithm>
#include <chrono>
+#include <cstring>
#include <iomanip>
#include <list>
#include <math.h>
this->TestLoad = 0;
this->Completed = 0;
this->RunningCount = 0;
+ this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable();
+ this->HaveAffinity = this->ProcessorsAvailable.size();
this->StopTimePassed = false;
this->HasCycles = false;
this->SerialTestRunning = false;
std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime();
if (stop_time != std::chrono::system_clock::time_point() &&
stop_time <= std::chrono::system_clock::now()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "The stop time has been passed. "
- "Stopping all tests."
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "The stop time has been passed. "
+ "Stopping all tests."
<< std::endl);
this->StopTimePassed = true;
return false;
}
+ if (this->HaveAffinity && this->Properties[test]->WantAffinity) {
+ size_t needProcessors = this->GetProcessorsUsed(test);
+ if (needProcessors > this->ProcessorsAvailable.size()) {
+ return false;
+ }
+ std::vector<size_t> affinity;
+ affinity.reserve(needProcessors);
+ for (size_t i = 0; i < needProcessors; ++i) {
+ auto p = this->ProcessorsAvailable.begin();
+ affinity.push_back(*p);
+ this->ProcessorsAvailable.erase(p);
+ }
+ this->Properties[test]->Affinity = std::move(affinity);
+ }
+
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"test " << test << "\n", this->Quiet);
this->TestRunningMap[test] = true; // mark the test as running
}
}
- cmWorkingDirectory workdir(this->Properties[test]->Directory);
-
- // Lock the resources we'll be using
+ // Always lock the resources we'll be using, even if we fail to set the
+ // working directory because FinishTestProcess() will try to unlock them
this->LockResources(test);
- if (testRun->StartTest(this->Total)) {
- return true;
+ cmWorkingDirectory workdir(this->Properties[test]->Directory);
+ if (workdir.Failed()) {
+ testRun->StartFailure("Failed to change working directory to " +
+ this->Properties[test]->Directory + " : " +
+ std::strerror(workdir.GetLastResult()));
+ } else {
+ if (testRun->StartTest(this->Total)) {
+ return true;
+ }
}
this->FinishTestProcess(testRun, false);
if (processors > this->ParallelLevel) {
processors = this->ParallelLevel;
}
+ // Cap tests that want affinity to the maximum affinity available.
+ if (this->HaveAffinity && processors > this->HaveAffinity &&
+ this->Properties[test]->WantAffinity) {
+ processors = this->HaveAffinity;
+ }
return processors;
}
bool testLoadOk = true;
if (this->TestLoad > 0) {
if (processors <= spareLoad) {
- cmCTestLog(this->CTest, DEBUG, "OK to run "
- << GetName(test) << ", it requires " << processors
- << " procs & system load is: " << systemLoad
- << std::endl);
+ cmCTestLog(this->CTest, DEBUG,
+ "OK to run " << GetName(test) << ", it requires "
+ << processors << " procs & system load is: "
+ << systemLoad << std::endl);
allTestsFailedTestLoadCheck = false;
} else {
testLoadOk = false;
this->UnlockResources(test);
this->RunningCount -= GetProcessorsUsed(test);
+ for (auto p : properties->Affinity) {
+ this->ProcessorsAvailable.insert(p);
+ }
+ properties->Affinity.clear();
+
delete runner;
if (started) {
this->StartNextTests();
count++;
cmCTestTestHandler::cmCTestTestProperties& p = *it.second;
+ // Don't worry if this fails, we are only showing the test list, not
+ // running the tests
cmWorkingDirectory workdir(p.Directory);
cmCTestRunTest testRun(*this);
if (!p.Labels.empty()) // print the labels
{
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Labels:",
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Labels:", this->Quiet);
}
for (std::string const& label : p.Labels) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " " << label,
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet);
}
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
<< "Total Tests: " << this->Total << std::endl,
this->Quiet);
}
cmCTestTestHandler* GetTestHandler() { return this->TestHandler; }
void SetQuiet(bool b) { this->Quiet = b; }
+
protected:
// Start the next test or tests as many as are allowed by
// ParallelLevel
// Number of tests that are complete
size_t Completed;
size_t RunningCount;
+ std::set<size_t> ProcessorsAvailable;
+ size_t HaveAffinity;
bool StopTimePassed;
// list of test properties (indices concurrent to the test map)
PropertiesMap Properties;
{
this->OldRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of repository is: " << this->OldRevision
+ << "\n");
this->PriorRev.Rev = this->OldRevision;
return true;
}
{
this->NewRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of repository is: " << this->NewRevision
+ << "\n");
return true;
}
// If any revision is unknown it means we couldn't contact the server.
// Do not process updates
if (this->OldRevision == "<unknown>" || this->NewRevision == "<unknown>") {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " At least one of the revisions "
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " At least one of the revisions "
<< "is unknown. No repository changes will be reported.\n");
return false;
}
#include "cmsys/RegularExpression.hxx"
#include <chrono>
#include <cmAlgorithms.h>
+#include <cstring>
#include <iomanip>
#include <ratio>
#include <sstream>
void cmCTestRunTest::CheckOutput(std::string const& line)
{
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex()
- << ": " << line << std::endl);
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->GetIndex() << ": " << line << std::endl);
this->ProcessOutput += line;
this->ProcessOutput += "\n";
if (!this->TestProperties->TimeoutRegularExpressions.empty()) {
for (auto& reg : this->TestProperties->TimeoutRegularExpressions) {
if (reg.first.find(this->ProcessOutput.c_str())) {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex()
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->GetIndex()
<< ": "
<< "Test timeout changed to "
<< std::chrono::duration_cast<std::chrono::seconds>(
*this->TestHandler->LogFile << "Test time = " << buf << std::endl;
}
- // Set the working directory to the tests directory to process Dart files.
- {
- cmWorkingDirectory workdir(this->TestProperties->Directory);
- this->DartProcessing();
- }
+ this->DartProcessing();
// if this is doing MemCheck then all the output needs to be put into
// Output since that is what is parsed by cmCTestMemCheckHandler
this->RunAgain = false; // reset
// change to tests directory
cmWorkingDirectory workdir(this->TestProperties->Directory);
+ if (workdir.Failed()) {
+ this->StartFailure("Failed to change working directory to " +
+ this->TestProperties->Directory + " : " +
+ std::strerror(workdir.GetLastResult()));
+ return true;
+ }
+
this->StartTest(this->TotalNumberOfTests);
return true;
}
if (!this->TestHandler->MemCheck) {
return;
}
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
- << ": process test output now: "
- << this->TestProperties->Name << " "
- << this->TestResult.Name << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": process test output now: "
+ << this->TestProperties->Name << " "
+ << this->TestResult.Name << std::endl,
this->TestHandler->GetQuiet());
cmCTestMemCheckHandler* handler =
static_cast<cmCTestMemCheckHandler*>(this->TestHandler);
handler->PostProcessTest(this->TestResult, this->Index);
}
+void cmCTestRunTest::StartFailure(std::string const& output)
+{
+ // Still need to log the Start message so the test summary records our
+ // attempt to start this test
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(2 * getNumWidth(this->TotalNumberOfTests) + 8)
+ << "Start "
+ << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
+ << this->TestProperties->Index << ": "
+ << this->TestProperties->Name << std::endl);
+
+ this->ProcessOutput.clear();
+ if (!output.empty()) {
+ *this->TestHandler->LogFile << output << std::endl;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, output << std::endl);
+ }
+
+ this->TestResult.Properties = this->TestProperties;
+ this->TestResult.ExecutionTime = cmDuration::zero();
+ this->TestResult.CompressOutput = false;
+ this->TestResult.ReturnValue = -1;
+ this->TestResult.CompletionStatus = "Failed to start";
+ this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+ this->TestResult.TestCount = this->TestProperties->Index;
+ this->TestResult.Name = this->TestProperties->Name;
+ this->TestResult.Path = this->TestProperties->Directory;
+ this->TestResult.Output = output;
+ this->TestResult.FullCommandLine.clear();
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
+}
+
// Starts the execution of a test. Returns once it has started
bool cmCTestRunTest::StartTest(size_t total)
{
this->TotalNumberOfTests = total; // save for rerun case
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(2 * getNumWidth(total) + 8)
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(2 * getNumWidth(total) + 8)
<< "Start "
<< std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
<< this->TestProperties->Index << ": "
}
return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout,
- &this->TestProperties->Environment);
+ &this->TestProperties->Environment,
+ &this->TestProperties->Affinity);
}
void cmCTestRunTest::ComputeArguments()
{
- this->Arguments.clear(); // reset becaue this might be a rerun
+ this->Arguments.clear(); // reset because this might be a rerun
std::vector<std::string>::const_iterator j =
this->TestProperties->Args.begin();
++j; // skip test name
this->TestResult.FullCommandLine = testCommand;
// Print the test command in verbose mode
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ std::endl
<< this->Index << ": "
<< (this->TestHandler->MemCheck ? "MemCheck" : "Test")
<< " command: " << testCommand << std::endl);
// Print any test-specific env vars in verbose mode
if (!this->TestProperties->Environment.empty()) {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
- << ": "
- << "Environment variables: " << std::endl);
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": "
+ << "Environment variables: " << std::endl);
}
for (std::string const& env : this->TestProperties->Environment) {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index << ": " << env
- << std::endl);
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": " << env << std::endl);
}
}
}
bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
- std::vector<std::string>* environment)
+ std::vector<std::string>* environment,
+ std::vector<size_t>* affinity)
{
this->TestProcess = cm::make_unique<cmProcess>(*this);
this->TestProcess->SetId(this->Index);
if (testTimeOut == cmDuration::zero() && explicitTimeout) {
timeout = cmDuration::zero();
}
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
- << ": "
- << "Test timeout computed to be: "
- << cmDurationTo<unsigned int>(timeout) << "\n",
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": "
+ << "Test timeout computed to be: "
+ << cmDurationTo<unsigned int>(timeout)
+ << "\n",
this->TestHandler->GetQuiet());
this->TestProcess->SetTimeout(timeout);
cmSystemTools::AppendEnv(*environment);
}
- return this->TestProcess->StartProcess(this->MultiTestHandler.Loop);
+ return this->TestProcess->StartProcess(this->MultiTestHandler.Loop,
+ affinity);
}
void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
// got for run until pass. Trick is when this is called we don't
// yet know if we are passing or failing.
if (this->NumberOfRunsLeft == 1) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << completed << "/");
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << total << " ");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(getNumWidth(total)) << completed << "/");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(getNumWidth(total)) << total << " ");
}
// if this is one of several runs of a test just print blank space
// to keep things neat
else {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << " "
- << " ");
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << " "
- << " ");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(getNumWidth(total)) << " "
+ << " ");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(getNumWidth(total)) << " "
+ << " ");
}
if (this->TestHandler->MemCheck) {
<< std::endl;
cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str());
- cmCTestLog(this->CTest, DEBUG, "Testing " << this->TestProperties->Name
- << " ... ");
+ cmCTestLog(this->CTest, DEBUG,
+ "Testing " << this->TestProperties->Name << " ... ");
}
void cmCTestRunTest::FinalizeTest()
bool StartAgain();
+ void StartFailure(std::string const& output);
+
cmCTest* GetCTest() const { return this->CTest; }
void FinalizeTest();
void DartProcessing();
void ExeNotFound(std::string exe);
bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
- std::vector<std::string>* environment);
+ std::vector<std::string>* environment,
+ std::vector<size_t>* affinity);
void WriteLogOutputTop(size_t completed, size_t total);
// Run post processing of the process output for MemCheck
void MemCheckPostProcess();
svninfo.OldRevision = this->LoadInfo(svninfo);
this->Log << "Revision for repository '" << svninfo.LocalPath
<< "' before update: " << svninfo.OldRevision << "\n";
- cmCTestLog(
- this->CTest, HANDLER_OUTPUT, " Old revision of external repository '"
- << svninfo.LocalPath << "' is: " << svninfo.OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of external repository '"
+ << svninfo.LocalPath << "' is: " << svninfo.OldRevision
+ << "\n");
}
// Set the global old revision to the one of the root
svninfo.NewRevision = this->LoadInfo(svninfo);
this->Log << "Revision for repository '" << svninfo.LocalPath
<< "' after update: " << svninfo.NewRevision << "\n";
- cmCTestLog(
- this->CTest, HANDLER_OUTPUT, " New revision of external repository '"
- << svninfo.LocalPath << "' is: " << svninfo.NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of external repository '"
+ << svninfo.LocalPath << "' is: " << svninfo.NewRevision
+ << "\n");
// svninfo.Root = ""; // uncomment to test GuessBase
this->Log << "Repository '" << svninfo.LocalPath
return RunChild(&args[0], out, err);
}
-class cmCTestSVN::LogParser : public cmCTestVC::OutputLogger,
- private cmXMLParser
+class cmCTestSVN::LogParser
+ : public cmCTestVC::OutputLogger
+ , private cmXMLParser
{
public:
LogParser(cmCTestSVN* svn, const char* prefix, SVNInfo& svninfo)
this->InitializeParser();
}
~LogParser() override { this->CleanupParser(); }
+
private:
cmCTestSVN* SVN;
cmCTestSVN::SVNInfo& SVNRepo;
#include "cmake.h"
#ifdef _WIN32
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
class cmExecutionStatus;
argv.push_back("-SR");
argv.push_back(total_script_arg.c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Executable for CTest is: "
- << cmSystemTools::GetCTestCommand() << "\n");
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Executable for CTest is: " << cmSystemTools::GetCTestCommand()
+ << "\n");
// now pass through all the other arguments
std::vector<std::string>& initArgs =
int pipe =
cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out, err);
while (pipe != cmsysProcess_Pipe_None) {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Output: " << line
- << "\n");
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Output: " << line << "\n");
if (pipe == cmsysProcess_Pipe_STDERR) {
cmCTestLog(this->CTest, ERROR_MESSAGE, line << "\n");
} else if (pipe == cmsysProcess_Pipe_STDOUT) {
retVal = cmsysProcess_GetExitValue(cp);
} else if (result == cmsysProcess_State_Exception) {
retVal = cmsysProcess_GetExitException(cp);
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was an exception: "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tThere was an exception: "
<< cmsysProcess_GetExceptionString(cp) << " " << retVal
<< std::endl);
failed = true;
} else if (result == cmsysProcess_State_Expired) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tThere was a timeout" << std::endl);
failed = true;
} else if (result == cmsysProcess_State_Error) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing ctest: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tError executing ctest: " << cmsysProcess_GetErrorString(cp)
+ << std::endl);
failed = true;
}
cmsysProcess_Delete(cp);
message << arg << " ";
}
}
- cmCTestLog(this->CTest, ERROR_MESSAGE, message.str() << argv[0]
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ message.str() << argv[0] << std::endl);
return -1;
}
return retVal;
this->Makefile->GetModulesFile("CTestScriptMode.cmake");
if (!this->Makefile->ReadListFile(systemFile.c_str()) ||
cmSystemTools::GetErrorOccuredFlag()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in read:" << systemFile
- << "\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error in read:" << systemFile << "\n");
return 2;
}
return result;
}
- // only run the curent script if we should
+ // only run the current script if we should
if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT") &&
this->ShouldRunCurrentScript) {
return this->RunCurrentScript();
}
size_t cnt = 0;
- const char* smodel = args[cnt].c_str();
+ const char* smodel = nullptr;
const char* src_dir = nullptr;
const char* bld_dir = nullptr;
- cnt++;
-
- this->CTest->SetSpecificTrack(nullptr);
- if (cnt < args.size() - 1) {
+ while (cnt < args.size()) {
if (args[cnt] == "TRACK") {
cnt++;
+ if (cnt >= args.size() || args[cnt] == "APPEND" ||
+ args[cnt] == "QUIET") {
+ this->SetError("TRACK argument missing track name");
+ return false;
+ }
this->CTest->SetSpecificTrack(args[cnt].c_str());
cnt++;
- }
- }
-
- if (cnt < args.size()) {
- if (args[cnt] == "APPEND") {
+ } else if (args[cnt] == "APPEND") {
cnt++;
this->CreateNewTag = false;
- }
- }
- if (cnt < args.size()) {
- if (args[cnt] == "QUIET") {
+ } else if (args[cnt] == "QUIET") {
cnt++;
this->Quiet = true;
- }
- }
-
- if (cnt < args.size()) {
- src_dir = args[cnt].c_str();
- cnt++;
- if (cnt < args.size()) {
+ } else if (!smodel) {
+ smodel = args[cnt].c_str();
+ cnt++;
+ } else if (!src_dir) {
+ src_dir = args[cnt].c_str();
+ cnt++;
+ } else if (!bld_dir) {
bld_dir = args[cnt].c_str();
+ cnt++;
+ } else {
+ this->SetError("Too many arguments");
+ return false;
}
}
+
if (!src_dir) {
src_dir = this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY");
}
"as an argument or set CTEST_BINARY_DIRECTORY");
return false;
}
+ if (!smodel && this->CreateNewTag) {
+ this->SetError("no test model specified and APPEND not specified. Specify "
+ "either a test model or the APPEND argument");
+ return false;
+ }
cmSystemTools::AddKeepPath(src_dir);
cmSystemTools::AddKeepPath(bld_dir);
this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir.c_str(),
this->Quiet);
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with model "
- << smodel << std::endl
- << " Source directory: " << src_dir << std::endl
- << " Build directory: " << bld_dir << std::endl,
- this->Quiet);
+ if (smodel) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "Run dashboard with model "
+ << smodel << std::endl
+ << " Source directory: " << src_dir << std::endl
+ << " Build directory: " << bld_dir << std::endl,
+ this->Quiet);
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "Run dashboard with "
+ "to-be-determined model"
+ << std::endl
+ << " Source directory: " << src_dir << std::endl
+ << " Build directory: " << bld_dir << std::endl,
+ this->Quiet);
+ }
const char* track = this->CTest->GetSpecificTrack();
if (track) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
this->CTest->SetRunCurrentScript(false);
this->CTest->SetSuppressUpdatingCTestConfiguration(true);
- int model = this->CTest->GetTestModelFromString(smodel);
+ int model;
+ if (smodel) {
+ model = this->CTest->GetTestModelFromString(smodel);
+ } else {
+ model = cmCTest::UNKNOWN;
+ }
this->CTest->SetTestModel(model);
this->CTest->SetProduceXML(true);
#include "cm_jsoncpp_value.h"
#include "cmsys/Process.h"
#include <chrono>
+#include <cstring>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include "cmake.h"
#if defined(CTEST_USE_XMLRPC)
-#include "cmVersion.h"
-#include "cm_sys_stat.h"
-#include "cm_xmlrpc.h"
+# include "cmVersion.h"
+# include "cm_sys_stat.h"
+# include "cm_xmlrpc.h"
#endif
#define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120
res = ::curl_easy_perform(curl);
if (!chunk.empty()) {
- cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: ["
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "CURL output: ["
<< cmCTestLogWrite(&*chunk.begin(), chunk.size())
<< "]" << std::endl,
this->Quiet);
}
if (!chunkDebug.empty()) {
cmCTestOptionalLog(
- this->CTest, DEBUG, "CURL debug output: ["
+ this->CTest, DEBUG,
+ "CURL debug output: ["
<< cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
<< std::endl,
this->Quiet);
fclose(ftpfile);
if (res) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Error when uploading file: "
- << local_file << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Error when uploading file: " << local_file
+ << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
" Error message was: " << error_buffer << std::endl);
*this->LogFile << " Error when uploading file: " << local_file
// avoid dereference of empty vector
if (!chunk.empty()) {
*this->LogFile << cmCTestLogWrite(&*chunk.begin(), chunk.size());
- cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "CURL output: ["
<< cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
<< std::endl);
}
// Add any additional headers that the user specified.
for (std::string const& h : this->HttpHeaders) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestOptionalLog(this->CTest, DEBUG,
" Add HTTP Header: \"" << h << "\"" << std::endl,
this->Quiet);
headers = ::curl_slist_append(headers, h.c_str());
}
}
std::string upload_as = url +
- ((url.find('?') == std::string::npos) ? '?' : '&') + "FileName=" +
- ofile;
+ ((url.find('?') == std::string::npos) ? '?' : '&') +
+ "FileName=" + ofile;
upload_as += "&MD5=";
res = ::curl_easy_perform(curl);
if (!chunk.empty()) {
- cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: ["
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "CURL output: ["
<< cmCTestLogWrite(&*chunk.begin(), chunk.size())
<< "]" << std::endl,
this->Quiet);
}
if (!chunkDebug.empty()) {
cmCTestOptionalLog(
- this->CTest, DEBUG, "CURL debug output: ["
+ this->CTest, DEBUG,
+ "CURL debug output: ["
<< cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
<< std::endl,
this->Quiet);
if (!chunk.empty()) {
cmCTestOptionalLog(
- this->CTest, DEBUG, "CURL output: ["
+ this->CTest, DEBUG,
+ "CURL output: ["
<< cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
<< std::endl,
this->Quiet);
fclose(ftpfile);
if (res) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Error when uploading file: "
- << local_file << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Error when uploading file: " << local_file
+ << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
" Error message was: " << error_buffer << std::endl);
*this->LogFile << " Error when uploading file: " << local_file
*this->LogFile << " Curl output was: "
<< cmCTestLogWrite(&*chunk.begin(), chunk.size())
<< std::endl;
- cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "CURL output: ["
<< cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
<< std::endl);
}
}
if (this->HasWarnings || this->HasErrors) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Server Response:\n"
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Server Response:\n"
<< cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n");
}
}
}
}
std::string turl = url +
- ((url.find('?') == std::string::npos) ? '?' : '&') + "xmlfile=" +
- ofile;
+ ((url.find('?') == std::string::npos) ? '?' : '&') +
+ "xmlfile=" + ofile;
*this->LogFile << "Trigger url: " << turl << std::endl;
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
" Trigger url: " << turl << std::endl, this->Quiet);
*this->LogFile << " Curl output was: "
<< cmCTestLogWrite(&*chunk.begin(), chunk.size())
<< std::endl;
- cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "CURL output: ["
<< cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
<< std::endl);
}
}
if (!chunk.empty()) {
- cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: ["
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "CURL output: ["
<< cmCTestLogWrite(&*chunk.begin(), chunk.size())
<< "]" << std::endl,
this->Quiet);
}
if (!chunkDebug.empty()) {
cmCTestOptionalLog(
- this->CTest, DEBUG, "CURL debug output: ["
+ this->CTest, DEBUG,
+ "CURL debug output: ["
<< cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
<< std::endl,
this->Quiet);
argv[1] = lfname.c_str();
std::string rfname = url + "/" + remoteprefix + file;
argv[2] = rfname.c_str();
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Execute \""
- << argv[0] << "\" \"" << argv[1] << "\" \"" << argv[2]
- << "\"" << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \""
+ << argv[2] << "\"" << std::endl,
this->Quiet);
*this->LogFile << "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \""
<< argv[2] << "\"" << std::endl;
*this->LogFile << "\tThere was an exception: " << retVal << std::endl;
problems++;
} else if (result == cmsysProcess_State_Expired) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tThere was a timeout" << std::endl);
*this->LogFile << "\tThere was a timeout" << std::endl;
problems++;
} else if (result == cmsysProcess_State_Error) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing SCP: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tError executing SCP: " << cmsysProcess_GetErrorString(cp)
+ << std::endl);
*this->LogFile << "\tError executing SCP: "
<< cmsysProcess_GetErrorString(cp) << std::endl;
problems++;
lfname += "/" + file;
std::string rfname = destination + "/" + remoteprefix + file;
cmSystemTools::CopyFileAlways(lfname, rfname);
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Copy file: "
- << lfname << " to " << rfname << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Copy file: " << lfname << " to " << rfname
+ << std::endl,
this->Quiet);
}
std::string tagDoneFile = destination + "/" + remoteprefix + "DONE";
xmlrpc_env_init(&env);
/* Call the famous server at UserLand. */
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Submitting to: "
- << realURL << " (" << remoteprefix << ")" << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Submitting to: " << realURL << " (" << remoteprefix
+ << ")" << std::endl,
this->Quiet);
for (std::string const& file : files) {
xmlrpc_value* result;
// make sure the file is not too big.
if (static_cast<off_t>(static_cast<size_t>(st.st_size)) !=
static_cast<off_t>(st.st_size)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " File too big: " << local_file
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " File too big: " << local_file << std::endl);
return false;
}
size_t fileSize = static_cast<size_t>(st.st_size);
delete[] fileBuffer;
if (env.fault_occurred) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Submission problem: "
- << env.fault_string << " (" << env.fault_code << ")"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Submission problem: " << env.fault_string << " ("
+ << env.fault_code << ")"
+ << std::endl);
xmlrpc_env_clean(&env);
xmlrpc_client_cleanup();
return false;
return -1;
}
if (!cmSystemTools::FileExists(file)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Upload file not found: '"
- << file << "'\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Upload file not found: '" << file << "'\n");
return -1;
}
cmCTestCurl curl(this->CTest);
unsigned long retryDelayValue = 0;
if (!cmSystemTools::StringToULong(retryDelayString.c_str(),
&retryDelayValue)) {
- cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : "
- << retryDelayString << std::endl);
+ cmCTestLog(this->CTest, WARNING,
+ "Invalid value for 'RETRY_DELAY' : " << retryDelayString
+ << std::endl);
} else {
retryDelay = std::chrono::seconds(retryDelayValue);
}
unsigned long retryCount = 0;
if (!retryCountString.empty()) {
if (!cmSystemTools::StringToULong(retryCountString.c_str(), &retryCount)) {
- cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : "
- << retryCountString << std::endl);
+ cmCTestLog(this->CTest, WARNING,
+ "Invalid value for 'RETRY_DELAY' : " << retryCountString
+ << std::endl);
}
}
}
}
if (!internalTest && !requestSucceeded) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in HttpRequest\n"
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error in HttpRequest\n"
<< response);
return -1;
}
Json::Value json;
Json::Reader reader;
if (!internalTest && !reader.parse(response, json)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "error parsing json string ["
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error parsing json string ["
<< response << "]\n"
<< reader.getFormattedErrorMessages() << "\n");
return -1;
}
if (!uploadSucceeded) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "error uploading to CDash. "
- << file << " " << url << " " << fstr.str());
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error uploading to CDash. " << file << " " << url << " "
+ << fstr.str());
return -1;
}
if (!reader.parse(response, json)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "error parsing json string ["
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error parsing json string ["
<< response << "]\n"
<< reader.getFormattedErrorMessages() << "\n");
return -1;
cnt++;
}
}
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Submit files (using "
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "Submit files (using "
<< this->CTest->GetCTestConfiguration("DropMethod")
<< ")" << std::endl,
this->Quiet);
std::string url = "ftp://";
url += cmCTest::MakeURLSafe(
this->CTest->GetCTestConfiguration("DropSiteUser")) +
- ":" + cmCTest::MakeURLSafe(
- this->CTest->GetCTestConfiguration("DropSitePassword")) +
+ ":" +
+ cmCTest::MakeURLSafe(
+ this->CTest->GetCTestConfiguration("DropSitePassword")) +
"@" + this->CTest->GetCTestConfiguration("DropSite") +
cmCTest::MakeURLSafe(this->CTest->GetCTestConfiguration("DropLocation"));
if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) {
return -1;
}
if (!this->CDash) {
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
- << std::endl
- << " Trigger site: "
- << this->CTest->GetCTestConfiguration("TriggerSite") << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Using HTTP trigger method"
+ << std::endl
+ << " Trigger site: "
+ << this->CTest->GetCTestConfiguration("TriggerSite")
+ << std::endl,
+ this->Quiet);
if (!this->TriggerUsingHTTP(
files, prefix,
this->CTest->GetCTestConfiguration("TriggerSite"))) {
return -1;
}
if (!this->CDash) {
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
- << std::endl
- << " Trigger site: "
- << this->CTest->GetCTestConfiguration("TriggerSite") << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Using HTTP trigger method"
+ << std::endl
+ << " Trigger site: "
+ << this->CTest->GetCTestConfiguration("TriggerSite")
+ << std::endl,
+ this->Quiet);
if (!this->TriggerUsingHTTP(
files, prefix,
this->CTest->GetCTestConfiguration("TriggerSite"))) {
}
}
if (this->HasErrors) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Errors occurred during "
- "submission."
+ 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);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Submission successful"
+ << (this->HasWarnings ? ", with warnings." : "")
+ << std::endl,
+ this->Quiet);
ofs << " Submission successful"
<< (this->HasWarnings ? ", with warnings." : "") << std::endl;
}
// change to the build directory so that we can uses a relative path
// on windows since scp doesn't support "c:" a drive in the path
cmWorkingDirectory workdir(buildDirectory);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Failed to change directory to "
+ << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ ofs << " Failed to change directory to " << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return -1;
+ }
if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"),
"Testing/" + this->CTest->GetCurrentTag(), files,
// change to the build directory so that we can uses a relative path
// on windows since scp doesn't support "c:" a drive in the path
cmWorkingDirectory workdir(buildDirectory);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Failed to change directory to "
+ << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ ofs << " Failed to change directory to " << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return -1;
+ }
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
" Change directory: " << buildDirectory << std::endl,
this->Quiet);
return 0;
}
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Unknown submission method: \""
- << dropMethod << "\"" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Unknown submission method: \"" << dropMethod << "\""
+ << std::endl);
return -1;
}
if (!cmSystemTools::StringToULong(this->Values[ctt_TEST_LOAD],
&testLoad)) {
testLoad = 0;
- cmCTestLog(this->CTest, WARNING, "Invalid value for 'TEST_LOAD' : "
+ cmCTestLog(this->CTest, WARNING,
+ "Invalid value for 'TEST_LOAD' : "
<< this->Values[ctt_TEST_LOAD] << std::endl);
}
} else if (ctestTestLoad && *ctestTestLoad) {
if (!cmSystemTools::StringToULong(ctestTestLoad, &testLoad)) {
testLoad = 0;
- cmCTestLog(this->CTest, WARNING, "Invalid value for 'CTEST_TEST_LOAD' : "
- << ctestTestLoad << std::endl);
+ cmCTestLog(this->CTest, WARNING,
+ "Invalid value for 'CTEST_TEST_LOAD' : " << ctestTestLoad
+ << std::endl);
}
} else {
testLoad = this->CTest->GetTestLoad();
#include <cmsys/Base64.h>
#include <cmsys/Directory.hxx>
#include <cmsys/RegularExpression.hxx>
+#include <cstring>
#include <functional>
#include <iomanip>
#include <iterator>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <time.h>
#include "cmAlgorithms.h"
bool readit = false;
{
cmWorkingDirectory workdir(fname);
+ if (workdir.Failed()) {
+ this->SetError("Failed to change directory to " + fname + " : " +
+ std::strerror(workdir.GetLastResult()));
+ return false;
+ }
const char* testFilename;
if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
// does the CTestTestfile.cmake exist ?
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
- */
+ */
bool InitialPass(std::vector<std::string> const& /*unused*/,
cmExecutionStatus& /*unused*/) override;
this->TestResults.clear();
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT, (this->MemCheck ? "Memory check" : "Test")
- << " project " << cmSystemTools::GetCurrentWorkingDirectory()
- << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ (this->MemCheck ? "Memory check" : "Test")
+ << " project "
+ << cmSystemTools::GetCurrentWorkingDirectory()
+ << std::endl,
+ this->Quiet);
if (!this->PreProcessHandler()) {
return -1;
}
if (total == 0) {
if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "No tests were found!!!"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "No tests were found!!!" << std::endl);
}
} else {
if (this->HandlerVerbose && !passed.empty() &&
(this->UseIncludeRegExpFlag || this->UseExcludeRegExpFlag)) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ std::endl
<< "The following tests passed:" << std::endl,
this->Quiet);
for (std::string const& j : passed) {
percent = 99;
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
<< static_cast<int>(percent + .5f) << "% tests passed, "
<< failed.size() << " tests failed out of " << total
<< std::endl);
if (!disabledTests.empty()) {
cmGeneratedFileStream ofs;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
<< "The following tests did not run:" << std::endl);
this->StartLogFile("TestsDisabled", ofs);
} else {
disabled_reason = "Skipped";
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t"
- << std::setw(3) << dt.TestCount << " - " << dt.Name
- << " (" << disabled_reason << ")" << std::endl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ "\t" << std::setw(3) << dt.TestCount << " - " << dt.Name
+ << " (" << disabled_reason << ")" << std::endl);
}
}
if (!failed.empty()) {
cmGeneratedFileStream ofs;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
<< "The following tests FAILED:" << std::endl);
this->StartLogFile("TestsFailed", ofs);
!cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") &&
ft.CompletionStatus != "Disabled") {
ofs << ft.TestCount << ":" << ft.Name << std::endl;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t"
- << std::setw(3) << ft.TestCount << " - " << ft.Name
- << " (" << this->GetTestStatus(ft) << ")" << std::endl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ "\t" << std::setw(3) << ft.TestCount << " - " << ft.Name
+ << " (" << this->GetTestStatus(ft) << ")"
+ << std::endl);
}
}
}
if (!this->StartResultingXML(
(this->MemCheck ? cmCTest::PartMemCheck : cmCTest::PartTest),
(this->MemCheck ? "DynamicAnalysis" : "Test"), xmlfile)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create "
<< (this->MemCheck ? "memory check" : "testing")
<< " XML file" << std::endl);
this->LogFile = nullptr;
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
"\nSubproject Time Summary:", this->Quiet);
} else {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\nLabel Time Summary:",
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "\nLabel Time Summary:", this->Quiet);
}
for (std::string const& i : labels) {
std::string label = i;
labelCountStr << "s";
}
labelCountStr << ")";
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n"
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "\n"
<< label << " = " << buf << " "
<< labelCountStr.str(),
this->Quiet);
}
}
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Added "
- << fixtureTestsAdded
- << " tests to meet fixture requirements" << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Added " << fixtureTestsAdded
+ << " tests to meet fixture requirements"
+ << std::endl,
this->Quiet);
}
fin >> value;
ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
fin >> value;
ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
#endif
ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
fin >> value;
ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
if (line == tag) {
ret = cmSystemTools::GetLineFromStream(fin, value);
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
}
}
if (fullPath.empty()) {
- cmCTestLog(ctest, HANDLER_OUTPUT, "Could not find executable "
+ cmCTestLog(ctest, HANDLER_OUTPUT,
+ "Could not find executable "
<< testCommand << "\n"
<< "Looked in the following places:\n");
for (std::string const& f : failed) {
cmsys::Directory directory;
if (directory.Load(dirName) == 0) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to read the contents of "
- << dirName << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to read the contents of " << dirName << std::endl);
return;
}
if (!cmSystemTools::FileExists(lastTestsFailedLog)) {
if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, lastTestsFailedLog
- << " does not exist!" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ lastTestsFailedLog << " does not exist!" << std::endl);
}
return;
}
ifs.close();
} else if (!this->CTest->GetShowOnly() &&
!this->CTest->ShouldPrintLabels()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem reading file: "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Problem reading file: "
<< lastTestsFailedLog
<< " while generating list of previously failed tests."
<< std::endl);
xml.Element("Value", "Image " + filename + " is empty");
xml.EndElement();
} else {
- cmsys::ifstream ifs(filename.c_str(), std::ios::in
+ cmsys::ifstream ifs(filename.c_str(),
+ std::ios::in
#ifdef _WIN32
| std::ios::binary
#endif
- );
+ );
unsigned char* file_buffer = new unsigned char[len + 1];
ifs.read(reinterpret_cast<char*>(file_buffer), len);
unsigned char* encoded_buffer = new unsigned char[static_cast<int>(
xml.Attribute("text", "text/string");
xml.Element("Value", "File " + filename + " not found");
xml.EndElement();
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "File \""
- << filename << "\" not found." << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ "File \"" << filename << "\" not found." << std::endl, this->Quiet);
}
cxml.erase(measurementfile.start(),
measurementfile.end() - measurementfile.start());
rt.Processors = 1;
}
}
+ if (key == "PROCESSOR_AFFINITY") {
+ rt.WantAffinity = cmSystemTools::IsOn(val.c_str());
+ }
if (key == "SKIP_RETURN_CODE") {
rt.SkipReturnCode = atoi(val.c_str());
if (rt.SkipReturnCode < 0 || rt.SkipReturnCode > 255) {
test.ExplicitTimeout = false;
test.Cost = 0;
test.Processors = 1;
+ test.WantAffinity = false;
test.SkipReturnCode = -1;
test.PreviousRuns = 0;
if (this->UseIncludeRegExpFlag &&
int Index;
// Requested number of process slots
int Processors;
+ bool WantAffinity;
+ std::vector<size_t> Affinity;
// return code of test which will mark test as "not run"
int SkipReturnCode;
std::vector<std::string> Environment;
int cmCTestUpdateHandler::DetermineType(const char* cmd, const char* type)
{
- cmCTestOptionalLog(this->CTest, DEBUG, "Determine update type from command: "
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Determine update type from command: "
<< cmd << " and type: " << type << std::endl,
this->Quiet);
if (type && *type) {
return -1;
}
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Use "
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Use "
<< cmCTestUpdateHandlerUpdateToString(this->UpdateType)
<< " repository type" << std::endl;
, this->Quiet);
//
cmGeneratedFileStream os;
if (!this->StartResultingXML(cmCTest::PartUpdate, "Update", os)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open log file"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open log file" << std::endl);
return -1;
}
std::string start_time = this->CTest->CurrentTime();
std::string("ctest-") + cmVersion::GetCMakeVersion());
xml.Element("Site", this->CTest->GetCTestConfiguration("Site"));
xml.Element("BuildName", buildname);
- xml.Element("BuildStamp", this->CTest->GetCurrentTag() + "-" +
+ xml.Element("BuildStamp",
+ this->CTest->GetCurrentTag() + "-" +
this->CTest->GetTestModelString());
xml.Element("StartDateTime", start_time);
xml.Element("StartTime", start_time_time);
this->Quiet);
}
if (int numModified = vc->GetPathCount(cmCTestVC::PathModified)) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Found "
- << numModified << " locally modified files\n",
- this->Quiet);
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ " Found " << numModified << " locally modified files\n", this->Quiet);
localModifications += numModified;
}
if (int numConflicting = vc->GetPathCount(cmCTestVC::PathConflicting)) {
if (!updated) {
xml.Content("Update command failed:\n");
xml.Content(vc->GetUpdateCommandLine());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Update command failed: "
- << vc->GetUpdateCommandLine() << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Update command failed: " << vc->GetUpdateCommandLine()
+ << "\n");
}
xml.EndElement(); // UpdateReturnStatus
xml.EndElement(); // Update
cmGeneratedFileStream ofs;
if (!this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(), "Upload.xml",
ofs)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open Upload.xml file"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open Upload.xml file" << std::endl);
return -1;
}
std::string buildname =
"<file:///Dart/Source/Server/XSL/Build.xsl> \"");
xml.StartElement("Site");
xml.Attribute("BuildName", buildname);
- xml.Attribute("BuildStamp", this->CTest->GetCurrentTag() + "-" +
+ xml.Attribute("BuildStamp",
+ this->CTest->GetCurrentTag() + "-" +
this->CTest->GetTestModelString());
xml.Attribute("Name", this->CTest->GetCTestConfiguration("Site"));
xml.Attribute("Generator",
bool result = this->RunChild(&vc_co[0], &out, &err, parent.c_str());
this->Log << "--- End Initial Checkout ---\n";
if (!result) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Initial checkout failed!"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Initial checkout failed!" << std::endl);
}
return result;
}
std::string line;
std::vector<std::string> separateLine;
if (!cmSystemTools::GetLineFromStream(in, line)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Empty file : "
- << file << " referenced in this line of cmcov data:\n"
- "["
- << line << "]\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Empty file : " << file
+ << " referenced in this line of cmcov data:\n"
+ "["
+ << line << "]\n");
return false;
}
separateLine.clear();
separateLine[1] != "Line" || separateLine[2] != "RtnLine" ||
separateLine[3] != "Code") {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Bad first line of cmcov file : " << file << " line:\n"
- "["
+ "Bad first line of cmcov file : " << file
+ << " line:\n"
+ "["
<< line << "]\n");
}
std::string routine;
if (separateLine.size() < 4) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Bad line of cmcov file expected at least 4 found: "
- << separateLine.size() << " " << file << " line:\n"
- "["
+ << separateLine.size() << " " << file
+ << " line:\n"
+ "["
<< line << "]\n");
for (std::string::size_type i = 0; i < separateLine.size(); ++i) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "" << separateLine[1] << " ");
while (true) {
lastoffset = line.find('(', pos);
if (lastoffset == std::string::npos) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, endnamepos
- << "File not found " << lastoffset << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ endnamepos << "File not found " << lastoffset
+ << std::endl,
this->Coverage.Quiet);
return false;
}
this->Coverage.TotalCoverage[lastpath][lastoffset + linenumber] +=
count;
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not find mumps file : "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Can not find mumps file : "
<< lastroutine
<< " referenced in this line of mcov data:\n"
"["
lastoffset = lineoffset;
}
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not find mumps file : "
- << routine << " referenced in this line of mcov data:\n"
- "["
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Can not find mumps file : "
+ << routine
+ << " referenced in this line of mcov data:\n"
+ "["
<< line << "]\n");
}
lastfunction = function;
linenum++; // move to next line count
}
lineoffset = 0;
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Could not find entry point : "
- << function << " in " << filepath << "\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Could not find entry point : " << function << " in " << filepath
+ << "\n");
return false;
}
}
// less then two arguments is an error
if (args.size() < 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing mcov line: ["
- << line << "]\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error parsing mcov line: [" << line << "]\n");
return false;
}
routine = args[0]; // the routine is the first argument
if (this->PackagePath.empty()) {
if (!this->FindPackagePath(fileName)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find file: "
- << this->PackageName << "/" << fileName << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot find file: " << this->PackageName << "/"
+ << fileName << std::endl);
this->Coverage.Error++;
return;
}
delete[] s;
// read close quote
if (in.get(c) && c != '"') {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "failed to read close quote\n"
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "failed to read close quote\n"
<< "read [" << c << "]\n");
return false;
}
}
for (int i = 0; i < size; i++) {
if (!this->ReadFileInformation(in)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Failed to read file #" << i
- << "\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Failed to read file #" << i << "\n");
return false;
}
in.get(c);
#include <signal.h>
#include <string>
#if !defined(_WIN32)
-#include <unistd.h>
+# include <unistd.h>
#endif
#define CM_PROCESS_BUF_SIZE 65536
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h>
+# include <io.h>
static int cmProcessGetPipes(int* fds)
{
return 0;
}
#else
-#include <errno.h>
+# include <errno.h>
static int cmProcessGetPipes(int* fds)
{
this->Arguments = args;
}
-bool cmProcess::StartProcess(uv_loop_t& loop)
+bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity)
{
this->ProcessState = cmProcess::State::Error;
if (this->Command.empty()) {
options.stdio_count = 3; // in, out and err
options.exit_cb = &cmProcess::OnExitCB;
options.stdio = stdio;
+#if !defined(CMAKE_USE_SYSTEM_LIBUV)
+ std::vector<char> cpumask;
+ if (affinity && !affinity->empty()) {
+ cpumask.resize(static_cast<size_t>(uv_cpumask_size()), 0);
+ for (auto p : *affinity) {
+ cpumask[p] = 1;
+ }
+ options.cpumask = cpumask.data();
+ options.cpumask_size = cpumask.size();
+ } else {
+ options.cpumask = nullptr;
+ options.cpumask_size = 0;
+ }
+#else
+ static_cast<void>(affinity);
+#endif
status =
uv_read_start(pipe_reader, &cmProcess::OnAllocateCB, &cmProcess::OnReadCB);
status = this->Process.spawn(loop, options, this);
if (status != 0) {
- cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, "Process not started\n "
- << this->Command << "\n[" << uv_strerror(status) << "]\n");
+ cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE,
+ "Process not started\n " << this->Command << "\n["
+ << uv_strerror(status) << "]\n");
return false;
}
#else
term_signal != 0
#endif
- ) {
+ ) {
this->ProcessState = cmProcess::State::Exception;
} else {
this->ProcessState = cmProcess::State::Exited;
{
auto exception = Exception::None;
#if defined(_WIN32) && !defined(__CYGWIN__)
- auto exit_code = (DWORD) this->ExitValue;
+ auto exit_code = (DWORD)this->ExitValue;
if ((exit_code & 0xF0000000) != 0xC0000000) {
return exception;
}
case STATUS_FLOAT_OVERFLOW:
case STATUS_FLOAT_STACK_CHECK:
case STATUS_FLOAT_UNDERFLOW:
-#ifdef STATUS_FLOAT_MULTIPLE_FAULTS
+# ifdef STATUS_FLOAT_MULTIPLE_FAULTS
case STATUS_FLOAT_MULTIPLE_FAULTS:
-#endif
-#ifdef STATUS_FLOAT_MULTIPLE_TRAPS
+# endif
+# ifdef STATUS_FLOAT_MULTIPLE_TRAPS
case STATUS_FLOAT_MULTIPLE_TRAPS:
-#endif
+# endif
case STATUS_INTEGER_DIVIDE_BY_ZERO:
case STATUS_INTEGER_OVERFLOW:
exception = Exception::Numerical;
case STATUS_FLOAT_UNDERFLOW:
exception_str = "Floating-point underflow";
break;
-#ifdef STATUS_FLOAT_MULTIPLE_FAULTS
+# ifdef STATUS_FLOAT_MULTIPLE_FAULTS
case STATUS_FLOAT_MULTIPLE_FAULTS:
exception_str = "Floating-point exception (multiple faults)";
break;
-#endif
-#ifdef STATUS_FLOAT_MULTIPLE_TRAPS
+# endif
+# ifdef STATUS_FLOAT_MULTIPLE_TRAPS
case STATUS_FLOAT_MULTIPLE_TRAPS:
exception_str = "Floating-point exception (multiple traps)";
break;
-#endif
+# endif
case STATUS_INTEGER_DIVIDE_BY_ZERO:
exception_str = "Integer divide-by-zero";
break;
}
#else
switch (this->Signal) {
-#ifdef SIGSEGV
+# ifdef SIGSEGV
case SIGSEGV:
exception_str = "Segmentation fault";
break;
-#endif
-#ifdef SIGBUS
-#if !defined(SIGSEGV) || SIGBUS != SIGSEGV
+# endif
+# ifdef SIGBUS
+# if !defined(SIGSEGV) || SIGBUS != SIGSEGV
case SIGBUS:
exception_str = "Bus error";
break;
-#endif
-#endif
-#ifdef SIGFPE
+# endif
+# endif
+# ifdef SIGFPE
case SIGFPE:
exception_str = "Floating-point exception";
break;
-#endif
-#ifdef SIGILL
+# endif
+# ifdef SIGILL
case SIGILL:
exception_str = "Illegal instruction";
break;
-#endif
-#ifdef SIGINT
+# endif
+# ifdef SIGINT
case SIGINT:
exception_str = "User interrupt";
break;
-#endif
-#ifdef SIGABRT
+# endif
+# ifdef SIGABRT
case SIGABRT:
exception_str = "Child aborted";
break;
-#endif
-#ifdef SIGKILL
+# endif
+# ifdef SIGKILL
case SIGKILL:
exception_str = "Child killed";
break;
-#endif
-#ifdef SIGTERM
+# endif
+# ifdef SIGTERM
case SIGTERM:
exception_str = "Child terminated";
break;
-#endif
-#ifdef SIGHUP
+# endif
+# ifdef SIGHUP
case SIGHUP:
exception_str = "SIGHUP";
break;
-#endif
-#ifdef SIGQUIT
+# endif
+# ifdef SIGQUIT
case SIGQUIT:
exception_str = "SIGQUIT";
break;
-#endif
-#ifdef SIGTRAP
+# endif
+# ifdef SIGTRAP
case SIGTRAP:
exception_str = "SIGTRAP";
break;
-#endif
-#ifdef SIGIOT
-#if !defined(SIGABRT) || SIGIOT != SIGABRT
+# endif
+# ifdef SIGIOT
+# if !defined(SIGABRT) || SIGIOT != SIGABRT
case SIGIOT:
exception_str = "SIGIOT";
break;
-#endif
-#endif
-#ifdef SIGUSR1
+# endif
+# endif
+# ifdef SIGUSR1
case SIGUSR1:
exception_str = "SIGUSR1";
break;
-#endif
-#ifdef SIGUSR2
+# endif
+# ifdef SIGUSR2
case SIGUSR2:
exception_str = "SIGUSR2";
break;
-#endif
-#ifdef SIGPIPE
+# endif
+# ifdef SIGPIPE
case SIGPIPE:
exception_str = "SIGPIPE";
break;
-#endif
-#ifdef SIGALRM
+# endif
+# ifdef SIGALRM
case SIGALRM:
exception_str = "SIGALRM";
break;
-#endif
-#ifdef SIGSTKFLT
+# endif
+# ifdef SIGSTKFLT
case SIGSTKFLT:
exception_str = "SIGSTKFLT";
break;
-#endif
-#ifdef SIGCHLD
+# endif
+# ifdef SIGCHLD
case SIGCHLD:
exception_str = "SIGCHLD";
break;
-#elif defined(SIGCLD)
+# elif defined(SIGCLD)
case SIGCLD:
exception_str = "SIGCLD";
break;
-#endif
-#ifdef SIGCONT
+# endif
+# ifdef SIGCONT
case SIGCONT:
exception_str = "SIGCONT";
break;
-#endif
-#ifdef SIGSTOP
+# endif
+# ifdef SIGSTOP
case SIGSTOP:
exception_str = "SIGSTOP";
break;
-#endif
-#ifdef SIGTSTP
+# endif
+# ifdef SIGTSTP
case SIGTSTP:
exception_str = "SIGTSTP";
break;
-#endif
-#ifdef SIGTTIN
+# endif
+# ifdef SIGTTIN
case SIGTTIN:
exception_str = "SIGTTIN";
break;
-#endif
-#ifdef SIGTTOU
+# endif
+# ifdef SIGTTOU
case SIGTTOU:
exception_str = "SIGTTOU";
break;
-#endif
-#ifdef SIGURG
+# endif
+# ifdef SIGURG
case SIGURG:
exception_str = "SIGURG";
break;
-#endif
-#ifdef SIGXCPU
+# endif
+# ifdef SIGXCPU
case SIGXCPU:
exception_str = "SIGXCPU";
break;
-#endif
-#ifdef SIGXFSZ
+# endif
+# ifdef SIGXFSZ
case SIGXFSZ:
exception_str = "SIGXFSZ";
break;
-#endif
-#ifdef SIGVTALRM
+# endif
+# ifdef SIGVTALRM
case SIGVTALRM:
exception_str = "SIGVTALRM";
break;
-#endif
-#ifdef SIGPROF
+# endif
+# ifdef SIGPROF
case SIGPROF:
exception_str = "SIGPROF";
break;
-#endif
-#ifdef SIGWINCH
+# endif
+# ifdef SIGWINCH
case SIGWINCH:
exception_str = "SIGWINCH";
break;
-#endif
-#ifdef SIGPOLL
+# endif
+# ifdef SIGPOLL
case SIGPOLL:
exception_str = "SIGPOLL";
break;
-#endif
-#ifdef SIGIO
-#if !defined(SIGPOLL) || SIGIO != SIGPOLL
+# endif
+# ifdef SIGIO
+# if !defined(SIGPOLL) || SIGIO != SIGPOLL
case SIGIO:
exception_str = "SIGIO";
break;
-#endif
-#endif
-#ifdef SIGPWR
+# endif
+# endif
+# ifdef SIGPWR
case SIGPWR:
exception_str = "SIGPWR";
break;
-#endif
-#ifdef SIGSYS
+# endif
+# ifdef SIGSYS
case SIGSYS:
exception_str = "SIGSYS";
break;
-#endif
-#ifdef SIGUNUSED
-#if !defined(SIGSYS) || SIGUNUSED != SIGSYS
+# endif
+# ifdef SIGUNUSED
+# if !defined(SIGSYS) || SIGUNUSED != SIGSYS
case SIGUNUSED:
exception_str = "SIGUNUSED";
break;
-#endif
-#endif
+# endif
+# endif
default:
exception_str = "Signal ";
exception_str += std::to_string(this->Signal);
void ChangeTimeout(cmDuration t);
void ResetStartTime();
// Return true if the process starts
- bool StartProcess(uv_loop_t& loop);
+ bool StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity);
enum class State
{
--- /dev/null
+message(STATUS "Checking for curses support")
+
+# Try compiling a simple project using curses.
+# Pass in any cache entries that the user may have set.
+set(CMakeCheckCurses_ARGS "")
+foreach(v
+ CURSES_INCLUDE_PATH
+ CURSES_CURSES_LIBRARY
+ CURSES_NCURSES_LIBRARY
+ CURSES_EXTRA_LIBRARY
+ CURSES_FORM_LIBRARY
+ )
+ if(${v})
+ list(APPEND CMakeCheckCurses_ARGS -D${v}=${${v}})
+ endif()
+endforeach()
+file(REMOVE_RECURSE "${CMake_BINARY_DIR}/Source/Checks/Curses-build")
+try_compile(CMakeCheckCurses_COMPILED
+ ${CMake_BINARY_DIR}/Source/Checks/Curses-build
+ ${CMake_SOURCE_DIR}/Source/Checks/Curses
+ CheckCurses # project name
+ CheckCurses # target name
+ CMAKE_FLAGS
+ "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}"
+ ${CMakeCheckCurses_ARGS}
+ OUTPUT_VARIABLE CMakeCheckCurses_OUTPUT
+ )
+
+# Convert result from cache entry to normal variable.
+set(CMakeCheckCurses_COMPILED "${CMakeCheckCurses_COMPILED}")
+unset(CMakeCheckCurses_COMPILED CACHE)
+
+if(CMakeCheckCurses_COMPILED)
+ message(STATUS "Checking for curses support - Success")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Checking for curses support passed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n")
+else()
+ message(STATUS "Checking for curses support - Failed")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Checking for curses support failed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n")
+endif()
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+if(POLICY CMP0060)
+ cmake_policy(SET CMP0060 NEW)
+endif()
+project(CheckCurses C)
+
+set(CURSES_NEED_NCURSES TRUE)
+find_package(Curses)
+if(NOT CURSES_FOUND)
+ return()
+endif()
+include_directories(${CURSES_INCLUDE_DIRS})
+add_executable(CheckCurses CheckCurses.c)
+target_link_libraries(CheckCurses ${CURSES_LIBRARIES})
+
+foreach(h
+ CURSES_HAVE_CURSES_H
+ CURSES_HAVE_NCURSES_H
+ CURSES_HAVE_NCURSES_NCURSES_H
+ CURSES_HAVE_NCURSES_CURSES_H
+ )
+ if(${h})
+ target_compile_definitions(CheckCurses PRIVATE ${h})
+ endif()
+endforeach()
--- /dev/null
+#if defined(CURSES_HAVE_NCURSES_H)
+# include <ncurses.h>
+#elif defined(CURSES_HAVE_NCURSES_NCURSES_H)
+# include <ncurses/ncurses.h>
+#elif defined(CURSES_HAVE_NCURSES_CURSES_H)
+# include <ncurses/curses.h>
+#else
+# include <curses.h>
+#endif
+
+int main()
+{
+ curses_version();
+ return 0;
+}
# Filter out warnings caused by local configuration.
string(REGEX REPLACE "[^\n]*warning:[^\n]*directory not found for option[^\n]*" "" check_output "${check_output}")
string(REGEX REPLACE "[^\n]*warning:[^\n]*object file compiled with -mlong-branch which is no longer needed[^\n]*" "" check_output "${check_output}")
+ # Filter out xcodebuild warnings.
+ string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}")
# If using the feature causes warnings, treat it as broken/unavailable.
if(check_output MATCHES "[Ww]arning")
set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE)
};
static const char* cmDocumentationUsage[][2] = {
- { nullptr, " ccmake <path-to-source>\n"
- " ccmake <path-to-existing-build>" },
- { nullptr, "Specify a source directory to (re-)generate a build system for "
- "it in the current working directory. Specify an existing build "
- "directory to re-generate its build system." },
+ { nullptr,
+ " ccmake <path-to-source>\n"
+ " ccmake <path-to-existing-build>" },
+ { nullptr,
+ "Specify a source directory to (re-)generate a build system for "
+ "it in the current working directory. Specify an existing build "
+ "directory to re-generate its build system." },
{ nullptr, nullptr }
};
{ nullptr, nullptr }
};
-static const char* cmDocumentationOptions[]
- [2] = { CMAKE_STANDARD_OPTIONS_TABLE,
- { nullptr, nullptr } };
+static const char* cmDocumentationOptions[][2] = {
+ CMAKE_STANDARD_OPTIONS_TABLE,
+ { nullptr, nullptr }
+};
cmCursesForm* cmCursesForm::CurrentForm = nullptr;
sprintf(thirdLine, toggleKeyInstruction,
this->AdvancedMode ? "On" : "Off");
}
- sprintf(secondLine, "Press [h] for help "
- "Press [q] to quit without generating");
+ sprintf(secondLine,
+ "Press [h] for help "
+ "Press [q] to quit without generating");
}
curses_move(y - 4, 0);
curses_clear();
curses_move(0, 0);
char fmt[] = "Window is too small. A size of at least %dx%d is required.";
- printw(fmt, (cmCursesMainForm::MIN_WIDTH < this->InitialWidth
- ? this->InitialWidth
- : cmCursesMainForm::MIN_WIDTH),
+ printw(fmt,
+ (cmCursesMainForm::MIN_WIDTH < this->InitialWidth
+ ? this->InitialWidth
+ : cmCursesMainForm::MIN_WIDTH),
cmCursesMainForm::MIN_HEIGHT);
touchwin(stdscr);
wrefresh(stdscr);
}
int xx, yy;
getmaxyx(stdscr, yy, xx);
- cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(
- this->Errors, cmSystemTools::GetErrorOccuredFlag()
- ? "Errors occurred during the last pass."
- : "CMake produced the following output.");
+ cmCursesLongMessageForm* msgs =
+ new cmCursesLongMessageForm(this->Errors,
+ cmSystemTools::GetErrorOccuredFlag()
+ ? "Errors occurred during the last pass."
+ : "CMake produced the following output.");
// reset error condition
cmSystemTools::ResetErrorOccuredFlag();
CurrentForm = msgs;
std::vector<cmCursesCacheEntryComposite*>* Entries;
// Errors produced during last run of cmake
std::vector<std::string> Errors;
- // Command line argumens to be passed to cmake each time
+ // Command line arguments to be passed to cmake each time
// it is run
std::vector<std::string> Args;
// Message displayed when user presses 'h'
#include "cmConfigure.h" // IWYU pragma: keep
+// Record whether __attribute__ is currently defined. See purpose below.
+#ifndef __attribute__
+# define cm_no__attribute__
+#endif
+
#if defined(__hpux)
-#define _BOOL_DEFINED
-#include <sys/time.h>
+# define _BOOL_DEFINED
+# include <sys/time.h>
#endif
#include <form.h>
#undef erase
#undef clear
+// The curses headers on some platforms (e.g. Solaris) may
+// define __attribute__ as a macro. This breaks C++ headers
+// in some cases, so undefine it now.
+#if defined(cm_no__attribute__) && defined(__attribute__)
+# undef __attribute__
+#endif
+#undef cm_no__attribute__
+
#endif // cmCursesStandardIncludes_h
if ((form->cols > width) || (form->rows > height))
RETURN(E_NO_ROOM);
- /* reset form->curpage to an invald value. This forces Set_Form_Page
+ /* reset form->curpage to an invalid value. This forces Set_Form_Page
to do the page initialization which is required by post_form.
*/
page = form->curpage;
#line 119 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleUse(parser, (yyvsp[-4].string));
+ cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string));
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
#line 125 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleUse(parser, (yyvsp[-6].string));
+ cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string));
free((yyvsp[-6].string));
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
| SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleUse(parser, $3);
+ cmFortranParser_RuleSubmodule(parser, $3, $5);
free($3);
free($5);
}
| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleUse(parser, $3);
+ cmFortranParser_RuleSubmoduleNested(parser, $3, $5, $7);
free($3);
free($5);
free($7);
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static const flex_int16_t yy_accept[81] =
+static const flex_int16_t yy_accept[79] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4,
25, 13, 22, 1, 16, 3, 13, 5, 6, 7,
- 15, 23, 23, 17, 19, 20, 21, 17, 10, 11,
- 8, 10, 12, 9, 24, 4, 13, 0, 13, 0,
- 22, 0, 0, 7, 13, 0, 13, 0, 2, 0,
- 13, 17, 0, 18, 10, 8, 4, 0, 14, 0,
- 0, 0, 0, 14, 0, 0, 14, 0, 0, 0,
- 2, 14, 0, 0, 0, 0, 0, 0, 0, 0
+ 15, 23, 23, 17, 19, 20, 21, 24, 10, 11,
+ 8, 12, 9, 4, 13, 0, 13, 0, 22, 0,
+ 0, 7, 13, 0, 13, 0, 2, 0, 13, 17,
+ 0, 18, 10, 8, 4, 0, 14, 0, 0, 0,
+ 0, 14, 0, 0, 14, 0, 0, 0, 2, 14,
+ 0, 0, 0, 0, 0, 0, 0, 0
} ;
static const YY_CHAR yy_ec[256] =
static const YY_CHAR yy_meta[17] =
{ 0,
1, 1, 2, 3, 4, 3, 1, 3, 5, 6,
- 1, 6, 1, 1, 7, 8
+ 1, 6, 1, 1, 7, 2
} ;
-static const flex_int16_t yy_base[99] =
+static const flex_int16_t yy_base[97] =
{ 0,
0, 0, 14, 28, 42, 56, 70, 84, 18, 19,
- 69, 100, 16, 323, 323, 55, 59, 323, 323, 13,
- 115, 0, 323, 52, 323, 323, 21, 51, 0, 323,
- 53, 0, 323, 323, 323, 0, 0, 126, 55, 0,
- 25, 25, 53, 0, 0, 136, 53, 0, 57, 0,
- 0, 42, 50, 323, 0, 43, 0, 146, 160, 45,
- 172, 43, 26, 0, 42, 184, 0, 42, 195, 40,
- 323, 40, 0, 38, 37, 34, 32, 31, 23, 323,
- 211, 219, 227, 235, 243, 251, 259, 267, 274, 281,
- 285, 291, 298, 302, 304, 310, 314, 316
+ 68, 100, 16, 298, 298, 54, 58, 298, 298, 13,
+ 115, 0, 298, 51, 298, 298, 21, 298, 0, 298,
+ 53, 298, 298, 0, 0, 126, 55, 0, 25, 25,
+ 53, 0, 0, 136, 53, 0, 57, 0, 0, 42,
+ 50, 298, 0, 43, 0, 146, 160, 45, 172, 43,
+ 26, 0, 42, 177, 0, 42, 188, 40, 298, 40,
+ 0, 38, 37, 34, 32, 31, 23, 298, 197, 204,
+ 211, 218, 225, 232, 239, 245, 252, 259, 262, 268,
+ 275, 278, 280, 286, 289, 291
} ;
-static const flex_int16_t yy_def[99] =
+static const flex_int16_t yy_def[97] =
{ 0,
- 80, 1, 81, 81, 82, 82, 83, 83, 84, 84,
- 80, 80, 80, 80, 80, 80, 12, 80, 80, 12,
- 80, 85, 80, 86, 80, 80, 86, 86, 87, 80,
- 80, 87, 80, 80, 80, 88, 12, 89, 12, 90,
- 80, 80, 91, 20, 12, 92, 12, 21, 80, 93,
- 12, 86, 86, 80, 87, 80, 88, 89, 80, 58,
- 89, 94, 80, 59, 91, 92, 59, 66, 92, 95,
- 80, 59, 96, 97, 94, 98, 95, 97, 98, 0,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80
+ 78, 1, 79, 79, 80, 80, 81, 81, 82, 82,
+ 78, 78, 78, 78, 78, 78, 12, 78, 78, 12,
+ 78, 83, 78, 84, 78, 78, 84, 78, 85, 78,
+ 78, 78, 78, 86, 12, 87, 12, 88, 78, 78,
+ 89, 20, 12, 90, 12, 21, 78, 91, 12, 84,
+ 84, 78, 85, 78, 86, 87, 78, 56, 87, 92,
+ 78, 57, 89, 90, 57, 64, 90, 93, 78, 57,
+ 94, 95, 92, 96, 93, 95, 96, 0, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78
} ;
-static const flex_int16_t yy_nxt[340] =
+static const flex_int16_t yy_nxt[315] =
{ 0,
12, 13, 14, 13, 15, 16, 17, 18, 19, 12,
- 12, 20, 21, 22, 12, 23, 25, 41, 26, 41,
- 14, 14, 44, 54, 44, 52, 41, 27, 41, 28,
- 25, 66, 26, 35, 35, 63, 63, 49, 49, 58,
- 67, 27, 66, 28, 30, 59, 58, 62, 67, 76,
- 64, 59, 74, 56, 52, 53, 31, 32, 30, 71,
- 70, 64, 62, 56, 53, 53, 43, 42, 80, 80,
- 31, 32, 30, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 34, 35, 30, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 34, 35,
-
- 37, 80, 80, 80, 38, 80, 39, 80, 80, 37,
- 37, 37, 37, 40, 37, 45, 80, 80, 80, 46,
- 80, 47, 80, 80, 45, 48, 45, 49, 50, 45,
- 59, 80, 60, 80, 80, 80, 80, 80, 80, 61,
- 67, 80, 68, 80, 80, 80, 80, 80, 80, 69,
- 59, 80, 60, 80, 80, 80, 80, 80, 80, 61,
- 59, 80, 80, 80, 38, 80, 72, 80, 80, 59,
- 59, 59, 59, 73, 59, 58, 80, 58, 80, 58,
- 58, 80, 80, 80, 80, 80, 80, 58, 67, 80,
- 68, 80, 80, 80, 80, 80, 80, 69, 66, 80,
-
- 66, 80, 66, 66, 80, 80, 80, 80, 80, 80,
- 66, 24, 24, 24, 24, 24, 24, 24, 24, 29,
- 29, 29, 29, 29, 29, 29, 29, 33, 33, 33,
- 33, 33, 33, 33, 33, 36, 36, 36, 36, 36,
- 36, 36, 36, 51, 80, 51, 51, 51, 51, 51,
- 51, 52, 80, 52, 80, 52, 52, 52, 52, 55,
- 80, 55, 55, 55, 55, 80, 55, 57, 80, 57,
- 57, 57, 57, 57, 58, 80, 80, 58, 80, 58,
- 58, 37, 80, 37, 37, 37, 37, 37, 37, 65,
- 65, 66, 80, 80, 66, 80, 66, 66, 45, 80,
-
- 45, 45, 45, 45, 45, 45, 75, 75, 77, 77,
- 59, 80, 59, 59, 59, 59, 59, 59, 78, 78,
- 79, 79, 11, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80
+ 12, 20, 21, 22, 12, 23, 25, 39, 26, 39,
+ 14, 14, 42, 52, 42, 50, 39, 27, 39, 28,
+ 25, 64, 26, 28, 28, 61, 61, 47, 47, 56,
+ 65, 27, 64, 28, 30, 57, 56, 60, 65, 74,
+ 62, 57, 72, 54, 50, 51, 31, 28, 30, 69,
+ 68, 62, 60, 54, 51, 41, 40, 78, 78, 78,
+ 31, 28, 30, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 33, 28, 30, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 33, 28,
+
+ 35, 78, 78, 78, 36, 78, 37, 78, 78, 35,
+ 35, 35, 35, 38, 35, 43, 78, 78, 78, 44,
+ 78, 45, 78, 78, 43, 46, 43, 47, 48, 43,
+ 57, 78, 58, 78, 78, 78, 78, 78, 78, 59,
+ 65, 78, 66, 78, 78, 78, 78, 78, 78, 67,
+ 57, 78, 58, 78, 78, 78, 78, 78, 78, 59,
+ 57, 78, 78, 78, 36, 78, 70, 78, 78, 57,
+ 57, 57, 57, 71, 57, 56, 78, 56, 78, 56,
+ 56, 65, 78, 66, 78, 78, 78, 78, 78, 78,
+ 67, 64, 78, 64, 78, 64, 64, 24, 24, 24,
+
+ 24, 24, 24, 24, 29, 29, 29, 29, 29, 29,
+ 29, 32, 32, 32, 32, 32, 32, 32, 34, 34,
+ 34, 34, 34, 34, 34, 49, 78, 49, 49, 49,
+ 49, 49, 50, 78, 50, 78, 50, 50, 50, 53,
+ 78, 53, 53, 53, 53, 55, 78, 55, 55, 55,
+ 55, 55, 56, 78, 78, 56, 78, 56, 56, 35,
+ 78, 35, 35, 35, 35, 35, 63, 63, 64, 78,
+ 78, 64, 78, 64, 64, 43, 78, 43, 43, 43,
+ 43, 43, 73, 73, 75, 75, 57, 78, 57, 57,
+ 57, 57, 57, 76, 76, 77, 77, 11, 78, 78,
+
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78
} ;
-static const flex_int16_t yy_chk[340] =
+static const flex_int16_t yy_chk[315] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 3, 13, 3, 13,
- 9, 10, 20, 27, 20, 27, 41, 3, 41, 3,
- 4, 79, 4, 9, 10, 42, 63, 42, 63, 78,
- 77, 4, 76, 4, 5, 75, 74, 72, 70, 68,
- 65, 62, 60, 56, 53, 52, 5, 5, 6, 49,
- 47, 43, 39, 31, 28, 24, 17, 16, 11, 0,
+ 9, 10, 20, 27, 20, 27, 39, 3, 39, 3,
+ 4, 77, 4, 9, 10, 40, 61, 40, 61, 76,
+ 75, 4, 74, 4, 5, 73, 72, 70, 68, 66,
+ 63, 60, 58, 54, 51, 50, 5, 5, 6, 47,
+ 45, 41, 37, 31, 24, 17, 16, 11, 0, 0,
6, 6, 7, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 7, 7, 8, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 8, 8,
12, 0, 0, 0, 12, 0, 12, 0, 0, 12,
12, 12, 12, 12, 12, 21, 0, 0, 0, 21,
0, 21, 0, 0, 21, 21, 21, 21, 21, 21,
- 38, 0, 38, 0, 0, 0, 0, 0, 0, 38,
- 46, 0, 46, 0, 0, 0, 0, 0, 0, 46,
- 58, 0, 58, 0, 0, 0, 0, 0, 0, 58,
- 59, 0, 0, 0, 59, 0, 59, 0, 0, 59,
- 59, 59, 59, 59, 59, 61, 0, 61, 0, 61,
- 61, 0, 0, 0, 0, 0, 0, 61, 66, 0,
- 66, 0, 0, 0, 0, 0, 0, 66, 69, 0,
-
- 69, 0, 69, 69, 0, 0, 0, 0, 0, 0,
- 69, 81, 81, 81, 81, 81, 81, 81, 81, 82,
- 82, 82, 82, 82, 82, 82, 82, 83, 83, 83,
- 83, 83, 83, 83, 83, 84, 84, 84, 84, 84,
- 84, 84, 84, 85, 0, 85, 85, 85, 85, 85,
- 85, 86, 0, 86, 0, 86, 86, 86, 86, 87,
- 0, 87, 87, 87, 87, 0, 87, 88, 0, 88,
- 88, 88, 88, 88, 89, 0, 0, 89, 0, 89,
- 89, 90, 0, 90, 90, 90, 90, 90, 90, 91,
- 91, 92, 0, 0, 92, 0, 92, 92, 93, 0,
-
- 93, 93, 93, 93, 93, 93, 94, 94, 95, 95,
- 96, 0, 96, 96, 96, 96, 96, 96, 97, 97,
- 98, 98, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80
+ 36, 0, 36, 0, 0, 0, 0, 0, 0, 36,
+ 44, 0, 44, 0, 0, 0, 0, 0, 0, 44,
+ 56, 0, 56, 0, 0, 0, 0, 0, 0, 56,
+ 57, 0, 0, 0, 57, 0, 57, 0, 0, 57,
+ 57, 57, 57, 57, 57, 59, 0, 59, 0, 59,
+ 59, 64, 0, 64, 0, 0, 0, 0, 0, 0,
+ 64, 67, 0, 67, 0, 67, 67, 79, 79, 79,
+
+ 79, 79, 79, 79, 80, 80, 80, 80, 80, 80,
+ 80, 81, 81, 81, 81, 81, 81, 81, 82, 82,
+ 82, 82, 82, 82, 82, 83, 0, 83, 83, 83,
+ 83, 83, 84, 0, 84, 0, 84, 84, 84, 85,
+ 0, 85, 85, 85, 85, 86, 0, 86, 86, 86,
+ 86, 86, 87, 0, 0, 87, 0, 87, 87, 88,
+ 0, 88, 88, 88, 88, 88, 89, 89, 90, 0,
+ 0, 90, 0, 90, 90, 91, 0, 91, 91, 91,
+ 91, 91, 92, 92, 93, 93, 94, 0, 94, 94,
+ 94, 94, 94, 95, 95, 96, 96, 78, 78, 78,
+
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78
} ;
/* Table of booleans, true if rule could match eol. */
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 81 )
+ if ( yy_current_state >= 79 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 323 );
+ while ( yy_base[yy_current_state] != 298 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 81 )
+ if ( yy_current_state >= 79 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 81 )
+ if ( yy_current_state >= 79 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
- yy_is_jam = (yy_current_state == 80);
+ yy_is_jam = (yy_current_state == 78);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
%x COMMENT
MAKEVAR \$\([A-Za-z0-9_]*\)
-UNQUOTED ([^ \0\t\r\n\(\)#\\\"[=]|\\.)
+UNQUOTED ([^ \0\t\r\n\(\)#\\\"[=]|\\[^\0\n])
LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
%%
return 1;
}
-<BRACKET>([^]\n])+ {
+<BRACKET>([^]\0\n])+ {
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
BEGIN(STRING);
}
-<STRING>([^\\\n\"]|\\.)+ {
+<STRING>([^\\\0\n\"]|\\[^\0\n])+ {
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
set(_LibUV_H_REGEX "#[ \t]*define[ \t]+UV_VERSION_(MAJOR|MINOR|PATCH)[ \t]+[0-9]+")
if(LibUV_INCLUDE_DIR AND EXISTS "${LibUV_INCLUDE_DIR}/uv-version.h")
file(STRINGS "${LibUV_INCLUDE_DIR}/uv-version.h" _LibUV_H REGEX "${_LibUV_H_REGEX}")
+elseif(LibUV_INCLUDE_DIR AND EXISTS "${LibUV_INCLUDE_DIR}/uv/version.h")
+ file(STRINGS "${LibUV_INCLUDE_DIR}/uv/version.h" _LibUV_H REGEX "${_LibUV_H_REGEX}")
elseif(LibUV_INCLUDE_DIR AND EXISTS "${LibUV_INCLUDE_DIR}/uv.h")
file(STRINGS "${LibUV_INCLUDE_DIR}/uv.h" _LibUV_H REGEX "${_LibUV_H_REGEX}")
else()
#include "ui_AddCacheEntry.h"
-class AddCacheEntry : public QWidget, public Ui::AddCacheEntry
+class AddCacheEntry
+ : public QWidget
+ , public Ui::AddCacheEntry
{
Q_OBJECT
public:
{ nullptr, nullptr } };
static const char* cmDocumentationUsage[][2] = {
- { nullptr, " cmake-gui [options]\n"
- " cmake-gui [options] <path-to-source>\n"
- " cmake-gui [options] <path-to-existing-build>" },
+ { nullptr,
+ " cmake-gui [options]\n"
+ " cmake-gui [options] <path-to-source>\n"
+ " cmake-gui [options] <path-to-existing-build>" },
{ nullptr, nullptr }
};
}
#if defined(Q_OS_MAC)
-#include "cm_sys_stat.h"
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
+# include "cm_sys_stat.h"
+# include <errno.h>
+# include <string.h>
+# include <unistd.h>
static bool cmOSXInstall(std::string const& dir, std::string const& tool)
{
if (tool.empty()) {
"Qt is licensed under terms of the GNU LGPLv" USE_LGPL ", available at:\n"
" \"%3\""
#endif
- );
+ );
msg = msg.arg(cmVersion::GetCMakeVersion());
msg = msg.arg(qVersion());
#ifdef USE_LGPL
void CMakeSetupDialog::selectionChanged()
{
QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
- if (idxs.count() && (this->CurrentState == ReadyConfigure ||
- this->CurrentState == ReadyGenerate)) {
+ if (idxs.count() &&
+ (this->CurrentState == ReadyConfigure ||
+ this->CurrentState == ReadyGenerate)) {
this->RemoveEntry->setEnabled(true);
} else {
this->RemoveEntry->setEnabled(false);
class QToolButton;
/// Qt user interface for CMake
-class CMakeSetupDialog : public QMainWindow, public Ui::CMakeSetupDialog
+class CMakeSetupDialog
+ : public QMainWindow
+ , public Ui::CMakeSetupDialog
{
Q_OBJECT
public:
#include <ui_Compilers.h>
-class Compilers : public QWidget, public Ui::Compilers
+class Compilers
+ : public QWidget
+ , public Ui::Compilers
{
Q_OBJECT
public:
};
//! the page that gives basic options for native compilers
-class NativeCompilerSetup : public QWizardPage, protected Ui::Compilers
+class NativeCompilerSetup
+ : public QWizardPage
+ , protected Ui::Compilers
{
Q_OBJECT
public:
};
//! the page that gives options for cross compilers
-class CrossCompilerSetup : public QWizardPage, protected Ui::CrossCompiler
+class CrossCompilerSetup
+ : public QWizardPage
+ , protected Ui::CrossCompiler
{
Q_OBJECT
public:
#include "cmSystemTools.h"
#ifdef Q_OS_WIN
-#include "qt_windows.h" // For SetErrorMode
+# include "qt_windows.h" // For SetErrorMode
#endif
QCMake::QCMake(QObject* p)
#include "cmake.h"
#ifdef _MSC_VER
-#pragma warning(disable : 4127)
-#pragma warning(disable : 4512)
+# pragma warning(disable : 4127)
+# pragma warning(disable : 4512)
#endif
#include <vector>
class QString;
class QWidget;
-class RegexExplorer : public QDialog, public Ui::RegexExplorer
+class RegexExplorer
+ : public QDialog
+ , public Ui::RegexExplorer
{
Q_OBJECT
public:
/**
* Dialog window for setting the warning message related options.
*/
-class WarningMessagesDialog : public QDialog, public Ui_MessagesDialog
+class WarningMessagesDialog
+ : public QDialog
+ , public Ui_MessagesDialog
{
Q_OBJECT
-------------------------------------------------------------------------*/
/*
-*----------------------------------------------------------------------
-* Program: dumpexts.exe
-* Author: Gordon Chaffee
-*
-* History: The real functionality of this file was written by
-* Matt Pietrek in 1993 in his pedump utility. I've
-* modified it to dump the externals in a bunch of object
-* files to create a .def file.
-*
-* Notes: Visual C++ puts an underscore before each exported symbol.
-* This file removes them. I don't know if this is a problem
-* this other compilers. If _MSC_VER is defined,
-* the underscore is removed. If not, it isn't. To get a
-* full dump of an object file, use the -f option. This can
-* help determine the something that may be different with a
-* compiler other than Visual C++.
-* ======================================
-* Corrections (Axel 2006-04-04):
-* Conversion to C++. Mostly.
-*
+ *----------------------------------------------------------------------
+ * Program: dumpexts.exe
+ * Author: Gordon Chaffee
+ *
+ * History: The real functionality of this file was written by
+ * Matt Pietrek in 1993 in his pedump utility. I've
+ * modified it to dump the externals in a bunch of object
+ * files to create a .def file.
+ *
+ * Notes: Visual C++ puts an underscore before each exported symbol.
+ * This file removes them. I don't know if this is a problem
+ * this other compilers. If _MSC_VER is defined,
+ * the underscore is removed. If not, it isn't. To get a
+ * full dump of an object file, use the -f option. This can
+ * help determine the something that may be different with a
+ * compiler other than Visual C++.
+ * ======================================
+ * Corrections (Axel 2006-04-04):
+ * Conversion to C++. Mostly.
+ *
* Extension (Axel 2006-03-15)
* As soon as an object file contains an /EXPORT directive (which
* is generated by the compiler when a symbol is declared as
* programmer).
*
* ======================================
-* ======================================
-* Corrections (Valery Fine 23/02/98):
-*
-* The "(vector) deleting destructor" MUST not be exported
-* To recognize it the following test are introduced:
-* "@@UAEPAXI@Z" scalar deleting dtor
-* "@@QAEPAXI@Z" vector deleting dtor
-* "AEPAXI@Z" vector deleting dtor with thunk adjustor
-* ======================================
-* Corrections (Valery Fine 12/02/97):
-*
-* It created a wrong EXPORTS for the global pointers and constants.
-* The Section Header has been involved to discover the missing information
-* Now the pointers are correctly supplied with "DATA" descriptor
-* the constants with no extra descriptor.
-*
-* Corrections (Valery Fine 16/09/96):
-*
-* It didn't work for C++ code with global variables and class definitions
-* The DumpExternalObject function has been introduced to generate .DEF file
-*
-* Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch)
-*----------------------------------------------------------------------
-*/
+ * ======================================
+ * Corrections (Valery Fine 23/02/98):
+ *
+ * The "(vector) deleting destructor" MUST not be exported
+ * To recognize it the following test are introduced:
+ * "@@UAEPAXI@Z" scalar deleting dtor
+ * "@@QAEPAXI@Z" vector deleting dtor
+ * "AEPAXI@Z" vector deleting dtor with thunk adjustor
+ * ======================================
+ * Corrections (Valery Fine 12/02/97):
+ *
+ * It created a wrong EXPORTS for the global pointers and constants.
+ * The Section Header has been involved to discover the missing information
+ * Now the pointers are correctly supplied with "DATA" descriptor
+ * the constants with no extra descriptor.
+ *
+ * Corrections (Valery Fine 16/09/96):
+ *
+ * It didn't work for C++ code with global variables and class definitions
+ * The DumpExternalObject function has been introduced to generate .DEF
+ *file
+ *
+ * Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch)
+ *----------------------------------------------------------------------
+ */
#include "bindexplib.h"
#include "cmsys/Encoding.hxx"
#include <windows.h>
#ifndef IMAGE_FILE_MACHINE_ARM
-#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
+# define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
#endif
#ifndef IMAGE_FILE_MACHINE_THUMB
-#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
+# define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
#endif
#ifndef IMAGE_FILE_MACHINE_ARMNT
-#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
+# define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
#endif
#ifndef IMAGE_FILE_MACHINE_ARM64
-#define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian
+# define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian
#endif
typedef struct cmANON_OBJECT_HEADER_BIGOBJ
{
this->ObjectImageHeader = ih;
this->SymbolTable =
- (SymbolTableType*)((DWORD_PTR) this->ObjectImageHeader +
+ (SymbolTableType*)((DWORD_PTR)this->ObjectImageHeader +
this->ObjectImageHeader->PointerToSymbolTable);
this->SectionHeaders = GetSectionHeaderOffset(this->ObjectImageHeader);
this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols;
(pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) {
if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
/*
- * The name of the Function entry points
- */
+ * The name of the Function entry points
+ */
if (pSymbolTable->N.Name.Short != 0) {
symbol.clear();
symbol.insert(0, (const char*)pSymbolTable->N.ShortName, 8);
}
/*
- * Take into account any aux symbols
- */
+ * Take into account any aux symbols
+ */
i += pSymbolTable->NumberOfAuxSymbols;
pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
pSymbolTable++;
(imageHeader->Machine == IMAGE_FILE_MACHINE_ARM64)) &&
(imageHeader->Characteristics == 0)) {
/*
- * The tests above are checking for IMAGE_FILE_HEADER.Machine
- * if it contains supported machine formats (currently ARM and x86)
- * and IMAGE_FILE_HEADER.Characteristics == 0 indicating that
- * this is not linked COFF OBJ file;
- */
+ * The tests above are checking for IMAGE_FILE_HEADER.Machine
+ * if it contains supported machine formats (currently ARM and x86)
+ * and IMAGE_FILE_HEADER.Characteristics == 0 indicating that
+ * this is not linked COFF OBJ file;
+ */
DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL> symbolDumper(
(PIMAGE_FILE_HEADER)lpFileBase, symbols, dataSymbols,
(imageHeader->Machine == IMAGE_FILE_MACHINE_I386));
(cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase;
if (h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX>
- symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase, symbols,
- dataSymbols, (h->Machine == IMAGE_FILE_MACHINE_I386));
+ symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase, symbols,
+ dataSymbols, (h->Machine == IMAGE_FILE_MACHINE_I386));
symbolDumper.DumpObjFile();
} else {
printf("unrecognized file format in '%s'\n", filename);
}
std::string str;
while (std::getline(infile, str)) {
- // skip the LIBRAY and EXPORTS lines (if any)
+ // skip the LIBRARY and EXPORTS lines (if any)
if ((str.compare(0, 7, "LIBRARY") == 0) ||
(str.compare(0, 7, "EXPORTS") == 0)) {
continue;
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddCompileDefinitionsCommand.h"
+
+#include "cmMakefile.h"
+
+class cmExecutionStatus;
+
+bool cmAddCompileDefinitionsCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
+{
+ if (args.empty()) {
+ return true;
+ }
+
+ for (std::string const& i : args) {
+ this->Makefile->AddCompileDefinition(i);
+ }
+ return true;
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmAddCompileDefinitionsCommand_h
+#define cmAddCompileDefinitionsCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmCommand.h"
+
+class cmExecutionStatus;
+
+class cmAddCompileDefinitionsCommand : public cmCommand
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ cmCommand* Clone() override { return new cmAddCompileDefinitionsCommand; }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) override;
+};
+
+#endif
if (!aliasedTarget) {
std::ostringstream e;
e << "cannot create ALIAS target \"" << libName << "\" because target \""
- << aliasedName << "\" does not already "
- "exist.";
+ << aliasedName
+ << "\" does not already "
+ "exist.";
this->SetError(e.str());
return false;
}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAffinity.h"
+
+#include "cm_uv.h"
+
+#ifndef CMAKE_USE_SYSTEM_LIBUV
+# ifdef _WIN32
+# define CM_HAVE_CPU_AFFINITY
+# include <windows.h>
+# elif defined(__linux__) || defined(__FreeBSD__)
+# define CM_HAVE_CPU_AFFINITY
+# include <pthread.h>
+# include <sched.h>
+# if defined(__FreeBSD__)
+# include <pthread_np.h>
+# include <sys/cpuset.h>
+# include <sys/param.h>
+# endif
+# if defined(__linux__)
+typedef cpu_set_t cm_cpuset_t;
+# else
+typedef cpuset_t cm_cpuset_t;
+# endif
+# endif
+#endif
+
+namespace cmAffinity {
+
+std::set<size_t> GetProcessorsAvailable()
+{
+ std::set<size_t> processorsAvailable;
+#ifdef CM_HAVE_CPU_AFFINITY
+ int cpumask_size = uv_cpumask_size();
+ if (cpumask_size > 0) {
+# ifdef _WIN32
+ DWORD_PTR procmask;
+ DWORD_PTR sysmask;
+ if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask) !=
+ 0) {
+ for (int i = 0; i < cpumask_size; ++i) {
+ if (procmask & (((DWORD_PTR)1) << i)) {
+ processorsAvailable.insert(i);
+ }
+ }
+ }
+# else
+ cm_cpuset_t cpuset;
+ CPU_ZERO(&cpuset); // NOLINT(clang-tidy)
+ if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset), &cpuset) == 0) {
+ for (int i = 0; i < cpumask_size; ++i) {
+ if (CPU_ISSET(i, &cpuset)) {
+ processorsAvailable.insert(i);
+ }
+ }
+ }
+# endif
+ }
+#endif
+ return processorsAvailable;
+}
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstddef>
+#include <set>
+
+namespace cmAffinity {
+
+std::set<size_t> GetProcessorsAvailable();
+}
#include <sstream>
#include <string.h>
#include <string>
+#include <unordered_set>
#include <utility>
#include <vector>
ContainerAlgorithms::BinarySearcher<MatchRange>(m));
}
-namespace ContainerAlgorithms {
-
-template <typename Range, typename T = typename Range::value_type>
-struct RemoveDuplicatesAPI
-{
- typedef typename Range::const_iterator const_iterator;
- typedef typename Range::const_iterator value_type;
-
- static bool lessThan(value_type a, value_type b) { return *a < *b; }
- static value_type uniqueValue(const_iterator a) { return a; }
- template <typename It>
- static bool valueCompare(It it, const_iterator it2)
- {
- return **it != *it2;
- }
-};
-
-template <typename Range, typename T>
-struct RemoveDuplicatesAPI<Range, T*>
-{
- typedef typename Range::const_iterator const_iterator;
- typedef T* value_type;
-
- static bool lessThan(value_type a, value_type b) { return a < b; }
- static value_type uniqueValue(const_iterator a) { return *a; }
- template <typename It>
- static bool valueCompare(It it, const_iterator it2)
- {
- return *it != *it2;
- }
-};
-}
-
template <typename Range>
typename Range::const_iterator cmRemoveDuplicates(Range& r)
{
- typedef typename ContainerAlgorithms::RemoveDuplicatesAPI<Range> API;
- typedef typename API::value_type T;
- std::vector<T> unique;
- unique.reserve(r.size());
+ typedef typename Range::value_type T;
+ std::unordered_set<T> unique;
std::vector<size_t> indices;
size_t count = 0;
const typename Range::const_iterator end = r.end();
for (typename Range::const_iterator it = r.begin(); it != end;
++it, ++count) {
- const typename std::vector<T>::iterator low = std::lower_bound(
- unique.begin(), unique.end(), API::uniqueValue(it), API::lessThan);
- if (low == unique.end() || API::valueCompare(low, it)) {
- unique.insert(low, API::uniqueValue(it));
+ const typename std::unordered_set<T>::iterator occur = unique.find(*it);
+ if (occur == unique.end()) {
+ unique.insert(*it);
} else {
indices.push_back(count);
}
// std::size backport from C++17.
template <class C>
-#if !defined(_MSC_VER) || _MSC_VER >= 1900
+# if !defined(_MSC_VER) || _MSC_VER >= 1900
constexpr
-#endif
+# endif
auto
size(C const& c) -> decltype(c.size())
{
}
template <typename T, size_t N>
-#if !defined(_MSC_VER) || _MSC_VER >= 1900
+# if !defined(_MSC_VER) || _MSC_VER >= 1900
constexpr
-#endif
+# endif
std::size_t
size(const T (&)[N]) throw()
{
// std::c{begin,end} backport from C++14
template <class C>
-#if defined(_MSC_VER) && _MSC_VER < 1900
+# if defined(_MSC_VER) && _MSC_VER < 1900
auto cbegin(C const& c)
-#else
+# else
constexpr auto cbegin(C const& c) noexcept(noexcept(std::begin(c)))
-#endif
+# endif
-> decltype(std::begin(c))
{
return std::begin(c);
}
template <class C>
-#if defined(_MSC_VER) && _MSC_VER < 1900
+# if defined(_MSC_VER) && _MSC_VER < 1900
auto cend(C const& c)
-#else
+# else
constexpr auto cend(C const& c) noexcept(noexcept(std::end(c)))
-#endif
+# endif
-> decltype(std::end(c))
{
return std::end(c);
#include <time.h>
#ifndef __LA_SSIZE_T
-#define __LA_SSIZE_T la_ssize_t
+# define __LA_SSIZE_T la_ssize_t
#endif
static std::string cm_archive_error_string(struct archive* a)
#include <string>
#if !defined(CMAKE_BUILD_WITH_CMAKE)
-#error "cmArchiveWrite not allowed during bootstrap build!"
+# error "cmArchiveWrite not allowed during bootstrap build!"
#endif
template <typename T>
void Clear() { this->IsValueSet = false; }
bool IsSet() const { return this->IsValueSet; }
T Get() const { return Value; }
+
private:
T Value;
bool IsValueSet;
{
typedef void (cmArchiveWrite::*safe_bool)();
void safe_bool_true() {}
+
public:
/** Compression type. */
enum Compress
#include "cmsys/SystemInformation.hxx"
#if defined(_WIN32)
-#include "cmAlgorithms.h"
-#include "cmGlobalGenerator.h"
-#include "cmGlobalVisualStudio15Generator.h"
-#include "cmSystemTools.h"
-#include "cmVSSetupHelper.h"
-#define HAVE_VS_SETUP_HELPER
+# include "cmAlgorithms.h"
+# include "cmGlobalGenerator.h"
+# include "cmGlobalVisualStudio15Generator.h"
+# include "cmSystemTools.h"
+# include "cmVSSetupHelper.h"
+# define HAVE_VS_SETUP_HELPER
#endif
class cmExecutionStatus;
// Make sure there was a version to check.
if (version_string.empty()) {
- return this->EnforceUnknownArguments();
+ return this->EnforceUnknownArguments(std::string());
+ }
+
+ // Separate the <min> version and any trailing ...<max> component.
+ std::string::size_type const dd = version_string.find("...");
+ std::string const version_min = version_string.substr(0, dd);
+ std::string const version_max = dd != std::string::npos
+ ? version_string.substr(dd + 3, std::string::npos)
+ : std::string();
+ if (dd != std::string::npos &&
+ (version_min.empty() || version_max.empty())) {
+ std::ostringstream e;
+ e << "VERSION \"" << version_string
+ << "\" does not have a version on both sides of \"...\".";
+ this->SetError(e.str());
+ return false;
}
// Save the required version string.
this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
- version_string.c_str());
+ version_min.c_str());
// Get the current version number.
unsigned int current_major = cmVersion::GetMajorVersion();
unsigned int required_minor = 0;
unsigned int required_patch = 0;
unsigned int required_tweak = 0;
- if (sscanf(version_string.c_str(), "%u.%u.%u.%u", &required_major,
+ if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &required_major,
&required_minor, &required_patch, &required_tweak) < 2) {
std::ostringstream e;
- e << "could not parse VERSION \"" << version_string << "\".";
+ e << "could not parse VERSION \"" << version_min << "\".";
this->SetError(e.str());
return false;
}
current_patch == required_patch && current_tweak < required_tweak)) {
// The current version is too low.
std::ostringstream e;
- e << "CMake " << version_string
+ e << "CMake " << version_min
<< " or higher is required. You are running version "
<< cmVersion::GetCMakeVersion();
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
// The version is not from the future, so enforce unknown arguments.
- if (!this->EnforceUnknownArguments()) {
+ if (!this->EnforceUnknownArguments(version_max)) {
return false;
}
this->Makefile->IssueMessage(
cmake::AUTHOR_WARNING,
"Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.");
- this->Makefile->SetPolicyVersion("2.4");
+ this->Makefile->SetPolicyVersion("2.4", version_max);
} else {
- this->Makefile->SetPolicyVersion(version_string.c_str());
+ this->Makefile->SetPolicyVersion(version_min, version_max);
}
return true;
}
-bool cmCMakeMinimumRequired::EnforceUnknownArguments()
+bool cmCMakeMinimumRequired::EnforceUnknownArguments(
+ std::string const& version_max)
{
- if (!this->UnknownArguments.empty()) {
- std::ostringstream e;
- e << "called with unknown argument \"" << this->UnknownArguments[0]
- << "\".";
- this->SetError(e.str());
- return false;
+ if (this->UnknownArguments.empty()) {
+ return true;
}
- return true;
+
+ // Consider the max version if at least two components were given.
+ unsigned int max_major = 0;
+ unsigned int max_minor = 0;
+ unsigned int max_patch = 0;
+ unsigned int max_tweak = 0;
+ if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &max_major, &max_minor,
+ &max_patch, &max_tweak) >= 2) {
+ unsigned int current_major = cmVersion::GetMajorVersion();
+ unsigned int current_minor = cmVersion::GetMinorVersion();
+ unsigned int current_patch = cmVersion::GetPatchVersion();
+ unsigned int current_tweak = cmVersion::GetTweakVersion();
+
+ if ((current_major < max_major) ||
+ (current_major == max_major && current_minor < max_minor) ||
+ (current_major == max_major && current_minor == max_minor &&
+ current_patch < max_patch) ||
+ (current_major == max_major && current_minor == max_minor &&
+ current_patch == max_patch && current_tweak < max_tweak)) {
+ // A ...<max> version was given that is larger than the current
+ // version of CMake, so tolerate unknown arguments.
+ return true;
+ }
+ }
+
+ std::ostringstream e;
+ e << "called with unknown argument \"" << this->UnknownArguments[0] << "\".";
+ this->SetError(e.str());
+ return false;
}
private:
std::vector<std::string> UnknownArguments;
- bool EnforceUnknownArguments();
+ bool EnforceUnknownArguments(std::string const& version_max);
};
#endif
bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args)
{
- if (args.size() != 3) {
+ bool parent_scope = false;
+ if (args.size() == 4 && args[3] == "PARENT_SCOPE") {
+ // Undocumented PARENT_SCOPE option for use within CMake.
+ parent_scope = true;
+ } else if (args.size() != 3) {
this->SetError("GET must be given exactly 2 additional arguments.");
return false;
}
}
// Lookup the policy setting.
- cmPolicies::PolicyStatus status = this->Makefile->GetPolicyStatus(pid);
+ cmPolicies::PolicyStatus status =
+ this->Makefile->GetPolicyStatus(pid, parent_scope);
switch (status) {
case cmPolicies::OLD:
// Report that the policy is set to OLD.
this->SetError("VERSION given too many arguments");
return false;
}
- this->Makefile->SetPolicyVersion(args[1].c_str());
+ std::string const& version_string = args[1];
+
+ // Separate the <min> version and any trailing ...<max> component.
+ std::string::size_type const dd = version_string.find("...");
+ std::string const version_min = version_string.substr(0, dd);
+ std::string const version_max = dd != std::string::npos
+ ? version_string.substr(dd + 3, std::string::npos)
+ : std::string();
+ if (dd != std::string::npos &&
+ (version_min.empty() || version_max.empty())) {
+ std::ostringstream e;
+ e << "VERSION \"" << version_string
+ << "\" does not have a version on both sides of \"...\".";
+ this->SetError(e.str());
+ return false;
+ }
+
+ this->Makefile->SetPolicyVersion(version_min, version_max);
return true;
}
#include <stdlib.h>
#ifdef __QNX__
-#include <malloc.h> /* for malloc/free on QNX */
+# include <malloc.h> /* for malloc/free on QNX */
#endif
extern "C" {
for (i = 0; i < numSrcs; ++i) {
srcs2.push_back(srcs[i]);
}
- mf->AddLibrary(libname, (shared ? cmStateEnums::SHARED_LIBRARY
- : cmStateEnums::STATIC_LIBRARY),
- srcs2);
+ mf->AddLibrary(
+ libname,
+ (shared ? cmStateEnums::SHARED_LIBRARY : cmStateEnums::STATIC_LIBRARY),
+ srcs2);
}
char CCONV* cmExpandVariablesInString(void* arg, const char* source,
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
std::string barf = source;
- std::string result = mf->ExpandVariablesInString(barf, escapeQuotes, atOnly);
+ std::string const& result =
+ mf->ExpandVariablesInString(barf, escapeQuotes, atOnly);
return strdup(result.c_str());
}
// First try and see whether the listed file can be found
// as is without extensions added on.
std::string hname = pathname;
- if (cmSystemTools::FileExists(hname.c_str())) {
+ if (cmSystemTools::FileExists(hname)) {
sf->SourceName = cmSystemTools::GetFilenamePath(name);
if (!sf->SourceName.empty()) {
sf->SourceName += "/";
hname = pathname;
hname += ".";
hname += *ext;
- if (cmSystemTools::FileExists(hname.c_str())) {
+ if (cmSystemTools::FileExists(hname)) {
sf->SourceExtension = *ext;
sf->FullPath = hname;
return;
hname = pathname;
hname += ".";
hname += *ext;
- if (cmSystemTools::FileExists(hname.c_str())) {
+ if (cmSystemTools::FileExists(hname)) {
sf->SourceExtension = *ext;
sf->FullPath = hname;
return;
#endif
#ifdef __WATCOMC__
-#define CCONV __cdecl
+# define CCONV __cdecl
#else
-#define CCONV
+# define CCONV
#endif
/*=========================================================================
this is the structure of function entry points that a plugin may call. This
CM_PLUGIN_EXPORT should be used by plugins
=========================================================================*/
#ifdef _WIN32
-#define CM_PLUGIN_EXPORT __declspec(dllexport)
+# define CM_PLUGIN_EXPORT __declspec(dllexport)
#else
-#define CM_PLUGIN_EXPORT
+# define CM_PLUGIN_EXPORT
#endif
/*=========================================================================
#include "cmake.h"
#if defined(__BEOS__) || defined(__HAIKU__)
-#include <be/kernel/OS.h> /* disable_debugger() API. */
+# include <be/kernel/OS.h> /* disable_debugger() API. */
#endif
#define DEBUGOUT \
// curl_getdate no longer assumes the day is today
sprintf(buf, "%d%02d%02d %s", lctime->tm_year + 1900, lctime->tm_mon + 1,
lctime->tm_mday, str.c_str());
- cmCTestLog(this, OUTPUT, "Determine Nightly Start Time"
- << std::endl
- << " Specified time: " << str << std::endl);
+ cmCTestLog(this, OUTPUT,
+ "Determine Nightly Start Time" << std::endl
+ << " Specified time: " << str
+ << std::endl);
// Convert the nightly start time to seconds. Since we are
// providing only a time and a timezone, the current date of
// the local machine is assumed. Consequently, nightlySeconds
// time of the current open dashboard
ntime -= dayLength;
cmCTestLog(this, DEBUG, "Pick yesterday" << std::endl);
- cmCTestLog(this, DEBUG, " Future time, subtract day: " << ntime
- << std::endl);
+ cmCTestLog(this, DEBUG,
+ " Future time, subtract day: " << ntime << std::endl);
}
while (tctime > (ntime + dayLength)) {
ntime += dayLength;
cmCTestLog(this, DEBUG, " Past time, add day: " << ntime << std::endl);
}
cmCTestLog(this, DEBUG, "nightlySeconds: " << ntime << std::endl);
- cmCTestLog(this, DEBUG, " Current time: " << tctime << " Nightly time: "
- << ntime << std::endl);
+ cmCTestLog(this, DEBUG,
+ " Current time: " << tctime << " Nightly time: " << ntime
+ << std::endl);
if (tomorrowtag) {
cmCTestLog(this, OUTPUT, " Use future tag, Add a day" << std::endl);
ntime += dayLength;
cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet);
if (this->ProduceXML) {
cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet);
- cmCTestOptionalLog(
- this, OUTPUT, " Site: "
- << this->GetCTestConfiguration("Site") << std::endl
- << " Build name: "
- << cmCTest::SafeBuildIdField(this->GetCTestConfiguration("BuildName"))
- << std::endl,
- quiet);
+ cmCTestOptionalLog(this, OUTPUT,
+ " Site: "
+ << this->GetCTestConfiguration("Site") << std::endl
+ << " Build name: "
+ << cmCTest::SafeBuildIdField(
+ this->GetCTestConfiguration("BuildName"))
+ << std::endl,
+ quiet);
cmCTestOptionalLog(this, DEBUG, "Produce XML is on" << std::endl, quiet);
if (this->TestModel == cmCTest::NIGHTLY &&
this->GetCTestConfiguration("NightlyStartTime").empty()) {
std::string testingDir = this->BinaryDir + "/Testing";
if (cmSystemTools::FileExists(testingDir)) {
if (!cmSystemTools::FileIsDirectory(testingDir)) {
- cmCTestLog(this, ERROR_MESSAGE, "File "
- << testingDir
- << " is in the place of the testing directory"
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "File " << testingDir
+ << " is in the place of the testing directory"
+ << std::endl);
return 0;
}
} else {
if (!cmSystemTools::MakeDirectory(testingDir)) {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory "
- << testingDir << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot create directory " << testingDir << std::endl);
return 0;
}
}
day != lctime->tm_mday) {
tag.clear();
}
- std::string tagmode;
- if (cmSystemTools::GetLineFromStream(tfin, tagmode)) {
- if (tagmode.size() > 4 && !this->Parts[PartStart]) {
- this->TestModel = cmCTest::GetTestModelFromString(tagmode.c_str());
- }
+ std::string track;
+ if (cmSystemTools::GetLineFromStream(tfin, track)) {
+ this->SpecificTrack = track;
+ }
+ std::string model;
+ if (cmSystemTools::GetLineFromStream(tfin, model)) {
+ this->TestModel = GetTestModelFromString(model.c_str());
}
tfin.close();
}
if (ofs) {
ofs << tag << std::endl;
ofs << this->GetTestModelString() << std::endl;
+ switch (this->TestModel) {
+ case cmCTest::EXPERIMENTAL:
+ ofs << "Experimental" << std::endl;
+ break;
+ case cmCTest::NIGHTLY:
+ ofs << "Nightly" << std::endl;
+ break;
+ case cmCTest::CONTINUOUS:
+ ofs << "Continuous" << std::endl;
+ break;
+ }
}
ofs.close();
if (nullptr == command) {
- cmCTestOptionalLog(this, OUTPUT, "Create new tag: "
- << tag << " - " << this->GetTestModelString()
- << std::endl,
+ cmCTestOptionalLog(this, OUTPUT,
+ "Create new tag: " << tag << " - "
+ << this->GetTestModelString()
+ << std::endl,
quiet);
}
}
} else {
+ std::string track;
+ std::string modelStr;
+ int model = cmCTest::UNKNOWN;
+
if (tfin) {
cmSystemTools::GetLineFromStream(tfin, tag);
+ cmSystemTools::GetLineFromStream(tfin, track);
+ if (cmSystemTools::GetLineFromStream(tfin, modelStr)) {
+ model = GetTestModelFromString(modelStr.c_str());
+ }
tfin.close();
}
if (tag.empty()) {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot read existing TAG file in "
- << testingDir << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot read existing TAG file in " << testingDir
+ << std::endl);
return 0;
}
- cmCTestOptionalLog(this, OUTPUT, " Use existing tag: "
- << tag << " - " << this->GetTestModelString()
- << std::endl,
+ if (this->TestModel == cmCTest::UNKNOWN) {
+ if (model == cmCTest::UNKNOWN) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "TAG file does not contain model and "
+ "no model specified in start command"
+ << std::endl);
+ return 0;
+ }
+
+ this->SetTestModel(model);
+ }
+
+ if (model != this->TestModel && model != cmCTest::UNKNOWN &&
+ this->TestModel != cmCTest::UNKNOWN) {
+ cmCTestOptionalLog(this, WARNING,
+ "Model given in TAG does not match "
+ "model given in ctest_start()"
+ << std::endl,
+ quiet);
+ }
+
+ if (!this->SpecificTrack.empty() && track != this->SpecificTrack) {
+ cmCTestOptionalLog(this, WARNING,
+ "Track given in TAG does not match "
+ "track given in ctest_start()"
+ << std::endl,
+ quiet);
+ } else {
+ this->SpecificTrack = track;
+ }
+
+ cmCTestOptionalLog(this, OUTPUT,
+ " Use existing tag: " << tag << " - "
+ << this->GetTestModelString()
+ << std::endl,
quiet);
}
}
if (!fname.empty()) {
- cmCTestOptionalLog(this, OUTPUT, " Reading ctest configuration file: "
- << fname << std::endl,
+ cmCTestOptionalLog(this, OUTPUT,
+ " Reading ctest configuration file: " << fname
+ << std::endl,
command->ShouldBeQuiet());
bool readit = mf->ReadDependentFile(fname.c_str());
if (!readit) {
<< bld_dir_fname << std::endl,
command->ShouldBeQuiet());
cmCTestOptionalLog(
- this, WARNING, "Cannot locate CTest configuration: in SourceDirectory: "
+ this, WARNING,
+ "Cannot locate CTest configuration: in SourceDirectory: "
<< src_dir_fname << std::endl,
command->ShouldBeQuiet());
}
if (dartVersion) {
this->DartVersion = atoi(dartVersion);
if (this->DartVersion < 0) {
- cmCTestLog(this, ERROR_MESSAGE, "Invalid Dart server version: "
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Invalid Dart server version: "
<< dartVersion << ". Please specify the version number."
<< std::endl);
return false;
if (!this->Initialize(bld_dir.c_str(), command)) {
return false;
}
- cmCTestOptionalLog(this, OUTPUT, " Use "
- << this->GetTestModelString()
- << " tag: " << this->GetCurrentTag() << std::endl,
+ cmCTestOptionalLog(this, OUTPUT,
+ " Use " << this->GetTestModelString() << " tag: "
+ << this->GetCurrentTag() << std::endl,
command->ShouldBeQuiet());
return true;
}
if (!cmSystemTools::FileExists(fileName)) {
// No need to exit if we are not producing XML
if (this->ProduceXML) {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot find file: " << fileName
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot find file: " << fileName << std::endl);
return false;
}
} else {
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Parse Config file:" << fileName
- << "\n");
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ "Parse Config file:" << fileName << "\n");
// parse the dart test file
cmsys::ifstream fin(fileName.c_str());
return true;
}
if (report) {
- cmCTestLog(this, ERROR_MESSAGE, "Don't know about test \""
- << ttype << "\" yet..." << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Don't know about test \"" << ttype << "\" yet..."
+ << std::endl);
}
return false;
}
}
if (cmSystemTools::FileExists(testingDir)) {
if (!cmSystemTools::FileIsDirectory(testingDir)) {
- cmCTestLog(this, ERROR_MESSAGE, "File "
- << testingDir << " is in the place of the testing directory"
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "File " << testingDir
+ << " is in the place of the testing directory"
+ << std::endl);
return false;
}
} else {
if (!cmSystemTools::MakeDirectory(testingDir)) {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory " << testingDir
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot create directory " << testingDir << std::endl);
return false;
}
}
std::string filename = testingDir + "/" + name;
stream.Open(filename.c_str());
if (!stream) {
- cmCTestLog(this, ERROR_MESSAGE, "Problem opening file: " << filename
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Problem opening file: " << filename << std::endl);
return false;
}
if (compress) {
int length;
cmProcessOutput processOutput(encoding);
std::string strdata;
- cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Each . represents "
- << tick_len << " bytes of output" << std::endl
- << " " << std::flush);
+ cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
+ " Each . represents " << tick_len << " bytes of output"
+ << std::endl
+ << " " << std::flush);
while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
processOutput.DecodeText(data, length, strdata);
for (char& cc : strdata) {
ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
}
}
- cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size of output: "
- << int(double(output.size()) / 1024.0) << "K" << std::endl);
+ cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
+ " Size of output: " << int(double(output.size()) / 1024.0) << "K"
+ << std::endl);
cmsysProcess_WaitForExit(cp, nullptr);
"Command exited with the value: " << *retVal << std::endl);
} else if (result == cmsysProcess_State_Exception) {
*retVal = cmsysProcess_GetExitException(cp);
- cmCTestLog(this, WARNING, "There was an exception: " << *retVal
- << std::endl);
+ cmCTestLog(this, WARNING,
+ "There was an exception: " << *retVal << std::endl);
} else if (result == cmsysProcess_State_Expired) {
cmCTestLog(this, WARNING, "There was a timeout" << std::endl);
} else if (result == cmsysProcess_State_Error) {
output += "\n*** ERROR executing: ";
output += cmsysProcess_GetErrorString(cp);
output += "\n***The build process failed.";
- cmCTestLog(this, ERROR_MESSAGE, "There was an error: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "There was an error: " << cmsysProcess_GetErrorString(cp)
+ << std::endl);
}
cmsysProcess_Delete(cp);
if (timeout <= cmDuration::zero()) {
timeout = std::chrono::seconds(1);
}
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Test timeout computed to be: "
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ "Test timeout computed to be: "
<< (timeout == cmCTest::MaxDuration()
? std::string("infinite")
: std::to_string(cmDurationTo<unsigned int>(timeout)))
if (output && tempOutput.begin() != tempOutput.end()) {
output->append(&*tempOutput.begin(), tempOutput.size());
}
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "-- Process completed"
- << std::endl);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ "-- Process completed" << std::endl);
int result = cmsysProcess_GetState(cp);
if (output) {
*output += outerr;
}
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl
- << std::flush);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ outerr << std::endl
+ << std::flush);
} else if (result == cmsysProcess_State_Error) {
std::string outerr = "\n*** ERROR executing: ";
outerr += cmsysProcess_GetErrorString(cp);
if (output) {
*output += outerr;
}
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl
- << std::flush);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ outerr << std::endl
+ << std::flush);
}
cmsysProcess_Delete(cp);
void cmCTest::StartXML(cmXMLWriter& xml, bool append)
{
if (this->CurrentTag.empty()) {
- cmCTestLog(this, ERROR_MESSAGE, "Current Tag empty, this may mean"
- " NightlStartTime was not set correctly."
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Current Tag empty, this may mean"
+ " NightlStartTime was not set correctly."
<< std::endl);
cmSystemTools::SetFatalErrorOccured();
}
ifs.close();
} else {
xml.Content("Problem reading file: " + file + "\n");
- cmCTestLog(this, ERROR_MESSAGE, "Problem reading file: "
- << file << " while creating notes" << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Problem reading file: " << file << " while creating notes"
+ << std::endl);
}
xml.EndElement(); // Text
xml.EndElement(); // Note
if (!cmSystemTools::CreateTar(tarFile.c_str(), files,
cmSystemTools::TarCompressGZip, false)) {
- cmCTestLog(this, ERROR_MESSAGE, "Error creating tar while "
- "encoding file: "
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Error creating tar while "
+ "encoding file: "
<< file << std::endl);
return "";
}
std::string cmCTest::Base64EncodeFile(std::string const& file)
{
size_t const len = cmSystemTools::FileLength(file);
- cmsys::ifstream ifs(file.c_str(), std::ios::in
+ cmsys::ifstream ifs(file.c_str(),
+ std::ios::in
#ifdef _WIN32
| std::ios::binary
#endif
- );
+ );
std::vector<char> file_buffer(len + 1);
ifs.read(&file_buffer[0], len);
ifs.close();
{
for (cmsys::String const& file : files) {
if (!cmSystemTools::FileExists(file)) {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot find extra file: "
- << file << " to submit." << std::endl;);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot find extra file: " << file << " to submit."
+ << std::endl;);
return false;
}
this->AddSubmitFile(PartExtraFiles, file.c_str());
"CTest -D called with incorrect option: " << val << std::endl);
cmCTestLog(
- this, ERROR_MESSAGE, "Available options are:"
+ this, ERROR_MESSAGE,
+ "Available options are:"
<< std::endl
<< " ctest -D Continuous" << std::endl
<< " ctest -D Continuous(Start|Update|Configure|Build)" << std::endl
i++;
if (!this->SetTest(args[i].c_str(), false)) {
success = false;
- cmCTestLog(this, ERROR_MESSAGE, "CTest -T called with incorrect option: "
- << args[i] << std::endl);
- cmCTestLog(this, ERROR_MESSAGE, "Available options are:"
+ cmCTestLog(this, ERROR_MESSAGE,
+ "CTest -T called with incorrect option: " << args[i]
+ << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Available options are:"
<< std::endl
<< " " << ctestExec << " -T all" << std::endl
<< " " << ctestExec << " -T start" << std::endl
this->SetTestModel(cmCTest::EXPERIMENTAL);
} else {
success = false;
- cmCTestLog(this, ERROR_MESSAGE, "CTest -M called with incorrect option: "
- << str << std::endl);
- cmCTestLog(this, ERROR_MESSAGE, "Available options are:"
+ cmCTestLog(this, ERROR_MESSAGE,
+ "CTest -M called with incorrect option: " << str
+ << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Available options are:"
<< std::endl
<< " " << ctestExec << " -M Continuous" << std::endl
<< " " << ctestExec << " -M Experimental" << std::endl
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
if (!this->Initialize(cwd.c_str(), nullptr)) {
res = 12;
- cmCTestLog(this, ERROR_MESSAGE, "Problem initializing the dashboard."
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Problem initializing the dashboard." << std::endl);
} else {
res = this->ProcessSteps();
}
cmDynamicLoader::FlushCache();
#endif
if (retv != 0) {
- cmCTestLog(this, DEBUG, "build and test failing returning: " << retv
- << std::endl);
+ cmCTestLog(this, DEBUG,
+ "build and test failing returning: " << retv << std::endl);
}
return retv;
}
bool found = false;
VectorOfStrings dirs;
VectorOfStrings ndirs;
- cmCTestLog(this, DEBUG, "* Read custom CTest configuration directory: "
- << dir << std::endl);
+ cmCTestLog(this, DEBUG,
+ "* Read custom CTest configuration directory: " << dir
+ << std::endl);
std::string fname = dir;
fname += "/CTestCustom.cmake";
cmCTestLog(this, DEBUG, "* Check for file: " << fname << std::endl);
if (cmSystemTools::FileExists(fname)) {
- cmCTestLog(this, DEBUG, "* Read custom CTest configuration file: "
- << fname << std::endl);
+ cmCTestLog(this, DEBUG,
+ "* Read custom CTest configuration file: " << fname
+ << std::endl);
bool erroroc = cmSystemTools::GetErrorOccuredFlag();
cmSystemTools::ResetErrorOccuredFlag();
if (!mf->ReadListFile(fname.c_str()) ||
cmSystemTools::GetErrorOccuredFlag()) {
- cmCTestLog(this, ERROR_MESSAGE, "Problem reading custom configuration: "
- << fname << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Problem reading custom configuration: " << fname
+ << std::endl);
}
found = true;
if (erroroc) {
std::vector<std::string>& files = gl.GetFiles();
std::vector<std::string>::iterator fileIt;
for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
- cmCTestLog(this, DEBUG, "* Read custom CTest configuration file: "
- << *fileIt << std::endl);
+ cmCTestLog(this, DEBUG,
+ "* Read custom CTest configuration file: " << *fileIt
+ << std::endl);
if (!mf->ReadListFile(fileIt->c_str()) ||
cmSystemTools::GetErrorOccuredFlag()) {
cmCTestLog(this, ERROR_MESSAGE,
if (found) {
for (auto& handler : this->TestingHandlers) {
- cmCTestLog(
- this, DEBUG, "* Read custom CTest configuration vectors for handler: "
- << handler.first << " (" << handler.second << ")" << std::endl);
+ cmCTestLog(this, DEBUG,
+ "* Read custom CTest configuration vectors for handler: "
+ << handler.first << " (" << handler.second << ")"
+ << std::endl);
handler.second->PopulateCustomVectors(mf);
}
}
void cmCTest::SetCTestConfiguration(const char* name, const char* value,
bool suppress)
{
- cmCTestOptionalLog(this, HANDLER_VERBOSE_OUTPUT, "SetCTestConfiguration:"
+ cmCTestOptionalLog(this, HANDLER_VERBOSE_OUTPUT,
+ "SetCTestConfiguration:"
<< name << ":" << (value ? value : "(null)") << "\n",
suppress);
ret = deflate(&strm, Z_FINISH);
if (ret != Z_STREAM_END) {
- cmCTestLog(this, ERROR_MESSAGE, "Error during gzip compression."
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Error during gzip compression." << std::endl);
return false;
}
*/
int TestDirectory(bool memcheck);
- /** what is the configuraiton type, e.g. Debug, Release etc. */
+ /** what is the configuration type, e.g. Debug, Release etc. */
std::string const& GetConfigType();
cmDuration GetTimeOut() { return this->TimeOut; }
void SetTimeOut(cmDuration t) { this->TimeOut = t; }
enum
{
- EXPERIMENTAL,
- NIGHTLY,
- CONTINUOUS
+ UNKNOWN = -1,
+ EXPERIMENTAL = 0,
+ NIGHTLY = 1,
+ CONTINUOUS = 2,
};
/** provide some more detailed info on the return code for ctest */
const std::string& cmake_var,
bool suppress = false);
- /** Make string safe to be send as an URL */
+ /** Make string safe to be sent as a URL */
static std::string MakeURLSafe(const std::string&);
/** Decode a URL to the original string. */
bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args,
std::string& errormsg);
- /** hande the -S -SP and -SR arguments */
+ /** handle the -S -SP and -SR arguments */
void HandleScriptArguments(size_t& i, std::vector<std::string>& args,
bool& SRArgumentSpecified);
#include <sstream>
#include <stdio.h>
#include <string.h>
+#include <string>
#include "cmGeneratedFileStream.h"
#include "cmMessenger.h"
currentcwd += "/CMakeCache.txt";
oldcwd += "/CMakeCache.txt";
if (!cmSystemTools::SameFile(oldcwd, currentcwd)) {
- std::string message =
- std::string("The current CMakeCache.txt directory ") + currentcwd +
- std::string(" is different than the directory ") +
- std::string(this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")) +
- std::string(" where CMakeCache.txt was created. This may result "
- "in binaries being created in the wrong place. If you "
- "are not sure, reedit the CMakeCache.txt");
- cmSystemTools::Error(message.c_str());
+ std::ostringstream message;
+ message << "The current CMakeCache.txt directory " << currentcwd
+ << " is different than the directory "
+ << this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")
+ << " where CMakeCache.txt was created. This may result "
+ "in binaries being created in the wrong place. If you "
+ "are not sure, reedit the CMakeCache.txt";
+ cmSystemTools::Error(message.str().c_str());
}
}
return true;
}
// before writing the cache, update the version numbers
// to the
- char temp[1024];
- sprintf(temp, "%d", cmVersion::GetMinorVersion());
- this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", temp,
- "Minor version of cmake used to create the "
+ this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION",
+ std::to_string(cmVersion::GetMajorVersion()).c_str(),
+ "Major version of cmake used to create the "
"current loaded cache",
cmStateEnums::INTERNAL);
- sprintf(temp, "%d", cmVersion::GetMajorVersion());
- this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", temp,
- "Major version of cmake used to create the "
+ this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION",
+ std::to_string(cmVersion::GetMinorVersion()).c_str(),
+ "Minor version of cmake used to create the "
"current loaded cache",
cmStateEnums::INTERNAL);
- sprintf(temp, "%d", cmVersion::GetPatchVersion());
- this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", temp,
+ this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION",
+ std::to_string(cmVersion::GetPatchVersion()).c_str(),
"Patch version of cmake used to create the "
"current loaded cache",
cmStateEnums::INTERNAL);
cmSystemTools::ConvertToUnixSlashes(e.Value);
}
}
- e.SetProperty("HELPSTRING", helpString
+ e.SetProperty("HELPSTRING",
+ helpString
? helpString
: "(This variable does not exist and should not be used)");
}
#include "cmSystemTools.h"
#if defined(_MSC_VER)
-#define HAVE_COMDEF_H
+# define HAVE_COMDEF_H
#endif
// Just for this file:
#if defined(HAVE_COMDEF_H)
-#include <comdef.h>
+# include <comdef.h>
// Copied from a correct comdef.h to avoid problems with deficient versions
// of comdef.h that exist in the wild... Fixes issue #7533.
//
-#ifdef _NATIVE_WCHAR_T_DEFINED
-#ifdef _DEBUG
-#pragma comment(lib, "comsuppwd.lib")
-#else
-#pragma comment(lib, "comsuppw.lib")
-#endif
-#else
-#ifdef _DEBUG
-#pragma comment(lib, "comsuppd.lib")
-#else
-#pragma comment(lib, "comsupp.lib")
-#endif
-#endif
+# ifdef _NATIVE_WCHAR_T_DEFINED
+# ifdef _DEBUG
+# pragma comment(lib, "comsuppwd.lib")
+# else
+# pragma comment(lib, "comsuppw.lib")
+# endif
+# else
+# ifdef _DEBUG
+# pragma comment(lib, "comsuppd.lib")
+# else
+# pragma comment(lib, "comsupp.lib")
+# endif
+# endif
///! Use ReportHRESULT to make a cmSystemTools::Message after calling
///! a COM method that may have failed.
-#define ReportHRESULT(hr, context) \
- if (FAILED(hr)) { \
- if (LogErrorsAsMessages) { \
- std::ostringstream _hresult_oss; \
- _hresult_oss.flags(std::ios::hex); \
- _hresult_oss << context << " failed HRESULT, hr = 0x" << hr \
- << std::endl; \
- _hresult_oss.flags(std::ios::dec); \
- _hresult_oss << __FILE__ << "(" << __LINE__ << ")"; \
- cmSystemTools::Message(_hresult_oss.str().c_str()); \
- } \
- }
+# define ReportHRESULT(hr, context) \
+ if (FAILED(hr)) { \
+ if (LogErrorsAsMessages) { \
+ std::ostringstream _hresult_oss; \
+ _hresult_oss.flags(std::ios::hex); \
+ _hresult_oss << context << " failed HRESULT, hr = 0x" << hr \
+ << std::endl; \
+ _hresult_oss.flags(std::ios::dec); \
+ _hresult_oss << __FILE__ << "(" << __LINE__ << ")"; \
+ cmSystemTools::Message(_hresult_oss.str().c_str()); \
+ } \
+ }
///! Using the given instance of Visual Studio, call the named macro
HRESULT InstanceCallMacro(IDispatch* vsIDE, const std::string& macro,
/** Is there a keyword which should be skipped in
the arguments (e.g. ARGS for ADD_CUSTOM_COMMAND) ? */
void SetIgnore(const char* ignore) { this->Ignore = ignore; }
+
private:
std::vector<std::string> Vector;
unsigned int DataStart;
/// Return the string
const std::string& GetString() const { return this->String; }
const char* GetCString() const { return this->String.c_str(); }
+
private:
std::string String;
unsigned int DataStart;
/// Has it been enabled ?
bool IsEnabled() const { return this->Enabled; }
+
private:
bool Enabled;
bool DoConsume(const std::string& arg, unsigned int index) override;
/// Is it still enabled ?
bool IsEnabled() const { return this->Enabled; }
+
private:
bool Enabled;
bool DoConsume(const std::string& arg, unsigned int index) override;
#include "cmPolicies.h"
#include "cmState.h"
+#include "cmAddCompileDefinitionsCommand.h"
#include "cmAddCustomCommandCommand.h"
#include "cmAddCustomTargetCommand.h"
#include "cmAddDefinitionsCommand.h"
#include "cmWhileCommand.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmAddCompileOptionsCommand.h"
-#include "cmAuxSourceDirectoryCommand.h"
-#include "cmBuildNameCommand.h"
-#include "cmCMakeHostSystemInformationCommand.h"
-#include "cmExportCommand.h"
-#include "cmExportLibraryDependenciesCommand.h"
-#include "cmFLTKWrapUICommand.h"
-#include "cmIncludeExternalMSProjectCommand.h"
-#include "cmInstallProgramsCommand.h"
-#include "cmLinkLibrariesCommand.h"
-#include "cmLoadCacheCommand.h"
-#include "cmLoadCommandCommand.h"
-#include "cmOutputRequiredFilesCommand.h"
-#include "cmQTWrapCPPCommand.h"
-#include "cmQTWrapUICommand.h"
-#include "cmRemoveCommand.h"
-#include "cmRemoveDefinitionsCommand.h"
-#include "cmSourceGroupCommand.h"
-#include "cmSubdirDependsCommand.h"
-#include "cmUseMangledMesaCommand.h"
-#include "cmUtilitySourceCommand.h"
-#include "cmVariableRequiresCommand.h"
-#include "cmVariableWatchCommand.h"
-#include "cmWriteFileCommand.h"
+# include "cmAddCompileOptionsCommand.h"
+# include "cmAuxSourceDirectoryCommand.h"
+# include "cmBuildNameCommand.h"
+# include "cmCMakeHostSystemInformationCommand.h"
+# include "cmExportCommand.h"
+# include "cmExportLibraryDependenciesCommand.h"
+# include "cmFLTKWrapUICommand.h"
+# include "cmIncludeExternalMSProjectCommand.h"
+# include "cmInstallProgramsCommand.h"
+# include "cmLinkLibrariesCommand.h"
+# include "cmLoadCacheCommand.h"
+# include "cmLoadCommandCommand.h"
+# include "cmOutputRequiredFilesCommand.h"
+# include "cmQTWrapCPPCommand.h"
+# include "cmQTWrapUICommand.h"
+# include "cmRemoveCommand.h"
+# include "cmRemoveDefinitionsCommand.h"
+# include "cmSourceGroupCommand.h"
+# include "cmSubdirDependsCommand.h"
+# include "cmUseMangledMesaCommand.h"
+# include "cmUtilitySourceCommand.h"
+# include "cmVariableRequiresCommand.h"
+# include "cmVariableWatchCommand.h"
+# include "cmWriteFileCommand.h"
#endif
void GetScriptingCommands(cmState* state)
state->AddBuiltinCommand("while", new cmWhileCommand);
state->AddUnexpectedCommand(
- "else", "An ELSE command was found outside of a proper "
- "IF ENDIF structure. Or its arguments did not match "
- "the opening IF command.");
+ "else",
+ "An ELSE command was found outside of a proper "
+ "IF ENDIF structure. Or its arguments did not match "
+ "the opening IF command.");
state->AddUnexpectedCommand(
- "elseif", "An ELSEIF command was found outside of a proper "
- "IF ENDIF structure.");
+ "elseif",
+ "An ELSEIF command was found outside of a proper "
+ "IF ENDIF structure.");
state->AddUnexpectedCommand(
- "endforeach", "An ENDFOREACH command was found outside of a proper "
- "FOREACH ENDFOREACH structure. Or its arguments did "
- "not match the opening FOREACH command.");
+ "endforeach",
+ "An ENDFOREACH command was found outside of a proper "
+ "FOREACH ENDFOREACH structure. Or its arguments did "
+ "not match the opening FOREACH command.");
state->AddUnexpectedCommand(
- "endfunction", "An ENDFUNCTION command was found outside of a proper "
- "FUNCTION ENDFUNCTION structure. Or its arguments did not "
- "match the opening FUNCTION command.");
+ "endfunction",
+ "An ENDFUNCTION command was found outside of a proper "
+ "FUNCTION ENDFUNCTION structure. Or its arguments did not "
+ "match the opening FUNCTION command.");
state->AddUnexpectedCommand(
- "endif", "An ENDIF command was found outside of a proper "
- "IF ENDIF structure. Or its arguments did not match "
- "the opening IF command.");
+ "endif",
+ "An ENDIF command was found outside of a proper "
+ "IF ENDIF structure. Or its arguments did not match "
+ "the opening IF command.");
state->AddUnexpectedCommand(
- "endmacro", "An ENDMACRO command was found outside of a proper "
- "MACRO ENDMACRO structure. Or its arguments did not "
- "match the opening MACRO command.");
+ "endmacro",
+ "An ENDMACRO command was found outside of a proper "
+ "MACRO ENDMACRO structure. Or its arguments did not "
+ "match the opening MACRO command.");
state->AddUnexpectedCommand(
- "endwhile", "An ENDWHILE command was found outside of a proper "
- "WHILE ENDWHILE structure. Or its arguments did not "
- "match the opening WHILE command.");
+ "endwhile",
+ "An ENDWHILE command was found outside of a proper "
+ "WHILE ENDWHILE structure. Or its arguments did not "
+ "match the opening WHILE command.");
#if defined(CMAKE_BUILD_WITH_CMAKE)
state->AddBuiltinCommand("cmake_host_system_information",
state->AddBuiltinCommand("try_run", new cmTryRunCommand);
#if defined(CMAKE_BUILD_WITH_CMAKE)
+ state->AddBuiltinCommand("add_compile_definitions",
+ new cmAddCompileDefinitionsCommand);
state->AddBuiltinCommand("add_compile_options",
new cmAddCompileOptionsCommand);
state->AddBuiltinCommand("aux_source_directory",
cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
for (auto const& item : items) {
cmGeneratorTarget const* linkee = item.Target;
- if (linkee && !linkee->IsImported()
+ if (linkee &&
+ !linkee->IsImported()
// We can ignore the INTERFACE_LIBRARY items because
// Target->GetLinkInformation already processed their
// link interface and they don't have any output themselves.
// Display the constraint graph.
if (this->DebugMode) {
- fprintf(stderr, "---------------------------------------"
- "---------------------------------------\n");
+ fprintf(stderr,
+ "---------------------------------------"
+ "---------------------------------------\n");
fprintf(stderr, "Link dependency analysis for target %s, config %s\n",
this->Target->GetName().c_str(),
this->HasConfig ? this->Config.c_str() : "noconfig");
cmComputeLinkInformation::cmComputeLinkInformation(
const cmGeneratorTarget* target, const std::string& config)
-{
// Store context information.
- this->Target = target;
- this->Makefile = this->Target->Target->GetMakefile();
- this->GlobalGenerator =
- this->Target->GetLocalGenerator()->GetGlobalGenerator();
- this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
-
+ : Target(target)
+ , Makefile(target->Target->GetMakefile())
+ , GlobalGenerator(target->GetLocalGenerator()->GetGlobalGenerator())
+ , CMakeInstance(this->GlobalGenerator->GetCMakeInstance())
+ // The configuration being linked.
+ , Config(config)
+{
// Check whether to recognize OpenBSD-style library versioned names.
this->OpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
"FIND_LIBRARY_USE_OPENBSD_VERSIONING");
- // The configuration being linked.
- this->Config = config;
-
// Allocate internals.
this->OrderLinkerSearchPath = new cmOrderDirectories(
this->GlobalGenerator, target, "linker search path");
}
cmComputeLinkInformation::ItemVector const&
-cmComputeLinkInformation::GetItems()
+cmComputeLinkInformation::GetItems() const
{
return this->Items;
}
std::vector<std::string> const& cmComputeLinkInformation::GetDirectories()
+ const
{
return this->OrderLinkerSearchPath->GetOrderedDirectories();
}
-std::string cmComputeLinkInformation::GetRPathLinkString()
+std::string cmComputeLinkInformation::GetRPathLinkString() const
{
// If there is no separate linker runtime search flag (-rpath-link)
// there is no reason to compute a string.
return cmJoin(this->OrderDependentRPath->GetOrderedDirectories(), ":");
}
-std::vector<std::string> const& cmComputeLinkInformation::GetDepends()
+std::vector<std::string> const& cmComputeLinkInformation::GetDepends() const
{
return this->Depends;
}
std::vector<std::string> const& cmComputeLinkInformation::GetFrameworkPaths()
+ const
{
return this->FrameworkPaths;
}
const std::set<const cmGeneratorTarget*>&
-cmComputeLinkInformation::GetSharedLibrariesLinked()
+cmComputeLinkInformation::GetSharedLibrariesLinked() const
{
return this->SharedLibrariesLinked;
}
if (!libName.empty()) {
this->AddItem(libName, nullptr);
}
+ } else if (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ // Ignore object library!
+ // Its object-files should already have been extracted for linking.
} else {
// Decide whether to use an import library.
bool implib =
(generator.find("Visual Studio") != std::string::npos ||
generator.find("Xcode") != std::string::npos)) {
std::string file = cmSystemTools::GetFilenameName(item);
- if (!this->ExtractAnyLibraryName.find(file.c_str())) {
+ if (!this->ExtractAnyLibraryName.find(file)) {
this->HandleBadFullItem(item, file);
return;
}
void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
{
// Try to separate the framework name and path.
- if (!this->SplitFramework.find(item.c_str())) {
+ if (!this->SplitFramework.find(item)) {
std::ostringstream e;
e << "Could not parse framework path \"" << item << "\" "
<< "linked by target " << this->Target->GetName() << ".";
}
std::vector<std::string> const&
-cmComputeLinkInformation::GetRuntimeSearchPath()
+cmComputeLinkInformation::GetRuntimeSearchPath() const
{
return this->OrderRuntimeSearchPath->GetOrderedDirectories();
}
if (!is_shared_library) {
// On some platforms (AIX) a shared library may look static.
if (this->ArchivesMayBeShared) {
- if (this->ExtractStaticLibraryName.find(file.c_str())) {
+ if (this->ExtractStaticLibraryName.find(file)) {
// This is the name of a shared library or archive.
is_shared_library = true;
}
}
void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
- bool for_install)
+ bool for_install) const
{
// Select whether to generate runtime search directories.
bool outputRuntime =
cmCLI_ExpandListUnique(this->RuntimeAlways.c_str(), runtimeDirs, emitted);
}
-std::string cmComputeLinkInformation::GetRPathString(bool for_install)
+std::string cmComputeLinkInformation::GetRPathString(bool for_install) const
{
// Get the directories to use.
std::vector<std::string> runtimeDirs;
return rpath;
}
-std::string cmComputeLinkInformation::GetChrpathString()
+std::string cmComputeLinkInformation::GetChrpathString() const
{
if (!this->RuntimeUseChrpath) {
return "";
cmGeneratorTarget const* Target;
};
typedef std::vector<Item> ItemVector;
- ItemVector const& GetItems();
- std::vector<std::string> const& GetDirectories();
- std::vector<std::string> const& GetDepends();
- std::vector<std::string> const& GetFrameworkPaths();
+ ItemVector const& GetItems() const;
+ std::vector<std::string> const& GetDirectories() const;
+ std::vector<std::string> const& GetDepends() const;
+ std::vector<std::string> const& GetFrameworkPaths() const;
std::string GetLinkLanguage() const { return this->LinkLanguage; }
- std::vector<std::string> const& GetRuntimeSearchPath();
+ std::vector<std::string> const& GetRuntimeSearchPath() const;
std::string const& GetRuntimeFlag() const { return this->RuntimeFlag; }
std::string const& GetRuntimeSep() const { return this->RuntimeSep; }
- void GetRPath(std::vector<std::string>& runtimeDirs, bool for_install);
- std::string GetRPathString(bool for_install);
- std::string GetChrpathString();
- std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked();
+ void GetRPath(std::vector<std::string>& runtimeDirs, bool for_install) const;
+ std::string GetRPathString(bool for_install) const;
+ std::string GetChrpathString() const;
+ std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked() const;
std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; }
- std::string GetRPathLinkString();
+ std::string GetRPathLinkString() const;
std::string GetConfig() const { return this->Config; }
+
private:
void AddItem(std::string const& item, const cmGeneratorTarget* tgt);
void AddSharedDepItem(std::string const& item, cmGeneratorTarget const* tgt);
std::set<cmGeneratorTarget const*> SharedLibrariesLinked;
// Context information.
- cmGeneratorTarget const* Target;
- cmMakefile* Makefile;
- cmGlobalGenerator* GlobalGenerator;
- cmake* CMakeInstance;
+ cmGeneratorTarget const* const Target;
+ cmMakefile* const Makefile;
+ cmGlobalGenerator* const GlobalGenerator;
+ cmake* const CMakeInstance;
// Configuration information.
- std::string Config;
+ std::string const Config;
std::string LinkLanguage;
// Modes for dealing with dependent shared libraries.
if (depender->GetType() != cmStateEnums::EXECUTABLE &&
depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
- depender->GetType() != cmStateEnums::MODULE_LIBRARY) {
+ depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
cmake::FATAL_ERROR,
- "Only executables and non-OBJECT libraries may "
- "reference target objects.",
+ "Only executables and libraries may reference target objects.",
depender->GetBacktrace());
return;
}
std::string InputFile;
std::string OutputFile;
- bool CopyOnly;
- bool EscapeQuotes;
- bool AtOnly;
+ bool CopyOnly = false;
+ bool EscapeQuotes = false;
+ bool AtOnly = false;
};
#endif
if (strcmp(tt, cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) ==
0) {
targetType = cmStateEnums::EXECUTABLE;
- } else if (strcmp(tt, cmState::GetTargetTypeName(
- cmStateEnums::STATIC_LIBRARY)) == 0) {
+ } else if (strcmp(tt,
+ cmState::GetTargetTypeName(
+ cmStateEnums::STATIC_LIBRARY)) == 0) {
targetType = cmStateEnums::STATIC_LIBRARY;
} else {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, std::string("Invalid value '") + tt +
+ cmake::FATAL_ERROR,
+ std::string("Invalid value '") + tt +
"' for "
"CMAKE_TRY_COMPILE_TARGET_TYPE. Only "
"'" +
- cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE) + "' and "
- "'" +
+ cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE) +
+ "' and "
+ "'" +
cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY) +
"' "
"are allowed.");
cmake::FATAL_ERROR,
"Only libraries may be used as try_compile or try_run IMPORTED "
"LINK_LIBRARIES. Got " +
- std::string(tgt->GetName()) + " of "
- "type " +
+ std::string(tgt->GetName()) +
+ " of "
+ "type " +
cmState::GetTargetTypeName(tgt->GetType()) + ".");
return -1;
}
const char* flags = this->Makefile->GetDefinition(langFlags);
fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li.c_str(),
cmOutputConverter::EscapeForCMake(flags ? flags : "").c_str());
- fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
- " ${COMPILE_DEFINITIONS}\")\n",
+ fprintf(fout,
+ "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
+ " ${COMPILE_DEFINITIONS}\")\n",
li.c_str(), li.c_str());
}
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0066)) {
}
break;
}
- fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}"
- " ${EXE_LINKER_FLAGS}\")\n");
+ fprintf(fout,
+ "set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}"
+ " ${EXE_LINKER_FLAGS}\")\n");
fprintf(fout, "include_directories(${INCLUDE_DIRECTORIES})\n");
fprintf(fout, "set(CMAKE_SUPPRESS_REGENERATION 1)\n");
fprintf(fout, "link_directories(${LINK_DIRECTORIES})\n");
// actually do the try compile now that everything is setup
int res = this->Makefile->TryCompile(
sourceDirectory, this->BinaryDirectory, projectName, targetName,
- this->SrcFileSignature, &cmakeFlags, output);
+ this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL, &cmakeFlags,
+ output);
if (erroroc) {
cmSystemTools::SetErrorOccured();
}
std::string BinaryDirectory;
std::string OutputFile;
std::string FindErrorMessage;
- bool SrcFileSignature;
+ bool SrcFileSignature = false;
private:
std::vector<std::string> WarnCMP0067;
#if !defined(CMAKE_USE_SYSTEM_CURL) && !defined(_WIN32) && \
!defined(__APPLE__) && !defined(CURL_CA_BUNDLE) && !defined(CURL_CA_PATH)
-#define CMAKE_FIND_CAFILE
-#include "cmSystemTools.h"
+# define CMAKE_FIND_CAFILE
+# include "cmSystemTools.h"
#endif
// curl versions before 7.21.5 did not provide this error code
#if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x071505
-#define CURLE_NOT_BUILT_IN 4
+# define CURLE_NOT_BUILT_IN 4
#endif
#define check_curl_result(result, errstr) \
check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
}
#ifdef CMAKE_FIND_CAFILE
-#define CMAKE_CAFILE_FEDORA "/etc/pki/tls/certs/ca-bundle.crt"
+# define CMAKE_CAFILE_FEDORA "/etc/pki/tls/certs/ca-bundle.crt"
else if (cmSystemTools::FileExists(CMAKE_CAFILE_FEDORA, true)) {
::CURLcode res =
::curl_easy_setopt(curl, CURLOPT_CAINFO, CMAKE_CAFILE_FEDORA);
check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
}
-#undef CMAKE_CAFILE_FEDORA
+# undef CMAKE_CAFILE_FEDORA
else {
-#define CMAKE_CAFILE_COMMON "/etc/ssl/certs/ca-certificates.crt"
+# define CMAKE_CAFILE_COMMON "/etc/ssl/certs/ca-certificates.crt"
if (cmSystemTools::FileExists(CMAKE_CAFILE_COMMON, true)) {
::CURLcode res =
::curl_easy_setopt(curl, CURLOPT_CAINFO, CMAKE_CAFILE_COMMON);
check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
}
-#undef CMAKE_CAFILE_COMMON
-#define CMAKE_CAPATH_COMMON "/etc/ssl/certs"
+# undef CMAKE_CAFILE_COMMON
+# define CMAKE_CAPATH_COMMON "/etc/ssl/certs"
if (cmSystemTools::FileIsDirectory(CMAKE_CAPATH_COMMON)) {
::CURLcode res =
::curl_easy_setopt(curl, CURLOPT_CAPATH, CMAKE_CAPATH_COMMON);
check_curl_result(res, "Unable to set TLS/SSL Verify CAPATH: ");
}
-#undef CMAKE_CAPATH_COMMON
+# undef CMAKE_CAPATH_COMMON
}
#endif
return e;
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
-#include "cmWorkingDirectory.h"
#include "cmsys/FStream.hxx"
#include <sstream>
#include <utility>
cmDepends::cmDepends(cmLocalGenerator* lg, const char* targetDir)
- : CompileDirectory()
- , LocalGenerator(lg)
+ : LocalGenerator(lg)
, Verbose(false)
, FileComparison(nullptr)
, TargetDirectory(targetDir)
bool cmDepends::Check(const char* makeFile, const char* internalFile,
std::map<std::string, DependencyVector>& validDeps)
{
- // Dependency checks must be done in proper working directory.
- cmWorkingDirectory workdir(this->CompileDirectory);
-
// Check whether dependencies must be regenerated.
bool okay = true;
cmsys::ifstream fin(internalFile);
path from the build directory to the target file. */
cmDepends(cmLocalGenerator* lg = nullptr, const char* targetDir = "");
- /** at what level will the compile be done from */
- void SetCompileDirectory(const char* dir) { this->CompileDirectory = dir; }
-
/** Set the local generator for the directory in which we are
scanning dependencies. This is not a full local generator; it
has been setup to do relative path conversions for the current
virtual bool Finalize(std::ostream& makeDepends,
std::ostream& internalDepends);
- // The directory in which the build rule for the target file is executed.
- std::string CompileDirectory;
-
// The local generator.
cmLocalGenerator* LocalGenerator;
std::set<std::string> dependencies;
bool haveDeps = false;
+ std::string binDir = this->LocalGenerator->GetBinaryDirectory();
+
+ // Compute a path to the object file to write to the internal depend file.
+ // Any existing content of the internal depend file has already been
+ // loaded in ValidDeps with this path as a key.
+ std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj);
+
if (this->ValidDeps != nullptr) {
std::map<std::string, DependencyVector>::const_iterator tmpIt =
- this->ValidDeps->find(obj);
+ this->ValidDeps->find(obj_i);
if (tmpIt != this->ValidDeps->end()) {
dependencies.insert(tmpIt->second.begin(), tmpIt->second.end());
haveDeps = true;
// written by the original local generator for this directory
// convert the dependencies to paths relative to the home output
// directory. We must do the same here.
- std::string binDir = this->LocalGenerator->GetBinaryDirectory();
- std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj);
std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i);
internalDepends << obj_i << std::endl;
#include <string.h>
#include <utility>
+#include "cmAlgorithms.h"
#include "cmFortranParser.h" /* Interface to parser object. */
#include "cmGeneratedFileStream.h"
#include "cmLocalGenerator.h"
// use lower case and some always use upper case. I do not know if any
// use the case from the source code.
+static void cmFortranModuleAppendUpperLower(std::string const& mod,
+ std::string& mod_upper,
+ std::string& mod_lower)
+{
+ std::string::size_type ext_len = 0;
+ if (cmHasLiteralSuffix(mod, ".mod")) {
+ ext_len = 4;
+ } else if (cmHasLiteralSuffix(mod, ".smod")) {
+ ext_len = 5;
+ }
+ std::string const& name = mod.substr(0, mod.size() - ext_len);
+ std::string const& ext = mod.substr(mod.size() - ext_len);
+ mod_upper += cmSystemTools::UpperCase(name) + ext;
+ mod_lower += mod;
+}
+
class cmDependsFortranInternals
{
public:
for (std::string const& i : provides) {
std::string mod_upper = mod_dir;
mod_upper += "/";
- mod_upper += cmSystemTools::UpperCase(i);
- mod_upper += ".mod";
std::string mod_lower = mod_dir;
mod_lower += "/";
- mod_lower += i;
- mod_lower += ".mod";
+ cmFortranModuleAppendUpperLower(i, mod_upper, mod_lower);
std::string stamp = stamp_dir;
stamp += "/";
stamp += i;
- stamp += ".mod.stamp";
+ stamp += ".stamp";
fcStream << "\n";
fcStream << " \""
<< this->MaybeConvertToRelativePath(currentBinDir, mod_lower)
if (line[0] == ' ') {
if (doing_provides) {
- this->ConsiderModule(line.c_str() + 1, stampDir);
+ std::string mod = line;
+ if (!cmHasLiteralSuffix(mod, ".mod") &&
+ !cmHasLiteralSuffix(mod, ".smod")) {
+ // Support fortran.internal files left by older versions of CMake.
+ // They do not include the ".mod" extension.
+ mod += ".mod";
+ }
+ this->ConsiderModule(mod.c_str() + 1, stampDir);
}
} else if (line == "provides") {
doing_provides = true;
std::string stampFile = stampDir;
stampFile += "/";
stampFile += name;
- stampFile += ".mod.stamp";
+ stampFile += ".stamp";
required->second = stampFile;
}
}
// Always use lower case for the mod stamp file name. The
// cmake_copy_f90_mod will call back to this class, which will
// try various cases for the real mod file name.
- std::string m = cmSystemTools::LowerCase(i);
std::string modFile = mod_dir;
modFile += "/";
modFile += i;
cmOutputConverter::SHELL);
std::string stampFile = stamp_dir;
stampFile += "/";
- stampFile += m;
- stampFile += ".mod.stamp";
+ stampFile += i;
+ stampFile += ".stamp";
stampFile = this->MaybeConvertToRelativePath(binDir, stampFile);
std::string const stampFileForShell =
this->LocalGenerator->ConvertToOutputFormat(stampFile,
bool cmDependsFortran::FindModule(std::string const& name, std::string& module)
{
// Construct possible names for the module file.
- std::string mod_upper = cmSystemTools::UpperCase(name);
- std::string mod_lower = name;
- mod_upper += ".mod";
- mod_lower += ".mod";
+ std::string mod_upper;
+ std::string mod_lower;
+ cmFortranModuleAppendUpperLower(name, mod_upper, mod_lower);
// Search the include path for the module.
std::string fullName;
if (args.size() >= 5) {
compilerId = args[4];
}
+ if (!cmHasLiteralSuffix(mod, ".mod") && !cmHasLiteralSuffix(mod, ".smod")) {
+ // Support depend.make files left by older versions of CMake.
+ // They do not include the ".mod" extension.
+ mod += ".mod";
+ }
std::string mod_dir = cmSystemTools::GetFilenamePath(mod);
if (!mod_dir.empty()) {
mod_dir += "/";
}
std::string mod_upper = mod_dir;
- mod_upper += cmSystemTools::UpperCase(cmSystemTools::GetFilenameName(mod));
std::string mod_lower = mod_dir;
- mod_lower += cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(mod));
- mod += ".mod";
- mod_upper += ".mod";
- mod_lower += ".mod";
+ 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())) {
// Include the ELF format information system header.
#if defined(__OpenBSD__)
-#include <elf_abi.h>
-#include <stdint.h>
+# include <elf_abi.h>
+# include <stdint.h>
#elif defined(__HAIKU__)
-#include <elf32.h>
-#include <elf64.h>
+# include <elf32.h>
+# include <elf64.h>
typedef struct Elf32_Ehdr Elf32_Ehdr;
typedef struct Elf32_Shdr Elf32_Shdr;
typedef struct Elf32_Sym Elf32_Sym;
typedef struct Elf32_Rel Elf32_Rel;
typedef struct Elf32_Rela Elf32_Rela;
-#define ELFMAG0 0x7F
-#define ELFMAG1 'E'
-#define ELFMAG2 'L'
-#define ELFMAG3 'F'
-#define ET_NONE 0
-#define ET_REL 1
-#define ET_EXEC 2
-#define ET_DYN 3
-#define ET_CORE 4
-#define EM_386 3
-#define EM_SPARC 2
-#define EM_PPC 20
+# define ELFMAG0 0x7F
+# define ELFMAG1 'E'
+# define ELFMAG2 'L'
+# define ELFMAG3 'F'
+# define ET_NONE 0
+# define ET_REL 1
+# define ET_EXEC 2
+# define ET_DYN 3
+# define ET_CORE 4
+# define EM_386 3
+# define EM_SPARC 2
+# define EM_PPC 20
#else
-#include <elf.h>
+# include <elf.h>
#endif
#if defined(__sun)
-#include <sys/link.h> // For dynamic section information
+# include <sys/link.h> // For dynamic section information
#endif
#ifdef _SCO_DS
-#include <link.h> // For DT_SONAME etc.
+# include <link.h> // For DT_SONAME etc.
#endif
#ifndef DT_RUNPATH
-#define DT_RUNPATH 29
+# define DT_RUNPATH 29
#endif
// Low-level byte swapping implementation.
// Return the recorded ELF type.
cmELF::FileType GetFileType() const { return this->ELFType; }
+
protected:
// Data common to all ELF class implementations.
#include <vector>
#if !defined(CMAKE_USE_ELF_PARSER)
-#error "This file may be included only if CMAKE_USE_ELF_PARSER is enabled."
+# error "This file may be included only if CMAKE_USE_ELF_PARSER is enabled."
#endif
class cmELFInternal;
} else {
commandInDir = command;
}
-#ifndef __VMS
+# ifndef __VMS
commandInDir += " 2>&1";
-#endif
+# endif
command = commandInDir.c_str();
if (verbose) {
cmSystemTools::Stdout("running ");
}
void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/)
{
std::string targetName = this->Namespace;
targetName += target->GetExportName();
#include "cmExportBuildFileGenerator.h"
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
class cmGeneratorTarget;
void GenerateImportHeaderCode(std::ostream& os,
const std::string& config = "") override;
void GenerateImportFooterCode(std::ostream& os) override;
- void GenerateImportTargetCode(std::ostream& os,
- const cmGeneratorTarget* target) override;
+ void GenerateImportTargetCode(
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/) override;
void GenerateExpectedTargetsCode(
std::ostream& os, const std::string& expectedTargets) override;
void GenerateImportPropertyCode(
this->LG->GetMakefile()->GetBacktrace());
return false;
}
- if (te->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
this->GenerateRequiredCMakeVersion(os, "3.0.0");
}
}
// Create all the imported targets.
for (cmGeneratorTarget* gte : this->Exports) {
- this->GenerateImportTargetCode(os, gte);
+ this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte));
gte->Target->AppendBuildInterfaceIncludes();
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte,
properties);
+
+ std::string errorMessage;
+ if (!this->PopulateExportProperties(gte, properties, errorMessage)) {
+ this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR, errorMessage,
+ this->LG->GetMakefile()->GetBacktrace());
+ return false;
+ }
+
const bool newCMP0022Behavior =
gte->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
gte->GetPolicyStatusCMP0022() != cmPolicies::OLD;
// Collect import properties for this target.
ImportPropertyMap properties;
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) != cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportLocationProperty(config, suffix, target, properties);
}
if (!properties.empty()) {
// Get the rest of the target details.
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) !=
+ cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportDetailProperties(config, suffix, target, properties,
missingTargets);
this->SetImportLinkInterface(config, suffix,
target, properties, missingTargets);
}
- // TOOD: PUBLIC_HEADER_LOCATION
+ // TODO: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
// is done. Then this can be a propagated include directory.
// this->GenerateImportProperty(config, te->HeaderGenerator,
}
}
+cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType(
+ cmGeneratorTarget const* target) const
+{
+ cmStateEnums::TargetType targetType = target->GetType();
+ // An object library exports as an interface library if we cannot
+ // tell clients where to find the objects. This is sufficient
+ // to support transitive usage requirements on other targets that
+ // use the object library.
+ if (targetType == cmStateEnums::OBJECT_LIBRARY &&
+ !this->LG->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) {
+ targetType = cmStateEnums::INTERFACE_LIBRARY;
+ }
+ return targetType;
+}
+
void cmExportBuildFileGenerator::SetExportSet(cmExportSet* exportSet)
{
this->ExportSet = exportSet;
}
// Add the import library for windows DLLs.
- if (target->HasImportLibrary() &&
+ if (target->HasImportLibrary(config) &&
mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
std::string prop = "IMPORTED_IMPLIB";
prop += suffix;
std::string value =
target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact);
- target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+ target->GetImplibGNUtoMS(config, value, value,
+ "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
properties[prop] = value;
}
}
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
#include <iosfwd>
#include <string>
void GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
std::vector<std::string>& missingTargets) override;
+ cmStateEnums::TargetType GetExportTargetType(
+ cmGeneratorTarget const* target) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender,
class cmExecutionStatus;
#if defined(__HAIKU__)
-#include <FindDirectory.h>
-#include <StorageDefs.h>
+# include <FindDirectory.h>
+# include <StorageDefs.h>
#endif
cmExportCommand::cmExportCommand()
}
if (cmTarget* target = gg->FindTarget(currentTarget)) {
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string reason;
- if (!this->Makefile->GetGlobalGenerator()
- ->HasKnownObjectFileLocation(&reason)) {
- std::ostringstream e;
- e << "given OBJECT library \"" << currentTarget
- << "\" which may not be exported" << reason << ".";
- this->SetError(e.str());
- return false;
- }
- }
if (target->GetType() == cmStateEnums::UTILITY) {
this->SetError("given custom target \"" + currentTarget +
"\" which may not be exported.");
}
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# include <windows.h>
void cmExportCommand::ReportRegistryError(std::string const& msg,
std::string const& key, long err)
const char* content,
const char* hash)
{
-#if defined(__HAIKU__)
+# if defined(__HAIKU__)
char dir[B_PATH_NAME_LENGTH];
if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, dir, sizeof(dir)) !=
B_OK) {
std::string fname = dir;
fname += "/cmake/packages/";
fname += package;
-#else
+# else
std::string fname;
if (!cmSystemTools::GetEnv("HOME", fname)) {
return;
cmSystemTools::ConvertToUnixSlashes(fname);
fname += "/.cmake/packages/";
fname += package;
-#endif
+# endif
cmSystemTools::MakeDirectory(fname);
fname += "/";
fname += hash;
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
+#include "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
s << "Directory:\n \"" << li
<< "\"\nin "
"INTERFACE_INCLUDE_DIRECTORIES of target \""
- << target->GetName() << "\" is a subdirectory of the install "
- "directory:\n \""
- << installDir << "\"\nhowever it is also "
- "a subdirectory of the "
+ << target->GetName()
+ << "\" is a subdirectory of the install "
+ "directory:\n \""
+ << installDir
+ << "\"\nhowever it is also "
+ "a subdirectory of the "
<< (inBinary ? "build" : "source") << " tree:\n \""
<< (inBinary ? topBinaryDir : topSourceDir) << "\""
<< std::endl;
properties[prop] = m.str();
}
}
+
+ // Add information if this target is a managed target
+ if (target->GetManagedType(config) !=
+ cmGeneratorTarget::ManagedType::Native) {
+ std::string prop = "IMPORTED_COMMON_LANGUAGE_RUNTIME";
+ prop += suffix;
+ std::string propval;
+ if (auto* p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
+ propval = p;
+ } else if (target->HasLanguage("CSharp", config)) {
+ // C# projects do not have the /clr flag, so we set the property
+ // here to mark the target as (only) managed (i.e. no .lib file
+ // to link to). Otherwise the COMMON_LANGUAGE_RUNTIME target
+ // property would have to be set manually for C# targets to make
+ // exporting/importing work.
+ propval = "CSharp";
+ }
+ properties[prop] = propval;
+ }
}
template <typename T>
"\n\n";
/* clang-format on */
}
+
void cmExportFileGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType targetType)
{
// Construct the imported target name.
std::string targetName = this->Namespace;
// Create the imported target.
os << "# Create imported target " << targetName << "\n";
- switch (target->GetType()) {
+ switch (targetType) {
case cmStateEnums::EXECUTABLE:
os << "add_executable(" << targetName << " IMPORTED)\n";
break;
os << ")\n\n";
}
+
+bool cmExportFileGenerator::PopulateExportProperties(
+ cmGeneratorTarget* gte, ImportPropertyMap& properties,
+ std::string& errorMessage)
+{
+ auto& targetProperties = gte->Target->GetProperties();
+ const auto& exportProperties = targetProperties.find("EXPORT_PROPERTIES");
+ if (exportProperties != targetProperties.end()) {
+ std::vector<std::string> propsToExport;
+ cmSystemTools::ExpandListArgument(exportProperties->second.GetValue(),
+ propsToExport);
+ for (auto& prop : propsToExport) {
+ /* Black list reserved properties */
+ if (cmSystemTools::StringStartsWith(prop, "IMPORTED_") ||
+ cmSystemTools::StringStartsWith(prop, "INTERFACE_")) {
+ std::ostringstream e;
+ e << "Target \"" << gte->Target->GetName() << "\" contains property \""
+ << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* "
+ << "properties are reserved.";
+ errorMessage = e.str();
+ return false;
+ }
+ auto propertyValue = targetProperties.GetPropertyValue(prop);
+ std::string evaluatedValue = cmGeneratorExpression::Preprocess(
+ propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions);
+ if (evaluatedValue != propertyValue) {
+ std::ostringstream e;
+ e << "Target \"" << gte->Target->GetName() << "\" contains property \""
+ << prop << "\" in EXPORT_PROPERTIES but this property contains a "
+ << "generator expression. This is not allowed.";
+ errorMessage = e.str();
+ return false;
+ }
+ properties[prop] = propertyValue;
+ }
+ }
+ return true;
+}
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmGeneratorExpression.h"
+#include "cmStateTypes.h"
#include "cmVersion.h"
#include "cmVersionConfig.h"
virtual void GenerateImportFooterCode(std::ostream& os);
void GenerateImportVersionCode(std::ostream& os);
virtual void GenerateImportTargetCode(std::ostream& os,
- cmGeneratorTarget const* target);
+ cmGeneratorTarget const* target,
+ cmStateEnums::TargetType targetType);
virtual void GenerateImportPropertyCode(std::ostream& os,
const std::string& config,
cmGeneratorTarget const* target,
virtual void GenerateRequiredCMakeVersion(std::ostream& os,
const char* versionString);
+ bool PopulateExportProperties(cmGeneratorTarget* gte,
+ ImportPropertyMap& properties,
+ std::string& errorMessage);
+
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
}
void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/)
{
std::string targetName = this->Namespace;
targetName += target->GetExportName();
#include "cmExportFileGenerator.h"
#include "cmExportInstallFileGenerator.h"
+#include "cmStateTypes.h"
class cmGeneratorTarget;
class cmInstallExportGenerator;
void GenerateImportHeaderCode(std::ostream& os,
const std::string& config = "") override;
void GenerateImportFooterCode(std::ostream& os) override;
- void GenerateImportTargetCode(std::ostream& os,
- const cmGeneratorTarget* target) override;
+ void GenerateImportTargetCode(
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/) override;
void GenerateExpectedTargetsCode(
std::ostream& os, const std::string& expectedTargets) override;
void GenerateImportPropertyCode(
// Create all the imported targets.
for (cmTargetExport* te : allTargets) {
cmGeneratorTarget* gt = te->Target;
+ cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
requiresConfigFiles =
- requiresConfigFiles || gt->GetType() != cmStateEnums::INTERFACE_LIBRARY;
+ requiresConfigFiles || targetType != cmStateEnums::INTERFACE_LIBRARY;
- this->GenerateImportTargetCode(os, gt);
+ this->GenerateImportTargetCode(os, gt, targetType);
ImportPropertyMap properties;
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
+ std::string errorMessage;
+ if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
+ cmSystemTools::Error(errorMessage.c_str());
+ return false;
+ }
+
const bool newCMP0022Behavior =
gt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
gt->GetPolicyStatusCMP0022() != cmPolicies::OLD;
require2_8_12 = true;
}
}
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (targetType == cmStateEnums::INTERFACE_LIBRARY) {
require3_0_0 = true;
}
if (gt->GetProperty("INTERFACE_SOURCES")) {
// Add each target in the set to the export.
for (cmTargetExport* te : *this->IEGen->GetExportSet()->GetTargetExports()) {
// Collect import properties for this target.
- if (te->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
cmGeneratorExpression::InstallInterface,
gtgt, properties, missingTargets);
- // TOOD: PUBLIC_HEADER_LOCATION
+ // TODO: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
// is done. Then this can be a propagated include directory.
// this->GenerateImportProperty(config, te->HeaderGenerator,
}
}
+cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
+ cmTargetExport const* targetExport) const
+{
+ cmStateEnums::TargetType targetType = targetExport->Target->GetType();
+ // An OBJECT library installed with no OBJECTS DESTINATION
+ // is transformed to an INTERFACE library.
+ if (targetType == cmStateEnums::OBJECT_LIBRARY &&
+ targetExport->ObjectsGenerator == nullptr) {
+ targetType = cmStateEnums::INTERFACE_LIBRARY;
+ }
+ return targetType;
+}
+
void cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
#include <iosfwd>
#include <map>
class cmGlobalGenerator;
class cmInstallExportGenerator;
class cmInstallTargetGenerator;
+class cmTargetExport;
/** \class cmExportInstallFileGenerator
* \brief Generate a file exporting targets from an install tree.
files. */
cmExportInstallFileGenerator(cmInstallExportGenerator* iegen);
- /** Get the per-config file generated for each configuraiton. This
+ /** Get the per-config file generated for each configuration. This
maps from the configuration name to the file temporary location
for installation. */
std::map<std::string, std::string> const& GetConfigImportFiles()
void GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
std::vector<std::string>& missingTargets) override;
+ cmStateEnums::TargetType GetExportTargetType(
+ cmTargetExport const* targetExport) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender,
private:
std::string Filename;
- bool Append;
+ bool Append = false;
void ConstFinalPass() const;
};
this->Exports.pop_back();
if (emitted.insert(te).second) {
emittedDeps.insert(te);
- this->GenerateImportTargetCode(os, te);
+ this->GenerateImportTargetCode(os, te, te->GetType());
ImportPropertyMap properties;
/** Set the list of targets to export. */
void SetConfig(const std::string& config) { this->Config = config; }
+
protected:
// Implement virtual methods from the superclass.
bool GenerateMainFile(std::ostream& os) override;
///! Contains the names of the global generators support by this generator.
std::vector<std::string> SupportedGlobalGenerators;
///! the global generator which creates the makefiles
- const cmGlobalGenerator* GlobalGenerator;
+ const cmGlobalGenerator* GlobalGenerator = nullptr;
std::string Name;
};
xml.EndElement(); // Build
// Collect all used source files in the project.
- // Keep a list of C/C++ source files which might have an acompanying header
+ // Keep a list of C/C++ source files which might have an accompanying header
// that should be looked for.
typedef std::map<std::string, CbpUnit> all_files_map_t;
all_files_map_t allFiles;
xml.StartElement("MakeCommands");
xml.StartElement("Build");
- xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
- targetName, makeFlags));
+ xml.Attribute(
+ "command",
+ this->BuildMakeCommand(make, makefileName.c_str(), targetName, makeFlags));
xml.EndElement();
xml.StartElement("CompileFile");
- xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
- "\"$file\"", makeFlags));
+ xml.Attribute("command",
+ this->BuildMakeCommand(make, makefileName.c_str(), "\"$file\"",
+ makeFlags));
xml.EndElement();
xml.StartElement("Clean");
- xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
- "clean", makeFlags));
+ xml.Attribute(
+ "command",
+ this->BuildMakeCommand(make, makefileName.c_str(), "clean", makeFlags));
xml.EndElement();
xml.StartElement("DistClean");
- xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
- "clean", makeFlags));
+ xml.Attribute(
+ "command",
+ this->BuildMakeCommand(make, makefileName.c_str(), "clean", makeFlags));
xml.EndElement();
xml.EndElement(); // MakeCommands
// Collect all used source files in the project
// Sort them into two containers, one for C/C++ implementation files
- // which may have an acompanying header, one for all other files
+ // which may have an accompanying header, one for all other files
std::map<std::string, cmSourceFile*> cFiles;
std::set<std::string> otherFiles;
const std::string& projectPath, const cmMakefile* mf,
const std::string& projectType, const std::string& targetName)
{
-
cmXMLWriter& xml(*_xml);
FindMatchingHeaderfiles(cFiles, otherFiles);
// Create 2 virtual folders: src and include
xml.EndElement(); // ResourceCompiler
xml.StartElement("General");
- std::string outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ std::string outputPath =
+ mf->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
+ if (outputPath.empty()) {
+ outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ }
std::string relapath;
if (!outputPath.empty()) {
- relapath = cmSystemTools::RelativePath(this->WorkspacePath, outputPath);
+ relapath = cmSystemTools::RelativePath(projectPath, outputPath);
xml.Attribute("OutputFile", relapath + "/$(ProjectName)");
} else {
xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
// Collect all used source files in the project
// Sort them into two containers, one for C/C++ implementation files
- // which may have an acompanying header, one for all other files
+ // which may have an accompanying header, one for all other files
std::string projectType;
std::map<std::string, cmSourceFile*> cFiles;
if (generator == "NMake Makefiles" || generator == "Ninja") {
ss << make;
} else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") {
- ss << make << " -j " << this->CpuCount;
+ ss << make << " -f$(ProjectPath)/Makefile -j " << this->CpuCount;
}
if (!targetName.empty()) {
ss << " " << targetName;
xml.StartDocument("UTF-8");
xml.StartElement("projectDescription");
- xml.Element("name", this->GenerateProjectName(
- lg->GetProjectName(),
- mf->GetSafeDefinition("CMAKE_BUILD_TYPE"),
- this->GetPathBasename(this->HomeOutputDirectory)));
+ xml.Element("name",
+ this->GenerateProjectName(
+ lg->GetProjectName(),
+ mf->GetSafeDefinition("CMAKE_BUILD_TYPE"),
+ this->GetPathBasename(this->HomeOutputDirectory)));
xml.Element("comment", "");
xml.Element("projects", "");
xml.EndElement(); // extension
} else if (systemName == "Darwin") {
xml.StartElement("extension");
- xml.Attribute("id", this->SupportsMachO64Parser
+ xml.Attribute("id",
+ this->SupportsMachO64Parser
? "org.eclipse.cdt.core.MachO64"
: "org.eclipse.cdt.core.MachO");
xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
xml.EndElement(); // project
xml.EndElement(); // storageModule
+
+ // Append additional cproject contents without applying any XML formatting
+ if (const char* extraCProjectContents =
+ mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_CPROJECT_CONTENTS")) {
+ fout << extraCProjectContents;
+ }
+
xml.EndElement(); // cproject
}
{
static char JsonSep = ' ';
- fout << "\t\t\t" << JsonSep << "{\"name\":\"" << target << "\", "
- "\"build_cmd\":\""
+ fout << "\t\t\t" << JsonSep << "{\"name\":\"" << target
+ << "\", "
+ "\"build_cmd\":\""
<< make << " -C \\\"" << (this->UseNinja ? homeOutputDir : path)
<< "\\\" " << makeArgs << " " << target << "\"}\n";
std::string defPropName = "COMPILE_DEFINITIONS_";
defPropName += cmSystemTools::UpperCase(config);
if (const char* config_compile_defs = source->GetProperty(defPropName)) {
- lg->AppendDefines(defines, genexInterpreter.Evaluate(config_compile_defs,
- COMPILE_DEFINITIONS));
+ lg->AppendDefines(
+ defines,
+ genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS));
}
std::string definesString;
#include "cmake.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmCurl.h"
-#include "cmFileLockResult.h"
-#include "cm_curl.h"
+# include "cmCurl.h"
+# include "cmFileLockResult.h"
+# include "cm_curl.h"
#endif
#if defined(CMAKE_USE_ELF_PARSER)
-#include "cmELF.h"
+# include "cmELF.h"
#endif
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#endif
class cmSystemToolsFileTime;
if (subCommand == "TO_NATIVE_PATH") {
return this->HandleCMakePathCommand(args, true);
}
+ if (subCommand == "TOUCH") {
+ return this->HandleTouchCommand(args, true);
+ }
+ if (subCommand == "TOUCH_NOCREATE") {
+ return this->HandleTouchCommand(args, false);
+ }
if (subCommand == "TIMESTAMP") {
return this->HandleTimestampCommand(args);
}
#else
mode | S_IWUSR | S_IWGRP
#endif
- );
+ );
}
// If GetPermissions fails, pretend like it is ok. File open will fail if
// the file is not writable
}
std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
file << message;
+ if (!file) {
+ std::string error = "write failed (";
+ error += cmSystemTools::GetLastSystemError();
+ error += "):\n ";
+ error += fileName;
+ this->SetError(error);
+ return false;
+ }
file.close();
if (mode) {
cmSystemTools::SetPermissions(fileName.c_str(), mode);
// Open the specified file.
#if defined(_WIN32) || defined(__CYGWIN__)
cmsys::ifstream file(
- fileName.c_str(), std::ios::in |
+ fileName.c_str(),
+ std::ios::in |
(hexOutputArg.IsEnabled() ? std::ios::binary : std::ios::in));
#else
cmsys::ifstream file(fileName.c_str());
} else {
std::string line;
bool has_newline = false;
- while (sizeLimit != 0 && cmSystemTools::GetLineFromStream(
- file, line, &has_newline, sizeLimit)) {
+ while (
+ sizeLimit != 0 &&
+ cmSystemTools::GetLineFromStream(file, line, &has_newline, sizeLimit)) {
if (sizeLimit > 0) {
sizeLimit = sizeLimit - static_cast<long>(line.size());
if (has_newline) {
} else if (encoding == encoding_utf8) {
// Check for UTF-8 encoded string (up to 4 octets)
static const unsigned char utf8_check_table[3][2] = {
- { 0xE0, 0xC0 }, { 0xF0, 0xE0 }, { 0xF8, 0xF0 },
+ { 0xE0, 0xC0 },
+ { 0xF0, 0xE0 },
+ { 0xF8, 0xF0 },
};
// how many octets are there?
}
}
- std::string output;
- bool first = true;
- for (; i != args.end(); ++i) {
+ std::vector<std::string> files;
+ bool configureDepends = false;
+ bool warnConfigureLate = false;
+ bool warnFollowedSymlinks = false;
+ const cmake::WorkingMode workingMode =
+ this->Makefile->GetCMakeInstance()->GetWorkingMode();
+ while (i != args.end()) {
if (*i == "LIST_DIRECTORIES") {
- ++i;
+ ++i; // skip LIST_DIRECTORIES
if (i != args.end()) {
if (cmSystemTools::IsOn(i->c_str())) {
g.SetListDirs(true);
this->SetError("LIST_DIRECTORIES missing bool value.");
return false;
}
+ ++i;
} else {
this->SetError("LIST_DIRECTORIES missing bool value.");
return false;
}
- continue;
- }
-
- if (recurse && (*i == "FOLLOW_SYMLINKS")) {
- explicitFollowSymlinks = true;
- g.RecurseThroughSymlinksOn();
- ++i;
- if (i == args.end()) {
- this->SetError(
- "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS");
- return false;
+ } else if (*i == "FOLLOW_SYMLINKS") {
+ ++i; // skip FOLLOW_SYMLINKS
+ if (recurse) {
+ explicitFollowSymlinks = true;
+ g.RecurseThroughSymlinksOn();
+ if (i == args.end()) {
+ this->SetError(
+ "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS.");
+ return false;
+ }
}
- }
-
- if (*i == "RELATIVE") {
+ } else if (*i == "RELATIVE") {
++i; // skip RELATIVE
if (i == args.end()) {
- this->SetError("GLOB requires a directory after the RELATIVE tag");
+ this->SetError("GLOB requires a directory after the RELATIVE tag.");
return false;
}
g.SetRelative(i->c_str());
++i;
if (i == args.end()) {
- this->SetError("GLOB requires a glob expression after the directory");
+ this->SetError("GLOB requires a glob expression after the directory.");
return false;
}
- }
-
- cmsys::Glob::GlobMessages globMessages;
- if (!cmsys::SystemTools::FileIsFullPath(*i)) {
- std::string expr = this->Makefile->GetCurrentSourceDirectory();
- // Handle script mode
- if (!expr.empty()) {
- expr += "/" + *i;
- g.FindFiles(expr, &globMessages);
- } else {
- g.FindFiles(*i, &globMessages);
+ } else if (*i == "CONFIGURE_DEPENDS") {
+ // Generated build system depends on glob results
+ if (!configureDepends && warnConfigureLate) {
+ this->Makefile->IssueMessage(
+ cmake::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,
+ "CONFIGURE_DEPENDS is invalid for script and find package modes.");
+ return false;
+ }
+ configureDepends = true;
+ ++i;
+ if (i == args.end()) {
+ this->SetError(
+ "GLOB requires a glob expression after CONFIGURE_DEPENDS.");
+ return false;
}
} else {
- g.FindFiles(*i, &globMessages);
- }
-
- if (!globMessages.empty()) {
- bool shouldExit = false;
- for (cmsys::Glob::Message const& globMessage : globMessages) {
- if (globMessage.type == cmsys::Glob::cyclicRecursion) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
- "Cyclic recursion detected while globbing for '" + *i + "':\n" +
- globMessage.content);
+ std::string expr = *i;
+ if (!cmsys::SystemTools::FileIsFullPath(*i)) {
+ expr = this->Makefile->GetCurrentSourceDirectory();
+ // Handle script mode
+ if (!expr.empty()) {
+ expr += "/" + *i;
} else {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "Error has occurred while globbing for '" +
- *i + "' - " + globMessage.content);
- shouldExit = true;
+ expr = *i;
}
}
- if (shouldExit) {
- return false;
+
+ cmsys::Glob::GlobMessages globMessages;
+ g.FindFiles(expr, &globMessages);
+
+ if (!globMessages.empty()) {
+ bool shouldExit = false;
+ for (cmsys::Glob::Message const& globMessage : globMessages) {
+ if (globMessage.type == cmsys::Glob::cyclicRecursion) {
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ "Cyclic recursion detected while globbing for '" + *i + "':\n" +
+ globMessage.content);
+ } else {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "Error has occurred while globbing for '" + *i + "' - " +
+ globMessage.content);
+ shouldExit = true;
+ }
+ }
+ if (shouldExit) {
+ return false;
+ }
}
- }
- std::vector<std::string>::size_type cc;
- std::vector<std::string>& files = g.GetFiles();
- std::sort(files.begin(), files.end());
- for (cc = 0; cc < files.size(); cc++) {
- if (!first) {
- output += ";";
+ if (recurse && !explicitFollowSymlinks &&
+ g.GetFollowedSymlinkCount() != 0) {
+ warnFollowedSymlinks = true;
}
- output += files[cc];
- first = false;
+
+ std::vector<std::string>& foundFiles = g.GetFiles();
+ files.insert(files.end(), foundFiles.begin(), foundFiles.end());
+
+ if (configureDepends) {
+ std::sort(foundFiles.begin(), foundFiles.end());
+ foundFiles.erase(std::unique(foundFiles.begin(), foundFiles.end()),
+ foundFiles.end());
+ this->Makefile->GetCMakeInstance()->AddGlobCacheEntry(
+ recurse, (recurse ? g.GetRecurseListDirs() : g.GetListDirs()),
+ (recurse ? g.GetRecurseThroughSymlinks() : false),
+ (g.GetRelative() ? g.GetRelative() : ""), expr, foundFiles, variable,
+ this->Makefile->GetBacktrace());
+ } else {
+ warnConfigureLate = true;
+ }
+ ++i;
}
}
- if (recurse && !explicitFollowSymlinks) {
- switch (status) {
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Correct behavior, yay!
- break;
- case cmPolicies::OLD:
- // Probably not really the expected behavior, but the author explicitly
- // asked for the old behavior... no warning.
- case cmPolicies::WARN:
- // Possibly unexpected old behavior *and* we actually traversed
- // symlinks without being explicitly asked to: warn the author.
- if (g.GetFollowedSymlinkCount() != 0) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
- cmPolicies::GetPolicyWarning(cmPolicies::CMP0009));
- }
- break;
- }
+ switch (status) {
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Correct behavior, yay!
+ break;
+ case cmPolicies::OLD:
+ // Probably not really the expected behavior, but the author explicitly
+ // asked for the old behavior... no warning.
+ case cmPolicies::WARN:
+ // Possibly unexpected old behavior *and* we actually traversed
+ // symlinks without being explicitly asked to: warn the author.
+ if (warnFollowedSymlinks) {
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0009));
+ }
+ break;
}
- this->Makefile->AddDefinition(variable, output.c_str());
+ std::sort(files.begin(), files.end());
+ files.erase(std::unique(files.begin(), files.end()), files.end());
+ this->Makefile->AddDefinition(variable, cmJoin(files, ";").c_str());
return true;
}
return true;
}
+bool cmFileCommand::HandleTouchCommand(std::vector<std::string> const& args,
+ bool create)
+{
+ // File command has at least one argument
+ assert(args.size() > 1);
+
+ std::vector<std::string>::const_iterator i = args.begin();
+
+ i++; // Get rid of subcommand
+
+ for (; i != args.end(); ++i) {
+ std::string tfile = *i;
+ if (!cmsys::SystemTools::FileIsFullPath(tfile)) {
+ tfile = this->Makefile->GetCurrentSourceDirectory();
+ tfile += "/" + *i;
+ }
+ if (!this->Makefile->CanIWriteThisFile(tfile)) {
+ std::string e =
+ "attempted to touch a file: " + tfile + " in a source directory.";
+ this->SetError(e);
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ if (!cmSystemTools::Touch(tfile, create)) {
+ std::string error = "problem touching file: " + tfile;
+ this->SetError(error);
+ return false;
+ }
+ }
+ return true;
+}
+
bool cmFileCommand::HandleDifferentCommand(
std::vector<std::string> const& args)
{
if (permissions) {
#ifdef WIN32
if (Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
+ // Store the mode in an NTFS alternate stream.
std::string mode_t_adt_filename =
std::string(toFile) + ":cmake_mode_t";
+ // Writing to an NTFS alternate stream changes the modification
+ // time, so we need to save and restore its original value.
+ cmSystemToolsFileTime* file_time_orig = cmSystemTools::FileTimeNew();
+ cmSystemTools::FileTimeGet(toFile, file_time_orig);
+
cmsys::ofstream permissionStream(mode_t_adt_filename.c_str());
if (permissionStream) {
permissionStream << std::oct << permissions << std::endl;
}
+
+ permissionStream.close();
+
+ cmSystemTools::FileTimeSet(toFile, file_time_orig);
+
+ cmSystemTools::FileTimeDelete(file_time_orig);
}
#endif
return false;
}
-#if defined(_WIN32)
+# if defined(_WIN32)
url = fix_file_url_windows(url);
-#endif
+# endif
::CURL* curl;
::curl_global_init(CURL_GLOBAL_DEFAULT);
unsigned long file_size = cmsys::SystemTools::FileLength(filename);
-#if defined(_WIN32)
+# if defined(_WIN32)
url = fix_file_url_windows(url);
-#endif
+# endif
::CURL* curl;
::curl_global_init(CURL_GLOBAL_DEFAULT);
bool HandleHashCommand(std::vector<std::string> const& args);
bool HandleStringsCommand(std::vector<std::string> const& args);
bool HandleGlobCommand(std::vector<std::string> const& args, bool recurse);
+ bool HandleTouchCommand(std::vector<std::string> const& args, bool create);
bool HandleMakeDirectoryCommand(std::vector<std::string> const& args);
bool HandleRelativePathCommand(std::vector<std::string> const& args);
}
#if defined(_WIN32)
-#include "cmFileLockWin32.cxx"
+# include "cmFileLockWin32.cxx"
#else
-#include "cmFileLockUnix.cxx"
+# include "cmFileLockUnix.cxx"
#endif
#include <string>
#if defined(_WIN32)
-#include <windows.h> // HANDLE
+# include <windows.h> // HANDLE
#endif
class cmFileLockResult;
/**
- * @brief Cross-platform file locking.
- * @details Under the hood this class use 'fcntl' for Unix-like platforms and
- * 'LockFileEx'/'UnlockFileEx' for Win32 platform. Locks are exclusive and
- * advisory.
- */
+ * @brief Cross-platform file locking.
+ * @details Under the hood this class use 'fcntl' for Unix-like platforms and
+ * 'LockFileEx'/'UnlockFileEx' for Win32 platform. Locks are exclusive and
+ * advisory.
+ */
class cmFileLock
{
CM_DISABLE_COPY(cmFileLock)
~cmFileLock();
/**
- * @brief Lock the file.
- * @param timeoutSec Lock timeout. If -1 try until success or fatal error.
- */
+ * @brief Lock the file.
+ * @param timeoutSec Lock timeout. If -1 try until success or fatal error.
+ */
cmFileLockResult Lock(const std::string& filename, unsigned long timeoutSec);
/**
- * @brief Unlock the file.
- */
+ * @brief Unlock the file.
+ */
cmFileLockResult Release();
/**
- * @brief Check file is locked by this class.
- * @details This function helps to find double locks (deadlocks) and to do
- * explicit unlocks.
- */
+ * @brief Check file is locked by this class.
+ * @details This function helps to find double locks (deadlocks) and to do
+ * explicit unlocks.
+ */
bool IsLocked(const std::string& filename) const;
private:
//@{
/**
- * @brief Function scope control.
- */
+ * @brief Function scope control.
+ */
void PushFunctionScope();
void PopFunctionScope();
//@}
//@{
/**
- * @brief File scope control.
- */
+ * @brief File scope control.
+ */
void PushFileScope();
void PopFileScope();
//@}
//@{
/**
- * @brief Lock the file in given scope.
- * @param timeoutSec Lock timeout. If -1 try until success or fatal error.
- */
+ * @brief Lock the file in given scope.
+ * @param timeoutSec Lock timeout. If -1 try until success or fatal error.
+ */
cmFileLockResult LockFunctionScope(const std::string& filename,
unsigned long timeoutSec);
cmFileLockResult LockFileScope(const std::string& filename,
//@}
/**
- * @brief Unlock the file explicitly.
- */
+ * @brief Unlock the file explicitly.
+ */
cmFileLockResult Release(const std::string& filename);
private:
#include <string>
#if defined(_WIN32)
-#include <windows.h> // DWORD
+# include <windows.h> // DWORD
#endif
/**
- * @brief Result of the locking/unlocking file.
- * @note See @c cmFileLock
- */
+ * @brief Result of the locking/unlocking file.
+ * @note See @c cmFileLock
+ */
class cmFileLockResult
{
public:
#endif
/**
- * @brief Successful lock/unlock.
- */
+ * @brief Successful lock/unlock.
+ */
static cmFileLockResult MakeOk();
/**
- * @brief Lock/Unlock failed. Read error/GetLastError.
- */
+ * @brief Lock/Unlock failed. Read error/GetLastError.
+ */
static cmFileLockResult MakeSystem();
/**
- * @brief Lock/Unlock failed. Timeout reached.
- */
+ * @brief Lock/Unlock failed. Timeout reached.
+ */
static cmFileLockResult MakeTimeout();
/**
- * @brief File already locked.
- */
+ * @brief File already locked.
+ */
static cmFileLockResult MakeAlreadyLocked();
/**
- * @brief Internal error.
- */
+ * @brief Internal error.
+ */
static cmFileLockResult MakeInternal();
/**
- * @brief Try to lock with function guard outside of the function
- */
+ * @brief Try to lock with function guard outside of the function
+ */
static cmFileLockResult MakeNoFunction();
bool IsOk() const;
// Use a platform-specific API to get file times efficiently.
#if !defined(_WIN32) || defined(__CYGWIN__)
-#include "cm_sys_stat.h"
-#define cmFileTimeComparison_Type struct stat
+# include "cm_sys_stat.h"
+# define cmFileTimeComparison_Type struct stat
#else
-#include "cmsys/Encoding.hxx"
-#include <windows.h>
-#define cmFileTimeComparison_Type FILETIME
+# include "cmsys/Encoding.hxx"
+# include <windows.h>
+# define cmFileTimeComparison_Type FILETIME
#endif
class cmFileTimeComparisonInternal
cmFileTimeComparison_Type* s2)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
-#if CMake_STAT_HAS_ST_MTIM
+# if CMake_STAT_HAS_ST_MTIM
// Compare using nanosecond resolution.
if (s1->st_mtim.tv_sec < s2->st_mtim.tv_sec) {
return -1;
if (s1->st_mtim.tv_nsec > s2->st_mtim.tv_nsec) {
return 1;
}
-#elif CMake_STAT_HAS_ST_MTIMESPEC
+# elif CMake_STAT_HAS_ST_MTIMESPEC
// Compare using nanosecond resolution.
if (s1->st_mtimespec.tv_sec < s2->st_mtimespec.tv_sec) {
return -1;
if (s1->st_mtimespec.tv_nsec > s2->st_mtimespec.tv_nsec) {
return 1;
}
-#else
+# else
// Compare using 1 second resolution.
if (s1->st_mtime < s2->st_mtime) {
return -1;
if (s1->st_mtime > s2->st_mtime) {
return 1;
}
-#endif
+# endif
// Files have the same time.
return 0;
#else
cmFileTimeComparison_Type* s2)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
-#if CMake_STAT_HAS_ST_MTIM
+# if CMake_STAT_HAS_ST_MTIM
// Times are integers in units of 1ns.
long long bil = 1000000000;
long long t1 = s1->st_mtim.tv_sec * bil + s1->st_mtim.tv_nsec;
return (t1 - t2) >= bil;
}
return false;
-#elif CMake_STAT_HAS_ST_MTIMESPEC
+# elif CMake_STAT_HAS_ST_MTIMESPEC
// Times are integers in units of 1ns.
long long bil = 1000000000;
long long t1 = s1->st_mtimespec.tv_sec * bil + s1->st_mtimespec.tv_nsec;
return (t1 - t2) >= bil;
}
return false;
-#else
+# else
// Times are integers in units of 1s.
if (s1->st_mtime < s2->st_mtime) {
return (s2->st_mtime - s1->st_mtime) >= 1;
return (s1->st_mtime - s2->st_mtime) >= 1;
}
return false;
-#endif
+# endif
#else
// Times are integers in units of 100ns.
LARGE_INTEGER t1;
class cmFileTimeComparisonInternal;
/** \class cmFileTimeComparison
- * \brief Helper class for performing globbing searches.
+ * \brief Helper class for comparing file modification times.
*
- * Finds all files that match a given globbing expression.
+ * Compare file modification times or test if file modification times differ.
*/
class cmFileTimeComparison
{
}
this->AlreadyInCache = false;
- this->SelectDefaultNoPackageRootPath();
-
// Find the current root path mode.
this->SelectDefaultRootPathMode();
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
- // Add package specific search prefixes
- // NOTE: This should be using const_reverse_iterator but HP aCC and
- // Oracle sunCC both currently have standard library issues
- // with the reverse iterator APIs.
- for (std::deque<std::string>::reverse_iterator pkg =
- this->Makefile->FindPackageModuleStack.rbegin();
- pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) {
- std::string varName = *pkg + "_ROOT";
- paths.AddCMakePrefixPath(varName);
- paths.AddEnvPrefixPath(varName);
+ // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
+ for (std::deque<std::vector<std::string>>::const_reverse_iterator pkgPaths =
+ this->Makefile->FindPackageRootPathStack.rbegin();
+ pkgPaths != this->Makefile->FindPackageRootPathStack.rend();
+ ++pkgPaths) {
+ paths.AddPrefixPaths(*pkgPaths);
}
paths.AddSuffixes(this->SearchPathSuffixes);
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake];
- // Add CMake varibles of the same name as the previous environment
- // varibles CMAKE_*_PATH to be used most of the time with -D
+ // Add CMake variables of the same name as the previous environment
+ // variables CMAKE_*_PATH to be used most of the time with -D
// command line options
std::string var = "CMAKE_";
var += this->CMakePathName;
{
std::vector<PathLabel>* labels;
- // Define the varoius different groups of path types
+ // Define the various different groups of path types
// All search paths
labels = &this->PathGroupLabelMap[PathGroup::All];
// Define the search group order
this->PathGroupOrder.push_back(PathGroup::All);
- // Create the idividual labeld search paths
+ // Create the individual labeled search paths
this->LabeledPaths.insert(
std::make_pair(PathLabel::PackageRoot, cmSearchPath(this)));
this->LabeledPaths.insert(
std::make_pair(PathLabel::Guess, cmSearchPath(this)));
}
-void cmFindCommon::SelectDefaultNoPackageRootPath()
-{
- if (!this->Makefile->IsOn("__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT")) {
- this->NoPackageRootPath = true;
- }
-}
-
void cmFindCommon::SelectDefaultRootPathMode()
{
// Check the policy variable for this find command type.
/** Compute final search path list (reroot + trailing slash). */
void ComputeFinalPaths();
- /** Decide whether to enable the PACKAGE_ROOT search entries. */
- void SelectDefaultNoPackageRootPath();
-
/** Compute the current default root path mode. */
void SelectDefaultRootPathMode();
#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmake.h"
#if defined(__HAIKU__)
-#include <FindDirectory.h>
-#include <StorageDefs.h>
+# include <FindDirectory.h>
+# include <StorageDefs.h>
#endif
class cmExecutionStatus;
this->SortDirection = strcmp(sd, "ASC") == 0 ? Asc : Dec;
}
- this->SelectDefaultNoPackageRootPath();
-
// Find the current root path mode.
this->SelectDefaultRootPathMode();
return true;
}
+ {
+ // Allocate a PACKAGE_ROOT_PATH for the current find_package call.
+ this->Makefile->FindPackageRootPathStack.emplace_back();
+ std::vector<std::string>& rootPaths =
+ *this->Makefile->FindPackageRootPathStack.rbegin();
+
+ // Add root paths from <PackageName>_ROOT CMake and environment variables,
+ // subject to CMP0074.
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0074)) {
+ case cmPolicies::WARN:
+ this->Makefile->MaybeWarnCMP0074(this->Name);
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to ignore the <pkg>_ROOT variables.
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0074));
+ break;
+ case cmPolicies::NEW: {
+ // NEW behavior is to honor the <pkg>_ROOT variables.
+ std::string const rootVar = this->Name + "_ROOT";
+ if (const char* pkgRoot = this->Makefile->GetDefinition(rootVar)) {
+ cmSystemTools::ExpandListArgument(pkgRoot, rootPaths, false);
+ }
+ cmSystemTools::GetPath(rootPaths, rootVar.c_str());
+ } break;
+ }
+ }
+
this->SetModuleVariables(components);
// See if there is a Find<package>.cmake module.
"Add NO_MODULE to exclusively request Config mode and search for a "
"package configuration file provided by "
<< this->Name << " (" << this->Name << "Config.cmake or "
- << cmSystemTools::LowerCase(this->Name) << "-config.cmake). "
- "Otherwise make Find"
- << this->Name << ".cmake available in "
- "CMAKE_MODULE_PATH.";
+ << cmSystemTools::LowerCase(this->Name)
+ << "-config.cmake). "
+ "Otherwise make Find"
+ << this->Name
+ << ".cmake available in "
+ "CMAKE_MODULE_PATH.";
}
aw << "\n"
"(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this warning.)";
exact += "_FIND_VERSION_EXACT";
this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
}
-
- // Push on to the package stack
- this->Makefile->FindPackageModuleStack.push_back(this->Name);
}
void cmFindPackageCommand::AddFindDefinition(const std::string& var,
if (result && !found) {
// warn if package required or neither quiet nor in config mode
if (this->Required ||
- !(this->Quiet || (this->UseConfigFiles && !this->UseFindModules &&
- this->ConsideredConfigs.empty()))) {
+ !(this->Quiet ||
+ (this->UseConfigFiles && !this->UseFindModules &&
+ this->ConsideredConfigs.empty()))) {
// The variable is not set.
std::ostringstream e;
std::ostringstream aw;
<< ".cmake\" in "
"CMAKE_MODULE_PATH this project has asked CMake to find a "
"package configuration file provided by \""
- << this->Name << "\", "
- "but CMake did not find one.\n";
+ << this->Name
+ << "\", "
+ "but CMake did not find one.\n";
}
if (this->Configs.size() == 1) {
<< "\" to a "
"directory containing one of the above files. "
"If \""
- << this->Name << "\" provides a separate development "
- "package or SDK, be sure it has been installed.";
+ << this->Name
+ << "\" provides a separate development "
+ "package or SDK, be sure it has been installed.";
} else // if(!this->UseFindModules && !this->UseConfigFiles)
{
e << "No \"Find" << this->Name << ".cmake\" found in "
this->RestoreFindDefinitions();
// Pop the package stack
- this->Makefile->FindPackageModuleStack.pop_back();
+ this->Makefile->FindPackageRootPathStack.pop_back();
}
void cmFindPackageCommand::ComputePrefixes()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
- // Add package specific search prefixes
- // NOTE: This should be using const_reverse_iterator but HP aCC and
- // Oracle sunCC both currently have standard library issues
- // with the reverse iterator APIs.
- for (std::deque<std::string>::reverse_iterator pkg =
- this->Makefile->FindPackageModuleStack.rbegin();
- pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) {
- std::string varName = *pkg + "_ROOT";
- paths.AddCMakePath(varName);
- paths.AddEnvPath(varName);
+ // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
+ for (std::deque<std::vector<std::string>>::const_reverse_iterator pkgPaths =
+ this->Makefile->FindPackageRootPathStack.rbegin();
+ pkgPaths != this->Makefile->FindPackageRootPathStack.rend();
+ ++pkgPaths) {
+ for (std::string const& path : *pkgPaths) {
+ paths.AddPath(path);
+ }
}
}
}
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# include <windows.h>
// http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx
-#if !defined(KEY_WOW64_32KEY)
-#define KEY_WOW64_32KEY 0x0200
-#endif
-#if !defined(KEY_WOW64_64KEY)
-#define KEY_WOW64_64KEY 0x0100
-#endif
+# if !defined(KEY_WOW64_32KEY)
+# define KEY_WOW64_32KEY 0x0200
+# endif
+# if !defined(KEY_WOW64_64KEY)
+# define KEY_WOW64_64KEY 0x0100
+# endif
void cmFindPackageCommand::LoadPackageRegistryWinUser()
{
// HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views.
common.push_back("lib");
common.push_back("share");
- // PREFIX/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/
+ // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
}
}
- // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/
+ // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
}
}
- // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/
+ // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
}
}
- // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
}
}
- // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
}
}
- // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
#include "cmConfigure.h" // IWYU pragma: keep
#include "cm_kwiml.h"
+#include <cstddef>
#include <map>
#include <set>
#include <string>
#include <vector>
+// IWYU insists we should forward-declare instead of including <functional>,
+// but we cannot forward-declare reliably because some C++ standard libraries
+// put the template in an inline namespace.
+#ifdef CMAKE_IWYU
+/* clang-format off */
+namespace std {
+ template <class T> struct hash;
+}
+/* clang-format on */
+#else
+# include <functional>
+#endif
+
#include "cmFindCommon.h"
class cmCommand;
}
};
std::vector<ConfigFileInfo> ConsideredConfigs;
+
+ friend struct std::hash<ConfigFileInfo>;
+};
+
+namespace std {
+
+template <>
+struct hash<cmFindPackageCommand::ConfigFileInfo>
+{
+ typedef cmFindPackageCommand::ConfigFileInfo argument_type;
+ typedef size_t result_type;
+
+ result_type operator()(argument_type const& s) const noexcept
+ {
+ result_type const h(std::hash<std::string>{}(s.filename));
+ return h;
+ }
};
+}
#endif
class cmExecutionStatus;
#if defined(__APPLE__)
-#include <CoreFoundation/CoreFoundation.h>
+# include <CoreFoundation/CoreFoundation.h>
#endif
struct cmFindProgramHelper
cmMakefile& mf,
cmExecutionStatus& inStatus)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "foreach")) {
+ if (lff.Name.Lower == "foreach") {
// record the number of nested foreach commands
this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endforeach")) {
+ } else if (lff.Name.Lower == "endforeach") {
// if this is the endofreach for this statement
if (!this->Depth) {
// Remove the function blocker for this scope or bail.
bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endforeach")) {
+ if (lff.Name.Lower == "endforeach") {
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments);
// if the endforeach has arguments then make sure
#define cmFortranParser_h
#if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx)
-#include "cmConfigure.h" // IWYU pragma: keep
+# include "cmConfigure.h" // IWYU pragma: keep
-#include <set>
-#include <string>
-#include <vector>
+# include <set>
+# include <string>
+# include <vector>
#endif
#include <stddef.h> /* size_t */
/* Callbacks for parser. */
void cmFortranParser_Error(cmFortranParser* parser, const char* message);
-void cmFortranParser_RuleUse(cmFortranParser* parser, const char* name);
+void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name);
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
const char* filename);
void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name);
-void cmFortranParser_RuleModule(cmFortranParser* parser, const char* name);
+void cmFortranParser_RuleModule(cmFortranParser* parser,
+ const char* module_name);
+void cmFortranParser_RuleSubmodule(cmFortranParser* parser,
+ const char* module_name,
+ const char* submodule_name);
+void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser,
+ const char* module_name,
+ const char* submodule_name,
+ const char* nested_submodule_name);
void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* name);
void cmFortranParser_RuleUndef(cmFortranParser* parser, const char* name);
void cmFortranParser_RuleIfdef(cmFortranParser* parser, const char* name);
#define YYSTYPE cmFortran_yystype
#define YYSTYPE_IS_DECLARED 1
#if !defined(cmFortranLexer_cxx)
-#define YY_NO_UNISTD_H
-#include "cmFortranLexer.h"
+# define YY_NO_UNISTD_H
+# include "cmFortranLexer.h"
#endif
#if !defined(cmFortranLexer_cxx)
-#if !defined(cmFortranParser_cxx)
-#undef YY_EXTRA_TYPE
-#undef YY_DECL
-#undef YYSTYPE
-#undef YYSTYPE_IS_DECLARED
-#endif
+# if !defined(cmFortranParser_cxx)
+# undef YY_EXTRA_TYPE
+# undef YY_DECL
+# undef YYSTYPE
+# undef YYSTYPE_IS_DECLARED
+# endif
#endif
#if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx)
-#include <stack>
+# include <stack>
// Information about a single source file.
class cmFortranSourceInfo
parser->Error = msg ? msg : "unknown error";
}
-void cmFortranParser_RuleUse(cmFortranParser* parser, const char* name)
+void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name)
{
- if (!parser->InPPFalseBranch) {
- parser->Info.Requires.insert(cmSystemTools::LowerCase(name));
+ if (parser->InPPFalseBranch) {
+ return;
}
+
+ // syntax: "use module_name"
+ // requires: "module_name.mod"
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ parser->Info.Requires.insert(mod_name + ".mod");
}
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
}
}
-void cmFortranParser_RuleModule(cmFortranParser* parser, const char* name)
+void cmFortranParser_RuleModule(cmFortranParser* parser,
+ const char* module_name)
{
- if (!parser->InPPFalseBranch && !parser->InInterface) {
- parser->Info.Provides.insert(cmSystemTools::LowerCase(name));
+ if (parser->InPPFalseBranch) {
+ return;
}
+
+ if (!parser->InInterface) {
+ // syntax: "module module_name"
+ // provides: "module_name.mod"
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ parser->Info.Provides.insert(mod_name + ".mod");
+ }
+}
+
+void cmFortranParser_RuleSubmodule(cmFortranParser* parser,
+ const char* module_name,
+ const char* submodule_name)
+{
+ if (parser->InPPFalseBranch) {
+ return;
+ }
+
+ // syntax: "submodule (module_name) submodule_name"
+ // requires: "module_name.mod"
+ // provides: "module_name@submodule_name.smod"
+ //
+ // FIXME: Some compilers split the submodule part of a module into a
+ // separate "module_name.smod" file. Whether it is generated or
+ // not depends on conditions more subtle than we currently detect.
+ // For now we depend directly on "module_name.mod".
+
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ std::string const& sub_name = cmSystemTools::LowerCase(submodule_name);
+ parser->Info.Requires.insert(mod_name + ".mod");
+ parser->Info.Provides.insert(mod_name + "@" + sub_name + ".smod");
+}
+
+void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser,
+ const char* module_name,
+ const char* submodule_name,
+ const char* nested_submodule_name)
+{
+ if (parser->InPPFalseBranch) {
+ return;
+ }
+
+ // syntax: "submodule (module_name:submodule_name) nested_submodule_name"
+ // requires: "module_name@submodule_name.smod"
+ // provides: "module_name@nested_submodule_name.smod"
+
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ std::string const& sub_name = cmSystemTools::LowerCase(submodule_name);
+ std::string const& nest_name =
+ cmSystemTools::LowerCase(nested_submodule_name);
+ parser->Info.Requires.insert(mod_name + "@" + sub_name + ".smod");
+ parser->Info.Provides.insert(mod_name + "@" + nest_name + ".smod");
}
void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* macro)
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmState.h"
-#include "cmSystemTools.h"
// define the class for function commands
class cmFunctionHelperCommand : public cmCommand
{
// record commands until we hit the ENDFUNCTION
// at the ENDFUNCTION call we shift gears and start looking for invocations
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "function")) {
+ if (lff.Name.Lower == "function") {
this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) {
+ } else if (lff.Name.Lower == "endfunction") {
// if this is the endfunction for this function then execute
if (!this->Depth) {
// create a new command and add it to cmake
bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) {
+ if (lff.Name.Lower == "endfunction") {
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str());
#include "cmSystemTools.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cm_codecvt.hxx"
-#include "cm_zlib.h"
+# include "cm_codecvt.hxx"
+# include "cm_zlib.h"
#endif
cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
* contents have changed to prevent the file modification time from
* being updated.
*/
-class cmGeneratedFileStream : private cmGeneratedFileStreamBase,
- public cmsys::ofstream
+class cmGeneratedFileStream
+ : private cmGeneratedFileStreamBase
+ , public cmsys::ofstream
{
public:
typedef cmsys::ofstream Stream;
/**
* Close the output file. This should be used only with an open
* stream. The temporary file is atomically renamed to the
- * destionation file if the stream is still valid when this method
+ * destination file if the stream is still valid when this method
* is called.
*/
bool Close();
return top->TransitivePropertiesOnly;
}
+bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression()
+{
+ const cmGeneratorExpressionDAGChecker* top = this;
+ const cmGeneratorExpressionDAGChecker* parent = this->Parent;
+ while (parent) {
+ top = parent;
+ parent = parent->Parent;
+ }
+
+ return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL";
+}
+
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
{
const cmGeneratorExpressionDAGChecker* top = this;
void ReportError(cmGeneratorExpressionContext* context,
const std::string& expr);
+ bool EvaluatingGenexExpression();
bool EvaluatingLinkLibraries(const char* tgt = nullptr);
#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
for (; it != end; ++it) {
if (node->RequiresLiteralInput()) {
if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) {
- reportError(context, this->GetOriginalExpression(), "$<" +
- identifier + "> expression requires literal input.");
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier +
+ "> expression requires literal input.");
return std::string();
}
}
reportError(context, this->GetOriginalExpression(),
"$<" + identifier + "> expression requires no parameters.");
} else if (numExpected == 1) {
- reportError(context, this->GetOriginalExpression(), "$<" + identifier +
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier +
"> expression requires "
"exactly one parameter.");
} else {
if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters &&
parameters.empty()) {
- reportError(context, this->GetOriginalExpression(), "$<" + identifier +
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier +
"> expression requires at least one parameter.");
}
if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
parameters.size() > 1) {
- reportError(context, this->GetOriginalExpression(), "$<" + identifier +
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier +
"> expression requires one or zero parameters.");
}
return std::string();
#include <stddef.h>
#include <string>
+#include <utility>
#include <vector>
struct cmGeneratorExpressionContext;
struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
{
GeneratorExpressionContent(const char* startContent, size_t length);
- void SetIdentifier(
- std::vector<cmGeneratorExpressionEvaluator*> const& identifier)
+
+ void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier)
{
- this->IdentifierChildren = identifier;
+ this->IdentifierChildren = std::move(identifier);
}
void SetParameters(
- std::vector<std::vector<cmGeneratorExpressionEvaluator*>> const&
- parameters)
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters)
{
- this->ParamChildren = parameters;
+ this->ParamChildren = std::move(parameters);
}
Type GetType() const override
}
} equalNode;
+static const struct InListNode : public cmGeneratorExpressionNode
+{
+ InListNode() {}
+
+ int NumExpectedParameters() const override { return 2; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ std::vector<std::string> values;
+ cmSystemTools::ExpandListArgument(parameters[1], values);
+ if (values.empty()) {
+ return "0";
+ }
+
+ return std::find(values.cbegin(), values.cend(), parameters.front()) ==
+ values.cend()
+ ? "0"
+ : "1";
+ }
+} inListNode;
+
+static const struct TargetExistsNode : public cmGeneratorExpressionNode
+{
+ TargetExistsNode() {}
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 1) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_EXISTS:...> expression requires one parameter");
+ return std::string();
+ }
+
+ std::string targetName = parameters.front();
+ if (targetName.empty() ||
+ !cmGeneratorExpression::IsValidTargetName(targetName)) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_EXISTS:tgt> expression requires a non-empty "
+ "valid target name.");
+ return std::string();
+ }
+
+ return context->LG->GetMakefile()->FindTargetToUse(targetName) ? "1" : "0";
+ }
+} targetExistsNode;
+
+static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode
+{
+ TargetNameIfExistsNode() {}
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 1) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_NAME_IF_EXISTS:...> expression requires one "
+ "parameter");
+ return std::string();
+ }
+
+ std::string targetName = parameters.front();
+ if (targetName.empty() ||
+ !cmGeneratorExpression::IsValidTargetName(targetName)) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_NAME_IF_EXISTS:tgt> expression requires a "
+ "non-empty valid target name.");
+ return std::string();
+ }
+
+ return context->LG->GetMakefile()->FindTargetToUse(targetName)
+ ? targetName
+ : std::string();
+ }
+} targetNameIfExistsNode;
+
+struct GenexEvaluator : public cmGeneratorExpressionNode
+{
+ GenexEvaluator() {}
+
+protected:
+ std::string EvaluateExpression(
+ const std::string& genexOperator, const std::string& expression,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const
+ {
+ if (context->HeadTarget) {
+ cmGeneratorExpressionDAGChecker dagChecker(
+ context->Backtrace, context->HeadTarget->GetName(), genexOperator,
+ content, dagCheckerParent);
+ switch (dagChecker.Check()) {
+ case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+ case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: {
+ dagChecker.ReportError(context, content->GetOriginalExpression());
+ return std::string();
+ }
+ case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+ case cmGeneratorExpressionDAGChecker::DAG:
+ break;
+ }
+
+ return this->EvaluateDependentExpression(
+ expression, context->LG, context, context->HeadTarget,
+ context->CurrentTarget, &dagChecker);
+ }
+
+ return this->EvaluateDependentExpression(
+ expression, context->LG, context, context->HeadTarget,
+ context->CurrentTarget, dagCheckerParent);
+ }
+};
+
+static const struct TargetGenexEvalNode : public GenexEvaluator
+{
+ TargetGenexEvalNode() {}
+
+ int NumExpectedParameters() const override { return 2; }
+
+ bool AcceptsArbitraryContentParameter() const override { return true; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
+ {
+ const std::string& targetName = parameters.front();
+ if (targetName.empty() ||
+ !cmGeneratorExpression::IsValidTargetName(targetName)) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_GENEX_EVAL:tgt, ...> expression requires a "
+ "non-empty valid target name.");
+ return std::string();
+ }
+
+ const auto* target = context->LG->FindGeneratorTargetToUse(targetName);
+ if (!target) {
+ std::ostringstream e;
+ e << "$<TARGET_GENEX_EVAL:tgt, ...> target \"" << targetName
+ << "\" not found.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+
+ const std::string& expression = parameters[1];
+ if (expression.empty()) {
+ return expression;
+ }
+
+ cmGeneratorExpressionContext targetContext(
+ context->LG, context->Config, context->Quiet, target, target,
+ context->EvaluateForBuildsystem, context->Backtrace, context->Language);
+
+ return this->EvaluateExpression("TARGET_GENEX_EVAL", expression,
+ &targetContext, content, dagCheckerParent);
+ }
+} targetGenexEvalNode;
+
+static const struct GenexEvalNode : public GenexEvaluator
+{
+ GenexEvalNode() {}
+
+ int NumExpectedParameters() const override { return 1; }
+
+ bool AcceptsArbitraryContentParameter() const override { return true; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
+ {
+ const std::string& expression = parameters[0];
+ if (expression.empty()) {
+ return expression;
+ }
+
+ return this->EvaluateExpression("GENEX_EVAL", expression, context, content,
+ dagCheckerParent);
+ }
+} genexEvalNode;
+
static const struct LowerCaseNode : public cmGeneratorExpressionNode
{
LowerCaseNode() {}
return std::string();
}
- std::vector<std::string> enabledLanguages;
cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
- gg->GetEnabledLanguages(enabledLanguages);
- if (!parameters.empty() &&
- std::find(enabledLanguages.begin(), enabledLanguages.end(),
- parameters.front()) == enabledLanguages.end()) {
- reportError(context, content->GetOriginalExpression(),
- "$<COMPILE_LANGUAGE:...> Unknown language.");
- return std::string();
- }
std::string genName = gg->GetName();
if (genName.find("Makefiles") == std::string::npos &&
genName.find("Ninja") == std::string::npos &&
const char* prop = target->GetProperty(propertyName);
if (dagCheckerParent) {
- if (dagCheckerParent->EvaluatingLinkLibraries()) {
+ if (dagCheckerParent->EvaluatingGenexExpression()) {
+ // No check required.
+ } else if (dagCheckerParent->EvaluatingLinkLibraries()) {
#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
(#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(
std::ostringstream e;
e << "The evaluation of the TARGET_OBJECTS generator expression "
"is only suitable for consumption by CMake (limited"
- << reason << "). "
- "It is not suitable for writing out elsewhere.";
+ << reason
+ << "). "
+ "It is not suitable for writing out elsewhere.";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
#undef TARGET_POLICY_LIST_ITEM
- );
+ );
return std::string();
}
"executables with ENABLE_EXPORTS.");
return std::string();
}
- cmStateEnums::ArtifactType artifact = target->HasImportLibrary()
+ cmStateEnums::ArtifactType artifact =
+ target->HasImportLibrary(context->Config)
? cmStateEnums::ImportLibraryArtifact
: cmStateEnums::RuntimeBinaryArtifact;
return target->GetFullPath(context->Config, artifact);
}
if (target->GetType() >= cmStateEnums::OBJECT_LIBRARY &&
target->GetType() != cmStateEnums::UNKNOWN_LIBRARY) {
- ::reportError(context, content->GetOriginalExpression(), "Target \"" +
- name + "\" is not an executable or library.");
+ ::reportError(context, content->GetOriginalExpression(),
+ "Target \"" + name +
+ "\" is not an executable or library.");
return std::string();
}
- if (dagChecker && (dagChecker->EvaluatingLinkLibraries(name.c_str()) ||
- (dagChecker->EvaluatingSources() &&
- name == dagChecker->TopTarget()))) {
+ if (dagChecker &&
+ (dagChecker->EvaluatingLinkLibraries(name.c_str()) ||
+ (dagChecker->EvaluatingSources() &&
+ name == dagChecker->TopTarget()))) {
::reportError(context, content->GetOriginalExpression(),
"Expressions which require the linker language may not "
"be used while evaluating link libraries");
nodeMap["TARGET_BUNDLE_CONTENT_DIR"] = &targetBundleContentDirNode;
nodeMap["STREQUAL"] = &strEqualNode;
nodeMap["EQUAL"] = &equalNode;
+ nodeMap["IN_LIST"] = &inListNode;
nodeMap["LOWER_CASE"] = &lowerCaseNode;
nodeMap["UPPER_CASE"] = &upperCaseNode;
nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode;
nodeMap["TARGET_NAME"] = &targetNameNode;
nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
nodeMap["TARGET_POLICY"] = &targetPolicyNode;
+ nodeMap["TARGET_EXISTS"] = &targetExistsNode;
+ nodeMap["TARGET_NAME_IF_EXISTS"] = &targetNameIfExistsNode;
+ nodeMap["TARGET_GENEX_EVAL"] = &targetGenexEvalNode;
+ nodeMap["GENEX_EVAL"] = &genexEvalNode;
nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
#include <assert.h>
#include <stddef.h>
+#include <utility>
cmGeneratorExpressionParser::cmGeneratorExpressionParser(
const std::vector<cmGeneratorExpressionToken>& tokens)
if (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::EndExpression) {
- GeneratorExpressionContent* content =
- new GeneratorExpressionContent(startToken->Content, this->it->Content -
- startToken->Content + this->it->Length);
+ GeneratorExpressionContent* content = new GeneratorExpressionContent(
+ startToken->Content,
+ this->it->Content - startToken->Content + this->it->Length);
assert(this->it != this->Tokens.end());
++this->it;
--this->NestingLevel;
- content->SetIdentifier(identifier);
+ content->SetIdentifier(std::move(identifier));
result.push_back(content);
return;
}
((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length;
GeneratorExpressionContent* content =
new GeneratorExpressionContent(startToken->Content, contentLength);
- content->SetIdentifier(identifier);
- content->SetParameters(parameters);
+ content->SetIdentifier(std::move(identifier));
+ content->SetParameters(std::move(parameters));
result.push_back(content);
}
}
template <>
-const char* cmTargetPropertyComputer::ComputeLocationForBuild<
- cmGeneratorTarget>(cmGeneratorTarget const* tgt)
+const char*
+cmTargetPropertyComputer::ComputeLocationForBuild<cmGeneratorTarget>(
+ cmGeneratorTarget const* tgt)
{
return tgt->GetLocation("");
}
this->SourceEntries, true);
this->DLLPlatform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ "") != 0;
this->PolicyMap = t->PolicyMap;
}
case cmStateEnums::MODULE_LIBRARY:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
- // Module import libraries are treated as archive targets.
+ // Module libraries are always treated as library targets.
return "LIBRARY";
case cmStateEnums::ImportLibraryArtifact:
- // Module libraries are always treated as library targets.
+ // Module import libraries are treated as archive targets.
return "ARCHIVE";
}
break;
+ case cmStateEnums::OBJECT_LIBRARY:
+ // Object libraries are always treated as object targets.
+ return "OBJECT";
case cmStateEnums::EXECUTABLE:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
}
}
+static void AddObjectEntries(
+ cmGeneratorTarget const* thisTarget, std::string const& config,
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
+{
+ if (cmLinkImplementationLibraries const* impl =
+ thisTarget->GetLinkImplementationLibraries(config)) {
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ if (lib.Target &&
+ lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ std::string genex = "$<TARGET_OBJECTS:" + lib + ">";
+ cmGeneratorExpression ge(lib.Backtrace);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
+ cge->SetEvaluateForBuildsystem(true);
+ entries.push_back(
+ new cmGeneratorTarget::TargetPropertyEntry(std::move(cge), lib));
+ }
+ }
+ }
+}
+
static bool processSources(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
std::ostringstream err;
if (!targetName.empty()) {
err << "Target \"" << targetName
- << "\" contains relative "
- "path in its INTERFACE_SOURCES:\n"
- " \""
+ << "\" contains relative path in its INTERFACE_SOURCES:\n \""
<< src << "\"";
} else {
- err << "Found relative path while evaluating sources of "
- "\""
+ err << "Found relative path while evaluating sources of \""
<< tgt->GetName() << "\":\n \"" << src << "\"\n";
}
tgt->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, err.str());
}
if (!usedSources.empty()) {
tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::LOG, std::string("Used sources for target ") + tgt->GetName() +
- ":\n" + usedSources,
+ cmake::LOG,
+ std::string("Used sources for target ") + tgt->GetName() + ":\n" +
+ usedSources,
entry->ge->GetBacktrace());
}
}
processSources(this, this->SourceEntries, files, uniqueSrcs, &dagChecker,
config, debugSources);
+ // Collect INTERFACE_SOURCES of all direct link-dependencies.
std::vector<cmGeneratorTarget::TargetPropertyEntry*>
linkInterfaceSourcesEntries;
-
AddInterfaceEntries(this, config, "INTERFACE_SOURCES",
linkInterfaceSourcesEntries);
-
std::vector<std::string>::size_type numFilesBefore = files.size();
bool contextDependentInterfaceSources =
processSources(this, linkInterfaceSourcesEntries, files, uniqueSrcs,
&dagChecker, config, debugSources);
+ // Collect TARGET_OBJECTS of direct object link-dependencies.
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkObjectsEntries;
+ AddObjectEntries(this, config, linkObjectsEntries);
+ std::vector<std::string>::size_type numFilesBefore2 = files.size();
+ bool contextDependentObjects =
+ processSources(this, linkObjectsEntries, files, uniqueSrcs, &dagChecker,
+ config, debugSources);
+
if (!contextDependentDirectSources &&
- !(contextDependentInterfaceSources && numFilesBefore < files.size())) {
+ !(contextDependentInterfaceSources && numFilesBefore < files.size()) &&
+ !(contextDependentObjects && numFilesBefore2 < files.size())) {
this->LinkImplementationLanguageIsContextDependent = false;
}
cmDeleteAll(linkInterfaceSourcesEntries);
+ cmDeleteAll(linkObjectsEntries);
}
void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
kind = SourceKindHeader;
} else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
kind = SourceKindExternalObject;
- if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- badObjLib.push_back(sf);
- }
} else if (!sf->GetLanguage().empty()) {
kind = SourceKindObjectSource;
} else if (ext == "def") {
return this->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::EXECUTABLE;
}
info.WindowsExportAllSymbols =
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
+#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
info.DefFileGenerated =
info.WindowsExportAllSymbols || info.Sources.size() > 1;
+#else
+ // Our __create_def helper is only available on Windows.
+ info.DefFileGenerated = false;
+#endif
if (info.DefFileGenerated) {
info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
} else if (!info.Sources.empty()) {
}
if (!usedIncludes.empty()) {
tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::LOG, std::string("Used includes for target ") + tgt->GetName() +
- ":\n" + usedIncludes,
+ cmake::LOG,
+ std::string("Used includes for target ") + tgt->GetName() + ":\n" +
+ usedIncludes,
entry->ge->GetBacktrace());
}
}
return includes;
}
+enum class OptionsParse
+{
+ None,
+ Shell
+};
+
static void processCompileOptionsInternal(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
std::vector<std::string>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
- bool debugOptions, const char* logName, std::string const& language)
+ bool debugOptions, const char* logName, std::string const& language,
+ OptionsParse parse)
{
for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
std::vector<std::string> entryOptions;
std::string usedOptions;
for (std::string const& opt : entryOptions) {
if (uniqueOptions.insert(opt).second) {
- options.push_back(opt);
+ if (parse == OptionsParse::Shell &&
+ cmHasLiteralPrefix(opt, "SHELL:")) {
+ cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, options);
+ } else {
+ options.push_back(opt);
+ }
if (debugOptions) {
usedOptions += " * " + opt + "\n";
}
}
if (!usedOptions.empty()) {
tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::LOG, std::string("Used compile ") + logName +
- std::string(" for target ") + tgt->GetName() + ":\n" + usedOptions,
+ cmake::LOG,
+ std::string("Used compile ") + logName + std::string(" for target ") +
+ tgt->GetName() + ":\n" + usedOptions,
entry->ge->GetBacktrace());
}
}
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions, "options",
- language);
+ language, OptionsParse::Shell);
}
void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions, "features",
- std::string());
+ std::string(), OptionsParse::None);
}
void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions,
- "definitions", language);
+ "definitions", language, OptionsParse::None);
}
void cmGeneratorTarget::GetCompileDefinitions(
e << "Property " << p << " on target \"" << tgt->GetName()
<< "\" does\nnot match the "
"INTERFACE_"
- << p << " property requirement\nof "
- "dependency \""
+ << p
+ << " property requirement\nof "
+ "dependency \""
<< theTarget->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str());
break;
// Select an output directory.
if (const char* config_outdir = this->GetProperty(configProp)) {
// Use the user-specified per-configuration output directory.
- out = config_outdir;
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(config_outdir);
+ out = cge->Evaluate(this->LocalGenerator, config);
// Skip per-configuration subdirectory.
conf.clear();
} else if (const char* outdir = this->GetProperty(propertyName)) {
// Use the user-specified output directory.
- out = outdir;
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outdir);
+ out = cge->Evaluate(this->LocalGenerator, config);
+
+ // Skip per-configuration subdirectory if the value contained a
+ // generator expression.
+ if (out != outdir) {
+ conf.clear();
+ }
}
if (out.empty()) {
return false;
}
}
+ // Get information if target is managed assembly.
+ {
+ std::string linkProp = "IMPORTED_COMMON_LANGUAGE_RUNTIME";
+ if (auto pc = this->GetProperty(linkProp + suffix)) {
+ info.Managed = this->CheckManagedType(pc);
+ } else if (auto p = this->GetProperty(linkProp)) {
+ info.Managed = this->CheckManagedType(p);
+ }
+ }
+
// Get the cyclic repetition count.
if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
}
}
+bool cmGeneratorTarget::HasLanguage(std::string const& language,
+ std::string const& config,
+ bool exclusive) const
+{
+ std::set<std::string> languages;
+ this->GetLanguages(languages, config);
+ // add linker language (if it is different from compiler languages)
+ languages.insert(this->GetLinkerLanguage(config));
+ return (languages.size() == 1 || !exclusive) &&
+ languages.count(language) > 0;
+}
+
void cmGeneratorTarget::ComputeLinkImplementationLanguages(
const std::string& config, cmOptionalLinkImplementation& impl) const
{
tgt = nullptr;
}
- if (tgt && tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::ostringstream e;
- e << "Target \"" << this->GetName() << "\" links to "
- "OBJECT library \""
- << tgt->GetName()
- << "\" but this is not "
- "allowed. "
- "One may link only to STATIC or SHARED libraries, or to executables "
- "with the ENABLE_EXPORTS property set.";
- cmake* cm = this->LocalGenerator->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
- tgt = nullptr;
- }
-
return tgt;
}
return "";
}
-bool cmGeneratorTarget::HasImplibGNUtoMS() const
+bool cmGeneratorTarget::HasImplibGNUtoMS(std::string const& config) const
{
- return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS");
+ return this->HasImportLibrary(config) && this->GetPropertyAsBool("GNUtoMS");
}
-bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& gnuName,
+bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& config,
+ std::string const& gnuName,
std::string& out,
const char* newExt) const
{
- if (this->HasImplibGNUtoMS() && gnuName.size() > 6 &&
+ if (this->HasImplibGNUtoMS(config) && gnuName.size() > 6 &&
gnuName.substr(gnuName.size() - 6) == ".dll.a") {
out = gnuName.substr(0, gnuName.size() - 6);
out += newExt ? newExt : ".lib";
this->GetPropertyAsBool("ENABLE_EXPORTS"));
}
-bool cmGeneratorTarget::HasImportLibrary() const
+bool cmGeneratorTarget::HasImportLibrary(std::string const& config) const
{
return (this->IsDLLPlatform() &&
(this->GetType() == cmStateEnums::SHARED_LIBRARY ||
- this->IsExecutableWithExports()));
+ this->IsExecutableWithExports()) &&
+ // Assemblies which have only managed code do not have
+ // import libraries.
+ this->GetManagedType(config) != ManagedType::Managed);
}
std::string cmGeneratorTarget::GetSupportDirectory() const
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
this->GetType() == cmStateEnums::UNKNOWN_LIBRARY ||
+ this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
this->IsExecutableWithExports());
}
return (this->GetType() == cmStateEnums::MODULE_LIBRARY &&
this->Makefile->IsOn("APPLE") && this->GetPropertyAsBool("BUNDLE"));
}
+
+cmGeneratorTarget::ManagedType cmGeneratorTarget::CheckManagedType(
+ std::string const& propval) const
+{
+ // The type of the managed assembly (mixed unmanaged C++ and C++/CLI,
+ // or only C++/CLI) does only depend on whether the property is an empty
+ // string or contains any value at all. In Visual Studio generators
+ // this propval is prepended with /clr[:] which results in:
+ //
+ // 1. propval does not exist: no /clr flag, unmanaged target, has import
+ // lib
+ // 2. empty propval: add /clr as flag, mixed unmanaged/managed
+ // target, has import lib
+ // 3. any value (safe,pure): add /clr:[propval] as flag, target with
+ // managed code only, no import lib
+ return propval.empty() ? ManagedType::Mixed : ManagedType::Managed;
+}
+
+cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType(
+ const std::string& config) const
+{
+ // Only libraries and executables can be managed targets.
+ if (this->GetType() > cmStateEnums::SHARED_LIBRARY) {
+ return ManagedType::Undefined;
+ }
+
+ if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ return ManagedType::Native;
+ }
+
+ // Check imported target.
+ if (this->IsImported()) {
+ if (cmGeneratorTarget::ImportInfo const* info =
+ this->GetImportInfo(config)) {
+ return info->Managed;
+ }
+ return ManagedType::Undefined;
+ }
+
+ // Check for explicitly set clr target property.
+ if (auto* clr = this->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
+ return this->CheckManagedType(clr);
+ }
+
+ // C# targets are always managed. This language specific check
+ // is added to avoid that the COMMON_LANGUAGE_RUNTIME target property
+ // has to be set manually for C# targets.
+ return this->HasLanguage("CSharp", config) ? ManagedType::Managed
+ : ManagedType::Native;
+}
BundleDirectoryLevel level) const;
/** Return the install name directory for the target in the
- * build tree. For example: "\@rpath/", "\@loader_path/",
- * or "/full/path/to/library". */
+ * build tree. For example: "\@rpath/", "\@loader_path/",
+ * or "/full/path/to/library". */
std::string GetInstallNameDirForBuildTree(const std::string& config) const;
/** Return the install name directory for the target in the
- * install tree. For example: "\@rpath/" or "\@loader_path/". */
+ * install tree. For example: "\@rpath/" or "\@loader_path/". */
std::string GetInstallNameDirForInstallTree() const;
cmListFileBacktrace GetBacktrace() const;
void GetLanguages(std::set<std::string>& languages,
std::string const& config) const;
+ // Evaluate if the target uses the given language for compilation
+ // and/or linking. If 'exclusive' is true, 'language' is expected
+ // to be the only language used for the target.
+ bool HasLanguage(std::string const& language, std::string const& config,
+ bool exclusive = true) const;
+
void GetObjectLibrariesCMP0026(
std::vector<cmGeneratorTarget*>& objlibs) const;
cmStateEnums::ArtifactType artifact) const;
/** Clears cached meta data for local and external source files.
- * The meta data will be recomputed on demand.
- */
+ * The meta data will be recomputed on demand.
+ */
void ClearSourcesCache();
void AddSource(const std::string& src);
std::string GetLinkerLanguage(const std::string& config) const;
/** Does this target have a GNU implib to convert to MS format? */
- bool HasImplibGNUtoMS() const;
+ bool HasImplibGNUtoMS(std::string const& config) const;
/** Convert the given GNU import library name (.dll.a) to a name with a new
extension (.lib or ${CMAKE_IMPORT_LIBRARY_SUFFIX}). */
- bool GetImplibGNUtoMS(std::string const& gnuName, std::string& out,
- const char* newExt = nullptr) const;
+ bool GetImplibGNUtoMS(std::string const& config, std::string const& gnuName,
+ std::string& out, const char* newExt = nullptr) const;
bool IsExecutableWithExports() const;
/** Return whether or not the target has a DLL import library. */
- bool HasImportLibrary() const;
+ bool HasImportLibrary(std::string const& config) const;
/** Get a build-tree directory in which to place target support files. */
std::string GetSupportDirectory() const;
/** Return whether this target is a CFBundle (plugin) on Apple. */
bool IsCFBundleOnApple() const;
+ /** Assembly types. The order of the values of this enum is relevant
+ because of smaller/larger comparison operations! */
+ enum ManagedType
+ {
+ Undefined = 0, // target is no lib or executable
+ Native, // target compiles to unmanaged binary.
+ Mixed, // target compiles to mixed (managed and unmanaged) binary.
+ Managed // target compiles to managed binary.
+ };
+
+ /** Return the type of assembly this target compiles to. */
+ ManagedType GetManagedType(const std::string& config) const;
+
struct SourceFileFlags GetTargetSourceFileFlags(
const cmSourceFile* sf) const;
{
ImportInfo()
: NoSOName(false)
+ , Managed(Native)
, Multiplicity(0)
{
}
bool NoSOName;
+ ManagedType Managed;
unsigned int Multiplicity;
std::string Location;
std::string SOName;
bool ComputePDBOutputDir(const std::string& kind, const std::string& config,
std::string& out) const;
+ ManagedType CheckManagedType(std::string const& propval) const;
+
public:
const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
const std::string& config) const;
config = cmSystemTools::UpperCase(config);
this->DynamicDownload = this->DetermineIfDynamicDownload(config, language);
if (this->DynamicDownload) {
- *this->GetFolderBuildStreams() << "#component integrity_dynamic_download"
- << std::endl;
+ *this->GetFolderBuildStreams()
+ << "#component integrity_dynamic_download" << std::endl;
}
GhsMultiGpj::WriteGpjTag(this->GetGpjTag(), this->GetFolderBuildStreams());
cmGlobalGhsMultiGenerator::WriteDisclaimer(this->GetFolderBuildStreams());
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;
+ *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;
+ *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;
+ *this->GetFolderBuildStreams()
+ << " -o \"" << outputDir << outputFilename << executable_suffix
+ << "\"" << std::endl;
}
}
}
this->FlagsByLanguage.find(language);
if (flagsByLangI != this->FlagsByLanguage.end()) {
if (!flagsByLangI->second.empty()) {
- *this->GetFolderBuildStreams() << " " << flagsByLangI->second
- << std::endl;
+ *this->GetFolderBuildStreams()
+ << " " << flagsByLangI->second << std::endl;
}
}
}
for (std::vector<std::string>::const_iterator includes_i = includes.begin();
includes_i != includes.end(); ++includes_i) {
- *this->GetFolderBuildStreams() << " -I\"" << *includes_i << "\""
- << std::endl;
+ *this->GetFolderBuildStreams()
+ << " -I\"" << *includes_i << "\"" << std::endl;
}
}
for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end();
++tdsI) {
const cmGeneratorTarget* tg = *tdsI;
- *this->GetFolderBuildStreams() << " -L\"" << GetAbsBuildFilePath(tg)
- << "\"" << std::endl;
+ *this->GetFolderBuildStreams()
+ << " -L\"" << GetAbsBuildFilePath(tg) << "\"" << std::endl;
}
// library targets
cmTarget::LinkLibraryVectorType llv =
if (NULL != tg) {
libName = tg->GetName() + ".a";
}
- *this->GetFolderBuildStreams() << " -l\"" << libName << "\""
- << std::endl;
+ *this->GetFolderBuildStreams()
+ << " -l\"" << libName << "\"" << std::endl;
}
if (!this->TargetGroup) {
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobVerificationManager.h"
+
+#include "cmsys/FStream.hxx"
+#include <sstream>
+
+#include "cmGeneratedFileStream.h"
+#include "cmListFileCache.h"
+#include "cmSystemTools.h"
+#include "cmVersion.h"
+#include "cmake.h"
+
+bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path)
+{
+ if (this->Cache.empty()) {
+ return true;
+ }
+
+ std::string scriptFile = path;
+ scriptFile += cmake::GetCMakeFilesDirectory();
+ std::string stampFile = scriptFile;
+ cmSystemTools::MakeDirectory(scriptFile);
+ scriptFile += "/VerifyGlobs.cmake";
+ stampFile += "/cmake.verify_globs";
+ cmGeneratedFileStream verifyScriptFile(scriptFile.c_str());
+ verifyScriptFile.SetCopyIfDifferent(true);
+ if (!verifyScriptFile) {
+ cmSystemTools::Error("Unable to open verification script file for save. ",
+ scriptFile.c_str());
+ cmSystemTools::ReportLastSystemError("");
+ return false;
+ }
+
+ verifyScriptFile << std::boolalpha;
+ verifyScriptFile << "# CMAKE generated file: DO NOT EDIT!\n"
+ << "# Generated by CMake Version "
+ << cmVersion::GetMajorVersion() << "."
+ << cmVersion::GetMinorVersion() << "\n";
+
+ for (auto const& i : this->Cache) {
+ CacheEntryKey k = std::get<0>(i);
+ CacheEntryValue v = std::get<1>(i);
+
+ if (!v.Initialized) {
+ continue;
+ }
+
+ verifyScriptFile << "\n";
+
+ for (auto const& bt : v.Backtraces) {
+ verifyScriptFile << "# " << std::get<0>(bt);
+ std::get<1>(bt).PrintTitle(verifyScriptFile);
+ verifyScriptFile << "\n";
+ }
+
+ k.PrintGlobCommand(verifyScriptFile, "NEW_GLOB");
+ verifyScriptFile << "\n";
+
+ verifyScriptFile << "set(OLD_GLOB\n";
+ for (const std::string& file : v.Files) {
+ verifyScriptFile << " \"" << file << "\"\n";
+ }
+ verifyScriptFile << " )\n";
+
+ verifyScriptFile << "if(NOT \"${NEW_GLOB}\" STREQUAL \"${OLD_GLOB}\")\n"
+ << " message(\"-- GLOB mismatch!\")\n"
+ << " file(TOUCH_NOCREATE \"" << stampFile << "\")\n"
+ << "endif()\n";
+ }
+ verifyScriptFile.Close();
+
+ cmsys::ofstream verifyStampFile(stampFile.c_str());
+ if (!verifyStampFile) {
+ cmSystemTools::Error("Unable to open verification stamp file for write. ",
+ stampFile.c_str());
+ return false;
+ }
+ verifyStampFile << "# This file is generated by CMake for checking of the "
+ "VerifyGlobs.cmake file\n";
+ this->VerifyScript = scriptFile;
+ this->VerifyStamp = stampFile;
+ return true;
+}
+
+bool cmGlobVerificationManager::DoWriteVerifyTarget() const
+{
+ return !this->VerifyScript.empty() && !this->VerifyStamp.empty();
+}
+
+bool cmGlobVerificationManager::CacheEntryKey::operator<(
+ const CacheEntryKey& r) const
+{
+ if (this->Recurse < r.Recurse) {
+ return true;
+ }
+ if (this->Recurse > r.Recurse) {
+ return false;
+ }
+ if (this->ListDirectories < r.ListDirectories) {
+ return true;
+ }
+ if (this->ListDirectories > r.ListDirectories) {
+ return false;
+ }
+ if (this->FollowSymlinks < r.FollowSymlinks) {
+ return true;
+ }
+ if (this->FollowSymlinks > r.FollowSymlinks) {
+ return false;
+ }
+ if (this->Relative < r.Relative) {
+ return true;
+ }
+ if (this->Relative > r.Relative) {
+ return false;
+ }
+ if (this->Expression < r.Expression) {
+ return true;
+ }
+ if (this->Expression > r.Expression) {
+ return false;
+ }
+ return false;
+}
+
+void cmGlobVerificationManager::CacheEntryKey::PrintGlobCommand(
+ std::ostream& out, const std::string& cmdVar)
+{
+ out << "file(GLOB" << (this->Recurse ? "_RECURSE " : " ");
+ out << cmdVar << " ";
+ if (this->Recurse && this->FollowSymlinks) {
+ out << "FOLLOW_SYMLINKS ";
+ }
+ out << "LIST_DIRECTORIES " << this->ListDirectories << " ";
+ if (!this->Relative.empty()) {
+ out << "RELATIVE \"" << this->Relative << "\" ";
+ }
+ out << "\"" << this->Expression << "\")";
+}
+
+void cmGlobVerificationManager::AddCacheEntry(
+ const bool recurse, const bool listDirectories, const bool followSymlinks,
+ const std::string& relative, const std::string& expression,
+ const std::vector<std::string>& files, const std::string& variable,
+ const cmListFileBacktrace& backtrace)
+{
+ CacheEntryKey key = CacheEntryKey(recurse, listDirectories, followSymlinks,
+ relative, expression);
+ CacheEntryValue& value = this->Cache[key];
+ if (!value.Initialized) {
+ value.Files = files;
+ value.Initialized = true;
+ value.Backtraces.emplace_back(variable, backtrace);
+ } else if (value.Initialized && value.Files != files) {
+ std::ostringstream message;
+ message << std::boolalpha;
+ message << "The glob expression\n";
+ key.PrintGlobCommand(message, variable);
+ backtrace.PrintTitle(message);
+ message << "\nwas already present in the glob cache but the directory\n"
+ "contents have changed during the configuration run.\n";
+ message << "Matching glob expressions:";
+ for (auto const& bt : value.Backtraces) {
+ message << "\n " << std::get<0>(bt);
+ std::get<1>(bt).PrintTitle(message);
+ }
+ cmSystemTools::Error(message.str().c_str());
+ } else {
+ value.Backtraces.emplace_back(variable, backtrace);
+ }
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmGlobVerificationManager_h
+#define cmGlobVerificationManager_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmListFileCache.h"
+
+#include <iosfwd>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+/** \class cmGlobVerificationManager
+ * \brief Class for expressing build-time dependencies on glob expressions.
+ *
+ * Generates a CMake script which verifies glob outputs during prebuild.
+ *
+ */
+class cmGlobVerificationManager
+{
+public:
+ cmGlobVerificationManager() {}
+
+protected:
+ ///! Save verification script for given makefile.
+ ///! Saves to output <path>/<CMakeFilesDirectory>/VerifyGlobs.cmake
+ bool SaveVerificationScript(const std::string& path);
+
+ ///! Add an entry into the glob cache
+ void AddCacheEntry(bool recurse, bool listDirectories, bool followSymlinks,
+ const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ const cmListFileBacktrace& bt);
+
+ ///! Check targets should be written in generated build system.
+ bool DoWriteVerifyTarget() const;
+
+ ///! Get the paths to the generated script and stamp files
+ std::string const& GetVerifyScript() const { return this->VerifyScript; }
+ std::string const& GetVerifyStamp() const { return this->VerifyStamp; }
+
+private:
+ struct CacheEntryKey
+ {
+ const bool Recurse;
+ const bool ListDirectories;
+ const bool FollowSymlinks;
+ const std::string Relative;
+ const std::string Expression;
+ CacheEntryKey(const bool rec, const bool l, const bool s,
+ const std::string& rel, const std::string& e)
+ : Recurse(rec)
+ , ListDirectories(l)
+ , FollowSymlinks(s)
+ , Relative(rel)
+ , Expression(e)
+ {
+ }
+ bool operator<(const CacheEntryKey& r) const;
+ void PrintGlobCommand(std::ostream& out, const std::string& cmdVar);
+ };
+
+ struct CacheEntryValue
+ {
+ bool Initialized;
+ std::vector<std::string> Files;
+ std::vector<std::pair<std::string, cmListFileBacktrace>> Backtraces;
+ CacheEntryValue()
+ : Initialized(false)
+ {
+ }
+ };
+
+ typedef std::map<CacheEntryKey, CacheEntryValue> CacheEntryMap;
+ CacheEntryMap Cache;
+ std::string VerifyScript;
+ std::string VerifyStamp;
+
+ // Only cmState should be able to add cache values.
+ // cmGlobVerificationManager should never be used directly.
+ friend class cmState; // allow access to add cache values
+};
+
+#endif
entry.Name = cmGlobalBorlandMakefileGenerator::GetActualName();
entry.Brief = "Generates Borland makefiles.";
}
+
+void cmGlobalBorlandMakefileGenerator::GenerateBuildCommand(
+ std::vector<std::string>& makeCommand, const std::string& makeProgram,
+ 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)
+{
+ this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeCommand, makeProgram, projectName, projectDir, targetName, config,
+ fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+}
+
+void cmGlobalBorlandMakefileGenerator::PrintBuildCommandAdvice(
+ std::ostream& os, int jobs) const
+{
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ // Borland's make does not support parallel builds
+ // see http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Make
+
+ /* clang-format off */
+ os <<
+ "Warning: Borland's make does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
+ /* clang-format on */
+ }
+
+ this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
+ os, cmake::NO_BUILD_PARALLEL_LEVEL);
+}
#include "cmGlobalNMakeMakefileGenerator.h"
+#include <iosfwd>
+
/** \class cmGlobalBorlandMakefileGenerator
* \brief Write a Borland makefiles.
*
}
///! Get the name for the generator.
- virtual std::string GetName() const
+ std::string GetName() const override
{
return cmGlobalBorlandMakefileGenerator::GetActualName();
}
static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/**
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
- virtual void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile*, bool optional);
-
- virtual bool AllowNotParallel() const { return false; }
- virtual bool AllowDeleteOnError() const { return false; }
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
+
+ bool AllowNotParallel() const override { return false; }
+ bool AllowDeleteOnError() const override { return false; }
+
+protected:
+ void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+ const std::string& makeProgram,
+ 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 =
+ std::vector<std::string>()) override;
+
+ void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
};
#endif
#include "cmsys/FStream.hxx"
#include <algorithm>
#include <assert.h>
+#include <cstring>
#include <iterator>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# include <windows.h>
#endif
#include "cmAlgorithms.h"
#include "cmake.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmCryptoHash.h"
-#include "cm_jsoncpp_value.h"
-#include "cm_jsoncpp_writer.h"
+# include "cmCryptoHash.h"
+# include "cm_jsoncpp_value.h"
+# include "cm_jsoncpp_writer.h"
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#endif
const std::string kCMAKE_PLATFORM_INFO_INITIALIZED =
for (std::string const& li : cur_languages) {
if (!this->LanguagesInProgress.insert(li).second) {
std::ostringstream e;
- e << "Language '" << li << "' is currently being enabled. "
- "Recursive call not allowed.";
+ e << "Language '" << li
+ << "' is currently being enabled. "
+ "Recursive call not allowed.";
mf->IssueMessage(cmake::FATAL_ERROR, e.str());
cmSystemTools::SetFatalErrorOccured();
return;
ZeroMemory(&osviex, sizeof(osviex));
osviex.dwOSVersionInfoSize = sizeof(osviex);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#pragma warning(disable : 4996)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# pragma warning(push)
+# pragma warning(disable : 4996)
+# endif
GetVersionExW((OSVERSIONINFOW*)&osviex);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# pragma warning(pop)
+# endif
std::ostringstream windowsVersionString;
windowsVersionString << osviex.dwMajorVersion << "."
<< osviex.dwMinorVersion << "."
}
this->LocalGenerators[i]->GenerateTestFiles();
this->CMakeInstance->UpdateProgress(
- "Generating", (static_cast<float>(i) + 1.0f) /
+ "Generating",
+ (static_cast<float>(i) + 1.0f) /
static_cast<float>(this->LocalGenerators.size()));
}
this->SetCurrentMakefile(nullptr);
cmBacktraceRange::const_iterator btIt =
noconfig_compile_definitions_bts.begin();
- for (cmStringRange::const_iterator
- it = noconfig_compile_definitions.begin();
+ for (cmStringRange::const_iterator it =
+ noconfig_compile_definitions.begin();
it != noconfig_compile_definitions.end(); ++it, ++btIt) {
t->InsertCompileDefinition(*it, *btIt);
}
}
}
this->CMakeInstance->UpdateProgress(
- "Configuring", 0.9f +
+ "Configuring",
+ 0.9f +
0.1f * (static_cast<float>(i) + 1.0f) /
static_cast<float>(this->Makefiles.size()));
}
}
}
-int cmGlobalGenerator::TryCompile(const std::string& srcdir,
+int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
const std::string& bindir,
const std::string& projectName,
const std::string& target, bool fast,
if (!target.empty()) {
newTarget += target;
#if 0
-#if defined(_WIN32) || defined(__CYGWIN__)
+# if defined(_WIN32) || defined(__CYGWIN__)
std::string tmp = target;
// if the target does not already end in . something
// then assume .exe
{
newTarget += ".exe";
}
-#endif // WIN32
+# endif // WIN32
#endif
}
std::string config =
mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
- return this->Build(srcdir, bindir, projectName, newTarget, output, "",
+ return this->Build(jobs, srcdir, bindir, projectName, newTarget, output, "",
config, false, fast, false, this->TryCompileTimeout);
}
std::vector<std::string>& makeCommand, const std::string& /*unused*/,
const std::string& /*unused*/, const std::string& /*unused*/,
const std::string& /*unused*/, const std::string& /*unused*/,
- bool /*unused*/, bool /*unused*/, std::vector<std::string> const& /*unused*/)
+ bool /*unused*/, int /*unused*/, bool /*unused*/,
+ std::vector<std::string> const& /*unused*/)
{
makeCommand.push_back(
"cmGlobalGenerator::GenerateBuildCommand not implemented");
}
-int cmGlobalGenerator::Build(const std::string& /*unused*/,
+void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
+ int /*jobs*/) const
+{
+ // Subclasses override this method if they e.g want to give a warning that
+ // they do not support certain build command line options
+}
+
+int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/,
const std::string& bindir,
const std::string& projectName,
const std::string& target, std::string& output,
cmSystemTools::OutputOption outputflag,
std::vector<std::string> const& nativeOptions)
{
+ bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
+
/**
* Run an executable command and put the stdout in output.
*/
output += "Change Dir: ";
output += bindir;
output += "\n";
+ if (workdir.Failed()) {
+ cmSystemTools::SetRunCommandHideConsole(hideconsole);
+ cmSystemTools::Error("Failed to change directory: ",
+ std::strerror(workdir.GetLastResult()));
+ output += "Failed to change directory: ";
+ output += std::strerror(workdir.GetLastResult());
+ output += "\n";
+ return 1;
+ }
int retVal;
- bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
cmSystemTools::SetRunCommandHideConsole(true);
std::string outputBuffer;
std::string* outputPtr = &outputBuffer;
std::vector<std::string> makeCommand;
this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName, bindir,
- target, config, fast, verbose, nativeOptions);
+ target, config, fast, jobs, verbose,
+ nativeOptions);
// Workaround to convince VCExpress.exe to produce output.
if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH &&
if (clean) {
std::vector<std::string> cleanCommand;
this->GenerateBuildCommand(cleanCommand, makeCommandCSTR, projectName,
- bindir, "clean", config, fast, verbose);
+ bindir, "clean", config, fast, jobs, verbose);
output += "\nRun Clean Command:";
output += cmSystemTools::PrintSingleCommand(cleanCommand);
output += "\n";
retVal = 1;
}
+ // The OpenWatcom tools do not return an error code when a link
+ // library is not found!
+ if (this->CMakeInstance->GetState()->UseWatcomWMake() && retVal == 0 &&
+ output.find("W1008: cannot open") != std::string::npos) {
+ retVal = 1;
+ }
+
return retVal;
}
bool skipInstallRules = mf->IsOn("CMAKE_SKIP_INSTALL_RULES");
if (this->InstallTargetEnabled && skipInstallRules) {
this->CMakeInstance->IssueMessage(
- cmake::WARNING, "CMAKE_SKIP_INSTALL_RULES was enabled even though "
- "installation rules have been specified",
+ cmake::WARNING,
+ "CMAKE_SKIP_INSTALL_RULES was enabled even though "
+ "installation rules have been specified",
mf->GetBacktrace());
} else if (this->InstallTargetEnabled && !skipInstallRules) {
if (!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.') {
#include "cm_codecvt.hxx"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmFileLockPool.h"
+# include "cmFileLockPool.h"
#endif
class cmExportBuildFileGenerator;
* Try running cmake and building a file. This is used for dynamically
* loaded commands, not as part of the usual build process.
*/
- int TryCompile(const std::string& srcdir, const std::string& bindir,
- const std::string& projectName, const std::string& targetName,
- bool fast, std::string& output, cmMakefile* mf);
+ int TryCompile(int jobs, const std::string& srcdir,
+ const std::string& bindir, const std::string& projectName,
+ const std::string& targetName, bool fast, std::string& output,
+ cmMakefile* mf);
/**
* Build a file given the following information. This is a more direct call
* empty then all is assumed. clean indicates if a "make clean" should be
* done first.
*/
- int Build(const std::string& srcdir, const std::string& bindir,
- const std::string& projectName, const std::string& targetName,
- std::string& output, const std::string& makeProgram,
- const std::string& config, bool clean, bool fast, bool verbose,
- cmDuration timeout, cmSystemTools::OutputOption outputflag =
- cmSystemTools::OUTPUT_NONE,
- std::vector<std::string> const& nativeOptions =
- std::vector<std::string>());
+ int Build(
+ int jobs, const std::string& srcdir, const std::string& bindir,
+ const std::string& projectName, const std::string& targetName,
+ std::string& output, const std::string& makeProgram,
+ const std::string& config, bool clean, bool fast, bool verbose,
+ cmDuration timeout,
+ cmSystemTools::OutputOption outputflag = cmSystemTools::OUTPUT_NONE,
+ std::vector<std::string> const& nativeOptions =
+ std::vector<std::string>());
/**
* Open a generated IDE project given the following information.
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& projectDir,
const std::string& targetName, const std::string& config, bool fast,
- bool verbose,
+ int jobs, bool verbose,
std::vector<std::string> const& makeOptions = std::vector<std::string>());
+ virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const;
+
/** Generate a "cmake --build" call for a given target and config. */
std::string GenerateCMakeBuildCommand(const std::string& target,
const std::string& config,
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& /*projectName*/, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
- bool /*verbose*/, std::vector<std::string> const& makeOptions)
+ int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
makeCommand.push_back(
this->SelectMakeProgram(makeProgram, this->GetGhsBuildCommand()));
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back("-parallel");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back(std::to_string(jobs));
+ }
+ }
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
if (!targetName.empty()) {
void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives()
{
- *this->GetBuildFileStream() << "primaryTarget=arm_integrity.tgt"
- << std::endl;
+ *this->GetBuildFileStream()
+ << "primaryTarget=arm_integrity.tgt" << std::endl;
char const* const customization =
this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
if (NULL != customization && strlen(customization) > 0) {
void cmGlobalGhsMultiGenerator::WriteCompilerOptions(std::string const& fOSDir)
{
- *this->GetBuildFileStream() << " -os_dir=\"" << fOSDir << "\""
- << std::endl;
+ *this->GetBuildFileStream()
+ << " -os_dir=\"" << fOSDir << "\"" << std::endl;
}
void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream* os)
static bool SupportsPlatform() { return false; }
/**
- * Try to determine system information such as shared library
- * extension, pthreads, byte order etc.
- */
+ * Try to determine system information such as shared library
+ * extension, pthreads, byte order etc.
+ */
virtual void EnableLanguage(std::vector<std::string> const& languages,
cmMakefile*, bool optional);
/*
- * Determine what program to use for building the project.
- */
+ * Determine what program to use for building the project.
+ */
bool FindMakeProgram(cmMakefile* mf) override;
cmGeneratedFileStream* GetBuildFileStream()
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& projectDir,
const std::string& targetName, const std::string& config, bool fast,
- bool verbose,
+ int jobs, bool verbose,
std::vector<std::string> const& makeOptions = std::vector<std::string>());
private:
}
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
+
+void cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
+ std::vector<std::string>& makeCommand, const std::string& makeProgram,
+ 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)
+{
+ std::vector<std::string> jomMakeOptions;
+
+ // Since we have full control over the invocation of JOM, let us
+ // make it quiet.
+ jomMakeOptions.push_back(this->MakeSilentFlag);
+ jomMakeOptions.insert(jomMakeOptions.end(), makeOptions.begin(),
+ makeOptions.end());
+
+ // JOM does parallel builds by default, the -j is only needed if a specific
+ // number is given
+ // see https://github.com/qt-labs/jom/blob/v1.1.2/src/jomlib/options.cpp
+ if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ jobs = cmake::NO_BUILD_PARALLEL_LEVEL;
+ }
+
+ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeCommand, makeProgram, projectName, projectDir, targetName, config,
+ fast, jobs, verbose, jomMakeOptions);
+}
#include "cmGlobalUnixMakefileGenerator3.h"
+#include <iosfwd>
+
/** \class cmGlobalJOMMakefileGenerator
* \brief Write a JOM makefiles.
*
return new cmGlobalGeneratorSimpleFactory<cmGlobalJOMMakefileGenerator>();
}
///! Get the name for the generator.
- virtual std::string GetName() const
+ std::string GetName() const override
{
return cmGlobalJOMMakefileGenerator::GetActualName();
}
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
- virtual void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile*, bool optional);
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
+
+protected:
+ void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+ const std::string& makeProgram,
+ 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 =
+ std::vector<std::string>()) override;
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
- const char* envVar) const;
+ const char* envVar) const override;
};
#endif
}
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
+
+void cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
+ std::vector<std::string>& makeCommand, const std::string& makeProgram,
+ 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)
+{
+ std::vector<std::string> nmakeMakeOptions;
+
+ // Since we have full control over the invocation of nmake, let us
+ // make it quiet.
+ nmakeMakeOptions.push_back(this->MakeSilentFlag);
+ nmakeMakeOptions.insert(nmakeMakeOptions.end(), makeOptions.begin(),
+ makeOptions.end());
+
+ this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeCommand, makeProgram, projectName, projectDir, targetName, config,
+ fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, nmakeMakeOptions);
+}
+
+void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
+ int jobs) const
+{
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ // nmake does not support parallel build level
+ // see https://msdn.microsoft.com/en-us/library/afyyse50.aspx
+
+ /* clang-format off */
+ os <<
+ "Warning: NMake does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
+ /* clang-format on */
+ }
+
+ this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
+ os, cmake::NO_BUILD_PARALLEL_LEVEL);
+}
#include "cmGlobalUnixMakefileGenerator3.h"
+#include <iosfwd>
+
/** \class cmGlobalNMakeMakefileGenerator
* \brief Write a NMake makefiles.
*
cmGlobalNMakeMakefileGenerator>();
}
///! Get the name for the generator.
- virtual std::string GetName() const
+ std::string GetName() const override
{
return cmGlobalNMakeMakefileGenerator::GetActualName();
}
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
- virtual void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile*, bool optional);
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
+
+protected:
+ void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+ const std::string& makeProgram,
+ 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 =
+ std::vector<std::string>()) override;
+
+ void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
- const char* envVar) const;
+ const char* envVar) const override;
};
#endif
return encoded;
}
-static bool IsIdentChar(char c)
-{
- return ('a' <= c && c <= 'z') ||
- ('+' <= c && c <= '9') || // +,-./ and numbers
- ('A' <= c && c <= 'Z') || (c == '_') || (c == '$') || (c == '\\') ||
- (c == ' ') || (c == ':');
-}
-
-std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string& ident,
- std::ostream& vars)
-{
- if (std::find_if(ident.begin(), ident.end(),
- [](char c) { return !IsIdentChar(c); }) != ident.end()) {
- static unsigned VarNum = 0;
- std::ostringstream names;
- names << "ident" << VarNum++;
- vars << names.str() << " = " << ident << "\n";
- return "$" + names.str();
- }
- std::string result = ident;
- cmSystemTools::ReplaceString(result, " ", "$ ");
- cmSystemTools::ReplaceString(result, ":", "$:");
- return result;
-}
-
std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit)
{
std::string result = lit;
else
std::replace(result.begin(), result.end(), '/', '\\');
#endif
- return EncodeLiteral(result);
+ result = EncodeLiteral(result);
+ cmSystemTools::ReplaceString(result, " ", "$ ");
+ cmSystemTools::ReplaceString(result, ":", "$:");
+ return result;
}
void cmGlobalNinjaGenerator::WriteBuild(
// Write explicit dependencies.
for (std::string const& explicitDep : explicitDeps) {
- arguments += " " + EncodeIdent(EncodePath(explicitDep), os);
+ arguments += " " + EncodePath(explicitDep);
}
// Write implicit dependencies.
if (!implicitDeps.empty()) {
arguments += " |";
for (std::string const& implicitDep : implicitDeps) {
- arguments += " " + EncodeIdent(EncodePath(implicitDep), os);
+ arguments += " " + EncodePath(implicitDep);
}
}
if (!orderOnlyDeps.empty()) {
arguments += " ||";
for (std::string const& orderOnlyDep : orderOnlyDeps) {
- arguments += " " + EncodeIdent(EncodePath(orderOnlyDep), os);
+ arguments += " " + EncodePath(orderOnlyDep);
}
}
// Write outputs files.
build += "build";
for (std::string const& output : outputs) {
- build += " " + EncodeIdent(EncodePath(output), os);
+ build += " " + EncodePath(output);
if (this->ComputingUnknownDependencies) {
this->CombinedBuildOutputs.insert(output);
}
if (!implicitOuts.empty()) {
build += " |";
for (std::string const& implicitOut : implicitOuts) {
- build += " " + EncodeIdent(EncodePath(implicitOut), os);
+ build += " " + EncodePath(implicitOut);
}
}
build += ":";
, PolicyCMP0058(cmPolicies::WARN)
, NinjaSupportsConsolePool(false)
, NinjaSupportsImplicitOuts(false)
+ , NinjaSupportsManifestRestat(false)
, NinjaSupportsDyndeps(0)
{
#ifdef _WIN32
if (!cmSystemTools::RunSingleCommand(command, &version, &error, nullptr,
nullptr,
cmSystemTools::OUTPUT_NONE)) {
- mf->IssueMessage(cmake::FATAL_ERROR, "Running\n '" +
- cmJoin(command, "' '") + "'\n"
- "failed with:\n " +
+ mf->IssueMessage(cmake::FATAL_ERROR,
+ "Running\n '" + cmJoin(command, "' '") +
+ "'\n"
+ "failed with:\n " +
error);
cmSystemTools::SetFatalErrorOccured();
return false;
this->NinjaSupportsImplicitOuts = !cmSystemTools::VersionCompare(
cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
this->RequiredNinjaVersionForImplicitOuts().c_str());
+ this->NinjaSupportsManifestRestat = !cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
+ RequiredNinjaVersionForManifestRestat().c_str());
{
// Our ninja branch adds ".dyndep-#" to its version number,
// where '#' is a feature-specific version number. Extract it.
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& /*projectName*/, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
- bool verbose, std::vector<std::string> const& makeOptions)
+ int jobs, bool verbose, std::vector<std::string> const& makeOptions)
{
makeCommand.push_back(this->SelectMakeProgram(makeProgram));
makeCommand.push_back("-v");
}
+ if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) &&
+ (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) {
+ makeCommand.push_back("-j");
+ makeCommand.push_back(std::to_string(jobs));
+ }
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
if (!targetName.empty()) {
void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
{
for (auto const& asd : this->AssumedSourceDependencies) {
- cmNinjaDeps deps;
- std::copy(asd.second.begin(), asd.second.end(), std::back_inserter(deps));
+ cmNinjaDeps orderOnlyDeps;
+ std::copy(asd.second.begin(), asd.second.end(),
+ std::back_inserter(orderOnlyDeps));
WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
"Assume dependencies for generated source file.",
/*depfile*/ "", /*uses_terminal*/ false,
- /*restat*/ true, cmNinjaDeps(1, asd.first), deps);
+ /*restat*/ true, cmNinjaDeps(1, asd.first),
+ cmNinjaDeps(), orderOnlyDeps);
}
}
for (std::string const& file : files) {
knownDependencies.insert(this->ConvertToNinjaPath(file));
}
- // get list files which are implicit dependencies as well and will be phony
- // for rebuild manifest
- std::vector<std::string> const& lf = lg->GetMakefile()->GetListFiles();
- for (std::string const& j : lf) {
- knownDependencies.insert(this->ConvertToNinjaPath(j));
+ if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ // get list files which are implicit dependencies as well and will be
+ // phony for rebuild manifest
+ std::vector<std::string> const& lf = lg->GetMakefile()->GetListFiles();
+ for (std::string const& j : lf) {
+ knownDependencies.insert(this->ConvertToNinjaPath(j));
+ }
}
std::vector<cmGeneratorExpressionEvaluationFile*> const& ef =
lg->GetMakefile()->GetEvaluationFiles();
void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return;
+ }
cmLocalGenerator* lg = this->LocalGenerators[0];
std::ostringstream cmd;
/*generator=*/true);
cmNinjaDeps implicitDeps;
+ cmNinjaDeps explicitDeps;
for (cmLocalGenerator* localGen : this->LocalGenerators) {
std::vector<std::string> const& lf =
localGen->GetMakefile()->GetListFiles();
}
implicitDeps.push_back(this->CMakeCacheFile);
- std::sort(implicitDeps.begin(), implicitDeps.end());
- implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()),
- implicitDeps.end());
-
cmNinjaVars variables;
// Use 'console' pool to get non buffered output of the CMake re-run call
// Available since Ninja 1.5
variables["pool"] = "console";
}
+ cmake* cm = this->GetCMakeInstance();
+ if (this->SupportsManifestRestat() && cm->DoWriteGlobVerifyTarget()) {
+ std::ostringstream verify_cmd;
+ verify_cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
+ cmOutputConverter::SHELL)
+ << " -P "
+ << lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+ cmOutputConverter::SHELL);
+
+ WriteRule(*this->RulesFileStream, "VERIFY_GLOBS", verify_cmd.str(),
+ "Re-checking globbed directories...",
+ "Rule for re-checking globbed directories.",
+ /*depfile=*/"",
+ /*deptype=*/"",
+ /*rspfile=*/"",
+ /*rspcontent*/ "",
+ /*restat=*/"",
+ /*generator=*/true);
+
+ std::string verifyForce = cm->GetGlobVerifyScript() + "_force";
+ cmNinjaDeps verifyForceDeps(1, this->NinjaOutputPath(verifyForce));
+
+ this->WritePhonyBuild(os, "Phony target to force glob verification run.",
+ verifyForceDeps, cmNinjaDeps());
+
+ variables["restat"] = "1";
+ std::string const verifyScriptFile =
+ this->NinjaOutputPath(cm->GetGlobVerifyScript());
+ std::string const verifyStampFile =
+ this->NinjaOutputPath(cm->GetGlobVerifyStamp());
+ this->WriteBuild(os,
+ "Re-run CMake to check if globbed directories changed.",
+ "VERIFY_GLOBS",
+ /*outputs=*/cmNinjaDeps(1, verifyStampFile),
+ /*implicitOuts=*/cmNinjaDeps(),
+ /*explicitDeps=*/cmNinjaDeps(),
+ /*implicitDeps=*/verifyForceDeps,
+ /*orderOnlyDeps=*/cmNinjaDeps(), variables);
+
+ variables.erase("restat");
+ implicitDeps.push_back(verifyScriptFile);
+ explicitDeps.push_back(verifyStampFile);
+ } else if (!this->SupportsManifestRestat() &&
+ cm->DoWriteGlobVerifyTarget()) {
+ std::ostringstream msg;
+ msg << "The detected version of Ninja:\n"
+ << " " << this->NinjaVersion << "\n"
+ << "is less than the version of Ninja required by CMake for adding "
+ "restat dependencies to the build.ninja manifest regeneration "
+ "target:\n"
+ << " " << this->RequiredNinjaVersionForManifestRestat() << "\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());
+ }
+
+ std::sort(implicitDeps.begin(), implicitDeps.end());
+ implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()),
+ implicitDeps.end());
+
std::string const ninjaBuildFile = this->NinjaOutputPath(NINJA_BUILD_FILE);
this->WriteBuild(os, "Re-run CMake if any of its inputs changed.",
"RERUN_CMAKE",
/*outputs=*/cmNinjaDeps(1, ninjaBuildFile),
- /*implicitOuts=*/cmNinjaDeps(),
- /*explicitDeps=*/cmNinjaDeps(), implicitDeps,
+ /*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps,
/*orderOnlyDeps=*/cmNinjaDeps(), variables);
+ cmNinjaDeps missingInputs;
+ std::set_difference(std::make_move_iterator(implicitDeps.begin()),
+ std::make_move_iterator(implicitDeps.end()),
+ CustomCommandOutputs.begin(), CustomCommandOutputs.end(),
+ std::back_inserter(missingInputs));
+
this->WritePhonyBuild(os, "A missing CMake input file is not an error.",
- implicitDeps, cmNinjaDeps());
+ missingInputs, cmNinjaDeps());
}
std::string cmGlobalNinjaGenerator::ninjaCmd() const
return this->NinjaSupportsImplicitOuts;
}
+bool cmGlobalNinjaGenerator::SupportsManifestRestat() const
+{
+ return this->NinjaSupportsManifestRestat;
+}
+
void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
{
WriteRule(*this->RulesFileStream, "CLEAN", ninjaCmd() + " -t clean",
Json::Value tm = Json::objectValue;
for (cmFortranObjectInfo const& object : objects) {
for (std::string const& p : object.Provides) {
- std::string const mod = module_dir + p + ".mod";
+ std::string const mod = module_dir + p;
mod_files[p] = mod;
tm[p] = mod;
}
static void WriteDivider(std::ostream& os);
static std::string EncodeRuleName(std::string const& name);
- static std::string EncodeIdent(const std::string& ident, std::ostream& vars);
static std::string EncodeLiteral(const std::string& lit);
std::string EncodePath(const std::string& path);
const std::string& projectName,
const std::string& projectDir,
const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
+ const std::string& config, bool fast, int jobs,
+ bool verbose,
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
static std::string RequiredNinjaVersion() { return "1.3"; }
static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; }
static std::string RequiredNinjaVersionForImplicitOuts() { return "1.7"; }
+ static std::string RequiredNinjaVersionForManifestRestat() { return "1.8"; }
bool SupportsConsolePool() const;
bool SupportsImplicitOuts() const;
+ bool SupportsManifestRestat() const;
std::string NinjaOutputPath(std::string const& path) const;
bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
std::string NinjaVersion;
bool NinjaSupportsConsolePool;
bool NinjaSupportsImplicitOuts;
+ bool NinjaSupportsManifestRestat;
unsigned long NinjaSupportsDyndeps;
private:
#include <sstream>
#include <utility>
-#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
lg->WriteMakeRule(makefileStream, "The main recursive preinstall target",
"preinstall", depends, no_commands, true);
+ // Write an empty clean:
+ lg->WriteMakeRule(makefileStream, "The main recursive clean target", "clean",
+ depends, no_commands, true);
+
// Write out the "special" stuff
lg->WriteSpecialTargetsTop(makefileStream);
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
{
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return;
+ }
+
// Open the output file. This should not be copy-if-different
// because the check-build-system step compares the makefile time to
// see if the build system must be regenerated.
lfiles.insert(lfiles.end(), lg->GetMakefile()->GetListFiles().begin(),
lg->GetMakefile()->GetListFiles().end());
}
+
+ cmake* cm = this->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ lfiles.push_back(cm->GetGlobVerifyScript());
+ lfiles.push_back(cm->GetGlobVerifyStamp());
+ }
+
// Sort the list and remove duplicates.
std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
#if !defined(__VMS) // The Compaq STL on VMS crashes, so accept duplicates.
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& /*projectName*/, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& /*config*/, bool fast,
- bool /*verbose*/, std::vector<std::string> const& makeOptions)
+ int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
+ cmMakefile* mf;
+ if (!this->Makefiles.empty()) {
+ mf = this->Makefiles[0];
+ } else {
+ cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot();
+ snapshot.GetDirectory().SetCurrentSource(
+ this->CMakeInstance->GetHomeDirectory());
+ snapshot.GetDirectory().SetCurrentBinary(
+ this->CMakeInstance->GetHomeOutputDirectory());
+ snapshot.SetDefaultDefinitions();
+ mf = new cmMakefile(this, snapshot);
+ }
+
makeCommand.push_back(this->SelectMakeProgram(makeProgram));
- // Since we have full control over the invocation of nmake, let us
- // make it quiet.
- if (cmHasLiteralPrefix(this->GetName(), "NMake Makefiles")) {
- makeCommand.push_back("/NOLOGO");
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back("-j");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back(std::to_string(jobs));
+ }
}
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
if (!targetName.empty()) {
- cmMakefile* mf;
- if (!this->Makefiles.empty()) {
- mf = this->Makefiles[0];
- } else {
- cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot();
- snapshot.GetDirectory().SetCurrentSource(
- this->CMakeInstance->GetHomeDirectory());
- snapshot.GetDirectory().SetCurrentBinary(
- this->CMakeInstance->GetHomeOutputDirectory());
- snapshot.SetDefaultDefinitions();
- mf = new cmMakefile(this, snapshot);
- }
-
std::string tname = targetName;
if (fast) {
tname += "/fast";
conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname);
cmSystemTools::ConvertToOutputSlashes(tname);
makeCommand.push_back(std::move(tname));
- if (this->Makefiles.empty()) {
- delete mf;
- }
+ }
+ if (this->Makefiles.empty()) {
+ delete mf;
}
}
std::vector<std::string> depends;
std::vector<std::string> commands;
- depends.push_back("cmake_check_build_system");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
// write the target convenience rules
for (cmLocalGenerator* localGen : this->LocalGenerators) {
tmp += "Makefile2";
commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), name));
depends.clear();
- depends.push_back("cmake_check_build_system");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name,
depends, commands, true);
// write the directory level rules for this local gen
this->WriteDirectoryRules2(ruleFileStream, lg);
- depends.push_back("cmake_check_build_system");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
// for each target Generate the rule files for each target.
const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
for (cmGeneratorTarget* gtarget : targets) {
int type = gtarget->GetType();
std::string name = gtarget->GetName();
- if (!name.empty() && ((type == cmStateEnums::EXECUTABLE) ||
- (type == cmStateEnums::STATIC_LIBRARY) ||
- (type == cmStateEnums::SHARED_LIBRARY) ||
- (type == cmStateEnums::MODULE_LIBRARY) ||
- (type == cmStateEnums::OBJECT_LIBRARY) ||
- (type == cmStateEnums::UTILITY))) {
+ if (!name.empty() &&
+ ((type == cmStateEnums::EXECUTABLE) ||
+ (type == cmStateEnums::STATIC_LIBRARY) ||
+ (type == cmStateEnums::SHARED_LIBRARY) ||
+ (type == cmStateEnums::MODULE_LIBRARY) ||
+ (type == cmStateEnums::OBJECT_LIBRARY) ||
+ (type == cmStateEnums::UTILITY))) {
std::string makefileName;
// Add a rule to build the target by name.
localName = lg->GetRelativeTargetDirectory(gtarget);
commands.push_back(progCmd.str());
}
depends.clear();
- depends.push_back("cmake_check_build_system");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
localName = lg->GetRelativeTargetDirectory(gtarget);
localName += "/rule";
lg->WriteMakeRule(ruleFileStream,
}
}
-// Build a map that contains a the set of targets used by each local
+// Build a map that contains the set of targets used by each local
// generator directory level.
void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks()
{
std::string path;
std::vector<std::string> no_depends;
std::vector<std::string> commands;
- lg->AppendEcho(commands, "The following are some of the valid targets "
- "for this Makefile:");
+ lg->AppendEcho(commands,
+ "The following are some of the valid targets "
+ "for this Makefile:");
lg->AppendEcho(commands, "... all (the default if no target is provided)");
lg->AppendEcho(commands, "... clean");
- lg->AppendEcho(commands, "... depend");
+ if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ lg->AppendEcho(commands, "... depend");
+ }
// Keep track of targets already listed.
std::set<std::string> emittedTargets;
const std::string& projectName,
const std::string& projectDir,
const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
+ const std::string& config, bool fast, int jobs,
+ bool verbose,
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
}
}
+ if (!this->GeneratorToolsetVersion.empty() &&
+ this->GeneratorToolsetVersion != "Test Toolset Version") {
+ // If a specific minor version of the toolset was requested, verify that it
+ // is compatible to the major version and that is exists on disk.
+ // If not clear the value.
+ std::string version = this->GeneratorToolsetVersion;
+ cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9][0-9]");
+ if (regex.find(version)) {
+ version = "v" + version.erase(2, 1);
+ } else {
+ // Version not recognized. Clear it.
+ version.clear();
+ }
+
+ if (version.find(this->GetPlatformToolsetString()) != 0) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset and version specification\n"
+ " " << this->GetPlatformToolsetString() << ",version=" <<
+ this->GeneratorToolsetVersion << "\n"
+ "contains an invalid version specification."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+
+ // Clear the configured tool-set
+ this->GeneratorToolsetVersion.clear();
+ }
+
+ bool const isDefaultToolset =
+ this->IsDefaultToolset(this->GeneratorToolsetVersion);
+ if (isDefaultToolset) {
+ // If the given version is the default toolset, remove the setting
+ this->GeneratorToolsetVersion.clear();
+ } else {
+ std::string const toolsetPath = this->GetAuxiliaryToolset();
+ if (!toolsetPath.empty() && !cmSystemTools::FileExists(toolsetPath)) {
+
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset and version specification\n"
+ " " << this->GetPlatformToolsetString() << ",version=" <<
+ this->GeneratorToolsetVersion << "\n"
+ "does not seem to be installed at\n" <<
+ " " << toolsetPath;
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+
+ // Clear the configured tool-set
+ this->GeneratorToolsetVersion.clear();
+ }
+ }
+ }
+
if (const char* toolset = this->GetPlatformToolset()) {
mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset);
}
+ if (const char* version = this->GetPlatformToolsetVersion()) {
+ mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VERSION", version);
+ }
if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) {
mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch);
}
this->GeneratorToolsetCuda = value;
return true;
}
+ if (key == "version") {
+ this->GeneratorToolsetVersion = value;
+ return true;
+ }
return false;
}
return empty;
}
+const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetVersion() const
+{
+ std::string const& version = this->GetPlatformToolsetVersionString();
+ if (version.empty()) {
+ return nullptr;
+ }
+ return version.c_str();
+}
+
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetVersionString() const
+{
+ if (!this->GeneratorToolsetVersion.empty()) {
+ return this->GeneratorToolsetVersion;
+ }
+ static std::string const empty;
+ return empty;
+}
+
const char*
cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const
{
return this->GeneratorToolsetCuda;
}
+bool cmGlobalVisualStudio10Generator::IsDefaultToolset(
+ const std::string&) const
+{
+ return true;
+}
+
+std::string cmGlobalVisualStudio10Generator::GetAuxiliaryToolset() const
+{
+ return {};
+}
+
bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf)
{
if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) {
cmsys::ofstream fout(vcxprojAbs.c_str());
cmXMLWriter xw(fout);
- /* clang-format off */
- xw.StartDocument();
- xw.StartElement("Project");
- xw.Attribute("DefaultTargets", "Build");
- xw.Attribute("ToolsVersion", "4.0");
- xw.Attribute("xmlns",
- "http://schemas.microsoft.com/developer/msbuild/2003");
- if (this->IsNsightTegra()) {
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "NsightTegraProject");
- xw.StartElement("NsightTegraProjectRevisionNumber");
- xw.Content("6");
- xw.EndElement(); // NsightTegraProjectRevisionNumber
- xw.EndElement(); // PropertyGroup
- }
- xw.StartElement("ItemGroup");
- xw.Attribute("Label", "ProjectConfigurations");
- xw.StartElement("ProjectConfiguration");
- xw.Attribute("Include", "Debug|" + this->GetPlatformName());
- xw.StartElement("Configuration");
- xw.Content("Debug");
- xw.EndElement(); // Configuration
- xw.StartElement("Platform");
- xw.Content(this->GetPlatformName());
- xw.EndElement(); // Platform
- xw.EndElement(); // ProjectConfiguration
- xw.EndElement(); // ItemGroup
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "Globals");
- xw.StartElement("ProjectGuid");
- xw.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
- xw.EndElement(); // ProjectGuid
- xw.StartElement("Keyword");
- xw.Content("Win32Proj");
- xw.EndElement(); // Keyword
- xw.StartElement("Platform");
- xw.Content(this->GetPlatformName());
- xw.EndElement(); // Platform
- if (this->GetSystemName() == "WindowsPhone") {
- xw.StartElement("ApplicationType");
- xw.Content("Windows Phone");
- xw.EndElement(); // ApplicationType
- xw.StartElement("ApplicationTypeRevision");
- xw.Content(this->GetSystemVersion());
- xw.EndElement(); // ApplicationTypeRevision
- } else if (this->GetSystemName() == "WindowsStore") {
- xw.StartElement("ApplicationType");
- xw.Content("Windows Store");
- xw.EndElement(); // ApplicationType
- xw.StartElement("ApplicationTypeRevision");
- xw.Content(this->GetSystemVersion());
- xw.EndElement(); // ApplicationTypeRevision
- }
- if (!this->WindowsTargetPlatformVersion.empty()) {
- xw.StartElement("WindowsTargetPlatformVersion");
- xw.Content(this->WindowsTargetPlatformVersion);
- xw.EndElement(); // WindowsTargetPlatformVersion
- }
- if (this->GetPlatformName() == "ARM64") {
- xw.StartElement("WindowsSDKDesktopARM64Support");
- xw.Content("true");
- xw.EndElement(); // WindowsSDK64DesktopARMSupport
- }
- else if (this->GetPlatformName() == "ARM") {
- xw.StartElement("WindowsSDKDesktopARMSupport");
- xw.Content("true");
- xw.EndElement(); // WindowsSDKDesktopARMSupport
- }
- xw.EndElement(); // PropertyGroup
- xw.StartElement("Import");
- xw.Attribute("Project",
- "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
- xw.EndElement(); // Import
+ cmXMLDocument doc(xw);
+ cmXMLElement eprj(doc, "Project");
+ eprj.Attribute("DefaultTargets", "Build");
+ eprj.Attribute("ToolsVersion", "4.0");
+ eprj.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
+ if (this->IsNsightTegra()) {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "NsightTegraProject");
+ cmXMLElement(epg, "NsightTegraProjectRevisionNumber").Content("6");
+ }
+ {
+ cmXMLElement eig(eprj, "ItemGroup");
+ eig.Attribute("Label", "ProjectConfigurations");
+ cmXMLElement epc(eig, "ProjectConfiguration");
+ epc.Attribute("Include", "Debug|" + this->GetPlatformName());
+ cmXMLElement(epc, "Configuration").Content("Debug");
+ cmXMLElement(epc, "Platform").Content(this->GetPlatformName());
+ }
+ {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "Globals");
+ cmXMLElement(epg, "ProjectGuid")
+ .Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
+ cmXMLElement(epg, "Keyword").Content("Win32Proj");
+ cmXMLElement(epg, "Platform").Content(this->GetPlatformName());
+ if (this->GetSystemName() == "WindowsPhone") {
+ cmXMLElement(epg, "ApplicationType").Content("Windows Phone");
+ cmXMLElement(epg, "ApplicationTypeRevision")
+ .Content(this->GetSystemVersion());
+ } else if (this->GetSystemName() == "WindowsStore") {
+ cmXMLElement(epg, "ApplicationType").Content("Windows Store");
+ cmXMLElement(epg, "ApplicationTypeRevision")
+ .Content(this->GetSystemVersion());
+ }
+ if (!this->WindowsTargetPlatformVersion.empty()) {
+ cmXMLElement(epg, "WindowsTargetPlatformVersion")
+ .Content(this->WindowsTargetPlatformVersion);
+ }
+ if (this->GetPlatformName() == "ARM64") {
+ cmXMLElement(epg, "WindowsSDKDesktopARM64Support").Content("true");
+ } else if (this->GetPlatformName() == "ARM") {
+ cmXMLElement(epg, "WindowsSDKDesktopARMSupport").Content("true");
+ }
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
if (!this->GeneratorToolsetHostArchitecture.empty()) {
- xw.StartElement("PropertyGroup");
- xw.StartElement("PreferredToolArchitecture");
- xw.Content(this->GeneratorToolsetHostArchitecture);
- xw.EndElement(); // PreferredToolArchitecture
- xw.EndElement(); // PropertyGroup
+ cmXMLElement epg(eprj, "PropertyGroup");
+ cmXMLElement(epg, "PreferredToolArchitecture")
+ .Content(this->GeneratorToolsetHostArchitecture);
}
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "Configuration");
- xw.StartElement("ConfigurationType");
+ {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "Configuration");
+ {
+ cmXMLElement ect(epg, "ConfigurationType");
+ if (this->IsNsightTegra()) {
+ // Tegra-Android platform does not understand "Utility".
+ ect.Content("StaticLibrary");
+ } else {
+ ect.Content("Utility");
+ }
+ }
+ cmXMLElement(epg, "CharacterSet").Content("MultiByte");
if (this->IsNsightTegra()) {
- // Tegra-Android platform does not understand "Utility".
- xw.Content("StaticLibrary");
+ cmXMLElement(epg, "NdkToolchainVersion")
+ .Content(this->GetPlatformToolsetString());
} else {
- xw.Content("Utility");
+ cmXMLElement(epg, "PlatformToolset")
+ .Content(this->GetPlatformToolsetString());
}
- xw.EndElement(); // ConfigurationType
- xw.StartElement("CharacterSet");
- xw.Content("MultiByte");
- xw.EndElement(); // CharacterSet
- if (this->IsNsightTegra()) {
- xw.StartElement("NdkToolchainVersion");
- xw.Content(this->GetPlatformToolsetString());
- xw.EndElement(); // NdkToolchainVersion
- } else {
- xw.StartElement("PlatformToolset");
- xw.Content(this->GetPlatformToolsetString());
- xw.EndElement(); // PlatformToolset
- }
- xw.EndElement(); // PropertyGroup
- xw.StartElement("Import");
- xw.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
- xw.EndElement(); // Import
- xw.StartElement("ItemDefinitionGroup");
- xw.StartElement("PostBuildEvent");
- xw.StartElement("Command");
- xw.Content("echo VCTargetsPath=$(VCTargetsPath)");
- xw.EndElement(); // Command
- xw.EndElement(); // PostBuildEvent
- xw.EndElement(); // ItemDefinitionGroup
- xw.StartElement("Import");
- xw.Attribute("Project",
- "$(VCTargetsPath)\\Microsoft.Cpp.targets");
- xw.EndElement(); // Import
- xw.EndElement(); // Project
- xw.EndDocument();
- /* clang-format on */
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
+ {
+ cmXMLElement eidg(eprj, "ItemDefinitionGroup");
+ cmXMLElement epbe(eidg, "PostBuildEvent");
+ cmXMLElement(epbe, "Command")
+ .Content("echo VCTargetsPath=$(VCTargetsPath)");
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
}
std::vector<std::string> cmd;
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& projectDir,
const std::string& targetName, const std::string& config, bool fast,
- bool verbose, std::vector<std::string> const& makeOptions)
+ int jobs, bool verbose, std::vector<std::string> const& makeOptions)
{
// Select the caller- or user-preferred make program, else MSBuild.
std::string makeProgramSelected =
// Use devenv to build solutions containing Intel Fortran projects.
cmGlobalVisualStudio7Generator::GenerateBuildCommand(
makeCommand, makeProgram, projectName, projectDir, targetName, config,
- fast, verbose, makeOptions);
+ fast, jobs, verbose, makeOptions);
return;
}
std::string realTarget = targetName;
// msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug /target:ALL_BUILD
+ // /m
if (realTarget.empty()) {
realTarget = "ALL_BUILD";
}
makeCommand.push_back(configArg);
makeCommand.push_back(std::string("/p:VisualStudioVersion=") +
this->GetIDEVersion());
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back("/m");
+ } else {
+ makeCommand.push_back(std::string("/m:") + std::to_string(jobs));
+ }
+ // Having msbuild.exe and cl.exe using multiple jobs is discouraged
+ makeCommand.push_back("/p:CL_MPCount=1");
+ }
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
}
const std::string& projectName,
const std::string& projectDir,
const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
+ const std::string& config, bool fast, int jobs,
+ bool verbose,
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
const char* GetPlatformToolset() const;
std::string const& GetPlatformToolsetString() const;
+ /** The toolset version. */
+ const char* GetPlatformToolsetVersion() const;
+ std::string const& GetPlatformToolsetVersionString() const;
+
/** The toolset host architecture name (e.g. x64 for 64-bit host tools). */
const char* GetPlatformToolsetHostArchitecture() const;
std::string Encoding() override;
virtual const char* GetToolsVersion() { return "4.0"; }
+ virtual bool IsDefaultToolset(const std::string& version) const;
+ virtual std::string GetAuxiliaryToolset() const;
+
bool FindMakeProgram(cmMakefile* mf) override;
static std::string GetInstalledNsightTegraVersion();
std::string const& GetMSBuildCommand();
std::string GeneratorToolset;
+ std::string GeneratorToolsetVersion;
std::string GeneratorToolsetHostArchitecture;
std::string GeneratorToolsetCuda;
std::string DefaultPlatformToolset;
if (!this->SelectWindowsPhoneToolset(this->DefaultPlatformToolset)) {
std::ostringstream e;
if (this->DefaultPlatformToolset.empty()) {
- e << this->GetName() << " supports Windows Phone '8.0' and '8.1', but "
- "not '"
+ e << this->GetName()
+ << " supports Windows Phone '8.0' and '8.1', but "
+ "not '"
<< this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION.";
} else {
e << "A Windows Phone component with CMake requires both the Windows "
if (!this->SelectWindowsStoreToolset(this->DefaultPlatformToolset)) {
std::ostringstream e;
if (this->DefaultPlatformToolset.empty()) {
- e << this->GetName() << " supports Windows Store '8.0' and '8.1', but "
- "not '"
+ e << this->GetName()
+ << " supports Windows Store '8.0' and '8.1', but "
+ "not '"
<< this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION.";
} else {
e << "A Windows Store component with CMake requires both the Windows "
// from the .Net Framework version and instead made it have it's own
// version number
const char* GetToolsVersion() override { return "12.0"; }
+
protected:
bool ProcessGeneratorToolsetField(std::string const& key,
std::string const& value) override;
bool IsWindowsPhoneToolsetInstalled() const;
bool IsWindowsStoreToolsetInstalled() const;
const char* GetIDEVersion() override { return "12.0"; }
+
private:
class Factory;
};
std::ostringstream e;
if (!this->SelectWindowsStoreToolset(this->DefaultPlatformToolset)) {
if (this->DefaultPlatformToolset.empty()) {
- e << this->GetName() << " supports Windows Store '8.0', '8.1' and "
- "'10.0', but not '"
+ e << this->GetName()
+ << " supports Windows Store '8.0', '8.1' and "
+ "'10.0', but not '"
<< this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION.";
} else {
e << "A Windows Store component with CMake requires both the Windows "
void WriteSLNHeader(std::ostream& fout) override;
const char* GetToolsVersion() override { return "14.0"; }
+
protected:
bool InitializeWindows(cmMakefile* mf) override;
bool InitializeWindowsStore(cmMakefile* mf) override;
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
bool GetVSInstance(std::string& dir) const;
+ bool IsDefaultToolset(const std::string& version) const override;
+ std::string GetAuxiliaryToolset() const override;
+
protected:
bool InitializeWindows(cmMakefile* mf) override;
bool SelectWindowsStoreToolset(std::string& toolset) const override;
ext = ".vfproj";
project = "Project(\"{6989167D-11E4-40FE-8C1A-2192A86A7E90}\") = \"";
}
- if (this->TargetIsCSharpOnly(t)) {
+ if (t->HasLanguage("CSharp", "")) {
ext = ".csproj";
project = "Project(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"";
}
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& config, bool /*fast*/,
- bool /*verbose*/, std::vector<std::string> const& makeOptions)
+ int /*jobs*/, bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
// Select the caller- or user-preferred make program, else devenv.
std::string makeProgramSelected =
if (!cmSystemTools::GetErrorOccuredFlag()) {
this->CallVisualStudioMacro(MacroReload);
}
-
- if (this->Version == VS8 && !this->CMakeInstance->GetIsInTryCompile()) {
- const char* cmakeWarnVS8 =
- this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_WARN_VS8");
- if (!cmakeWarnVS8 || !cmSystemTools::IsOff(cmakeWarnVS8)) {
- this->CMakeInstance->IssueMessage(
- cmake::WARNING,
- "The \"Visual Studio 8 2005\" generator is deprecated "
- "and will be removed in a future version of CMake."
- "\n"
- "Add CMAKE_WARN_VS8=OFF to the cache to disable this warning.");
- }
- }
}
void cmGlobalVisualStudio7Generator::OutputSLNFile(
const std::string& projectName,
const std::string& projectDir,
const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
+ const std::string& config, bool fast, int jobs,
+ bool verbose,
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
#include "cmVisualStudioWCEPlatformParser.h"
#include "cmake.h"
-static const char vs8generatorName[] = "Visual Studio 8 2005";
-
-class cmGlobalVisualStudio8Generator::Factory : public cmGlobalGeneratorFactory
-{
-public:
- cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const override
- {
- if (strncmp(name.c_str(), vs8generatorName,
- sizeof(vs8generatorName) - 1) != 0) {
- return 0;
- }
-
- const char* p = name.c_str() + sizeof(vs8generatorName) - 1;
- if (p[0] == '\0') {
- return new cmGlobalVisualStudio8Generator(cm, name, "");
- }
-
- if (p[0] != ' ') {
- return 0;
- }
-
- ++p;
-
- if (!strcmp(p, "Win64")) {
- return new cmGlobalVisualStudio8Generator(cm, name, "x64");
- }
-
- cmVisualStudioWCEPlatformParser parser(p);
- parser.ParseVersion("8.0");
- if (!parser.Found()) {
- return 0;
- }
-
- cmGlobalVisualStudio8Generator* ret =
- new cmGlobalVisualStudio8Generator(cm, name, p);
- ret->WindowsCEVersion = parser.GetOSVersion();
- return ret;
- }
-
- void GetDocumentation(cmDocumentationEntry& entry) const override
- {
- entry.Name = std::string(vs8generatorName) + " [arch]";
- entry.Brief = "Deprecated. Generates Visual Studio 2005 project files. "
- "Optional [arch] can be \"Win64\".";
- }
-
- void GetGenerators(std::vector<std::string>& names) const override
- {
- names.push_back(vs8generatorName);
- names.push_back(vs8generatorName + std::string(" Win64"));
- cmVisualStudioWCEPlatformParser parser;
- parser.ParseVersion("8.0");
- const std::vector<std::string>& availablePlatforms =
- parser.GetAvailablePlatforms();
- for (std::string const& i : availablePlatforms) {
- names.push_back("Visual Studio 8 2005 " + i);
- }
- }
-
- bool SupportsToolset() const override { return false; }
- bool SupportsPlatform() const override { return true; }
-};
-
-cmGlobalGeneratorFactory* cmGlobalVisualStudio8Generator::NewFactory()
-{
- return new Factory;
-}
-
cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
cmake* cm, const std::string& name, const std::string& platformName)
: cmGlobalVisualStudio71Generator(cm, platformName)
this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms";
this->Name = name;
this->ExtraFlagTable = this->GetExtraFlagTableVS8();
- this->Version = VS8;
- std::string vc8Express;
- this->ExpressEdition = cmSystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\8.0\\Setup\\VC;"
- "ProductDir",
- vc8Express, cmSystemTools::KeyWOW64_32);
}
std::string cmGlobalVisualStudio8Generator::FindDevEnvCommand()
}
}
-// output standard header for dsw file
-void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
-{
- fout << "Microsoft Visual Studio Solution File, Format Version 9.00\n";
- fout << "# Visual Studio 2005\n";
-}
-
std::string cmGlobalVisualStudio8Generator::GetGenerateStampList()
{
return "generate.stamp.list";
return IsExpressEdition() ? false : cmGlobalGenerator::UseFolderProperty();
}
-std::string cmGlobalVisualStudio8Generator::GetUserMacrosDirectory()
-{
- // Some VS8 sp0 versions cannot run macros.
- // See http://support.microsoft.com/kb/928209
- const char* vc8sp1Registry =
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\"
- "InstalledProducts\\KB926601;";
- const char* vc8exSP1Registry =
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\"
- "InstalledProducts\\KB926748;";
- std::string vc8sp1;
- if (!cmSystemTools::ReadRegistryValue(vc8sp1Registry, vc8sp1) &&
- !cmSystemTools::ReadRegistryValue(vc8exSP1Registry, vc8sp1)) {
- return "";
- }
-
- std::string base;
- std::string path;
-
- // base begins with the VisualStudioProjectsLocation reg value...
- if (cmSystemTools::ReadRegistryValue(
- "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\8.0;"
- "VisualStudioProjectsLocation",
- base)) {
- cmSystemTools::ConvertToUnixSlashes(base);
-
- // 8.0 macros folder:
- path = base + "/VSMacros80";
- }
-
- // path is (correctly) still empty if we did not read the base value from
- // the Registry value
- return path;
-}
-
-std::string cmGlobalVisualStudio8Generator::GetUserMacrosRegKeyBase()
-{
- return "Software\\Microsoft\\VisualStudio\\8.0\\vsmacros";
-}
-
bool cmGlobalVisualStudio8Generator::AddCheckTarget()
{
// Add a special target on which all other targets depend that
// checks the build system and optionally re-runs CMake.
- const char* no_working_directory = 0;
+ // Skip the target if no regeneration is to be done.
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return false;
+ }
+
+ const char* no_working_directory = nullptr;
std::vector<std::string> no_depends;
std::vector<cmLocalGenerator*> const& generators = this->LocalGenerators;
cmLocalVisualStudio7Generator* lg =
static_cast<cmLocalVisualStudio7Generator*>(generators[0]);
cmMakefile* mf = lg->GetMakefile();
- // Skip the target if no regeneration is to be done.
- if (mf->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
- return false;
- }
-
cmCustomCommandLines noCommandLines;
cmTarget* tgt = mf->AddUtilityCommand(
CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator,
listFiles.insert(listFiles.end(), lmf->GetListFiles().begin(),
lmf->GetListFiles().end());
}
+
+ // Add a custom prebuild target to run the VerifyGlobs script.
+ cmake* cm = this->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ cmCustomCommandLine verifyCommandLine;
+ verifyCommandLine.push_back(cmSystemTools::GetCMakeCommand());
+ verifyCommandLine.push_back("-P");
+ verifyCommandLine.push_back(cm->GetGlobVerifyScript());
+ cmCustomCommandLines verifyCommandLines;
+ verifyCommandLines.push_back(verifyCommandLine);
+ std::vector<std::string> byproducts;
+ byproducts.push_back(cm->GetGlobVerifyStamp());
+
+ mf->AddCustomCommandToTarget(CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts,
+ no_depends, verifyCommandLines,
+ cmTarget::PRE_BUILD, "Checking File Globs",
+ no_working_directory, false);
+
+ // Ensure ZERO_CHECK always runs in Visual Studio using MSBuild,
+ // otherwise the prebuild command will not be run.
+ tgt->SetProperty("VS_GLOBAL_DisableFastUpToDateCheck", "true");
+ listFiles.push_back(cm->GetGlobVerifyStamp());
+ }
+
// Sort the list of input files and remove duplicates.
std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>());
std::vector<std::string>::iterator new_end =
listFiles.erase(new_end, listFiles.end());
// Create a rule to re-run CMake.
- std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash();
- stampName += "generate.stamp";
cmCustomCommandLine commandLine;
commandLine.push_back(cmSystemTools::GetCMakeCommand());
std::string argH = "-H";
public:
cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name,
const std::string& platformName);
- static cmGlobalGeneratorFactory* NewFactory();
///! Get the name for the generator.
std::string GetName() const override { return this->Name; }
*/
void Configure() override;
- /**
- * Where does this version of Visual Studio look for macros for the
- * current user? Returns the empty string if this version of Visual
- * Studio does not implement support for VB macros.
- */
- std::string GetUserMacrosDirectory() override;
-
- /**
- * What is the reg key path to "vsmacros" for this version of Visual
- * Studio?
- */
- std::string GetUserMacrosRegKeyBase() override;
-
/** Return true if the target project file should have the option
LinkLibraryDependencies and link to .sln dependencies. */
bool NeedLinkLibraryDependencies(cmGeneratorTarget* target) override;
virtual bool NeedsDeploy(cmStateEnums::TargetType type) const;
static cmIDEFlagTable const* GetExtraFlagTableVS8();
- void WriteSLNHeader(std::ostream& fout) override;
void WriteSolutionConfigurations(
std::ostream& fout, std::vector<std::string> const& configs) override;
void WriteProjectConfigurations(
std::string Name;
std::string WindowsCEVersion;
bool ExpressEdition;
-
-private:
- class Factory;
- friend class Factory;
};
#endif
protected:
const char* GetIDEVersion() override { return "9.0"; }
+
private:
class Factory;
friend class Factory;
lastWriteTime.dwHighDateTime = 0;
lastWriteTime.dwLowDateTime = 0;
- while (ERROR_SUCCESS == RegEnumKeyExW(hkey, index, subkeyname,
- &cch_subkeyname, 0, keyclass,
- &cch_keyclass, &lastWriteTime)) {
+ while (ERROR_SUCCESS ==
+ RegEnumKeyExW(hkey, index, subkeyname, &cch_subkeyname, 0, keyclass,
+ &cch_keyclass, &lastWriteTime)) {
// Open the subkey and query the values of interest:
HKEY hsubkey = NULL;
result = RegOpenKeyExW(hkey, subkeyname, 0, KEY_READ, &hsubkey);
return false;
}
-bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(
- cmGeneratorTarget const* gt)
-{
- // check to see if this is a C# build
- std::set<std::string> languages;
- {
- // Issue diagnostic if the source files depend on the config.
- std::vector<cmSourceFile*> sources;
- if (!gt->GetConfigCommonSourceFiles(sources)) {
- return false;
- }
- // Only "real" targets are allowed to be C# targets.
- if (gt->Target->GetType() > cmStateEnums::OBJECT_LIBRARY) {
- return false;
- }
- }
- gt->GetLanguages(languages, "");
- if (languages.size() == 1) {
- if (*languages.begin() == "CSharp") {
- return true;
- }
- }
- return false;
-}
-
-bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced(
- cmGeneratorTarget const* gt)
-{
- if (this->TargetIsCSharpOnly(gt)) {
- return true;
- }
- if (gt->GetType() != cmStateEnums::SHARED_LIBRARY &&
- gt->GetType() != cmStateEnums::EXECUTABLE) {
- return false;
- }
- return true;
-}
-
bool cmGlobalVisualStudioGenerator::TargetCompare::operator()(
cmGeneratorTarget const* l, cmGeneratorTarget const* r) const
{
/** Known versions of Visual Studio. */
enum VSVersion
{
- VS8 = 80,
VS9 = 90,
VS10 = 100,
VS11 = 110,
// return true if target is fortran only
bool TargetIsFortranOnly(const cmGeneratorTarget* gt);
- // return true if target is C# only
- static bool TargetIsCSharpOnly(cmGeneratorTarget const* gt);
-
- // return true if target can be referenced by C# targets
- bool TargetCanBeReferenced(cmGeneratorTarget const* gt);
-
/** Get the top-level registry key for this VS version. */
std::string GetRegistryBase();
#include "cmState.h"
#include "cmake.h"
+#include <ostream>
+
cmGlobalWatcomWMakeGenerator::cmGlobalWatcomWMakeGenerator(cmake* cm)
: cmGlobalUnixMakefileGenerator3(cm)
{
entry.Name = cmGlobalWatcomWMakeGenerator::GetActualName();
entry.Brief = "Generates Watcom WMake makefiles.";
}
+
+void cmGlobalWatcomWMakeGenerator::GenerateBuildCommand(
+ std::vector<std::string>& makeCommand, const std::string& makeProgram,
+ 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)
+{
+ this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeCommand, makeProgram, projectName, projectDir, targetName, config,
+ fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+}
+
+void cmGlobalWatcomWMakeGenerator::PrintBuildCommandAdvice(std::ostream& os,
+ int jobs) const
+{
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ // wmake does not support parallel build level
+
+ /* clang-format off */
+ os <<
+ "Warning: Watcom's WMake does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
+ /* clang-format on */
+ }
+
+ this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
+ os, cmake::NO_BUILD_PARALLEL_LEVEL);
+}
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include <iosfwd>
#include <string>
#include <vector>
bool AllowNotParallel() const override { return false; }
bool AllowDeleteOnError() const override { return false; }
+
+protected:
+ void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+ const std::string& makeProgram,
+ 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 =
+ std::vector<std::string>()) override;
+
+ void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
};
#endif
struct cmLinkImplementation;
#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(__APPLE__)
-#define HAVE_APPLICATION_SERVICES
-#include <ApplicationServices/ApplicationServices.h>
+# define HAVE_APPLICATION_SERVICES
+# include <ApplicationServices/ApplicationServices.h>
#endif
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmXMLParser.h"
+# include "cmXMLParser.h"
// parse the xml file storing the installed version of Xcode on
// the machine
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& /*projectDir*/,
const std::string& targetName, const std::string& config, bool /*fast*/,
- bool /*verbose*/, std::vector<std::string> const& makeOptions)
+ int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
// now build the test
makeCommand.push_back(
}
makeCommand.push_back("-configuration");
makeCommand.push_back(!config.empty() ? config : "Debug");
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back("-jobs");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.push_back(std::to_string(jobs));
+ }
+ }
+
makeCommand.insert(makeCommand.end(), makeOptions.begin(),
makeOptions.end());
}
makeHelper.push_back(""); // placeholder, see below
// Add ZERO_CHECK
- bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
bool generateTopLevelProjectOnly =
mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
bool isTopLevel =
if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) {
this->CreateReRunCMakeFile(root, gens);
std::string file =
- this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str());
+ this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile);
cmSystemTools::ReplaceString(file, "\\ ", " ");
cmTarget* check = mf->AddUtilityCommand(
CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator,
std::vector<std::string>::iterator new_end =
std::unique(lfiles.begin(), lfiles.end());
lfiles.erase(new_end, lfiles.end());
+
+ cmake* cm = this->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ lfiles.emplace_back(cm->GetGlobVerifyStamp());
+ }
+
this->CurrentReRunCMakeMakefile = root->GetCurrentBinaryDirectory();
this->CurrentReRunCMakeMakefile += "/CMakeScripts";
cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile.c_str());
for (const auto& lfile : lfiles) {
makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard "
- << this->ConvertToRelativeForMake(lfile.c_str()) << "))\n";
+ << this->ConvertToRelativeForMake(lfile) << "))\n";
}
+ makefileStream << "\n";
std::string checkCache = root->GetBinaryDirectory();
checkCache += "/";
checkCache += cmake::GetCMakeFilesDirectoryPostSlash();
checkCache += "cmake.check_cache";
- makefileStream << "\n"
- << this->ConvertToRelativeForMake(checkCache.c_str())
+ if (cm->DoWriteGlobVerifyTarget()) {
+ makefileStream << ".NOTPARALLEL:\n\n";
+ makefileStream << ".PHONY: all VERIFY_GLOBS\n\n";
+ makefileStream << "all: VERIFY_GLOBS "
+ << this->ConvertToRelativeForMake(checkCache) << "\n\n";
+ makefileStream << "VERIFY_GLOBS:\n";
+ makefileStream << "\t"
+ << this->ConvertToRelativeForMake(
+ cmSystemTools::GetCMakeCommand())
+ << " -P "
+ << this->ConvertToRelativeForMake(cm->GetGlobVerifyScript())
+ << "\n\n";
+ }
+
+ makefileStream << this->ConvertToRelativeForMake(checkCache)
<< ": $(TARGETS)\n";
makefileStream << "\t"
<< this->ConvertToRelativeForMake(
- cmSystemTools::GetCMakeCommand().c_str())
+ cmSystemTools::GetCMakeCommand())
<< " -H"
<< this->ConvertToRelativeForMake(root->GetSourceDirectory())
<< " -B"
}
std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
- cdir = this->ConvertToRelativeForMake(cdir.c_str());
+ cdir = this->ConvertToRelativeForMake(cdir);
std::string makecmd = "make -C ";
makecmd += cdir;
makecmd += " -f ";
- makecmd +=
- this->ConvertToRelativeForMake((makefile + "$CONFIGURATION").c_str());
+ makecmd += this->ConvertToRelativeForMake((makefile + "$CONFIGURATION"));
makecmd += " all";
buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
const std::vector<std::string>& outputs = ccg.GetOutputs();
if (!outputs.empty()) {
for (auto const& output : outputs) {
- makefileStream << "\\\n\t"
- << this->ConvertToRelativeForMake(output.c_str());
+ makefileStream << "\\\n\t" << this->ConvertToRelativeForMake(output);
}
} else {
std::ostringstream str;
// There is at least one output, start the rule for it
const char* sep = "";
for (auto const& output : outputs) {
- makefileStream << sep
- << this->ConvertToRelativeForMake(output.c_str());
+ makefileStream << sep << this->ConvertToRelativeForMake(output);
sep = " ";
}
makefileStream << ": ";
std::string dep;
if (this->CurrentLocalGenerator->GetRealDependency(d, configName,
dep)) {
- makefileStream << "\\\n"
- << this->ConvertToRelativeForMake(dep.c_str());
+ makefileStream << "\\\n" << this->ConvertToRelativeForMake(dep);
}
}
makefileStream << "\n";
// Build the command line in a single string.
std::string cmd2 = ccg.GetCommand(c);
cmSystemTools::ReplaceString(cmd2, "/./", "/");
- cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
+ cmd2 = this->ConvertToRelativeForMake(cmd2);
std::string cmd;
std::string wd = ccg.GetWorkingDirectory();
if (!wd.empty()) {
cmd += "cd ";
- cmd += this->ConvertToRelativeForMake(wd.c_str());
+ cmd += this->ConvertToRelativeForMake(wd);
cmd += " && ";
}
cmd += cmd2;
if (this->Architectures.empty()) {
// With no ARCHS we use ONLY_ACTIVE_ARCH.
// Look up the arch that Xcode chooses in this case.
- if (const char* arch = mf->GetDefinition("CMAKE_XCODE_CURRENT_ARCH")) {
+ if (const char* arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) {
this->ObjectDirArchDefault = arch;
+ // We expect only one arch but choose the first just in case.
+ std::string::size_type pos = this->ObjectDirArchDefault.find(';');
+ if (pos != std::string::npos) {
+ this->ObjectDirArchDefault = this->ObjectDirArchDefault.substr(0, pos);
+ }
}
}
gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
std::string tfull = gt->GetFullPath(configName);
- std::string trel = this->ConvertToRelativeForMake(tfull.c_str());
+ std::string trel = this->ConvertToRelativeForMake(tfull);
// Add this target to the post-build phases of its dependencies.
std::map<std::string, cmXCodeObject::StringVec>::const_iterator y =
target->GetDependLibraries().find(configName);
if (x != target->GetDependLibraries().end()) {
for (auto const& deplib : x->second) {
- std::string file = this->ConvertToRelativeForMake(deplib.c_str());
+ std::string file = this->ConvertToRelativeForMake(deplib);
makefileStream << "\\\n\t" << file;
dummyRules.insert(file);
}
d += objLibName;
d += ".a";
- std::string dependency = this->ConvertToRelativeForMake(d.c_str());
+ std::string dependency = this->ConvertToRelativeForMake(d);
makefileStream << "\\\n\t" << dependency;
dummyRules.insert(dependency);
}
// Write the action to remove the target if it is out of date.
makefileStream << "\n";
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(tfull.c_str())
- << "\n";
+ << this->ConvertToRelativeForMake(tfull) << "\n";
// if building for more than one architecture
// then remove those executables as well
if (this->Architectures.size() > 1) {
universalFile += "/";
universalFile += gt->GetFullName(configName);
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(
- universalFile.c_str())
+ << this->ConvertToRelativeForMake(universalFile)
<< "\n";
}
}
}
this->WriteXCodePBXProj(fout, root, generators);
- // Since the lowest available Xcode version for testing was 6.4,
- // I'm setting this as a limit then
- if (this->XcodeVersion >= 64) {
- if (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() ||
- root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")) {
- this->OutputXCodeSharedSchemes(xcodeDir);
- this->OutputXCodeWorkspaceSettings(xcodeDir);
- }
+ if (this->IsGeneratingScheme(root)) {
+ this->OutputXCodeSharedSchemes(xcodeDir);
}
+ this->OutputXCodeWorkspaceSettings(xcodeDir, root);
this->ClearXCodeObjects();
root->GetBinaryDirectory());
}
+bool cmGlobalXCodeGenerator::IsGeneratingScheme(cmLocalGenerator* root) const
+{
+ // Since the lowest available Xcode version for testing was 6.4,
+ // I'm setting this as a limit then
+ return this->XcodeVersion >= 64 &&
+ (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() ||
+ root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME"));
+}
+
void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
const std::string& xcProjDir)
{
}
void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings(
- const std::string& xcProjDir)
+ const std::string& xcProjDir, cmLocalGenerator* root)
{
std::string xcodeSharedDataDir = xcProjDir;
xcodeSharedDataDir += "/project.xcworkspace/xcshareddata";
xout.StartElement("plist");
xout.Attribute("version", "1.0");
xout.StartElement("dict");
- xout.Element("key", "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded");
- xout.Element("false");
+ if (this->XcodeVersion >= 100) {
+ xout.Element("key", "BuildSystemType");
+ xout.Element("string", "Original");
+ }
+ if (this->IsGeneratingScheme(root)) {
+ xout.Element("key",
+ "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded");
+ xout.Element("false");
+ }
xout.EndElement(); // dict
xout.EndElement(); // plist
xout.EndDocument();
const std::string& projectName,
const std::string& projectDir,
const std::string& targetName,
- const std::string& config, bool fast, bool verbose,
+ const std::string& config, bool fast, int jobs,
+ bool verbose,
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
std::vector<cmLocalGenerator*>& generators);
void OutputXCodeProject(cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
+ bool IsGeneratingScheme(cmLocalGenerator* root) const;
// Write shared scheme files for all the native targets
void OutputXCodeSharedSchemes(const std::string& xcProjDir);
- void OutputXCodeWorkspaceSettings(const std::string& xcProjDir);
+ void OutputXCodeWorkspaceSettings(const std::string& xcProjDir,
+ cmLocalGenerator* root);
void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath,
operator int() const { return this->Dest; }
bool IsStrong() const { return this->Strong; }
+
private:
int Dest;
bool Strong;
{
}
-void cmIDEOptions::HandleFlag(const char* flag)
+void cmIDEOptions::HandleFlag(std::string const& flag)
{
// If the last option was -D then this option is the definition.
if (this->DoingDefine) {
}
// Look for known arguments.
- if (flag[0] == '-' || (this->AllowSlash && flag[0] == '/')) {
+ size_t len = flag.length();
+ if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) {
// Look for preprocessor definitions.
- if (this->AllowDefine && flag[1] == 'D') {
- if (flag[2] == '\0') {
+ if (this->AllowDefine && len > 1 && flag[1] == 'D') {
+ if (len <= 2) {
// The next argument will have the definition.
this->DoingDefine = true;
} else {
// Store this definition.
- this->Defines.push_back(flag + 2);
+ this->Defines.push_back(flag.substr(2));
}
return;
}
// Look for include directory.
- if (this->AllowInclude && flag[1] == 'I') {
- if (flag[2] == '\0') {
+ if (this->AllowInclude && len > 1 && flag[1] == 'I') {
+ if (len <= 2) {
// The next argument will have the include directory.
this->DoingInclude = true;
} else {
// Store this include directory.
- this->Includes.push_back(flag + 2);
+ this->Includes.push_back(flag.substr(2));
}
return;
}
}
bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
- const char* flag, bool& flag_handled)
+ std::string const& flag, bool& flag_handled)
{
+ const char* pf = flag.c_str() + 1;
// Look for an entry in the flag table matching this flag.
for (cmIDEFlagTable const* entry = table; entry->IDEName; ++entry) {
bool entry_found = false;
// the entry specifies UserRequired we must match only if a
// non-empty value is given.
int n = static_cast<int>(strlen(entry->commandFlag));
- if ((strncmp(flag + 1, entry->commandFlag, n) == 0 ||
+ if ((strncmp(pf, entry->commandFlag, n) == 0 ||
(entry->special & cmIDEFlagTable::CaseInsensitive &&
- cmsysString_strncasecmp(flag + 1, entry->commandFlag, n))) &&
+ cmsysString_strncasecmp(pf, entry->commandFlag, n))) &&
(!(entry->special & cmIDEFlagTable::UserRequired) ||
- static_cast<int>(strlen(flag + 1)) > n)) {
- this->FlagMapUpdate(entry, flag + n + 1);
+ static_cast<int>(strlen(pf)) > n)) {
+ this->FlagMapUpdate(entry, std::string(pf + n));
entry_found = true;
}
- } else if (strcmp(flag + 1, entry->commandFlag) == 0 ||
+ } else if (strcmp(pf, entry->commandFlag) == 0 ||
(entry->special & cmIDEFlagTable::CaseInsensitive &&
- cmsysString_strcasecmp(flag + 1, entry->commandFlag) == 0)) {
+ cmsysString_strcasecmp(pf, entry->commandFlag) == 0)) {
if (entry->special & cmIDEFlagTable::UserFollowing) {
// This flag expects a value in the following argument.
this->DoingFollowing = entry;
}
void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
- const char* new_value)
+ std::string const& new_value)
{
if (entry->special & cmIDEFlagTable::UserIgnored) {
// Ignore the user-specified value.
this->Defines.push_back(def);
}
-void cmIDEOptions::AddDefines(const char* defines)
+void cmIDEOptions::AddDefines(std::string const& defines)
{
- if (defines) {
+ if (!defines.empty()) {
// Expand the list of definitions.
cmSystemTools::ExpandListArgument(defines, this->Defines);
}
this->Includes.push_back(include);
}
-void cmIDEOptions::AddIncludes(const char* includes)
+void cmIDEOptions::AddIncludes(std::string const& includes)
{
- if (includes) {
+ if (!includes.empty()) {
// Expand the list of includes.
cmSystemTools::ExpandListArgument(includes, this->Includes);
}
// Store definitions, includes and flags.
void AddDefine(const std::string& define);
- void AddDefines(const char* defines);
+ void AddDefines(std::string const& defines);
void AddDefines(const std::vector<std::string>& defines);
std::vector<std::string> const& GetDefines() const;
void AddInclude(const std::string& includes);
- void AddIncludes(const char* includes);
+ void AddIncludes(std::string const& includes);
void AddIncludes(const std::vector<std::string>& includes);
std::vector<std::string> const& GetIncludes() const;
FlagTableCount = 16
};
cmIDEFlagTable const* FlagTable[FlagTableCount];
- void HandleFlag(const char* flag);
- bool CheckFlagTable(cmIDEFlagTable const* table, const char* flag,
+ void HandleFlag(std::string const& flag);
+ bool CheckFlagTable(cmIDEFlagTable const* table, std::string const& flag,
bool& flag_handled);
- void FlagMapUpdate(cmIDEFlagTable const* entry, const char* new_value);
- virtual void StoreUnknownFlag(const char* flag) = 0;
+ void FlagMapUpdate(cmIDEFlagTable const* entry,
+ std::string const& new_value);
+ virtual void StoreUnknownFlag(std::string const& flag) = 0;
};
#endif
cmExecutionStatus& inStatus)
{
// we start by recording all the functions
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "if")) {
+ if (lff.Name.Lower == "if") {
this->ScopeDepth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endif")) {
+ } else if (lff.Name.Lower == "endif") {
this->ScopeDepth--;
// if this is the endif for this if statement, then start executing
if (!this->ScopeDepth) {
int scopeDepth = 0;
for (cmListFileFunction const& func : this->Functions) {
// keep track of scope depth
- if (!cmSystemTools::Strucmp(func.Name.c_str(), "if")) {
+ if (func.Name.Lower == "if") {
scopeDepth++;
}
- if (!cmSystemTools::Strucmp(func.Name.c_str(), "endif")) {
+ if (func.Name.Lower == "endif") {
scopeDepth--;
}
// watch for our state change
- if (scopeDepth == 0 &&
- !cmSystemTools::Strucmp(func.Name.c_str(), "else")) {
+ if (scopeDepth == 0 && func.Name.Lower == "else") {
if (this->ElseSeen) {
cmListFileBacktrace bt = mf.GetBacktrace(func);
if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) {
mf.PrintCommandTrace(func);
}
- } else if (scopeDepth == 0 &&
- !cmSystemTools::Strucmp(func.Name.c_str(), "elseif")) {
+ } else if (scopeDepth == 0 && func.Name.Lower == "elseif") {
if (this->ElseSeen) {
cmListFileBacktrace bt = mf.GetBacktrace(func);
mf.GetCMakeInstance()->IssueMessage(
bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endif")) {
+ if (lff.Name.Lower == "endif") {
// if the endif has arguments, then make sure
// they match the arguments of the matching if
if (lff.Arguments.empty() || lff.Arguments == this->Args) {
messageType = cmake::FATAL_ERROR;
}
if (modal) {
- e << "The file\n " << fname_abs << "\nwas generated by the export() "
- "command. It "
+ e << "The file\n " << fname_abs
+ << "\nwas generated by the export() "
+ "command. It "
<< modal
<< " not be used as the argument to the "
"include() command. Use ALIAS targets instead to refer to targets "
#include "cmIncludeExternalMSProjectCommand.h"
#ifdef _WIN32
-#include "cmGlobalGenerator.h"
-#include "cmMakefile.h"
-#include "cmStateTypes.h"
-#include "cmSystemTools.h"
-#include "cmTarget.h"
+# include "cmGlobalGenerator.h"
+# include "cmMakefile.h"
+# include "cmStateTypes.h"
+# include "cmSystemTools.h"
+# include "cmTarget.h"
#endif
class cmExecutionStatus;
#include "cmsys/Glob.hxx"
#include <sstream>
#include <stddef.h>
+#include <string.h>
#include <utility>
#include "cmAlgorithms.h"
static cmInstallTargetGenerator* CreateInstallTargetGenerator(
cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
- bool forceOpt = false)
+ bool forceOpt = false, bool namelink = false)
{
cmInstallGenerator::MessageLevel message =
cmInstallGenerator::SelectMessageLevel(target.GetMakefile());
target.SetHaveInstallRule(true);
+ const char* component = namelink ? args.GetNamelinkComponent().c_str()
+ : args.GetComponent().c_str();
return new cmInstallTargetGenerator(
target.GetName(), args.GetDestination().c_str(), impLib,
- args.GetPermissions().c_str(), args.GetConfigurations(),
- args.GetComponent().c_str(), message, args.GetExcludeFromAll(),
- args.GetOptional() || forceOpt);
+ args.GetPermissions().c_str(), args.GetConfigurations(), component,
+ message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt);
}
static cmInstallFilesGenerator* CreateInstallFilesGenerator(
"The NAMELINK_SKIP option may be specified only following LIBRARY.");
return false;
}
+ if (archiveArgs.HasNamelinkComponent() ||
+ runtimeArgs.HasNamelinkComponent() ||
+ objectArgs.HasNamelinkComponent() ||
+ frameworkArgs.HasNamelinkComponent() ||
+ bundleArgs.HasNamelinkComponent() ||
+ privateHeaderArgs.HasNamelinkComponent() ||
+ publicHeaderArgs.HasNamelinkComponent() ||
+ resourceArgs.HasNamelinkComponent()) {
+ this->SetError(
+ "TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
+ "The NAMELINK_COMPONENT option may be specified only following "
+ "LIBRARY.");
+ return false;
+ }
if (libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip()) {
this->SetError("TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
"At most one of these two options may be specified.");
// Check whether this is a DLL platform.
bool dll_platform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ "") != 0;
for (std::string const& tgt : targetList.GetVector()) {
this->SetError(e.str());
return false;
}
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string reason;
- if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
- &reason)) {
- std::ostringstream e;
- e << "TARGETS given OBJECT library \"" << tgt
- << "\" which may not be installed" << reason << ".";
- this->SetError(e.str());
- return false;
- }
- }
// Store the target in the list to be installed.
targets.push_back(target);
} else {
// any files of the given type.
bool installsArchive = false;
bool installsLibrary = false;
+ bool installsNamelink = false;
bool installsRuntime = false;
bool installsObject = false;
bool installsFramework = false;
cmTarget& target = *ti;
cmInstallTargetGenerator* archiveGenerator = nullptr;
cmInstallTargetGenerator* libraryGenerator = nullptr;
+ cmInstallTargetGenerator* namelinkGenerator = nullptr;
cmInstallTargetGenerator* runtimeGenerator = nullptr;
cmInstallTargetGenerator* objectGenerator = nullptr;
cmInstallTargetGenerator* frameworkGenerator = nullptr;
} else {
// The shared library uses the LIBRARY properties.
if (!libraryArgs.GetDestination().empty()) {
- libraryGenerator =
- CreateInstallTargetGenerator(target, libraryArgs, false);
- libraryGenerator->SetNamelinkMode(namelinkMode);
+ if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
+ libraryGenerator =
+ CreateInstallTargetGenerator(target, libraryArgs, false);
+ libraryGenerator->SetNamelinkMode(
+ cmInstallTargetGenerator::NamelinkModeSkip);
+ }
+ if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
+ namelinkGenerator = CreateInstallTargetGenerator(
+ target, libraryArgs, false, false, true);
+ namelinkGenerator->SetNamelinkMode(
+ cmInstallTargetGenerator::NamelinkModeOnly);
+ }
namelinkOnly =
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
} else {
case cmStateEnums::OBJECT_LIBRARY: {
// Objects use OBJECT properties.
if (!objectArgs.GetDestination().empty()) {
+ // Verify that we know where the objects are to install them.
+ std::string reason;
+ if (!this->Makefile->GetGlobalGenerator()
+ ->HasKnownObjectFileLocation(&reason)) {
+ std::ostringstream e;
+ e << "TARGETS given OBJECT library \"" << target.GetName()
+ << "\" whose objects may not be installed" << reason << ".";
+ this->SetError(e.str());
+ return false;
+ }
+
objectGenerator =
CreateInstallTargetGenerator(target, objectArgs, false);
} else {
- std::ostringstream e;
- e << "TARGETS given no OBJECTS DESTINATION for object library "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
+ // Installing an OBJECT library without a destination transforms
+ // it to an INTERFACE library. It installs no files but can be
+ // exported.
}
} break;
case cmStateEnums::EXECUTABLE: {
// Keep track of whether we're installing anything in each category
installsArchive = installsArchive || archiveGenerator != nullptr;
installsLibrary = installsLibrary || libraryGenerator != nullptr;
+ installsNamelink = installsNamelink || namelinkGenerator != nullptr;
installsRuntime = installsRuntime || runtimeGenerator != nullptr;
installsObject = installsObject || objectGenerator != nullptr;
installsFramework = installsFramework || frameworkGenerator != nullptr;
this->Makefile->AddInstallGenerator(archiveGenerator);
this->Makefile->AddInstallGenerator(libraryGenerator);
+ this->Makefile->AddInstallGenerator(namelinkGenerator);
this->Makefile->AddInstallGenerator(runtimeGenerator);
this->Makefile->AddInstallGenerator(objectGenerator);
this->Makefile->AddInstallGenerator(frameworkGenerator);
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
libraryArgs.GetComponent().c_str());
}
+ if (installsNamelink) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ libraryArgs.GetNamelinkComponent().c_str());
+ }
if (installsRuntime) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
runtimeArgs.GetComponent().c_str());
messageType = cmake::FATAL_ERROR;
}
if (modal) {
- e << "The file\n " << file << "\nwas generated by the export() "
- "command. It "
- << modal << " not be installed with the "
- "install() command. Use the install(EXPORT) mechanism "
- "instead. See the cmake-packages(7) manual for more.\n";
+ e << "The file\n " << file
+ << "\nwas generated by the export() "
+ "command. It "
+ << modal
+ << " not be installed with the "
+ "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) {
return false;
, ArgumentGroup()
, Destination(&Parser, "DESTINATION", &ArgumentGroup)
, Component(&Parser, "COMPONENT", &ArgumentGroup)
+ , NamelinkComponent(&Parser, "NAMELINK_COMPONENT", &ArgumentGroup)
, ExcludeFromAll(&Parser, "EXCLUDE_FROM_ALL", &ArgumentGroup)
, Rename(&Parser, "RENAME", &ArgumentGroup)
, Permissions(&Parser, "PERMISSIONS", &ArgumentGroup)
return unspecifiedComponent;
}
+const std::string& cmInstallCommandArguments::GetNamelinkComponent() const
+{
+ if (!this->NamelinkComponent.GetString().empty()) {
+ return this->NamelinkComponent.GetString();
+ }
+ return this->GetComponent();
+}
+
const std::string& cmInstallCommandArguments::GetRename() const
{
if (!this->Rename.GetString().empty()) {
return false;
}
+bool cmInstallCommandArguments::HasNamelinkComponent() const
+{
+ if (!this->NamelinkComponent.GetString().empty()) {
+ return true;
+ }
+ if (this->GenericArguments != nullptr) {
+ return this->GenericArguments->HasNamelinkComponent();
+ }
+ return false;
+}
+
const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
const
{
const std::string& GetDestination() const;
const std::string& GetComponent() const;
+ const std::string& GetNamelinkComponent() const;
bool GetExcludeFromAll() const;
const std::string& GetRename() const;
const std::string& GetPermissions() const;
bool GetOptional() const;
bool GetNamelinkOnly() const;
bool GetNamelinkSkip() const;
+ bool HasNamelinkComponent() const;
// once HandleDirectoryMode() is also switched to using
// cmInstallCommandArguments then these two functions can become non-static
cmInstallCommandArguments(); // disabled
cmCAString Destination;
cmCAString Component;
+ cmCAString NamelinkComponent;
cmCAEnabler ExcludeFromAll;
cmCAString Rename;
cmCAStringVector Permissions;
#include <utility>
#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmExportInstallAndroidMKGenerator.h"
+# include "cmExportInstallAndroidMKGenerator.h"
#endif
#include "cmExportInstallFileGenerator.h"
#include "cmExportSet.h"
private:
std::vector<std::string> FinalArgs;
- bool IsFilesForm;
+ bool IsFilesForm = false;
std::string Destination;
std::vector<std::string> Files;
};
filesFrom.push_back(std::move(from1));
filesTo.push_back(std::move(to1));
std::string targetNameImportLib;
- if (this->Target->GetImplibGNUtoMS(targetNameImport,
+ if (this->Target->GetImplibGNUtoMS(config, targetNameImport,
targetNameImportLib)) {
filesFrom.push_back(fromDirConfig + targetNameImportLib);
filesTo.push_back(toDir + targetNameImportLib);
filesFrom.push_back(std::move(from1));
filesTo.push_back(std::move(to1));
std::string targetNameImportLib;
- if (this->Target->GetImplibGNUtoMS(targetNameImport,
+ if (this->Target->GetImplibGNUtoMS(config, targetNameImport,
targetNameImportLib)) {
filesFrom.push_back(fromDirConfig + targetNameImportLib);
filesTo.push_back(toDir + targetNameImportLib);
targetNamePDB, config);
if (nameType == NameImplib) {
// Use the import library name.
- if (!target->GetImplibGNUtoMS(targetNameImport, fname,
+ if (!target->GetImplibGNUtoMS(config, targetNameImport, fname,
"${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
fname = targetNameImport;
}
targetNameImport, targetNamePDB, config);
if (nameType == NameImplib) {
// Use the import library name.
- if (!target->GetImplibGNUtoMS(targetNameImport, fname,
+ if (!target->GetImplibGNUtoMS(config, targetNameImport, fname,
"${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
fname = targetNameImport;
}
if (args.empty()) {
return true;
}
- // add libraries, nothe that there is an optional prefix
+ // add libraries, note that there is an optional prefix
// of debug and optimized than can be used
for (std::vector<std::string>::const_iterator i = args.begin();
i != args.end(); ++i) {
#include "cmLinkLineDeviceComputer.h"
-#include <set>
#include <sstream>
+#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
ItemVector const& items = cli.GetItems();
std::string config = cli.GetConfig();
for (auto const& item : items) {
- if (!item.Target) {
- continue;
- }
-
- bool skippable = false;
- switch (item.Target->GetType()) {
- case cmStateEnums::SHARED_LIBRARY:
- case cmStateEnums::MODULE_LIBRARY:
- case cmStateEnums::INTERFACE_LIBRARY:
- skippable = true;
- break;
- case cmStateEnums::STATIC_LIBRARY:
- // If a static library is resolving its device linking, it should
- // be removed for other device linking
- skippable =
- item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
- break;
- default:
- break;
- }
-
- if (skippable) {
- continue;
- }
-
- std::set<std::string> langs;
- item.Target->GetLanguages(langs, config);
- if (langs.count("CUDA") == 0) {
- continue;
+ if (item.Target) {
+ bool skip = false;
+ switch (item.Target->GetType()) {
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ skip = true;
+ break;
+ case cmStateEnums::STATIC_LIBRARY:
+ skip = item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
+ break;
+ default:
+ break;
+ }
+ if (skip) {
+ continue;
+ }
}
if (item.IsPath) {
+ // nvcc understands absolute paths to libraries ending in '.a' should
+ // be passed to nvlink. Other extensions like '.so' or '.dylib' are
+ // rejected by the nvcc front-end even though nvlink knows to ignore
+ // them. Bypass the front-end via '-Xnvlink'.
+ if (!cmHasLiteralSuffix(item.Value, ".a")) {
+ fout << "-Xnvlink ";
+ }
fout << this->ConvertToOutputFormat(
this->ConvertToLinkReference(item.Value));
} else {
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <assert.h>
+#include <functional>
#include <iterator>
+#include <set>
#include <sstream>
+#include <stdexcept>
#include <stdio.h>
#include <stdlib.h> // required for atoi
#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
+#include "cmStringReplaceHelper.h"
#include "cmSystemTools.h"
#include "cmake.h"
if (subCommand == "INSERT") {
return this->HandleInsertCommand(args);
}
+ if (subCommand == "JOIN") {
+ return this->HandleJoinCommand(args);
+ }
if (subCommand == "REMOVE_AT") {
return this->HandleRemoveAtCommand(args);
}
if (subCommand == "REMOVE_DUPLICATES") {
return this->HandleRemoveDuplicatesCommand(args);
}
+ if (subCommand == "TRANSFORM") {
+ return this->HandleTransformCommand(args);
+ }
if (subCommand == "SORT") {
return this->HandleSortCommand(args);
}
+ if (subCommand == "SUBLIST") {
+ return this->HandleSublistCommand(args);
+ }
if (subCommand == "REVERSE") {
return this->HandleReverseCommand(args);
}
return true;
}
+bool cmListCommand::HandleJoinCommand(std::vector<std::string> const& args)
+{
+ if (args.size() != 4) {
+ std::ostringstream error;
+ error << "sub-command JOIN requires three arguments (" << args.size() - 1
+ << " found).";
+ this->SetError(error.str());
+ return false;
+ }
+
+ const std::string& listName = args[1];
+ const std::string& glue = args[2];
+ const std::string& variableName = args[3];
+
+ // expand the variable
+ std::vector<std::string> varArgsExpanded;
+ if (!this->GetList(varArgsExpanded, listName)) {
+ this->Makefile->AddDefinition(variableName, "");
+ return true;
+ }
+
+ std::string value =
+ cmJoin(cmMakeRange(varArgsExpanded.begin(), varArgsExpanded.end()), glue);
+
+ this->Makefile->AddDefinition(variableName, value.c_str());
+ return true;
+}
+
bool cmListCommand::HandleRemoveItemCommand(
std::vector<std::string> const& args)
{
return true;
}
+// Helpers for list(TRANSFORM <list> ...)
+namespace {
+using transform_type = std::function<std::string(const std::string&)>;
+
+class transform_error : public std::runtime_error
+{
+public:
+ transform_error(const std::string& error)
+ : std::runtime_error(error)
+ {
+ }
+};
+
+class TransformSelector
+{
+public:
+ virtual ~TransformSelector() {}
+
+ std::string Tag;
+
+ virtual bool Validate(std::size_t count = 0) = 0;
+
+ virtual bool InSelection(const std::string&) = 0;
+
+ virtual void Transform(std::vector<std::string>& list,
+ const transform_type& transform)
+ {
+ std::transform(list.begin(), list.end(), list.begin(), transform);
+ }
+
+protected:
+ TransformSelector(std::string&& tag)
+ : Tag(std::move(tag))
+ {
+ }
+};
+class TransformNoSelector : public TransformSelector
+{
+public:
+ TransformNoSelector()
+ : TransformSelector("NO SELECTOR")
+ {
+ }
+
+ bool Validate(std::size_t) override { return true; }
+
+ bool InSelection(const std::string&) override { return true; }
+};
+class TransformSelectorRegex : public TransformSelector
+{
+public:
+ TransformSelectorRegex(const std::string& regex)
+ : TransformSelector("REGEX")
+ , Regex(regex)
+ {
+ }
+
+ bool Validate(std::size_t) override { return this->Regex.is_valid(); }
+
+ bool InSelection(const std::string& value) override
+ {
+ return this->Regex.find(value);
+ }
+
+ cmsys::RegularExpression Regex;
+};
+class TransformSelectorIndexes : public TransformSelector
+{
+public:
+ std::vector<int> Indexes;
+
+ bool InSelection(const std::string&) override { return true; }
+
+ void Transform(std::vector<std::string>& list,
+ const transform_type& transform) override
+ {
+ this->Validate(list.size());
+
+ for (auto index : this->Indexes) {
+ list[index] = transform(list[index]);
+ }
+ }
+
+protected:
+ TransformSelectorIndexes(std::string&& tag)
+ : TransformSelector(std::move(tag))
+ {
+ }
+ TransformSelectorIndexes(std::string&& tag, std::vector<int>&& indexes)
+ : TransformSelector(std::move(tag))
+ , Indexes(indexes)
+ {
+ }
+
+ int NormalizeIndex(int index, std::size_t count)
+ {
+ if (index < 0) {
+ index = static_cast<int>(count) + index;
+ }
+ if (index < 0 || count <= static_cast<std::size_t>(index)) {
+ std::ostringstream str;
+ str << "sub-command TRANSFORM, selector " << this->Tag
+ << ", index: " << index << " out of range (-" << count << ", "
+ << count - 1 << ").";
+ throw transform_error(str.str());
+ }
+ return index;
+ }
+};
+class TransformSelectorAt : public TransformSelectorIndexes
+{
+public:
+ TransformSelectorAt(std::vector<int>&& indexes)
+ : TransformSelectorIndexes("AT", std::move(indexes))
+ {
+ }
+
+ bool Validate(std::size_t count) override
+ {
+ decltype(Indexes) indexes;
+
+ for (auto index : Indexes) {
+ indexes.push_back(this->NormalizeIndex(index, count));
+ }
+ this->Indexes = std::move(indexes);
+
+ return true;
+ }
+};
+class TransformSelectorFor : public TransformSelectorIndexes
+{
+public:
+ TransformSelectorFor(int start, int stop, int step)
+ : TransformSelectorIndexes("FOR")
+ , Start(start)
+ , Stop(stop)
+ , Step(step)
+ {
+ }
+
+ bool Validate(std::size_t count) override
+ {
+ this->Start = this->NormalizeIndex(this->Start, count);
+ this->Stop = this->NormalizeIndex(this->Stop, count);
+
+ // compute indexes
+ auto size = (this->Stop - this->Start + 1) / this->Step;
+ if ((this->Stop - this->Start + 1) % this->Step != 0) {
+ size += 1;
+ }
+
+ this->Indexes.resize(size);
+ auto start = this->Start, step = this->Step;
+ std::generate(this->Indexes.begin(), this->Indexes.end(),
+ [&start, step]() -> int {
+ auto r = start;
+ start += step;
+ return r;
+ });
+
+ return true;
+ }
+
+private:
+ int Start, Stop, Step;
+};
+
+class TransformAction
+{
+public:
+ virtual ~TransformAction() {}
+
+ virtual std::string Transform(const std::string& input) = 0;
+};
+class TransformReplace : public TransformAction
+{
+public:
+ TransformReplace(const std::vector<std::string>& arguments,
+ cmMakefile* makefile)
+ : ReplaceHelper(arguments[0], arguments[1], makefile)
+ {
+ makefile->ClearMatches();
+
+ if (!this->ReplaceHelper.IsRegularExpressionValid()) {
+ std::ostringstream error;
+ error
+ << "sub-command TRANSFORM, action REPLACE: Failed to compile regex \""
+ << arguments[0] << "\".";
+ throw transform_error(error.str());
+ }
+ if (!this->ReplaceHelper.IsReplaceExpressionValid()) {
+ std::ostringstream error;
+ error << "sub-command TRANSFORM, action REPLACE: "
+ << this->ReplaceHelper.GetError() << ".";
+ throw transform_error(error.str());
+ }
+ }
+
+ std::string Transform(const std::string& input) override
+ {
+ // Scan through the input for all matches.
+ std::string output;
+
+ if (!this->ReplaceHelper.Replace(input, output)) {
+ std::ostringstream error;
+ error << "sub-command TRANSFORM, action REPLACE: "
+ << this->ReplaceHelper.GetError() << ".";
+ throw transform_error(error.str());
+ }
+
+ return output;
+ }
+
+private:
+ cmStringReplaceHelper ReplaceHelper;
+};
+}
+
+bool cmListCommand::HandleTransformCommand(
+ std::vector<std::string> const& args)
+{
+ if (args.size() < 3) {
+ this->SetError(
+ "sub-command TRANSFORM requires an action to be specified.");
+ return false;
+ }
+
+ // Structure collecting all elements of the command
+ struct Command
+ {
+ Command(const std::string& listName)
+ : ListName(listName)
+ , OutputName(listName)
+ {
+ }
+
+ std::string Name;
+ std::string ListName;
+ std::vector<std::string> Arguments;
+ std::unique_ptr<TransformAction> Action;
+ std::unique_ptr<TransformSelector> Selector;
+ std::string OutputName;
+ } command(args[1]);
+
+ // Descriptor of action
+ // Arity: number of arguments required for the action
+ // Transform: lambda function implementing the action
+ struct ActionDescriptor
+ {
+ ActionDescriptor(const std::string& name)
+ : Name(name)
+ {
+ }
+ ActionDescriptor(const std::string& name, int arity,
+ const transform_type& transform)
+ : Name(name)
+ , Arity(arity)
+ , Transform(transform)
+ {
+ }
+
+ operator const std::string&() const { return Name; }
+
+ std::string Name;
+ int Arity = 0;
+ transform_type Transform;
+ };
+
+ // Build a set of supported actions.
+ std::set<ActionDescriptor,
+ std::function<bool(const std::string&, const std::string&)>>
+ descriptors(
+ [](const std::string& x, const std::string& y) { return x < y; });
+ descriptors = { { "APPEND", 1,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return s + command.Arguments[0];
+ }
+
+ return s;
+ } },
+ { "PREPEND", 1,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return command.Arguments[0] + s;
+ }
+
+ return s;
+ } },
+ { "TOUPPER", 0,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return cmSystemTools::UpperCase(s);
+ }
+
+ return s;
+ } },
+ { "TOLOWER", 0,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return cmSystemTools::LowerCase(s);
+ }
+
+ return s;
+ } },
+ { "STRIP", 0,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return cmSystemTools::TrimWhitespace(s);
+ }
+
+ return s;
+ } },
+ { "GENEX_STRIP", 0,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return cmGeneratorExpression::Preprocess(
+ s,
+ cmGeneratorExpression::StripAllGeneratorExpressions);
+ }
+
+ return s;
+ } },
+ { "REPLACE", 2,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return command.Action->Transform(s);
+ }
+
+ return s;
+ } } };
+
+ using size_type = std::vector<std::string>::size_type;
+ size_type index = 2;
+
+ // Parse all possible function parameters
+ auto descriptor = descriptors.find(args[index]);
+
+ if (descriptor == descriptors.end()) {
+ std::ostringstream error;
+ error << " sub-command TRANSFORM, " << args[index] << " invalid action.";
+ this->SetError(error.str());
+ return false;
+ }
+
+ // Action arguments
+ index += 1;
+ if (args.size() < index + descriptor->Arity) {
+ std::ostringstream error;
+ error << "sub-command TRANSFORM, action " << descriptor->Name
+ << " expects " << descriptor->Arity << " argument(s).";
+ this->SetError(error.str());
+ return false;
+ }
+
+ command.Name = descriptor->Name;
+ index += descriptor->Arity;
+ if (descriptor->Arity > 0) {
+ command.Arguments =
+ std::vector<std::string>(args.begin() + 3, args.begin() + index);
+ }
+
+ if (command.Name == "REPLACE") {
+ try {
+ command.Action =
+ cm::make_unique<TransformReplace>(command.Arguments, this->Makefile);
+ } catch (const transform_error& e) {
+ this->SetError(e.what());
+ return false;
+ }
+ }
+
+ const std::string REGEX{ "REGEX" }, AT{ "AT" }, FOR{ "FOR" },
+ OUTPUT_VARIABLE{ "OUTPUT_VARIABLE" };
+
+ // handle optional arguments
+ while (args.size() > index) {
+ if ((args[index] == REGEX || args[index] == AT || args[index] == FOR) &&
+ command.Selector) {
+ std::ostringstream error;
+ error << "sub-command TRANSFORM, selector already specified ("
+ << command.Selector->Tag << ").";
+ this->SetError(error.str());
+ return false;
+ }
+
+ // REGEX selector
+ if (args[index] == REGEX) {
+ if (args.size() == ++index) {
+ this->SetError("sub-command TRANSFORM, selector REGEX expects "
+ "'regular expression' argument.");
+ return false;
+ }
+
+ command.Selector = cm::make_unique<TransformSelectorRegex>(args[index]);
+ if (!command.Selector->Validate()) {
+ std::ostringstream error;
+ error << "sub-command TRANSFORM, selector REGEX failed to compile "
+ "regex \"";
+ error << args[index] << "\".";
+ this->SetError(error.str());
+ return false;
+ }
+
+ index += 1;
+ continue;
+ }
+
+ // AT selector
+ if (args[index] == AT) {
+ // get all specified indexes
+ std::vector<int> indexes;
+ while (args.size() > ++index) {
+ std::size_t pos;
+ int value;
+
+ try {
+ value = std::stoi(args[index], &pos);
+ if (pos != args[index].length()) {
+ // this is not a number, stop processing
+ break;
+ }
+ indexes.push_back(value);
+ } catch (const std::invalid_argument&) {
+ // this is not a number, stop processing
+ break;
+ }
+ }
+
+ if (indexes.empty()) {
+ this->SetError(
+ "sub-command TRANSFORM, selector AT expects at least one "
+ "numeric value.");
+ return false;
+ }
+
+ command.Selector =
+ cm::make_unique<TransformSelectorAt>(std::move(indexes));
+
+ continue;
+ }
+
+ // FOR selector
+ if (args[index] == FOR) {
+ if (args.size() <= ++index + 1) {
+ this->SetError("sub-command TRANSFORM, selector FOR expects, at least,"
+ " two arguments.");
+ return false;
+ }
+
+ int start = 0, stop = 0, step = 1;
+ bool valid = true;
+ try {
+ std::size_t pos;
+
+ start = std::stoi(args[index], &pos);
+ if (pos != args[index].length()) {
+ // this is not a number
+ valid = false;
+ } else {
+ stop = std::stoi(args[++index], &pos);
+ if (pos != args[index].length()) {
+ // this is not a number
+ valid = false;
+ }
+ }
+ } catch (const std::invalid_argument&) {
+ // this is not numbers
+ valid = false;
+ }
+ if (!valid) {
+ this->SetError("sub-command TRANSFORM, selector FOR expects, "
+ "at least, two numeric values.");
+ return false;
+ }
+ // try to read a third numeric value for step
+ if (args.size() > ++index) {
+ try {
+ std::size_t pos;
+
+ step = std::stoi(args[index], &pos);
+ if (pos != args[index].length()) {
+ // this is not a number
+ step = 1;
+ } else {
+ index += 1;
+ }
+ } catch (const std::invalid_argument&) {
+ // this is not number, ignore exception
+ }
+ }
+
+ if (step < 0) {
+ this->SetError("sub-command TRANSFORM, selector FOR expects "
+ "non negative numeric value for <step>.");
+ }
+
+ command.Selector =
+ cm::make_unique<TransformSelectorFor>(start, stop, step);
+
+ continue;
+ }
+
+ // output variable
+ if (args[index] == OUTPUT_VARIABLE) {
+ if (args.size() == ++index) {
+ this->SetError("sub-command TRANSFORM, OUTPUT_VARIABLE "
+ "expects variable name argument.");
+ return false;
+ }
+
+ command.OutputName = args[index++];
+ continue;
+ }
+
+ std::ostringstream error;
+ error << "sub-command TRANSFORM, '"
+ << cmJoin(cmMakeRange(args).advance(index), " ")
+ << "': unexpected argument(s).";
+ this->SetError(error.str());
+ return false;
+ }
+
+ // expand the list variable
+ std::vector<std::string> varArgsExpanded;
+ if (!this->GetList(varArgsExpanded, command.ListName)) {
+ this->Makefile->AddDefinition(command.OutputName, "");
+ return true;
+ }
+
+ if (!command.Selector) {
+ // no selector specified, apply transformation to all elements
+ command.Selector = cm::make_unique<TransformNoSelector>();
+ }
+
+ try {
+ command.Selector->Transform(varArgsExpanded, descriptor->Transform);
+ } catch (const transform_error& e) {
+ this->SetError(e.what());
+ return false;
+ }
+
+ this->Makefile->AddDefinition(command.OutputName,
+ cmJoin(varArgsExpanded, ";").c_str());
+
+ return true;
+}
+
bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args)
{
assert(args.size() >= 2);
return true;
}
+bool cmListCommand::HandleSublistCommand(std::vector<std::string> const& args)
+{
+ if (args.size() != 5) {
+ std::ostringstream error;
+ error << "sub-command SUBLIST requires four arguments (" << args.size() - 1
+ << " found).";
+ this->SetError(error.str());
+ return false;
+ }
+
+ const std::string& listName = args[1];
+ const std::string& variableName = args[args.size() - 1];
+
+ // expand the variable
+ std::vector<std::string> varArgsExpanded;
+ if (!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) {
+ this->Makefile->AddDefinition(variableName, "");
+ return true;
+ }
+
+ const int start = atoi(args[2].c_str());
+ const int length = atoi(args[3].c_str());
+
+ using size_type = decltype(varArgsExpanded)::size_type;
+
+ if (start < 0 || size_type(start) >= varArgsExpanded.size()) {
+ std::ostringstream error;
+ error << "begin index: " << start << " is out of range 0 - "
+ << varArgsExpanded.size() - 1;
+ this->SetError(error.str());
+ return false;
+ }
+ if (length < -1) {
+ std::ostringstream error;
+ error << "length: " << length << " should be -1 or greater";
+ this->SetError(error.str());
+ return false;
+ }
+
+ const size_type end =
+ (length == -1 || size_type(start + length) > varArgsExpanded.size())
+ ? varArgsExpanded.size()
+ : size_type(start + length);
+ std::vector<std::string> sublist(varArgsExpanded.begin() + start,
+ varArgsExpanded.begin() + end);
+ this->Makefile->AddDefinition(variableName, cmJoin(sublist, ";").c_str());
+ return true;
+}
+
bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args)
{
if (args.size() < 3) {
bool HandleAppendCommand(std::vector<std::string> const& args);
bool HandleFindCommand(std::vector<std::string> const& args);
bool HandleInsertCommand(std::vector<std::string> const& args);
+ bool HandleJoinCommand(std::vector<std::string> const& args);
bool HandleRemoveAtCommand(std::vector<std::string> const& args);
bool HandleRemoveItemCommand(std::vector<std::string> const& args);
bool HandleRemoveDuplicatesCommand(std::vector<std::string> const& args);
+ bool HandleTransformCommand(std::vector<std::string> const& args);
bool HandleSortCommand(std::vector<std::string> const& args);
+ bool HandleSublistCommand(std::vector<std::string> const& args);
bool HandleReverseCommand(std::vector<std::string> const& args);
bool HandleFilterCommand(std::vector<std::string> const& args);
bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
#include <assert.h>
#include <sstream>
+cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=(
+ std::string const& name)
+{
+ this->Original = name;
+ this->Lower = cmSystemTools::LowerCase(name);
+ return *this;
+}
+
struct cmListFileParser
{
cmListFileParser(cmListFile* lf, cmListFileBacktrace const& lfbt,
struct cmCommandContext
{
- std::string Name;
+ struct cmCommandName
+ {
+ std::string Lower;
+ std::string Original;
+ cmCommandName() {}
+ cmCommandName(std::string const& name) { *this = name; }
+ cmCommandName& operator=(std::string const& name);
+ } Name;
long Line;
cmCommandContext()
- : Name()
- , Line(0)
+ : Line(0)
+ {
+ }
+ cmCommandContext(const char* name, int line)
+ : Name(name)
+ , Line(line)
{
}
};
cmListFileContext lfc;
lfc.FilePath = fileName;
lfc.Line = lfcc.Line;
- lfc.Name = lfcc.Name;
+ lfc.Name = lfcc.Name.Original;
return lfc;
}
};
#ifndef cmListFileLexer_h
#define cmListFileLexer_h
-typedef enum cmListFileLexer_Type_e {
+typedef enum cmListFileLexer_Type_e
+{
cmListFileLexer_Token_None,
cmListFileLexer_Token_Space,
cmListFileLexer_Token_Newline,
class cmExecutionStatus;
#ifdef __QNX__
-#include <malloc.h> /* for malloc/free on QNX */
+# include <malloc.h> /* for malloc/free on QNX */
#endif
extern "C" void TrapsForSignalsCFunction(int sig);
#include "cmake.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#define CM_LG_ENCODE_OBJECT_NAMES
-#include "cmCryptoHash.h"
+# define CM_LG_ENCODE_OBJECT_NAMES
+# include "cmCryptoHash.h"
#endif
#include "cmsys/RegularExpression.hxx"
#include <utility>
#if defined(__HAIKU__)
-#include <FindDirectory.h>
-#include <StorageDefs.h>
+# include <FindDirectory.h>
+# include <StorageDefs.h>
#endif
// List of variables that are replaced when
this->ObjectMaxPathViolations.clear();
}
+void cmLocalGenerator::MoveSystemIncludesToEnd(
+ std::vector<std::string>& includeDirs, const std::string& config,
+ const std::string& lang, const cmGeneratorTarget* target) const
+{
+ if (!target) {
+ return;
+ }
+
+ std::stable_sort(
+ includeDirs.begin(), includeDirs.end(),
+ [&target, &config, &lang](std::string const& a, std::string const& b) {
+ return !target->IsSystemIncludeDirectory(a, config, lang) &&
+ target->IsSystemIncludeDirectory(b, config, lang);
+ });
+}
+
void cmLocalGenerator::TraceDependencies()
{
std::vector<std::string> configs;
}
std::string cmLocalGenerator::GetIncludeFlags(
- const std::vector<std::string>& includes, cmGeneratorTarget* target,
+ const std::vector<std::string>& includeDirs, cmGeneratorTarget* target,
const std::string& lang, bool forceFullPaths, bool forResponseFile,
const std::string& config)
{
return "";
}
+ std::vector<std::string> includes = includeDirs;
+ this->MoveSystemIncludesToEnd(includes, config, lang, target);
+
OutputFormat shellFormat = forResponseFile ? RESPONSE : SHELL;
std::ostringstream includeFlags;
}
}
+ this->MoveSystemIncludesToEnd(dirs, config, lang, target);
+
// Add standard include directories for this language.
// We do not filter out implicit directories here.
std::string const standardIncludesVar =
target->Target->GetMakefile()->GetDefinition(option_flag);
if (!opt) {
std::ostringstream e;
- e << "Target \"" << target->GetName() << "\" requires the language "
- "dialect \""
+ e << "Target \"" << target->GetName()
+ << "\" requires the language "
+ "dialect \""
<< lang << standardProp << "\" "
<< (ext ? "(with compiler extensions)" : "")
<< ", but CMake "
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");
int targetType);
void ComputeObjectMaxPath();
+ void MoveSystemIncludesToEnd(std::vector<std::string>& includeDirs,
+ const std::string& config,
+ const std::string& lang,
+ cmGeneratorTarget const* target) const;
};
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include <stdio.h>
#include <utility>
+#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmake.h"
+#include "cmsys/FStream.hxx"
cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
cmMakefile* mf)
if (!showIncludesPrefix.empty()) {
cmGlobalNinjaGenerator::WriteComment(this->GetRulesFileStream(),
"localized /showIncludes string");
- this->GetRulesFileStream() << "msvc_deps_prefix = " << showIncludesPrefix
- << "\n\n";
+ this->GetRulesFileStream()
+ << "msvc_deps_prefix = " << showIncludesPrefix << "\n\n";
}
}
this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForConsolePool();
}
+ // The Ninja generator writes rules which require support for restat
+ // when rebuilding build.ninja manifest (>= 1.8)
+ if (this->GetGlobalNinjaGenerator()->SupportsManifestRestat() &&
+ this->GetCMakeInstance()->DoWriteGlobVerifyTarget() &&
+ !this->GetGlobalNinjaGenerator()->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
+ requiredVersion =
+ this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForManifestRestat();
+ }
+
cmGlobalNinjaGenerator::WriteComment(
os, "Minimal version of Ninja required by this file");
os << "ninja_required_version = " << requiredVersion << std::endl
cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
std::string const ninjaRulesFile =
ng->NinjaOutputPath(cmGlobalNinjaGenerator::NINJA_RULES_FILE);
- std::string const rulesFilePath =
- ng->EncodeIdent(ng->EncodePath(ninjaRulesFile), os);
+ std::string const rulesFilePath = ng->EncodePath(ninjaRulesFile);
cmGlobalNinjaGenerator::WriteInclude(os, rulesFilePath,
"Include rules file.");
os << "\n";
}
}
+std::string cmLocalNinjaGenerator::WriteCommandScript(
+ std::vector<std::string> const& cmdLines, std::string const& customStep,
+ cmGeneratorTarget const* target) const
+{
+ std::string scriptPath;
+ if (target) {
+ scriptPath = target->GetSupportDirectory();
+ } else {
+ scriptPath = this->GetCurrentBinaryDirectory();
+ scriptPath += cmake::GetCMakeFilesDirectory();
+ }
+ cmSystemTools::MakeDirectory(scriptPath);
+ scriptPath += '/';
+ scriptPath += customStep;
+#ifdef _WIN32
+ scriptPath += ".bat";
+#else
+ scriptPath += ".sh";
+#endif
+
+ cmsys::ofstream script(scriptPath.c_str());
+
+#ifndef _WIN32
+ script << "set -e\n\n";
+#endif
+
+ for (auto const& i : cmdLines) {
+ std::string cmd = i;
+ // The command line was built assuming it would be written to
+ // the build.ninja file, so it uses '$$' for '$'. Remove this
+ // for the raw shell script.
+ cmSystemTools::ReplaceString(cmd, "$$", "$");
+#ifdef _WIN32
+ script << cmd << " || exit /b" << '\n';
+#else
+ script << cmd << '\n';
+#endif
+ }
+
+ return scriptPath;
+}
+
std::string cmLocalNinjaGenerator::BuildCommandLine(
- const std::vector<std::string>& cmdLines)
+ std::vector<std::string> const& cmdLines, std::string const& customStep,
+ cmGeneratorTarget const* target) const
{
// If we have no commands but we need to build a command anyway, use noop.
// This happens when building a POST_BUILD value for link targets that
return cmGlobalNinjaGenerator::SHELL_NOOP;
}
+ // If this is a custom step then we will have no '$VAR' ninja placeholders.
+ // This means we can deal with long command sequences by writing to a script.
+ // Do this if the command lines are on the scale of the OS limit.
+ if (!customStep.empty()) {
+ size_t cmdLinesTotal = 0;
+ for (std::string const& cmd : cmdLines) {
+ cmdLinesTotal += cmd.length() + 6;
+ }
+ if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) {
+ std::string const scriptPath =
+ this->WriteCommandScript(cmdLines, customStep, target);
+ std::string cmd
+#ifndef _WIN32
+ = "/bin/sh "
+#endif
+ ;
+ cmd += this->ConvertToOutputFormat(
+ this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(scriptPath),
+ cmOutputConverter::SHELL);
+
+ // Add an unused argument based on script content so that Ninja
+ // knows when the command lines change.
+ cmd += " ";
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ cmd += hash.HashFile(scriptPath).substr(0, 16);
+ return cmd;
+ }
+ }
+
std::ostringstream cmd;
for (std::vector<std::string>::const_iterator li = cmdLines.begin();
li != cmdLines.end(); ++li)
}
#if 0
-#error TODO: Once CC in an ExternalProject target must provide the \
+# error TODO: Once CC in an ExternalProject target must provide the \
file of each imported target that has an add_dependencies pointing \
at us. How to know which ExternalProject step actually provides it?
#endif
"Phony custom command for " + ninjaOutputs[0], ninjaOutputs, ninjaDeps,
cmNinjaDeps(), orderOnlyDeps, cmNinjaVars());
} else {
+ std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
+ // Hash full path to make unique.
+ customStep += '-';
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+
this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
- this->BuildCommandLine(cmdLines), this->ConstructComment(ccg),
- "Custom command for " + ninjaOutputs[0], cc->GetDepfile(),
- cc->GetUsesTerminal(),
+ this->BuildCommandLine(cmdLines, customStep),
+ this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
+ cc->GetDepfile(), cc->GetUsesTerminal(),
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps,
orderOnlyDeps);
}
return this->HomeRelativeOutputPath;
}
- std::string BuildCommandLine(const std::vector<std::string>& cmdLines);
+ std::string BuildCommandLine(
+ std::vector<std::string> const& cmdLines,
+ std::string const& customStep = std::string(),
+ cmGeneratorTarget const* target = nullptr) const;
void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs);
void AppendTargetDepends(
std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
+ std::string WriteCommandScript(std::vector<std::string> const& cmdLines,
+ std::string const& customStep,
+ cmGeneratorTarget const* target) const;
+
std::string HomeRelativeOutputPath;
typedef std::map<cmCustomCommand const*, std::set<cmGeneratorTarget*>>
// C/C++ scanner is needed for bootstrapping CMake.
#include "cmDependsC.h"
#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmDependsFortran.h"
-#include "cmDependsJava.h"
+# include "cmDependsFortran.h"
+# include "cmDependsJava.h"
#endif
// Escape special characters in Makefile dependency lines
// Write special "cmake_check_build_system" target to run cmake with
// the --check-build-system flag.
- {
+ if (!this->GlobalGenerator->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
// Build command to run CMake to check if anything needs regenerating.
+ std::vector<std::string> commands;
+ cmake* cm = this->GlobalGenerator->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ std::string rescanRule = "$(CMAKE_COMMAND) -P ";
+ rescanRule += this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+ cmOutputConverter::SHELL);
+ commands.push_back(rescanRule);
+ }
std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
cmakefileName += "Makefile.cmake";
std::string runRule =
runRule += " 0";
std::vector<std::string> no_depends;
- std::vector<std::string> commands;
commands.push_back(std::move(runRule));
if (!this->IsRootMakefile()) {
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
}
- this->WriteMakeRule(
- makefileStream, "Special rule to run CMake to check the build system "
- "integrity.\n"
- "No rule that depends on this can have "
- "commands that come from listfiles\n"
- "because they might be regenerated.",
- "cmake_check_build_system", no_depends, commands, true);
+ this->WriteMakeRule(makefileStream,
+ "Special rule to run CMake to check the build system "
+ "integrity.\n"
+ "No rule that depends on this can have "
+ "commands that come from listfiles\n"
+ "because they might be regenerated.",
+ "cmake_check_build_system", no_depends, commands,
+ true);
}
}
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
if (gg->AllowNotParallel()) {
std::vector<std::string> no_depends;
- this->WriteMakeRule(ruleFileStream, "Allow only one \"make -f "
- "Makefile2\" at a time, but pass "
- "parallelism.",
+ this->WriteMakeRule(ruleFileStream,
+ "Allow only one \"make -f "
+ "Makefile2\" at a time, but pass "
+ "parallelism.",
".NOTPARALLEL", no_depends, no_commands, false);
}
}
std::string recursiveTarget = this->GetCurrentBinaryDirectory();
recursiveTarget += "/all";
- depends.push_back("cmake_check_build_system");
+ bool regenerate =
+ !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
std::string progressDir = this->GetBinaryDirectory();
progressDir += cmake::GetCMakeFilesDirectory();
if (!noall || cmSystemTools::IsOff(noall)) {
// Drive the build before installing.
depends.push_back("all");
- } else {
+ } else if (regenerate) {
// At least make sure the build system is up to date.
depends.push_back("cmake_check_build_system");
}
this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.",
"preinstall/fast", depends, commands, true);
- // write the depend rule, really a recompute depends rule
- depends.clear();
- commands.clear();
- std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
- cmakefileName += "Makefile.cmake";
- {
- std::string runRule =
- "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
- runRule += " --check-build-system ";
- runRule +=
- this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
- runRule += " 1";
- commands.push_back(std::move(runRule));
+ if (regenerate) {
+ // write the depend rule, really a recompute depends rule
+ depends.clear();
+ commands.clear();
+ cmake* cm = this->GlobalGenerator->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ std::string rescanRule = "$(CMAKE_COMMAND) -P ";
+ rescanRule += this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+ cmOutputConverter::SHELL);
+ commands.push_back(rescanRule);
+ }
+ std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
+ cmakefileName += "Makefile.cmake";
+ {
+ std::string runRule =
+ "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
+ runRule += " --check-build-system ";
+ runRule +=
+ this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
+ runRule += " 1";
+ commands.push_back(std::move(runRule));
+ }
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
+ this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
+ commands, true);
}
- this->CreateCDCommand(commands, this->GetBinaryDirectory(),
- this->GetCurrentBinaryDirectory());
- this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
- commands, true);
}
void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
cmGeneratorTarget* target,
const char* filename = nullptr);
- // Helper methods for dependeny updates.
+ // Helper methods for dependency updates.
bool ScanDependencies(
const char* targetDir,
std::map<std::string, cmDepends::DependencyVector>& validDeps);
{
}
+void cmLocalVisualStudio10Generator::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;
+ auto& deps = this->GlobalGenerator->GetTargetDirectDepends(target);
+ for (auto& d : deps) {
+ // FIXME: Revise CreateSingleVCProj so we do not have to drop `const` here.
+ auto dependee = const_cast<cmGeneratorTarget*>(&*d);
+ GenerateTargetsDepthFirst(dependee, remaining);
+ // Take the union of visited source files of custom commands
+ auto visited = GetSourcesVisited(dependee);
+ GetSourcesVisited(target).insert(visited.begin(), visited.end());
+ }
+ if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
+ ->TargetIsFortranOnly(target)) {
+ this->CreateSingleVCProj(target->GetName(), target);
+ } else {
+ cmVisualStudio10TargetGenerator tg(
+ target,
+ static_cast<cmGlobalVisualStudio10Generator*>(
+ this->GetGlobalGenerator()));
+ tg.Generate();
+ }
+}
+
void cmLocalVisualStudio10Generator::Generate()
{
- const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
- for (cmGeneratorTarget* l : tgts) {
- if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- continue;
- }
- if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(l)) {
- this->CreateSingleVCProj(l->GetName(), l);
- } else {
- cmVisualStudio10TargetGenerator tg(
- l, static_cast<cmGlobalVisualStudio10Generator*>(
- this->GetGlobalGenerator()));
- tg.Generate();
+ std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets();
+ for (auto& t : remaining) {
+ if (t) {
+ GenerateTargetsDepthFirst(t, remaining);
}
}
this->WriteStampFiles();
void ReadAndStoreExternalGUID(const std::string& name,
const char* path) override;
+ std::set<cmSourceFile const*>& GetSourcesVisited(cmGeneratorTarget* target)
+ {
+ return SourcesVisited[target];
+ };
+
protected:
const char* ReportErrorLabel() const override;
bool CustomCommandUseLocal() const override { return true; }
private:
+ void GenerateTargetsDepthFirst(cmGeneratorTarget* target,
+ std::vector<cmGeneratorTarget*>& remaining);
+
+ std::map<cmGeneratorTarget*, std::set<cmSourceFile const*>> SourcesVisited;
};
#endif
depName += ".depend";
cmsys::ofstream depFile(depName.c_str());
depFile << "# CMake generation dependency list for this directory.\n";
- std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
- for (std::vector<std::string>::const_iterator lf = listFiles.begin();
- lf != listFiles.end(); ++lf) {
- depFile << *lf << std::endl;
+
+ std::vector<std::string> listFiles(this->Makefile->GetListFiles());
+ cmake* cm = this->GlobalGenerator->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ listFiles.push_back(cm->GetGlobVerifyStamp());
+ }
+
+ // Sort the list of input files and remove duplicates.
+ std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>());
+ std::vector<std::string>::iterator new_end =
+ std::unique(listFiles.begin(), listFiles.end());
+ listFiles.erase(new_end, listFiles.end());
+
+ for (const std::string& lf : listFiles) {
+ depFile << lf << "\n";
}
}
cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
{
- if (this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ if (this->GlobalGenerator->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
return nullptr;
}
return nullptr;
}
+ std::vector<std::string> listFiles = this->Makefile->GetListFiles();
+ cmake* cm = this->GlobalGenerator->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ listFiles.push_back(cm->GetGlobVerifyStamp());
+ }
+
+ // Sort the list of input files and remove duplicates.
+ std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>());
+ std::vector<std::string>::iterator new_end =
+ std::unique(listFiles.begin(), listFiles.end());
+ listFiles.erase(new_end, listFiles.end());
+
std::string stampName = this->GetCurrentBinaryDirectory();
stampName += "/";
stampName += cmake::GetCMakeFilesDirectoryPostSlash();
commandLine.push_back(args);
commandLine.push_back("--check-stamp-file");
commandLine.push_back(stampName);
-
- std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
-
cmCustomCommandLines commandLines;
commandLines.push_back(commandLine);
const char* no_working_directory = 0;
std::string fullpathStampName =
cmSystemTools::CollapseFullPath(stampName.c_str());
this->Makefile->AddCustomCommandToOutput(
- fullpathStampName.c_str(), listFiles, makefileIn.c_str(), commandLines,
- comment.c_str(), no_working_directory, true, false);
+ fullpathStampName, listFiles, makefileIn, commandLines, comment.c_str(),
+ no_working_directory, true, false);
if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) {
// Finalize the source file path now since we're adding this after
// the generator validated all project-named sources.
<< "\\$(ConfigurationName)\"\n";
}
targetOptions.OutputAdditionalIncludeDirectories(
- fout, "\t\t\t\t", "\n",
- this->FortranProject ? "Fortran" : langForClCompile);
- targetOptions.OutputFlagMap(fout, "\t\t\t\t");
- targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
- langForClCompile);
+ fout, 4, this->FortranProject ? "Fortran" : langForClCompile);
+ targetOptions.OutputFlagMap(fout, 4);
+ targetOptions.OutputPreprocessorDefinitions(fout, 4, langForClCompile);
fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
if (target->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
// Specify the compiler program database file if configured.
"\t\t\t\tName=\"MASM\"\n"
;
/* clang-format on */
- targetOptions.OutputAdditionalIncludeDirectories(fout, "\t\t\t\t", "\n",
- "ASM_MASM");
+ targetOptions.OutputAdditionalIncludeDirectories(fout, 4, "ASM_MASM");
// Use same preprocessor definitions as VCCLCompilerTool.
- targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
- "ASM_MASM");
- masmOptions.OutputFlagMap(fout, "\t\t\t\t");
+ targetOptions.OutputPreprocessorDefinitions(fout, 4, "ASM_MASM");
+ masmOptions.OutputFlagMap(fout, 4);
/* clang-format off */
fout <<
"\t\t\t\tObjectFile=\"$(IntDir)\\\"\n"
tool = "VFResourceCompilerTool";
}
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
- targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
- "RC");
+ targetOptions.OutputAdditionalIncludeDirectories(fout, 4, "RC");
// add the -D flags to the RC tool
- targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC");
- fout << "/>\n";
+ targetOptions.OutputPreprocessorDefinitions(fout, 4, "RC");
+ fout << "\t\t\t/>\n";
tool = "VCMIDLTool";
if (this->FortranProject) {
tool = "VFMIDLTool";
}
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
- targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
- "MIDL");
+ targetOptions.OutputAdditionalIncludeDirectories(fout, 4, "MIDL");
fout << "\t\t\t\tMkTypLibCompatible=\"false\"\n";
if (gg->GetPlatformName() == "x64") {
fout << "\t\t\t\tTargetEnvironment=\"3\"\n";
fout << "\t\t\t\tOutputFile=\""
<< this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
this->WriteTargetVersionAttribute(fout, target);
- linkOptions.OutputFlagMap(fout, "\t\t\t\t");
+ linkOptions.OutputFlagMap(fout, 4);
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
this->OutputLibraryDirectories(fout, cli.GetDirectories());
fout << "\"\n";
fout << "\t\t\t\tOutputFile=\""
<< this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
this->WriteTargetVersionAttribute(fout, target);
- linkOptions.OutputFlagMap(fout, "\t\t\t\t");
+ linkOptions.OutputFlagMap(fout, 4);
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
this->OutputLibraryDirectories(fout, cli.GetDirectories());
fout << "\"\n";
}
Options fileOptions(this, tool, table, gg->ExtraFlagTable);
fileOptions.Parse(fc.CompileFlags.c_str());
- fileOptions.AddDefines(fc.CompileDefs.c_str());
- fileOptions.AddDefines(fc.CompileDefsConfig.c_str());
+ fileOptions.AddDefines(fc.CompileDefs);
+ fileOptions.AddDefines(fc.CompileDefsConfig);
// validate source level include directories
std::vector<std::string> includes;
this->AppendIncludeDirectories(includes, fc.IncludeDirs, **sf);
fileOptions.AddIncludes(includes);
- fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
+ fileOptions.OutputFlagMap(fout, 5);
fileOptions.OutputAdditionalIncludeDirectories(
- fout, "\t\t\t\t\t", "\n",
+ fout, 5,
ppLang == "CXX" && this->FortranProject ? "Fortran" : ppLang);
- fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n",
- ppLang);
+ fileOptions.OutputPreprocessorDefinitions(fout, 5, ppLang);
}
if (!fc.AdditionalDeps.empty()) {
fout << "\t\t\t\t\tAdditionalDependencies=\"" << fc.AdditionalDeps
return ret;
}
+void cmVS7GeneratorOptions::OutputFlag(std::ostream& fout, int indent,
+ const char* flag,
+ const std::string& content)
+{
+ fout.fill('\t');
+ fout.width(indent);
+ // write an empty string to get the fill level indent to print
+ fout << "";
+ fout << flag << "=\"";
+ fout << cmLocalVisualStudio7GeneratorEscapeForXML(content);
+ fout << "\"\n";
+}
+
// This class is used to parse an existing vs 7 project
// and extract the GUID
class cmVS7XMLParser : public cmXMLParser
class cmSourceFile;
class cmSourceGroup;
+class cmVS7GeneratorOptions : public cmVisualStudioGeneratorOptions
+{
+public:
+ cmVS7GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
+ cmVS7FlagTable const* table = nullptr,
+ cmVS7FlagTable const* extraTable = nullptr)
+ : cmVisualStudioGeneratorOptions(lg, tool, table, extraTable)
+ {
+ }
+ void OutputFlag(std::ostream& fout, int indent, const char* tag,
+ const std::string& content) override;
+};
+
/** \class cmLocalVisualStudio7Generator
* \brief Write Visual Studio .NET project files.
*
void CreateSingleVCProj(const std::string& lname, cmGeneratorTarget* tgt);
private:
- typedef cmVisualStudioGeneratorOptions Options;
+ typedef cmVS7GeneratorOptions Options;
typedef cmLocalVisualStudio7GeneratorFCInfo FCInfo;
std::string GetBuildTypeLinkerFlags(std::string rootLinkerFlags,
const std::string& configName);
#include "cmMSVC60LinkLineComputer.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "cmSystemTools.h"
+# include "cmSystemTools.h"
#endif
class cmOutputConverter;
#include <string>
#if !defined(CMAKE_USE_MACH_PARSER)
-#error "This file may be included only if CMAKE_USE_MACH_PARSER is enabled."
+# error "This file may be included only if CMAKE_USE_MACH_PARSER is enabled."
#endif
class cmMachOInternal;
argVs.reserve(expandedArgs.size());
char argvName[60];
for (unsigned int j = 0; j < expandedArgs.size(); ++j) {
- sprintf(argvName, "${ARGV%i}", j);
+ sprintf(argvName, "${ARGV%u}", j);
argVs.push_back(argvName);
}
// Invoke all the functions that were collected in the block.
{
// record commands until we hit the ENDMACRO
// at the ENDMACRO call we shift gears and start looking for invocations
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "macro")) {
+ if (lff.Name.Lower == "macro") {
this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) {
+ } else if (lff.Name.Lower == "endmacro") {
// if this is the endmacro for this macro then execute
if (!this->Depth) {
mf.AppendProperty("MACROS", this->Args[0].c_str());
bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) {
+ if (lff.Name.Lower == "endmacro") {
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str());
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <assert.h>
+#include <cstring>
#include <ctype.h>
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdlib.h>
-#include <string.h>
#include <utility>
#include "cmAlgorithms.h"
#include "cmake.h"
#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmVariableWatch.h"
+# include "cmVariableWatch.h"
#endif
class cmMessenger;
return true;
}
+void cmMakefile::MaybeWarnCMP0074(std::string const& pkg)
+{
+ // Warn if a <pkg>_ROOT variable we may use is set.
+ std::string const varName = pkg + "_ROOT";
+ const char* var = this->GetDefinition(varName);
+ std::string env;
+ cmSystemTools::GetEnv(varName, env);
+
+ bool const haveVar = var && *var;
+ bool const haveEnv = !env.empty();
+ if ((haveVar || haveEnv) && this->WarnedCMP0074.insert(varName).second) {
+ std::ostringstream w;
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0074) << "\n";
+ if (haveVar) {
+ w << "CMake variable " << varName << " is set to:\n"
+ << " " << var << "\n";
+ }
+ if (haveEnv) {
+ w << "Environment variable " << varName << " is set to:\n"
+ << " " << env << "\n";
+ }
+ w << "For compatibility, CMake is ignoring the variable.";
+ this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+}
+
cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const
{
return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries();
cmListFileBacktrace cmMakefile::GetBacktrace(cmCommandContext const& cc) const
{
cmListFileContext lfc;
- lfc.Name = cc.Name;
+ lfc.Name = cc.Name.Original;
lfc.Line = cc.Line;
lfc.FilePath = this->StateSnapshot.GetExecutionListFile();
return this->Backtrace.Push(lfc);
std::ostringstream msg;
msg << full_path << "(" << lff.Line << "): ";
- msg << lff.Name << "(";
+ msg << lff.Name.Original << "(";
bool expand = this->GetCMakeInstance()->GetTraceExpand();
std::string temp;
for (cmListFileArgument const& arg : lff.Arguments) {
return result;
}
- std::string name = lff.Name;
-
// Place this call on the call stack.
cmMakefileCall stack_manager(this, lff, status);
static_cast<void>(stack_manager);
// Lookup the command prototype.
- if (cmCommand* proto = this->GetState()->GetCommand(name)) {
+ if (cmCommand* proto =
+ this->GetState()->GetCommandByExactName(lff.Name.Lower)) {
// Clone the prototype.
std::unique_ptr<cmCommand> pcmd(proto->Clone());
pcmd->SetMakefile(this);
if (!invokeSucceeded || hadNestedError) {
if (!hadNestedError) {
// The command invocation requested that we report an error.
- std::string const error = name + " " + pcmd->GetError();
+ std::string const error =
+ std::string(lff.Name.Original) + " " + pcmd->GetError();
this->IssueMessage(cmake::FATAL_ERROR, error);
}
result = false;
} else {
if (!cmSystemTools::GetFatalErrorOccured()) {
std::string error = "Unknown CMake command \"";
- error += lff.Name;
+ error += lff.Name.Original;
error += "\".";
this->IssueMessage(cmake::FATAL_ERROR, error);
result = false;
return target;
}
+static void s_AddDefineFlag(std::string const& flag, std::string& dflags)
+{
+ // remove any \n\r
+ std::string::size_type initSize = dflags.size();
+ dflags += ' ';
+ dflags += flag;
+ std::string::iterator flagStart = dflags.begin() + initSize + 1;
+ std::replace(flagStart, dflags.end(), '\n', ' ');
+ std::replace(flagStart, dflags.end(), '\r', ' ');
+}
+
void cmMakefile::AddDefineFlag(std::string const& flag)
{
if (flag.empty()) {
}
// Update the string used for the old DEFINITIONS property.
- this->AddDefineFlag(flag, this->DefineFlagsOrig);
+ s_AddDefineFlag(flag, this->DefineFlagsOrig);
// If this is really a definition, update COMPILE_DEFINITIONS.
if (this->ParseDefineFlag(flag, false)) {
}
// Add this flag that does not look like a definition.
- this->AddDefineFlag(flag, this->DefineFlags);
+ s_AddDefineFlag(flag, this->DefineFlags);
}
-void cmMakefile::AddDefineFlag(std::string const& flag, std::string& dflags)
+static void s_RemoveDefineFlag(std::string const& flag, std::string& dflags)
{
- // remove any \n\r
- std::string::size_type initSize = dflags.size();
- dflags += std::string(" ") + flag;
- std::string::iterator flagStart = dflags.begin() + initSize + 1;
- std::replace(flagStart, dflags.end(), '\n', ' ');
- std::replace(flagStart, dflags.end(), '\r', ' ');
+ std::string::size_type const len = flag.length();
+ // Remove all instances of the flag that are surrounded by
+ // whitespace or the beginning/end of the string.
+ for (std::string::size_type lpos = dflags.find(flag, 0);
+ lpos != std::string::npos; lpos = dflags.find(flag, lpos)) {
+ std::string::size_type rpos = lpos + len;
+ if ((lpos <= 0 || isspace(dflags[lpos - 1])) &&
+ (rpos >= dflags.size() || isspace(dflags[rpos]))) {
+ dflags.erase(lpos, len);
+ } else {
+ ++lpos;
+ }
+ }
}
void cmMakefile::RemoveDefineFlag(std::string const& flag)
if (flag.empty()) {
return;
}
- std::string::size_type const len = flag.length();
+
// Update the string used for the old DEFINITIONS property.
- this->RemoveDefineFlag(flag, len, this->DefineFlagsOrig);
+ s_RemoveDefineFlag(flag, this->DefineFlagsOrig);
// If this is really a definition, update COMPILE_DEFINITIONS.
if (this->ParseDefineFlag(flag, true)) {
}
// Remove this flag that does not look like a definition.
- this->RemoveDefineFlag(flag, len, this->DefineFlags);
+ s_RemoveDefineFlag(flag, this->DefineFlags);
}
-void cmMakefile::RemoveDefineFlag(std::string const& flag,
- std::string::size_type len,
- std::string& dflags)
+void cmMakefile::AddCompileDefinition(std::string const& option)
{
- // Remove all instances of the flag that are surrounded by
- // whitespace or the beginning/end of the string.
- for (std::string::size_type lpos = dflags.find(flag, 0);
- lpos != std::string::npos; lpos = dflags.find(flag, lpos)) {
- std::string::size_type rpos = lpos + len;
- if ((lpos <= 0 || isspace(dflags[lpos - 1])) &&
- (rpos >= dflags.size() || isspace(dflags[rpos]))) {
- dflags.erase(lpos, len);
- } else {
- ++lpos;
- }
- }
+ this->AppendProperty("COMPILE_DEFINITIONS", option.c_str());
}
void cmMakefile::AddCompileOption(std::string const& option)
bool hasVersion = false;
// search for the right policy command
for (cmListFileFunction const& func : listFile.Functions) {
- if (cmSystemTools::LowerCase(func.Name) == "cmake_minimum_required") {
+ if (func.Name.Lower == "cmake_minimum_required") {
hasVersion = true;
break;
}
allowedCommands.insert("message");
isProblem = false;
for (cmListFileFunction const& func : listFile.Functions) {
- std::string name = cmSystemTools::LowerCase(func.Name);
- if (allowedCommands.find(name) == allowedCommands.end()) {
+ if (allowedCommands.find(func.Name.Lower) == allowedCommands.end()) {
isProblem = true;
break;
}
this->SetCheckCMP0000(true);
// Implicitly set the version for the user.
- this->SetPolicyVersion("2.4");
+ this->SetPolicyVersion("2.4", std::string());
}
}
bool hasProject = false;
// search for a project command
for (cmListFileFunction const& func : listFile.Functions) {
- if (cmSystemTools::LowerCase(func.Name) == "project") {
+ if (func.Name.Lower == "project") {
hasProject = true;
break;
}
// if no project command is found, add one
if (!hasProject) {
cmListFileFunction project;
- project.Name = "PROJECT";
+ project.Name.Lower = "project";
project.Arguments.emplace_back("Project", cmListFileArgument::Unquoted,
0);
listFile.Functions.insert(listFile.Functions.begin(), project);
// must be outside the following if() to keep it alive long enough
std::string nvalue;
- if (existingValue && (this->GetState()->GetCacheEntryType(name) ==
- cmStateEnums::UNINITIALIZED)) {
+ if (existingValue &&
+ (this->GetState()->GetCacheEntryType(name) ==
+ cmStateEnums::UNINITIALIZED)) {
// if this is not a force, then use the value from the cache
// if it is a force, then use the value being passed in
if (!force) {
std::vector<std::string> linkDirs;
cmSystemTools::ExpandListArgument(linkDirsProp, linkDirs);
- for (std::string const& linkDir : linkDirs) {
- std::string newdir = linkDir;
- // remove trailing slashes
- if (*linkDir.rbegin() == '/') {
- newdir = linkDir.substr(0, linkDir.size() - 1);
- }
+ for (std::string& linkDir : linkDirs) {
+ // Sanitize the path the same way the link_directories command does
+ // in case projects set the LINK_DIRECTORIES property directly.
+ cmSystemTools::ConvertToUnixSlashes(linkDir);
target.AddLinkDirectory(linkDir);
}
}
// Clear its dependencies. Otherwise, dependencies might persist
// over changes in CMakeLists.txt, making the information stale and
// hence useless.
- target->ClearDependencyInformation(*this, lname);
+ target->ClearDependencyInformation(*this);
if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
#ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch* vv = this->GetVariableWatch();
if (vv && !this->SuppressWatches) {
- bool const watch_function_executed = vv->VariableAccessed(
- name, def ? cmVariableWatch::VARIABLE_READ_ACCESS
- : cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS,
- def, this);
+ bool const watch_function_executed =
+ vv->VariableAccessed(name,
+ def ? cmVariableWatch::VARIABLE_READ_ACCESS
+ : cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS,
+ def, this);
if (watch_function_executed) {
// A callback was executed and may have caused re-allocation of the
return res;
}
-const char* cmMakefile::ExpandVariablesInString(std::string& source) const
+const std::string& cmMakefile::ExpandVariablesInString(
+ std::string& source) const
{
return this->ExpandVariablesInString(source, false, false);
}
-const char* cmMakefile::ExpandVariablesInString(
+const std::string& cmMakefile::ExpandVariablesInString(
std::string& source, bool escapeQuotes, bool noEscapes, bool atOnly,
const char* filename, long line, bool removeEmpty, bool replaceAt) const
{
this->IssueMessage(cmake::INTERNAL_ERROR,
"ExpandVariablesInString @ONLY called "
"on something with escapes.");
- return source.c_str();
+ return source;
}
// Variables used in the WARN case.
this->IssueMessage(cmake::AUTHOR_WARNING, msg);
}
- return source.c_str();
+ return source;
}
cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
return mtype;
}
-typedef enum { NORMAL, ENVIRONMENT, CACHE } t_domain;
+typedef enum
+{
+ NORMAL,
+ ENVIRONMENT,
+ CACHE
+} t_domain;
struct t_lookup
{
t_lookup()
const char* nextAt = strchr(in + 1, '@');
if (nextAt && nextAt != in + 1 &&
nextAt ==
- in + 1 + strspn(in + 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789/_.+-")) {
+ in + 1 +
+ strspn(in + 1,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789/_.+-")) {
std::string variable(in + 1, nextAt - in - 1);
std::string varresult = this->GetSafeDefinition(variable);
if (escapeQuotes) {
cmSourceFile* cmMakefile::GetSource(const std::string& sourceName,
cmSourceFileLocationKind kind) const
{
+ // First check "Known" paths (avoids the creation of cmSourceFileLocation)
+ if (kind == cmSourceFileLocationKind::Known) {
+ auto sfsi = this->KnownFileSearchIndex.find(sourceName);
+ if (sfsi != this->KnownFileSearchIndex.end()) {
+ return sfsi->second;
+ }
+ }
+
cmSourceFileLocation sfl(this, sourceName, kind);
auto name = this->GetCMakeInstance()->StripExtension(sfl.GetName());
#if defined(_WIN32) || defined(__APPLE__)
name = cmSystemTools::LowerCase(name);
#endif
this->SourceFileSearchIndex[name].push_back(sf);
+ // for "Known" paths add direct lookup (used for faster lookup in GetSource)
+ if (kind == cmSourceFileLocationKind::Known) {
+ this->KnownFileSearchIndex[sourceName] = sf;
+ }
return sf;
}
int cmMakefile::TryCompile(const std::string& srcdir,
const std::string& bindir,
const std::string& projectName,
- const std::string& targetName, bool fast,
+ const std::string& targetName, bool fast, int jobs,
const std::vector<std::string>* cmakeArgs,
std::string& output)
{
// change to the tests directory and run cmake
// use the cmake object instead of calling cmake
cmWorkingDirectory workdir(bindir);
+ if (workdir.Failed()) {
+ this->IssueMessage(cmake::FATAL_ERROR,
+ "Failed to set working directory to " + bindir + " : " +
+ std::strerror(workdir.GetLastResult()));
+ cmSystemTools::SetFatalErrorOccured();
+ this->IsSourceFileTryCompile = false;
+ return 1;
+ }
// make sure the same generator is used
// use this program as the cmake to be run, it should not
cmGlobalGenerator* gg =
cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName());
if (!gg) {
- this->IssueMessage(cmake::INTERNAL_ERROR, "Global generator '" +
+ this->IssueMessage(cmake::INTERNAL_ERROR,
+ "Global generator '" +
this->GetGlobalGenerator()->GetName() +
"' could not be created.");
cmSystemTools::SetFatalErrorOccured();
// finally call the generator to actually build the resulting project
int ret = this->GetGlobalGenerator()->TryCompile(
- srcdir, bindir, projectName, targetName, fast, output, this);
+ jobs, srcdir, bindir, projectName, targetName, fast, output, this);
this->IsSourceFileTryCompile = false;
return ret;
const char* cmMakefile::GetProperty(const std::string& prop) const
{
+ // Check for computed properties.
+ static std::string output;
+ if (prop == "TESTS") {
+ std::vector<std::string> keys;
+ // get list of keys
+ std::transform(this->Tests.begin(), this->Tests.end(),
+ std::back_inserter(keys),
+ [](decltype(this->Tests)::value_type const& pair) {
+ return pair.first;
+ });
+ output = cmJoin(keys, ";");
+ return output.c_str();
+ }
+
return this->StateSnapshot.GetDirectory().GetProperty(prop);
}
std::ostringstream m;
m << "Cannot set \"" << var << "\": current scope has no parent.";
this->IssueMessage(cmake::AUTHOR_WARNING, m.str());
+ return;
}
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ cmVariableWatch* vv = this->GetVariableWatch();
+ if (vv) {
+ vv->VariableAccessed(var, cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
+ varDef, this);
+ }
+#endif
}
cmTarget* cmMakefile::AddImportedTarget(const std::string& name,
{
// Create the target.
std::unique_ptr<cmTarget> target(
- new cmTarget(name, type, global ? cmTarget::VisibilityImportedGlobally
- : cmTarget::VisibilityImported,
+ new cmTarget(name, type,
+ global ? cmTarget::VisibilityImportedGlobally
+ : cmTarget::VisibilityImported,
this));
// Add to the set of available imported targets.
return this->DefineFlagsOrig.c_str();
}
-cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(
- cmPolicies::PolicyID id) const
+cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id,
+ bool parent_scope) const
{
- return this->StateSnapshot.GetPolicy(id);
+ return this->StateSnapshot.GetPolicy(id, parent_scope);
}
bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var)
assert(this->StateSnapshot.IsValid());
}
-bool cmMakefile::SetPolicyVersion(const char* version)
+bool cmMakefile::SetPolicyVersion(std::string const& version_min,
+ std::string const& version_max)
{
- return cmPolicies::ApplyPolicyVersion(this, version);
+ return cmPolicies::ApplyPolicyVersion(this, version_min, version_max);
}
bool cmMakefile::HasCMP0054AlreadyBeenReported(
#undef FEATURE_STRING
static const char* const C_STANDARDS[] = { "90", "99", "11" };
-static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17" };
+static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17", "20" };
bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
const std::string& feature,
} else {
e << "Specified";
}
- e << " unknown feature \"" << feature << "\" for "
- "target \""
+ e << " unknown feature \"" << feature
+ << "\" for "
+ "target \""
<< target->GetName() << "\".";
if (error) {
*error = e.str();
bool needCxx11 = false;
bool needCxx14 = false;
bool needCxx17 = false;
+ bool needCxx20 = false;
this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
- needCxx17);
+ needCxx17, needCxx20);
const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
if (!existingCxxStandard) {
/* clang-format off */
const char* const* needCxxLevel =
- needCxx17 ? &CXX_STANDARDS[3]
+ needCxx20 ? &CXX_STANDARDS[4]
+ : needCxx17 ? &CXX_STANDARDS[3]
: needCxx14 ? &CXX_STANDARDS[2]
: needCxx11 ? &CXX_STANDARDS[1]
: needCxx98 ? &CXX_STANDARDS[0]
void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
bool& needCxx98, bool& needCxx11,
- bool& needCxx14, bool& needCxx17) const
+ bool& needCxx14, bool& needCxx17,
+ bool& needCxx20) const
{
if (const char* propCxx98 =
this->GetDefinition("CMAKE_CXX98_COMPILE_FEATURES")) {
cmSystemTools::ExpandListArgument(propCxx17, props);
needCxx17 = std::find(props.begin(), props.end(), feature) != props.end();
}
+ if (const char* propCxx20 =
+ this->GetDefinition("CMAKE_CXX20_COMPILE_FEATURES")) {
+ std::vector<std::string> props;
+ cmSystemTools::ExpandListArgument(propCxx20, props);
+ needCxx20 = std::find(props.begin(), props.end(), feature) != props.end();
+ }
}
bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
bool needCxx11 = false;
bool needCxx14 = false;
bool needCxx17 = false;
+ bool needCxx20 = false;
this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
- needCxx17);
+ needCxx17, needCxx20);
const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
const char* const* existingCxxLevel = nullptr;
/* clang-format off */
const char* const* needCxxLevel =
- needCxx17 ? &CXX_STANDARDS[3]
+ needCxx20 ? &CXX_STANDARDS[4]
+ : needCxx17 ? &CXX_STANDARDS[3]
: needCxx14 ? &CXX_STANDARDS[2]
: needCxx11 ? &CXX_STANDARDS[1]
: needCxx98 ? &CXX_STANDARDS[0]
#include "cmake.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmSourceGroup.h"
+# include "cmSourceGroup.h"
#endif
class cmCommand;
*/
int TryCompile(const std::string& srcdir, const std::string& bindir,
const std::string& projectName, const std::string& targetName,
- bool fast, const std::vector<std::string>* cmakeArgs,
+ bool fast, int jobs,
+ const std::vector<std::string>* cmakeArgs,
std::string& output);
bool GetIsSourceFileTryCompile() const;
*/
void AddDefineFlag(std::string const& definition);
void RemoveDefineFlag(std::string const& definition);
+ void AddCompileDefinition(std::string const& definition);
void AddCompileOption(std::string const& option);
/** Create a new imported target with the name and type given. */
//@{
/**
- * Set, Push, Pop policy values for CMake.
- */
+ * Set, Push, Pop policy values for CMake.
+ */
bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
bool SetPolicy(const char* id, cmPolicies::PolicyStatus status);
- cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id) const;
- bool SetPolicyVersion(const char* version);
+ cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id,
+ bool parent_scope = false) const;
+ bool SetPolicyVersion(std::string const& version_min,
+ std::string const& version_max);
void RecordPolicies(cmPolicies::PolicyMap& pm);
//@}
* entry in the this->Definitions map. Also \@var\@ is
* expanded to match autoconf style expansions.
*/
- const char* ExpandVariablesInString(std::string& source) const;
- const char* ExpandVariablesInString(std::string& source, bool escapeQuotes,
- bool noEscapes, bool atOnly = false,
- const char* filename = nullptr,
- long line = -1, bool removeEmpty = false,
- bool replaceAt = false) const;
+ const std::string& ExpandVariablesInString(std::string& source) const;
+ const std::string& ExpandVariablesInString(
+ std::string& source, bool escapeQuotes, bool noEscapes,
+ bool atOnly = false, const char* filename = nullptr, long line = -1,
+ bool removeEmpty = false, bool replaceAt = false) const;
/**
* Remove any remaining variables in the string. Anything with ${var} or
~FunctionPushPop();
void Quiet() { this->ReportError = false; }
+
private:
cmMakefile* Makefile;
bool ReportError;
~MacroPushPop();
void Quiet() { this->ReportError = false; }
+
private:
cmMakefile* Makefile;
bool ReportError;
this->Makefile->PushScope();
}
~ScopePushPop() { this->Makefile->PopScope(); }
+
private:
cmMakefile* Makefile;
};
void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen);
void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen);
- // Maintain a stack of package names to determine the depth of find modules
- // we are currently being called with
- std::deque<std::string> FindPackageModuleStack;
+ // Maintain a stack of package roots to allow nested PACKAGE_ROOT_PATH
+ // searches
+ std::deque<std::vector<std::string>> FindPackageRootPathStack;
+
+ void MaybeWarnCMP0074(std::string const& pkg);
protected:
// add link libraries and directories to the target
typedef std::unordered_map<std::string, SourceFileVec> SourceFileMap;
SourceFileMap SourceFileSearchIndex;
+ // For "Known" paths we can store a direct filename to cmSourceFile map
+ std::unordered_map<std::string, cmSourceFile*> KnownFileSearchIndex;
+
// Tests
std::map<std::string, cmTest*> Tests;
std::string DefineFlags;
// Track the value of the computed DEFINITIONS property.
- void AddDefineFlag(std::string const& flag, std::string&);
- void RemoveDefineFlag(std::string const& flag, std::string::size_type,
- std::string&);
std::string DefineFlagsOrig;
#if defined(CMAKE_BUILD_WITH_CMAKE)
bool& needC99, bool& needC11) const;
void CheckNeededCxxLanguage(const std::string& feature, bool& needCxx98,
bool& needCxx11, bool& needCxx14,
- bool& needCxx17) const;
+ bool& needCxx17, bool& needCxx20) const;
bool HaveCStandardAvailable(cmTarget const* target,
const std::string& feature) const;
bool WarnUnused;
bool CheckSystemVars;
bool CheckCMP0000;
+ std::set<std::string> WarnedCMP0074;
bool IsSourceFileTryCompile;
mutable bool SuppressWatches;
};
this->LocalGenerator->GetCurrentBinaryDirectory(),
targetFullPathImport));
std::string implib;
- if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport,
- implib)) {
+ if (this->GeneratorTarget->GetImplibGNUtoMS(
+ this->ConfigName, targetFullPathImport, implib)) {
exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
}
#include <algorithm>
#include <memory> // IWYU pragma: keep
#include <sstream>
+#include <stddef.h>
#include <vector>
#include "cmGeneratedFileStream.h"
this->LocalGenerator->GetCurrentBinaryDirectory(),
targetFullPathImport));
std::string implib;
- if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport,
- implib)) {
+ if (this->GeneratorTarget->GetImplibGNUtoMS(
+ this->ConfigName, targetFullPathImport, implib)) {
libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
}
// Archiving rules never use a response file.
useResponseFileForObjects = false;
- // Limit the length of individual object lists to less than the
- // 32K command line length limit on Windows. We could make this a
- // platform file variable but this should work everywhere.
- archiveCommandLimit = 30000;
+ // Limit the length of individual object lists to less than half of
+ // the command line length limit (leaving half for other flags).
+ // This may result in several calls to the archiver.
+ if (size_t limit = cmSystemTools::CalculateCommandLineLengthLimit()) {
+ archiveCommandLimit = limit / 2;
+ } else {
+ archiveCommandLimit = 8000;
+ }
}
// Expand the rule variables.
source.GetFullPath(), workingDirectory, compileCommand);
}
+ // See if we need to use a compiler launcher like ccache or distcc
+ std::string compilerLauncher;
+ if (!compileCommands.empty() &&
+ (lang == "C" || lang == "CXX" || lang == "Fortran" ||
+ lang == "CUDA")) {
+ std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
+ const char* clauncher =
+ this->GeneratorTarget->GetProperty(clauncher_prop);
+ if (clauncher && *clauncher) {
+ compilerLauncher = clauncher;
+ }
+ }
+
// Maybe insert an include-what-you-use runner.
if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) {
std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint) ||
(cppcheck && *cppcheck)) {
std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile";
+ if (!compilerLauncher.empty()) {
+ // In __run_co_compile case the launcher command is supplied
+ // via --launcher=<maybe-list> and consumed
+ run_iwyu += " --launcher=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
+ compilerLauncher.clear();
+ }
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->LocalGenerator->EscapeForShell(iwyu);
}
}
- // Maybe insert a compiler launcher like ccache or distcc
- if (!compileCommands.empty() && (lang == "C" || lang == "CXX" ||
- lang == "Fortran" || lang == "CUDA")) {
- std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
- const char* clauncher =
- this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && *clauncher) {
- std::vector<std::string> launcher_cmd;
- cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true);
- for (std::string& i : launcher_cmd) {
- i = this->LocalGenerator->EscapeForShell(i);
- }
- std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
- compileCommands.front().insert(0, run_launcher);
+ // If compiler launcher was specified and not consumed above, it
+ // goes to the beginning of the command line.
+ if (!compileCommands.empty() && !compilerLauncher.empty()) {
+ std::vector<std::string> args;
+ cmSystemTools::ExpandListArgument(compilerLauncher, args, true);
+ for (std::string& i : args) {
+ i = this->LocalGenerator->EscapeForShell(i);
}
+ compileCommands.front().insert(0, cmJoin(args, " ") + " ");
}
std::string launcher;
// paths. Make sure PWD is set to the original name of the home
// output directory to help cmSystemTools to create the same
// translation table for the dependency scanning process.
- depCmd << "cd " << (this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(
- this->LocalGenerator->GetBinaryDirectory()),
- cmOutputConverter::SHELL))
+ depCmd << "cd "
+ << (this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(
+ this->LocalGenerator->GetBinaryDirectory()),
+ cmOutputConverter::SHELL))
<< " && ";
#endif
// Generate a call this signature:
const std::string& linkRuleVar)
{
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
- if (this->GeneratorTarget->HasImplibGNUtoMS()) {
+ if (this->GeneratorTarget->HasImplibGNUtoMS(this->ConfigName)) {
std::string ruleVar = "CMAKE_";
ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
ruleVar += "_GNUtoMS_RULE";
#include "cmSystemTools.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmsys/SystemInformation.hxx"
+# include "cmsys/SystemInformation.hxx"
#endif
#include <sstream>
{
return this->TargetLinkLanguage + "_" +
cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
- "_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName(
- this->GetGeneratorTarget()->GetName());
+ "_LINKER__" +
+ cmGlobalNinjaGenerator::EncodeRuleName(
+ this->GetGeneratorTarget()->GetName());
}
std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule() const
{
return this->TargetLinkLanguage + "_" +
cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
- "_DEVICE_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName(
- this->GetGeneratorTarget()->GetName());
+ "_DEVICE_LINKER__" +
+ cmGlobalNinjaGenerator::EncodeRuleName(
+ this->GetGeneratorTarget()->GetName());
}
struct cmNinjaRemoveNoOpCommands
std::string responseFlag;
if (!useResponseFile) {
vars.Objects = "$in";
- vars.LinkLibraries = "$LINK_LIBRARIES";
+ vars.LinkLibraries = "$LINK_PATH $LINK_LIBRARIES";
} else {
std::string cmakeVarLang = "CMAKE_";
cmakeVarLang += this->TargetLinkLanguage;
this->GetGlobalGenerator()->AddRule(
"CMAKE_SYMLINK_EXECUTABLE",
this->GetLocalGenerator()->BuildCommandLine(commandLines),
- "Creating executable symlink $out", "Rule for creating "
- "executable symlink.",
+ "Creating executable symlink $out",
+ "Rule for creating "
+ "executable symlink.",
/*depfile*/ "",
/*deptype*/ "",
/*rspfile*/ "",
this->GetGlobalGenerator()->AddRule(
"CMAKE_SYMLINK_LIBRARY",
this->GetLocalGenerator()->BuildCommandLine(commandLines),
- "Creating library symlink $out", "Rule for creating "
- "library symlink.",
+ "Creating library symlink $out",
+ "Rule for creating "
+ "library symlink.",
/*depfile*/ "",
/*deptype*/ "",
/*rspfile*/ "",
const char* linkCmd = mf->GetDefinition(linkCmdVar);
if (linkCmd) {
std::string linkCmdStr = linkCmd;
- if (this->GetGeneratorTarget()->HasImplibGNUtoMS()) {
+ if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) {
std::string ruleVar = "CMAKE_";
ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
ruleVar += "_GNUtoMS_RULE";
static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule());
- const std::string rspfile =
+ const std::string rspfile = this->ConvertToNinjaPath(
std::string(cmake::GetCMakeFilesDirectoryPostSlash()) +
- genTarget.GetName() + ".rsp";
+ genTarget.GetName() + ".rsp");
// Gather order-only dependencies.
cmNinjaDeps orderOnlyDeps;
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
const cmStateEnums::TargetType targetType = gt.GetType();
- this->GetBuildFileStream() << "# Link build statements for "
- << cmState::GetTargetTypeName(targetType)
- << " target " << this->GetTargetName() << "\n\n";
+ this->GetBuildFileStream()
+ << "# Link build statements for " << cmState::GetTargetTypeName(targetType)
+ << " target " << this->GetTargetName() << "\n\n";
cmNinjaDeps emptyDeps;
cmNinjaVars vars;
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
EnsureParentDirectoryExists(impLibPath);
- if (genTarget.HasImportLibrary()) {
+ if (genTarget.HasImportLibrary(cfgName)) {
byproducts.push_back(targetOutputImplib);
}
}
preLinkCmdLines.push_back("cd " + homeOutDir);
}
- vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines);
- std::string postBuildCmdLine = localGen.BuildCommandLine(postBuildCmdLines);
+ vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link",
+ this->GeneratorTarget);
+ std::string postBuildCmdLine = localGen.BuildCommandLine(
+ postBuildCmdLines, "post-build", this->GeneratorTarget);
cmNinjaVars symlinkVars;
bool const symlinkNeeded =
globalGen.GetRuleCmdLength(this->LanguageLinkerRule());
}
- const std::string rspfile =
+ const std::string rspfile = this->ConvertToNinjaPath(
std::string(cmake::GetCMakeFilesDirectoryPostSlash()) + gt.GetName() +
- ".rsp";
+ ".rsp");
// Gather order-only dependencies.
cmNinjaDeps orderOnlyDeps;
cmMakefile* mf = this->GetMakefile();
std::string flags = "$FLAGS";
- std::string rspfile;
- std::string rspcontent;
+ std::string responseFlag;
bool const lang_supports_response = !(lang == "RC" || lang == "CUDA");
if (lang_supports_response && this->ForceResponseFile()) {
std::string const responseFlagVar =
"CMAKE_" + lang + "_RESPONSE_FILE_FLAG";
- std::string responseFlag =
- this->Makefile->GetSafeDefinition(responseFlagVar);
+ responseFlag = this->Makefile->GetSafeDefinition(responseFlagVar);
if (responseFlag.empty()) {
responseFlag = "@";
}
- rspfile = "$RSP_FILE";
- responseFlag += rspfile;
- rspcontent = " $DEFINES $INCLUDES $FLAGS";
- flags = std::move(responseFlag);
- vars.Defines = "";
- vars.Includes = "";
}
- // Tell ninja dependency format so all deps can be loaded into a database
- std::string deptype;
- std::string depfile;
- std::string cldeps;
- if (explicitPP) {
- // The explicit preprocessing step will handle dependency scanning.
- } else if (this->NeedDepTypeMSVC(lang)) {
- deptype = "msvc";
- depfile.clear();
- flags += " /showIncludes";
- } else if (mf->IsOn("CMAKE_NINJA_CMCLDEPS_" + lang)) {
- // For the MS resource compiler we need cmcldeps, but skip dependencies
- // for source-file try_compile cases because they are always fresh.
- if (!mf->GetIsSourceFileTryCompile()) {
- deptype = "gcc";
- depfile = "$DEP_FILE";
- const std::string cl = mf->GetDefinition("CMAKE_C_COMPILER")
- ? mf->GetSafeDefinition("CMAKE_C_COMPILER")
- : mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
- cldeps = "\"";
- cldeps += cmSystemTools::GetCMClDepsCommand();
- cldeps += "\" " + lang + " " + vars.Source + " $DEP_FILE $out \"";
- cldeps += mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX");
- cldeps += "\" \"" + cl + "\" ";
- }
- } else {
- deptype = "gcc";
- const char* langdeptype = mf->GetDefinition("CMAKE_NINJA_DEPTYPE_" + lang);
- if (langdeptype) {
- deptype = langdeptype;
- }
- depfile = "$DEP_FILE";
- const std::string flagsName = "CMAKE_DEPFILE_FLAGS_" + lang;
- std::string depfileFlags = mf->GetSafeDefinition(flagsName);
- if (!depfileFlags.empty()) {
- cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE");
- cmSystemTools::ReplaceString(depfileFlags, "<OBJECT>", "$out");
- cmSystemTools::ReplaceString(depfileFlags, "<CMAKE_C_COMPILER>",
- mf->GetDefinition("CMAKE_C_COMPILER"));
- flags += " " + depfileFlags;
- }
- }
-
- vars.Flags = flags.c_str();
- vars.DependencyFile = depfile.c_str();
-
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
vars.Source = "$in";
// Preprocessing and compilation use the same flags.
- ppVars.Flags = vars.Flags;
+ std::string ppFlags = flags;
// Move preprocessor definitions to the preprocessor rule.
ppVars.Defines = vars.Defines;
// compilation rule still needs them for the INCLUDE directive.
ppVars.Includes = vars.Includes;
+ // If using a response file, move defines, includes, and flags into it.
+ std::string ppRspFile;
+ std::string ppRspContent;
+ if (!responseFlag.empty()) {
+ ppRspFile = "$RSP_FILE";
+ ppRspContent = std::string(" ") + ppVars.Defines + " " +
+ ppVars.Includes + " " + ppFlags;
+ ppFlags = responseFlag + ppRspFile;
+ ppVars.Defines = "";
+ ppVars.Includes = "";
+ }
+
+ ppVars.Flags = ppFlags.c_str();
+
// Rule for preprocessing source file.
std::vector<std::string> ppCmds;
cmSystemTools::ExpandListArgument(ppCmd, ppCmds);
std::string const cmake = this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
ppCmds.push_back(
- cmake + " -E cmake_ninja_depends"
- " --tdi=" +
- tdi + " --pp=$out"
- " --dep=$DEP_FILE" +
+ cmake +
+ " -E cmake_ninja_depends"
+ " --tdi=" +
+ tdi +
+ " --pp=$out"
+ " --dep=$DEP_FILE" +
(needDyndep ? " --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE" : ""));
std::string const ppCmdLine =
ppComment << "Rule for preprocessing " << lang << " files.";
std::ostringstream ppDesc;
ppDesc << "Building " << lang << " preprocessed $out";
- this->GetGlobalGenerator()->AddRule(this->LanguagePreprocessRule(lang),
- ppCmdLine, ppDesc.str(),
- ppComment.str(), ppDepfile, ppDeptype,
- /*rspfile*/ "",
- /*rspcontent*/ "",
- /*restat*/ "",
- /*generator*/ false);
+ this->GetGlobalGenerator()->AddRule(
+ this->LanguagePreprocessRule(lang), ppCmdLine, ppDesc.str(),
+ ppComment.str(), ppDepfile, ppDeptype, ppRspFile, ppRspContent,
+ /*restat*/ "",
+ /*generator*/ false);
}
if (needDyndep) {
// Run CMake dependency scanner on preprocessed output.
std::string const cmake = this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- ddCmds.push_back(cmake + " -E cmake_ninja_dyndep"
- " --tdi=" +
- tdi + " --dd=$out"
- " " +
+ ddCmds.push_back(cmake +
+ " -E cmake_ninja_dyndep"
+ " --tdi=" +
+ tdi +
+ " --dd=$out"
+ " " +
ddInput);
std::string const ddCmdLine =
/*generator*/ false);
}
+ // If using a response file, move defines, includes, and flags into it.
+ std::string rspfile;
+ std::string rspcontent;
+ if (!responseFlag.empty()) {
+ rspfile = "$RSP_FILE";
+ rspcontent =
+ std::string(" ") + vars.Defines + " " + vars.Includes + " " + flags;
+ flags = responseFlag + rspfile;
+ vars.Defines = "";
+ vars.Includes = "";
+ }
+
+ // Tell ninja dependency format so all deps can be loaded into a database
+ std::string deptype;
+ std::string depfile;
+ std::string cldeps;
+ if (explicitPP) {
+ // The explicit preprocessing step will handle dependency scanning.
+ } else if (this->NeedDepTypeMSVC(lang)) {
+ deptype = "msvc";
+ depfile.clear();
+ flags += " /showIncludes";
+ } else if (mf->IsOn("CMAKE_NINJA_CMCLDEPS_" + lang)) {
+ // For the MS resource compiler we need cmcldeps, but skip dependencies
+ // for source-file try_compile cases because they are always fresh.
+ if (!mf->GetIsSourceFileTryCompile()) {
+ deptype = "gcc";
+ depfile = "$DEP_FILE";
+ const std::string cl = mf->GetDefinition("CMAKE_C_COMPILER")
+ ? mf->GetSafeDefinition("CMAKE_C_COMPILER")
+ : mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
+ cldeps = "\"";
+ cldeps += cmSystemTools::GetCMClDepsCommand();
+ cldeps += "\" " + lang + " " + vars.Source + " $DEP_FILE $out \"";
+ cldeps += mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX");
+ cldeps += "\" \"" + cl + "\" ";
+ }
+ } else {
+ deptype = "gcc";
+ const char* langdeptype = mf->GetDefinition("CMAKE_NINJA_DEPTYPE_" + lang);
+ if (langdeptype) {
+ deptype = langdeptype;
+ }
+ depfile = "$DEP_FILE";
+ const std::string flagsName = "CMAKE_DEPFILE_FLAGS_" + lang;
+ std::string depfileFlags = mf->GetSafeDefinition(flagsName);
+ if (!depfileFlags.empty()) {
+ cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE");
+ cmSystemTools::ReplaceString(depfileFlags, "<OBJECT>", "$out");
+ cmSystemTools::ReplaceString(depfileFlags, "<CMAKE_C_COMPILER>",
+ mf->GetDefinition("CMAKE_C_COMPILER"));
+ flags += " " + depfileFlags;
+ }
+ }
+
+ vars.Flags = flags.c_str();
+ vars.DependencyFile = depfile.c_str();
+
// Rule for compiling object file.
std::vector<std::string> compileCmds;
if (lang == "CUDA") {
cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
}
+ // See if we need to use a compiler launcher like ccache or distcc
+ std::string compilerLauncher;
+ if (!compileCmds.empty() &&
+ (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) {
+ std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
+ const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
+ if (clauncher && *clauncher) {
+ compilerLauncher = clauncher;
+ }
+ }
+
// Maybe insert an include-what-you-use runner.
if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) {
std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
std::string run_iwyu = this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
run_iwyu += " -E __run_co_compile";
+ if (!compilerLauncher.empty()) {
+ // In __run_co_compile case the launcher command is supplied
+ // via --launcher=<maybe-list> and consumed
+ run_iwyu += " --launcher=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
+ compilerLauncher.clear();
+ }
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->GetLocalGenerator()->EscapeForShell(iwyu);
}
}
- // Maybe insert a compiler launcher like ccache or distcc
- if (!compileCmds.empty() &&
- (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) {
- std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
- const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && *clauncher) {
- std::vector<std::string> launcher_cmd;
- cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true);
- for (std::string& i : launcher_cmd) {
- i = this->LocalGenerator->EscapeForShell(i);
- }
- std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
- compileCmds.front().insert(0, run_launcher);
+ // If compiler launcher was specified and not consumed above, it
+ // goes to the beginning of the command line.
+ if (!compileCmds.empty() && !compilerLauncher.empty()) {
+ std::vector<std::string> args;
+ cmSystemTools::ExpandListArgument(compilerLauncher, args, true);
+ for (std::string& i : args) {
+ i = this->LocalGenerator->EscapeForShell(i);
}
+ compileCmds.front().insert(0, cmJoin(args, " ") + " ");
}
if (!compileCmds.empty()) {
orderOnlyDeps.erase(std::unique(orderOnlyDeps.begin(), orderOnlyDeps.end()),
orderOnlyDeps.end());
+ // The phony target must depend on at least one input or ninja will explain
+ // that "output ... of phony edge with no inputs doesn't exist" and consider
+ // the phony output "dirty".
+ if (orderOnlyDeps.empty()) {
+ // Any path that always exists will work here. It would be nice to
+ // use just "." but that is not supported by Ninja < 1.7.
+ std::string tgtDir;
+ tgtDir += this->LocalGenerator->GetCurrentBinaryDirectory();
+ tgtDir += "/";
+ tgtDir += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir));
+ }
+
{
cmNinjaDeps orderOnlyTarget;
orderOnlyTarget.push_back(this->OrderDependsTargetForTarget());
std::string const objectFileDir =
cmSystemTools::GetFilenamePath(objectFileName);
+ bool const lang_supports_response =
+ !(language == "RC" || language == "CUDA");
+ int const commandLineLengthLimit =
+ ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0;
+
cmNinjaVars vars;
vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
vars["DEFINES"] = this->ComputeDefines(source, language);
vars["INCLUDES"] = this->ComputeIncludes(source, language);
+
if (!this->NeedDepTypeMSVC(language)) {
- vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- objectFileName + ".d", cmOutputConverter::SHELL);
+ bool replaceExt(false);
+ if (!language.empty()) {
+ std::string repVar = "CMAKE_";
+ repVar += language;
+ repVar += "_DEPFILE_EXTENSION_REPLACE";
+ replaceExt = this->Makefile->IsOn(repVar);
+ }
+ if (!replaceExt) {
+ // use original code
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileName + ".d", cmOutputConverter::SHELL);
+ } else {
+ // Replace the original source file extension with the
+ // depend file extension.
+ std::string dependFileName =
+ cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d";
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileDir + "/" + dependFileName, cmOutputConverter::SHELL);
+ }
}
this->ExportObjectCompileCommand(
this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
ppVars);
+ std::string const ppRspFile = ppFileName + ".rsp";
+
this->GetGlobalGenerator()->WriteBuild(
this->GetBuildFileStream(), ppComment, ppRule, ppOutputs, ppImplicitOuts,
- ppExplicitDeps, ppImplicitDeps, ppOrderOnlyDeps, ppVars);
+ ppExplicitDeps, ppImplicitDeps, ppOrderOnlyDeps, ppVars, ppRspFile,
+ commandLineLengthLimit);
}
if (needDyndep) {
std::string const dyndep = this->GetDyndepFilePath(language);
this->SetMsvcTargetPdbVariable(vars);
- bool const lang_supports_response =
- !(language == "RC" || language == "CUDA");
- int const commandLineLengthLimit =
- ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0;
std::string const rspfile = objectFileName + ".rsp";
this->GetGlobalGenerator()->WriteBuild(
std::string escapedSourceFileName = sourceFileName;
if (!cmSystemTools::FileIsFullPath(sourceFileName)) {
- escapedSourceFileName = cmSystemTools::CollapseFullPath(
- escapedSourceFileName, this->GetGlobalGenerator()
- ->GetCMakeInstance()
- ->GetHomeOutputDirectory());
+ escapedSourceFileName =
+ cmSystemTools::CollapseFullPath(escapedSourceFileName,
+ this->GetGlobalGenerator()
+ ->GetCMakeInstance()
+ ->GetHomeOutputDirectory());
}
escapedSourceFileName = this->LocalGenerator->ConvertToOutputFormat(
this->GetBuildFileStream(),
"Utility command for " + this->GetTargetName(), outputs, deps);
} else {
- std::string command =
- this->GetLocalGenerator()->BuildCommandLine(commands);
+ std::string command = this->GetLocalGenerator()->BuildCommandLine(
+ commands, "utility", this->GeneratorTarget);
const char* echoStr =
this->GetGeneratorTarget()->GetProperty("EchoString");
std::string desc;
#include <assert.h>
#include <ctype.h>
#include <set>
-#include <sstream>
+#include <string.h>
#include <vector>
#include "cmAlgorithms.h"
use the caret character itself (^), use two in a row (^^).
*/
-int cmOutputConverter::Shell__CharIsWhitespace(char c)
+/* Some helpers to identify character classes */
+static int Shell__CharIsWhitespace(char c)
{
return ((c == ' ') || (c == '\t'));
}
-int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c)
+static int Shell__CharNeedsQuotesOnUnix(char c)
{
return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
(c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
(c == '\\'));
}
-int cmOutputConverter::Shell__CharNeedsQuotesOnWindows(char c)
+static int Shell__CharNeedsQuotesOnWindows(char c)
{
return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
(c == '>') || (c == '|') || (c == '^'));
}
+static int Shell__CharIsMakeVariableName(char c)
+{
+ return c && (c == '_' || isalpha((static_cast<int>(c))));
+}
+
int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
{
/* On Windows the built-in command shell echo never needs quotes. */
return 0;
}
-int cmOutputConverter::Shell__CharIsMakeVariableName(char c)
-{
- return c && (c == '_' || isalpha((static_cast<int>(c))));
-}
-
const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c)
{
while (*c == '$' && *(c + 1) == '(') {
std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
{
- std::ostringstream out;
+ /* Output will be at least as long as input string. */
+ std::string out;
+ out.reserve(strlen(in));
/* String iterator. */
const char* c;
/* Add the opening quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) {
if (flags & Shell_Flag_IsUnix) {
- out << '"';
+ out += '"';
}
- out << '\'';
+ out += '\'';
} else {
- out << '"';
+ out += '"';
}
}
if (skip != c) {
/* Copy to the end of the make variable references. */
while (c != skip) {
- out << *c++;
+ out += *c++;
}
/* The make variable reference eliminates any escaping needed
quoted argument. */
if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
/* This character needs a backslash to escape it. */
- out << '\\';
+ out += '\\';
}
} else if (flags & Shell_Flag_EchoWindows) {
/* On Windows the built-in command shell echo never needs escaping. */
backslashes. */
while (windows_backslashes > 0) {
--windows_backslashes;
- out << '\\';
+ out += '\\';
}
/* Add the backslash to escape the double-quote. */
- out << '\\';
+ out += '\\';
} else {
/* We encountered a normal character. This eliminates any
escaping needed for preceding backslashes. */
if (flags & Shell_Flag_Make) {
/* In Makefiles a dollar is written $$. The make tool will
replace it with just $ before passing it to the shell. */
- out << "$$";
+ out += "$$";
} else if (flags & Shell_Flag_VSIDE) {
/* In a VS IDE a dollar is written "$". If this is written in
an un-quoted argument it starts a quoted segment, inserts
argument it ends quoting, inserts the $ and restarts
quoting. Either way the $ is isolated from surrounding
text to avoid looking like a variable reference. */
- out << "\"$\"";
+ out += "\"$\"";
} else {
/* Otherwise a dollar is written just $. */
- out << '$';
+ out += '$';
}
} else if (*c == '#') {
if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
/* In Watcom WMake makefiles a pound is written $#. The make
tool will replace it with just # before passing it to the
shell. */
- out << "$#";
+ out += "$#";
} else {
/* Otherwise a pound is written just #. */
- out << '#';
+ out += '#';
}
} else if (*c == '%') {
if ((flags & Shell_Flag_VSIDE) ||
((flags & Shell_Flag_Make) &&
((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
/* In the VS IDE, NMake, or MinGW make a percent is written %%. */
- out << "%%";
+ out += "%%";
} else {
/* Otherwise a percent is written just %. */
- out << '%';
+ out += '%';
}
} else if (*c == ';') {
if (flags & Shell_Flag_VSIDE) {
inserts the ; and ends the segment. If it is written in a
quoted argument it ends quoting, inserts the ; and restarts
quoting. Either way the ; is isolated. */
- out << "\";\"";
+ out += "\";\"";
} else {
/* Otherwise a semicolon is written just ;. */
- out << ';';
+ out += ';';
}
} else {
/* Store this character. */
- out << *c;
+ out += *c;
}
}
/* Add enough backslashes to escape any trailing ones. */
while (windows_backslashes > 0) {
--windows_backslashes;
- out << '\\';
+ out += '\\';
}
/* Add the closing quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) {
- out << '\'';
+ out += '\'';
if (flags & Shell_Flag_IsUnix) {
- out << '"';
+ out += '"';
}
} else {
- out << '"';
+ out += '"';
}
}
- return out.str();
+ return out;
}
private:
cmState* GetState() const;
- static int Shell__CharIsWhitespace(char c);
- static int Shell__CharNeedsQuotesOnUnix(char c);
- static int Shell__CharNeedsQuotesOnWindows(char c);
static int Shell__CharNeedsQuotes(char c, int flags);
- static int Shell__CharIsMakeVariableName(char c);
static const char* Shell__SkipMakeVariables(const char* c);
static int Shell__ArgumentNeedsQuotes(const char* in, int flags);
static std::string Shell__GetArgument(const char* in, int flags);
parseFromArgV = true;
argIter++; // move past PARSE_ARGV
if (!cmSystemTools::StringToULong(argIter->c_str(), &argvStart)) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, "PARSE_ARGV index '" +
- *argIter +
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "PARSE_ARGV index '" + *argIter +
"' is not an unsigned integer");
cmSystemTools::SetFatalErrorOccured();
return true;
return true;
}
-bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
+bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf,
+ std::string const& version_min,
+ std::string const& version_max)
{
- std::string ver = "2.4.0";
-
- if (version && strlen(version) > 0) {
- ver = version;
- }
-
- unsigned int majorVer = 2;
- unsigned int minorVer = 0;
- unsigned int patchVer = 0;
- unsigned int tweakVer = 0;
-
- // parse the string
- if (sscanf(ver.c_str(), "%u.%u.%u.%u", &majorVer, &minorVer, &patchVer,
- &tweakVer) < 2) {
+ // Parse components of the minimum version.
+ unsigned int minMajor = 2;
+ unsigned int minMinor = 0;
+ unsigned int minPatch = 0;
+ unsigned int minTweak = 0;
+ if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &minMajor, &minMinor,
+ &minPatch, &minTweak) < 2) {
std::ostringstream e;
- e << "Invalid policy version value \"" << ver << "\". "
+ e << "Invalid policy version value \"" << version_min << "\". "
<< "A numeric major.minor[.patch[.tweak]] must be given.";
mf->IssueMessage(cmake::FATAL_ERROR, e.str());
return false;
}
// it is an error if the policy version is less than 2.4
- if (majorVer < 2 || (majorVer == 2 && minorVer < 4)) {
+ if (minMajor < 2 || (minMajor == 2 && minMinor < 4)) {
mf->IssueMessage(
cmake::FATAL_ERROR,
"Compatibility with CMake < 2.4 is not supported by CMake >= 3.0. "
// It is an error if the policy version is greater than the running
// CMake.
- if (majorVer > cmVersion::GetMajorVersion() ||
- (majorVer == cmVersion::GetMajorVersion() &&
- minorVer > cmVersion::GetMinorVersion()) ||
- (majorVer == cmVersion::GetMajorVersion() &&
- minorVer == cmVersion::GetMinorVersion() &&
- patchVer > cmVersion::GetPatchVersion()) ||
- (majorVer == cmVersion::GetMajorVersion() &&
- minorVer == cmVersion::GetMinorVersion() &&
- patchVer == cmVersion::GetPatchVersion() &&
- tweakVer > cmVersion::GetTweakVersion())) {
+ if (minMajor > cmVersion::GetMajorVersion() ||
+ (minMajor == cmVersion::GetMajorVersion() &&
+ minMinor > cmVersion::GetMinorVersion()) ||
+ (minMajor == cmVersion::GetMajorVersion() &&
+ minMinor == cmVersion::GetMinorVersion() &&
+ minPatch > cmVersion::GetPatchVersion()) ||
+ (minMajor == cmVersion::GetMajorVersion() &&
+ minMinor == cmVersion::GetMinorVersion() &&
+ minPatch == cmVersion::GetPatchVersion() &&
+ minTweak > cmVersion::GetTweakVersion())) {
std::ostringstream e;
e << "An attempt was made to set the policy version of CMake to \""
- << version << "\" which is greater than this version of CMake. "
+ << version_min << "\" which is greater than this version of CMake. "
<< "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.";
return false;
}
+ unsigned int polMajor = minMajor;
+ unsigned int polMinor = minMinor;
+ unsigned int polPatch = minPatch;
+
+ if (!version_max.empty()) {
+ // Parse components of the maximum version.
+ unsigned int maxMajor = 0;
+ unsigned int maxMinor = 0;
+ unsigned int maxPatch = 0;
+ unsigned int maxTweak = 0;
+ if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &maxMajor, &maxMinor,
+ &maxPatch, &maxTweak) < 2) {
+ 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());
+ return false;
+ }
+
+ // It is an error if the min version is greater than the max version.
+ if (minMajor > maxMajor || (minMajor == maxMajor && minMinor > maxMinor) ||
+ (minMajor == maxMajor && minMinor == maxMinor &&
+ minPatch > maxPatch) ||
+ (minMajor == maxMajor && minMinor == maxMinor &&
+ minPatch == maxPatch && minTweak > maxTweak)) {
+ std::ostringstream e;
+ e << "Policy VERSION range \"" << version_min << "..." << version_max
+ << "\""
+ << " specifies a larger minimum than maximum.";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+
+ // Use the max version as the policy version.
+ polMajor = maxMajor;
+ polMinor = maxMinor;
+ polPatch = maxPatch;
+ }
+
+ return cmPolicies::ApplyPolicyVersion(mf, polMajor, polMinor, polPatch);
+}
+
+bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
+ unsigned int minorVer,
+ unsigned int patchVer)
+{
// now loop over all the policies and set them as appropriate
std::vector<cmPolicies::PolicyID> ancientPolicies;
for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;
std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id)
{
std::ostringstream msg;
- msg << "Policy " << idToString(id) << " is not set: "
- ""
- << idToShortDescription(id) << " "
- "Run \"cmake --help-policy "
- << idToString(id) << "\" for "
- "policy details. "
- "Use the cmake_policy command to set the policy "
- "and suppress this warning.";
+ msg << "Policy " << idToString(id)
+ << " is not set: "
+ ""
+ << idToShortDescription(id)
+ << " "
+ "Run \"cmake --help-policy "
+ << idToString(id)
+ << "\" for "
+ "policy details. "
+ "Use the cmake_policy command to set the policy "
+ "and suppress this warning.";
return msg.str();
}
std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id)
{
std::ostringstream error;
- error << "Policy " << idToString(id) << " is not set to NEW: "
- ""
- << idToShortDescription(id) << " "
- "Run \"cmake --help-policy "
+ error << "Policy " << idToString(id)
+ << " is not set to NEW: "
+ ""
+ << idToShortDescription(id)
+ << " "
+ "Run \"cmake --help-policy "
<< idToString(id)
<< "\" for "
"policy details. "
"CMake now requires this policy to be set to NEW by the project. "
"The policy may be set explicitly using the code\n"
" cmake_policy(SET "
- << idToString(id) << " NEW)\n"
- "or by upgrading all policies with the code\n"
- " cmake_policy(VERSION "
+ << idToString(id)
+ << " NEW)\n"
+ "or by upgrading all policies with the code\n"
+ " cmake_policy(VERSION "
<< idToVersion(id)
<< ") # or later\n"
"Run \"cmake --help-command cmake_policy\" for more information.";
3, 0, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0051, "List TARGET_OBJECTS in SOURCES target property.", \
3, 1, 0, cmPolicies::WARN) \
- SELECT(POLICY, CMP0052, "Reject source and build dirs in installed " \
- "INTERFACE_INCLUDE_DIRECTORIES.", \
+ SELECT(POLICY, CMP0052, \
+ "Reject source and build dirs in installed " \
+ "INTERFACE_INCLUDE_DIRECTORIES.", \
3, 1, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0053, \
"Simplify variable reference and escape sequence evaluation.", 3, 1, \
3, 10, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0072, \
"FindOpenGL prefers GLVND by default when available.", 3, 11, 0, \
- cmPolicies::WARN)
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0073, \
+ "Do not produce legacy _LIB_DEPENDS cache entries.", 3, 12, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0074, "find_package uses PackageName_ROOT variables.", 3, \
+ 12, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0075, \
+ "Include file check macros honor CMAKE_REQUIRED_LIBRARIES.", 3, 12, \
+ 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
F(CMP0063) \
F(CMP0065) \
F(CMP0068) \
- F(CMP0069)
+ F(CMP0069) \
+ F(CMP0073)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
*
- * See the cmake wiki section on
- * <a href="https://cmake.org/Wiki/CMake/Policies">policies</a>
- * for an overview of this class's purpose
+ * See the cmake-policies(7) manual for an overview of this class's purpose.
*/
class cmPolicies
{
static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id);
///! Set a policy level for this listfile
- static bool ApplyPolicyVersion(cmMakefile* mf, const char* version);
+ static bool ApplyPolicyVersion(cmMakefile* mf,
+ std::string const& version_min,
+ std::string const& version_max);
+ static bool ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
+ unsigned int minorVer, unsigned int patchVer);
///! return a warning string for a given policy
static std::string GetPolicyWarning(cmPolicies::PolicyID id);
#include "cmProcessOutput.h"
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
unsigned int cmProcessOutput::defaultCodepage =
KWSYS_ENCODING_DEFAULT_CODEPAGE;
#endif
};
/**
- * Find encoding enum value for given encoding \a name.
- * \param name a encoding name.
- * \return encoding enum value or Auto if \a name was not found.
- */
+ * Find encoding enum value for given encoding \a name.
+ * \param name a encoding name.
+ * \return encoding enum value or Auto if \a name was not found.
+ */
static Encoding FindEncoding(std::string const& name);
/// The code page that is used as internal encoding to which we will encode.
}
virtual ~OutputParser() {}
+
protected:
/** Implement in a subclass to process a chunk of data. It should
return true only if it is interested in more data. */
#include "cmProjectCommand.h"
#include "cmsys/RegularExpression.hxx"
+#include <functional>
#include <sstream>
#include <stdio.h>
+#include "cmAlgorithms.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
bool haveVersion = false;
bool haveLanguages = false;
bool haveDescription = false;
+ bool haveHomepage = false;
std::string version;
std::string description;
+ std::string homepage;
std::vector<std::string> languages;
+ std::function<void()> missedValueReporter;
+ auto resetReporter = [&missedValueReporter]() {
+ missedValueReporter = std::function<void()>();
+ };
enum Doing
{
DoingDescription,
+ DoingHomepage,
DoingLanguages,
DoingVersion
};
return true;
}
haveLanguages = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingLanguages;
+ if (!languages.empty()) {
+ std::string msg =
+ "the following parameters must be specified after LANGUAGES "
+ "keyword: ";
+ msg += cmJoin(languages, ", ");
+ msg += '.';
+ this->Makefile->IssueMessage(cmake::WARNING, msg);
+ }
} else if (args[i] == "VERSION") {
if (haveVersion) {
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
return true;
}
haveVersion = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingVersion;
+ missedValueReporter = [this, &resetReporter]() {
+ this->Makefile->IssueMessage(
+ cmake::WARNING,
+ "VERSION keyword not followed by a value or was followed by a "
+ "value that expanded to nothing.");
+ resetReporter();
+ };
} else if (args[i] == "DESCRIPTION") {
if (haveDescription) {
this->Makefile->IssueMessage(
return true;
}
haveDescription = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingDescription;
+ missedValueReporter = [this, &resetReporter]() {
+ this->Makefile->IssueMessage(
+ cmake::WARNING,
+ "DESCRIPTION keyword not followed by a value or was followed "
+ "by a value that expanded to nothing.");
+ resetReporter();
+ };
+ } else if (args[i] == "HOMEPAGE_URL") {
+ if (haveHomepage) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, "HOMEPAGE_URL may be specified at most once.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ haveHomepage = true;
+ doing = DoingHomepage;
+ missedValueReporter = [this, &resetReporter]() {
+ this->Makefile->IssueMessage(
+ cmake::WARNING,
+ "HOMEPAGE_URL keyword not followed by a value or was followed "
+ "by a value that expanded to nothing.");
+ resetReporter();
+ };
} else if (doing == DoingVersion) {
doing = DoingLanguages;
version = args[i];
+ resetReporter();
} else if (doing == DoingDescription) {
doing = DoingLanguages;
description = args[i];
+ resetReporter();
+ } else if (doing == DoingHomepage) {
+ doing = DoingLanguages;
+ homepage = args[i];
+ resetReporter();
} else // doing == DoingLanguages
{
languages.push_back(args[i]);
}
}
- if (haveVersion && !haveLanguages && !languages.empty()) {
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
+
+ if ((haveVersion || haveDescription || haveHomepage) && !haveLanguages &&
+ !languages.empty()) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
- "project with VERSION must use LANGUAGES before language names.");
+ "project with VERSION, DESCRIPTION or HOMEPAGE_URL must "
+ "use LANGUAGES before language names.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
vv = projectName + "_VERSION_TWEAK";
this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", vb[3]);
this->Makefile->AddDefinition(vv, vb[3]);
+ // Also, try set top level variables
+ TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION", vs.c_str());
+ TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MAJOR", vb[0]);
+ TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MINOR", vb[1]);
+ TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_PATCH", vb[2]);
+ TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_TWEAK", vb[3]);
} else if (cmp0048 != cmPolicies::OLD) {
// Set project VERSION variables to empty
std::vector<std::string> vv;
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");
+ }
std::string vw;
for (std::string const& i : vv) {
const char* v = this->Makefile->GetDefinition(i);
if (haveDescription) {
this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str());
- // Set the CMAKE_PROJECT_DESCRIPTION variable to be the highest-level
- // project name in the tree. If there are two project commands
- // in the same CMakeLists.txt file, and it is the top level
- // CMakeLists.txt file, then go with the last one.
- if (!this->Makefile->GetDefinition("CMAKE_PROJECT_DESCRIPTION") ||
- (this->Makefile->IsRootMakefile())) {
- this->Makefile->AddDefinition("CMAKE_PROJECT_DESCRIPTION",
- description.c_str());
- this->Makefile->AddCacheDefinition(
- "CMAKE_PROJECT_DESCRIPTION", description.c_str(),
- "Value Computed by CMake", cmStateEnums::STATIC);
- }
+ this->Makefile->AddDefinition(projectName + "_DESCRIPTION",
+ description.c_str());
+ TopLevelCMakeVarCondSet("CMAKE_PROJECT_DESCRIPTION", description.c_str());
+ }
+
+ if (haveHomepage) {
+ this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage.c_str());
+ this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL",
+ homepage.c_str());
+ TopLevelCMakeVarCondSet("CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str());
}
if (languages.empty()) {
}
return true;
}
+
+void cmProjectCommand::TopLevelCMakeVarCondSet(const char* const name,
+ const char* const value)
+{
+ // Set the CMAKE_PROJECT_XXX variable to be the highest-level
+ // project name in the tree. If there are two project commands
+ // in the same CMakeLists.txt file, and it is the top level
+ // CMakeLists.txt file, then go with the last one.
+ if (!this->Makefile->GetDefinition(name) ||
+ (this->Makefile->IsRootMakefile())) {
+ this->Makefile->AddDefinition(name, value);
+ this->Makefile->AddCacheDefinition(name, value, "Value Computed by CMake",
+ cmStateEnums::STATIC);
+ }
+}
*/
bool InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status) override;
+
+private:
+ void TopLevelCMakeVarCondSet(const char* name, const char* value);
};
#endif
}
}
// Test if this is a value option and change the existing value
- if (!optName.empty() && (std::find(valueOpts.begin(), valueOpts.end(),
- optName) != valueOpts.end())) {
+ if (!optName.empty() &&
+ (std::find(valueOpts.begin(), valueOpts.end(), optName) !=
+ valueOpts.end())) {
const Iter existItNext(existIt + 1);
const CIter fitNext(fit + 1);
if ((existItNext != baseOpts.end()) && (fitNext != fitEnd)) {
/// @brief Returns the generator name in upper case
static std::string GeneratorNameUpper(GeneratorT genType);
- /// @brief Returns a the string escaped and enclosed in quotes
+ /// @brief Returns the string escaped and enclosed in quotes
static std::string Quoted(std::string const& text);
static std::string QuotedCommand(std::vector<std::string> const& command);
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGen.h"
#include "cmQtAutoGenInitializer.h"
+#include "cmQtAutoGen.h"
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
if (!qrc.Unique) {
base += qrc.PathChecksum;
}
+
+ qrc.LockFile = base;
+ qrc.LockFile += ".lock";
+
qrc.InfoFile = base;
qrc.InfoFile += "Info.cmake";
+
qrc.SettingsFile = base;
qrc.SettingsFile += "Settings.txt";
}
std::vector<std::string> ccOutput;
ccOutput.push_back(qrc.RccFile);
+
cmCustomCommandLines commandLines;
- {
+ if (this->MultiConfig) {
+ // Build for all configurations
+ for (std::string const& config : this->ConfigsList) {
+ cmCustomCommandLine currentLine;
+ currentLine.push_back(cmSystemTools::GetCMakeCommand());
+ currentLine.push_back("-E");
+ currentLine.push_back("cmake_autorcc");
+ currentLine.push_back(qrc.InfoFile);
+ currentLine.push_back(config);
+ commandLines.push_back(std::move(currentLine));
+ }
+ } else {
cmCustomCommandLine currentLine;
currentLine.push_back(cmSystemTools::GetCMakeCommand());
currentLine.push_back("-E");
currentLine.push_back("cmake_autorcc");
currentLine.push_back(qrc.InfoFile);
- currentLine.push_back("$<CONFIGURATION>");
+ currentLine.push_back("$<CONFIG>");
commandLines.push_back(std::move(currentLine));
}
std::string ccComment = "Automatic RCC for ";
std::vector<std::string> const& list) {
CWrite(key, cmJoin(list, ";"));
};
- auto CWriteNestedLists = [&CWrite](
- const char* key, std::vector<std::vector<std::string>> const& lists) {
- std::vector<std::string> seplist;
- for (const std::vector<std::string>& list : lists) {
- std::string blist = "{";
- blist += cmJoin(list, ";");
- blist += "}";
- seplist.push_back(std::move(blist));
- }
- CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));
- };
+ auto CWriteNestedLists =
+ [&CWrite](const char* key,
+ std::vector<std::vector<std::string>> const& lists) {
+ std::vector<std::string> seplist;
+ for (const std::vector<std::string>& list : lists) {
+ std::string blist = "{";
+ blist += cmJoin(list, ";");
+ blist += "}";
+ seplist.push_back(std::move(blist));
+ }
+ CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));
+ };
auto CWriteSet = [&CWrite](const char* key,
std::set<std::string> const& list) {
CWrite(key, cmJoin(list, ";"));
ofs << "set(" << key << " "
<< cmOutputConverter::EscapeForCMake(value) << ")\n";
};
- auto CWriteMap = [&ofs](
- const char* key, std::map<std::string, std::string> const& map) {
- for (auto const& item : map) {
- ofs << "set(" << key << "_" << item.first << " "
- << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
- }
- };
+ auto CWriteMap =
+ [&ofs](const char* key,
+ std::map<std::string, std::string> const& map) {
+ for (auto const& item : map) {
+ ofs << "set(" << key << "_" << item.first << " "
+ << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
+ }
+ };
// Write
ofs << "# Configurations\n";
CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->RccListOptions, ";"));
ofs << "# Rcc job\n";
+ CWrite("ARCC_LOCK_FILE", qrc.LockFile);
CWrite("ARCC_SOURCE", qrc.QrcFile);
CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
CWrite("ARCC_OUTPUT_NAME",
}
public:
+ std::string LockFile;
std::string QrcFile;
std::string QrcName;
std::string PathChecksum;
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
+#include "cmQtAutoGen.h"
#include "cmsys/FStream.hxx"
return cmSystemTools::RemoveFile(filename);
}
-bool cmQtAutoGenerator::FileSystem::Touch(std::string const& filename)
+bool cmQtAutoGenerator::FileSystem::Touch(std::string const& filename,
+ bool create)
{
std::lock_guard<std::mutex> lock(Mutex_);
- return cmSystemTools::Touch(filename, false);
+ return cmSystemTools::Touch(filename, create);
}
bool cmQtAutoGenerator::FileSystem::MakeDirectory(std::string const& dirname)
auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
// The OLD/WARN behavior for policy CMP0053 caused a speed regression.
// https://gitlab.kitware.com/cmake/cmake/issues/17570
- makefile->SetPolicyVersion("3.9");
+ makefile->SetPolicyVersion("3.9", std::string());
gg.SetCurrentMakefile(makefile.get());
success = this->Init(makefile.get());
}
bool FileDiffers(std::string const& filename, std::string const& content);
bool FileRemove(std::string const& filename);
- bool Touch(std::string const& filename);
+ bool Touch(std::string const& filename, bool create = false);
// -- Directory access
bool MakeDirectory(std::string const& dirname);
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGen.h"
#include "cmQtAutoGeneratorMocUic.h"
+#include "cmQtAutoGen.h"
#include <algorithm>
#include <array>
#include "cmake.h"
#if defined(__APPLE__)
-#include <unistd.h>
+# include <unistd.h>
#endif
// -- Class methods
JobHandleT jobHandle(new JobMocT(std::move(jobPre.SourceFile), FileName,
std::move(jobPre.IncludeString)));
if (jobPre.self) {
- // Read depdendencies from this source
+ // Read dependencies from this source
static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
}
if (!wrk.Gen().ParallelJobPushMoc(jobHandle)) {
if (!macroName.empty()) {
JobHandleT jobHandle(
new JobMocT(std::string(FileName), std::string(), std::string()));
- // Read depdendencies from this source
+ // Read dependencies from this source
static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
success = wrk.Gen().ParallelJobPushMoc(jobHandle);
}
std::string error;
// Insert default filter for Q_PLUGIN_METADATA
if (Base().QtVersionMajor != 4) {
- pushFilter("Q_PLUGIN_METADATA", "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
- "[^\\)]*FILE[ \t]*\"([^\"]+)\"",
+ pushFilter("Q_PLUGIN_METADATA",
+ "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
+ "[^\\)]*FILE[ \t]*\"([^\"]+)\"",
error);
}
// Insert user defined dependency filters
// Compare list sizes
if (sources.size() != options.size()) {
std::ostringstream ost;
- ost << "files/options lists sizes missmatch (" << sources.size() << "/"
+ ost << "files/options lists sizes mismatch (" << sources.size() << "/"
<< options.size() << ")";
Log().ErrorFile(GeneratorT::UIC, InfoFile(), ost.str());
return false;
error += Quoted(mocJob.IncluderFile);
error += " and\n ";
error += Quoted(otherJob.IncluderFile);
- error += "\ncontain the the same moc include string ";
+ error += "\ncontain the same moc include string ";
error += Quoted(mocJob.IncludeString);
error += "\nbut the moc file would be generated from different "
"source files\n ";
error += Quoted(uicJob.IncluderFile);
error += " and\n ";
error += Quoted(otherJob.IncluderFile);
- error += "\ncontain the the same uic include string ";
+ error += "\ncontain the same uic include string ";
error += Quoted(uicJob.IncludeString);
error += "\nbut the uic file would be generated from different "
"source files\n ";
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGen.h"
#include "cmQtAutoGeneratorRcc.h"
+#include "cmQtAutoGen.h"
#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
+#include "cmFileLockResult.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmUVHandlePtr.h"
RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
// - Job
+ LockFile_ = InfoGet("ARCC_LOCK_FILE");
QrcFile_ = InfoGet("ARCC_SOURCE");
QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
// - Validity checks
+ if (LockFile_.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Lock file name missing");
+ return false;
+ }
if (SettingsFile_.empty()) {
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Settings file name missing");
return false;
switch (Stage_) {
// -- Initialize
case StageT::SETTINGS_READ:
- SettingsFileRead();
- SetStage(StageT::TEST_QRC_RCC_FILES);
+ if (SettingsFileRead()) {
+ SetStage(StageT::TEST_QRC_RCC_FILES);
+ } else {
+ SetStage(StageT::FINISH);
+ }
break;
// -- Change detection
return res;
}
-void cmQtAutoGeneratorRcc::SettingsFileRead()
+bool cmQtAutoGeneratorRcc::SettingsFileRead()
{
// Compose current settings strings
{
}
}
+ // Make sure the settings file exists
+ if (!FileSys().FileExists(SettingsFile_, true)) {
+ // Touch the settings file to make sure it exists
+ FileSys().Touch(SettingsFile_, true);
+ }
+
+ // Lock the lock file
+ {
+ // Make sure the lock file exists
+ if (!FileSys().FileExists(LockFile_, true)) {
+ if (!FileSys().Touch(LockFile_, true)) {
+ Log().ErrorFile(GeneratorT::RCC, LockFile_,
+ "Lock file creation failed");
+ Error_ = true;
+ return false;
+ }
+ }
+ // Lock the lock file
+ cmFileLockResult lockResult =
+ LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1));
+ if (!lockResult.IsOk()) {
+ Log().ErrorFile(GeneratorT::RCC, LockFile_,
+ "File lock failed: " + lockResult.GetOutputMessage());
+ Error_ = true;
+ return false;
+ }
+ }
+
// Read old settings
{
std::string content;
if (FileSys().FileRead(content, SettingsFile_)) {
SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc"));
- // In case any setting changed remove the old settings file.
+ // In case any setting changed clear the old settings file.
// This triggers a full rebuild on the next run if the current
// build is aborted before writing the current settings in the end.
if (SettingsChanged_) {
- FileSys().FileRemove(SettingsFile_);
+ FileSys().FileWrite(GeneratorT::RCC, SettingsFile_, "");
}
} else {
SettingsChanged_ = true;
}
}
+
+ return true;
}
void cmQtAutoGeneratorRcc::SettingsFileWrite()
Error_ = true;
}
}
+
+ // Unlock the lock file
+ LockFileLock_.Release();
}
bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmFileLock.h"
#include "cmQtAutoGenerator.h"
#include "cm_uv.h"
void PollStage();
void SetStage(StageT stage);
// -- Settings file
- void SettingsFileRead();
+ bool SettingsFileRead();
void SettingsFileWrite();
// -- Tests
bool TestQrcRccFiles();
std::string RccExecutable_;
std::vector<std::string> RccListOptions_;
// -- Job
+ std::string LockFile_;
+ cmFileLock LockFileLock_;
std::string QrcFile_;
std::string QrcFileName_;
std::string QrcFileDir_;
, NoteDirective("^.. note::[ \t]*(.*)$")
, ModuleRST("^#\\[(=*)\\[\\.rst:$")
, CMakeRole("(:cmake)?:("
- "command|generator|variable|module|policy|"
+ "command|generator|variable|envvar|module|policy|"
"prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|"
"prop_test|prop_tgt|"
"manual"
"):`(<*([^`<]|[^` \t]<)*)([ \t]+<[^`]*>)?`")
+ , InlineLink("`(<*([^`<]|[^` \t]<)*)([ \t]+<[^`]*>)?`_")
+ , InlineLiteral("``([^`]*)``")
, Substitution("(^|[^A-Za-z0-9_])"
"((\\|[^| \t\r\n]([^|\r\n]*[^| \t\r\n])?\\|)(__|_|))"
"([^A-Za-z0-9_]|$)")
this->LastLineEndedInColonColon = false;
// A line starting in .. is an explicit markup start.
- if (line == ".." || (line.size() >= 3 && line[0] == '.' && line[1] == '.' &&
- isspace(line[2]))) {
+ if (line == ".." ||
+ (line.size() >= 3 && line[0] == '.' && line[1] == '.' &&
+ isspace(line[2]))) {
this->Reset();
this->Markup =
(line.find_first_not_of(" \t", 2) == std::string::npos ? MarkupEmpty
if (inlineMarkup) {
std::string line = this->ReplaceSubstitutions(line_in);
std::string::size_type pos = 0;
- while (this->CMakeRole.find(line.c_str() + pos)) {
- this->OS << line.substr(pos, this->CMakeRole.start());
- std::string text = this->CMakeRole.match(3);
- // If a command reference has no explicit target and
- // no explicit "(...)" then add "()" to the text.
- if (this->CMakeRole.match(2) == "command" &&
- this->CMakeRole.match(5).empty() &&
- text.find_first_of("()") == std::string::npos) {
- text += "()";
+ for (;;) {
+ std::string::size_type* first = nullptr;
+ std::string::size_type role_start = std::string::npos;
+ std::string::size_type link_start = std::string::npos;
+ std::string::size_type lit_start = std::string::npos;
+ if (this->CMakeRole.find(line.c_str() + pos)) {
+ role_start = this->CMakeRole.start();
+ first = &role_start;
+ }
+ if (this->InlineLiteral.find(line.c_str() + pos)) {
+ lit_start = this->InlineLiteral.start();
+ if (!first || lit_start < *first) {
+ first = &lit_start;
+ }
+ }
+ if (this->InlineLink.find(line.c_str() + pos)) {
+ link_start = this->InlineLink.start();
+ if (!first || link_start < *first) {
+ first = &link_start;
+ }
+ }
+ if (first == &role_start) {
+ this->OS << line.substr(pos, role_start);
+ std::string text = this->CMakeRole.match(3);
+ // If a command reference has no explicit target and
+ // no explicit "(...)" then add "()" to the text.
+ if (this->CMakeRole.match(2) == "command" &&
+ this->CMakeRole.match(5).empty() &&
+ text.find_first_of("()") == std::string::npos) {
+ text += "()";
+ }
+ this->OS << "``" << text << "``";
+ pos += this->CMakeRole.end();
+ } else if (first == &lit_start) {
+ this->OS << line.substr(pos, lit_start);
+ std::string text = this->InlineLiteral.match(1);
+ pos += this->InlineLiteral.end();
+ this->OS << "``" << text << "``";
+ } else if (first == &link_start) {
+ this->OS << line.substr(pos, link_start);
+ std::string text = this->InlineLink.match(1);
+ bool escaped = false;
+ for (char c : text) {
+ if (escaped) {
+ escaped = false;
+ this->OS << c;
+ } else if (c == '\\') {
+ escaped = true;
+ } else {
+ this->OS << c;
+ }
+ }
+ pos += this->InlineLink.end();
+ } else {
+ break;
}
- this->OS << "``" << text << "``";
- pos += this->CMakeRole.end();
}
this->OS << line.substr(pos) << "\n";
} else {
cmsys::RegularExpression NoteDirective;
cmsys::RegularExpression ModuleRST;
cmsys::RegularExpression CMakeRole;
+ cmsys::RegularExpression InlineLink;
+ cmsys::RegularExpression InlineLiteral;
cmsys::RegularExpression Substitution;
cmsys::RegularExpression TocTreeLink;
this->TargetImpLib = targetImpLib;
}
- // Create a struct to hold the varibles passed into
+ // Create a struct to hold the variables passed into
// ExpandRuleVariables
struct RuleVariables
{
void AddCMakePrefixPath(const std::string& variable);
void AddEnvPrefixPath(const std::string& variable, bool stripBin = false);
void AddSuffixes(const std::vector<std::string>& suffixes);
-
-protected:
void AddPrefixPaths(const std::vector<std::string>& paths,
const char* base = nullptr);
+
+protected:
void AddPathInternal(const std::string& path, const char* base = nullptr);
cmFindCommon* FC;
#include <algorithm>
#ifdef _WIN32
-#include "io.h"
+# include "io.h"
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
#include <cassert>
value = cachedValue;
}
if (!cachedValue.empty() && cachedValue != value) {
- setErrorMessage(errorMessage, std::string("\"") + key +
+ setErrorMessage(errorMessage,
+ std::string("\"") + key +
"\" is set but incompatible with configured " +
keyDescription + " value.");
return false;
std::string platform = request.Data[kPLATFORM_KEY].asString();
if (buildDirectory.empty()) {
- setErrorMessage(errorMessage, std::string("\"") + kBUILD_DIRECTORY_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kBUILD_DIRECTORY_KEY +
"\" is missing.");
return false;
}
cmake* cm = CMakeInstance();
if (cmSystemTools::PathExists(buildDirectory)) {
if (!cmSystemTools::FileIsDirectory(buildDirectory)) {
- setErrorMessage(errorMessage, std::string("\"") + kBUILD_DIRECTORY_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kBUILD_DIRECTORY_KEY +
"\" exists but is not a directory.");
return false;
}
}
if (sourceDirectory.empty()) {
- setErrorMessage(errorMessage, std::string("\"") + kSOURCE_DIRECTORY_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kSOURCE_DIRECTORY_KEY +
"\" is unset but required.");
return false;
}
if (!cmSystemTools::FileIsDirectory(sourceDirectory)) {
- setErrorMessage(errorMessage, std::string("\"") + kSOURCE_DIRECTORY_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kSOURCE_DIRECTORY_KEY +
"\" is not a directory.");
return false;
}
if (generator.empty()) {
- setErrorMessage(errorMessage, std::string("\"") + kGENERATOR_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kGENERATOR_KEY +
"\" is unset but required.");
return false;
}
return info.name == generator;
});
if (baseIt == generators.end()) {
- setErrorMessage(errorMessage, std::string("Generator \"") + generator +
+ setErrorMessage(errorMessage,
+ std::string("Generator \"") + generator +
"\" not supported.");
return false;
}
size_t result =
hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags);
for (auto const& i : in.IncludePathList) {
- result = result ^ (hash<std::string>()(i.first) ^
- (i.second ? std::numeric_limits<size_t>::max() : 0));
+ result = result ^
+ (hash<std::string>()(i.first) ^
+ (i.second ? std::numeric_limits<size_t>::max() : 0));
}
for (auto const& i : in.Defines) {
result = result ^ hash<std::string>()(i);
for (const auto& include : includes) {
fileData.IncludePathList.push_back(
- std::make_pair(include, target->IsSystemIncludeDirectory(
- include, config, fileData.Language)));
+ std::make_pair(include,
+ target->IsSystemIncludeDirectory(
+ include, config, fileData.Language)));
}
}
const std::string defPropName =
"COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
if (const char* config_defs = file->GetProperty(defPropName)) {
- lg->AppendDefines(defines, genexInterpreter.Evaluate(
- config_defs, COMPILE_DEFINITIONS));
+ lg->AppendDefines(
+ defines,
+ genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS));
}
defines.insert(ld.Defines.begin(), ld.Defines.end());
* Get the cmMakefile instance for which the source file was created.
*/
cmMakefile const* GetMakefile() const { return this->Makefile; }
+
private:
cmMakefile const* const Makefile;
bool AmbiguousDirectory;
tokenizedPath = tokenizePath(sgFilesPath);
}
- if (tokenizedPath.size() > 1) {
+ if (!tokenizedPath.empty()) {
tokenizedPath.pop_back();
+ if (tokenizedPath.empty()) {
+ tokenizedPath.push_back("");
+ }
+
sg = makefile.GetOrCreateSourceGroup(tokenizedPath);
if (!sg) {
/* Disable some warnings. */
#if defined(_MSC_VER)
-#pragma warning(disable : 4018)
-#pragma warning(disable : 4127)
-#pragma warning(disable : 4131)
-#pragma warning(disable : 4244)
-#pragma warning(disable : 4251)
-#pragma warning(disable : 4267)
-#pragma warning(disable : 4305)
-#pragma warning(disable : 4309)
-#pragma warning(disable : 4706)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4018)
+# pragma warning(disable : 4127)
+# pragma warning(disable : 4131)
+# pragma warning(disable : 4244)
+# pragma warning(disable : 4251)
+# pragma warning(disable : 4267)
+# pragma warning(disable : 4305)
+# pragma warning(disable : 4309)
+# pragma warning(disable : 4706)
+# pragma warning(disable : 4786)
#endif
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
-#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
-#pragma GCC diagnostic ignored "-Wconversion"
-#pragma GCC diagnostic ignored "-Wsign-compare"
-#endif
-#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 403
-#pragma GCC diagnostic ignored "-Wsign-conversion"
-#endif
+# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
+# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wsign-compare"
+# endif
+# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 403
+# pragma GCC diagnostic ignored "-Wsign-conversion"
+# endif
#endif
/* Make sure isatty is available. */
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h>
-#if defined(_MSC_VER)
-#define isatty _isatty
-#endif
+# include <io.h>
+# if defined(_MSC_VER)
+# define isatty _isatty
+# endif
#else
-#include <unistd.h> // IWYU pragma: export
+# include <unistd.h> // IWYU pragma: export
#endif
/* Make sure malloc and free are available on QNX. */
#ifdef __QNX__
-#include <malloc.h>
+# include <malloc.h>
#endif
/* Disable features we do not need. */
#include "cmCommand.h"
#include "cmDefinitions.h"
#include "cmDisallowedCommand.h"
+#include "cmGlobVerificationManager.h"
#include "cmListFileCache.h"
#include "cmStatePrivate.h"
#include "cmStateSnapshot.h"
, MSYSShell(false)
{
this->CacheManager = new cmCacheManager;
+ this->GlobVerificationManager = new cmGlobVerificationManager;
}
cmState::~cmState()
{
delete this->CacheManager;
+ delete this->GlobVerificationManager;
cmDeleteAll(this->BuiltinCommands);
cmDeleteAll(this->ScriptedCommands);
}
this->CacheManager->AddCacheEntry(key, value, helpString, type);
}
+bool cmState::DoWriteGlobVerifyTarget() const
+{
+ return this->GlobVerificationManager->DoWriteVerifyTarget();
+}
+
+std::string const& cmState::GetGlobVerifyScript() const
+{
+ return this->GlobVerificationManager->GetVerifyScript();
+}
+
+std::string const& cmState::GetGlobVerifyStamp() const
+{
+ return this->GlobVerificationManager->GetVerifyStamp();
+}
+
+bool cmState::SaveVerificationScript(const std::string& path)
+{
+ return this->GlobVerificationManager->SaveVerificationScript(path);
+}
+
+void cmState::AddGlobCacheEntry(bool recurse, bool listDirectories,
+ bool followSymlinks,
+ const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ cmListFileBacktrace const& backtrace)
+{
+ this->GlobVerificationManager->AddCacheEntry(
+ recurse, listDirectories, followSymlinks, relative, expression, files,
+ variable, backtrace);
+}
+
void cmState::RemoveCacheEntry(std::string const& key)
{
this->CacheManager->RemoveCacheEntry(key);
cmCommand* cmState::GetCommand(std::string const& name) const
{
- std::string sName = cmSystemTools::LowerCase(name);
+ return GetCommandByExactName(cmSystemTools::LowerCase(name));
+}
+
+cmCommand* cmState::GetCommandByExactName(std::string const& name) const
+{
std::map<std::string, cmCommand*>::const_iterator pos;
- pos = this->ScriptedCommands.find(sName);
+ pos = this->ScriptedCommands.find(name);
if (pos != this->ScriptedCommands.end()) {
return pos->second;
}
- pos = this->BuiltinCommands.find(sName);
+ pos = this->BuiltinCommands.find(name);
if (pos != this->BuiltinCommands.end()) {
return pos->second;
}
#include "cmDefinitions.h"
#include "cmLinkedTree.h"
+#include "cmListFileCache.h"
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmPropertyDefinitionMap.h"
class cmCacheManager;
class cmCommand;
+class cmGlobVerificationManager;
class cmPropertyDefinition;
class cmStateSnapshot;
class cmMessenger;
bool GetIsGeneratorMultiConfig() const;
void SetIsGeneratorMultiConfig(bool b);
+ // Returns a command from its name, case insensitive, or nullptr
cmCommand* GetCommand(std::string const& name) const;
+ // Returns a command from its name, or nullptr
+ cmCommand* GetCommandByExactName(std::string const& name) const;
+
void AddBuiltinCommand(std::string const& name, cmCommand* command);
void AddDisallowedCommand(std::string const& name, cmCommand* command,
cmPolicies::PolicyID policy, const char* message);
const char* helpString,
cmStateEnums::CacheEntryType type);
+ bool DoWriteGlobVerifyTarget() const;
+ std::string const& GetGlobVerifyScript() const;
+ std::string const& GetGlobVerifyStamp() const;
+ bool SaveVerificationScript(const std::string& path);
+ void AddGlobCacheEntry(bool recurse, bool listDirectories,
+ bool followSymlinks, const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ cmListFileBacktrace const& bt);
+
std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions;
std::vector<std::string> EnabledLanguages;
std::map<std::string, cmCommand*> BuiltinCommands;
std::map<std::string, cmCommand*> ScriptedCommands;
cmPropertyMap GlobalProperties;
cmCacheManager* CacheManager;
+ cmGlobVerificationManager* GlobVerificationManager;
cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>
BuildsystemDirectory;
#include <algorithm>
#include <assert.h>
#include <iterator>
-#include <stdio.h>
+#include <string>
#include "cmAlgorithms.h"
#include "cmDefinitions.h"
#include "cmake.h"
#if !defined(_WIN32)
-#include <sys/utsname.h>
+# include <sys/utsname.h>
#endif
#if defined(__CYGWIN__)
-#include "cmSystemTools.h"
+# include "cmSystemTools.h"
#endif
cmStateSnapshot::cmStateSnapshot(cmState* state)
}
}
-cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(
- cmPolicies::PolicyID id) const
+cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id,
+ bool parent_scope) const
{
cmPolicies::PolicyStatus status = cmPolicies::GetPolicyStatus(id);
cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root =
dir->DirectoryEnd->PolicyRoot;
for (; leaf != root; ++leaf) {
+ if (parent_scope) {
+ parent_scope = false;
+ continue;
+ }
if (leaf->IsDefined(id)) {
status = leaf->Get(id);
return status;
this->SetDefinition("CMAKE_HOST_SOLARIS", "1");
#endif
- char temp[1024];
- sprintf(temp, "%d", cmVersion::GetMinorVersion());
- this->SetDefinition("CMAKE_MINOR_VERSION", temp);
- sprintf(temp, "%d", cmVersion::GetMajorVersion());
- this->SetDefinition("CMAKE_MAJOR_VERSION", temp);
- sprintf(temp, "%d", cmVersion::GetPatchVersion());
- this->SetDefinition("CMAKE_PATCH_VERSION", temp);
- sprintf(temp, "%d", cmVersion::GetTweakVersion());
- this->SetDefinition("CMAKE_TWEAK_VERSION", temp);
+ this->SetDefinition("CMAKE_MAJOR_VERSION",
+ std::to_string(cmVersion::GetMajorVersion()));
+ this->SetDefinition("CMAKE_MINOR_VERSION",
+ std::to_string(cmVersion::GetMinorVersion()));
+ this->SetDefinition("CMAKE_PATCH_VERSION",
+ std::to_string(cmVersion::GetPatchVersion()));
+ this->SetDefinition("CMAKE_TWEAK_VERSION",
+ std::to_string(cmVersion::GetTweakVersion()));
this->SetDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion());
this->SetDefinition("CMAKE_FILES_DIRECTORY",
cmStateEnums::SnapshotType GetType() const;
void SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
- cmPolicies::PolicyStatus GetPolicy(cmPolicies::PolicyID id) const;
+ cmPolicies::PolicyStatus GetPolicy(cmPolicies::PolicyID id,
+ bool parent_scope = false) const;
bool HasDefinedPolicyCMP0011();
void PushPolicy(cmPolicies::PolicyMap const& entry, bool weak);
bool PopPolicy();
#include "cmCryptoHash.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmStringReplaceHelper.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cmUuid.h"
if (subCommand == "CONCAT") {
return this->HandleConcatCommand(args);
}
+ if (subCommand == "JOIN") {
+ return this->HandleJoinCommand(args);
+ }
if (subCommand == "SUBSTRING") {
return this->HandleSubstringCommand(args);
}
std::string const& regex = args[2];
std::string const& replace = args[3];
std::string const& outvar = args[4];
+ cmStringReplaceHelper replaceHelper(regex, replace, this->Makefile);
- // Pull apart the replace expression to find the escaped [0-9] values.
- std::vector<RegexReplacement> replacement;
- std::string::size_type l = 0;
- while (l < replace.length()) {
- std::string::size_type r = replace.find('\\', l);
- if (r == std::string::npos) {
- r = replace.length();
- replacement.push_back(replace.substr(l, r - l));
- } else {
- if (r - l > 0) {
- replacement.push_back(replace.substr(l, r - l));
- }
- if (r == (replace.length() - 1)) {
- this->SetError("sub-command REGEX, mode REPLACE: "
- "replace-expression ends in a backslash.");
- return false;
- }
- if ((replace[r + 1] >= '0') && (replace[r + 1] <= '9')) {
- replacement.push_back(replace[r + 1] - '0');
- } else if (replace[r + 1] == 'n') {
- replacement.push_back("\n");
- } else if (replace[r + 1] == '\\') {
- replacement.push_back("\\");
- } else {
- std::string e = "sub-command REGEX, mode REPLACE: Unknown escape \"";
- e += replace.substr(r, 2);
- e += "\" in replace-expression.";
- this->SetError(e);
- return false;
- }
- r += 2;
- }
- l = r;
+ if (!replaceHelper.IsReplaceExpressionValid()) {
+ this->SetError(
+ "sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + ".");
+ return false;
}
this->Makefile->ClearMatches();
- // Compile the regular expression.
- cmsys::RegularExpression re;
- if (!re.compile(regex.c_str())) {
+
+ if (!replaceHelper.IsRegularExpressionValid()) {
std::string e =
"sub-command REGEX, mode REPLACE failed to compile regex \"" + regex +
"\".";
}
// Concatenate all the last arguments together.
- std::string input = cmJoin(cmMakeRange(args).advance(5), std::string());
-
- // Scan through the input for all matches.
+ const std::string input =
+ cmJoin(cmMakeRange(args).advance(5), std::string());
std::string output;
- std::string::size_type base = 0;
- while (re.find(input.c_str() + base)) {
- this->Makefile->ClearMatches();
- this->Makefile->StoreMatches(re);
- std::string::size_type l2 = re.start();
- std::string::size_type r = re.end();
-
- // Concatenate the part of the input that was not matched.
- output += input.substr(base, l2);
-
- // Make sure the match had some text.
- if (r - l2 == 0) {
- std::string e = "sub-command REGEX, mode REPLACE regex \"" + regex +
- "\" matched an empty string.";
- this->SetError(e);
- return false;
- }
-
- // Concatenate the replacement for the match.
- for (RegexReplacement const& i : replacement) {
- if (i.number < 0) {
- // This is just a plain-text part of the replacement.
- output += i.value;
- } else {
- // Replace with part of the match.
- int n = i.number;
- std::string::size_type start = re.start(n);
- std::string::size_type end = re.end(n);
- std::string::size_type len = input.length() - base;
- if ((start != std::string::npos) && (end != std::string::npos) &&
- (start <= len) && (end <= len)) {
- output += input.substr(base + start, end - start);
- } else {
- std::string e =
- "sub-command REGEX, mode REPLACE: replace expression \"" +
- replace + "\" contains an out-of-range escape for regex \"" +
- regex + "\".";
- this->SetError(e);
- return false;
- }
- }
- }
- // Move past the match.
- base += r;
+ if (!replaceHelper.Replace(input, output)) {
+ this->SetError(
+ "sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + ".");
+ return false;
}
- // Concatenate the text after the last match.
- output += input.substr(base, input.length() - base);
-
// Store the output in the provided variable.
this->Makefile->AddDefinition(outvar, output.c_str());
return true;
return false;
}
- std::string const& variableName = args[1];
- std::string value = cmJoin(cmMakeRange(args).advance(2), std::string());
+ return this->joinImpl(args, std::string(), 1);
+}
+
+bool cmStringCommand::HandleJoinCommand(std::vector<std::string> const& args)
+{
+ if (args.size() < 3) {
+ this->SetError("sub-command JOIN requires at least two arguments.");
+ return false;
+ }
+
+ return this->joinImpl(args, args[1], 2);
+}
+
+bool cmStringCommand::joinImpl(std::vector<std::string> const& args,
+ std::string const& glue, const size_t varIdx)
+{
+ std::string const& variableName = args[varIdx];
+ // NOTE Items to concat/join placed right after the variable for
+ // both `CONCAT` and `JOIN` sub-commands.
+ std::string value = cmJoin(cmMakeRange(args).advance(varIdx + 1), glue);
this->Makefile->AddDefinition(variableName, value.c_str());
return true;
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <string>
#include <vector>
bool HandleAppendCommand(std::vector<std::string> const& args);
bool HandlePrependCommand(std::vector<std::string> const& args);
bool HandleConcatCommand(std::vector<std::string> const& args);
+ bool HandleJoinCommand(std::vector<std::string> const& args);
bool HandleStripCommand(std::vector<std::string> const& args);
bool HandleRandomCommand(std::vector<std::string> const& args);
bool HandleFindCommand(std::vector<std::string> const& args);
bool HandleGenexStripCommand(std::vector<std::string> const& args);
bool HandleUuidCommand(std::vector<std::string> const& args);
- class RegexReplacement
- {
- public:
- RegexReplacement(const char* s)
- : number(-1)
- , value(s)
- {
- }
- RegexReplacement(const std::string& s)
- : number(-1)
- , value(s)
- {
- }
- RegexReplacement(int n)
- : number(n)
- , value()
- {
- }
- RegexReplacement() {}
- int number;
- std::string value;
- };
+ bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
+ size_t varIdx);
};
#endif
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmStringReplaceHelper.h"
+
+#include "cmMakefile.h"
+#include <sstream>
+
+cmStringReplaceHelper::cmStringReplaceHelper(const std::string& regex,
+ const std::string& replace_expr,
+ cmMakefile* makefile)
+ : RegExString(regex)
+ , RegularExpression(regex)
+ , ReplaceExpression(replace_expr)
+ , Makefile(makefile)
+{
+ this->ParseReplaceExpression();
+}
+
+bool cmStringReplaceHelper::Replace(const std::string& input,
+ std::string& output)
+{
+ output.clear();
+
+ // Scan through the input for all matches.
+ std::string::size_type base = 0;
+ while (this->RegularExpression.find(input.c_str() + base)) {
+ if (this->Makefile != nullptr) {
+ this->Makefile->ClearMatches();
+ this->Makefile->StoreMatches(this->RegularExpression);
+ }
+ auto l2 = this->RegularExpression.start();
+ auto r = this->RegularExpression.end();
+
+ // Concatenate the part of the input that was not matched.
+ output += input.substr(base, l2);
+
+ // Make sure the match had some text.
+ if (r - l2 == 0) {
+ std::ostringstream error;
+ error << "regex \"" << this->RegExString << "\" matched an empty string";
+ this->ErrorString = error.str();
+ return false;
+ }
+
+ // Concatenate the replacement for the match.
+ for (const auto& replacement : this->Replacements) {
+ if (replacement.Number < 0) {
+ // This is just a plain-text part of the replacement.
+ output += replacement.Value;
+ } else {
+ // Replace with part of the match.
+ auto n = replacement.Number;
+ auto start = this->RegularExpression.start(n);
+ auto end = this->RegularExpression.end(n);
+ auto len = input.length() - base;
+ if ((start != std::string::npos) && (end != std::string::npos) &&
+ (start <= len) && (end <= len)) {
+ output += input.substr(base + start, end - start);
+ } else {
+ std::ostringstream error;
+ error << "replace expression \"" << this->ReplaceExpression
+ << "\" contains an out-of-range escape for regex \""
+ << this->RegExString << "\"";
+ this->ErrorString = error.str();
+ return false;
+ }
+ }
+ }
+
+ // Move past the match.
+ base += r;
+ }
+
+ // Concatenate the text after the last match.
+ output += input.substr(base, input.length() - base);
+
+ return true;
+}
+
+void cmStringReplaceHelper::ParseReplaceExpression()
+{
+ std::string::size_type l = 0;
+ while (l < this->ReplaceExpression.length()) {
+ 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));
+ } else {
+ if (r - l > 0) {
+ this->Replacements.push_back(this->ReplaceExpression.substr(l, r - l));
+ }
+ if (r == (this->ReplaceExpression.length() - 1)) {
+ this->ValidReplaceExpression = false;
+ this->ErrorString = "replace-expression ends in a backslash";
+ return;
+ }
+ if ((this->ReplaceExpression[r + 1] >= '0') &&
+ (this->ReplaceExpression[r + 1] <= '9')) {
+ this->Replacements.push_back(this->ReplaceExpression[r + 1] - '0');
+ } else if (this->ReplaceExpression[r + 1] == 'n') {
+ this->Replacements.push_back("\n");
+ } else if (this->ReplaceExpression[r + 1] == '\\') {
+ this->Replacements.push_back("\\");
+ } else {
+ this->ValidReplaceExpression = false;
+ std::ostringstream error;
+ error << "Unknown escape \"" << this->ReplaceExpression.substr(r, 2)
+ << "\" in replace-expression";
+ this->ErrorString = error.str();
+ return;
+ }
+ r += 2;
+ }
+ l = r;
+ }
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmStringReplaceHelper_h
+#define cmStringReplaceHelper_h
+
+#include "cmsys/RegularExpression.hxx"
+
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+class cmStringReplaceHelper
+{
+public:
+ cmStringReplaceHelper(const std::string& regex,
+ const std::string& replace_expr,
+ cmMakefile* makefile = nullptr);
+
+ bool IsRegularExpressionValid() const
+ {
+ return this->RegularExpression.is_valid();
+ }
+ bool IsReplaceExpressionValid() const
+ {
+ return this->ValidReplaceExpression;
+ }
+
+ bool Replace(const std::string& input, std::string& output);
+
+ const std::string& GetError() { return this->ErrorString; }
+
+private:
+ class RegexReplacement
+ {
+ public:
+ RegexReplacement(const char* s)
+ : Number(-1)
+ , Value(s)
+ {
+ }
+ RegexReplacement(const std::string& s)
+ : Number(-1)
+ , Value(s)
+ {
+ }
+ RegexReplacement(int n)
+ : Number(n)
+ , Value()
+ {
+ }
+ RegexReplacement() {}
+
+ int Number;
+ std::string Value;
+ };
+
+ void ParseReplaceExpression();
+
+ std::string ErrorString;
+ std::string RegExString;
+ cmsys::RegularExpression RegularExpression;
+ bool ValidReplaceExpression = true;
+ std::string ReplaceExpression;
+ std::vector<RegexReplacement> Replacements;
+ cmMakefile* Makefile = nullptr;
+};
+
+#endif
#include "cm_sys_stat.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmArchiveWrite.h"
-#include "cmLocale.h"
-#include "cm_libarchive.h"
-#ifndef __LA_INT64_T
-#define __LA_INT64_T la_int64_t
-#endif
+# include "cmArchiveWrite.h"
+# include "cmLocale.h"
+# include "cm_libarchive.h"
+# ifndef __LA_INT64_T
+# define __LA_INT64_T la_int64_t
+# endif
+# ifndef __LA_SSIZE_T
+# define __LA_SSIZE_T la_ssize_t
+# endif
#endif
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmCryptoHash.h"
+# include "cmCryptoHash.h"
#endif
#if defined(CMAKE_USE_ELF_PARSER)
-#include "cmELF.h"
+# include "cmELF.h"
#endif
#if defined(CMAKE_USE_MACH_PARSER)
-#include "cmMachO.h"
+# include "cmMachO.h"
#endif
#include "cmsys/Directory.hxx"
#include <utility>
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
// include wincrypt.h after windows.h
-#include <wincrypt.h>
+# include <wincrypt.h>
-#include <fcntl.h> /* _O_TEXT */
+# include <fcntl.h> /* _O_TEXT */
-#include "cm_uv.h"
+# include "cm_uv.h"
#else
-#include <sys/time.h>
-#include <unistd.h>
-#include <utime.h>
+# include <sys/time.h>
+# include <unistd.h>
+# include <utime.h>
#endif
#if defined(_WIN32) && \
(defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__))
-#include <io.h>
+# include <io.h>
#endif
#if defined(__APPLE__)
-#include <mach-o/dyld.h>
+# include <mach-o/dyld.h>
#endif
#ifdef __QNX__
-#include <malloc.h> /* for malloc/free on QNX */
+# include <malloc.h> /* for malloc/free on QNX */
#endif
static bool cm_isspace(char c)
#if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
// For GetEnvironmentVariables
-#if defined(_WIN32)
+# if defined(_WIN32)
extern __declspec(dllimport) char** environ;
-#else
+# else
extern char** environ;
-#endif
+# endif
#endif
#if defined(CMAKE_BUILD_WITH_CMAKE)
static std::string cm_archive_entry_pathname(struct archive_entry* entry)
{
-#if cmsys_STL_HAS_WSTRING
+# if cmsys_STL_HAS_WSTRING
return cmsys::Encoding::ToNarrow(archive_entry_pathname_w(entry));
-#else
+# else
return archive_entry_pathname(entry);
-#endif
+# endif
}
static int cm_archive_read_open_file(struct archive* a, const char* file,
int block_size)
{
-#if cmsys_STL_HAS_WSTRING
+# if cmsys_STL_HAS_WSTRING
std::wstring wfile = cmsys::Encoding::ToWide(file);
return archive_read_open_filename_w(a, wfile.c_str(), block_size);
-#else
+# else
return archive_read_open_filename(a, file, block_size);
-#endif
+# endif
}
#endif
HANDLE handle_;
};
#elif defined(__APPLE__)
-#include <crt_externs.h>
+# include <crt_externs.h>
-#define environ (*_NSGetEnviron())
+# define environ (*_NSGetEnviron())
#endif
bool cmSystemTools::s_RunCommandHideConsole = false;
// We estimate the size of the environment block to be 1000.
// This isn't accurate at all, but leaves some headroom.
szArgMax = szArgMax < 1000 ? 0 : szArgMax - 1000;
-#if defined(_WIN32) || defined(__linux)
+# if defined(_WIN32) || defined(__linux)
sz = std::min(sz, static_cast<size_t>(szArgMax));
-#else
+# else
sz = static_cast<size_t>(szArgMax);
-#endif
+# endif
}
#endif
return sz;
// global _fmode setting so that using libuv does not change the
// default file text/binary mode. See libuv issue 840.
uv_loop_close(uv_default_loop());
-#ifdef _MSC_VER
+# ifdef _MSC_VER
_set_fmode(_O_TEXT);
-#else
+# else
_fmode = _O_TEXT;
-#endif
+# endif
#endif
}
bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
{
#ifdef _WIN32
-#ifndef INVALID_FILE_ATTRIBUTES
-#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
-#endif
+# ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+# endif
/* Windows MoveFileEx may not replace read-only or in-use files. If it
fails then remove the read-only attribute from any existing destination.
Try multiple times since we may be racing against another process
#ifdef CMAKE_BUILD_WITH_CMAKE
bool cmSystemTools::UnsetEnv(const char* value)
{
-#if !defined(HAVE_UNSETENV)
+# if !defined(HAVE_UNSETENV)
std::string var = value;
var += "=";
return cmSystemTools::PutEnv(var.c_str());
-#else
+# else
unsetenv(value);
return true;
-#endif
+# endif
}
std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
void cmSystemTools::EnableVSConsoleOutput()
{
#ifdef _WIN32
- // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
+ // Visual Studio tools like devenv may not
// display output to the console unless this environment variable is
// set. We need it to capture the output of these build tools.
// Note for future work that one could pass "/out \\.\pipe\NAME" to
// output and allow it to be captured on the fly.
cmSystemTools::PutEnv("vsconsoleoutput=1");
-#ifdef CMAKE_BUILD_WITH_CMAKE
+# ifdef CMAKE_BUILD_WITH_CMAKE
// VS sets an environment variable to tell MS tools like "cl" to report
// output through a backdoor pipe instead of stdout/stderr. Unset the
// environment variable to close this backdoor for any path of process
// invocations that passes through CMake so we can capture the output.
cmSystemTools::UnsetEnv("VS_UNICODE_OUTPUT");
-#endif
+# endif
#endif
}
#if defined(CMAKE_BUILD_WITH_CMAKE)
namespace {
-#define BSDTAR_FILESIZE_PRINTF "%lu"
-#define BSDTAR_FILESIZE_TYPE unsigned long
+# define BSDTAR_FILESIZE_PRINTF "%lu"
+# define BSDTAR_FILESIZE_TYPE unsigned long
void list_item_verbose(FILE* out, struct archive_entry* entry)
{
char tmp[100];
/* Format the time using 'ls -l' conventions. */
tim = archive_entry_mtime(entry);
-#define HALF_YEAR ((time_t)365 * 86400 / 2)
-#if defined(_WIN32) && !defined(__CYGWIN__)
+# define HALF_YEAR ((time_t)365 * 86400 / 2)
+# if defined(_WIN32) && !defined(__CYGWIN__)
/* Windows' strftime function does not support %e format. */
-#define DAY_FMT "%d"
-#else
-#define DAY_FMT "%e" /* Day number without leading zeros */
-#endif
+# define DAY_FMT "%d"
+# else
+# define DAY_FMT "%e" /* Day number without leading zeros */
+# endif
if (tim < now - HALF_YEAR || tim > now + HALF_YEAR) {
fmt = DAY_FMT " %b %Y";
} else {
fflush(out);
}
-long copy_data(struct archive* ar, struct archive* aw)
+// Return 'true' on success
+bool copy_data(struct archive* ar, struct archive* aw)
{
long r;
const void* buff;
size_t size;
-#if defined(ARCHIVE_VERSION_NUMBER) && ARCHIVE_VERSION_NUMBER >= 3000000
+# if defined(ARCHIVE_VERSION_NUMBER) && ARCHIVE_VERSION_NUMBER >= 3000000
__LA_INT64_T offset;
-#else
+# else
off_t offset;
-#endif
+# endif
for (;;) {
+ // Return value:
+ // * ARCHIVE_OK - read succeed
+ // * ARCHIVE_EOF - no more data to read left
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF) {
- return (ARCHIVE_OK);
+ return true;
}
if (r != ARCHIVE_OK) {
- return (r);
+ return false;
}
- r = archive_write_data_block(aw, buff, size, offset);
- if (r != ARCHIVE_OK) {
+ // Return value:
+ // * >= ARCHIVE_OK - write succeed
+ // * < ARCHIVE_OK - write failed
+ const __LA_SSIZE_T w_size =
+ archive_write_data_block(aw, buff, size, offset);
+ if (w_size < ARCHIVE_OK) {
cmSystemTools::Message("archive_write_data_block()",
archive_error_string(aw));
- return (r);
+ return false;
}
}
-#if !defined(__clang__) && !defined(__HP_aCC)
- return r; /* this should not happen but it quiets some compilers */
-#endif
+# if !defined(__clang__) && !defined(__HP_aCC)
+ return false; /* this should not happen but it quiets some compilers */
+# endif
}
bool extract_tar(const char* outFileName, bool verbose, bool extract)
r = archive_write_header(ext, entry);
if (r == ARCHIVE_OK) {
- copy_data(a, ext);
+ if (!copy_data(a, ext)) {
+ cmSystemTools::Error("Problem with copy_data");
+ break;
+ }
r = archive_write_finish_entry(ext);
if (r != ARCHIVE_OK) {
cmSystemTools::Error("Problem with archive_write_finish_entry(): ",
break;
}
}
-#ifdef _WIN32
+# ifdef _WIN32
else if (const char* linktext = archive_entry_symlink(entry)) {
std::cerr << "cmake -E tar: warning: skipping symbolic link \""
<< cm_archive_entry_pathname(entry) << "\" -> \"" << linktext
<< "\"." << std::endl;
}
-#endif
+# endif
else {
cmSystemTools::Error("Problem with archive_write_header(): ",
archive_error_string(ext));
}
#ifdef _WIN32
-#ifndef CRYPT_SILENT
-#define CRYPT_SILENT 0x40 /* Not defined by VS 6 version of header. */
-#endif
+# ifndef CRYPT_SILENT
+# define CRYPT_SILENT 0x40 /* Not defined by VS 6 version of header. */
+# endif
static int WinCryptRandom(void* data, size_t size)
{
int result = 0;
exe_dir = cmSystemTools::GetFilenamePath(realPath);
#elif defined(__APPLE__)
(void)argv0; // ignore this on OS X
-#define CM_EXE_PATH_LOCAL_SIZE 16384
+# define CM_EXE_PATH_LOCAL_SIZE 16384
char exe_path_local[CM_EXE_PATH_LOCAL_SIZE];
-#if defined(MAC_OS_X_VERSION_10_3) && !defined(MAC_OS_X_VERSION_10_4)
+# if defined(MAC_OS_X_VERSION_10_3) && !defined(MAC_OS_X_VERSION_10_4)
unsigned long exe_path_size = CM_EXE_PATH_LOCAL_SIZE;
-#else
+# else
uint32_t exe_path_size = CM_EXE_PATH_LOCAL_SIZE;
-#endif
-#undef CM_EXE_PATH_LOCAL_SIZE
+# endif
+# undef CM_EXE_PATH_LOCAL_SIZE
char* exe_path = exe_path_local;
if (_NSGetExecutablePath(exe_path, &exe_path_size) < 0) {
exe_path = static_cast<char*>(malloc(exe_path_size));
static FileFormat GetFileFormat(const char* ext);
/** Windows if this is true, the CreateProcess in RunCommand will
- * not show new consol windows when running programs.
+ * not show new console windows when running programs.
*/
static void SetRunCommandHideConsole(bool v) { s_RunCommandHideConsole = v; }
static bool GetRunCommandHideConsole() { return s_RunCommandHideConsole; }
}
if (!noMessage) {
e << "Target \"" << tgt->GetName()
- << "\" contains "
- "$<TARGET_OBJECTS> generator expression in its sources "
- "list. "
- "This content was not previously part of the SOURCES "
- "property "
- "when that property was read at configure time. Code "
- "reading "
- "that property needs to be adapted to ignore the generator "
- "expression using the string(GENEX_STRIP) command.";
+ << "\" contains $<TARGET_OBJECTS> generator expression in its "
+ "sources list. This content was not previously part of the "
+ "SOURCES property when that property was read at configure "
+ "time. Code reading that property needs to be adapted to "
+ "ignore the generator expression using the string(GENEX_STRIP) "
+ "command.";
messenger->IssueMessage(messageType, e.str(), context);
}
if (addContent) {
this->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
this->BuildInterfaceIncludesAppended = false;
- // only add dependency information for library targets
- if (this->TargetTypeValue >= cmStateEnums::STATIC_LIBRARY &&
- this->TargetTypeValue <= cmStateEnums::MODULE_LIBRARY) {
- this->RecordDependencies = true;
- } else {
- this->RecordDependencies = false;
- }
-
// Check whether this is a DLL platform.
this->DLLPlatform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ "") != 0;
// Check whether we are targeting an Android platform.
this->IsAndroid =
this->SetPropertyDefault("CUDA_SEPARABLE_COMPILATION", nullptr);
this->SetPropertyDefault("LINK_SEARCH_START_STATIC", nullptr);
this->SetPropertyDefault("LINK_SEARCH_END_STATIC", nullptr);
+ this->SetPropertyDefault("FOLDER", nullptr);
}
// Collect the set of configuration types.
this->SetPropertyDefault("JOB_POOL_COMPILE", nullptr);
this->SetPropertyDefault("JOB_POOL_LINK", nullptr);
}
+
+ if (this->TargetTypeValue <= cmStateEnums::UTILITY) {
+ this->SetPropertyDefault("DOTNET_TARGET_FRAMEWORK_VERSION", nullptr);
+ }
}
cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
{
std::string src = s;
- // For backwards compatibility replace varibles in source names.
+ // For backwards compatibility replace variables in source names.
// This should eventually be removed.
this->Makefile->ExpandVariablesInString(src);
if (src != s) {
return this->LinkDirectories;
}
-void cmTarget::ClearDependencyInformation(cmMakefile& mf,
- const std::string& target)
+void cmTarget::ClearDependencyInformation(cmMakefile& mf)
{
- // Clear the dependencies. The cache variable must exist iff we are
- // recording dependency information for this target.
- std::string depname = target;
+ std::string depname = this->GetName();
depname += "_LIB_DEPENDS";
- if (this->RecordDependencies) {
- mf.AddCacheDefinition(depname, "", "Dependencies for target",
- cmStateEnums::STATIC);
- } else {
- if (mf.GetDefinition(depname)) {
- std::string message = "Target ";
- message += target;
- message += " has dependency information when it shouldn't.\n";
- message += "Your cache is probably stale. Please remove the entry\n ";
- message += depname;
- message += "\nfrom the cache.";
- cmSystemTools::Error(message.c_str());
- }
- }
+ mf.RemoveCacheDefinition(depname);
}
std::string cmTarget::GetDebugGeneratorExpressions(
}
if (cmGeneratorExpression::Find(lib) != std::string::npos ||
- (tgt && tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
+ (tgt &&
+ (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
(this->Name == lib)) {
return;
}
- {
- cmTarget::LibraryID tmp;
- tmp.first = lib;
- tmp.second = llt;
- this->OriginalLinkLibraries.emplace_back(lib, llt);
- }
+ this->OriginalLinkLibraries.emplace_back(lib, llt);
- // Add the explicit dependency information for this target. This is
+ // Add the explicit dependency information for libraries. This is
// simply a set of libraries separated by ";". There should always
// be a trailing ";". These library names are not canonical, in that
// they may be "-framework x", "-ly", "/path/libz.a", etc.
// may be purposefully duplicated to handle recursive dependencies,
// and we removing one instance will break the link line. Duplicates
// will be appropriately eliminated at emit time.
- if (this->RecordDependencies) {
+ if (this->TargetTypeValue >= cmStateEnums::STATIC_LIBRARY &&
+ this->TargetTypeValue <= cmStateEnums::MODULE_LIBRARY &&
+ (this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
+ this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
std::string targetEntry = this->Name;
targetEntry += "_LIB_DEPENDS";
std::string dependencies;
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY ||
!this->IsImported()) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, prop +
+ cmake::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, prop +
- " property value\n " + value +
+ this->Makefile->IssueMessage(cmake::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, prop + " property value\n " + value +
- "\nmay not contain '" + value.substr(bad, 1) + "'.");
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ prop + " property value\n " + value +
+ "\nmay not contain '" +
+ value.substr(bad, 1) + "'.");
return false;
}
}
cmTargetInternalPointer& operator=(cmTargetInternalPointer const& r);
cmTargetInternals* operator->() const { return this->Pointer; }
cmTargetInternals* Get() const { return this->Pointer; }
+
private:
cmTargetInternals* Pointer;
};
/**
* Clear the dependency information recorded for this target, if any.
*/
- void ClearDependencyInformation(cmMakefile& mf, const std::string& target);
+ void ClearDependencyInformation(cmMakefile& mf);
void AddLinkLibrary(cmMakefile& mf, const std::string& lib,
cmTargetLinkLibraryType llt);
void SetHaveInstallRule(bool h) { this->HaveInstallRule = h; }
/**
- * Get/Set whether this target was auto-created by a generator.
- */
+ * Get/Set whether this target was auto-created by a generator.
+ */
bool GetIsGeneratorProvided() const { return this->IsGeneratorProvided; }
void SetIsGeneratorProvided(bool igp) { this->IsGeneratorProvided = igp; }
cmTargetInternalPointer Internal;
cmStateEnums::TargetType TargetTypeValue;
bool HaveInstallRule;
- bool RecordDependencies;
bool DLLPlatform;
bool IsAndroid;
bool IsImportedTarget;
return true;
}
- // OBJECT libraries are not allowed on the LHS of the command.
- if (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::ostringstream e;
- e << "Object library target \"" << args[0] << "\" "
- << "may not link to anything.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
-
// Having a UTILITY library on the LHS is a bug.
if (this->Target->GetType() == cmStateEnums::UTILITY) {
std::ostringstream e;
// form must be the plain form.
const char* existingSig =
(sig == cmTarget::KeywordTLLSignature ? "plain" : "keyword");
- e << "The " << existingSig << " signature for target_link_libraries has "
- "already been used with the target \""
+ e << "The " << existingSig
+ << " signature for target_link_libraries has "
+ "already been used with the target \""
<< this->Target->GetName()
<< "\". All uses of target_link_libraries with a target " << modal
<< " be either all-keyword or all-plain.\n";
if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) &&
(tgt->GetType() != cmStateEnums::SHARED_LIBRARY) &&
(tgt->GetType() != cmStateEnums::UNKNOWN_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
(tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
!tgt->IsExecutableWithExports()) {
std::ostringstream e;
e << "Target \"" << lib << "\" of type "
<< cmState::GetTargetTypeName(tgt->GetType())
<< " may not be linked into another target. One may link only to "
- "INTERFACE, STATIC or SHARED libraries, or to executables with the "
- "ENABLE_EXPORTS property set.";
+ "INTERFACE, OBJECT, STATIC or SHARED libraries, or to executables "
+ "with the ENABLE_EXPORTS property set.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
void LinkLibraryTypeSpecifierWarning(int left, int right);
static const char* LinkLibraryTypeNames[3];
- cmTarget* Target;
+ cmTarget* Target = nullptr;
enum ProcessingState
{
ProcessingLinkLibraries,
ProcessingKeywordPrivateInterface
};
- ProcessingState CurrentProcessingState;
+ ProcessingState CurrentProcessingState = ProcessingLinkLibraries;
bool HandleLibrary(const std::string& lib, cmTargetLinkLibraryType llt);
};
protected:
std::string Property;
- cmTarget* Target;
+ cmTarget* Target = nullptr;
virtual void HandleInterfaceContent(cmTarget* tgt,
const std::vector<std::string>& content,
os << cmOutputConverter::EscapeForCMake(exe);
for (std::vector<std::string>::const_iterator ci = command.begin() + 1;
ci != command.end(); ++ci) {
- os << " " << cmOutputConverter::EscapeForCMake(
- ge.Parse(*ci)->Evaluate(this->LG, config));
+ os << " "
+ << cmOutputConverter::EscapeForCMake(
+ ge.Parse(*ci)->Evaluate(this->LG, config));
}
// Finish the test command.
struct uv_handle_deleter<uv_async_t>
{
/***
- * Wile uv_async_send is itself thread-safe, there are
- * no strong guarantees that close hasn't already been
- * called on the handle; and that it might be deleted
- * as the send call goes through. This mutex guards
- * against that.
- *
- * The shared_ptr here is to allow for copy construction
- * which is mandated by the standard for Deleter on
- * shared_ptrs.
- */
+ * Wile uv_async_send is itself thread-safe, there are
+ * no strong guarantees that close hasn't already been
+ * called on the handle; and that it might be deleted
+ * as the send call goes through. This mutex guards
+ * against that.
+ *
+ * The shared_ptr here is to allow for copy construction
+ * which is mandated by the standard for Deleter on
+ * shared_ptrs.
+ */
std::shared_ptr<std::mutex> handleMutex;
uv_handle_deleter()
namespace cm {
/***
-* RAII class to simplify and insure the safe usage of uv_*_t types. This
-* includes making sure resources are properly freed and contains casting
-* operators which allow for passing into relevant uv_* functions.
-*
-*@tparam T actual uv_*_t type represented.
-*/
+ * RAII class to simplify and insure the safe usage of uv_*_t types. This
+ * includes making sure resources are properly freed and contains casting
+ * operators which allow for passing into relevant uv_* functions.
+ *
+ *@tparam T actual uv_*_t type represented.
+ */
template <typename T>
class uv_handle_ptr_base_
{
* that initializes something like uv_pipe_ptr or uv_tcp_ptr and interact
* and clean up after it without caring about the exact type.
*/
- template <typename S, typename = typename std::enable_if<
- std::is_rvalue_reference<S&&>::value>::type>
+ template <typename S,
+ typename = typename std::enable_if<
+ std::is_rvalue_reference<S&&>::value>::type>
uv_handle_ptr_base_(S&& rhs)
{
// This will force a compiler error if rhs doesn't have a casting
extern template class uv_handle_ptr_base_<uv_handle_t>;
-#define UV_HANDLE_PTR_INSTANTIATE_EXTERN(NAME) \
- extern template class uv_handle_ptr_base_<uv_##NAME##_t>; \
- extern template class uv_handle_ptr_<uv_##NAME##_t>;
+# define UV_HANDLE_PTR_INSTANTIATE_EXTERN(NAME) \
+ extern template class uv_handle_ptr_base_<uv_##NAME##_t>; \
+ extern template class uv_handle_ptr_<uv_##NAME##_t>;
UV_HANDLE_PTR_INSTANTIATE_EXTERN(async)
UV_HANDLE_PTR_INSTANTIATE_EXTERN(tty)
-#undef UV_HANDLE_PTR_INSTANTIATE_EXTERN
+# undef UV_HANDLE_PTR_INSTANTIATE_EXTERN
#endif
}
#if defined(CMAKE_USE_SYSTEM_LIBUV) && !defined(_WIN32) && \
UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR < 19
-#define CMAKE_UV_SIGNAL_HACK
-#include "cmUVHandlePtr.h"
+# define CMAKE_UV_SIGNAL_HACK
+# include "cmUVHandlePtr.h"
/*
libuv does not use SA_RESTART on its signal handler, but C++ streams
depend on it for reliable i/o operations. This RAII helper convinces
uv_loop_t HackLoop;
cm::uv_signal_ptr HackSignal;
static void HackCB(uv_signal_t*, int) {}
+
public:
cmUVSignalHackRAII()
{
}
} else {
cmState* state = this->Makefile->GetState();
- haveCacheValue =
- (cacheValue && (strstr(cacheValue, "(IntDir)") == nullptr ||
- (intDir && strcmp(intDir, "$(IntDir)") == 0)) &&
- (state->GetCacheMajorVersion() != 0 &&
- state->GetCacheMinorVersion() != 0));
+ haveCacheValue = (cacheValue &&
+ (strstr(cacheValue, "(IntDir)") == nullptr ||
+ (intDir && strcmp(intDir, "$(IntDir)") == 0)) &&
+ (state->GetCacheMajorVersion() != 0 &&
+ state->GetCacheMinorVersion() != 0));
}
if (haveCacheValue) {
{ "HostDebugInfo", "g", "", "true", 0 },
{ "HostDebugInfo", "-debug", "", "true", 0 },
+ { "MaxRegCount", "maxrregcount=", "", "", cmVS7FlagTable::UserValue },
+ { "MaxRegCount", "maxrregcount", "", "", cmVS7FlagTable::UserFollowing },
+
{ 0, 0, 0, 0, 0 }
};
// String List Properties
// Skip [AdditionalDependencies] - no command line Switch.
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
+ { "AdditionalLibraryDirectories",
+ "LIBPATH:", "Additional Library Directories", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
+ { "IgnoreSpecificDefaultLibraries",
+ "NODEFAULTLIB:", "Ignore Specific Default Libraries", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValueRequired },
// String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
+ { "AdditionalLibraryDirectories",
+ "LIBPATH:", "Additional Library Directories", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
// Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
+ { "IgnoreSpecificDefaultLibraries",
+ "NODEFAULTLIB:", "Ignore Specific Default Libraries", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
+ { "EmbedManagedResourceFile",
+ "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
+ { "AdditionalManifestDependencies",
+ "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
// String Properties
// String List Properties
// Skip [AdditionalDependencies] - no command line Switch.
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
+ { "AdditionalLibraryDirectories",
+ "LIBPATH:", "Additional Library Directories", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
+ { "IgnoreSpecificDefaultLibraries",
+ "NODEFAULTLIB:", "Ignore Specific Default Libraries", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValueRequired },
// String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
+ { "AdditionalLibraryDirectories",
+ "LIBPATH:", "Additional Library Directories", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
// Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
+ { "IgnoreSpecificDefaultLibraries",
+ "NODEFAULTLIB:", "Ignore Specific Default Libraries", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
+ { "EmbedManagedResourceFile",
+ "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
+ { "AdditionalManifestDependencies",
+ "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ManifestInput", "manifestinput:", "Manifest Input", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
// String List Properties
// Skip [AdditionalDependencies] - no command line Switch.
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
+ { "AdditionalLibraryDirectories",
+ "LIBPATH:", "Additional Library Directories", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
+ { "IgnoreSpecificDefaultLibraries",
+ "NODEFAULTLIB:", "Ignore Specific Default Libraries", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValueRequired },
// String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
+ { "AdditionalLibraryDirectories",
+ "LIBPATH:", "Additional Library Directories", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
// Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
+ { "IgnoreSpecificDefaultLibraries",
+ "NODEFAULTLIB:", "Ignore Specific Default Libraries", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
+ { "EmbedManagedResourceFile",
+ "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
+ { "AdditionalManifestDependencies",
+ "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ManifestInput", "manifestinput:", "Manifest Input", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValueRequired },
// String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
+ { "AdditionalLibraryDirectories",
+ "LIBPATH:", "Additional Library Directories", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "Natvis", "NATVIS:", "Natvis files", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
// Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
+ { "IgnoreSpecificDefaultLibraries",
+ "NODEFAULTLIB:", "Ignore Specific Default Libraries", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
+ { "EmbedManagedResourceFile",
+ "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
+ { "AdditionalManifestDependencies",
+ "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ManifestInput", "manifestinput:", "Manifest Input", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValueRequired },
// String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
+ { "AdditionalLibraryDirectories",
+ "LIBPATH:", "Additional Library Directories", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "Natvis", "NATVIS:", "Natvis files", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
// Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
+ { "IgnoreSpecificDefaultLibraries",
+ "NODEFAULTLIB:", "Ignore Specific Default Libraries", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
+ { "EmbedManagedResourceFile",
+ "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
"", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
+ { "AdditionalManifestDependencies",
+ "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ManifestInput", "manifestinput:", "Manifest Input", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
// String List Properties
// Skip [AdditionalDependencies] - no command line Switch.
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
+ { "AdditionalLibraryDirectories",
+ "LIBPATH:", "Additional Library Directories", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
+ { "IgnoreSpecificDefaultLibraries",
+ "NODEFAULTLIB:", "Ignore Specific Default Libraries", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
{ "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "",
cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
#include "cmsys/FStream.hxx"
#ifndef VSSetupConstants
-#define VSSetupConstants
+# define VSSetupConstants
/* clang-format off */
const IID IID_ISetupConfiguration = {
0x42843719, 0xDB4C, 0x46C2,
if (!cmSystemTools::FileIsDirectory(vcToolsDir)) {
return false;
}
+ vsInstanceInfo.VCToolsetVersion = vcToolsVersion;
}
// Reboot may have been required before the product package was registered
return isInstalled;
}
+bool cmVSSetupAPIHelper::GetVCToolsetVersion(std::string& vsToolsetVersion)
+{
+ vsToolsetVersion.clear();
+ bool isInstalled = this->EnumerateAndChooseVSInstance();
+
+ if (isInstalled) {
+ vsToolsetVersion = chosenInstanceInfo.VCToolsetVersion;
+ }
+
+ return isInstalled && !vsToolsetVersion.empty();
+}
+
bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
{
bool isVSInstanceExists = false;
#define cmVSSetupHelper_h
#ifndef NOMINMAX
-#define NOMINMAX // Undefine min and max defined by windows.h
+# define NOMINMAX // Undefine min and max defined by windows.h
#endif
// Published by Visual Studio Setup team
operator BSTR() const { return str; }
BSTR* operator&() throw() { return &str; }
~SmartBSTR() throw() { ::SysFreeString(str); }
+
private:
BSTR str;
};
std::wstring InstanceId;
std::wstring VSInstallLocation;
std::wstring Version;
- ULONGLONG ullVersion;
- bool IsWin10SDKInstalled;
- bool IsWin81SDKInstalled;
+ std::string VCToolsetVersion;
+ ULONGLONG ullVersion = 0;
+ bool IsWin10SDKInstalled = false;
+ bool IsWin81SDKInstalled = false;
- VSInstanceInfo()
- {
- InstanceId = VSInstallLocation = Version = L"";
- ullVersion = 0;
- IsWin10SDKInstalled = IsWin81SDKInstalled = false;
- }
+ VSInstanceInfo() = default;
std::string GetInstallLocation() const;
};
bool IsVS2017Installed();
bool GetVSInstanceInfo(std::string& vsInstallLocation);
+ bool GetVCToolsetVersion(std::string& vsToolsetVersion);
bool IsWin10SDKInstalled();
bool IsWin81SDKInstalled();
#define CMake_VERSION_PATCH_IS_RELEASE(patch) ((patch) < 20000000)
#if CMake_VERSION_PATCH_IS_RELEASE(CMake_VERSION_PATCH)
-#define CMake_VERSION_IS_RELEASE 1
+# define CMake_VERSION_IS_RELEASE 1
#endif
#endif
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalVisualStudio10Generator.h"
-#include "cmLocalVisualStudio7Generator.h"
+#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
return arg;
}
-static std::string cmVS10EscapeQuotes(std::string arg)
+static std::string cmVS10EscapeAttr(std::string arg)
{
+ cmSystemTools::ReplaceString(arg, "&", "&");
+ cmSystemTools::ReplaceString(arg, "<", "<");
+ cmSystemTools::ReplaceString(arg, ">", ">");
cmSystemTools::ReplaceString(arg, "\"", """);
return arg;
}
+struct cmVisualStudio10TargetGenerator::Elem
+{
+ std::ostream& S;
+ const int Indent;
+ bool HasElements = false;
+ bool HasContent = false;
+ std::string Tag;
+
+ Elem(std::ostream& s)
+ : S(s)
+ , Indent(0)
+ {
+ }
+ Elem(const Elem&) = delete;
+ Elem(Elem& par)
+ : S(par.S)
+ , Indent(par.Indent + 1)
+ {
+ par.SetHasElements();
+ }
+ Elem(Elem& par, const char* tag)
+ : S(par.S)
+ , Indent(par.Indent + 1)
+ {
+ par.SetHasElements();
+ this->StartElement(tag);
+ }
+ void SetHasElements()
+ {
+ if (!HasElements) {
+ this->S << ">\n";
+ HasElements = true;
+ }
+ }
+ std::ostream& WriteString(const char* line);
+ Elem& StartElement(const std::string& tag)
+ {
+ this->Tag = tag;
+ this->WriteString("<") << tag;
+ return *this;
+ }
+ void Element(const char* tag, const std::string& val)
+ {
+ Elem(*this, tag).Content(val);
+ }
+ Elem& Attribute(const char* an, const std::string& av)
+ {
+ this->S << " " << an << "=\"" << cmVS10EscapeAttr(av) << "\"";
+ return *this;
+ }
+ // This method for now assumes that this->Tag has been set, e.g. by calling
+ // StartElement().
+ void Content(const std::string& val)
+ {
+ if (!this->HasContent) {
+ this->S << ">";
+ this->HasContent = true;
+ }
+ this->S << cmVS10EscapeXML(val);
+ }
+ ~Elem()
+ {
+ // Do not emit element which has not been started
+ if (Tag.empty()) {
+ return;
+ }
+
+ if (HasElements) {
+ this->WriteString("</") << this->Tag << ">";
+ if (this->Indent > 0) {
+ this->S << '\n';
+ } else {
+ // special case: don't print EOL at EOF
+ }
+ } else if (HasContent) {
+ this->S << "</" << this->Tag << ">\n";
+ } else {
+ this->S << " />\n";
+ }
+ }
+
+ void WritePlatformConfigTag(const char* tag, const std::string& cond,
+ const std::string& content);
+};
+
+class cmVS10GeneratorOptions : public cmVisualStudioGeneratorOptions
+{
+public:
+ typedef cmVisualStudio10TargetGenerator::Elem Elem;
+ cmVS10GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
+ cmVS7FlagTable const* table,
+ cmVisualStudio10TargetGenerator* g = nullptr)
+ : cmVisualStudioGeneratorOptions(lg, tool, table)
+ , TargetGenerator(g)
+ {
+ }
+
+ void OutputFlag(std::ostream& /*fout*/, int /*indent*/, const char* tag,
+ const std::string& content) override
+ {
+ if (!this->GetConfiguration().empty()) {
+ // if there are configuration specific flags, then
+ // use the configuration specific tag for PreprocessorDefinitions
+ const std::string cond =
+ this->TargetGenerator->CalcCondition(this->GetConfiguration());
+ this->Parent->WritePlatformConfigTag(tag, cond, content);
+ } else {
+ this->Parent->Element(tag, content);
+ }
+ }
+
+private:
+ cmVisualStudio10TargetGenerator* const TargetGenerator;
+ Elem* Parent = nullptr;
+ friend cmVisualStudio10TargetGenerator::OptionsHelper;
+};
+
+struct cmVisualStudio10TargetGenerator::OptionsHelper
+{
+ cmVS10GeneratorOptions& O;
+ OptionsHelper(cmVS10GeneratorOptions& o, Elem& e)
+ : O(o)
+ {
+ O.Parent = &e;
+ }
+ ~OptionsHelper() { O.Parent = nullptr; }
+
+ void OutputPreprocessorDefinitions(const std::string& lang)
+ {
+ O.OutputPreprocessorDefinitions(O.Parent->S, O.Parent->Indent + 1, lang);
+ }
+ void OutputAdditionalIncludeDirectories(const std::string& lang)
+ {
+ O.OutputAdditionalIncludeDirectories(O.Parent->S, O.Parent->Indent + 1,
+ lang);
+ }
+ void OutputFlagMap() { O.OutputFlagMap(O.Parent->S, O.Parent->Indent + 1); }
+ void PrependInheritedString(std::string const& key)
+ {
+ O.PrependInheritedString(key);
+ }
+};
+
static std::string cmVS10EscapeComment(std::string comment)
{
// MSBuild takes the CDATA of a <Message></Message> element and just
{
std::string res;
res = ".vcxproj";
- std::string lang = t->GetLinkerLanguage(config);
- if (cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(t) ||
- lang == "CSharp") {
+ if (t->HasLanguage("CSharp", config)) {
res = ".csproj";
}
return res;
cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg)
+ : GeneratorTarget(target)
+ , Makefile(target->Target->GetMakefile())
+ , Platform(gg->GetPlatformName())
+ , Name(target->GetName())
+ , GUID(gg->GetGUID(this->Name))
+ , GlobalGenerator(gg)
+ , LocalGenerator(
+ (cmLocalVisualStudio10Generator*)target->GetLocalGenerator())
{
- this->GlobalGenerator = gg;
- this->GeneratorTarget = target;
- this->Makefile = target->Target->GetMakefile();
this->Makefile->GetConfigurations(this->Configurations);
- this->LocalGenerator =
- (cmLocalVisualStudio7Generator*)this->GeneratorTarget->GetLocalGenerator();
- this->Name = this->GeneratorTarget->GetName();
- this->GUID = this->GlobalGenerator->GetGUID(this->Name);
- this->Platform = gg->GetPlatformName();
this->NsightTegra = gg->IsNsightTegra();
for (int i = 0; i < 4; ++i) {
this->NsightTegraVersion[i] = 0;
this->MSTools = !this->NsightTegra;
this->Managed = false;
this->TargetCompileAsWinRT = false;
- this->BuildFileStream = 0;
this->IsMissingFiles = false;
this->DefaultArtifactDir =
this->LocalGenerator->GetCurrentBinaryDirectory() + std::string("/") +
cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
{
- if (!this->BuildFileStream) {
- return;
- }
- if (this->BuildFileStream->Close()) {
- this->GlobalGenerator->FileReplacedDuringGenerate(this->PathToProjectFile);
- }
- delete this->BuildFileStream;
}
-void cmVisualStudio10TargetGenerator::WritePlatformConfigTag(
- const char* tag, const std::string& config, int indentLevel,
- const char* attribute, const char* end, std::ostream* stream)
-
+std::string cmVisualStudio10TargetGenerator::CalcCondition(
+ const std::string& config) const
{
- if (!stream) {
- stream = this->BuildFileStream;
- }
- stream->fill(' ');
- stream->width(indentLevel * 2);
- (*stream) << ""; // applies indentation
- (*stream) << "<" << tag << " Condition=\"";
- (*stream) << "'$(Configuration)|$(Platform)'=='";
- (*stream) << config << "|" << this->Platform;
- (*stream) << "'";
+ std::ostringstream oss;
+ oss << "'$(Configuration)|$(Platform)'=='";
+ oss << config << "|" << this->Platform;
+ oss << "'";
// handle special case for 32 bit C# targets
if (this->ProjectType == csproj && this->Platform == "Win32") {
- (*stream) << " Or ";
- (*stream) << "'$(Configuration)|$(Platform)'=='";
- (*stream) << config << "|x86";
- (*stream) << "'";
- }
- (*stream) << "\"";
- if (attribute) {
- (*stream) << attribute;
- }
- // close the tag
- (*stream) << ">";
- if (end) {
- (*stream) << end;
+ oss << " Or ";
+ oss << "'$(Configuration)|$(Platform)'=='";
+ oss << config << "|x86";
+ oss << "'";
}
+ return oss.str();
}
-void cmVisualStudio10TargetGenerator::WriteString(const char* line,
- int indentLevel)
+void cmVisualStudio10TargetGenerator::Elem::WritePlatformConfigTag(
+ const char* tag, const std::string& cond, const std::string& content)
{
- this->BuildFileStream->fill(' ');
- this->BuildFileStream->width(indentLevel * 2);
+ Elem(*this, tag).Attribute("Condition", cond).Content(content);
+}
+
+std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
+ const char* line)
+{
+ this->S.fill(' ');
+ this->S.width(this->Indent * 2);
// write an empty string to get the fill level indent to print
- (*this->BuildFileStream) << "";
- (*this->BuildFileStream) << line;
+ this->S << "";
+ this->S << line;
+ return this->S;
}
#define VS10_CXX_DEFAULT_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) {
return;
}
- this->ProjectFileExtension = computeProjectFileExtension(
+ const std::string ProjectFileExtension = computeProjectFileExtension(
this->GeneratorTarget, *this->Configurations.begin());
- if (this->ProjectFileExtension == ".vcxproj") {
+ if (ProjectFileExtension == ".vcxproj") {
this->ProjectType = vcxproj;
this->Managed = false;
- } else if (this->ProjectFileExtension == ".csproj") {
+ } else if (ProjectFileExtension == ".csproj") {
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ std::string message = "The C# target \"" +
+ 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->ProjectType = csproj;
this->Managed = true;
}
// 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", this->ProjectFileExtension.c_str());
+ this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
+ ProjectFileExtension.c_str());
+ this->DotNetHintReferences.clear();
+ this->AdditionalUsingDirectories.clear();
if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
if (!this->ComputeClOptions()) {
return;
std::string path = this->LocalGenerator->GetCurrentBinaryDirectory();
path += "/";
path += this->Name;
- path += this->ProjectFileExtension;
- this->BuildFileStream = new cmGeneratedFileStream(path.c_str());
- this->PathToProjectFile = path;
- this->BuildFileStream->SetCopyIfDifferent(true);
+ path += ProjectFileExtension;
+ cmGeneratedFileStream BuildFileStream(path.c_str());
+ const std::string PathToProjectFile = path;
+ BuildFileStream.SetCopyIfDifferent(true);
// Write the encoding header into the file
char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
- this->BuildFileStream->write(magic, 3);
-
- // get the tools version to use
- const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
- std::string project_defaults = "<?xml version=\"1.0\" encoding=\"" +
- this->GlobalGenerator->Encoding() + "\"?>\n";
- project_defaults.append("<Project DefaultTargets=\"Build\" ToolsVersion=\"");
- project_defaults.append(toolsVer + "\" ");
- project_defaults.append(
- "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
- this->WriteString(project_defaults.c_str(), 0);
-
- if (this->NsightTegra) {
- this->WriteString("<PropertyGroup Label=\"NsightTegraProject\">\n", 1);
- const int nsightTegraMajorVersion = this->NsightTegraVersion[0];
- const int nsightTegraMinorVersion = this->NsightTegraVersion[1];
- if (nsightTegraMajorVersion >= 2) {
- this->WriteString("<NsightTegraProjectRevisionNumber>", 2);
- if (nsightTegraMajorVersion > 3 ||
- (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) {
- (*this->BuildFileStream) << "11";
+ BuildFileStream.write(magic, 3);
+ BuildFileStream << "<?xml version=\"1.0\" encoding=\""
+ << this->GlobalGenerator->Encoding() << "\"?>"
+ << "\n";
+ {
+ Elem e0(BuildFileStream);
+ e0.StartElement("Project");
+ e0.Attribute("DefaultTargets", "Build");
+ e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion());
+ e0.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
+
+ if (this->NsightTegra) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Label", "NsightTegraProject");
+ const unsigned int nsightTegraMajorVersion = this->NsightTegraVersion[0];
+ const unsigned int nsightTegraMinorVersion = this->NsightTegraVersion[1];
+ if (nsightTegraMajorVersion >= 2) {
+ if (nsightTegraMajorVersion > 3 ||
+ (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) {
+ e1.Element("NsightTegraProjectRevisionNumber", "11");
+ } else {
+ // Nsight Tegra 2.0 uses project revision 9.
+ e1.Element("NsightTegraProjectRevisionNumber", "9");
+ }
+ // Tell newer versions to upgrade silently when loading.
+ e1.Element("NsightTegraUpgradeOnceWithoutPrompt", "true");
} else {
- // Nsight Tegra 2.0 uses project revision 9.
- (*this->BuildFileStream) << "9";
+ // Require Nsight Tegra 1.6 for JCompile support.
+ e1.Element("NsightTegraProjectRevisionNumber", "7");
}
- (*this->BuildFileStream) << "</NsightTegraProjectRevisionNumber>\n";
- // Tell newer versions to upgrade silently when loading.
- this->WriteString("<NsightTegraUpgradeOnceWithoutPrompt>"
- "true"
- "</NsightTegraUpgradeOnceWithoutPrompt>\n",
- 2);
- } else {
- // Require Nsight Tegra 1.6 for JCompile support.
- this->WriteString("<NsightTegraProjectRevisionNumber>"
- "7"
- "</NsightTegraProjectRevisionNumber>\n",
- 2);
}
- this->WriteString("</PropertyGroup>\n", 1);
- }
- if (const char* hostArch =
- this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
- this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<PreferredToolArchitecture>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(hostArch)
- << "</PreferredToolArchitecture>\n";
- this->WriteString("</PropertyGroup>\n", 1);
- }
+ if (const char* hostArch =
+ this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("PreferredToolArchitecture", hostArch);
+ }
- if (this->ProjectType != csproj) {
- this->WriteProjectConfigurations();
- }
- this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
- this->WriteString("<ProjectGuid>", 2);
- (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGuid>\n";
+ if (this->ProjectType != csproj) {
+ this->WriteProjectConfigurations(e0);
+ }
- if (this->MSTools &&
- this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
- this->WriteApplicationTypeSettings();
- this->VerifyNecessaryFiles();
- }
+ {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Label", "Globals");
+ e1.Element("ProjectGuid", "{" + this->GUID + "}");
+
+ if (this->MSTools &&
+ this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
+ this->WriteApplicationTypeSettings(e1);
+ this->VerifyNecessaryFiles();
+ }
- const char* vsProjectTypes =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
- if (vsProjectTypes) {
- std::string tagName = "ProjectTypes";
- if (this->ProjectType == csproj) {
- tagName = "ProjectTypeGuids";
- }
- this->WriteString("", 2);
- (*this->BuildFileStream) << "<" << tagName << ">"
- << cmVS10EscapeXML(vsProjectTypes) << "</"
- << tagName << ">\n";
- }
+ const char* vsProjectTypes =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
+ if (vsProjectTypes) {
+ const char* tagName = "ProjectTypes";
+ if (this->ProjectType == csproj) {
+ tagName = "ProjectTypeGuids";
+ }
+ e1.Element(tagName, vsProjectTypes);
+ }
- const char* vsProjectName =
- this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
- const char* vsLocalPath =
- this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
- const char* vsProvider =
- this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
+ const char* vsProjectName =
+ this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
+ const char* vsLocalPath =
+ this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
+ const char* vsProvider =
+ this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
+
+ if (vsProjectName && vsLocalPath && vsProvider) {
+ e1.Element("SccProjectName", vsProjectName);
+ e1.Element("SccLocalPath", vsLocalPath);
+ e1.Element("SccProvider", vsProvider);
+
+ const char* vsAuxPath =
+ this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
+ if (vsAuxPath) {
+ e1.Element("SccAuxPath", vsAuxPath);
+ }
+ }
- if (vsProjectName && vsLocalPath && vsProvider) {
- this->WriteString("<SccProjectName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectName)
- << "</SccProjectName>\n";
- this->WriteString("<SccLocalPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsLocalPath)
- << "</SccLocalPath>\n";
- this->WriteString("<SccProvider>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProvider)
- << "</SccProvider>\n";
+ if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
+ e1.Element("WinMDAssembly", "true");
+ }
- const char* vsAuxPath =
- this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
- if (vsAuxPath) {
- this->WriteString("<SccAuxPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsAuxPath)
- << "</SccAuxPath>\n";
- }
- }
+ const char* vsGlobalKeyword =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
+ if (!vsGlobalKeyword) {
+ e1.Element("Keyword", "Win32Proj");
+ } else {
+ e1.Element("Keyword", vsGlobalKeyword);
+ }
- if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
- this->WriteString("<WinMDAssembly>true</WinMDAssembly>\n", 2);
- }
+ const char* vsGlobalRootNamespace =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
+ if (vsGlobalRootNamespace) {
+ e1.Element("RootNamespace", vsGlobalRootNamespace);
+ }
- const char* vsGlobalKeyword =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
- if (!vsGlobalKeyword) {
- this->WriteString("<Keyword>Win32Proj</Keyword>\n", 2);
- } else {
- this->WriteString("<Keyword>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalKeyword)
- << "</Keyword>\n";
- }
-
- const char* vsGlobalRootNamespace =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
- if (vsGlobalRootNamespace) {
- this->WriteString("<RootNamespace>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalRootNamespace)
- << "</RootNamespace>\n";
- }
-
- this->WriteString("<Platform>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
- << "</Platform>\n";
- const char* projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
- if (!projLabel) {
- projLabel = this->Name.c_str();
- }
- this->WriteString("<ProjectName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(projLabel) << "</ProjectName>\n";
- if (const char* targetFrameworkVersion = this->GeneratorTarget->GetProperty(
- "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
- this->WriteString("<TargetFrameworkVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetFrameworkVersion)
- << "</TargetFrameworkVersion>\n";
- }
-
- // Disable the project upgrade prompt that is displayed the first time a
- // project using an older toolset version is opened in a newer version of
- // the IDE (respected by VS 2013 and above).
- if (this->GlobalGenerator->GetVersion() >=
- cmGlobalVisualStudioGenerator::VS12) {
- this->WriteString("<VCProjectUpgraderObjectName>NoUpgrade"
- "</VCProjectUpgraderObjectName>\n",
- 2);
- }
-
- std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
- for (std::string const& keyIt : keys) {
- static const char* prefix = "VS_GLOBAL_";
- if (keyIt.find(prefix) != 0)
- continue;
- std::string globalKey = keyIt.substr(strlen(prefix));
- // Skip invalid or separately-handled properties.
- if (globalKey.empty() || globalKey == "PROJECT_TYPES" ||
- globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
- continue;
+ e1.Element("Platform", this->Platform);
+ const char* projLabel =
+ this->GeneratorTarget->GetProperty("PROJECT_LABEL");
+ if (!projLabel) {
+ projLabel = this->Name.c_str();
+ }
+ e1.Element("ProjectName", projLabel);
+ {
+ // TODO: add deprecation warning for VS_* property?
+ const char* targetFrameworkVersion =
+ this->GeneratorTarget->GetProperty(
+ "VS_DOTNET_TARGET_FRAMEWORK_VERSION");
+ if (!targetFrameworkVersion) {
+ targetFrameworkVersion = this->GeneratorTarget->GetProperty(
+ "DOTNET_TARGET_FRAMEWORK_VERSION");
+ }
+ if (targetFrameworkVersion) {
+ e1.Element("TargetFrameworkVersion", targetFrameworkVersion);
+ }
+ }
+
+ // Disable the project upgrade prompt that is displayed the first time a
+ // project using an older toolset version is opened in a newer version of
+ // the IDE (respected by VS 2013 and above).
+ if (this->GlobalGenerator->GetVersion() >=
+ cmGlobalVisualStudioGenerator::VS12) {
+ e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
+ }
+
+ std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
+ for (std::string const& keyIt : keys) {
+ static const char* prefix = "VS_GLOBAL_";
+ if (keyIt.find(prefix) != 0)
+ continue;
+ std::string globalKey = keyIt.substr(strlen(prefix));
+ // Skip invalid or separately-handled properties.
+ if (globalKey.empty() || globalKey == "PROJECT_TYPES" ||
+ globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
+ continue;
+ }
+ const char* value = this->GeneratorTarget->GetProperty(keyIt);
+ if (!value)
+ continue;
+ e1.Element(globalKey.c_str(), value);
+ }
+
+ if (this->Managed) {
+ std::string outputType;
+ switch (this->GeneratorTarget->GetType()) {
+ case cmStateEnums::OBJECT_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ outputType = "Library";
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ outputType = "Module";
+ break;
+ case cmStateEnums::EXECUTABLE:
+ if (this->GeneratorTarget->Target->GetPropertyAsBool(
+ "WIN32_EXECUTABLE")) {
+ outputType = "WinExe";
+ } else {
+ outputType = "Exe";
+ }
+ break;
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ outputType = "Utility";
+ break;
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ break;
+ }
+ e1.Element("OutputType", outputType);
+ e1.Element("AppDesignerFolder", "Properties");
+ }
}
- const char* value = this->GeneratorTarget->GetProperty(keyIt);
- if (!value)
- continue;
- this->WriteString("<", 2);
- (*this->BuildFileStream) << globalKey << ">" << cmVS10EscapeXML(value)
- << "</" << globalKey << ">\n";
- }
- if (this->Managed) {
- std::string outputType = "<OutputType>";
- switch (this->GeneratorTarget->GetType()) {
- case cmStateEnums::OBJECT_LIBRARY:
- case cmStateEnums::STATIC_LIBRARY:
- case cmStateEnums::SHARED_LIBRARY:
- outputType += "Library";
- break;
- case cmStateEnums::MODULE_LIBRARY:
- outputType += "Module";
- break;
- case cmStateEnums::EXECUTABLE:
- if (this->GeneratorTarget->Target->GetPropertyAsBool(
- "WIN32_EXECUTABLE")) {
- outputType += "WinExe";
- } else {
- outputType += "Exe";
+ switch (this->ProjectType) {
+ case vcxproj:
+ if (this->GlobalGenerator->GetPlatformToolsetVersion()) {
+ Elem(e0, "Import")
+ .Attribute("Project",
+ this->GlobalGenerator->GetAuxiliaryToolset());
}
+ Elem(e0, "Import").Attribute("Project", VS10_CXX_DEFAULT_PROPS);
break;
- case cmStateEnums::UTILITY:
- case cmStateEnums::GLOBAL_TARGET:
- outputType += "Utility";
- break;
- case cmStateEnums::UNKNOWN_LIBRARY:
- case cmStateEnums::INTERFACE_LIBRARY:
+ case csproj:
+ Elem(e0, "Import")
+ .Attribute("Project", VS10_CSharp_DEFAULT_PROPS)
+ .Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')");
break;
}
- outputType += "</OutputType>\n";
- this->WriteString(outputType.c_str(), 2);
- this->WriteString("<AppDesignerFolder>Properties</AppDesignerFolder>\n",
- 2);
- }
- this->WriteString("</PropertyGroup>\n", 1);
+ this->WriteProjectConfigurationValues(e0);
- switch (this->ProjectType) {
- case vcxproj:
- this->WriteString("<Import Project=\"" VS10_CXX_DEFAULT_PROPS "\" />\n",
- 1);
- break;
- case csproj:
- this->WriteString("<Import Project=\"" VS10_CSharp_DEFAULT_PROPS "\" "
- "Condition=\"Exists('" VS10_CSharp_DEFAULT_PROPS "')\""
- "/>\n",
- 1);
- break;
- }
+ if (this->ProjectType == vcxproj) {
+ Elem(e0, "Import").Attribute("Project", VS10_CXX_PROPS);
+ }
+ {
+ Elem e1(e0, "ImportGroup");
+ e1.Attribute("Label", "ExtensionSettings");
+ e1.SetHasElements();
+
+ if (this->GlobalGenerator->IsCudaEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\CUDA " +
+ this->GlobalGenerator->GetPlatformToolsetCudaString() +
+ ".props");
+ }
+ if (this->GlobalGenerator->IsMasmEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\masm.props");
+ }
+ if (this->GlobalGenerator->IsNasmEnabled()) {
+ // Always search in the standard modules location.
+ std::string propsTemplate =
+ GetCMakeFilePath("Templates/MSBuild/nasm.props.in");
+
+ std::string propsLocal;
+ propsLocal += this->DefaultArtifactDir;
+ propsLocal += "\\nasm.props";
+ ConvertToWindowsSlash(propsLocal);
+ this->Makefile->ConfigureFile(propsTemplate.c_str(),
+ propsLocal.c_str(), false, true, true);
+ Elem(e1, "Import").Attribute("Project", propsLocal);
+ }
+ }
+ {
+ Elem e1(e0, "ImportGroup");
+ e1.Attribute("Label", "PropertySheets");
+ std::string props;
+ switch (this->ProjectType) {
+ case vcxproj:
+ props = VS10_CXX_USER_PROPS;
+ break;
+ case csproj:
+ props = VS10_CSharp_USER_PROPS;
+ break;
+ }
+ if (const char* p =
+ this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
+ props = p;
+ }
+ if (!props.empty()) {
+ ConvertToWindowsSlash(props);
+ Elem(e1, "Import")
+ .Attribute("Project", props)
+ .Attribute("Condition", "exists('" + props + "')")
+ .Attribute("Label", "LocalAppDataPlatform");
+ }
- this->WriteProjectConfigurationValues();
-
- if (this->ProjectType == vcxproj) {
- this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1);
- }
- this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
- if (this->GlobalGenerator->IsCudaEnabled()) {
- this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\CUDA ",
- 2);
- (*this->BuildFileStream)
- << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString())
- << ".props\" />\n";
- }
- if (this->GlobalGenerator->IsMasmEnabled()) {
- this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\masm.props\" />\n",
- 2);
- }
- if (this->GlobalGenerator->IsNasmEnabled()) {
- // Always search in the standard modules location.
- std::string propsTemplate =
- GetCMakeFilePath("Templates/MSBuild/nasm.props.in");
-
- std::string propsLocal;
- propsLocal += this->DefaultArtifactDir;
- propsLocal += "\\nasm.props";
- ConvertToWindowsSlash(propsLocal);
- this->Makefile->ConfigureFile(propsTemplate.c_str(), propsLocal.c_str(),
- false, true, true);
- std::string import = std::string("<Import Project=\"") +
- cmVS10EscapeXML(propsLocal) + "\" />\n";
- this->WriteString(import.c_str(), 2);
- }
- this->WriteString("</ImportGroup>\n", 1);
- this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1);
- {
- std::string props;
+ this->WritePlatformExtensions(e1);
+ }
+ Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros");
+ this->WriteWinRTPackageCertificateKeyFile(e0);
+ this->WritePathAndIncrementalLinkOptions(e0);
+ this->WriteItemDefinitionGroups(e0);
+ this->WriteCustomCommands(e0);
+ this->WriteAllSources(e0);
+ this->WriteDotNetReferences(e0);
+ this->WriteEmbeddedResourceGroup(e0);
+ this->WriteXamlFilesGroup(e0);
+ this->WriteWinRTReferences(e0);
+ this->WriteProjectReferences(e0);
+ this->WriteSDKReferences(e0);
switch (this->ProjectType) {
case vcxproj:
- props = VS10_CXX_USER_PROPS;
+ Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS);
break;
case csproj:
- props = VS10_CSharp_USER_PROPS;
+ Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS);
break;
}
- if (const char* p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
- props = p;
- }
- if (!props.empty()) {
- ConvertToWindowsSlash(props);
- this->WriteString("", 2);
- (*this->BuildFileStream)
- << "<Import Project=\"" << cmVS10EscapeXML(props) << "\""
- << " Condition=\"exists('" << cmVS10EscapeXML(props) << "')\""
- << " Label=\"LocalAppDataPlatform\" />\n";
- }
- }
- this->WritePlatformExtensions();
- this->WriteString("</ImportGroup>\n", 1);
- this->WriteString("<PropertyGroup Label=\"UserMacros\" />\n", 1);
- this->WriteWinRTPackageCertificateKeyFile();
- this->WritePathAndIncrementalLinkOptions();
- this->WriteItemDefinitionGroups();
- this->WriteCustomCommands();
- this->WriteAllSources();
- this->WriteDotNetReferences();
- this->WriteEmbeddedResourceGroup();
- this->WriteXamlFilesGroup();
- this->WriteWinRTReferences();
- this->WriteProjectReferences();
- this->WriteSDKReferences();
- switch (this->ProjectType) {
- case vcxproj:
- this->WriteString("<Import Project=\"" VS10_CXX_TARGETS "\" />\n", 1);
- break;
- case csproj:
- this->WriteString("<Import Project=\"" VS10_CSharp_TARGETS "\" />\n", 1);
- break;
+
+ this->WriteTargetSpecificReferences(e0);
+ {
+ Elem e1(e0, "ImportGroup");
+ e1.Attribute("Label", "ExtensionTargets");
+ e1.SetHasElements();
+ this->WriteTargetsFileReferences(e1);
+ if (this->GlobalGenerator->IsCudaEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\CUDA " +
+ this->GlobalGenerator->GetPlatformToolsetCudaString() +
+ ".targets");
+ }
+ if (this->GlobalGenerator->IsMasmEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\masm.targets");
+ }
+ if (this->GlobalGenerator->IsNasmEnabled()) {
+ std::string nasmTargets =
+ GetCMakeFilePath("Templates/MSBuild/nasm.targets");
+ Elem(e1, "Import").Attribute("Project", nasmTargets);
+ }
+ }
+ if (this->ProjectType == csproj) {
+ for (std::string const& c : this->Configurations) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Condition", "'$(Configuration)' == '" + c + "'");
+ e1.SetHasElements();
+ this->WriteEvents(e1, c);
+ }
+ // make sure custom commands are executed before build (if necessary)
+ {
+ Elem e1(e0, "PropertyGroup");
+ std::ostringstream oss;
+ oss << "\n";
+ for (std::string const& i : this->CSharpCustomCommandNames) {
+ oss << " " << i << ";\n";
+ }
+ oss << " "
+ << "$(BuildDependsOn)\n";
+ e1.Element("BuildDependsOn", oss.str());
+ }
+ }
+ }
+
+ if (BuildFileStream.Close()) {
+ this->GlobalGenerator->FileReplacedDuringGenerate(PathToProjectFile);
}
- this->WriteTargetSpecificReferences();
- this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
- this->WriteTargetsFileReferences();
- if (this->GlobalGenerator->IsCudaEnabled()) {
- this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\CUDA ",
- 2);
- (*this->BuildFileStream)
- << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString())
- << ".targets\" />\n";
- }
- if (this->GlobalGenerator->IsMasmEnabled()) {
- this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\masm.targets\" />\n",
- 2);
- }
- if (this->GlobalGenerator->IsNasmEnabled()) {
- std::string nasmTargets =
- GetCMakeFilePath("Templates/MSBuild/nasm.targets");
- std::string import = "<Import Project=\"";
- import += cmVS10EscapeXML(nasmTargets) + "\" />\n";
- this->WriteString(import.c_str(), 2);
- }
- this->WriteString("</ImportGroup>\n", 1);
- if (this->ProjectType == csproj) {
- for (std::string const& i : this->Configurations) {
- this->WriteString("<PropertyGroup Condition=\"'$(Configuration)' == '",
- 1);
- (*this->BuildFileStream) << i << "'\">\n";
- this->WriteEvents(i);
- this->WriteString("</PropertyGroup>\n", 1);
- }
- // make sure custom commands are executed before build (if necessary)
- this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<BuildDependsOn>\n", 2);
- for (std::string const& i : this->CSharpCustomCommandNames) {
- this->WriteString(i.c_str(), 3);
- (*this->BuildFileStream) << ";\n";
- }
- this->WriteString("$(BuildDependsOn)\n", 3);
- this->WriteString("</BuildDependsOn>\n", 2);
- this->WriteString("</PropertyGroup>\n", 1);
- }
- this->WriteString("</Project>", 0);
// The groups are stored in a separate file for VS 10
this->WriteGroups();
}
-void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
+void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0)
{
std::vector<std::string> references;
- typedef std::pair<std::string, std::string> HintReference;
- std::vector<HintReference> hintReferences;
if (const char* vsDotNetReferences =
this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) {
cmSystemTools::ExpandListArgument(vsDotNetReferences, references);
if (!name.empty()) {
std::string path = i.second.GetValue();
if (!cmsys::SystemTools::FileIsFullPath(path)) {
- path = std::string(this->GeneratorTarget->Target->GetMakefile()
- ->GetCurrentSourceDirectory()) +
+ path = std::string(this->Makefile->GetCurrentSourceDirectory()) +
"/" + path;
}
ConvertToWindowsSlash(path);
- hintReferences.push_back(HintReference(name, path));
+ this->DotNetHintReferences[""].push_back(
+ DotNetHintReference(name, path));
}
}
}
- if (!references.empty() || !hintReferences.empty()) {
- this->WriteString("<ItemGroup>\n", 1);
+ if (!references.empty() || !this->DotNetHintReferences.empty()) {
+ Elem e1(e0, "ItemGroup");
for (std::string const& ri : references) {
// if the entry from VS_DOTNET_REFERENCES is an existing file, generate
// a new hint-reference and name it from the filename
std::string name = cmsys::SystemTools::GetFilenameWithoutExtension(ri);
std::string path = ri;
ConvertToWindowsSlash(path);
- hintReferences.push_back(HintReference(name, path));
+ this->DotNetHintReferences[""].push_back(
+ DotNetHintReference(name, path));
} else {
- this->WriteDotNetReference(ri, "");
+ this->WriteDotNetReference(e1, ri, "", "");
}
}
- for (const auto& i : hintReferences) {
- this->WriteDotNetReference(i.first, i.second);
+ for (const auto& h : this->DotNetHintReferences) {
+ // DotNetHintReferences is also populated from AddLibraries().
+ // The configuration specific hint references are added there.
+ for (const auto& i : h.second) {
+ this->WriteDotNetReference(e1, i.first, i.second, h.first);
+ }
}
- this->WriteString("</ItemGroup>\n", 1);
}
}
void cmVisualStudio10TargetGenerator::WriteDotNetReference(
- std::string const& ref, std::string const& hint)
+ Elem& e1, std::string const& ref, std::string const& hint,
+ std::string const& config)
{
- this->WriteString("<Reference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(ref) << "\">\n";
- this->WriteString("<CopyLocalSatelliteAssemblies>true"
- "</CopyLocalSatelliteAssemblies>\n",
- 3);
- this->WriteString("<ReferenceOutputAssembly>true"
- "</ReferenceOutputAssembly>\n",
- 3);
+ Elem e2(e1, "Reference");
+ // If 'config' is not empty, the reference is only added for the given
+ // configuration. This is used when referencing imported managed assemblies.
+ // See also cmVisualStudio10TargetGenerator::AddLibraries().
+ if (!config.empty()) {
+ e2.Attribute("Condition", this->CalcCondition(config));
+ }
+ e2.Attribute("Include", ref);
+ e2.Element("CopyLocalSatelliteAssemblies", "true");
+ e2.Element("ReferenceOutputAssembly", "true");
if (!hint.empty()) {
const char* privateReference = "True";
if (const char* value = this->GeneratorTarget->GetProperty(
privateReference = "False";
}
}
- this->WriteString("<Private>", 3);
- (*this->BuildFileStream) << privateReference << "</Private>\n";
- this->WriteString("<HintPath>", 3);
- (*this->BuildFileStream) << hint << "</HintPath>\n";
+ e2.Element("Private", privateReference);
+ e2.Element("HintPath", hint);
}
- this->WriteDotNetReferenceCustomTags(ref);
- this->WriteString("</Reference>\n", 2);
+ this->WriteDotNetReferenceCustomTags(e2, ref);
}
void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags(
- std::string const& ref)
+ Elem& e2, std::string const& ref)
{
static const std::string refpropPrefix = "VS_DOTNET_REFERENCEPROP_";
}
}
for (auto const& tag : tags) {
- this->WriteString("<", 3);
- (*this->BuildFileStream) << tag.first << ">" << cmVS10EscapeXML(tag.second)
- << "</" << tag.first << ">\n";
+ e2.Element(tag.first.c_str(), tag.second);
}
}
-void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
+void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
{
std::vector<cmSourceFile const*> resxObjs;
this->GeneratorTarget->GetResxSources(resxObjs, "");
if (!resxObjs.empty()) {
- this->WriteString("<ItemGroup>\n", 1);
+ Elem e1(e0, "ItemGroup");
std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
ConvertToWindowsSlash(srcDir);
for (cmSourceFile const* oi : resxObjs) {
std::string obj = oi->GetFullPath();
- this->WriteString("<EmbeddedResource Include=\"", 2);
ConvertToWindowsSlash(obj);
bool useRelativePath = false;
if (this->ProjectType == csproj && this->InSourceBuild) {
useRelativePath = true;
}
}
- (*this->BuildFileStream) << obj << "\">\n";
+ Elem e2(e1, "EmbeddedResource");
+ e2.Attribute("Include", obj);
if (this->ProjectType != csproj) {
- this->WriteString("<DependentUpon>", 3);
std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
- (*this->BuildFileStream) << hFileName << "</DependentUpon>\n";
+ e2.Element("DependentUpon", hFileName);
- for (std::string const& i : this->Configurations) {
- this->WritePlatformConfigTag("LogicalName", i, 3);
+ for (std::string const& c : this->Configurations) {
+ std::string s;
if (this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE") ||
// Handle variant of VS_GLOBAL_<variable> for RootNamespace.
this->GeneratorTarget->GetProperty("VS_GLOBAL_RootNamespace")) {
- (*this->BuildFileStream) << "$(RootNamespace).";
+ s = "$(RootNamespace).";
}
- (*this->BuildFileStream) << "%(Filename)";
- (*this->BuildFileStream) << ".resources";
- (*this->BuildFileStream) << "</LogicalName>\n";
+ s += "%(Filename).resources";
+ e2.WritePlatformConfigTag("LogicalName", this->CalcCondition(c), s);
}
} else {
std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
link = cmsys::SystemTools::GetFilenameName(obj);
}
if (!link.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ e2.Element("Link", link);
}
}
// Determine if this is a generated resource from a .Designer.cs file
generator = g;
}
if (!generator.empty()) {
- this->WriteString("<Generator>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(generator)
- << "</Generator>\n";
+ e2.Element("Generator", generator);
if (designerResource.find(srcDir) == 0) {
designerResource = designerResource.substr(srcDir.length() + 1);
} else if (designerResource.find(binDir) == 0) {
cmsys::SystemTools::GetFilenameName(designerResource);
}
ConvertToWindowsSlash(designerResource);
- this->WriteString("<LastGenOutput>", 3);
- (*this->BuildFileStream) << designerResource
- << "</LastGenOutput>\n";
+ e2.Element("LastGenOutput", designerResource);
}
}
const cmPropertyMap& props = oi->GetProperties();
if (!tagName.empty()) {
std::string value = props.GetPropertyValue(p.first);
if (!value.empty()) {
- this->WriteString("<", 3);
- (*this->BuildFileStream) << tagName << ">";
- (*this->BuildFileStream) << cmVS10EscapeXML(value);
- (*this->BuildFileStream) << "</" << tagName << ">\n";
+ e2.Element(tagName.c_str(), value);
}
}
}
}
}
-
- this->WriteString("</EmbeddedResource>\n", 2);
}
- this->WriteString("</ItemGroup>\n", 1);
}
}
-void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
+void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0)
{
std::vector<cmSourceFile const*> xamlObjs;
this->GeneratorTarget->GetXamlSources(xamlObjs, "");
if (!xamlObjs.empty()) {
- this->WriteString("<ItemGroup>\n", 1);
+ Elem e1(e0, "ItemGroup");
for (cmSourceFile const* oi : xamlObjs) {
std::string obj = oi->GetFullPath();
- std::string xamlType;
+ const char* xamlType;
const char* xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
if (xamlTypeProperty) {
xamlType = xamlTypeProperty;
xamlType = "Page";
}
- this->WriteSource(xamlType, oi, ">\n");
+ Elem e2(e1);
+ this->WriteSource(e2, xamlType, oi);
+ e2.SetHasElements();
if (this->ProjectType == csproj && !this->InSourceBuild) {
// add <Link> tag to written XAML source if necessary
const std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
}
if (!link.empty()) {
ConvertToWindowsSlash(link);
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ e2.Element("Link", link);
}
}
- this->WriteString("<SubType>Designer</SubType>\n", 3);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << xamlType << ">\n";
+ e2.Element("SubType", "Designer");
}
- this->WriteString("</ItemGroup>\n", 1);
}
}
-void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences()
+void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences(Elem& e0)
{
if (this->MSTools) {
if (this->GlobalGenerator->TargetsWindowsPhone() &&
this->GlobalGenerator->GetSystemVersion() == "8.0") {
- this->WriteString("<Import Project=\""
- "$(MSBuildExtensionsPath)\\Microsoft\\WindowsPhone\\v"
- "$(TargetPlatformVersion)\\Microsoft.Cpp.WindowsPhone."
- "$(TargetPlatformVersion).targets\" />\n",
- 1);
+ Elem(e0, "Import")
+ .Attribute("Project",
+ "$(MSBuildExtensionsPath)\\Microsoft\\WindowsPhone\\v"
+ "$(TargetPlatformVersion)\\Microsoft.Cpp.WindowsPhone."
+ "$(TargetPlatformVersion).targets");
}
}
}
-void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences()
+void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences(Elem& e1)
{
- for (std::vector<TargetsFileAndConfigs>::iterator i =
- this->TargetsFileAndConfigsVec.begin();
- i != this->TargetsFileAndConfigsVec.end(); ++i) {
- TargetsFileAndConfigs const& tac = *i;
- this->WriteString("<Import Project=\"", 3);
- (*this->BuildFileStream) << tac.File << "\" ";
- (*this->BuildFileStream) << "Condition=\"";
- (*this->BuildFileStream) << "Exists('" << tac.File << "')";
+ for (TargetsFileAndConfigs const& tac : this->TargetsFileAndConfigsVec) {
+ std::ostringstream oss;
+ oss << "Exists('" << tac.File << "')";
if (!tac.Configs.empty()) {
- (*this->BuildFileStream) << " And (";
+ oss << " And (";
for (size_t j = 0; j < tac.Configs.size(); ++j) {
if (j > 0) {
- (*this->BuildFileStream) << " Or ";
+ oss << " Or ";
}
- (*this->BuildFileStream) << "'$(Configuration)'=='" << tac.Configs[j]
- << "'";
+ oss << "'$(Configuration)'=='" << tac.Configs[j] << "'";
}
- (*this->BuildFileStream) << ")";
+ oss << ")";
}
- (*this->BuildFileStream) << "\" />\n";
+
+ Elem(e1, "Import")
+ .Attribute("Project", tac.File)
+ .Attribute("Condition", oss.str());
}
}
-void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
+void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0)
{
std::vector<std::string> references;
if (const char* vsWinRTReferences =
references.push_back("platform.winmd");
}
if (!references.empty()) {
- this->WriteString("<ItemGroup>\n", 1);
- for (std::vector<std::string>::iterator ri = references.begin();
- ri != references.end(); ++ri) {
- this->WriteString("<Reference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\">\n";
- this->WriteString("<IsWinMDFile>true</IsWinMDFile>\n", 3);
- this->WriteString("</Reference>\n", 2);
+ Elem e1(e0, "ItemGroup");
+ for (std::string const& ri : references) {
+ Elem e2(e1, "Reference");
+ e2.Attribute("Include", ri);
+ e2.Element("IsWinMDFile", "true");
}
- this->WriteString("</ItemGroup>\n", 1);
}
}
// ConfigurationType Application, Utility StaticLibrary DynamicLibrary
-void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
+void cmVisualStudio10TargetGenerator::WriteProjectConfigurations(Elem& e0)
{
- this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1);
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WriteString("<ProjectConfiguration Include=\"", 2);
- (*this->BuildFileStream) << *i << "|" << this->Platform << "\">\n";
- this->WriteString("<Configuration>", 3);
- (*this->BuildFileStream) << *i << "</Configuration>\n";
- this->WriteString("<Platform>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
- << "</Platform>\n";
- this->WriteString("</ProjectConfiguration>\n", 2);
- }
- this->WriteString("</ItemGroup>\n", 1);
+ Elem e1(e0, "ItemGroup");
+ e1.Attribute("Label", "ProjectConfigurations");
+ for (std::string const& c : this->Configurations) {
+ Elem e2(e1, "ProjectConfiguration");
+ e2.Attribute("Include", c + "|" + this->Platform);
+ e2.Element("Configuration", c);
+ e2.Element("Platform", this->Platform);
+ }
}
-void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
+void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
{
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WritePlatformConfigTag("PropertyGroup", *i, 1,
- " Label=\"Configuration\"", "\n");
+ for (std::string const& c : this->Configurations) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Condition", this->CalcCondition(c));
+ e1.Attribute("Label", "Configuration");
if (this->ProjectType != csproj) {
- std::string configType = "<ConfigurationType>";
+ std::string configType;
if (const char* vsConfigurationType =
this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
- configType += cmVS10EscapeXML(vsConfigurationType);
+ configType = vsConfigurationType;
} else {
switch (this->GeneratorTarget->GetType()) {
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
- configType += "DynamicLibrary";
+ configType = "DynamicLibrary";
break;
case cmStateEnums::OBJECT_LIBRARY:
case cmStateEnums::STATIC_LIBRARY:
- configType += "StaticLibrary";
+ configType = "StaticLibrary";
break;
case cmStateEnums::EXECUTABLE:
if (this->NsightTegra &&
!this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
// Android executables are .so too.
- configType += "DynamicLibrary";
+ configType = "DynamicLibrary";
} else {
- configType += "Application";
+ configType = "Application";
}
break;
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
if (this->NsightTegra) {
// Tegra-Android platform does not understand "Utility".
- configType += "StaticLibrary";
+ configType = "StaticLibrary";
} else {
- configType += "Utility";
+ configType = "Utility";
}
break;
case cmStateEnums::UNKNOWN_LIBRARY:
break;
}
}
- configType += "</ConfigurationType>\n";
- this->WriteString(configType.c_str(), 2);
+ e1.Element("ConfigurationType", configType);
}
if (this->MSTools) {
if (!this->Managed) {
- this->WriteMSToolConfigurationValues(*i);
+ this->WriteMSToolConfigurationValues(e1, c);
} else {
- this->WriteMSToolConfigurationValuesManaged(*i);
+ this->WriteMSToolConfigurationValuesManaged(e1, c);
}
} else if (this->NsightTegra) {
- this->WriteNsightTegraConfigurationValues(*i);
+ this->WriteNsightTegraConfigurationValues(e1, c);
}
-
- this->WriteString("</PropertyGroup>\n", 1);
}
}
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- const char* mfcFlag =
- this->GeneratorTarget->Target->GetMakefile()->GetDefinition(
- "CMAKE_MFC_FLAG");
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
if (mfcFlag) {
std::string const mfcFlagValue = mfcFlag;
useOfMfcValue = "Dynamic";
}
}
- std::string mfcLine = "<UseOfMfc>";
- mfcLine += useOfMfcValue + "</UseOfMfc>\n";
- this->WriteString(mfcLine.c_str(), 2);
+ e1.Element("UseOfMfc", useOfMfcValue);
}
if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY &&
this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore() ||
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
- this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2);
+ e1.Element("CharacterSet", "Unicode");
} else if (this->GeneratorTarget->GetType() <=
cmStateEnums::MODULE_LIBRARY &&
this->ClOptions[config]->UsingSBCS()) {
- this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2);
+ e1.Element("CharacterSet", "NotSet");
} else {
- this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2);
+ e1.Element("CharacterSet", "MultiByte");
}
if (const char* toolset = gg->GetPlatformToolset()) {
- std::string pts = "<PlatformToolset>";
- pts += toolset;
- pts += "</PlatformToolset>\n";
- this->WriteString(pts.c_str(), 2);
+ e1.Element("PlatformToolset", toolset);
}
if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
- this->WriteString("<WindowsAppContainer>true"
- "</WindowsAppContainer>\n",
- 2);
+ e1.Element("WindowsAppContainer", "true");
}
}
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
Options& o = *(this->ClOptions[config]);
if (o.IsDebug()) {
- this->WriteString("<DebugSymbols>true</DebugSymbols>\n", 2);
- this->WriteString("<DefineDebug>true</DefineDebug>\n", 2);
+ e1.Element("DebugSymbols", "true");
+ e1.Element("DefineDebug", "true");
}
std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
ConvertToWindowsSlash(outDir);
- this->WriteString("<OutputPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(outDir) << "</OutputPath>\n";
+ e1.Element("OutputPath", outDir);
if (o.HasFlag("Platform")) {
- this->WriteString("<PlatformTarget>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(o.GetFlag("Platform"))
- << "</PlatformTarget>\n";
+ e1.Element("PlatformTarget", o.GetFlag("Platform"));
o.RemoveFlag("Platform");
}
if (const char* toolset = gg->GetPlatformToolset()) {
- this->WriteString("<PlatformToolset>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(toolset)
- << "</PlatformToolset>\n";
+ e1.Element("PlatformToolset", toolset);
}
std::string postfixName = cmSystemTools::UpperCase(config);
if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) {
assemblyName += postfix;
}
- this->WriteString("<AssemblyName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(assemblyName)
- << "</AssemblyName>\n";
+ e1.Element("AssemblyName", assemblyName);
if (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType()) {
- this->WriteString("<StartAction>Program</StartAction>\n", 2);
- this->WriteString("<StartProgram>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(outDir)
- << cmVS10EscapeXML(assemblyName)
- << ".exe</StartProgram>\n";
+ e1.Element("StartAction", "Program");
+ e1.Element("StartProgram", outDir + assemblyName + ".exe");
}
- o.OutputFlagMap(*this->BuildFileStream, " ");
+ OptionsHelper oh(o, e1);
+ oh.OutputFlagMap();
}
//----------------------------------------------------------------------------
void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
- std::string const&)
+ Elem& e1, std::string const&)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
const char* toolset = gg->GetPlatformToolset();
- std::string ntv = "<NdkToolchainVersion>";
- ntv += toolset ? toolset : "Default";
- ntv += "</NdkToolchainVersion>\n";
- this->WriteString(ntv.c_str(), 2);
+ e1.Element("NdkToolchainVersion", toolset ? toolset : "Default");
if (const char* minApi =
this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) {
- this->WriteString("<AndroidMinAPI>", 2);
- (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(minApi)
- << "</AndroidMinAPI>\n";
+ e1.Element("AndroidMinAPI", "android-" + std::string(minApi));
}
if (const char* api = this->GeneratorTarget->GetProperty("ANDROID_API")) {
- this->WriteString("<AndroidTargetAPI>", 2);
- (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(api)
- << "</AndroidTargetAPI>\n";
+ e1.Element("AndroidTargetAPI", "android-" + std::string(api));
}
if (const char* cpuArch =
this->GeneratorTarget->GetProperty("ANDROID_ARCH")) {
- this->WriteString("<AndroidArch>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(cpuArch) << "</AndroidArch>\n";
+ e1.Element("AndroidArch", cpuArch);
}
if (const char* stlType =
this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
- this->WriteString("<AndroidStlType>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(stlType)
- << "</AndroidStlType>\n";
+ e1.Element("AndroidStlType", stlType);
}
}
-void cmVisualStudio10TargetGenerator::WriteCustomCommands()
+void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0)
{
- this->SourcesVisited.clear();
this->CSharpCustomCommandNames.clear();
std::vector<cmSourceFile const*> customCommands;
this->GeneratorTarget->GetCustomCommands(customCommands, "");
- for (std::vector<cmSourceFile const*>::const_iterator si =
- customCommands.begin();
- si != customCommands.end(); ++si) {
- this->WriteCustomCommand(*si);
+ for (cmSourceFile const* si : customCommands) {
+ this->WriteCustomCommand(e0, si);
}
// Add CMakeLists.txt file with rule to re-run CMake for user convenience.
this->GeneratorTarget->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
if (cmSourceFile const* sf =
this->LocalGenerator->CreateVCProjBuildRule()) {
- this->WriteCustomCommand(sf);
+ this->WriteCustomCommand(e0, sf);
}
}
}
void cmVisualStudio10TargetGenerator::WriteCustomCommand(
- cmSourceFile const* sf)
+ Elem& e0, cmSourceFile const* sf)
{
- if (this->SourcesVisited.insert(sf).second) {
+ if (this->LocalGenerator->GetSourcesVisited(this->GeneratorTarget)
+ .insert(sf)
+ .second) {
if (std::vector<cmSourceFile*> const* depends =
this->GeneratorTarget->GetSourceDepends(sf)) {
- for (std::vector<cmSourceFile*>::const_iterator di = depends->begin();
- di != depends->end(); ++di) {
- this->WriteCustomCommand(*di);
+ for (cmSourceFile const* di : *depends) {
+ this->WriteCustomCommand(e0, di);
}
}
if (cmCustomCommand const* command = sf->GetCustomCommand()) {
// C# projects write their <Target> within WriteCustomRule()
- if (this->ProjectType != csproj) {
- this->WriteString("<ItemGroup>\n", 1);
- }
- this->WriteCustomRule(sf, *command);
- if (this->ProjectType != csproj) {
- this->WriteString("</ItemGroup>\n", 1);
- }
+ this->WriteCustomRule(e0, sf, *command);
}
}
}
void cmVisualStudio10TargetGenerator::WriteCustomRule(
- cmSourceFile const* source, cmCustomCommand const& command)
+ Elem& e0, cmSourceFile const* source, cmCustomCommand const& command)
{
std::string sourcePath = source->GetFullPath();
// VS 10 will always rebuild a custom command attached to a .rule
// file that doesn't exist so create the file explicitly.
if (source->GetPropertyAsBool("__CMAKE_RULE")) {
- if (!cmSystemTools::FileExists(sourcePath.c_str())) {
+ if (!cmSystemTools::FileExists(sourcePath)) {
// Make sure the path exists for the file
std::string path = cmSystemTools::GetFilenamePath(sourcePath);
- cmSystemTools::MakeDirectory(path.c_str());
+ cmSystemTools::MakeDirectory(path);
cmsys::ofstream fout(sourcePath.c_str());
if (fout) {
fout << "# generated from CMake\n";
}
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
+ std::unique_ptr<Elem> spe1;
+ std::unique_ptr<Elem> spe2;
if (this->ProjectType != csproj) {
- this->WriteSource("CustomBuild", source, ">\n");
+ spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
+ spe2 = cm::make_unique<Elem>(*spe1);
+ this->WriteSource(*spe2, "CustomBuild", source);
+ spe2->SetHasElements();
} else {
- this->WriteString("<ItemGroup>\n", 1);
+ Elem e1(e0, "ItemGroup");
+ Elem e2(e1);
std::string link;
this->GetCSharpSourceLink(source, link);
- this->WriteSource("None", source, ">\n");
+ this->WriteSource(e2, "None", source);
+ e2.SetHasElements();
if (!link.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ e2.Element("Link", link);
}
- this->WriteString("</None>\n", 2);
- this->WriteString("</ItemGroup>\n", 1);
}
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- cmCustomCommandGenerator ccg(command, *i, this->LocalGenerator);
+ for (std::string const& c : this->Configurations) {
+ cmCustomCommandGenerator ccg(command, c, lg);
std::string comment = lg->ConstructComment(ccg);
comment = cmVS10EscapeComment(comment);
- std::string script = cmVS10EscapeXML(lg->ConstructScript(ccg));
+ std::string script = lg->ConstructScript(ccg);
// input files for custom command
std::stringstream inputs;
- inputs << cmVS10EscapeXML(source->GetFullPath());
- for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin();
- d != ccg.GetDepends().end(); ++d) {
+ inputs << source->GetFullPath();
+ for (std::string const& d : ccg.GetDepends()) {
std::string dep;
- if (this->LocalGenerator->GetRealDependency(*d, *i, dep)) {
+ if (lg->GetRealDependency(d, c, dep)) {
ConvertToWindowsSlash(dep);
- inputs << ";" << cmVS10EscapeXML(dep);
+ inputs << ";" << dep;
}
}
// output files for custom command
std::stringstream outputs;
const char* sep = "";
- for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
- o != ccg.GetOutputs().end(); ++o) {
- std::string out = *o;
+ for (std::string const& o : ccg.GetOutputs()) {
+ std::string out = o;
ConvertToWindowsSlash(out);
- outputs << sep << cmVS10EscapeXML(out);
+ outputs << sep << out;
sep = ";";
}
if (this->ProjectType == csproj) {
- std::string name = "CustomCommand_" + *i + "_" +
+ std::string name = "CustomCommand_" + c + "_" +
cmSystemTools::ComputeStringMD5(sourcePath);
- std::string inputs_s = inputs.str();
- std::string outputs_s = outputs.str();
- comment = cmVS10EscapeQuotes(comment);
- script = cmVS10EscapeQuotes(script);
- inputs_s = cmVS10EscapeQuotes(inputs_s);
- outputs_s = cmVS10EscapeQuotes(outputs_s);
- this->WriteCustomRuleCSharp(*i, name, script, inputs_s, outputs_s,
- comment);
+ this->WriteCustomRuleCSharp(e0, c, name, script, inputs.str(),
+ outputs.str(), comment);
} else {
- this->WriteCustomRuleCpp(*i, script, inputs.str(), outputs.str(),
+ this->WriteCustomRuleCpp(*spe2, c, script, inputs.str(), outputs.str(),
comment);
}
}
- if (this->ProjectType != csproj) {
- this->WriteString("</CustomBuild>\n", 2);
- }
}
void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
- std::string const& config, std::string const& script,
+ Elem& e2, std::string const& config, std::string const& script,
std::string const& inputs, std::string const& outputs,
std::string const& comment)
{
- this->WritePlatformConfigTag("Message", config, 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n";
- this->WritePlatformConfigTag("Command", config, 3);
- (*this->BuildFileStream) << script << "</Command>\n";
- this->WritePlatformConfigTag("AdditionalInputs", config, 3);
- (*this->BuildFileStream) << inputs;
- (*this->BuildFileStream) << ";%(AdditionalInputs)</AdditionalInputs>\n";
- this->WritePlatformConfigTag("Outputs", config, 3);
- (*this->BuildFileStream) << outputs << "</Outputs>\n";
+ const std::string cond = this->CalcCondition(config);
+ e2.WritePlatformConfigTag("Message", cond, comment);
+ e2.WritePlatformConfigTag("Command", cond, script);
+ e2.WritePlatformConfigTag("AdditionalInputs", cond,
+ inputs + ";%(AdditionalInputs)");
+ e2.WritePlatformConfigTag("Outputs", cond, outputs);
if (this->LocalGenerator->GetVersion() >
cmGlobalVisualStudioGenerator::VS10) {
// VS >= 11 let us turn off linking of custom command outputs.
- this->WritePlatformConfigTag("LinkObjects", config, 3);
- (*this->BuildFileStream) << "false</LinkObjects>\n";
+ e2.WritePlatformConfigTag("LinkObjects", cond, "false");
}
}
void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
- std::string const& config, std::string const& name,
+ Elem& e0, std::string const& config, std::string const& name,
std::string const& script, std::string const& inputs,
std::string const& outputs, std::string const& comment)
{
this->CSharpCustomCommandNames.insert(name);
- std::stringstream attributes;
- attributes << "\n Name=\"" << name << "\"";
- attributes << "\n Inputs=\"" << inputs << "\"";
- attributes << "\n Outputs=\"" << outputs << "\"";
- this->WritePlatformConfigTag("Target", config, 1, attributes.str().c_str(),
- "\n");
+ Elem e1(e0, "Target");
+ e1.Attribute("Condition", this->CalcCondition(config));
+ e1.S << "\n Name=\"" << name << "\"";
+ e1.S << "\n Inputs=\"" << cmVS10EscapeAttr(inputs) << "\"";
+ e1.S << "\n Outputs=\"" << cmVS10EscapeAttr(outputs) << "\"";
if (!comment.empty()) {
- this->WriteString("<Exec Command=\"", 2);
- (*this->BuildFileStream) << "echo " << cmVS10EscapeXML(comment)
- << "\" />\n";
+ Elem(e1, "Exec").Attribute("Command", "echo " + comment);
}
- this->WriteString("<Exec Command=\"", 2);
- (*this->BuildFileStream) << script << "\" />\n";
- this->WriteString("</Target>\n", 1);
+ Elem(e1, "Exec").Attribute("Command", script);
}
std::string cmVisualStudio10TargetGenerator::ConvertPath(
{
return forceRelative
? cmSystemTools::RelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), path.c_str())
- : path.c_str();
+ this->LocalGenerator->GetCurrentBinaryDirectory(), path)
+ : path;
}
static void ConvertToWindowsSlash(std::string& s)
pos++;
}
}
+
void cmVisualStudio10TargetGenerator::WriteGroups()
{
if (this->ProjectType == csproj) {
this->GeneratorTarget->GetAllConfigSources();
std::set<cmSourceGroup*> groupsUsed;
- for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
- sources.begin();
- si != sources.end(); ++si) {
- std::string const& source = si->Source->GetFullPath();
+ for (cmGeneratorTarget::AllConfigSource const& si : sources) {
+ std::string const& source = si.Source->GetFullPath();
cmSourceGroup* sourceGroup =
this->Makefile->FindSourceGroup(source, sourceGroups);
groupsUsed.insert(sourceGroup);
fout.SetCopyIfDifferent(true);
char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
fout.write(magic, 3);
- cmGeneratedFileStream* save = this->BuildFileStream;
- this->BuildFileStream = &fout;
-
- // get the tools version to use
- const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
- std::string project_defaults = "<?xml version=\"1.0\" encoding=\"" +
- this->GlobalGenerator->Encoding() + "\"?>\n";
- project_defaults.append("<Project ToolsVersion=\"");
- project_defaults.append(toolsVer + "\" ");
- project_defaults.append(
- "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
- this->WriteString(project_defaults.c_str(), 0);
-
- for (ToolSourceMap::const_iterator ti = this->Tools.begin();
- ti != this->Tools.end(); ++ti) {
- this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
- }
-
- // Added files are images and the manifest.
- if (!this->AddedFiles.empty()) {
- this->WriteString("<ItemGroup>\n", 1);
- for (std::string const& oi : this->AddedFiles) {
- std::string fileName =
- cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(oi));
- if (fileName == "wmappmanifest.xml") {
- this->WriteString("<XML Include=\"", 2);
- (*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
- this->WriteString("</XML>\n", 2);
- } else if (cmSystemTools::GetFilenameExtension(fileName) ==
- ".appxmanifest") {
- this->WriteString("<AppxManifest Include=\"", 2);
- (*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
- this->WriteString("</AppxManifest>\n", 2);
- } else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") {
- this->WriteString("<None Include=\"", 2);
- (*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
- this->WriteString("</None>\n", 2);
- } else {
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
- this->WriteString("</Image>\n", 2);
+
+ fout << "<?xml version=\"1.0\" encoding=\""
+ << this->GlobalGenerator->Encoding() << "\"?>"
+ << "\n";
+ {
+ Elem e0(fout);
+ e0.StartElement("Project");
+ e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion());
+ e0.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
+
+ for (auto const& ti : this->Tools) {
+ this->WriteGroupSources(e0, ti.first, ti.second, sourceGroups);
+ }
+
+ // Added files are images and the manifest.
+ if (!this->AddedFiles.empty()) {
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
+ for (std::string const& oi : this->AddedFiles) {
+ std::string fileName =
+ cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(oi));
+ if (fileName == "wmappmanifest.xml") {
+ Elem e2(e1, "XML");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ } else if (cmSystemTools::GetFilenameExtension(fileName) ==
+ ".appxmanifest") {
+ Elem e2(e1, "AppxManifest");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ } else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") {
+ Elem e2(e1, "None");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ } else {
+ Elem e2(e1, "Image");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ }
}
}
- this->WriteString("</ItemGroup>\n", 1);
- }
- std::vector<cmSourceFile const*> resxObjs;
- this->GeneratorTarget->GetResxSources(resxObjs, "");
- if (!resxObjs.empty()) {
- this->WriteString("<ItemGroup>\n", 1);
- for (cmSourceFile const* oi : resxObjs) {
- std::string obj = oi->GetFullPath();
- this->WriteString("<EmbeddedResource Include=\"", 2);
- ConvertToWindowsSlash(obj);
- (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
- this->WriteString("</EmbeddedResource>\n", 2);
- }
- this->WriteString("</ItemGroup>\n", 1);
- }
-
- this->WriteString("<ItemGroup>\n", 1);
- std::vector<cmSourceGroup*> groupsVec(groupsUsed.begin(), groupsUsed.end());
- std::sort(groupsVec.begin(), groupsVec.end(),
- [](cmSourceGroup* l, cmSourceGroup* r) {
- return l->GetFullName() < r->GetFullName();
- });
- for (cmSourceGroup* sg : groupsVec) {
- std::string const& name = sg->GetFullName();
- if (!name.empty()) {
- this->WriteString("<Filter Include=\"", 2);
- (*this->BuildFileStream) << name << "\">\n";
- std::string guidName = "SG_Filter_";
- guidName += name;
- this->WriteString("<UniqueIdentifier>", 3);
- std::string guid = this->GlobalGenerator->GetGUID(guidName);
- (*this->BuildFileStream) << "{" << guid << "}"
- << "</UniqueIdentifier>\n";
- this->WriteString("</Filter>\n", 2);
- }
- }
-
- if (!resxObjs.empty() || !this->AddedFiles.empty()) {
- this->WriteString("<Filter Include=\"Resource Files\">\n", 2);
- std::string guidName = "SG_Filter_Resource Files";
- this->WriteString("<UniqueIdentifier>", 3);
- std::string guid = this->GlobalGenerator->GetGUID(guidName);
- (*this->BuildFileStream) << "{" << guid << "}"
- << "</UniqueIdentifier>\n";
- this->WriteString("<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;", 3);
- (*this->BuildFileStream) << "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;";
- (*this->BuildFileStream) << "mfcribbon-ms</Extensions>\n";
- this->WriteString("</Filter>\n", 2);
- }
-
- this->WriteString("</ItemGroup>\n", 1);
- this->WriteString("</Project>\n", 0);
- // restore stream pointer
- this->BuildFileStream = save;
+ std::vector<cmSourceFile const*> resxObjs;
+ this->GeneratorTarget->GetResxSources(resxObjs, "");
+ if (!resxObjs.empty()) {
+ Elem e1(e0, "ItemGroup");
+ for (cmSourceFile const* oi : resxObjs) {
+ std::string obj = oi->GetFullPath();
+ ConvertToWindowsSlash(obj);
+ Elem e2(e1, "EmbeddedResource");
+ e2.Attribute("Include", obj);
+ e2.Element("Filter", "Resource Files");
+ }
+ }
+ {
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
+ std::vector<cmSourceGroup*> groupsVec(groupsUsed.begin(),
+ groupsUsed.end());
+ std::sort(groupsVec.begin(), groupsVec.end(),
+ [](cmSourceGroup* l, cmSourceGroup* r) {
+ return l->GetFullName() < r->GetFullName();
+ });
+ for (cmSourceGroup* sg : groupsVec) {
+ std::string const& name = sg->GetFullName();
+ if (!name.empty()) {
+ std::string guidName = "SG_Filter_" + name;
+ std::string guid = this->GlobalGenerator->GetGUID(guidName);
+ Elem e2(e1, "Filter");
+ e2.Attribute("Include", name);
+ e2.Element("UniqueIdentifier", "{" + guid + "}");
+ }
+ }
+
+ if (!resxObjs.empty() || !this->AddedFiles.empty()) {
+ std::string guidName = "SG_Filter_Resource Files";
+ std::string guid = this->GlobalGenerator->GetGUID(guidName);
+ Elem e2(e1, "Filter");
+ e2.Attribute("Include", "Resource Files");
+ e2.Element("UniqueIdentifier", "{" + guid + "}");
+ e2.Element("Extensions",
+ "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;"
+ "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms");
+ }
+ }
+ }
+ fout << '\n';
if (fout.Close()) {
this->GlobalGenerator->FileReplacedDuringGenerate(path);
}
void cmVisualStudio10TargetGenerator::WriteGroupSources(
- const char* name, ToolSources const& sources,
+ Elem& e0, std::string const& name, ToolSources const& sources,
std::vector<cmSourceGroup>& sourceGroups)
{
- this->WriteString("<ItemGroup>\n", 1);
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
for (ToolSource const& s : sources) {
cmSourceFile const* sf = s.SourceFile;
std::string const& source = sf->GetFullPath();
cmSourceGroup* sourceGroup =
this->Makefile->FindSourceGroup(source, sourceGroups);
std::string const& filter = sourceGroup->GetFullName();
- this->WriteString("<", 2);
std::string path = this->ConvertPath(source, s.RelativePath);
ConvertToWindowsSlash(path);
- (*this->BuildFileStream) << name << " Include=\"" << cmVS10EscapeXML(path);
+ Elem e2(e1, name.c_str());
+ e2.Attribute("Include", path);
if (!filter.empty()) {
- (*this->BuildFileStream) << "\">\n";
- this->WriteString("<Filter>", 3);
- (*this->BuildFileStream) << filter << "</Filter>\n";
- this->WriteString("</", 2);
- (*this->BuildFileStream) << name << ">\n";
- } else {
- (*this->BuildFileStream) << "\" />\n";
+ e2.Element("Filter", filter);
}
}
- this->WriteString("</ItemGroup>\n", 1);
}
-void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf)
+void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1,
+ cmSourceFile const* sf)
{
std::string const& fileName = sf->GetFullPath();
+ Elem e2(e1);
+ this->WriteSource(e2, "ClInclude", sf);
if (this->IsResxHeader(fileName)) {
- this->WriteSource("ClInclude", sf, ">\n");
- this->WriteString("<FileType>CppForm</FileType>\n", 3);
- this->WriteString("</ClInclude>\n", 2);
+ e2.Element("FileType", "CppForm");
} else if (this->IsXamlHeader(fileName)) {
- this->WriteSource("ClInclude", sf, ">\n");
- this->WriteString("<DependentUpon>", 3);
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
- (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
- this->WriteString("</ClInclude>\n", 2);
- } else {
- this->WriteSource("ClInclude", sf);
+ e2.Element("DependentUpon", xamlFileName);
}
}
-void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
+void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
+ cmSourceFile const* sf)
{
bool toolHasSettings = false;
- std::string tool = "None";
+ const char* tool = "None";
std::string shaderType;
std::string shaderEntryPoint;
std::string shaderModel;
std::string shaderAdditionalFlags;
std::string shaderDisableOptimizations;
std::string shaderEnableDebug;
+ std::string shaderObjectFileName;
std::string outputHeaderFile;
std::string variableName;
std::string settingsGenerator;
}
// Figure out if debug information should be generated
if (const char* sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) {
- shaderEnableDebug = cmSystemTools::IsOn(sed) ? "true" : "false";
+ shaderEnableDebug = sed;
toolHasSettings = true;
}
// Figure out if optimizations should be disabled
if (const char* sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) {
- shaderDisableOptimizations = cmSystemTools::IsOn(sdo) ? "true" : "false";
+ shaderDisableOptimizations = sdo;
+ toolHasSettings = true;
+ }
+ if (const char* sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) {
+ shaderObjectFileName = sofn;
toolHasSettings = true;
}
} else if (ext == "jpg" || ext == "png") {
}
}
+ Elem e2(e1);
+ this->WriteSource(e2, tool, sf);
if (toolHasSettings) {
- this->WriteSource(tool, sf, ">\n");
+ e2.SetHasElements();
if (!deployContent.empty()) {
cmGeneratorExpression ge;
ge.Parse(deployContent);
// Deployment location cannot be set on a configuration basis
if (!deployLocation.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << deployLocation
- << "\\%(FileName)%(Extension)";
- this->WriteString("</Link>\n", 0);
+ e2.Element("Link", deployLocation + "\\%(FileName)%(Extension)");
}
for (size_t i = 0; i != this->Configurations.size(); ++i) {
- if (0 == strcmp(cge->Evaluate(this->LocalGenerator,
- this->Configurations[i]),
- "1")) {
- this->WriteString("<DeploymentContent Condition=\""
- "'$(Configuration)|$(Platform)'=='",
- 3);
- (*this->BuildFileStream) << this->Configurations[i] << "|"
- << this->Platform << "'\">true";
- this->WriteString("</DeploymentContent>\n", 0);
+ if (0 ==
+ strcmp(
+ cge->Evaluate(this->LocalGenerator, this->Configurations[i]),
+ "1")) {
+ e2.WritePlatformConfigTag("DeploymentContent",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" +
+ this->Platform + "'",
+ "true");
} else {
- this->WriteString("<ExcludedFromBuild Condition=\""
- "'$(Configuration)|$(Platform)'=='",
- 3);
- (*this->BuildFileStream) << this->Configurations[i] << "|"
- << this->Platform << "'\">true";
- this->WriteString("</ExcludedFromBuild>\n", 0);
+ e2.WritePlatformConfigTag("ExcludedFromBuild",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" +
+ this->Platform + "'",
+ "true");
}
}
}
if (!shaderType.empty()) {
- this->WriteString("<ShaderType>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderType)
- << "</ShaderType>\n";
+ e2.Element("ShaderType", shaderType);
}
if (!shaderEntryPoint.empty()) {
- this->WriteString("<EntryPointName>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderEntryPoint)
- << "</EntryPointName>\n";
+ e2.Element("EntryPointName", shaderEntryPoint);
}
if (!shaderModel.empty()) {
- this->WriteString("<ShaderModel>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderModel)
- << "</ShaderModel>\n";
+ e2.Element("ShaderModel", shaderModel);
}
if (!outputHeaderFile.empty()) {
for (size_t i = 0; i != this->Configurations.size(); ++i) {
- this->WriteString("<HeaderFileOutput Condition=\""
- "'$(Configuration)|$(Platform)'=='",
- 3);
- (*this->BuildFileStream) << this->Configurations[i] << "|"
- << this->Platform << "'\">"
- << cmVS10EscapeXML(outputHeaderFile);
- this->WriteString("</HeaderFileOutput>\n", 0);
+ e2.WritePlatformConfigTag("HeaderFileOutput",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" +
+ this->Platform + "'",
+ outputHeaderFile);
}
}
if (!variableName.empty()) {
for (size_t i = 0; i != this->Configurations.size(); ++i) {
- this->WriteString("<VariableName Condition=\""
- "'$(Configuration)|$(Platform)'=='",
- 3);
- (*this->BuildFileStream) << this->Configurations[i] << "|"
- << this->Platform << "'\">"
- << cmVS10EscapeXML(variableName);
- this->WriteString("</VariableName>\n", 0);
+ e2.WritePlatformConfigTag("VariableName",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" +
+ this->Platform + "'",
+ variableName);
}
}
if (!shaderEnableDebug.empty()) {
- this->WriteString("<EnableDebuggingInformation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderEnableDebug)
- << "</EnableDebuggingInformation>\n";
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(shaderEnableDebug);
+
+ for (size_t i = 0; i != this->Configurations.size(); ++i) {
+ const char* enableDebug =
+ cge->Evaluate(this->LocalGenerator, this->Configurations[i]);
+ if (strlen(enableDebug) > 0) {
+ e2.WritePlatformConfigTag(
+ "EnableDebuggingInformation",
+ "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] +
+ "|" + this->Platform + "'",
+ cmSystemTools::IsOn(enableDebug) ? "true" : "false");
+ }
+ }
}
if (!shaderDisableOptimizations.empty()) {
- this->WriteString("<DisableOptimizations>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderDisableOptimizations)
- << "</DisableOptimizations>\n";
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(shaderDisableOptimizations);
+
+ for (size_t i = 0; i != this->Configurations.size(); ++i) {
+ const char* disableOptimizations =
+ cge->Evaluate(this->LocalGenerator, this->Configurations[i]);
+ if (strlen(disableOptimizations) > 0) {
+ e2.WritePlatformConfigTag(
+ "DisableOptimizations",
+ "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] +
+ "|" + this->Platform + "'",
+ (cmSystemTools::IsOn(disableOptimizations) ? "true" : "false"));
+ }
+ }
+ }
+ if (!shaderObjectFileName.empty()) {
+ e2.Element("ObjectFileOutput", shaderObjectFileName);
}
if (!shaderAdditionalFlags.empty()) {
- this->WriteString("<AdditionalOptions>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags)
- << "</AdditionalOptions>\n";
+ e2.Element("AdditionalOptions", shaderAdditionalFlags);
}
if (!settingsGenerator.empty()) {
- this->WriteString("<Generator>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(settingsGenerator)
- << "</Generator>\n";
+ e2.Element("Generator", settingsGenerator);
}
if (!settingsLastGenOutput.empty()) {
- this->WriteString("<LastGenOutput>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(settingsLastGenOutput)
- << "</LastGenOutput>\n";
+ e2.Element("LastGenOutput", settingsLastGenOutput);
}
if (!sourceLink.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(sourceLink) << "</Link>\n";
+ e2.Element("Link", sourceLink);
}
if (!subType.empty()) {
- this->WriteString("<SubType>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(subType) << "</SubType>\n";
+ e2.Element("SubType", subType);
}
if (!copyToOutDir.empty()) {
- this->WriteString("<CopyToOutputDirectory>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(copyToOutDir)
- << "</CopyToOutputDirectory>\n";
+ e2.Element("CopyToOutputDirectory", copyToOutDir);
}
if (!includeInVsix.empty()) {
- this->WriteString("<IncludeInVSIX>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(includeInVsix)
- << "</IncludeInVSIX>\n";
+ e2.Element("IncludeInVSIX", includeInVsix);
}
// write source file specific tags
- this->WriteCSharpSourceProperties(sourceFileTags);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- this->WriteSource(tool, sf);
+ this->WriteCSharpSourceProperties(e2, sourceFileTags);
}
}
-void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
- cmSourceFile const* sf,
- const char* end)
+void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
+ std::string const& tool,
+ cmSourceFile const* sf)
{
// Visual Studio tools append relative paths to the current dir, as in:
//
std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
if (this->LocalGenerator->GetVersion() ==
cmGlobalVisualStudioGenerator::VS10 &&
- cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
+ cmSystemTools::FileIsFullPath(sourceFile)) {
// Normal path conversion resulted in a full path. VS 10 (but not 11)
// refuses to show the property page in the IDE for a source file with a
// full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a
}
}
ConvertToWindowsSlash(sourceFile);
- this->WriteString("<", 2);
- (*this->BuildFileStream) << tool << " Include=\""
- << cmVS10EscapeXML(sourceFile) << "\""
- << (end ? end : " />\n");
+ e2.StartElement(tool.c_str());
+ e2.Attribute("Include", sourceFile);
ToolSource toolSource = { sf, forceRelative };
this->Tools[tool].push_back(toolSource);
}
-void cmVisualStudio10TargetGenerator::WriteAllSources()
+void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
{
if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
return;
}
- this->WriteString("<ItemGroup>\n", 1);
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
std::vector<size_t> all_configs;
for (size_t ci = 0; ci < this->Configurations.size(); ++ci) {
// Skip explicit reference to CMakeLists.txt source.
continue;
}
- std::string tool;
+ const char* tool = nullptr;
switch (si.Kind) {
case cmGeneratorTarget::SourceKindAppManifest:
tool = "AppxManifest";
}
break;
case cmGeneratorTarget::SourceKindExtra:
- this->WriteExtraSource(si.Source);
+ this->WriteExtraSource(e1, si.Source);
break;
case cmGeneratorTarget::SourceKindHeader:
- this->WriteHeaderSource(si.Source);
+ this->WriteHeaderSource(e1, si.Source);
break;
case cmGeneratorTarget::SourceKindIDL:
tool = "Midl";
break;
}
- if (!tool.empty()) {
+ if (tool) {
// Compute set of configurations to exclude, if any.
std::vector<size_t> const& include_configs = si.Configs;
std::vector<size_t> exclude_configs;
include_configs.begin(), include_configs.end(),
std::back_inserter(exclude_configs));
+ Elem e2(e1);
+ this->WriteSource(e2, tool, si.Source);
if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) {
- // FIXME: refactor generation to avoid tracking XML syntax state.
- this->WriteSource(tool, si.Source, "");
- bool have_nested = this->OutputSourceSpecificFlags(si.Source);
- if (!exclude_configs.empty()) {
- if (!have_nested) {
- (*this->BuildFileStream) << ">\n";
- }
- this->WriteExcludeFromBuild(exclude_configs);
- have_nested = true;
- }
- if (have_nested) {
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- (*this->BuildFileStream) << " />\n";
- }
- } else if (!exclude_configs.empty()) {
- this->WriteSource(tool, si.Source, ">\n");
- this->WriteExcludeFromBuild(exclude_configs);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- this->WriteSource(tool, si.Source);
+ this->OutputSourceSpecificFlags(e2, si.Source);
+ }
+ if (!exclude_configs.empty()) {
+ this->WriteExcludeFromBuild(e2, exclude_configs);
}
}
}
if (this->IsMissingFiles) {
- this->WriteMissingFiles();
+ this->WriteMissingFiles(e1);
}
-
- this->WriteString("</ItemGroup>\n", 1);
}
-bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
- cmSourceFile const* source)
+void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
+ Elem& e2, cmSourceFile const* source)
{
cmSourceFile const& sf = *source;
}
}
bool noWinRT = this->TargetCompileAsWinRT && lang == "C";
- bool hasFlags = false;
// for the first time we need a new line if there is something
// produced here.
- const char* firstString = ">\n";
if (!objectName.empty()) {
- (*this->BuildFileStream) << firstString;
- firstString = "";
- hasFlags = true;
if (lang == "CUDA") {
- this->WriteString("<CompileOut>", 3);
- (*this->BuildFileStream) << "$(IntDir)/" << objectName
- << "</CompileOut>\n";
+ e2.Element("CompileOut", "$(IntDir)/" + objectName);
} else {
- this->WriteString("<ObjectFileName>", 3);
- (*this->BuildFileStream) << "$(IntDir)/" << objectName
- << "</ObjectFileName>\n";
+ e2.Element("ObjectFileName", "$(IntDir)/" + objectName);
}
}
for (std::string const& config : this->Configurations) {
// use them
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
!includes.empty() || compileAs || noWinRT) {
- (*this->BuildFileStream) << firstString;
- firstString = ""; // only do firstString once
- hasFlags = true;
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmIDEFlagTable const* flagtable = nullptr;
const std::string& srclang = source->GetLanguage();
if (srclang == "C" || srclang == "CXX") {
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget, config,
this->GeneratorTarget->GetName(), lang);
- cmVisualStudioGeneratorOptions clOptions(
+ cmVS10GeneratorOptions clOptions(
this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
- flagtable, 0, this);
+ flagtable, this);
if (compileAs) {
clOptions.AddFlag("CompileAs", compileAs);
}
clOptions.AddDefines(
genexInterpreter.Evaluate(configDefines, "COMPILE_DEFINITIONS"));
} else {
- clOptions.AddDefines(configDefines.c_str());
+ clOptions.AddDefines(configDefines);
}
std::vector<std::string> includeList;
if (configDependentIncludes) {
*source);
}
clOptions.AddIncludes(includeList);
- clOptions.SetConfiguration(config.c_str());
- clOptions.PrependInheritedString("AdditionalOptions");
- clOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", lang);
- clOptions.OutputFlagMap(*this->BuildFileStream, " ");
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", lang);
+ clOptions.SetConfiguration(config);
+ OptionsHelper oh(clOptions, e2);
+ oh.PrependInheritedString("AdditionalOptions");
+ oh.OutputAdditionalIncludeDirectories(lang);
+ oh.OutputFlagMap();
+ oh.OutputPreprocessorDefinitions(lang);
}
}
if (this->IsXamlSource(source->GetFullPath())) {
- (*this->BuildFileStream) << firstString;
- firstString = ""; // only do firstString once
- hasFlags = true;
- this->WriteString("<DependentUpon>", 3);
const std::string& fileName = source->GetFullPath();
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
- (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
+ e2.Element("DependentUpon", xamlFileName);
}
if (this->ProjectType == csproj) {
std::string f = source->GetFullPath();
this->GetCSharpSourceProperties(&sf, sourceFileTags);
// write source file specific tags
if (!sourceFileTags.empty()) {
- hasFlags = true;
- (*this->BuildFileStream) << firstString;
- firstString = "";
- this->WriteCSharpSourceProperties(sourceFileTags);
+ this->WriteCSharpSourceProperties(e2, sourceFileTags);
}
}
-
- return hasFlags;
}
void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
- std::vector<size_t> const& exclude_configs)
+ Elem& e2, std::vector<size_t> const& exclude_configs)
{
for (size_t ci : exclude_configs) {
- this->WriteString("", 3);
- (*this->BuildFileStream)
- << "<ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='"
- << cmVS10EscapeXML(this->Configurations[ci]) << "|"
- << cmVS10EscapeXML(this->Platform) << "'\">true</ExcludedFromBuild>\n";
+ e2.WritePlatformConfigTag("ExcludedFromBuild",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[ci] + "|" +
+ this->Platform + "'",
+ "true");
}
}
-void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
+void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
+ Elem& e0)
{
cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
if (ttype > cmStateEnums::GLOBAL_TARGET) {
return;
}
- this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<_ProjectFileVersion>10.0.20506.1"
- "</_ProjectFileVersion>\n",
- 2);
+ Elem e1(e0, "PropertyGroup");
+ 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) {
- this->WritePlatformConfigTag("IntDir", config, 2);
- *this->BuildFileStream
- << "$(Platform)\\$(Configuration)\\$(ProjectName)\\"
- << "</IntDir>\n";
+ e1.WritePlatformConfigTag(
+ "IntDir", cond, "$(Platform)\\$(Configuration)\\$(ProjectName)\\");
} else {
std::string intermediateDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
ConvertToWindowsSlash(intermediateDir);
ConvertToWindowsSlash(outDir);
- this->WritePlatformConfigTag("OutDir", config, 2);
- *this->BuildFileStream << cmVS10EscapeXML(outDir) << "</OutDir>\n";
+ e1.WritePlatformConfigTag("OutDir", cond, outDir);
+
+ e1.WritePlatformConfigTag("IntDir", cond, intermediateDir);
+
+ if (const char* sdkExecutableDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("ExecutablePath", cond,
+ sdkExecutableDirectories);
+ }
+
+ if (const char* sdkIncludeDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_INCLUDE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("IncludePath", cond, sdkIncludeDirectories);
+ }
+
+ if (const char* sdkReferenceDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_REFERENCE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("ReferencePath", cond,
+ sdkReferenceDirectories);
+ }
+
+ if (const char* sdkLibraryDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_LIBRARY_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("LibraryPath", cond, sdkLibraryDirectories);
+ }
- this->WritePlatformConfigTag("IntDir", config, 2);
- *this->BuildFileStream << cmVS10EscapeXML(intermediateDir)
- << "</IntDir>\n";
+ if (const char* sdkLibraryWDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("LibraryWPath", cond,
+ sdkLibraryWDirectories);
+ }
+
+ if (const char* sdkSourceDirectories =
+ this->Makefile->GetDefinition("CMAKE_VS_SDK_SOURCE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("SourcePath", cond, sdkSourceDirectories);
+ }
+
+ if (const char* sdkExcludeDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_EXCLUDE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("ExcludePath", cond, sdkExcludeDirectories);
+ }
if (const char* workingDir = this->GeneratorTarget->GetProperty(
"VS_DEBUGGER_WORKING_DIRECTORY")) {
- this->WritePlatformConfigTag("LocalDebuggerWorkingDirectory", config,
- 2);
- *this->BuildFileStream << cmVS10EscapeXML(workingDir)
- << "</LocalDebuggerWorkingDirectory>\n";
+ e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond,
+ workingDir);
+ }
+
+ if (const char* debuggerCommand =
+ this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
+ e1.WritePlatformConfigTag("LocalDebuggerCommand", cond,
+ debuggerCommand);
}
std::string name =
cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
- this->WritePlatformConfigTag("TargetName", config, 2);
- *this->BuildFileStream << cmVS10EscapeXML(name) << "</TargetName>\n";
+ e1.WritePlatformConfigTag("TargetName", cond, name);
std::string ext =
cmSystemTools::GetFilenameLastExtension(targetNameFull);
// A single "." appears to be treated as an empty extension.
ext = ".";
}
- this->WritePlatformConfigTag("TargetExt", config, 2);
- *this->BuildFileStream << cmVS10EscapeXML(ext) << "</TargetExt>\n";
+ e1.WritePlatformConfigTag("TargetExt", cond, ext);
- this->OutputLinkIncremental(config);
+ this->OutputLinkIncremental(e1, config);
}
}
- this->WriteString("</PropertyGroup>\n", 1);
}
void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools) {
return;
return;
}
Options& linkOptions = *(this->LinkOptions[configName]);
+ const std::string cond = this->CalcCondition(configName);
const char* incremental = linkOptions.GetFlag("LinkIncremental");
- this->WritePlatformConfigTag("LinkIncremental", configName, 2);
- *this->BuildFileStream << (incremental ? incremental : "true")
- << "</LinkIncremental>\n";
+ e1.WritePlatformConfigTag("LinkIncremental", cond,
+ (incremental ? incremental : "true"));
linkOptions.RemoveFlag("LinkIncremental");
const char* manifest = linkOptions.GetFlag("GenerateManifest");
- this->WritePlatformConfigTag("GenerateManifest", configName, 2);
- *this->BuildFileStream << (manifest ? manifest : "true")
- << "</GenerateManifest>\n";
+ e1.WritePlatformConfigTag("GenerateManifest", cond,
+ (manifest ? manifest : "true"));
linkOptions.RemoveFlag("GenerateManifest");
// Some link options belong here. Use them now and remove them so that
for (const char** f = flags; *f; ++f) {
const char* flag = *f;
if (const char* value = linkOptions.GetFlag(flag)) {
- this->WritePlatformConfigTag(flag, configName, 2);
- *this->BuildFileStream << value << "</" << flag << ">\n";
+ e1.WritePlatformConfigTag(flag, cond, value);
linkOptions.RemoveFlag(flag);
}
}
bool cmVisualStudio10TargetGenerator::ComputeClOptions()
{
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeClOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeClOptions(c)) {
return false;
}
}
// copied from cmLocalVisualStudio7Generator.cxx 805
// TODO: Integrate code below with cmLocalVisualStudio7Generator.
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
std::unique_ptr<Options> pOptions;
switch (this->ProjectType) {
case vcxproj:
std::string baseFlagVar = "CMAKE_";
baseFlagVar += langForClCompile;
baseFlagVar += "_FLAGS";
- flags =
- this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- baseFlagVar);
+ flags = this->Makefile->GetRequiredDefinition(baseFlagVar);
std::string flagVar =
baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
flags += " ";
- flags +=
- this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- flagVar);
+ flags += this->Makefile->GetRequiredDefinition(flagVar);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
langForClCompile, configName);
}
this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
// Get preprocessor definitions for this directory.
- std::string defineFlags =
- this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+ std::string defineFlags = this->Makefile->GetDefineFlags();
if (this->MSTools) {
if (this->ProjectType == vcxproj) {
clOptions.FixExceptionHandlingDefault();
clOptions.AddFlag("AssemblerListingLocation", asmLocation);
}
}
+
+ // check for managed C++ assembly compiler flag. This overrides any
+ // /clr* compiler flags which may be defined in the flags variable(s).
+ if (this->ProjectType != csproj) {
+ // Warn if /clr was added manually. This should not be done
+ // anymore, because cmGeneratorTarget may not be aware that the
+ // target uses C++/CLI.
+ if (flags.find("/clr") != std::string::npos ||
+ defineFlags.find("/clr") != std::string::npos) {
+ if (configName == this->Configurations[0]) {
+ std::string message = "For the target \"" +
+ this->GeneratorTarget->GetName() +
+ "\" 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);
+ }
+ }
+ if (auto* clr =
+ this->GeneratorTarget->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
+ std::string clrString = clr;
+ if (!clrString.empty()) {
+ clrString = ":" + clrString;
+ }
+ flags += " /clr" + clrString;
+ }
+ }
+
clOptions.Parse(flags.c_str());
clOptions.Parse(defineFlags.c_str());
std::vector<std::string> targetDefines;
if (this->ProjectType != csproj && clOptions.IsManaged()) {
this->Managed = true;
std::string managedType = clOptions.GetFlag("CompileAsManaged");
- if (managedType == "Safe") {
+ if (managedType == "Safe" || managedType == "Pure") {
// force empty calling convention if safe clr is used
clOptions.AddFlag("CallingConvention", "");
}
+ // The default values of these flags are incompatible to
+ // managed assemblies. We have to force valid values if
+ // the target is a managed C++ target.
+ clOptions.AddFlag("ExceptionHandling", "Async");
+ clOptions.AddFlag("BasicRuntimeChecks", "Default");
}
if (this->ProjectType == csproj) {
// /nowin32manifest overrides /win32manifest: parameter
}
void cmVisualStudio10TargetGenerator::WriteClOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
Options& clOptions = *(this->ClOptions[configName]);
if (this->ProjectType == csproj) {
return;
}
- this->WriteString("<ClCompile>\n", 2);
- clOptions.PrependInheritedString("AdditionalOptions");
- clOptions.OutputAdditionalIncludeDirectories(
- *this->BuildFileStream, " ", "\n", this->LangForClCompile);
- clOptions.OutputFlagMap(*this->BuildFileStream, " ");
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", this->LangForClCompile);
+ Elem e2(e1, "ClCompile");
+ OptionsHelper oh(clOptions, e2);
+ oh.PrependInheritedString("AdditionalOptions");
+ oh.OutputAdditionalIncludeDirectories(this->LangForClCompile);
+ oh.OutputFlagMap();
+ oh.OutputPreprocessorDefinitions(this->LangForClCompile);
if (this->NsightTegra) {
if (const char* processMax =
this->GeneratorTarget->GetProperty("ANDROID_PROCESS_MAX")) {
- this->WriteString("<ProcessMax>", 3);
- *this->BuildFileStream << cmVS10EscapeXML(processMax)
- << "</ProcessMax>\n";
+ e2.Element("ProcessMax", processMax);
}
}
cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*");
const char* toolset = this->GlobalGenerator->GetPlatformToolset();
if (toolset && clangToolset.find(toolset)) {
- this->WriteString("<ObjectFileName>"
- "$(IntDir)%(filename).obj"
- "</ObjectFileName>\n",
- 3);
+ e2.Element("ObjectFileName", "$(IntDir)%(filename).obj");
} else {
- this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
+ e2.Element("ObjectFileName", "$(IntDir)");
}
// If not in debug mode, write the DebugInformationFormat field
// goes on its own line because Visual Studio corrects it this
// way when saving the project after CMake generates it.
if (!clOptions.IsDebug()) {
- this->WriteString("<DebugInformationFormat>\n", 3);
- this->WriteString("</DebugInformationFormat>\n", 3);
+ Elem e3(e2, "DebugInformationFormat");
+ e3.SetHasElements();
}
// Specify the compiler program database file if configured.
std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
if (!pdb.empty()) {
ConvertToWindowsSlash(pdb);
- this->WriteString("<ProgramDataBaseFileName>", 3);
- *this->BuildFileStream << cmVS10EscapeXML(pdb)
- << "</ProgramDataBaseFileName>\n";
+ e2.Element("ProgramDataBaseFileName", pdb);
}
- }
- this->WriteString("</ClCompile>\n", 2);
+ // add AdditionalUsingDirectories
+ if (this->AdditionalUsingDirectories.count(configName) > 0) {
+ std::string dirs;
+ for (auto u : this->AdditionalUsingDirectories[configName]) {
+ if (!dirs.empty()) {
+ dirs.append(";");
+ }
+ dirs.append(u);
+ }
+ e2.Element("AdditionalUsingDirectories", dirs);
+ }
+ }
}
bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
{
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeRcOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeRcOptions(c)) {
return false;
}
}
bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::ResourceCompiler, gg->GetRcFlagTable());
Options& rcOptions = *pOptions;
}
void cmVisualStudio10TargetGenerator::WriteRCOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools) {
return;
}
- this->WriteString("<ResourceCompile>\n", 2);
+ Elem e2(e1, "ResourceCompile");
- Options& rcOptions = *(this->RcOptions[configName]);
- rcOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "RC");
- rcOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", "RC");
+ OptionsHelper rcOptions(*(this->RcOptions[configName]), e2);
+ rcOptions.OutputPreprocessorDefinitions("RC");
+ rcOptions.OutputAdditionalIncludeDirectories("RC");
rcOptions.PrependInheritedString("AdditionalOptions");
- rcOptions.OutputFlagMap(*this->BuildFileStream, " ");
-
- this->WriteString("</ResourceCompile>\n", 2);
+ rcOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
if (!this->GlobalGenerator->IsCudaEnabled()) {
return true;
}
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeCudaOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeCudaOptions(c)) {
return false;
}
}
bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
Options& cudaOptions = *pOptions;
configName);
// Get preprocessor definitions for this directory.
- std::string defineFlags =
- this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+ std::string defineFlags = this->Makefile->GetDefineFlags();
cudaOptions.Parse(flags.c_str());
cudaOptions.Parse(defineFlags.c_str());
cudaOptions.AppendFlagString("AdditionalOptions", "-x cu");
}
+ // Specify the compiler program database file if configured.
+ std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
+ if (!pdb.empty()) {
+ // CUDA does not have a field for this and does not honor the
+ // ProgramDataBaseFileName field in ClCompile. Work around this
+ // limitation by creating the directory and passing the flag ourselves.
+ std::string const pdbDir = cmSystemTools::GetFilenamePath(pdb);
+ cmSystemTools::MakeDirectory(pdbDir);
+ pdb = this->ConvertPath(pdb, true);
+ ConvertToWindowsSlash(pdb);
+ std::string const clFd = "-Xcompiler=\"-Fd\\\"" + pdb + "\\\"\"";
+ cudaOptions.AppendFlagString("AdditionalOptions", clFd);
+ }
+
// CUDA automatically passes the proper '--machine' flag to nvcc
// for the current architecture, but does not reflect this default
// in the user-visible IDE settings. Set it explicitly.
// Get includes for this target
cudaOptions.AddIncludes(this->GetIncludes(configName, "CUDA"));
+ cudaOptions.AddFlag("UseHostInclude", "false");
this->CudaOptions[configName] = std::move(pOptions);
return true;
}
void cmVisualStudio10TargetGenerator::WriteCudaOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
return;
}
- this->WriteString("<CudaCompile>\n", 2);
+ Elem e2(e1, "CudaCompile");
- Options& cudaOptions = *(this->CudaOptions[configName]);
- cudaOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", "CUDA");
- cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "CUDA");
+ OptionsHelper cudaOptions(*(this->CudaOptions[configName]), e2);
+ cudaOptions.OutputAdditionalIncludeDirectories("CUDA");
+ cudaOptions.OutputPreprocessorDefinitions("CUDA");
cudaOptions.PrependInheritedString("AdditionalOptions");
- cudaOptions.OutputFlagMap(*this->BuildFileStream, " ");
-
- this->WriteString("</CudaCompile>\n", 2);
+ cudaOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
if (!this->GlobalGenerator->IsCudaEnabled()) {
return true;
}
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeCudaLinkOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeCudaLinkOptions(c)) {
return false;
}
}
bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
Options& cudaLinkOptions = *pOptions;
}
void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
if (this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
return;
return;
}
- this->WriteString("<CudaLink>\n", 2);
- Options& cudaLinkOptions = *(this->CudaLinkOptions[configName]);
- cudaLinkOptions.OutputFlagMap(*this->BuildFileStream, " ");
- this->WriteString("</CudaLink>\n", 2);
+ Elem e2(e1, "CudaLink");
+ OptionsHelper cudaLinkOptions(*(this->CudaLinkOptions[configName]), e2);
+ cudaLinkOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
if (!this->GlobalGenerator->IsMasmEnabled()) {
return true;
}
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeMasmOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeMasmOptions(c)) {
return false;
}
}
bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::MasmCompiler, gg->GetMasmFlagTable());
Options& masmOptions = *pOptions;
}
void cmVisualStudio10TargetGenerator::WriteMasmOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools || !this->GlobalGenerator->IsMasmEnabled()) {
return;
}
- this->WriteString("<MASM>\n", 2);
+ Elem e2(e1, "MASM");
// Preprocessor definitions and includes are shared with clOptions.
- Options& clOptions = *(this->ClOptions[configName]);
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "ASM_MASM");
+ OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
+ clOptions.OutputPreprocessorDefinitions("ASM_MASM");
- Options& masmOptions = *(this->MasmOptions[configName]);
- masmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", "ASM_MASM");
+ OptionsHelper masmOptions(*(this->MasmOptions[configName]), e2);
+ masmOptions.OutputAdditionalIncludeDirectories("ASM_MASM");
masmOptions.PrependInheritedString("AdditionalOptions");
- masmOptions.OutputFlagMap(*this->BuildFileStream, " ");
-
- this->WriteString("</MASM>\n", 2);
+ masmOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
if (!this->GlobalGenerator->IsNasmEnabled()) {
return true;
}
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeNasmOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeNasmOptions(c)) {
return false;
}
}
bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable());
Options& nasmOptions = *pOptions;
std::string configFlagsVar = std::string("CMAKE_ASM_NASM_FLAGS_") + CONFIG;
std::string flags =
std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS")) +
- std::string(" -f") + std::string(this->Makefile->GetSafeDefinition(
- "CMAKE_ASM_NASM_OBJECT_FORMAT")) +
+ std::string(" -f") +
+ std::string(
+ this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT")) +
std::string(" ") +
std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
nasmOptions.Parse(flags.c_str());
}
void cmVisualStudio10TargetGenerator::WriteNasmOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
if (!this->GlobalGenerator->IsNasmEnabled()) {
return;
}
- this->WriteString("<NASM>\n", 2);
+ Elem e2(e1, "NASM");
std::vector<std::string> includes =
this->GetIncludes(configName, "ASM_NASM");
- Options& nasmOptions = *(this->NasmOptions[configName]);
- nasmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", "ASM_NASM");
- nasmOptions.OutputFlagMap(*this->BuildFileStream, " ");
+ OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2);
+ nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM");
+ nasmOptions.OutputFlagMap();
nasmOptions.PrependInheritedString("AdditionalOptions");
- nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "ASM_NASM");
+ nasmOptions.OutputPreprocessorDefinitions("ASM_NASM");
// Preprocessor definitions and includes are shared with clOptions.
- Options& clOptions = *(this->ClOptions[configName]);
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "ASM_NASM");
-
- this->WriteString("</NASM>\n", 2);
+ OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
+ clOptions.OutputPreprocessorDefinitions("ASM_NASM");
}
void cmVisualStudio10TargetGenerator::WriteLibOptions(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY &&
this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
this->LocalGenerator->GetStaticLibraryFlags(
libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget);
if (!libflags.empty()) {
- this->WriteString("<Lib>\n", 2);
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- cmVisualStudioGeneratorOptions libOptions(
- this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker,
- gg->GetLibFlagTable(), 0, this);
+ Elem e2(e1, "Lib");
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ cmVS10GeneratorOptions libOptions(this->LocalGenerator,
+ cmVisualStudioGeneratorOptions::Linker,
+ gg->GetLibFlagTable(), this);
libOptions.Parse(libflags.c_str());
- libOptions.PrependInheritedString("AdditionalOptions");
- libOptions.OutputFlagMap(*this->BuildFileStream, " ");
- this->WriteString("</Lib>\n", 2);
+ OptionsHelper oh(libOptions, e2);
+ oh.PrependInheritedString("AdditionalOptions");
+ oh.OutputFlagMap();
}
// We cannot generate metadata for static libraries. WindowsPhone
// Link tool options even for static libraries.
if (this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore()) {
- this->WriteString("<Link>\n", 2);
- this->WriteString("<GenerateWindowsMetadata>false"
- "</GenerateWindowsMetadata>\n",
- 3);
- this->WriteString("</Link>\n", 2);
+ Elem e2(e1, "Link");
+ e2.Element("GenerateWindowsMetadata", "false");
}
}
void cmVisualStudio10TargetGenerator::WriteManifestOptions(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
if (this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE &&
this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY &&
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, config);
if (!manifest_srcs.empty()) {
- this->WriteString("<Manifest>\n", 2);
- this->WriteString("<AdditionalManifestFiles>", 3);
+ std::ostringstream oss;
for (cmSourceFile const* mi : manifest_srcs) {
std::string m = this->ConvertPath(mi->GetFullPath(), false);
ConvertToWindowsSlash(m);
- (*this->BuildFileStream) << m << ";";
+ oss << m << ";";
}
- (*this->BuildFileStream) << "</AdditionalManifestFiles>\n";
- this->WriteString("</Manifest>\n", 2);
+ Elem e2(e1, "Manifest");
+ e2.Element("AdditionalManifestFiles", oss.str());
}
}
void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
// Look through the sources for AndroidManifest.xml and use
// its location as the root source directory.
}
// Tell MSBuild to launch Ant.
+ Elem e2(e1, "AntBuild");
{
std::string antBuildPath = rootDir;
- this->WriteString("<AntBuild>\n", 2);
- this->WriteString("<AntBuildPath>", 3);
ConvertToWindowsSlash(antBuildPath);
- (*this->BuildFileStream) << cmVS10EscapeXML(antBuildPath)
- << "</AntBuildPath>\n";
+ e2.Element("AntBuildPath", antBuildPath);
}
if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) {
- this->WriteString("<SkipAntStep>true</SkipAntStep>\n", 3);
+ e2.Element("SkipAntStep", "true");
}
if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_PROGUARD")) {
- this->WriteString("<EnableProGuard>true</EnableProGuard>\n", 3);
+ e2.Element("EnableProGuard", "true");
}
if (const char* proGuardConfigLocation =
this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) {
- this->WriteString("<ProGuardConfigLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(proGuardConfigLocation)
- << "</ProGuardConfigLocation>\n";
+ e2.Element("ProGuardConfigLocation", proGuardConfigLocation);
}
if (const char* securePropertiesLocation =
this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) {
- this->WriteString("<SecurePropertiesLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(securePropertiesLocation)
- << "</SecurePropertiesLocation>\n";
+ e2.Element("SecurePropertiesLocation", securePropertiesLocation);
}
if (const char* nativeLibDirectoriesExpression =
ge.Parse(nativeLibDirectoriesExpression);
std::string nativeLibDirs =
cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<NativeLibDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDirs)
- << "</NativeLibDirectories>\n";
+ e2.Element("NativeLibDirectories", nativeLibDirs);
}
if (const char* nativeLibDependenciesExpression =
ge.Parse(nativeLibDependenciesExpression);
std::string nativeLibDeps =
cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<NativeLibDependencies>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDeps)
- << "</NativeLibDependencies>\n";
+ e2.Element("NativeLibDependencies", nativeLibDeps);
}
if (const char* javaSourceDir =
this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) {
- this->WriteString("<JavaSourceDir>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(javaSourceDir)
- << "</JavaSourceDir>\n";
+ e2.Element("JavaSourceDir", javaSourceDir);
}
if (const char* jarDirectoriesExpression =
ge.Parse(jarDirectoriesExpression);
std::string jarDirectories =
cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<JarDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(jarDirectories)
- << "</JarDirectories>\n";
+ e2.Element("JarDirectories", jarDirectories);
}
if (const char* jarDeps =
this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) {
- this->WriteString("<JarDependencies>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(jarDeps)
- << "</JarDependencies>\n";
+ e2.Element("JarDependencies", jarDeps);
}
if (const char* assetsDirectories =
this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) {
- this->WriteString("<AssetsDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(assetsDirectories)
- << "</AssetsDirectories>\n";
+ e2.Element("AssetsDirectories", assetsDirectories);
}
{
std::string manifest_xml = rootDir + "/AndroidManifest.xml";
ConvertToWindowsSlash(manifest_xml);
- this->WriteString("<AndroidManifestLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(manifest_xml)
- << "</AndroidManifestLocation>\n";
+ e2.Element("AndroidManifestLocation", manifest_xml);
}
if (const char* antAdditionalOptions =
this->GeneratorTarget->GetProperty("ANDROID_ANT_ADDITIONAL_OPTIONS")) {
- this->WriteString("<AdditionalOptions>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(antAdditionalOptions)
- << " %(AdditionalOptions)</AdditionalOptions>\n";
+ e2.Element("AdditionalOptions",
+ std::string(antAdditionalOptions) + " %(AdditionalOptions)");
}
-
- this->WriteString("</AntBuild>\n", 2);
}
bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeLinkOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeLinkOptions(c)) {
return false;
}
}
bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- auto pOptions =
- cm::make_unique<Options>(this->LocalGenerator, Options::Linker,
- gg->GetLinkFlagTable(), nullptr, this);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ auto pOptions = cm::make_unique<Options>(
+ this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), this);
Options& linkOptions = *pOptions;
cmGeneratorTarget::LinkClosure const* linkClosure =
linkFlagVarBase += linkType;
linkFlagVarBase += "_LINKER_FLAGS";
flags += " ";
- flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- linkFlagVarBase);
+ flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase);
std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
flags += " ";
- flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- linkFlagVar);
+ flags += this->Makefile->GetRequiredDefinition(linkFlagVar);
const char* targetLinkFlags =
this->GeneratorTarget->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
std::vector<std::string> libVec;
std::vector<std::string> vsTargetVec;
- this->AddLibraries(cli, libVec, vsTargetVec);
+ this->AddLibraries(cli, libVec, vsTargetVec, config);
if (std::find(linkClosure->Languages.begin(), linkClosure->Languages.end(),
"CUDA") != linkClosure->Languages.end()) {
switch (this->CudaOptions[config]->GetCudaRuntime()) {
case cmVisualStudioGeneratorOptions::CudaRuntimeStatic:
+ libVec.push_back("cudadevrt.lib");
libVec.push_back("cudart_static.lib");
break;
case cmVisualStudioGeneratorOptions::CudaRuntimeShared:
+ libVec.push_back("cudadevrt.lib");
libVec.push_back("cudart.lib");
break;
case cmVisualStudioGeneratorOptions::CudaRuntimeNone:
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetModuleDefinitionInfo(config);
if (mdi && !mdi->DefFile.empty()) {
- linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile.c_str());
+ linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile);
}
linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
"%(IgnoreSpecificDefaultLibraries)");
}
}
+ // Managed code cannot be linked with /DEBUG:FASTLINK
+ if (this->Managed) {
+ if (const char* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
+ if (strcmp(debug, "DebugFastLink") == 0) {
+ linkOptions.AddFlag("GenerateDebugInformation", "Debug");
+ }
+ }
+ }
+
this->LinkOptions[config] = std::move(pOptions);
return true;
}
bool cmVisualStudio10TargetGenerator::ComputeLibOptions()
{
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeLibOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeLibOptions(c)) {
return false;
}
}
}
void cmVisualStudio10TargetGenerator::WriteLinkOptions(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
if (this->ProjectType == csproj) {
return;
}
- Options& linkOptions = *(this->LinkOptions[config]);
- this->WriteString("<Link>\n", 2);
- linkOptions.PrependInheritedString("AdditionalOptions");
- linkOptions.OutputFlagMap(*this->BuildFileStream, " ");
+ {
+ Elem e2(e1, "Link");
+ OptionsHelper linkOptions(*(this->LinkOptions[config]), e2);
+ linkOptions.PrependInheritedString("AdditionalOptions");
+ linkOptions.OutputFlagMap();
+ }
- this->WriteString("</Link>\n", 2);
if (!this->GlobalGenerator->NeedLinkLibraryDependencies(
this->GeneratorTarget)) {
- this->WriteString("<ProjectReference>\n", 2);
- this->WriteString(
- "<LinkLibraryDependencies>false</LinkLibraryDependencies>\n", 3);
- this->WriteString("</ProjectReference>\n", 2);
+ Elem e2(e1, "ProjectReference");
+ e2.Element("LinkLibraryDependencies", "false");
}
}
void cmVisualStudio10TargetGenerator::AddLibraries(
- cmComputeLinkInformation& cli, std::vector<std::string>& libVec,
- std::vector<std::string>& vsTargetVec)
+ const cmComputeLinkInformation& cli, std::vector<std::string>& libVec,
+ std::vector<std::string>& vsTargetVec, const std::string& config)
{
typedef cmComputeLinkInformation::ItemVector ItemVector;
ItemVector const& libs = cli.GetItems();
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
for (cmComputeLinkInformation::Item const& l : libs) {
+ if (l.Target) {
+ auto managedType = l.Target->GetManagedType(config);
+ if (managedType != cmGeneratorTarget::ManagedType::Native &&
+ this->GeneratorTarget->GetManagedType(config) !=
+ cmGeneratorTarget::ManagedType::Native &&
+ l.Target->IsImported()) {
+ auto location = l.Target->GetFullPath(config);
+ if (!location.empty()) {
+ ConvertToWindowsSlash(location);
+ switch (this->ProjectType) {
+ case csproj:
+ // If the target we want to "link" to is an imported managed
+ // target and this is a C# project, we add a hint reference. This
+ // reference is written to project file in
+ // WriteDotNetReferences().
+ this->DotNetHintReferences[config].push_back(
+ DotNetHintReference(l.Target->GetName(), location));
+ break;
+ case vcxproj:
+ // Add path of assembly to list of using-directories, so the
+ // managed assembly can be used by '#using <assembly.dll>' in
+ // code.
+ this->AdditionalUsingDirectories[config].insert(
+ cmSystemTools::GetFilenamePath(location));
+ break;
+ }
+ }
+ }
+ // Do not allow C# targets to be added to the LIB listing. LIB files are
+ // used for linking C++ dependencies. C# libraries do not have lib files.
+ // Instead, they compile down to C# reference libraries (DLL files). The
+ // `<ProjectReference>` elements added to the vcxproj are enough for the
+ // IDE to deduce the DLL file required by other C# projects that need its
+ // reference library.
+ if (managedType == cmGeneratorTarget::ManagedType::Managed) {
+ continue;
+ }
+ }
+
if (l.IsPath) {
std::string path =
this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value);
}
void cmVisualStudio10TargetGenerator::WriteMidlOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools) {
return;
// up (for non-directory form, it ends up looking in project binary dir
// only). Perhaps there's something to be done to make this more automatic
// on the CMake side?
- this->WriteString("<Midl>\n", 2);
- this->WriteString("<AdditionalIncludeDirectories>", 3);
std::vector<std::string> const includes =
this->GetIncludes(configName, "MIDL");
+ std::ostringstream oss;
for (std::string const& i : includes) {
- *this->BuildFileStream << cmVS10EscapeXML(i) << ";";
- }
- this->WriteString("%(AdditionalIncludeDirectories)"
- "</AdditionalIncludeDirectories>\n",
- 0);
- this->WriteString("<OutputDirectory>$(ProjectDir)/$(IntDir)"
- "</OutputDirectory>\n",
- 3);
- this->WriteString("<HeaderFileName>%(Filename).h</HeaderFileName>\n", 3);
- this->WriteString("<TypeLibraryName>%(Filename).tlb</TypeLibraryName>\n", 3);
- this->WriteString("<InterfaceIdentifierFileName>"
- "%(Filename)_i.c</InterfaceIdentifierFileName>\n",
- 3);
- this->WriteString("<ProxyFileName>%(Filename)_p.c</ProxyFileName>\n", 3);
- this->WriteString("</Midl>\n", 2);
+ oss << i << ";";
+ }
+ oss << "%(AdditionalIncludeDirectories)";
+
+ Elem e2(e1, "Midl");
+ e2.Element("AdditionalIncludeDirectories", oss.str());
+ e2.Element("OutputDirectory", "$(ProjectDir)/$(IntDir)");
+ e2.Element("HeaderFileName", "%(Filename).h");
+ e2.Element("TypeLibraryName", "%(Filename).tlb");
+ e2.Element("InterfaceIdentifierFileName", "%(Filename)_i.c");
+ e2.Element("ProxyFileName", "%(Filename)_p.c");
}
-void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
+void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
{
if (this->ProjectType == csproj) {
return;
}
- for (const auto& i : this->Configurations) {
- this->WritePlatformConfigTag("ItemDefinitionGroup", i, 1);
- *this->BuildFileStream << "\n";
+ for (const std::string& c : this->Configurations) {
+ Elem e1(e0, "ItemDefinitionGroup");
+ e1.Attribute("Condition", this->CalcCondition(c));
+
// output cl compile flags <ClCompile></ClCompile>
if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
- this->WriteClOptions(i);
+ this->WriteClOptions(e1, c);
// output rc compile flags <ResourceCompile></ResourceCompile>
- this->WriteRCOptions(i);
- this->WriteCudaOptions(i);
- this->WriteMasmOptions(i);
- this->WriteNasmOptions(i);
+ this->WriteRCOptions(e1, c);
+ this->WriteCudaOptions(e1, c);
+ this->WriteMasmOptions(e1, c);
+ this->WriteNasmOptions(e1, c);
}
// output midl flags <Midl></Midl>
- this->WriteMidlOptions(i);
+ this->WriteMidlOptions(e1, c);
// write events
if (this->ProjectType != csproj) {
- this->WriteEvents(i);
+ this->WriteEvents(e1, c);
}
// output link flags <Link></Link>
- this->WriteLinkOptions(i);
- this->WriteCudaLinkOptions(i);
+ this->WriteLinkOptions(e1, c);
+ this->WriteCudaLinkOptions(e1, c);
// output lib flags <Lib></Lib>
- this->WriteLibOptions(i);
+ this->WriteLibOptions(e1, c);
// output manifest flags <Manifest></Manifest>
- this->WriteManifestOptions(i);
+ this->WriteManifestOptions(e1, c);
if (this->NsightTegra &&
this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
- this->WriteAntBuildOptions(i);
+ this->WriteAntBuildOptions(e1, c);
}
- this->WriteString("</ItemDefinitionGroup>\n", 1);
}
}
void cmVisualStudio10TargetGenerator::WriteEvents(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
bool addedPrelink = false;
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetPreLinkCommands();
this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
commands, configName);
- this->WriteEvent("PreLinkEvent", commands, configName);
+ this->WriteEvent(e1, "PreLinkEvent", commands, configName);
}
if (!addedPrelink) {
- this->WriteEvent("PreLinkEvent",
+ this->WriteEvent(e1, "PreLinkEvent",
this->GeneratorTarget->GetPreLinkCommands(), configName);
}
- this->WriteEvent("PreBuildEvent",
+ this->WriteEvent(e1, "PreBuildEvent",
this->GeneratorTarget->GetPreBuildCommands(), configName);
- this->WriteEvent("PostBuildEvent",
+ this->WriteEvent(e1, "PostBuildEvent",
this->GeneratorTarget->GetPostBuildCommands(), configName);
}
void cmVisualStudio10TargetGenerator::WriteEvent(
- const char* name, std::vector<cmCustomCommand> const& commands,
+ Elem& e1, const char* name, std::vector<cmCustomCommand> const& commands,
std::string const& configName)
{
if (commands.empty()) {
return;
}
- this->WriteString("<", 2);
- (*this->BuildFileStream) << name << ">\n";
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
std::string script;
const char* pre = "";
std::string comment;
- for (cmCustomCommand const& i : commands) {
- cmCustomCommandGenerator ccg(i, configName, this->LocalGenerator);
+ for (cmCustomCommand const& cc : commands) {
+ cmCustomCommandGenerator ccg(cc, configName, lg);
if (!ccg.HasOnlyEmptyCommandLines()) {
comment += pre;
comment += lg->ConstructComment(ccg);
script += pre;
pre = "\n";
- script += cmVS10EscapeXML(lg->ConstructScript(ccg));
+ script += lg->ConstructScript(ccg);
}
}
comment = cmVS10EscapeComment(comment);
if (this->ProjectType != csproj) {
- this->WriteString("<Message>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n";
- this->WriteString("<Command>", 3);
+ Elem e2(e1, name);
+ e2.Element("Message", comment);
+ e2.Element("Command", script);
} else {
std::string strippedComment = comment;
strippedComment.erase(
std::remove(strippedComment.begin(), strippedComment.end(), '\t'),
strippedComment.end());
+ std::ostringstream oss;
if (!comment.empty() && !strippedComment.empty()) {
- (*this->BuildFileStream) << "echo " << cmVS10EscapeXML(comment) << "\n";
+ oss << "echo " << comment << "\n";
}
+ oss << script << "\n";
+ e1.Element(name, oss.str());
}
- (*this->BuildFileStream) << script;
- if (this->ProjectType != csproj) {
- (*this->BuildFileStream) << "</Command>";
- }
- (*this->BuildFileStream) << "\n";
- this->WriteString("</", 2);
- (*this->BuildFileStream) << name << ">\n";
}
-void cmVisualStudio10TargetGenerator::WriteProjectReferences()
+void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
{
cmGlobalGenerator::TargetDependSet const& unordered =
this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
typedef cmGlobalVisualStudioGenerator::OrderedTargetDependSet
OrderedTargetDependSet;
OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
- this->WriteString("<ItemGroup>\n", 1);
- for (cmTargetDepend const& i : depends) {
- cmGeneratorTarget const* dt = i;
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
+ for (cmGeneratorTarget const* dt : depends) {
if (dt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
// skip fortran targets as they can not be processed by MSBuild
// the only reference will be in the .sln file
- if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(dt)) {
+ if (this->GlobalGenerator->TargetIsFortranOnly(dt)) {
continue;
}
- this->WriteString("<ProjectReference Include=\"", 2);
cmLocalGenerator* lg = dt->GetLocalGenerator();
std::string name = dt->GetName();
std::string path;
path += computeProjectFileExtension(dt, *this->Configurations.begin());
}
ConvertToWindowsSlash(path);
- (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n";
- this->WriteString("<Project>", 3);
- (*this->BuildFileStream) << "{" << this->GlobalGenerator->GetGUID(name)
- << "}";
- (*this->BuildFileStream) << "</Project>\n";
- this->WriteString("<Name>", 3);
- (*this->BuildFileStream) << name << "</Name>\n";
- this->WriteDotNetReferenceCustomTags(name);
- if (csproj == this->ProjectType) {
- if (!static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetCanBeReferenced(dt)) {
- this->WriteString(
- "<ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n", 3);
+ Elem e2(e1, "ProjectReference");
+ e2.Attribute("Include", path);
+ e2.Element("Project", "{" + this->GlobalGenerator->GetGUID(name) + "}");
+ e2.Element("Name", name);
+ this->WriteDotNetReferenceCustomTags(e2, name);
+ if (this->Managed) {
+ // If the dependency target is not managed (compiled with /clr or
+ // C# target) we cannot reference it and have to set
+ // 'ReferenceOutputAssembly' to false.
+ auto referenceNotManaged =
+ dt->GetManagedType("") < cmGeneratorTarget::ManagedType::Mixed;
+ // Workaround to check for manually set /clr flags.
+ if (referenceNotManaged) {
+ if (const auto* flags = dt->GetProperty("COMPILE_OPTIONS")) {
+ std::string flagsStr = flags;
+ if (flagsStr.find("clr") != std::string::npos) {
+ // There is a warning already issued when building the flags.
+ referenceNotManaged = false;
+ }
+ }
+ }
+ // Workaround for static library C# targets
+ if (referenceNotManaged &&
+ dt->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ referenceNotManaged = !dt->HasLanguage("CSharp", "");
+ }
+ if (referenceNotManaged) {
+ e2.Element("ReferenceOutputAssembly", "false");
+ e2.Element("CopyToOutputDirectory", "Never");
}
}
- this->WriteString("</ProjectReference>\n", 2);
}
- this->WriteString("</ItemGroup>\n", 1);
}
-void cmVisualStudio10TargetGenerator::WritePlatformExtensions()
+void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1)
{
// This only applies to Windows 10 apps
if (this->GlobalGenerator->TargetsWindowsStore() &&
const char* desktopExtensionsVersion =
this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
if (desktopExtensionsVersion) {
- this->WriteSinglePlatformExtension("WindowsDesktop",
+ this->WriteSinglePlatformExtension(e1, "WindowsDesktop",
desktopExtensionsVersion);
}
const char* mobileExtensionsVersion =
this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
if (mobileExtensionsVersion) {
- this->WriteSinglePlatformExtension("WindowsMobile",
+ this->WriteSinglePlatformExtension(e1, "WindowsMobile",
mobileExtensionsVersion);
}
}
}
void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension(
- std::string const& extension, std::string const& version)
+ Elem& e1, std::string const& extension, std::string const& version)
{
- this->WriteString("<Import Project=", 2);
- (*this->BuildFileStream)
- << "\"$([Microsoft.Build.Utilities.ToolLocationHelper]"
- << "::GetPlatformExtensionSDKLocation(`" << extension
- << ", Version=" << version
- << "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
- << "$(ExtensionSDKDirectoryRoot), null))"
- << "\\DesignTime\\CommonConfiguration\\Neutral\\" << extension
- << ".props\" "
- << "Condition=\"exists('$("
- << "[Microsoft.Build.Utilities.ToolLocationHelper]"
- << "::GetPlatformExtensionSDKLocation(`" << extension
- << ", Version=" << version
- << "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
- << "$(ExtensionSDKDirectoryRoot), null))"
- << "\\DesignTime\\CommonConfiguration\\Neutral\\" << extension
- << ".props')\" />\n";
+ const std::string s = "$([Microsoft.Build.Utilities.ToolLocationHelper]"
+ "::GetPlatformExtensionSDKLocation(`" +
+ extension + ", Version=" + version +
+ "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
+ "$(ExtensionSDKDirectoryRoot), null))"
+ "\\DesignTime\\CommonConfiguration\\Neutral\\" +
+ extension + ".props";
+
+ Elem e2(e1, "Import");
+ e2.Attribute("Project", s);
+ e2.Attribute("Condition", "exists('" + s + "')");
}
-void cmVisualStudio10TargetGenerator::WriteSDKReferences()
+void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
{
std::vector<std::string> sdkReferences;
+ Elem e1(e0);
bool hasWrittenItemGroup = false;
if (const char* vsSDKReferences =
this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) {
cmSystemTools::ExpandListArgument(vsSDKReferences, sdkReferences);
- this->WriteString("<ItemGroup>\n", 1);
+ e1.StartElement("ItemGroup");
hasWrittenItemGroup = true;
for (std::string const& ri : sdkReferences) {
- this->WriteString("<SDKReference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(ri) << "\"/>\n";
+ Elem(e1, "SDKReference").Attribute("Include", ri);
}
}
if (desktopExtensionsVersion || mobileExtensionsVersion ||
iotExtensionsVersion) {
if (!hasWrittenItemGroup) {
- this->WriteString("<ItemGroup>\n", 1);
- hasWrittenItemGroup = true;
+ e1.StartElement("ItemGroup");
}
if (desktopExtensionsVersion) {
- this->WriteSingleSDKReference("WindowsDesktop",
+ this->WriteSingleSDKReference(e1, "WindowsDesktop",
desktopExtensionsVersion);
}
if (mobileExtensionsVersion) {
- this->WriteSingleSDKReference("WindowsMobile",
+ this->WriteSingleSDKReference(e1, "WindowsMobile",
mobileExtensionsVersion);
}
if (iotExtensionsVersion) {
- this->WriteSingleSDKReference("WindowsIoT", iotExtensionsVersion);
+ this->WriteSingleSDKReference(e1, "WindowsIoT", iotExtensionsVersion);
}
}
}
-
- if (hasWrittenItemGroup) {
- this->WriteString("</ItemGroup>\n", 1);
- }
}
void cmVisualStudio10TargetGenerator::WriteSingleSDKReference(
- std::string const& extension, std::string const& version)
+ Elem& e1, std::string const& extension, std::string const& version)
{
- this->WriteString("<SDKReference Include=\"", 2);
- (*this->BuildFileStream) << extension << ", Version=" << version
- << "\" />\n";
+ Elem(e1, "SDKReference")
+ .Attribute("Include", extension + ", Version=" + version);
}
-void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
+void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
+ Elem& e0)
{
if ((this->GlobalGenerator->TargetsWindowsStore() ||
this->GlobalGenerator->TargetsWindowsPhone()) &&
std::string artifactDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
ConvertToWindowsSlash(artifactDir);
- this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<AppxPackageArtifactsDir>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(artifactDir)
- << "\\</AppxPackageArtifactsDir>\n";
- this->WriteString("<ProjectPriFullPath>", 2);
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("AppxPackageArtifactsDir", artifactDir + "\\");
std::string resourcePriFile =
this->DefaultArtifactDir + "/resources.pri";
ConvertToWindowsSlash(resourcePriFile);
- (*this->BuildFileStream) << resourcePriFile << "</ProjectPriFullPath>\n";
+ e1.Element("ProjectPriFullPath", resourcePriFile);
// If we are missing files and we don't have a certificate and
// aren't targeting WP8.0, add a default certificate
pfxFile, false);
ConvertToWindowsSlash(pfxFile);
this->AddedFiles.push_back(pfxFile);
+ this->AddedDefaultCertificate = true;
}
- this->WriteString("<", 2);
- (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
- << "</PackageCertificateKeyFile>\n";
+ e1.Element("PackageCertificateKeyFile", pfxFile);
std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
if (!thumb.empty()) {
- this->WriteString("<PackageCertificateThumbprint>", 2);
- (*this->BuildFileStream) << thumb
- << "</PackageCertificateThumbprint>\n";
+ e1.Element("PackageCertificateThumbprint", thumb);
}
- this->WriteString("</PropertyGroup>\n", 1);
} else if (!pfxFile.empty()) {
- this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<", 2);
- (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
- << "</PackageCertificateKeyFile>\n";
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("PackageCertificateKeyFile", pfxFile);
std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
if (!thumb.empty()) {
- this->WriteString("<PackageCertificateThumbprint>", 2);
- (*this->BuildFileStream) << thumb
- << "</PackageCertificateThumbprint>\n";
+ e1.Element("PackageCertificateThumbprint", thumb);
}
- this->WriteString("</PropertyGroup>\n", 1);
}
}
}
return it != expectedXamlSources.end();
}
-void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
+void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
bool isAppContainer = false;
bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
std::string const& v = this->GlobalGenerator->GetSystemVersion();
if (isWindowsPhone || isWindowsStore) {
- this->WriteString("<ApplicationType>", 2);
- (*this->BuildFileStream)
- << (isWindowsPhone ? "Windows Phone" : "Windows Store")
- << "</ApplicationType>\n";
- this->WriteString("<DefaultLanguage>en-US"
- "</DefaultLanguage>\n",
- 2);
+ e1.Element("ApplicationType",
+ (isWindowsPhone ? "Windows Phone" : "Windows Store"));
+ e1.Element("DefaultLanguage", "en-US");
if (cmHasLiteralPrefix(v, "10.0")) {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML("10.0")
- << "</ApplicationTypeRevision>\n";
+ e1.Element("ApplicationTypeRevision", "10.0");
// Visual Studio 14.0 is necessary for building 10.0 apps
- this->WriteString("<MinimumVisualStudioVersion>14.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ e1.Element("MinimumVisualStudioVersion", "14.0");
if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
isAppContainer = true;
}
} else if (v == "8.1") {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(v)
- << "</ApplicationTypeRevision>\n";
+ e1.Element("ApplicationTypeRevision", v);
// Visual Studio 12.0 is necessary for building 8.1 apps
- this->WriteString("<MinimumVisualStudioVersion>12.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ e1.Element("MinimumVisualStudioVersion", "12.0");
if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
isAppContainer = true;
}
} else if (v == "8.0") {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(v)
- << "</ApplicationTypeRevision>\n";
+ e1.Element("ApplicationTypeRevision", v);
// Visual Studio 11.0 is necessary for building 8.0 apps
- this->WriteString("<MinimumVisualStudioVersion>11.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ e1.Element("MinimumVisualStudioVersion", "11.0");
if (isWindowsStore &&
this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
} else if (isWindowsPhone &&
this->GeneratorTarget->GetType() ==
cmStateEnums::EXECUTABLE) {
- this->WriteString("<XapOutputs>true</XapOutputs>\n", 2);
- this->WriteString("<XapFilename>", 2);
- (*this->BuildFileStream)
- << cmVS10EscapeXML(this->Name)
- << "_$(Configuration)_$(Platform).xap</XapFilename>\n";
+ e1.Element("XapOutputs", "true");
+ e1.Element("XapFilename",
+ this->Name + "_$(Configuration)_$(Platform).xap");
}
}
}
if (isAppContainer) {
- this->WriteString("<AppContainerApplication>true"
- "</AppContainerApplication>\n",
- 2);
+ e1.Element("AppContainerApplication", "true");
} else if (this->Platform == "ARM64") {
- this->WriteString("<WindowsSDKDesktopARM64Support>true"
- "</WindowsSDKDesktopARM64Support>\n",
- 2);
+ e1.Element("WindowsSDKDesktopARM64Support", "true");
} else if (this->Platform == "ARM") {
- this->WriteString("<WindowsSDKDesktopARMSupport>true"
- "</WindowsSDKDesktopARMSupport>\n",
- 2);
+ e1.Element("WindowsSDKDesktopARMSupport", "true");
}
std::string const& targetPlatformVersion =
gg->GetWindowsTargetPlatformVersion();
if (!targetPlatformVersion.empty()) {
- this->WriteString("<WindowsTargetPlatformVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
- << "</WindowsTargetPlatformVersion>\n";
+ e1.Element("WindowsTargetPlatformVersion", targetPlatformVersion);
}
const char* targetPlatformMinVersion = this->GeneratorTarget->GetProperty(
"VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION");
if (targetPlatformMinVersion) {
- this->WriteString("<WindowsTargetPlatformMinVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformMinVersion)
- << "</WindowsTargetPlatformMinVersion>\n";
+ e1.Element("WindowsTargetPlatformMinVersion", targetPlatformMinVersion);
} else if (isWindowsStore && cmHasLiteralPrefix(v, "10.0")) {
// If the min version is not set, then use the TargetPlatformVersion
if (!targetPlatformVersion.empty()) {
- this->WriteString("<WindowsTargetPlatformMinVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
- << "</WindowsTargetPlatformMinVersion>\n";
+ e1.Element("WindowsTargetPlatformMinVersion", targetPlatformVersion);
}
}
// Added IoT Startup Task support
if (this->GeneratorTarget->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) {
- this->WriteString("<ContainsStartupTask>true</ContainsStartupTask>\n", 2);
+ e1.Element("ContainsStartupTask", "true");
}
}
}
}
-void cmVisualStudio10TargetGenerator::WriteMissingFiles()
+void cmVisualStudio10TargetGenerator::WriteMissingFiles(Elem& e1)
{
std::string const& v = this->GlobalGenerator->GetSystemVersion();
if (this->GlobalGenerator->TargetsWindowsPhone()) {
if (v == "8.0") {
- this->WriteMissingFilesWP80();
+ this->WriteMissingFilesWP80(e1);
} else if (v == "8.1") {
- this->WriteMissingFilesWP81();
+ this->WriteMissingFilesWP81(e1);
}
} else if (this->GlobalGenerator->TargetsWindowsStore()) {
if (v == "8.0") {
- this->WriteMissingFilesWS80();
+ this->WriteMissingFilesWS80(e1);
} else if (v == "8.1") {
- this->WriteMissingFilesWS81();
+ this->WriteMissingFilesWS81(e1);
} else if (cmHasLiteralPrefix(v, "10.0")) {
- this->WriteMissingFilesWS10_0();
+ this->WriteMissingFilesWS10_0(e1);
}
}
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1)
{
std::string templateFolder =
cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
std::string sourceFile = this->ConvertPath(manifestFile, false);
ConvertToWindowsSlash(sourceFile);
- this->WriteString("<Xml Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
- this->WriteString("<SubType>Designer</SubType>\n", 3);
- this->WriteString("</Xml>\n", 2);
+ {
+ Elem e2(e1, "Xml");
+ e2.Attribute("Include", sourceFile);
+ e2.Element("SubType", "Designer");
+ }
this->AddedFiles.push_back(sourceFile);
std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
false);
ConvertToWindowsSlash(smallLogo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo) << "\" />\n";
+ Elem(e1, "Image").Attribute("Include", smallLogo);
this->AddedFiles.push_back(smallLogo);
std::string logo = this->DefaultArtifactDir + "/Logo.png";
cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
ConvertToWindowsSlash(logo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(logo) << "\" />\n";
+ Elem(e1, "Image").Attribute("Include", logo);
this->AddedFiles.push_back(logo);
std::string applicationIcon =
cmSystemTools::CopyAFile(templateFolder + "/ApplicationIcon.png",
applicationIcon, false);
ConvertToWindowsSlash(applicationIcon);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(applicationIcon) << "\" />\n";
+ Elem(e1, "Image").Attribute("Include", applicationIcon);
this->AddedFiles.push_back(applicationIcon);
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81(Elem& e1)
{
std::string manifestFile =
this->DefaultArtifactDir + "/package.appxManifest";
"</Package>\n";
/* clang-format on */
- this->WriteCommonMissingFiles(manifestFile);
+ this->WriteCommonMissingFiles(e1, manifestFile);
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80(Elem& e1)
{
std::string manifestFile =
this->DefaultArtifactDir + "/package.appxManifest";
"</Package>\n";
/* clang-format on */
- this->WriteCommonMissingFiles(manifestFile);
+ this->WriteCommonMissingFiles(e1, manifestFile);
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81(Elem& e1)
{
std::string manifestFile =
this->DefaultArtifactDir + "/package.appxManifest";
"</Package>\n";
/* clang-format on */
- this->WriteCommonMissingFiles(manifestFile);
+ this->WriteCommonMissingFiles(e1, manifestFile);
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0(Elem& e1)
{
std::string manifestFile =
this->DefaultArtifactDir + "/package.appxManifest";
"</Package>\n";
/* clang-format on */
- this->WriteCommonMissingFiles(manifestFile);
+ this->WriteCommonMissingFiles(e1, manifestFile);
}
void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
- const std::string& manifestFile)
+ Elem& e1, const std::string& manifestFile)
{
std::string templateFolder =
cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
std::string sourceFile = this->ConvertPath(manifestFile, false);
ConvertToWindowsSlash(sourceFile);
- this->WriteString("<AppxManifest Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
- this->WriteString("<SubType>Designer</SubType>\n", 3);
- this->WriteString("</AppxManifest>\n", 2);
+ {
+ Elem e2(e1, "AppxManifest");
+ e2.Attribute("Include", sourceFile);
+ e2.Element("SubType", "Designer");
+ }
this->AddedFiles.push_back(sourceFile);
std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
false);
ConvertToWindowsSlash(smallLogo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo) << "\" />\n";
+ Elem(e1, "Image").Attribute("Include", smallLogo);
this->AddedFiles.push_back(smallLogo);
std::string smallLogo44 = this->DefaultArtifactDir + "/SmallLogo44x44.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo44x44.png", smallLogo44,
false);
ConvertToWindowsSlash(smallLogo44);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo44) << "\" />\n";
+ Elem(e1, "Image").Attribute("Include", smallLogo44);
this->AddedFiles.push_back(smallLogo44);
std::string logo = this->DefaultArtifactDir + "/Logo.png";
cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
ConvertToWindowsSlash(logo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(logo) << "\" />\n";
+ Elem(e1, "Image").Attribute("Include", logo);
this->AddedFiles.push_back(logo);
std::string storeLogo = this->DefaultArtifactDir + "/StoreLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/StoreLogo.png", storeLogo,
false);
ConvertToWindowsSlash(storeLogo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(storeLogo) << "\" />\n";
+ Elem(e1, "Image").Attribute("Include", storeLogo);
this->AddedFiles.push_back(storeLogo);
std::string splashScreen = this->DefaultArtifactDir + "/SplashScreen.png";
cmSystemTools::CopyAFile(templateFolder + "/SplashScreen.png", splashScreen,
false);
ConvertToWindowsSlash(splashScreen);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(splashScreen) << "\" />\n";
+ Elem(e1, "Image").Attribute("Include", splashScreen);
this->AddedFiles.push_back(splashScreen);
- // This file has already been added to the build so don't copy it
- std::string keyFile = this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
- ConvertToWindowsSlash(keyFile);
- this->WriteString("<None Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(keyFile) << "\" />\n";
+ if (this->AddedDefaultCertificate) {
+ // This file has already been added to the build so don't copy it
+ std::string keyFile =
+ this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
+ ConvertToWindowsSlash(keyFile);
+ Elem(e1, "None").Attribute("Include", keyFile);
+ }
}
bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const
}
void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties(
- const std::map<std::string, std::string>& tags)
+ Elem& e2, const std::map<std::string, std::string>& tags)
{
if (!tags.empty()) {
for (const auto& i : tags) {
- this->WriteString("<", 3);
- (*this->BuildFileStream) << i.first << ">" << cmVS10EscapeXML(i.second)
- << "</" << i.first << ">\n";
+ e2.Element(i.first.c_str(), i.second);
}
}
}
void cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
cmSourceFile const* sf, std::string& link)
{
- std::string f = sf->GetFullPath();
- if (!this->InSourceBuild) {
+ std::string const& sourceFilePath = sf->GetFullPath();
+ std::string const& binaryDir = LocalGenerator->GetCurrentBinaryDirectory();
+
+ if (!cmSystemTools::IsSubDirectory(sourceFilePath, binaryDir)) {
const std::string stripFromPath =
this->Makefile->GetCurrentSourceDirectory();
- if (f.find(stripFromPath) != std::string::npos) {
- link = f.substr(stripFromPath.length() + 1);
+ if (sourceFilePath.find(stripFromPath) == 0) {
if (const char* l = sf->GetProperty("VS_CSHARP_Link")) {
link = l;
+ } else {
+ link = sourceFilePath.substr(stripFromPath.length() + 1);
}
ConvertToWindowsSlash(link);
}
class cmGeneratedFileStream;
class cmGeneratorTarget;
class cmGlobalVisualStudio10Generator;
-class cmLocalVisualStudio7Generator;
+class cmLocalVisualStudio10Generator;
class cmMakefile;
class cmSourceFile;
class cmSourceGroup;
-class cmVisualStudioGeneratorOptions;
+class cmVS10GeneratorOptions;
class cmVisualStudio10TargetGenerator
{
cmGlobalVisualStudio10Generator* gg);
~cmVisualStudio10TargetGenerator();
void Generate();
- // used by cmVisualStudioGeneratorOptions
- void WritePlatformConfigTag(const char* tag, const std::string& config,
- int indentLevel, const char* attribute = 0,
- const char* end = 0, std::ostream* strm = 0);
private:
struct ToolSource
std::vector<std::string> Configs;
};
+ struct Elem;
+ struct OptionsHelper;
+
std::string ConvertPath(std::string const& path, bool forceRelative);
- void WriteString(const char* line, int indentLevel);
- void WriteProjectConfigurations();
- void WriteProjectConfigurationValues();
- void WriteMSToolConfigurationValues(std::string const& config);
- void WriteMSToolConfigurationValuesManaged(std::string const& config);
- void WriteHeaderSource(cmSourceFile const* sf);
- void WriteExtraSource(cmSourceFile const* sf);
- void WriteNsightTegraConfigurationValues(std::string const& config);
- void WriteSource(std::string const& tool, cmSourceFile const* sf,
- const char* end = 0);
- void WriteExcludeFromBuild(std::vector<size_t> const& exclude_configs);
- void WriteAllSources();
- void WriteDotNetReferences();
- void WriteDotNetReference(std::string const& ref, std::string const& hint);
- void WriteDotNetReferenceCustomTags(std::string const& ref);
- void WriteEmbeddedResourceGroup();
- void WriteWinRTReferences();
- void WriteWinRTPackageCertificateKeyFile();
- void WriteXamlFilesGroup();
- void WritePathAndIncrementalLinkOptions();
- void WriteItemDefinitionGroups();
+ std::string CalcCondition(const std::string& config) const;
+ void WriteProjectConfigurations(Elem& e0);
+ void WriteProjectConfigurationValues(Elem& e0);
+ void WriteMSToolConfigurationValues(Elem& e1, std::string const& config);
+ void WriteMSToolConfigurationValuesManaged(Elem& e1,
+ std::string const& config);
+ void WriteHeaderSource(Elem& e1, cmSourceFile const* sf);
+ void WriteExtraSource(Elem& e1, cmSourceFile const* sf);
+ void WriteNsightTegraConfigurationValues(Elem& e1,
+ std::string const& config);
+ void WriteSource(Elem& e2, std::string const& tool, cmSourceFile const* sf);
+ void WriteExcludeFromBuild(Elem& e2,
+ std::vector<size_t> const& exclude_configs);
+ void WriteAllSources(Elem& e0);
+ void WriteDotNetReferences(Elem& e0);
+ void WriteDotNetReference(Elem& e1, std::string const& ref,
+ std::string const& hint,
+ std::string const& config);
+ void WriteDotNetReferenceCustomTags(Elem& e2, std::string const& ref);
+ void WriteEmbeddedResourceGroup(Elem& e0);
+ void WriteWinRTReferences(Elem& e0);
+ void WriteWinRTPackageCertificateKeyFile(Elem& e0);
+ void WriteXamlFilesGroup(Elem& e0);
+ void WritePathAndIncrementalLinkOptions(Elem& e0);
+ void WriteItemDefinitionGroups(Elem& e0);
void VerifyNecessaryFiles();
- void WriteMissingFiles();
- void WriteMissingFilesWP80();
- void WriteMissingFilesWP81();
- void WriteMissingFilesWS80();
- void WriteMissingFilesWS81();
- void WriteMissingFilesWS10_0();
- void WritePlatformExtensions();
- void WriteSinglePlatformExtension(std::string const& extension,
+ void WriteMissingFiles(Elem& e1);
+ void WriteMissingFilesWP80(Elem& e1);
+ void WriteMissingFilesWP81(Elem& e1);
+ void WriteMissingFilesWS80(Elem& e1);
+ void WriteMissingFilesWS81(Elem& e1);
+ void WriteMissingFilesWS10_0(Elem& e1);
+ void WritePlatformExtensions(Elem& e1);
+ void WriteSinglePlatformExtension(Elem& e1, std::string const& extension,
std::string const& version);
- void WriteSDKReferences();
- void WriteSingleSDKReference(std::string const& extension,
+ void WriteSDKReferences(Elem& e0);
+ void WriteSingleSDKReference(Elem& e1, std::string const& extension,
std::string const& version);
- void WriteCommonMissingFiles(const std::string& manifestFile);
- void WriteTargetSpecificReferences();
- void WriteTargetsFileReferences();
+ void WriteCommonMissingFiles(Elem& e1, const std::string& manifestFile);
+ void WriteTargetSpecificReferences(Elem& e0);
+ void WriteTargetsFileReferences(Elem& e1);
std::vector<std::string> GetIncludes(std::string const& config,
std::string const& lang) const;
bool ComputeClOptions();
bool ComputeClOptions(std::string const& configName);
- void WriteClOptions(std::string const& config);
+ void WriteClOptions(Elem& e1, std::string const& config);
bool ComputeRcOptions();
bool ComputeRcOptions(std::string const& config);
- void WriteRCOptions(std::string const& config);
+ void WriteRCOptions(Elem& e1, std::string const& config);
bool ComputeCudaOptions();
bool ComputeCudaOptions(std::string const& config);
- void WriteCudaOptions(std::string const& config);
+ void WriteCudaOptions(Elem& e1, std::string const& config);
bool ComputeCudaLinkOptions();
bool ComputeCudaLinkOptions(std::string const& config);
- void WriteCudaLinkOptions(std::string const& config);
+ void WriteCudaLinkOptions(Elem& e1, std::string const& config);
bool ComputeMasmOptions();
bool ComputeMasmOptions(std::string const& config);
- void WriteMasmOptions(std::string const& config);
+ void WriteMasmOptions(Elem& e1, std::string const& config);
bool ComputeNasmOptions();
bool ComputeNasmOptions(std::string const& config);
- void WriteNasmOptions(std::string const& config);
+ void WriteNasmOptions(Elem& e1, std::string const& config);
bool ComputeLinkOptions();
bool ComputeLinkOptions(std::string const& config);
bool ComputeLibOptions();
bool ComputeLibOptions(std::string const& config);
- void WriteLinkOptions(std::string const& config);
- void WriteMidlOptions(std::string const& config);
- void WriteAntBuildOptions(std::string const& config);
- void OutputLinkIncremental(std::string const& configName);
- void WriteCustomRule(cmSourceFile const* source,
+ void WriteLinkOptions(Elem& e1, std::string const& config);
+ void WriteMidlOptions(Elem& e1, std::string const& config);
+ void WriteAntBuildOptions(Elem& e1, std::string const& config);
+ void OutputLinkIncremental(Elem& e1, std::string const& configName);
+ void WriteCustomRule(Elem& e0, cmSourceFile const* source,
cmCustomCommand const& command);
- void WriteCustomRuleCpp(std::string const& config, std::string const& script,
- std::string const& inputs,
+ void WriteCustomRuleCpp(Elem& e2, std::string const& config,
+ std::string const& script, std::string const& inputs,
std::string const& outputs,
std::string const& comment);
- void WriteCustomRuleCSharp(std::string const& config,
+ void WriteCustomRuleCSharp(Elem& e0, std::string const& config,
std::string const& commandName,
std::string const& script,
std::string const& inputs,
std::string const& outputs,
std::string const& comment);
- void WriteCustomCommands();
- void WriteCustomCommand(cmSourceFile const* sf);
+ void WriteCustomCommands(Elem& e0);
+ void WriteCustomCommand(Elem& e0, cmSourceFile const* sf);
void WriteGroups();
- void WriteProjectReferences();
- void WriteApplicationTypeSettings();
- bool OutputSourceSpecificFlags(cmSourceFile const* source);
- void AddLibraries(cmComputeLinkInformation& cli,
+ void WriteProjectReferences(Elem& e0);
+ void WriteApplicationTypeSettings(Elem& e1);
+ void OutputSourceSpecificFlags(Elem& e2, cmSourceFile const* source);
+ void AddLibraries(const cmComputeLinkInformation& cli,
std::vector<std::string>& libVec,
- std::vector<std::string>& vsTargetVec);
+ std::vector<std::string>& vsTargetVec,
+ const std::string& config);
void AddTargetsFileAndConfigPair(std::string const& targetsFile,
std::string const& config);
- void WriteLibOptions(std::string const& config);
- void WriteManifestOptions(std::string const& config);
- void WriteEvents(std::string const& configName);
- void WriteEvent(const char* name,
+ void WriteLibOptions(Elem& e1, std::string const& config);
+ void WriteManifestOptions(Elem& e1, std::string const& config);
+ void WriteEvents(Elem& e1, std::string const& configName);
+ void WriteEvent(Elem& e1, const char* name,
std::vector<cmCustomCommand> const& commands,
std::string const& configName);
- void WriteGroupSources(const char* name, ToolSources const& sources,
+ void WriteGroupSources(Elem& e0, std::string const& name,
+ ToolSources const& sources,
std::vector<cmSourceGroup>&);
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
void GetCSharpSourceProperties(cmSourceFile const* sf,
std::map<std::string, std::string>& tags);
void WriteCSharpSourceProperties(
- const std::map<std::string, std::string>& tags);
+ Elem& e2, const std::map<std::string, std::string>& tags);
void GetCSharpSourceLink(cmSourceFile const* sf, std::string& link);
private:
- typedef cmVisualStudioGeneratorOptions Options;
+ friend class cmVS10GeneratorOptions;
+ typedef cmVS10GeneratorOptions Options;
typedef std::map<std::string, std::unique_ptr<Options>> OptionsMap;
OptionsMap ClOptions;
OptionsMap RcOptions;
OptionsMap NasmOptions;
OptionsMap LinkOptions;
std::string LangForClCompile;
- std::string PathToProjectFile;
- std::string ProjectFileExtension;
enum VsProjectType
{
vcxproj,
bool InSourceBuild;
std::vector<std::string> Configurations;
std::vector<TargetsFileAndConfigs> TargetsFileAndConfigsVec;
- cmGeneratorTarget* GeneratorTarget;
- cmMakefile* Makefile;
- std::string Platform;
- std::string GUID;
- std::string Name;
+ cmGeneratorTarget* const GeneratorTarget;
+ cmMakefile* const Makefile;
+ std::string const Platform;
+ std::string const Name;
+ std::string const GUID;
bool MSTools;
bool Managed;
bool NsightTegra;
- int NsightTegraVersion[4];
+ unsigned int NsightTegraVersion[4];
bool TargetCompileAsWinRT;
- cmGlobalVisualStudio10Generator* GlobalGenerator;
- cmGeneratedFileStream* BuildFileStream;
- cmLocalVisualStudio7Generator* LocalGenerator;
- std::set<cmSourceFile const*> SourcesVisited;
+ cmGlobalVisualStudio10Generator* const GlobalGenerator;
+ cmLocalVisualStudio10Generator* const LocalGenerator;
std::set<std::string> CSharpCustomCommandNames;
bool IsMissingFiles;
std::vector<std::string> AddedFiles;
std::string DefaultArtifactDir;
+ bool AddedDefaultCertificate = false;
+ // managed C++/C# relevant members
+ typedef std::pair<std::string, std::string> DotNetHintReference;
+ typedef std::vector<DotNetHintReference> DotNetHintReferenceList;
+ typedef std::map<std::string, DotNetHintReferenceList>
+ DotNetHintReferenceMap;
+ DotNetHintReferenceMap DotNetHintReferences;
+ typedef std::set<std::string> UsingDirectories;
+ typedef std::map<std::string, UsingDirectories> UsingDirectoriesMap;
+ UsingDirectoriesMap AdditionalUsingDirectories;
typedef std::map<std::string, ToolSources> ToolSourceMap;
ToolSourceMap Tools;
#include "cmLocalVisualStudioGenerator.h"
#include "cmOutputConverter.h"
#include "cmSystemTools.h"
-#include "cmVisualStudio10TargetGenerator.h"
-static std::string cmVisualStudio10GeneratorOptionsEscapeForXML(
- std::string ret)
+static void cmVS10EscapeForMSBuild(std::string& ret)
{
cmSystemTools::ReplaceString(ret, ";", "%3B");
- cmSystemTools::ReplaceString(ret, "&", "&");
- cmSystemTools::ReplaceString(ret, "<", "<");
- cmSystemTools::ReplaceString(ret, ">", ">");
- return ret;
-}
-
-static std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret)
-{
- cmSystemTools::ReplaceString(ret, "&", "&");
- cmSystemTools::ReplaceString(ret, "\"", """);
- cmSystemTools::ReplaceString(ret, "<", "<");
- cmSystemTools::ReplaceString(ret, ">", ">");
- cmSystemTools::ReplaceString(ret, "\n", "
");
- return ret;
-}
-
-cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
- cmLocalVisualStudioGenerator* lg, Tool tool,
- cmVisualStudio10TargetGenerator* g)
- : cmVisualStudioGeneratorOptions(lg, tool, nullptr, nullptr, g)
-{
}
cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
cmLocalVisualStudioGenerator* lg, Tool tool, cmVS7FlagTable const* table,
- cmVS7FlagTable const* extraTable, cmVisualStudio10TargetGenerator* g)
+ cmVS7FlagTable const* extraTable)
: cmIDEOptions()
, LocalGenerator(lg)
, Version(lg->GetVersion())
, CurrentTool(tool)
- , TargetGenerator(g)
{
// Store the given flag tables.
this->AddTable(table);
bool cmVisualStudioGeneratorOptions::UsingUnicode() const
{
- // Look for the a _UNICODE definition.
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di) {
- if (*di == "_UNICODE") {
+ // Look for a _UNICODE definition.
+ for (std::string const& di : this->Defines) {
+ if (di == "_UNICODE") {
return true;
}
}
}
bool cmVisualStudioGeneratorOptions::UsingSBCS() const
{
- // Look for the a _SBCS definition.
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di) {
- if (*di == "_SBCS") {
+ // Look for a _SBCS definition.
+ for (std::string const& di : this->Defines) {
+ if (di == "_SBCS") {
return true;
}
}
// It translates to -arch=<virtual> -code=<real>.
cmSystemTools::ReplaceString(arch_name, "sm_", "compute_");
}
- for (auto const& c : codes) {
+ for (std::string const& c : codes) {
std::string entry = arch_name + "," + c;
result.push_back(entry);
}
// -gencode=<arch>,<code>
// -gencode=<arch>,[<code1>,<code2>]
// -gencode=<arch>,"<code1>,<code2>"
- for (auto const& e : gencode) {
+ for (std::string const& e : gencode) {
std::string entry = e;
cmSystemTools::ReplaceString(entry, "arch=", "");
cmSystemTools::ReplaceString(entry, "code=", "");
uacExecuteLevelMap["highestAvailable"] = "HighestAvailable";
uacExecuteLevelMap["requireAdministrator"] = "RequireAdministrator";
- for (auto const& subopt : subOptions) {
+ for (std::string const& subopt : subOptions) {
std::vector<std::string> keyValue;
cmsys::SystemTools::Split(subopt, keyValue, '=');
if (keyValue.size() != 2 || (uacMap.find(keyValue[0]) == uacMap.end())) {
// Process flags that need to be represented specially in the IDE
// project file.
- for (std::vector<std::string>::iterator ai = args.begin(); ai != args.end();
- ++ai) {
- this->HandleFlag(ai->c_str());
+ for (std::string const& ai : args) {
+ this->HandleFlag(ai);
}
}
this->Parse(original.c_str());
}
-void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
+void cmVisualStudioGeneratorOptions::StoreUnknownFlag(std::string const& flag)
{
// Look for Intel Fortran flags that do not map well in the flag table.
if (this->CurrentTool == FortranCompiler) {
- if (strcmp(flag, "/dbglibs") == 0) {
+ if (flag == "/dbglibs") {
this->FortranRuntimeDebug = true;
return;
}
- if (strcmp(flag, "/threads") == 0) {
+ if (flag == "/threads") {
this->FortranRuntimeMT = true;
return;
}
- if (strcmp(flag, "/libs:dll") == 0) {
+ if (flag == "/libs:dll") {
this->FortranRuntimeDLL = true;
return;
}
- if (strcmp(flag, "/libs:static") == 0) {
+ if (flag == "/libs:static") {
this->FortranRuntimeDLL = false;
return;
}
// This option is not known. Store it in the output flags.
std::string const opts = cmOutputConverter::EscapeWindowsShellArgument(
- flag, cmOutputConverter::Shell_Flag_AllowMakeVariables |
+ flag.c_str(),
+ cmOutputConverter::Shell_Flag_AllowMakeVariables |
cmOutputConverter::Shell_Flag_VSIDE);
this->AppendFlagString(this->UnknownFlagField, opts);
}
return value;
}
-void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
+void cmVisualStudioGeneratorOptions::SetConfiguration(
+ const std::string& config)
{
this->Configuration = config;
}
+const std::string& cmVisualStudioGeneratorOptions::GetConfiguration() const
+{
+ return this->Configuration;
+}
+
void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
- std::ostream& fout, const char* prefix, const char* suffix,
- const std::string& lang)
+ std::ostream& fout, int indent, const std::string& lang)
{
if (this->Defines.empty()) {
return;
if (lang == "CUDA") {
tag = "Defines";
}
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- // if there are configuration specific flags, then
- // use the configuration specific tag for PreprocessorDefinitions
- if (!this->Configuration.empty()) {
- fout << prefix;
- this->TargetGenerator->WritePlatformConfigTag(
- tag, this->Configuration.c_str(), 0, 0, 0, &fout);
- } else {
- fout << prefix << "<" << tag << ">";
- }
- } else {
- fout << prefix << tag << "=\"";
- }
+
+ std::ostringstream oss;
const char* sep = "";
std::vector<std::string>::const_iterator de =
cmRemoveDuplicates(this->Defines);
// Escape the definition for the compiler.
std::string define;
if (this->Version < cmGlobalVisualStudioGenerator::VS10) {
- define = this->LocalGenerator->EscapeForShell(di->c_str(), true);
+ define = this->LocalGenerator->EscapeForShell(*di, true);
} else {
define = *di;
}
- // Escape this flag for the IDE.
+ // Escape this flag for the MSBuild.
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- define = cmVisualStudio10GeneratorOptionsEscapeForXML(define);
-
+ cmVS10EscapeForMSBuild(define);
if (lang == "RC") {
cmSystemTools::ReplaceString(define, "\"", "\\\"");
}
- } else {
- define = cmVisualStudioGeneratorOptionsEscapeForXML(define);
}
// Store the flag in the project file.
- fout << sep << define;
+ oss << sep << define;
sep = ";";
}
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- fout << ";%(" << tag << ")</" << tag << ">" << suffix;
- } else {
- fout << "\"" << suffix;
+ oss << ";%(" << tag << ")";
}
+
+ this->OutputFlag(fout, indent, tag, oss.str());
}
void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
- std::ostream& fout, const char* prefix, const char* suffix,
- const std::string& lang)
+ std::ostream& fout, int indent, const std::string& lang)
{
if (this->Includes.empty()) {
return;
tag = "IncludePaths";
}
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- // if there are configuration specific flags, then
- // use the configuration specific tag for PreprocessorDefinitions
- if (!this->Configuration.empty()) {
- fout << prefix;
- this->TargetGenerator->WritePlatformConfigTag(
- tag, this->Configuration.c_str(), 0, 0, 0, &fout);
- } else {
- fout << prefix << "<" << tag << ">";
- }
- } else {
- fout << prefix << tag << "=\"";
- }
-
+ std::ostringstream oss;
const char* sep = "";
for (std::string include : this->Includes) {
// first convert all of the slashes
include += "\\";
}
- // Escape this include for the IDE.
- fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
- ? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
- : cmVisualStudioGeneratorOptionsEscapeForXML(include));
+ // Escape this include for the MSBuild.
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ cmVS10EscapeForMSBuild(include);
+ }
+ oss << sep << include;
sep = ";";
if (lang == "Fortran") {
include += "/$(ConfigurationName)";
- fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
- ? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
- : cmVisualStudioGeneratorOptionsEscapeForXML(include));
+ oss << sep << include;
}
}
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- fout << sep << "%(" << tag << ")</" << tag << ">" << suffix;
- } else {
- fout << "\"" << suffix;
+ oss << sep << "%(" << tag << ")";
}
+
+ this->OutputFlag(fout, indent, tag, oss.str());
}
void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
- const char* indent)
+ int indent)
{
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
- fout << indent;
- if (!this->Configuration.empty()) {
- this->TargetGenerator->WritePlatformConfigTag(
- m->first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout);
- } else {
- fout << "<" << m->first << ">";
+ for (auto const& m : this->FlagMap) {
+ std::ostringstream oss;
+ const char* sep = "";
+ for (std::string i : m.second) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ cmVS10EscapeForMSBuild(i);
}
- const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(*i);
- sep = ";";
- }
- fout << "</" << m->first << ">\n";
- }
- } else {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
- fout << indent << m->first << "=\"";
- const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(*i);
- sep = ";";
- }
- fout << "\"\n";
+ oss << sep << i;
+ sep = ";";
}
+
+ this->OutputFlag(fout, indent, m.first.c_str(), oss.str());
}
}
typedef cmIDEFlagTable cmVS7FlagTable;
-class cmVisualStudio10TargetGenerator;
-
class cmVisualStudioGeneratorOptions : public cmIDEOptions
{
public:
CSharpCompiler
};
cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
- cmVS7FlagTable const* table,
- cmVS7FlagTable const* extraTable = 0,
- cmVisualStudio10TargetGenerator* g = 0);
-
- cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
- cmVisualStudio10TargetGenerator* g = 0);
+ cmVS7FlagTable const* table = nullptr,
+ cmVS7FlagTable const* extraTable = nullptr);
// Add a table of flags.
void AddTable(cmVS7FlagTable const* table);
bool IsWinRt() const;
bool IsManaged() const;
// Write options to output.
- void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix,
- const char* suffix,
+ void OutputPreprocessorDefinitions(std::ostream& fout, int indent,
const std::string& lang);
- void OutputAdditionalIncludeDirectories(std::ostream& fout,
- const char* prefix,
- const char* suffix,
+ void OutputAdditionalIncludeDirectories(std::ostream& fout, int indent,
const std::string& lang);
- void OutputFlagMap(std::ostream& fout, const char* indent);
- void SetConfiguration(const char* config);
+ void OutputFlagMap(std::ostream& fout, int indent);
+ void SetConfiguration(const std::string& config);
+ const std::string& GetConfiguration() const;
+
+protected:
+ virtual void OutputFlag(std::ostream& fout, int indent, const char* tag,
+ const std::string& content) = 0;
private:
cmLocalVisualStudioGenerator* LocalGenerator;
std::string Configuration;
Tool CurrentTool;
- cmVisualStudio10TargetGenerator* TargetGenerator;
bool FortranRuntimeDebug;
bool FortranRuntimeDLL;
std::string UnknownFlagField;
- virtual void StoreUnknownFlag(const char* flag);
+ void StoreUnknownFlag(std::string const& flag) override;
FlagValue TakeFlag(std::string const& key);
};
cmExecutionStatus& inStatus)
{
// at end of for each execute recorded commands
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "while")) {
+ if (lff.Name.Lower == "while") {
// record the number of while commands past this one
this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) {
+ } else if (lff.Name.Lower == "endwhile") {
// if this is the endwhile for this while loop then execute
if (!this->Depth) {
// Remove the function blocker for this scope or bail.
bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) {
+ if (lff.Name.Lower == "endwhile") {
// if the endwhile has arguments, then make sure
// they match the arguments of the matching while
if (lff.Arguments.empty() || lff.Arguments == this->Args) {
#include "cmSystemTools.h"
+#include <cerrno>
+
cmWorkingDirectory::cmWorkingDirectory(std::string const& newdir)
{
this->OldDir = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(newdir);
+ this->SetDirectory(newdir);
}
cmWorkingDirectory::~cmWorkingDirectory()
this->Pop();
}
+bool cmWorkingDirectory::SetDirectory(std::string const& newdir)
+{
+ if (cmSystemTools::ChangeDirectory(newdir) == 0) {
+ this->ResultCode = 0;
+ return true;
+ }
+ this->ResultCode = errno;
+ return false;
+}
+
void cmWorkingDirectory::Pop()
{
if (!this->OldDir.empty()) {
- cmSystemTools::ChangeDirectory(this->OldDir);
+ this->SetDirectory(this->OldDir);
this->OldDir.clear();
}
}
/** \class cmWorkingDirectory
* \brief An RAII class to manipulate the working directory.
+ *
+ * The current working directory is set to the location given to the
+ * constructor. The working directory can be changed again as needed
+ * by calling SetDirectory(). When the object is destroyed, the destructor
+ * will restore the working directory to what it was when the object was
+ * created, regardless of any calls to SetDirectory() in the meantime.
*/
class cmWorkingDirectory
{
cmWorkingDirectory(std::string const& newdir);
~cmWorkingDirectory();
+ bool SetDirectory(std::string const& newdir);
void Pop();
+ bool Failed() const { return ResultCode != 0; }
+
+ /** \return 0 if the last attempt to set the working directory was
+ * successful. If it failed, the value returned will be the
+ * \c errno value associated with the failure. A description
+ * of the error code can be obtained by passing the result
+ * to \c std::strerror().
+ */
+ int GetLastResult() const { return ResultCode; }
private:
std::string OldDir;
+ int ResultCode;
};
#endif
#else
mode | S_IWUSR | S_IWGRP
#endif
- );
+ );
}
// If GetPermissions fails, pretend like it is ok. File open will fail if
// the file is not writable
: Output(output)
, IndentationElement(1, '\t')
, Level(level)
+ , Indent(0)
, ElementOpen(false)
, BreakAttrib(false)
, IsContent(false)
cmXMLWriter::~cmXMLWriter()
{
- assert(this->Elements.empty());
+ assert(this->Indent == 0);
}
void cmXMLWriter::StartDocument(const char* encoding)
void cmXMLWriter::EndDocument()
{
- assert(this->Elements.empty());
+ assert(this->Indent == 0);
this->Output << '\n';
}
void cmXMLWriter::StartElement(std::string const& name)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << '<' << name;
this->Elements.push(name);
+ ++this->Indent;
this->ElementOpen = true;
this->BreakAttrib = false;
}
void cmXMLWriter::EndElement()
{
- assert(!this->Elements.empty());
+ assert(this->Indent > 0);
+ --this->Indent;
if (this->ElementOpen) {
this->Output << "/>";
} else {
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size() - 1);
+ this->ConditionalLineBreak(!this->IsContent);
this->IsContent = false;
this->Output << "</" << this->Elements.top() << '>';
}
void cmXMLWriter::Element(const char* name)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << '<' << name << "/>";
}
void cmXMLWriter::Comment(const char* comment)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << "<!-- " << comment << " -->";
}
void cmXMLWriter::Doctype(const char* doctype)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << "<!DOCTYPE " << doctype << ">";
}
void cmXMLWriter::ProcessingInstruction(const char* target, const char* data)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << "<?" << target << ' ' << data << "?>";
}
this->IndentationElement = element;
}
-void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent)
+void cmXMLWriter::ConditionalLineBreak(bool condition)
{
if (condition) {
this->Output << '\n';
- for (std::size_t i = 0; i < indent + this->Level; ++i) {
+ for (std::size_t i = 0; i < this->Indent + this->Level; ++i) {
this->Output << this->IndentationElement;
}
}
void cmXMLWriter::PreAttribute()
{
assert(this->ElementOpen);
- this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
+ this->ConditionalLineBreak(this->BreakAttrib);
if (!this->BreakAttrib) {
this->Output << ' ';
}
void cmXMLWriter::CloseStartElement()
{
if (this->ElementOpen) {
- this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
+ this->ConditionalLineBreak(this->BreakAttrib);
this->Output << '>';
this->ElementOpen = false;
}
void SetIndentationElement(std::string const& element);
private:
- void ConditionalLineBreak(bool condition, std::size_t indent);
+ void ConditionalLineBreak(bool condition);
void PreAttribute();
void PreContent();
std::stack<std::string, std::vector<std::string>> Elements;
std::string IndentationElement;
std::size_t Level;
+ std::size_t Indent;
bool ElementOpen;
bool BreakAttrib;
bool IsContent;
};
+class cmXMLElement; // IWYU pragma: keep
+
+class cmXMLDocument
+{
+public:
+ cmXMLDocument(cmXMLWriter& xml)
+ : xmlwr(xml)
+ {
+ xmlwr.StartDocument();
+ }
+ ~cmXMLDocument() { xmlwr.EndDocument(); }
+
+private:
+ friend class cmXMLElement;
+ cmXMLWriter& xmlwr;
+};
+
+class cmXMLElement
+{
+public:
+ cmXMLElement(cmXMLWriter& xml, const char* tag)
+ : xmlwr(xml)
+ {
+ xmlwr.StartElement(tag);
+ }
+ cmXMLElement(cmXMLElement& par, const char* tag)
+ : xmlwr(par.xmlwr)
+ {
+ xmlwr.StartElement(tag);
+ }
+ cmXMLElement(cmXMLDocument& doc, const char* tag)
+ : xmlwr(doc.xmlwr)
+ {
+ xmlwr.StartElement(tag);
+ }
+ ~cmXMLElement() { xmlwr.EndElement(); }
+
+ template <typename T>
+ cmXMLElement& Attribute(const char* name, T const& value)
+ {
+ xmlwr.Attribute(name, value);
+ return *this;
+ }
+ template <typename T>
+ void Content(T const& content)
+ {
+ xmlwr.Content(content);
+ }
+ template <typename T>
+ void Element(std::string const& name, T const& value)
+ {
+ xmlwr.Element(name, value);
+ }
+ void Comment(const char* comment) { xmlwr.Comment(comment); }
+
+private:
+ cmXMLWriter& xmlwr;
+};
+
#endif
#include "cm_codecvt.hxx"
#if defined(_WIN32)
-#include <assert.h>
-#include <string.h>
-#include <windows.h>
-#undef max
-#include "cmsys/Encoding.hxx"
+# include <assert.h>
+# include <string.h>
+# include <windows.h>
+# undef max
+# include "cmsys/Encoding.hxx"
#endif
#if defined(_WIN32)
};
bool m_noconv;
-#if defined(_WIN32)
+# if defined(_WIN32)
unsigned int m_codepage;
result Decode(mbstate_t& state, int need, const char*& from_next,
char*& to_next, char* to_end) const;
result DecodePartial(mbstate_t& state, char*& to_next, char* to_end) const;
void BufferPartial(mbstate_t& state, int need, const char*& from_next) const;
-#endif
+# endif
#endif
};
#include "cm_sys_stat.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cm_jsoncpp_writer.h"
+# include "cm_jsoncpp_writer.h"
-#include "cmGraphVizWriter.h"
-#include "cmVariableWatch.h"
-#include <unordered_map>
+# include "cmGraphVizWriter.h"
+# include "cmVariableWatch.h"
+# include <unordered_map>
#endif
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#define CMAKE_USE_ECLIPSE
+# define CMAKE_USE_ECLIPSE
#endif
#if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE)
-#define CMAKE_BOOT_MINGW
+# define CMAKE_BOOT_MINGW
#endif
// include the generator
#if defined(_WIN32) && !defined(__CYGWIN__)
-#if !defined(CMAKE_BOOT_MINGW)
-#include "cmGlobalBorlandMakefileGenerator.h"
-#include "cmGlobalGhsMultiGenerator.h"
-#include "cmGlobalJOMMakefileGenerator.h"
-#include "cmGlobalNMakeMakefileGenerator.h"
-#include "cmGlobalVisualStudio10Generator.h"
-#include "cmGlobalVisualStudio11Generator.h"
-#include "cmGlobalVisualStudio12Generator.h"
-#include "cmGlobalVisualStudio14Generator.h"
-#include "cmGlobalVisualStudio15Generator.h"
-#include "cmGlobalVisualStudio8Generator.h"
-#include "cmGlobalVisualStudio9Generator.h"
-#include "cmVSSetupHelper.h"
-
-#define CMAKE_HAVE_VS_GENERATORS
-#endif
-#include "cmGlobalMSYSMakefileGenerator.h"
-#include "cmGlobalMinGWMakefileGenerator.h"
+# if !defined(CMAKE_BOOT_MINGW)
+# include "cmGlobalBorlandMakefileGenerator.h"
+# include "cmGlobalGhsMultiGenerator.h"
+# include "cmGlobalJOMMakefileGenerator.h"
+# include "cmGlobalNMakeMakefileGenerator.h"
+# include "cmGlobalVisualStudio10Generator.h"
+# include "cmGlobalVisualStudio11Generator.h"
+# include "cmGlobalVisualStudio12Generator.h"
+# include "cmGlobalVisualStudio14Generator.h"
+# include "cmGlobalVisualStudio15Generator.h"
+# include "cmGlobalVisualStudio9Generator.h"
+# include "cmVSSetupHelper.h"
+
+# define CMAKE_HAVE_VS_GENERATORS
+# endif
+# include "cmGlobalMSYSMakefileGenerator.h"
+# include "cmGlobalMinGWMakefileGenerator.h"
#else
#endif
#if defined(CMAKE_USE_WMAKE)
-#include "cmGlobalWatcomWMakeGenerator.h"
+# include "cmGlobalWatcomWMakeGenerator.h"
#endif
#include "cmGlobalUnixMakefileGenerator3.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmGlobalNinjaGenerator.h"
+# include "cmGlobalNinjaGenerator.h"
#endif
#include "cmExtraCodeLiteGenerator.h"
#if !defined(CMAKE_BOOT_MINGW)
-#include "cmExtraCodeBlocksGenerator.h"
+# include "cmExtraCodeBlocksGenerator.h"
#endif
#include "cmExtraKateGenerator.h"
#include "cmExtraSublimeTextGenerator.h"
#ifdef CMAKE_USE_ECLIPSE
-#include "cmExtraEclipseCDT4Generator.h"
+# include "cmExtraEclipseCDT4Generator.h"
#endif
#if defined(__APPLE__)
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmGlobalXCodeGenerator.h"
+# if defined(CMAKE_BUILD_WITH_CMAKE)
+# include "cmGlobalXCodeGenerator.h"
-#define CMAKE_USE_XCODE 1
-#endif
-#include <sys/resource.h>
-#include <sys/time.h>
+# define CMAKE_USE_XCODE 1
+# endif
+# include <sys/resource.h>
+# include <sys/time.h>
#endif
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cstring>
#include <iostream>
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <utility>
namespace {
this->ExtraGenerators.push_back(cmExtraSublimeTextGenerator::GetFactory());
this->ExtraGenerators.push_back(cmExtraKateGenerator::GetFactory());
-#ifdef CMAKE_USE_ECLIPSE
+# ifdef CMAKE_USE_ECLIPSE
this->ExtraGenerators.push_back(cmExtraEclipseCDT4Generator::GetFactory());
-#endif
+# endif
#endif
}
// only save the cache if there were no fatal errors
if (this->GetWorkingMode() == NORMAL_MODE) {
+ this->State->SaveVerificationScript(this->GetHomeOutputDirectory());
this->SaveCache(this->GetHomeOutputDirectory());
}
if (cmSystemTools::GetErrorOccuredFlag()) {
{ "12.0", "Visual Studio 12 2013" }, //
{ "11.0", "Visual Studio 11 2012" }, //
{ "10.0", "Visual Studio 10 2010" }, //
- { "9.0", "Visual Studio 9 2008" }, //
- { "8.0", "Visual Studio 8 2005" }
+ { "9.0", "Visual Studio 9 2008" }
};
static const char* const vsEntries[] = {
"\\Setup\\VC;ProductDir", //
this->UnwatchUnusedCli(key);
}
+bool cmake::DoWriteGlobVerifyTarget() const
+{
+ return this->State->DoWriteGlobVerifyTarget();
+}
+
+std::string const& cmake::GetGlobVerifyScript() const
+{
+ return this->State->GetGlobVerifyScript();
+}
+
+std::string const& cmake::GetGlobVerifyStamp() const
+{
+ return this->State->GetGlobVerifyStamp();
+}
+
+void cmake::AddGlobCacheEntry(bool recurse, bool listDirectories,
+ bool followSymlinks, const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ cmListFileBacktrace const& backtrace)
+{
+ this->State->AddGlobCacheEntry(recurse, listDirectories, followSymlinks,
+ relative, expression, files, variable,
+ backtrace);
+}
+
std::string cmake::StripExtension(const std::string& file) const
{
auto dotpos = file.rfind('.');
void cmake::AddDefaultGenerators()
{
#if defined(_WIN32) && !defined(__CYGWIN__)
-#if !defined(CMAKE_BOOT_MINGW)
+# if !defined(CMAKE_BOOT_MINGW)
this->Generators.push_back(cmGlobalVisualStudio15Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio14Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio12Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio11Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio10Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio9Generator::NewFactory());
- this->Generators.push_back(cmGlobalVisualStudio8Generator::NewFactory());
this->Generators.push_back(cmGlobalBorlandMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalNMakeMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalJOMMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory());
-#endif
+# endif
this->Generators.push_back(cmGlobalMSYSMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalMinGWMakefileGenerator::NewFactory());
#endif
{
// now run cmake on the CMakeLists file
cmWorkingDirectory workdir(destPath);
+ if (workdir.Failed()) {
+ // We created the directory and we were able to copy the CMakeLists.txt
+ // file to it, so we wouldn't expect to get here unless the default
+ // permissions are questionable or some other process has deleted the
+ // directory
+ std::cerr << "Failed to change to directory " << destPath << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return 1;
+ }
std::vector<std::string> args2;
args2.push_back(args[0]);
args2.push_back(destPath);
return this->Messenger;
}
-int cmake::Build(const std::string& dir, const std::string& target,
+int cmake::Build(int jobs, const std::string& dir, const std::string& target,
const std::string& config,
const std::vector<std::string>& nativeOptions, bool clean)
{
std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
return 1;
}
- std::unique_ptr<cmGlobalGenerator> gen(
- this->CreateGlobalGenerator(cachedGenerator));
- if (!gen.get()) {
+ cmGlobalGenerator* gen = this->CreateGlobalGenerator(cachedGenerator);
+ if (!gen) {
std::cerr << "Error: could create CMAKE_GENERATOR \"" << cachedGenerator
<< "\"\n";
return 1;
}
+ this->SetGlobalGenerator(gen);
const char* cachedGeneratorInstance =
this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE");
if (cachedGeneratorInstance) {
- cmMakefile mf(gen.get(), this->GetCurrentSnapshot());
+ cmMakefile mf(gen, this->GetCurrentSnapshot());
if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) {
return 1;
}
// to limitations of the underlying build system.
std::string const stampList = cachePath + "/" +
GetCMakeFilesDirectoryPostSlash() +
- cmGlobalVisualStudio8Generator::GetGenerateStampList();
+ cmGlobalVisualStudio9Generator::GetGenerateStampList();
// Note that the stampList file only exists for VS generators.
- if (cmSystemTools::FileExists(stampList) &&
- !cmakeCheckStampList(stampList.c_str(), false)) {
-
- // Correctly initialize the home (=source) and home output (=binary)
- // directories, which is required for running the generation step.
- std::string homeOrig = this->GetHomeDirectory();
- std::string homeOutputOrig = this->GetHomeOutputDirectory();
- this->SetDirectoriesFromFile(cachePath.c_str());
+ if (cmSystemTools::FileExists(stampList)) {
+ // Check if running for Visual Studio 9 - we need to explicitly run
+ // the glob verification script before starting the build
this->AddScriptingCommands();
- this->AddProjectCommands();
-
- int ret = this->Configure();
- if (ret) {
- cmSystemTools::Message("CMake Configure step failed. "
- "Build files cannot be regenerated correctly.");
- return ret;
- }
- ret = this->Generate();
- if (ret) {
- cmSystemTools::Message("CMake Generate step failed. "
- "Build files cannot be regenerated correctly.");
- return ret;
+ if (this->GlobalGenerator->MatchesGeneratorName("Visual Studio 9 2008")) {
+ std::string const globVerifyScript = cachePath + "/" +
+ GetCMakeFilesDirectoryPostSlash() + "VerifyGlobs.cmake";
+ if (cmSystemTools::FileExists(globVerifyScript)) {
+ std::vector<std::string> args;
+ this->ReadListFile(args, globVerifyScript.c_str());
+ }
}
- std::string message = "Build files have been written to: ";
- message += this->GetHomeOutputDirectory();
- this->UpdateProgress(message.c_str(), -1);
- // Restore the previously set directories to their original value.
- this->SetHomeDirectory(homeOrig);
- this->SetHomeOutputDirectory(homeOutputOrig);
+ if (!cmakeCheckStampList(stampList.c_str(), false)) {
+ // Correctly initialize the home (=source) and home output (=binary)
+ // directories, which is required for running the generation step.
+ std::string homeOrig = this->GetHomeDirectory();
+ std::string homeOutputOrig = this->GetHomeOutputDirectory();
+ this->SetDirectoriesFromFile(cachePath.c_str());
+
+ this->AddProjectCommands();
+
+ int ret = this->Configure();
+ if (ret) {
+ cmSystemTools::Message("CMake Configure step failed. "
+ "Build files cannot be regenerated correctly.");
+ return ret;
+ }
+ ret = this->Generate();
+ if (ret) {
+ cmSystemTools::Message("CMake Generate step failed. "
+ "Build files cannot be regenerated correctly.");
+ return ret;
+ }
+ std::string message = "Build files have been written to: ";
+ message += this->GetHomeOutputDirectory();
+ this->UpdateProgress(message.c_str(), -1);
+
+ // Restore the previously set directories to their original value.
+ this->SetHomeDirectory(homeOrig);
+ this->SetHomeOutputDirectory(homeOutputOrig);
+ }
}
#endif
- return gen->Build("", dir, projName, target, output, "", config, clean,
+ gen->PrintBuildCommandAdvice(std::cerr, jobs);
+
+ return gen->Build(jobs, "", dir, projName, target, output, "", config, clean,
false, verbose, cmDuration::zero(),
cmSystemTools::OUTPUT_PASSTHROUGH, nativeOptions);
}
#include "cmStateTypes.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cm_jsoncpp_value.h"
+# include "cm_jsoncpp_value.h"
#endif
class cmExternalMakefileProjectGeneratorFactory;
typedef std::map<std::string, cmInstalledFile> InstalledFilesMap;
+ static const int NO_BUILD_PARALLEL_LEVEL = -1;
+ static const int DEFAULT_BUILD_PARALLEL_LEVEL = 0;
+
/// Default constructor
cmake(Role role);
/// Destructor
void AddCacheEntry(const std::string& key, const char* value,
const char* helpString, int type);
+ bool DoWriteGlobVerifyTarget() const;
+ std::string const& GetGlobVerifyScript() const;
+ std::string const& GetGlobVerifyStamp() const;
+ void AddGlobCacheEntry(bool recurse, bool listDirectories,
+ bool followSymlinks, const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ cmListFileBacktrace const& bt);
+
/**
* Get the system information and write it to the file specified
*/
cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
///! run the --build option
- int Build(const std::string& dir, const std::string& target,
+ int Build(int jobs, const std::string& dir, const std::string& target,
const std::string& config,
const std::vector<std::string>& nativeOptions, bool clean);
#define CMAKE_STANDARD_OPTIONS_TABLE \
{ "-C <initial-cache>", "Pre-load a script to populate the cache." }, \
- { "-D <var>[:<type>]=<value>", "Create a cmake cache entry." }, \
+ { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \
{ "-U <globbing_expr>", "Remove matching entries from CMake cache." }, \
{ "-G <generator-name>", "Specify a build system generator." }, \
{ "-T <toolset-name>", \
{ "-Wno-error=dev", "Make developer warnings not errors." }, \
{ "-Wdeprecated", "Enable deprecation warnings." }, \
{ "-Wno-deprecated", "Suppress deprecation warnings." }, \
- { "-Werror=deprecated", "Make deprecated macro and function warnings " \
- "errors." }, \
+ { "-Werror=deprecated", \
+ "Make deprecated macro and function warnings " \
+ "errors." }, \
{ \
- "-Wno-error=deprecated", "Make deprecated macro and function warnings " \
- "not errors." \
+ "-Wno-error=deprecated", \
+ "Make deprecated macro and function warnings " \
+ "not errors." \
}
#define FOR_EACH_C_FEATURE(F) \
F(cxx_std_11) \
F(cxx_std_14) \
F(cxx_std_17) \
+ F(cxx_std_20) \
F(cxx_aggregate_default_initializers) \
F(cxx_alias_templates) \
F(cxx_alignas) \
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmake.h"
#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
+#include "cmake.h"
#include "cmcmd.h"
#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmDocumentation.h"
-#include "cmDynamicLoader.h"
+# include "cmDocumentation.h"
+# include "cmDynamicLoader.h"
#endif
#include "cm_uv.h"
#include "cmsys/Encoding.hxx"
#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmsys/ConsoleBuf.hxx"
+# include "cmsys/ConsoleBuf.hxx"
#endif
+
+#include <ctype.h>
#include <iostream>
#include <string.h>
#include <string>
};
static const char* cmDocumentationUsage[][2] = {
- { nullptr, " cmake [options] <path-to-source>\n"
- " cmake [options] <path-to-existing-build>" },
- { nullptr, "Specify a source directory to (re-)generate a build system for "
- "it in the current working directory. Specify an existing build "
- "directory to re-generate its build system." },
+ { nullptr,
+ " cmake [options] <path-to-source>\n"
+ " cmake [options] <path-to-existing-build>" },
+ { nullptr,
+ "Specify a source directory to (re-)generate a build system for "
+ "it in the current working directory. Specify an existing build "
+ "directory to re-generate its build system." },
{ nullptr, nullptr }
};
{ nullptr, nullptr }
};
-#define CMAKE_BUILD_OPTIONS \
- " <dir> = Project binary directory to be built.\n" \
- " --target <tgt> = Build <tgt> instead of default targets.\n" \
- " May only be specified once.\n" \
- " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
- " --clean-first = Build target 'clean' first, then build.\n" \
- " (To clean only, use --target 'clean'.)\n" \
- " --use-stderr = Ignored. Behavior is default in CMake >= 3.0.\n" \
- " -- = Pass remaining options to the native tool.\n"
+# define CMAKE_BUILD_OPTIONS \
+ " <dir> = Project binary directory to be built.\n" \
+ " -j [<jobs>] --parallel [<jobs>] = Build in parallel using\n" \
+ " the given number of jobs. If <jobs> is omitted\n" \
+ " the native build tool's default number is used.\n" \
+ " The CMAKE_BUILD_PARALLEL_LEVEL environment " \
+ "variable\n" \
+ " specifies a default parallel level when this " \
+ "option\n" \
+ " is not given.\n" \
+ " --target <tgt> = Build <tgt> instead of default targets.\n" \
+ " May only be specified once.\n" \
+ " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
+ " --clean-first = Build target 'clean' first, then build.\n" \
+ " (To clean only, use --target 'clean'.)\n" \
+ " --use-stderr = Ignored. Behavior is default in CMake >= 3.0.\n" \
+ " -- = Pass remaining options to the native tool.\n"
static const char* cmDocumentationOptions[][2] = {
CMAKE_STANDARD_OPTIONS_TABLE,
{ "-N", "View mode only." },
{ "-P <file>", "Process script mode." },
{ "--find-package", "Run in pkg-config like mode." },
- { "--graphviz=[file]", "Generate graphviz of dependencies, see "
- "CMakeGraphVizOptions.cmake for more." },
+ { "--graphviz=[file]",
+ "Generate graphviz of dependencies, see "
+ "CMakeGraphVizOptions.cmake for more." },
{ "--system-information [file]", "Dump information about this system." },
- { "--debug-trycompile", "Do not delete the try_compile build tree. Only "
- "useful on one try_compile at a time." },
+ { "--debug-trycompile",
+ "Do not delete the try_compile build tree. Only "
+ "useful on one try_compile at a time." },
{ "--debug-output", "Put cmake in a debug mode." },
{ "--trace", "Put cmake in trace mode." },
{ "--trace-expand", "Put cmake in trace mode with variable expansion." },
{ "--warn-uninitialized", "Warn about uninitialized values." },
{ "--warn-unused-vars", "Warn about unused variables." },
{ "--no-warn-unused-cli", "Don't warn about command line options." },
- { "--check-system-vars", "Find problems with variable usage in system "
- "files." },
+ { "--check-system-vars",
+ "Find problems with variable usage in system "
+ "files." },
{ nullptr, nullptr }
};
std::cerr << "This cmake does not support --build\n";
return -1;
#else
+ int jobs = cmake::NO_BUILD_PARALLEL_LEVEL;
std::string target;
std::string config = "Debug";
std::string dir;
enum Doing
{
DoingNone,
+ DoingJobs,
DoingDir,
DoingTarget,
DoingConfig,
for (int i = 2; i < ac; ++i) {
if (doing == DoingNative) {
nativeOptions.push_back(av[i]);
+ } else if ((strcmp(av[i], "-j") == 0) ||
+ (strcmp(av[i], "--parallel") == 0)) {
+ jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL;
+ /* does the next argument start with a number? */
+ if ((i + 1 < ac) && (isdigit(*av[i + 1]))) {
+ doing = DoingJobs;
+ }
} else if (strcmp(av[i], "--target") == 0) {
if (!hasTarget) {
doing = DoingTarget;
doing = DoingNative;
} else {
switch (doing) {
+ case DoingJobs: {
+ unsigned long numJobs = 0;
+ if (cmSystemTools::StringToULong(av[i], &numJobs)) {
+ jobs = int(numJobs);
+ doing = DoingNone;
+ } else {
+ std::cerr << "'" << av[i - 1] << "' invalid number '" << av[i]
+ << "' given.\n\n";
+ dir.clear();
+ break;
+ }
+ } break;
case DoingDir:
dir = cmSystemTools::CollapseFullPath(av[i]);
doing = DoingNone;
}
}
}
+
+ if (jobs == cmake::NO_BUILD_PARALLEL_LEVEL) {
+ std::string parallel;
+ if (cmSystemTools::GetEnv("CMAKE_BUILD_PARALLEL_LEVEL", parallel)) {
+ if (parallel.empty()) {
+ jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL;
+ } else {
+ unsigned long numJobs = 0;
+ if (cmSystemTools::StringToULong(parallel.c_str(), &numJobs)) {
+ jobs = int(numJobs);
+ } else {
+ std::cerr << "'CMAKE_BUILD_PARALLEL_LEVEL' environment variable\n"
+ << "invalid number '" << parallel << "' given.\n\n";
+ dir.clear();
+ }
+ }
+ }
+ }
+
if (dir.empty()) {
/* clang-format off */
std::cerr <<
cmake cm(cmake::RoleInternal);
cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm);
cm.SetProgressCallback(cmakemainProgressCallback, &cm);
- return cm.Build(dir, target, config, nativeOptions, clean);
+ return cm.Build(jobs, dir, target, config, nativeOptions, clean);
#endif
}
#include "cmake.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
-#include "cmServer.h"
-#include "cmServerConnection.h"
+# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
+# include "cmServer.h"
+# include "cmServerConnection.h"
#endif
#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32)
-#include "bindexplib.h"
+# include "bindexplib.h"
#endif
#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) && !defined(__CYGWIN__)
-#include "cmVisualStudioWCEPlatformParser.h"
+# include "cmVisualStudioWCEPlatformParser.h"
#endif
#include "cmsys/Directory.hxx"
int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
{
std::vector<CoCompileJob> jobs;
- std::string sourceFile; // store --source=
+ std::string sourceFile; // store --source=
+ std::vector<std::string> launchers; // store --launcher=
// Default is to run the original command found after -- if the option
// does not need to do that, it should be specified here, currently only
}
}
}
- if (cmHasLiteralPrefix(arg, "--source=")) {
- sourceFile = arg.substr(9);
- optionFound = true;
- }
- // if it was not a co-compiler or --source then error
if (!optionFound) {
- std::cerr << "__run_co_compile given unknown argument: " << arg
- << "\n";
- return 1;
+ if (cmHasLiteralPrefix(arg, "--source=")) {
+ sourceFile = arg.substr(9);
+ } else if (cmHasLiteralPrefix(arg, "--launcher=")) {
+ cmSystemTools::ExpandListArgument(arg.substr(11), launchers, true);
+ } else {
+ // if it was not a co-compiler or --source/--launcher then error
+ std::cerr << "__run_co_compile given unknown argument: " << arg
+ << "\n";
+ return 1;
+ }
}
} else { // if not doing_options then push to orig_cmd
orig_cmd.push_back(arg);
return 0;
}
+ // Prepend launcher argument(s), if any
+ if (!launchers.empty()) {
+ orig_cmd.insert(orig_cmd.begin(), launchers.begin(), launchers.end());
+ }
+
// Now run the real compiler command and return its result value
int ret;
if (!cmSystemTools::RunSingleCommand(orig_cmd, nullptr, nullptr, &ret,
// Touch file
if (args[1] == "touch_nocreate" && args.size() > 2) {
for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- // Complain if the file could not be removed, still exists,
- // and the -f option was not given.
if (!cmSystemTools::Touch(args[cc], false)) {
return 1;
}
if (!fout) {
return -1;
}
- fout << this->Type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ "
- "24 /* RT_MANIFEST */ \""
+ fout << this->Type
+ << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ "
+ "24 /* RT_MANIFEST */ \""
<< absManifestFile << "\"";
}
#include "cmsys/Encoding.hxx"
#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmsys/ConsoleBuf.hxx"
+# include "cmsys/ConsoleBuf.hxx"
#endif
#include <iostream>
#include <string.h>
{ "-V,--verbose", "Enable verbose output from tests." },
{ "-VV,--extra-verbose", "Enable more verbose output from tests." },
{ "--debug", "Displaying more verbose internals of CTest." },
- { "--output-on-failure", "Output anything outputted by the test program "
- "if the test should fail." },
- { "--test-output-size-passed <size>", "Limit the output for passed tests "
- "to <size> bytes" },
- { "--test-output-size-failed <size>", "Limit the output for failed tests "
- "to <size> bytes" },
+ { "--output-on-failure",
+ "Output anything outputted by the test program "
+ "if the test should fail." },
+ { "--test-output-size-passed <size>",
+ "Limit the output for passed tests "
+ "to <size> bytes" },
+ { "--test-output-size-failed <size>",
+ "Limit the output for failed tests "
+ "to <size> bytes" },
{ "-F", "Enable failover." },
- { "-j <jobs>, --parallel <jobs>", "Run the tests in parallel using the "
- "given number of jobs." },
+ { "-j <jobs>, --parallel <jobs>",
+ "Run the tests in parallel using the "
+ "given number of jobs." },
{ "-Q,--quiet", "Make ctest quiet." },
{ "-O <file>, --output-log <file>", "Output to log file" },
{ "-N,--show-only", "Disable actual execution of tests." },
- { "-L <regex>, --label-regex <regex>", "Run tests with labels matching "
- "regular expression." },
- { "-R <regex>, --tests-regex <regex>", "Run tests matching regular "
- "expression." },
- { "-E <regex>, --exclude-regex <regex>", "Exclude tests matching regular "
- "expression." },
- { "-LE <regex>, --label-exclude <regex>", "Exclude tests with labels "
- "matching regular expression." },
- { "-FA <regex>, --fixture-exclude-any <regex>", "Do not automatically "
- "add any tests for "
- "fixtures matching "
- "regular expression." },
- { "-FS <regex>, --fixture-exclude-setup <regex>", "Do not automatically "
- "add setup tests for "
- "fixtures matching "
- "regular expression." },
- { "-FC <regex>, --fixture-exclude-cleanup <regex>", "Do not automatically "
- "add cleanup tests for "
- "fixtures matching "
- "regular expression." },
+ { "-L <regex>, --label-regex <regex>",
+ "Run tests with labels matching "
+ "regular expression." },
+ { "-R <regex>, --tests-regex <regex>",
+ "Run tests matching regular "
+ "expression." },
+ { "-E <regex>, --exclude-regex <regex>",
+ "Exclude tests matching regular "
+ "expression." },
+ { "-LE <regex>, --label-exclude <regex>",
+ "Exclude tests with labels "
+ "matching regular expression." },
+ { "-FA <regex>, --fixture-exclude-any <regex>",
+ "Do not automatically "
+ "add any tests for "
+ "fixtures matching "
+ "regular expression." },
+ { "-FS <regex>, --fixture-exclude-setup <regex>",
+ "Do not automatically "
+ "add setup tests for "
+ "fixtures matching "
+ "regular expression." },
+ { "-FC <regex>, --fixture-exclude-cleanup <regex>",
+ "Do not automatically "
+ "add cleanup tests for "
+ "fixtures matching "
+ "regular expression." },
{ "-D <dashboard>, --dashboard <dashboard>", "Execute dashboard test" },
{ "-D <var>:<type>=<value>", "Define a variable for script mode" },
{ "-M <model>, --test-model <model>", "Sets the model for a dashboard" },
- { "-T <action>, --test-action <action>", "Sets the dashboard action to "
- "perform" },
+ { "-T <action>, --test-action <action>",
+ "Sets the dashboard action to "
+ "perform" },
{ "--track <track>", "Specify the track to submit dashboard to" },
- { "-S <script>, --script <script>", "Execute a dashboard for a "
- "configuration" },
- { "-SP <script>, --script-new-process <script>", "Execute a dashboard for a "
- "configuration" },
+ { "-S <script>, --script <script>",
+ "Execute a dashboard for a "
+ "configuration" },
+ { "-SP <script>, --script-new-process <script>",
+ "Execute a dashboard for a "
+ "configuration" },
{ "-A <file>, --add-notes <file>", "Add a notes file with submission" },
{ "-I [Start,End,Stride,test#,test#|Test file], --tests-information",
"Run a specific number of tests by number." },
{ "-U, --union", "Take the Union of -I and -R" },
{ "--rerun-failed", "Run only the tests that failed previously" },
- { "--repeat-until-fail <n>", "Require each test to run <n> "
- "times without failing in order to pass" },
+ { "--repeat-until-fail <n>",
+ "Require each test to run <n> "
+ "times without failing in order to pass" },
{ "--max-width <width>", "Set the max width for a test name to output" },
{ "--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1." },
{ "--no-label-summary", "Disable timing summary information for labels." },
- { "--no-subproject-summary", "Disable timing summary information for "
- "subprojects." },
+ { "--no-subproject-summary",
+ "Disable timing summary information for "
+ "subprojects." },
{ "--build-and-test", "Configure, build and run a test." },
{ "--build-target", "Specify a specific target to build." },
{ "--build-nocmake", "Run the build without running cmake first." },
!(cmSystemTools::FileExists("CTestTestfile.cmake") ||
cmSystemTools::FileExists("DartTestfile.txt"))) {
if (argc == 1) {
- cmCTestLog(&inst, ERROR_MESSAGE, "*********************************"
+ cmCTestLog(&inst, ERROR_MESSAGE,
+ "*********************************"
<< std::endl
<< "No test configuration file found!" << std::endl
<< "*********************************" << std::endl);
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Base64.h.in"
+# include "Base64.h.in"
#endif
static const unsigned char kwsysBase64EncodeTable[65] =
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysBase64 kwsys_ns(Base64)
-#define kwsysBase64_Decode kwsys_ns(Base64_Decode)
-#define kwsysBase64_Decode3 kwsys_ns(Base64_Decode3)
-#define kwsysBase64_Encode kwsys_ns(Base64_Encode)
-#define kwsysBase64_Encode1 kwsys_ns(Base64_Encode1)
-#define kwsysBase64_Encode2 kwsys_ns(Base64_Encode2)
-#define kwsysBase64_Encode3 kwsys_ns(Base64_Encode3)
+# define kwsysBase64 kwsys_ns(Base64)
+# define kwsysBase64_Decode kwsys_ns(Base64_Decode)
+# define kwsysBase64_Decode3 kwsys_ns(Base64_Decode3)
+# define kwsysBase64_Encode kwsys_ns(Base64_Encode)
+# define kwsysBase64_Encode1 kwsys_ns(Base64_Encode1)
+# define kwsysBase64_Encode2 kwsys_ns(Base64_Encode2)
+# define kwsysBase64_Encode3 kwsys_ns(Base64_Encode3)
#endif
#if defined(__cplusplus)
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysBase64
-#undef kwsysBase64_Decode
-#undef kwsysBase64_Decode3
-#undef kwsysBase64_Encode
-#undef kwsysBase64_Encode1
-#undef kwsysBase64_Encode2
-#undef kwsysBase64_Encode3
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysBase64
+# undef kwsysBase64_Decode
+# undef kwsysBase64_Decode3
+# undef kwsysBase64_Encode
+# undef kwsysBase64_Encode1
+# undef kwsysBase64_Encode2
+# undef kwsysBase64_Encode3
+# endif
#endif
#endif
ENDIF()
ENDIF()
+# Choose default shared/static build if not specified.
+IF(NOT DEFINED KWSYS_BUILD_SHARED)
+ SET(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS})
+ENDIF()
+
# Include helper macros.
INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake)
INCLUDE(CheckTypeSize)
# Setup library install rules.
SET(KWSYS_INSTALL_LIBRARY_RULE)
+SET(KWSYS_INSTALL_NAMELINK_RULE)
IF(KWSYS_INSTALL_LIB_DIR)
IF(KWSYS_INSTALL_EXPORT_NAME)
LIST(APPEND KWSYS_INSTALL_LIBRARY_RULE EXPORT ${KWSYS_INSTALL_EXPORT_NAME})
ENDIF()
# Install the shared library to the lib directory.
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
- LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR}
+ LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR} NAMELINK_SKIP
)
# Assign the shared library to the runtime component.
IF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME)
COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME}
)
ENDIF()
+ IF(KWSYS_BUILD_SHARED)
+ SET(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE}
+ LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR} NAMELINK_ONLY
+ )
+ # Assign the namelink to the development component.
+ IF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT)
+ SET(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE}
+ COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT}
+ )
+ ENDIF()
+ ENDIF()
# Install the archive to the lib directory.
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
SET(KWSYS_NAME_IS_KWSYS 0)
ENDIF()
-# Choose default shared/static build if not specified.
-IF(KWSYS_BUILD_SHARED MATCHES "^KWSYS_BUILD_SHARED$")
- SET(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS})
-ENDIF()
-
IF(KWSYS_BUILD_SHARED)
SET(KWSYS_BUILD_SHARED 1)
SET(KWSYS_LIBRARY_TYPE SHARED)
IF(KWSYS_INSTALL_LIBRARY_RULE)
INSTALL(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_LIBRARY_RULE})
ENDIF()
+ IF(KWSYS_INSTALL_NAMELINK_RULE)
+ INSTALL(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_NAMELINK_RULE})
+ ENDIF()
ENDIF()
# Add a C-only library if requested.
Code Style
==========
-We use `clang-format`_ version **3.8** to define our style for C++ code in
+We use `clang-format`_ version **6.0** to define our style for C++ code in
the KWSys source tree. See the `.clang-format`_ configuration file for
our style settings. Use the `clang-format.bash`_ script to format source
code. It automatically runs ``clang-format`` on the set of source files
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "CommandLineArguments.hxx.in"
-#include "Configure.hxx.in"
-#include "String.hxx.in"
+# include "CommandLineArguments.hxx.in"
+# include "Configure.hxx.in"
+# include "String.hxx.in"
#endif
#include <iostream>
#include <string.h>
#ifdef _MSC_VER
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 1375 /* base class destructor not virtual */
+# pragma set woff 1375 /* base class destructor not virtual */
#endif
#if 0
-#define CommandLineArguments_DEBUG(x) \
- std::cout << __LINE__ << " CLA: " << x << std::endl
+# define CommandLineArguments_DEBUG(x) \
+ std::cout << __LINE__ << " CLA: " << x << std::endl
#else
-#define CommandLineArguments_DEBUG(x)
+# define CommandLineArguments_DEBUG(x)
#endif
namespace KWSYS_NAMESPACE {
namespace. When not building a kwsys source file these macros are
temporarily defined inside the headers that use them. */
#if defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
/* Disable some warnings inside kwsys source files. */
#if defined(KWSYS_NAMESPACE)
-#if defined(__BORLANDC__)
-#pragma warn - 8027 /* function not inlined. */
-#endif
-#if defined(__INTEL_COMPILER)
-#pragma warning(disable : 1572) /* floating-point equality test */
-#endif
-#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 3970 /* pointer to int conversion */
-#pragma set woff 3968 /* 64 bit conversion */
-#endif
+# if defined(__BORLANDC__)
+# pragma warn - 8027 /* function not inlined. */
+# endif
+# if defined(__INTEL_COMPILER)
+# pragma warning(disable : 1572) /* floating-point equality test */
+# endif
+# if defined(__sgi) && !defined(__GNUC__)
+# pragma set woff 3970 /* pointer to int conversion */
+# pragma set woff 3968 /* 64 bit conversion */
+# endif
#endif
/* Whether kwsys namespace is "kwsys". */
/* Whether Large File Support is available. */
#if @KWSYS_NAMESPACE@_LFS_REQUESTED
-#define @KWSYS_NAMESPACE@_LFS_AVAILABLE @KWSYS_LFS_AVAILABLE@
+# define @KWSYS_NAMESPACE@_LFS_AVAILABLE @KWSYS_LFS_AVAILABLE@
#endif
/* Setup Large File Support if requested. */
#if @KWSYS_NAMESPACE@_LFS_REQUESTED
/* Since LFS is requested this header must be included before system
headers whether or not LFS is available. */
-#if 0 && (defined(_SYS_TYPES_H) || defined(_SYS_TYPES_INCLUDED))
-#error "@KWSYS_NAMESPACE@/Configure.h must be included before sys/types.h"
-#endif
+# if 0 && (defined(_SYS_TYPES_H) || defined(_SYS_TYPES_INCLUDED))
+# error "@KWSYS_NAMESPACE@/Configure.h must be included before sys/types.h"
+# endif
/* Enable the large file API if it is available. */
-#if @KWSYS_NAMESPACE@_LFS_AVAILABLE && \
- !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINES)
-#if !defined(_LARGEFILE_SOURCE) && \
- !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGEFILE_SOURCE)
-#define _LARGEFILE_SOURCE
-#endif
-#if !defined(_LARGEFILE64_SOURCE) && \
- !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGEFILE64_SOURCE)
-#define _LARGEFILE64_SOURCE
-#endif
-#if !defined(_LARGE_FILES) && \
- !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGE_FILES)
-#define _LARGE_FILES
-#endif
-#if !defined(_FILE_OFFSET_BITS) && \
- !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_FILE_OFFSET_BITS)
-#define _FILE_OFFSET_BITS 64
-#endif
-#endif
+# if @KWSYS_NAMESPACE@_LFS_AVAILABLE && \
+ !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINES)
+# if !defined(_LARGEFILE_SOURCE) && \
+ !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGEFILE_SOURCE)
+# define _LARGEFILE_SOURCE
+# endif
+# if !defined(_LARGEFILE64_SOURCE) && \
+ !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGEFILE64_SOURCE)
+# define _LARGEFILE64_SOURCE
+# endif
+# if !defined(_LARGE_FILES) && \
+ !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGE_FILES)
+# define _LARGE_FILES
+# endif
+# if !defined(_FILE_OFFSET_BITS) && \
+ !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_FILE_OFFSET_BITS)
+# define _FILE_OFFSET_BITS 64
+# endif
+# endif
#endif
/* Setup the export macro. */
#if @KWSYS_BUILD_SHARED@
-#if defined(_WIN32) || defined(__CYGWIN__)
-#if defined(@KWSYS_NAMESPACE@_EXPORTS)
-#define @KWSYS_NAMESPACE@_EXPORT __declspec(dllexport)
+# if defined(_WIN32) || defined(__CYGWIN__)
+# if defined(@KWSYS_NAMESPACE@_EXPORTS)
+# define @KWSYS_NAMESPACE@_EXPORT __declspec(dllexport)
+# else
+# define @KWSYS_NAMESPACE@_EXPORT __declspec(dllimport)
+# endif
+# elif __GNUC__ >= 4
+# define @KWSYS_NAMESPACE@_EXPORT __attribute__((visibility("default")))
+# else
+# define @KWSYS_NAMESPACE@_EXPORT
+# endif
#else
-#define @KWSYS_NAMESPACE@_EXPORT __declspec(dllimport)
-#endif
-#elif __GNUC__ >= 4
-#define @KWSYS_NAMESPACE@_EXPORT __attribute__((visibility("default")))
-#else
-#define @KWSYS_NAMESPACE@_EXPORT
-#endif
-#else
-#define @KWSYS_NAMESPACE@_EXPORT
+# define @KWSYS_NAMESPACE@_EXPORT
#endif
/* Enable warnings that are off by default but are useful. */
#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_ENABLE)
-#if defined(_MSC_VER)
-#pragma warning(default : 4263) /* no override, call convention differs */
-#endif
+# if defined(_MSC_VER)
+# pragma warning(default : 4263) /* no override, call convention differs \
+ */
+# endif
#endif
/* Disable warnings that are on by default but occur in valid code. */
#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_DISABLE)
-#if defined(_MSC_VER)
-#pragma warning(disable : 4097) /* typedef is synonym for class */
-#pragma warning(disable : 4127) /* conditional expression is constant */
-#pragma warning(disable : 4244) /* possible loss in conversion */
-#pragma warning(disable : 4251) /* missing DLL-interface */
-#pragma warning(disable : 4305) /* truncation from type1 to type2 */
-#pragma warning(disable : 4309) /* truncation of constant value */
-#pragma warning(disable : 4514) /* unreferenced inline function */
-#pragma warning(disable : 4706) /* assignment in conditional expression */
-#pragma warning(disable : 4710) /* function not inlined */
-#pragma warning(disable : 4786) /* identifier truncated in debug info */
-#endif
-#if defined(__BORLANDC__) && !defined(__cplusplus)
+# if defined(_MSC_VER)
+# pragma warning(disable : 4097) /* typedef is synonym for class */
+# pragma warning(disable : 4127) /* conditional expression is constant */
+# pragma warning(disable : 4244) /* possible loss in conversion */
+# pragma warning(disable : 4251) /* missing DLL-interface */
+# pragma warning(disable : 4305) /* truncation from type1 to type2 */
+# pragma warning(disable : 4309) /* truncation of constant value */
+# pragma warning(disable : 4514) /* unreferenced inline function */
+# pragma warning(disable : 4706) /* assignment in conditional expression \
+ */
+# pragma warning(disable : 4710) /* function not inlined */
+# pragma warning(disable : 4786) /* identifier truncated in debug info */
+# endif
+# if defined(__BORLANDC__) && !defined(__cplusplus)
/* Code has no effect; raised by winnt.h in C (not C++) when ignoring an
unused parameter using "(param)" syntax (i.e. no cast to void). */
-#pragma warn - 8019
-#endif
+# pragma warn - 8019
+# endif
#endif
/* MSVC 6.0 in release mode will warn about code it produces with its
configuration. Real warnings will be revealed by a debug build or
by other compilers. */
#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_DISABLE_BOGUS)
-#if defined(_MSC_VER) && (_MSC_VER < 1300) && defined(NDEBUG)
-#pragma warning(disable : 4701) /* Variable may be used uninitialized. */
-#pragma warning(disable : 4702) /* Unreachable code. */
-#endif
+# if defined(_MSC_VER) && (_MSC_VER < 1300) && defined(NDEBUG)
+# pragma warning(disable : 4701) /* Variable may be used uninitialized. */
+# pragma warning(disable : 4702) /* Unreachable code. */
+# endif
#endif
#endif
@KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H@
#if defined(__SUNPRO_CC) && __SUNPRO_CC > 0x5130 && defined(__has_attribute)
-#define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_attribute(x)
+# define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_attribute(x)
#elif defined(__has_cpp_attribute)
-#define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_cpp_attribute(x)
+# define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_cpp_attribute(x)
#else
-#define @KWSYS_NAMESPACE@__has_cpp_attribute(x) 0
+# define @KWSYS_NAMESPACE@__has_cpp_attribute(x) 0
#endif
#if __cplusplus >= 201103L
-#define @KWSYS_NAMESPACE@_NULLPTR nullptr
+# define @KWSYS_NAMESPACE@_NULLPTR nullptr
#else
-#define @KWSYS_NAMESPACE@_NULLPTR 0
+# define @KWSYS_NAMESPACE@_NULLPTR 0
#endif
#ifndef @KWSYS_NAMESPACE@_FALLTHROUGH
-#if __cplusplus >= 201703L && @KWSYS_NAMESPACE@__has_cpp_attribute(fallthrough)
-#define @KWSYS_NAMESPACE@_FALLTHROUGH [[fallthrough]]
-#elif __cplusplus >= 201103L && \
- @KWSYS_NAMESPACE@__has_cpp_attribute(gnu::fallthrough)
-#define @KWSYS_NAMESPACE@_FALLTHROUGH [[gnu::fallthrough]]
-#elif __cplusplus >= 201103L && \
- @KWSYS_NAMESPACE@__has_cpp_attribute(clang::fallthrough)
-#define @KWSYS_NAMESPACE@_FALLTHROUGH [[clang::fallthrough]]
-#endif
+# if __cplusplus >= 201703L && \
+ @KWSYS_NAMESPACE@__has_cpp_attribute(fallthrough)
+# define @KWSYS_NAMESPACE@_FALLTHROUGH [[fallthrough]]
+# elif __cplusplus >= 201103L && \
+ @KWSYS_NAMESPACE@__has_cpp_attribute(gnu::fallthrough)
+# define @KWSYS_NAMESPACE@_FALLTHROUGH [[gnu::fallthrough]]
+# elif __cplusplus >= 201103L && \
+ @KWSYS_NAMESPACE@__has_cpp_attribute(clang::fallthrough)
+# define @KWSYS_NAMESPACE@_FALLTHROUGH [[clang::fallthrough]]
+# endif
#endif
#ifndef @KWSYS_NAMESPACE@_FALLTHROUGH
-#define @KWSYS_NAMESPACE@_FALLTHROUGH static_cast<void>(0)
+# define @KWSYS_NAMESPACE@_FALLTHROUGH static_cast<void>(0)
#endif
#undef @KWSYS_NAMESPACE@__has_cpp_attribute
/* If building a C++ file in kwsys itself, give the source file
access to the macros without a configured namespace. */
#if defined(KWSYS_NAMESPACE)
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsys @KWSYS_NAMESPACE@
-#endif
-#define KWSYS_NAME_IS_KWSYS @KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define KWSYS_STL_HAS_WSTRING @KWSYS_NAMESPACE@_STL_HAS_WSTRING
-#define KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H \
- @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
-#define KWSYS_FALLTHROUGH @KWSYS_NAMESPACE@_FALLTHROUGH
-#define KWSYS_NULLPTR @KWSYS_NAMESPACE@_NULLPTR
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# define kwsys @KWSYS_NAMESPACE@
+# endif
+# define KWSYS_NAME_IS_KWSYS @KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# define KWSYS_STL_HAS_WSTRING @KWSYS_NAMESPACE@_STL_HAS_WSTRING
+# define KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H \
+ @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
+# define KWSYS_FALLTHROUGH @KWSYS_NAMESPACE@_FALLTHROUGH
+# define KWSYS_NULLPTR @KWSYS_NAMESPACE@_NULLPTR
#endif
#endif
#include <string>
#if defined(_WIN32)
-#include <windows.h>
-#if __cplusplus >= 201103L
-#include <system_error>
-#endif
+# include <windows.h>
+# if __cplusplus >= 201103L
+# include <system_error>
+# endif
#endif
namespace @KWSYS_NAMESPACE@ {
(!input && m_hOutput == INVALID_HANDLE_VALUE)) {
std::string errmsg =
"GetStdHandle(" + handleName + ") returned INVALID_HANDLE_VALUE";
-#if __cplusplus >= 201103L
+# if __cplusplus >= 201103L
throw std::system_error(::GetLastError(), std::system_category(),
errmsg);
-#else
+# else
throw std::runtime_error(errmsg);
-#endif
+# endif
}
}
UINT getConsolesCodepage()
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Configure.hxx.in"
-#include "Directory.hxx.in"
-#include "Encoding.hxx.in"
+# include "Configure.hxx.in"
+# include "Directory.hxx.in"
+# include "Encoding.hxx.in"
#endif
#include <string>
// First Windows platforms
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# include <windows.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <io.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
+# include <ctype.h>
+# include <fcntl.h>
+# include <io.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/stat.h>
+# include <sys/types.h>
// Wide function names can vary depending on compiler:
-#ifdef __BORLANDC__
-#define _wfindfirst_func __wfindfirst
-#define _wfindnext_func __wfindnext
-#else
-#define _wfindfirst_func _wfindfirst
-#define _wfindnext_func _wfindnext
-#endif
+# ifdef __BORLANDC__
+# define _wfindfirst_func __wfindfirst
+# define _wfindnext_func __wfindnext
+# else
+# define _wfindfirst_func _wfindfirst
+# define _wfindnext_func _wfindnext
+# endif
namespace KWSYS_NAMESPACE {
bool Directory::Load(const std::string& name)
{
this->Clear();
-#if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
+# if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
// Older Visual C++ and Embarcadero compilers.
long srchHandle;
-#else // Newer Visual C++
+# else // Newer Visual C++
intptr_t srchHandle;
-#endif
+# endif
char* buf;
size_t n = name.size();
if (*name.rbegin() == '/' || *name.rbegin() == '\\') {
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
{
-#if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
+# if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
// Older Visual C++ and Embarcadero compilers.
long srchHandle;
-#else // Newer Visual C++
+# else // Newer Visual C++
intptr_t srchHandle;
-#endif
+# endif
char* buf;
size_t n = name.size();
if (*name.rbegin() == '/') {
// Now the POSIX style directory access
-#include <sys/types.h>
+# include <sys/types.h>
-#include <dirent.h>
+# include <dirent.h>
// PGI with glibc has trouble with dirent and large file support:
// http://www.pgroup.com/userforum/viewtopic.php?
// p=1992&sid=f16167f51964f1a68fe5041b8eb213b6
// Work around the problem by mapping dirent the same way as readdir.
-#if defined(__PGI) && defined(__GLIBC__)
-#define kwsys_dirent_readdir dirent
-#define kwsys_dirent_readdir64 dirent64
-#define kwsys_dirent kwsys_dirent_lookup(readdir)
-#define kwsys_dirent_lookup(x) kwsys_dirent_lookup_delay(x)
-#define kwsys_dirent_lookup_delay(x) kwsys_dirent_##x
-#else
-#define kwsys_dirent dirent
-#endif
+# if defined(__PGI) && defined(__GLIBC__)
+# define kwsys_dirent_readdir dirent
+# define kwsys_dirent_readdir64 dirent64
+# define kwsys_dirent kwsys_dirent_lookup(readdir)
+# define kwsys_dirent_lookup(x) kwsys_dirent_lookup_delay(x)
+# define kwsys_dirent_lookup_delay(x) kwsys_dirent_##x
+# else
+# define kwsys_dirent dirent
+# endif
namespace KWSYS_NAMESPACE {
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Configure.hxx.in"
-#include "DynamicLoader.hxx.in"
+# include "Configure.hxx.in"
+# include "DynamicLoader.hxx.in"
#endif
// This file actually contains several different implementations:
#if !KWSYS_SUPPORTS_SHARED_LIBS
// Implementation for environments without dynamic libs
-#include <string.h> // for strerror()
+# include <string.h> // for strerror()
namespace KWSYS_NAMESPACE {
#elif defined(__hpux)
// Implementation for HPUX machines
-#include <dl.h>
-#include <errno.h>
+# include <dl.h>
+# include <errno.h>
namespace KWSYS_NAMESPACE {
#elif defined(__APPLE__) && (MAC_OS_X_VERSION_MAX_ALLOWED < 1030)
// Implementation for Mac OS X 10.2.x and earlier
-#include <mach-o/dyld.h>
-#include <string.h> // for strlen
+# include <mach-o/dyld.h>
+# include <string.h> // for strlen
namespace KWSYS_NAMESPACE {
if (rc != NSObjectFileImageSuccess) {
return 0;
}
- NSModule handle =
- NSLinkModule(image, libname.c_str(), NSLINKMODULE_OPTION_BINDNOW |
- NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+ NSModule handle = NSLinkModule(image, libname.c_str(),
+ NSLINKMODULE_OPTION_BINDNOW |
+ NSLINKMODULE_OPTION_RETURN_ON_ERROR);
NSDestroyObjectFileImage(image);
return handle;
}
#elif defined(_WIN32) && !defined(__CYGWIN__)
// Implementation for Windows win32 code but not cygwin
-#include <windows.h>
+# include <windows.h>
namespace KWSYS_NAMESPACE {
// Note that the "@X" part of the name above is the total size (in
// bytes) of the arguments on the stack.
void* result;
-#if defined(__BORLANDC__) || defined(__WATCOMC__)
+# if defined(__BORLANDC__) || defined(__WATCOMC__)
// Need to prepend symbols with '_'
std::string ssym = '_' + sym;
const char* rsym = ssym.c_str();
-#else
+# else
const char* rsym = sym.c_str();
-#endif
+# endif
result = (void*)GetProcAddress(lib, rsym);
// Hack to cast pointer-to-data to pointer-to-function.
-#ifdef __WATCOMC__
+# ifdef __WATCOMC__
return *(DynamicLoader::SymbolPointer*)(&result);
-#else
+# else
return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
-#endif
+# endif
}
const char* DynamicLoader::LastError()
#elif defined(__BEOS__)
// Implementation for BeOS / Haiku
-#include <string.h> // for strerror()
+# include <string.h> // for strerror()
-#include <be/kernel/image.h>
-#include <be/support/Errors.h>
+# include <be/kernel/image.h>
+# include <be/support/Errors.h>
namespace KWSYS_NAMESPACE {
#elif defined(__MINT__)
// Implementation for FreeMiNT on Atari
-#define _GNU_SOURCE /* for program_invocation_name */
-#include <dld.h>
-#include <errno.h>
-#include <malloc.h>
-#include <string.h>
+# define _GNU_SOURCE /* for program_invocation_name */
+# include <dld.h>
+# include <errno.h>
+# include <malloc.h>
+# include <string.h>
namespace KWSYS_NAMESPACE {
#else
// Default implementation for *NIX systems (including Mac OS X 10.3 and
// later) which use dlopen
-#include <dlfcn.h>
+# include <dlfcn.h>
namespace KWSYS_NAMESPACE {
#include <string>
#if defined(__hpux)
-#include <dl.h>
+# include <dl.h>
#elif defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# include <windows.h>
#elif defined(__APPLE__)
-#include <AvailabilityMacros.h>
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
-#include <mach-o/dyld.h>
-#endif
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+# include <mach-o/dyld.h>
+# endif
#elif defined(__BEOS__)
-#include <be/kernel/image.h>
+# include <be/kernel/image.h>
#endif
namespace @KWSYS_NAMESPACE@ {
#elif defined(_WIN32) && !defined(__CYGWIN__)
typedef HMODULE LibraryHandle;
#elif defined(__APPLE__)
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
typedef NSModule LibraryHandle;
-#else
+# else
typedef void* LibraryHandle;
-#endif
+# endif
#elif defined(__BEOS__)
typedef image_id LibraryHandle;
#else // POSIX
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysEncoding kwsys_ns(Encoding)
-#define kwsysEncoding_mbstowcs kwsys_ns(Encoding_mbstowcs)
-#define kwsysEncoding_DupToWide kwsys_ns(Encoding_DupToWide)
-#define kwsysEncoding_wcstombs kwsys_ns(Encoding_wcstombs)
-#define kwsysEncoding_DupToNarrow kwsys_ns(Encoding_DupToNarrow)
+# define kwsysEncoding kwsys_ns(Encoding)
+# define kwsysEncoding_mbstowcs kwsys_ns(Encoding_mbstowcs)
+# define kwsysEncoding_DupToWide kwsys_ns(Encoding_DupToWide)
+# define kwsysEncoding_wcstombs kwsys_ns(Encoding_wcstombs)
+# define kwsysEncoding_DupToNarrow kwsys_ns(Encoding_DupToNarrow)
#endif
#if defined(__cplusplus)
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysEncoding
-#undef kwsysEncoding_mbstowcs
-#undef kwsysEncoding_DupToWide
-#undef kwsysEncoding_wcstombs
-#undef kwsysEncoding_DupToNarrow
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysEncoding
+# undef kwsysEncoding_mbstowcs
+# undef kwsysEncoding_DupToWide
+# undef kwsysEncoding_wcstombs
+# undef kwsysEncoding_DupToNarrow
+# endif
#endif
#endif
std::vector<char*> argv_;
};
-/**
- * Convert between char and wchar_t
- */
+ /**
+ * Convert between char and wchar_t
+ */
#if @KWSYS_NAMESPACE@_STL_HAS_WSTRING
static std::string ToNarrow(const std::wstring& str);
static std::string ToNarrow(const wchar_t* str);
-#if defined(_WIN32)
+# if defined(_WIN32)
/**
* Convert the path to an extended length path to avoid MAX_PATH length
* limitations on Windows. If the input is a local path the result will be
* absolute paths with Windows-style backslashes.
**/
static std::wstring ToWindowsExtendedPath(std::string const&);
-#endif
+# endif
#endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Encoding.h.in"
+# include "Encoding.h.in"
#endif
#include <stdlib.h>
#ifdef _WIN32
-#include <windows.h>
+# include <windows.h>
#endif
size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* str, size_t n)
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef __osf__
-#define _OSF_SOURCE
-#define _POSIX_C_SOURCE 199506L
-#define _XOPEN_SOURCE_EXTENDED
+# define _OSF_SOURCE
+# define _POSIX_C_SOURCE 199506L
+# define _XOPEN_SOURCE_EXTENDED
#endif
#include "kwsysPrivate.h"
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Encoding.h.in"
-#include "Encoding.hxx.in"
+# include "Encoding.h.in"
+# include "Encoding.hxx.in"
#endif
#include <stdlib.h>
#include <vector>
#ifdef _MSC_VER
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
// Windows API.
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
-#include <ctype.h>
-#include <shellapi.h>
+# include <ctype.h>
+# include <shellapi.h>
#endif
namespace KWSYS_NAMESPACE {
std::wstring Encoding::ToWide(const std::string& str)
{
std::wstring wstr;
-#if defined(_WIN32)
+# if defined(_WIN32)
const int wlength = MultiByteToWideChar(
KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(), int(str.size()), NULL, 0);
if (wlength > 0) {
}
delete[] wdata;
}
-#else
+# else
size_t pos = 0;
size_t nullPos = 0;
do {
wstr += wchar_t('\0');
}
} while (nullPos != std::string::npos);
-#endif
+# endif
return wstr;
}
std::string Encoding::ToNarrow(const std::wstring& str)
{
std::string nstr;
-#if defined(_WIN32)
+# if defined(_WIN32)
int length =
WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
int(str.size()), NULL, 0, NULL, NULL);
}
delete[] data;
}
-#else
+# else
size_t pos = 0;
size_t nullPos = 0;
do {
nstr += '\0';
}
} while (nullPos != std::string::npos);
-#endif
+# endif
return nstr;
}
return str;
}
-#if defined(_WIN32)
+# if defined(_WIN32)
// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
{
// unchanged
return Encoding::ToWide(source);
}
-#endif
+# endif
#endif // KWSYS_STL_HAS_WSTRING
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "FStream.hxx.in"
+# include "FStream.hxx.in"
#endif
namespace KWSYS_NAMESPACE {
#include <fstream>
#if defined(_WIN32)
-#if !defined(_MSC_VER) && @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
-#include <ext/stdio_filebuf.h>
-#endif
+# if !defined(_MSC_VER) && @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
+# include <ext/stdio_filebuf.h>
+# endif
#endif
namespace @KWSYS_NAMESPACE@ {
#if defined(_WIN32) && \
(defined(_MSC_VER) || @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H)
-#if defined(_NOEXCEPT)
-#define @KWSYS_NAMESPACE@_FStream_NOEXCEPT _NOEXCEPT
-#else
-#define @KWSYS_NAMESPACE@_FStream_NOEXCEPT
-#endif
+# if defined(_NOEXCEPT)
+# define @KWSYS_NAMESPACE@_FStream_NOEXCEPT _NOEXCEPT
+# else
+# define @KWSYS_NAMESPACE@_FStream_NOEXCEPT
+# endif
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
template <typename CharType, typename Traits>
class basic_filebuf : public std::basic_filebuf<CharType, Traits>
{
-#if _MSC_VER >= 1400
+# if _MSC_VER >= 1400
public:
typedef std::basic_filebuf<CharType, Traits> my_base_type;
basic_filebuf* open(char const* s, std::ios_base::openmode mode)
const std::wstring wstr = Encoding::ToWindowsExtendedPath(s);
return static_cast<basic_filebuf*>(my_base_type::open(wstr.c_str(), mode));
}
-#endif
+# endif
};
-#else
+# else
inline std::wstring getcmode(const std::ios_base::openmode mode)
{
return cmode;
};
-#endif
+# endif
template <typename CharType, typename Traits = std::char_traits<CharType> >
class basic_efilebuf
{
public:
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
typedef basic_filebuf<CharType, Traits> internal_buffer_type;
-#else
+# else
typedef __gnu_cxx::stdio_filebuf<CharType, Traits> internal_buffer_type;
-#endif
+# endif
basic_efilebuf()
: file_(0)
if (is_open() || file_) {
return false;
}
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
const bool success = buf_->open(file_name, mode) != 0;
-#else
+# else
const std::wstring wstr = Encoding::ToWindowsExtendedPath(file_name);
bool success = false;
std::wstring cmode = getcmode(mode);
buf_ = new internal_buffer_type(file_, mode);
success = true;
}
-#endif
+# endif
return success;
}
bool success = false;
if (buf_) {
success = buf_->close() != 0;
-#if !defined(_MSC_VER)
+# if !defined(_MSC_VER)
if (file_) {
success = fclose(file_) == 0 ? success : false;
file_ = 0;
}
-#endif
+# endif
}
return success;
}
static void _set_state(bool success, std::basic_ios<CharType, Traits>* ios,
basic_efilebuf* efilebuf)
{
-#if !defined(_MSC_VER)
+# if !defined(_MSC_VER)
ios->rdbuf(efilebuf->buf_);
-#else
+# else
static_cast<void>(efilebuf);
-#endif
+# endif
if (!success) {
ios->setstate(std::ios_base::failbit);
} else {
};
template <typename CharType, typename Traits = std::char_traits<CharType> >
-class basic_ifstream : public std::basic_istream<CharType, Traits>,
- public basic_efilebuf<CharType, Traits>
+class basic_ifstream
+ : public std::basic_istream<CharType, Traits>
+ , public basic_efilebuf<CharType, Traits>
{
public:
typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
};
template <typename CharType, typename Traits = std::char_traits<CharType> >
-class basic_ofstream : public std::basic_ostream<CharType, Traits>,
- public basic_efilebuf<CharType, Traits>
+class basic_ofstream
+ : public std::basic_ostream<CharType, Traits>
+ , public basic_efilebuf<CharType, Traits>
{
using basic_efilebuf<CharType, Traits>::is_open;
typedef basic_ifstream<char> ifstream;
typedef basic_ofstream<char> ofstream;
-#undef @KWSYS_NAMESPACE@_FStream_NOEXCEPT
+# undef @KWSYS_NAMESPACE@_FStream_NOEXCEPT
#else
using std::ofstream;
using std::ifstream;
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Configure.hxx.in"
-#include "Directory.hxx.in"
-#include "Glob.hxx.in"
-#include "RegularExpression.hxx.in"
-#include "SystemTools.hxx.in"
+# include "Configure.hxx.in"
+# include "Directory.hxx.in"
+# include "Glob.hxx.in"
+# include "RegularExpression.hxx.in"
+# include "SystemTools.hxx.in"
#endif
#include <algorithm>
namespace KWSYS_NAMESPACE {
#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
// On Windows and Apple, no difference between lower and upper case
-#define KWSYS_GLOB_CASE_INDEPENDENT
+# define KWSYS_GLOB_CASE_INDEPENDENT
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
// Handle network paths
-#define KWSYS_GLOB_SUPPORT_NETWORK_PATHS
+# define KWSYS_GLOB_SUPPORT_NETWORK_PATHS
#endif
class GlobInternals
if (!realPathErrorMessage.empty()) {
if (messages) {
- messages->push_back(Message(
- Glob::error, "Canonical path generation from path '" + dir +
- "' failed! Reason: '" + realPathErrorMessage + "'"));
+ messages->push_back(
+ Message(Glob::error,
+ "Canonical path generation from path '" + dir +
+ "' failed! Reason: '" + realPathErrorMessage + "'"));
}
return false;
}
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Configure.hxx.in"
-#include "IOStream.hxx.in"
+# include "Configure.hxx.in"
+# include "IOStream.hxx.in"
#endif
// Implement the rest of this file only if it is needed.
#if KWSYS_IOS_NEED_OPERATORS_LL
-#include <stdio.h> // sscanf, sprintf
-#include <string.h> // memchr
+# include <stdio.h> // sscanf, sprintf
+# include <string.h> // memchr
-#if defined(_MAX_INT_DIG)
-#define KWSYS_IOS_INT64_MAX_DIG _MAX_INT_DIG
-#else
-#define KWSYS_IOS_INT64_MAX_DIG 32
-#endif
+# if defined(_MAX_INT_DIG)
+# define KWSYS_IOS_INT64_MAX_DIG _MAX_INT_DIG
+# else
+# define KWSYS_IOS_INT64_MAX_DIG 32
+# endif
namespace KWSYS_NAMESPACE {
try {
// Copy the string to a buffer and construct the format string.
char buffer[KWSYS_IOS_INT64_MAX_DIG];
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
char format[] = "%I64_";
const int typeIndex = 4;
-#else
+# else
char format[] = "%ll_";
const int typeIndex = 3;
-#endif
+# endif
switch (IOStreamScanStream(is, buffer)) {
case 8:
format[typeIndex] = 'o';
if (os.flags() & std::ios_base::showbase) {
*f++ = '#';
}
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
*f++ = 'I';
*f++ = '6';
*f++ = '4';
-#else
+# else
*f++ = 'l';
*f++ = 'l';
-#endif
+# endif
long bflags = os.flags() & std::ios_base::basefield;
if (bflags == std::ios_base::oct) {
*f++ = 'o';
return os;
}
-#if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG
+# if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG
// Implement input stream operator for IOStreamSLL.
std::istream& IOStreamScan(std::istream& is, IOStreamSLL& value)
{
{
return IOStreamScanTemplate(is, value, 'u');
}
-#endif
+# endif
-#if !KWSYS_IOS_HAS_OSTREAM_LONG_LONG
+# if !KWSYS_IOS_HAS_OSTREAM_LONG_LONG
// Implement output stream operator for IOStreamSLL.
std::ostream& IOStreamPrint(std::ostream& os, IOStreamSLL value)
{
{
return IOStreamPrintTemplate(os, value, 'u');
}
-#endif
+# endif
} // namespace KWSYS_NAMESPACE
/* Define these macros temporarily to keep the code readable. */
#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
/* Whether istream supports long long. */
/* Determine whether we need to define the streaming operators for
long long or __int64. */
#if @KWSYS_USE_LONG_LONG@
-#if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG || \
- !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
-#define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
+# if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG || \
+ !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
+# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
namespace @KWSYS_NAMESPACE@ {
typedef long long IOStreamSLL;
typedef unsigned long long IOStreamULL;
}
-#endif
+# endif
#elif defined(_MSC_VER) && _MSC_VER < 1300
-#define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
+# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
namespace @KWSYS_NAMESPACE@ {
typedef __int64 IOStreamSLL;
typedef unsigned __int64 IOStreamULL;
}
#endif
#if !defined(@KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL)
-#define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 0
+# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 0
#endif
#if @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL
-#if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
+# if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
/* Input stream operator implementation functions. */
namespace @KWSYS_NAMESPACE@ {
}
/* Provide input stream operator for long long. */
-#if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_LONG_LONG) && \
- !defined(KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED)
-#define KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED
-#define @KWSYS_NAMESPACE@_IOS_ISTREAM_LONG_LONG_DEFINED
+# if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_LONG_LONG) && \
+ !defined(KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED)
+# define KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED
+# define @KWSYS_NAMESPACE@_IOS_ISTREAM_LONG_LONG_DEFINED
inline std::istream& operator>>(std::istream& is,
@KWSYS_NAMESPACE@::IOStreamSLL& value)
{
return @KWSYS_NAMESPACE@::IOStreamScan(is, value);
}
-#endif
+# endif
/* Provide input stream operator for unsigned long long. */
-#if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_UNSIGNED_LONG_LONG) && \
- !defined(KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED)
-#define KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED
-#define @KWSYS_NAMESPACE@_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED
+# if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_UNSIGNED_LONG_LONG) && \
+ !defined(KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED)
+# define KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED
+# define @KWSYS_NAMESPACE@_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED
inline std::istream& operator>>(std::istream& is,
@KWSYS_NAMESPACE@::IOStreamULL& value)
{
return @KWSYS_NAMESPACE@::IOStreamScan(is, value);
}
-#endif
-#endif /* !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG */
+# endif
+# endif /* !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG */
-#if !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
+# if !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
/* Output stream operator implementation functions. */
namespace @KWSYS_NAMESPACE@ {
}
/* Provide output stream operator for long long. */
-#if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_LONG_LONG) && \
- !defined(KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED)
-#define KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED
-#define @KWSYS_NAMESPACE@_IOS_OSTREAM_LONG_LONG_DEFINED
+# if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_LONG_LONG) && \
+ !defined(KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED)
+# define KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED
+# define @KWSYS_NAMESPACE@_IOS_OSTREAM_LONG_LONG_DEFINED
inline std::ostream& operator<<(std::ostream& os,
@KWSYS_NAMESPACE@::IOStreamSLL value)
{
return @KWSYS_NAMESPACE@::IOStreamPrint(os, value);
}
-#endif
+# endif
/* Provide output stream operator for unsigned long long. */
-#if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_UNSIGNED_LONG_LONG) && \
- !defined(KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED)
-#define KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED
-#define @KWSYS_NAMESPACE@_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED
+# if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_UNSIGNED_LONG_LONG) && \
+ !defined(KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED)
+# define KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED
+# define @KWSYS_NAMESPACE@_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED
inline std::ostream& operator<<(std::ostream& os,
@KWSYS_NAMESPACE@::IOStreamULL value)
{
return @KWSYS_NAMESPACE@::IOStreamPrint(os, value);
}
-#endif
-#endif /* !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG */
-#endif /* @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL */
+# endif
+# endif /* !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG */
+#endif /* @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL */
/* Undefine temporary macros. */
#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysEXPORT
+# undef kwsysEXPORT
#endif
/* If building a C++ file in kwsys itself, give the source file
access to the macros without a configured namespace. */
#if defined(KWSYS_NAMESPACE)
-#define KWSYS_IOS_HAS_ISTREAM_LONG_LONG \
- @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
-#define KWSYS_IOS_HAS_OSTREAM_LONG_LONG \
- @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
-#define KWSYS_IOS_NEED_OPERATORS_LL @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL
+# define KWSYS_IOS_HAS_ISTREAM_LONG_LONG \
+ @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
+# define KWSYS_IOS_HAS_OSTREAM_LONG_LONG \
+ @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
+# define KWSYS_IOS_NEED_OPERATORS_LL @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL
#endif
#endif
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "MD5.h.in"
+# include "MD5.h.in"
#endif
#include <stddef.h> /* size_t */
implementation file. */
#if defined(__clang__) && !defined(__INTEL_COMPILER)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-align"
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wcast-align"
#endif
/*
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
-#define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
-#define BYTE_ORDER 0
+# define BYTE_ORDER 0
#endif
#define T_MASK ((md5_word_t)~0)
const md5_byte_t* xp = data;
int i;
-#if BYTE_ORDER == 0
+# if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
-#else
-#define xbuf X /* (static only) */
-#endif
+# else
+# define xbuf X /* (static only) */
+# endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] =
(md5_word_t)(xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24));
}
#if defined(__clang__) && !defined(__INTEL_COMPILER)
-#pragma clang diagnostic pop
+# pragma clang diagnostic pop
#endif
/* Wrap up the MD5 state in our opaque structure. */
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysMD5 kwsys_ns(MD5)
-#define kwsysMD5_s kwsys_ns(MD5_s)
-#define kwsysMD5_New kwsys_ns(MD5_New)
-#define kwsysMD5_Delete kwsys_ns(MD5_Delete)
-#define kwsysMD5_Initialize kwsys_ns(MD5_Initialize)
-#define kwsysMD5_Append kwsys_ns(MD5_Append)
-#define kwsysMD5_Finalize kwsys_ns(MD5_Finalize)
-#define kwsysMD5_FinalizeHex kwsys_ns(MD5_FinalizeHex)
-#define kwsysMD5_DigestToHex kwsys_ns(MD5_DigestToHex)
+# define kwsysMD5 kwsys_ns(MD5)
+# define kwsysMD5_s kwsys_ns(MD5_s)
+# define kwsysMD5_New kwsys_ns(MD5_New)
+# define kwsysMD5_Delete kwsys_ns(MD5_Delete)
+# define kwsysMD5_Initialize kwsys_ns(MD5_Initialize)
+# define kwsysMD5_Append kwsys_ns(MD5_Append)
+# define kwsysMD5_Finalize kwsys_ns(MD5_Finalize)
+# define kwsysMD5_FinalizeHex kwsys_ns(MD5_FinalizeHex)
+# define kwsysMD5_DigestToHex kwsys_ns(MD5_DigestToHex)
#endif
#if defined(__cplusplus)
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysMD5
-#undef kwsysMD5_s
-#undef kwsysMD5_New
-#undef kwsysMD5_Delete
-#undef kwsysMD5_Initialize
-#undef kwsysMD5_Append
-#undef kwsysMD5_Finalize
-#undef kwsysMD5_FinalizeHex
-#undef kwsysMD5_DigestToHex
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysMD5
+# undef kwsysMD5_s
+# undef kwsysMD5_New
+# undef kwsysMD5_Delete
+# undef kwsysMD5_Initialize
+# undef kwsysMD5_Append
+# undef kwsysMD5_Finalize
+# undef kwsysMD5_FinalizeHex
+# undef kwsysMD5_DigestToHex
+# endif
#endif
#endif
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysProcess kwsys_ns(Process)
-#define kwsysProcess_s kwsys_ns(Process_s)
-#define kwsysProcess_New kwsys_ns(Process_New)
-#define kwsysProcess_Delete kwsys_ns(Process_Delete)
-#define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand)
-#define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand)
-#define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout)
-#define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory)
-#define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile)
-#define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative)
-#define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared)
-#define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach)
-#define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow)
-#define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput)
-#define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim)
-#define kwsysProcess_Option_CreateProcessGroup \
- kwsys_ns(Process_Option_CreateProcessGroup)
-#define kwsysProcess_GetOption kwsys_ns(Process_GetOption)
-#define kwsysProcess_SetOption kwsys_ns(Process_SetOption)
-#define kwsysProcess_Option_e kwsys_ns(Process_Option_e)
-#define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting)
-#define kwsysProcess_State_Error kwsys_ns(Process_State_Error)
-#define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception)
-#define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing)
-#define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited)
-#define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired)
-#define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed)
-#define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned)
-#define kwsysProcess_State_e kwsys_ns(Process_State_e)
-#define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None)
-#define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault)
-#define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal)
-#define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt)
-#define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical)
-#define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other)
-#define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e)
-#define kwsysProcess_GetState kwsys_ns(Process_GetState)
-#define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
-#define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode)
-#define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue)
-#define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString)
-#define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString)
-#define kwsysProcess_GetStateByIndex kwsys_ns(Process_GetStateByIndex)
-#define kwsysProcess_GetExitExceptionByIndex \
- kwsys_ns(Process_GetExitExceptionByIndex)
-#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
-#define kwsysProcess_GetExitValueByIndex kwsys_ns(Process_GetExitValueByIndex)
-#define kwsysProcess_GetExceptionStringByIndex \
- kwsys_ns(Process_GetExceptionStringByIndex)
-#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
-#define kwsysProcess_Execute kwsys_ns(Process_Execute)
-#define kwsysProcess_Disown kwsys_ns(Process_Disown)
-#define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData)
-#define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e)
-#define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None)
-#define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN)
-#define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT)
-#define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR)
-#define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout)
-#define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle)
-#define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit)
-#define kwsysProcess_Interrupt kwsys_ns(Process_Interrupt)
-#define kwsysProcess_Kill kwsys_ns(Process_Kill)
-#define kwsysProcess_KillPID kwsys_ns(Process_KillPID)
-#define kwsysProcess_ResetStartTime kwsys_ns(Process_ResetStartTime)
+# define kwsysProcess kwsys_ns(Process)
+# define kwsysProcess_s kwsys_ns(Process_s)
+# define kwsysProcess_New kwsys_ns(Process_New)
+# define kwsysProcess_Delete kwsys_ns(Process_Delete)
+# define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand)
+# define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand)
+# define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout)
+# define kwsysProcess_SetWorkingDirectory \
+ kwsys_ns(Process_SetWorkingDirectory)
+# define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile)
+# define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative)
+# define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared)
+# define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach)
+# define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow)
+# define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput)
+# define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim)
+# define kwsysProcess_Option_CreateProcessGroup \
+ kwsys_ns(Process_Option_CreateProcessGroup)
+# define kwsysProcess_GetOption kwsys_ns(Process_GetOption)
+# define kwsysProcess_SetOption kwsys_ns(Process_SetOption)
+# define kwsysProcess_Option_e kwsys_ns(Process_Option_e)
+# define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting)
+# define kwsysProcess_State_Error kwsys_ns(Process_State_Error)
+# define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception)
+# define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing)
+# define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited)
+# define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired)
+# define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed)
+# define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned)
+# define kwsysProcess_State_e kwsys_ns(Process_State_e)
+# define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None)
+# define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault)
+# define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal)
+# define kwsysProcess_Exception_Interrupt \
+ kwsys_ns(Process_Exception_Interrupt)
+# define kwsysProcess_Exception_Numerical \
+ kwsys_ns(Process_Exception_Numerical)
+# define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other)
+# define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e)
+# define kwsysProcess_GetState kwsys_ns(Process_GetState)
+# define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
+# define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode)
+# define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue)
+# define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString)
+# define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString)
+# define kwsysProcess_GetStateByIndex kwsys_ns(Process_GetStateByIndex)
+# define kwsysProcess_GetExitExceptionByIndex \
+ kwsys_ns(Process_GetExitExceptionByIndex)
+# define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
+# define kwsysProcess_GetExitValueByIndex \
+ kwsys_ns(Process_GetExitValueByIndex)
+# define kwsysProcess_GetExceptionStringByIndex \
+ kwsys_ns(Process_GetExceptionStringByIndex)
+# define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
+# define kwsysProcess_Execute kwsys_ns(Process_Execute)
+# define kwsysProcess_Disown kwsys_ns(Process_Disown)
+# define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData)
+# define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e)
+# define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None)
+# define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN)
+# define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT)
+# define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR)
+# define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout)
+# define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle)
+# define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit)
+# define kwsysProcess_Interrupt kwsys_ns(Process_Interrupt)
+# define kwsysProcess_Kill kwsys_ns(Process_Kill)
+# define kwsysProcess_KillPID kwsys_ns(Process_KillPID)
+# define kwsysProcess_ResetStartTime kwsys_ns(Process_ResetStartTime)
#endif
#if defined(__cplusplus)
kwsysEXPORT const char* kwsysProcess_GetExceptionString(kwsysProcess* cp);
/**
-* Get the current state of the Process instance. Possible states are:
-*
-* kwsysProcess_StateByIndex_Starting = Execute has not yet been called.
-* kwsysProcess_StateByIndex_Exception = Child process exited abnormally.
-* kwsysProcess_StateByIndex_Exited = Child process exited normally.
-* kwsysProcess_StateByIndex_Error = Error getting the child return code.
-*/
+ * Get the current state of the Process instance. Possible states are:
+ *
+ * kwsysProcess_StateByIndex_Starting = Execute has not yet been called.
+ * kwsysProcess_StateByIndex_Exception = Child process exited abnormally.
+ * kwsysProcess_StateByIndex_Exited = Child process exited normally.
+ * kwsysProcess_StateByIndex_Error = Error getting the child return code.
+ */
kwsysEXPORT int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx);
enum kwsysProcess_StateByIndex_e
{
};
/**
-* When GetState returns "Exception", this method returns a
-* platform-independent description of the exceptional behavior that
-* caused the child to terminate abnormally. Possible exceptions are:
-*
-* kwsysProcess_Exception_None = No exceptional behavior occurred.
-* kwsysProcess_Exception_Fault = Child crashed with a memory fault.
-* kwsysProcess_Exception_Illegal = Child crashed with an illegal
-* instruction.
-* kwsysProcess_Exception_Interrupt = Child was interrupted by user
-* (Cntl-C/Break).
-* kwsysProcess_Exception_Numerical = Child crashed with a numerical
-* exception.
-* kwsysProcess_Exception_Other = Child terminated for another reason.
-*/
+ * When GetState returns "Exception", this method returns a
+ * platform-independent description of the exceptional behavior that
+ * caused the child to terminate abnormally. Possible exceptions are:
+ *
+ * kwsysProcess_Exception_None = No exceptional behavior occurred.
+ * kwsysProcess_Exception_Fault = Child crashed with a memory fault.
+ * kwsysProcess_Exception_Illegal = Child crashed with an illegal
+ * instruction.
+ * kwsysProcess_Exception_Interrupt = Child was interrupted by user
+ * (Cntl-C/Break).
+ * kwsysProcess_Exception_Numerical = Child crashed with a numerical
+ * exception.
+ * kwsysProcess_Exception_Other = Child terminated for another reason.
+ */
kwsysEXPORT int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp,
int idx);
/**
-* When GetState returns "Exited" or "Exception", this method returns
-* the platform-specific raw exit code of the process. UNIX platforms
-* should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access
-* this value. Windows users should compare the value to the various
-* EXCEPTION_* values.
-*
-* If GetState returns "Exited", use GetExitValue to get the
-* platform-independent child return value.
-*/
+ * When GetState returns "Exited" or "Exception", this method returns
+ * the platform-specific raw exit code of the process. UNIX platforms
+ * should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access
+ * this value. Windows users should compare the value to the various
+ * EXCEPTION_* values.
+ *
+ * If GetState returns "Exited", use GetExitValue to get the
+ * platform-independent child return value.
+ */
kwsysEXPORT int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx);
/**
-* When GetState returns "Exited", this method returns the child's
-* platform-independent exit code (such as the value returned by the
-* child's main).
-*/
+ * When GetState returns "Exited", this method returns the child's
+ * platform-independent exit code (such as the value returned by the
+ * child's main).
+ */
kwsysEXPORT int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx);
/**
-* When GetState returns "Exception", this method returns a string
-* describing the problem. Otherwise, it returns NULL.
-*/
+ * When GetState returns "Exception", this method returns a string
+ * describing the problem. Otherwise, it returns NULL.
+ */
kwsysEXPORT const char* kwsysProcess_GetExceptionStringByIndex(
kwsysProcess* cp, int idx);
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysProcess
-#undef kwsysProcess_s
-#undef kwsysProcess_New
-#undef kwsysProcess_Delete
-#undef kwsysProcess_SetCommand
-#undef kwsysProcess_AddCommand
-#undef kwsysProcess_SetTimeout
-#undef kwsysProcess_SetWorkingDirectory
-#undef kwsysProcess_SetPipeFile
-#undef kwsysProcess_SetPipeNative
-#undef kwsysProcess_SetPipeShared
-#undef kwsysProcess_Option_Detach
-#undef kwsysProcess_Option_HideWindow
-#undef kwsysProcess_Option_MergeOutput
-#undef kwsysProcess_Option_Verbatim
-#undef kwsysProcess_Option_CreateProcessGroup
-#undef kwsysProcess_GetOption
-#undef kwsysProcess_SetOption
-#undef kwsysProcess_Option_e
-#undef kwsysProcess_State_Starting
-#undef kwsysProcess_State_Error
-#undef kwsysProcess_State_Exception
-#undef kwsysProcess_State_Executing
-#undef kwsysProcess_State_Exited
-#undef kwsysProcess_State_Expired
-#undef kwsysProcess_State_Killed
-#undef kwsysProcess_State_Disowned
-#undef kwsysProcess_GetState
-#undef kwsysProcess_State_e
-#undef kwsysProcess_Exception_None
-#undef kwsysProcess_Exception_Fault
-#undef kwsysProcess_Exception_Illegal
-#undef kwsysProcess_Exception_Interrupt
-#undef kwsysProcess_Exception_Numerical
-#undef kwsysProcess_Exception_Other
-#undef kwsysProcess_GetExitException
-#undef kwsysProcess_Exception_e
-#undef kwsysProcess_GetExitCode
-#undef kwsysProcess_GetExitValue
-#undef kwsysProcess_GetErrorString
-#undef kwsysProcess_GetExceptionString
-#undef kwsysProcess_Execute
-#undef kwsysProcess_Disown
-#undef kwsysProcess_WaitForData
-#undef kwsysProcess_Pipes_e
-#undef kwsysProcess_Pipe_None
-#undef kwsysProcess_Pipe_STDIN
-#undef kwsysProcess_Pipe_STDOUT
-#undef kwsysProcess_Pipe_STDERR
-#undef kwsysProcess_Pipe_Timeout
-#undef kwsysProcess_Pipe_Handle
-#undef kwsysProcess_WaitForExit
-#undef kwsysProcess_Interrupt
-#undef kwsysProcess_Kill
-#undef kwsysProcess_ResetStartTime
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysProcess
+# undef kwsysProcess_s
+# undef kwsysProcess_New
+# undef kwsysProcess_Delete
+# undef kwsysProcess_SetCommand
+# undef kwsysProcess_AddCommand
+# undef kwsysProcess_SetTimeout
+# undef kwsysProcess_SetWorkingDirectory
+# undef kwsysProcess_SetPipeFile
+# undef kwsysProcess_SetPipeNative
+# undef kwsysProcess_SetPipeShared
+# undef kwsysProcess_Option_Detach
+# undef kwsysProcess_Option_HideWindow
+# undef kwsysProcess_Option_MergeOutput
+# undef kwsysProcess_Option_Verbatim
+# undef kwsysProcess_Option_CreateProcessGroup
+# undef kwsysProcess_GetOption
+# undef kwsysProcess_SetOption
+# undef kwsysProcess_Option_e
+# undef kwsysProcess_State_Starting
+# undef kwsysProcess_State_Error
+# undef kwsysProcess_State_Exception
+# undef kwsysProcess_State_Executing
+# undef kwsysProcess_State_Exited
+# undef kwsysProcess_State_Expired
+# undef kwsysProcess_State_Killed
+# undef kwsysProcess_State_Disowned
+# undef kwsysProcess_GetState
+# undef kwsysProcess_State_e
+# undef kwsysProcess_Exception_None
+# undef kwsysProcess_Exception_Fault
+# undef kwsysProcess_Exception_Illegal
+# undef kwsysProcess_Exception_Interrupt
+# undef kwsysProcess_Exception_Numerical
+# undef kwsysProcess_Exception_Other
+# undef kwsysProcess_GetExitException
+# undef kwsysProcess_Exception_e
+# undef kwsysProcess_GetExitCode
+# undef kwsysProcess_GetExitValue
+# undef kwsysProcess_GetErrorString
+# undef kwsysProcess_GetExceptionString
+# undef kwsysProcess_Execute
+# undef kwsysProcess_Disown
+# undef kwsysProcess_WaitForData
+# undef kwsysProcess_Pipes_e
+# undef kwsysProcess_Pipe_None
+# undef kwsysProcess_Pipe_STDIN
+# undef kwsysProcess_Pipe_STDOUT
+# undef kwsysProcess_Pipe_STDERR
+# undef kwsysProcess_Pipe_Timeout
+# undef kwsysProcess_Pipe_Handle
+# undef kwsysProcess_WaitForExit
+# undef kwsysProcess_Interrupt
+# undef kwsysProcess_Kill
+# undef kwsysProcess_ResetStartTime
+# endif
#endif
#endif
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Process.h.in"
-#include "System.h.in"
+# include "Process.h.in"
+# include "System.h.in"
#endif
/*
#if defined(__CYGWIN__)
/* Increase the file descriptor limit for select() before including
related system headers. (Default: 64) */
-#define FD_SETSIZE 16384
+# define FD_SETSIZE 16384
#endif
#include <assert.h> /* assert */
#include <unistd.h> /* pipe, close, fork, execvp, select, _exit */
#if defined(__VMS)
-#define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK
+# define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK
#else
-#define KWSYSPE_VMS_NONBLOCK
+# define KWSYSPE_VMS_NONBLOCK
#endif
#if defined(KWSYS_C_HAS_PTRDIFF_T) && KWSYS_C_HAS_PTRDIFF_T
#if defined(__BEOS__) && !defined(__ZETA__)
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
-#include <be/kernel/OS.h>
+# include <be/kernel/OS.h>
static inline void kwsysProcess_usleep(unsigned int msec)
{
snooze(msec);
}
#else
-#define kwsysProcess_usleep usleep
+# define kwsysProcess_usleep usleep
#endif
/*
*/
#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__) && \
!defined(KWSYSPE_USE_SELECT)
-#define KWSYSPE_USE_SELECT 1
+# define KWSYSPE_USE_SELECT 1
#endif
/* Some platforms do not have siginfo on their signal handlers. */
#if defined(SA_SIGINFO) && !defined(__BEOS__)
-#define KWSYSPE_USE_SIGINFO 1
+# define KWSYSPE_USE_SIGINFO 1
#endif
/* The number of pipes for the child's output. The standard stdout
} else if (n == 0) /* EOF */
{
/* We are done reading from this pipe. */
-#if defined(__VMS)
+# if defined(__VMS)
if (!cp->CommandsLeft)
-#endif
+# endif
{
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
--cp->PipesLeft;
}
} else if (n < 0) /* error */
{
-#if defined(__VMS)
+# if defined(__VMS)
if (!cp->CommandsLeft) {
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
--cp->PipesLeft;
} else
-#endif
+# endif
if ((errno != EINTR) && (errno != EAGAIN)) {
strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE);
/* Kill the children now. */
/* clang has made it impossible to free memory that points to volatile
without first using special pragmas to disable a warning... */
#if defined(__clang__) && !defined(__INTEL_COMPILER)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-qual"
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wcast-qual"
#endif
free((void*)p); /* The cast will silence most compilers, but not clang. */
#if defined(__clang__) && !defined(__INTEL_COMPILER)
-#pragma clang diagnostic pop
+# pragma clang diagnostic pop
#endif
}
break;
#endif
#ifdef SIGBUS
-#if !defined(SIGSEGV) || SIGBUS != SIGSEGV
+# if !defined(SIGSEGV) || SIGBUS != SIGSEGV
case SIGBUS:
KWSYSPE_CASE(Fault, "Bus error");
break;
-#endif
+# endif
#endif
#ifdef SIGFPE
case SIGFPE:
break;
#endif
#ifdef SIGIOT
-#if !defined(SIGABRT) || SIGIOT != SIGABRT
+# if !defined(SIGABRT) || SIGIOT != SIGABRT
case SIGIOT:
KWSYSPE_CASE(Other, "SIGIOT");
break;
-#endif
+# endif
#endif
#ifdef SIGUSR1
case SIGUSR1:
break;
#endif
#ifdef SIGIO
-#if !defined(SIGPOLL) || SIGIO != SIGPOLL
+# if !defined(SIGPOLL) || SIGIO != SIGPOLL
case SIGIO:
KWSYSPE_CASE(Other, "SIGIO");
break;
-#endif
+# endif
#endif
#ifdef SIGPWR
case SIGPWR:
break;
#endif
#ifdef SIGUNUSED
-#if !defined(SIGSYS) || SIGUNUSED != SIGSYS
+# if !defined(SIGSYS) || SIGUNUSED != SIGSYS
case SIGUNUSED:
KWSYSPE_CASE(Other, "SIGUNUSED");
break;
-#endif
+# endif
#endif
default:
cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
have two integers to store: the pid and then the ppid. */
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
defined(__OpenBSD__) || defined(__GLIBC__) || defined(__GNU__)
-#define KWSYSPE_PS_COMMAND "ps axo pid,ppid"
-#define KWSYSPE_PS_FORMAT "%d %d\n"
+# define KWSYSPE_PS_COMMAND "ps axo pid,ppid"
+# define KWSYSPE_PS_FORMAT "%d %d\n"
#elif defined(__sun) && (defined(__SVR4) || defined(__svr4__)) /* Solaris */
-#define KWSYSPE_PS_COMMAND "ps -e -o pid,ppid"
-#define KWSYSPE_PS_FORMAT "%d %d\n"
+# define KWSYSPE_PS_COMMAND "ps -e -o pid,ppid"
+# define KWSYSPE_PS_FORMAT "%d %d\n"
#elif defined(__hpux) || defined(__sun__) || defined(__sgi) || \
defined(_AIX) || defined(__sparc)
-#define KWSYSPE_PS_COMMAND "ps -ef"
-#define KWSYSPE_PS_FORMAT "%*s %d %d %*[^\n]\n"
+# define KWSYSPE_PS_COMMAND "ps -ef"
+# define KWSYSPE_PS_FORMAT "%*s %d %d %*[^\n]\n"
#elif defined(__QNX__)
-#define KWSYSPE_PS_COMMAND "ps -Af"
-#define KWSYSPE_PS_FORMAT "%*d %d %d %*[^\n]\n"
+# define KWSYSPE_PS_COMMAND "ps -Af"
+# define KWSYSPE_PS_FORMAT "%*d %d %d %*[^\n]\n"
#elif defined(__CYGWIN__)
-#define KWSYSPE_PS_COMMAND "ps aux"
-#define KWSYSPE_PS_FORMAT "%d %d %*[^\n]\n"
+# define KWSYSPE_PS_COMMAND "ps aux"
+# define KWSYSPE_PS_FORMAT "%d %d %*[^\n]\n"
#endif
void kwsysProcess_KillPID(unsigned long process_id)
#if defined(__linux__) || defined(__CYGWIN__)
/* First try using the /proc filesystem. */
if ((procdir = opendir("/proc")) != NULL) {
-#if defined(MAXPATHLEN)
+# if defined(MAXPATHLEN)
char fname[MAXPATHLEN];
-#elif defined(PATH_MAX)
+# elif defined(PATH_MAX)
char fname[PATH_MAX];
-#else
+# else
char fname[4096];
-#endif
+# endif
char buffer[KWSYSPE_PIPE_BUFFER_SIZE + 1];
struct dirent* d;
#if KWSYSPE_USE_SIGINFO
newSigAction.sa_sigaction = kwsysProcessesSignalHandler;
newSigAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
-#ifdef SA_RESTART
+# ifdef SA_RESTART
newSigAction.sa_flags |= SA_RESTART;
-#endif
+# endif
#else
newSigAction.sa_handler = kwsysProcessesSignalHandler;
newSigAction.sa_flags = SA_NOCLDSTOP;
,
siginfo_t* info, void* ucontext
#endif
- )
+)
{
int i, j, procStatus, old_errno = errno;
#if KWSYSPE_USE_SIGINFO
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Encoding.h.in"
-#include "Process.h.in"
+# include "Encoding.h.in"
+# include "Process.h.in"
#endif
/*
*/
#ifdef _MSC_VER
-#pragma warning(push, 1)
+# pragma warning(push, 1)
#endif
#include <windows.h> /* Windows API */
#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#endif
#include <io.h> /* _unlink */
#include <stdio.h> /* sprintf */
#include <string.h> /* strlen, strdup */
#ifdef __WATCOMC__
-#define _unlink unlink
+# define _unlink unlink
#endif
#ifndef _MAX_FNAME
-#define _MAX_FNAME 4096
+# define _MAX_FNAME 4096
#endif
#ifndef _MAX_PATH
-#define _MAX_PATH 4096
+# define _MAX_PATH 4096
#endif
#ifdef _MSC_VER
-#pragma warning(pop)
-#pragma warning(disable : 4514)
-#pragma warning(disable : 4706)
+# pragma warning(pop)
+# pragma warning(disable : 4514)
+# pragma warning(disable : 4706)
#endif
#if defined(__BORLANDC__)
-#pragma warn - 8004 /* assigned a value that is never used */
-#pragma warn - 8060 /* Assignment inside if() condition. */
+# pragma warn - 8004 /* assigned a value that is never used */
+# pragma warn - 8060 /* Assignment inside if() condition. */
#endif
/* There are pipes for the process pipeline's stdout and stderr. */
/* Debug output macro. */
#if 0
-#define KWSYSPE_DEBUG(x) \
- ((void*)cp == (void*)0x00226DE0 \
- ? (fprintf(stderr, "%d/%p/%d ", (int)GetCurrentProcessId(), cp, \
- __LINE__), \
- fprintf x, fflush(stderr), 1) \
- : (1))
+# define KWSYSPE_DEBUG(x) \
+ ((void*)cp == (void*)0x00226DE0 \
+ ? (fprintf(stderr, "%d/%p/%d ", (int)GetCurrentProcessId(), cp, \
+ __LINE__), \
+ fprintf x, fflush(stderr), 1) \
+ : (1))
#else
-#define KWSYSPE_DEBUG(x) (void)1
+# define KWSYSPE_DEBUG(x) (void)1
#endif
typedef LARGE_INTEGER kwsysProcessTime;
ZeroMemory(&osv, sizeof(osv));
osv.dwOSVersionInfoSize = sizeof(osv);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# else
+# pragma warning(disable : 4996)
+# endif
#endif
GetVersionEx(&osv);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
+# pragma warning(pop)
#endif
if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
/* Win9x no longer supported. */
ZeroMemory(&osv, sizeof(osv));
osv.dwOSVersionInfoSize = sizeof(osv);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# else
+# pragma warning(disable : 4996)
+# endif
#endif
GetVersionEx(&osv);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
+# pragma warning(pop)
#endif
self->NT4 =
(osv.dwPlatformId == VER_PLATFORM_WIN32_NT && osv.dwMajorVersion < 5) ? 1
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "RegularExpression.hxx.in"
+# include "RegularExpression.hxx.in"
#endif
#include <stdio.h>
*/
// definition number opnd? meaning
-#define END 0 // no End of program.
-#define BOL 1 // no Match "" at beginning of line.
-#define EOL 2 // no Match "" at end of line.
-#define ANY 3 // no Match any one character.
-#define ANYOF 4 // str Match any character in this string.
-#define ANYBUT 5 // str Match any character not in this
- // string.
-#define BRANCH 6 // node Match this alternative, or the
+#define END 0 // no End of program.
+#define BOL 1 // no Match "" at beginning of line.
+#define EOL 2 // no Match "" at end of line.
+#define ANY 3 // no Match any one character.
+#define ANYOF 4 // str Match any character in this string.
+#define ANYBUT \
+ 5 // str Match any character not in this
+ // string.
+#define BRANCH \
+ 6 // node Match this alternative, or the
// next...
#define BACK 7 // no Match "", "next" ptr points backward.
#define EXACTLY 8 // str Match this string.
#define NOTHING 9 // no Match empty string.
-#define STAR 10 // node Match this (simple) thing 0 or more
- // times.
-#define PLUS 11 // node Match this (simple) thing 1 or more
- // times.
-#define OPEN 20 // no Mark this point in input as start of
- // #n.
+#define STAR \
+ 10 // node Match this (simple) thing 0 or more
+ // times.
+#define PLUS \
+ 11 // node Match this (simple) thing 1 or more
+ // times.
+#define OPEN \
+ 20 // no Mark this point in input as start of
+ // #n.
// OPEN+1 is number 1, etc.
#define CLOSE 30 // no Analogous to OPEN.
/* Disable useless Borland warnings. KWSys tries not to force things
on its includers, but there is no choice here. */
#if defined(__BORLANDC__)
-#pragma warn - 8027 /* function not inlined. */
+# pragma warn - 8027 /* function not inlined. */
#endif
namespace @KWSYS_NAMESPACE@ {
if (this->startp[n] == 0) {
return std::string();
} else {
- return std::string(this->startp[n], static_cast<std::string::size_type>(
- this->endp[n] - this->startp[n]));
+ return std::string(
+ this->startp[n],
+ static_cast<std::string::size_type>(this->endp[n] - this->startp[n]));
}
}
* object as an argument and creates an object initialized with the
* information from the given RegularExpression object.
*
- * The find member function finds the first occurrence of the regular
+ * The find member function finds the first occurrence of the regular
* expression of that object in the string given to find as an argument. Find
* returns a boolean, and if true, mutates the private data appropriately.
* Find sets pointers to the beginning and end of the thing last found, they
* the to see if the compiled regular expression is the same, and the
* deep_equal functions also checks to see if the start and end pointers are
* the same. The is_valid function returns false if program is set to NULL,
- * (i.e. there is no valid compiled exression). The set_invalid function sets
- * the program to NULL (Warning: this deletes the compiled expression). The
- * following examples may help clarify regular expression usage:
+ * (i.e. there is no valid compiled expression). The set_invalid function
+ * sets the program to NULL (Warning: this deletes the compiled expression).
+ * The following examples may help clarify regular expression usage:
*
* * The regular expression "^hello" matches a "hello" only at the
* beginning of a line. It would match "hello there" but not "hi,
*
* * The regular expression "(..p)b" matches something ending with pb
* and beginning with whatever the two characters before the first p
- * encounterd in the line were. It would find "repb" in "rep drepa
+ * encountered in the line were. It would find "repb" in "rep drepa
* qrepb". The regular expression "(..p)a" would find "repa qrepb"
* in "rep drepa qrepb"
*
* * The regular expression "d(..p)" matches something ending with p,
* beginning with d, and having two characters in between that are
- * the same as the two characters before the first p encounterd in
+ * the same as the two characters before the first p encountered in
* the line. It would match "drepa qrepb" in "rep drepa qrepb".
*
* All methods of RegularExpression can be called simultaneously from
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifndef @KWSYS_NAMESPACE@_SharedForward_h
-#define @KWSYS_NAMESPACE@_SharedForward_h
+# define @KWSYS_NAMESPACE@_SharedForward_h
/*
This header is used to create a forwarding executable sets up the
/* Disable -Wcast-qual warnings since they are too hard to fix in a
cross-platform way. */
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wcast-qual")
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-qual"
-#endif
-#endif
-
-#if defined(__BORLANDC__) && !defined(__cplusplus)
+# if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wcast-qual")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wcast-qual"
+# endif
+# endif
+
+# if defined(__BORLANDC__) && !defined(__cplusplus)
/* Code has no effect; raised by winnt.h in C (not C++) when ignoring an
unused parameter using "(param)" syntax (i.e. no cast to void). */
-#pragma warn - 8019
-#endif
+# pragma warn - 8019
+# endif
/* Full path to the directory in which this executable is built. Do
not include a trailing slash. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_DIR_BUILD)
-#define KWSYS_SHARED_FORWARD_DIR_BUILD \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_DIR_BUILD)
+# define KWSYS_SHARED_FORWARD_DIR_BUILD \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD
+# endif
/* Library search path for build tree. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_PATH_BUILD)
-#define KWSYS_SHARED_FORWARD_PATH_BUILD \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_PATH_BUILD)
+# define KWSYS_SHARED_FORWARD_PATH_BUILD \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD
+# endif
/* Library search path for install tree. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_PATH_INSTALL)
-#define KWSYS_SHARED_FORWARD_PATH_INSTALL \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_PATH_INSTALL)
+# define KWSYS_SHARED_FORWARD_PATH_INSTALL \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL
+# endif
/* The real executable to which to forward in the build tree. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_EXE_BUILD)
-#define KWSYS_SHARED_FORWARD_EXE_BUILD \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_EXE_BUILD)
+# define KWSYS_SHARED_FORWARD_EXE_BUILD \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD
+# endif
/* The real executable to which to forward in the install tree. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_EXE_INSTALL)
-#define KWSYS_SHARED_FORWARD_EXE_INSTALL \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_EXE_INSTALL)
+# define KWSYS_SHARED_FORWARD_EXE_INSTALL \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL
+# endif
/* The configuration name with which this executable was built (Debug/Release).
*/
-#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME)
-#define KWSYS_SHARED_FORWARD_CONFIG_NAME \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME
-#else
-#undef KWSYS_SHARED_FORWARD_CONFIG_NAME
-#endif
+# if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME)
+# define KWSYS_SHARED_FORWARD_CONFIG_NAME \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME
+# else
+# undef KWSYS_SHARED_FORWARD_CONFIG_NAME
+# endif
/* Create command line option to replace executable. */
-#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND)
-#if !defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
-#define KWSYS_SHARED_FORWARD_OPTION_COMMAND \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND
-#endif
-#else
-#undef KWSYS_SHARED_FORWARD_OPTION_COMMAND
-#endif
+# if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND)
+# if !defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
+# define KWSYS_SHARED_FORWARD_OPTION_COMMAND \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND
+# endif
+# else
+# undef KWSYS_SHARED_FORWARD_OPTION_COMMAND
+# endif
/* Create command line option to print environment setting and exit. */
-#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT)
-#if !defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
-#define KWSYS_SHARED_FORWARD_OPTION_PRINT \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT
-#endif
-#else
-#undef KWSYS_SHARED_FORWARD_OPTION_PRINT
-#endif
+# if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT)
+# if !defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
+# define KWSYS_SHARED_FORWARD_OPTION_PRINT \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT
+# endif
+# else
+# undef KWSYS_SHARED_FORWARD_OPTION_PRINT
+# endif
/* Create command line option to run ldd or equivalent. */
-#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD)
-#if !defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
-#define KWSYS_SHARED_FORWARD_OPTION_LDD \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD
-#endif
-#else
-#undef KWSYS_SHARED_FORWARD_OPTION_LDD
-#endif
+# if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD)
+# if !defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
+# define KWSYS_SHARED_FORWARD_OPTION_LDD \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD
+# endif
+# else
+# undef KWSYS_SHARED_FORWARD_OPTION_LDD
+# endif
/* Include needed system headers. */
-#include <errno.h>
-#include <limits.h>
-#include <stddef.h> /* size_t */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+# include <errno.h>
+# include <limits.h>
+# include <stddef.h> /* size_t */
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# include <windows.h>
-#include <io.h>
-#include <process.h>
-#define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
-#else
-#include <sys/stat.h>
-#include <unistd.h>
-#endif
+# include <io.h>
+# include <process.h>
+# define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
+# else
+# include <sys/stat.h>
+# include <unistd.h>
+# endif
/* Configuration for this platform. */
/* The path separator for this platform. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define KWSYS_SHARED_FORWARD_PATH_SEP ';'
-#define KWSYS_SHARED_FORWARD_PATH_SLASH '\\'
-#else
-#define KWSYS_SHARED_FORWARD_PATH_SEP ':'
-#define KWSYS_SHARED_FORWARD_PATH_SLASH '/'
-#endif
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define KWSYS_SHARED_FORWARD_PATH_SEP ';'
+# define KWSYS_SHARED_FORWARD_PATH_SLASH '\\'
+# else
+# define KWSYS_SHARED_FORWARD_PATH_SEP ':'
+# define KWSYS_SHARED_FORWARD_PATH_SLASH '/'
+# endif
static const char kwsys_shared_forward_path_sep[2] = {
KWSYS_SHARED_FORWARD_PATH_SEP, 0
};
};
/* The maximum length of a file name. */
-#if defined(PATH_MAX)
-#define KWSYS_SHARED_FORWARD_MAXPATH PATH_MAX
-#elif defined(MAXPATHLEN)
-#define KWSYS_SHARED_FORWARD_MAXPATH MAXPATHLEN
-#else
-#define KWSYS_SHARED_FORWARD_MAXPATH 16384
-#endif
+# if defined(PATH_MAX)
+# define KWSYS_SHARED_FORWARD_MAXPATH PATH_MAX
+# elif defined(MAXPATHLEN)
+# define KWSYS_SHARED_FORWARD_MAXPATH MAXPATHLEN
+# else
+# define KWSYS_SHARED_FORWARD_MAXPATH 16384
+# endif
/* Select the environment variable holding the shared library runtime
search path for this platform and build configuration. Also select
ldd command equivalent. */
/* Linux */
-#if defined(__linux)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# if defined(__linux)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
/* FreeBSD */
-#elif defined(__FreeBSD__)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# elif defined(__FreeBSD__)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
/* OpenBSD */
-#elif defined(__OpenBSD__)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# elif defined(__OpenBSD__)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
/* OS X */
-#elif defined(__APPLE__)
-#define KWSYS_SHARED_FORWARD_LDD "otool", "-L"
-#define KWSYS_SHARED_FORWARD_LDD_N 2
-#define KWSYS_SHARED_FORWARD_LDPATH "DYLD_LIBRARY_PATH"
+# elif defined(__APPLE__)
+# define KWSYS_SHARED_FORWARD_LDD "otool", "-L"
+# define KWSYS_SHARED_FORWARD_LDD_N 2
+# define KWSYS_SHARED_FORWARD_LDPATH "DYLD_LIBRARY_PATH"
/* AIX */
-#elif defined(_AIX)
-#define KWSYS_SHARED_FORWARD_LDD "dump", "-H"
-#define KWSYS_SHARED_FORWARD_LDD_N 2
-#define KWSYS_SHARED_FORWARD_LDPATH "LIBPATH"
+# elif defined(_AIX)
+# define KWSYS_SHARED_FORWARD_LDD "dump", "-H"
+# define KWSYS_SHARED_FORWARD_LDD_N 2
+# define KWSYS_SHARED_FORWARD_LDPATH "LIBPATH"
/* SUN */
-#elif defined(__sun)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#include <sys/isa_defs.h>
-#if defined(_ILP32)
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-#elif defined(_LP64)
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH_64"
-#endif
+# elif defined(__sun)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# include <sys/isa_defs.h>
+# if defined(_ILP32)
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# elif defined(_LP64)
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH_64"
+# endif
/* HP-UX */
-#elif defined(__hpux)
-#define KWSYS_SHARED_FORWARD_LDD "chatr"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#if defined(__LP64__)
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-#else
-#define KWSYS_SHARED_FORWARD_LDPATH "SHLIB_PATH"
-#endif
+# elif defined(__hpux)
+# define KWSYS_SHARED_FORWARD_LDD "chatr"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# if defined(__LP64__)
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# else
+# define KWSYS_SHARED_FORWARD_LDPATH "SHLIB_PATH"
+# endif
/* SGI MIPS */
-#elif defined(__sgi) && defined(_MIPS_SIM)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#if _MIPS_SIM == _ABIO32
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-#elif _MIPS_SIM == _ABIN32
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARYN32_PATH"
-#elif _MIPS_SIM == _ABI64
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY64_PATH"
-#endif
+# elif defined(__sgi) && defined(_MIPS_SIM)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# if _MIPS_SIM == _ABIO32
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# elif _MIPS_SIM == _ABIN32
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARYN32_PATH"
+# elif _MIPS_SIM == _ABI64
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY64_PATH"
+# endif
/* Cygwin */
-#elif defined(__CYGWIN__)
-#define KWSYS_SHARED_FORWARD_LDD "cygcheck" /* TODO: cygwin 1.7 has ldd */
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "PATH"
+# elif defined(__CYGWIN__)
+# define KWSYS_SHARED_FORWARD_LDD \
+ "cygcheck" /* TODO: cygwin 1.7 has ldd \
+ */
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "PATH"
/* Windows */
-#elif defined(_WIN32)
-#define KWSYS_SHARED_FORWARD_LDPATH "PATH"
+# elif defined(_WIN32)
+# define KWSYS_SHARED_FORWARD_LDPATH "PATH"
/* Guess on this unknown system. */
-#else
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-#endif
+# else
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# endif
-#ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
+# ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
typedef struct kwsys_sf_arg_info_s
{
const char* arg;
return out;
}
-#endif
+# endif
/* Function to convert a logical or relative path to a physical full path. */
static int kwsys_shared_forward_realpath(const char* in_path, char* out_path)
{
-#if defined(_WIN32) && !defined(__CYGWIN__)
+# if defined(_WIN32) && !defined(__CYGWIN__)
/* Implementation for Windows. */
DWORD n =
GetFullPathNameA(in_path, KWSYS_SHARED_FORWARD_MAXPATH, out_path, 0);
return n > 0 && n <= KWSYS_SHARED_FORWARD_MAXPATH;
-#else
+# else
/* Implementation for UNIX. */
return realpath(in_path, out_path) != 0;
-#endif
+# endif
}
static int kwsys_shared_forward_samepath(const char* file1, const char* file2)
{
-#if defined(_WIN32)
+# if defined(_WIN32)
int result = 0;
HANDLE h1 = CreateFileA(file1, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
CloseHandle(h1);
CloseHandle(h2);
return result;
-#else
+# else
struct stat fs1, fs2;
return (stat(file1, &fs1) == 0 && stat(file2, &fs2) == 0 &&
memcmp(&fs2.st_dev, &fs1.st_dev, sizeof(fs1.st_dev)) == 0 &&
memcmp(&fs2.st_ino, &fs1.st_ino, sizeof(fs1.st_ino)) == 0 &&
fs2.st_size == fs1.st_size);
-#endif
+# endif
}
/* Function to report a system error message. */
static void kwsys_shared_forward_strerror(char* message)
{
-#if defined(_WIN32) && !defined(__CYGWIN__)
+# if defined(_WIN32) && !defined(__CYGWIN__)
/* Implementation for Windows. */
DWORD original = GetLastError();
DWORD length =
"Error 0x%X (FormatMessage failed with error 0x%X)", original,
GetLastError());
}
-#else
+# else
/* Implementation for UNIX. */
strcpy(message, strerror(errno));
-#endif
+# endif
}
/* Functions to execute a child process. */
static void kwsys_shared_forward_execvp(const char* cmd,
char const* const* argv)
{
-#ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
+# ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
/* Count the number of arguments. */
int argc = 0;
{
/* Replace the command line to be used. */
argv = (char const* const*)nargv;
}
-#endif
+# endif
/* Invoke the child process. */
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
_execvp(cmd, argv);
-#elif defined(__MINGW32__) && !defined(__MINGW64__)
+# elif defined(__MINGW32__) && !defined(__MINGW64__)
execvp(cmd, argv);
-#else
+# else
execvp(cmd, (char* const*)argv);
-#endif
+# endif
}
/* Function to get the directory containing the given file or directory. */
/* Only one leading slash. */
strcpy(result, kwsys_shared_forward_path_slash);
}
-#if defined(_WIN32)
+# if defined(_WIN32)
else if (last_slash_index == 2 && begin[1] == ':') {
/* Only one leading drive letter and slash. */
strncpy(result, begin, (size_t)last_slash_index);
result[last_slash_index] = KWSYS_SHARED_FORWARD_PATH_SLASH;
result[last_slash_index + 1] = 0;
}
-#endif
+# endif
else {
/* A non-leading slash. */
strncpy(result, begin, (size_t)last_slash_index);
/* Function to check if a file exists and is executable. */
static int kwsys_shared_forward_is_executable(const char* f)
{
-#if defined(_MSC_VER)
-#define KWSYS_SHARED_FORWARD_ACCESS _access
-#else
-#define KWSYS_SHARED_FORWARD_ACCESS access
-#endif
-#if defined(X_OK)
-#define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK
-#else
-#define KWSYS_SHARED_FORWARD_ACCESS_OK 04
-#endif
+# if defined(_MSC_VER)
+# define KWSYS_SHARED_FORWARD_ACCESS _access
+# else
+# define KWSYS_SHARED_FORWARD_ACCESS access
+# endif
+# if defined(X_OK)
+# define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK
+# else
+# define KWSYS_SHARED_FORWARD_ACCESS_OK 04
+# endif
if (KWSYS_SHARED_FORWARD_ACCESS(f, KWSYS_SHARED_FORWARD_ACCESS_OK) == 0) {
return 1;
} else {
/* Already a full path. */
strcpy(result, in_path);
}
-#if defined(_WIN32)
+# if defined(_WIN32)
else if (in_path[0] && in_path[1] == ':') {
/* Already a full path. */
strcpy(result, in_path);
}
-#endif
+# endif
else {
/* Relative to self path. */
char temp_path[KWSYS_SHARED_FORWARD_MAXPATH];
const char* exe_path;
/* Get the real name of the build and self paths. */
-#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
+# if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
char build_path[] =
KWSYS_SHARED_FORWARD_DIR_BUILD "/" KWSYS_SHARED_FORWARD_CONFIG_NAME;
char self_path_logical[KWSYS_SHARED_FORWARD_MAXPATH];
-#else
+# else
char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD;
const char* self_path_logical = self_path;
-#endif
+# endif
char build_path_real[KWSYS_SHARED_FORWARD_MAXPATH];
char self_path_real[KWSYS_SHARED_FORWARD_MAXPATH];
if (!kwsys_shared_forward_realpath(self_path, self_path_real)) {
kwsys_shared_forward_samepath(self_path_real, build_path_real)) {
/* Running in build tree. Use the build path and exe. */
search_path = search_path_build;
-#if defined(_WIN32)
+# if defined(_WIN32)
exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD ".exe";
-#else
+# else
exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD;
-#endif
+# endif
-#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
+# if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
/* Remove the configuration directory from self_path. */
kwsys_shared_forward_dirname(self_path, self_path_logical);
-#endif
+# endif
} else {
/* Running in install tree. Use the install path and exe. */
search_path = search_path_install;
-#if defined(_WIN32)
+# if defined(_WIN32)
exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL ".exe";
-#else
+# else
exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL;
-#endif
+# endif
-#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
+# if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
/* Use the original self path directory. */
strcpy(self_path_logical, self_path);
-#endif
+# endif
}
/* Construct the runtime search path. */
/* Store the environment variable. */
putenv(kwsys_shared_forward_ldpath);
-#if defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
+# if defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
/* Look for the command line replacement option. */
if (argc > 1 &&
strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_COMMAND) == 0) {
argc -= 2;
} else {
/* The option was not given an executable. */
- fprintf(stderr, "Option " KWSYS_SHARED_FORWARD_OPTION_COMMAND
- " must be followed by a command line.\n");
+ fprintf(stderr,
+ "Option " KWSYS_SHARED_FORWARD_OPTION_COMMAND
+ " must be followed by a command line.\n");
return 1;
}
}
-#endif
+# endif
-#if defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
+# if defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
/* Look for the print command line option. */
if (argc > 1 &&
strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_PRINT) == 0) {
fprintf(stdout, "%s\n", exe);
return 0;
}
-#endif
+# endif
-#if defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
+# if defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
/* Look for the ldd command line option. */
if (argc > 1 && strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_LDD) == 0) {
-#if defined(KWSYS_SHARED_FORWARD_LDD)
+# if defined(KWSYS_SHARED_FORWARD_LDD)
/* Use the named ldd-like executable and arguments. */
char const* ldd_argv[] = { KWSYS_SHARED_FORWARD_LDD, 0, 0 };
ldd_argv[KWSYS_SHARED_FORWARD_LDD_N] = exe;
/* Report why execution failed. */
kwsys_shared_forward_print_failure(ldd_argv);
return 1;
-#else
+# else
/* We have no ldd-like executable available on this platform. */
fprintf(stderr, "No ldd-like tool is known to this executable.\n");
return 1;
-#endif
+# endif
}
-#endif
+# endif
/* Replace this process with the real executable. */
argv[0] = exe;
}
/* Restore warning stack. */
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wcast-qual")
-#pragma clang diagnostic pop
-#endif
-#endif
+# if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wcast-qual")
+# pragma clang diagnostic pop
+# endif
+# endif
#else
-#error "@KWSYS_NAMESPACE@/SharedForward.h should be included only once."
+# error "@KWSYS_NAMESPACE@/SharedForward.h should be included only once."
#endif
source to try to get the definition of the string template. This
condition blocks the compiler from seeing the symbols defined here.
*/
-#include "kwsysPrivate.h"
-#include KWSYS_HEADER(String.h)
+# include "kwsysPrivate.h"
+# include KWSYS_HEADER(String.h)
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
-#if 0
-#include "String.h.in"
-#endif
+# if 0
+# include "String.h.in"
+# endif
/* Select an implementation for strcasecmp. */
-#if defined(_MSC_VER)
-#define KWSYS_STRING_USE_STRICMP
-#include <string.h>
-#elif defined(__GNUC__)
-#define KWSYS_STRING_USE_STRCASECMP
-#include <strings.h>
-#else
+# if defined(_MSC_VER)
+# define KWSYS_STRING_USE_STRICMP
+# include <string.h>
+# elif defined(__GNUC__)
+# define KWSYS_STRING_USE_STRCASECMP
+# include <strings.h>
+# else
/* Table to convert upper case letters to lower case and leave all
other characters alone. */
static char kwsysString_strcasecmp_tolower[] = {
'\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373',
'\374', '\375', '\376', '\377'
};
-#endif
+# endif
/*--------------------------------------------------------------------------*/
int kwsysString_strcasecmp(const char* lhs, const char* rhs)
{
-#if defined(KWSYS_STRING_USE_STRICMP)
+# if defined(KWSYS_STRING_USE_STRICMP)
return _stricmp(lhs, rhs);
-#elif defined(KWSYS_STRING_USE_STRCASECMP)
+# elif defined(KWSYS_STRING_USE_STRCASECMP)
return strcasecmp(lhs, rhs);
-#else
+# else
const char* const lower = kwsysString_strcasecmp_tolower;
unsigned char const* us1 = (unsigned char const*)lhs;
unsigned char const* us2 = (unsigned char const*)rhs;
while ((result = lower[*us1] - lower[*us2++], result == 0) && *us1++) {
}
return result;
-#endif
+# endif
}
/*--------------------------------------------------------------------------*/
int kwsysString_strncasecmp(const char* lhs, const char* rhs, size_t n)
{
-#if defined(KWSYS_STRING_USE_STRICMP)
+# if defined(KWSYS_STRING_USE_STRICMP)
return _strnicmp(lhs, rhs, n);
-#elif defined(KWSYS_STRING_USE_STRCASECMP)
+# elif defined(KWSYS_STRING_USE_STRCASECMP)
return strncasecmp(lhs, rhs, n);
-#else
+# else
const char* const lower = kwsysString_strcasecmp_tolower;
unsigned char const* us1 = (unsigned char const*)lhs;
unsigned char const* us2 = (unsigned char const*)rhs;
--n;
}
return result;
-#endif
+# endif
}
#endif /* KWSYS_STRING_C */
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysString_strcasecmp kwsys_ns(String_strcasecmp)
-#define kwsysString_strncasecmp kwsys_ns(String_strncasecmp)
+# define kwsysString_strcasecmp kwsys_ns(String_strcasecmp)
+# define kwsysString_strncasecmp kwsys_ns(String_strncasecmp)
#endif
#if defined(__cplusplus)
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysString_strcasecmp
-#undef kwsysString_strncasecmp
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysString_strcasecmp
+# undef kwsysString_strncasecmp
+# endif
#endif
#endif
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "System.h.in"
+# include "System.h.in"
#endif
#include <ctype.h> /* isspace */
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysSystem_Parse_CommandForUnix kwsys_ns(System_Parse_CommandForUnix)
+# define kwsysSystem_Parse_CommandForUnix \
+ kwsys_ns(System_Parse_CommandForUnix)
#endif
#if defined(__cplusplus)
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysSystem_Parse_CommandForUnix
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysSystem_Parse_CommandForUnix
+# endif
#endif
#endif
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#if defined(_WIN32)
-#define NOMINMAX // use our min,max
-#if !defined(_WIN32_WINNT) && !(defined(_MSC_VER) && _MSC_VER < 1300)
-#define _WIN32_WINNT 0x0501
-#endif
-#include <winsock.h> // WSADATA, include before sys/types.h
+# define NOMINMAX // use our min,max
+# if !defined(_WIN32_WINNT) && !(defined(_MSC_VER) && _MSC_VER < 1300)
+# define _WIN32_WINNT 0x0501
+# endif
+# include <winsock.h> // WSADATA, include before sys/types.h
#endif
#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
+# define _GNU_SOURCE
#endif
// TODO:
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Process.h.in"
-#include "SystemInformation.hxx.in"
+# include "Process.h.in"
+# include "SystemInformation.hxx.in"
#endif
#include <algorithm>
#include <vector>
#if defined(_WIN32)
-#include <windows.h>
-#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#endif
-#include <errno.h>
-#if defined(KWSYS_SYS_HAS_PSAPI)
-#include <psapi.h>
-#endif
-#if !defined(siginfo_t)
+# include <windows.h>
+# if defined(_MSC_VER) && _MSC_VER >= 1800
+# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# endif
+# include <errno.h>
+# if defined(KWSYS_SYS_HAS_PSAPI)
+# include <psapi.h>
+# endif
+# if !defined(siginfo_t)
typedef int siginfo_t;
-#endif
+# endif
#else
-#include <sys/types.h>
-
-#include <errno.h> // extern int errno;
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/resource.h> // getrlimit
-#include <sys/time.h>
-#include <sys/utsname.h> // int uname(struct utsname *buf);
-#include <unistd.h>
+# include <sys/types.h>
+
+# include <errno.h> // extern int errno;
+# include <fcntl.h>
+# include <signal.h>
+# include <sys/resource.h> // getrlimit
+# include <sys/time.h>
+# include <sys/utsname.h> // int uname(struct utsname *buf);
+# include <unistd.h>
#endif
#if defined(__CYGWIN__) && !defined(_WIN32)
-#include <windows.h>
-#undef _WIN32
+# include <windows.h>
+# undef _WIN32
#endif
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__)
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#if defined(KWSYS_SYS_HAS_IFADDRS_H)
-#include <ifaddrs.h>
-#include <net/if.h>
-#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
-#endif
+# include <netdb.h>
+# include <netinet/in.h>
+# include <sys/param.h>
+# include <sys/socket.h>
+# include <sys/sysctl.h>
+# if defined(KWSYS_SYS_HAS_IFADDRS_H)
+# include <ifaddrs.h>
+# include <net/if.h>
+# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
+# endif
#endif
#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
-#include <machine/cpu.h>
+# include <machine/cpu.h>
#endif
#ifdef __APPLE__
-#include <fenv.h>
-#include <mach/host_info.h>
-#include <mach/mach.h>
-#include <mach/mach_types.h>
-#include <mach/vm_statistics.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#if defined(KWSYS_SYS_HAS_IFADDRS_H)
-#include <ifaddrs.h>
-#include <net/if.h>
-#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
-#endif
-#if !(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - 0 >= 1050)
-#undef KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE
-#endif
+# include <mach/host_info.h>
+# include <mach/mach.h>
+# include <mach/mach_types.h>
+# include <mach/vm_statistics.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# include <sys/socket.h>
+# include <sys/sysctl.h>
+# if defined(KWSYS_SYS_HAS_IFADDRS_H)
+# include <ifaddrs.h>
+# include <net/if.h>
+# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
+# endif
+# if !(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - 0 >= 1050)
+# undef KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE
+# endif
#endif
#if defined(__linux) || defined(__sun) || defined(_SCO_DS)
-#include <fenv.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#if defined(KWSYS_SYS_HAS_IFADDRS_H)
-#include <ifaddrs.h>
-#include <net/if.h>
-#if defined(__LSB_VERSION__)
+# include <netdb.h>
+# include <netinet/in.h>
+# include <sys/socket.h>
+# if defined(KWSYS_SYS_HAS_IFADDRS_H)
+# include <ifaddrs.h>
+# include <net/if.h>
+# if defined(__LSB_VERSION__)
/* LSB has no getifaddrs */
-#elif defined(__ANDROID_API__) && __ANDROID_API__ < 24
+# elif defined(__ANDROID_API__) && __ANDROID_API__ < 24
/* Android has no getifaddrs prior to API 24. */
-#else
-#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
-#endif
-#endif
-#if defined(KWSYS_CXX_HAS_RLIMIT64)
+# else
+# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
+# endif
+# endif
+# if defined(KWSYS_CXX_HAS_RLIMIT64)
typedef struct rlimit64 ResourceLimitType;
-#define GetResourceLimit getrlimit64
-#else
+# define GetResourceLimit getrlimit64
+# else
typedef struct rlimit ResourceLimitType;
-#define GetResourceLimit getrlimit
-#endif
+# define GetResourceLimit getrlimit
+# endif
#elif defined(__hpux)
-#include <sys/param.h>
-#include <sys/pstat.h>
-#if defined(KWSYS_SYS_HAS_MPCTL_H)
-#include <sys/mpctl.h>
-#endif
+# include <sys/param.h>
+# include <sys/pstat.h>
+# if defined(KWSYS_SYS_HAS_MPCTL_H)
+# include <sys/mpctl.h>
+# endif
#endif
#ifdef __HAIKU__
-#include <OS.h>
+# include <OS.h>
#endif
#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
-#include <execinfo.h>
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
-#include <cxxabi.h>
-#endif
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
-#include <dlfcn.h>
-#endif
+# include <execinfo.h>
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+# include <cxxabi.h>
+# endif
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# include <dlfcn.h>
+# endif
#else
-#undef KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE
-#undef KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP
+# undef KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE
+# undef KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP
#endif
#include <ctype.h> // int isdigit(int c);
#include <string.h>
#if defined(KWSYS_USE_LONG_LONG)
-#if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
-#define iostreamLongLong(x) (x)
-#else
-#define iostreamLongLong(x) ((long)(x))
-#endif
+# if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)(x))
+# endif
#elif defined(KWSYS_USE___INT64)
-#if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
-#define iostreamLongLong(x) (x)
+# if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)(x))
+# endif
#else
-#define iostreamLongLong(x) ((long)(x))
-#endif
-#else
-#error "No Long Long"
+# error "No Long Long"
#endif
#if defined(KWSYS_CXX_HAS_ATOLL)
-#define atoLongLong atoll
-#else
-#if defined(KWSYS_CXX_HAS__ATOI64)
-#define atoLongLong _atoi64
-#elif defined(KWSYS_CXX_HAS_ATOL)
-#define atoLongLong atol
+# define atoLongLong atoll
#else
-#define atoLongLong atoi
-#endif
+# if defined(KWSYS_CXX_HAS__ATOI64)
+# define atoLongLong _atoi64
+# elif defined(KWSYS_CXX_HAS_ATOL)
+# define atoLongLong atol
+# else
+# define atoLongLong atoi
+# endif
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64) && \
!defined(__clang__)
-#define USE_ASM_INSTRUCTIONS 1
+# define USE_ASM_INSTRUCTIONS 1
#else
-#define USE_ASM_INSTRUCTIONS 0
+# define USE_ASM_INSTRUCTIONS 0
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__clang__)
-#include <intrin.h>
-#define USE_CPUID_INTRINSICS 1
+# include <intrin.h>
+# define USE_CPUID_INTRINSICS 1
#else
-#define USE_CPUID_INTRINSICS 0
+# define USE_CPUID_INTRINSICS 0
#endif
#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS || \
defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
-#define USE_CPUID 1
+# define USE_CPUID 1
#else
-#define USE_CPUID 0
+# define USE_CPUID 0
#endif
#if USE_CPUID
-#define CPUID_AWARE_COMPILER
+# define CPUID_AWARE_COMPILER
/**
* call CPUID instruction
*/
static bool call_cpuid(int select, int result[4])
{
-#if USE_CPUID_INTRINSICS
+# if USE_CPUID_INTRINSICS
__cpuid(result, select);
return true;
-#else
+# else
int tmp[4];
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
// Use SEH to determine CPUID presence
__try {
_asm {
-#ifdef CPUID_AWARE_COMPILER
+# ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser does not know about <<CPUID>>, and so does not expect
; these registers to change.
push ebx
push ecx
push edx
-#endif
+# endif
; <<CPUID>>
mov eax, select
-#ifdef CPUID_AWARE_COMPILER
+# ifdef CPUID_AWARE_COMPILER
cpuid
-#else
+# else
_asm _emit 0x0f
_asm _emit 0xa2
-#endif
+# endif
mov tmp[0 * TYPE int], eax
mov tmp[1 * TYPE int], ebx
mov tmp[2 * TYPE int], ecx
mov tmp[3 * TYPE int], edx
-#ifdef CPUID_AWARE_COMPILER
+# ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
-#endif
+# endif
}
} __except (1) {
return false;
}
memcpy(result, tmp, sizeof(tmp));
-#elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
+# elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
unsigned int a, b, c, d;
__asm {
mov EAX, select;
result[1] = b;
result[2] = c;
result[3] = d;
-#endif
+# endif
// The cpuid instruction succeeded.
return true;
-#endif
+# endif
}
#endif
return nRead;
}
-#if defined(__linux)
+# if defined(__linux)
// *****************************************************************************
int LoadLines(const char* fileName, std::vector<std::string>& lines)
{
fclose(file);
return nRead;
}
-#endif
+# endif
// ****************************************************************************
template <typename T>
void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
void* /*sigContext*/)
{
-#if defined(__linux) || defined(__APPLE__)
+# if defined(__linux) || defined(__APPLE__)
std::ostringstream oss;
oss << std::endl
<< "========================================================="
<< (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
<< sigInfo->si_addr << " ";
switch (sigInfo->si_code) {
-#if defined(FPE_INTDIV)
+# if defined(FPE_INTDIV)
case FPE_INTDIV:
oss << "integer division by zero";
break;
-#endif
+# endif
-#if defined(FPE_INTOVF)
+# if defined(FPE_INTOVF)
case FPE_INTOVF:
oss << "integer overflow";
break;
-#endif
+# endif
case FPE_FLTDIV:
oss << "floating point divide by zero";
oss << "floating point invalid operation";
break;
-#if defined(FPE_FLTSUB)
+# if defined(FPE_FLTSUB)
case FPE_FLTSUB:
oss << "floating point subscript out of range";
break;
-#endif
+# endif
default:
oss << "code " << sigInfo->si_code;
oss << "invalid address alignment";
break;
-#if defined(BUS_ADRERR)
+# if defined(BUS_ADRERR)
case BUS_ADRERR:
oss << "nonexistent physical address";
break;
-#endif
+# endif
-#if defined(BUS_OBJERR)
+# if defined(BUS_OBJERR)
case BUS_OBJERR:
oss << "object-specific hardware error";
break;
-#endif
+# endif
-#if defined(BUS_MCEERR_AR)
+# if defined(BUS_MCEERR_AR)
case BUS_MCEERR_AR:
oss << "Hardware memory error consumed on a machine check; action "
"required.";
break;
-#endif
+# endif
-#if defined(BUS_MCEERR_AO)
+# if defined(BUS_MCEERR_AO)
case BUS_MCEERR_AO:
oss << "Hardware memory error detected in process but not consumed; "
"action optional.";
break;
-#endif
+# endif
default:
oss << "code " << sigInfo->si_code;
oss << "illegal opcode";
break;
-#if defined(ILL_ILLOPN)
+# if defined(ILL_ILLOPN)
case ILL_ILLOPN:
oss << "illegal operand";
break;
-#endif
+# endif
-#if defined(ILL_ILLADR)
+# if defined(ILL_ILLADR)
case ILL_ILLADR:
oss << "illegal addressing mode.";
break;
-#endif
+# endif
case ILL_ILLTRP:
oss << "illegal trap";
oss << "privileged opcode";
break;
-#if defined(ILL_PRVREG)
+# if defined(ILL_PRVREG)
case ILL_PRVREG:
oss << "privileged register";
break;
-#endif
+# endif
-#if defined(ILL_COPROC)
+# if defined(ILL_COPROC)
case ILL_COPROC:
oss << "co-processor error";
break;
-#endif
+# endif
-#if defined(ILL_BADSTK)
+# if defined(ILL_BADSTK)
case ILL_BADSTK:
oss << "internal stack error";
break;
-#endif
+# endif
default:
oss << "code " << sigInfo->si_code;
// and abort
SystemInformationImplementation::SetStackTraceOnError(0);
abort();
-#else
+# else
// avoid warning C4100
(void)sigNo;
(void)sigInfo;
-#endif
+# endif
}
#endif
#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
-#define safes(_arg) ((_arg) ? (_arg) : "???")
+# define safes(_arg) ((_arg) ? (_arg) : "???")
// Description:
// A container for symbol properties. Each instance
long GetLineNumber() const { return this->LineNumber; }
// Description:
- // Set the address where the biinary image is mapped
+ // Set the address where the binary image is mapped
// into memory.
void SetBinaryBaseAddress(void* address)
{
std::ostream& operator<<(std::ostream& os, const SymbolProperties& sp)
{
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
os << std::hex << sp.GetAddress() << " : " << sp.GetFunction() << " [("
<< sp.GetBinary() << ") " << sp.GetSourceFile() << ":" << std::dec
<< sp.GetLineNumber() << "]";
-#elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+# elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
void* addr = sp.GetAddress();
char** syminfo = backtrace_symbols(&addr, 1);
os << safes(syminfo[0]);
free(syminfo);
-#else
+# else
(void)os;
(void)sp;
-#endif
+# endif
return os;
}
std::string SymbolProperties::GetBinary() const
{
// only linux has proc fs
-#if defined(__linux__)
+# if defined(__linux__)
if (this->Binary == "/proc/self/exe") {
std::string binary;
char buf[1024] = { '\0' };
}
return this->GetFileName(binary);
}
-#endif
+# endif
return this->GetFileName(this->Binary);
}
std::string SymbolProperties::Demangle(const char* symbol) const
{
std::string result = safes(symbol);
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
int status = 0;
size_t bufferLen = 1024;
char* buffer = (char*)malloc(1024);
result = demangledSymbol;
}
free(buffer);
-#else
+# else
(void)symbol;
-#endif
+# endif
return result;
}
void SymbolProperties::Initialize(void* address)
{
this->Address = address;
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
// first fallback option can demangle c++ functions
Dl_info info;
int ierr = dladdr(this->Address, &info);
this->SetBinary(info.dli_fname);
this->SetFunction(info.dli_sname);
}
-#else
+# else
// second fallback use builtin backtrace_symbols
// to decode the bactrace.
-#endif
+# endif
}
#endif // don't define this class if we're not using it
#if defined(_WIN32) || defined(__CYGWIN__)
-#define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
+# define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
#endif
#if defined(_MSC_VER) && _MSC_VER < 1310
-#undef KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
+# undef KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
#endif
#if defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes)
double calculateCPULoad(unsigned __int64 idleTicks,
#if USE_CPUID
int dummy[4] = { 0, 0, 0, 0 };
-#if USE_ASM_INSTRUCTIONS
+# if USE_ASM_INSTRUCTIONS
return call_cpuid(0, dummy);
-#else
+# else
call_cpuid(0, dummy);
return dummy[0] || dummy[1] || dummy[2] || dummy[3];
-#endif
+# endif
#else
// Assume no cpuid instruction.
return false;
this->Features.HasIA64 =
((cpuinfo[3] & 0x40000000) != 0); // IA64 Present --> Bit 30
-#if USE_ASM_INSTRUCTIONS
+# if USE_ASM_INSTRUCTIONS
// Retrieve extended SSE capabilities if SSE is available.
if (this->Features.HasSSE) {
// Set the advanced SSE capabilities to not available.
this->Features.HasSSEFP = false;
}
-#else
+# else
this->Features.HasSSEFP = false;
-#endif
+# endif
// Retrieve Intel specific extended features.
if (this->ChipManufacturer == Intel) {
{
#if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN)
// IRIX names this slightly different
-#define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
+# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
#endif
#ifdef _SC_NPROCESSORS_ONLN
SystemInformationImplementation::GetHostMemoryTotal()
{
#if defined(_WIN32)
-#if defined(_MSC_VER) && _MSC_VER < 1300
+# if defined(_MSC_VER) && _MSC_VER < 1300
MEMORYSTATUS stat;
stat.dwLength = sizeof(stat);
GlobalMemoryStatus(&stat);
return stat.dwTotalPhys / 1024;
-#else
+# else
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
return statex.ullTotalPhys / 1024;
-#endif
+# endif
#elif defined(__linux)
SystemInformation::LongLong memTotal = 0;
int ierr = GetFieldFromFile("/proc/meminfo", "MemTotal:", memTotal);
SystemInformationImplementation::GetHostMemoryUsed()
{
#if defined(_WIN32)
-#if defined(_MSC_VER) && _MSC_VER < 1300
+# if defined(_MSC_VER) && _MSC_VER < 1300
MEMORYSTATUS stat;
stat.dwLength = sizeof(stat);
GlobalMemoryStatus(&stat);
return (stat.dwTotalPhys - stat.dwAvailPhys) / 1024;
-#else
+# else
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
return (statex.ullTotalPhys - statex.ullAvailPhys) / 1024;
-#endif
+# endif
#elif defined(__linux)
// First try to use MemAvailable, but it only works on newer kernels
const char* names2[3] = { "MemTotal:", "MemAvailable:", NULL };
"WARNING: The stack trace will not use advanced "
"capabilities because this is a release build.\n"
#else
-#if !defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# if !defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
"WARNING: Function names will not be demangled "
"because "
"dladdr is not available.\n"
-#endif
-#if !defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+# endif
+# if !defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
"WARNING: Function names will not be demangled "
"because cxxabi is not available.\n"
-#endif
+# endif
#endif
;
struct sigaction sa;
sa.sa_sigaction = (SigAction)StacktraceSignalHandler;
sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
-#ifdef SA_RESTART
+# ifdef SA_RESTART
sa.sa_flags |= SA_RESTART;
-#endif
+# endif
sigemptyset(&sa.sa_mask);
sigaction(SIGABRT, &sa, KWSYS_NULLPTR);
bool SystemInformationImplementation::QueryWindowsMemory()
{
#if defined(_WIN32)
-#if defined(_MSC_VER) && _MSC_VER < 1300
+# if defined(_MSC_VER) && _MSC_VER < 1300
MEMORYSTATUS ms;
unsigned long tv, tp, av, ap;
ms.dwLength = sizeof(ms);
GlobalMemoryStatus(&ms);
-#define MEM_VAL(value) dw##value
-#else
+# define MEM_VAL(value) dw##value
+# else
MEMORYSTATUSEX ms;
DWORDLONG tv, tp, av, ap;
ms.dwLength = sizeof(ms);
if (0 == GlobalMemoryStatusEx(&ms)) {
return 0;
}
-#define MEM_VAL(value) ull##value
-#endif
+# define MEM_VAL(value) ull##value
+# endif
tv = ms.MEM_VAL(TotalPageFile);
tp = ms.MEM_VAL(TotalPhys);
av = ms.MEM_VAL(AvailPageFile);
if (linuxMajor >= 3 || ((linuxMajor >= 2) && (linuxMinor >= 6))) {
// new /proc/meminfo format since kernel 2.6.x
- // Rigorously, this test should check from the developping version 2.5.x
+ // Rigorously, this test should check from the developing version 2.5.x
// that introduced the new format...
enum
this->TotalPhysicalMemory = p;
this->TotalPhysicalMemory /= pagediv;
-#if defined(_SC_AVPHYS_PAGES)
+# if defined(_SC_AVPHYS_PAGES)
p = sysconf(_SC_AVPHYS_PAGES);
if (p < 0) {
return false;
this->AvailablePhysicalMemory = p;
this->AvailablePhysicalMemory /= pagediv;
-#endif
+# endif
return true;
#else
static_cast<size_t>(available_memory / 1048576);
}
-#ifdef VM_SWAPUSAGE
+# ifdef VM_SWAPUSAGE
// Virtual memory.
int mib[2] = { CTL_VM, VM_SWAPUSAGE };
size_t miblen = sizeof(mib) / sizeof(mib[0]);
static_cast<size_t>(swap.xsu_avail / 1048576);
this->TotalVirtualMemory = static_cast<size_t>(swap.xsu_total / 1048576);
}
-#else
+# else
this->AvailableVirtualMemory = 0;
this->TotalVirtualMemory = 0;
-#endif
+# endif
// CPU Info
len = sizeof(this->NumberOfPhysicalCPU);
// a 32 bit process on a 64 bit host the returned memory will be
// limited to 4GiB. So if this is a 32 bit process or if the sysconf
// method fails use the kstat interface.
-#if SIZEOF_VOID_P == 8
+# if SIZEOF_VOID_P == 8
if (this->QueryMemoryBySysconf()) {
return true;
}
-#endif
+# endif
char* tail;
unsigned long totalMemory =
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__)
int ctrl[2] = { CTL_HW, HW_PHYSMEM };
-#if defined(HW_PHYSMEM64)
+# if defined(HW_PHYSMEM64)
int64_t k;
ctrl[1] = HW_PHYSMEM64;
-#else
+# else
int k;
-#endif
+# endif
size_t sz = sizeof(k);
if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
this->NumberOfPhysicalCPU = k;
this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
-#if defined(HW_CPUSPEED)
+# if defined(HW_CPUSPEED)
ctrl[1] = HW_CPUSPEED;
if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
}
this->CPUSpeedInMHz = (float)k;
-#endif
+# endif
-#if defined(CPU_SSE)
+# if defined(CPU_SSE)
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_SSE;
}
this->Features.HasSSE = (k > 0);
-#endif
+# endif
-#if defined(CPU_SSE2)
+# if defined(CPU_SSE2)
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_SSE2;
}
this->Features.HasSSE2 = (k > 0);
-#endif
+# endif
-#if defined(CPU_CPUVENDOR)
+# if defined(CPU_CPUVENDOR)
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_CPUVENDOR;
char vbuf[25];
this->ChipID.Vendor = vbuf;
this->FindManufacturer();
-#endif
+# endif
return true;
#else
bool SystemInformationImplementation::QueryHPUXProcessor()
{
#if defined(__hpux)
-#if defined(KWSYS_SYS_HAS_MPCTL_H)
+# if defined(KWSYS_SYS_HAS_MPCTL_H)
int c = mpctl(MPC_GETNUMSPUS_SYS, 0, 0);
if (c <= 0) {
return false;
this->ChipID.Vendor = "Hewlett-Packard";
this->ChipID.Family = 0x200;
break;
-#if defined(CPU_HP_INTEL_EM_1_0) || defined(CPU_IA64_ARCHREV_0)
-#ifdef CPU_HP_INTEL_EM_1_0
+# if defined(CPU_HP_INTEL_EM_1_0) || defined(CPU_IA64_ARCHREV_0)
+# ifdef CPU_HP_INTEL_EM_1_0
case CPU_HP_INTEL_EM_1_0:
-#endif
-#ifdef CPU_IA64_ARCHREV_0
+# endif
+# ifdef CPU_IA64_ARCHREV_0
case CPU_IA64_ARCHREV_0:
-#endif
+# endif
this->ChipID.Vendor = "GenuineIntel";
this->Features.HasIA64 = true;
break;
-#endif
+# endif
default:
return false;
}
this->FindManufacturer();
return true;
-#else
+# else
return false;
-#endif
+# endif
#else
return false;
#endif
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXW));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# else
+# pragma warning(disable : 4996)
+# endif
+# endif
bOsVersionInfoEx = GetVersionExW((OSVERSIONINFOW*)&osvi);
if (!bOsVersionInfoEx) {
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
return false;
}
}
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# pragma warning(pop)
+# endif
switch (osvi.dwPlatformId) {
case VER_PLATFORM_WIN32_NT:
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
this->OSRelease = "XP";
}
-#ifdef VER_NT_WORKSTATION
+# ifdef VER_NT_WORKSTATION
// Test for product type.
if (bOsVersionInfoEx) {
if (osvi.wProductType == VER_NT_WORKSTATION) {
this->OSRelease = "7";
}
// VER_SUITE_PERSONAL may not be defined
-#ifdef VER_SUITE_PERSONAL
+# ifdef VER_SUITE_PERSONAL
else {
if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {
this->OSRelease += " Personal";
this->OSRelease += " Professional";
}
}
-#endif
+# endif
} else if (osvi.wProductType == VER_NT_SERVER) {
// Check for .NET Server instead of Windows XP.
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
osvi.dwBuildNumber & 0xFFFF);
this->OSVersion = operatingSystem;
} else
-#endif // VER_NT_WORKSTATION
+# endif // VER_NT_WORKSTATION
{
HKEY hKey;
wchar_t szProductType[80];
}
}
-#ifdef __APPLE__
+# ifdef __APPLE__
this->OSName = "Unknown Apple OS";
this->OSRelease = "Unknown product version";
this->OSVersion = "Unknown build version";
this->CallSwVers("-productName", this->OSName);
this->CallSwVers("-productVersion", this->OSRelease);
this->CallSwVers("-buildVersion", this->OSVersion);
-#endif
+# endif
#endif
#elif @KWSYS_USE___INT64@
typedef __int64 LongLong;
#else
-#error "No Long Long"
+# error "No Long Long"
#endif
friend class SystemInformationImplementation;
SystemInformationImplementation* Implementation;
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef __osf__
-#define _OSF_SOURCE
-#define _POSIX_C_SOURCE 199506L
-#define _XOPEN_SOURCE_EXTENDED
+# define _OSF_SOURCE
+# define _POSIX_C_SOURCE 199506L
+# define _XOPEN_SOURCE_EXTENDED
#endif
-#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || \
- defined(__BORLANDC__) || defined(__MINGW32__))
-#define KWSYS_WINDOWS_DIRS
+#if defined(_WIN32) && \
+ (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || \
+ defined(__MINGW32__))
+# define KWSYS_WINDOWS_DIRS
#else
-#if defined(__SUNPRO_CC)
-#include <fcntl.h>
-#endif
+# if defined(__SUNPRO_CC)
+# include <fcntl.h>
+# endif
#endif
#include "kwsysPrivate.h"
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Directory.hxx.in"
-#include "Encoding.hxx.in"
-#include "FStream.hxx.in"
-#include "RegularExpression.hxx.in"
-#include "SystemTools.hxx.in"
+# include "Directory.hxx.in"
+# include "Encoding.hxx.in"
+# include "FStream.hxx.in"
+# include "RegularExpression.hxx.in"
+# include "SystemTools.hxx.in"
#endif
#ifdef _MSC_VER
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 1375 /* base class destructor not virtual */
+# pragma set woff 1375 /* base class destructor not virtual */
#endif
#include <ctype.h>
#include <errno.h>
#ifdef __QNX__
-#include <malloc.h> /* for malloc/free on QNX */
+# include <malloc.h> /* for malloc/free on QNX */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#if defined(_WIN32) && !defined(_MSC_VER) && defined(__GNUC__)
-#include <strings.h> /* for strcasecmp */
+# include <strings.h> /* for strcasecmp */
#endif
#ifdef _MSC_VER
-#define umask _umask // Note this is still umask on Borland
+# define umask _umask // Note this is still umask on Borland
#endif
// support for realpath call
#ifndef _WIN32
-#include <limits.h>
-#include <pwd.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <utime.h>
-#ifndef __VMS
-#include <sys/param.h>
-#include <termios.h>
-#endif
-#include <signal.h> /* sigprocmask */
+# include <limits.h>
+# include <pwd.h>
+# include <sys/ioctl.h>
+# include <sys/time.h>
+# include <sys/wait.h>
+# include <unistd.h>
+# include <utime.h>
+# ifndef __VMS
+# include <sys/param.h>
+# include <termios.h>
+# endif
+# include <signal.h> /* sigprocmask */
#endif
// Windows API.
#if defined(_WIN32)
-#include <windows.h>
-#include <winioctl.h>
-#ifndef INVALID_FILE_ATTRIBUTES
-#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
-#endif
-#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#endif
+# include <windows.h>
+# include <winioctl.h>
+# ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+# endif
+# if defined(_MSC_VER) && _MSC_VER >= 1800
+# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# endif
#elif defined(__CYGWIN__)
-#include <windows.h>
-#undef _WIN32
+# include <windows.h>
+# undef _WIN32
#endif
#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
#endif
#ifdef __CYGWIN__
-#include <sys/cygwin.h>
+# include <sys/cygwin.h>
#endif
// getpwnam doesn't exist on Windows and Cray Xt3/Catamount
// same for TIOCGWINSZ
#if defined(_WIN32) || defined(__LIBCATAMOUNT__) || \
(defined(HAVE_GETPWNAM) && HAVE_GETPWNAM == 0)
-#undef HAVE_GETPWNAM
-#undef HAVE_TTY_INFO
+# undef HAVE_GETPWNAM
+# undef HAVE_TTY_INFO
#else
-#define HAVE_GETPWNAM 1
-#define HAVE_TTY_INFO 1
+# define HAVE_GETPWNAM 1
+# define HAVE_TTY_INFO 1
#endif
#define VTK_URL_PROTOCOL_REGEX "([a-zA-Z0-9]*)://(.*)"
"(.+)?"
#ifdef _MSC_VER
-#include <sys/utime.h>
+# include <sys/utime.h>
#else
-#include <utime.h>
+# include <utime.h>
#endif
// This is a hack to prevent warnings about these functions being
// declared but not referenced.
#if defined(__sgi) && !defined(__GNUC__)
-#include <sys/termios.h>
+# include <sys/termios.h>
namespace KWSYS_NAMESPACE {
class SystemToolsHack
{
}
#endif
-#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || \
- defined(__BORLANDC__) || defined(__MINGW32__))
-#include <direct.h>
-#include <io.h>
-#define _unlink unlink
+#if defined(_WIN32) && \
+ (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || \
+ defined(__MINGW32__))
+# include <direct.h>
+# include <io.h>
+# define _unlink unlink
#endif
/* The maximum length of a file name. */
#if defined(PATH_MAX)
-#define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX
+# define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX
#elif defined(MAXPATHLEN)
-#define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN
+# define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN
#else
-#define KWSYS_SYSTEMTOOLS_MAXPATH 16384
+# define KWSYS_SYSTEMTOOLS_MAXPATH 16384
#endif
#if defined(__WATCOMC__)
-#include <direct.h>
-#define _mkdir mkdir
-#define _rmdir rmdir
-#define _getcwd getcwd
-#define _chdir chdir
+# include <direct.h>
+# define _mkdir mkdir
+# define _rmdir rmdir
+# define _getcwd getcwd
+# define _chdir chdir
#endif
#if defined(__BEOS__) && !defined(__ZETA__)
-#include <be/kernel/OS.h>
-#include <be/storage/Path.h>
+# include <be/kernel/OS.h>
+# include <be/storage/Path.h>
// BeOS 5 doesn't have usleep(), but it has snooze(), which is identical.
static inline void usleep(unsigned int msec)
#endif
#ifdef KWSYS_WINDOWS_DIRS
-#include <wctype.h>
+# include <wctype.h>
inline int Mkdir(const std::string& dir)
{
}
inline int Chdir(const std::string& dir)
{
-#if defined(__BORLANDC__)
+# if defined(__BORLANDC__)
return chdir(dir.c_str());
-#else
+# else
return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
-#endif
+# endif
}
inline void Realpath(const std::string& path, std::string& resolved_path,
std::string* errorMessage = 0)
}
}
#else
-#include <sys/types.h>
+# include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
+# include <fcntl.h>
+# include <unistd.h>
inline int Mkdir(const std::string& dir)
{
return mkdir(dir.c_str(), 00777);
{
bool operator()(std::string const& l, std::string const& r) const
{
-#ifdef _MSC_VER
+# ifdef _MSC_VER
return _stricmp(l.c_str(), r.c_str()) < 0;
-#elif defined(__GNUC__)
+# elif defined(__GNUC__)
return strcasecmp(l.c_str(), r.c_str()) < 0;
-#else
+# else
return SystemTools::Strucmp(l.c_str(), r.c_str()) < 0;
-#endif
+# endif
}
};
environment values that may still reference memory we allocated. Then free
the memory. This will not affect any environment values we never set. */
-#ifdef __INTEL_COMPILER
-#pragma warning disable 444 /* base has non-virtual destructor */
-#endif
+# ifdef __INTEL_COMPILER
+# pragma warning disable 444 /* base has non-virtual destructor */
+# endif
class kwsysEnv : public kwsysEnvSet
{
~kwsysEnv()
{
for (iterator i = this->begin(); i != this->end(); ++i) {
-#if defined(_WIN32)
+# if defined(_WIN32)
const std::string s = Encoding::ToNarrow(*i);
kwsysUnPutEnv(s.c_str());
-#else
+# else
kwsysUnPutEnv(*i);
-#endif
+# endif
free(const_cast<envchar*>(*i));
}
}
bool Put(const char* env)
{
-#if defined(_WIN32)
+# if defined(_WIN32)
const std::wstring wEnv = Encoding::ToWide(env);
wchar_t* newEnv = _wcsdup(wEnv.c_str());
-#else
+# else
char* newEnv = strdup(env);
-#endif
+# endif
Free oldEnv(this->Release(newEnv));
this->insert(newEnv);
-#if defined(_WIN32)
+# if defined(_WIN32)
return _wputenv(newEnv) == 0;
-#else
+# else
return putenv(newEnv) == 0;
-#endif
+# endif
}
bool UnPut(const char* env)
{
-#if defined(_WIN32)
+# if defined(_WIN32)
const std::wstring wEnv = Encoding::ToWide(env);
Free oldEnv(this->Release(wEnv.c_str()));
-#else
+# else
Free oldEnv(this->Release(env));
-#endif
+# endif
return kwsysUnPutEnv(env) == 0;
}
};
#ifdef __BORLANDC__
&& (errno != EACCES)
#endif
- ) {
+ ) {
return false;
}
} else if (mode != KWSYS_NULLPTR) {
#if defined(_WIN32) && !defined(__CYGWIN__)
-#if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
-#define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
-#define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
-#else
-#define KWSYS_ST_KEY_WOW64_32KEY 0x0200
-#define KWSYS_ST_KEY_WOW64_64KEY 0x0100
-#endif
+# if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
+# define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
+# define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
+# else
+# define KWSYS_ST_KEY_WOW64_32KEY 0x0200
+# define KWSYS_ST_KEY_WOW64_64KEY 0x0100
+# endif
static bool SystemToolsParseRegistryKey(const std::string& key,
HKEY& primaryKey, std::string& second,
INVALID_FILE_ATTRIBUTES);
#else
// SCO OpenServer 5.0.7/3.2's command has 711 permission.
-#if defined(_SCO_DS)
+# if defined(_SCO_DS)
return access(filename.c_str(), F_OK) == 0;
-#else
+# else
return access(filename.c_str(), R_OK) == 0;
-#endif
+# endif
#endif
}
// long paths, but _wstat64 rejects paths with '?' in them, thinking
// they are wildcards.
std::wstring const& wpath = Encoding::ToWide(path);
-#if defined(__BORLANDC__)
+# if defined(__BORLANDC__)
return _wstati64(wpath.c_str(), buf);
-#else
+# else
return _wstat64(wpath.c_str(), buf);
-#endif
+# endif
#else
return stat(path.c_str(), buf);
#endif
}
struct timeval mtime;
gettimeofday(&mtime, 0);
-#if KWSYS_CXX_HAS_UTIMES
+# if KWSYS_CXX_HAS_UTIMES
struct timeval atime;
-#if KWSYS_CXX_STAT_HAS_ST_MTIM
+# if KWSYS_CXX_STAT_HAS_ST_MTIM
atime.tv_sec = st.st_atim.tv_sec;
atime.tv_usec = st.st_atim.tv_nsec / 1000;
-#elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
+# elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
atime.tv_sec = st.st_atimespec.tv_sec;
atime.tv_usec = st.st_atimespec.tv_nsec / 1000;
-#else
+# else
atime.tv_sec = st.st_atime;
atime.tv_usec = 0;
-#endif
+# endif
struct timeval times[2] = { atime, mtime };
if (utimes(filename.c_str(), times) < 0) {
return false;
}
-#else
+# else
struct utimbuf times = { st.st_atime, mtime.tv_sec };
if (utime(filename.c_str(), ×) < 0) {
return false;
}
-#endif
+# endif
#endif
return true;
}
if (stat(f2.c_str(), &s2) != 0) {
return false;
}
-#if KWSYS_CXX_STAT_HAS_ST_MTIM
+# if KWSYS_CXX_STAT_HAS_ST_MTIM
// Compare using nanosecond resolution.
if (s1.st_mtim.tv_sec < s2.st_mtim.tv_sec) {
*result = -1;
} else if (s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec) {
*result = 1;
}
-#elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
+# elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
// Compare using nanosecond resolution.
if (s1.st_mtimespec.tv_sec < s2.st_mtimespec.tv_sec) {
*result = -1;
} else if (s1.st_mtimespec.tv_nsec > s2.st_mtimespec.tv_nsec) {
*result = 1;
}
-#else
+# else
// Compare using 1 second resolution.
if (s1.st_mtime < s2.st_mtime) {
*result = -1;
} else if (s1.st_mtime > s2.st_mtime) {
*result = 1;
}
-#endif
+# endif
#else
// Windows version. Get the modification time from extended file attributes.
WIN32_FILE_ATTRIBUTE_DATA f1d;
// Also, reuse the loop to check for slash followed by another slash
if (!hasDoubleSlash && *(pos0 + 1) == '/' && *(pos0 + 2) == '/') {
-#ifdef _WIN32
+# ifdef _WIN32
// However, on windows if the first characters are both slashes,
// then keep them that way, so that network paths can be handled.
if (pos > 0) {
hasDoubleSlash = true;
}
-#else
+# else
hasDoubleSlash = true;
-#endif
+# endif
}
pos0++;
const std::string& destination, bool always)
{
Directory dir;
- dir.Load(source);
+ if (dir.Load(source) == 0) {
+ return false;
+ }
size_t fileNum;
if (!SystemTools::MakeDirectory(destination)) {
return false;
static bool IsJunction(const std::wstring& source)
{
-#ifdef FSCTL_GET_REPARSE_POINT
+# ifdef FSCTL_GET_REPARSE_POINT
const DWORD JUNCTION_ATTRS =
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
DWORD attrs = GetFileAttributesW(source.c_str());
return (success &&
(reparse_buffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT));
-#else
+# else
return false;
-#endif
+# endif
}
static bool DeleteJunction(const std::wstring& source)
{
-#ifdef FSCTL_DELETE_REPARSE_POINT
+# ifdef FSCTL_DELETE_REPARSE_POINT
// Adjust privileges so that we can succefully open junction points as
// read/write.
HANDLE token;
CloseHandle(dir);
return !!success;
-#else
+# else
return false;
-#endif
+# endif
}
#endif
#else
localSplit[sameCount] == remoteSplit[sameCount]
#endif
- ) {
+ ) {
// put the common parts of the path into the commonPath array
commonPath.push_back(localSplit[sameCount]);
// erase the common parts of the path from the original path arrays
static std::string GetCasePathName(std::string const& pathIn)
{
std::string casePath;
- std::vector<std::string> path_components;
- SystemTools::SplitPath(pathIn, path_components);
- if (path_components[0].empty()) // First component always exists.
- {
- // Relative paths cannot be converted.
+
+ // First check if the file is relative. We don't fix relative paths since the
+ // real case depends on the root directory and the given path fragment may
+ // have meaning elsewhere in the project.
+ if (!SystemTools::FileIsFullPath(pathIn)) {
+ // This looks unnecessary, but it allows for the return value optimization
+ // since all return paths return the same local variable.
casePath = pathIn;
return casePath;
}
+ std::vector<std::string> path_components;
+ SystemTools::SplitPath(pathIn, path_components);
+
// Start with root component.
std::vector<std::string>::size_type idx = 0;
casePath = path_components[idx++];
bool SystemTools::ComparePath(const std::string& c1, const std::string& c2)
{
#if defined(_WIN32) || defined(__APPLE__)
-#ifdef _MSC_VER
+# ifdef _MSC_VER
return _stricmp(c1.c_str(), c2.c_str()) == 0;
-#elif defined(__APPLE__) || defined(__GNUC__)
+# elif defined(__APPLE__) || defined(__GNUC__)
return strcasecmp(c1.c_str(), c2.c_str()) == 0;
-#else
+# else
return SystemTools::Strucmp(c1.c_str(), c2.c_str()) == 0;
-#endif
+# endif
#else
return c1 == c2;
#endif
return str;
}
-// Due to a buggy stream library on the HP and another on Mac OS X, we
-// need this very carefully written version of getline. Returns true
+// Convenience function around std::getline which removes a trailing carriage
+// return and can truncate the buffer as needed. Returns true
// if any data were read before the end-of-file was reached.
bool SystemTools::GetLineFromStream(std::istream& is, std::string& line,
bool* has_newline /* = 0 */,
long sizeLimit /* = -1 */)
{
- const int bufferSize = 1024;
- char buffer[bufferSize];
- bool haveData = false;
- bool haveNewline = false;
-
// Start with an empty line.
line = "";
- long leftToRead = sizeLimit;
-
// Early short circuit return if stream is no good. Just return
// false and the empty line. (Probably means caller tried to
// create a file stream with a non-existent file name...)
return false;
}
- // If no characters are read from the stream, the end of file has
- // been reached. Clear the fail bit just before reading.
- while (!haveNewline && leftToRead != 0 &&
- (static_cast<void>(is.clear(is.rdstate() & ~std::ios::failbit)),
- static_cast<void>(is.getline(buffer, bufferSize)),
- is.gcount() > 0)) {
- // We have read at least one byte.
- haveData = true;
-
- // If newline character was read the gcount includes the character
- // but the buffer does not: the end of line has been reached.
- size_t length = strlen(buffer);
- if (length < static_cast<size_t>(is.gcount())) {
- haveNewline = true;
- }
-
+ std::getline(is, line);
+ bool haveData = !line.empty() || !is.eof();
+ if (!line.empty()) {
// Avoid storing a carriage return character.
- if (length > 0 && buffer[length - 1] == '\r') {
- buffer[length - 1] = 0;
+ if (*line.rbegin() == '\r') {
+ line.resize(line.size() - 1);
}
// if we read too much then truncate the buffer
- if (leftToRead > 0) {
- if (static_cast<long>(length) > leftToRead) {
- buffer[leftToRead] = 0;
- leftToRead = 0;
- } else {
- leftToRead -= static_cast<long>(length);
- }
+ if (sizeLimit >= 0 && line.size() >= static_cast<size_t>(sizeLimit)) {
+ line.resize(sizeLimit);
}
-
- // Append the data read to the line.
- line.append(buffer);
}
// Return the results.
if (has_newline) {
- *has_newline = haveNewline;
+ *has_newline = !is.eof();
}
return haveData;
}
}
size_t dotPos = file.rfind('.');
const char* ext = dotPos == std::string::npos ? 0 : (file.c_str() + dotPos);
- if (ext && (Strucmp(ext, ".exe") == 0 || Strucmp(ext, ".com") == 0 ||
- Strucmp(ext, ".cmd") == 0 || Strucmp(ext, ".bat") == 0)) {
+ if (ext &&
+ (Strucmp(ext, ".exe") == 0 || Strucmp(ext, ".com") == 0 ||
+ Strucmp(ext, ".cmd") == 0 || Strucmp(ext, ".bat") == 0)) {
mode |= (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6));
}
#else
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(osvi);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# else
+# pragma warning(disable : 4996)
+# endif
+# endif
bOsVersionInfoEx = GetVersionExA((OSVERSIONINFOA*)&osvi);
if (!bOsVersionInfoEx) {
return 0;
}
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# pragma warning(pop)
+# endif
switch (osvi.dwPlatformId) {
- // Test for the Windows NT product family.
+ // Test for the Windows NT product family.
case VER_PLATFORM_WIN32_NT:
else {
HKEY hKey;
-#define BUFSIZE 80
+# define BUFSIZE 80
wchar_t szProductType[BUFSIZE];
DWORD dwBufLen = BUFSIZE;
LONG lRet;
break;
- // Test for the Windows 95 product family.
+ // Test for the Windows 95 product family.
case VER_PLATFORM_WIN32_WINDOWS:
} // namespace KWSYS_NAMESPACE
#if defined(_MSC_VER) && defined(_DEBUG)
-#include <crtdbg.h>
-#include <stdio.h>
-#include <stdlib.h>
+# include <crtdbg.h>
+# include <stdio.h>
+# include <stdlib.h>
namespace KWSYS_NAMESPACE {
static int SystemToolsDebugReport(int, char* message, int*)
#include <sys/stat.h>
#if !defined(_WIN32) || defined(__CYGWIN__)
-#include <unistd.h> // For access permissions for use with access()
+# include <unistd.h> // For access permissions for use with access()
#endif
// Required for va_list
* Cross platform wrapper for stat struct
*/
#if defined(_WIN32) && !defined(__CYGWIN__)
-#if defined(__BORLANDC__)
+# if defined(__BORLANDC__)
typedef struct stati64 Stat_t;
-#else
+# else
typedef struct _stat64 Stat_t;
-#endif
+# endif
#else
typedef struct stat Stat_t;
#endif
static bool GetShortPath(const std::string& path, std::string& result);
/**
- * Read line from file. Make sure to get everything. Due to a buggy stream
- * library on the HP and another on Mac OS X, we need this very carefully
- * written version of getline. Returns true if any data were read before the
+ * Read line from file. Make sure to read a full line and truncates it if
+ * requested via sizeLimit. Returns true if any data were read before the
* end-of-file was reached. If the has_newline argument is specified, it will
* be true when the line read had a newline character.
*/
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Terminal.h.in"
+# include "Terminal.h.in"
#endif
/* Configure support for this platform. */
#if defined(_WIN32) || defined(__CYGWIN__)
-#define KWSYS_TERMINAL_SUPPORT_CONSOLE
+# define KWSYS_TERMINAL_SUPPORT_CONSOLE
#endif
#if !defined(_WIN32)
-#define KWSYS_TERMINAL_ISATTY_WORKS
+# define KWSYS_TERMINAL_ISATTY_WORKS
#endif
/* Include needed system APIs. */
#include <string.h> /* strcmp */
#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
-#include <io.h> /* _get_osfhandle */
-#include <windows.h> /* SetConsoleTextAttribute */
+# include <io.h> /* _get_osfhandle */
+# include <windows.h> /* SetConsoleTextAttribute */
#endif
#if defined(KWSYS_TERMINAL_ISATTY_WORKS)
-#include <unistd.h> /* isatty */
+# include <unistd.h> /* isatty */
#else
-#include <sys/stat.h> /* fstat */
+# include <sys/stat.h> /* fstat */
#endif
static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
"xterm-88color",
"xterm-color",
"xterm-debian",
+ "xterm-kitty",
"xterm-termite",
0 };
#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
-#define KWSYS_TERMINAL_MASK_FOREGROUND \
- (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
-#define KWSYS_TERMINAL_MASK_BACKGROUND \
- (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
+# define KWSYS_TERMINAL_MASK_FOREGROUND \
+ (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | \
+ FOREGROUND_INTENSITY)
+# define KWSYS_TERMINAL_MASK_BACKGROUND \
+ (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | \
+ BACKGROUND_INTENSITY)
/* Get the Windows handle for a FILE stream. */
static HANDLE kwsysTerminalGetStreamHandle(FILE* stream)
/* Get the C-library file descriptor from the stream. */
int fd = fileno(stream);
-#if defined(__CYGWIN__)
+# if defined(__CYGWIN__)
/* Cygwin seems to have an extra pipe level. If the file descriptor
corresponds to stdout or stderr then obtain the matching windows
handle directly. */
} else if (fd == fileno(stderr)) {
return GetStdHandle(STD_ERROR_HANDLE);
}
-#endif
+# endif
/* Get the underlying Windows handle for the descriptor. */
return (HANDLE)_get_osfhandle(fd);
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysTerminal_cfprintf kwsys_ns(Terminal_cfprintf)
-#define kwsysTerminal_Color_e kwsys_ns(Terminal_Color_e)
-#define kwsysTerminal_Color_Normal kwsys_ns(Terminal_Color_Normal)
-#define kwsysTerminal_Color_ForegroundBlack \
- kwsys_ns(Terminal_Color_ForegroundBlack)
-#define kwsysTerminal_Color_ForegroundRed \
- kwsys_ns(Terminal_Color_ForegroundRed)
-#define kwsysTerminal_Color_ForegroundGreen \
- kwsys_ns(Terminal_Color_ForegroundGreen)
-#define kwsysTerminal_Color_ForegroundYellow \
- kwsys_ns(Terminal_Color_ForegroundYellow)
-#define kwsysTerminal_Color_ForegroundBlue \
- kwsys_ns(Terminal_Color_ForegroundBlue)
-#define kwsysTerminal_Color_ForegroundMagenta \
- kwsys_ns(Terminal_Color_ForegroundMagenta)
-#define kwsysTerminal_Color_ForegroundCyan \
- kwsys_ns(Terminal_Color_ForegroundCyan)
-#define kwsysTerminal_Color_ForegroundWhite \
- kwsys_ns(Terminal_Color_ForegroundWhite)
-#define kwsysTerminal_Color_ForegroundMask \
- kwsys_ns(Terminal_Color_ForegroundMask)
-#define kwsysTerminal_Color_BackgroundBlack \
- kwsys_ns(Terminal_Color_BackgroundBlack)
-#define kwsysTerminal_Color_BackgroundRed \
- kwsys_ns(Terminal_Color_BackgroundRed)
-#define kwsysTerminal_Color_BackgroundGreen \
- kwsys_ns(Terminal_Color_BackgroundGreen)
-#define kwsysTerminal_Color_BackgroundYellow \
- kwsys_ns(Terminal_Color_BackgroundYellow)
-#define kwsysTerminal_Color_BackgroundBlue \
- kwsys_ns(Terminal_Color_BackgroundBlue)
-#define kwsysTerminal_Color_BackgroundMagenta \
- kwsys_ns(Terminal_Color_BackgroundMagenta)
-#define kwsysTerminal_Color_BackgroundCyan \
- kwsys_ns(Terminal_Color_BackgroundCyan)
-#define kwsysTerminal_Color_BackgroundWhite \
- kwsys_ns(Terminal_Color_BackgroundWhite)
-#define kwsysTerminal_Color_BackgroundMask \
- kwsys_ns(Terminal_Color_BackgroundMask)
-#define kwsysTerminal_Color_ForegroundBold \
- kwsys_ns(Terminal_Color_ForegroundBold)
-#define kwsysTerminal_Color_BackgroundBold \
- kwsys_ns(Terminal_Color_BackgroundBold)
-#define kwsysTerminal_Color_AssumeTTY kwsys_ns(Terminal_Color_AssumeTTY)
-#define kwsysTerminal_Color_AssumeVT100 kwsys_ns(Terminal_Color_AssumeVT100)
-#define kwsysTerminal_Color_AttributeMask \
- kwsys_ns(Terminal_Color_AttributeMask)
+# define kwsysTerminal_cfprintf kwsys_ns(Terminal_cfprintf)
+# define kwsysTerminal_Color_e kwsys_ns(Terminal_Color_e)
+# define kwsysTerminal_Color_Normal kwsys_ns(Terminal_Color_Normal)
+# define kwsysTerminal_Color_ForegroundBlack \
+ kwsys_ns(Terminal_Color_ForegroundBlack)
+# define kwsysTerminal_Color_ForegroundRed \
+ kwsys_ns(Terminal_Color_ForegroundRed)
+# define kwsysTerminal_Color_ForegroundGreen \
+ kwsys_ns(Terminal_Color_ForegroundGreen)
+# define kwsysTerminal_Color_ForegroundYellow \
+ kwsys_ns(Terminal_Color_ForegroundYellow)
+# define kwsysTerminal_Color_ForegroundBlue \
+ kwsys_ns(Terminal_Color_ForegroundBlue)
+# define kwsysTerminal_Color_ForegroundMagenta \
+ kwsys_ns(Terminal_Color_ForegroundMagenta)
+# define kwsysTerminal_Color_ForegroundCyan \
+ kwsys_ns(Terminal_Color_ForegroundCyan)
+# define kwsysTerminal_Color_ForegroundWhite \
+ kwsys_ns(Terminal_Color_ForegroundWhite)
+# define kwsysTerminal_Color_ForegroundMask \
+ kwsys_ns(Terminal_Color_ForegroundMask)
+# define kwsysTerminal_Color_BackgroundBlack \
+ kwsys_ns(Terminal_Color_BackgroundBlack)
+# define kwsysTerminal_Color_BackgroundRed \
+ kwsys_ns(Terminal_Color_BackgroundRed)
+# define kwsysTerminal_Color_BackgroundGreen \
+ kwsys_ns(Terminal_Color_BackgroundGreen)
+# define kwsysTerminal_Color_BackgroundYellow \
+ kwsys_ns(Terminal_Color_BackgroundYellow)
+# define kwsysTerminal_Color_BackgroundBlue \
+ kwsys_ns(Terminal_Color_BackgroundBlue)
+# define kwsysTerminal_Color_BackgroundMagenta \
+ kwsys_ns(Terminal_Color_BackgroundMagenta)
+# define kwsysTerminal_Color_BackgroundCyan \
+ kwsys_ns(Terminal_Color_BackgroundCyan)
+# define kwsysTerminal_Color_BackgroundWhite \
+ kwsys_ns(Terminal_Color_BackgroundWhite)
+# define kwsysTerminal_Color_BackgroundMask \
+ kwsys_ns(Terminal_Color_BackgroundMask)
+# define kwsysTerminal_Color_ForegroundBold \
+ kwsys_ns(Terminal_Color_ForegroundBold)
+# define kwsysTerminal_Color_BackgroundBold \
+ kwsys_ns(Terminal_Color_BackgroundBold)
+# define kwsysTerminal_Color_AssumeTTY kwsys_ns(Terminal_Color_AssumeTTY)
+# define kwsysTerminal_Color_AssumeVT100 kwsys_ns(Terminal_Color_AssumeVT100)
+# define kwsysTerminal_Color_AttributeMask \
+ kwsys_ns(Terminal_Color_AttributeMask)
#endif
#if defined(__cplusplus)
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysTerminal_cfprintf
-#undef kwsysTerminal_Color_e
-#undef kwsysTerminal_Color_Normal
-#undef kwsysTerminal_Color_ForegroundBlack
-#undef kwsysTerminal_Color_ForegroundRed
-#undef kwsysTerminal_Color_ForegroundGreen
-#undef kwsysTerminal_Color_ForegroundYellow
-#undef kwsysTerminal_Color_ForegroundBlue
-#undef kwsysTerminal_Color_ForegroundMagenta
-#undef kwsysTerminal_Color_ForegroundCyan
-#undef kwsysTerminal_Color_ForegroundWhite
-#undef kwsysTerminal_Color_ForegroundMask
-#undef kwsysTerminal_Color_BackgroundBlack
-#undef kwsysTerminal_Color_BackgroundRed
-#undef kwsysTerminal_Color_BackgroundGreen
-#undef kwsysTerminal_Color_BackgroundYellow
-#undef kwsysTerminal_Color_BackgroundBlue
-#undef kwsysTerminal_Color_BackgroundMagenta
-#undef kwsysTerminal_Color_BackgroundCyan
-#undef kwsysTerminal_Color_BackgroundWhite
-#undef kwsysTerminal_Color_BackgroundMask
-#undef kwsysTerminal_Color_ForegroundBold
-#undef kwsysTerminal_Color_BackgroundBold
-#undef kwsysTerminal_Color_AssumeTTY
-#undef kwsysTerminal_Color_AssumeVT100
-#undef kwsysTerminal_Color_AttributeMask
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysTerminal_cfprintf
+# undef kwsysTerminal_Color_e
+# undef kwsysTerminal_Color_Normal
+# undef kwsysTerminal_Color_ForegroundBlack
+# undef kwsysTerminal_Color_ForegroundRed
+# undef kwsysTerminal_Color_ForegroundGreen
+# undef kwsysTerminal_Color_ForegroundYellow
+# undef kwsysTerminal_Color_ForegroundBlue
+# undef kwsysTerminal_Color_ForegroundMagenta
+# undef kwsysTerminal_Color_ForegroundCyan
+# undef kwsysTerminal_Color_ForegroundWhite
+# undef kwsysTerminal_Color_ForegroundMask
+# undef kwsysTerminal_Color_BackgroundBlack
+# undef kwsysTerminal_Color_BackgroundRed
+# undef kwsysTerminal_Color_BackgroundGreen
+# undef kwsysTerminal_Color_BackgroundYellow
+# undef kwsysTerminal_Color_BackgroundBlue
+# undef kwsysTerminal_Color_BackgroundMagenta
+# undef kwsysTerminal_Color_BackgroundCyan
+# undef kwsysTerminal_Color_BackgroundWhite
+# undef kwsysTerminal_Color_BackgroundMask
+# undef kwsysTerminal_Color_ForegroundBold
+# undef kwsysTerminal_Color_BackgroundBold
+# undef kwsysTerminal_Color_AssumeTTY
+# undef kwsysTerminal_Color_AssumeVT100
+# undef kwsysTerminal_Color_AttributeMask
+# endif
#endif
#endif
#include <functional> // equal_to
#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4284)
-#pragma warning(disable : 4786)
+# pragma warning(push)
+# pragma warning(disable : 4284)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
-#pragma set woff 1174
-#pragma set woff 1375
+# pragma set woff 1174
+# pragma set woff 1375
#endif
namespace @KWSYS_NAMESPACE@ {
} // namespace @KWSYS_NAMESPACE@
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
-#pragma reset woff 1174
-#pragma reset woff 1375
+# pragma reset woff 1174
+# pragma reset woff 1375
#endif
#if defined(_MSC_VER)
-#pragma warning(pop)
+# pragma warning(pop)
#endif
#endif
#include <functional> // equal_to
#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4284)
-#pragma warning(disable : 4786)
+# pragma warning(push)
+# pragma warning(disable : 4284)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
-#pragma set woff 1174
-#pragma set woff 1375
+# pragma set woff 1174
+# pragma set woff 1375
#endif
namespace @KWSYS_NAMESPACE@ {
} // namespace @KWSYS_NAMESPACE@
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
-#pragma reset woff 1174
-#pragma reset woff 1375
+# pragma reset woff 1174
+# pragma reset woff 1375
#endif
#if defined(_MSC_VER)
-#pragma warning(pop)
+# pragma warning(pop)
#endif
#endif
*
*/
#ifdef __BORLANDC__
-#pragma warn - 8027 /* 'for' not inlined. */
-#pragma warn - 8026 /* 'exception' not inlined. */
+# pragma warn - 8027 /* 'for' not inlined. */
+# pragma warn - 8026 /* 'exception' not inlined. */
#endif
#ifndef @KWSYS_NAMESPACE@_hashtable_hxx
-#define @KWSYS_NAMESPACE@_hashtable_hxx
-
-#include <@KWSYS_NAMESPACE@/Configure.hxx>
-
-#include <algorithm> // lower_bound
-#include <iterator> // iterator_traits
-#include <memory> // allocator
-#include <stddef.h> // size_t
-#include <utility> // pair
-#include <vector> // vector
-
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4284)
-#pragma warning(disable : 4786)
-#pragma warning(disable : 4512) /* no assignment operator for class */
-#endif
-#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 3970 /* pointer to int conversion */ 3321 3968
-#endif
+# define @KWSYS_NAMESPACE@_hashtable_hxx
+
+# include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+# include <algorithm> // lower_bound
+# include <iterator> // iterator_traits
+# include <memory> // allocator
+# include <stddef.h> // size_t
+# include <utility> // pair
+# include <vector> // vector
+
+# if defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable : 4284)
+# pragma warning(disable : 4786)
+# pragma warning(disable : 4512) /* no assignment operator for class */
+# endif
+# if defined(__sgi) && !defined(__GNUC__)
+# pragma set woff 3970 /* pointer to int conversion */ 3321 3968
+# endif
// In C++11, clang will warn about using dynamic exception specifications
// as they are deprecated. But as this class is trying to faithfully
// mimic unordered_set and unordered_map, we want to keep the 'throw()'
// decorations below. So we suppress the warning.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wdeprecated")
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated"
-#endif
-#endif
+# if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated"
+# endif
+# endif
namespace @KWSYS_NAMESPACE@ {
public:
typedef typename _Alloc::template rebind<_Val>::other allocator_type;
allocator_type get_allocator() const { return _M_node_allocator; }
+
private:
typedef
typename _Alloc::template rebind<_Node>::other _M_node_allocator_type;
template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
class _All>
_Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
- _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
+_Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
{
const _Node* __old = _M_cur;
_M_cur = _M_cur->_M_next;
template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
class _All>
inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
- _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
+_Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
{
iterator __tmp = *this;
++*this;
template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
class _All>
_Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
- _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
+_Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
{
const _Node* __old = _M_cur;
_M_cur = _M_cur->_M_next;
template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
class _All>
inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
- _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
+_Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
{
const_iterator __tmp = *this;
++*this;
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference hashtable<
- _Val, _Key, _HF, _Ex, _Eq, _All>::find_or_insert(const value_type& __obj)
+typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference
+hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::find_or_insert(
+ const value_type& __obj)
{
resize(_M_num_elements + 1);
_Node* __copy = _M_new_node(__cur->_M_val);
_M_buckets[__i] = __copy;
- for (_Node *__next = __cur->_M_next; __next;
+ for (_Node* __next = __cur->_M_next; __next;
__cur = __next, __next = __cur->_M_next) {
__copy->_M_next = _M_new_node(__next->_M_val);
__copy = __copy->_M_next;
} // namespace @KWSYS_NAMESPACE@
// Undo warning suppression.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wdeprecated")
-#pragma clang diagnostic pop
-#endif
-#endif
-
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
+# if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic pop
+# endif
+# endif
+
+# if defined(_MSC_VER)
+# pragma warning(pop)
+# endif
#endif
}
*/
#if defined(__CLASSIC_C__)
-#define KWSYS_PLATFORM_TEST_C_MAIN() main()
-#define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \
- main(argc, argv) int argc; \
- char* argv[];
+# define KWSYS_PLATFORM_TEST_C_MAIN() main()
+# define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \
+ main(argc, argv) int argc; \
+ char* argv[];
#else
-#define KWSYS_PLATFORM_TEST_C_MAIN() main(void)
-#define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \
- main(int argc, char* argv[])
+# define KWSYS_PLATFORM_TEST_C_MAIN() main(void)
+# define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \
+ main(int argc, char* argv[])
#endif
#ifdef TEST_KWSYS_C_HAS_PTRDIFF_T
-#include <stddef.h>
+# include <stddef.h>
int f(ptrdiff_t n)
{
return n > 0;
#endif
#ifdef TEST_KWSYS_C_HAS_SSIZE_T
-#include <unistd.h>
+# include <unistd.h>
int f(ssize_t n)
{
return (int)n;
#endif
#ifdef TEST_KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC
-#if defined(__APPLE__)
-#include <AvailabilityMacros.h>
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 101200
-#error "clock_gettime not available on macOS < 10.12"
-#endif
-#endif
-#include <time.h>
+# if defined(__APPLE__)
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MIN_REQUIRED < 101200
+# error "clock_gettime not available on macOS < 10.12"
+# endif
+# endif
+# include <time.h>
int KWSYS_PLATFORM_TEST_C_MAIN()
{
struct timespec ts;
#ifdef TEST_KWSYS_C_TYPE_MACROS
char* info_macros =
-#if defined(__SIZEOF_SHORT__)
+# if defined(__SIZEOF_SHORT__)
"INFO:macro[__SIZEOF_SHORT__]\n"
-#endif
-#if defined(__SIZEOF_INT__)
+# endif
+# if defined(__SIZEOF_INT__)
"INFO:macro[__SIZEOF_INT__]\n"
-#endif
-#if defined(__SIZEOF_LONG__)
+# endif
+# if defined(__SIZEOF_LONG__)
"INFO:macro[__SIZEOF_LONG__]\n"
-#endif
-#if defined(__SIZEOF_LONG_LONG__)
+# endif
+# if defined(__SIZEOF_LONG_LONG__)
"INFO:macro[__SIZEOF_LONG_LONG__]\n"
-#endif
-#if defined(__SHORT_MAX__)
+# endif
+# if defined(__SHORT_MAX__)
"INFO:macro[__SHORT_MAX__]\n"
-#endif
-#if defined(__INT_MAX__)
+# endif
+# if defined(__INT_MAX__)
"INFO:macro[__INT_MAX__]\n"
-#endif
-#if defined(__LONG_MAX__)
+# endif
+# if defined(__LONG_MAX__)
"INFO:macro[__LONG_MAX__]\n"
-#endif
-#if defined(__LONG_LONG_MAX__)
+# endif
+# if defined(__LONG_LONG_MAX__)
"INFO:macro[__LONG_LONG_MAX__]\n"
-#endif
+# endif
"";
int KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv)
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef TEST_KWSYS_CXX_HAS_CSTDIO
-#include <cstdio>
+# include <cstdio>
int main()
{
return 0;
#endif
#ifdef TEST_KWSYS_CXX_STAT_HAS_ST_MTIM
-#include <sys/types.h>
+# include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
+# include <sys/stat.h>
+# include <unistd.h>
int main()
{
struct stat stat1;
#endif
#ifdef TEST_KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
-#include <sys/types.h>
+# include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
+# include <sys/stat.h>
+# include <unistd.h>
int main()
{
struct stat stat1;
#endif
#ifdef TEST_KWSYS_IOS_HAS_ISTREAM_LONG_LONG
-#include <iostream>
+# include <iostream>
int test_istream(std::istream& is, long long& x)
{
return (is >> x) ? 1 : 0;
#endif
#ifdef TEST_KWSYS_IOS_HAS_OSTREAM_LONG_LONG
-#include <iostream>
+# include <iostream>
int test_ostream(std::ostream& os, long long x)
{
return (os << x) ? 1 : 0;
#endif
#ifdef TEST_KWSYS_IOS_HAS_ISTREAM___INT64
-#include <iostream>
+# include <iostream>
int test_istream(std::istream& is, __int64& x)
{
return (is >> x) ? 1 : 0;
#endif
#ifdef TEST_KWSYS_IOS_HAS_OSTREAM___INT64
-#include <iostream>
+# include <iostream>
int test_ostream(std::ostream& os, __int64 x)
{
return (os << x) ? 1 : 0;
#ifdef TEST_KWSYS_LFS_WORKS
/* Return 0 when LFS is available and 1 otherwise. */
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-#define _LARGE_FILES
-#define _FILE_OFFSET_BITS 64
-#include <sys/types.h>
-
-#include <assert.h>
-#include <sys/stat.h>
-#if KWSYS_CXX_HAS_CSTDIO
-#include <cstdio>
-#endif
-#include <stdio.h>
+# define _LARGEFILE_SOURCE
+# define _LARGEFILE64_SOURCE
+# define _LARGE_FILES
+# define _FILE_OFFSET_BITS 64
+# include <sys/types.h>
+
+# include <assert.h>
+# include <sys/stat.h>
+# if KWSYS_CXX_HAS_CSTDIO
+# include <cstdio>
+# endif
+# include <stdio.h>
int main(int, char** argv)
{
/* check that off_t can hold 2^63 - 1 and perform basic operations... */
-#define OFF_T_64 (((off_t)1 << 62) - 1 + ((off_t)1 << 62))
+# define OFF_T_64 (((off_t)1 << 62) - 1 + ((off_t)1 << 62))
if (OFF_T_64 % 2147483647 != 1)
return 1;
#endif
#ifdef TEST_KWSYS_CXX_HAS_SETENV
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
return setenv("A", "B", 1);
#endif
#ifdef TEST_KWSYS_CXX_HAS_UNSETENV
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
unsetenv("A");
#endif
#ifdef TEST_KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
char* e = environ[0];
#ifdef TEST_KWSYS_CXX_HAS_GETLOADAVG
// Match feature definitions from SystemInformation.cxx
-#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#include <stdlib.h>
+# if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+# endif
+# include <stdlib.h>
int main()
{
double loadavg[3] = { 0.0, 0.0, 0.0 };
#endif
#ifdef TEST_KWSYS_CXX_HAS_RLIMIT64
-#if defined(KWSYS_HAS_LFS)
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-#define _LARGE_FILES
-#define _FILE_OFFSET_BITS 64
-#endif
-#include <sys/resource.h>
+# if defined(KWSYS_HAS_LFS)
+# define _LARGEFILE_SOURCE
+# define _LARGEFILE64_SOURCE
+# define _LARGE_FILES
+# define _FILE_OFFSET_BITS 64
+# endif
+# include <sys/resource.h>
int main()
{
struct rlimit64 rlim;
#endif
#ifdef TEST_KWSYS_CXX_HAS_ATOLL
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
const char* str = "1024";
#endif
#ifdef TEST_KWSYS_CXX_HAS_ATOL
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
const char* str = "1024";
#endif
#ifdef TEST_KWSYS_CXX_HAS__ATOI64
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
const char* str = "1024";
#endif
#ifdef TEST_KWSYS_CXX_HAS_UTIMES
-#include <sys/time.h>
+# include <sys/time.h>
int main()
{
struct timeval* current_time = 0;
#endif
#ifdef TEST_KWSYS_CXX_HAS_UTIMENSAT
-#include <fcntl.h>
-#include <sys/stat.h>
-#if defined(__APPLE__)
-#include <AvailabilityMacros.h>
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 101300
-#error "utimensat not available on macOS < 10.13"
-#endif
-#endif
+# include <fcntl.h>
+# include <sys/stat.h>
+# if defined(__APPLE__)
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MIN_REQUIRED < 101300
+# error "utimensat not available on macOS < 10.13"
+# endif
+# endif
int main()
{
struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, UTIME_NOW } };
#endif
#ifdef TEST_KWSYS_CXX_HAS_BACKTRACE
-#if defined(__PATHSCALE__) || defined(__PATHCC__) || \
- (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41))
+# if defined(__PATHSCALE__) || defined(__PATHCC__) || \
+ (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41))
backtrace does not work with this compiler or os
-#endif
-#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#include <execinfo.h>
+# endif
+# if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+# endif
+# include <execinfo.h>
int main()
{
void* stackSymbols[256];
#endif
#ifdef TEST_KWSYS_CXX_HAS_DLADDR
-#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#include <dlfcn.h>
+# if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+# endif
+# include <dlfcn.h>
int main()
{
Dl_info info;
#endif
#ifdef TEST_KWSYS_CXX_HAS_CXXABI
-#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#if defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5130 && __linux && \
- __SUNPRO_CC_COMPAT == 'G'
-#include <iostream>
-#endif
-#include <cxxabi.h>
+# if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+# endif
+# if defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5130 && __linux && \
+ __SUNPRO_CC_COMPAT == 'G'
+# include <iostream>
+# endif
+# include <cxxabi.h>
int main()
{
int status = 0;
#endif
#ifdef TEST_KWSYS_STL_HAS_WSTRING
-#include <string>
+# include <string>
void f(std::wstring*)
{
}
#endif
#ifdef TEST_KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H
-#include <ext/stdio_filebuf.h>
+# include <ext/stdio_filebuf.h>
int main()
{
return 0;
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifndef KWSYS_NAMESPACE
-#error "Do not include kwsysPrivate.h outside of kwsys c and cxx files."
+# error "Do not include kwsysPrivate.h outside of kwsys c and cxx files."
#endif
#ifndef _kwsysPrivate_h
-#define _kwsysPrivate_h
+# define _kwsysPrivate_h
/*
Define KWSYS_HEADER macro to help the c and cxx files include kwsys
/* clang-format off */
#define KWSYS_HEADER(x) KWSYS_HEADER0(KWSYS_NAMESPACE/x)
/* clang-format on */
-#define KWSYS_HEADER0(x) KWSYS_HEADER1(x)
-#define KWSYS_HEADER1(x) <x>
+# define KWSYS_HEADER0(x) KWSYS_HEADER1(x)
+# define KWSYS_HEADER1(x) <x>
/*
Define KWSYS_NAMESPACE_STRING to be a string constant containing the
name configured for this instance of the kwsys library.
*/
-#define KWSYS_NAMESPACE_STRING KWSYS_NAMESPACE_STRING0(KWSYS_NAMESPACE)
-#define KWSYS_NAMESPACE_STRING0(x) KWSYS_NAMESPACE_STRING1(x)
-#define KWSYS_NAMESPACE_STRING1(x) #x
+# define KWSYS_NAMESPACE_STRING KWSYS_NAMESPACE_STRING0(KWSYS_NAMESPACE)
+# define KWSYS_NAMESPACE_STRING0(x) KWSYS_NAMESPACE_STRING1(x)
+# define KWSYS_NAMESPACE_STRING1(x) # x
#else
-#error "kwsysPrivate.h included multiple times."
+# error "kwsysPrivate.h included multiple times."
#endif
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "CommandLineArguments.hxx.in"
+# include "CommandLineArguments.hxx.in"
#endif
#include <iostream>
arg.AddCallback("-C", argT::EQUAL_ARGUMENT, argument, random_ptr,
"Option -C takes argument after =");
arg.AddCallback("-D", argT::CONCAT_ARGUMENT, argument, random_ptr,
- "This option takes concatinated argument");
+ "This option takes concatenated argument");
arg.AddCallback("--long1", argT::NO_ARGUMENT, argument, random_ptr, "-A");
arg.AddCallback("--long2", argT::SPACE_ARGUMENT, argument, random_ptr, "-B");
arg.AddCallback("--long3", argT::EQUAL_ARGUMENT, argument, random_ptr,
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "CommandLineArguments.hxx.in"
+# include "CommandLineArguments.hxx.in"
#endif
#include <iostream>
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Configure.hxx.in"
+# include "Configure.hxx.in"
#endif
static bool testFallthrough(int n)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Encoding.hxx.in"
+# include "Encoding.hxx.in"
#endif
#if defined(_WIN32)
-#include <algorithm>
-#include <iomanip>
-#include <iostream>
-#include <stdexcept>
-#include <string.h>
-#include <wchar.h>
-#include <windows.h>
+# include <algorithm>
+# include <iomanip>
+# include <iostream>
+# include <stdexcept>
+# include <string.h>
+# include <wchar.h>
+# include <windows.h>
-#include "testConsoleBuf.hxx"
+# include "testConsoleBuf.hxx"
-#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersion
-#endif
+# if defined(_MSC_VER) && _MSC_VER >= 1800
+# define KWSYS_WINDOWS_DEPRECATED_GetVersion
+# endif
// يونيكود
static const WCHAR UnicodeInputTestString[] =
L"\u064A\u0648\u0646\u064A\u0643\u0648\u062F!";
}
}
-#ifndef MAPVK_VK_TO_VSC
-#define MAPVK_VK_TO_VSC (0)
-#endif
+# ifndef MAPVK_VK_TO_VSC
+# define MAPVK_VK_TO_VSC (0)
+# endif
static void writeInputKeyEvent(INPUT_RECORD inputBuffer[], WCHAR chr)
{
return didFail;
}
-#ifndef _WIN32_WINNT_VISTA
-#define _WIN32_WINNT_VISTA 0x0600
-#endif
+# ifndef _WIN32_WINNT_VISTA
+# define _WIN32_WINNT_VISTA 0x0600
+# endif
static int testConsole()
{
DWORD FaceNameSize = sizeof(FaceName);
DWORD FontFamily = TestFontFamily;
DWORD FontSize = TestFontSize;
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# else
+# pragma warning(disable : 4996)
+# endif
+# endif
const bool isVistaOrGreater =
LOBYTE(LOWORD(GetVersion())) >= HIBYTE(_WIN32_WINNT_VISTA);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
-#pragma warning(pop)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
+# pragma warning(pop)
+# endif
if (!isVistaOrGreater) {
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ | KEY_WRITE,
&hConsoleKey) == ERROR_SUCCESS) {
newConsole = true;
}
-#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
+# if _WIN32_WINNT >= _WIN32_WINNT_VISTA
if (isVistaOrGreater) {
CONSOLE_FONT_INFOEX consoleFont;
memset(&consoleFont, 0, sizeof(consoleFont));
std::cerr << "GetCurrentConsoleFontEx failed!" << std::endl;
}
} else {
-#endif
+# endif
if (restoreConsole &&
RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_WRITE,
&hConsoleKey) == ERROR_SUCCESS) {
sizeof(FontSize));
RegCloseKey(hConsoleKey);
}
-#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
+# if _WIN32_WINNT >= _WIN32_WINNT_VISTA
}
-#endif
+# endif
if (createProcess(NULL, NULL, NULL)) {
try {
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "ConsoleBuf.hxx.in"
-#include "Encoding.hxx.in"
+# include "ConsoleBuf.hxx.in"
+# include "Encoding.hxx.in"
#endif
#include <iostream>
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Directory.hxx.in"
-#include "Encoding.hxx.in"
-#include "SystemTools.hxx.in"
+# include "Directory.hxx.in"
+# include "Encoding.hxx.in"
+# include "SystemTools.hxx.in"
#endif
#include <fstream>
return res;
}
+int _copyDirectoryTest()
+{
+ using namespace kwsys;
+ const std::string source(TEST_SYSTEMTOOLS_BINARY_DIR
+ "/directory_testing/copyDirectoryTestSrc");
+ if (SystemTools::PathExists(source)) {
+ std::cerr << source << " shouldn't exist before test" << std::endl;
+ return 1;
+ }
+ const std::string destination(TEST_SYSTEMTOOLS_BINARY_DIR
+ "/directory_testing/copyDirectoryTestDst");
+ if (SystemTools::PathExists(destination)) {
+ std::cerr << destination << " shouldn't exist before test" << std::endl;
+ return 2;
+ }
+ const bool copysuccess = SystemTools::CopyADirectory(source, destination);
+ const bool destinationexists = SystemTools::PathExists(destination);
+ if (copysuccess) {
+ std::cerr << "CopyADirectory should have returned false" << std::endl;
+ SystemTools::RemoveADirectory(destination);
+ return 3;
+ }
+ if (destinationexists) {
+ std::cerr << "CopyADirectory returned false, but destination directory"
+ << " has been created" << std::endl;
+ SystemTools::RemoveADirectory(destination);
+ return 4;
+ }
+ return 0;
+}
+
int testDirectory(int, char* [])
{
- return _doLongPathTest();
+ return _doLongPathTest() + _copyDirectoryTest();
}
#include KWSYS_HEADER(DynamicLoader.hxx)
#if defined(__BEOS__) || defined(__HAIKU__)
-#include <be/kernel/OS.h> /* disable_debugger() API. */
+# include <be/kernel/OS.h> /* disable_debugger() API. */
#endif
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "DynamicLoader.hxx.in"
+# include "DynamicLoader.hxx.in"
#endif
#include <iostream>
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef _WIN32
-#define DL_EXPORT __declspec(dllexport)
+# define DL_EXPORT __declspec(dllexport)
#else
-#define DL_EXPORT
+# define DL_EXPORT
#endif
DL_EXPORT int TestDynamicLoaderData = 0;
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "MD5.h.in"
+# include "MD5.h.in"
#endif
#include <stdio.h>
#include "kwsysPrivate.h"
#if defined(_MSC_VER)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#include KWSYS_HEADER(Encoding.hxx)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Encoding.h.in"
-#include "Encoding.hxx.in"
+# include "Encoding.h.in"
+# include "Encoding.hxx.in"
#endif
static const unsigned char helloWorldStrings[][32] = {
#include "kwsysPrivate.h"
#if defined(_MSC_VER)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#include KWSYS_HEADER(FStream.hxx)
#include <string.h>
#ifdef __BORLANDC__
-#include <mem.h> /* memcmp */
+# include <mem.h> /* memcmp */
#endif
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "FStream.hxx.in"
+# include "FStream.hxx.in"
#endif
#include <iostream>
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "hash_map.hxx.in"
-#include "hash_set.hxx.in"
+# include "hash_map.hxx.in"
+# include "hash_set.hxx.in"
#endif
#include <iostream>
#if defined(_MSC_VER)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 1468 /* inline function cannot be explicitly instantiated */
+# pragma set woff 1468 /* inline function cannot be explicitly instantiated \
+ */
#endif
template class kwsys::hash_map<const char*, int>;
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Encoding.h.in"
-#include "Process.h.in"
+# include "Encoding.h.in"
+# include "Process.h.in"
#endif
#include <assert.h>
#include <string.h>
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <signal.h>
-#include <unistd.h>
+# include <signal.h>
+# include <unistd.h>
#endif
#if defined(__BORLANDC__)
-#pragma warn - 8060 /* possibly incorrect assignment */
+# pragma warn - 8060 /* possibly incorrect assignment */
#endif
/* Platform-specific sleep functions. */
#if defined(__BEOS__) && !defined(__ZETA__)
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
-#include <be/kernel/OS.h>
+# include <be/kernel/OS.h>
static inline void testProcess_usleep(unsigned int usec)
{
snooze(usec);
Sleep(usec / 1000);
}
#else
-#define testProcess_usleep usleep
+# define testProcess_usleep usleep
#endif
#if defined(_WIN32)
if (result) {
if (exception != kwsysProcess_GetExitException(kp)) {
- fprintf(stderr, "Mismatch in exit exception. "
- "Should have been %d, was %d.\n",
+ fprintf(stderr,
+ "Mismatch in exit exception. "
+ "Should have been %d, was %d.\n",
exception, kwsysProcess_GetExitException(kp));
}
if (value != kwsysProcess_GetExitValue(kp)) {
- fprintf(stderr, "Mismatch in exit value. "
- "Should have been %d, was %d.\n",
+ fprintf(stderr,
+ "Mismatch in exit value. "
+ "Should have been %d, was %d.\n",
value, kwsysProcess_GetExitValue(kp));
}
}
if (kwsysProcess_GetState(kp) != state) {
- fprintf(stderr, "Mismatch in state. "
- "Should have been %d, was %d.\n",
+ fprintf(stderr,
+ "Mismatch in state. "
+ "Should have been %d, was %d.\n",
state, kwsysProcess_GetState(kp));
result = 1;
}
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#if defined(CMAKE_INTDIR)
-#define CONFIG_DIR_PRE CMAKE_INTDIR "/"
-#define CONFIG_DIR_POST "/" CMAKE_INTDIR
+# define CONFIG_DIR_PRE CMAKE_INTDIR "/"
+# define CONFIG_DIR_POST "/" CMAKE_INTDIR
#else
-#define CONFIG_DIR_PRE ""
-#define CONFIG_DIR_POST ""
+# define CONFIG_DIR_PRE ""
+# define CONFIG_DIR_POST ""
#endif
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD "@EXEC_DIR@"
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD "." CONFIG_DIR_POST
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT "--print"
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD "--ldd"
#if defined(CMAKE_INTDIR)
-#define @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME CMAKE_INTDIR
+# define @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME CMAKE_INTDIR
#endif
#include <@KWSYS_NAMESPACE@/SharedForward.h>
int main(int argc, char** argv)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "SystemInformation.hxx.in"
+# include "SystemInformation.hxx.in"
#endif
#include <iostream>
#if defined(KWSYS_USE_LONG_LONG)
-#if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
-#define iostreamLongLong(x) (x)
-#else
-#define iostreamLongLong(x) ((long)x)
-#endif
+# if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
#elif defined(KWSYS_USE___INT64)
-#if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
-#define iostreamLongLong(x) (x)
+# if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
#else
-#define iostreamLongLong(x) ((long)x)
-#endif
-#else
-#error "No Long Long"
+# error "No Long Long"
#endif
#define printMethod(info, m) std::cout << #m << ": " << info.m() << "\n"
}
/* test stack trace
- */
+ */
std::cout << "Program Stack:" << std::endl
<< kwsys::SystemInformation::GetProgramStack(0, 0) << std::endl
<< std::endl;
#include "kwsysPrivate.h"
#if defined(_MSC_VER)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#include KWSYS_HEADER(FStream.hxx)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "FStream.hxx.in"
-#include "SystemTools.hxx.in"
+# include "FStream.hxx.in"
+# include "SystemTools.hxx.in"
#endif
// Include with <> instead of "" to avoid getting any in-source copy
#include <stdlib.h> /* free */
#include <string.h> /* strcmp */
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h> /* _umask (MSVC) / umask (Borland) */
-#ifdef _MSC_VER
-#define umask _umask // Note this is still umask on Borland
-#endif
+# include <io.h> /* _umask (MSVC) / umask (Borland) */
+# ifdef _MSC_VER
+# define umask _umask // Note this is still umask on Borland
+# endif
#endif
#include <sys/stat.h> /* umask (POSIX), _S_I* constants (Windows) */
// Visual C++ does not define mode_t (note that Borland does, however).
#endif
const char* registryPath = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MyApp; MyKey]";
- std::vector<std::string> originalPathes;
- originalPathes.push_back(registryPath);
+ std::vector<std::string> originalPaths;
+ originalPaths.push_back(registryPath);
- std::vector<std::string> expectedPathes;
- expectedPathes.push_back(registryPath);
+ std::vector<std::string> expectedPaths;
+ expectedPaths.push_back(registryPath);
#ifdef _WIN32
- expectedPathes.push_back("C:/Somewhere/something");
- expectedPathes.push_back("D:/Temp");
+ expectedPaths.push_back("C:/Somewhere/something");
+ expectedPaths.push_back("D:/Temp");
#else
- expectedPathes.push_back("/Somewhere/something");
- expectedPathes.push_back("/tmp");
+ expectedPaths.push_back("/Somewhere/something");
+ expectedPaths.push_back("/tmp");
#endif
bool res = true;
res &= CheckPutEnv(std::string(envName) + "=" + envValue, envName, envValue);
- std::vector<std::string> pathes = originalPathes;
- kwsys::SystemTools::GetPath(pathes, envName);
+ std::vector<std::string> paths = originalPaths;
+ kwsys::SystemTools::GetPath(paths, envName);
- if (pathes != expectedPathes) {
- std::cerr << "GetPath(" << StringVectorToString(originalPathes) << ", "
- << envName << ") yielded " << StringVectorToString(pathes)
- << " instead of " << StringVectorToString(expectedPathes)
+ if (paths != expectedPaths) {
+ std::cerr << "GetPath(" << StringVectorToString(originalPaths) << ", "
+ << envName << ") yielded " << StringVectorToString(paths)
+ << " instead of " << StringVectorToString(expectedPaths)
<< std::endl;
res = false;
}
return ret;
}
+static bool CheckGetLineFromStreamLongLine()
+{
+ const std::string fileWithLongLine("longlines.txt");
+ std::string firstLine, secondLine;
+ // First line: large buffer, containing a carriage return for some reason.
+ firstLine.assign(2050, ' ');
+ firstLine += "\rfirst";
+ secondLine.assign(2050, 'y');
+ secondLine += "second";
+
+ // Create file with long lines.
+ {
+ kwsys::ofstream out(fileWithLongLine.c_str(), std::ios::binary);
+ if (!out) {
+ std::cerr << "Problem opening for write: " << fileWithLongLine
+ << std::endl;
+ return false;
+ }
+ out << firstLine << "\r\n\n" << secondLine << "\n";
+ }
+
+ kwsys::ifstream file(fileWithLongLine.c_str(), std::ios::binary);
+ if (!file) {
+ std::cerr << "Problem opening: " << fileWithLongLine << std::endl;
+ return false;
+ }
+
+ std::string line;
+ bool has_newline = false;
+ bool result;
+
+ // Read first line.
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || line != firstLine) {
+ std::cerr << "First line does not match, expected " << firstLine.size()
+ << " characters, got " << line.size() << std::endl;
+ return false;
+ }
+ if (!has_newline) {
+ std::cerr << "Expected new line to be read from first line" << std::endl;
+ return false;
+ }
+
+ // Read empty line.
+ has_newline = false;
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || !line.empty()) {
+ std::cerr << "Expected successful read with an empty line, got "
+ << line.size() << " characters" << std::endl;
+ return false;
+ }
+ if (!has_newline) {
+ std::cerr << "Expected new line to be read for an empty line" << std::endl;
+ return false;
+ }
+
+ // Read second line.
+ has_newline = false;
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || line != secondLine) {
+ std::cerr << "Second line does not match, expected " << secondLine.size()
+ << " characters, got " << line.size() << std::endl;
+ return false;
+ }
+ if (!has_newline) {
+ std::cerr << "Expected new line to be read from second line" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
int testSystemTools(int, char* [])
{
bool res = true;
res &= CheckGetLineFromStream();
+ res &= CheckGetLineFromStreamLongLine();
+
res &= CheckGetFilenameName();
return res ? 0 : 1;
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Terminal.h.in"
+# include "Terminal.h.in"
#endif
int testTerminal(int argc, char* argv[])
/* Create map. */
-typedef int (*MainFuncPointer)(int, char* []);
-typedef struct
+typedef int (*MainFuncPointer)(int, char* []); /* NOLINT */
+typedef struct /* NOLINT */
{
const char* name;
MainFuncPointer func;
#ifndef FOO_DEFINE
-#error Expected FOO_DEFINE
+# error Expected FOO_DEFINE
#endif
#ifndef BAR_DEFINE
-#error Expected Bar_DEFINE
+# error Expected Bar_DEFINE
#endif
#include "commandoutput.h"
#ifndef COMMANDOUTPUT_DEFINE
-#error Expected COMMANDOUTPUT_DEFINE
+# error Expected COMMANDOUTPUT_DEFINE
#endif
#include "targetoutput.h"
#ifndef TARGETOUTPUT_DEFINE
-#error Expected TARGETOUTPUT_DEFINE
+# error Expected TARGETOUTPUT_DEFINE
#endif
#ifdef _WIN32
list(APPEND _cmake_options "-DCMAKE_FORCE_DEPFILES=1")
-if(NOT CMAKE_GENERATOR MATCHES "Visual Studio ([^89]|[89][0-9])")
+if(NOT CMAKE_GENERATOR MATCHES "Visual Studio ([^9]|9[0-9])")
set(TEST_MULTI3 1)
list(APPEND _cmake_options "-DTEST_MULTI3=1")
endif()
cmake_minimum_required(VERSION 2.6)
project(testRebuild)
-function(test_for_xcode4 result_var)
- set(${result_var} 0 PARENT_SCOPE)
- if(APPLE)
- execute_process(COMMAND xcodebuild -version
- OUTPUT_VARIABLE ov RESULT_VARIABLE rv
+if(APPLE)
+ set(CMake_TEST_XCODE_VERSION 0)
+ if(XCODE_VERSION)
+ set(CMake_TEST_XCODE_VERSION "${XCODE_VERSION}")
+ else()
+ execute_process(
+ COMMAND xcodebuild -version
+ OUTPUT_VARIABLE _version ERROR_VARIABLE _version
)
- if("${rv}" STREQUAL "0" AND ov MATCHES "^Xcode ([0-9]+)\\.")
- if(NOT CMAKE_MATCH_1 VERSION_LESS 4)
- set(${result_var} 1 PARENT_SCOPE)
- endif()
+ if(_version MATCHES "^Xcode ([0-9]+(\\.[0-9]+)*)")
+ set(CMake_TEST_XCODE_VERSION "${CMAKE_MATCH_1}")
endif()
endif()
-endfunction()
-
-if(APPLE)
# only use multi-arch if the sysroot exists on this machine
# Ninja needs -M which could not be used with multiple -arch flags
if(EXISTS "${CMAKE_OSX_SYSROOT}" AND NOT "${CMAKE_GENERATOR}" MATCHES "Ninja")
- set(CMAKE_OSX_ARCHITECTURES "ppc;i386")
- test_for_xcode4(is_xcode4)
- if(is_xcode4)
- # Xcode 4, use modern architectures as defaults
- # Arch 'ppc' no longer works: tools no longer available starting with Xcode 4
+ if(CMake_TEST_XCODE_VERSION VERSION_GREATER_EQUAL 10)
+ # Arch 'i386' no longer works in Xcode 10.
+ set(CMAKE_OSX_ARCHITECTURES x86_64)
+ elseif(CMake_TEST_XCODE_VERSION VERSION_GREATER_EQUAL 4)
+ # Arch 'ppc' no longer works in Xcode 4.
set(CMAKE_OSX_ARCHITECTURES i386 x86_64)
+ else()
+ set(CMAKE_OSX_ARCHITECTURES ppc i386)
endif()
endif()
endif()
int fileExists(char* filename)
{
#ifndef R_OK
-#define R_OK 04
+# define R_OK 04
#endif
if (access(filename, R_OK) != 0) {
printf("Cannot find file: %s\n", filename);
#define framework_h
#ifdef WIN32
-#ifdef framework_EXPORTS
-#define FRAMEWORK_EXPORT __declspec(dllexport)
+# ifdef framework_EXPORTS
+# define FRAMEWORK_EXPORT __declspec(dllexport)
+# else
+# define FRAMEWORK_EXPORT __declspec(dllimport)
+# endif
#else
-#define FRAMEWORK_EXPORT __declspec(dllimport)
-#endif
-#else
-#define FRAMEWORK_EXPORT
+# define FRAMEWORK_EXPORT
#endif
void FRAMEWORK_EXPORT framework();
#define shared_h
#ifdef WIN32
-#ifdef shared_EXPORTS
-#define SHARED_EXPORT __declspec(dllexport)
+# ifdef shared_EXPORTS
+# define SHARED_EXPORT __declspec(dllexport)
+# else
+# define SHARED_EXPORT __declspec(dllimport)
+# endif
#else
-#define SHARED_EXPORT __declspec(dllimport)
-#endif
-#else
-#define SHARED_EXPORT
+# define SHARED_EXPORT
#endif
void SHARED_EXPORT shared();
#define shared2_h
#ifdef WIN32
-#ifdef shared2_EXPORTS
-#define SHARED2_EXPORT __declspec(dllexport)
+# ifdef shared2_EXPORTS
+# define SHARED2_EXPORT __declspec(dllexport)
+# else
+# define SHARED2_EXPORT __declspec(dllimport)
+# endif
#else
-#define SHARED2_EXPORT __declspec(dllimport)
-#endif
-#else
-#define SHARED2_EXPORT
+# define SHARED2_EXPORT
#endif
void SHARED2_EXPORT shared2();
#include "stdio.h"
#if defined(WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include "dlfcn.h"
+# include "dlfcn.h"
#endif
int main(int, char**)
#include "stdio.h"
#if defined(WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include "dlfcn.h"
+# include "dlfcn.h"
#endif
int main(int, char**)
#include "stdio.h"
#if defined(WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include "dlfcn.h"
+# include "dlfcn.h"
#endif
int main(int, char**)
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(add_compile_definitions LANGUAGES CXX)
+
+add_compile_definitions(TEST_DEFINITION
+ $<$<COMPILE_LANGUAGE:CXX>:LANG_$<COMPILE_LANGUAGE>>
+ $<$<EQUAL:0,1>:UNEXPECTED_DEFINITION>)
+
+add_executable(add_compile_definitions main.cpp)
+
+add_library(imp UNKNOWN IMPORTED)
+get_target_property(_res imp COMPILE_DEFINITIONS)
+if (_res)
+ message(SEND_ERROR "add_compile_definitions populated the COMPILE_DEFINITIONS target property")
+endif()
--- /dev/null
+
+#ifndef TEST_DEFINITION
+# error Expected TEST_DEFINITION
+#endif
+
+#ifndef LANG_CXX
+# error Expected LANG_CXX
+#endif
+
+#ifdef UNPEXTED_DEFINITION
+# error Unexpected UNPEXTED_DEFINITION
+#endif
+
+int main(void)
+{
+ return 0;
+}
#ifdef DO_GNU_TESTS
-#ifndef TEST_OPTION
-#error Expected TEST_OPTION
-#endif
+# ifndef TEST_OPTION
+# error Expected TEST_OPTION
+# endif
#endif
int main(void)
// Visual Studio allows only one set of flags for C and C++.
// In a target using C++ we pick the C++ flags even for C sources.
#ifdef TEST_LANG_DEFINES_FOR_VISUAL_STUDIO_OR_XCODE
-#ifndef CONSUMER_LANG_CXX
-#error Expected CONSUMER_LANG_CXX
-#endif
+# ifndef CONSUMER_LANG_CXX
+# error Expected CONSUMER_LANG_CXX
+# endif
-#ifdef CONSUMER_LANG_C
-#error Unexpected CONSUMER_LANG_C
-#endif
+# ifdef CONSUMER_LANG_C
+# error Unexpected CONSUMER_LANG_C
+# endif
-#if !LANG_IS_CXX
-#error Expected LANG_IS_CXX
-#endif
+# if !LANG_IS_CXX
+# error Expected LANG_IS_CXX
+# endif
-#if LANG_IS_C
-#error Unexpected LANG_IS_C
-#endif
+# if LANG_IS_C
+# error Unexpected LANG_IS_C
+# endif
#else
-#ifdef CONSUMER_LANG_CXX
-#error Unexpected CONSUMER_LANG_CXX
-#endif
+# ifdef CONSUMER_LANG_CXX
+# error Unexpected CONSUMER_LANG_CXX
+# endif
-#ifndef CONSUMER_LANG_C
-#error Expected CONSUMER_LANG_C
-#endif
+# ifndef CONSUMER_LANG_C
+# error Expected CONSUMER_LANG_C
+# endif
-#if !LANG_IS_C
-#error Expected LANG_IS_C
-#endif
+# if !LANG_IS_C
+# error Expected LANG_IS_C
+# endif
-#if LANG_IS_CXX
-#error Unexpected LANG_IS_CXX
-#endif
+# if LANG_IS_CXX
+# error Unexpected LANG_IS_CXX
+# endif
#endif
void consumer_c()
#ifdef MY_PRIVATE_DEFINE
-#error Unexpected MY_PRIVATE_DEFINE
+# error Unexpected MY_PRIVATE_DEFINE
#endif
#ifndef MY_PUBLIC_DEFINE
-#error Expected MY_PUBLIC_DEFINE
+# error Expected MY_PUBLIC_DEFINE
#endif
#ifndef MY_INTERFACE_DEFINE
-#error Expected MY_INTERFACE_DEFINE
+# error Expected MY_INTERFACE_DEFINE
#endif
#ifndef DASH_D_DEFINE
-#error Expected DASH_D_DEFINE
+# error Expected DASH_D_DEFINE
#endif
#ifndef CONSUMER_LANG_CXX
-#error Expected CONSUMER_LANG_CXX
+# error Expected CONSUMER_LANG_CXX
#endif
#ifdef CONSUMER_LANG_C
-#error Unexpected CONSUMER_LANG_C
+# error Unexpected CONSUMER_LANG_C
#endif
#if !LANG_IS_CXX
-#error Expected LANG_IS_CXX
+# error Expected LANG_IS_CXX
#endif
#if LANG_IS_C
-#error Unexpected LANG_IS_C
+# error Unexpected LANG_IS_C
#endif
int main()
#ifndef MY_PRIVATE_DEFINE
-#error Expected MY_PRIVATE_DEFINE
+# error Expected MY_PRIVATE_DEFINE
#endif
#ifndef MY_PUBLIC_DEFINE
-#error Expected MY_PUBLIC_DEFINE
+# error Expected MY_PUBLIC_DEFINE
#endif
#ifdef MY_INTERFACE_DEFINE
-#error Unexpected MY_INTERFACE_DEFINE
+# error Unexpected MY_INTERFACE_DEFINE
#endif
int main()
-cmake_minimum_required(VERSION 3.0)
-cmake_policy(SET CMP0057 NEW)
+cmake_minimum_required(VERSION 3.3)
project(target_compile_features)
set(CMAKE_VERBOSE_MAKEFILE ON)
target_link_libraries(c_restrict_user_specific c_lib_restrict_specific)
endif()
-if (c_std_99 IN_LIST CMAKE_C_COMPILE_FEATURES)
+if (c_std_99 IN_LIST CMAKE_C_COMPILE_FEATURES AND
+ NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
add_executable(c_target_compile_features_meta main.c)
target_compile_features(c_target_compile_features_meta
PRIVATE c_std_99
// Visual Studio allows only one set of flags for C and C++.
// In a target using C++ we pick the C++ flags even for C sources.
#ifdef TEST_LANG_DEFINES_FOR_VISUAL_STUDIO
-#ifndef CONSUMER_LANG_CXX
-#error Expected CONSUMER_LANG_CXX
-#endif
+# ifndef CONSUMER_LANG_CXX
+# error Expected CONSUMER_LANG_CXX
+# endif
-#ifdef CONSUMER_LANG_C
-#error Unexpected CONSUMER_LANG_C
-#endif
+# ifdef CONSUMER_LANG_C
+# error Unexpected CONSUMER_LANG_C
+# endif
-#if !LANG_IS_CXX
-#error Expected LANG_IS_CXX
-#endif
+# if !LANG_IS_CXX
+# error Expected LANG_IS_CXX
+# endif
-#if LANG_IS_C
-#error Unexpected LANG_IS_C
-#endif
+# if LANG_IS_C
+# error Unexpected LANG_IS_C
+# endif
#else
-#ifdef CONSUMER_LANG_CXX
-#error Unexpected CONSUMER_LANG_CXX
-#endif
+# ifdef CONSUMER_LANG_CXX
+# error Unexpected CONSUMER_LANG_CXX
+# endif
-#ifndef CONSUMER_LANG_C
-#error Expected CONSUMER_LANG_C
-#endif
+# ifndef CONSUMER_LANG_C
+# error Expected CONSUMER_LANG_C
+# endif
-#if !LANG_IS_C
-#error Expected LANG_IS_C
-#endif
+# if !LANG_IS_C
+# error Expected LANG_IS_C
+# endif
-#if LANG_IS_CXX
-#error Unexpected LANG_IS_CXX
-#endif
+# if LANG_IS_CXX
+# error Unexpected LANG_IS_CXX
+# endif
#endif
void consumer_c()
#ifdef DO_GNU_TESTS
-#ifdef MY_PRIVATE_DEFINE
-#error Unexpected MY_PRIVATE_DEFINE
-#endif
+# ifdef MY_PRIVATE_DEFINE
+# error Unexpected MY_PRIVATE_DEFINE
+# endif
-#ifndef MY_PUBLIC_DEFINE
-#error Expected MY_PUBLIC_DEFINE
-#endif
+# ifndef MY_PUBLIC_DEFINE
+# error Expected MY_PUBLIC_DEFINE
+# endif
-#ifndef MY_INTERFACE_DEFINE
-#error Expected MY_INTERFACE_DEFINE
-#endif
+# ifndef MY_INTERFACE_DEFINE
+# error Expected MY_INTERFACE_DEFINE
+# endif
#endif
#ifndef CONSUMER_LANG_CXX
-#error Expected CONSUMER_LANG_CXX
+# error Expected CONSUMER_LANG_CXX
#endif
#ifdef CONSUMER_LANG_C
-#error Unexpected CONSUMER_LANG_C
+# error Unexpected CONSUMER_LANG_C
#endif
#if !LANG_IS_CXX
-#error Expected LANG_IS_CXX
+# error Expected LANG_IS_CXX
#endif
#if LANG_IS_C
-#error Unexpected LANG_IS_C
+# error Unexpected LANG_IS_C
#endif
int main()
#ifdef DO_GNU_TESTS
-#ifndef MY_PRIVATE_DEFINE
-#error Expected MY_PRIVATE_DEFINE
-#endif
+# ifndef MY_PRIVATE_DEFINE
+# error Expected MY_PRIVATE_DEFINE
+# endif
-#ifndef MY_PUBLIC_DEFINE
-#error Expected MY_PUBLIC_DEFINE
-#endif
+# ifndef MY_PUBLIC_DEFINE
+# error Expected MY_PUBLIC_DEFINE
+# endif
-#ifdef MY_INTERFACE_DEFINE
-#error Unexpected MY_INTERFACE_DEFINE
-#endif
+# ifdef MY_INTERFACE_DEFINE
+# error Unexpected MY_INTERFACE_DEFINE
+# endif
#endif
// Visual Studio allows only one set of flags for C and C++.
// In a target using C++ we pick the C++ flags even for C sources.
#ifdef TEST_LANG_DEFINES_FOR_VISUAL_STUDIO_OR_XCODE
-#include "cxx_only.h"
+# include "cxx_only.h"
-#ifndef CXX_ONLY_DEFINE
-#error Expected CXX_ONLY_DEFINE
-#endif
+# ifndef CXX_ONLY_DEFINE
+# error Expected CXX_ONLY_DEFINE
+# endif
#else
-#include "c_only.h"
+# include "c_only.h"
-#ifndef C_ONLY_DEFINE
-#error Expected C_ONLY_DEFINE
-#endif
+# ifndef C_ONLY_DEFINE
+# error Expected C_ONLY_DEFINE
+# endif
#endif
int consumer_c()
#include "relative_dir.h"
#ifdef PRIVATEINCLUDE_DEFINE
-#error Unexpected PRIVATEINCLUDE_DEFINE
+# error Unexpected PRIVATEINCLUDE_DEFINE
#endif
#ifndef PUBLICINCLUDE_DEFINE
-#error Expected PUBLICINCLUDE_DEFINE
+# error Expected PUBLICINCLUDE_DEFINE
#endif
#ifndef INTERFACEINCLUDE_DEFINE
-#error Expected INTERFACEINCLUDE_DEFINE
+# error Expected INTERFACEINCLUDE_DEFINE
#endif
#ifndef CURE_DEFINE
-#error Expected CURE_DEFINE
+# error Expected CURE_DEFINE
#endif
#ifndef RELATIVE_DIR_DEFINE
-#error Expected RELATIVE_DIR_DEFINE
+# error Expected RELATIVE_DIR_DEFINE
#endif
#ifndef CONSUMER_DEFINE
-#error Expected CONSUMER_DEFINE
+# error Expected CONSUMER_DEFINE
#endif
#ifndef CXX_ONLY_DEFINE
-#error Expected CXX_ONLY_DEFINE
+# error Expected CXX_ONLY_DEFINE
#endif
int main()
#include "publicinclude.h"
#ifndef PRIVATEINCLUDE_DEFINE
-#error Expected PRIVATEINCLUDE_DEFINE
+# error Expected PRIVATEINCLUDE_DEFINE
#endif
#ifndef PUBLICINCLUDE_DEFINE
-#error Expected PUBLICINCLUDE_DEFINE
+# error Expected PUBLICINCLUDE_DEFINE
#endif
#ifdef INTERFACEINCLUDE_DEFINE
-#error Unexpected INTERFACEINCLUDE_DEFINE
+# error Unexpected INTERFACEINCLUDE_DEFINE
#endif
#ifndef CURE_DEFINE
-#error Expected CURE_DEFINE
+# error Expected CURE_DEFINE
#endif
int main()
#include "libgenex_export.h"
#ifndef LIBGENEX_H
-#define LIBGENEX_H
+# define LIBGENEX_H
struct LIBGENEX_EXPORT LibGenex
{
#include "foo.h"
#ifndef TEST_DEF
-#error Expected TEST_DEF definition
+# error Expected TEST_DEF definition
#endif
int main(int, char**)
endif()
add_subdirectory(PseudoMemcheck)
+
+add_executable(testAffinity testAffinity.cxx)
+target_link_libraries(testAffinity CMakeLib)
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAffinity.h"
+
+#include <cstddef>
+#include <iostream>
+#include <set>
+
+int main()
+{
+ std::set<size_t> cpus = cmAffinity::GetProcessorsAvailable();
+ if (!cpus.empty()) {
+ std::cout << "CPU affinity mask count is '" << cpus.size() << "'.\n";
+ } else {
+ std::cout << "CPU affinity not supported on this platform.\n";
+ }
+ return 0;
+}
#include <string>
#ifdef _WIN32
-#include "cmsys/ConsoleBuf.hxx"
+# include "cmsys/ConsoleBuf.hxx"
#endif
#ifdef _WIN32
Variable ``VARIABLE_<PLACEHOLDER>`` with trailing placeholder.
Variable ``<PLACEHOLDER>_VARIABLE`` with leading placeholder and target.
Variable ``VARIABLE_<PLACEHOLDER>`` with trailing placeholder and target.
+Environment variable ``SOME_ENV_VAR``.
+Environment variable ``some env var`` with space and target.
Generator ``Some Generator`` with space.
+Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
+Inline link Link Text.
+Inline link Link Text <With \-escaped Brackets>.
+Inline literal ``__`` followed by inline link Link Text.
First TOC entry.
Variable :variable:`VARIABLE_<PLACEHOLDER>` with trailing placeholder.
Variable :variable:`<PLACEHOLDER>_VARIABLE <target>` with leading placeholder and target.
Variable :variable:`VARIABLE_<PLACEHOLDER> <target>` with trailing placeholder and target.
+Environment variable :envvar:`SOME_ENV_VAR`.
+Environment variable :envvar:`some env var <SOME_ENV_VAR>` with space and target.
Generator :generator:`Some Generator` with space.
+Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
+Inline link `Link Text <ExternalDest>`_.
+Inline link `Link Text \<With \\-escaped Brackets\> <ExternalDest>`_.
+Inline literal ``__`` followed by inline link `Link Text <InternalDest_>`_.
.. |not replaced| replace:: not replaced through toctree
.. |not replaced in literal| replace:: replaced in parsed literal
std::thread([&] {
std::this_thread::sleep_for(std::chrono::seconds(2));
signal.send();
- }).detach();
+ })
+ .detach();
if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
std::cerr << "Unclean exit state in testAsyncDtor" << std::endl;
}
const std::vector<cmSlnProjectEntry>& projects = data.GetProjects();
const char* const names[] = {
- "3rdParty", "ALL_BUILD", "CMakeLib", "CMakeLibTests",
- "CMakePredefinedTargets", "CPackLib", "CTestDashboardTargets",
- "CTestLib", "Continuous", "Documentation", "Experimental", "INSTALL",
- "KWSys", "LIBCURL", "Nightly", "NightlyMemoryCheck", "PACKAGE",
- "RUN_TESTS", "Tests", "Utilities", "Win9xCompat", "ZERO_CHECK",
- "cmIML_test", "cmake", "cmbzip2", "cmcldeps", "cmcompress", "cmcurl",
- "cmexpat", "cmlibarchive", "cmsys", "cmsysEncodeExecutable",
- "cmsysProcessFwd9x", "cmsysTestDynload", "cmsysTestProcess",
- "cmsysTestSharedForward", "cmsysTestsC", "cmsysTestsCxx", "cmsys_c",
- "cmw9xcom", "cmzlib", "cpack", "ctest", "documentation", "memcheck_fail",
- "pseudo_BC", "pseudo_purify", "pseudo_valgrind", "test_clean",
+ "3rdParty",
+ "ALL_BUILD",
+ "CMakeLib",
+ "CMakeLibTests",
+ "CMakePredefinedTargets",
+ "CPackLib",
+ "CTestDashboardTargets",
+ "CTestLib",
+ "Continuous",
+ "Documentation",
+ "Experimental",
+ "INSTALL",
+ "KWSys",
+ "LIBCURL",
+ "Nightly",
+ "NightlyMemoryCheck",
+ "PACKAGE",
+ "RUN_TESTS",
+ "Tests",
+ "Utilities",
+ "Win9xCompat",
+ "ZERO_CHECK",
+ "cmIML_test",
+ "cmake",
+ "cmbzip2",
+ "cmcldeps",
+ "cmcompress",
+ "cmcurl",
+ "cmexpat",
+ "cmlibarchive",
+ "cmsys",
+ "cmsysEncodeExecutable",
+ "cmsysProcessFwd9x",
+ "cmsysTestDynload",
+ "cmsysTestProcess",
+ "cmsysTestSharedForward",
+ "cmsysTestsC",
+ "cmsysTestsCxx",
+ "cmsys_c",
+ "cmw9xcom",
+ "cmzlib",
+ "cpack",
+ "ctest",
+ "documentation",
+ "memcheck_fail",
+ "pseudo_BC",
+ "pseudo_purify",
+ "pseudo_valgrind",
+ "test_clean",
"uninstall"
/* clang-format needs this comment to break after the opening brace */
};
set(CMake_TEST_DEVENV "")
if(CMAKE_VS_DEVENV_COMMAND)
set(CMake_TEST_DEVENV "${CMAKE_VS_DEVENV_COMMAND}")
- elseif(CMAKE_GENERATOR MATCHES "Visual Studio [89] " AND
+ elseif(CMAKE_GENERATOR MATCHES "Visual Studio 9 " AND
NOT CMAKE_MAKE_PROGRAM MATCHES "[mM][sS][bB][uU][iI][lL][dD]\\.[eE][xX][eE]")
set(CMake_TEST_DEVENV "${CMAKE_MAKE_PROGRAM}")
endif()
set(CPACK_BINARY_RPM OFF)
endif()
- # Look for rpmbuild to use for tests.
- # The tool does not work with spaces in the path.
+ # Look for dpkg to use for tests.
find_program(DPKG_EXECUTABLE NAMES dpkg)
if(DPKG_EXECUTABLE)
set(CPACK_BINARY_DEB OFF)
endif()
+ # Look for NuGet to use for tests.
+ find_program(NUGET_EXECUTABLE NAMES NuGet nuget)
+
+ if(NUGET_EXECUTABLE)
+ set(CPACK_BINARY_NUGET ON)
+ else()
+ set(CPACK_BINARY_NUGET OFF)
+ endif()
+
#---------------------------------------------------------------------------
# Add tests below here.
set(CMake_TEST_XCODE_VERSION "${CMAKE_MATCH_1}")
endif()
endif()
+ if(NOT CMake_TEST_XCODE_VERSION VERSION_LESS 10)
+ # Since Xcode 10 we do not have two supported architectures for the host.
+ set(CTEST_TEST_OSX_ARCH 0)
+ endif()
if(CMAKE_OSX_SYSROOT)
execute_process(
COMMAND xcodebuild -sdk ${CMAKE_OSX_SYSROOT} -version ProductName
endif()
endif()
- if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
+ if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
ADD_TEST_MACRO(CSharpOnly CSharpOnly)
ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
+ ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx)
endif()
ADD_TEST_MACRO(COnly COnly)
ADD_TEST_MACRO(CustomCommandByproducts CustomCommandByproducts)
+ ADD_TEST_MACRO(CommandLength CommandLength)
+
ADD_TEST_MACRO(EmptyDepends ${CMAKE_CTEST_COMMAND})
add_test(CustomCommandWorkingDirectory ${CMAKE_CTEST_COMMAND}
endif()
endif()
+ if(CTEST_TEST_CPACK)
+ add_test(CPackUseDefaultVersion ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/CPackUseDefaultVersion"
+ "${CMake_BINARY_DIR}/Tests/CPackUseDefaultVersion"
+ ${build_generator_args}
+ --build-project CPackUseDefaultVersion
+ --build-two-config
+ --build-options ${build_options}
+ ${CPackUseDefaultVersion_BUILD_OPTIONS})
+ set_tests_properties(CPackUseDefaultVersion PROPERTIES PASS_REGULAR_EXPRESSION "CPACK_PACKAGE_VERSION=0\\.1\\.1")
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackUseDefaultVersion")
+
+ add_test(CPackUseProjectVersion ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/CPackUseProjectVersion"
+ "${CMake_BINARY_DIR}/Tests/CPackUseProjectVersion"
+ ${build_generator_args}
+ --build-project CPackUseProjectVersion
+ --build-two-config
+ --build-options ${build_options}
+ ${CPackUseProjectVersion_BUILD_OPTIONS})
+ set_tests_properties(CPackUseProjectVersion PROPERTIES PASS_REGULAR_EXPRESSION "CPACK_PACKAGE_VERSION=1\\.2\\.3")
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackUseProjectVersion")
+
+ add_test(CPackUseShortProjectVersion ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/CPackUseShortProjectVersion"
+ "${CMake_BINARY_DIR}/Tests/CPackUseShortProjectVersion"
+ ${build_generator_args}
+ --build-project CPackUseShortProjectVersion
+ --build-two-config
+ --build-options ${build_options}
+ ${CPackUseProjectVersion_BUILD_OPTIONS})
+ set_tests_properties(CPackUseShortProjectVersion PROPERTIES PASS_REGULAR_EXPRESSION "CPACK_PACKAGE_VERSION=2")
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackUseShortProjectVersion")
+ endif()
+
if(CTEST_RUN_CPackComponents)
set(CPackComponents_BUILD_OPTIONS)
if(APPLE)
if(CPACK_BINARY_DEB)
list(APPEND ACTIVE_CPACK_GENERATORS DEB)
endif()
+ # Check whether if NuGet command is found
+ # before adding NuGet tests
+ if(CPACK_BINARY_NUGET)
+ list(APPEND ACTIVE_CPACK_GENERATORS NUGET)
+ set(CPACK_GENERATOR_STRING_NUGET NuGet)
+ endif()
# ACTIVE_CPACK_GENERATORS variable
# now contains the list of 'active generators'
list(APPEND CWAYLST "IgnoreGroup")
list(APPEND CWAYLST "AllInOne")
foreach(CPackGen IN LISTS ACTIVE_CPACK_GENERATORS)
- set(CPackRun_CPackGen "-DCPackGen=${CPackGen}")
+ if(NOT DEFINED CPACK_GENERATOR_STRING_${CPackGen})
+ set(CPACK_GENERATOR_STRING_${CPackGen} ${CPackGen})
+ endif()
+ set(CPackRun_CPackGen "-DCPackGen=${CPACK_GENERATOR_STRING_${CPackGen}}")
foreach(CPackComponentWay ${CWAYLST})
set(CPackRun_CPackComponentWay "-DCPackComponentWay=${CPackComponentWay}")
add_test(CPackComponentsForAll-${CPackGen}-${CPackComponentWay}
${build_generator_args}
--build-project CPackComponentsForAll
--build-options ${build_options}
- -DCPACK_GENERATOR:STRING=${CPackGen}
+ -DCPACK_GENERATOR:STRING=${CPACK_GENERATOR_STRING_${CPackGen}}
-DCPACK_BINARY_${CPackGen}:BOOL=ON
${CPackRun_CPackComponentWay}
${CPackComponentsForAll_BUILD_OPTIONS}
endif()
endif()
+ if(CMake_TEST_FindALSA)
+ add_subdirectory(FindALSA)
+ endif()
+
if(CMake_TEST_CUDA)
add_subdirectory(Cuda)
add_subdirectory(CudaOnly)
add_subdirectory(FindBZip2)
endif()
+ if(CMake_TEST_FindCURL)
+ add_subdirectory(FindCURL)
+ endif()
+
if(CMake_TEST_FindDoxygen)
add_subdirectory(FindDoxygen)
endif()
add_subdirectory(FindICU)
endif()
+ if(CMake_TEST_FindJPEG)
+ add_subdirectory(FindJPEG)
+ endif()
+
if(CMake_TEST_FindJsonCpp)
add_subdirectory(FindJsonCpp)
endif()
add_subdirectory(FindLibUV)
endif()
+ if(CMake_TEST_FindLibXml2)
+ add_subdirectory(FindLibXml2)
+ endif()
+
if(CMake_TEST_FindLTTngUST)
add_subdirectory(FindLTTngUST)
endif()
+ if(CMake_TEST_FindODBC)
+ add_subdirectory(FindODBC)
+ endif()
+
if(CMake_TEST_FindOpenCL)
add_subdirectory(FindOpenCL)
endif()
add_subdirectory(FindXercesC)
endif()
+ if(CMake_TEST_FindPython)
+ add_subdirectory(FindPython)
+ endif()
+
+ if(CMake_TEST_UseSWIG)
+ add_subdirectory(UseSWIG)
+ endif()
+
add_subdirectory(FindThreads)
# Matlab module
- if(CMake_TEST_FindMatlab)
+ # CMake_TEST_FindMatlab: indicates to look for Matlab (from PATH for Linux)
+ # CMake_TEST_FindMatlab_MCR: indicates the MCR is installed
+ # CMake_TEST_FindMatlab_MCR_ROOT_DIR: indicates an optional root directory for the MCR, required on Linux
+ if(CMake_TEST_FindMatlab OR CMake_TEST_FindMatlab_MCR OR (NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL ""))
+ set(FindMatlab_additional_test_options )
+ if(CMake_TEST_FindMatlab_MCR OR NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "")
+ set(FindMatlab_additional_test_options -DIS_MCR=TRUE)
+ endif()
+ if(NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "")
+ set(FindMatlab_additional_test_options ${FindMatlab_additional_test_options} "-DMCR_ROOT:FILEPATH=${CMake_TEST_FindMatlab_MCR_ROOT_DIR}")
+ endif()
+ set(FindMatlab.basic_checks_BUILD_OPTIONS ${FindMatlab_additional_test_options})
ADD_TEST_MACRO(FindMatlab.basic_checks ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>)
+ set(FindMatlab.versions_checks_BUILD_OPTIONS ${FindMatlab_additional_test_options})
ADD_TEST_MACRO(FindMatlab.versions_checks ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>)
+ set(FindMatlab.components_checks_BUILD_OPTIONS ${FindMatlab_additional_test_options})
ADD_TEST_MACRO(FindMatlab.components_checks ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>)
+ set(FindMatlab.failure_reports_BUILD_OPTIONS ${FindMatlab_additional_test_options})
+ ADD_TEST_MACRO(FindMatlab.failure_reports ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>)
endif()
find_package(GTK2 QUIET)
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProject")
set_tests_properties(ExternalProject PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
add_test(NAME ExternalProjectSubdir
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectLocal")
set_tests_properties(ExternalProjectLocal PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
add_test(ExternalProjectUpdateSetup ${CMAKE_CTEST_COMMAND}
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate")
set_tests_properties(ExternalProjectUpdateSetup PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
add_test(NAME ExternalProjectUpdate
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate")
set_tests_properties(ExternalProjectUpdate PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT}
WORKING_DIRECTORY ${CMake_SOURCE_DIR}/Tests/ExternalProjectUpdate
DEPENDS ExternalProjectUpdateSetup )
endif()
if(MSVC AND NOT MSVC_VERSION LESS 1310
- AND (NOT CMAKE_GENERATOR MATCHES "Visual Studio [89]( |$)"
+ AND (NOT CMAKE_GENERATOR MATCHES "Visual Studio 9 "
OR CMAKE_SIZEOF_VOID_P EQUAL 4)
)
ADD_TEST_MACRO(VSMASM VSMASM)
ADD_TEST_MACRO(SBCS SBCS)
endif()
- if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio [89]( |$)"
+ if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio 9 "
AND NOT CMAKE_GENERATOR_TOOLSET)
ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx)
endif()
endif()
endif()
- if(CMAKE_GENERATOR MATCHES "Visual Studio ([^89]|[89][0-9])" AND nasm)
+ if(CMAKE_GENERATOR MATCHES "Visual Studio ([^9]|9[0-9])" AND nasm)
ADD_TEST_MACRO(VSNASM VSNASM)
endif()
--output-log "${CMake_BINARY_DIR}/Tests/CTestConfig/ScriptWithArgs.log"
)
+ ADD_TEST_MACRO(CMakeCommands.add_compile_definitions add_compile_definitions)
ADD_TEST_MACRO(CMakeCommands.add_compile_options add_compile_options)
ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries)
ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories)
endforeach()
foreach(VTEST BISON Boost CUDA DOXYGEN FLEX GIF GTK2
- HDF5 LibArchive OPENSCENEGRAPH RUBY SWIG Protobuf)
+ HDF5 JPEG LibArchive OPENSCENEGRAPH RUBY SWIG Protobuf)
check_version_string(${VTEST} ${VTEST}_VERSION)
endforeach()
if(CMAKE_Fortran_COMPILER)
add_CMakeOnly_test(CompilerIdFortran)
endif()
-if(CMAKE_GENERATOR MATCHES "Visual Studio ([^89]|[89][0-9])")
+if(CMAKE_GENERATOR MATCHES "Visual Studio ([^9]|9[0-9])")
add_CMakeOnly_test(CompilerIdCSharp)
endif()
if("$ENV{DASHBOARD_TEST_FROM_CTEST}" STREQUAL "")
# developers are allowed to have local additions and modifications...
- set(is_dashboard 0)
message("interactive test run")
message("")
else()
- set(is_dashboard 1)
message("dashboard test run")
message("")
# Not even developers.
#
if(nonadditions)
- if(in_source_build AND is_dashboard)
+ if(in_source_build)
message("
warning: test results confounded because this is an 'in-source' build - cannot
distinguish between non-added files that are in-source build products and
#ifdef _WIN32
-#ifdef testc2_EXPORTS
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# ifdef testc2_EXPORTS
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# else
+# define CM_TEST_LIB_EXPORT __declspec(dllimport)
+# endif
#else
-#define CM_TEST_LIB_EXPORT __declspec(dllimport)
-#endif
-#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
CM_TEST_LIB_EXPORT float LibC2Func();
#ifdef _WIN32
-#define TEST_EXPORT __declspec(dllexport)
+# define TEST_EXPORT __declspec(dllexport)
#else
-#define TEST_EXPORT
+# define TEST_EXPORT
#endif
TEST_EXPORT int testCModule(void)
{
# set CPACK_DEBIAN_FILE_NAME to use default package name format
set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
+# set some tags for NuGet packages
+# 1. all in one package
+set(CPACK_NUGET_PACKAGE_TAGS "nuget" "unit" "test" "all-in-one")
+# 2. per component packages
+set(CPACK_NUGET_APPLICATIONS_PACKAGE_TAGS "nuget" "unit" "test" "applications")
+set(CPACK_NUGET_LIBRARIES_PACKAGE_TAGS "nuget" "unit" "test" "libraries")
+set(CPACK_NUGET_HEADERS_PACKAGE_TAGS "nuget" "unit" "test" "headers")
+set(CPACK_NUGET_UNSPECIFIED_PACKAGE_TAGS "nuget" "unit" "test" "uNsP3c1FiEd")
+# 3. per group packages
+set(CPACK_NUGET_RUNTIME_PACKAGE_TAGS "nuget" "unit" "test" "run-time")
+set(CPACK_NUGET_DEVELOPMENT_PACKAGE_TAGS "nuget" "unit" "test" "development")
+
# We may use the CPack specific config file in order
# to tailor CPack behavior on a CPack generator specific way
# (Behavior would be different for RPM or TGZ or DEB ...)
set(CPACK_DEB_COMPONENT_INSTALL "ON")
endif()
+if(CPACK_GENERATOR MATCHES "NuGet")
+ set(CPACK_NUGET_COMPONENT_INSTALL "ON")
+endif()
+
#
# Choose grouping way
#
set(CPACK_DEB_COMPONENT_INSTALL "ON")
endif()
+if(CPACK_GENERATOR MATCHES "NuGet")
+ set(CPACK_NUGET_COMPONENT_INSTALL "ON")
+endif()
+
#
# Choose grouping way
#
set(CPACK_COMPONENTS_GROUPING "ONE_PER_GROUP")
endif()
+if(CPACK_GENERATOR MATCHES "NuGet")
+ set(CPACK_NUGET_COMPONENT_INSTALL "ON")
+endif()
+
#
# Choose grouping way
#
if(CPackGen MATCHES "ZIP")
set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/MyLib-*.zip")
- if (${CPackComponentWay} STREQUAL "default")
+ if(${CPackComponentWay} STREQUAL "default")
set(expected_count 1)
- elseif (${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
set(expected_count 3)
- elseif (${CPackComponentWay} STREQUAL "IgnoreGroup")
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
set(expected_count 4)
- elseif (${CPackComponentWay} STREQUAL "AllInOne")
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
set(expected_count 1)
- endif ()
-elseif (CPackGen MATCHES "RPM")
+ endif()
+elseif(CPackGen MATCHES "RPM")
set(config_verbose -D "CPACK_RPM_PACKAGE_DEBUG=1")
set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/MyLib-*.rpm")
- if (${CPackComponentWay} STREQUAL "default")
+ if(${CPackComponentWay} STREQUAL "default")
set(expected_count 1)
- elseif (${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
set(expected_count 3)
- elseif (${CPackComponentWay} STREQUAL "IgnoreGroup")
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
set(expected_count 4)
- elseif (${CPackComponentWay} STREQUAL "AllInOne")
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
set(expected_count 1)
- endif ()
-elseif (CPackGen MATCHES "DEB")
+ endif()
+elseif(CPackGen MATCHES "DEB")
set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/mylib*_1.0.2_*.deb")
- if (${CPackComponentWay} STREQUAL "default")
+ if(${CPackComponentWay} STREQUAL "default")
set(expected_count 1)
- elseif (${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
set(expected_count 3)
- elseif (${CPackComponentWay} STREQUAL "IgnoreGroup")
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
set(expected_count 4)
- elseif (${CPackComponentWay} STREQUAL "AllInOne")
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
set(expected_count 1)
- endif ()
+ endif()
+elseif(CPackGen MATCHES "NuGet")
+ set(config_verbose -D "CPACK_NUGET_PACKAGE_DEBUG=1")
+ set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/MyLib*1.0.2.nupkg")
+ if(${CPackComponentWay} STREQUAL "default")
+ set(expected_count 1)
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ set(expected_count 3)
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
+ set(expected_count 4)
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
+ set(expected_count 1)
+ endif()
endif()
if(CPackGen MATCHES "DragNDrop")
set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/MyLib-*.dmg")
- if (${CPackComponentWay} STREQUAL "default")
+ if(${CPackComponentWay} STREQUAL "default")
set(expected_count 1)
- elseif (${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
set(expected_count 3)
- elseif (${CPackComponentWay} STREQUAL "IgnoreGroup")
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
set(expected_count 4)
- elseif (${CPackComponentWay} STREQUAL "AllInOne")
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
set(expected_count 1)
- endif ()
+ endif()
endif()
# clean-up previously CPack generated files
if(expected_file_mask)
file(GLOB expected_file "${expected_file_mask}")
- if (expected_file)
+ if(expected_file)
file(REMOVE ${expected_file})
endif()
endif()
ERROR_VARIABLE CPack_error
WORKING_DIRECTORY ${CPackComponentsForAll_BINARY_DIR})
-if (CPack_result)
+if(CPack_result)
message(FATAL_ERROR "error: CPack execution went wrong!, CPack_output=${CPack_output}, CPack_error=${CPack_error}")
else ()
message(STATUS "CPack_output=${CPack_output}")
--- /dev/null
+cmake_minimum_required(VERSION 3.2)
+project(CPackUseProjectVersion NONE)
+
+include(CPack)
+
+message("CPACK_PACKAGE_VERSION=${CPACK_PACKAGE_VERSION}")
--- /dev/null
+cmake_minimum_required(VERSION 3.2)
+project(CPackUseProjectVersion VERSION 1.2.3 LANGUAGES NONE)
+
+include(CPack)
+
+message("CPACK_PACKAGE_VERSION=${CPACK_PACKAGE_VERSION}")
--- /dev/null
+cmake_minimum_required(VERSION 3.2)
+project(CPackUseProjectVersion VERSION 2 LANGUAGES NONE)
+
+include(CPack)
+
+message("CPACK_PACKAGE_VERSION=${CPACK_PACKAGE_VERSION}")
--- /dev/null
+# Take a C# shared library and link it to a managed C++ shared library
+cmake_minimum_required(VERSION 3.10)
+project (CSharpLinkFromCxx CXX CSharp)
+
+add_library(CSharpLibrary SHARED UsefulCSharpClass.cs)
+
+# we have to change the default flags for the
+# managed C++ project to build
+string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
+
+# The C# project is a dependency of the C++/CLI project
+add_library(ManagedCppLibrary SHARED UsefulManagedCppClass.cpp UsefulManagedCppClass.hpp)
+target_compile_options(ManagedCppLibrary PRIVATE "/clr")
+target_link_libraries(ManagedCppLibrary PUBLIC CSharpLibrary)
+
+# Main executable for the test framework
+add_executable(CSharpLinkFromCxx CSharpLinkFromCxx.cs)
+target_link_libraries(CSharpLinkFromCxx PRIVATE ManagedCppLibrary)
--- /dev/null
+using System;
+using CSharpLibrary;
+
+namespace CSharpLinkFromCxx
+{
+ internal class CSharpLinkFromCxx
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Starting test for CSharpLinkFromCxx");
+
+ var useful = new UsefulManagedCppClass();
+ useful.RunTest();
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace CSharpLibrary
+{
+ public class UsefulCSharpClass
+ {
+ public string GetSomethingUseful()
+ {
+ return "Something Useful";
+ }
+ }
+}
--- /dev/null
+#include "UsefulManagedCppClass.hpp"
+
+namespace CSharpLibrary
+{
+ UsefulManagedCppClass::UsefulManagedCppClass()
+ {
+ auto useful = gcnew UsefulCSharpClass();
+ m_usefulString = useful->GetSomethingUseful();
+ }
+
+ void UsefulManagedCppClass::RunTest()
+ {
+ Console::WriteLine("Printing from Managed CPP Class: " + m_usefulString);
+ }
+}
--- /dev/null
+using namespace System;
+
+namespace CSharpLibrary
+{
+ public ref class UsefulManagedCppClass
+ {
+ public:
+
+ UsefulManagedCppClass();
+ void RunTest();
+
+ private:
+
+ String^ m_usefulString;
+ };
+}
set (CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@/Tests/CTestTest")
-# set any extra environment varibles here
+# set any extra environment variables here
set (CTEST_ENVIRONMENT
)
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
/* sleeps for 1 second */
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
/* sleeps for 0.1 second */
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
/* sleeps for 4n seconds, where n is the argument to the program */
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
/* sleeps for n seconds, where n is the argument to the program */
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
#include <stdio.h>
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
/* sleeps for n seconds, where n is the argument to the program */
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
/* sleeps for 5 seconds */
--- /dev/null
+cmake_minimum_required(VERSION 3.10)
+project(CommandLength C)
+
+add_executable(CommandLength test.c)
+add_custom_command(TARGET CommandLength POST_BUILD VERBATIM
+ COMMAND ${CMAKE_COMMAND} -E make_directory log)
+
+set(msg "xxxx $$$$ yyyy")
+set(msg "${msg} ${msg}")
+set(msg "${msg} ${msg}")
+set(msg "${msg} ${msg}")
+set(msg "${msg} ${msg}")
+foreach(i RANGE 1 1000)
+ add_custom_command(TARGET CommandLength POST_BUILD VERBATIM
+ COMMAND ${CMAKE_COMMAND} -E echo "${i} ${msg}" > log/${i}
+ )
+endforeach()
--- /dev/null
+int main()
+{
+ return 0;
+}
#ifndef BOOL_PROP1
-#error Expected BOOL_PROP1
+# error Expected BOOL_PROP1
#endif
#ifndef BOOL_PROP2
-#error Expected BOOL_PROP2
+# error Expected BOOL_PROP2
#endif
#ifndef BOOL_PROP3
-#error Expected BOOL_PROP3
+# error Expected BOOL_PROP3
#endif
#ifndef STRING_PROP1
-#error Expected STRING_PROP1
+# error Expected STRING_PROP1
#endif
#ifndef STRING_PROP2
-#error Expected STRING_PROP2
+# error Expected STRING_PROP2
#endif
#ifndef STRING_PROP3
-#error Expected STRING_PROP3
+# error Expected STRING_PROP3
#endif
template <bool test>
#if defined(_WIN32)
-#ifdef test2_EXPORTS
-#define TEST2_EXPORT __declspec(dllexport)
+# ifdef test2_EXPORTS
+# define TEST2_EXPORT __declspec(dllexport)
+# else
+# define TEST2_EXPORT __declspec(dllimport)
+# endif
#else
-#define TEST2_EXPORT __declspec(dllimport)
-#endif
-#else
-#define TEST2_EXPORT
+# define TEST2_EXPORT
#endif
TEST2_EXPORT void relative();
#ifndef LINK_C_DEFINE
-#error Expected LINK_C_DEFINE
+# error Expected LINK_C_DEFINE
#endif
#ifndef LINK_LANGUAGE_IS_C
-#error Expected LINK_LANGUAGE_IS_C
+# error Expected LINK_LANGUAGE_IS_C
#endif
#ifdef LINK_CXX_DEFINE
-#error Unexpected LINK_CXX_DEFINE
+# error Unexpected LINK_CXX_DEFINE
#endif
#ifdef LINK_LANGUAGE_IS_CXX
-#error Unexpected LINK_LANGUAGE_IS_CXX
+# error Unexpected LINK_LANGUAGE_IS_CXX
#endif
#ifdef DEBUG_MODE
-#error Unexpected DEBUG_MODE
+# error Unexpected DEBUG_MODE
#endif
int main(void)
#ifndef CMAKE_IS_FUN
-#error Expect CMAKE_IS_FUN definition
+# error Expect CMAKE_IS_FUN definition
#endif
#if CMAKE_IS != Fun
-#error Expect CMAKE_IS=Fun definition
+# error Expect CMAKE_IS=Fun definition
#endif
template <bool test>
};
#ifdef TEST_GENERATOR_EXPRESSIONS
-#ifndef CMAKE_IS_DECLARATIVE
-#error Expect declarative definition
-#endif
-#ifdef GE_NOT_DEFINED
-#error Expect not defined generator expression
-#endif
-
-#ifndef ARGUMENT
-#error Expected define expanded from list
-#endif
-#ifndef LIST
-#error Expected define expanded from list
-#endif
-
-#ifndef PREFIX_DEF1
-#error Expect PREFIX_DEF1
-#endif
-
-#ifndef PREFIX_DEF2
-#error Expect PREFIX_DEF2
-#endif
-
-#ifndef LINK_CXX_DEFINE
-#error Expected LINK_CXX_DEFINE
-#endif
-#ifndef LINK_LANGUAGE_IS_CXX
-#error Expected LINK_LANGUAGE_IS_CXX
-#endif
-
-#ifdef LINK_C_DEFINE
-#error Unexpected LINK_C_DEFINE
-#endif
-#ifdef LINK_LANGUAGE_IS_C
-#error Unexpected LINK_LANGUAGE_IS_C
-#endif
+# ifndef CMAKE_IS_DECLARATIVE
+# error Expect declarative definition
+# endif
+# ifdef GE_NOT_DEFINED
+# error Expect not defined generator expression
+# endif
+
+# ifndef ARGUMENT
+# error Expected define expanded from list
+# endif
+# ifndef LIST
+# error Expected define expanded from list
+# endif
+
+# ifndef PREFIX_DEF1
+# error Expect PREFIX_DEF1
+# endif
+
+# ifndef PREFIX_DEF2
+# error Expect PREFIX_DEF2
+# endif
+
+# ifndef LINK_CXX_DEFINE
+# error Expected LINK_CXX_DEFINE
+# endif
+# ifndef LINK_LANGUAGE_IS_CXX
+# error Expected LINK_LANGUAGE_IS_CXX
+# endif
+
+# ifdef LINK_C_DEFINE
+# error Unexpected LINK_C_DEFINE
+# endif
+# ifdef LINK_LANGUAGE_IS_C
+# error Unexpected LINK_LANGUAGE_IS_C
+# endif
// TEST_GENERATOR_EXPRESSIONS
#endif
#ifndef BUILD_IS_DEBUG
-#error "BUILD_IS_DEBUG not defined!"
+# error "BUILD_IS_DEBUG not defined!"
#endif
#ifndef BUILD_IS_NOT_DEBUG
-#error "BUILD_IS_NOT_DEBUG not defined!"
+# error "BUILD_IS_NOT_DEBUG not defined!"
#endif
// Check per-config definitions.
#ifdef TEST_CONFIG_DEBUG
-#if !BUILD_IS_DEBUG
-#error "BUILD_IS_DEBUG false with TEST_CONFIG_DEBUG!"
-#endif
-#if BUILD_IS_NOT_DEBUG
-#error "BUILD_IS_NOT_DEBUG true with TEST_CONFIG_DEBUG!"
-#endif
+# if !BUILD_IS_DEBUG
+# error "BUILD_IS_DEBUG false with TEST_CONFIG_DEBUG!"
+# endif
+# if BUILD_IS_NOT_DEBUG
+# error "BUILD_IS_NOT_DEBUG true with TEST_CONFIG_DEBUG!"
+# endif
#else
-#if BUILD_IS_DEBUG
-#error "BUILD_IS_DEBUG true without TEST_CONFIG_DEBUG!"
-#endif
-#if !BUILD_IS_NOT_DEBUG
-#error "BUILD_IS_NOT_DEBUG false without TEST_CONFIG_DEBUG!"
-#endif
+# if BUILD_IS_DEBUG
+# error "BUILD_IS_DEBUG true without TEST_CONFIG_DEBUG!"
+# endif
+# if !BUILD_IS_NOT_DEBUG
+# error "BUILD_IS_NOT_DEBUG false without TEST_CONFIG_DEBUG!"
+# endif
#endif
int main(int argc, char** argv)
#ifndef LINK_CXX_DEFINE
-#error Expected LINK_CXX_DEFINE
+# error Expected LINK_CXX_DEFINE
#endif
#ifndef LINK_LANGUAGE_IS_CXX
-#error Expected LINK_LANGUAGE_IS_CXX
+# error Expected LINK_LANGUAGE_IS_CXX
#endif
#ifdef LINK_C_DEFINE
-#error Unexpected LINK_C_DEFINE
+# error Unexpected LINK_C_DEFINE
#endif
#ifdef LINK_LANGUAGE_IS_C
-#error Unexpected LINK_LANGUAGE_IS_C
+# error Unexpected LINK_LANGUAGE_IS_C
#endif
#ifndef C_EXECUTABLE_LINK_LANGUAGE_IS_C
-#error Expected C_EXECUTABLE_LINK_LANGUAGE_IS_C define
+# error Expected C_EXECUTABLE_LINK_LANGUAGE_IS_C define
#endif
void someFunc(void)
#ifndef LINK_CXX_DEFINE
-#error Expected LINK_CXX_DEFINE
+# error Expected LINK_CXX_DEFINE
#endif
#ifndef LINK_LANGUAGE_IS_CXX
-#error Expected LINK_LANGUAGE_IS_CXX
+# error Expected LINK_LANGUAGE_IS_CXX
#endif
#ifdef LINK_C_DEFINE
-#error Unexpected LINK_C_DEFINE
+# error Unexpected LINK_C_DEFINE
#endif
#ifdef LINK_LANGUAGE_IS_C
-#error Unexpected LINK_LANGUAGE_IS_C
+# error Unexpected LINK_LANGUAGE_IS_C
#endif
#ifndef C_EXECUTABLE_LINK_LANGUAGE_IS_C
-#error Expected C_EXECUTABLE_LINK_LANGUAGE_IS_C define
+# error Expected C_EXECUTABLE_LINK_LANGUAGE_IS_C define
#endif
int main(int argc, char** argv)
#include <string.h>
#ifndef BUILD_CONFIG_NAME
-#error "BUILD_CONFIG_NAME not defined!"
+# error "BUILD_CONFIG_NAME not defined!"
#endif
int main()
#ifndef TGT_DEF
-#error TGT_DEF incorrectly not defined
+# error TGT_DEF incorrectly not defined
#endif
#ifndef TGT_TYPE_STATIC_LIBRARY
-#error TGT_TYPE_STATIC_LIBRARY incorrectly not defined
+# error TGT_TYPE_STATIC_LIBRARY incorrectly not defined
#endif
#ifdef TGT_TYPE_EXECUTABLE
-#error TGT_TYPE_EXECUTABLE incorrectly defined
+# error TGT_TYPE_EXECUTABLE incorrectly defined
#endif
int main(void)
{
add_executable(CompileFeaturesGenex_C genex_test.c)
set_property(TARGET CompileFeaturesGenex_C PROPERTY C_STANDARD 11)
- if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
- if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6)
- list(APPEND expected_defs
- EXPECT_C_STATIC_ASSERT=1
- )
- else()
- list(APPEND expected_defs
- EXPECT_C_STATIC_ASSERT=0
+ foreach(f
+ c_restrict
+ c_static_assert
+ c_function_prototypes
)
- endif()
- elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang"
- OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
- list(APPEND expected_defs
- EXPECT_C_STATIC_ASSERT=1
- )
- elseif (CMAKE_C_COMPILER_ID STREQUAL "Intel")
- if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15)
- list(APPEND expected_defs
- EXPECT_C_STATIC_ASSERT=1
- )
+ if(${f} IN_LIST C_expected_features)
+ set(expect_${f} 1)
else()
- list(APPEND expected_defs
- EXPECT_C_STATIC_ASSERT=0
- )
+ set(expect_${f} 0)
endif()
- elseif (CMAKE_C_COMPILER_ID STREQUAL "SunPro")
- if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.13)
- list(APPEND expected_defs
- EXPECT_C_STATIC_ASSERT=1
- )
- else()
- list(APPEND expected_defs
- EXPECT_C_STATIC_ASSERT=0
- )
- endif()
- endif()
-
- list(APPEND expected_defs
- EXPECT_C_FUNCTION_PROTOTYPES=1
- EXPECT_C_RESTRICT=1
- )
-
- target_compile_definitions(CompileFeaturesGenex_C PRIVATE
- HAVE_C_FUNCTION_PROTOTYPES=$<COMPILE_FEATURES:c_function_prototypes>
- HAVE_C_RESTRICT=$<COMPILE_FEATURES:c_restrict>
- HAVE_C_STATIC_ASSERT=$<COMPILE_FEATURES:c_static_assert>
- ${expected_defs}
- )
+ string(TOUPPER "${f}" F)
+ target_compile_definitions(CompileFeaturesGenex_C PRIVATE
+ EXPECT_${F}=${expect_${f}}
+ HAVE_${F}=$<COMPILE_FEATURES:${f}>
+ )
+ endforeach()
endif()
if (CMAKE_CXX_COMPILE_FEATURES)
if (std_flag_idx EQUAL -1)
add_executable(default_dialect default_dialect.cpp)
target_compile_definitions(default_dialect PRIVATE
+ DEFAULT_CXX20=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},20>
DEFAULT_CXX17=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},17>
DEFAULT_CXX14=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},14>
DEFAULT_CXX11=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},11>
add_executable(IfaceCompileFeatures main.cpp)
target_link_libraries(IfaceCompileFeatures iface)
- if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=1
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
- )
- elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7)
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=0
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
- )
- else()
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=0
- -DEXPECT_INHERITING_CONSTRUCTORS=0
- -DEXPECT_FINAL=0
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
- )
- endif()
- elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=1
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
- )
- elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
- if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=1
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
- )
- else()
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=0
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
- )
- endif()
- elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
- if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0)
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=1
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
- )
- elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0)
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=0
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
- )
- else()
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=0
- -DEXPECT_INHERITING_CONSTRUCTORS=0
- -DEXPECT_FINAL=0
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
- )
- endif()
- elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=1
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
- )
- elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
- if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=1
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1
- )
- elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=1
- -DEXPECT_INHERITING_CONSTRUCTORS=0
- -DEXPECT_FINAL=1
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
+ foreach(f
+ cxx_final
+ cxx_override
+ cxx_auto_type
+ cxx_inheriting_constructors
)
+ if(${f} IN_LIST CXX_expected_features)
+ set(expect_${f} 1)
else()
- add_definitions(
- -DEXPECT_OVERRIDE_CONTROL=0
- -DEXPECT_INHERITING_CONSTRUCTORS=0
- -DEXPECT_FINAL=0
- -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0
- )
+ set(expect_${f} 0)
endif()
+ endforeach()
+
+ if(expect_cxx_final AND expect_cxx_override)
+ set(expect_override_control 1)
+ else()
+ set(expect_override_control 0)
+ endif()
+ if(expect_cxx_inheriting_constructors AND expect_cxx_final)
+ set(expect_inheriting_constructors_and_final 1)
+ else()
+ set(expect_inheriting_constructors_and_final 0)
endif()
- add_executable(CompileFeaturesGenex genex_test.cpp)
- set_property(TARGET CompileFeaturesGenex PROPERTY CXX_STANDARD 11)
- target_compile_definitions(CompileFeaturesGenex PRIVATE
+ set(genex_test_defs
HAVE_OVERRIDE_CONTROL=$<COMPILE_FEATURES:cxx_final,cxx_override>
HAVE_AUTO_TYPE=$<COMPILE_FEATURES:cxx_auto_type>
HAVE_INHERITING_CONSTRUCTORS=$<COMPILE_FEATURES:cxx_inheriting_constructors>
HAVE_FINAL=$<COMPILE_FEATURES:cxx_final>
HAVE_INHERITING_CONSTRUCTORS_AND_FINAL=$<COMPILE_FEATURES:cxx_inheriting_constructors,cxx_final>
- )
+ EXPECT_OVERRIDE_CONTROL=${expect_override_control}
+ EXPECT_INHERITING_CONSTRUCTORS=${expect_cxx_inheriting_constructors}
+ EXPECT_FINAL=${expect_cxx_final}
+ EXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=${expect_inheriting_constructors_and_final}
+ )
if (CMAKE_CXX_STANDARD_DEFAULT)
- target_compile_definitions(CompileFeaturesGenex PRIVATE
+ list(APPEND genex_test_defs
TEST_CXX_STD
HAVE_CXX_STD_11=$<COMPILE_FEATURES:cxx_std_11>
HAVE_CXX_STD_14=$<COMPILE_FEATURES:cxx_std_14>
HAVE_CXX_STD_17=$<COMPILE_FEATURES:cxx_std_17>
+ HAVE_CXX_STD_20=$<COMPILE_FEATURES:cxx_std_20>
)
endif()
+ add_executable(CompileFeaturesGenex genex_test.cpp)
+ set_property(TARGET CompileFeaturesGenex PROPERTY CXX_STANDARD 11)
+ target_compile_definitions(CompileFeaturesGenex PRIVATE ${genex_test_defs})
+
add_executable(CompileFeaturesGenex2 genex_test.cpp)
target_compile_features(CompileFeaturesGenex2 PRIVATE cxx_std_11)
- target_compile_definitions(CompileFeaturesGenex2 PRIVATE
- HAVE_OVERRIDE_CONTROL=$<COMPILE_FEATURES:cxx_final,cxx_override>
- HAVE_AUTO_TYPE=$<COMPILE_FEATURES:cxx_auto_type>
- HAVE_INHERITING_CONSTRUCTORS=$<COMPILE_FEATURES:cxx_inheriting_constructors>
- HAVE_FINAL=$<COMPILE_FEATURES:cxx_final>
- HAVE_INHERITING_CONSTRUCTORS_AND_FINAL=$<COMPILE_FEATURES:cxx_inheriting_constructors,cxx_final>
- )
+ target_compile_definitions(CompileFeaturesGenex2 PRIVATE ${genex_test_defs})
add_library(std_11_iface INTERFACE)
target_compile_features(std_11_iface INTERFACE cxx_std_11)
add_executable(CompileFeaturesGenex3 genex_test.cpp)
target_link_libraries(CompileFeaturesGenex3 PRIVATE std_11_iface)
- target_compile_definitions(CompileFeaturesGenex3 PRIVATE
- HAVE_OVERRIDE_CONTROL=$<COMPILE_FEATURES:cxx_final,cxx_override>
- HAVE_AUTO_TYPE=$<COMPILE_FEATURES:cxx_auto_type>
- HAVE_INHERITING_CONSTRUCTORS=$<COMPILE_FEATURES:cxx_inheriting_constructors>
- HAVE_FINAL=$<COMPILE_FEATURES:cxx_final>
- HAVE_INHERITING_CONSTRUCTORS_AND_FINAL=$<COMPILE_FEATURES:cxx_inheriting_constructors,cxx_final>
- )
+ target_compile_definitions(CompileFeaturesGenex3 PRIVATE ${genex_test_defs})
endif()
-[[deprecated]] int foo()
-{
- return 0;
-}
+[[deprecated]] int foo() { return 0; }
int someFunc()
{
}
operator T&() { return val; }
operator T() const { return val; }
+
private:
T val;
};
#if defined(_MSC_VER) && _MSC_VER == 1800 && _MSC_FULL_VER < 180030723
-#error "VS 2013 safely supports this only with Update 3 or greater"
+# error "VS 2013 safely supports this only with Update 3 or greater"
#endif
// Dummy implementation. Test only the compiler feature.
int someFunc()
{
int a = 0;
- return [b = static_cast<int&&>(a)]() { return b; }
- ();
+ return [b = static_cast<int&&>(a)]() { return b; }();
}
#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) < 407)
-#define OLD_GNU
+# define OLD_GNU
#endif
#ifdef OLD_GNU
#if DEFAULT_C11
-#if __STDC_VERSION__ < 201112L
-#error Unexpected value for __STDC_VERSION__.
-#endif
+# if __STDC_VERSION__ < 201112L
+# error Unexpected value for __STDC_VERSION__.
+# endif
#elif DEFAULT_C99
-#if __STDC_VERSION__ != 199901L
-#error Unexpected value for __STDC_VERSION__.
-#endif
+# if __STDC_VERSION__ != 199901L
+# error Unexpected value for __STDC_VERSION__.
+# endif
#else
-#if !DEFAULT_C90
-#error Buildsystem error
-#endif
-#if defined(__STDC_VERSION__) && \
- !(defined(__SUNPRO_C) && __STDC_VERSION__ == 199409L)
-#error Unexpected __STDC_VERSION__ definition
-#endif
+# if !DEFAULT_C90
+# error Buildsystem error
+# endif
+# if defined(__STDC_VERSION__) && \
+ !(defined(__SUNPRO_C) && __STDC_VERSION__ == 199409L)
+# error Unexpected __STDC_VERSION__ definition
+# endif
#endif
int main()
struct Outputter;
#if defined(_MSC_VER) && defined(_MSVC_LANG)
-#define CXX_STD _MSVC_LANG
+# define CXX_STD _MSVC_LANG
#else
-#define CXX_STD __cplusplus
+# define CXX_STD __cplusplus
#endif
-#if DEFAULT_CXX17
-#if CXX_STD <= 201402L
+#if DEFAULT_CXX20
+# if CXX_STD <= 201703L
Outputter<CXX_STD> o;
-#endif
+# endif
+#elif DEFAULT_CXX17
+# if CXX_STD <= 201402L
+Outputter<CXX_STD> o;
+# endif
#elif DEFAULT_CXX14
-#if CXX_STD != 201402L
+# if CXX_STD != 201402L
Outputter<CXX_STD> o;
-#endif
+# endif
#elif DEFAULT_CXX11
-#if CXX_STD != 201103L
+# if CXX_STD != 201103L
Outputter<CXX_STD> o;
-#endif
+# endif
#else
-#if !DEFAULT_CXX98
-#error Buildsystem error
-#endif
-#if CXX_STD != 199711L && CXX_STD != 1 && !defined(__GXX_EXPERIMENTAL_CXX0X__)
+# if !DEFAULT_CXX98
+# error Buildsystem error
+# endif
+# if CXX_STD != 199711L && CXX_STD != 1 && \
+ !defined(__GXX_EXPERIMENTAL_CXX0X__)
Outputter<CXX_STD> o;
-#endif
+# endif
#endif
int main()
#ifndef EXPECT_C_STATIC_ASSERT
-#error EXPECT_C_STATIC_ASSERT not defined
+# error EXPECT_C_STATIC_ASSERT not defined
#endif
#ifndef EXPECT_C_FUNCTION_PROTOTYPES
-#error EXPECT_C_FUNCTION_PROTOTYPES not defined
+# error EXPECT_C_FUNCTION_PROTOTYPES not defined
#endif
#ifndef EXPECT_C_RESTRICT
-#error EXPECT_C_RESTRICT not defined
+# error EXPECT_C_RESTRICT not defined
#endif
-#if !EXPECT_C_STATIC_ASSERT
-#if EXPECT_C_STATIC_ASSERT
-#error "Expect c_static_assert feature"
-#endif
+#if !HAVE_C_STATIC_ASSERT
+# if EXPECT_C_STATIC_ASSERT
+# error "Expect c_static_assert feature"
+# endif
#else
-#if !EXPECT_C_STATIC_ASSERT
-#error "Expect no c_static_assert feature"
-#endif
+# if !EXPECT_C_STATIC_ASSERT
+# error "Expect no c_static_assert feature"
+# endif
#endif
-#if !EXPECT_C_FUNCTION_PROTOTYPES
-#error Expect c_function_prototypes support
+#if !HAVE_C_FUNCTION_PROTOTYPES
+# if EXPECT_C_FUNCTION_PROTOTYPES
+# error Expect c_function_prototypes support
+# endif
+#else
+# if !EXPECT_C_FUNCTION_PROTOTYPES
+# error Expect no c_function_prototypes support
+# endif
#endif
-#if !EXPECT_C_RESTRICT
-#if EXPECT_C_RESTRICT
-#error Expect c_restrict support
-#endif
+#if !HAVE_C_RESTRICT
+# if EXPECT_C_RESTRICT
+# error Expect c_restrict support
+# endif
#else
-#if !EXPECT_C_RESTRICT
-#error Expect no c_restrict support
-#endif
+# if !EXPECT_C_RESTRICT
+# error Expect no c_restrict support
+# endif
#endif
int main()
#ifndef EXPECT_FINAL
-#error EXPECT_FINAL not defined
+# error EXPECT_FINAL not defined
#endif
#ifndef EXPECT_INHERITING_CONSTRUCTORS
-#error EXPECT_INHERITING_CONSTRUCTORS not defined
+# error EXPECT_INHERITING_CONSTRUCTORS not defined
#endif
#ifndef EXPECT_INHERITING_CONSTRUCTORS_AND_FINAL
-#error EXPECT_INHERITING_CONSTRUCTORS_AND_FINAL not defined
+# error EXPECT_INHERITING_CONSTRUCTORS_AND_FINAL not defined
#endif
#ifndef EXPECT_OVERRIDE_CONTROL
-#error EXPECT_OVERRIDE_CONTROL not defined
+# error EXPECT_OVERRIDE_CONTROL not defined
#endif
#ifdef TEST_CXX_STD
-#if !HAVE_CXX_STD_11
-#error HAVE_CXX_STD_11 is false with CXX_STANDARD == 11
-#endif
-#if HAVE_CXX_STD_14
-#error HAVE_CXX_STD_14 is true with CXX_STANDARD == 11
-#endif
-#if HAVE_CXX_STD_17
-#error HAVE_CXX_STD_17 is true with CXX_STANDARD == 11
-#endif
+# if !HAVE_CXX_STD_11
+# error HAVE_CXX_STD_11 is false with CXX_STANDARD == 11
+# endif
+# if HAVE_CXX_STD_14
+# error HAVE_CXX_STD_14 is true with CXX_STANDARD == 11
+# endif
+# if HAVE_CXX_STD_17
+# error HAVE_CXX_STD_17 is true with CXX_STANDARD == 11
+# endif
#endif
#if !HAVE_OVERRIDE_CONTROL
-#if EXPECT_OVERRIDE_CONTROL
-#error "Expect override control feature"
-#endif
+# if EXPECT_OVERRIDE_CONTROL
+# error "Expect override control feature"
+# endif
#else
-#if !EXPECT_OVERRIDE_CONTROL
-#error "Expect no override control feature"
-#endif
+# if !EXPECT_OVERRIDE_CONTROL
+# error "Expect no override control feature"
+# endif
struct A
{
#endif
#if !HAVE_AUTO_TYPE
-#error Expect cxx_auto_type support
+# error Expect cxx_auto_type support
#endif
#if !HAVE_INHERITING_CONSTRUCTORS
-#if EXPECT_INHERITING_CONSTRUCTORS
-#error Expect cxx_inheriting_constructors support
-#endif
+# if EXPECT_INHERITING_CONSTRUCTORS
+# error Expect cxx_inheriting_constructors support
+# endif
#else
-#if !EXPECT_INHERITING_CONSTRUCTORS
-#error Expect no cxx_inheriting_constructors support
-#endif
+# if !EXPECT_INHERITING_CONSTRUCTORS
+# error Expect no cxx_inheriting_constructors support
+# endif
#endif
#if !HAVE_FINAL
-#if EXPECT_FINAL
-#error Expect cxx_final support
-#endif
+# if EXPECT_FINAL
+# error Expect cxx_final support
+# endif
#else
-#if !EXPECT_FINAL
-#error Expect no cxx_final support
-#endif
+# if !EXPECT_FINAL
+# error Expect no cxx_final support
+# endif
#endif
#if !HAVE_INHERITING_CONSTRUCTORS_AND_FINAL
-#if EXPECT_INHERITING_CONSTRUCTORS_AND_FINAL
-#error Expect cxx_inheriting_constructors and cxx_final support
-#endif
+# if EXPECT_INHERITING_CONSTRUCTORS_AND_FINAL
+# error Expect cxx_inheriting_constructors and cxx_final support
+# endif
#else
-#if !EXPECT_INHERITING_CONSTRUCTORS_AND_FINAL
-#error Expect no combined cxx_inheriting_constructors and cxx_final support
-#endif
+# if !EXPECT_INHERITING_CONSTRUCTORS_AND_FINAL
+# error Expect no combined cxx_inheriting_constructors and cxx_final support
+# endif
#endif
int main()
"-DTEST_DEFINE"
"-DNEEDS_ESCAPE=\"E$CAPE\""
"$<$<CXX_COMPILER_ID:GNU>:-DTEST_DEFINE_GNU>"
+ "SHELL:" # produces no options
${c_tests}
${cxx_tests}
)
+if(BORLAND OR WATCOM)
+ # these compilers do not support separate -D flags
+ target_compile_definitions(CompileOptions PRIVATE NO_DEF_TESTS)
+else()
+ set_property(TARGET CompileOptions APPEND PROPERTY COMPILE_OPTIONS
+ "SHELL:-D DEF_A"
+ "$<1:SHELL:-D DEF_B>"
+ "SHELL:-D 'DEF_C' -D \"DEF_D\""
+ [[SHELL:-D "DEF_STR=\"string with spaces\""]]
+ )
+endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Borland|Embarcadero")
set_property(TARGET CompileOptions APPEND PROPERTY COMPILE_OPTIONS
#ifndef TEST_DEFINE
-#error Expected definition TEST_DEFINE
+# error Expected definition TEST_DEFINE
#endif
#ifndef NEEDS_ESCAPE
-#error Expected definition NEEDS_ESCAPE
+# error Expected definition NEEDS_ESCAPE
#endif
#ifdef DO_GNU_TESTS
-#ifndef TEST_DEFINE_GNU
-#error Expected definition TEST_DEFINE_GNU
+# ifndef TEST_DEFINE_GNU
+# error Expected definition TEST_DEFINE_GNU
+# endif
#endif
+
+#ifndef NO_DEF_TESTS
+# ifndef DEF_A
+# error Expected definition DEF_A
+# endif
+
+# ifndef DEF_B
+# error Expected definition DEF_B
+# endif
+
+# ifndef DEF_C
+# error Expected definition DEF_C
+# endif
+
+# ifndef DEF_D
+# error Expected definition DEF_D
+# endif
+
+# ifndef DEF_STR
+# error Expected definition DEF_STR
+# endif
#endif
#include <string.h>
#ifdef TEST_OCTOTHORPE
&& strcmp(TEST_OCTOTHORPE, "#") == 0
#endif
+#ifndef NO_DEF_TESTS
+ && strcmp(DEF_STR, "string with spaces") == 0
+#endif
&&
strcmp(EXPECTED_C_COMPILER_VERSION, TEST_C_COMPILER_VERSION) == 0 &&
strcmp(EXPECTED_CXX_COMPILER_VERSION, TEST_CXX_COMPILER_VERSION) ==
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
-# KEY is the name of a varible in the cache.
+# KEY is the name of a variable in the cache.
# TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
#include <stdio.h>
#include <sys/stat.h>
#if !defined(S_ISDIR)
-#define S_ISDIR(mode) ((mode)&_S_IFDIR)
+# define S_ISDIR(mode) ((mode)&_S_IFDIR)
#endif
#ifdef COMPLEX_TEST_LINK_STATIC
}
#ifndef COMPLEX_DEFINED_PRE
-#error "COMPLEX_DEFINED_PRE not defined!"
+# error "COMPLEX_DEFINED_PRE not defined!"
#endif
#ifdef COMPLEX_DEFINED
-#error "COMPLEX_DEFINED is defined but it should not!"
+# error "COMPLEX_DEFINED is defined but it should not!"
#endif
#ifndef COMPLEX_DEFINED_POST
-#error "COMPLEX_DEFINED_POST not defined!"
+# error "COMPLEX_DEFINED_POST not defined!"
#endif
#ifndef CMAKE_IS_REALLY_FUN
-#error This is a problem. Looks like ADD_DEFINITIONS and REMOVE_DEFINITIONS does not work
+# error This is a problem. Looks like ADD_DEFINITIONS and REMOVE_DEFINITIONS does not work
#endif
#if defined(NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE)
-#error Per-configuration directory-level definition not inherited.
+# error Per-configuration directory-level definition not inherited.
#endif
// ======================================================================
cmFailed(msg);
}
-// ----------------------------------------------------------------------
-// Test ADD_DEFINITIONS
+ // ----------------------------------------------------------------------
+ // Test ADD_DEFINITIONS
#ifndef CMAKE_IS_FUN
cmFailed("CMake is not fun, so it is broken and should be fixed.");
cmPassed("CMake found the listfile stack properly");
#endif
-// ----------------------------------------------------------------------
-// Test SET, VARIABLE_REQUIRES
+ // ----------------------------------------------------------------------
+ // Test SET, VARIABLE_REQUIRES
#ifdef SHOULD_NOT_BE_DEFINED
cmFailed("IF or SET is broken, SHOULD_NOT_BE_DEFINED is defined.");
}
#endif
-// ----------------------------------------------------------------------
-// Test various IF/ELSE combinations
+ // ----------------------------------------------------------------------
+ // Test various IF/ELSE combinations
#ifdef SHOULD_NOT_BE_DEFINED_NOT
cmFailed("IF or SET is broken, SHOULD_NOT_BE_DEFINED_NOT is defined.");
cmPassed("SHOULD_BE_DEFINED_STRGREATER_EQUAL3 is defined.");
#endif
-// ----------------------------------------------------------------------
-// Test FOREACH
+ // ----------------------------------------------------------------------
+ // Test FOREACH
#ifndef FOREACH_VAR1
cmFailed("the FOREACH, SET or CONFIGURE_FILE command is broken, "
cmPassed("WHILE command is working");
}
-// ----------------------------------------------------------------------
-// Test LOAD_CACHE
+ // ----------------------------------------------------------------------
+ // Test LOAD_CACHE
#ifndef CACHE_TEST_VAR1
cmFailed("the LOAD_CACHE or CONFIGURE_FILE command is broken, "
TestAndRemoveFile("Executable/Temp/complex-required.txt");
-// ----------------------------------------------------------------------
-// Test FIND_LIBRARY
+ // ----------------------------------------------------------------------
+ // Test FIND_LIBRARY
#ifndef FIND_DUMMY_LIB
cmFailed("the CONFIGURE_FILE command is broken, "
}
#endif
-// ----------------------------------------------------------------------
-// Test SET_SOURCE_FILES_PROPERTIES
+ // ----------------------------------------------------------------------
+ // Test SET_SOURCE_FILES_PROPERTIES
#ifndef FILE_HAS_EXTRA_COMPILE_FLAGS
cmFailed("SET_SOURCE_FILES_PROPERTIES failed at setting "
#endif
#if 0 // Disable until implemented everywhere.
-#ifndef FILE_DEFINE_STRING
+# ifndef FILE_DEFINE_STRING
cmFailed("SET_SOURCE_FILES_PROPERTIES failed at setting FILE_DEFINE_STRING flag");
-#else
+# else
if(strcmp(FILE_DEFINE_STRING, "hello") != 0)
{
cmFailed("SET_SOURCE_FILES_PROPERTIES failed at setting FILE_DEFINE_STRING flag correctly");
{
cmPassed("SET_SOURCE_FILES_PROPERTIES succeeded in setting FILE_DEFINE_STRING flag");
}
-#endif
+# endif
#endif
#ifndef FILE_HAS_ABSTRACT
// ----------------------------------------------------------------------
// Test registry (win32)
#if defined(_WIN32) && !defined(__CYGWIN__)
-#ifndef REGISTRY_TEST_PATH
+# ifndef REGISTRY_TEST_PATH
cmFailed("the CONFIGURE_FILE command is broken, REGISTRY_TEST_PATH is not "
"defined.");
-#else
+# else
std::cout << "REGISTRY_TEST_PATH == " << REGISTRY_TEST_PATH << "\n";
if (stricmp(REGISTRY_TEST_PATH, BINARY_DIR "/registry_dir") != 0) {
cmFailed("the 'read registry value' function or CONFIGURE_FILE command is "
} else {
cmPassed("REGISTRY_TEST_PATH == ", REGISTRY_TEST_PATH);
}
-#endif
+# endif
#endif // defined(_WIN32) && !defined(__CYGWIN__)
if (strcmp(CMAKE_MINIMUM_REQUIRED_VERSION, "2.4") == 0) {
#if 0
-#include "cmMissingHeader.h"
+# include "cmMissingHeader.h"
#endif
int main(int, char**)
}
#if 1
-#error "This target should not be compiled by ALL."
+# error "This target should not be compiled by ALL."
#endif
define_property(
TARGET PROPERTY FOO
BRIEF_DOCS "a test property"
- FULL_DOCS "A simple etst proerty that means nothign and is used for nothing"
+ FULL_DOCS "A simple test property that means nothing and is used for nothing"
)
set_target_properties(CMakeTestCLibraryShared PROPERTIES FOO BAR)
if(NOT BEOS AND NOT WIN32 AND NOT HAIKU) # No libm on BeOS.
}
#if 1
-#error "This target should not be compiled by ALL."
+# error "This target should not be compiled by ALL."
#endif
#if defined(_WIN32) || defined(WIN32) /* Win32 version */
-#ifdef CMakeTestLibraryShared_EXPORTS
-#define CMakeTest_EXPORT __declspec(dllexport)
-#else
-#define CMakeTest_EXPORT __declspec(dllimport)
-#endif
+# ifdef CMakeTestLibraryShared_EXPORTS
+# define CMakeTest_EXPORT __declspec(dllexport)
+# else
+# define CMakeTest_EXPORT __declspec(dllimport)
+# endif
#else
/* unix needs nothing */
-#define CMakeTest_EXPORT
+# define CMakeTest_EXPORT
#endif
CMakeTest_EXPORT int sharedFunction();
#if defined(_WIN32) || defined(WIN32) /* Win32 version */
-#ifdef CMakeTestCLibraryShared_EXPORTS
-#define CMakeTest_EXPORT __declspec(dllexport)
-#else
-#define CMakeTest_EXPORT __declspec(dllimport)
-#endif
+# ifdef CMakeTestCLibraryShared_EXPORTS
+# define CMakeTest_EXPORT __declspec(dllexport)
+# else
+# define CMakeTest_EXPORT __declspec(dllimport)
+# endif
#else
/* unix needs nothing */
-#define CMakeTest_EXPORT
+# define CMakeTest_EXPORT
#endif
CMakeTest_EXPORT int CsharedFunction();
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
-# KEY is the name of a varible in the cache.
+# KEY is the name of a variable in the cache.
# TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
#include <stdio.h>
#include <sys/stat.h>
#if !defined(S_ISDIR)
-#define S_ISDIR(mode) ((mode)&_S_IFDIR)
+# define S_ISDIR(mode) ((mode)&_S_IFDIR)
#endif
#ifdef COMPLEX_TEST_LINK_STATIC
}
#ifndef COMPLEX_DEFINED_PRE
-#error "COMPLEX_DEFINED_PRE not defined!"
+# error "COMPLEX_DEFINED_PRE not defined!"
#endif
#ifdef COMPLEX_DEFINED
-#error "COMPLEX_DEFINED is defined but it should not!"
+# error "COMPLEX_DEFINED is defined but it should not!"
#endif
#ifndef COMPLEX_DEFINED_POST
-#error "COMPLEX_DEFINED_POST not defined!"
+# error "COMPLEX_DEFINED_POST not defined!"
#endif
#ifndef CMAKE_IS_REALLY_FUN
-#error This is a problem. Looks like ADD_DEFINITIONS and REMOVE_DEFINITIONS does not work
+# error This is a problem. Looks like ADD_DEFINITIONS and REMOVE_DEFINITIONS does not work
#endif
#if defined(NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE)
-#error Per-configuration directory-level definition not inherited.
+# error Per-configuration directory-level definition not inherited.
#endif
// ======================================================================
cmFailed(msg);
}
-// ----------------------------------------------------------------------
-// Test ADD_DEFINITIONS
+ // ----------------------------------------------------------------------
+ // Test ADD_DEFINITIONS
#ifndef CMAKE_IS_FUN
cmFailed("CMake is not fun, so it is broken and should be fixed.");
cmPassed("CMake found the listfile stack properly");
#endif
-// ----------------------------------------------------------------------
-// Test SET, VARIABLE_REQUIRES
+ // ----------------------------------------------------------------------
+ // Test SET, VARIABLE_REQUIRES
#ifdef SHOULD_NOT_BE_DEFINED
cmFailed("IF or SET is broken, SHOULD_NOT_BE_DEFINED is defined.");
}
#endif
-// ----------------------------------------------------------------------
-// Test various IF/ELSE combinations
+ // ----------------------------------------------------------------------
+ // Test various IF/ELSE combinations
#ifdef SHOULD_NOT_BE_DEFINED_NOT
cmFailed("IF or SET is broken, SHOULD_NOT_BE_DEFINED_NOT is defined.");
cmPassed("SHOULD_BE_DEFINED_STRGREATER_EQUAL3 is defined.");
#endif
-// ----------------------------------------------------------------------
-// Test FOREACH
+ // ----------------------------------------------------------------------
+ // Test FOREACH
#ifndef FOREACH_VAR1
cmFailed("the FOREACH, SET or CONFIGURE_FILE command is broken, "
cmPassed("WHILE command is working");
}
-// ----------------------------------------------------------------------
-// Test LOAD_CACHE
+ // ----------------------------------------------------------------------
+ // Test LOAD_CACHE
#ifndef CACHE_TEST_VAR1
cmFailed("the LOAD_CACHE or CONFIGURE_FILE command is broken, "
TestAndRemoveFile("Executable/Temp/complex-required.txt");
-// ----------------------------------------------------------------------
-// Test FIND_LIBRARY
+ // ----------------------------------------------------------------------
+ // Test FIND_LIBRARY
#ifndef FIND_DUMMY_LIB
cmFailed("the CONFIGURE_FILE command is broken, "
}
#endif
-// ----------------------------------------------------------------------
-// Test SET_SOURCE_FILES_PROPERTIES
+ // ----------------------------------------------------------------------
+ // Test SET_SOURCE_FILES_PROPERTIES
#ifndef FILE_HAS_EXTRA_COMPILE_FLAGS
cmFailed("SET_SOURCE_FILES_PROPERTIES failed at setting "
#endif
#if 0 // Disable until implemented everywhere.
-#ifndef FILE_DEFINE_STRING
+# ifndef FILE_DEFINE_STRING
cmFailed("SET_SOURCE_FILES_PROPERTIES failed at setting FILE_DEFINE_STRING flag");
-#else
+# else
if(strcmp(FILE_DEFINE_STRING, "hello") != 0)
{
cmFailed("SET_SOURCE_FILES_PROPERTIES failed at setting FILE_DEFINE_STRING flag correctly");
{
cmPassed("SET_SOURCE_FILES_PROPERTIES succeeded in setting FILE_DEFINE_STRING flag");
}
-#endif
+# endif
#endif
#ifndef FILE_HAS_ABSTRACT
// ----------------------------------------------------------------------
// Test registry (win32)
#if defined(_WIN32) && !defined(__CYGWIN__)
-#ifndef REGISTRY_TEST_PATH
+# ifndef REGISTRY_TEST_PATH
cmFailed("the CONFIGURE_FILE command is broken, REGISTRY_TEST_PATH is not "
"defined.");
-#else
+# else
std::cout << "REGISTRY_TEST_PATH == " << REGISTRY_TEST_PATH << "\n";
if (stricmp(REGISTRY_TEST_PATH, BINARY_DIR "/registry_dir") != 0) {
cmFailed("the 'read registry value' function or CONFIGURE_FILE command is "
} else {
cmPassed("REGISTRY_TEST_PATH == ", REGISTRY_TEST_PATH);
}
-#endif
+# endif
#endif // defined(_WIN32) && !defined(__CYGWIN__)
if (strcmp(CMAKE_MINIMUM_REQUIRED_VERSION, "2.4") == 0) {
#if 0
-#include "cmMissingHeader.h"
+# include "cmMissingHeader.h"
#endif
int main(int, char**)
}
#if 1
-#error "This target should not be compiled by ALL."
+# error "This target should not be compiled by ALL."
#endif
define_property(
TARGET PROPERTY FOO
BRIEF_DOCS "a test property"
- FULL_DOCS "A simple etst proerty that means nothign and is used for nothing"
+ FULL_DOCS "A simple test property that means nothing and is used for nothing"
)
set_target_properties(CMakeTestCLibraryShared PROPERTIES FOO BAR)
if(NOT BEOS AND NOT WIN32 AND NOT HAIKU) # No libm on BeOS.
}
#if 1
-#error "This target should not be compiled by ALL."
+# error "This target should not be compiled by ALL."
#endif
#if defined(_WIN32) || defined(WIN32) /* Win32 version */
-#ifdef CMakeTestLibraryShared_EXPORTS
-#define CMakeTest_EXPORT __declspec(dllexport)
-#else
-#define CMakeTest_EXPORT __declspec(dllimport)
-#endif
+# ifdef CMakeTestLibraryShared_EXPORTS
+# define CMakeTest_EXPORT __declspec(dllexport)
+# else
+# define CMakeTest_EXPORT __declspec(dllimport)
+# endif
#else
/* unix needs nothing */
-#define CMakeTest_EXPORT
+# define CMakeTest_EXPORT
#endif
CMakeTest_EXPORT int sharedFunction();
#if defined(_WIN32) || defined(WIN32) /* Win32 version */
-#ifdef CMakeTestCLibraryShared_EXPORTS
-#define CMakeTest_EXPORT __declspec(dllexport)
-#else
-#define CMakeTest_EXPORT __declspec(dllimport)
-#endif
+# ifdef CMakeTestCLibraryShared_EXPORTS
+# define CMakeTest_EXPORT __declspec(dllexport)
+# else
+# define CMakeTest_EXPORT __declspec(dllimport)
+# endif
#else
/* unix needs nothing */
-#define CMakeTest_EXPORT
+# define CMakeTest_EXPORT
#endif
CMakeTest_EXPORT int CsharedFunction();
set(PLplot_GIT_TAG "plplot-5.13.0")
endif()
ExternalProject_Add(PLplot
- GIT_REPOSITORY "https://git.code.sf.net/p/plplot/plplot.git"
+ GIT_REPOSITORY "https://git.code.sf.net/p/plplot/plplot"
GIT_TAG "${PLplot_GIT_TAG}"
PREFIX "${PLplot_PREFIX}"
CMAKE_ARGS
#ifdef _WIN32
-#define EXPORT __declspec(dllexport)
+# define EXPORT __declspec(dllexport)
#else
-#define EXPORT
+# define EXPORT
#endif
EXPORT int dynamic_base_func(int x)
#include <string>
#ifdef _WIN32
-#define EXPORT __declspec(dllexport)
+# define EXPORT __declspec(dllexport)
#else
-#define EXPORT
+# define EXPORT
#endif
int dynamic_base_func(int);
#include "file2.h"
#ifdef _WIN32
-#define IMPORT __declspec(dllimport)
+# define IMPORT __declspec(dllimport)
#else
-#define IMPORT
+# define IMPORT
#endif
IMPORT int choose_cuda_device();
#ifdef _WIN32
-#define EXPORT __declspec(dllexport)
-#define IMPORT __declspec(dllimport)
+# define EXPORT __declspec(dllexport)
+# define IMPORT __declspec(dllimport)
#else
-#define EXPORT
-#define IMPORT
+# define EXPORT
+# define IMPORT
#endif
int dynamic_base_func(int);
#include "file2.h"
#ifdef _WIN32
-#define EXPORT __declspec(dllexport)
-#define IMPORT __declspec(dllimport)
+# define EXPORT __declspec(dllexport)
+# define IMPORT __declspec(dllimport)
#else
-#define EXPORT
-#define IMPORT
+# define EXPORT
+# define IMPORT
#endif
result_type __device__ file1_func(int x);
extern int use_cuda(void);
#ifdef _WIN32
-#include <windows.h>
+# include <windows.h>
#endif
int main()
ADD_TEST_MACRO(CudaOnly.EnableStandard CudaOnlyEnableStandard)
ADD_TEST_MACRO(CudaOnly.ExportPTX CudaOnlyExportPTX)
ADD_TEST_MACRO(CudaOnly.GPUDebugFlag CudaOnlyGPUDebugFlag)
+ADD_TEST_MACRO(CudaOnly.LinkSystemDeviceLibraries CudaOnlyLinkSystemDeviceLibraries)
ADD_TEST_MACRO(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
ADD_TEST_MACRO(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation)
ADD_TEST_MACRO(CudaOnly.WithDefs CudaOnlyWithDefs)
+
+if(MSVC)
+ ADD_TEST_MACRO(CudaOnly.PDB CudaOnlyPDB)
+endif()
#include <iostream>
#ifdef _WIN32
-#define IMPORT __declspec(dllimport)
+# define IMPORT __declspec(dllimport)
#else
-#define IMPORT
+# define IMPORT
#endif
int static_cuda11_func(int);
#include <type_traits>
#ifdef _WIN32
-#define EXPORT __declspec(dllexport)
+# define EXPORT __declspec(dllexport)
#else
-#define EXPORT
+# define EXPORT
#endif
using tt = std::true_type;
--- /dev/null
+cmake_minimum_required(VERSION 3.8)
+project(CudaOnlyLinkSystemDeviceLibraries CUDA)
+
+string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_35,code=compute_35 -gencode arch=compute_35,code=sm_35")
+set(CMAKE_CUDA_STANDARD 11)
+
+add_executable(CudaOnlyLinkSystemDeviceLibraries main.cu)
+set_target_properties( CudaOnlyLinkSystemDeviceLibraries
+ PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
+target_link_libraries( CudaOnlyLinkSystemDeviceLibraries PRIVATE cublas_device)
+
+if(APPLE)
+ # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
+ set_property(TARGET CudaOnlyLinkSystemDeviceLibraries PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+endif()
--- /dev/null
+
+#include <cublas_v2.h>
+#include <cuda_runtime.h>
+#include <iostream>
+
+__global__ void deviceCublasSgemm(int n, float alpha, float beta,
+ const float* d_A, const float* d_B,
+ float* d_C)
+{
+ cublasHandle_t cnpHandle;
+ cublasStatus_t status = cublasCreate(&cnpHandle);
+
+ if (status != CUBLAS_STATUS_SUCCESS) {
+ return;
+ }
+
+ // Call function defined in the cublas_device system static library.
+ // This way we can verify that we properly pass system libraries to the
+ // device link line
+ status = cublasSgemm(cnpHandle, CUBLAS_OP_N, CUBLAS_OP_N, n, n, n, &alpha,
+ d_A, n, d_B, n, &beta, d_C, n);
+
+ cublasDestroy(cnpHandle);
+}
+
+int choose_cuda_device()
+{
+ int nDevices = 0;
+ cudaError_t err = cudaGetDeviceCount(&nDevices);
+ if (err != cudaSuccess) {
+ std::cerr << "Failed to retrieve the number of CUDA enabled devices"
+ << std::endl;
+ return 1;
+ }
+ for (int i = 0; i < nDevices; ++i) {
+ cudaDeviceProp prop;
+ cudaError_t err = cudaGetDeviceProperties(&prop, i);
+ if (err != cudaSuccess) {
+ std::cerr << "Could not retrieve properties from CUDA device " << i
+ << std::endl;
+ return 1;
+ }
+
+ if (prop.major > 3 || (prop.major == 3 && prop.minor >= 5)) {
+ err = cudaSetDevice(i);
+ if (err != cudaSuccess) {
+ std::cout << "Could not select CUDA device " << i << std::endl;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ std::cout << "Could not find a CUDA enabled card supporting compute >=3.5"
+ << std::endl;
+ return 1;
+}
+
+int main(int argc, char** argv)
+{
+ int ret = choose_cuda_device();
+ if (ret) {
+ return 0;
+ }
+
+ // initial values that will make sure that the cublasSgemm won't actually
+ // do any work
+ int n = 0;
+ float alpha = 1;
+ float beta = 1;
+ float* d_A = nullptr;
+ float* d_B = nullptr;
+ float* d_C = nullptr;
+ deviceCublasSgemm<<<1, 1>>>(n, alpha, beta, d_A, d_B, d_C);
+
+ return 0;
+}
--- /dev/null
+cmake_minimum_required(VERSION 3.11)
+project (CudaOnlyPDB CUDA)
+
+add_executable(CudaOnlyPDB main.cu)
+set_target_properties(CudaOnlyPDB PROPERTIES
+ PDB_NAME LinkPDBName
+ PDB_OUTPUT_DIRECTORY LinkPDBDir
+ COMPILE_PDB_NAME CompPDBName
+ COMPILE_PDB_OUTPUT_DIRECTORY CompPDBDir
+ )
+
+set(pdbs
+ ${CMAKE_CURRENT_BINARY_DIR}/CompPDBDir/${CMAKE_CFG_INTDIR}/CompPDBName.pdb
+ ${CMAKE_CURRENT_BINARY_DIR}/LinkPDBDir/${CMAKE_CFG_INTDIR}/LinkPDBName.pdb
+ )
+add_custom_command(TARGET CudaOnlyPDB POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIG> "-Dpdbs=${pdbs}"
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/check_pdbs.cmake
+ )
--- /dev/null
+if(NOT "${config}" MATCHES "[Dd][Ee][Bb]")
+ return()
+endif()
+foreach(pdb ${pdbs})
+ if(EXISTS "${pdb}")
+ message(STATUS "PDB Exists: ${pdb}")
+ else()
+ message(SEND_ERROR "PDB MISSING:\n ${pdb}")
+ endif()
+endforeach()
--- /dev/null
+int main()
+{
+ return 0;
+}
#include <inc_cuda.h>
#ifndef INC_CUDA
-#error "INC_CUDA not defined!"
+# error "INC_CUDA not defined!"
#endif
#ifndef HOST_DEFINE
-#error "HOST_DEFINE not defined!"
+# error "HOST_DEFINE not defined!"
#endif
#ifndef PACKED_DEFINE
-#error "PACKED_DEFINE not defined!"
+# error "PACKED_DEFINE not defined!"
#endif
#ifndef FLAG_COMPILE_LANG_CUDA
-#error "FLAG_COMPILE_LANG_CUDA not defined!"
+# error "FLAG_COMPILE_LANG_CUDA not defined!"
#endif
#ifndef FLAG_LANG_IS_CUDA
-#error "FLAG_LANG_IS_CUDA not defined!"
+# error "FLAG_LANG_IS_CUDA not defined!"
#endif
#if !FLAG_LANG_IS_CUDA
-#error "Expected FLAG_LANG_IS_CUDA"
+# error "Expected FLAG_LANG_IS_CUDA"
#endif
#ifndef DEF_COMPILE_LANG_CUDA
-#error "DEF_COMPILE_LANG_CUDA not defined!"
+# error "DEF_COMPILE_LANG_CUDA not defined!"
#endif
#ifndef DEF_LANG_IS_CUDA
-#error "DEF_LANG_IS_CUDA not defined!"
+# error "DEF_LANG_IS_CUDA not defined!"
#endif
#if !DEF_LANG_IS_CUDA
-#error "Expected DEF_LANG_IS_CUDA"
+# error "Expected DEF_LANG_IS_CUDA"
#endif
static __global__ void DetermineIfValidCudaDevice()
}
#ifdef _MSC_VER
-#pragma pack(push, 1)
-#undef PACKED_DEFINE
-#define PACKED_DEFINE
+# pragma pack(push, 1)
+# undef PACKED_DEFINE
+# define PACKED_DEFINE
#endif
struct PACKED_DEFINE result_type
{
bool valid;
int value;
#if defined(NDEBUG) && !defined(DEFREL)
-#error missing DEFREL flag
+# error missing DEFREL flag
#endif
};
#ifdef _MSC_VER
-#pragma pack(pop)
+# pragma pack(pop)
#endif
result_type can_launch_kernel()
#ifdef _WIN32
-#ifdef bar_EXPORTS
-#define BAR_EXPORT __declspec(dllexport)
+# ifdef bar_EXPORTS
+# define BAR_EXPORT __declspec(dllexport)
+# else
+# define BAR_EXPORT __declspec(dllimport)
+# endif
#else
-#define BAR_EXPORT __declspec(dllimport)
-#endif
-#else
-#define BAR_EXPORT
+# define BAR_EXPORT
#endif
#ifdef CMAKE_INTDIR
const char* cfg = (argc >= 4) ? argv[3] : "";
if (strcmp(cfg, CMAKE_INTDIR) != 0) {
- fprintf(stderr, "Did not receive expected configuration argument:\n"
- " expected [" CMAKE_INTDIR "]\n"
- " received [%s]\n",
+ fprintf(stderr,
+ "Did not receive expected configuration argument:\n"
+ " expected [" CMAKE_INTDIR "]\n"
+ " received [%s]\n",
cfg);
return 1;
}
#ifdef _WIN32
-#ifdef testcxx2_EXPORTS
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# ifdef testcxx2_EXPORTS
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# else
+# define CM_TEST_LIB_EXPORT __declspec(dllimport)
+# endif
#else
-#define CM_TEST_LIB_EXPORT __declspec(dllimport)
-#endif
-#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
class CM_TEST_LIB_EXPORT LibCxx2Class
#ifdef _WIN32
-#define TEST_EXPORT __declspec(dllexport)
+# define TEST_EXPORT __declspec(dllexport)
#else
-#define TEST_EXPORT
+# define TEST_EXPORT
#endif
TEST_EXPORT int testCxxModule(void)
{
add_library(testLib8 OBJECT testLib8A.c testLib8B.c sub/testLib8C.c)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
- set(maybe_testLib8 testLib8)
+ set(maybe_OBJECTS_DESTINATION OBJECTS DESTINATION $<1:lib>)
else()
- set(maybe_testLib8 "")
+ set(maybe_OBJECTS_DESTINATION "")
endif()
+cmake_policy(PUSH)
+cmake_policy(SET CMP0022 NEW)
+add_library(testLib9ObjPub OBJECT testLib9ObjPub.c)
+target_compile_definitions(testLib9ObjPub INTERFACE testLib9ObjPub_USED)
+add_library(testLib9ObjPriv OBJECT testLib9ObjPriv.c)
+target_compile_definitions(testLib9ObjPriv INTERFACE testLib9ObjPriv_USED)
+add_library(testLib9ObjIface OBJECT testLib9ObjIface.c)
+target_compile_definitions(testLib9ObjIface INTERFACE testLib9ObjIface_USED)
+add_library(testLib9 STATIC testLib9.c)
+target_link_libraries(testLib9 INTERFACE testLib9ObjIface PUBLIC testLib9ObjPub PRIVATE testLib9ObjPriv)
+cmake_policy(POP)
+
# Test using the target_link_libraries command to set the
# LINK_INTERFACE_LIBRARIES* properties. We construct two libraries
# providing the same two symbols. In each library one of the symbols
set_property(TARGET testLib2 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB2)
set_property(TARGET testLib3 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB3)
+set_target_properties(testLib3 PROPERTIES
+ EXPORT_PROPERTIES "EXPORTED_PROPERTY1"
+ EXPORTED_PROPERTY1 "EXPORTING_TESTLIB3")
+set_target_properties(testLib4 PROPERTIES
+ EXPORTED_PROPERTY2 "EXPORTING_TESTLIB4_1"
+ EXPORTED_PROPERTY3 "EXPORTING_TESTLIB4_2")
+set_property(TARGET testLib4 PROPERTY
+ EXPORT_PROPERTIES EXPORTED_PROPERTY2 EXPORTED_PROPERTY3)
set_property(TARGET cmp0022NEW APPEND PROPERTY INTERFACE_LINK_LIBRARIES testLib2)
# set_property(TARGET cmp0022NEW APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLibIncludeRequired2) # TODO: Test for error
TARGETS
testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3 testExe4
testExe2lib testLib4lib testLib4libdbg testLib4libopt
- testLib6 testLib7 ${maybe_testLib8}
+ testLib6 testLib7 testLib8
+ testLib9
testLibCycleA testLibCycleB
testLibNoSONAME
cmp0022NEW cmp0022OLD
RUNTIME DESTINATION $<1:bin>
LIBRARY DESTINATION $<1:lib> NAMELINK_SKIP
ARCHIVE DESTINATION $<1:lib>
- OBJECTS DESTINATION $<1:lib>
+ ${maybe_OBJECTS_DESTINATION}
FRAMEWORK DESTINATION Frameworks
BUNDLE DESTINATION Applications
)
+install(
+ TARGETS
+ testLib9ObjPub testLib9ObjPriv testLib9ObjIface
+ EXPORT exp
+ )
if (APPLE)
file(COPY testLib4.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/testLib4.framework/Headers)
file(COPY testLib4.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug/testLib4.framework/Headers)
FILE ExportBuildTree.cmake
)
export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 testExe2lib
- ${maybe_testLib8}
+ testLib8
+ testLib9 testLib9ObjPub testLib9ObjPriv testLib9ObjIface
testLib4lib testLib4libdbg testLib4libopt
testLibCycleA testLibCycleB
testLibNoSONAME
#ifndef USE_FROM_BUILD_DIR
-#error Expected define USE_FROM_BUILD_DIR
+# error Expected define USE_FROM_BUILD_DIR
#endif
#ifdef USE_FROM_INSTALL_DIR
-#error Unexpected define USE_FROM_INSTALL_DIR
+# error Unexpected define USE_FROM_INSTALL_DIR
#endif
int source_symbol()
#ifdef USE_FROM_BUILD_DIR
-#error Unexpected define USE_FROM_BUILD_DIR
+# error Unexpected define USE_FROM_BUILD_DIR
#endif
#ifndef USE_FROM_INSTALL_DIR
-#error Expected define USE_FROM_INSTALL_DIR
+# error Expected define USE_FROM_INSTALL_DIR
#endif
int source_symbol()
#define SYSTEMLIB_H
#if defined(_WIN32) || defined(__CYGWIN__)
-#define systemlib_EXPORT __declspec(dllexport)
+# define systemlib_EXPORT __declspec(dllexport)
#else
-#define systemlib_EXPORT
+# define systemlib_EXPORT
#endif
struct systemlib_EXPORT SystemStruct
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testExe2_EXPORT __declspec(dllexport)
+# define testExe2_EXPORT __declspec(dllexport)
#else
-#define testExe2_EXPORT
+# define testExe2_EXPORT
#endif
testExe2_EXPORT int testExe2Func(void)
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testExe2lib_EXPORT __declspec(dllexport)
-#define testExe2libImp_IMPORT __declspec(dllimport)
+# define testExe2lib_EXPORT __declspec(dllexport)
+# define testExe2libImp_IMPORT __declspec(dllimport)
#else
-#define testExe2lib_EXPORT
-#define testExe2libImp_IMPORT
+# define testExe2lib_EXPORT
+# define testExe2libImp_IMPORT
#endif
testExe2libImp_IMPORT int testExe2libImp(void);
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testExe2libImp_EXPORT __declspec(dllexport)
+# define testExe2libImp_EXPORT __declspec(dllexport)
#else
-#define testExe2libImp_EXPORT
+# define testExe2libImp_EXPORT
#endif
testExe2libImp_EXPORT int testExe2libImp(void)
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testLib3_EXPORT __declspec(dllexport)
-#define testLib3Imp_IMPORT __declspec(dllimport)
+# define testLib3_EXPORT __declspec(dllexport)
+# define testLib3Imp_IMPORT __declspec(dllimport)
#else
-#define testLib3_EXPORT
-#define testLib3Imp_IMPORT
+# define testLib3_EXPORT
+# define testLib3Imp_IMPORT
#endif
testLib3Imp_IMPORT int testLib3Imp(void);
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testLib3Imp_EXPORT __declspec(dllexport)
-#define testLib3ImpDep_IMPORT __declspec(dllimport)
+# define testLib3Imp_EXPORT __declspec(dllexport)
+# define testLib3ImpDep_IMPORT __declspec(dllimport)
#else
-#define testLib3Imp_EXPORT
-#define testLib3ImpDep_IMPORT
+# define testLib3Imp_EXPORT
+# define testLib3ImpDep_IMPORT
#endif
testLib3ImpDep_IMPORT int testLib3ImpDep(void);
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testLib3ImpDep_EXPORT __declspec(dllexport)
+# define testLib3ImpDep_EXPORT __declspec(dllexport)
#else
-#define testLib3ImpDep_EXPORT
+# define testLib3ImpDep_EXPORT
#endif
testLib3ImpDep_EXPORT int testLib3ImpDep(void)
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testLib4_EXPORT __declspec(dllexport)
+# define testLib4_EXPORT __declspec(dllexport)
#else
-#define testLib4_EXPORT
+# define testLib4_EXPORT
#endif
testLib4_EXPORT int testLib4(void)
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testLib5_EXPORT __declspec(dllexport)
+# define testLib5_EXPORT __declspec(dllexport)
#else
-#define testLib5_EXPORT
+# define testLib5_EXPORT
#endif
testLib5_EXPORT int testLib5(void)
--- /dev/null
+#ifndef testLib9ObjPub_USED
+# error "testLib9ObjPub_USED not defined!"
+#endif
+#ifndef testLib9ObjPriv_USED
+# error "testLib9ObjPriv_USED not defined!"
+#endif
+#ifdef testLib9ObjIface_USED
+# error "testLib9ObjIface_USED defined but should not be!"
+#endif
+int testLib9ObjPub(void);
+int testLib9ObjPriv(void);
+int testLib9(void)
+{
+ return (testLib9ObjPub() + testLib9ObjPriv());
+}
--- /dev/null
+/* Duplicate symbols from other sources to verify that this source
+ is not included when the object library is used. */
+int testLib9ObjMissing(void);
+int testLib9ObjPub(void)
+{
+ return testLib9ObjMissing();
+}
+int testLib9ObjPriv(void)
+{
+ return testLib9ObjMissing();
+}
--- /dev/null
+int testLib9ObjPriv(void)
+{
+ return 0;
+}
--- /dev/null
+int testLib9ObjPub(void)
+{
+ return 0;
+}
#include "testLibIncludeRequired4.h"
#ifndef testLibRequired_IFACE_DEFINE
-#error Expected testLibRequired_IFACE_DEFINE
+# error Expected testLibRequired_IFACE_DEFINE
#endif
#ifndef BuildOnly_DEFINE
-#error Expected BuildOnly_DEFINE
+# error Expected BuildOnly_DEFINE
#endif
#ifdef InstallOnly_DEFINE
-#error Unexpected InstallOnly_DEFINE
+# error Unexpected InstallOnly_DEFINE
#endif
extern int testLibRequired(void);
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testLibNoSONAME_EXPORT __declspec(dllexport)
+# define testLibNoSONAME_EXPORT __declspec(dllexport)
#else
-#define testLibNoSONAME_EXPORT
+# define testLibNoSONAME_EXPORT
#endif
testLibNoSONAME_EXPORT int testLibNoSoName(void)
${Import_BINARY_DIR}/exp_generated4.c
)
+function(checkForProperty _TARGET _PROP _EXPECTED)
+ get_target_property(EXPORTED_PROPERTY ${_TARGET} "${_PROP}")
+ if (NOT EXPORTED_PROPERTY STREQUAL "${_EXPECTED}")
+ message(SEND_ERROR "${_TARGET} was expected to export \"${_PROP}\" with value \"${_EXPECTED}\" but got \"${EXPORTED_PROPERTY}\"")
+ endif()
+endfunction()
+
+checkForProperty(bld_testLib3 "EXPORTED_PROPERTY1" "EXPORTING_TESTLIB3")
+checkForProperty(exp_testLib3 "EXPORTED_PROPERTY1" "EXPORTING_TESTLIB3")
+checkForProperty(bld_testLib4 "EXPORTED_PROPERTY2" "EXPORTING_TESTLIB4_1")
+checkForProperty(exp_testLib4 "EXPORTED_PROPERTY2" "EXPORTING_TESTLIB4_1")
+checkForProperty(bld_testLib4 "EXPORTED_PROPERTY3" "EXPORTING_TESTLIB4_2")
+checkForProperty(exp_testLib4 "EXPORTED_PROPERTY3" "EXPORTING_TESTLIB4_2")
+
# Try linking to a library imported from the install tree.
target_link_libraries(imp_testExe1
exp_testLib2
target_link_libraries(imp_lib1b bld_testLib2)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
- # Create a executable that is using objects imported from the install tree
- add_executable(imp_testLib8 imp_testLib8.c $<TARGET_OBJECTS:exp_testLib8>)
+ set(bld_objlib_type OBJECT_LIBRARY)
+
+ # Create executables using objects imported from the install tree
+ add_executable(imp_testLib8_src imp_testLib8.c $<TARGET_OBJECTS:exp_testLib8>)
+ add_executable(imp_testLib8_link imp_testLib8.c)
+ target_link_libraries(imp_testLib8_link exp_testLib8)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT XCODE_VERSION VERSION_LESS 5)
- # Create a executable that is using objects imported from the build tree
- add_executable(imp_testLib8b imp_testLib8.c $<TARGET_OBJECTS:bld_testLib8>)
+ # Create executables using objects imported from the build tree
+ add_executable(imp_testLib8b_src imp_testLib8.c $<TARGET_OBJECTS:bld_testLib8>)
+ add_executable(imp_testLib8b_link imp_testLib8.c)
+ target_link_libraries(imp_testLib8b_link bld_testLib8)
endif()
+else()
+ set(bld_objlib_type INTERFACE_LIBRARY)
endif()
+# Create an executable that uses a library imported from the install tree
+# that itself was built using an object library. Verify we get the usage
+# requirements.
+add_executable(imp_testLib9 imp_testLib9.c)
+target_link_libraries(imp_testLib9 exp_testLib9)
+# Similarly for importing from the build tree.
+add_executable(imp_testLib9b imp_testLib9.c)
+target_link_libraries(imp_testLib9b bld_testLib9)
+
+# Check that object libraries were transformed on export as expected.
+foreach(vis Pub Priv Iface)
+ get_property(type TARGET exp_testLib9Obj${vis} PROPERTY TYPE)
+ if(NOT type STREQUAL INTERFACE_LIBRARY)
+ message(FATAL_ERROR "exp_testLib9Obj${vis} type is '${type}', not 'INTERFACE_LIBRARY'")
+ endif()
+ get_property(type TARGET bld_testLib9Obj${vis} PROPERTY TYPE)
+ if(NOT type STREQUAL "${bld_objlib_type}")
+ message(FATAL_ERROR "bld_testLib9Obj${vis} type is '${type}', not '${bld_objlib_type}'")
+ endif()
+endforeach()
+
#-----------------------------------------------------------------------------
# Test that handling imported targets, including transitive dependencies,
# works in CheckFunctionExists (...and hopefully all other try_compile() checks
#ifndef USING_TESTLIB2
-#error Expected USING_TESTLIB2
+# error Expected USING_TESTLIB2
#endif
#ifdef USING_TESTLIB3
-#error Unexpected USING_TESTLIB3
+# error Unexpected USING_TESTLIB3
#endif
int main(void)
#ifdef USING_TESTLIB2
-#error Unexpected USING_TESTLIB2
+# error Unexpected USING_TESTLIB2
#endif
#ifndef USING_TESTLIB3
-#error Expected USING_TESTLIB3
+# error Expected USING_TESTLIB3
#endif
int main(void)
#include "installIncludesTest8.h"
#ifndef testLibRequired_IFACE_DEFINE
-#error Expected testLibRequired_IFACE_DEFINE
+# error Expected testLibRequired_IFACE_DEFINE
#endif
#ifdef BuildOnly_DEFINE
-#error Unexpected BuildOnly_DEFINE
+# error Unexpected BuildOnly_DEFINE
#endif
#ifndef InstallOnly_DEFINE
-#error Expected InstallOnly_DEFINE
+# error Expected InstallOnly_DEFINE
#endif
extern int testLibDepends(void);
#include "testSharedLibDepends.h"
#ifdef CHECK_PIC_WORKS
-#if defined(__ELF__) && !defined(__PIC__) && !defined(__PIE__)
-#error Expected by INTERFACE_POSITION_INDEPENDENT_CODE property of dependency
-#endif
+# if defined(__ELF__) && !defined(__PIC__) && !defined(__PIE__)
+# error Expected by INTERFACE_POSITION_INDEPENDENT_CODE property of dependency
+# endif
#endif
#ifndef PIC_PROPERTY_IS_ON
-#error Expected PIC_PROPERTY_IS_ON
+# error Expected PIC_PROPERTY_IS_ON
#endif
#ifndef CUSTOM_PROPERTY_IS_ON
-#error Expected CUSTOM_PROPERTY_IS_ON
+# error Expected CUSTOM_PROPERTY_IS_ON
#endif
#ifndef CUSTOM_STRING_IS_MATCH
-#error Expected CUSTOM_STRING_IS_MATCH
+# error Expected CUSTOM_STRING_IS_MATCH
#endif
#ifdef TEST_SUBDIR_LIB
-#include "renamed.h"
-#include "subdir.h"
+# include "renamed.h"
+# include "subdir.h"
#endif
#ifdef DO_GNU_TESTS
-#ifndef CUSTOM_COMPILE_OPTION
-#error Expected CUSTOM_COMPILE_OPTION
-#endif
+# ifndef CUSTOM_COMPILE_OPTION
+# error Expected CUSTOM_COMPILE_OPTION
+# endif
#endif
int main(int, char**)
#include <testLib4/testLib4.h>
#ifndef TESTLIB4_H
-#error Expected define TESTLIB4_H
+# error Expected define TESTLIB4_H
#endif
#ifndef USING_TESTSHAREDLIBREQUIRED
-#error Expected USING_TESTSHAREDLIBREQUIRED
+# error Expected USING_TESTSHAREDLIBREQUIRED
#endif
#include "excludedFromAll.h"
#if defined(_WIN32) || defined(__CYGWIN__)
-#define testExe2_IMPORT __declspec(dllimport)
+# define testExe2_IMPORT __declspec(dllimport)
#else
-#define testExe2_IMPORT
+# define testExe2_IMPORT
#endif
testExe2_IMPORT int testExe2Func(void);
/* Switch a symbol between debug and optimized builds to make sure the
proper library is found from the testLib4 link interface. */
#ifdef EXE_DBG
-#define testLib4libcfg testLib4libdbg
+# define testLib4libcfg testLib4libdbg
#else
-#define testLib4libcfg testLib4libopt
+# define testLib4libcfg testLib4libopt
#endif
extern testLib4libcfg(void);
#include "testLibAbs1a.h"
#include "testLibAbs1b.h"
#ifndef testLibAbs1a
-#error "testLibAbs1a not defined"
+# error "testLibAbs1a not defined"
#endif
#ifndef testLibAbs1b
-#error "testLibAbs1b not defined"
+# error "testLibAbs1b not defined"
#endif
int main()
{
--- /dev/null
+#ifndef testLib9ObjPub_USED
+# error "testLib9ObjPub_USED not defined!"
+#endif
+#ifdef testLib9ObjPriv_USED
+# error "testLib9ObjPriv_USED defined but should not be!"
+#endif
+#ifndef testLib9ObjIface_USED
+# error "testLib9ObjIface_USED not defined!"
+#endif
+
+int testLib9(void);
+
+int main()
+{
+ return testLib9();
+}
#include "headeronly.h"
#ifndef HEADERONLY_DEFINE
-#error Expected HEADERONLY_DEFINE
+# error Expected HEADERONLY_DEFINE
#endif
#ifdef SHAREDLIB_DEFINE
-#error Unexpected SHAREDLIB_DEFINE
+# error Unexpected SHAREDLIB_DEFINE
#endif
int main(int, char**)
#include "sharedlib.h"
#ifndef SHAREDLIB_DEFINE
-#error Expected SHAREDLIB_DEFINE
+# error Expected SHAREDLIB_DEFINE
#endif
#ifdef HEADERONLY_DEFINE
-#error Unexpected HEADERONLY_DEFINE
+# error Unexpected HEADERONLY_DEFINE
#endif
#ifndef DEFINE_IFACE_DEFINE
-#error Expected DEFINE_IFACE_DEFINE
+# error Expected DEFINE_IFACE_DEFINE
#endif
int main(int, char**)
--- /dev/null
+add_test(NAME FindALSA.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindALSA/Test"
+ "${CMake_BINARY_DIR}/Tests/FindALSA/Test"
+ ${build_generator_args}
+ --build-project TestFindALSA
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
--- /dev/null
+cmake_minimum_required(VERSION 3.10)
+project(TestFindALSA C)
+include(CTest)
+
+find_package(ALSA REQUIRED)
+
+add_definitions(-DCMAKE_EXPECTED_ALSA_VERSION="${ALSA_VERSION_STRING}")
+
+add_executable(test_tgt main.c)
+target_link_libraries(test_tgt ALSA::ALSA)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.c)
+target_include_directories(test_var PRIVATE ${ALSA_INCLUDE_DIRS})
+target_link_libraries(test_var PRIVATE ${ALSA_LIBRARIES})
+add_test(NAME test_var COMMAND test_var)
--- /dev/null
+#include <alsa/global.h>
+#include <stdio.h>
+#include <string.h>
+
+int main()
+{
+ printf("Found ALSA version %s, expected version %s\n",
+ snd_asoundlib_version(), CMAKE_EXPECTED_ALSA_VERSION);
+ return strcmp(snd_asoundlib_version(), CMAKE_EXPECTED_ALSA_VERSION);
+}
--- /dev/null
+add_test(NAME FindCURL.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindCURL/Test"
+ "${CMake_BINARY_DIR}/Tests/FindCURL/Test"
+ ${build_generator_args}
+ --build-project TestFindCURL
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
--- /dev/null
+cmake_minimum_required(VERSION 3.10)
+project(TestFindCURL C)
+include(CTest)
+
+find_package(CURL REQUIRED)
+
+add_definitions(-DCMAKE_EXPECTED_CURL_VERSION="${CURL_VERSION_STRING}")
+
+add_executable(test_tgt main.c)
+target_link_libraries(test_tgt CURL::libcurl)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.c)
+target_include_directories(test_var PRIVATE ${CURL_INCLUDE_DIRS})
+target_link_libraries(test_var PRIVATE ${CURL_LIBRARIES})
+add_test(NAME test_var COMMAND test_var)
--- /dev/null
+#include <curl/curl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main()
+{
+ struct curl_slist* slist;
+
+ curl_global_init(0);
+
+ slist = curl_slist_append(NULL, "CMake");
+ curl_slist_free_all(slist);
+
+ curl_global_cleanup();
+
+ return 0;
+}
--- /dev/null
+cmake_minimum_required(VERSION 3.10)
+project(TestFindDoxygen VERSION 1.0 LANGUAGES NONE)
+enable_testing()
+
+find_package(Doxygen REQUIRED)
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp [[
+/**
+ * \file
+ * \brief One C++ file w/ sample Doxygen comment just to produce any docs...
+ */
+]])
+
+set(DOXYGEN_OUTPUT_DIRECTORY outDirWithout)
+file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/${DOXYGEN_OUTPUT_DIRECTORY})
+doxygen_add_docs(docsNoAll ${CMAKE_CURRENT_BINARY_DIR}/main.cpp)
+
+set(DOXYGEN_OUTPUT_DIRECTORY outDirWith)
+file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/${DOXYGEN_OUTPUT_DIRECTORY})
+doxygen_add_docs(docsWithAll ALL ${CMAKE_CURRENT_BINARY_DIR}/main.cpp)
+
+# Define tests cases that check whether targets were built
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dirExists.cmake [[
+cmake_minimum_required(VERSION 3.11)
+if(NOT EXISTS ${dirName})
+ message(FATAL_ERROR "Directory does not exist: ${dirName}")
+endif()
+]])
+
+add_test(NAME checkWith COMMAND
+ ${CMAKE_COMMAND}
+ -D dirName=${CMAKE_CURRENT_BINARY_DIR}/outDirWith
+ -P dirExists.cmake
+)
+add_test(NAME checkWithout COMMAND
+ ${CMAKE_COMMAND}
+ -D dirName=${CMAKE_CURRENT_BINARY_DIR}/outDirWithout
+ -P dirExists.cmake
+)
+set_tests_properties(checkWithout PROPERTIES
+ WILL_FAIL TRUE
+)
--build-options ${build_options}
)
+add_test(NAME FindDoxygen.AllTarget COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindDoxygen/AllTarget"
+ "${CMake_BINARY_DIR}/Tests/FindDoxygen/AllTarget"
+ ${build_generator_args}
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+)
+
if(CMake_TEST_FindDoxygen_Dot)
add_test(NAME FindDoxygen.DotComponentTest COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
* et. al.
*/
#if defined(_MSC_VER)
-#define _USE_MATH_DEFINES
+# define _USE_MATH_DEFINES
#endif
#include <cairomm/context.h>
--- /dev/null
+add_test(NAME FindJPEG.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindJPEG/Test"
+ "${CMake_BINARY_DIR}/Tests/FindJPEG/Test"
+ ${build_generator_args}
+ --build-project TestFindJPEG
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+project(TestFindJPEG C)
+include(CTest)
+
+find_package(JPEG)
+
+add_executable(test_jpeg_tgt main.c)
+target_link_libraries(test_jpeg_tgt JPEG::JPEG)
+add_test(NAME test_jpeg_tgt COMMAND test_jpeg_tgt)
+
+add_executable(test_jpeg_var main.c)
+target_include_directories(test_jpeg_var PRIVATE ${JPEG_INCLUDE_DIRS})
+target_link_libraries(test_jpeg_var PRIVATE ${JPEG_LIBRARIES})
+add_test(NAME test_jpeg_var COMMAND test_jpeg_var)
--- /dev/null
+#include <assert.h>
+#include <stdio.h>
+
+#include <jpeglib.h>
+
+int main()
+{
+ /* Without any JPEG file to open, test that the call fails as
+ expected. This tests that linking worked. */
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+
+ return 0;
+}
#include <string.h>
#ifdef CMAKE_LTTNGUST_HAS_TRACEF
-#include <lttng/tracef.h>
+# include <lttng/tracef.h>
#endif
#ifdef CMAKE_LTTNGUST_HAS_TRACELOG
-#include <lttng/tracelog.h>
+# include <lttng/tracelog.h>
#endif
int main(void)
--- /dev/null
+add_test(NAME FindLibXml2.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindLibXml2/Test"
+ "${CMake_BINARY_DIR}/Tests/FindLibXml2/Test"
+ ${build_generator_args}
+ --build-project TestFindLibXml2
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
--- /dev/null
+cmake_minimum_required(VERSION 3.4)
+project(TestFindLibXml2 C)
+include(CTest)
+
+find_package(LibXml2 REQUIRED)
+
+add_definitions(-DCMAKE_EXPECTED_LibXml2_VERSION="${LIBXML2_VERSION_STRING}")
+
+add_executable(test_tgt main.c)
+target_link_libraries(test_tgt LibXml2::LibXml2)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.c)
+target_include_directories(test_var PRIVATE ${LIBXML2_INCLUDE_DIRS})
+target_link_libraries(test_var PRIVATE ${LIBXML2_LIBRARIES})
+add_test(NAME test_var COMMAND test_var)
--- /dev/null
+#include <assert.h>
+#include <libxml/tree.h>
+#include <string.h>
+
+int main()
+{
+ xmlDoc* doc;
+
+ xmlInitParser();
+
+ doc = xmlNewDoc(BAD_CAST "1.0");
+ xmlFreeDoc(doc);
+
+ assert(strstr(CMAKE_EXPECTED_LibXml2_VERSION, LIBXML_DOTTED_VERSION));
+
+ xmlCleanupParser();
+
+ return 0;
+}
# the success of the following command is dependent on the current configuration:
# - on 32bits builds (cmake is building with 32 bits), it looks for 32 bits Matlab
# - on 64bits builds (cmake is building with 64 bits), it looks for 64 bits Matlab
-find_package(Matlab REQUIRED COMPONENTS MX_LIBRARY MAIN_PROGRAM)
+if(IS_MCR)
+ set(components MX_LIBRARY)
+ set(RUN_UNIT_TESTS FALSE)
+else()
+ set(RUN_UNIT_TESTS TRUE)
+ set(components MX_LIBRARY MAIN_PROGRAM)
+endif()
+
+if(NOT "${MCR_ROOT}" STREQUAL "")
+ set(Matlab_ROOT_DIR "${MCR_ROOT}")
+ if(NOT EXISTS "${MCR_ROOT}")
+ message(FATAL_ERROR "MCR does not exist ${MCR_ROOT}")
+ endif()
+endif()
+
+find_package(Matlab REQUIRED COMPONENTS ${components})
matlab_add_mex(
DOCUMENTATION ${CMAKE_CURRENT_SOURCE_DIR}/../help_text1.m.txt
)
+if(RUN_UNIT_TESTS)
+ matlab_add_unit_test(
+ NAME ${PROJECT_NAME}_matlabtest-1
+ TIMEOUT 300
+ UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests1.m
+ ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
+ )
+
+ # timeout tests, TIMEOUT set to very short on purpose
+ matlab_add_unit_test(
+ NAME ${PROJECT_NAME}_matlabtest-2
+ TIMEOUT 15
+ UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests_timeout.m
+ ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
+ )
+ set_tests_properties(${PROJECT_NAME}_matlabtest-2 PROPERTIES WILL_FAIL TRUE)
+
+
+ # testing the test without the unittest framework of Matlab
+ matlab_add_unit_test(
+ NAME ${PROJECT_NAME}_matlabtest-3
+ TIMEOUT 300
+ NO_UNITTEST_FRAMEWORK
+ UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests2.m
+ ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
+ )
-matlab_add_unit_test(
- NAME ${PROJECT_NAME}_matlabtest-1
- TIMEOUT 90
- UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests1.m
- ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
- )
-
-matlab_add_unit_test(
- NAME ${PROJECT_NAME}_matlabtest-2
- TIMEOUT 15
- UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests_timeout.m
- ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
- )
-set_tests_properties(${PROJECT_NAME}_matlabtest-2 PROPERTIES WILL_FAIL TRUE)
-
-
-# testing the test without the unittest framework of Matlab
-matlab_add_unit_test(
- NAME ${PROJECT_NAME}_matlabtest-3
- TIMEOUT 30
- NO_UNITTEST_FRAMEWORK
- UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests2.m
- ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
- )
-
-matlab_add_unit_test(
- NAME ${PROJECT_NAME}_matlabtest-4
- TIMEOUT 30
- NO_UNITTEST_FRAMEWORK
- UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests3.m
- ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
- )
-set_tests_properties(${PROJECT_NAME}_matlabtest-4 PROPERTIES WILL_FAIL TRUE)
+ matlab_add_unit_test(
+ NAME ${PROJECT_NAME}_matlabtest-4
+ TIMEOUT 300
+ NO_UNITTEST_FRAMEWORK
+ UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests3.m
+ ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
+ )
+ set_tests_properties(${PROJECT_NAME}_matlabtest-4 PROPERTIES WILL_FAIL TRUE)
+endif()
set(MATLAB_FIND_DEBUG TRUE)
+if(NOT "${MCR_ROOT}" STREQUAL "")
+ set(Matlab_ROOT_DIR "${MCR_ROOT}")
+ if(NOT EXISTS "${MCR_ROOT}")
+ message(FATAL_ERROR "MCR does not exist ${MCR_ROOT}")
+ endif()
+endif()
+
# the success of the following command is dependent on the current configuration:
# - on 32bits builds (cmake is building with 32 bits), it looks for 32 bits Matlab
# - on 64bits builds (cmake is building with 64 bits), it looks for 64 bits Matlab
-find_package(Matlab REQUIRED COMPONENTS MX_LIBRARY ENG_LIBRARY MAT_LIBRARY MAIN_PROGRAM)
+find_package(Matlab REQUIRED COMPONENTS MX_LIBRARY ENG_LIBRARY MAT_LIBRARY
+ OPTIONAL_COMPONENTS MAIN_PROGRAM)
message(STATUS "FindMatlab libraries: ${Matlab_LIBRARIES}")
--- /dev/null
+
+cmake_minimum_required (VERSION 2.8.12)
+enable_testing()
+project(failure_reports)
+
+# gather tests about proper failure reports
+
+set(MATLAB_FIND_DEBUG TRUE)
+
+if(IS_MCR)
+ set(components MX_LIBRARY)
+ set(RUN_UNIT_TESTS FALSE)
+else()
+ set(RUN_UNIT_TESTS TRUE)
+ set(components MX_LIBRARY MAIN_PROGRAM)
+endif()
+
+if(NOT "${MCR_ROOT}" STREQUAL "")
+ set(Matlab_ROOT_DIR "${MCR_ROOT}")
+ if(NOT EXISTS "${MCR_ROOT}")
+ message(FATAL_ERROR "MCR does not exist ${MCR_ROOT}")
+ endif()
+endif()
+
+find_package(Matlab REQUIRED COMPONENTS ${components})
+
+# main extensions for testing, same as other tests
+matlab_add_mex(
+ # target name
+ NAME cmake_matlab_test_wrapper1
+ # output name
+ OUTPUT_NAME cmake_matlab_mex1
+ SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper1.cpp
+ DOCUMENTATION ${CMAKE_CURRENT_SOURCE_DIR}/../help_text1.m.txt
+ )
+
+if(RUN_UNIT_TESTS)
+ # the unit test file does not exist: the failure should be properly reported
+ matlab_add_unit_test(
+ NAME ${PROJECT_NAME}_matlabtest-1
+ TIMEOUT 300
+ UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../nonexistantfile.m
+ ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
+ )
+ set_tests_properties(${PROJECT_NAME}_matlabtest-1 PROPERTIES WILL_FAIL TRUE)
+
+ # without the unit test framework
+ matlab_add_unit_test(
+ NAME ${PROJECT_NAME}_matlabtest-2
+ TIMEOUT 300
+ NO_UNITTEST_FRAMEWORK
+ UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../nonexistantfile2.m
+ ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1>
+ )
+ set_tests_properties(${PROJECT_NAME}_matlabtest-2 PROPERTIES WILL_FAIL TRUE)
+endif()
set(MATLAB_ADDITIONAL_VERSIONS
"dummy=14.9")
+if(NOT "${MCR_ROOT}" STREQUAL "")
+ set(Matlab_ROOT_DIR "${MCR_ROOT}")
+ if(NOT EXISTS "${MCR_ROOT}")
+ message(FATAL_ERROR "MCR does not exist ${MCR_ROOT}")
+ endif()
+endif()
+
# the success of the following command is dependent on the current configuration
# in this case, we are only interested in the version macros
find_package(Matlab)
--- /dev/null
+add_test(NAME FindODBC.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindODBC/Test"
+ "${CMake_BINARY_DIR}/Tests/FindODBC/Test"
+ ${build_generator_args}
+ --build-project TestFindODBC
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+project(TestFindODBC C)
+include(CTest)
+
+find_package(ODBC)
+
+add_executable(test_odbc_tgt main.c)
+target_link_libraries(test_odbc_tgt ODBC::ODBC)
+add_test(NAME test_odbc_tgt COMMAND test_odbc_tgt)
+
+add_executable(test_odbc_var main.c)
+target_include_directories(test_odbc_var PRIVATE ${ODBC_INCLUDE_DIRS})
+target_link_libraries(test_odbc_var PRIVATE ${ODBC_LIBRARIES})
+add_test(NAME test_odbc_var COMMAND test_odbc_var)
--- /dev/null
+#ifdef WIN32
+# include <windows.h>
+#endif
+#include <sql.h>
+
+int main()
+{
+ SQLHENV env;
+ SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
+ SQLFreeHandle(SQL_HANDLE_ENV, env);
+ return 0;
+}
#ifdef __APPLE__
-#include <OpenCL/opencl.h>
+# include <OpenCL/opencl.h>
#else
-#include <CL/cl.h>
+# include <CL/cl.h>
#endif
int main()
#ifdef _WIN32
-#include <windows.h>
+# include <windows.h>
#endif
#ifdef __APPLE__
-#include <OpenGL/gl.h>
+# include <OpenGL/gl.h>
#else
-#include <GL/gl.h>
+# include <GL/gl.h>
#endif
#include <stdio.h>
#ifdef __cplusplus
-#include <iostream>
+# include <iostream>
extern "C"
#else
-#include <stdio.h>
+# include <stdio.h>
#endif
int scalprod(int n, double* x, double* y, double* res);
endif()
-
#-----------------------------------------------------------------------------
# Test write_basic_config_version_file().
-# also test that an empty CMAKE_SIZEOF_VOID_P is accepted:
-set(_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
-set(CMAKE_SIZEOF_VOID_P "")
-
-write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/Foo123ConfigVersion.cmake
- VERSION 1.2.3
- COMPATIBILITY AnyNewerVersion)
-
-set(CMAKE_SIZEOF_VOID_P ${_CMAKE_SIZEOF_VOID_P})
-
-set(PACKAGE_FIND_VERSION 2.3.4)
-include(${CMAKE_CURRENT_BINARY_DIR}/Foo123ConfigVersion.cmake)
-if(PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Found Foo123 with version 1.2.3, but 2.3.4 was requested !")
-endif()
-
-set(PACKAGE_FIND_VERSION 0.0.1)
-include(${CMAKE_CURRENT_BINARY_DIR}/Foo123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Foo123 with version 1.2.3 (0.0.1 was requested) !")
-endif()
-
-if(PACKAGE_VERSION_UNSUITABLE)
- message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, but must not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 1.0.0)
-include(${CMAKE_CURRENT_BINARY_DIR}/Foo123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Foo123 with version 1.2.3 (1.0.0 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 1.2.3)
-include(${CMAKE_CURRENT_BINARY_DIR}/Foo123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Foo123 with version 1.2.3 (1.2.3 was requested) !")
-endif()
-if(NOT PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT not set, although it should be !")
-endif()
-
-
-#######################
include(WriteBasicConfigVersionFile)
-write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/Boo123ConfigVersion.cmake
- VERSION 1.2.3
- COMPATIBILITY SameMajorVersion)
-
-unset(PACKAGE_VERSION_UNSUITABLE)
-set(PACKAGE_VERSION_EXACT FALSE)
-set(PACKAGE_FIND_VERSION 2.3.4)
-set(PACKAGE_FIND_VERSION_MAJOR 2)
-include(${CMAKE_CURRENT_BINARY_DIR}/Boo123ConfigVersion.cmake)
-if(PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Found Boo123 with version 1.2.3, but 2.3.4 was requested !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 0.0.1)
-set(PACKAGE_FIND_VERSION_MAJOR 0)
-include(${CMAKE_CURRENT_BINARY_DIR}/Boo123ConfigVersion.cmake)
-if(PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Found Boo123 with version 1.2.3, but 0.0.1 was requested !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 1.0.0)
-set(PACKAGE_FIND_VERSION_MAJOR 1)
-include(${CMAKE_CURRENT_BINARY_DIR}/Boo123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Boo123 with version 1.2.3 (1.0.0 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 1.2.3)
-set(PACKAGE_FIND_VERSION_MAJOR 1)
-include(${CMAKE_CURRENT_BINARY_DIR}/Boo123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Boo123 with version 1.2.3 (1.2.3 was requested) !")
-endif()
-if(NOT PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT not set, although it should be !")
-endif()
-
-if(PACKAGE_VERSION_UNSUITABLE)
- message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, but must not be !")
-endif()
-
-#######################
-
-write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/Zot123ConfigVersion.cmake
- VERSION 1.2.3.17
- COMPATIBILITY SameMinorVersion)
-
-unset(PACKAGE_VERSION_UNSUITABLE)
-set(PACKAGE_VERSION_EXACT FALSE)
-set(PACKAGE_FIND_VERSION 2.3.4)
-set(PACKAGE_FIND_VERSION_MAJOR 2)
-set(PACKAGE_FIND_VERSION_MINOR 3)
-include(${CMAKE_CURRENT_BINARY_DIR}/Zot123ConfigVersion.cmake)
-if(PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Found Zot123 with version 1.2.3.17, but 2.3.4 was requested !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 0.0.1)
-set(PACKAGE_FIND_VERSION_MAJOR 0)
-set(PACKAGE_FIND_VERSION_MINOR 0)
-include(${CMAKE_CURRENT_BINARY_DIR}/Zot123ConfigVersion.cmake)
-if(PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Found Zot123 with version 1.2.3.17, but 0.0.1 was requested !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 1.0.0)
-set(PACKAGE_FIND_VERSION_MAJOR 1)
-set(PACKAGE_FIND_VERSION_MINOR 0)
-include(${CMAKE_CURRENT_BINARY_DIR}/Zot123ConfigVersion.cmake)
-if(PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Found Zot123 with version 1.2.3.17 (1.0.0 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 1.2.0)
-set(PACKAGE_FIND_VERSION_MAJOR 1)
-set(PACKAGE_FIND_VERSION_MINOR 2)
-include(${CMAKE_CURRENT_BINARY_DIR}/Zot123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Zot123 with version 1.2.3.17 (1.2.0 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 1.2.3)
-set(PACKAGE_FIND_VERSION_MAJOR 1)
-set(PACKAGE_FIND_VERSION_MINOR 2)
-include(${CMAKE_CURRENT_BINARY_DIR}/Zot123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Zot123 with version 1.2.3.17 (1.2.3 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 1.2.3.17)
-set(PACKAGE_FIND_VERSION_MAJOR 1)
-set(PACKAGE_FIND_VERSION_MINOR 2)
-include(${CMAKE_CURRENT_BINARY_DIR}/Zot123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Zot123 with version 1.2.3.17 (1.2.3.17 was requested) !")
-endif()
-if(NOT PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT not set, although it should be !")
-endif()
-
-if(PACKAGE_VERSION_UNSUITABLE)
- message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, but must not be !")
-endif()
-
-#######################
-
-write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake
- VERSION 1.2.3.17
- COMPATIBILITY ExactVersion)
-
-unset(PACKAGE_VERSION_UNSUITABLE)
-set(PACKAGE_VERSION_EXACT FALSE)
-set(PACKAGE_FIND_VERSION 2.3.4)
-include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
-if(PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Found Bar123 with version 1.2.3.17 (2.3.4 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
-
-set(PACKAGE_FIND_VERSION 1.2)
-include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
-if(PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Found Bar123 with version 1.2.3.17 (1.2 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
+set(_compatibilities AnyNewerVersion
+ SameMajorVersion
+ SameMinorVersion
+ ExactVersion)
+
+function(TEST_WRITE_BASIC_CONFIG_VERSION_FILE_PREPARE _version_installed)
+ set(_same_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
+ set(_no_CMAKE_SIZEOF_VOID_P "")
+ math(EXPR _diff_CMAKE_SIZEOF_VOID_P "${CMAKE_SIZEOF_VOID_P} + 1")
+ foreach(_compat ${_compatibilities})
+ set(_pkg ${_compat}${_version_installed})
+ string(REPLACE "." "" _pkg ${_pkg})
+ set(_filename "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}ConfigVersion.cmake")
+ set(_filename_novoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}NoVoidConfigVersion.cmake")
+ set(_filename_diffvoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}DiffVoidConfigVersion.cmake")
+
+ set(CMAKE_SIZEOF_VOID_P ${_same_CMAKE_SIZEOF_VOID_P})
+ write_basic_config_version_file("${_filename}"
+ VERSION ${_version_installed}
+ COMPATIBILITY ${_compat})
+
+ # Test that an empty CMAKE_SIZEOF_VOID_P is accepted:
+ set(CMAKE_SIZEOF_VOID_P ${_no_CMAKE_SIZEOF_VOID_P})
+ write_basic_config_version_file("${_filename_novoid}"
+ VERSION ${_version_installed}
+ COMPATIBILITY ${_compat})
+
+ # Test that a different CMAKE_SIZEOF_VOID_P results in
+ # PACKAGE_VERSION_UNSUITABLE
+ set(CMAKE_SIZEOF_VOID_P ${_diff_CMAKE_SIZEOF_VOID_P})
+ write_basic_config_version_file("${_filename_diffvoid}"
+ VERSION ${_version_installed}
+ COMPATIBILITY ${_compat})
+ endforeach()
+endfunction()
+
+macro(TEST_WRITE_BASIC_CONFIG_VERSION_FILE_CHECK _filename)
+ include("${_filename}")
+
+ if(_expected_compatible AND NOT PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Did not find package with version ${_version_installed} (${_version_requested} was requested)!")
+ elseif(NOT _expected_compatible AND PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Found package with version ${_version_installed}, but ${_version_requested} was requested!")
+ endif()
-set(PACKAGE_FIND_VERSION 1)
-include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
-if(PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Found Bar123 with version 1.2.3.17 (1 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
+ if(${_expected_exact} AND NOT PACKAGE_VERSION_EXACT)
+ message(SEND_ERROR "PACKAGE_VERSION_EXACT not set, although it should be!")
+ elseif(NOT ${_expected_exact} AND PACKAGE_VERSION_EXACT)
+ message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be!")
+ endif()
-set(PACKAGE_FIND_VERSION 1.2.3.4)
-include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Bar123 with version 1.2.3.17 (1.2.3.4 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
+ if(${_expected_unsuitable} AND NOT PACKAGE_VERSION_UNSUITABLE)
+ message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, although it should not be!")
+ elseif(NOT ${_expected_unsuitable} AND PACKAGE_VERSION_UNSUITABLE)
+ message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE not set, although it should be!")
+ endif()
-set(PACKAGE_FIND_VERSION 1.2.3)
-set(PACKAGE_VERSION_EXACT FALSE)
-set(PACKAGE_VERSION_COMPATIBLE FALSE)
-include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Bar123 with version 1.2.3.17 (1.2.3 was requested) !")
-endif()
-if(PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
-endif()
+ unset(PACKAGE_VERSION_COMPATIBLE)
+ unset(PACKAGE_VERSION_EXACT)
+ unset(PACKAGE_VERSION_UNSUITABLE)
+endmacro()
+
+function(TEST_WRITE_BASIC_CONFIG_VERSION_FILE _version_installed
+ _version_requested
+ _expected_compatible_AnyNewerVersion
+ _expected_compatible_SameMajorVersion
+ _expected_compatible_SameMinorVersion
+ _expected_compatible_ExactVersion)
+ set(PACKAGE_FIND_VERSION ${_version_requested})
+ if("${PACKAGE_FIND_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
+ set(PACKAGE_FIND_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(PACKAGE_FIND_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(PACKAGE_FIND_VERSION_PATCH "${CMAKE_MATCH_3}")
+ set(PACKAGE_FIND_VERSION_TWEAK "${CMAKE_MATCH_4}")
+ elseif("${PACKAGE_FIND_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
+ set(PACKAGE_FIND_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(PACKAGE_FIND_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(PACKAGE_FIND_VERSION_PATCH "${CMAKE_MATCH_3}")
+ set(PACKAGE_FIND_VERSION_TWEAK "")
+ elseif("${PACKAGE_FIND_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)$")
+ set(PACKAGE_FIND_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(PACKAGE_FIND_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(PACKAGE_FIND_VERSION_PATCH "")
+ set(PACKAGE_FIND_VERSION_TWEAK "")
+ elseif("${PACKAGE_FIND_VERSION}" MATCHES "^([0-9]+)$")
+ set(PACKAGE_FIND_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(PACKAGE_FIND_VERSION_MINOR "")
+ set(PACKAGE_FIND_VERSION_PATCH "")
+ set(PACKAGE_FIND_VERSION_TWEAK "")
+ elseif("${PACKAGE_FIND_VERSION}" STREQUAL "")
+ set(PACKAGE_FIND_VERSION_MAJOR "")
+ set(PACKAGE_FIND_VERSION_MINOR "")
+ set(PACKAGE_FIND_VERSION_PATCH "")
+ set(PACKAGE_FIND_VERSION_TWEAK "")
+ else()
+ message(FATAL_ERROR "_version_requested (${_version_requested}) should be a version number")
+ endif()
-set(PACKAGE_FIND_VERSION 1.2.3.17)
-set(PACKAGE_VERSION_EXACT FALSE)
-set(PACKAGE_VERSION_COMPATIBLE FALSE)
-include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
-if(NOT PACKAGE_VERSION_COMPATIBLE)
- message(SEND_ERROR "Did not find Bar123 with version 1.2.3.17 (1.2.3.17 was requested) !")
-endif()
-if(NOT PACKAGE_VERSION_EXACT)
- message(SEND_ERROR "PACKAGE_VERSION_EXACT not set, although it should be !")
-endif()
+ if ("${_version_installed}" STREQUAL "${_version_requested}")
+ set(_expected_exact 1)
+ else()
+ set(_expected_exact 0)
+ endif()
-if(PACKAGE_VERSION_UNSUITABLE)
- message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, but must not be !")
-endif()
+ unset(PACKAGE_VERSION_COMPATIBLE)
+ unset(PACKAGE_VERSION_EXACT)
+ unset(PACKAGE_VERSION_UNSUITABLE)
+
+ foreach(_compat ${_compatibilities})
+ set(_pkg ${_compat}${_version_installed})
+ string(REPLACE "." "" _pkg ${_pkg})
+ set(_filename "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}ConfigVersion.cmake")
+ set(_filename_novoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}NoVoidConfigVersion.cmake")
+ set(_filename_diffvoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}DiffVoidConfigVersion.cmake")
+
+ set(_expected_compatible ${_expected_compatible_${_compat}})
+
+ # Test "normal" version
+ set(_expected_unsuitable 0)
+ message("TEST write_basic_config_version_file(VERSION ${_version_installed} \
+COMPATIBILITY ${_compat}) vs. ${_version_requested} \
+(expected compatible = ${_expected_compatible}, exact = ${_expected_exact}, unsuitable = ${_expected_unsuitable})")
+ test_write_basic_config_version_file_check("${_filename}")
+
+ # test empty CMAKE_SIZEOF_VOID_P version:
+ set(_expected_unsuitable 0)
+ message("TEST write_basic_config_version_file(VERSION ${_version_installed} \
+COMPATIBILITY ${_compat}) vs. ${_version_requested} (no CMAKE_SIZEOF_VOID_P) \
+(expected compatible = ${_expected_compatible}, exact = ${_expected_exact}, unsuitable = ${_expected_unsuitable})")
+ test_write_basic_config_version_file_check("${_filename_novoid}")
+
+ # test different CMAKE_SIZEOF_VOID_P version:
+ set(_expected_unsuitable 1)
+ message("TEST write_basic_config_version_file(VERSION ${_version_installed} \
+COMPATIBILITY ${_compat}) vs. ${_version_requested} (different CMAKE_SIZEOF_VOID_P) \
+(expected compatible = ${_expected_compatible}, exact = ${_expected_exact}, unsuitable = ${_expected_unsuitable})")
+ test_write_basic_config_version_file_check("${_filename_diffvoid}")
+
+ endforeach()
+endfunction()
+
+
+test_write_basic_config_version_file_prepare(4)
+test_write_basic_config_version_file_prepare(4.5)
+test_write_basic_config_version_file_prepare(4.5.6)
+test_write_basic_config_version_file_prepare(4.5.6.7)
+
+# AnyNewerVersion
+# | SameMajorVersion
+# | | SameMinorVersion
+# | | | ExactVersion
+# | | | |
+test_write_basic_config_version_file(4 0 1 0 0 0) # Request 0
+test_write_basic_config_version_file(4 2 1 0 0 0) # Request [older major]
+test_write_basic_config_version_file(4 4 1 1 1 1) # Request [same major]
+test_write_basic_config_version_file(4 9 0 0 0 0) # Request [newer major]
+
+test_write_basic_config_version_file(4 0.0 1 0 0 0) # Request 0.0
+test_write_basic_config_version_file(4 0.9 1 0 0 0) # Request 0.[newer minor]
+test_write_basic_config_version_file(4 2.0 1 0 0 0) # Request [older major].0
+test_write_basic_config_version_file(4 2.9 1 0 0 0) # Request [older major].[newer minor]
+test_write_basic_config_version_file(4 4.0 1 1 0 0) # Request [same major].0
+test_write_basic_config_version_file(4 4.9 0 0 0 0) # Request [same major].[newer minor]
+test_write_basic_config_version_file(4 9.0 0 0 0 0) # Request [newer major].0
+test_write_basic_config_version_file(4 9.9 0 0 0 0) # Request [newer major].[newer minor]
+
+test_write_basic_config_version_file(4 0.0.0 1 0 0 0) # Request 0.0.0
+test_write_basic_config_version_file(4 0.0.9 1 0 0 0) # Request 0.0.[newer patch]
+test_write_basic_config_version_file(4 0.9.0 1 0 0 0) # Request 0.[newer minor].0
+test_write_basic_config_version_file(4 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch]
+test_write_basic_config_version_file(4 2.0.0 1 0 0 0) # Request [older major].0.0
+test_write_basic_config_version_file(4 2.0.9 1 0 0 0) # Request [older major].0.[newer patch]
+test_write_basic_config_version_file(4 2.9.0 1 0 0 0) # Request [older major].[newer minor].0
+test_write_basic_config_version_file(4 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4 4.0.0 1 1 0 0) # Request [same major].0.0
+test_write_basic_config_version_file(4 4.0.9 0 0 0 0) # Request [same major].0.[newer patch]
+test_write_basic_config_version_file(4 4.9.0 0 0 0 0) # Request [same major].[newer minor].0
+test_write_basic_config_version_file(4 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4 9.0.0 0 0 0 0) # Request [newer major].0.0
+test_write_basic_config_version_file(4 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch]
+test_write_basic_config_version_file(4 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0
+test_write_basic_config_version_file(4 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch]
+
+test_write_basic_config_version_file(4 0.0.0.0 1 0 0 0) # Request 0.0.0.0
+test_write_basic_config_version_file(4 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak]
+test_write_basic_config_version_file(4 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0
+test_write_basic_config_version_file(4 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0
+test_write_basic_config_version_file(4 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0
+test_write_basic_config_version_file(4 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4 2.0.0.0 1 0 0 0) # Request [older major].0.0.0
+test_write_basic_config_version_file(4 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak]
+test_write_basic_config_version_file(4 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0
+test_write_basic_config_version_file(4 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0
+test_write_basic_config_version_file(4 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4 4.0.0.0 1 1 0 0) # Request [same major].0.0.0
+test_write_basic_config_version_file(4 4.0.0.9 0 0 0 0) # Request [same major].0.0.[newer tweak]
+test_write_basic_config_version_file(4 4.0.9.0 0 0 0 0) # Request [same major].0.[newer patch].0
+test_write_basic_config_version_file(4 4.0.9.9 0 0 0 0) # Request [same major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0
+test_write_basic_config_version_file(4 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0
+test_write_basic_config_version_file(4 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak]
+test_write_basic_config_version_file(4 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0
+test_write_basic_config_version_file(4 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0
+test_write_basic_config_version_file(4 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak]
+
+
+
+test_write_basic_config_version_file(4.5 0 1 0 0 0) # Request 0
+test_write_basic_config_version_file(4.5 2 1 0 0 0) # Request [older major]
+test_write_basic_config_version_file(4.5 4 1 1 0 0) # Request [same major]
+test_write_basic_config_version_file(4.5 9 0 0 0 0) # Request [newer major]
+
+test_write_basic_config_version_file(4.5 0.0 1 0 0 0) # Request 0.0
+test_write_basic_config_version_file(4.5 0.2 1 0 0 0) # Request 0.[older minor]
+test_write_basic_config_version_file(4.5 0.5 1 0 0 0) # Request 0.[same minor]
+test_write_basic_config_version_file(4.5 0.9 1 0 0 0) # Request 0.[newer minor]
+test_write_basic_config_version_file(4.5 2.0 1 0 0 0) # Request [older major].0
+test_write_basic_config_version_file(4.5 2.2 1 0 0 0) # Request [older major].[older minor]
+test_write_basic_config_version_file(4.5 2.5 1 0 0 0) # Request [older major].[same minor]
+test_write_basic_config_version_file(4.5 2.9 1 0 0 0) # Request [older major].[newer minor]
+test_write_basic_config_version_file(4.5 4.0 1 1 0 0) # Request [same major].0
+test_write_basic_config_version_file(4.5 4.2 1 1 0 0) # Request [same major].[older minor]
+test_write_basic_config_version_file(4.5 4.5 1 1 1 1) # Request [same major].[same minor]
+test_write_basic_config_version_file(4.5 4.9 0 0 0 0) # Request [same major].[newer minor]
+test_write_basic_config_version_file(4.5 9.0 0 0 0 0) # Request [newer major].0
+test_write_basic_config_version_file(4.5 9.1 0 0 0 0) # Request [newer major].[older minor]
+test_write_basic_config_version_file(4.5 9.5 0 0 0 0) # Request [newer major].[same minor]
+test_write_basic_config_version_file(4.5 9.9 0 0 0 0) # Request [newer major].[newer minor]
+
+test_write_basic_config_version_file(4.5 0.0.0 1 0 0 0) # Request 0.0.0
+test_write_basic_config_version_file(4.5 0.0.9 1 0 0 0) # Request 0.0.[newer patch]
+test_write_basic_config_version_file(4.5 0.2.0 1 0 0 0) # Request 0.[older minor].0
+test_write_basic_config_version_file(4.5 0.2.9 1 0 0 0) # Request 0.[older minor].[newer patch]
+test_write_basic_config_version_file(4.5 0.5.0 1 0 0 0) # Request 0.[same minor].0
+test_write_basic_config_version_file(4.5 0.5.9 1 0 0 0) # Request 0.[same minor].[newer patch]
+test_write_basic_config_version_file(4.5 0.9.0 1 0 0 0) # Request 0.[newer minor].0
+test_write_basic_config_version_file(4.5 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5 2.0.0 1 0 0 0) # Request [older major].0.0
+test_write_basic_config_version_file(4.5 2.0.9 1 0 0 0) # Request [older major].0.[newer patch]
+test_write_basic_config_version_file(4.5 2.2.0 1 0 0 0) # Request [older major].[older minor].0
+test_write_basic_config_version_file(4.5 2.2.9 1 0 0 0) # Request [older major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5 2.5.0 1 0 0 0) # Request [older major].[same minor].0
+test_write_basic_config_version_file(4.5 2.5.9 1 0 0 0) # Request [older major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5 2.9.0 1 0 0 0) # Request [older major].[newer minor].0
+test_write_basic_config_version_file(4.5 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5 4.0.0 1 1 0 0) # Request [same major].0.0
+test_write_basic_config_version_file(4.5 4.0.9 1 1 0 0) # Request [same major].0.[newer patch]
+test_write_basic_config_version_file(4.5 4.2.0 1 1 0 0) # Request [same major].[older minor].0
+test_write_basic_config_version_file(4.5 4.2.9 1 1 0 0) # Request [same major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5 4.5.0 1 1 1 0) # Request [same major].[same minor].0
+test_write_basic_config_version_file(4.5 4.5.9 0 0 0 0) # Request [same major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5 4.9.0 0 0 0 0) # Request [same major].[newer minor].0
+test_write_basic_config_version_file(4.5 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5 9.0.0 0 0 0 0) # Request [newer major].0.0
+test_write_basic_config_version_file(4.5 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch]
+test_write_basic_config_version_file(4.5 9.2.0 0 0 0 0) # Request [newer major].[older minor].0
+test_write_basic_config_version_file(4.5 9.2.9 0 0 0 0) # Request [newer major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5 9.5.0 0 0 0 0) # Request [newer major].[same minor].0
+test_write_basic_config_version_file(4.5 9.5.9 0 0 0 0) # Request [newer major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0
+test_write_basic_config_version_file(4.5 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch]
+
+test_write_basic_config_version_file(4.5 0.0.0.0 1 0 0 0) # Request 0.0.0.0
+test_write_basic_config_version_file(4.5 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak]
+test_write_basic_config_version_file(4.5 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0
+test_write_basic_config_version_file(4.5 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 0.2.0.0 1 0 0 0) # Request 0.[older minor].0.0
+test_write_basic_config_version_file(4.5 0.2.0.9 1 0 0 0) # Request 0.[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 0.2.9.0 1 0 0 0) # Request 0.[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5 0.2.9.9 1 0 0 0) # Request 0.[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 0.5.0.0 1 0 0 0) # Request 0.[same minor].0.0
+test_write_basic_config_version_file(4.5 0.5.0.9 1 0 0 0) # Request 0.[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 0.5.9.0 1 0 0 0) # Request 0.[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5 0.5.9.9 1 0 0 0) # Request 0.[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0
+test_write_basic_config_version_file(4.5 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 2.0.0.0 1 0 0 0) # Request [older major].0.0.0
+test_write_basic_config_version_file(4.5 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0
+test_write_basic_config_version_file(4.5 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 2.2.0.0 1 0 0 0) # Request [older major].[older minor].0.0
+test_write_basic_config_version_file(4.5 2.2.0.9 1 0 0 0) # Request [older major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 2.2.9.0 1 0 0 0) # Request [older major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5 2.2.9.9 1 0 0 0) # Request [older major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 2.5.0.0 1 0 0 0) # Request [older major].[same minor].0.0
+test_write_basic_config_version_file(4.5 2.5.0.9 1 0 0 0) # Request [older major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 2.5.9.0 1 0 0 0) # Request [older major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5 2.5.9.9 1 0 0 0) # Request [older major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0
+test_write_basic_config_version_file(4.5 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 4.0.0.0 1 1 0 0) # Request [same major].0.0.0
+test_write_basic_config_version_file(4.5 4.0.0.9 1 1 0 0) # Request [same major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5 4.0.9.0 1 1 0 0) # Request [same major].0.[newer patch].0
+test_write_basic_config_version_file(4.5 4.0.9.9 1 1 0 0) # Request [same major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 4.2.0.0 1 1 0 0) # Request [same major].[older minor].0.0
+test_write_basic_config_version_file(4.5 4.2.0.9 1 1 0 0) # Request [same major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 4.2.9.0 1 1 0 0) # Request [same major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5 4.2.9.9 1 1 0 0) # Request [same major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 4.5.0.0 1 1 1 0) # Request [same major].[same minor].0.0
+test_write_basic_config_version_file(4.5 4.5.0.9 0 0 0 0) # Request [same major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 4.5.9.0 0 0 0 0) # Request [same major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5 4.5.9.9 0 0 0 0) # Request [same major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0
+test_write_basic_config_version_file(4.5 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0
+test_write_basic_config_version_file(4.5 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0
+test_write_basic_config_version_file(4.5 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 9.2.0.0 0 0 0 0) # Request [newer major].[older minor].0.0
+test_write_basic_config_version_file(4.5 9.2.0.9 0 0 0 0) # Request [newer major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 9.2.9.0 0 0 0 0) # Request [newer major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5 9.2.9.9 0 0 0 0) # Request [newer major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 9.5.0.0 0 0 0 0) # Request [newer major].[same minor].0.0
+test_write_basic_config_version_file(4.5 9.5.0.9 0 0 0 0) # Request [newer major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 9.5.9.0 0 0 0 0) # Request [newer major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5 9.5.9.9 0 0 0 0) # Request [newer major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0
+test_write_basic_config_version_file(4.5 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak]
+
+
+test_write_basic_config_version_file(4.5.6 0 1 0 0 0) # Request 0
+test_write_basic_config_version_file(4.5.6 2 1 0 0 0) # Request [older major]
+test_write_basic_config_version_file(4.5.6 4 1 1 0 0) # Request [same major]
+test_write_basic_config_version_file(4.5.6 9 0 0 0 0) # Request [newer major]
+
+test_write_basic_config_version_file(4.5.6 0.0 1 0 0 0) # Request 0.0
+test_write_basic_config_version_file(4.5.6 0.2 1 0 0 0) # Request 0.[older minor]
+test_write_basic_config_version_file(4.5.6 0.5 1 0 0 0) # Request 0.[same minor]
+test_write_basic_config_version_file(4.5.6 0.9 1 0 0 0) # Request 0.[newer minor]
+test_write_basic_config_version_file(4.5.6 2.0 1 0 0 0) # Request [older major].0
+test_write_basic_config_version_file(4.5.6 2.2 1 0 0 0) # Request [older major].[older minor]
+test_write_basic_config_version_file(4.5.6 2.5 1 0 0 0) # Request [older major].[same minor]
+test_write_basic_config_version_file(4.5.6 2.9 1 0 0 0) # Request [older major].[newer minor]
+test_write_basic_config_version_file(4.5.6 4.0 1 1 0 0) # Request [same major].0
+test_write_basic_config_version_file(4.5.6 4.2 1 1 0 0) # Request [same major].[older minor]
+test_write_basic_config_version_file(4.5.6 4.5 1 1 1 0) # Request [same major].[same minor]
+test_write_basic_config_version_file(4.5.6 4.9 0 0 0 0) # Request [same major].[newer minor]
+test_write_basic_config_version_file(4.5.6 9.0 0 0 0 0) # Request [newer major].0
+test_write_basic_config_version_file(4.5.6 9.1 0 0 0 0) # Request [newer major].[older minor]
+test_write_basic_config_version_file(4.5.6 9.5 0 0 0 0) # Request [newer major].[same minor]
+test_write_basic_config_version_file(4.5.6 9.9 0 0 0 0) # Request [newer major].[newer minor]
+
+test_write_basic_config_version_file(4.5.6 0.0.0 1 0 0 0) # Request 0.0.0
+test_write_basic_config_version_file(4.5.6 0.0.2 1 0 0 0) # Request 0.0.[older patch]
+test_write_basic_config_version_file(4.5.6 0.0.6 1 0 0 0) # Request 0.0.[same patch]
+test_write_basic_config_version_file(4.5.6 0.0.9 1 0 0 0) # Request 0.0.[newer patch]
+test_write_basic_config_version_file(4.5.6 0.2.0 1 0 0 0) # Request 0.[older minor].0
+test_write_basic_config_version_file(4.5.6 0.2.2 1 0 0 0) # Request 0.[older minor].[older patch]
+test_write_basic_config_version_file(4.5.6 0.2.6 1 0 0 0) # Request 0.[older minor].[same patch]
+test_write_basic_config_version_file(4.5.6 0.2.9 1 0 0 0) # Request 0.[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 0.5.0 1 0 0 0) # Request 0.[same minor].0
+test_write_basic_config_version_file(4.5.6 0.5.2 1 0 0 0) # Request 0.[same minor].[older patch]
+test_write_basic_config_version_file(4.5.6 0.5.6 1 0 0 0) # Request 0.[same minor].[same patch]
+test_write_basic_config_version_file(4.5.6 0.5.9 1 0 0 0) # Request 0.[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 0.9.0 1 0 0 0) # Request 0.[newer minor].0
+test_write_basic_config_version_file(4.5.6 0.9.2 1 0 0 0) # Request 0.[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.6 0.9.6 1 0 0 0) # Request 0.[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.6 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 2.0.0 1 0 0 0) # Request [older major].0.0
+test_write_basic_config_version_file(4.5.6 2.0.2 1 0 0 0) # Request [older major].0.[older patch]
+test_write_basic_config_version_file(4.5.6 2.0.6 1 0 0 0) # Request [older major].0.[same patch]
+test_write_basic_config_version_file(4.5.6 2.0.9 1 0 0 0) # Request [older major].0.[newer patch]
+test_write_basic_config_version_file(4.5.6 2.2.0 1 0 0 0) # Request [older major].[older minor].0
+test_write_basic_config_version_file(4.5.6 2.2.2 1 0 0 0) # Request [older major].[older minor].[older patch]
+test_write_basic_config_version_file(4.5.6 2.2.6 1 0 0 0) # Request [older major].[older minor].[same patch]
+test_write_basic_config_version_file(4.5.6 2.2.9 1 0 0 0) # Request [older major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 2.5.0 1 0 0 0) # Request [older major].[same minor].0
+test_write_basic_config_version_file(4.5.6 2.5.2 1 0 0 0) # Request [older major].[same minor].[older patch]
+test_write_basic_config_version_file(4.5.6 2.5.6 1 0 0 0) # Request [older major].[same minor].[same patch]
+test_write_basic_config_version_file(4.5.6 2.5.9 1 0 0 0) # Request [older major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 2.9.0 1 0 0 0) # Request [older major].[newer minor].0
+test_write_basic_config_version_file(4.5.6 2.9.2 1 0 0 0) # Request [older major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.6 2.9.6 1 0 0 0) # Request [older major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.6 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 4.0.0 1 1 0 0) # Request [same major].0.0
+test_write_basic_config_version_file(4.5.6 4.0.2 1 1 0 0) # Request [same major].0.[older patch]
+test_write_basic_config_version_file(4.5.6 4.0.6 1 1 0 0) # Request [same major].0.[same patch]
+test_write_basic_config_version_file(4.5.6 4.0.9 1 1 0 0) # Request [same major].0.[newer patch]
+test_write_basic_config_version_file(4.5.6 4.2.0 1 1 0 0) # Request [same major].[older minor].0
+test_write_basic_config_version_file(4.5.6 4.2.2 1 1 0 0) # Request [same major].[older minor].[older patch]
+test_write_basic_config_version_file(4.5.6 4.2.6 1 1 0 0) # Request [same major].[older minor].[same patch]
+test_write_basic_config_version_file(4.5.6 4.2.9 1 1 0 0) # Request [same major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 4.5.0 1 1 1 0) # Request [same major].[same minor].0
+test_write_basic_config_version_file(4.5.6 4.5.2 1 1 1 0) # Request [same major].[same minor].[older patch]
+test_write_basic_config_version_file(4.5.6 4.5.6 1 1 1 1) # Request [same major].[same minor].[same patch]
+test_write_basic_config_version_file(4.5.6 4.5.9 0 0 0 0) # Request [same major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 4.9.0 0 0 0 0) # Request [same major].[newer minor].0
+test_write_basic_config_version_file(4.5.6 4.9.2 0 0 0 0) # Request [same major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.6 4.9.6 0 0 0 0) # Request [same major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.6 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 9.0.0 0 0 0 0) # Request [newer major].0.0
+test_write_basic_config_version_file(4.5.6 9.0.2 0 0 0 0) # Request [newer major].0.[older patch]
+test_write_basic_config_version_file(4.5.6 9.0.6 0 0 0 0) # Request [newer major].0.[same patch]
+test_write_basic_config_version_file(4.5.6 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch]
+test_write_basic_config_version_file(4.5.6 9.2.0 0 0 0 0) # Request [newer major].[older minor].0
+test_write_basic_config_version_file(4.5.6 9.2.2 0 0 0 0) # Request [newer major].[older minor].[older patch]
+test_write_basic_config_version_file(4.5.6 9.2.6 0 0 0 0) # Request [newer major].[older minor].[same patch]
+test_write_basic_config_version_file(4.5.6 9.2.9 0 0 0 0) # Request [newer major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 9.5.0 0 0 0 0) # Request [newer major].[same minor].0
+test_write_basic_config_version_file(4.5.6 9.5.2 0 0 0 0) # Request [newer major].[same minor].[older patch]
+test_write_basic_config_version_file(4.5.6 9.5.6 0 0 0 0) # Request [newer major].[same minor].[same patch]
+test_write_basic_config_version_file(4.5.6 9.5.9 0 0 0 0) # Request [newer major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.6 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0
+test_write_basic_config_version_file(4.5.6 9.9.2 0 0 0 0) # Request [newer major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.6 9.9.6 0 0 0 0) # Request [newer major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.6 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch]
+
+test_write_basic_config_version_file(4.5.6 0.0.0.0 1 0 0 0) # Request 0.0.0.0
+test_write_basic_config_version_file(4.5.6 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.0.2.0 1 0 0 0) # Request 0.0.[older patch].0
+test_write_basic_config_version_file(4.5.6 0.0.2.9 1 0 0 0) # Request 0.0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.0.6.0 1 0 0 0) # Request 0.0.[same patch].0
+test_write_basic_config_version_file(4.5.6 0.0.6.9 1 0 0 0) # Request 0.0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0
+test_write_basic_config_version_file(4.5.6 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.2.0.0 1 0 0 0) # Request 0.[older minor].0.0
+test_write_basic_config_version_file(4.5.6 0.2.0.9 1 0 0 0) # Request 0.[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.2.2.0 1 0 0 0) # Request 0.[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 0.2.2.9 1 0 0 0) # Request 0.[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.2.6.0 1 0 0 0) # Request 0.[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 0.2.6.9 1 0 0 0) # Request 0.[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.2.9.0 1 0 0 0) # Request 0.[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 0.2.9.9 1 0 0 0) # Request 0.[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.5.0.0 1 0 0 0) # Request 0.[same minor].0.0
+test_write_basic_config_version_file(4.5.6 0.5.0.9 1 0 0 0) # Request 0.[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.5.2.0 1 0 0 0) # Request 0.[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 0.5.2.9 1 0 0 0) # Request 0.[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.5.6.0 1 0 0 0) # Request 0.[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 0.5.6.9 1 0 0 0) # Request 0.[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.5.9.0 1 0 0 0) # Request 0.[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 0.5.9.9 1 0 0 0) # Request 0.[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0
+test_write_basic_config_version_file(4.5.6 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.9.2.0 1 0 0 0) # Request 0.[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 0.9.2.9 1 0 0 0) # Request 0.[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.9.6.0 1 0 0 0) # Request 0.[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 0.9.6.9 1 0 0 0) # Request 0.[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.0.0.0 1 0 0 0) # Request [older major].0.0.0
+test_write_basic_config_version_file(4.5.6 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.0.2.0 1 0 0 0) # Request [older major].0.[older patch].0
+test_write_basic_config_version_file(4.5.6 2.0.2.9 1 0 0 0) # Request [older major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.0.6.0 1 0 0 0) # Request [older major].0.[same patch].0
+test_write_basic_config_version_file(4.5.6 2.0.6.9 1 0 0 0) # Request [older major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0
+test_write_basic_config_version_file(4.5.6 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.2.0.0 1 0 0 0) # Request [older major].[older minor].0.0
+test_write_basic_config_version_file(4.5.6 2.2.0.9 1 0 0 0) # Request [older major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.2.2.0 1 0 0 0) # Request [older major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 2.2.2.9 1 0 0 0) # Request [older major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.2.6.0 1 0 0 0) # Request [older major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 2.2.6.9 1 0 0 0) # Request [older major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.2.9.0 1 0 0 0) # Request [older major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 2.2.9.9 1 0 0 0) # Request [older major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.5.0.0 1 0 0 0) # Request [older major].[same minor].0.0
+test_write_basic_config_version_file(4.5.6 2.5.0.9 1 0 0 0) # Request [older major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.5.2.0 1 0 0 0) # Request [older major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 2.5.2.9 1 0 0 0) # Request [older major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.5.6.0 1 0 0 0) # Request [older major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 2.5.6.9 1 0 0 0) # Request [older major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.5.9.0 1 0 0 0) # Request [older major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 2.5.9.9 1 0 0 0) # Request [older major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0
+test_write_basic_config_version_file(4.5.6 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.9.2.0 1 0 0 0) # Request [older major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 2.9.2.9 1 0 0 0) # Request [older major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.9.6.0 1 0 0 0) # Request [older major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 2.9.6.9 1 0 0 0) # Request [older major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.0.0.0 1 1 0 0) # Request [same major].0.0.0
+test_write_basic_config_version_file(4.5.6 4.0.0.9 1 1 0 0) # Request [same major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.0.2.0 1 1 0 0) # Request [same major].0.[older patch].0
+test_write_basic_config_version_file(4.5.6 4.0.2.9 1 1 0 0) # Request [same major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.0.6.0 1 1 0 0) # Request [same major].0.[same patch].0
+test_write_basic_config_version_file(4.5.6 4.0.6.9 1 1 0 0) # Request [same major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.0.9.0 1 1 0 0) # Request [same major].0.[newer patch].0
+test_write_basic_config_version_file(4.5.6 4.0.9.9 1 1 0 0) # Request [same major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.2.0.0 1 1 0 0) # Request [same major].[older minor].0.0
+test_write_basic_config_version_file(4.5.6 4.2.0.9 1 1 0 0) # Request [same major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.2.2.0 1 1 0 0) # Request [same major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 4.2.2.9 1 1 0 0) # Request [same major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.2.6.0 1 1 0 0) # Request [same major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 4.2.6.9 1 1 0 0) # Request [same major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.2.9.0 1 1 0 0) # Request [same major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 4.2.9.9 1 1 0 0) # Request [same major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.5.0.0 1 1 1 0) # Request [same major].[same minor].0.0
+test_write_basic_config_version_file(4.5.6 4.5.0.9 1 1 1 0) # Request [same major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.5.2.0 1 1 1 0) # Request [same major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 4.5.2.9 1 1 1 0) # Request [same major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.5.6.0 1 1 1 1) # Request [same major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 4.5.6.9 0 0 0 1) # Request [same major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.5.9.0 0 0 0 0) # Request [same major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 4.5.9.9 0 0 0 0) # Request [same major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0
+test_write_basic_config_version_file(4.5.6 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.9.2.0 0 0 0 0) # Request [same major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 4.9.2.9 0 0 0 0) # Request [same major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.9.6.0 0 0 0 0) # Request [same major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 4.9.6.9 0 0 0 0) # Request [same major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0
+test_write_basic_config_version_file(4.5.6 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.0.2.0 0 0 0 0) # Request [newer major].0.[older patch].0
+test_write_basic_config_version_file(4.5.6 9.0.2.9 0 0 0 0) # Request [newer major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.0.6.0 0 0 0 0) # Request [newer major].0.[same patch].0
+test_write_basic_config_version_file(4.5.6 9.0.6.9 0 0 0 0) # Request [newer major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0
+test_write_basic_config_version_file(4.5.6 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.2.0.0 0 0 0 0) # Request [newer major].[older minor].0.0
+test_write_basic_config_version_file(4.5.6 9.2.0.9 0 0 0 0) # Request [newer major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.2.2.0 0 0 0 0) # Request [newer major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 9.2.2.9 0 0 0 0) # Request [newer major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.2.6.0 0 0 0 0) # Request [newer major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 9.2.6.9 0 0 0 0) # Request [newer major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.2.9.0 0 0 0 0) # Request [newer major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 9.2.9.9 0 0 0 0) # Request [newer major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.5.0.0 0 0 0 0) # Request [newer major].[same minor].0.0
+test_write_basic_config_version_file(4.5.6 9.5.0.9 0 0 0 0) # Request [newer major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.5.2.0 0 0 0 0) # Request [newer major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 9.5.2.9 0 0 0 0) # Request [newer major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.5.6.0 0 0 0 0) # Request [newer major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 9.5.6.9 0 0 0 0) # Request [newer major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.5.9.0 0 0 0 0) # Request [newer major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 9.5.9.9 0 0 0 0) # Request [newer major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0
+test_write_basic_config_version_file(4.5.6 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.9.2.0 0 0 0 0) # Request [newer major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.6 9.9.2.9 0 0 0 0) # Request [newer major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.9.6.0 0 0 0 0) # Request [newer major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.6 9.9.6.9 0 0 0 0) # Request [newer major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak]
+
+
+test_write_basic_config_version_file(4.5.6.7 0 1 0 0 0) # Request 0
+test_write_basic_config_version_file(4.5.6.7 2 1 0 0 0) # Request [older major]
+test_write_basic_config_version_file(4.5.6.7 4 1 1 0 0) # Request [same major]
+test_write_basic_config_version_file(4.5.6.7 9 0 0 0 0) # Request [newer major]
+
+test_write_basic_config_version_file(4.5.6.7 0.0 1 0 0 0) # Request 0.0
+test_write_basic_config_version_file(4.5.6.7 0.2 1 0 0 0) # Request 0.[older minor]
+test_write_basic_config_version_file(4.5.6.7 0.5 1 0 0 0) # Request 0.[same minor]
+test_write_basic_config_version_file(4.5.6.7 0.9 1 0 0 0) # Request 0.[newer minor]
+test_write_basic_config_version_file(4.5.6.7 2.0 1 0 0 0) # Request [older major].0
+test_write_basic_config_version_file(4.5.6.7 2.2 1 0 0 0) # Request [older major].[older minor]
+test_write_basic_config_version_file(4.5.6.7 2.5 1 0 0 0) # Request [older major].[same minor]
+test_write_basic_config_version_file(4.5.6.7 2.9 1 0 0 0) # Request [older major].[newer minor]
+test_write_basic_config_version_file(4.5.6.7 4.0 1 1 0 0) # Request [same major].0
+test_write_basic_config_version_file(4.5.6.7 4.2 1 1 0 0) # Request [same major].[older minor]
+test_write_basic_config_version_file(4.5.6.7 4.5 1 1 1 0) # Request [same major].[same minor]
+test_write_basic_config_version_file(4.5.6.7 4.9 0 0 0 0) # Request [same major].[newer minor]
+test_write_basic_config_version_file(4.5.6.7 9.0 0 0 0 0) # Request [newer major].0
+test_write_basic_config_version_file(4.5.6.7 9.1 0 0 0 0) # Request [newer major].[older minor]
+test_write_basic_config_version_file(4.5.6.7 9.5 0 0 0 0) # Request [newer major].[same minor]
+test_write_basic_config_version_file(4.5.6.7 9.9 0 0 0 0) # Request [newer major].[newer minor]
+
+test_write_basic_config_version_file(4.5.6.7 0.0.0 1 0 0 0) # Request 0.0.0
+test_write_basic_config_version_file(4.5.6.7 0.0.2 1 0 0 0) # Request 0.0.[older patch]
+test_write_basic_config_version_file(4.5.6.7 0.0.6 1 0 0 0) # Request 0.0.[same patch]
+test_write_basic_config_version_file(4.5.6.7 0.0.9 1 0 0 0) # Request 0.0.[newer patch]
+test_write_basic_config_version_file(4.5.6.7 0.2.0 1 0 0 0) # Request 0.[older minor].0
+test_write_basic_config_version_file(4.5.6.7 0.2.2 1 0 0 0) # Request 0.[older minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 0.2.6 1 0 0 0) # Request 0.[older minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 0.2.9 1 0 0 0) # Request 0.[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 0.5.0 1 0 0 0) # Request 0.[same minor].0
+test_write_basic_config_version_file(4.5.6.7 0.5.2 1 0 0 0) # Request 0.[same minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 0.5.6 1 0 0 0) # Request 0.[same minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 0.5.9 1 0 0 0) # Request 0.[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 0.9.0 1 0 0 0) # Request 0.[newer minor].0
+test_write_basic_config_version_file(4.5.6.7 0.9.2 1 0 0 0) # Request 0.[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 0.9.6 1 0 0 0) # Request 0.[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 2.0.0 1 0 0 0) # Request [older major].0.0
+test_write_basic_config_version_file(4.5.6.7 2.0.2 1 0 0 0) # Request [older major].0.[older patch]
+test_write_basic_config_version_file(4.5.6.7 2.0.6 1 0 0 0) # Request [older major].0.[same patch]
+test_write_basic_config_version_file(4.5.6.7 2.0.9 1 0 0 0) # Request [older major].0.[newer patch]
+test_write_basic_config_version_file(4.5.6.7 2.2.0 1 0 0 0) # Request [older major].[older minor].0
+test_write_basic_config_version_file(4.5.6.7 2.2.2 1 0 0 0) # Request [older major].[older minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 2.2.6 1 0 0 0) # Request [older major].[older minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 2.2.9 1 0 0 0) # Request [older major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 2.5.0 1 0 0 0) # Request [older major].[same minor].0
+test_write_basic_config_version_file(4.5.6.7 2.5.2 1 0 0 0) # Request [older major].[same minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 2.5.6 1 0 0 0) # Request [older major].[same minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 2.5.9 1 0 0 0) # Request [older major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 2.9.0 1 0 0 0) # Request [older major].[newer minor].0
+test_write_basic_config_version_file(4.5.6.7 2.9.2 1 0 0 0) # Request [older major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 2.9.6 1 0 0 0) # Request [older major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 4.0.0 1 1 0 0) # Request [same major].0.0
+test_write_basic_config_version_file(4.5.6.7 4.0.2 1 1 0 0) # Request [same major].0.[older patch]
+test_write_basic_config_version_file(4.5.6.7 4.0.6 1 1 0 0) # Request [same major].0.[same patch]
+test_write_basic_config_version_file(4.5.6.7 4.0.9 1 1 0 0) # Request [same major].0.[newer patch]
+test_write_basic_config_version_file(4.5.6.7 4.2.0 1 1 0 0) # Request [same major].[older minor].0
+test_write_basic_config_version_file(4.5.6.7 4.2.2 1 1 0 0) # Request [same major].[older minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 4.2.6 1 1 0 0) # Request [same major].[older minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 4.2.9 1 1 0 0) # Request [same major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 4.5.0 1 1 1 0) # Request [same major].[same minor].0
+test_write_basic_config_version_file(4.5.6.7 4.5.2 1 1 1 0) # Request [same major].[same minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 4.5.6 1 1 1 1) # Request [same major].[same minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 4.5.9 0 0 0 0) # Request [same major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 4.9.0 0 0 0 0) # Request [same major].[newer minor].0
+test_write_basic_config_version_file(4.5.6.7 4.9.2 0 0 0 0) # Request [same major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 4.9.6 0 0 0 0) # Request [same major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 9.0.0 0 0 0 0) # Request [newer major].0.0
+test_write_basic_config_version_file(4.5.6.7 9.0.2 0 0 0 0) # Request [newer major].0.[older patch]
+test_write_basic_config_version_file(4.5.6.7 9.0.6 0 0 0 0) # Request [newer major].0.[same patch]
+test_write_basic_config_version_file(4.5.6.7 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch]
+test_write_basic_config_version_file(4.5.6.7 9.2.0 0 0 0 0) # Request [newer major].[older minor].0
+test_write_basic_config_version_file(4.5.6.7 9.2.2 0 0 0 0) # Request [newer major].[older minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 9.2.6 0 0 0 0) # Request [newer major].[older minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 9.2.9 0 0 0 0) # Request [newer major].[older minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 9.5.0 0 0 0 0) # Request [newer major].[same minor].0
+test_write_basic_config_version_file(4.5.6.7 9.5.2 0 0 0 0) # Request [newer major].[same minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 9.5.6 0 0 0 0) # Request [newer major].[same minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 9.5.9 0 0 0 0) # Request [newer major].[same minor].[newer patch]
+test_write_basic_config_version_file(4.5.6.7 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0
+test_write_basic_config_version_file(4.5.6.7 9.9.2 0 0 0 0) # Request [newer major].[newer minor].[older patch]
+test_write_basic_config_version_file(4.5.6.7 9.9.6 0 0 0 0) # Request [newer major].[newer minor].[same patch]
+test_write_basic_config_version_file(4.5.6.7 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch]
+
+test_write_basic_config_version_file(4.5.6.7 0.0.0.0 1 0 0 0) # Request 0.0.0.0
+test_write_basic_config_version_file(4.5.6.7 0.0.0.2 1 0 0 0) # Request 0.0.0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.0.7 1 0 0 0) # Request 0.0.0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.2.0 1 0 0 0) # Request 0.0.[older patch].0
+test_write_basic_config_version_file(4.5.6.7 0.0.2.2 1 0 0 0) # Request 0.0.[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.2.7 1 0 0 0) # Request 0.0.[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.2.9 1 0 0 0) # Request 0.0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.6.0 1 0 0 0) # Request 0.0.[same patch].0
+test_write_basic_config_version_file(4.5.6.7 0.0.6.2 1 0 0 0) # Request 0.0.[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.6.7 1 0 0 0) # Request 0.0.[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.6.9 1 0 0 0) # Request 0.0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 0.0.9.2 1 0 0 0) # Request 0.0.[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.9.7 1 0 0 0) # Request 0.0.[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.0.0 1 0 0 0) # Request 0.[older minor].0.0
+test_write_basic_config_version_file(4.5.6.7 0.2.0.2 1 0 0 0) # Request 0.[older minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.0.7 1 0 0 0) # Request 0.[older minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.0.9 1 0 0 0) # Request 0.[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.2.0 1 0 0 0) # Request 0.[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 0.2.2.2 1 0 0 0) # Request 0.[older minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.2.7 1 0 0 0) # Request 0.[older minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.2.9 1 0 0 0) # Request 0.[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.6.0 1 0 0 0) # Request 0.[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 0.2.6.2 1 0 0 0) # Request 0.[older minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.6.7 1 0 0 0) # Request 0.[older minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.6.9 1 0 0 0) # Request 0.[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.9.0 1 0 0 0) # Request 0.[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 0.2.9.2 1 0 0 0) # Request 0.[older minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.9.7 1 0 0 0) # Request 0.[older minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.2.9.9 1 0 0 0) # Request 0.[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.0.0 1 0 0 0) # Request 0.[same minor].0.0
+test_write_basic_config_version_file(4.5.6.7 0.5.0.2 1 0 0 0) # Request 0.[same minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.0.7 1 0 0 0) # Request 0.[same minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.0.9 1 0 0 0) # Request 0.[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.2.0 1 0 0 0) # Request 0.[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 0.5.2.2 1 0 0 0) # Request 0.[same minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.2.7 1 0 0 0) # Request 0.[same minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.2.9 1 0 0 0) # Request 0.[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.6.0 1 0 0 0) # Request 0.[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 0.5.6.2 1 0 0 0) # Request 0.[same minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.6.7 1 0 0 0) # Request 0.[same minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.6.9 1 0 0 0) # Request 0.[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.9.0 1 0 0 0) # Request 0.[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 0.5.9.2 1 0 0 0) # Request 0.[same minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.9.7 1 0 0 0) # Request 0.[same minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.5.9.9 1 0 0 0) # Request 0.[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0
+test_write_basic_config_version_file(4.5.6.7 0.9.0.2 1 0 0 0) # Request 0.[newer minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.0.7 1 0 0 0) # Request 0.[newer minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.2.0 1 0 0 0) # Request 0.[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 0.9.2.2 1 0 0 0) # Request 0.[newer minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.2.7 1 0 0 0) # Request 0.[newer minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.2.9 1 0 0 0) # Request 0.[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.6.0 1 0 0 0) # Request 0.[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 0.9.6.2 1 0 0 0) # Request 0.[newer minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.6.7 1 0 0 0) # Request 0.[newer minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.6.9 1 0 0 0) # Request 0.[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 0.9.9.2 1 0 0 0) # Request 0.[newer minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.9.7 1 0 0 0) # Request 0.[newer minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.0.0 1 0 0 0) # Request [older major].0.0.0
+test_write_basic_config_version_file(4.5.6.7 2.0.0.2 1 0 0 0) # Request [older major].0.0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.0.7 1 0 0 0) # Request [older major].0.0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.2.0 1 0 0 0) # Request [older major].0.[older patch].0
+test_write_basic_config_version_file(4.5.6.7 2.0.2.2 1 0 0 0) # Request [older major].0.[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.2.7 1 0 0 0) # Request [older major].0.[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.2.9 1 0 0 0) # Request [older major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.6.0 1 0 0 0) # Request [older major].0.[same patch].0
+test_write_basic_config_version_file(4.5.6.7 2.0.6.2 1 0 0 0) # Request [older major].0.[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.6.7 1 0 0 0) # Request [older major].0.[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.6.9 1 0 0 0) # Request [older major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 2.0.9.2 1 0 0 0) # Request [older major].0.[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.9.7 1 0 0 0) # Request [older major].0.[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.0.0 1 0 0 0) # Request [older major].[older minor].0.0
+test_write_basic_config_version_file(4.5.6.7 2.2.0.2 1 0 0 0) # Request [older major].[older minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.0.7 1 0 0 0) # Request [older major].[older minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.0.9 1 0 0 0) # Request [older major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.2.0 1 0 0 0) # Request [older major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 2.2.2.2 1 0 0 0) # Request [older major].[older minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.2.7 1 0 0 0) # Request [older major].[older minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.2.9 1 0 0 0) # Request [older major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.6.0 1 0 0 0) # Request [older major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 2.2.6.2 1 0 0 0) # Request [older major].[older minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.6.7 1 0 0 0) # Request [older major].[older minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.6.9 1 0 0 0) # Request [older major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.9.0 1 0 0 0) # Request [older major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 2.2.9.2 1 0 0 0) # Request [older major].[older minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.9.7 1 0 0 0) # Request [older major].[older minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.2.9.9 1 0 0 0) # Request [older major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.0.0 1 0 0 0) # Request [older major].[same minor].0.0
+test_write_basic_config_version_file(4.5.6.7 2.5.0.2 1 0 0 0) # Request [older major].[same minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.0.7 1 0 0 0) # Request [older major].[same minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.0.9 1 0 0 0) # Request [older major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.2.0 1 0 0 0) # Request [older major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 2.5.2.2 1 0 0 0) # Request [older major].[same minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.2.7 1 0 0 0) # Request [older major].[same minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.2.9 1 0 0 0) # Request [older major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.6.0 1 0 0 0) # Request [older major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 2.5.6.2 1 0 0 0) # Request [older major].[same minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.6.7 1 0 0 0) # Request [older major].[same minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.6.9 1 0 0 0) # Request [older major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.9.0 1 0 0 0) # Request [older major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 2.5.9.2 1 0 0 0) # Request [older major].[same minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.9.7 1 0 0 0) # Request [older major].[same minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.5.9.9 1 0 0 0) # Request [older major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0
+test_write_basic_config_version_file(4.5.6.7 2.9.0.2 1 0 0 0) # Request [older major].[newer minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.0.7 1 0 0 0) # Request [older major].[newer minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.2.0 1 0 0 0) # Request [older major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 2.9.2.2 1 0 0 0) # Request [older major].[newer minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.2.7 1 0 0 0) # Request [older major].[newer minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.2.9 1 0 0 0) # Request [older major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.6.0 1 0 0 0) # Request [older major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 2.9.6.2 1 0 0 0) # Request [older major].[newer minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.6.7 1 0 0 0) # Request [older major].[newer minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.6.9 1 0 0 0) # Request [older major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 2.9.9.2 1 0 0 0) # Request [older major].[newer minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.9.7 1 0 0 0) # Request [older major].[newer minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.0.0 1 1 0 0) # Request [same major].0.0.0
+test_write_basic_config_version_file(4.5.6.7 4.0.0.2 1 1 0 0) # Request [same major].0.0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.0.7 1 1 0 0) # Request [same major].0.0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.0.9 1 1 0 0) # Request [same major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.2.0 1 1 0 0) # Request [same major].0.[older patch].0
+test_write_basic_config_version_file(4.5.6.7 4.0.2.2 1 1 0 0) # Request [same major].0.[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.2.7 1 1 0 0) # Request [same major].0.[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.2.9 1 1 0 0) # Request [same major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.6.0 1 1 0 0) # Request [same major].0.[same patch].0
+test_write_basic_config_version_file(4.5.6.7 4.0.6.2 1 1 0 0) # Request [same major].0.[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.6.7 1 1 0 0) # Request [same major].0.[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.6.9 1 1 0 0) # Request [same major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.9.0 1 1 0 0) # Request [same major].0.[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 4.0.9.2 1 1 0 0) # Request [same major].0.[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.9.7 1 1 0 0) # Request [same major].0.[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.0.9.9 1 1 0 0) # Request [same major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.0.0 1 1 0 0) # Request [same major].[older minor].0.0
+test_write_basic_config_version_file(4.5.6.7 4.2.0.2 1 1 0 0) # Request [same major].[older minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.0.7 1 1 0 0) # Request [same major].[older minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.0.9 1 1 0 0) # Request [same major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.2.0 1 1 0 0) # Request [same major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 4.2.2.2 1 1 0 0) # Request [same major].[older minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.2.7 1 1 0 0) # Request [same major].[older minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.2.9 1 1 0 0) # Request [same major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.6.0 1 1 0 0) # Request [same major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 4.2.6.2 1 1 0 0) # Request [same major].[older minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.6.7 1 1 0 0) # Request [same major].[older minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.6.9 1 1 0 0) # Request [same major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.9.0 1 1 0 0) # Request [same major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 4.2.9.2 1 1 0 0) # Request [same major].[older minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.9.7 1 1 0 0) # Request [same major].[older minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.2.9.9 1 1 0 0) # Request [same major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.0.0 1 1 1 0) # Request [same major].[same minor].0.0
+test_write_basic_config_version_file(4.5.6.7 4.5.0.2 1 1 1 0) # Request [same major].[same minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.0.7 1 1 1 0) # Request [same major].[same minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.0.9 1 1 1 0) # Request [same major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.2.0 1 1 1 0) # Request [same major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 4.5.2.2 1 1 1 0) # Request [same major].[same minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.2.7 1 1 1 0) # Request [same major].[same minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.2.9 1 1 1 0) # Request [same major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.6.0 1 1 1 1) # Request [same major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 4.5.6.2 1 1 1 1) # Request [same major].[same minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.6.7 1 1 1 1) # Request [same major].[same minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.6.9 0 0 0 1) # Request [same major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.9.0 0 0 0 0) # Request [same major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 4.5.9.2 0 0 0 0) # Request [same major].[same minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.9.7 0 0 0 0) # Request [same major].[same minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.5.9.9 0 0 0 0) # Request [same major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0
+test_write_basic_config_version_file(4.5.6.7 4.9.0.2 0 0 0 0) # Request [same major].[newer minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.0.7 0 0 0 0) # Request [same major].[newer minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.2.0 0 0 0 0) # Request [same major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 4.9.2.2 0 0 0 0) # Request [same major].[newer minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.2.7 0 0 0 0) # Request [same major].[newer minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.2.9 0 0 0 0) # Request [same major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.6.0 0 0 0 0) # Request [same major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 4.9.6.2 0 0 0 0) # Request [same major].[newer minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.6.7 0 0 0 0) # Request [same major].[newer minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.6.9 0 0 0 0) # Request [same major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 4.9.9.2 0 0 0 0) # Request [same major].[newer minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.9.7 0 0 0 0) # Request [same major].[newer minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0
+test_write_basic_config_version_file(4.5.6.7 9.0.0.2 0 0 0 0) # Request [newer major].0.0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.0.7 0 0 0 0) # Request [newer major].0.0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.2.0 0 0 0 0) # Request [newer major].0.[older patch].0
+test_write_basic_config_version_file(4.5.6.7 9.0.2.2 0 0 0 0) # Request [newer major].0.[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.2.7 0 0 0 0) # Request [newer major].0.[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.2.9 0 0 0 0) # Request [newer major].0.[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.6.0 0 0 0 0) # Request [newer major].0.[same patch].0
+test_write_basic_config_version_file(4.5.6.7 9.0.6.2 0 0 0 0) # Request [newer major].0.[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.6.7 0 0 0 0) # Request [newer major].0.[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.6.9 0 0 0 0) # Request [newer major].0.[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 9.0.9.2 0 0 0 0) # Request [newer major].0.[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.9.7 0 0 0 0) # Request [newer major].0.[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.0.0 0 0 0 0) # Request [newer major].[older minor].0.0
+test_write_basic_config_version_file(4.5.6.7 9.2.0.2 0 0 0 0) # Request [newer major].[older minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.0.7 0 0 0 0) # Request [newer major].[older minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.0.9 0 0 0 0) # Request [newer major].[older minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.2.0 0 0 0 0) # Request [newer major].[older minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 9.2.2.2 0 0 0 0) # Request [newer major].[older minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.2.7 0 0 0 0) # Request [newer major].[older minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.2.9 0 0 0 0) # Request [newer major].[older minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.6.0 0 0 0 0) # Request [newer major].[older minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 9.2.6.2 0 0 0 0) # Request [newer major].[older minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.6.7 0 0 0 0) # Request [newer major].[older minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.6.9 0 0 0 0) # Request [newer major].[older minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.9.0 0 0 0 0) # Request [newer major].[older minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 9.2.9.2 0 0 0 0) # Request [newer major].[older minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.9.7 0 0 0 0) # Request [newer major].[older minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.2.9.9 0 0 0 0) # Request [newer major].[older minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.0.0 0 0 0 0) # Request [newer major].[same minor].0.0
+test_write_basic_config_version_file(4.5.6.7 9.5.0.2 0 0 0 0) # Request [newer major].[same minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.0.7 0 0 0 0) # Request [newer major].[same minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.0.9 0 0 0 0) # Request [newer major].[same minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.2.0 0 0 0 0) # Request [newer major].[same minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 9.5.2.2 0 0 0 0) # Request [newer major].[same minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.2.7 0 0 0 0) # Request [newer major].[same minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.2.9 0 0 0 0) # Request [newer major].[same minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.6.0 0 0 0 0) # Request [newer major].[same minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 9.5.6.2 0 0 0 0) # Request [newer major].[same minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.6.7 0 0 0 0) # Request [newer major].[same minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.6.9 0 0 0 0) # Request [newer major].[same minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.9.0 0 0 0 0) # Request [newer major].[same minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 9.5.9.2 0 0 0 0) # Request [newer major].[same minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.9.7 0 0 0 0) # Request [newer major].[same minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.5.9.9 0 0 0 0) # Request [newer major].[same minor].[newer patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0
+test_write_basic_config_version_file(4.5.6.7 9.9.0.2 0 0 0 0) # Request [newer major].[newer minor].0.[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.0.7 0 0 0 0) # Request [newer major].[newer minor].0.[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.2.0 0 0 0 0) # Request [newer major].[newer minor].[older patch].0
+test_write_basic_config_version_file(4.5.6.7 9.9.2.2 0 0 0 0) # Request [newer major].[newer minor].[older patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.2.7 0 0 0 0) # Request [newer major].[newer minor].[older patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.2.9 0 0 0 0) # Request [newer major].[newer minor].[older patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.6.0 0 0 0 0) # Request [newer major].[newer minor].[same patch].0
+test_write_basic_config_version_file(4.5.6.7 9.9.6.2 0 0 0 0) # Request [newer major].[newer minor].[same patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.6.7 0 0 0 0) # Request [newer major].[newer minor].[same patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.6.9 0 0 0 0) # Request [newer major].[newer minor].[same patch].[newer tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0
+test_write_basic_config_version_file(4.5.6.7 9.9.9.2 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[older tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.9.7 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[same tweak]
+test_write_basic_config_version_file(4.5.6.7 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak]
############################################################################
--- /dev/null
+add_test(NAME FindPython.Python2 COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindPython/Python2"
+ "${CMake_BINARY_DIR}/Tests/FindPython/Python2"
+ ${build_generator_args}
+ --build-project TestPython2
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+
+add_test(NAME FindPython.Python2Fail COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindPython/Python2Fail"
+ "${CMake_BINARY_DIR}/Tests/FindPython/Python2Fail"
+ ${build_generator_args}
+ --build-project TestPython2Fail
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+set_tests_properties(FindPython.Python2Fail PROPERTIES
+ PASS_REGULAR_EXPRESSION "Could NOT find Python2 \\(missing: foobar\\)")
+
+add_test(NAME FindPython.Python3 COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindPython/Python3"
+ "${CMake_BINARY_DIR}/Tests/FindPython/Python3"
+ ${build_generator_args}
+ --build-project TestPython3
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+
+add_test(NAME FindPython.Python3Fail COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindPython/Python3Fail"
+ "${CMake_BINARY_DIR}/Tests/FindPython/Python3Fail"
+ ${build_generator_args}
+ --build-project TestPython3Fail
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+set_tests_properties(FindPython.Python3Fail PROPERTIES
+ PASS_REGULAR_EXPRESSION "Could NOT find Python3 \\(missing: foobar\\)")
+
+add_test(NAME FindPython.Python COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindPython/Python"
+ "${CMake_BINARY_DIR}/Tests/FindPython/Python"
+ ${build_generator_args}
+ --build-project TestPython
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+
+add_test(NAME FindPython.MultiplePackages COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindPython/MultiplePackages"
+ "${CMake_BINARY_DIR}/Tests/FindPython/MultiplePackages"
+ ${build_generator_args}
+ --build-project TestMultiplePackages
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestMultiplePackages C)
+
+find_package (Python2 REQUIRED COMPONENTS Interpreter Development)
+find_package (Python3 REQUIRED COMPONENTS Interpreter Development)
+
+# Must find Python 3
+find_package (Python REQUIRED)
+
+if (NOT Python3_EXECUTABLE STREQUAL Python_EXECUTABLE)
+ message (FATAL_ERROR
+ "Python interpreters do not match:\n"
+ " Python_EXECUTABLE='${Python_EXECUTABLE}'\n"
+ " Python3_EXECUTABLE='${Python3_EXECUTABLE}'\n"
+ )
+endif()
+
+
+Python2_add_library (spam2 MODULE ../spam.c)
+target_compile_definitions (spam2 PRIVATE PYTHON2)
+
+Python3_add_library (spam3 MODULE ../spam.c)
+target_compile_definitions (spam3 PRIVATE PYTHON3)
+
+
+add_test (NAME python2_spam2
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+ "${Python2_EXECUTABLE}" -c "import spam2; spam2.system(\"cd\")")
+
+add_test (NAME python3_spam3
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+ "${Python3_EXECUTABLE}" -c "import spam3; spam3.system(\"cd\")")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython C)
+
+include(CTest)
+
+find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
+if (NOT Python_FOUND)
+ message (FATAL_ERROR "Fail to found Python 3")
+endif()
+
+Python_add_library (spam3 MODULE ../spam.c)
+target_compile_definitions (spam3 PRIVATE PYTHON3)
+
+add_test (NAME python_spam3
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+ "${Python_EXECUTABLE}" -c "import spam3; spam3.system(\"cd\")")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython2 C)
+
+include(CTest)
+
+find_package(Python2 3 QUIET)
+if (Python2_FOUND)
+ message (FATAL_ERROR "Wrong python version found: ${Python2_VERSION}")
+endif()
+
+find_package(Python2 REQUIRED COMPONENTS Interpreter Development)
+if (NOT Python2_FOUND)
+ message (FATAL_ERROR "Fail to found Python 2")
+endif()
+
+Python2_add_library (spam2 MODULE ../spam.c)
+target_compile_definitions (spam2 PRIVATE PYTHON2)
+
+add_test (NAME python2_spam2
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam2>"
+ "${Python2_EXECUTABLE}" -c "import spam2; spam2.system(\"cd\")")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython2Fail C)
+
+include(CTest)
+
+find_package(Python2 REQUIRED COMPONENTS Interpreter Development foobar)
+
+Python2_add_library (spam2 MODULE ../spam.c)
+target_compile_definitions (spam2 PRIVATE PYTHON2)
+
+add_test (NAME python2_spam2
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam2>"
+ "${Python2_EXECUTABLE}" -c "import spam2; spam2.system(\"cd\")")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython3 C)
+
+include(CTest)
+
+find_package(Python3 2 QUIET)
+if (Python3_FOUND)
+ message (FATAL_ERROR "Wrong python version found: ${Python3_VERSION}")
+endif()
+
+find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
+if (NOT Python3_FOUND)
+ message (FATAL_ERROR "Fail to found Python 3")
+endif()
+
+Python3_add_library (spam3 MODULE ../spam.c)
+target_compile_definitions (spam3 PRIVATE PYTHON3)
+
+add_test (NAME python3_spam3
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+ "${Python3_EXECUTABLE}" -c "import spam3; spam3.system(\"cd\")")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython3Fail C)
+
+include(CTest)
+
+find_package(Python3 REQUIRED COMPONENTS Interpreter Development foobar)
+
+Python3_add_library (spam3 MODULE ../spam.c)
+target_compile_definitions (spam3 PRIVATE PYTHON3)
+
+add_test (NAME python3_spam3
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+ "${Python3_EXECUTABLE}" -c "import spam3; spam3.system(\"cd\")")
--- /dev/null
+
+#include <Python.h>
+
+static PyObject* spam_system(PyObject* self, PyObject* args)
+{
+ const char* command;
+ int sts;
+
+ if (!PyArg_ParseTuple(args, "s", &command))
+ return NULL;
+ sts = system(command);
+ /* return PyLong_FromLong(sts); */
+ return Py_BuildValue("i", sts);
+}
+
+static PyMethodDef SpamMethods[] = {
+ { "system", spam_system, METH_VARARGS, "Execute a shell command." },
+ { NULL, NULL, 0, NULL } /* Sentinel */
+};
+
+#if defined(PYTHON2)
+PyMODINIT_FUNC initspam2(void)
+{
+ (void)Py_InitModule("spam2", SpamMethods);
+}
+#endif
+
+#if defined(PYTHON3)
+static struct PyModuleDef spammodule = {
+ PyModuleDef_HEAD_INIT, "spam3", /* name of module */
+ NULL, /* module documentation, may be NULL */
+ -1, /* size of per-interpreter state of the module,
+ or -1 if the module keeps state in global variables. */
+ SpamMethods
+};
+
+PyMODINIT_FUNC PyInit_spam3(void)
+{
+ return PyModule_Create(&spammodule);
+}
+#endif
#ifndef FOO_1
-#error "foo1.h not included by /FI"
+# error "foo1.h not included by /FI"
#endif
#ifndef FOO_2
-#error "foo2.h not included by /FI"
+# error "foo2.h not included by /FI"
#endif
int main(void)
{
-add_executable(submod main.f90 provide.f90)
+# The program units in this file consist of a module/submodule
+# tree represented by the following graph:
+#
+# parent
+# |
+# / \
+# / \
+# child sibling
+# |
+# grandchild
+# |
+# GreatGrandChild
+#
+# where the parent node is a module and all other nodes are submodules.
+
+add_executable(submod
+ main.f90
+ parent.f90
+ child.f90
+ grandchild.f90
+ greatgrandchild.f90
+ sibling.f90
+ )
--- /dev/null
+! Test the notation for a 1st-generation direct
+! descendant of a parent module
+submodule ( parent ) child
+ implicit none
+contains
+ module function child_function() result(child_stuff)
+ logical :: child_stuff
+ child_stuff=.true.
+ end function
+end submodule child
--- /dev/null
+! Test the notation for an Nth-generation descendant
+! for N>1, which necessitates the colon.
+submodule ( parent : child ) grandchild
+contains
+ module subroutine grandchild_subroutine()
+ print *,"Test passed."
+ end subroutine
+end submodule grandchild
--- /dev/null
+! Test the notation for an Nth-generation descendant
+! for N>1, which necessitates the colon.
+submodule ( parent : grandchild ) GreatGrandChild
+contains
+ module subroutine GreatGrandChild_subroutine()
+ print *,"Test passed."
+ end subroutine
+end submodule GreatGrandChild
program main
use parent, only : child_function,grandchild_subroutine
+ use parent, only : sibling_function,GreatGrandChild_subroutine
implicit none
if (child_function()) call grandchild_subroutine
+ if (sibling_function()) call GreatGrandChild_subroutine
end program
--- /dev/null
+module parent
+ implicit none
+
+ interface
+
+ ! Test Fortran 2008 "module function" syntax
+ module function child_function() result(child_stuff)
+ logical :: child_stuff
+ end function
+ module function sibling_function() result(sibling_stuff)
+ logical :: sibling_stuff
+ end function
+
+ ! Test Fortran 2008 "module subroutine" syntax
+ module subroutine grandchild_subroutine()
+ end subroutine
+ module subroutine GreatGrandChild_subroutine()
+ end subroutine
+
+ end interface
+
+end module parent
+++ /dev/null
-! The program units in this file consist of a
-! module/submodule tree represented by the following
-! graph:
-!
-! parent
-! |
-! / \
-! / \
-! child sibling
-! |
-! grandchild
-!
-! where the parent node is a module and all other
-! nodes are submodules.
-
-module parent
- implicit none
-
- interface
-
- ! Test Fortran 2008 "module function" syntax
- module function child_function() result(child_stuff)
- logical :: child_stuff
- end function
-
- ! Test Fortran 2008 "module subroutine" syntax
- module subroutine grandchild_subroutine()
- end subroutine
-
- end interface
-
-end module parent
-
-! Test the notation for a 1st-generation direct
-! descendant of a parent module
-submodule ( parent ) child
- implicit none
-contains
- module function child_function() result(child_stuff)
- logical :: child_stuff
- child_stuff=.true.
- end function
-end submodule child
-
-! Empty submodule for checking disambiguation of
-! nodes at the same vertical level in the tree
-submodule ( parent ) sibling
-end submodule sibling
-
-! Test the notation for an Nth-generation descendant
-! for N>1, which necessitates the colon.
-submodule ( parent : child ) grandchild
-contains
- module subroutine grandchild_subroutine()
- print *,"Test passed."
- end subroutine
-end submodule grandchild
--- /dev/null
+! Empty submodule for checking disambiguation of
+! nodes at the same vertical level in the tree
+submodule ( parent ) sibling
+contains
+ module function sibling_function() result(sibling_stuff)
+ logical :: sibling_stuff
+ sibling_stuff=.true.
+ end function
+end submodule sibling
#include <stdio.h>
#if defined(_WIN32) && defined(foo_EXPORTS)
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
CM_TEST_LIB_EXPORT void foo()
{
#ifdef Type_Is_
-#if !Result
-#error Result should be 1 in WARN mode
-#endif
+# if !Result
+# error Result should be 1 in WARN mode
+# endif
#endif
#ifdef Type_Is_NEW
-#if Result
-#error Result should be 0 in NEW mode
-#endif
+# if Result
+# error Result should be 0 in NEW mode
+# endif
#endif
#ifdef Type_Is_OLD
-#if !Result
-#error Result should be 1 in OLD mode
-#endif
+# if !Result
+# error Result should be 1 in OLD mode
+# endif
#endif
#if !defined(Type_Is_) && !defined(Type_Is_OLD) && !defined(Type_Is_NEW)
-#error No expected definition present
+# error No expected definition present
#endif
void foo(void)
-Dtest_strequal_angle_r_comma=$<STREQUAL:$<ANGLE-R>,$<COMMA>>
-Dtest_strequal_both_empty=$<STREQUAL:,>
-Dtest_strequal_one_empty=$<STREQUAL:something,>
+ -Dtest_inlist_true=$<IN_LIST:a,a$<SEMICOLON>b>
+ -Dtest_inlist_false=$<IN_LIST:c,a$<SEMICOLON>b>
+ -Dtest_inlist_empty_1=$<IN_LIST:a,>
+ -Dtest_inlist_empty_2=$<IN_LIST:,a>
+ -Dtest_inlist_empty_3=$<IN_LIST:,>
-Dtest_angle_r=$<ANGLE-R>
-Dtest_comma=$<COMMA>
-Dtest_semicolon=$<SEMICOLON>
check(test_strequal_angle_r_comma "0")
check(test_strequal_both_empty "1")
check(test_strequal_one_empty "0")
+check(test_inlist_true "1")
+check(test_inlist_false "0")
+check(test_inlist_empty_1 "0")
+check(test_inlist_empty_2 "0")
+check(test_inlist_empty_3 "0")
check(test_angle_r ">")
check(test_comma ",")
check(test_semicolon ";")
#include <stdlib.h>
#ifdef _WIN32
-#include <direct.h>
-#define getcurdir _getcwd
+# include <direct.h>
+# define getcurdir _getcwd
#else
-#include <unistd.h>
-#define getcurdir getcwd
+# include <unistd.h>
+# define getcurdir getcwd
#endif
int main(int argc, char* argv[])
#include "cmp0021.h"
#ifndef CMP0021_DEFINE
-#error Expected CMP0021_DEFINE
+# error Expected CMP0021_DEFINE
#endif
int main(int, char**)
PROPERTIES COMPILE_FLAGS "-ITarProp")
endif()
+add_library(ordertest ordertest.cpp)
+target_include_directories(ordertest SYSTEM PUBLIC SystemIncludeDirectories/systemlib)
+target_include_directories(ordertest PUBLIC SystemIncludeDirectories/userlib)
+
add_subdirectory(StandardIncludeDirectories)
add_subdirectory(TargetIncludeDirectories)
--- /dev/null
+#error ordertest.h includes from systemlib
--- /dev/null
+/* empty file */
--- /dev/null
+#include "ordertest.h"
#ifndef IFACE_DEFINE
-#error Expected IFACE_DEFINE
+# error Expected IFACE_DEFINE
#endif
#include "iface_header.h"
#ifndef IFACE_HEADER_SRCDIR
-#error Expected IFACE_HEADER_SRCDIR
+# error Expected IFACE_HEADER_SRCDIR
#endif
#include "iface_header_builddir.h"
#ifndef IFACE_HEADER_BUILDDIR
-#error Expected IFACE_HEADER_BUILDDIR
+# error Expected IFACE_HEADER_BUILDDIR
#endif
extern int obj();
#ifdef DEBUG_MODE
-#ifndef SPECIAL_MODE
-#error Special configuration should be mapped to debug configuration.
-#endif
+# ifndef SPECIAL_MODE
+# error Special configuration should be mapped to debug configuration.
+# endif
#else
-#ifdef SPECIAL_MODE
-#error Special configuration should not be enabled if not debug configuration
-#endif
+# ifdef SPECIAL_MODE
+# error Special configuration should not be enabled if not debug configuration
+# endif
#endif
int main(int, char**)
#ifndef SHAREDLIB_DEFINE
-#error Expected SHAREDLIB_DEFINE
+# error Expected SHAREDLIB_DEFINE
#endif
#ifndef SHAREDDEPENDLIB_DEFINE
-#error Expected SHAREDDEPENDLIB_DEFINE
+# error Expected SHAREDDEPENDLIB_DEFINE
#endif
-#include "sharedlib.h"
#include "shareddependlib.h"
+#include "sharedlib.h"
int main(int, char**)
{
#ifdef FOO_LIBRARY
-#error Unexpected FOO_LIBRARY
+# error Unexpected FOO_LIBRARY
#endif
#ifdef BAR_LIBRARY
-#error Unexpected BAR_LIBRARY
+# error Unexpected BAR_LIBRARY
#endif
#include "bang.h"
#ifdef FOO_LIBRARY
-#error Unexpected FOO_LIBRARY
+# error Unexpected FOO_LIBRARY
#endif
#ifdef BAR_USE_BANG
-#ifndef BANG_LIBRARY
-#error Expected BANG_LIBRARY
-#endif
-#include "bang.h"
+# ifndef BANG_LIBRARY
+# error Expected BANG_LIBRARY
+# endif
+# include "bang.h"
#else
-#ifdef BANG_LIBRARY
-#error Unexpected BANG_LIBRARY
-#endif
+# ifdef BANG_LIBRARY
+# error Unexpected BANG_LIBRARY
+# endif
#endif
#include "bar.h"
#ifdef BAR_LIBRARY
-#error Unexpected BAR_LIBRARY
+# error Unexpected BAR_LIBRARY
#endif
#ifdef BANG_LIBRARY
-#error Unexpected BANG_LIBRARY
+# error Unexpected BANG_LIBRARY
#endif
#include "foo.h"
#ifndef FOO_LIBRARY
-#error Expected FOO_LIBRARY
+# error Expected FOO_LIBRARY
#endif
#ifndef BAR_LIBRARY
-#error Expected BAR_LIBRARY
+# error Expected BAR_LIBRARY
#endif
#ifdef BANG_LIBRARY
-#error Unexpected BANG_LIBRARY
+# error Unexpected BANG_LIBRARY
#endif
#ifdef ZOT_LIBRARY
-#error Unexpected ZOT_LIBRARY
+# error Unexpected ZOT_LIBRARY
#endif
#include "zot.h"
#ifdef _WIN32
-#define JUMP_IMPORT __declspec(dllimport)
+# define JUMP_IMPORT __declspec(dllimport)
#else
-#define JUMP_IMPORT extern
+# define JUMP_IMPORT extern
#endif
extern int jumpStatic();
#ifdef _WIN32
-#define JUMP_EXPORT __declspec(dllexport)
+# define JUMP_EXPORT __declspec(dllexport)
#else
-#define JUMP_EXPORT
+# define JUMP_EXPORT
#endif
JUMP_EXPORT int jumpShared()
/* Intel compiler does not reject bad flags or objects! */
#if defined(__INTEL_COMPILER)
-#error BADFLAG
+# error BADFLAG
#endif
/* Intel compiler does not reject bad flags or objects! */
#if defined(__INTEL_COMPILER)
-#error BADFLAG
+# error BADFLAG
#endif
#include "ChildFrm.h"
#ifdef _DEBUG
-#define new DEBUG_NEW
+# define new DEBUG_NEW
#endif
// CChildFrame
#include "MainFrm.h"
#ifdef _DEBUG
-#define new DEBUG_NEW
+# define new DEBUG_NEW
#endif
// CMainFrame
static UINT indicators[] = {
ID_SEPARATOR, // status line indicator
- ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL,
+ ID_INDICATOR_CAPS,
+ ID_INDICATOR_NUM,
+ ID_INDICATOR_SCRL,
};
// CMainFrame construction/destruction
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
- if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE |
- CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS |
- CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
+ if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT,
+ WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER |
+ CBRS_TOOLTIPS | CBRS_FLYBY |
+ CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) {
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 130
-#define _APS_NEXT_CONTROL_VALUE 1000
-#define _APS_NEXT_SYMED_VALUE 101
-#define _APS_NEXT_COMMAND_VALUE 32771
-#endif
+# ifndef APSTUDIO_READONLY_SYMBOLS
+# define _APS_NEXT_RESOURCE_VALUE 130
+# define _APS_NEXT_CONTROL_VALUE 1000
+# define _APS_NEXT_SYMED_VALUE 101
+# define _APS_NEXT_COMMAND_VALUE 32771
+# endif
#endif
#include "mfc1View.h"
#ifdef _DEBUG
-#define new DEBUG_NEW
+# define new DEBUG_NEW
#endif
// Cmfc1App
#pragma once
#ifndef __AFXWIN_H__
-#error include 'stdafx.h' before including this file for PCH
+# error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
#include "mfc1Doc.h"
#ifdef _DEBUG
-#define new DEBUG_NEW
+# define new DEBUG_NEW
#endif
// Cmfc1Doc
#include "mfc1View.h"
#ifdef _DEBUG
-#define new DEBUG_NEW
+# define new DEBUG_NEW
#endif
// Cmfc1View
#pragma once
#ifndef VC_EXTRALEAN
-#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+# define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#endif
// See http://msdn.microsoft.com/en-us/library/6sehtctf.aspx for more info
// platforms.
#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4
// or later.
-#if _MSC_VER < 1600
-#define WINVER \
- 0x0400 // Change this to the appropriate value to target Windows 98 and
- // Windows 2000 or later.
-#else
-#define WINVER 0x0501 // Target Windows XP and later with VS 10 and later
-#endif
+# if _MSC_VER < 1600
+# define WINVER \
+ 0x0400 // Change this to the appropriate value to target Windows 98 and
+ // Windows 2000 or later.
+# else
+# define WINVER 0x0501 // Target Windows XP and later with VS 10 and later
+# endif
#endif
#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or
// later.
-#if _MSC_VER < 1600
-#define _WIN32_WINNT \
- 0x0400 // Change this to the appropriate value to target Windows 98 and
- // Windows 2000 or later.
-#else
-#define _WIN32_WINNT 0x0501 // Target Windows XP and later with VS 10 and later
-#endif
+# if _MSC_VER < 1600
+# define _WIN32_WINNT \
+ 0x0400 // Change this to the appropriate value to target Windows 98 and
+ // Windows 2000 or later.
+# else
+# define _WIN32_WINNT \
+ 0x0501 // Target Windows XP and later with VS 10 and later
+# endif
#endif
#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or
// later.
-#if _MSC_VER < 1600
-#define _WIN32_WINDOWS \
- 0x0410 // Change this to the appropriate value to target Windows Me or later.
-#endif
+# if _MSC_VER < 1600
+# define _WIN32_WINDOWS \
+ 0x0410 // Change this to the appropriate value to target Windows Me or
+ // later.
+# endif
#endif
#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later.
-#if _MSC_VER < 1600
-#define _WIN32_IE \
- 0x0400 // Change this to the appropriate value to target IE 5.0 or later.
-#endif
+# if _MSC_VER < 1600
+# define _WIN32_IE \
+ 0x0400 // Change this to the appropriate value to target IE 5.0 or later.
+# endif
#endif
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
-#include <afxcmn.h> // MFC support for Windows Common Controls
-#endif // _AFX_NO_AFXCMN_SUPPORT
+# include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
#define framework_h
#ifdef WIN32
-#ifdef framework_EXPORTS
-#define FRAMEWORK_EXPORT __declspec(dllexport)
+# ifdef framework_EXPORTS
+# define FRAMEWORK_EXPORT __declspec(dllexport)
+# else
+# define FRAMEWORK_EXPORT __declspec(dllimport)
+# endif
#else
-#define FRAMEWORK_EXPORT __declspec(dllimport)
-#endif
-#else
-#define FRAMEWORK_EXPORT
+# define FRAMEWORK_EXPORT
#endif
void FRAMEWORK_EXPORT framework();
#define framework2_h
#ifdef WIN32
-#ifdef framework2_EXPORTS
-#define FRAMEWORK2_EXPORT __declspec(dllexport)
+# ifdef framework2_EXPORTS
+# define FRAMEWORK2_EXPORT __declspec(dllexport)
+# else
+# define FRAMEWORK2_EXPORT __declspec(dllimport)
+# endif
#else
-#define FRAMEWORK2_EXPORT __declspec(dllimport)
-#endif
-#else
-#define FRAMEWORK2_EXPORT
+# define FRAMEWORK2_EXPORT
#endif
void FRAMEWORK2_EXPORT framework2();
#define shared_h
#ifdef WIN32
-#ifdef shared_EXPORTS
-#define SHARED_EXPORT __declspec(dllexport)
+# ifdef shared_EXPORTS
+# define SHARED_EXPORT __declspec(dllexport)
+# else
+# define SHARED_EXPORT __declspec(dllimport)
+# endif
#else
-#define SHARED_EXPORT __declspec(dllimport)
-#endif
-#else
-#define SHARED_EXPORT
+# define SHARED_EXPORT
#endif
void SHARED_EXPORT shared();
#include "somestruct.h"
#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+# include <sys/types.h>
#endif
#ifdef HAVE_STDINT_H
-#include <stdint.h>
+# include <stdint.h>
#endif
#ifdef HAVE_STDDEF_H
-#include <stddef.h>
+# include <stddef.h>
#endif
#include <stdio.h>
/* long long */
#if defined(SIZEOF_LONG_LONG)
CHECK(long long, SIZEOF_LONG_LONG);
-#if !defined(HAVE_SIZEOF_LONG_LONG)
+# if !defined(HAVE_SIZEOF_LONG_LONG)
NODEF(HAVE_SIZEOF_LONG_LONG);
-#endif
+# endif
#endif
/* __int64 */
#if defined(SIZEOF___INT64)
CHECK(__int64, SIZEOF___INT64);
-#if !defined(HAVE_SIZEOF___INT64)
+# if !defined(HAVE_SIZEOF___INT64)
NODEF(HAVE_SIZEOF___INT64);
-#endif
+# endif
#elif defined(HAVE_SIZEOF___INT64)
NODEF(SIZEOF___INT64);
#endif
/* ssize_t */
#if defined(SIZEOF_SSIZE_T)
CHECK(ssize_t, SIZEOF_SSIZE_T);
-#if !defined(HAVE_SIZEOF_SSIZE_T)
+# if !defined(HAVE_SIZEOF_SSIZE_T)
NODEF(HAVE_SIZEOF_SSIZE_T);
-#endif
+# endif
#elif defined(HAVE_SIZEOF_SSIZE_T)
NODEF(SIZEOF_SSIZE_T);
#endif
#if defined(SIZEOF_STRUCTMEMBER_INT)
CHECK(x.someint, SIZEOF_STRUCTMEMBER_INT);
CHECK(x.someint, SIZEOF_INT);
-#if !defined(HAVE_SIZEOF_STRUCTMEMBER_INT)
+# if !defined(HAVE_SIZEOF_STRUCTMEMBER_INT)
NODEF(HAVE_SIZEOF_STRUCTMEMBER_INT);
-#endif
+# endif
#elif defined(HAVE_SIZEOF_STRUCTMEMBER_INT)
NODEF(SIZEOF_STRUCTMEMBER_INT);
#endif
#if defined(SIZEOF_STRUCTMEMBER_PTR)
CHECK(x.someptr, SIZEOF_STRUCTMEMBER_PTR);
CHECK(x.someptr, SIZEOF_DATA_PTR);
-#if !defined(HAVE_SIZEOF_STRUCTMEMBER_PTR)
+# if !defined(HAVE_SIZEOF_STRUCTMEMBER_PTR)
NODEF(HAVE_SIZEOF_STRUCTMEMBER_PTR);
-#endif
+# endif
#elif defined(HAVE_SIZEOF_STRUCTMEMBER_PTR)
NODEF(SIZEOF_STRUCTMEMBER_PTR);
#endif
#if defined(SIZEOF_STRUCTMEMBER_CHAR)
CHECK(x.somechar, SIZEOF_STRUCTMEMBER_CHAR);
CHECK(x.somechar, SIZEOF_CHAR);
-#if !defined(HAVE_SIZEOF_STRUCTMEMBER_CHAR)
+# if !defined(HAVE_SIZEOF_STRUCTMEMBER_CHAR)
NODEF(HAVE_SIZEOF_STRUCTMEMBER_CHAR);
-#endif
+# endif
#elif defined(HAVE_SIZEOF_STRUCTMEMBER_CHAR)
NODEF(SIZEOF_STRUCTMEMBER_CHAR);
#endif
#include "someclass.hxx"
#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+# include <sys/types.h>
#endif
#ifdef HAVE_STDINT_H
-#include <stdint.h>
+# include <stdint.h>
#endif
#ifdef HAVE_STDDEF_H
-#include <stddef.h>
+# include <stddef.h>
#endif
#include <stdio.h>
/* long long */
#if defined(SIZEOF_LONG_LONG)
CHECK(long long, SIZEOF_LONG_LONG);
-#if !defined(HAVE_SIZEOF_LONG_LONG)
+# if !defined(HAVE_SIZEOF_LONG_LONG)
NODEF(HAVE_SIZEOF_LONG_LONG);
-#endif
+# endif
#endif
/* __int64 */
#if defined(SIZEOF___INT64)
CHECK(__int64, SIZEOF___INT64);
-#if !defined(HAVE_SIZEOF___INT64)
+# if !defined(HAVE_SIZEOF___INT64)
NODEF(HAVE_SIZEOF___INT64);
-#endif
+# endif
#elif defined(HAVE_SIZEOF___INT64)
NODEF(SIZEOF___INT64);
#endif
/* ssize_t */
#if defined(SIZEOF_SSIZE_T)
CHECK(ssize_t, SIZEOF_SSIZE_T);
-#if !defined(HAVE_SIZEOF_SSIZE_T)
+# if !defined(HAVE_SIZEOF_SSIZE_T)
NODEF(HAVE_SIZEOF_SSIZE_T);
-#endif
+# endif
#elif defined(HAVE_SIZEOF_SSIZE_T)
NODEF(SIZEOF_SSIZE_T);
#endif
#if defined(SIZEOF_NS_CLASSMEMBER_INT)
CHECK(y.someint, SIZEOF_NS_CLASSMEMBER_INT);
CHECK(y.someint, SIZEOF_INT);
-#if !defined(HAVE_SIZEOF_NS_CLASSMEMBER_INT)
+# if !defined(HAVE_SIZEOF_NS_CLASSMEMBER_INT)
NODEF(HAVE_SIZEOF_STRUCTMEMBER_INT);
-#endif
+# endif
#elif defined(HAVE_SIZEOF_STRUCTMEMBER_INT)
NODEF(SIZEOF_STRUCTMEMBER_INT);
#endif
#if defined(SIZEOF_NS_CLASSMEMBER_PTR)
CHECK(y.someptr, SIZEOF_NS_CLASSMEMBER_PTR);
CHECK(y.someptr, SIZEOF_DATA_PTR);
-#if !defined(HAVE_SIZEOF_NS_CLASSMEMBER_PTR)
+# if !defined(HAVE_SIZEOF_NS_CLASSMEMBER_PTR)
NODEF(HAVE_SIZEOF_NS_CLASSMEMBER_PTR);
-#endif
+# endif
#elif defined(HAVE_SIZEOF_NS_CLASSMEMBER_PTR)
NODEF(SIZEOF_NS_CLASSMEMBER_PTR);
#endif
#if defined(SIZEOF_NS_CLASSMEMBER_CHAR)
CHECK(y.somechar, SIZEOF_NS_CLASSMEMBER_CHAR);
CHECK(y.somechar, SIZEOF_CHAR);
-#if !defined(HAVE_SIZEOF_NS_CLASSMEMBER_CHAR)
+# if !defined(HAVE_SIZEOF_NS_CLASSMEMBER_CHAR)
NODEF(HAVE_SIZEOF_NS_CLASSMEMBER_CHAR);
-#endif
+# endif
#elif defined(HAVE_SIZEOF_NS_CLASSMEMBER_CHAR)
NODEF(SIZEOF_NS_CLASSMEMBER_CHAR);
#endif
#if defined(SIZEOF_NS_CLASSMEMBER_BOOL)
CHECK(y.somechar, SIZEOF_NS_CLASSMEMBER_BOOL);
CHECK(y.somechar, SIZEOF_BOOL);
-#if !defined(HAVE_SIZEOF_NS_CLASSMEMBER_BOOL)
+# if !defined(HAVE_SIZEOF_NS_CLASSMEMBER_BOOL)
NODEF(HAVE_SIZEOF_NS_CLASSMEMBER_BOOL);
-#endif
+# endif
#elif defined(HAVE_SIZEOF_NS_CLASSMEMBER_BOOL)
NODEF(SIZEOF_NS_CLASSMEMBER_BOOL);
#endif
ExternalData_Add_Test(Data5.A
NAME Data5Check.A
COMMAND ${CMAKE_COMMAND}
- -D Data5=DATA{../Data.dat}
+ -D Data5=DATA{Data5.dat}
-P ${CMAKE_CURRENT_SOURCE_DIR}/Data5Check.cmake
)
ExternalData_Add_Target(Data5.A)
ExternalData_Add_Test(Data5.B
NAME Data5Check.B
COMMAND ${CMAKE_COMMAND}
- -D Data5=DATA{../Data.dat}
+ -D Data5=DATA{Data5.dat}
-P ${CMAKE_CURRENT_SOURCE_DIR}/Data5Check.cmake
)
ExternalData_Add_Target(Data5.B)
ExternalData_Add_Test(Data5.C
NAME Data5Check.C
COMMAND ${CMAKE_COMMAND}
- -D Data5=DATA{../Data.dat}
+ -D Data5=DATA{Data5.dat}
-P ${CMAKE_CURRENT_SOURCE_DIR}/Data5Check.cmake
)
ExternalData_Add_Target(Data5.C)
--- /dev/null
+8c018830e3efa5caf3c7415028335a57
#ifndef HAVE_PACK1
-#error Expected HAVE_PACK1
+# error Expected HAVE_PACK1
#endif
#ifndef HAVE_PACK2
-#error Expected HAVE_PACK2
+# error Expected HAVE_PACK2
#endif
#ifndef HAVE_PACK3
-#error Expected HAVE_PACK3
+# error Expected HAVE_PACK3
#endif
#ifndef HAVE_PACK4
-#error Expected HAVE_PACK4
+# error Expected HAVE_PACK4
#endif
#ifndef HAVE_PACK5
-#error Expected HAVE_PACK5
+# error Expected HAVE_PACK5
#endif
#ifndef HAVE_PACK6
-#error Expected HAVE_PACK6
+# error Expected HAVE_PACK6
#endif
int main(int argc, char** argv)
ALLOW_UNKNOWN_COMPILERS
)
-# intentionally abuse the TEST_NULLPR variable: this will only work
+# intentionally abuse the TEST_NULLPTR variable: this will only work
# with the fallback code.
check_cxx_source_compiles("#include \"${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_allow_unknown.h\"
int main() {\n int i = TEST_NULLPTR;\n return 0; }\n"
if (NOT file_include_works_allow_unknown)
message(SEND_ERROR "Inclusion of ${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_allow_unknown.h was expected to work, but did not.")
endif()
+
+# test for BARE_FEATURES
+
+write_compiler_detection_header(
+ FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection_bare_features.h"
+ PREFIX TEST
+ COMPILERS GNU Clang AppleClang MSVC SunPro Intel
+ VERSION 3.1
+ BARE_FEATURES cxx_nullptr cxx_override cxx_noexcept cxx_final
+)
+
+add_executable(WriteCompilerDetectionHeaderBareFeatures main_bare.cpp)
+set_property(TARGET WriteCompilerDetectionHeaderBareFeatures PROPERTY CXX_STANDARD 11)
JOIN(EXPECTED_COMPILER_, FEATURE))
#if !CHECK(CXX_DELEGATING_CONSTRUCTORS)
-#error cxx_delegating_constructors expected availability did not match.
+# error cxx_delegating_constructors expected availability did not match.
#endif
#if !CHECK(CXX_VARIADIC_TEMPLATES)
-#error cxx_variadic_templates expected availability did not match.
+# error cxx_variadic_templates expected availability did not match.
#endif
#if !CHECK(VERSION_MAJOR)
-#error Compiler major version did not match.
+# error Compiler major version did not match.
#endif
#if !CHECK(VERSION_MINOR)
-#error Compiler minor version did not match.
+# error Compiler minor version did not match.
#endif
#if !CHECK(VERSION_PATCH)
-#error Compiler patch version did not match.
+# error Compiler patch version did not match.
#endif
#if !defined(TEST_COMPILER_C_FUNCTION_PROTOTYPES) || \
!TEST_COMPILER_C_FUNCTION_PROTOTYPES
-#error Expected TEST_COMPILER_C_FUNCTION_PROTOTYPES
+# error Expected TEST_COMPILER_C_FUNCTION_PROTOTYPES
#endif
#if !EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES
-#error Expected EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES
+# error Expected EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES
#endif
#if !defined(TEST_COMPILER_C_RESTRICT) || !TEST_COMPILER_C_RESTRICT
-#if EXPECTED_COMPILER_C_RESTRICT
-#error Expected TEST_COMPILER_C_RESTRICT
-#endif
+# if EXPECTED_COMPILER_C_RESTRICT
+# error Expected TEST_COMPILER_C_RESTRICT
+# endif
#else
-#if !EXPECTED_COMPILER_C_RESTRICT
-#error Expect no TEST_COMPILER_C_RESTRICT
-#endif
+# if !EXPECTED_COMPILER_C_RESTRICT
+# error Expect no TEST_COMPILER_C_RESTRICT
+# endif
#endif
#ifdef TEST_COMPILER_CXX_STATIC_ASSERT
-#error Expect no CXX features defined
+# error Expect no CXX features defined
#endif
int main()
#include "compile_tests.h"
#ifdef TEST_COMPILER_C_STATIC_ASSERT
-#error Expect no C features defined
+# error Expect no C features defined
#endif
TEST_STATIC_ASSERT(true);
--- /dev/null
+#include "test_compiler_detection_bare_features.h"
+
+class base
+{
+public:
+ virtual ~base() {}
+ virtual void baz() = 0;
+};
+
+class foo final
+{
+public:
+ virtual ~foo() {}
+ char* bar;
+ void baz() noexcept override { bar = nullptr; }
+};
+
+int main()
+{
+ foo f;
+
+ return 0;
+}
#if !defined(MULTI_COMPILER_C_FUNCTION_PROTOTYPES) || \
!MULTI_COMPILER_C_FUNCTION_PROTOTYPES
-#error Expected MULTI_COMPILER_C_FUNCTION_PROTOTYPES
+# error Expected MULTI_COMPILER_C_FUNCTION_PROTOTYPES
#endif
#if !EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES
-#error Expected EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES
+# error Expected EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES
#endif
#if !defined(MULTI_COMPILER_C_RESTRICT) || !MULTI_COMPILER_C_RESTRICT
-#if EXPECTED_COMPILER_C_RESTRICT
-#error Expected MULTI_COMPILER_C_RESTRICT
-#endif
+# if EXPECTED_COMPILER_C_RESTRICT
+# error Expected MULTI_COMPILER_C_RESTRICT
+# endif
#else
-#if !EXPECTED_COMPILER_C_RESTRICT
-#error Expect no MULTI_COMPILER_C_RESTRICT
-#endif
+# if !EXPECTED_COMPILER_C_RESTRICT
+# error Expect no MULTI_COMPILER_C_RESTRICT
+# endif
#endif
#ifdef MULTI_COMPILER_CXX_STATIC_ASSERT
-#error Expect no CXX features defined
+# error Expect no CXX features defined
#endif
int main()
#include "compile_tests.h"
#ifdef MULTI_COMPILER_C_STATIC_ASSERT
-#error Expect no C features defined
+# error Expect no C features defined
#endif
MULTI_STATIC_ASSERT(true);
#ifdef __WATCOMC__
-#define MODULE_CCONV __cdecl
+# define MODULE_CCONV __cdecl
#else
-#define MODULE_CCONV
+# define MODULE_CCONV
#endif
int __declspec(dllimport) example_exe_function(void);
#include "libcxx1.h"
#ifdef TEST_FLAG_1
-#ifdef TEST_FLAG_2
+# ifdef TEST_FLAG_2
float LibCxx1Class::Method()
{
return 2.0;
}
-#endif
+# endif
#endif
{
public:
#ifdef TEST_FLAG_1
-#ifdef TEST_FLAG_2
+# ifdef TEST_FLAG_2
static float Method();
-#endif
+# endif
#endif
};
#ifndef A_DEF
-#error "A_DEF not defined"
+# error "A_DEF not defined"
#endif
#ifdef B_DEF
-#error "B_DEF must not be defined"
+# error "B_DEF must not be defined"
#endif
#ifdef A_DEF
-#error "A_DEF must not be defined"
+# error "A_DEF must not be defined"
#endif
#ifndef B_DEF
-#error "B_DEF not defined"
+# error "B_DEF not defined"
#endif
#if defined(_WIN32) && defined(Bexport)
-#define EXPORT_B __declspec(dllexport)
+# define EXPORT_B __declspec(dllexport)
#else
-#define EXPORT_B
+# define EXPORT_B
#endif
#if defined(_WIN32) && defined(SHARED_B)
-#define IMPORT_B __declspec(dllimport)
+# define IMPORT_B __declspec(dllimport)
#else
-#define IMPORT_B
+# define IMPORT_B
#endif
#if defined(_WIN32) && defined(Cshared_EXPORTS)
-#define EXPORT_C __declspec(dllexport)
+# define EXPORT_C __declspec(dllexport)
#else
-#define EXPORT_C
+# define EXPORT_C
#endif
extern int a1(void);
#if defined(_WIN32) && defined(SHARED_C)
-#define IMPORT_C __declspec(dllimport)
+# define IMPORT_C __declspec(dllimport)
#else
-#define IMPORT_C
+# define IMPORT_C
#endif
extern IMPORT_C int b1(void);
extern IMPORT_C int b2(void);
# Use a separate variable for computation.
set(MAXPATH "${CMAKE_OBJECT_PATH_MAX}")
- # VS8 adds "OutOfSource/SubDir/OutOfSourceSubdir/../../../" to the
+ # VS adds "OutOfSource/SubDir/OutOfSourceSubdir/../../../" to the
# path of the source file for no good reason. Reduce the length
# limit by 46 characters to account for it. It should still be long
# enough to require special object file name conversion.
- if(${CMAKE_GENERATOR} MATCHES "Visual Studio (8|10)")
+ if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
math(EXPR MAXPATH "${MAXPATH} - 46")
endif()
#ifdef _WIN32
-#ifdef testlib_EXPORTS
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# ifdef testlib_EXPORTS
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# else
+# define CM_TEST_LIB_EXPORT __declspec(dllimport)
+# endif
#else
-#define CM_TEST_LIB_EXPORT __declspec(dllimport)
-#endif
-#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
CM_TEST_LIB_EXPORT float TestLib();
add_library(mylibA SHARED mylibA.c)
set_target_properties(mylibA PROPERTIES
PDB_NAME "mylibA_Special"
- PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibA_PDB"
+ PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibA_PDB/$<CONFIG>"
)
list(APPEND my_targets mylibA)
if(NOT pdb_dir)
set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR})
endif()
- list(APPEND pdbs ${pdb_dir}/${CMAKE_CFG_INTDIR}/${pdb_name}.pdb)
+ if (pdb_dir MATCHES "\\$<.*>")
+ # Skip per-configuration subdirectory if the value contained
+ # a generator expression.
+ list(APPEND pdbs ${pdb_dir}/${pdb_name}.pdb)
+ else()
+ list(APPEND pdbs ${pdb_dir}/${CMAKE_CFG_INTDIR}/${pdb_name}.pdb)
+ endif()
endforeach()
add_custom_target(check_pdbs ALL VERBATIM
COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIGURATION> "-Dpdbs=${pdbs}"
#define pcShared_h
#ifdef _WIN32
-#ifdef pcShared_EXPORTS
-#define PC_EXPORT __declspec(dllexport)
+# ifdef pcShared_EXPORTS
+# define PC_EXPORT __declspec(dllexport)
+# else
+# define PC_EXPORT __declspec(dllimport)
+# endif
#else
-#define PC_EXPORT __declspec(dllimport)
-#endif
-#else
-#define PC_EXPORT
+# define PC_EXPORT
#endif
PC_EXPORT const char* pcShared(void);
#define example_h
#if defined(_WIN32) || defined(__CYGWIN__)
-#if defined(example_exe_EXPORTS)
-#define EXAMPLE_EXPORT __declspec(dllexport)
+# if defined(example_exe_EXPORTS)
+# define EXAMPLE_EXPORT __declspec(dllexport)
+# else
+# define EXAMPLE_EXPORT __declspec(dllimport)
+# endif
#else
-#define EXAMPLE_EXPORT __declspec(dllimport)
-#endif
-#else
-#define EXAMPLE_EXPORT
+# define EXAMPLE_EXPORT
#endif
#ifdef __cplusplus
}
#ifdef CMAKE_INTDIR
-#define CONFIG_DIR "/" CMAKE_INTDIR
+# define CONFIG_DIR "/" CMAKE_INTDIR
#else
-#define CONFIG_DIR ""
+# define CONFIG_DIR ""
#endif
int main()
#include <stdio.h>
#if defined(_WIN32)
-#define MODULE_EXPORT __declspec(dllexport)
+# define MODULE_EXPORT __declspec(dllexport)
#else
-#define MODULE_EXPORT
+# define MODULE_EXPORT
#endif
#ifdef __WATCOMC__
-#define MODULE_CCONV __cdecl
+# define MODULE_CCONV __cdecl
#else
-#define MODULE_CCONV
+# define MODULE_CCONV
#endif
MODULE_EXPORT int MODULE_CCONV example_mod_1_function(int n)
# CMP0002 should be changed when this function is invoked
cmake_policy(GET CMP0002 cmp)
check(CMP0002 "OLD" "${cmp}")
+
+ # The undocumented PARENT_SCOPE option sees the caller's setting.
+ cmake_policy(GET CMP0002 cmp PARENT_SCOPE)
+ check(CMP0002 "NEW" "${cmp}")
endfunction()
# Unset CMP0002
cmake_policy(GET CMP0002 cmp)
check(CMP0002 "" "${cmp}")
+ # The undocumented PARENT_SCOPE option sees the caller's setting.
+ cmake_policy(GET CMP0002 cmp PARENT_SCOPE)
+ check(CMP0002 "NEW" "${cmp}")
+
# Setting the policy should work here and also in the caller.
cmake_policy(SET CMP0002 OLD)
cmake_policy(GET CMP0002 cmp)
#ifndef foo_h
-#error "Precompiled header foo_precompiled.h has not been loaded."
+# error "Precompiled header foo_precompiled.h has not been loaded."
#endif
int main()
#ifndef foo_h
-#include "foo.h"
-#error "Precompiled header foo_precompiled.h has not been loaded."
+# include "foo.h"
+# error "Precompiled header foo_precompiled.h has not been loaded."
#endif
int foo()
}
}
#ifdef NDEBUG
-#ifdef FILE_DEF_DEBUG
+# ifdef FILE_DEF_DEBUG
{
fprintf(stderr, "FILE_DEF_DEBUG should not be defined in C\n");
result = 0;
}
-#endif
-#ifdef TARGET_DEF_DEBUG
+# endif
+# ifdef TARGET_DEF_DEBUG
{
fprintf(stderr, "TARGET_DEF_DEBUG should not be defined in C\n");
result = 0;
}
-#endif
-#ifdef DIRECTORY_DEF_DEBUG
+# endif
+# ifdef DIRECTORY_DEF_DEBUG
{
fprintf(stderr, "DIRECTORY_DEF_DEBUG should not be defined in C\n");
result = 0;
}
-#endif
-#ifndef FILE_DEF_RELEASE
-#ifndef PREPROCESS_XCODE
+# endif
+# ifndef FILE_DEF_RELEASE
+# ifndef PREPROCESS_XCODE
{
fprintf(stderr, "FILE_DEF_RELEASE should be defined in C\n");
result = 0;
}
-#endif
-#endif
-#ifndef TARGET_DEF_RELEASE
+# endif
+# endif
+# ifndef TARGET_DEF_RELEASE
{
fprintf(stderr, "TARGET_DEF_RELEASE should be defined in C\n");
result = 0;
}
-#endif
-#ifndef DIRECTORY_DEF_RELEASE
+# endif
+# ifndef DIRECTORY_DEF_RELEASE
{
fprintf(stderr, "DIRECTORY_DEF_RELEASE should be defined in C\n");
result = 0;
}
-#endif
+# endif
#endif
#ifdef PREPROCESS_DEBUG
-#ifndef FILE_DEF_DEBUG
-#ifndef PREPROCESS_XCODE
+# ifndef FILE_DEF_DEBUG
+# ifndef PREPROCESS_XCODE
{
fprintf(stderr, "FILE_DEF_DEBUG should be defined in C\n");
result = 0;
}
-#endif
-#endif
-#ifndef TARGET_DEF_DEBUG
+# endif
+# endif
+# ifndef TARGET_DEF_DEBUG
{
fprintf(stderr, "TARGET_DEF_DEBUG should be defined in C\n");
result = 0;
}
-#endif
-#ifndef DIRECTORY_DEF_DEBUG
+# endif
+# ifndef DIRECTORY_DEF_DEBUG
{
fprintf(stderr, "DIRECTORY_DEF_DEBUG should be defined in C\n");
result = 0;
}
-#endif
-#ifdef FILE_DEF_RELEASE
+# endif
+# ifdef FILE_DEF_RELEASE
{
fprintf(stderr, "FILE_DEF_RELEASE should not be defined in C\n");
result = 0;
}
-#endif
-#ifdef TARGET_DEF_RELEASE
+# endif
+# ifdef TARGET_DEF_RELEASE
{
fprintf(stderr, "TARGET_DEF_RELEASE should not be defined in C\n");
result = 0;
}
-#endif
-#ifdef DIRECTORY_DEF_RELEASE
+# endif
+# ifdef DIRECTORY_DEF_RELEASE
{
fprintf(stderr, "DIRECTORY_DEF_RELEASE should not be defined in C\n");
result = 0;
}
-#endif
+# endif
#endif
#if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG)
-#if !defined(FILE_DEF_DEBUG) || !defined(TARGET_DEF_DEBUG)
-#ifndef PREPROCESS_XCODE
+# if !defined(FILE_DEF_DEBUG) || !defined(TARGET_DEF_DEBUG)
+# ifndef PREPROCESS_XCODE
{
fprintf(stderr, "FILE_DEF_DEBUG and TARGET_DEF_DEBUG inconsistent in C\n");
result = 0;
}
-#endif
-#endif
-#if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE)
+# endif
+# endif
+# if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE)
{
fprintf(stderr, "DEBUG and RELEASE definitions inconsistent in C\n");
result = 0;
}
-#endif
+# endif
#endif
#if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE)
-#if !defined(FILE_DEF_RELEASE) || !defined(TARGET_DEF_RELEASE)
-#ifndef PREPROCESS_XCODE
+# if !defined(FILE_DEF_RELEASE) || !defined(TARGET_DEF_RELEASE)
+# ifndef PREPROCESS_XCODE
{
fprintf(stderr,
"FILE_DEF_RELEASE and TARGET_DEF_RELEASE inconsistent in C\n");
result = 0;
}
-#endif
-#endif
-#if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG)
+# endif
+# endif
+# if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG)
{
fprintf(stderr, "RELEASE and DEBUG definitions inconsistent in C\n");
result = 0;
}
-#endif
+# endif
#endif
#ifndef FILE_PATH_DEF
{
}
}
#ifdef NDEBUG
-#ifdef FILE_DEF_DEBUG
+# ifdef FILE_DEF_DEBUG
{
fprintf(stderr, "FILE_DEF_DEBUG should not be defined in CXX\n");
result = 0;
}
-#endif
-#ifdef TARGET_DEF_DEBUG
+# endif
+# ifdef TARGET_DEF_DEBUG
{
fprintf(stderr, "TARGET_DEF_DEBUG should not be defined in CXX\n");
result = 0;
}
-#endif
-#ifdef DIRECTORY_DEF_DEBUG
+# endif
+# ifdef DIRECTORY_DEF_DEBUG
{
fprintf(stderr, "DIRECTORY_DEF_DEBUG should not be defined in CXX\n");
result = 0;
}
-#endif
-#ifndef FILE_DEF_RELEASE
-#ifndef PREPROCESS_XCODE
+# endif
+# ifndef FILE_DEF_RELEASE
+# ifndef PREPROCESS_XCODE
{
fprintf(stderr, "FILE_DEF_RELEASE should be defined in CXX\n");
result = 0;
}
-#endif
-#endif
-#ifndef TARGET_DEF_RELEASE
+# endif
+# endif
+# ifndef TARGET_DEF_RELEASE
{
fprintf(stderr, "TARGET_DEF_RELEASE should be defined in CXX\n");
result = 0;
}
-#endif
-#ifndef DIRECTORY_DEF_RELEASE
+# endif
+# ifndef DIRECTORY_DEF_RELEASE
{
fprintf(stderr, "DIRECTORY_DEF_RELEASE should be defined in CXX\n");
result = 0;
}
-#endif
+# endif
#endif
#ifdef PREPROCESS_DEBUG
-#ifndef FILE_DEF_DEBUG
-#ifndef PREPROCESS_XCODE
+# ifndef FILE_DEF_DEBUG
+# ifndef PREPROCESS_XCODE
{
fprintf(stderr, "FILE_DEF_DEBUG should be defined in CXX\n");
result = 0;
}
-#endif
-#endif
-#ifndef TARGET_DEF_DEBUG
+# endif
+# endif
+# ifndef TARGET_DEF_DEBUG
{
fprintf(stderr, "TARGET_DEF_DEBUG should be defined in CXX\n");
result = 0;
}
-#endif
-#ifndef DIRECTORY_DEF_DEBUG
+# endif
+# ifndef DIRECTORY_DEF_DEBUG
{
fprintf(stderr, "DIRECTORY_DEF_DEBUG should be defined in CXX\n");
result = 0;
}
-#endif
-#ifdef FILE_DEF_RELEASE
+# endif
+# ifdef FILE_DEF_RELEASE
{
fprintf(stderr, "FILE_DEF_RELEASE should not be defined in CXX\n");
result = 0;
}
-#endif
-#ifdef TARGET_DEF_RELEASE
+# endif
+# ifdef TARGET_DEF_RELEASE
{
fprintf(stderr, "TARGET_DEF_RELEASE should not be defined in CXX\n");
result = 0;
}
-#endif
-#ifdef DIRECTORY_DEF_RELEASE
+# endif
+# ifdef DIRECTORY_DEF_RELEASE
{
fprintf(stderr, "DIRECTORY_DEF_RELEASE should not be defined in CXX\n");
result = 0;
}
-#endif
+# endif
#endif
#if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG)
-#if !defined(FILE_DEF_DEBUG) || !defined(TARGET_DEF_DEBUG)
-#ifndef PREPROCESS_XCODE
+# if !defined(FILE_DEF_DEBUG) || !defined(TARGET_DEF_DEBUG)
+# ifndef PREPROCESS_XCODE
{
fprintf(stderr,
"FILE_DEF_DEBUG and TARGET_DEF_DEBUG inconsistent in CXX\n");
result = 0;
}
-#endif
-#endif
-#if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE)
+# endif
+# endif
+# if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE)
{
fprintf(stderr, "DEBUG and RELEASE definitions inconsistent in CXX\n");
result = 0;
}
-#endif
+# endif
#endif
#if defined(FILE_DEF_RELEASE) || defined(TARGET_DEF_RELEASE)
-#if !defined(FILE_DEF_RELEASE) || !defined(TARGET_DEF_RELEASE)
-#ifndef PREPROCESS_XCODE
+# if !defined(FILE_DEF_RELEASE) || !defined(TARGET_DEF_RELEASE)
+# ifndef PREPROCESS_XCODE
{
fprintf(stderr,
"FILE_DEF_RELEASE and TARGET_DEF_RELEASE inconsistent in CXX\n");
result = 0;
}
-#endif
-#endif
-#if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG)
+# endif
+# endif
+# if defined(FILE_DEF_DEBUG) || defined(TARGET_DEF_DEBUG)
{
fprintf(stderr, "RELEASE and DEBUG definitions inconsistent in CXX\n");
result = 0;
}
-#endif
+# endif
#endif
#ifndef FILE_PATH_DEF
{
#ifndef SUBDIR_TEST
-#error Expected SUBDIR_TEST
+# error Expected SUBDIR_TEST
#endif
int main(int, char**)
#include <QApplication>
#ifndef QT_QAXSERVER_LIB
-#error Expected QT_QAXSERVER_LIB
+# error Expected QT_QAXSERVER_LIB
#endif
#include <QAxFactory>
#include <QString>
#ifndef QT_CORE_LIB
-#error Expected QT_CORE_LIB
+# error Expected QT_CORE_LIB
#endif
#ifndef QT_GUI_LIB
-#error Expected QT_GUI_LIB
+# error Expected QT_GUI_LIB
#endif
int main(int argc, char** argv)
#include "myinterface.h"
-class MyObject : public QObject, MyInterface
+class MyObject
+ : public QObject
+ , MyInterface
{
Q_OBJECT
Q_INTERFACES(MyInterface)
#include "myinterface.h"
-class MyWrapObject : public QObject, MyInterface
+class MyWrapObject
+ : public QObject
+ , MyInterface
{
Q_OBJECT
Q_INTERFACES(MyInterface)
# Autogen tests common for Qt4 and Qt5
+ADD_AUTOGEN_TEST(Complex QtAutogen)
+ADD_AUTOGEN_TEST(LowMinimumVersion lowMinimumVersion)
ADD_AUTOGEN_TEST(MocOnly mocOnly)
ADD_AUTOGEN_TEST(MocOptions mocOptions)
ADD_AUTOGEN_TEST(UicOnly uicOnly)
ADD_AUTOGEN_TEST(ParallelAUTO parallelAUTO)
ADD_AUTOGEN_TEST(SameName sameName)
ADD_AUTOGEN_TEST(StaticLibraryCycle slc)
-ADD_AUTOGEN_TEST(Complex QtAutogen)
# Rerun tests
ADD_AUTOGEN_TEST(RerunMocBasic)
if(NOT QT_TEST_VERSION STREQUAL 4)
ADD_AUTOGEN_TEST(RerunMocPlugin)
endif()
ADD_AUTOGEN_TEST(RerunRccDepends)
+ADD_AUTOGEN_TEST(RerunRccConfigChange)
#include "ui_calwidget.h"
#ifdef UI_CALWIDGET_H
-#error Definition of UI_CALWIDGET_H should be disabled by file option.
+# error Definition of UI_CALWIDGET_H should be disabled by file option.
#endif
Window::Window()
#include "myinterface.h"
#include "myotherinterface.h"
-class Generated : public QObject, MyInterface, MyOtherInterface
+class Generated
+ : public QObject
+ , MyInterface
+ , MyOtherInterface
{
Q_OBJECT
Q_INTERFACES(MyInterface MyOtherInterface)
#include "xyz.h"
#include "yaf.h"
#ifdef TEST_DEBUG_CLASS
-#include "debug_class.h"
-#include <iostream>
+# include "debug_class.h"
+# include <iostream>
#endif
int main(int argv, char** args)
#include <QObject>
#ifdef QT_GUI_LIB
-#include <QTextDocument>
+# include <QTextDocument>
class SomeDocument : public QTextDocument
{
--- /dev/null
+# Use a low minimum version
+cmake_minimum_required(VERSION 3.0)
+project(LowMinimumVersion)
+include("../AutogenTest.cmake")
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTORCC ON)
+add_executable(lowMinimumVersion
+ main.cpp
+ item.hpp
+ item.cpp
+ view.ui
+ someText.txt
+ example.qrc)
+target_link_libraries(lowMinimumVersion ${QT_QTCORE_TARGET})
--- /dev/null
+<RCC>
+ <qresource prefix="Example">
+ <file>someText.txt</file>
+ </qresource>
+</RCC>
--- /dev/null
+#include "item.hpp"
+#include <ui_view.h>
+
+class MocLocal : public QObject
+{
+ Q_OBJECT;
+
+public:
+ MocLocal() = default;
+ ~MocLocal() = default;
+};
+
+void Item::go()
+{
+ Ui_View ui;
+ MocLocal obj;
+}
+
+#include "item.moc"
--- /dev/null
+#ifndef ITEM_HPP
+#define ITEM_HPP
+
+#include <QObject>
+
+class Item : public QObject
+{
+ Q_OBJECT
+
+public:
+ Q_SLOT
+ void go();
+};
+
+#endif
--- /dev/null
+#include "item.hpp"
+
+int main(int argc, char* argv[])
+{
+ Q_INIT_RESOURCE(example);
+ Item item;
+ item.go();
+
+ return 0;
+}
--- /dev/null
+Hello world, you're an interesting place.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>View</class>
+ <widget class="QWidget" name="Base">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QTreeView" name="treeView"/>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+cmake_minimum_required(VERSION 3.11.2)
+project(RerunRccConfigChange)
+include("../AutogenTest.cmake")
+
+# Tests rcc rebuilding after a configuration change
+
+# Dummy executable to generate a clean target
+add_executable(dummy dummy.cpp)
+
+# When a .qrc or a file listed in a .qrc file changes,
+# the target must be rebuilt
+set(timeformat "%Y%j%H%M%S")
+set(rccDepSD "${CMAKE_CURRENT_SOURCE_DIR}/RccConfigChange")
+set(rccDepBD "${CMAKE_CURRENT_BINARY_DIR}/RccConfigChange")
+
+# Initial build
+try_compile(RCC_DEPENDS
+ "${rccDepBD}"
+ "${rccDepSD}"
+ RccConfigChange
+ CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+ "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+ OUTPUT_VARIABLE output
+)
+if (NOT RCC_DEPENDS)
+ message(SEND_ERROR "Initial build of rccConfigChange failed. Output: ${output}")
+endif()
+
+# - Rebuild Release
+message("Rebuilding rccConfigChange in Release configuration")
+execute_process(COMMAND "${CMAKE_COMMAND}" --build . --config Release WORKING_DIRECTORY "${rccDepBD}" RESULT_VARIABLE result)
+if (result)
+ message(SEND_ERROR "Release build of rccConfigChange failed.")
+endif()
+
+# - Rebuild Debug
+message("Rebuilding rccConfigChange in Debug configuration")
+execute_process(COMMAND "${CMAKE_COMMAND}" --build . --config Debug WORKING_DIRECTORY "${rccDepBD}" RESULT_VARIABLE result)
+if (result)
+ message(SEND_ERROR "Debug build of rccConfigChange failed.")
+endif()
--- /dev/null
+cmake_minimum_required(VERSION 3.11.2)
+project(RccConfigChange)
+include("../../AutogenTest.cmake")
+
+# Enable AUTORCC for all targets
+set(CMAKE_AUTORCC ON)
+
+# Initial resource files setup
+configure_file(resGen/input1.txt.in resGen/input1.txt COPYONLY)
+configure_file(resGen/input2.txt.in resGen/input2.txt COPYONLY)
+configure_file(resGen.qrc.in resGen.qrc COPYONLY)
+
+# Generated qrc file with dependency
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/resGen.qrc
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/resGen.qrc.in
+ COMMAND ${CMAKE_COMMAND} -E sleep 2
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/resGen.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/resGen.qrc
+)
+
+# Target that uses a plain .qrc file
+add_executable(rccConfigChangePlain main.cpp resPlain.qrc)
+target_link_libraries(rccConfigChangePlain ${QT_QTCORE_TARGET})
+
+# Target that uses a GENERATED .qrc file
+add_executable(rccConfigChangeGen main.cpp ${CMAKE_CURRENT_BINARY_DIR}/resGen.qrc )
+target_link_libraries(rccConfigChangeGen ${QT_QTCORE_TARGET})
--- /dev/null
+
+int main()
+{
+ return 0;
+}
--- /dev/null
+<RCC>
+ <qresource prefix="/TextsGenerated">
+ <file>resGen/input1.txt</file>
+ <file>resGen/input2.txt</file>
+ </qresource>
+</RCC>
--- /dev/null
+Generated resource input.
--- /dev/null
+Generated resource input.
--- /dev/null
+<RCC>
+ <qresource prefix="/TextsPlain">
+ <file>resPlain/input1.txt</file>
+ <file>resPlain/input2.txt</file>
+ </qresource>
+</RCC>
--- /dev/null
+Plain resource input.
--- /dev/null
+Plain resource input.
--- /dev/null
+
+int main(int argv, char** args)
+{
+ return 0;
+}
# - Change a resource files listed in the .qrc file
# - Rebuild
execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
-execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resPlain/input.txt")
-execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resGen/input.txt")
+file(TOUCH "${rccDepBD}/resPlain/input.txt" "${rccDepBD}/resGen/input.txt")
execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${rccDepBD}" RESULT_VARIABLE result)
if (result)
message(SEND_ERROR "Second build of rccDepends failed.")
endif()
-message("Changing a the .qrc file")
+message("Changing the .qrc file")
# - Acquire binary timestamps before the build
file(TIMESTAMP "${rccDepBinPlain}" rdPlainBefore "${timeformat}")
file(TIMESTAMP "${rccDepBinGen}" rdGenBefore "${timeformat}")
# - Change a newly added resource files listed in the .qrc file
# - Rebuild
execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
-execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resPlain/inputAdded.txt")
-execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resGen/inputAdded.txt")
+file(TOUCH "${rccDepBD}/resPlain/inputAdded.txt" "${rccDepBD}/resGen/inputAdded.txt")
execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${rccDepBD}" RESULT_VARIABLE result)
if (result)
message(SEND_ERROR "Fourth build of rccDepends failed.")
#include <memory>
#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
-#include <klocalizedstring.h>
+# include <klocalizedstring.h>
#endif
#include "ui_libwidget.h"
#include <memory>
#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
-#include <klocalizedstring.h>
+# include <klocalizedstring.h>
#endif
#include "ui_mywidget.h"
-DCMAKE_ANDROID_ARM_MODE=0
)
run_cmake(ndk-badarm)
- set(RunCMake_TEST_OPTIONS
- -DCMAKE_SYSTEM_NAME=Android
- -DCMAKE_ANDROID_NDK=${ndk}
- -DCMAKE_ANDROID_ARM_NEON=0
- )
- run_cmake(ndk-badneon)
+ if("armeabi" IN_LIST _abis_)
+ set(RunCMake_TEST_OPTIONS
+ -DCMAKE_SYSTEM_NAME=Android
+ -DCMAKE_ANDROID_NDK=${ndk}
+ -DCMAKE_ANDROID_ARM_NEON=0
+ )
+ run_cmake(ndk-badneon)
+ endif()
set(RunCMake_TEST_OPTIONS
-DCMAKE_SYSTEM_NAME=Android
-DCMAKE_ANDROID_NDK=${ndk}
#include "android.h"
#ifndef STL_NONE
-#include <cmath>
-#include <cstdio>
-#ifndef STL_SYSTEM
-#include <exception>
-#include <typeinfo>
-#ifndef STL_STLPORT
-#include <cxxabi.h>
-#endif
-#ifndef STL_GABI
-#include <iostream>
-#include <string>
-#endif
-#endif
+# include <cmath>
+# include <cstdio>
+# ifndef STL_SYSTEM
+# include <exception>
+# include <typeinfo>
+# ifndef STL_STLPORT
+# include <cxxabi.h>
+# endif
+# ifndef STL_GABI
+# include <iostream>
+# include <string>
+# endif
+# endif
#endif
int main()
try {
delete (new int);
} catch (std::exception const& e) {
-#if defined(STL_GABI)
+# if defined(STL_GABI)
e.what();
typeid(e).name();
-#else
+# else
std::cerr << e.what() << std::endl;
std::cerr << typeid(e).name() << std::endl;
-#endif
+# endif
}
-#if defined(STL_GABI)
+# if defined(STL_GABI)
return 0;
-#else
+# else
std::string s;
return static_cast<int>(s.size());
-#endif
+# endif
#endif
}
#ifndef __ANDROID__
-#error "__ANDROID__ not defined"
+# error "__ANDROID__ not defined"
#endif
#include <android/api-level.h>
#if API_LEVEL != __ANDROID_API__
-#error "API levels do not match"
+# error "API levels do not match"
#endif
#ifdef COMPILER_IS_CLANG
-#ifndef __clang__
-#error "COMPILER_IS_CLANG but __clang__ is not defined"
-#endif
+# ifndef __clang__
+# error "COMPILER_IS_CLANG but __clang__ is not defined"
+# endif
#else
-#ifdef __clang__
-#error "!COMPILER_IS_CLANG but __clang__ is defined"
-#endif
+# ifdef __clang__
+# error "!COMPILER_IS_CLANG but __clang__ is defined"
+# endif
#endif
#ifdef ARM_MODE
-#if ARM_MODE == 1 && defined(__thumb__)
-#error "ARM_MODE==1 but __thumb__ is defined"
-#elif ARM_MODE == 0 && !defined(__thumb__)
-#error "ARM_MODE==0 but __thumb__ is not defined"
-#endif
+# if ARM_MODE == 1 && defined(__thumb__)
+# error "ARM_MODE==1 but __thumb__ is defined"
+# elif ARM_MODE == 0 && !defined(__thumb__)
+# error "ARM_MODE==0 but __thumb__ is not defined"
+# endif
#endif
#ifdef ARM_NEON
-#if ARM_NEON == 0 && defined(__ARM_NEON__)
-#error "ARM_NEON==0 but __ARM_NEON__ is defined"
-#elif ARM_NEON == 1 && !defined(__ARM_NEON__)
-#error "ARM_NEON==1 but __ARM_NEON__ is not defined"
-#endif
+# if ARM_NEON == 0 && defined(__ARM_NEON__)
+# error "ARM_NEON==0 but __ARM_NEON__ is defined"
+# elif ARM_NEON == 1 && !defined(__ARM_NEON__)
+# error "ARM_NEON==1 but __ARM_NEON__ is not defined"
+# endif
#endif
#ifdef ABI_armeabi
-#ifndef __ARM_EABI__
-#error "ABI_armeabi: __ARM_EABI__ not defined"
-#endif
-#if __ARM_ARCH != 5
-#error "ABI_armeabi: __ARM_ARCH is not 5"
-#endif
+# ifndef __ARM_EABI__
+# error "ABI_armeabi: __ARM_EABI__ not defined"
+# endif
+# if __ARM_ARCH != 5
+# error "ABI_armeabi: __ARM_ARCH is not 5"
+# endif
#endif
#ifdef ABI_armeabi_v6
-#ifndef __ARM_EABI__
-#error "ABI_armeabi_v6: __ARM_EABI__ not defined"
-#endif
-#if __ARM_ARCH != 6
-#error "ABI_armeabi_v6: __ARM_ARCH is not 6"
-#endif
+# ifndef __ARM_EABI__
+# error "ABI_armeabi_v6: __ARM_EABI__ not defined"
+# endif
+# if __ARM_ARCH != 6
+# error "ABI_armeabi_v6: __ARM_ARCH is not 6"
+# endif
#endif
#ifdef ABI_armeabi_v7a
-#ifndef __ARM_EABI__
-#error "ABI_armeabi_v7a: __ARM_EABI__ not defined"
-#endif
-#if __ARM_ARCH != 7
-#error "ABI_armeabi_v7a: __ARM_ARCH is not 7"
-#endif
+# ifndef __ARM_EABI__
+# error "ABI_armeabi_v7a: __ARM_EABI__ not defined"
+# endif
+# if __ARM_ARCH != 7
+# error "ABI_armeabi_v7a: __ARM_ARCH is not 7"
+# endif
#endif
#ifdef ABI_arm64_v8a
-#ifdef __ARM_EABI__
-#error "ABI_arm64_v8a: __ARM_EABI__ defined"
-#endif
-#ifndef __aarch64__
-#error "ABI_arm64_v8a: __aarch64__ not defined"
-#endif
+# ifdef __ARM_EABI__
+# error "ABI_arm64_v8a: __ARM_EABI__ defined"
+# endif
+# ifndef __aarch64__
+# error "ABI_arm64_v8a: __aarch64__ not defined"
+# endif
#endif
#ifdef ABI_mips
-#if __mips != 32
-#error "ABI_mips: __mips != 32"
-#endif
-#ifndef _ABIO32
-#error "ABI_mips: _ABIO32 not defined"
-#endif
+# if __mips != 32
+# error "ABI_mips: __mips != 32"
+# endif
+# ifndef _ABIO32
+# error "ABI_mips: _ABIO32 not defined"
+# endif
#endif
#ifdef ABI_mips64
-#if __mips != 64
-#error "ABI_mips64: __mips != 64"
-#endif
-#ifndef _ABI64
-#error "ABI_mips: _ABI64 not defined"
-#endif
+# if __mips != 64
+# error "ABI_mips64: __mips != 64"
+# endif
+# ifndef _ABI64
+# error "ABI_mips: _ABI64 not defined"
+# endif
#endif
#ifdef ABI_x86
-#ifndef __i686__
-#error "ABI_x86: __i686__ not defined"
-#endif
+# ifndef __i686__
+# error "ABI_x86: __i686__ not defined"
+# endif
#endif
#ifdef ABI_x86_64
-#ifndef __x86_64__
-#error "ABI_x86_64: __x86_64__ not defined"
-#endif
+# ifndef __x86_64__
+# error "ABI_x86_64: __x86_64__ not defined"
+# endif
#endif
#include <stddef.h>
--- /dev/null
+int android_lib()
+{
+ return 0;
+}
#include <dlfcn.h>
#ifndef NOT_SYSTEM_DLFCN_HEADER
-#error "sysroot /usr/include appears too early"
+# error "sysroot /usr/include appears too early"
#endif
#include "android.c"
#include <dlfcn.h>
#ifndef NOT_SYSTEM_DLFCN_HEADER
-#error "sysroot /usr/include appears too early"
+# error "sysroot /usr/include appears too early"
#endif
#include "android.cxx"
--- /dev/null
+if(NOT EXISTS "${file}")
+ message(FATAL_ERROR "Missing file:\n ${file}")
+endif()
+execute_process(COMMAND "${objdump}" -p ${file} OUTPUT_VARIABLE out)
+if(out MATCHES "NEEDED[^\n]*stdc\\+\\+")
+ string(REPLACE "\n" "\n " out " ${out}")
+ message(FATAL_ERROR "File:\n ${file}\ndepends on libstdc++:\n${out}")
+endif()
endif()
add_executable(android_c android.c)
add_executable(android_cxx android.cxx)
+add_library(android_cxx_lib SHARED android_lib.cxx)
+
+set(objdump "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}objdump")
+if(NOT EXISTS "${objdump}")
+ message(FATAL_ERROR "Expected tool missing:\n ${objdump}")
+endif()
+
+if(NOT CMAKE_ANDROID_STL_TYPE MATCHES "^(system|stlport_static|stlport_shared)$")
+ foreach(tgt android_cxx android_cxx_lib)
+ add_custom_command(TARGET ${tgt} POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ -Dobjdump=${objdump}
+ -Dfile=$<TARGET_FILE:${tgt}>
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/check_binary.cmake
+ )
+ endforeach()
+endif()
# Test that an explicit /usr/include is ignored in favor of
# appearing as a standard include directory at the end.
^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\):
- Android: No toolchain for ABI 'armeabi' found in the NDK:
+ Android: No toolchain for ABI 'armeabi(-v7a)?' found in the NDK:
.*
#ifdef _MSC_VER
-#include "windows.h"
+# include "windows.h"
#else
-#define WINAPI
+# define WINAPI
#endif
int WINAPI foo()
#ifndef _MSC_VER
-#define winexport
+# define winexport
#else
-#ifdef autoexport_EXPORTS
-#define winexport
-#else
-#define winexport __declspec(dllimport)
-#endif
+# ifdef autoexport_EXPORTS
+# define winexport
+# else
+# define winexport __declspec(dllimport)
+# endif
#endif
class Hello
#include "hello.h"
#include <stdio.h>
#ifdef _MSC_VER
-#include "windows.h"
+# include "windows.h"
#else
-#define WINAPI
+# define WINAPI
#endif
extern "C" {
-DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION}
-DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX}
-DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX})
+ if(CMAKE_Fortran_COMPILER)
+ list(APPEND Ninja_ARGS -DTEST_Fortran=1)
+ endif()
add_RunCMake_test(Ninja)
endif()
add_RunCMake_test(CTest)
add_RunCMake_test(FeatureSummary)
add_RunCMake_test(FPHSA)
add_RunCMake_test(FindBoost)
+add_RunCMake_test(FindLua)
add_RunCMake_test(FindOpenGL)
if(NOT CMAKE_C_COMPILER_ID MATCHES "Watcom")
add_RunCMake_test(GenerateExportHeader)
endif()
add_RunCMake_test(CompatibleInterface)
add_RunCMake_test(Syntax)
+add_RunCMake_test(WorkingDirectory)
add_RunCMake_test(add_custom_command)
add_RunCMake_test(add_custom_target)
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio")
add_RunCMake_test(include_external_msproject)
- if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([89]|10)" AND NOT CMAKE_VS_DEVENV_COMMAND)
+ if("${CMAKE_GENERATOR}" MATCHES "Visual Studio (9|10)" AND NOT CMAKE_VS_DEVENV_COMMAND)
set(NO_USE_FOLDERS 1)
endif()
add_RunCMake_test(VSSolution -DNO_USE_FOLDERS=${NO_USE_FOLDERS})
endif()
-if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([^89]|[89][0-9])")
+if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([^9]|9[0-9])")
add_RunCMake_test(VS10Project)
endif()
add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
add_RunCMake_test(CommandLineTar)
-add_RunCMake_test(install)
+if(CMAKE_PLATFORM_NO_VERSIONED_SONAME OR (NOT CMAKE_SHARED_LIBRARY_SONAME_FLAG AND NOT CMAKE_SHARED_LIBRARY_SONAME_C_FLAG))
+ set(NO_NAMELINK 1)
+else()
+ set(NO_NAMELINK 0)
+endif()
+
+add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN})
add_RunCMake_test(CPackCommandLine)
add_RunCMake_test(CPackConfig)
add_RunCMake_test(CPackInstallProperties)
add_RunCMake_test(ExternalProject)
add_RunCMake_test(FetchContent)
+if(NOT CMake_TEST_EXTERNAL_CMAKE)
+ set(CTestCommandLine_ARGS -DTEST_AFFINITY=$<TARGET_FILE:testAffinity>)
+endif()
add_RunCMake_test(CTestCommandLine)
add_RunCMake_test(CacheNewline)
# Only run this test on unix platforms that support
add_RunCMake_test(IfacePaths_SOURCES TEST_DIR IfacePaths)
# Matlab module related tests
-if(CMake_TEST_FindMatlab)
- add_RunCMake_test(FindMatlab)
+if(CMake_TEST_FindMatlab OR CMake_TEST_FindMatlab_MCR OR (NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL ""))
+ set(FindMatlab_additional_test_options )
+ if(CMake_TEST_FindMatlab_MCR OR NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "")
+ set(FindMatlab_additional_test_options -DIS_MCR=TRUE)
+ endif()
+ if(NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "")
+ set(FindMatlab_additional_test_options ${FindMatlab_additional_test_options} "-DMCR_ROOT:FILEPATH=${CMake_TEST_FindMatlab_MCR_ROOT_DIR}")
+ endif()
+
+ add_RunCMake_test(FindMatlab ${FindMatlab_additional_test_options})
endif()
add_executable(pseudo_emulator pseudo_emulator.c)
set_property(TEST RunCMake.Android PROPERTY TIMEOUT ${CMake_TEST_ANDROID_TIMEOUT})
endif()
-if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
+if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|9[0-9])")
add_RunCMake_test(CSharpCustomCommand)
+ add_RunCMake_test(CSharpReferenceImport)
endif()
--- /dev/null
+cmake_minimum_required(VERSION 3.3)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+enable_language(CXX CSharp)
+
+if(NOT DEFINED exportFileName OR
+ NOT DEFINED exportNameSpace OR
+ NOT DEFINED exportTargetName)
+ message(FATAL_ERROR "export information missing")
+endif()
+
+add_library(${exportTargetName}CSharp SHARED
+ ImportLib.cs)
+
+# native c++ dll
+add_library(${exportTargetName}Native SHARED
+ ImportLibNative.h
+ ImportLibNative.cxx)
+
+# mixed c++ dll
+add_library(${exportTargetName}Mixed SHARED
+ ImportLibMixed.cxx
+ ImportLibMixedNative.h
+ ImportLibMixedNative.cxx)
+set_target_properties(${exportTargetName}Mixed PROPERTIES
+ COMMON_LANGUAGE_RUNTIME "")
+
+# pure c++ dll
+add_library(${exportTargetName}Pure SHARED
+ ImportLibPure.cxx)
+set_target_properties(${exportTargetName}Pure PROPERTIES
+ COMMON_LANGUAGE_RUNTIME "pure")
+
+# safe c++ dll
+add_library(${exportTargetName}Safe SHARED
+ ImportLibSafe.cxx)
+set_target_properties(${exportTargetName}Safe PROPERTIES
+ COMMON_LANGUAGE_RUNTIME "safe")
+
+# generate export file
+export(TARGETS
+ ${exportTargetName}CSharp
+ ${exportTargetName}Native
+ ${exportTargetName}Mixed
+ ${exportTargetName}Pure
+ ${exportTargetName}Safe
+ NAMESPACE "${exportNameSpace}:"
+ FILE "${exportFileName}")
--- /dev/null
+using System;
+
+public
+class ImportLibCSharp
+{
+public
+ static void Message() { Console.WriteLine("ImportLibCSharp"); }
+}
--- /dev/null
+using namespace System;
+
+public
+ref class ImportLibMixed
+{
+public:
+ static void Message() { Console::WriteLine("ImportLibMixed"); }
+};
--- /dev/null
+#include "ImportLibMixedNative.h"
+
+#include <iostream>
+
+void ImportLibMixedNative::Message()
+{
+ std::cout << "ImportLibMixedNative" << std::endl;
+}
--- /dev/null
+#pragma once
+
+#ifdef ImportLibMixed_EXPORTS
+# define mixedAPI __declspec(dllexport)
+#else
+# define mixedAPI __declspec(dllimport)
+#endif
+
+class mixedAPI ImportLibMixedNative
+{
+public:
+ static void Message();
+};
--- /dev/null
+#include "ImportLibNative.h"
+
+#include <iostream>
+
+void ImportLibNative::Message()
+{
+ std::cout << "ImportLibNative" << std::endl;
+}
--- /dev/null
+#pragma once
+
+#ifdef ImportLibNative_EXPORTS
+# define nativeAPI __declspec(dllexport)
+#else
+# define nativeAPI __declspec(dllimport)
+#endif
+
+class nativeAPI ImportLibNative
+{
+public:
+ static void Message();
+};
--- /dev/null
+using namespace System;
+
+public
+ref class ImportLibPure
+{
+public:
+ static void Message() { Console::WriteLine("ImportLibPure"); }
+};
--- /dev/null
+using namespace System;
+
+public
+ref class ImportLibSafe
+{
+public:
+ static void Message() { Console::WriteLine("ImportLibSafe"); }
+};
--- /dev/null
+enable_language(CXX CSharp)
+
+if(NOT DEFINED exportFileName OR
+ NOT DEFINED exportNameSpace OR
+ NOT DEFINED exportTargetName)
+ message(FATAL_ERROR "export information missing")
+endif()
+
+# Include generated export file.
+if(NOT EXISTS "${exportFileName}")
+ message(FATAL_ERROR "exportFileNameCSharp does not exist: ${exportFileName}")
+endif()
+include(${exportFileName})
+
+# Verify expected targets are imported
+set(linkNames linkNameCSharp linkNameNative linkNameMixed
+ linkNamePure linkNameSafe)
+set(linkNameCSharp "${exportNameSpace}:${exportTargetName}CSharp")
+set(linkNameNative "${exportNameSpace}:${exportTargetName}Native")
+set(linkNameMixed "${exportNameSpace}:${exportTargetName}Mixed")
+set(linkNamePure "${exportNameSpace}:${exportTargetName}Pure")
+set(linkNameSafe "${exportNameSpace}:${exportTargetName}Safe")
+foreach(l ${linkNames})
+ if(NOT TARGET ${${l}})
+ message(FATAL_ERROR "imported target not found (${${l}})")
+ endif()
+endforeach()
+
+# Test referencing managed assemblies from C# executable.
+add_executable(ReferenceImportCSharp ReferenceImport.cs)
+target_link_libraries(ReferenceImportCSharp
+ ${linkNameCSharp}
+ ${linkNameNative} # ignored
+ ${linkNameMixed}
+ ${linkNamePure}
+ ${linkNameSafe}
+ )
+
+# native C++ executable.
+add_executable(ReferenceImportNative ReferenceImportNative.cxx)
+target_link_libraries(ReferenceImportNative
+ ${linkNameCSharp} # ignored
+ ${linkNameNative}
+ ${linkNameMixed}
+ ${linkNamePure} # ignored
+ ${linkNameSafe} # ignored
+ )
+add_custom_command(TARGET ReferenceImportNative POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "$<TARGET_FILE:${linkNameNative}>"
+ "${CMAKE_BINARY_DIR}/$<CONFIG>"
+ )
+
+# mixed C++ executable.
+add_executable(ReferenceImportMixed ReferenceImportMixed.cxx)
+target_link_libraries(ReferenceImportMixed
+ ${linkNameCSharp}
+ ${linkNameNative}
+ ${linkNameMixed}
+ ${linkNamePure}
+ ${linkNameSafe}
+ )
+set_target_properties(ReferenceImportMixed PROPERTIES
+ COMMON_LANGUAGE_RUNTIME "")
+
+# pure C++ executable.
+add_executable(ReferenceImportPure ReferenceImportPure.cxx)
+target_link_libraries(ReferenceImportPure
+ ${linkNameCSharp}
+ ${linkNameNative} # ignored
+ ${linkNameMixed}
+ ${linkNamePure}
+ ${linkNameSafe}
+ )
+set_target_properties(ReferenceImportPure PROPERTIES
+ COMMON_LANGUAGE_RUNTIME "pure")
+
+# native C++ executable.
+add_executable(ReferenceImportSafe ReferenceImportSafe.cxx)
+target_link_libraries(ReferenceImportSafe
+ ${linkNameCSharp}
+ ${linkNameNative} # ignored
+ ${linkNameMixed}
+ ${linkNamePure}
+ ${linkNameSafe}
+ )
+set_target_properties(ReferenceImportSafe PROPERTIES
+ COMMON_LANGUAGE_RUNTIME "safe")
--- /dev/null
+using System;
+
+public class ReferenceImport
+{
+ public static void Main()
+ {
+ Console.WriteLine("ReferenceImportCSharp");
+ ImportLibMixed.Message();
+ ImportLibPure.Message();
+ ImportLibSafe.Message();
+ ImportLibCSharp.Message();
+ }
+}
--- /dev/null
+// clang-format off
+
+using namespace System;
+
+#using <ImportLibMixed.dll>
+#using <ImportLibPure.dll>
+#using <ImportLibSafe.dll>
+#using <ImportLibCSharp.dll>
+
+#include "ImportLibNative.h"
+
+int main()
+{
+ Console::WriteLine("ReferenceImportMixed");
+ ImportLibNative::Message();
+ ImportLibMixed::Message();
+ ImportLibPure::Message();
+ ImportLibSafe::Message();
+ ImportLibCSharp::Message();
+};
--- /dev/null
+// clang-format off
+
+#include "ImportLibNative.h"
+#include "ImportLibMixedNative.h"
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "ReferenceImportNative" << std::endl;
+ ImportLibNative::Message();
+ ImportLibMixedNative::Message();
+};
--- /dev/null
+// clang-format off
+
+using namespace System;
+
+#using <ImportLibMixed.dll>
+#using <ImportLibPure.dll>
+#using <ImportLibSafe.dll>
+#using <ImportLibCSharp.dll>
+
+int main()
+{
+ Console::WriteLine("ReferenceImportPure");
+ ImportLibMixed::Message();
+ ImportLibPure::Message();
+ ImportLibSafe::Message();
+ ImportLibCSharp::Message();
+};
--- /dev/null
+// clang-format off
+
+using namespace System;
+
+#using <ImportLibMixed.dll>
+#using <ImportLibPure.dll>
+#using <ImportLibSafe.dll>
+#using <ImportLibCSharp.dll>
+
+int main()
+{
+ Console::WriteLine("ReferenceImportSafe");
+ ImportLibMixed::Message();
+ ImportLibPure::Message();
+ ImportLibSafe::Message();
+ ImportLibCSharp::Message();
+};
--- /dev/null
+include(RunCMake)
+
+set(RunCMake_TEST_NO_CLEAN 1)
+
+set(exportFileName "${RunCMake_BINARY_DIR}/module.cmake")
+set(exportNameSpace "ex")
+set(exportTargetName "ImportLib")
+
+set(RunCMake_TEST_OPTIONS_BASE ${RunCMake_TEST_OPTIONS}
+ "-DexportNameSpace:INTERNAL=${exportNameSpace}"
+ "-DexportTargetName:INTERNAL=${exportTargetName}")
+
+file(REMOVE "${exportFileName}")
+
+# generate C# & C++ assemblies for use as imported target
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ImportLib-build)
+file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+set(RunCMake_TEST_OPTIONS ${RunCMake_TEST_OPTIONS_BASE}
+ "-DexportFileName:INTERNAL=${exportFileName}"
+ # make sure we know the RunCMake_TEST if configuring the project again
+ # with cmake-gui for debugging.
+ "-DRunCMake_TEST:INTERNAL=ImportLib")
+
+run_cmake(ImportLib)
+run_cmake_command(ImportLib-build ${CMAKE_COMMAND} --build . --config Debug)
+
+# generate C# & managed C++ programs which reference imported managed assemblies.
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ReferenceImport-build)
+file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+set(RunCMake_TEST_OPTIONS ${RunCMake_TEST_OPTIONS_BASE}
+ "-DexportFileName:INTERNAL=${exportFileName}"
+ # make sure we know the RunCMake_TEST if configuring the project again
+ # with cmake-gui for debugging.
+ "-DRunCMake_TEST:INTERNAL=ReferenceImport")
+
+run_cmake(ReferenceImport)
+run_cmake_command(ReferenceImport-build ${CMAKE_COMMAND} --build . --config Debug)
)
endfunction()
run_TestOutputSize()
+
+function(run_TestAffinity)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestAffinity)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ # Create a test with affinity enabled. The default PROCESSORS
+ # value is 1, so our expected output checks that this is the
+ # number of processors in the mask.
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+ add_test(Affinity \"${TEST_AFFINITY}\")
+ set_tests_properties(Affinity PROPERTIES PROCESSOR_AFFINITY ON)
+")
+ # Run ctest with a large parallel level so that the value is
+ # not responsible for capping the number of processors available.
+ run_cmake_command(TestAffinity ${CMAKE_CTEST_COMMAND} -V -j 64)
+endfunction()
+if(TEST_AFFINITY)
+ run_TestAffinity()
+endif()
--- /dev/null
+1: CPU affinity (mask count is '1'|not supported on this platform)\.
--- /dev/null
+^CMake Warning \(dev\) at [^
+]*/Modules/CheckIncludeFile.cmake:[0-9]+ \(message\):
+ Policy CMP0075 is not set: Include file check macros honor
+ CMAKE_REQUIRED_LIBRARIES. Run "cmake --help-policy CMP0075" for policy
+ details. Use the cmake_policy command to set the policy and suppress this
+ warning.
+
+ CMAKE_REQUIRED_LIBRARIES is set to:
+
+ does_not_exist
+
+ For compatibility with CMake 3.11 and below this check is ignoring it.
+Call Stack \(most recent call first\):
+ CMP0075.cmake:11 \(check_include_file\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/CheckIncludeFileCXX.cmake:[0-9]+ \(message\):
+ Policy CMP0075 is not set: Include file check macros honor
+ CMAKE_REQUIRED_LIBRARIES. Run "cmake --help-policy CMP0075" for policy
+ details. Use the cmake_policy command to set the policy and suppress this
+ warning.
+
+ CMAKE_REQUIRED_LIBRARIES is set to:
+
+ does_not_exist
+
+ For compatibility with CMake 3.11 and below this check is ignoring it.
+Call Stack \(most recent call first\):
+ CMP0075.cmake:26 \(check_include_file_cxx\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at [^
+]*/Modules/CheckIncludeFiles.cmake:[0-9]+ \(message\):
+ Policy CMP0075 is not set: Include file check macros honor
+ CMAKE_REQUIRED_LIBRARIES. Run "cmake --help-policy CMP0075" for policy
+ details. Use the cmake_policy command to set the policy and suppress this
+ warning.
+
+ CMAKE_REQUIRED_LIBRARIES is set to:
+
+ does_not_exist
+
+ For compatibility with CMake 3.11 and below this check is ignoring it.
+Call Stack \(most recent call first\):
+ CMP0075.cmake:41 \(check_include_files\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
--- /dev/null
+enable_language(C)
+enable_language(CXX)
+include(CheckIncludeFile)
+include(CheckIncludeFileCXX)
+include(CheckIncludeFiles)
+
+set(CMAKE_REQUIRED_LIBRARIES does_not_exist)
+
+#============================================================================
+
+check_include_file("stddef.h" HAVE_STDDEF_H_1)
+if(NOT HAVE_STDDEF_H_1)
+ message(SEND_ERROR "HAVE_STDDEF_H_1 failed but should have passed.")
+endif()
+if(NOT _CIF_CMP0075_WARNED)
+ message(SEND_ERROR "HAVE_STDDEF_H_1 did not warn but should have")
+endif()
+check_include_file("stddef.h" HAVE_STDDEF_H_2) # second does not warn
+if(NOT HAVE_STDDEF_H_2)
+ message(SEND_ERROR "HAVE_STDDEF_H_2 failed but should have passed.")
+endif()
+unset(_CIF_CMP0075_WARNED)
+
+#----------------------------------------------------------------------------
+
+check_include_file_cxx("stddef.h" HAVE_STDDEF_H_CXX_1)
+if(NOT HAVE_STDDEF_H_CXX_1)
+ message(SEND_ERROR "HAVE_STDDEF_H_CXX_1 failed but should have passed.")
+endif()
+if(NOT _CIF_CMP0075_WARNED)
+ message(SEND_ERROR "HAVE_STDDEF_H_CXX_1 did not warn but should have")
+endif()
+check_include_file_cxx("stddef.h" HAVE_STDDEF_H_CXX_2) # second does not warn
+if(NOT HAVE_STDDEF_H_CXX_2)
+ message(SEND_ERROR "HAVE_STDDEF_H_CXX_2 failed but should have passed.")
+endif()
+unset(_CIF_CMP0075_WARNED)
+
+#----------------------------------------------------------------------------
+
+check_include_files("stddef.h;stdlib.h" HAVE_STDLIB_H_1)
+if(NOT HAVE_STDLIB_H_1)
+ message(SEND_ERROR "HAVE_STDLIB_H_1 failed but should have passed.")
+endif()
+if(NOT _CIF_CMP0075_WARNED)
+ message(SEND_ERROR "HAVE_STDLIB_H_1 did not warn but should have")
+endif()
+check_include_files("stddef.h;stdlib.h" HAVE_STDLIB_H_2) # second does not warn
+if(NOT HAVE_STDLIB_H_2)
+ message(SEND_ERROR "HAVE_STDLIB_H_2 failed but should have passed.")
+endif()
+unset(_CIF_CMP0075_WARNED)
+
+#============================================================================
+cmake_policy(SET CMP0075 OLD)
+# These should not warn.
+# These should pass the checks due to ignoring 'does_not_exist'.
+
+check_include_file("stddef.h" HAVE_STDDEF_H_3)
+if(NOT HAVE_STDDEF_H_3)
+ message(SEND_ERROR "HAVE_STDDEF_H_3 failed but should have passed.")
+endif()
+if(_CIF_CMP0075_WARNED)
+ message(SEND_ERROR "HAVE_STDDEF_H_3 warned but should not have")
+endif()
+unset(_CIF_CMP0075_WARNED)
+
+#----------------------------------------------------------------------------
+
+check_include_file_cxx("stddef.h" HAVE_STDDEF_H_CXX_3)
+if(NOT HAVE_STDDEF_H_CXX_3)
+ message(SEND_ERROR "HAVE_STDDEF_H_CXX_3 failed but should have passed.")
+endif()
+if(_CIF_CMP0075_WARNED)
+ message(SEND_ERROR "HAVE_STDDEF_H_CXX_3 warned but should not have")
+endif()
+unset(_CIF_CMP0075_WARNED)
+
+#----------------------------------------------------------------------------
+
+check_include_files("stddef.h;stdlib.h" HAVE_STDLIB_H_3)
+if(NOT HAVE_STDLIB_H_3)
+ message(SEND_ERROR "HAVE_STDLIB_H_3 failed but should have passed.")
+endif()
+if(_CIF_CMP0075_WARNED)
+ message(SEND_ERROR "HAVE_STDLIB_H_3 warned but should not have")
+endif()
+unset(_CIF_CMP0075_WARNED)
+
+#============================================================================
+cmake_policy(SET CMP0075 NEW)
+# These should not warn.
+# These should fail the checks due to requiring 'does_not_exist'.
+
+check_include_file("stddef.h" HAVE_STDDEF_H_4)
+if(HAVE_STDDEF_H_4)
+ message(SEND_ERROR "HAVE_STDDEF_H_4 passed but should have failed.")
+endif()
+if(_CIF_CMP0075_WARNED)
+ message(SEND_ERROR "HAVE_STDDEF_H_4 warned but should not have")
+endif()
+unset(_CIF_CMP0075_WARNED)
+
+#----------------------------------------------------------------------------
+
+check_include_file_cxx("stddef.h" HAVE_STDDEF_H_CXX_4)
+if(HAVE_STDDEF_H_CXX_4)
+ message(SEND_ERROR "HAVE_STDDEF_H_CXX_4 passed but should have failed.")
+endif()
+if(_CIF_CMP0075_WARNED)
+ message(SEND_ERROR "HAVE_STDDEF_H_CXX_4 warned but should not have")
+endif()
+unset(_CIF_CMP0075_WARNED)
+
+#----------------------------------------------------------------------------
+
+check_include_files("stddef.h;stdlib.h" HAVE_STDLIB_H_4)
+if(HAVE_STDLIB_H_4)
+ message(SEND_ERROR "HAVE_STDLIB_H_4 passed but should have failed.")
+endif()
+if(_CIF_CMP0075_WARNED)
+ message(SEND_ERROR "HAVE_STDLIB_H_4 warned but should not have")
+endif()
+unset(_CIF_CMP0075_WARNED)
include(RunCMake)
+run_cmake(CMP0075)
+
run_cmake(CheckStructHasMemberOk)
run_cmake(CheckStructHasMemberUnknownLanguage)
run_cmake(CheckStructHasMemberMissingLanguage)
--- /dev/null
+^'--parallel' invalid number '12ab' given\.
++
+Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\]
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+^'-j' invalid number '12ab' given\.
++
+Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\]
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
--- /dev/null
+(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.)
+++ /dev/null
-^CMake Warning:
- The "Visual Studio 8 2005" generator is deprecated and will be removed in a
- future version of CMake.
-
- Add CMAKE_WARN_VS8=OFF to the cache to disable this warning.$
${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget)
run_cmake_command(BuildDir--build-multiple-targets ${CMAKE_COMMAND} -E chdir ..
${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget2 --target CustomTarget3)
+ run_cmake_command(BuildDir--build-jobs-bad-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build -j 12ab)
+ run_cmake_command(BuildDir--build-jobs-good-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build -j 2)
+ run_cmake_command(BuildDir--build-jobs-good-number-trailing--target ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build -j 2 --target CustomTarget)
+ run_cmake_command(BuildDir--build--parallel-bad-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel 12ab)
+ run_cmake_command(BuildDir--build--parallel-good-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel 2)
+ run_cmake_command(BuildDir--build--parallel-good-number-trailing--target ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel 2 --target CustomTarget)
+ # No default jobs for Xcode and FreeBSD build command
+ if(NOT RunCMake_GENERATOR MATCHES "Xcode" AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ run_cmake_command(BuildDir--build-jobs-no-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build -j)
+ run_cmake_command(BuildDir--build-jobs-no-number-trailing--target ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build -j --target CustomTarget)
+ run_cmake_command(BuildDir--build--parallel-no-number ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel)
+ run_cmake_command(BuildDir--build--parallel-no-number-trailing--target ${CMAKE_COMMAND} -E chdir ..
+ ${CMAKE_COMMAND} --build BuildDir-build --parallel --target CustomTarget)
+ endif()
endfunction()
run_BuildDir()
unset(RunCMake_TEST_NO_CLEAN)
endif()
-if(RunCMake_GENERATOR MATCHES "^Visual Studio 8 2005")
- set(RunCMake_WARN_VS8 1)
- run_cmake(DeprecateVS8-WARN-ON)
- unset(RunCMake_WARN_VS8)
- run_cmake(DeprecateVS8-WARN-OFF)
-endif()
-
if(UNIX)
run_cmake_command(E_create_symlink-no-arg
${CMAKE_COMMAND} -E create_symlink
--- /dev/null
+cmake_minimum_required(VERSION 3.4)
+project(${RunCMake_TEST} C)
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+unset(VERSION)
+
+# Ignore all default paths for this test to avoid finding system Lua
+set(CMAKE_INCLUDE_PATH )
+set(CMAKE_PREFIX_PATH )
+set(CMAKE_FRAMEWORK_PATH )
+
+set(ENV{CMAKE_INCLUDE_PATH} )
+set(ENV{CMAKE_PREFIX_PATH} )
+set(ENV{CMAKE_FRAMEWORK_PATH} )
+
+set(ENV{PATH} )
+set(ENV{INCLUDE} )
+
+set(CMAKE_SYSTEM_INCLUDE_PATH )
+set(CMAKE_SYSTEM_PREFIX_PATH )
+set(CMAKE_SYSTEM_FRAMEWORK_PATH )
+
+function(require_found path version)
+ find_package(Lua ${VERSION} QUIET)
+ if(NOT "${LUA_INCLUDE_DIR}" STREQUAL "${path}")
+ message(FATAL_ERROR "LUA_INCLUDE_PATH != path: '${LUA_INCLUDE_DIR}' != '${path}'")
+ endif()
+ if(NOT LUA_VERSION_STRING MATCHES "^${version}\.[0-9]$")
+ message(FATAL_ERROR "Wrong versionfound in '${LUA_INCLUDE_DIR}': ${LUA_VERSION_STRING} != ${version}")
+ endif()
+endfunction()
+
+# Use functions for scoping and better error messages
+function(require_find path version)
+ unset(LUA_INCLUDE_DIR CACHE)
+ require_found(${lua_path} ${version})
+endfunction()
+
+function(test_prefix_path path lua_path version)
+ set(CMAKE_PREFIX_PATH ${path})
+ require_find(lua_path ${version})
+endfunction()
+
+function(test_include_path path lua_path version)
+ set(CMAKE_INCLUDE_PATH ${path})
+ require_find(lua_path ${version})
+endfunction()
+
+function(test_env_path path lua_path version)
+ set(ENV{LUA_DIR} ${path})
+ require_find(lua_path ${version})
+ unset(ENV{LUA_DIR})
+endfunction()
+
+function(test_path prefix_path lua_path version)
+ # Shortcut: Make paths relative to current list dir
+ set(prefix_path ${CMAKE_CURRENT_LIST_DIR}/${prefix_path})
+ set(lua_path ${CMAKE_CURRENT_LIST_DIR}/${lua_path})
+
+ test_prefix_path(${prefix_path} ${lua_path} ${version})
+ test_include_path(${prefix_path}/include ${lua_path} ${version})
+ test_env_path(${prefix_path} ${lua_path} ${version})
+endfunction()
+
+# Simple test
+test_path(prefix1 prefix1/include 5.3)
+# Find highest version
+test_path(prefix2 prefix2/include/lua5.3 5.3)
+foreach(ver 5.3 5.2 5.1)
+ # At least X or X.0 -> Highest
+ set(VERSION "${ver}")
+ test_path(prefix2 prefix2/include/lua5.3 5.3)
+ set(VERSION "${ver}.0")
+ test_path(prefix2 prefix2/include/lua5.3 5.3)
+ # Exactly X/X.0
+ set(VERSION "${ver}" EXACT)
+ test_path(prefix2 prefix2/include/lua${ver} ${ver})
+ set(VERSION "${ver}.0" EXACT)
+ test_path(prefix2 prefix2/include/lua${ver} ${ver})
+endforeach()
+
+# Find unknown version
+set(VERSION "5.9")
+test_path(prefix2 prefix2/include/lua5.9 5.9)
+set(VERSION "5.9" EXACT)
+test_path(prefix2 prefix2/include/lua5.9 5.9)
+
+# Set LUA_INCLUDE_DIR (non-cache) to unsuitable version
+set(LUA_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/prefix2/include/lua5.2)
+set(VERSION "5.1" EXACT)
+test_path(prefix2 prefix2/include/lua5.1 5.1)
--- /dev/null
+include(RunCMake)
+
+run_cmake(FindLuaTest)
--- /dev/null
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "3"
+#define LUA_VERSION_NUM 503
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
--- /dev/null
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "1"
+#define LUA_VERSION_NUM 501
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
--- /dev/null
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "2"
+#define LUA_VERSION_NUM 502
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
--- /dev/null
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "3"
+#define LUA_VERSION_NUM 503
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
--- /dev/null
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "9"
+#define LUA_VERSION_NUM 509
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
enable_testing()
project(test_should_fail)
+if(NOT "${matlab_root}" STREQUAL "")
+ set(Matlab_ROOT_DIR ${matlab_root})
+endif()
find_package(Matlab REQUIRED COMPONENTS MX_LIBRARY)
matlab_add_mex(
set(matlab_required REQUIRED)
endif()
+if(NOT DEFINED Matlab_ROOT_DIR AND NOT "${matlab_root}" STREQUAL "")
+ set(Matlab_ROOT_DIR ${matlab_root})
+endif()
+
find_package(Matlab ${matlab_required} COMPONENTS MX_LIBRARY)
include(RunCMake)
+
+
+if(NOT "${MCR_ROOT}" STREQUAL "")
+ if(NOT EXISTS "${MCR_ROOT}")
+ message(FATAL_ERROR "MCR does not exist ${MCR_ROOT}")
+ endif()
+ set(RunCMake_TEST_OPTIONS "-Dmatlab_root=${MCR_ROOT}")
+endif()
run_cmake(MatlabTest1)
if(RunCMake_GENERATOR MATCHES "Make" AND UNIX)
message(STATUS "RerunFindMatlab: first configuration to extract real Matlab_ROOT_DIR")
set(RunCMake_TEST_OPTIONS "-Dmatlab_required=REQUIRED")
+ if(NOT "${MCR_ROOT}" STREQUAL "")
+ set(RunCMake_TEST_OPTIONS ${RunCMake_TEST_OPTIONS} "-Dmatlab_root=${MCR_ROOT}")
+ endif()
run_cmake(MatlabTest2)
message(STATUS "RerunFindMatlab: flushing the variables")
if (NOT TARGET PkgConfig::FakePackage2)
message(FATAL_ERROR "No import target for fake package 2 with prefix path")
endif()
+
+# check that the full library path is also returned
+if (NOT FakePackage2_LINK_LIBRARIES STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a")
+ message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on first run: ${FakePackage2_LINK_LIBRARIES}")
+endif()
+
+# the information in *_LINK_LIBRARIES is not cached, so ensure is also is present on second run
+unset(FakePackage2_LINK_LIBRARIES)
+pkg_check_modules(FakePackage2 REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakepackage2)
+if (NOT FakePackage2_LINK_LIBRARIES STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a")
+ message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on second run: ${FakePackage2_LINK_LIBRARIES}")
+endif()
#include "libshared_and_static.h"
#ifndef MY_CUSTOM_CONTENT_ADDED
-#error "MY_CUSTOM_CONTENT_ADDED not defined!"
+# error "MY_CUSTOM_CONTENT_ADDED not defined!"
#endif
int libshared_and_static::Class::method() const
+++ /dev/null
-CMake Error at COMPILE_LANGUAGE-unknown-lang.cmake:4 \(target_compile_options\):
- Error evaluating generator expression:
-
- \$<COMPILE_LANGUAGE:CXX>
-
- \$<COMPILE_LANGUAGE:...> Unknown language.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
enable_language(C)
add_executable(empty empty.c)
-target_compile_options(empty PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wall>)
+target_compile_options(empty PRIVATE $<$<COMPILE_LANGUAGE:CXX>:$<TARGET_EXISTS:too,many,parameters>>)
--- /dev/null
+file(READ "${RunCMake_TEST_BINARY_DIR}/GENEX_EVAL-generated.txt" content)
+
+set(expected "BEFORE_PROPERTY1_AFTER")
+if(NOT content STREQUAL expected)
+ set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
+endif()
--- /dev/null
+^CMake Error at GENEX_EVAL-recursion1.cmake:7 \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY>>
+
+ Dependency loop found.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at GENEX_EVAL-recursion1.cmake:7 \(add_custom_target\):
+ Loop step 1
+
+ \$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY>>
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at GENEX_EVAL-recursion1.cmake:7 \(add_custom_target\):
+ Loop step 2
+
+ \$<TARGET_GENEX_EVAL:recursion,\$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY>>
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+
+enable_language(C)
+
+add_library (recursion SHARED empty.c)
+set_property (TARGET recursion PROPERTY CUSTOM_PROPERTY "$<GENEX_EVAL:$<TARGET_PROPERTY:CUSTOM_PROPERTY>>")
+
+add_custom_target (drive
+ COMMAND echo "$<TARGET_GENEX_EVAL:recursion,$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY>>"
+ DEPENDS recursion)
--- /dev/null
+^CMake Error at GENEX_EVAL-recursion2.cmake:8 \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY1>>
+
+ Dependency loop found.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at GENEX_EVAL-recursion2.cmake:8 \(add_custom_target\):
+ Loop step 1
+
+ \$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY2>>
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at GENEX_EVAL-recursion2.cmake:8 \(add_custom_target\):
+ Loop step 2
+
+ \$<TARGET_GENEX_EVAL:recursion,\$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY1>>
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+
+enable_language(C)
+
+add_library(recursion SHARED empty.c)
+set_property (TARGET recursion PROPERTY CUSTOM_PROPERTY1 "$<GENEX_EVAL:$<TARGET_PROPERTY:CUSTOM_PROPERTY2>>")
+set_property (TARGET recursion PROPERTY CUSTOM_PROPERTY2 "$<GENEX_EVAL:$<TARGET_PROPERTY:CUSTOM_PROPERTY1>>")
+
+add_custom_target (drive
+ COMMAND echo "$<TARGET_GENEX_EVAL:recursion,$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY1>>"
+ DEPENDS recursion)
--- /dev/null
+
+cmake_policy(VERSION 3.11)
+
+enable_language(C)
+
+add_library (example SHARED empty.c)
+set_property (TARGET example PROPERTY CUSTOM_PROPERTY1 "PROPERTY1")
+set_property (TARGET example PROPERTY CUSTOM_PROPERTY2 "$<TARGET_PROPERTY:CUSTOM_PROPERTY1>")
+set_property (TARGET example PROPERTY CUSTOM_PROPERTY3 "$<GENEX_EVAL:BEFORE_$<TARGET_PROPERTY:CUSTOM_PROPERTY2>_AFTER>")
+
+file(GENERATE OUTPUT "GENEX_EVAL-generated.txt" CONTENT "$<TARGET_GENEX_EVAL:example,$<TARGET_PROPERTY:example,CUSTOM_PROPERTY3>>")
run_cmake(TARGET_PROPERTY-LOCATION)
run_cmake(TARGET_PROPERTY-SOURCES)
run_cmake(LINK_ONLY-not-linking)
+run_cmake(TARGET_EXISTS-no-arg)
+run_cmake(TARGET_EXISTS-empty-arg)
+run_cmake(TARGET_EXISTS)
+run_cmake(TARGET_EXISTS-not-a-target)
+run_cmake(TARGET_NAME_IF_EXISTS-no-arg)
+run_cmake(TARGET_NAME_IF_EXISTS-empty-arg)
+run_cmake(TARGET_NAME_IF_EXISTS)
+run_cmake(TARGET_NAME_IF_EXISTS-not-a-target)
+run_cmake(TARGET_GENEX_EVAL-no-arg)
+run_cmake(TARGET_GENEX_EVAL-no-target)
+run_cmake(TARGET_GENEX_EVAL-non-valid-target)
+run_cmake(TARGET_GENEX_EVAL-recursion1)
+run_cmake(TARGET_GENEX_EVAL-recursion2)
+run_cmake(TARGET_GENEX_EVAL)
+run_cmake(GENEX_EVAL-recursion1)
+run_cmake(GENEX_EVAL-recursion2)
+run_cmake(GENEX_EVAL)
run_cmake(ImportedTarget-TARGET_BUNDLE_DIR)
run_cmake(ImportedTarget-TARGET_BUNDLE_CONTENT_DIR)
--- /dev/null
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_EXISTS-generated.txt" content)
+
+set(expected "1")
+if(NOT content STREQUAL expected)
+ set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
+endif()
--- /dev/null
+CMake Error at TARGET_EXISTS-empty-arg.cmake:2 \(file\):
+ Error evaluating generator expression:
+
+ \$<TARGET_EXISTS:>
+
+ \$<TARGET_EXISTS:tgt> expression requires a non-empty valid target name.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
--- /dev/null
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_EXISTS-generated.txt CONTENT "$<TARGET_EXISTS:${empty}>")
--- /dev/null
+CMake Error at TARGET_EXISTS-no-arg.cmake:2 \(file\):
+ Error evaluating generator expression:
+
+ \$<TARGET_EXISTS>
+
+ \$<TARGET_EXISTS> expression requires exactly one parameter.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
--- /dev/null
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_EXISTS-generated.txt CONTENT "$<TARGET_EXISTS>")
--- /dev/null
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_EXISTS-not-a-target-generated.txt" content)
+
+set(expected "0")
+if(NOT content STREQUAL expected)
+ set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
+endif()
--- /dev/null
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_EXISTS-not-a-target-generated.txt CONTENT "$<TARGET_EXISTS:just-random-string>")
--- /dev/null
+cmake_policy(SET CMP0070 NEW)
+add_custom_target(foo)
+file(GENERATE OUTPUT TARGET_EXISTS-generated.txt CONTENT "$<TARGET_EXISTS:foo>")
--- /dev/null
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_GENEX_EVAL-generated.txt" content)
+
+set(expected "BEFORE_PROPERTY1_AFTER")
+if(NOT content STREQUAL expected)
+ set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
+endif()
--- /dev/null
+^CMake Error at TARGET_GENEX_EVAL-no-arg.cmake:4 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<TARGET_GENEX_EVAL:>
+
+ \$<TARGET_GENEX_EVAL> expression requires 2 comma separated parameters, but
+ got 1 instead.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+
+cmake_policy(VERSION 3.11)
+
+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$<TARGET_GENEX_EVAL:>.c"
+)
+add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")
--- /dev/null
+^CMake Error at TARGET_GENEX_EVAL-no-target.cmake:2 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<TARGET_GENEX_EVAL:,>
+
+ \$<TARGET_GENEX_EVAL:tgt, ...> expression requires a non-empty valid target
+ name.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+
+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$<TARGET_GENEX_EVAL:,>.c"
+)
+add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")
--- /dev/null
+^CMake Error at TARGET_GENEX_EVAL-non-valid-target.cmake:2 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<TARGET_GENEX_EVAL:bad-target,>
+
+ \$<TARGET_GENEX_EVAL:tgt, ...> target "bad-target" not found.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+
+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$<TARGET_GENEX_EVAL:bad-target,>.c"
+)
+add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")
--- /dev/null
+^CMake Error at TARGET_GENEX_EVAL-recursion1.cmake:7 \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<TARGET_GENEX_EVAL:recursion,\$<TARGET_PROPERTY:CUSTOM_PROPERTY>>
+
+ Self reference on target "recursion".
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+
+enable_language(C)
+
+add_library (recursion SHARED empty.c)
+set_property (TARGET recursion PROPERTY CUSTOM_PROPERTY "$<TARGET_GENEX_EVAL:recursion,$<TARGET_PROPERTY:CUSTOM_PROPERTY>>")
+
+add_custom_target (drive
+ COMMAND echo "$<TARGET_GENEX_EVAL:recursion,$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY>>"
+ DEPENDS recursion)
--- /dev/null
+^CMake Error at TARGET_GENEX_EVAL-recursion2.cmake:10 \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<TARGET_GENEX_EVAL:recursion1,\$<TARGET_PROPERTY:recursion1,CUSTOM_PROPERTY1>>
+
+ Dependency loop found.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at TARGET_GENEX_EVAL-recursion2.cmake:10 \(add_custom_target\):
+ Loop step 1
+
+ \$<TARGET_GENEX_EVAL:recursion2,\$<TARGET_PROPERTY:recursion2,CUSTOM_PROPERTY2>>
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at TARGET_GENEX_EVAL-recursion2.cmake:10 \(add_custom_target\):
+ Loop step 2
+
+ \$<TARGET_GENEX_EVAL:recursion1,\$<TARGET_PROPERTY:recursion1,CUSTOM_PROPERTY1>>
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+
+enable_language(C)
+
+add_library (recursion1 SHARED empty.c)
+set_property (TARGET recursion1 PROPERTY CUSTOM_PROPERTY1 "$<TARGET_GENEX_EVAL:recursion2,$<TARGET_PROPERTY:recursion2,CUSTOM_PROPERTY2>>")
+
+add_library (recursion2 SHARED empty.c)
+set_property (TARGET recursion2 PROPERTY CUSTOM_PROPERTY2 "$<TARGET_GENEX_EVAL:recursion1,$<TARGET_PROPERTY:recursion1,CUSTOM_PROPERTY1>>")
+
+add_custom_target (drive
+ COMMAND echo "$<TARGET_GENEX_EVAL:recursion1,$<TARGET_PROPERTY:recursion1,CUSTOM_PROPERTY1>>"
+ DEPENDS recursion)
--- /dev/null
+
+cmake_policy(VERSION 3.11)
+
+enable_language(C)
+
+add_library (example SHARED empty.c)
+set_property (TARGET example PROPERTY CUSTOM_PROPERTY1 "PROPERTY1")
+set_property (TARGET example PROPERTY CUSTOM_PROPERTY2 "BEFORE_$<TARGET_PROPERTY:CUSTOM_PROPERTY1>_AFTER")
+
+file(GENERATE OUTPUT "TARGET_GENEX_EVAL-generated.txt" CONTENT "$<TARGET_GENEX_EVAL:example,$<TARGET_PROPERTY:example,CUSTOM_PROPERTY2>>")
--- /dev/null
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_NAME_IF_EXISTS-generated.txt" content)
+
+set(expected "foo")
+if(NOT content STREQUAL expected)
+ set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
+endif()
--- /dev/null
+CMake Error at TARGET_NAME_IF_EXISTS-empty-arg.cmake:2 \(file\):
+ Error evaluating generator expression:
+
+ \$<TARGET_NAME_IF_EXISTS:>
+
+ \$<TARGET_NAME_IF_EXISTS:tgt> expression requires a non-empty valid target
+ name.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
--- /dev/null
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-generated.txt CONTENT "$<TARGET_NAME_IF_EXISTS:${empty}>")
--- /dev/null
+CMake Error at TARGET_NAME_IF_EXISTS-no-arg.cmake:2 \(file\):
+ Error evaluating generator expression:
+
+ \$<TARGET_NAME_IF_EXISTS>
+
+ \$<TARGET_NAME_IF_EXISTS> expression requires exactly one parameter.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
--- /dev/null
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-generated.txt CONTENT "$<TARGET_NAME_IF_EXISTS>")
--- /dev/null
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_NAME_IF_EXISTS-not-a-target-generated.txt" content)
+
+if(content)
+ set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected an empty string")
+endif()
--- /dev/null
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-not-a-target-generated.txt CONTENT "$<TARGET_NAME_IF_EXISTS:just-random-string>")
--- /dev/null
+cmake_policy(SET CMP0070 NEW)
+add_custom_target(foo)
+file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-generated.txt CONTENT "$<TARGET_NAME_IF_EXISTS:foo>")
--- /dev/null
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+ Generator
+
+ .*
+
+ given toolset and version specification
+
+ Test Toolset,version=Bad Toolset Version
+
+ contains an invalid version specification.
--- /dev/null
+message(FATAL_ERROR "This should not be reached!")
--- /dev/null
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+ Generator
+
+ .*
+
+ given toolset specification
+
+ Test Toolset,version=Test Toolset Version,version=Test Toolset Version
+
+ that contains duplicate field key 'version'\.$
--- /dev/null
+message(FATAL_ERROR "This should not be reached!")
run_cmake(BadToolsetHostArch)
set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x64")
run_cmake(BadToolsetHostArchTwice)
+ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 15")
+ set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version")
+ run_cmake(TestToolsetVersionBoth)
+ set(RunCMake_GENERATOR_TOOLSET ",version=Test Toolset Version")
+ run_cmake(TestToolsetVersionOnly)
+ set(RunCMake_GENERATOR_TOOLSET "version=Test Toolset Version")
+ run_cmake(TestToolsetVersionOnly)
+ set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Bad Toolset Version")
+ run_cmake(BadToolsetVersion)
+ set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version,version=Test Toolset Version")
+ run_cmake(BadToolsetVersionTwice)
+ endif()
else()
set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64")
run_cmake(BadToolsetHostArch)
--- /dev/null
+-- CMAKE_VS_PLATFORM_TOOLSET='Test Toolset'
+-- CMAKE_VS_PLATFORM_TOOLSET_VERSION='Test Toolset Version'
--- /dev/null
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_VERSION='${CMAKE_VS_PLATFORM_TOOLSET_VERSION}'")
--- /dev/null
+-- CMAKE_VS_PLATFORM_TOOLSET='v[0-9]+'
+-- CMAKE_VS_PLATFORM_TOOLSET_VERSION='Test Toolset Version'
--- /dev/null
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_VERSION='${CMAKE_VS_PLATFORM_TOOLSET_VERSION}'")
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
#include <iostream>
--- /dev/null
+^ninja: no work to do
--- /dev/null
+enable_language(C)
+add_executable(hello hello.c)
--- /dev/null
+set(ENV{CMAKE_NINJA_FORCE_RESPONSE_FILE} 1)
+enable_language(C)
--- /dev/null
+set(ENV{CMAKE_NINJA_FORCE_RESPONSE_FILE} 1)
+enable_language(CXX)
--- /dev/null
+set(ENV{CMAKE_NINJA_FORCE_RESPONSE_FILE} 1)
+enable_language(Fortran)
endfunction()
run_NinjaToolMissing()
+function(run_NoWorkToDo)
+ run_cmake(NoWorkToDo)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/NoWorkToDo-build)
+ run_cmake_command(NoWorkToDo-build ${CMAKE_COMMAND} --build .)
+ run_cmake_command(NoWorkToDo-nowork ${CMAKE_COMMAND} --build . -- -d explain)
+endfunction()
+run_NoWorkToDo()
+
function(run_CMP0058 case)
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0058-${case}-build)
run_cmake(CustomCommandDepfile)
+run_cmake(RspFileC)
+run_cmake(RspFileCXX)
+if(TEST_Fortran)
+ run_cmake(RspFileFortran)
+endif()
+
function(run_CommandConcat)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CommandConcat-build)
set(RunCMake_TEST_NO_CLEAN 1)
+++ /dev/null
-CMake Error at BadObjSource2.cmake:1 \(add_library\):
- OBJECT library "A" contains:
-
- bad.obj
-
- but may contain only sources that compile, header files, and other files
- that would not affect linking of a normal library.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
-cmake_minimum_required(VERSION 2.8.4)
+cmake_minimum_required(VERSION 3.10)
project(${RunCMake_TEST} C)
include(${RunCMake_TEST}.cmake)
+++ /dev/null
-CMake Error at ExportNotSupported.cmake:[0-9]+ \(export\):
- export given OBJECT library "A" which may not be exported under Xcode with
- multiple architectures.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+++ /dev/null
-add_library(A OBJECT a.c)
-export(TARGETS A FILE AExport.cmake)
--- /dev/null
+CMake Error: install\(EXPORT "exp" ...\) includes target "UseA" which requires target "A" that is not in the export set.
--- /dev/null
+add_library(A OBJECT a.c)
+add_library(UseA STATIC)
+target_link_libraries(UseA PUBLIC A)
+
+install(TARGETS UseA EXPORT exp ARCHIVE DESTINATION lib)
+install(EXPORT exp DESTINATION lib/cmake/exp)
--- /dev/null
+add_library(A OBJECT a.c)
+add_library(UseA STATIC)
+target_link_libraries(UseA PUBLIC A)
+
+install(TARGETS UseA A EXPORT exp ARCHIVE DESTINATION lib)
+install(EXPORT exp DESTINATION lib/cmake/exp)
CMake Error at InstallNotSupported.cmake:[0-9]+ \(install\):
- install TARGETS given OBJECT library "A" which may not be installed under
- Xcode with multiple architectures.
+ install TARGETS given OBJECT library "A" whose objects may not be installed
+ under Xcode with multiple architectures.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
+++ /dev/null
-CMake Error at LinkObjLHS.cmake:2 \(target_link_libraries\):
- Object library target "AnObjLib" may not link to anything.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+++ /dev/null
-add_library(AnObjLib OBJECT a.c)
-target_link_libraries(AnObjLib OtherLib)
--- /dev/null
+project(LinkObjLHSShared C)
+
+add_library(OtherLib SHARED a.c)
+target_compile_definitions(OtherLib INTERFACE REQUIRED)
+
+add_library(AnObjLib OBJECT requires.c)
+target_link_libraries(AnObjLib OtherLib)
--- /dev/null
+project(LinkObjLHSStatic C)
+
+add_library(OtherLib STATIC a.c)
+target_compile_definitions(OtherLib INTERFACE REQUIRED)
+
+add_library(AnObjLib OBJECT requires.c)
+target_link_libraries(AnObjLib OtherLib)
+++ /dev/null
-CMake Error at LinkObjRHS1.cmake:3 \(target_link_libraries\):
- Target "AnObjLib" of type OBJECT_LIBRARY may not be linked into another
- target. One may link only to INTERFACE, STATIC or SHARED libraries, or to
- executables with the ENABLE_EXPORTS property set.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+++ /dev/null
-add_library(A STATIC a.c)
-add_library(AnObjLib OBJECT a.c)
-target_link_libraries(A AnObjLib)
+++ /dev/null
-CMake Error at LinkObjRHS2.cmake:1 \(add_library\):
- Target "A" links to OBJECT library "AnObjLib" but this is not allowed. One
- may link only to STATIC or SHARED libraries, or to executables with the
- ENABLE_EXPORTS property set.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+++ /dev/null
-add_library(A SHARED a.c)
-target_link_libraries(A AnObjLib)
-add_library(AnObjLib OBJECT a.c)
--- /dev/null
+[1-9][0-9]*
--- /dev/null
+REQUIRED needs to be defined
--- /dev/null
+cmake_policy(SET CMP0022 NEW)
+
+enable_language(C)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+
+add_library(AnotherObjLib OBJECT b.c)
+target_link_libraries(AnotherObjLib PRIVATE AnObjLib)
+
+add_executable(exe exe.c)
+target_link_libraries(exe AnotherObjLib)
--- /dev/null
+[1-9][0-9]*
--- /dev/null
+cmake_policy(SET CMP0022 NEW)
+
+enable_language(C)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+
+add_library(AnotherObjLib OBJECT b.c)
+target_link_libraries(AnotherObjLib PUBLIC AnObjLib)
+
+add_executable(exe exe.c)
+target_link_libraries(exe AnotherObjLib)
--- /dev/null
+enable_language(C)
+
+add_definitions(-DCOMPILE_FOR_SHARED_LIB)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+set_target_properties(AnObjLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
+
+add_library(A SHARED b.c $<TARGET_OBJECTS:AnObjLib>)
+target_link_libraries(A PUBLIC AnObjLib)
+
+add_executable(exe exe.c)
+target_link_libraries(exe A)
--- /dev/null
+enable_language(C)
+
+add_definitions(-DCOMPILE_FOR_SHARED_LIB)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+set_target_properties(AnObjLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
+
+add_library(A SHARED b.c)
+target_link_libraries(A PRIVATE AnObjLib)
+target_compile_definitions(A INTERFACE $<TARGET_PROPERTY:AnObjLib,INTERFACE_COMPILE_DEFINITIONS>)
+
+add_executable(exe exe.c)
+target_link_libraries(exe A)
--- /dev/null
+enable_language(C)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+
+add_library(A STATIC b.c $<TARGET_OBJECTS:AnObjLib>)
+target_link_libraries(A PUBLIC AnObjLib)
+
+add_executable(exe exe.c)
+target_link_libraries(exe A)
--- /dev/null
+enable_language(C)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+
+add_library(A STATIC b.c)
+target_link_libraries(A PRIVATE AnObjLib)
+target_compile_definitions(A INTERFACE $<TARGET_PROPERTY:AnObjLib,INTERFACE_COMPILE_DEFINITIONS>)
+
+add_executable(exe exe.c)
+target_link_libraries(exe A)
+++ /dev/null
-CMake Error at ObjWithObj.cmake:2 \(add_library\):
- Only executables and non-OBJECT libraries may reference target objects.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
run_cmake(BadObjSource1)
run_cmake(BadObjSource2)
if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
- run_cmake(ExportNotSupported)
run_cmake(ImportNotSupported)
run_cmake(InstallNotSupported)
else()
- run_cmake(Export)
run_cmake(Import)
run_cmake(Install)
+ run_cmake(InstallLinkedObj1)
+ run_cmake(InstallLinkedObj2)
endif()
-run_cmake(LinkObjLHS)
-run_cmake(LinkObjRHS1)
-run_cmake(LinkObjRHS2)
+run_cmake(Export)
+
+function (run_object_lib_build name)
+ # Use a single build tree for a few tests without cleaning.
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(${name})
+ run_cmake_command(${name}-build ${CMAKE_COMMAND} --build .)
+endfunction ()
+
+function (run_object_lib_build2 name)
+ # Use a single build tree for a few tests without cleaning.
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(${name})
+ set(RunCMake_TEST_OUTPUT_MERGE 1)
+ run_cmake_command(${name}-build ${CMAKE_COMMAND} --build .)
+endfunction ()
+
+run_object_lib_build(LinkObjLHSShared)
+run_object_lib_build(LinkObjLHSStatic)
+run_object_lib_build(LinkObjRHSShared)
+run_object_lib_build(LinkObjRHSStatic)
+run_object_lib_build2(LinkObjRHSObject)
+run_object_lib_build(LinkObjRHSShared2)
+run_object_lib_build(LinkObjRHSStatic2)
+run_object_lib_build2(LinkObjRHSObject2)
+
run_cmake(MissingSource)
run_cmake(ObjWithObj)
run_cmake(OwnSources)
-int a(void)
+#if defined(_WIN32) && defined(COMPILE_FOR_SHARED_LIB)
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT
+#endif
+
+EXPORT int a(void)
{
return 0;
}
-int b(void)
+#if defined(_WIN32) && defined(COMPILE_FOR_SHARED_LIB)
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT
+#endif
+
+extern int a(void);
+EXPORT int b()
{
- return 0;
+ return a();
}
+#ifndef REQUIRED
+# error "REQUIRED needs to be defined"
+#endif
--- /dev/null
+#if defined(_WIN32) && defined(COMPILE_FOR_SHARED_LIB)
+# define IMPORT __declspec(dllimport)
+#else
+# define IMPORT
+#endif
+
+extern IMPORT int b(void);
+int main()
+{
+ return b();
+}
+#ifndef REQUIRED
+# error "REQUIRED needs to be defined"
+#endif
--- /dev/null
+#ifdef REQUIRED
+int required()
+{
+ return 0;
+}
+#else
+# error "REQUIRED not defined"
+#endif
if(APPLE)
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0025=NEW)
endif()
- if(RunCMake_GENERATOR MATCHES "^Visual Studio 8 2005" AND NOT RunCMake_WARN_VS8)
- list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_WARN_VS8=OFF)
- endif()
if(RunCMake_MAKE_PROGRAM)
list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}")
endif()
"|clang[^:]*: warning: the object size sanitizer has no effect at -O0, but is explicitly enabled:"
"|Error kstat returned"
"|Hit xcodebuild bug"
+ "|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type"
+ "|ld: 0711-224 WARNING: Duplicate symbol: .__init_aix_libgcc_cxa_atexit"
+ "|ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information"
"|[^\n]*is a member of multiple groups"
"|[^\n]*from Time Machine by path"
"|[^\n]*Bullseye Testing Technology"
--- /dev/null
+CMake Error at NullAfterBackslash.cmake:1:
+ Parse error. Function missing ending "\)". Instead found bad character
+ with text "\\".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
run_cmake(Escape1)
run_cmake(Escape2)
run_cmake(EscapeCharsAllowed)
+run_cmake(NullAfterBackslash)
run_cmake(NullTerminatedArgument)
include("${RunCMake_SOURCE_DIR}/EscapeCharsDisallowed.cmake")
run_cmake(ParenNoSpace0)
\* CMP0065
\* CMP0068
\* CMP0069
+ \* CMP0073
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
run_cmake(VsTargetsFileReferences)
run_cmake(VsCustomProps)
run_cmake(VsDebuggerWorkingDir)
+run_cmake(VsDebuggerCommand)
run_cmake(VsCSharpCustomTags)
run_cmake(VsCSharpReferenceProps)
run_cmake(VsCSharpWithoutSources)
+run_cmake(VsSdkDirectories)
--- /dev/null
+^CMake Deprecation Warning in CMakeLists.txt:
+ The C# target "foo" is of type STATIC_LIBRARY. This is discouraged \(and
+ may be disabled in future\). Make it a SHARED library instead.$
foreach(e ${fileExtensions})
set(currentFile "${CMAKE_CURRENT_BINARY_DIR}/foo.${e}")
list(APPEND fileNames ${currentFile})
- execute_process(COMMAND ${CMAKE_COMMAND} -E touch
- "${currentFile}")
+ file(TOUCH "${currentFile}")
string(TOUPPER ${e} eUC)
set_source_files_properties("${currentFile}"
PROPERTIES
--- /dev/null
+^CMake Deprecation Warning in CMakeLists.txt:
+ The C# target "foo2" is of type STATIC_LIBRARY. This is discouraged \(and
+ may be disabled in future\). Make it a SHARED library instead.
+
+
+CMake Deprecation Warning in CMakeLists.txt:
+ The C# target "foo" is of type STATIC_LIBRARY. This is discouraged \(and
+ may be disabled in future\). Make it a SHARED library instead.$
--- /dev/null
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
+ return()
+endif()
+
+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")
+ message(STATUS "foo.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()
--- /dev/null
+enable_language(CXX)
+add_library(foo foo.cpp)
+
+set_target_properties(foo PROPERTIES
+ VS_DEBUGGER_COMMAND "my-debugger-command")
--- /dev/null
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
+ return()
+endif()
+
+set(ExecutablePathSet FALSE)
+set(IncludePathSet FALSE)
+set(ReferencePathSet FALSE)
+set(LibraryPathSet FALSE)
+set(LibraryWPathSet FALSE)
+set(SourcePathSet FALSE)
+set(ExcludePathSet FALSE)
+
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+ if(line MATCHES "^ *<ExecutablePath[^>]*>([^<>]+)</ExecutablePath>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "$(VC_ExecutablePath_x86);C:\\Program Files\\Custom-SDK\\;")
+ message(STATUS "foo.vcxproj has executable path set")
+ set(ExecutablePathSet TRUE)
+ endif()
+ elseif(line MATCHES "^ *<IncludePath[^>]*>([^<>]+)</IncludePath>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "$(VC_IncludePath);C:\\Program Files\\Custom-SDK\\;")
+ message(STATUS "foo.vcxproj has include path set")
+ set(IncludePathSet TRUE)
+ endif()
+ elseif(line MATCHES "^ *<ReferencePath[^>]*>([^<>]+)</ReferencePath>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "$(VC_ReferencesPath_x86);C:\\Program Files\\Custom-SDK\\;")
+ message(STATUS "foo.vcxproj has reference path set")
+ set(ReferencePathSet TRUE)
+ endif()
+ elseif(line MATCHES "^ *<LibraryPath[^>]*>([^<>]+)</LibraryPath>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "$(VC_LibraryPath_x86);C:\\Program Files\\Custom-SDK\\;")
+ message(STATUS "foo.vcxproj has library path set")
+ set(LibraryPathSet TRUE)
+ endif()
+ elseif(line MATCHES "^ *<LibraryWPath[^>]*>([^<>]+)</LibraryWPath>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "$(WindowsSDK_MetadataPath);C:\\Program Files\\Custom-SDK\\;")
+ message(STATUS "foo.vcxproj has library WinRT path set")
+ set(LibraryWPathSet TRUE)
+ endif()
+ elseif(line MATCHES "^ *<SourcePath[^>]*>([^<>]+)</SourcePath>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "$(VC_SourcePath);C:\\Program Files\\Custom-SDK\\;")
+ message(STATUS "foo.vcxproj has source path set")
+ set(SourcePathSet TRUE)
+ endif()
+ elseif(line MATCHES "^ *<ExcludePath[^>]*>([^<>]+)</ExcludePath>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "$(VC_IncludePath);C:\\Program Files\\Custom-SDK\\;")
+ message(STATUS "foo.vcxproj has exclude path set")
+ set(ExcludePathSet TRUE)
+ endif()
+ endif()
+endforeach()
+
+if(NOT ExecutablePathSet)
+ set(RunCMake_TEST_FAILED "ExecutablePath not found or not set correctly.")
+ return()
+endif()
+
+if(NOT IncludePathSet)
+ set(RunCMake_TEST_FAILED "IncludePath not found or not set correctly.")
+ return()
+endif()
+
+if(NOT ReferencePathSet)
+ set(RunCMake_TEST_FAILED "ReferencePath not found or not set correctly.")
+ return()
+endif()
+
+if(NOT LibraryPathSet)
+ set(RunCMake_TEST_FAILED "LibraryPath not found or not set correctly.")
+ return()
+endif()
+
+if(NOT LibraryWPathSet)
+ set(RunCMake_TEST_FAILED "LibraryWPath not found or not set correctly.")
+ return()
+endif()
+
+if(NOT SourcePathSet)
+ set(RunCMake_TEST_FAILED "SourcePath not found or not set correctly.")
+ return()
+endif()
+
+if(NOT ExcludePathSet)
+ set(RunCMake_TEST_FAILED "ExcludePath not found or not set correctly.")
+ return()
+endif()
--- /dev/null
+enable_language(CXX)
+
+set(CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES "$(VC_ExecutablePath_x86);C:\\Program Files\\Custom-SDK\\;")
+set(CMAKE_VS_SDK_INCLUDE_DIRECTORIES "$(VC_IncludePath);C:\\Program Files\\Custom-SDK\\;")
+set(CMAKE_VS_SDK_REFERENCE_DIRECTORIES "$(VC_ReferencesPath_x86);C:\\Program Files\\Custom-SDK\\;")
+set(CMAKE_VS_SDK_LIBRARY_DIRECTORIES "$(VC_LibraryPath_x86);C:\\Program Files\\Custom-SDK\\;")
+set(CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES "$(WindowsSDK_MetadataPath);C:\\Program Files\\Custom-SDK\\;")
+set(CMAKE_VS_SDK_SOURCE_DIRECTORIES "$(VC_SourcePath);C:\\Program Files\\Custom-SDK\\;")
+set(CMAKE_VS_SDK_EXCLUDE_DIRECTORIES "$(VC_IncludePath);C:\\Program Files\\Custom-SDK\\;")
+
+add_library(foo foo.cpp)
--- /dev/null
+cmake_minimum_required(VERSION 3.11)
+project(@CASE_NAME@ NONE)
+include("@RunCMake_SOURCE_DIR@/@CASE_NAME@.cmake")
--- /dev/null
+set(CTEST_PROJECT_NAME "CTestTestWorkingDir.@CASE_NAME@")
--- /dev/null
+include(RunCTest)
+
+run_ctest(dirNotExist)
+run_ctest(buildAndTestNoBuildDir
+ --build-and-test
+ ${RunCMake_BINARY_DIR}/buildAndTestNoBuildDir
+ ${RunCMake_BINARY_DIR}/buildAndTestNoBuildDir/CMakeLists.txt # Deliberately a file
+ --build-generator "${RunCMake_GENERATOR}"
+)
--- /dev/null
+if(EXISTS ${RunCMake_TEST_BINARY_DIR}/CMakeCache.txt)
+ set(RunCMake_TEST_FAILED "Default build dir ${RunCMake_TEST_BINARY_DIR} was used, should not have been")
+endif()
--- /dev/null
+^[^0][0-9]*$
--- /dev/null
+Failed to change working directory to .*[/\\]buildAndTestNoBuildDir[/\\]CMakeLists.txt :
--- /dev/null
+# We want a single test that always passes. We should never actually get to
+# configure with this file, so we use a successful configure-build-test
+# sequence to denote failure of the test case.
+include(CTest)
+add_test(NAME willPass
+ COMMAND ${CMAKE_COMMAND} -E touch someFile.txt
+)
--- /dev/null
+Failed to change working directory to .*[/\\]dirNotExist-build[/\\]thisDirWillNotExist :
--- /dev/null
+Test project .*/Tests/RunCMake/WorkingDirectory/dirNotExist-build
+.* +Start 1: dirNotExist
+1/1 Test #1: dirNotExist +\.+\*\*\*Not Run +[0-9.]+ sec
++
+0% tests passed, 1 tests failed out of 1
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests FAILED:
+.* +1 - dirNotExist \(Not Run\)$
--- /dev/null
+include(CTest)
+
+add_test(NAME dirNotExist
+ COMMAND ${CMAKE_COMMAND} -E touch someFile.txt
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/thisDirWillNotExist
+)
--- /dev/null
+cmake_minimum_required(VERSION 3.11)
+
+set(CTEST_SITE "test-site")
+set(CTEST_BUILD_NAME "test-build-name")
+set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@")
+set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build")
+set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@")
+set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@")
+set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@")
+set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}")
+
+ctest_start(Experimental)
+ctest_configure()
+ctest_build()
+ctest_test()
CMake Error at .*Modules/WriteCompilerDetectionHeader.cmake:[0-9]+ \(message\):
Unsupported feature not_a_feature.
Call Stack \(most recent call first\):
+ .*Modules/WriteCompilerDetectionHeader.cmake:[0-9]+ \(_check_feature_lists\)
InvalidFeature.cmake:4 \(write_compiler_detection_header\)
CMakeLists.txt:3 \(include\)
#include <TargetConditionals.h>
#if TARGET_OS_OSX
-#if __MAC_OS_X_VERSION_MIN_REQUIRED != __MAC_10_11
-#error macOS deployment version mismatch
-#endif
+# if __MAC_OS_X_VERSION_MIN_REQUIRED != __MAC_10_11
+# error macOS deployment version mismatch
+# endif
#elif TARGET_OS_IOS
-#if __IPHONE_OS_VERSION_MIN_REQUIRED != __IPHONE_9_1
-#error iOS deployment version mismatch
-#endif
+# if __IPHONE_OS_VERSION_MIN_REQUIRED != __IPHONE_9_1
+# error iOS deployment version mismatch
+# endif
#elif TARGET_OS_WATCH
-#if __WATCH_OS_VERSION_MIN_REQUIRED != __WATCHOS_2_0
-#error watchOS deployment version mismatch
-#endif
+# if __WATCH_OS_VERSION_MIN_REQUIRED != __WATCHOS_2_0
+# error watchOS deployment version mismatch
+# endif
#elif TARGET_OS_TV
-#if __TV_OS_VERSION_MIN_REQUIRED != __TVOS_9_0
-#error tvOS deployment version mismatch
-#endif
+# if __TV_OS_VERSION_MIN_REQUIRED != __TVOS_9_0
+# error tvOS deployment version mismatch
+# endif
#else
-#error unknown OS
+# error unknown OS
#endif
void foo()
--- /dev/null
+enable_language(CXX)
+
+add_custom_command(OUTPUT generated.cpp
+ MAIN_DEPENDENCY a.c
+ COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/generate-once.cmake ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp
+ VERBATIM)
+
+add_executable(exe1 ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp)
+add_executable(exe2 ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp)
+add_executable(exe3 ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp)
+
+add_dependencies(exe1 exe2)
+add_dependencies(exe3 exe1)
if(${RunCMake_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
run_cmake(RemoveEmptyCommands)
endif()
+
+run_cmake(AssigningMultipleTargets)
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AssigningMultipleTargets-build)
+set(RunCMake_TEST_NO_CLEAN 1)
+run_cmake_command(AssigningMultipleTargets-build ${CMAKE_COMMAND} --build .)
+unset(RunCMake_TEST_BINARY_DIR)
+unset(RunCMake_TEST_NO_CLEAN)
--- /dev/null
+void a()
+{
+}
--- /dev/null
+if (${CMAKE_ARGC} LESS 4)
+ message(FATAL_ERROR "Too few arguments")
+endif()
+set(output "${CMAKE_ARGV3}")
+if(EXISTS ${output})
+ message(FATAL_ERROR "${output} already exists")
+endif()
+file(WRITE ${output} "int main() { return 0; }\n")
--- /dev/null
+-- warn_LIB_DEPENDS='general;bar;'
+-- old_LIB_DEPENDS='general;bar;'
+-- new_LIB_DEPENDS=''
--- /dev/null
+enable_language(C)
+
+add_library(warn empty.c)
+target_link_libraries(warn bar)
+message(STATUS "warn_LIB_DEPENDS='${warn_LIB_DEPENDS}'")
+
+cmake_policy(SET CMP0073 OLD)
+add_library(old empty.c)
+target_link_libraries(old bar)
+message(STATUS "old_LIB_DEPENDS='${old_LIB_DEPENDS}'")
+
+cmake_policy(SET CMP0073 NEW)
+add_library(new empty.c)
+target_link_libraries(new bar)
+message(STATUS "new_LIB_DEPENDS='${new_LIB_DEPENDS}'")
+if(DEFINED new_LIB_DEPENDS)
+ message(FATAL_ERROR "new_LIB_DEPENDS set but should not be")
+endif()
-^CMake Error at OBJECTwithNoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
- Object library target \"TestObjectLibWithoutSources\" may not link to
- anything.
+^CMake Error at OBJECTwithNoSourcesButLinkObjects.cmake:[0-9]+ \(add_library\):
+ No SOURCES given to target: TestObjectLibWithoutSources
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$
+++ /dev/null
-^CMake Error at OBJECTwithOnlyObjectSources.cmake:[0-9]+ \(add_library\):
- OBJECT library \"TestObjectLibWithoutSources\" contains:
-
- [^
-]*test(\.cpp)?\.o(bj)?
-
- but may contain only sources that compile, header files, and other files
- that would not affect linking of a normal library.
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-
-
-CMake Error at OBJECTwithOnlyObjectSources.cmake:[0-9]+ \(add_library\):
- Only executables and non-OBJECT libraries may reference target objects.
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)$
include(RunCMake)
+run_cmake(CMP0073)
+
run_cmake(INTERFACEwithNoSources)
run_cmake(OBJECTwithNoSources)
run_cmake(STATICwithNoSources)
--- /dev/null
+cmake_minimum_required(VERSION 3.11...99.0 SOME_FUTURE_OPTION)
--- /dev/null
+^CMAKE_MINIMUM_REQUIRED_VERSION='3\.10'
+CMP0071='NEW'
+CMP0072='NEW'
+CMP0073=''$
--- /dev/null
+cmake_minimum_required(VERSION 3.10...3.11)
+message("CMAKE_MINIMUM_REQUIRED_VERSION='${CMAKE_MINIMUM_REQUIRED_VERSION}'")
+foreach(policy CMP0071 CMP0072 CMP0073)
+ cmake_policy(GET ${policy} status)
+ message("${policy}='${status}'")
+endforeach()
--- /dev/null
+^CMake Error at RangeBad.cmake:1 \(cmake_minimum_required\):
+ cmake_minimum_required VERSION "3.11..." does not have a version on both
+ sides of "...".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:2 \(cmake_minimum_required\):
+ cmake_minimum_required VERSION "...3.11" does not have a version on both
+ sides of "...".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:3 \(cmake_minimum_required\):
+ cmake_minimum_required VERSION "..." does not have a version on both sides
+ of "...".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:4 \(cmake_minimum_required\):
+ Invalid policy max version value "4". A numeric
+ major.minor\[.patch\[.tweak\]\] must be given.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:5 \(cmake_minimum_required\):
+ Policy VERSION range "3.11...3.10" specifies a larger minimum than maximum.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:6 \(cmake_policy\):
+ cmake_policy VERSION "3.11..." does not have a version on both sides of
+ "...".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:7 \(cmake_policy\):
+ cmake_policy VERSION "...3.11" does not have a version on both sides of
+ "...".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:8 \(cmake_policy\):
+ cmake_policy VERSION "..." does not have a version on both sides of "...".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:9 \(cmake_policy\):
+ Invalid policy max version value "4". A numeric
+ major.minor\[.patch\[.tweak\]\] must be given.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:10 \(cmake_policy\):
+ Policy VERSION range "3.11...3.10" specifies a larger minimum than maximum.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+cmake_minimum_required(VERSION 3.11...)
+cmake_minimum_required(VERSION ...3.11)
+cmake_minimum_required(VERSION ...)
+cmake_minimum_required(VERSION 3.11...4)
+cmake_minimum_required(VERSION 3.11...3.10)
+cmake_policy(VERSION 3.11...)
+cmake_policy(VERSION ...3.11)
+cmake_policy(VERSION ...)
+cmake_policy(VERSION 3.11...4)
+cmake_policy(VERSION 3.11...3.10)
run_cmake(Before24)
run_cmake(CompatBefore24)
+run_cmake(Future)
run_cmake(PolicyBefore24)
+run_cmake(Range)
+run_cmake(RangeBad)
+run_cmake(Unknown)
--- /dev/null
+^CMake Error at Unknown.cmake:1 \(cmake_minimum_required\):
+ cmake_minimum_required called with unknown argument "SOME_UNKNOWN_OPTION".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
--- /dev/null
+cmake_minimum_required(VERSION 3.11 SOME_UNKNOWN_OPTION)
--- /dev/null
+check_tag_contents("^19551112-2204\nContinuousTrack\nContinuous\n$")
--- /dev/null
+^Model given in TAG does not match model given in ctest_start\(\)$
--- /dev/null
+Run dashboard with model Experimental
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendDifferentModel
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendDifferentModel-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendDifferentModel/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ContinuousTrack
+ Use ContinuousTrack tag: [0-9-]+
--- /dev/null
+^Track given in TAG does not match track given in ctest_start\(\)$
--- /dev/null
+Run dashboard with to-be-determined model
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendDifferentTrack
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendDifferentTrack-build
+ Track: ExperimentalDifferent
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendDifferentTrack/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ExperimentalDifferent
+ Use ExperimentalDifferent tag: [0-9-]+
--- /dev/null
+Run dashboard with model Continuous
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendNoMatchingTrack
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendNoMatchingTrack-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendNoMatchingTrack/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - SomeWeirdTrackName
+ Use SomeWeirdTrackName tag: [0-9-]+
--- /dev/null
+check_tag_contents("^19551112-2204\nContinuousTrack\nContinuous\n$")
--- /dev/null
+Run dashboard with to-be-determined model
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendNoModel
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendNoModel-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendNoModel/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ContinuousTrack
+ Use ContinuousTrack tag: [0-9-]+
--- /dev/null
+Run dashboard with model Continuous
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendOldContinuous
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendOldContinuous-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendOldContinuous/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ContinuousTrack
+ Use ContinuousTrack tag: 19551112-2204
--- /dev/null
+^TAG file does not contain model and no model specified in start command
+CMake Error at .*/Tests/RunCMake/ctest_start/AppendOldNoModel/test.cmake:[0-9]+ \(ctest_start\):
+ ctest_start unknown error.$
--- /dev/null
+Run dashboard with to-be-determined model
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendOldNoModel
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendOldNoModel-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendOldNoModel/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
--- /dev/null
+check_tag_contents("^19551112-2204\nContinuousTrack\nContinuous\n$")
--- /dev/null
+Run dashboard with model Continuous
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendSameModel
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendSameModel-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendSameModel/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ContinuousTrack
+ Use ContinuousTrack tag: [0-9-]+
--- /dev/null
+^CMake Error at .*/Tests/RunCMake/ctest_start/MissingTrackArg/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start TRACK argument missing track name$
--- /dev/null
+^CMake Error at .*/Tests/RunCMake/ctest_start/MissingTrackArgAppend/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start TRACK argument missing track name$
--- /dev/null
+^CMake Error at .*/Tests/RunCMake/ctest_start/MissingTrackArgQuiet/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start TRACK argument missing track name$
--- /dev/null
+^CMake Error at .*/Tests/RunCMake/ctest_start/NoModel/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start no test model specified and APPEND not specified. Specify
+ either a test model or the APPEND argument$
run_ctest(${CASE_NAME})
endfunction()
-run_ctest_start(StartQuiet Experimental QUIET)
+function(check_tag_contents EXPECTED)
+ set(_tag_file "${RunCMake_BINARY_DIR}/${CASE_NAME}-build/Testing/TAG")
+ if(EXISTS "${_tag_file}")
+ file(READ "${_tag_file}" _tag_contents)
+ if(NOT _tag_contents MATCHES "${EXPECTED}")
+ set(RunCMake_TEST_FAILED "Testing/TAG file does not match expected value.\nActual TAG file:\n${_tag_contents}\nExpected TAG file:\n${EXPECTED}\n" PARENT_SCOPE)
+ endif()
+ else()
+ set(RunCMake_TEST_FAILED "Testing/TAG file does not exist." PARENT_SCOPE)
+ endif()
+endfunction()
+run_ctest_start(StartQuiet Experimental QUIET)
run_ctest_start(ConfigInSource Experimental)
-
run_ctest_start(FunctionScope Experimental QUIET)
+run_ctest_start(WriteModelToTagExperimental Experimental QUIET)
+run_ctest_start(WriteModelToTagContinuous Continuous QUIET)
+run_ctest_start(WriteModelToTagNightly Nightly QUIET)
+run_ctest_start(WriteModelToTagNoMatchingTrack Continuous TRACK SomeWeirdTrackName QUIET)
+run_ctest_start(AppendSameModel Continuous APPEND)
+run_ctest_start(AppendDifferentModel Experimental APPEND)
+run_ctest_start(AppendNoModel APPEND)
+run_ctest_start(AppendDifferentTrack TRACK ExperimentalDifferent APPEND)
+run_ctest_start(AppendNoMatchingTrack Continuous APPEND)
+run_ctest_start(AppendOldContinuous Continuous APPEND)
+run_ctest_start(AppendOldNoModel APPEND)
+run_ctest_start(NoModel QUIET)
+run_ctest_start(MissingTrackArg Experimental TRACK)
+run_ctest_start(MissingTrackArgAppend Experimental TRACK APPEND)
+run_ctest_start(MissingTrackArgQuiet Experimental TRACK QUIET)
+run_ctest_start(TooManyArgs Experimental
+ ${RunCMake_BINARY_DIR}/TooManyArgs-build
+ ${RunCMake_BINARY_DIR}/TooManyArgs-build
+ ${RunCMake_BINARY_DIR}/TooManyArgs-build)
function(run_ConfigInBuild)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ConfigInBuild-build)
--- /dev/null
+^CMake Error at .*/Tests/RunCMake/ctest_start/TooManyArgs/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start Too many arguments$
--- /dev/null
+check_tag_contents("^[0-9-]+\nContinuous\nContinuous\n$")
--- /dev/null
+check_tag_contents("^[0-9-]+\nExperimental\nExperimental\n$")
--- /dev/null
+check_tag_contents("^[0-9-]+\nNightly\nNightly\n$")
--- /dev/null
+check_tag_contents("^[0-9-]+\nSomeWeirdTrackName\nContinuous\n$")
set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@")
set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@")
set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}")
+set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
function(setup_tests)
ctest_start(${ctest_start_args})
endfunction()
+if("@CASE_NAME@" MATCHES "^Append")
+ if("@CASE_NAME@" MATCHES "^AppendNoMatchingTrack$")
+ file(WRITE "${CTEST_BINARY_DIRECTORY}/Testing/TAG" "19551112-2204\nSomeWeirdTrackName\n")
+ else()
+ file(WRITE "${CTEST_BINARY_DIRECTORY}/Testing/TAG" "19551112-2204\nContinuousTrack\n")
+ endif()
+ if(NOT "@CASE_NAME@" MATCHES "^AppendOld")
+ file(APPEND "${CTEST_BINARY_DIRECTORY}/Testing/TAG" "Continuous\n")
+ endif()
+endif()
+
set(ctest_start_args "@CASE_CTEST_START_ARGS@")
if("@CASE_NAME@" STREQUAL "FunctionScope")
setup_tests()
- *Error when uploading file: .*/Configure.xml
*Error message was: ([Cc]ould *n.t resolve host:? '?-no-site-'?.*|The requested URL returned error:.*)
- *Problems when submitting via HTTP
set(CASE_DROP_SITE "-no-site-")
set(CASE_CTEST_SUBMIT_ARGS "")
-#-----------------------------------------------------------------------------
-# Test bad argument combinations.
function(run_ctest_submit CASE_NAME)
set(CASE_CTEST_SUBMIT_ARGS "${ARGN}")
run_ctest(${CASE_NAME})
endfunction()
+function(run_ctest_submit_debug CASE_NAME)
+ set(CASE_CTEST_SUBMIT_ARGS "${ARGN}")
+ run_ctest(${CASE_NAME} "--debug")
+endfunction()
+
+#-----------------------------------------------------------------------------
+# Test bad argument combinations.
run_ctest_submit(BadArg bad-arg)
run_ctest_submit(BadPARTS PARTS bad-part)
run_ctest_submit(BadFILES FILES bad-file)
run_ctest_submit(CDashUploadMissingFile CDASH_UPLOAD bad-upload)
run_ctest_submit(CDashUploadRetry CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo RETRY_COUNT 2 RETRY_DELAY 1 INTERNAL_TEST_CHECKSUM)
run_ctest_submit(CDashSubmitQuiet QUIET)
-run_ctest_submit(CDashSubmitHeaders HTTPHEADER "Authorization: Bearer asdf")
-run_ctest_submit(CDashUploadHeaders CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo HTTPHEADER "Authorization: Bearer asdf")
+run_ctest_submit_debug(CDashSubmitHeaders HTTPHEADER "Authorization: Bearer asdf")
+run_ctest_submit_debug(CDashUploadHeaders CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo HTTPHEADER "Authorization: Bearer asdf")
function(run_ctest_CDashUploadFTP)
set(CASE_DROP_METHOD ftp)
--- /dev/null
+CMake Error in CMakeLists.txt:
+ Target \"foo\" contains property \"IMPORTED_FOOBAR\" in EXPORT_PROPERTIES but
+ IMPORTED_\* and INTERFACE_\* properties are reserved.
--- /dev/null
+enable_language(CXX)
+add_library(foo empty.cpp)
+set_target_properties(foo PROPERTIES
+ IMPORTED_FOOBAR "Some other string"
+ EXPORT_PROPERTIES "IMPORTED_FOOBAR"
+)
+export(TARGETS foo FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake")
+install(TARGETS foo EXPORT fooExport
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+)
--- /dev/null
+CMake Error in CMakeLists.txt:
+ Target \"foo\" contains property \"INTERFACE_FOOBAR\" in EXPORT_PROPERTIES but
+ IMPORTED_\* and INTERFACE_\* properties are reserved.
--- /dev/null
+enable_language(CXX)
+add_library(foo empty.cpp)
+set_target_properties(foo PROPERTIES
+ INTERFACE_FOOBAR "Some string"
+ EXPORT_PROPERTIES "INTERFACE_FOOBAR"
+)
+export(TARGETS foo FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake")
+install(TARGETS foo EXPORT fooExport
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+)
--- /dev/null
+CMake Error in CMakeLists.txt:
+ Target \"foo\" contains property \"JUST_A_PROPERTY\" in EXPORT_PROPERTIES but
+ this property contains a generator expression. This is not allowed.
--- /dev/null
+enable_language(CXX)
+add_library(foo empty.cpp)
+set_target_properties(foo PROPERTIES
+ JUST_A_PROPERTY "$<C_COMPILER_VERSION:0>"
+ EXPORT_PROPERTIES "JUST_A_PROPERTY"
+)
+export(TARGETS foo FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake")
+install(TARGETS foo EXPORT fooExport
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+)
run_cmake(AppendExport)
run_cmake(OldIface)
run_cmake(NoExportSet)
+run_cmake(ForbiddenToExportInterfaceProperties)
+run_cmake(ForbiddenToExportImportedProperties)
+run_cmake(ForbiddenToExportPropertyWithGenExp)
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
--- /dev/null
+.*b9fbdd8803c036dbe9f5ea6b74db4b9670c78a72
--- /dev/null
+.*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake
+.*6bc141b40c0f851d20fa9a1fe5fbdae94acc5de0
--- /dev/null
+.*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake
+.*0c3ceab9daa7914fde7410c34cae4049e140aa51
--- /dev/null
+.*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake
--- /dev/null
+message(STATUS "Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake")
+file(GLOB_RECURSE
+ CONTENT_LIST
+ CONFIGURE_DEPENDS
+ LIST_DIRECTORIES false
+ RELATIVE "${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_CURRENT_BINARY_DIR}/test/*"
+ )
+string(SHA1 CONTENT_LIST_HASH "${CONTENT_LIST}")
+add_custom_target(CONTENT_ECHO ALL ${CMAKE_COMMAND} -E echo ${CONTENT_LIST_HASH})
--- /dev/null
+.*CONFIGURE_DEPENDS is invalid for script and find package modes\.
--- /dev/null
+file(GLOB CONTENT_LIST CONFIGURE_DEPENDS)
--- /dev/null
+^CMake Error: The glob expression
+.* at GLOB-error-CONFIGURE_DEPENDS-modified\.cmake:[0-9]+ \(file\)
+was already present in the glob cache but the directory
+contents have changed during the configuration run.
+Matching glob expressions:
+ CONTENT_LIST_1 at GLOB-error-CONFIGURE_DEPENDS-modified\.cmake:[0-9]+ \(file\)
+ CONTENT_LIST_2 at GLOB-error-CONFIGURE_DEPENDS-modified\.cmake:[0-9]+ \(file\)$
--- /dev/null
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/first")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/second")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/third")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/first/one" "one")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/second/two" "two")
+file(GLOB_RECURSE CONTENT_LIST_1
+ CONFIGURE_DEPENDS
+ "${CMAKE_CURRENT_BINARY_DIR}/test/*"
+ )
+
+file(GLOB_RECURSE CONTENT_LIST_2
+ CONFIGURE_DEPENDS
+ "${CMAKE_CURRENT_BINARY_DIR}/test/*"
+ )
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/third/three" "three")
+file(GLOB_RECURSE CONTENT_LIST_3
+ CONFIGURE_DEPENDS
+ "${CMAKE_CURRENT_BINARY_DIR}/test/*"
+ )
--- /dev/null
+^CMake Error at GLOB-error-RELATIVE-no-arg\.cmake:[0-9]+ \(file\):
+ file GLOB requires a directory after the RELATIVE tag\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
--- /dev/null
+file(GLOB CONTENT_LIST RELATIVE)
--- /dev/null
+^CMake Error at GLOB-noexp-CONFIGURE_DEPENDS\.cmake:[0-9]+ \(file\):
+ file GLOB requires a glob expression after CONFIGURE_DEPENDS\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
--- /dev/null
+file(GLOB CONTENT_LIST CONFIGURE_DEPENDS)
--- /dev/null
+file(GLOB CONTENT_LIST FOLLOW_SYMLINKS)
--- /dev/null
+^CMake Error at GLOB-noexp-RELATIVE\.cmake:[0-9]+ \(file\):
+ file GLOB requires a glob expression after the directory\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
--- /dev/null
+file(GLOB CONTENT_LIST RELATIVE "${CMAKE_CURRENT_BINARY_DIR}")
--- /dev/null
+content: 7[ ]
+1aAb/\.hide;1aAb/1\.log;1aAb/1\.txt;1aAb/xkcd\.txt;a/1\.log;a/1\.txt;a/boot\.ini
--- /dev/null
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/a")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/a/1.log" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/a/1.txt" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/a/boot.ini" "")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb/.hide" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb/1.txt" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb/1.log" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb/xkcd.txt" "")
+
+file(GLOB CONTENT_LIST
+ LIST_DIRECTORIES false
+ RELATIVE "${CMAKE_CURRENT_BINARY_DIR}/test"
+ "${CMAKE_CURRENT_BINARY_DIR}/test/a/*"
+ "${CMAKE_CURRENT_BINARY_DIR}/test/*/*"
+ )
+list(LENGTH CONTENT_LIST CONTENT_COUNT)
+message("content: ${CONTENT_COUNT} ")
+message("${CONTENT_LIST}")
--- /dev/null
+^CMake Warning \(dev\) at GLOB-warn-CONFIGURE_DEPENDS-late\.cmake:[0-9]+ \(file\):
+ CONFIGURE_DEPENDS flag was given after a glob expression was already
+ evaluated\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
--- /dev/null
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/first")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/second")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/first/one" "Hi, Mom!")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/second/two" "Love you!")
+
+file(GLOB CONTENT_LIST
+ "${CMAKE_CURRENT_BINARY_DIR}/test/first/*"
+ CONFIGURE_DEPENDS
+ "${CMAKE_CURRENT_BINARY_DIR}/test/second/*"
+ )
--- /dev/null
+^CMake Error at GLOB_RECURSE-noexp-FOLLOW_SYMLINKS\.cmake:[0-9]+ \(file\):
+ file GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
--- /dev/null
+file(GLOB_RECURSE CONTENT_LIST FOLLOW_SYMLINKS)
--- /dev/null
+^CMake Warning \(dev\):
+ The detected version of Ninja:
+
+ .*
+
+ is less than the version of Ninja required by CMake for adding restat
+ dependencies to the build\.ninja manifest regeneration target:
+
+ 1\.8
+
+ Any pre-check scripts, such as those generated for file\(GLOB
+ CONFIGURE_DEPENDS\), will not be run by Ninja\.
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
--- /dev/null
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/first")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/first/one" "one")
+file(GLOB_RECURSE CONTENT_LIST
+ CONFIGURE_DEPENDS
+ "${CMAKE_CURRENT_BINARY_DIR}/test/*"
+ )
run_cmake(DOWNLOAD-httpheader-not-set)
run_cmake(DOWNLOAD-netrc-bad)
run_cmake(DOWNLOAD-pass-not-set)
+run_cmake(TOUCH)
+run_cmake(TOUCH-error-in-source-directory)
+run_cmake(TOUCH-error-missing-directory)
run_cmake(UPLOAD-unused-argument)
run_cmake(UPLOAD-httpheader-not-set)
run_cmake(UPLOAD-netrc-bad)
run_cmake(READ_ELF)
run_cmake(GLOB)
run_cmake(GLOB_RECURSE)
-# test is valid both for GLOB and GLOB_RECURSE
+run_cmake(GLOB_RECURSE-noexp-FOLLOW_SYMLINKS)
+
+# tests are valid both for GLOB and GLOB_RECURSE
+run_cmake(GLOB-sort-dedup)
run_cmake(GLOB-error-LIST_DIRECTORIES-not-boolean)
-# test is valid both for GLOB and GLOB_RECURSE
run_cmake(GLOB-error-LIST_DIRECTORIES-no-arg)
+run_cmake(GLOB-error-RELATIVE-no-arg)
+run_cmake(GLOB-error-CONFIGURE_DEPENDS-modified)
+run_cmake(GLOB-noexp-CONFIGURE_DEPENDS)
+run_cmake(GLOB-noexp-FOLLOW_SYMLINKS)
run_cmake(GLOB-noexp-LIST_DIRECTORIES)
+run_cmake(GLOB-noexp-RELATIVE)
+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(GLOB_RECURSE-cyclic-recursion)
run_cmake(INSTALL-SYMLINK)
endif()
+
+if(RunCMake_GENERATOR STREQUAL "Ninja")
+ # Detect ninja version so we know what tests can be supported.
+ execute_process(
+ COMMAND "${RunCMake_MAKE_PROGRAM}" --version
+ OUTPUT_VARIABLE ninja_out
+ ERROR_VARIABLE ninja_out
+ RESULT_VARIABLE ninja_res
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(ninja_res EQUAL 0 AND "x${ninja_out}" MATCHES "^x[0-9]+\\.[0-9]+")
+ set(ninja_version "${ninja_out}")
+ message(STATUS "ninja version: ${ninja_version}")
+ else()
+ message(FATAL_ERROR "'ninja --version' reported:\n${ninja_out}")
+ endif()
+
+ if("${ninja_version}" VERSION_LESS 1.8)
+ message(STATUS "Ninja is too old for GLOB CONFIGURE_DEPENDS; expect a warning.")
+ endif()
+endif()
+
+if(RunCMake_GENERATOR STREQUAL "Ninja" AND "${ninja_version}" VERSION_LESS 1.8)
+ run_cmake(GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version)
+else()
+ run_cmake(GLOB-warn-CONFIGURE_DEPENDS-late)
+
+ # Use a single build tree for a few tests without cleaning.
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GLOB-CONFIGURE_DEPENDS-RerunCMake-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_DEFAULT_stderr ".*")
+ if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR
+ RunCMake_GENERATOR STREQUAL "Watcom WMake")
+ set(fs_delay 3)
+ else()
+ set(fs_delay 1.125)
+ endif()
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/test")
+ set(tf_1 "${RunCMake_TEST_BINARY_DIR}/test/1.txt")
+ file(WRITE "${tf_1}" "1")
+
+ message(STATUS "GLOB-RerunCMake: first configuration...")
+ run_cmake(GLOB-CONFIGURE_DEPENDS-RerunCMake)
+ run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-build ${CMAKE_COMMAND} --build .)
+
+ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${fs_delay})
+ message(STATUS "GLOB-CONFIGURE_DEPENDS-RerunCMake: add another file...")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/test/sub")
+ set(tf_2 "${RunCMake_TEST_BINARY_DIR}/test/sub/2.txt")
+ file(WRITE "${tf_2}" "2")
+ run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first ${CMAKE_COMMAND} --build .)
+ run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-nowork ${CMAKE_COMMAND} --build .)
+
+ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${fs_delay})
+ message(STATUS "GLOB-CONFIGURE_DEPENDS-RerunCMake: remove first test file...")
+ file(REMOVE "${RunCMake_TEST_BINARY_DIR}/test/1.txt")
+ run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second ${CMAKE_COMMAND} --build .)
+ run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-nowork ${CMAKE_COMMAND} --build .)
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+ unset(RunCMake_DEFAULT_stderr)
+endif()
--- /dev/null
+.*file attempted to touch a file:
--- /dev/null
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+file(TOUCH "${CMAKE_CURRENT_SOURCE_DIR}/touch_test")
--- /dev/null
+.*file problem touching file:
--- /dev/null
+file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/missing/directory/file.to-touch")
--- /dev/null
+^CMake Error at TOUCH\.cmake:[0-9]+ \(file\):
+ file must be called with at least two arguments\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at TOUCH\.cmake:[0-9]+ \(file\):
+ file must be called with at least two arguments\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
--- /dev/null
+set(file "${CMAKE_CURRENT_BINARY_DIR}/file-to-touch")
+
+file(REMOVE "${file}")
+file(TOUCH_NOCREATE "${file}")
+if(EXISTS "${file}")
+ message(FATAL_ERROR "error: TOUCH_NOCREATE created a file!")
+endif()
+
+file(TOUCH "${file}")
+if(NOT EXISTS "${file}")
+ message(FATAL_ERROR "error: TOUCH did not create a file!")
+endif()
+file(REMOVE "${file}")
+
+file(TOUCH)
+file(TOUCH_NOCREATE)
--- /dev/null
+----------
+Foo_ROOT :<base>/foo/cmake_root
+ENV{Foo_ROOT} :<base>/foo/env_root
+
+find_package\(Foo\)
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_FILE_ZOT :FOO_TEST_FILE_ZOT-NOTFOUND
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PATH_ZOT :FOO_TEST_PATH_ZOT-NOTFOUND
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+
+----------
--- /dev/null
+cmake_policy(SET CMP0074 OLD)
+include(CMP0074-common.cmake)
--- /dev/null
+----------
+Foo_ROOT :<base>/foo/cmake_root
+ENV{Foo_ROOT} :<base>/foo/env_root
++
+CMake Warning \(dev\) at CMP0074-common.cmake:[0-9]+ \(find_package\):
+ Policy CMP0074 is not set: find_package uses PackageName_ROOT variables.
+ Run "cmake --help-policy CMP0074" for policy details. Use the cmake_policy
+ command to set the policy and suppress this warning.
+
+ CMake variable Foo_ROOT is set to:
+
+ .*/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root
+
+ Environment variable Foo_ROOT is set to:
+
+ .*/Tests/RunCMake/find_package/PackageRoot/foo/env_root
+
+ For compatibility, CMake is ignoring the variable.
+Call Stack \(most recent call first\):
+ CMP0074-common.cmake:[0-9]+ \(RunPackageRootTest\)
+ CMP0074-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+find_package\(Foo\)
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_FILE_ZOT :FOO_TEST_FILE_ZOT-NOTFOUND
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PATH_ZOT :FOO_TEST_PATH_ZOT-NOTFOUND
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+
+----------
--- /dev/null
+# (do not set CMP0074)
+include(CMP0074-common.cmake)
--- /dev/null
+# (includer selects CMP0074)
+cmake_policy(SET CMP0057 NEW)
+list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
+set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
+
+function(PrintPath label path)
+ string(REPLACE "${PackageRoot_BASE}" "<base>" out "${path}")
+ message("${label}${out}")
+endfunction()
+
+macro(CleanUpPackageRootTest)
+ unset(Foo_ROOT)
+ unset(ENV{Foo_ROOT})
+ unset(FOO_TEST_FILE_FOO)
+ unset(FOO_TEST_FILE_ZOT)
+ unset(FOO_TEST_PATH_FOO)
+ unset(FOO_TEST_PATH_ZOT)
+ unset(FOO_TEST_PROG_FOO)
+ unset(FOO_TEST_FILE_FOO CACHE)
+ unset(FOO_TEST_FILE_ZOT CACHE)
+ unset(FOO_TEST_PATH_FOO CACHE)
+ unset(FOO_TEST_PATH_ZOT CACHE)
+ unset(FOO_TEST_PROG_FOO CACHE)
+endmacro()
+
+macro(RunPackageRootTest)
+ message("----------")
+ PrintPath("Foo_ROOT :" "${Foo_ROOT}")
+ PrintPath("ENV{Foo_ROOT} :" "$ENV{Foo_ROOT}")
+ message("")
+
+ find_package(Foo)
+ message("find_package(Foo)")
+ PrintPath("FOO_TEST_FILE_FOO :" "${FOO_TEST_FILE_FOO}")
+ PrintPath("FOO_TEST_FILE_ZOT :" "${FOO_TEST_FILE_ZOT}")
+ PrintPath("FOO_TEST_PATH_FOO :" "${FOO_TEST_PATH_FOO}")
+ PrintPath("FOO_TEST_PATH_ZOT :" "${FOO_TEST_PATH_ZOT}")
+ PrintPath("FOO_TEST_PROG_FOO :" "${FOO_TEST_PROG_FOO}")
+ CleanUpPackageRootTest()
+ message("")
+endmacro()
+
+set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root)
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+RunPackageRootTest()
+message("----------")
-set(__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT 1)
cmake_policy(SET CMP0057 NEW)
+cmake_policy(SET CMP0074 NEW)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
-set(__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT 1)
cmake_policy(SET CMP0057 NEW)
+cmake_policy(SET CMP0074 NEW)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
-set(__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT 1)
cmake_policy(SET CMP0057 NEW)
+cmake_policy(SET CMP0074 NEW)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
include(RunCMake)
+run_cmake(CMP0074-WARN)
+run_cmake(CMP0074-OLD)
run_cmake(ComponentRequiredAndOptional)
run_cmake(MissingNormal)
run_cmake(MissingNormalRequired)
get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build/directory_properties<--
get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build/directory_properties<--
get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--
-get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--$
+get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--
+get_directory_property: --><--
+get_property: --><--
+get_directory_property: -->test1;test2<--
+get_property: -->test1;test2<--
+get_directory_property: -->test1;test2;test3<--
+get_property: -->test1;test2;test3<--
+get_directory_property: -->Sub/test1;Sub/test2<--
+get_property: -->Sub/test1;Sub/test2<--$
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" SOURCE_DIR)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" BINARY_DIR)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" SOURCE_DIR)
+
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS)
+add_test(NAME test1 COMMAND "${CMAKE_COMMAND}" -E echo "test1")
+add_test(NAME test2 COMMAND "${CMAKE_COMMAND}" -E echo "test2")
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS)
+add_test(NAME test3 COMMAND "${CMAKE_COMMAND}" -E echo "test3")
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS)
+
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" TESTS)
add_custom_target(CustomSub)
add_library(InterfaceSub INTERFACE)
add_library(my::InterfaceSub ALIAS InterfaceSub)
+
+add_test(Sub/test1 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test1")
+add_test(Sub/test2 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test2")
# Check explicit component.
set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-exc)
run_cmake_command(${case}-exc ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=exc -P cmake_install.cmake)
+ set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-lib)
+ run_cmake_command(${case}-lib ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=lib -P cmake_install.cmake)
+ set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-dev)
+ run_cmake_command(${case}-dev ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=dev -P cmake_install.cmake)
endif()
endfunction()
run_cmake(CMP0062-OLD)
run_cmake(CMP0062-NEW)
run_cmake(CMP0062-WARN)
+run_cmake(TARGETS-NAMELINK_COMPONENT-bad-all)
+run_cmake(TARGETS-NAMELINK_COMPONENT-bad-exc)
if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
run_install_test(FILES-TARGET_OBJECTS)
set(run_install_test_components 1)
run_install_test(FILES-EXCLUDE_FROM_ALL)
run_install_test(TARGETS-EXCLUDE_FROM_ALL)
+run_install_test(TARGETS-NAMELINK_COMPONENT)
--- /dev/null
+if(WIN32)
+ set(_check_files
+ [[lib]]
+ [[lib/(lib)?namelink-none\.dll]]
+ [[lib/(lib)?namelink-same\.dll]]
+ [[lib/(lib)?namelink-sep\.dll]]
+ [[lib/(lib)?namelink-skip\.dll]]
+ [[lib/(lib)?namelink-uns-dev\.dll]]
+ [[lib/(lib)?namelink-uns\.dll]]
+ )
+elseif(CYGWIN)
+ set(_check_files
+ [[lib]]
+ [[lib/cygnamelink-none\.dll]]
+ [[lib/cygnamelink-same-1\.dll]]
+ [[lib/cygnamelink-sep-1\.dll]]
+ [[lib/cygnamelink-skip-1\.dll]]
+ [[lib/cygnamelink-uns-1\.dll]]
+ [[lib/cygnamelink-uns-dev-1\.dll]]
+ )
+elseif(APPLE)
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-none\.dylib]]
+ [[lib/libnamelink-only\.dylib]]
+ [[lib/libnamelink-same\.1\.0\.dylib]]
+ [[lib/libnamelink-same\.1\.dylib]]
+ [[lib/libnamelink-same\.dylib]]
+ [[lib/libnamelink-sep\.1\.0\.dylib]]
+ [[lib/libnamelink-sep\.1\.dylib]]
+ [[lib/libnamelink-sep\.dylib]]
+ [[lib/libnamelink-skip\.1\.0\.dylib]]
+ [[lib/libnamelink-skip\.1\.dylib]]
+ [[lib/libnamelink-uns-dev\.1\.0\.dylib]]
+ [[lib/libnamelink-uns-dev\.1\.dylib]]
+ [[lib/libnamelink-uns-dev\.dylib]]
+ [[lib/libnamelink-uns\.1\.0\.dylib]]
+ [[lib/libnamelink-uns\.1\.dylib]]
+ [[lib/libnamelink-uns\.dylib]]
+ )
+elseif(NO_NAMELINK)
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-none\.so]]
+ [[lib/libnamelink-same\.so]]
+ [[lib/libnamelink-sep\.so]]
+ [[lib/libnamelink-skip\.so]]
+ [[lib/libnamelink-uns-dev\.so]]
+ [[lib/libnamelink-uns\.so]]
+ )
+else()
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-none\.so]]
+ [[lib/libnamelink-only\.so]]
+ [[lib/libnamelink-same\.so]]
+ [[lib/libnamelink-same\.so\.1]]
+ [[lib/libnamelink-same\.so\.1\.0]]
+ [[lib/libnamelink-sep\.so]]
+ [[lib/libnamelink-sep\.so\.1]]
+ [[lib/libnamelink-sep\.so\.1\.0]]
+ [[lib/libnamelink-skip\.so\.1]]
+ [[lib/libnamelink-skip\.so\.1\.0]]
+ [[lib/libnamelink-uns-dev\.so]]
+ [[lib/libnamelink-uns-dev\.so\.1]]
+ [[lib/libnamelink-uns-dev\.so\.1\.0]]
+ [[lib/libnamelink-uns\.so]]
+ [[lib/libnamelink-uns\.so\.1]]
+ [[lib/libnamelink-uns\.so\.1\.0]]
+ )
+endif()
+
+check_installed("^${_check_files}$")
--- /dev/null
+^CMake Error at TARGETS-NAMELINK_COMPONENT-bad-all\.cmake:5 \(install\):
+ install TARGETS given NAMELINK_COMPONENT option not in LIBRARY group\. The
+ NAMELINK_COMPONENT option may be specified only following LIBRARY\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)$
--- /dev/null
+enable_language(C)
+
+add_library(namelink-lib empty.c)
+
+install(TARGETS namelink-lib
+ DESTINATION lib
+ COMPONENT lib
+ NAMELINK_COMPONENT dev
+)
--- /dev/null
+^CMake Error at TARGETS-NAMELINK_COMPONENT-bad-exc\.cmake:5 \(install\):
+ install TARGETS given NAMELINK_COMPONENT option not in LIBRARY group\. The
+ NAMELINK_COMPONENT option may be specified only following LIBRARY\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)$
--- /dev/null
+enable_language(C)
+
+add_executable(namelink-exc main.c)
+
+install(TARGETS namelink-exc
+ RUNTIME
+ DESTINATION bin
+ COMPONENT exc
+ NAMELINK_COMPONENT dev
+)
--- /dev/null
+if(WIN32 OR CYGWIN OR NO_NAMELINK)
+ set(_check_files)
+else()
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-only\.(so|dylib)]]
+ [[lib/libnamelink-sep\.(so|dylib)]]
+ [[lib/libnamelink-uns-dev\.(so|dylib)]]
+ )
+endif()
+check_installed("^${_check_files}$")
--- /dev/null
+if(WIN32)
+ set(_check_files
+ [[lib]]
+ [[lib/(lib)?namelink-none\.dll]]
+ [[lib/(lib)?namelink-same\.dll]]
+ [[lib/(lib)?namelink-sep\.dll]]
+ [[lib/(lib)?namelink-skip\.dll]]
+ )
+elseif(CYGWIN)
+ set(_check_files
+ [[lib]]
+ [[lib/cygnamelink-none\.dll]]
+ [[lib/cygnamelink-same-1\.dll]]
+ [[lib/cygnamelink-sep-1\.dll]]
+ [[lib/cygnamelink-skip-1\.dll]]
+ )
+elseif(APPLE)
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-none\.dylib]]
+ [[lib/libnamelink-same\.1\.0\.dylib]]
+ [[lib/libnamelink-same\.1\.dylib]]
+ [[lib/libnamelink-same\.dylib]]
+ [[lib/libnamelink-sep\.1\.0\.dylib]]
+ [[lib/libnamelink-sep\.1\.dylib]]
+ [[lib/libnamelink-skip\.1\.0\.dylib]]
+ [[lib/libnamelink-skip\.1\.dylib]]
+ )
+elseif(NO_NAMELINK)
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-none\.so]]
+ [[lib/libnamelink-same\.so]]
+ [[lib/libnamelink-sep\.so]]
+ [[lib/libnamelink-skip\.so]]
+ )
+else()
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-none\.so]]
+ [[lib/libnamelink-same\.so]]
+ [[lib/libnamelink-same\.so\.1]]
+ [[lib/libnamelink-same\.so\.1\.0]]
+ [[lib/libnamelink-sep\.so\.1]]
+ [[lib/libnamelink-sep\.so\.1\.0]]
+ [[lib/libnamelink-skip\.so\.1]]
+ [[lib/libnamelink-skip\.so\.1\.0]]
+ )
+endif()
+check_installed("^${_check_files}$")
--- /dev/null
+if(WIN32)
+ set(_check_files
+ [[lib]]
+ [[lib/(lib)?namelink-uns-dev\.dll]]
+ [[lib/(lib)?namelink-uns\.dll]]
+ )
+elseif(CYGWIN)
+ set(_check_files
+ [[lib]]
+ [[lib/cygnamelink-uns-1\.dll]]
+ [[lib/cygnamelink-uns-dev-1\.dll]]
+ )
+elseif(APPLE)
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-uns-dev\.1\.0\.dylib]]
+ [[lib/libnamelink-uns-dev\.1\.dylib]]
+ [[lib/libnamelink-uns\.1\.0\.dylib]]
+ [[lib/libnamelink-uns\.1\.dylib]]
+ [[lib/libnamelink-uns\.dylib]]
+ )
+elseif(NO_NAMELINK)
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-uns-dev\.so]]
+ [[lib/libnamelink-uns\.so]]
+ )
+else()
+ set(_check_files
+ [[lib]]
+ [[lib/libnamelink-uns-dev\.so\.1]]
+ [[lib/libnamelink-uns-dev\.so\.1\.0]]
+ [[lib/libnamelink-uns\.so]]
+ [[lib/libnamelink-uns\.so\.1]]
+ [[lib/libnamelink-uns\.so\.1\.0]]
+ )
+endif()
+check_installed("^${_check_files}$")
--- /dev/null
+enable_language(C)
+
+macro(add_versioned_library NAME)
+ add_library(${NAME} SHARED obj1.c)
+ set_target_properties(${NAME} PROPERTIES
+ VERSION 1.0
+ SOVERSION 1
+ )
+endmacro()
+
+add_versioned_library(namelink-sep)
+add_versioned_library(namelink-same)
+add_versioned_library(namelink-uns)
+add_versioned_library(namelink-uns-dev)
+add_versioned_library(namelink-only)
+add_versioned_library(namelink-skip)
+add_library(namelink-none SHARED obj1.c)
+
+install(TARGETS namelink-sep namelink-none
+ RUNTIME
+ DESTINATION lib
+ COMPONENT lib
+ LIBRARY
+ DESTINATION lib
+ COMPONENT lib
+ NAMELINK_COMPONENT dev
+)
+install(TARGETS namelink-same
+ RUNTIME
+ DESTINATION lib
+ COMPONENT lib
+ LIBRARY
+ DESTINATION lib
+ COMPONENT lib
+)
+install(TARGETS namelink-uns
+ RUNTIME
+ DESTINATION lib
+ LIBRARY
+ DESTINATION lib
+)
+install(TARGETS namelink-uns-dev
+ RUNTIME
+ DESTINATION lib
+ LIBRARY
+ DESTINATION lib
+ NAMELINK_COMPONENT dev
+)
+install(TARGETS namelink-only
+ RUNTIME
+ DESTINATION lib
+ COMPONENT lib
+ LIBRARY
+ DESTINATION lib
+ COMPONENT lib
+ NAMELINK_COMPONENT dev
+ NAMELINK_ONLY
+)
+install(TARGETS namelink-skip
+ RUNTIME
+ DESTINATION lib
+ COMPONENT lib
+ LIBRARY
+ DESTINATION lib
+ COMPONENT lib
+ NAMELINK_COMPONENT dev
+ NAMELINK_SKIP
+)
--- /dev/null
+^CMake Error at JOIN-NoArguments.cmake:1 \(list\):
+ list sub-command JOIN requires three arguments \(1 found\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+list(JOIN mylist)
--- /dev/null
+^CMake Error at JOIN-NoVariable.cmake:1 \(list\):
+ list sub-command JOIN requires three arguments \(2 found\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+list(JOIN mylist "glue")
--- /dev/null
+^CMake Error at JOIN-TooManyArguments.cmake:1 \(list\):
+ list sub-command JOIN requires three arguments \(4 found\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+list(JOIN mylist "glue" out one_too_many)
--- /dev/null
+list(JOIN undefList % out)
+if(NOT out STREQUAL "")
+ message(FATAL_ERROR "\"list(JOIN undefList % out)\" set out to \"${out}\"")
+endif()
+set(myList a)
+list(JOIN myList % out)
+if(NOT out STREQUAL "a")
+ message(FATAL_ERROR "\"list(JOIN \"a\" % out)\" set out to \"${out}\"")
+endif()
+set(myList a b)
+list(JOIN myList % out)
+if(NOT out STREQUAL "a%b")
+ message(FATAL_ERROR "\"list(JOIN \"a;b\" % out)\" set out to \"${out}\"")
+endif()
+list(JOIN myList "" out)
+if(NOT out STREQUAL "ab")
+ message(FATAL_ERROR "\"list(JOIN \"a;b\" \"\" out a)\" set out to \"${out}\"")
+endif()
run_cmake(GET-InvalidIndex)
run_cmake(INSERT-InvalidIndex)
run_cmake(REMOVE_AT-InvalidIndex)
+run_cmake(SUBLIST-InvalidIndex)
run_cmake(FILTER-REGEX-TooManyArguments)
+run_cmake(JOIN-TooManyArguments)
run_cmake(LENGTH-TooManyArguments)
run_cmake(REMOVE_DUPLICATES-TooManyArguments)
run_cmake(REVERSE-TooManyArguments)
run_cmake(SORT-TooManyArguments)
+run_cmake(SUBLIST-TooManyArguments)
run_cmake(FILTER-NotList)
run_cmake(REMOVE_AT-NotList)
run_cmake(FILTER-REGEX-InvalidOperator)
run_cmake(FILTER-REGEX-Valid0)
run_cmake(FILTER-REGEX-Valid1)
+
+run_cmake(JOIN-NoArguments)
+run_cmake(JOIN-NoVariable)
+run_cmake(JOIN)
+
+run_cmake(SUBLIST-NoArguments)
+run_cmake(SUBLIST-NoVariable)
+run_cmake(SUBLIST-InvalidLength)
+run_cmake(SUBLIST)
+
+run_cmake(TRANSFORM-NoAction)
+run_cmake(TRANSFORM-InvalidAction)
+# 'action' oriented tests
+run_cmake(TRANSFORM-TOUPPER-TooManyArguments)
+run_cmake(TRANSFORM-TOLOWER-TooManyArguments)
+run_cmake(TRANSFORM-STRIP-TooManyArguments)
+run_cmake(TRANSFORM-GENEX_STRIP-TooManyArguments)
+run_cmake(TRANSFORM-APPEND-NoArguments)
+run_cmake(TRANSFORM-APPEND-TooManyArguments)
+run_cmake(TRANSFORM-PREPEND-NoArguments)
+run_cmake(TRANSFORM-PREPEND-TooManyArguments)
+run_cmake(TRANSFORM-REPLACE-NoArguments)
+run_cmake(TRANSFORM-REPLACE-NoEnoughArguments)
+run_cmake(TRANSFORM-REPLACE-TooManyArguments)
+run_cmake(TRANSFORM-REPLACE-InvalidRegex)
+run_cmake(TRANSFORM-REPLACE-InvalidReplace1)
+run_cmake(TRANSFORM-REPLACE-InvalidReplace2)
+# 'selector' oriented tests
+run_cmake(TRANSFORM-Selector-REGEX-NoArguments)
+run_cmake(TRANSFORM-Selector-REGEX-TooManyArguments)
+run_cmake(TRANSFORM-Selector-REGEX-InvalidRegex)
+run_cmake(TRANSFORM-Selector-AT-NoArguments)
+run_cmake(TRANSFORM-Selector-AT-BadArgument)
+run_cmake(TRANSFORM-Selector-AT-InvalidIndex)
+run_cmake(TRANSFORM-Selector-FOR-NoArguments)
+run_cmake(TRANSFORM-Selector-FOR-NoEnoughArguments)
+run_cmake(TRANSFORM-Selector-FOR-TooManyArguments)
+run_cmake(TRANSFORM-Selector-FOR-BadArgument)
+run_cmake(TRANSFORM-Selector-FOR-InvalidIndex)
+# 'output' oriented tests
+run_cmake(TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments)
+run_cmake(TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments)
+# Successful tests
+run_cmake(TRANSFORM-TOUPPER)
+run_cmake(TRANSFORM-TOLOWER)
+run_cmake(TRANSFORM-STRIP)
+run_cmake(TRANSFORM-GENEX_STRIP)
+run_cmake(TRANSFORM-APPEND)
+run_cmake(TRANSFORM-PREPEND)
+run_cmake(TRANSFORM-REPLACE)
--- /dev/null
+^CMake Error at SUBLIST-InvalidIndex.cmake:2 \(list\):
+ list begin index: 3 is out of range 0 - 2
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(SUBLIST mylist 3 -1 result)
--- /dev/null
+^CMake Error at SUBLIST-InvalidLength.cmake:2 \(list\):
+ list length: -2 should be -1 or greater
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(SUBLIST mylist 0 -2 result)
--- /dev/null
+^CMake Error at SUBLIST-NoArguments.cmake:1 \(list\):
+ list sub-command SUBLIST requires four arguments \(1 found\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+list(SUBLIST mylist)
--- /dev/null
+^CMake Error at SUBLIST-NoVariable.cmake:2 \(list\):
+ list sub-command SUBLIST requires four arguments \(3 found\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(SUBLIST mylist 0 -1)
--- /dev/null
+^CMake Error at SUBLIST-TooManyArguments.cmake:1 \(list\):
+ list sub-command SUBLIST requires four arguments \(5 found\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+list(SUBLIST mylist 0 -1 result one_too_many)
--- /dev/null
+set(mylist alpha bravo charlie delta)
+list(SUBLIST mylist 1 2 result)
+
+if (NOT result STREQUAL "bravo;charlie")
+ message (FATAL_ERROR "SUBLIST is \"${result}\", expected is \"bravo;charlie\"")
+endif()
+
+
+unset(result)
+list(SUBLIST mylist 0 2 result)
+
+if (NOT result STREQUAL "alpha;bravo")
+ message (FATAL_ERROR "SUBLIST is \"${result}\", expected is \"alpha;bravo\"")
+endif()
+
+
+unset(result)
+list(SUBLIST mylist 3 2 result)
+
+if (NOT result STREQUAL "delta")
+ message (FATAL_ERROR "SUBLIST is \"${result}\", expected is \"delta\"")
+endif()
+
+
+unset(result)
+list(SUBLIST mylist 2 0 result)
+list(LENGTH result length)
+if (NOT length EQUAL 0)
+ message (FATAL_ERROR "SUBLIST is \"${result}\", expected is an empty list")
+endif()
+
+
+unset(result)
+list(SUBLIST mylist 1 5 result)
+
+if (NOT result STREQUAL "bravo;charlie;delta")
+ message (FATAL_ERROR "SUBLIST is \"${result}\", expected is \"bravo;charlie;delta\"")
+endif()
+
+
+unset(result)
+list(SUBLIST mylist 1 -1 result)
+
+if (NOT result STREQUAL "bravo;charlie;delta")
+ message (FATAL_ERROR "SUBLIST is \"${result}\", expected is \"bravo;charlie;delta\"")
+endif()
--- /dev/null
+^CMake Error at TRANSFORM-APPEND-NoArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, action APPEND expects 1 argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist APPEND)
--- /dev/null
+^CMake Error at TRANSFORM-APPEND-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist APPEND delta one_too_many)
--- /dev/null
+set(mylist alpha bravo charlie delta)
+
+list(TRANSFORM mylist APPEND "_A" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha_A;bravo_A;charlie_A;delta_A")
+ message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha_A;bravo_A;charlie_A;delta_A\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie;delta_A")
+ message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie;delta_A\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie_A;delta")
+ message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie_A;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie_A;delta")
+ message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie_A;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie_A;delta_A")
+ message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie_A;delta_A\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha_A;bravo;charlie_A;delta")
+ message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha_A;bravo;charlie_A;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie;delta_A")
+ message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie;delta_A\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" REGEX "(r|t)a")
+if (NOT mylist STREQUAL "alpha;bravo_A;charlie;delta_A")
+ message (FATAL_ERROR "TRANSFORM(APPEND) is \"${mylist}\", expected is \"alpha;bravo_A;charlie;delta_A\"")
+endif()
--- /dev/null
+^CMake Error at TRANSFORM-GENEX_STRIP-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist GENEX_STRIP one_too_many)
--- /dev/null
+set(mylist one "$<1:two\;three>" four "$<TARGET_OBJECTS:some_target>")
+
+list(TRANSFORM mylist GENEX_STRIP OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one;;four;")
+ message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one;;four;\"")
+endif()
+
+set(mylist "one $<CONFIG>" "$<1:two\;three>-$<PLATFORM_ID>" "$<ANGLE-R>four" "$<TARGET_OBJECTS:some_target>")
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one $<CONFIG>;-;$<ANGLE-R>four;")
+ message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one $<CONFIG>;-;$<ANGLE-R>four;\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one $<CONFIG>;-;four;$<TARGET_OBJECTS:some_target>")
+ message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one $<CONFIG>;-;four;$<TARGET_OBJECTS:some_target>\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one $<CONFIG>;-;four;$<TARGET_OBJECTS:some_target>")
+ message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one $<CONFIG>;-;four;$<TARGET_OBJECTS:some_target>\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one $<CONFIG>;-;four;")
+ message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one $<CONFIG>;-;four;\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one ;$<1:two;three>-$<PLATFORM_ID>;four;$<TARGET_OBJECTS:some_target>")
+ message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one ;$<1:two;three>-$<PLATFORM_ID>;four;$<TARGET_OBJECTS:some_target>\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP REGEX "(D|G)>" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one ;-;$<ANGLE-R>four;$<TARGET_OBJECTS:some_target>")
+ message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one ;-;$<ANGLE-R>four;$<TARGET_OBJECTS:some_target>\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP REGEX "(D|G)>")
+if (NOT mylist STREQUAL "one ;-;$<ANGLE-R>four;$<TARGET_OBJECTS:some_target>")
+ message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${mylist}\", expected is \"one ;-;$<ANGLE-R>four;$<TARGET_OBJECTS:some_target>\"")
+endif()
--- /dev/null
+^CMake Error at TRANSFORM-InvalidAction.cmake:2 \(list\):
+ list sub-command TRANSFORM, BAD_ACTION invalid action.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist BAD_ACTION)
--- /dev/null
+^CMake Error at TRANSFORM-NoAction.cmake:2 \(list\):
+ list sub-command TRANSFORM requires an action to be specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist)
--- /dev/null
+^CMake Error at TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, OUTPUT_VARIABLE expects variable name argument.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER OUTPUT_VARIABLE)
--- /dev/null
+^CMake Error at TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER OUTPUT_VARIABLE output one_too_many)
--- /dev/null
+^CMake Error at TRANSFORM-PREPEND-NoArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, action PREPEND expects 1 argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist PREPEND)
--- /dev/null
+^CMake Error at TRANSFORM-PREPEND-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist PREPEND delta one_too_many)
--- /dev/null
+set(mylist alpha bravo charlie delta)
+
+list(TRANSFORM mylist PREPEND "P_" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "P_alpha;P_bravo;P_charlie;P_delta")
+ message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"P_alpha;P_bravo;P_charlie;P_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;charlie;P_delta")
+ message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;charlie;P_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;P_charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;P_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;P_charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;P_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;P_charlie;P_delta")
+ message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;P_charlie;P_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "P_alpha;bravo;P_charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"P_alpha;bravo;P_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;charlie;P_delta")
+ message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;charlie;P_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" REGEX "(r|t)a")
+if (NOT mylist STREQUAL "alpha;P_bravo;charlie;P_delta")
+ message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${mylist}\", expected is \"alpha;P_bravo;charlie;P_delta\"")
+endif()
--- /dev/null
+^CMake Error at TRANSFORM-REPLACE-InvalidRegex.cmake:2 \(list\):
+ list sub-command TRANSFORM, action REPLACE: Failed to compile regex
+ "\^\(alpha\$".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^(alpha$" "zulu")
--- /dev/null
+^CMake Error at TRANSFORM-REPLACE-InvalidReplace1.cmake:2 \(list\):
+ list sub-command TRANSFORM, action REPLACE: replace-expression ends in a
+ backslash.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^alpha$" "zulu\\")
--- /dev/null
+^CMake Error at TRANSFORM-REPLACE-InvalidReplace2.cmake:2 \(list\):
+ list sub-command TRANSFORM, action REPLACE: Unknown escape "\\z" in
+ replace-expression.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^alpha$" "\\zulu")
--- /dev/null
+^CMake Error at TRANSFORM-REPLACE-NoArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, action REPLACE expects 2 argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE)
--- /dev/null
+^CMake Error at TRANSFORM-REPLACE-NoEnoughArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, action REPLACE expects 2 argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^alpha$")
--- /dev/null
+^CMake Error at TRANSFORM-REPLACE-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^alpha$" "zulu" "one_too_many")
--- /dev/null
+set(mylist alpha bravo charlie delta)
+
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha_alpha;bravo;charlie;delta_delta")
+ message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha_alpha;bravo;charlie;delta_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta_delta")
+ message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie;delta_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+e)$" "\\1_\\1" AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie_charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+e)$" "\\1_\\1" FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie_charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta_delta")
+ message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie_A;delta_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha_alpha;bravo;charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha_alpha;bravo;charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta_delta")
+ message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie;delta_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" REGEX "(r|t)a")
+if (NOT mylist STREQUAL "alpha;bravo;charlie;delta_delta")
+ message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${mylist}\", expected is \"alpha;bravo;charlie;delta_delta\"")
+endif()
--- /dev/null
+^CMake Error at TRANSFORM-STRIP-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist STRIP one_too_many)
--- /dev/null
+set(mylist " alpha" "bravo " " charlie " delta)
+
+list(TRANSFORM mylist STRIP OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \"alpha;bravo;charlie;delta\"")
+endif()
+
+set(mylist " alpha" "bravo " " charlie " "delta ")
+unset(output)
+list(TRANSFORM mylist STRIP AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo; charlie ;delta")
+ message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo; charlie ;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo;charlie;delta ")
+ message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo;charlie;delta \"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo;charlie;delta ")
+ message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo;charlie;delta \"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo;charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo;charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo ;charlie;delta ")
+ message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \"alpha;bravo ;charlie;delta \"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo; charlie ;delta")
+ message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo; charlie ;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP REGEX "(r|t)a")
+if (NOT mylist STREQUAL " alpha;bravo; charlie ;delta")
+ message (FATAL_ERROR "TRANSFORM(STRIP) is \"${mylist}\", expected is \" alpha;bravo; charlie ;delta\"")
+endif()
--- /dev/null
+^CMake Error at TRANSFORM-Selector-AT-BadArgument.cmake:2 \(list\):
+ list sub-command TRANSFORM, '1x 2': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER AT 0 1x 2)
--- /dev/null
+^CMake Error at TRANSFORM-Selector-AT-InvalidIndex.cmake:2 \(list\):
+ list sub-command TRANSFORM, selector AT, index: 3 out of range \(-3, 2\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER AT 0 3 2)
--- /dev/null
+^CMake Error at TRANSFORM-Selector-AT-NoArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, selector AT expects at least one numeric value.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER AT)
--- /dev/null
+^CMake Error at TRANSFORM-Selector-FOR-BadArgument.cmake:2 \(list\):
+ list sub-command TRANSFORM, selector FOR expects, at least, two numeric
+ values.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR 0 1x 2)
--- /dev/null
+^CMake Error at TRANSFORM-Selector-FOR-InvalidIndex.cmake:2 \(list\):
+ list sub-command TRANSFORM, selector FOR, index: 6 out of range \(-3, 2\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR 0 6 2)
--- /dev/null
+^CMake Error at TRANSFORM-Selector-FOR-NoArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, selector FOR expects, at least, two arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR)
--- /dev/null
+^CMake Error at TRANSFORM-Selector-FOR-NoEnoughArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, selector FOR expects, at least, two arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR 1)
--- /dev/null
+^CMake Error at TRANSFORM-Selector-FOR-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, '3': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR 0 1 2 3)
--- /dev/null
+^CMake Error at TRANSFORM-Selector-REGEX-InvalidRegex.cmake:2 \(list\):
+ list sub-command TRANSFORM, selector REGEX failed to compile regex
+ "\^\(alpha\$".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER REGEX "^(alpha$")
--- /dev/null
+^CMake Error at TRANSFORM-Selector-REGEX-NoArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, selector REGEX expects 'regular expression'
+ argument.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER REGEX)
--- /dev/null
+^CMake Error at TRANSFORM-Selector-REGEX-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER REGEX "^alpha$" "one_too_many")
--- /dev/null
+^CMake Error at TRANSFORM-TOLOWER-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOLOWER one_too_many)
--- /dev/null
+set(mylist ALPHA BRAVO CHARLIE DELTA)
+
+list(TRANSFORM mylist TOLOWER OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"alpha;bravo;charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;CHARLIE;delta")
+ message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;charlie;DELTA")
+ message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;charlie;DELTA")
+ message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;charlie;delta")
+ message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;charlie;DELTA")
+ message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"alpha;BRAVO;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER REGEX "(R|T)A" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;CHARLIE;delta")
+ message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER REGEX "(R|T)A")
+if (NOT mylist STREQUAL "ALPHA;bravo;CHARLIE;delta")
+ message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${mylist}\", expected is \"ALPHA;bravo;CHARLIE;delta\"")
+endif()
--- /dev/null
+^CMake Error at TRANSFORM-TOUPPER-TooManyArguments.cmake:2 \(list\):
+ list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER one_too_many)
--- /dev/null
+set(mylist alpha bravo charlie delta)
+
+list(TRANSFORM mylist TOUPPER OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;BRAVO;CHARLIE;DELTA")
+ message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"ALPHA;BRAVO;CHARLIE;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;charlie;DELTA")
+ message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;CHARLIE;delta")
+ message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;CHARLIE;delta")
+ message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;CHARLIE;DELTA")
+ message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;CHARLIE;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;CHARLIE;delta")
+ message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"ALPHA;bravo;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;charlie;DELTA")
+ message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER REGEX "(r|t)a")
+if (NOT mylist STREQUAL "alpha;BRAVO;charlie;DELTA")
+ message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${mylist}\", expected is \"alpha;BRAVO;charlie;DELTA\"")
+endif()
--- /dev/null
+ the following parameters must be specified after LANGUAGES keyword: C.
--- /dev/null
+project(ProjectA C LANGUAGES CXX)
--- /dev/null
+ DESCRIPTION keyword not followed by a value or was followed by a value that
+ expanded to nothing.
--- /dev/null
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 LANGUAGES NONE DESCRIPTION)
--- /dev/null
+ DESCRIPTION keyword not followed by a value or was followed by a value that
+ expanded to nothing.
--- /dev/null
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 DESCRIPTION LANGUAGES NONE)
--- /dev/null
+-- PROJECT_HOMEPAGE_URL=http://example.com
+-- CMAKE_PROJECT_HOMEPAGE_URL=http://example.com
+-- ProjectHomepageTest_HOMEPAGE_URL=http://example.com
--- /dev/null
+cmake_policy(SET CMP0048 NEW)
+project(ProjectHomepageTest VERSION 1.0.0 HOMEPAGE_URL "http://example.com" LANGUAGES)
+if(NOT PROJECT_HOMEPAGE_URL)
+ message(FATAL_ERROR "PROJECT_HOMEPAGE_URL expected to be set")
+endif()
+if(NOT CMAKE_PROJECT_HOMEPAGE_URL)
+ message(FATAL_ERROR "CMAKE_PROJECT_HOMEPAGE_URL expected to be set")
+endif()
+if(NOT ProjectHomepageTest_HOMEPAGE_URL)
+ message(FATAL_ERROR "ProjectHomepageTest_HOMEPAGE_URL expected to be set")
+endif()
+message(STATUS "PROJECT_HOMEPAGE_URL=${PROJECT_HOMEPAGE_URL}")
+message(STATUS "CMAKE_PROJECT_HOMEPAGE_URL=${CMAKE_PROJECT_HOMEPAGE_URL}")
+message(STATUS "ProjectHomepageTest_HOMEPAGE_URL=${ProjectHomepageTest_HOMEPAGE_URL}")
--- /dev/null
+^CMake Error at ProjectHomepage2.cmake:2 \(project\):
+ HOMEPAGE_URL may be specified at most once.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
--- /dev/null
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 HOMEPAGE_URL "http://example.com" HOMEPAGE_URL "http://example.com" LANGUAGES)
--- /dev/null
+^CMake Warning at ProjectHomepageNoArg.cmake:2 \(project\):
+ HOMEPAGE_URL keyword not followed by a value or was followed by a value
+ that expanded to nothing.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
--- /dev/null
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 LANGUAGES NONE HOMEPAGE_URL)
run_cmake(LanguagesEmpty)
run_cmake(LanguagesNONE)
run_cmake(LanguagesTwice)
+run_cmake(LanguagesUnordered)
run_cmake(ProjectDescription)
run_cmake(ProjectDescription2)
+run_cmake(ProjectDescriptionNoArg)
+run_cmake(ProjectDescriptionNoArg2)
+run_cmake(ProjectHomepage)
+run_cmake(ProjectHomepage2)
+run_cmake(ProjectHomepageNoArg)
run_cmake(VersionAndLanguagesEmpty)
run_cmake(VersionEmpty)
run_cmake(VersionInvalid)
CMake Error at VersionMissingLanguages.cmake:2 \(project\):
- project with VERSION must use LANGUAGES before language names.
+ project with VERSION, DESCRIPTION or HOMEPAGE_URL must use LANGUAGES before
+ language names.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)$
--- /dev/null
+ VERSION keyword not followed by a value or was followed by a value that
+ expanded to nothing.
fprintf(stderr,
"[/foo/bar.c:2]: (error) Array 'abc[10]' accessed at index 12,"
" which is out of bounds.\n");
- fprintf(stderr, "[/foo/bar.c:2]: (warning) Member variable 'foo::bar' is "
- "not initialized in the constructor.\n");
+ fprintf(stderr,
+ "[/foo/bar.c:2]: (warning) Member variable 'foo::bar' is "
+ "not initialized in the constructor.\n");
fprintf(stderr, "[/foo/bar.c:2]: (style) C-style pointer casting.\n");
- fprintf(stderr, "[/foo/bar.c:2]: (performance) Variable 'm_message' is "
- "assigned in constructor body. Consider performing "
- "initialization in initialization list.\n");
- fprintf(stderr, "[/foo/bar.c:2]: (portability) scanf without field width "
- "limits can crash with huge input data on some versions of "
- "libc\n");
- fprintf(stderr, "[/foo/bar.c:2]: (information) cannot find all the include "
- "files (use --check-config for details)\n");
+ fprintf(stderr,
+ "[/foo/bar.c:2]: (performance) Variable 'm_message' is "
+ "assigned in constructor body. Consider performing "
+ "initialization in initialization list.\n");
+ fprintf(stderr,
+ "[/foo/bar.c:2]: (portability) scanf without field width "
+ "limits can crash with huge input data on some versions of "
+ "libc\n");
+ fprintf(stderr,
+ "[/foo/bar.c:2]: (information) cannot find all the include "
+ "files (use --check-config for details)\n");
// we allow this to return 1 as we ignore it
return 1;
}
run_cmake(SOURCES)
run_cmake(TYPE)
run_cmake(USER_PROP)
+run_cmake(USER_PROP_INHERITED)
--- /dev/null
+-- TopDir-to-nothing chaining: ''
+-- TopDir-to-global chaining: 'vGlobal'
+-- TopDir no chaining required: 'vTopDir'
+-- TopDir unset append chaining: 'aTopDir'
+-- TopDir preset append chaining: 'vTopDir;aTopDir'
+-- Subdir-to-parent chaining: 'vTopDir'
+-- Subdir-to-global chaining: 'vGlobal'
+-- Subdir no chaining required: 'vSubdir'
+-- Subdir preset append chaining: 'vSubdir;aSubdir'
+-- Subdir unset append chaining: 'aSubdir'
+-- Subdir undefined append chaining: 'aSubdir'
+-- Target-to-directory chaining: 'vTopDir'
+-- Target unset append chaining: 'aTarget'
+-- Target no chaining required: 'vTarget'
+-- Target preset append chaining: 'vTarget;aTarget'
+-- Target undefined get chaining: ''
+-- Target undefined append chaining: 'aTarget'
+-- Source-to-directory chaining: 'vTopDir'
+-- Source unset append chaining: 'aSource'
+-- Source no chaining required: 'vSource'
+-- Source preset append chaining: 'vSource;aSource'
+-- Source undefined get chaining: ''
+-- Source undefined append chaining: 'aSource'
+-- Test-to-directory chaining: 'vTopDir'
+-- Test unset append chaining: 'aTest'
+-- Test no chaining required: 'vTest'
+-- Test preset append chaining: 'vTest;aTest'
+-- Test undefined get chaining: ''
+-- Test undefined append chaining: 'aTest'
--- /dev/null
+# Needed for source property tests
+enable_language(C)
+
+#=================================================
+# Directory property chaining
+#=================================================
+
+foreach(i RANGE 1 5)
+ foreach(propType DIRECTORY TARGET SOURCE TEST)
+ define_property(${propType} PROPERTY USER_PROP${i} INHERITED
+ BRIEF_DOCS "Brief" FULL_DOCS "Full"
+ )
+ endforeach()
+endforeach()
+
+get_property(val DIRECTORY PROPERTY USER_PROP1)
+message(STATUS "TopDir-to-nothing chaining: '${val}'")
+
+set_property(GLOBAL PROPERTY USER_PROP1 vGlobal)
+set_property(GLOBAL PROPERTY USER_PROP2 vGlobal)
+set_property(DIRECTORY PROPERTY USER_PROP2 vTopDir)
+set_property(GLOBAL PROPERTY USER_PROP3 vGlobal)
+set_property(DIRECTORY PROPERTY USER_PROP4 vTopDir)
+
+get_property(val DIRECTORY PROPERTY USER_PROP1)
+message(STATUS "TopDir-to-global chaining: '${val}'")
+
+get_property(val DIRECTORY PROPERTY USER_PROP2)
+message(STATUS "TopDir no chaining required: '${val}'")
+
+set_property(DIRECTORY APPEND PROPERTY USER_PROP3 aTopDir)
+get_property(val DIRECTORY PROPERTY USER_PROP3)
+message(STATUS "TopDir unset append chaining: '${val}'")
+
+set_property(DIRECTORY APPEND PROPERTY USER_PROP4 aTopDir)
+get_property(val DIRECTORY PROPERTY USER_PROP4)
+message(STATUS "TopDir preset append chaining: '${val}'")
+
+add_subdirectory(USER_PROP_INHERITED)
+
+#=================================================
+# The other property types all chain the same way
+#=================================================
+macro(__chainToDirTests propType)
+ string(TOUPPER ${propType} propTypeUpper)
+
+ get_property(val ${propTypeUpper} ${propType}1 PROPERTY USER_PROP2)
+ message(STATUS "${propType}-to-directory chaining: '${val}'")
+
+ set_property(${propTypeUpper} ${propType}1 APPEND PROPERTY USER_PROP2 a${propType})
+ get_property(val ${propTypeUpper} ${propType}1 PROPERTY USER_PROP2)
+ message(STATUS "${propType} unset append chaining: '${val}'")
+
+ set_property(${propTypeUpper} ${propType}1 PROPERTY USER_PROP1 v${propType})
+ get_property(val ${propTypeUpper} ${propType}1 PROPERTY USER_PROP1)
+ message(STATUS "${propType} no chaining required: '${val}'")
+
+ set_property(${propTypeUpper} ${propType}1 APPEND PROPERTY USER_PROP1 a${propType})
+ get_property(val ${propTypeUpper} ${propType}1 PROPERTY USER_PROP1)
+ message(STATUS "${propType} preset append chaining: '${val}'")
+
+ get_property(val ${propTypeUpper} ${propType}2 PROPERTY USER_PROP5)
+ message(STATUS "${propType} undefined get chaining: '${val}'")
+
+ set_property(${propTypeUpper} ${propType}2 APPEND PROPERTY USER_PROP5 a${propType})
+ get_property(val ${propTypeUpper} ${propType}2 PROPERTY USER_PROP5)
+ message(STATUS "${propType} undefined append chaining: '${val}'")
+endmacro()
+
+add_custom_target(Target1)
+add_custom_target(Target2)
+__chainToDirTests(Target)
+
+foreach(i RANGE 1 2)
+ set(Source${i} "${CMAKE_CURRENT_BINARY_DIR}/src${i}.c")
+ file(WRITE ${Source${i}} "int foo${i}() { return ${i}; }")
+endforeach()
+add_library(srcProps OBJECT ${Source1} ${Source2})
+__chainToDirTests(Source)
+
+add_test(NAME Test1 COMMAND ${CMAKE_COMMAND} -E touch_nocreate iDoNotExist)
+add_test(NAME Test2 COMMAND ${CMAKE_COMMAND} -E touch_nocreate iDoNotExist)
+__chainToDirTests(Test)
--- /dev/null
+get_property(val DIRECTORY PROPERTY USER_PROP2)
+message(STATUS "Subdir-to-parent chaining: '${val}'")
+
+get_property(val DIRECTORY PROPERTY USER_PROP1)
+message(STATUS "Subdir-to-global chaining: '${val}'")
+
+set_property(DIRECTORY PROPERTY USER_PROP1 vSubdir)
+get_property(val DIRECTORY PROPERTY USER_PROP1)
+message(STATUS "Subdir no chaining required: '${val}'")
+
+set_property(DIRECTORY APPEND PROPERTY USER_PROP1 aSubdir)
+get_property(val DIRECTORY PROPERTY USER_PROP1)
+message(STATUS "Subdir preset append chaining: '${val}'")
+
+set_property(DIRECTORY APPEND PROPERTY USER_PROP2 aSubdir)
+get_property(val DIRECTORY PROPERTY USER_PROP2)
+message(STATUS "Subdir unset append chaining: '${val}'")
+
+set_property(DIRECTORY APPEND PROPERTY USER_PROP5 aSubdir)
+get_property(val DIRECTORY PROPERTY USER_PROP5)
+message(STATUS "Subdir undefined append chaining: '${val}'")
--- /dev/null
+string(JOIN % out)
+if(NOT out STREQUAL "")
+ message(FATAL_ERROR "\"string(JOIN % out)\" set out to \"${out}\"")
+endif()
+string(JOIN % out a)
+if(NOT out STREQUAL "a")
+ message(FATAL_ERROR "\"string(JOIN % out a)\" set out to \"${out}\"")
+endif()
+string(JOIN % out a "b")
+if(NOT out STREQUAL "a%b")
+ message(FATAL_ERROR "\"string(JOIN % out a \"b\")\" set out to \"${out}\"")
+endif()
+string(JOIN :: out a "b")
+if(NOT out STREQUAL "a::b")
+ message(FATAL_ERROR "\"string(JOIN :: out a \"b\")\" set out to \"${out}\"")
+endif()
--- /dev/null
+CMake Error at JoinNoArgs.cmake:1 \(string\):
+ string sub-command JOIN requires at least two arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+string(JOIN)
--- /dev/null
+CMake Error at JoinNoVar.cmake:1 \(string\):
+ string sub-command JOIN requires at least two arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+string(JOIN ";")
run_cmake(Concat)
run_cmake(ConcatNoArgs)
+run_cmake(Join)
+run_cmake(JoinNoArgs)
+run_cmake(JoinNoVar)
+
run_cmake(Timestamp)
run_cmake(TimestampEmpty)
run_cmake(TimestampInvalid)
#if __STDC_VERSION__ != 199901L
-#error "Not GNU C 99 mode!"
+# error "Not GNU C 99 mode!"
#endif
#ifndef __STRICT_ANSI__
-#error "Not GNU C strict ANSI!"
+# error "Not GNU C strict ANSI!"
#endif
int main(void)
{
#if __cplusplus != 201103L && \
!(__cplusplus < 201103L && defined(__GXX_EXPERIMENTAL_CXX0X__))
-#error "Not GNU C++ 11 mode!"
+# error "Not GNU C++ 11 mode!"
#endif
#ifndef __STRICT_ANSI__
-#error "Not GNU C++ strict ANSI!"
+# error "Not GNU C++ strict ANSI!"
#endif
int main()
{
return 0;
}
#ifdef PP_ERROR
-#error PP_ERROR is defined
+# error PP_ERROR is defined
#endif
--- /dev/null
+var MODIFIED_ACCESS a
+var MODIFIED_ACCESS b
--- /dev/null
+
+function(watch variable access value)
+ message("${variable} ${access} ${value}")
+endfunction ()
+
+# --------------
+
+variable_watch(var watch)
+set(var "a")
+
+function(f)
+ set(var "b" PARENT_SCOPE)
+endfunction(f)
+
+f()
run_cmake(NoWatcher)
run_cmake(WatchTwice)
run_cmake(ModifyWatchInCallback)
+run_cmake(RaiseInParentScope)
cmake_minimum_required(VERSION 3.4)
project(Server CXX)
-find_package(PythonInterp REQUIRED)
+find_package(Python REQUIRED)
macro(do_test bsname file type)
- execute_process(COMMAND ${PYTHON_EXECUTABLE}
+ execute_process(COMMAND ${Python_EXECUTABLE}
-B # no .pyc files
"${CMAKE_SOURCE_DIR}/${type}-test.py"
"${CMAKE_COMMAND}"
#include "foo.h"
#ifdef STAGE_2
-#include <foo/lib1.h>
-#include <foo/lib2renamed.h>
-#include <lib3.h>
-#include <old/lib2.h>
-#include <old/lib3.h>
+# include <foo/lib1.h>
+# include <foo/lib2renamed.h>
+# include <lib3.h>
+# include <old/lib2.h>
+# include <old/lib3.h>
#else
-#include "lib1.h"
-#include "lib2.h"
+# include "lib1.h"
+# include "lib2.h"
#endif
#include "lib4.h"
#ifdef _WIN32
-#ifdef test2_EXPORTS
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# ifdef test2_EXPORTS
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# else
+# define CM_TEST_LIB_EXPORT __declspec(dllimport)
+# endif
#else
-#define CM_TEST_LIB_EXPORT __declspec(dllimport)
-#endif
-#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
CM_TEST_LIB_EXPORT float Lib2Func();
#ifdef _WIN32
-#ifdef test3_EXPORTS
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# ifdef test3_EXPORTS
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# else
+# define CM_TEST_LIB_EXPORT __declspec(dllimport)
+# endif
#else
-#define CM_TEST_LIB_EXPORT __declspec(dllimport)
-#endif
-#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
CM_TEST_LIB_EXPORT float Lib3Func();
#ifdef _WIN32
-#ifdef test4_EXPORTS
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# ifdef test4_EXPORTS
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# else
+# define CM_TEST_LIB_EXPORT __declspec(dllimport)
+# endif
#else
-#define CM_TEST_LIB_EXPORT __declspec(dllimport)
-#endif
-#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
CM_TEST_LIB_EXPORT float Lib4Func();
#include "foo.h"
#ifdef STAGE_2
-#include <foo/lib1.h>
-#include <foo/lib2renamed.h>
-#include <lib3.h>
-#include <old/lib2.h>
-#include <old/lib3.h>
+# include <foo/lib1.h>
+# include <foo/lib2renamed.h>
+# include <lib3.h>
+# include <old/lib2.h>
+# include <old/lib3.h>
#else
-#include "lib1.h"
-#include "lib2.h"
+# include "lib1.h"
+# include "lib2.h"
#endif
#include "lib4.h"
#ifdef _WIN32
-#ifdef test2_EXPORTS
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# ifdef test2_EXPORTS
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# else
+# define CM_TEST_LIB_EXPORT __declspec(dllimport)
+# endif
#else
-#define CM_TEST_LIB_EXPORT __declspec(dllimport)
-#endif
-#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
CM_TEST_LIB_EXPORT float Lib2Func();
#ifdef _WIN32
-#ifdef test3_EXPORTS
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# ifdef test3_EXPORTS
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# else
+# define CM_TEST_LIB_EXPORT __declspec(dllimport)
+# endif
#else
-#define CM_TEST_LIB_EXPORT __declspec(dllimport)
-#endif
-#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
CM_TEST_LIB_EXPORT float Lib3Func();
#ifdef _WIN32
-#ifdef test4_EXPORTS
-#define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# ifdef test4_EXPORTS
+# define CM_TEST_LIB_EXPORT __declspec(dllexport)
+# else
+# define CM_TEST_LIB_EXPORT __declspec(dllimport)
+# endif
#else
-#define CM_TEST_LIB_EXPORT __declspec(dllimport)
-#endif
-#else
-#define CM_TEST_LIB_EXPORT
+# define CM_TEST_LIB_EXPORT
#endif
CM_TEST_LIB_EXPORT float Lib4Func();
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
-#include <io.h>
+# include <io.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
// return true if the file exists
int FileExists(const char* filename)
{
#ifdef _MSC_VER
-#define access _access
+# define access _access
#endif
#ifndef F_OK
-#define F_OK 0
+# define F_OK 0
#endif
if (access(filename, F_OK) != 0) {
return false;
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
-#include <io.h>
+# include <io.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
// return true if the file exists
int FileExists(const char* filename)
{
#ifdef _MSC_VER
-#define access _access
+# define access _access
#endif
#ifndef F_OK
-#define F_OK 0
+# define F_OK 0
#endif
if (access(filename, F_OK) != 0) {
return false;
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
-#include <io.h>
+# include <io.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
// return true if the file exists
int FileExists(const char* filename)
{
#ifdef _MSC_VER
-#define access _access
+# define access _access
#endif
#ifndef F_OK
-#define F_OK 0
+# define F_OK 0
#endif
if (access(filename, F_OK) != 0) {
return false;
+++ /dev/null
-# file: runme.py
-
-# This file illustrates the shadow-class C++ interface generated
-# by SWIG.
-
-import example
-
-# ----- Object creation -----
-
-print "Creating some objects:"
-c = example.Circle(10)
-print " Created circle", c
-s = example.Square(10)
-print " Created square", s
-
-# ----- Access a static member -----
-
-print "\nA total of", example.cvar.Shape_nshapes,"shapes were created"
-
-# ----- Member data access -----
-
-# Set the location of the object
-
-c.x = 20
-c.y = 30
-
-s.x = -10
-s.y = 5
-
-print "\nHere is their current position:"
-print " Circle = (%f, %f)" % (c.x,c.y)
-print " Square = (%f, %f)" % (s.x,s.y)
-
-# ----- Call some methods -----
-
-print "\nHere are some properties of the shapes:"
-for o in [c,s]:
- print " ", o
- print " area = ", o.area()
- print " perimeter = ", o.perimeter()
-
-print "\nGuess I'll clean up now"
-
-# Note: this invokes the virtual destructor
-del c
-del s
-
-s = 3
-print example.cvar.Shape_nshapes,"shapes remain"
-print "Goodbye"
-
#include <stdlib.h>
#include <string.h>
-#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || \
- defined(__BORLANDC__) || defined(__MINGW32__))
+#if defined(_WIN32) && \
+ (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || \
+ defined(__MINGW32__))
-#include <direct.h>
-#include <io.h>
+# include <direct.h>
+# include <io.h>
-#if defined(__WATCOMC__)
-#include <direct.h>
-#define _getcwd getcwd
-#endif
+# if defined(__WATCOMC__)
+# include <direct.h>
+# define _getcwd getcwd
+# endif
static const char* Getcwd(char* buf, unsigned int len)
{
}
#else
-#include <fcntl.h>
-#include <sys/types.h>
-#include <unistd.h>
+# include <fcntl.h>
+# include <sys/types.h>
+# include <unistd.h>
static const char* Getcwd(char* buf, unsigned int len)
{
#ifndef TESTDEF
-#error "TESTDEF should be defined!"
+# error "TESTDEF should be defined!"
#endif
int main(void)
{
#include <stdlib.h>
#ifdef USE_MYMATH
-#include "MathFunctions.h"
+# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
#include <stdlib.h>
#ifdef USE_MYMATH
-#include "MathFunctions.h"
+# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
#include <stdlib.h>
#ifdef USE_MYMATH
-#include "MathFunctions.h"
+# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
#include <stdlib.h>
#ifdef USE_MYMATH
-#include "MathFunctions.h"
+# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
#include <stdlib.h>
#ifdef USE_MYMATH
-#include "MathFunctions.h"
+# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
+++ /dev/null
-set(CTEST_SOURCE_DIRECTORY "$ENV{HOME}/Dashboards/My Tests/CMake/Tests/Tutorial/Step7")
-set(CTEST_BINARY_DIRECTORY "${CTEST_SOURCE_DIRECTORY}-build2")
-set(CTEST_CMAKE_GENERATOR "Visual Studio 8 2005")
-
-CTEST_START("Experimental")
-CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}")
-CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}")
-CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}")
-CTEST_SUBMIT()
#include <stdlib.h>
#ifdef USE_MYMATH
-#include "MathFunctions.h"
+# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
--- /dev/null
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+# Path separator
+if (WIN32)
+ set (PS "$<SEMICOLON>")
+else()
+ set (PS ":")
+endif()
+
+unset(SWIG_LANG_TYPE)
+unset(SWIG_LANG_INCLUDE_DIRECTORIES)
+unset(SWIG_LANG_DEFINITIONS)
+unset(SWIG_LANG_OPTIONS)
+unset(SWIG_LANG_LIBRARIES)
+
+if(${language} MATCHES csharp)
+ set(SWIG_LANG_TYPE TYPE SHARED)
+endif()
+if(${language} MATCHES python)
+ find_package(Python REQUIRED COMPONENTS Interpreter Development)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${Python_INCLUDE_DIRS})
+ set(SWIG_LANG_LIBRARIES ${Python_LIBRARIES})
+endif()
+if(${language} MATCHES perl)
+ find_package(Perl REQUIRED)
+ find_package(PerlLibs REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${PERL_INCLUDE_PATH})
+ separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}")
+ set(SWIG_LANG_OPTIONS ${c_flags})
+ set(SWIG_LANG_LIBRARIES ${PERL_LIBRARY})
+endif()
+if(${language} MATCHES tcl)
+ find_package(TCL REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${TCL_INCLUDE_PATH})
+ set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY})
+endif()
+if(${language} MATCHES ruby)
+ find_package(Ruby REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${RUBY_INCLUDE_PATH})
+ set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY})
+endif()
+if(${language} MATCHES php4)
+ find_package(PHP4 REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${PHP4_INCLUDE_PATH})
+ set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY})
+endif()
+if(${language} MATCHES pike)
+ find_package(Pike REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${PIKE_INCLUDE_PATH})
+ set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY})
+endif()
+if(${language} MATCHES lua)
+ find_package(Lua REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${LUA_INCLUDE_DIR})
+ set(SWIG_LANG_TYPE TYPE SHARED)
+ set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES})
+endif()
+
+set(UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
+unset(CMAKE_SWIG_FLAGS)
+
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set_property(SOURCE "${CMAKE_CURRENT_LIST_DIR}/example.i" PROPERTY CPLUSPLUS ON)
+set_property(SOURCE "${CMAKE_CURRENT_LIST_DIR}/example.i" PROPERTY COMPILE_OPTIONS -includeall)
+
+set_property(SOURCE "${CMAKE_CURRENT_LIST_DIR}/example.i"
+ PROPERTY GENERATED_INCLUDE_DIRECTORIES ${SWIG_LANG_INCLUDE_DIRECTORIES}
+ "${CMAKE_CURRENT_LIST_DIR}")
+set_property(SOURCE "${CMAKE_CURRENT_LIST_DIR}/example.i"
+ PROPERTY GENERATED_COMPILE_DEFINITIONS ${SWIG_LANG_DEFINITIONS})
+set_property(SOURCE "${CMAKE_CURRENT_LIST_DIR}/example.i"
+ PROPERTY GENERATED_COMPILE_OPTIONS ${SWIG_LANG_OPTIONS})
+
+
+SWIG_ADD_LIBRARY(example
+ LANGUAGE "${language}"
+ ${SWIG_LANG_TYPE}
+ SOURCES "${CMAKE_CURRENT_LIST_DIR}/example.i"
+ "${CMAKE_CURRENT_LIST_DIR}/example.cxx")
+TARGET_INCLUDE_DIRECTORIES(example PUBLIC ${CMAKE_CURRENT_LIST_DIR})
+TARGET_LINK_LIBRARIES(example PRIVATE ${SWIG_LANG_LIBRARIES})
--- /dev/null
+cmake_minimum_required(VERSION 3.12)
+
+project(TestBasicCsharp CXX CSharp)
+
+include(CTest)
+
+set(language "csharp")
+
+include (../BasicConfiguration.cmake)
+
+set_source_files_properties(Square.cs Circle.cs Shape.cs PROPERTIES GENERATED 1)
+add_library(example_cs SHARED $<TARGET_PROPERTY:example,SWIG_SUPPORT_FILES> Square.cs Circle.cs Shape.cs)
+set_target_properties(example_cs PROPERTIES LINKER_LANGUAGE CSharp)
+target_link_libraries(example_cs example)
+
+add_executable(runme ${CMAKE_CURRENT_SOURCE_DIR}/../runme.cs)
+target_link_libraries(runme example_cs)
+set_target_properties(runme PROPERTIES LINKER_LANGUAGE CSharp)
+
+add_test (NAME BasicCsharp
+ COMMAND $<TARGET_FILE:runme>)
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestBasicPerl CXX)
+
+include(CTest)
+
+set(language "perl")
+
+include (../BasicConfiguration.cmake)
+
+add_test (NAME BasicPerl
+ COMMAND "${PERL_EXECUTABLE}" "-I${CMAKE_CURRENT_BINARY_DIR}"
+ "-I$<TARGET_FILE_DIR:example>"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../runme.pl")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestBasicPython CXX)
+
+include(CTest)
+
+set(language "python")
+
+include (../BasicConfiguration.cmake)
+
+add_test (NAME BasicPython
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}${PS}$<TARGET_FILE_DIR:example>"
+ "${Python_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py")
--- /dev/null
+add_test(NAME UseSWIG.LegacyPython COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/LegacyPython"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/LegacyPython"
+ ${build_generator_args}
+ --build-project TestLegacyPython
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+add_test(NAME UseSWIG.LegacyPerl COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/LegacyPerl"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/LegacyPerl"
+ ${build_generator_args}
+ --build-project TestLegacyPerl
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+
+include(CheckLanguage)
+check_language(CSharp)
+if (CMAKE_CSharp_COMPILER)
+ add_test(NAME UseSWIG.BasicCsharp COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/BasicCsharp"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/BasicCsharp"
+ ${build_generator_args}
+ --build-project TestBasicCsharp
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+endif()
+
+add_test(NAME UseSWIG.BasicPython COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/BasicPython"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/BasicPython"
+ ${build_generator_args}
+ --build-project TestBasicPython
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+add_test(NAME UseSWIG.BasicPerl COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/BasicPerl"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/BasicPerl"
+ ${build_generator_args}
+ --build-project TestBasicPerl
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+
+
+add_test(NAME UseSWIG.MultipleModules COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/MultipleModules"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/MultipleModules"
+ ${build_generator_args}
+ --build-project TestMultipleModules
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+add_test(NAME UseSWIG.MultiplePython COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/MultiplePython"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/MultiplePython"
+ ${build_generator_args}
+ --build-project TestMultiplePython
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+
+
+add_test(NAME UseSWIG.ModuleVersion2 COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/ModuleVersion2"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/ModuleVersion2"
+ ${build_generator_args}
+ --build-project TestModuleVersion2
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
-set(language "python")
-cmake_minimum_required (VERSION 2.6)
-
-project(example_${language}_class)
+# Prevent deprecated warnings from new UseSWIG module
+set (CMAKE_WARN_DEPRECATED FALSE)
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
+# Path separator
+if (WIN32)
+ set (PS "$<SEMICOLON>")
+else()
+ set (PS ":")
+endif()
+
unset(SWIG_LANG_TYPE)
if(${language} MATCHES python)
- find_package(PythonLibs)
+ find_package(PythonInterp REQUIRED)
+ find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${PYTHON_LIBRARIES})
endif()
if(${language} MATCHES perl)
- find_package(PerlLibs)
+ find_package(Perl REQUIRED)
+ find_package(PerlLibs REQUIRED)
include_directories(${PERL_INCLUDE_PATH})
- add_definitions(${PERL_EXTRA_C_FLAGS})
+ separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}")
+ add_compile_options(${c_flags})
set(SWIG_LANG_LIBRARIES ${PERL_LIBRARY})
endif()
if(${language} MATCHES tcl)
- find_package(TCL)
+ find_package(TCL REQUIRED)
include_directories(${TCL_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY})
endif()
if(${language} MATCHES ruby)
- find_package(Ruby)
+ find_package(Ruby REQUIRED)
include_directories(${RUBY_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY})
endif()
if(${language} MATCHES php4)
- find_package(PHP4)
+ find_package(PHP4 REQUIRED)
include_directories(${PHP4_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY})
endif()
if(${language} MATCHES pike)
- find_package(Pike)
+ find_package(Pike REQUIRED)
include_directories(${PIKE_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY})
endif()
if(${language} MATCHES lua)
- find_package(Lua)
+ find_package(Lua REQUIRED)
include_directories(${LUA_INCLUDE_DIR})
set(SWIG_LANG_TYPE TYPE SHARED)
set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES})
endif()
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+unset(CMAKE_SWIG_FLAGS)
-set(CMAKE_SWIG_FLAGS "")
+include_directories(${CMAKE_CURRENT_LIST_DIR})
-set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON)
-set_source_files_properties(example.i PROPERTIES SWIG_FLAGS "-includeall")
+set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/example.i" PROPERTIES CPLUSPLUS ON)
+set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/example.i" PROPERTIES SWIG_FLAGS "-includeall")
SWIG_ADD_LIBRARY(example
LANGUAGE "${language}"
${SWIG_LANG_TYPE}
- SOURCES example.i example.cxx)
+ SOURCES "${CMAKE_CURRENT_LIST_DIR}/example.i"
+ "${CMAKE_CURRENT_LIST_DIR}/example.cxx")
SWIG_LINK_LIBRARIES(example ${SWIG_LANG_LIBRARIES})
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestLegacyPerl CXX)
+
+include(CTest)
+
+set(language "perl")
+
+include (../LegacyConfiguration.cmake)
+
+add_test (NAME LegacyPerl
+ COMMAND "${PERL_EXECUTABLE}" "-I${CMAKE_CURRENT_BINARY_DIR}"
+ "-I$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../runme.pl")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestLegacyPython CXX)
+
+include(CTest)
+
+set(language "python")
+
+include (../LegacyConfiguration.cmake)
+
+add_test (NAME LegacyPython
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}${PS}$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>"
+ "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestModuleVersion2 CXX)
+
+include(CTest)
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+find_package(Python2 REQUIRED COMPONENTS Interpreter Development)
+find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
+
+if (WIN32)
+ set (PS $<SEMICOLON>)
+else()
+ set (PS ":")
+endif()
+
+set(UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
+set (UseSWIG_MODULE_VERSION 2)
+unset(CMAKE_SWIG_FLAGS)
+
+set_property(SOURCE "../example.i" PROPERTY CPLUSPLUS ON)
+set_property(SOURCE "../example.i" PROPERTY COMPILE_OPTIONS -includeall)
+
+set_property(SOURCE "../example.i"
+ PROPERTY GENERATED_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/..")
+
+swig_add_library(example1
+ LANGUAGE python
+ SOURCES ../example.i ../example.cxx)
+set_target_properties (example1 PROPERTIES
+ OUTPUT_NAME example
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2"
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2")
+target_link_libraries(example1 PRIVATE Python2::Python)
+
+# re-use sample interface file for another plugin
+swig_add_library(example2
+ LANGUAGE python
+ SOURCES ../example.i ../example.cxx)
+set_target_properties (example2 PROPERTIES
+ OUTPUT_NAME example
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3"
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3")
+target_link_libraries(example2 PRIVATE Python3::Python)
+
+
+add_test (NAME ModuleVersion2.example1
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_PROPERTY:example1,SWIG_SUPPORT_FILES_DIRECTORY>${PS}$<TARGET_FILE_DIR:example1>"
+ "${Python2_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py")
+
+add_test (NAME ModuleVersion2.example2
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_PROPERTY:example2,SWIG_SUPPORT_FILES_DIRECTORY>${PS}$<TARGET_FILE_DIR:example2>"
+ "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestMultipleModules CXX)
+
+include(CTest)
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+find_package(Python REQUIRED COMPONENTS Interpreter Development)
+
+find_package(Perl REQUIRED)
+find_package(PerlLibs REQUIRED)
+
+# Path separator
+if (WIN32)
+ set (PS "$<SEMICOLON>")
+else()
+ set (PS ":")
+endif()
+
+set(UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
+unset(CMAKE_SWIG_FLAGS)
+
+set_property(SOURCE "../example.i" PROPERTY CPLUSPLUS ON)
+set_property(SOURCE "../example.i" PROPERTY COMPILE_OPTIONS -includeall)
+
+set_property(SOURCE "../example.i"
+ PROPERTY GENERATED_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/..")
+
+swig_add_library(example1
+ LANGUAGE python
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/Python"
+ SOURCES ../example.i ../example.cxx)
+set_target_properties (example1 PROPERTIES
+ OUTPUT_NAME example
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python"
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python")
+target_link_libraries(example1 PRIVATE Python::Python)
+
+# re-use sample interface file for another plugin
+set_property(SOURCE "../example.i" APPEND PROPERTY
+ GENERATED_INCLUDE_DIRECTORIES ${PERL_INCLUDE_PATH})
+separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}")
+set_property(SOURCE "../example.i" PROPERTY GENERATED_COMPILE_OPTIONS ${c_flags})
+
+swig_add_library(example2
+ LANGUAGE perl
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/Perl"
+ SOURCES ../example.i ../example.cxx)
+set_target_properties (example2 PROPERTIES
+ OUTPUT_NAME example
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Perl"
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Perl"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Perl")
+target_link_libraries(example2 PRIVATE ${PERL_LIBRARY})
+
+
+
+add_test (NAME MultipleModules.Python
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/Python${PS}$<TARGET_FILE_DIR:example1>"
+ "${Python_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py")
+
+
+add_test (NAME MultipleModules.Perl
+ COMMAND "${PERL_EXECUTABLE}" "-I${CMAKE_CURRENT_BINARY_DIR}/Perl"
+ "-I$<TARGET_FILE_DIR:example2>"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../runme.pl")
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+
+project(TestMultiplePython CXX)
+
+include(CTest)
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+find_package(Python2 REQUIRED COMPONENTS Interpreter Development)
+find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
+
+# Path separator
+if (WIN32)
+ set (PS "$<SEMICOLON>")
+else()
+ set (PS ":")
+endif()
+
+set(UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
+unset(CMAKE_SWIG_FLAGS)
+
+set_property(SOURCE "../example.i" PROPERTY CPLUSPLUS ON)
+set_property(SOURCE "../example.i" PROPERTY COMPILE_OPTIONS -includeall)
+
+set_property(SOURCE "../example.i"
+ PROPERTY GENERATED_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/..")
+
+swig_add_library(example1
+ LANGUAGE python
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/Python2"
+ SOURCES ../example.i ../example.cxx)
+set_target_properties (example1 PROPERTIES
+ OUTPUT_NAME example
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2"
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2")
+target_link_libraries(example1 PRIVATE Python2::Python)
+
+# re-use sample interface file for another plugin
+swig_add_library(example2
+ LANGUAGE python
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/Python3"
+ SOURCES ../example.i ../example.cxx)
+set_target_properties (example2 PROPERTIES
+ OUTPUT_NAME example
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3"
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3")
+target_link_libraries(example2 PRIVATE Python3::Python)
+
+
+
+add_test (NAME MultiplePython.example1
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/Python2${PS}$<TARGET_FILE_DIR:example1>"
+ "${Python2_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py")
+
+add_test (NAME MultiplePython.example2
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/Python3${PS}$<TARGET_FILE_DIR:example2>"
+ "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py")
/* Let's just grab the original header file here */
%include "example.h"
-
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+public class runme
+{
+ static void Main()
+ {
+ // ----- Object creation -----
+
+ Console.WriteLine("Creating some objects:");
+ Circle c = new Circle(10);
+ Console.WriteLine(" Created " + c);
+ Square s = new Square(10);
+ Console.WriteLine(" Created " + s);
+
+ // ----- Access a static member -----
+
+ Console.WriteLine("\nA total of " + Shape.nshapes + " shapes were created");
+
+ // ----- Member data access -----
+
+ // Set the location of the object
+
+ c.x = 20;
+ c.y = 30;
+
+ s.x = -10;
+ s.y = 5;
+
+ Console.WriteLine("\nHere is their current position:");
+ Console.WriteLine(" Circle = ({0}, {1})", c.x,c.y);
+ Console.WriteLine(" Square = ({0}, {1})", s.x,s.y);
+
+ // ----- Call some methods -----
+
+ Console.WriteLine("\nHere are some properties of the shapes:");
+ List <Shape> shapeList = new List <Shape> { c,s };
+ foreach(var o in shapeList){
+ Console.WriteLine(" " + o);
+ Console.WriteLine(" area = " + o.area());
+ Console.WriteLine(" perimeter = " + o.perimeter());
+ }
+
+ Console.WriteLine("\nGuess I'll clean up now");
+
+ // Note: this invokes the virtual destructor
+ c.Dispose();
+ s.Dispose();
+
+ s = new Square(10);;
+ Console.WriteLine(Shape.nshapes + " shapes remain");
+ Console.WriteLine("Goodbye");
+ }
+}
print $examplec::Shape_nshapes," shapes remain\n";
print "Goodbye\n";
-
--- /dev/null
+# file: runme.py
+
+# This file illustrates the shadow-class C++ interface generated
+# by SWIG.
+
+from __future__ import print_function
+
+import example
+
+# ----- Object creation -----
+
+print ("Creating some objects:")
+c = example.Circle(10)
+print (" Created circle", c)
+s = example.Square(10)
+print (" Created square", s)
+
+# ----- Access a static member -----
+
+print ("\nA total of", example.cvar.Shape_nshapes,"shapes were created")
+
+# ----- Member data access -----
+
+# Set the location of the object
+
+c.x = 20
+c.y = 30
+
+s.x = -10
+s.y = 5
+
+print ("\nHere is their current position:")
+print (" Circle = (%f, %f)" % (c.x,c.y))
+print (" Square = (%f, %f)" % (s.x,s.y))
+
+# ----- Call some methods -----
+
+print ("\nHere are some properties of the shapes:")
+for o in [c,s]:
+ print (" ", o)
+ print (" area = ", o.area())
+ print (" perimeter = ", o.perimeter())
+
+print ("\nGuess I'll clean up now")
+
+# Note: this invokes the virtual destructor
+del c
+del s
+
+s = 3
+print (example.cvar.Shape_nshapes,"shapes remain")
+print ("Goodbye")
puts "$Shape_nshapes shapes remain"
puts "Goodbye"
-
puts "$Shape_nshapes shapes remain"
puts "Goodbye"
-
#if WINVER > 0x0602
m_orientation = DisplayInformation::GetForCurrentView()->CurrentOrientation;
#else
-#if PHONE
+# if PHONE
// WP8 doesn't support rotations so always make it landscape
m_orientation = DisplayOrientations::Landscape;
-#else
+# else
m_orientation = DisplayProperties::CurrentOrientation;
-#endif
+# endif
#endif
bool swapDimensions = m_orientation == DisplayOrientations::Portrait ||
m_orientation == DisplayOrientations::PortraitFlipped;
if (strcmp(av[i], "-o") == 0 || strcmp(av[i], "-h") == 0) {
fprintf(stdout, "fakefluid is creating file \"%s\"\n", av[i + 1]);
FILE* file = fopen(av[i + 1], "w");
- fprintf(file, "// Solaris needs non-empty content so ensure\n"
- "// we have at least one symbol\n"
- "int Solaris_requires_a_symbol_here = 0;\n");
+ fprintf(file,
+ "// Solaris needs non-empty content so ensure\n"
+ "// we have at least one symbol\n"
+ "int Solaris_requires_a_symbol_here = 0;\n");
fclose(file);
}
}
#include <qapplication.h>
#ifndef _WIN32
-#include <stdio.h>
-#include <stdlib.h>
+# include <stdio.h>
+# include <stdlib.h>
#endif
int main(int argc, char* argv[])
*/
#ifndef MAIN_H
-#define MAIN_H 1
+# define MAIN_H 1
-#include <iostream>
-#include <stdlib.h>
+# include <iostream>
+# include <stdlib.h>
/* include the X library headers */
-#include <X11/Xlib.h>
-#include <X11/Xos.h>
-#include <X11/Xutil.h>
+# include <X11/Xlib.h>
+# include <X11/Xos.h>
+# include <X11/Xutil.h>
class Main
{
#include "stdio.h"
#ifdef CMAKE_HAS_X
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
+# include <X11/Xlib.h>
+# include <X11/Xutil.h>
int main()
{
CURSES_INCLUDE_PATH:PATH=/home/kitware/ncurses-5.9/include
FORM_LIBRARY:FILEPATH=/home/kitware/ncurses-5.9/lib/libform.a
CMAKE_USE_OPENSSL:BOOL=ON
-OPENSSL_CRYPTO_LIBRARY:STRING=/home/kitware/openssl-1.1.0g/lib/libcrypto.a;-pthread
-OPENSSL_INCLUDE_DIR:PATH=/home/kitware/openssl-1.1.0g/include
-OPENSSL_SSL_LIBRARY:FILEPATH=/home/kitware/openssl-1.1.0g/lib/libssl.a
+OPENSSL_CRYPTO_LIBRARY:STRING=/home/kitware/openssl-1.1.0h/lib/libcrypto.a;-pthread
+OPENSSL_INCLUDE_DIR:PATH=/home/kitware/openssl-1.1.0h/include
+OPENSSL_SSL_LIBRARY:FILEPATH=/home/kitware/openssl-1.1.0h/lib/libssl.a
PYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3
CPACK_SYSTEM_NAME:STRING=Linux-x86_64
-BUILD_QtDialog:BOOL:=TRUE
+BUILD_QtDialog:BOOL=TRUE
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
CMAKE_PREFIX_PATH:STRING=${qt_prefix}
set(CTEST_RUN_CURRENT_SCRIPT 0)
if(NOT VERSION)
- set(VERSION 3.11)
+ set(VERSION 3.12)
endif()
if(NOT DEFINED PROJECT_PREFIX)
set(PROJECT_PREFIX cmake-${VERSION})
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMAKE_Fortran_COMPILER:FILEPATH=FALSE
CMAKE_GENERATOR:INTERNAL=Ninja
-BUILD_QtDialog:BOOL:=TRUE
+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_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMAKE_Fortran_COMPILER:FILEPATH=FALSE
CMAKE_GENERATOR:INTERNAL=Ninja
-BUILD_QtDialog:BOOL:=TRUE
+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
# Find a default tool.
tools='
+ clang-format-6.0
clang-format
- clang-format-3.8
'
if test "x$clang_format" = "x"; then
for tool in $tools; do
exit 1
fi
+if ! "$clang_format" --version | grep 'clang-format version 6\.0' >/dev/null 2>/dev/null; then
+ echo "clang-format version 6.0 is required (exactly)"
+ exit 1
+fi
+
# Select listing mode.
case "$mode" in
'') echo "$usage"; exit 0 ;;
$git_ls |
# Select sources with our attribute.
- git check-attr --stdin format.clang-format |
- grep -e ': format\.clang-format: set$' |
+ git check-attr --stdin format.clang-format-6.0 |
+ grep -e ': format\.clang-format-6\.0: set$' |
sed -n 's/:[^:]*:[^:]*$//p' |
# Update sources in-place.
set -e
+forced=1
+if [[ "${1}" = "make" ]]; then
+ forced=0
+fi
+
pushd "${BASH_SOURCE%/*}/../../Source/LexerParser" > /dev/null
for lexer in \
Expr \
Fortran
do
+ cxx_file=cm${lexer}Lexer.cxx
+ h_file=cm${lexer}Lexer.h
+ in_file=cm${lexer}Lexer.in.l
+
+ if [[ (${in_file} -nt ${cxx_file}) || (${in_file} -nt ${h_file}) || (${forced} -gt 0) ]]; then
echo "Generating Lexer ${lexer}"
- flex --nounistd -DFLEXINT_H --noline --header-file=cm${lexer}Lexer.h -ocm${lexer}Lexer.cxx cm${lexer}Lexer.in.l
- sed -i 's/\s*$//' cm${lexer}Lexer.h cm${lexer}Lexer.cxx # remove trailing whitespaces
- sed -i '${/^$/d;}' cm${lexer}Lexer.h cm${lexer}Lexer.cxx # remove blank line at the end
- sed -i '1i#include "cmStandardLexer.h"' cm${lexer}Lexer.cxx # add cmStandardLexer.h include
+ flex --nounistd -DFLEXINT_H --noline --header-file=${h_file} -o${cxx_file} ${in_file}
+ sed -i 's/\s*$//' ${h_file} ${cxx_file} # remove trailing whitespaces
+ sed -i '${/^$/d;}' ${h_file} ${cxx_file} # remove blank line at the end
+ sed -i '1i#include "cmStandardLexer.h"' ${cxx_file} # add cmStandardLexer.h include
+ else
+ echo "Skipped generating Lexer ${lexer}"
+ fi
done
# these lexers (at the moment only the ListFileLexer) are compiled as C and do not generate a header
for lexer in ListFile
do
-
- echo "Generating Lexer ${lexer}"
- flex --nounistd -DFLEXINT_H --noline -ocm${lexer}Lexer.c cm${lexer}Lexer.in.l
- sed -i 's/\s*$//' cm${lexer}Lexer.c # remove trailing whitespaces
- sed -i '${/^$/d;}' cm${lexer}Lexer.c # remove blank line at the end
- sed -i '1i#include "cmStandardLexer.h"' cm${lexer}Lexer.c # add cmStandardLexer.h include
+ c_file=cm${lexer}Lexer.c
+ in_file=cm${lexer}Lexer.in.l
+
+ if [[ (${in_file} -nt ${c_file}) || (${forced} -gt 0) ]]; then
+ echo "Generating Lexer ${lexer}"
+ flex --nounistd -DFLEXINT_H --noline -o${c_file} ${in_file}
+ sed -i 's/\s*$//' ${c_file} # remove trailing whitespaces
+ sed -i '${/^$/d;}' ${c_file} # remove blank line at the end
+ sed -i '1i#include "cmStandardLexer.h"' ${c_file} # add cmStandardLexer.h include
+ else
+ echo "Skipped generating Lexer ${lexer}"
+ fi
done
--- /dev/null
+#!/usr/bin/env bash
+
+set -e
+
+forced=1
+if [[ "${1}" = "make" ]]; then
+ forced=0
+fi
+
+pushd "${BASH_SOURCE%/*}/../../Source/LexerParser" > /dev/null
+
+for parser in \
+ CommandArgument \
+ DependsJava \
+ Expr \
+ Fortran
+do
+ in_file=cm${parser}Parser.y
+ cxx_file=cm${parser}Parser.cxx
+ h_file=cm${parser}ParserTokens.h
+ prefix=cm${parser}_yy
+
+ if [[ (${in_file} -nt ${cxx_file}) || (${in_file} -nt ${h_file}) || (${forced} -gt 0) ]]; then
+ echo "Generating Parser ${parser}"
+ bison --yacc --name-prefix=${prefix} --defines=${h_file} -o${cxx_file} ${in_file}
+ sed -i '/\/\* Else will try to reuse/ i\
+#if 0
+/^yyerrlab1:/ a\
+#endif
+' ${cxx_file}
+ else
+ echo "Skipped generating Parser ${parser}"
+ fi
+done
+
+
+popd > /dev/null
readonly ownership="Curl Upstream <curl-library@cool.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_58_0"
+readonly tag="curl-7_60_0"
readonly shortlog=false
readonly paths="
CMake/*
endif()
project(CMakeHelp NONE)
+option(SPHINX_INFO "Build Info manual with Sphinx" OFF)
option(SPHINX_MAN "Build man pages with Sphinx" OFF)
option(SPHINX_HTML "Build html help with Sphinx" OFF)
option(SPHINX_SINGLEHTML "Build html single page help with Sphinx" OFF)
mark_as_advanced(SPHINX_TEXT)
mark_as_advanced(SPHINX_FLAGS)
-if(NOT SPHINX_MAN AND NOT SPHINX_HTML AND NOT SPHINX_SINGLEHTML AND NOT SPHINX_QTHELP AND NOT SPHINX_TEXT)
+if(NOT SPHINX_INFO AND NOT SPHINX_MAN AND NOT SPHINX_HTML AND NOT SPHINX_SINGLEHTML AND NOT SPHINX_QTHELP AND NOT SPHINX_TEXT)
return()
elseif(NOT SPHINX_EXECUTABLE)
message(FATAL_ERROR "SPHINX_EXECUTABLE (sphinx-build) is not found!")
if(SPHINX_TEXT)
list(APPEND doc_formats text)
endif()
+if(SPHINX_INFO)
+ find_program(MAKEINFO_EXECUTABLE
+ NAMES makeinfo
+ DOC "makeinfo tool"
+ )
+ if (NOT MAKEINFO_EXECUTABLE)
+ message(FATAL_ERROR "MAKEINFO_EXECUTABLE (makeinfo) not found!")
+ endif()
+ list(APPEND doc_formats texinfo)
+
+ # Sphinx texinfo builder supports .info, .txt, .html and .pdf output.
+ # SPHINX_INFO controls the .info output.
+ set(texinfo_extra_commands
+ COMMAND ${MAKEINFO_EXECUTABLE} --no-split -o
+ ${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.info
+ ${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.texi
+ )
+endif()
if(SPHINX_QTHELP)
find_package(PythonInterp REQUIRED)
endforeach()
endif()
+if(SPHINX_INFO)
+ CMake_OPTIONAL_COMPONENT(sphinx-info)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.info
+ DESTINATION ${CMAKE_INFO_DIR}
+ ${COMPONENT}
+ )
+endif()
+
if(SPHINX_MAN)
file(GLOB man_rst RELATIVE ${CMake_SOURCE_DIR}/Help/manual
${CMake_SOURCE_DIR}/Help/manual/*.[1-9].rst)
_cmake_index_objs = {
'command': _cmake_index_entry('command'),
+ 'envvar': _cmake_index_entry('envvar'),
'generator': _cmake_index_entry('generator'),
'manual': _cmake_index_entry('manual'),
'module': _cmake_index_entry('module'),
# We cannot insert index nodes using the result_nodes method
# because CMakeXRefRole is processed before substitution_reference
# nodes are evaluated so target nodes (with 'ids' fields) would be
- # duplicated in each evaluted substitution replacement. The
+ # duplicated in each evaluated substitution replacement. The
# docutils substitution transform does not allow this. Instead we
# use our own CMakeXRefTransform below to add index entries after
# substitutions are completed.
label = 'CMake'
object_types = {
'command': ObjType('command', 'command'),
+ 'envvar': ObjType('envvar', 'envvar'),
'generator': ObjType('generator', 'generator'),
'variable': ObjType('variable', 'variable'),
'module': ObjType('module', 'module'),
}
directives = {
'command': CMakeObject,
+ 'envvar': CMakeObject,
'variable': CMakeObject,
# Other object types cannot be created except by the CMakeTransform
# 'generator': CMakeObject,
}
roles = {
'command': CMakeXRefRole(fix_parens = True, lowercase = True),
+ 'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
'variable': CMakeXRefRole(),
'module': CMakeXRefRole(),
release = '@conf_release@' # full version string
primary_domain = 'cmake'
+highlight_language = 'none'
exclude_patterns = [
'dev', # ignore developer-only documentation
for line in lines:
mapping = (("command", "command"),
+ ("envvar", "envvar"),
("variable", "variable"),
+ ("generator", "generator"),
("target property", "prop_tgt"),
("test property", "prop_test"),
("source file property", "prop_sf"),
div.sphinxsidebarwrapper {
word-wrap: break-word;
}
+
+/* Make links inside parsed-literal blocks more obvious
+ by using a background color and increased line spacing
+ to make them look boxed. */
+.literal-block {
+ line-height: 1.4;
+}
+.literal-block a.reference.internal {
+ background-color: #dfdfdf;
+}
/* Use the bzip2 library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_BZIP2
-#include <bzlib.h>
+# include <bzlib.h>
#else
-#include <cmbzip2/bzlib.h>
+# include <cmbzip2/bzlib.h>
#endif
#endif
/* Use the curl library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_CURL
-#include <curl/curl.h>
+# include <curl/curl.h>
#else
-#include <cmcurl/include/curl/curl.h>
+# include <cmcurl/include/curl/curl.h>
#endif
#endif
/* Use the expat library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_EXPAT
-#include <expat.h>
+# include <expat.h>
#else
-#include <cmexpat/lib/expat.h>
+# include <cmexpat/lib/expat.h>
#endif
#endif
/* Use the jsoncpp library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_JSONCPP
-#include <json/reader.h>
+# include <json/reader.h>
#else
-#include <cmjsoncpp/include/json/reader.h>
+# include <cmjsoncpp/include/json/reader.h>
#endif
#endif
/* Use the jsoncpp library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_JSONCPP
-#include <json/value.h>
+# include <json/value.h>
#else
-#include <cmjsoncpp/include/json/value.h>
+# include <cmjsoncpp/include/json/value.h>
#endif
#endif
/* Use the jsoncpp library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_JSONCPP
-#include <json/writer.h>
+# include <json/writer.h>
#else
-#include <cmjsoncpp/include/json/writer.h>
+# include <cmjsoncpp/include/json/writer.h>
#endif
#endif
/* Use the KWIML library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_KWIML
-#include <kwiml/abi.h>
-#include <kwiml/int.h>
+# include <kwiml/abi.h>
+# include <kwiml/int.h>
#else
-#include "KWIML/include/kwiml/abi.h"
-#include "KWIML/include/kwiml/int.h"
+# include "KWIML/include/kwiml/abi.h"
+# include "KWIML/include/kwiml/int.h"
#endif
#endif
/* Use the libarchive configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_LIBARCHIVE
-#include <archive.h>
-#include <archive_entry.h>
+# include <archive.h>
+# include <archive_entry.h>
#else
-#include <cmlibarchive/libarchive/archive.h>
-#include <cmlibarchive/libarchive/archive_entry.h>
+# include <cmlibarchive/libarchive/archive.h>
+# include <cmlibarchive/libarchive/archive_entry.h>
#endif
#endif
/* Use the liblzma configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_LIBLZMA
-#include <lzma.h>
+# include <lzma.h>
#else
-#include <cmliblzma/liblzma/api/lzma.h>
+# include <cmliblzma/liblzma/api/lzma.h>
#endif
#endif
/* Use the LibRHash library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_LIBRHASH
-#include <rhash.h>
+# include <rhash.h>
#else
-#include <cmlibrhash/librhash/rhash.h>
+# include <cmlibrhash/librhash/rhash.h>
#endif
#endif
/* Use the libuv library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_LIBUV
-#include <uv.h>
+# include <uv.h>
#else
-#include <cmlibuv/include/uv.h>
+# include <cmlibuv/include/uv.h>
#endif
#endif
/* Use the xmlrpc library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CTEST_USE_XMLRPC
-#include <xmlrpc.h>
-#include <xmlrpc_client.h>
+# include <xmlrpc.h>
+# include <xmlrpc_client.h>
#endif
#endif
/* Use the zlib library configured for CMake. */
#include "cmThirdParty.h"
#ifdef CMAKE_USE_SYSTEM_ZLIB
-#include <zlib.h>
+# include <zlib.h>
#else
-#include <cmzlib/zlib.h>
+# include <cmzlib/zlib.h>
#endif
#endif
--- /dev/null
+include(FindPackageHandleStandardArgs)
+
+find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
+
+find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
+find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
+
+find_package_handle_standard_args(BROTLI
+ FOUND_VAR
+ BROTLI_FOUND
+ REQUIRED_VARS
+ BROTLIDEC_LIBRARY
+ BROTLICOMMON_LIBRARY
+ BROTLI_INCLUDE_DIR
+ FAIL_MESSAGE
+ "Could NOT find BROTLI"
+)
+
+set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
+set(BROTLI_LIBRARIES ${BROTLICOMMON_LIBRARY} ${BROTLIDEC_LIBRARY})
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
endif(BORLAND)
-if(CURL_WERROR)
- if(MSVC_VERSION)
- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /WX")
- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /WX")
- else()
- # this assumes clang or gcc style options
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
- endif()
-endif(CURL_WERROR)
-
# If we are on AIX, do the _ALL_SOURCE magic
if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
set(_ALL_SOURCE 1)
if(WIN32)
check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32)
check_library_exists_concat("winmm" getch HAVE_LIBWINMM)
+ list(APPEND CURL_LIBS "advapi32")
endif()
# check SSL libraries
set(HAVE_ZLIB_H 0)
endif()
+option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
+set(HAVE_BROTLI OFF)
+if(CURL_BROTLI)
+ find_package(BROTLI QUIET)
+ if(BROTLI_FOUND)
+ set(HAVE_BROTLI ON)
+ list(APPEND CURL_LIBS ${BROTLI_LIBRARIES})
+ include_directories(${BROTLI_INCLUDE_DIRS})
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${BROTLI_INCLUDE_DIRS})
+ endif()
+endif()
+
#libSSH2
option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON)
mark_as_advanced(CMAKE_USE_LIBSSH2)
endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
endif(MSVC)
+if(CURL_WERROR)
+ if(MSVC_VERSION)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
+ else()
+ # this assumes clang or gcc style options
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
+ endif()
+endif(CURL_WERROR)
+
# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
size_t nitems,
void *outstream);
-
+/* This callback will be called when a new resolver request is made */
+typedef int (*curl_resolver_start_callback)(void *resolver_state,
+ void *reserved, void *userdata);
/* enumeration of file types */
typedef enum {
CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer
*/
+ CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from
+ inside a callback */
CURL_LAST /* never use! */
} CURLcode;
SSL backends where such behavior is present. */
#define CURLSSLOPT_NO_REVOKE (1<<1)
+/* The default connection attempt delay in milliseconds for happy eyeballs.
+ CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
+ this value, keep them in sync. */
+#define CURL_HET_DEFAULT 200L
+
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
* Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222),
- /* Set the local IPv4 address to use for outgoing DNS requests.
+ /* Set the local IPv6 address to use for outgoing DNS requests.
* Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223),
/* Post MIME data. */
CINIT(MIMEPOST, OBJECTPOINT, 269),
+ /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of
+ seconds since 1 Jan 1970. */
+ CINIT(TIMEVALUE_LARGE, OFF_T, 270),
+
+ /* Head start in milliseconds to give happy eyeballs. */
+ CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271),
+
+ /* Function that will be called before a resolver request is made */
+ CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272),
+
+ /* User data to pass to the resolver start callback. */
+ CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273),
+
+ /* send HAProxy PROXY protocol header? */
+ CINIT(HAPROXYPROTOCOL, LONG, 274),
+
+ /* shuffle addresses before use when DNS returns multiple */
+ CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
CURLINFO_FILETIME = CURLINFO_LONG + 14,
+ CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14,
CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15,
CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2017 Daniel Stenberg, <daniel@haxx.se>."
+#define LIBCURL_COPYRIGHT "1996 - 2018 Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.58.0"
+#define LIBCURL_VERSION "7.60.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 58
+#define LIBCURL_VERSION_MINOR 60
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x073A00
+#define LIBCURL_VERSION_NUM 0x073C00
/*
* This is the date and time when the full source package was created. The
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
attempted to get added - again */
+ CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
+ callback */
CURLM_LAST
} CURLMcode;
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
- * still have occurred problems on invidual transfers even when this
- * returns OK.
+ * still have occurred problems on individual transfers even when
+ * this returns OK.
*/
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
#elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
- defined(__i386) || defined(__sparcv8))
+ defined(__i386) || \
+ defined(__sparcv8) || \
+ defined(__sparcv8plus))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
if(_curl_is_write_cb_option(_curl_opt)) \
if(!_curl_is_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
+ if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
+ if(!_curl_is_resolver_start_callback(value)) \
+ _curl_easy_setopt_err_resolver_start_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!_curl_is_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
)
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback,
+ "curl_easy_setopt expects a "
+ "curl_resolver_start_callback argument for this option"
+ )
_CURL_WARNING(_curl_easy_setopt_err_read_cb,
"curl_easy_setopt expects a curl_read_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
(option) == CURLOPT_SSH_KEYDATA || \
(option) == CURLOPT_SSL_CTX_DATA || \
(option) == CURLOPT_WRITEDATA || \
+ (option) == CURLOPT_RESOLVER_START_DATA || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
(__builtin_types_compatible_p(__typeof__(func), type) || \
__builtin_types_compatible_p(__typeof__(func) *, type))
+/* evaluates to true if expr is of type curl_resolver_start_callback */
+#define _curl_is_resolver_start_callback(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_resolver_start_callback))
+
/* evaluates to true if expr is of type curl_read_callback or "similar" */
#define _curl_is_read_cb(expr) \
(_curl_is_NULL(expr) || \
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \
vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.c \
- vtls/cyassl.c vtls/schannel.c vtls/darwinssl.c vtls/gskit.c \
- vtls/mbedtls.c
+ vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c \
+ vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c
LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \
vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h \
http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \
strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \
inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \
- ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
+ ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \
pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \
openldap.c curl_gethostname.c gopher.c idn_win32.c \
http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \
curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \
x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \
- mime.c sha256.c setopt.c curl_path.c
+ mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \
- curl_path.h
+ curl_path.h curl_ctype.h curl_range.h
LIB_RCFILES = libcurl.rc
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "curl_memory.h"
#include "memdebug.h"
+struct resdata {
+ struct curltime start;
+};
+
/*
* Curl_resolver_global_init()
* Called from curl_global_init() to initialize global resolver environment.
* Curl_resolver_init()
* Called from curl_easy_init() -> Curl_open() to initialize resolver
* URL-state specific environment ('resolver' member of the UrlState
- * structure). Does nothing here.
+ * structure).
*/
CURLcode Curl_resolver_init(void **resolver)
{
- (void)resolver;
+ *resolver = calloc(1, sizeof(struct resdata));
+ if(!*resolver)
+ return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
* Curl_resolver_cleanup()
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
* URL-state specific environment ('resolver' member of the UrlState
- * structure). Does nothing here.
+ * structure).
*/
void Curl_resolver_cleanup(void *resolver)
{
- (void)resolver;
+ free(resolver);
}
/*
* Curl_resolver_duphandle()
* Called from curl_easy_duphandle() to duplicate resolver URL state-specific
- * environment ('resolver' member of the UrlState structure). Does nothing
- * here.
+ * environment ('resolver' member of the UrlState structure).
*/
int Curl_resolver_duphandle(void **to, void *from)
{
- (void)to;
(void)from;
- return CURLE_OK;
+ return Curl_resolver_init(to);
}
static void destroy_async_data(struct Curl_async *);
curl_socket_t *socks,
int numsocks)
{
- (void)conn;
+ time_t milli;
+ timediff_t ms;
+ struct Curl_easy *data = conn->data;
+ struct resdata *reslv = (struct resdata *)data->state.resolver;
(void)socks;
(void)numsocks;
+ ms = Curl_timediff(Curl_now(), reslv->start);
+ if(ms < 10)
+ milli = ms/3;
+ else if(ms <= 50)
+ milli = 10;
+ else if(ms <= 250)
+ milli = 50;
+ else
+ milli = 200;
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return 0;
}
int *waitp)
{
struct in_addr in;
+ struct Curl_easy *data = conn->data;
+ struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */
/* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(AF_INET, &in, hostname, port);
+ reslv->start = Curl_now();
+
/* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, NULL)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- /* fall-back to blocking version */
- return Curl_ipv4_resolve_r(hostname, port);
+ failf(conn->data, "getaddrinfo() thread failed\n");
+
+ return NULL;
}
#else /* !HAVE_GETADDRINFO */
int *waitp)
{
struct addrinfo hints;
- Curl_addrinfo *res;
- int error;
char sbuf[12];
int pf = PF_INET;
+ struct Curl_easy *data = conn->data;
+ struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */
snprintf(sbuf, sizeof(sbuf), "%d", port);
+ reslv->start = Curl_now();
/* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, &hints)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- /* fall-back to blocking version */
- infof(conn->data, "init_resolve_thread() failed for %s; %s\n",
- hostname, Curl_strerror(conn, errno));
-
- error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
- if(error) {
- infof(conn->data, "getaddrinfo() failed for %s:%d; %s\n",
- hostname, port, Curl_strerror(conn, SOCKERRNO));
- return NULL;
- }
- else {
- Curl_addrinfo_set_port(res, port);
- }
+ failf(data, "getaddrinfo() thread failed to start\n");
+ return NULL;
- return res;
}
#endif /* !HAVE_GETADDRINFO */
/* retrieves ip address and port from a sockaddr structure.
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
-static bool getaddressinfo(struct sockaddr *sa, char *addr,
- long *port)
+bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
+ long *port)
{
unsigned short us_port;
struct sockaddr_in *si = NULL;
return;
}
- if(!getaddressinfo((struct sockaddr*)&ssrem,
- conn->primary_ip, &conn->primary_port)) {
+ if(!Curl_getaddressinfo((struct sockaddr*)&ssrem,
+ conn->primary_ip, &conn->primary_port)) {
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(conn, errno));
return;
}
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
- if(!getaddressinfo((struct sockaddr*)&ssloc,
- conn->local_ip, &conn->local_port)) {
+ if(!Curl_getaddressinfo((struct sockaddr*)&ssloc,
+ conn->local_ip, &conn->local_port)) {
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(conn, errno));
return;
/* should we try another protocol family? */
if(i == 0 && conn->tempaddr[1] == NULL &&
- Curl_timediff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
+ (Curl_timediff(now, conn->connecttime) >=
+ data->set.happy_eyeballs_timeout)) {
trynextip(conn, sockindex, 1);
}
}
return CURLE_OK;
/* store remote address and port used in this connection attempt */
- if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
- ipaddress, &port)) {
+ if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr,
+ ipaddress, &port)) {
/* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(conn, errno));
if(data->set.fsockopt) {
/* activate callback for setting socket options */
+ Curl_set_in_callback(data, true);
error = data->set.fsockopt(data->set.sockopt_client,
sockfd,
CURLSOCKTYPE_IPCXN);
+ Curl_set_in_callback(data, false);
if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
isconnected = TRUE;
}
data->info.numconnects++; /* to track the number of connections made */
- Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
+ Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
+ EXPIRE_HAPPY_EYEBALLS);
return CURLE_OK;
}
status */
conn->sock_accepted[SECONDARYSOCKET] = FALSE;
else {
+ int rc;
Curl_multi_closed(conn, sock);
- return conn->fclosesocket(conn->closesocket_client, sock);
+ Curl_set_in_callback(conn->data, true);
+ rc = conn->fclosesocket(conn->closesocket_client, sock);
+ Curl_set_in_callback(conn->data, false);
+ return rc;
}
}
addr->addrlen = sizeof(struct Curl_sockaddr_storage);
memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
- if(data->set.fopensocket)
+ if(data->set.fopensocket) {
/*
* If the opensocket callback is set, all the destination address
* information is passed to the callback. Depending on this information the
* might have been changed and this 'new' address will actually be used
* here to connect.
*/
+ Curl_set_in_callback(data, true);
*sockfd = data->set.fopensocket(data->set.opensocket_client,
CURLSOCKTYPE_IPCXN,
(struct curl_sockaddr *)addr);
+ Curl_set_in_callback(data, false);
+ }
else
/* opensocket callback not set, so simply create the socket now */
*sockfd = socket(addr->family, addr->socktype, addr->protocol);
bool duringconnect);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
-#define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between
- IPv4/IPv6 connection attempts */
/*
* Used to extract socket and connectdata struct for the most recent
int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
/*
+ * Get presentation format IP address and port from a sockaddr.
+ */
+bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, long *port);
+
+/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold any
* protocol-specific address structures. The variable declared here will be
static const content_encoding identity_encoding = {
"identity",
- NULL,
+ "none",
identity_init_writer,
identity_unencode_write,
identity_close_writer,
contenc_writer *downstream)
{
size_t sz = offsetof(contenc_writer, params) + handler->paramsize;
- contenc_writer *writer = (contenc_writer *) malloc(sz);
+ contenc_writer *writer = (contenc_writer *) calloc(1, sz);
if(writer) {
- memset(writer, 0, sz);
writer->handler = handler;
writer->downstream = downstream;
if(handler->init_writer(conn, writer)) {
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
}
/*
+ * Return true if the given string is an IP(v4|v6) address.
+ */
+static bool isip(const char *domain)
+{
+ struct in_addr addr;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+
+ if(Curl_inet_pton(AF_INET, domain, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, domain, &addr6)
+#endif
+ ) {
+ /* domain name given as IP address */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
* matching cookie path and url path
* RFC6265 5.1.4 Paths and Path-Match
*/
}
/*
+ * Return the top-level domain, for optimal hashing.
+ */
+static const char *get_top_domain(const char * const domain, size_t *outlen)
+{
+ size_t len;
+ const char *first = NULL, *last;
+
+ if(!domain)
+ return NULL;
+
+ len = strlen(domain);
+ last = memrchr(domain, '.', len);
+ if(last) {
+ first = memrchr(domain, '.', (size_t) (last - domain));
+ if(first)
+ len -= (size_t) (++first - domain);
+ }
+
+ if(outlen)
+ *outlen = len;
+
+ return first? first: domain;
+}
+
+/*
+ * A case-insensitive hash for the cookie domains.
+ */
+static size_t cookie_hash_domain(const char *domain, const size_t len)
+{
+ const char *end = domain + len;
+ size_t h = 5381;
+
+ while(domain < end) {
+ h += h << 5;
+ h ^= Curl_raw_toupper(*domain++);
+ }
+
+ return (h % COOKIE_HASH_SIZE);
+}
+
+/*
+ * Hash this domain.
+ */
+static size_t cookiehash(const char * const domain)
+{
+ const char *top;
+ size_t len;
+
+ if(!domain || isip(domain))
+ return 0;
+
+ top = get_top_domain(domain, &len);
+ return cookie_hash_domain(top, len);
+}
+
+/*
* cookie path sanitize
*/
static char *sanitize_cookie_path(const char *cookie_path)
{
struct Cookie *co, *nx, *pv;
curl_off_t now = (curl_off_t)time(NULL);
-
- co = cookies->cookies;
- pv = NULL;
- while(co) {
- nx = co->next;
- if(co->expires && co->expires < now) {
- if(!pv) {
- cookies->cookies = co->next;
+ unsigned int i;
+
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ co = cookies->cookies[i];
+ pv = NULL;
+ while(co) {
+ nx = co->next;
+ if(co->expires && co->expires < now) {
+ if(!pv) {
+ cookies->cookies[i] = co->next;
+ }
+ else {
+ pv->next = co->next;
+ }
+ cookies->numcookies--;
+ freecookie(co);
}
else {
- pv->next = co->next;
+ pv = co;
}
- cookies->numcookies--;
- freecookie(co);
- }
- else {
- pv = co;
+ co = nx;
}
- co = nx;
- }
-}
-
-/*
- * Return true if the given string is an IP(v4|v6) address.
- */
-static bool isip(const char *domain)
-{
- struct in_addr addr;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
-
- if(Curl_inet_pton(AF_INET, domain, &addr)
-#ifdef ENABLE_IPV6
- || Curl_inet_pton(AF_INET6, domain, &addr6)
-#endif
- ) {
- /* domain name given as IP address */
- return TRUE;
}
-
- return FALSE;
}
/****************************************************************************
struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */
+ bool noexpire, /* if TRUE, skip remove_expired() */
char *lineptr, /* first character of the line */
const char *domain, /* default domain */
const char *path) /* full path used when this cookie is set,
time_t now = time(NULL);
bool replace_old = FALSE;
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
+ size_t myhash;
#ifdef USE_LIBPSL
const psl_ctx_t *psl;
size_t nlen = strlen(name);
const char *endofn = &ptr[ nlen ];
- infof(data, "cookie size: name/val %d + %d bytes\n",
- nlen, len);
-
if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
((nlen + len) > MAX_NAME)) {
/* too long individual name or contents, or too long combination of
while(*whatptr && ISBLANK(*whatptr))
whatptr++;
- if(!co->name && sep) {
+ if(!co->name) {
/* The very first name/value pair is the actual cookie name */
+ if(!sep) {
+ /* Bad name/value pair. */
+ badcookie = TRUE;
+ break;
+ }
co->name = strdup(name);
co->value = strdup(whatptr);
+ done = TRUE;
if(!co->name || !co->value) {
badcookie = TRUE;
break;
the same domain and path as this */
/* at first, remove expired cookies */
- remove_expired(c);
+ if(!noexpire)
+ remove_expired(c);
#ifdef USE_LIBPSL
/* Check if the domain is a Public Suffix and if yes, ignore the cookie.
}
#endif
- clist = c->cookies;
+ myhash = cookiehash(co->domain);
+ clist = c->cookies[myhash];
replace_old = FALSE;
while(clist) {
if(strcasecompare(clist->name, co->name)) {
if(lastc)
lastc->next = co;
else
- c->cookies = co;
+ c->cookies[myhash] = co;
c->numcookies++; /* one more cookie in the jar */
}
while(*lineptr && ISBLANK(*lineptr))
lineptr++;
- Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
+ Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL);
}
free(line); /* free the line buffer */
+ remove_expired(c); /* run this once, not on every cookie */
if(fromfile)
fclose(fp);
struct Cookie *mainco = NULL;
size_t matches = 0;
bool is_ip;
+ const size_t myhash = cookiehash(host);
- if(!c || !c->cookies)
+ if(!c || !c->cookies[myhash])
return NULL; /* no cookie struct or no cookies in the struct */
/* at first, remove expired cookies */
/* check if host is an IP(v4|v6) address */
is_ip = isip(host);
- co = c->cookies;
+ co = c->cookies[myhash];
while(co) {
/* only process this cookie if it is not expired or had no expire
void Curl_cookie_clearall(struct CookieInfo *cookies)
{
if(cookies) {
- Curl_cookie_freelist(cookies->cookies);
- cookies->cookies = NULL;
+ unsigned int i;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ Curl_cookie_freelist(cookies->cookies[i]);
+ cookies->cookies[i] = NULL;
+ }
cookies->numcookies = 0;
}
}
void Curl_cookie_clearsess(struct CookieInfo *cookies)
{
struct Cookie *first, *curr, *next, *prev = NULL;
+ unsigned int i;
- if(!cookies || !cookies->cookies)
+ if(!cookies)
return;
- first = curr = prev = cookies->cookies;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ if(!cookies->cookies[i])
+ continue;
- for(; curr; curr = next) {
- next = curr->next;
- if(!curr->expires) {
- if(first == curr)
- first = next;
+ first = curr = prev = cookies->cookies[i];
- if(prev == curr)
- prev = next;
- else
- prev->next = next;
+ for(; curr; curr = next) {
+ next = curr->next;
+ if(!curr->expires) {
+ if(first == curr)
+ first = next;
+
+ if(prev == curr)
+ prev = next;
+ else
+ prev->next = next;
- freecookie(curr);
- cookies->numcookies--;
+ freecookie(curr);
+ cookies->numcookies--;
+ }
+ else
+ prev = curr;
}
- else
- prev = curr;
- }
- cookies->cookies = first;
+ cookies->cookies[i] = first;
+ }
}
****************************************************************************/
void Curl_cookie_cleanup(struct CookieInfo *c)
{
+ unsigned int i;
+
if(c) {
free(c->filename);
- Curl_cookie_freelist(c->cookies);
+ for(i = 0; i < COOKIE_HASH_SIZE; i++)
+ Curl_cookie_freelist(c->cookies[i]);
free(c); /* free the base struct as well */
}
}
FILE *out;
bool use_stdout = FALSE;
char *format_ptr;
+ unsigned int i;
if((NULL == c) || (0 == c->numcookies))
/* If there are no known cookies, we don't write or even create any
/* at first, remove expired cookies */
remove_expired(c);
+ /* make sure we still have cookies after expiration */
+ if(0 == c->numcookies)
+ return 0;
+
if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
- for(co = c->cookies; co; co = co->next) {
- if(!co->domain)
- continue;
- format_ptr = get_netscape_format(co);
- if(format_ptr == NULL) {
- fprintf(out, "#\n# Fatal libcurl error\n");
- if(!use_stdout)
- fclose(out);
- return 1;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ for(co = c->cookies[i]; co; co = co->next) {
+ if(!co->domain)
+ continue;
+ format_ptr = get_netscape_format(co);
+ if(format_ptr == NULL) {
+ fprintf(out, "#\n# Fatal libcurl error\n");
+ if(!use_stdout)
+ fclose(out);
+ return 1;
+ }
+ fprintf(out, "%s\n", format_ptr);
+ free(format_ptr);
}
- fprintf(out, "%s\n", format_ptr);
- free(format_ptr);
}
if(!use_stdout)
struct curl_slist *beg;
struct Cookie *c;
char *line;
+ unsigned int i;
if((data->cookies == NULL) ||
(data->cookies->numcookies == 0))
return NULL;
- for(c = data->cookies->cookies; c; c = c->next) {
- if(!c->domain)
- continue;
- line = get_netscape_format(c);
- if(!line) {
- curl_slist_free_all(list);
- return NULL;
- }
- beg = Curl_slist_append_nodup(list, line);
- if(!beg) {
- free(line);
- curl_slist_free_all(list);
- return NULL;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ for(c = data->cookies->cookies[i]; c; c = c->next) {
+ if(!c->domain)
+ continue;
+ line = get_netscape_format(c);
+ if(!line) {
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ beg = Curl_slist_append_nodup(list, line);
+ if(!beg) {
+ free(line);
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ list = beg;
}
- list = beg;
}
return list;
bool httponly; /* true if the httponly directive is present */
};
+#define COOKIE_HASH_SIZE 256
+
struct CookieInfo {
/* linked list of cookies we know of */
- struct Cookie *cookies;
+ struct Cookie *cookies[COOKIE_HASH_SIZE];
char *filename; /* file we read from/write to */
bool running; /* state info, for cookie adding information */
*/
#define MAX_COOKIE_LINE 5000
-#define MAX_COOKIE_LINE_TXT "4999"
/* This is the maximum length of a cookie name or content we deal with: */
#define MAX_NAME 4096
*/
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
- struct CookieInfo *, bool header, char *lineptr,
+ struct CookieInfo *, bool header, bool noexpiry,
+ char *lineptr,
const char *domain, const char *path);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
# define in_addr_t unsigned long
#endif
+#if defined(WIN32) && defined(USE_UNIX_SOCKETS)
+#include <afunix.h>
+#endif
+
#include <stddef.h>
#include "curl_addrinfo.h"
addr = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
- addr->sin_family = (unsigned short)(he->h_addrtype);
+ addr->sin_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
addr->sin_port = htons((unsigned short)port);
break;
addr6 = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
- addr6->sin6_family = (unsigned short)(he->h_addrtype);
+ addr6->sin6_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
/* if zlib is available */
#cmakedefine HAVE_LIBZ 1
+/* if brotli is available */
+#cmakedefine HAVE_BROTLI 1
+
/* if your compiler supports LL */
#cmakedefine HAVE_LL 1
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DOES_CONVERSIONS
+
+#undef _U
+#define _U (1<<0) /* upper case */
+#undef _L
+#define _L (1<<1) /* lower case */
+#undef _N
+#define _N (1<<2) /* decimal numerical digit */
+#undef _S
+#define _S (1<<3) /* space */
+#undef _P
+#define _P (1<<4) /* punctuation */
+#undef _C
+#define _C (1<<5) /* control */
+#undef _X
+#define _X (1<<6) /* hexadecimal letter */
+#undef _B
+#define _B (1<<7) /* blank */
+
+static const unsigned char ascii[128] = {
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _S|_B, _P, _P, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, _P, _P, _P, _P,
+ _N, _N, _N, _N, _N, _N, _N, _N,
+ _N, _N, _P, _P, _P, _P, _P, _P,
+ _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _P, _P, _P, _P, _P,
+ _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _P, _P, _P, _P, _C
+};
+
+int Curl_isspace(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & _S);
+}
+
+int Curl_isdigit(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & _N);
+}
+
+int Curl_isalnum(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_N|_U|_L));
+}
+
+int Curl_isxdigit(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_N|_X));
+}
+
+int Curl_isgraph(int c)
+{
+ if((c < 0) || (c >= 0x80) || (c == ' '))
+ return FALSE;
+ return (ascii[c] & (_N|_X|_U|_L|_P|_S));
+}
+
+int Curl_isprint(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_N|_X|_U|_L|_P|_S));
+}
+
+int Curl_isalpha(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_U|_L));
+}
+
+int Curl_isupper(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_U));
+}
+
+int Curl_islower(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_L));
+}
+
+int Curl_iscntrl(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_C));
+}
+
+#endif /* !CURL_DOES_CONVERSIONS */
--- /dev/null
+#ifndef HEADER_CURL_CTYPE_H
+#define HEADER_CURL_CTYPE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef CURL_DOES_CONVERSIONS
+
+/*
+ * Uppercase macro versions of ANSI/ISO is*() functions/macros which
+ * avoid negative number inputs with argument byte codes > 127.
+ *
+ * For non-ASCII platforms the C library character classification routines
+ * are used despite being locale-dependent, because this is better than
+ * not to work at all.
+ */
+#include <ctype.h>
+
+#define ISSPACE(x) (isspace((int) ((unsigned char)x)))
+#define ISDIGIT(x) (isdigit((int) ((unsigned char)x)))
+#define ISALNUM(x) (isalnum((int) ((unsigned char)x)))
+#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
+#define ISGRAPH(x) (isgraph((int) ((unsigned char)x)))
+#define ISALPHA(x) (isalpha((int) ((unsigned char)x)))
+#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
+#define ISUPPER(x) (isupper((int) ((unsigned char)x)))
+#define ISLOWER(x) (islower((int) ((unsigned char)x)))
+#define ISCNTRL(x) (iscntrl((int) ((unsigned char)x)))
+#define ISASCII(x) (isascii((int) ((unsigned char)x)))
+
+#else
+
+int Curl_isspace(int c);
+int Curl_isdigit(int c);
+int Curl_isalnum(int c);
+int Curl_isxdigit(int c);
+int Curl_isgraph(int c);
+int Curl_isprint(int c);
+int Curl_isalpha(int c);
+int Curl_isupper(int c);
+int Curl_islower(int c);
+int Curl_iscntrl(int c);
+
+#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x)))
+#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x)))
+#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x)))
+#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x)))
+#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x)))
+#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x)))
+#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x)))
+#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x)))
+#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x)))
+#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x)))
+#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80))
+
+#endif
+
+#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
+ (((unsigned char)x) == '\t'))
+
+#endif /* HEADER_CURL_CTYPE_H */
#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10)
typedef enum {
- CURLFNM_LOOP_DEFAULT = 0,
- CURLFNM_LOOP_BACKSLASH
-} loop_state;
-
-typedef enum {
CURLFNM_SCHS_DEFAULT = 0,
- CURLFNM_SCHS_MAYRANGE,
- CURLFNM_SCHS_MAYRANGE2,
CURLFNM_SCHS_RIGHTBR,
CURLFNM_SCHS_RIGHTBRLEFTBR
} setcharset_state;
CURLFNM_PKW_DDOT
} parsekey_state;
+typedef enum {
+ CCLASS_OTHER = 0,
+ CCLASS_DIGIT,
+ CCLASS_UPPER,
+ CCLASS_LOWER
+} char_class;
+
#define SETCHARSET_OK 1
#define SETCHARSET_FAIL 0
return SETCHARSET_FAIL;
switch(state) {
case CURLFNM_PKW_INIT:
- if(ISALPHA(c) && ISLOWER(c))
+ if(ISLOWER(c))
keyword[i] = c;
else if(c == ':')
state = CURLFNM_PKW_DDOT;
else
- return 0;
+ return SETCHARSET_FAIL;
break;
case CURLFNM_PKW_DDOT:
if(c == ']')
return SETCHARSET_OK;
}
+/* Return the character class. */
+static char_class charclass(unsigned char c)
+{
+ if(ISUPPER(c))
+ return CCLASS_UPPER;
+ if(ISLOWER(c))
+ return CCLASS_LOWER;
+ if(ISDIGIT(c))
+ return CCLASS_DIGIT;
+ return CCLASS_OTHER;
+}
+
+/* Include a character or a range in set. */
+static void setcharorrange(unsigned char **pp, unsigned char *charset)
+{
+ unsigned char *p = (*pp)++;
+ unsigned char c = *p++;
+
+ charset[c] = 1;
+ if(ISALNUM(c) && *p++ == '-') {
+ char_class cc = charclass(c);
+ unsigned char endrange = *p++;
+
+ if(endrange == '\\')
+ endrange = *p++;
+ if(endrange >= c && charclass(endrange) == cc) {
+ while(c++ != endrange)
+ if(charclass(c) == cc) /* Chars in class may be not consecutive. */
+ charset[c] = 1;
+ *pp = p;
+ }
+ }
+}
+
/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
static int setcharset(unsigned char **p, unsigned char *charset)
{
setcharset_state state = CURLFNM_SCHS_DEFAULT;
- unsigned char rangestart = 0;
- unsigned char lastchar = 0;
bool something_found = FALSE;
unsigned char c;
+
+ memset(charset, 0, CURLFNM_CHSET_SIZE);
for(;;) {
c = **p;
if(!c)
switch(state) {
case CURLFNM_SCHS_DEFAULT:
- if(ISALNUM(c)) { /* ASCII value */
- rangestart = c;
- charset[c] = 1;
- (*p)++;
- state = CURLFNM_SCHS_MAYRANGE;
- something_found = TRUE;
- }
- else if(c == ']') {
+ if(c == ']') {
if(something_found)
return SETCHARSET_OK;
something_found = TRUE;
(*p)++;
}
else if(c == '[') {
- char c2 = *((*p) + 1);
- if(c2 == ':') { /* there has to be a keyword */
- (*p) += 2;
- if(parsekeyword(p, charset)) {
- state = CURLFNM_SCHS_DEFAULT;
- }
- else
- return SETCHARSET_FAIL;
- }
+ unsigned char *pp = *p + 1;
+
+ if(*pp++ == ':' && parsekeyword(&pp, charset))
+ *p = pp;
else {
charset[c] = 1;
(*p)++;
}
something_found = TRUE;
}
- else if(c == '?' || c == '*') {
- something_found = TRUE;
- charset[c] = 1;
- (*p)++;
- }
else if(c == '^' || c == '!') {
if(!something_found) {
if(charset[CURLFNM_NEGATE]) {
}
else if(c == '\\') {
c = *(++(*p));
- if(ISPRINT((c))) {
- something_found = TRUE;
- state = CURLFNM_SCHS_MAYRANGE;
- charset[c] = 1;
- rangestart = c;
- (*p)++;
- }
+ if(c)
+ setcharorrange(p, charset);
else
- return SETCHARSET_FAIL;
+ charset['\\'] = 1;
+ something_found = TRUE;
}
else {
- charset[c] = 1;
- (*p)++;
+ setcharorrange(p, charset);
something_found = TRUE;
}
break;
- case CURLFNM_SCHS_MAYRANGE:
- if(c == '-') {
- charset[c] = 1;
- (*p)++;
- lastchar = '-';
- state = CURLFNM_SCHS_MAYRANGE2;
- }
- else if(c == '[') {
- state = CURLFNM_SCHS_DEFAULT;
- }
- else if(ISALNUM(c)) {
- charset[c] = 1;
- (*p)++;
- }
- else if(c == '\\') {
- c = *(++(*p));
- if(ISPRINT(c)) {
- charset[c] = 1;
- (*p)++;
- }
- else
- return SETCHARSET_FAIL;
- }
- else if(c == ']') {
- return SETCHARSET_OK;
- }
- else
- return SETCHARSET_FAIL;
- break;
- case CURLFNM_SCHS_MAYRANGE2:
- if(c == ']') {
- return SETCHARSET_OK;
- }
- else if(c == '\\') {
- c = *(++(*p));
- if(ISPRINT(c)) {
- charset[c] = 1;
- state = CURLFNM_SCHS_DEFAULT;
- (*p)++;
- }
- else
- return SETCHARSET_FAIL;
- }
- else if(c >= rangestart) {
- if((ISLOWER(c) && ISLOWER(rangestart)) ||
- (ISDIGIT(c) && ISDIGIT(rangestart)) ||
- (ISUPPER(c) && ISUPPER(rangestart))) {
- charset[lastchar] = 0;
- rangestart++;
- while(rangestart++ <= c)
- charset[rangestart-1] = 1;
- (*p)++;
- state = CURLFNM_SCHS_DEFAULT;
- }
- else
- return SETCHARSET_FAIL;
- }
- else
- return SETCHARSET_FAIL;
- break;
case CURLFNM_SCHS_RIGHTBR:
if(c == '[') {
state = CURLFNM_SCHS_RIGHTBRLEFTBR;
goto fail;
break;
case CURLFNM_SCHS_RIGHTBRLEFTBR:
- if(c == ']') {
+ if(c == ']')
return SETCHARSET_OK;
- }
- else {
- state = CURLFNM_SCHS_DEFAULT;
- charset[c] = 1;
- (*p)++;
- }
+ state = CURLFNM_SCHS_DEFAULT;
+ charset[c] = 1;
+ (*p)++;
break;
}
}
static int loop(const unsigned char *pattern, const unsigned char *string,
int maxstars)
{
- loop_state state = CURLFNM_LOOP_DEFAULT;
unsigned char *p = (unsigned char *)pattern;
unsigned char *s = (unsigned char *)string;
unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
- int rc = 0;
for(;;) {
- switch(state) {
- case CURLFNM_LOOP_DEFAULT:
- if(*p == '*') {
- if(!maxstars)
- return CURL_FNMATCH_NOMATCH;
- while(*(p + 1) == '*') /* eliminate multiple stars */
- p++;
- if(*s == '\0' && *(p + 1) == '\0')
- return CURL_FNMATCH_MATCH;
- rc = loop(p + 1, s, maxstars - 1); /* *.txt matches .txt <=>
- .txt matches .txt */
- if(rc == CURL_FNMATCH_MATCH)
+ unsigned char *pp;
+
+ switch(*p) {
+ case '*':
+ if(!maxstars)
+ return CURL_FNMATCH_NOMATCH;
+ /* Regroup consecutive stars and question marks. This can be done because
+ '*?*?*' can be expressed as '??*'. */
+ for(;;) {
+ if(*++p == '\0')
return CURL_FNMATCH_MATCH;
- if(*s) /* let the star eat up one character */
- s++;
- else
- return CURL_FNMATCH_NOMATCH;
- }
- else if(*p == '?') {
- if(ISPRINT(*s)) {
- s++;
- p++;
+ if(*p == '?') {
+ if(!*s++)
+ return CURL_FNMATCH_NOMATCH;
}
- else if(*s == '\0')
- return CURL_FNMATCH_NOMATCH;
- else
- return CURL_FNMATCH_FAIL; /* cannot deal with other character */
+ else if(*p != '*')
+ break;
}
- else if(*p == '\0') {
- if(*s == '\0')
+ /* Skip string characters until we find a match with pattern suffix. */
+ for(maxstars--; *s; s++) {
+ if(loop(p, s, maxstars) == CURL_FNMATCH_MATCH)
return CURL_FNMATCH_MATCH;
- return CURL_FNMATCH_NOMATCH;
}
- else if(*p == '\\') {
- state = CURLFNM_LOOP_BACKSLASH;
+ return CURL_FNMATCH_NOMATCH;
+ case '?':
+ if(!*s)
+ return CURL_FNMATCH_NOMATCH;
+ s++;
+ p++;
+ break;
+ case '\0':
+ return *s? CURL_FNMATCH_NOMATCH: CURL_FNMATCH_MATCH;
+ case '\\':
+ if(p[1])
p++;
- }
- else if(*p == '[') {
- unsigned char *pp = p + 1; /* cannot handle with pointer to register */
- if(setcharset(&pp, charset)) {
- int found = FALSE;
- if(charset[(unsigned int)*s])
- found = TRUE;
- else if(charset[CURLFNM_ALNUM])
- found = ISALNUM(*s);
- else if(charset[CURLFNM_ALPHA])
- found = ISALPHA(*s);
- else if(charset[CURLFNM_DIGIT])
- found = ISDIGIT(*s);
- else if(charset[CURLFNM_XDIGIT])
- found = ISXDIGIT(*s);
- else if(charset[CURLFNM_PRINT])
- found = ISPRINT(*s);
- else if(charset[CURLFNM_SPACE])
- found = ISSPACE(*s);
- else if(charset[CURLFNM_UPPER])
- found = ISUPPER(*s);
- else if(charset[CURLFNM_LOWER])
- found = ISLOWER(*s);
- else if(charset[CURLFNM_BLANK])
- found = ISBLANK(*s);
- else if(charset[CURLFNM_GRAPH])
- found = ISGRAPH(*s);
+ if(*s++ != *p++)
+ return CURL_FNMATCH_NOMATCH;
+ break;
+ case '[':
+ pp = p + 1; /* Copy in case of syntax error in set. */
+ if(setcharset(&pp, charset)) {
+ int found = FALSE;
+ if(!*s)
+ return CURL_FNMATCH_NOMATCH;
+ if(charset[(unsigned int)*s])
+ found = TRUE;
+ else if(charset[CURLFNM_ALNUM])
+ found = ISALNUM(*s);
+ else if(charset[CURLFNM_ALPHA])
+ found = ISALPHA(*s);
+ else if(charset[CURLFNM_DIGIT])
+ found = ISDIGIT(*s);
+ else if(charset[CURLFNM_XDIGIT])
+ found = ISXDIGIT(*s);
+ else if(charset[CURLFNM_PRINT])
+ found = ISPRINT(*s);
+ else if(charset[CURLFNM_SPACE])
+ found = ISSPACE(*s);
+ else if(charset[CURLFNM_UPPER])
+ found = ISUPPER(*s);
+ else if(charset[CURLFNM_LOWER])
+ found = ISLOWER(*s);
+ else if(charset[CURLFNM_BLANK])
+ found = ISBLANK(*s);
+ else if(charset[CURLFNM_GRAPH])
+ found = ISGRAPH(*s);
- if(charset[CURLFNM_NEGATE])
- found = !found;
+ if(charset[CURLFNM_NEGATE])
+ found = !found;
- if(found) {
- p = pp + 1;
- if(*s)
- /* don't advance if we're matching on an empty string */
- s++;
- memset(charset, 0, CURLFNM_CHSET_SIZE);
- }
- else
- return CURL_FNMATCH_NOMATCH;
- }
- else
- return CURL_FNMATCH_FAIL;
- }
- else {
- if(*p++ != *s++)
+ if(!found)
return CURL_FNMATCH_NOMATCH;
+ p = pp + 1;
+ s++;
+ break;
}
- break;
- case CURLFNM_LOOP_BACKSLASH:
- if(ISPRINT(*p)) {
- if(*p++ == *s++)
- state = CURLFNM_LOOP_DEFAULT;
- else
- return CURL_FNMATCH_NOMATCH;
- }
- else
- return CURL_FNMATCH_FAIL;
+
+ /* Syntax error in set: this must be taken as a regular character. */
+ /* FALLTHROUGH */
+ default:
+ if(*p++ != *s++)
+ return CURL_FNMATCH_NOMATCH;
break;
}
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "curl_gssapi.h"
#include "sendf.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
static char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02";
gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes };
static char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02";
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
void *
Curl_memrchr(const void *s, int c, size_t n)
{
- const unsigned char *p = s;
- const unsigned char *q = s;
+ if(n > 0) {
+ const unsigned char *p = s;
+ const unsigned char *q = s;
- p += n - 1;
+ p += n - 1;
- while(p >= q) {
- if(*p == (unsigned char)c)
- return (void *)p;
- p--;
+ while(p >= q) {
+ if(*p == (unsigned char)c)
+ return (void *)p;
+ p--;
+ }
}
-
return NULL;
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
return CURLE_OK;
}
-#ifndef SIZE_T_MAX
-/* some limits.h headers have this defined, some don't */
-#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
-#define SIZE_T_MAX 18446744073709551615U
-#else
-#define SIZE_T_MAX 4294967295U
-#endif
-#endif
-
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
* (uppercase UserName + Domain) as the data
*/
len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
/* Allocate the response */
- ptr = malloc(len);
+ ptr = calloc(1, len);
if(!ptr)
return CURLE_OUT_OF_MEMORY;
- memset(ptr, 0, len);
-
/* Create the BLOB structure */
snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
"%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
case NTLMSTATE_TYPE1:
default:
/* Use Samba's 'winbind' daemon to support NTLM authentication,
- * by delegating the NTLM challenge/response protocal to a helper
+ * by delegating the NTLM challenge/response protocol to a helper
* in ntlm_auth.
* http://devel.squid-cache.org/ntlm/squid_helper_protocol.html
* https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
+#ifndef HEADER_CURL_PATH_H
+#define HEADER_CURL_PATH_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
char **path);
CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir);
+#endif
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include <curl/curl.h>
+#include "curl_range.h"
+#include "sendf.h"
+#include "strtoofft.h"
+
+/* Only include this function if one or more of FTP, FILE are enabled. */
+#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)
+
+ /*
+ Check if this is a range download, and if so, set the internal variables
+ properly.
+ */
+CURLcode Curl_range(struct connectdata *conn)
+{
+ curl_off_t from, to;
+ char *ptr;
+ char *ptr2;
+ struct Curl_easy *data = conn->data;
+
+ if(data->state.use_range && data->state.range) {
+ CURLofft from_t;
+ CURLofft to_t;
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+ if(from_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ ptr++;
+ to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+ if(to_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ if((to_t == CURL_OFFT_INVAL) && !from_t) {
+ /* X - */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
+ from));
+ }
+ else if((from_t == CURL_OFFT_INVAL) && !to_t) {
+ /* -Y */
+ data->req.maxdownload = to;
+ data->state.resume_from = -to;
+ DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ to));
+ }
+ else {
+ /* X-Y */
+ curl_off_t totalsize;
+
+ /* Ensure the range is sensible - to should follow from. */
+ if(from > to)
+ return CURLE_RANGE_ERROR;
+
+ totalsize = to - from;
+ if(totalsize == CURL_OFF_T_MAX)
+ return CURLE_RANGE_ERROR;
+
+ data->req.maxdownload = totalsize + 1; /* include last byte */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
+ " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, data->req.maxdownload));
+ }
+ DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
+ " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, to, data->req.maxdownload));
+ }
+ else
+ data->req.maxdownload = -1;
+ return CURLE_OK;
+}
+
+#endif
--- /dev/null
+#ifndef HEADER_CURL_RANGE_H
+#define HEADER_CURL_RANGE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "urldata.h"
+
+CURLcode Curl_range(struct connectdata *conn);
+
+#endif /* HEADER_CURL_RANGE_H */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
-#if defined(USE_KERBEROS5)
+#if defined(USE_KERBEROS5) || defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_ntlm_type1_message(data,
conn->user, conn->passwd,
- &conn->ntlm, &resp, &len);
+ service,
+ hostname,
+ &conn->ntlm, &resp,
+ &len);
}
else
#endif
conn->oauth_bearer,
&resp, &len);
}
- else if(enabledmechs & SASL_MECH_LOGIN) {
- mech = SASL_MECH_STRING_LOGIN;
- state1 = SASL_LOGIN;
- state2 = SASL_LOGIN_PASSWD;
- sasl->authused = SASL_MECH_LOGIN;
-
- if(force_ir || data->set.sasl_ir)
- result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
- }
else if(enabledmechs & SASL_MECH_PLAIN) {
mech = SASL_MECH_STRING_PLAIN;
state1 = SASL_PLAIN;
result = Curl_auth_create_plain_message(data, conn->user, conn->passwd,
&resp, &len);
}
+ else if(enabledmechs & SASL_MECH_LOGIN) {
+ mech = SASL_MECH_STRING_LOGIN;
+ state1 = SASL_LOGIN;
+ state2 = SASL_LOGIN_PASSWD;
+ sasl->authused = SASL_MECH_LOGIN;
+
+ if(force_ir || data->set.sasl_ir)
+ result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
+ }
}
if(!result && mech) {
char *chlg = NULL;
size_t chlglen = 0;
#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5)
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
+ defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_NTLM)
char *serverdata;
#endif
size_t len = 0;
/* Create the type-1 message */
result = Curl_auth_create_ntlm_type1_message(data,
conn->user, conn->passwd,
+ service, hostname,
&conn->ntlm, &resp, &len);
newstate = SASL_NTLM_TYPE2MSG;
break;
# define LSEEK_ERROR (off_t)-1
#endif
+#ifndef SIZEOF_TIME_T
+/* assume default size of time_t to be 32 bit */
+#define SIZEOF_TIME_T 4
+#endif
+
/*
* Default sizeof(off_t) in case it hasn't been defined in config file.
*/
#endif
#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
+#if (SIZEOF_TIME_T == 4)
+# ifdef HAVE_TIME_T_UNSIGNED
+# define TIME_T_MAX UINT_MAX
+# define TIME_T_MIN 0
+# else
+# define TIME_T_MAX INT_MAX
+# define TIME_T_MIN INT_MIN
+# endif
+#else
+# ifdef HAVE_TIME_T_UNSIGNED
+# define TIME_T_MAX 0xFFFFFFFFFFFFFFFF
+# define TIME_T_MIN 0
+# else
+# define TIME_T_MAX 0x7FFFFFFFFFFFFFFF
+# define TIME_T_MIN (-TIME_T_MAX - 1)
+# endif
+#endif
+
+#ifndef SIZE_T_MAX
+/* some limits.h headers have this defined, some don't */
+#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
+#define SIZE_T_MAX 18446744073709551615U
+#else
+#define SIZE_T_MAX 4294967295U
+#endif
+#endif
+
/*
* Arg 2 type for gethostname in case it hasn't been defined in config file.
*/
#error "Both libidn2 and WinIDN are enabled, choose one."
#endif
-#ifndef SIZEOF_TIME_T
-/* assume default size of time_t to be 32 bit */
-#define SIZEOF_TIME_T 4
-#endif
-
#define LIBIDN_REQUIRED_VERSION "0.4.1"
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
# if defined(WIN32) || defined(__CYGWIN__)
# define USE_RECV_BEFORE_SEND_WORKAROUND
# endif
-#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
+#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
# ifdef USE_RECV_BEFORE_SEND_WORKAROUND
# undef USE_RECV_BEFORE_SEND_WORKAROUND
# endif
-#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
+#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
/* Detect Windows App environment which has a restricted access
* to the Win32 APIs. */
# endif
# endif
+/* for systems that don't detect this in configure, use a sensible default */
+#ifndef CURL_SA_FAMILY_T
+#define CURL_SA_FAMILY_T unsigned short
+#endif
+
#endif /* HEADER_CURL_SETUP_H */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
# endif
#endif
-
/*
* Definition of timeval struct for platforms that don't have it.
*/
# define sfcntl fcntl
#endif
-/*
- * Uppercase macro versions of ANSI/ISO is*() functions/macros which
- * avoid negative number inputs with argument byte codes > 127.
- */
-
-#define ISSPACE(x) (isspace((int) ((unsigned char)x)))
-#define ISDIGIT(x) (isdigit((int) ((unsigned char)x)))
-#define ISALNUM(x) (isalnum((int) ((unsigned char)x)))
-#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
-#define ISGRAPH(x) (isgraph((int) ((unsigned char)x)))
-#define ISALPHA(x) (isalpha((int) ((unsigned char)x)))
-#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
-#define ISUPPER(x) (isupper((int) ((unsigned char)x)))
-#define ISLOWER(x) (islower((int) ((unsigned char)x)))
-#define ISASCII(x) (isascii((int) ((unsigned char)x)))
-
-#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
- (((unsigned char)x) == '\t'))
-
#define TOLOWER(x) (tolower((int) ((unsigned char)x)))
#define FALSE false
#endif
+#include "curl_ctype.h"
/*
* Macro WHILE_FALSE may be used to build single-iteration do-while loops,
#include "strdup.h"
#include "progress.h"
#include "easyif.h"
+#include "multiif.h"
#include "select.h"
#include "sendf.h" /* for failf function prototype */
#include "connect.h" /* for Curl_getconnectinfo */
#include "sigpipe.h"
#include "ssh.h"
#include "setopt.h"
+#include "http_digest.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(data->set.errorbuffer)
+ /* clear this as early as possible */
+ data->set.errorbuffer[0] = 0;
+
if(data->multi) {
failf(data, "easy handle already used in multi handle");
return CURLE_FAILED_INIT;
data->multi_easy = multi;
}
+ if(multi->in_callback)
+ return CURLE_RECURSIVE_API_CALL;
+
/* Copy the MAXCONNECTS option to the multi handle */
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
/* Duplicate mime data. */
result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
+ if(src->set.resolve)
+ dst->change.resolve = dst->set.resolve;
+
return result;
}
/* zero out authentication data: */
memset(&data->state.authhost, 0, sizeof(struct auth));
memset(&data->state.authproxy, 0, sizeof(struct auth));
+ Curl_digest_cleanup(data);
}
/*
* the pausing, you may get your write callback called at this point.
*
* Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
+ *
+ * NOTE: This is one of few API functions that are allowed to be called from
+ * within a callback.
*/
CURLcode curl_easy_pause(struct Curl_easy *data, int action)
{
/* even if one function returns error, this loops through and frees all
buffers */
if(!result)
- result = Curl_client_chop_write(conn,
- writebuf[i].type,
- writebuf[i].buf,
- writebuf[i].len);
+ result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
+ writebuf[i].len);
free(writebuf[i].buf);
}
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
+ /* This transfer may have been moved in or out of the bundle, update
+ the corresponding socket callback, if used */
+ Curl_updatesocket(data);
+
return result;
}
ssize_t n1;
struct connectdata *c;
+ if(Curl_is_in_callback(data))
+ return CURLE_RECURSIVE_API_CALL;
+
result = easy_connection(data, &sfd, &c);
if(result)
return result;
ssize_t n1;
struct connectdata *c = NULL;
+ if(Curl_is_in_callback(data))
+ return CURLE_RECURSIVE_API_CALL;
+
result = easy_connection(data, &sfd, &c);
if(result)
return result;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "url.h"
#include "parsedate.h" /* for the week day and month names */
#include "warnless.h"
+#include "curl_range.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
return CURLE_OK;
}
- /*
- Check if this is a range download, and if so, set the internal variables
- properly. This code is copied from the FTP implementation and might as
- well be factored out.
- */
-static CURLcode file_range(struct connectdata *conn)
-{
- curl_off_t from, to;
- curl_off_t totalsize = -1;
- char *ptr;
- char *ptr2;
- struct Curl_easy *data = conn->data;
-
- if(data->state.use_range && data->state.range) {
- CURLofft from_t;
- CURLofft to_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
- if(from_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
- ptr++;
- to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
- if(to_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- if((to_t == CURL_OFFT_INVAL) && !from_t) {
- /* X - */
- data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
- from));
- }
- else if((from_t == CURL_OFFT_INVAL) && !to_t) {
- /* -Y */
- data->req.maxdownload = to;
- data->state.resume_from = -to;
- DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- to));
- }
- else {
- /* X-Y */
- totalsize = to-from;
- if(totalsize == CURL_OFF_T_MAX)
- /* this is too big to increase, so bail out */
- return CURLE_RANGE_ERROR;
- data->req.maxdownload = totalsize + 1; /* include last byte */
- data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
- " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- from, data->req.maxdownload));
- }
- DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
- " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
- CURL_FORMAT_CURL_OFF_T " bytes\n",
- from, to, data->req.maxdownload));
- }
- else
- data->req.maxdownload = -1;
- return CURLE_OK;
-}
-
/*
* file_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time. We emulate a
/* we could stat it, then read out the size */
expected_size = statbuf.st_size;
/* and store the modification time */
- data->info.filetime = (long)statbuf.st_mtime;
+ data->info.filetime = statbuf.st_mtime;
fstated = TRUE;
}
if(fstated && !data->state.range && data->set.timecondition) {
- if(!Curl_meets_timecondition(data, (time_t)data->info.filetime)) {
+ if(!Curl_meets_timecondition(data, data->info.filetime)) {
*done = TRUE;
return CURLE_OK;
}
}
/* Check whether file range has been specified */
- file_range(conn);
+ result = Curl_range(conn);
+ if(result)
+ return result;
/* Adjust the start offset in case we want to get the N last bytes
* of the stream iff the filesize could be determined */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
return calloc(1, sizeof(struct fileinfo));
}
-void Curl_fileinfo_dtor(void *user, void *element)
+void Curl_fileinfo_cleanup(struct fileinfo *finfo)
{
- struct fileinfo *finfo = element;
- (void) user;
if(!finfo)
return;
Curl_safefree(finfo->info.b_data);
-
free(finfo);
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
};
struct fileinfo *Curl_fileinfo_alloc(void);
-
-void Curl_fileinfo_dtor(void *, void *);
+void Curl_fileinfo_cleanup(struct fileinfo *finfo);
#endif /* HEADER_CURL_FILEINFO_H */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
/***************************************************************************
*
- * ContentTypeForFilename()
- *
- * Provides content type for filename if one of the known types (else
- * (either the prevtype or the default is returned).
- *
- * Returns some valid contenttype for filename.
- *
- ***************************************************************************/
-static const char *ContentTypeForFilename(const char *filename,
- const char *prevtype)
-{
- const char *contenttype = NULL;
- unsigned int i;
- /*
- * No type was specified, we scan through a few well-known
- * extensions and pick the first we match!
- */
- struct ContentType {
- const char *extension;
- const char *type;
- };
- static const struct ContentType ctts[]={
- {".gif", "image/gif"},
- {".jpg", "image/jpeg"},
- {".jpeg", "image/jpeg"},
- {".txt", "text/plain"},
- {".html", "text/html"},
- {".xml", "application/xml"}
- };
-
- if(prevtype)
- /* default to the previously set/used! */
- contenttype = prevtype;
- else
- contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
-
- if(filename) { /* in case a NULL was passed in */
- for(i = 0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
- if(strlen(filename) >= strlen(ctts[i].extension)) {
- if(strcasecompare(filename +
- strlen(filename) - strlen(ctts[i].extension),
- ctts[i].extension)) {
- contenttype = ctts[i].type;
- break;
- }
- }
- }
- }
- /* we have a contenttype by now */
- return contenttype;
-}
-
-/***************************************************************************
- *
* FormAdd()
*
* Stores a formpost parameter and builds the appropriate linked list.
!form->contenttype) {
char *f = form->flags & HTTPPOST_BUFFER?
form->showfilename : form->value;
+ char const *type;
+ type = Curl_mime_contenttype(f);
+ if(!type)
+ type = prevtype;
+ if(!type)
+ type = FILE_CONTENTTYPE_DEFAULT;
/* our contenttype is missing */
- form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
+ form->contenttype = strdup(type);
if(!form->contenttype) {
return_value = CURL_FORMADD_MEMORY;
break;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "ftp.h"
#include "fileinfo.h"
#include "ftplistparser.h"
+#include "curl_range.h"
#include "curl_sec.h"
#include "strtoofft.h"
#include "strcase.h"
int error = 0;
/* activate callback for setting socket options */
+ Curl_set_in_callback(data, true);
error = data->set.fsockopt(data->set.sockopt_client,
s,
CURLSOCKTYPE_ACCEPT);
+ Curl_set_in_callback(data, false);
if(error) {
close_secondarysocket(conn);
slashPos = strrchr(inpath, '/');
n = slashPos - inpath;
}
- result = Curl_urldecode(data, inpath, n, &lstArg, NULL, FALSE);
+ result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE);
if(result)
return result;
}
date. */
if(data->set.opt_no_body && ftpc->file &&
ftp_need_type(conn, data->set.prefer_ascii)) {
- /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
+ /* The SIZE command is _not_ RFC 959 specified, and therefore many servers
may not support it! It is however the only way we have to get a file's
size! */
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
{
CURLcode result = CURLE_OK;
- if(conn->bits.ipv6) {
+ if(conn->bits.ipv6 && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)) {
/* We can't disable EPSV when doing IPv6, so this is instead a fail */
failf(conn->data, "Failed EPSV attempt, exiting\n");
return CURLE_WEIRD_SERVER_REPLY;
if(data->set.ftp_skip_ip) {
/* told to ignore the remotely given IP but instead use the host we used
for the control connection */
- infof(data, "Skip %d.%d.%d.%d for data connection, re-use %s instead\n",
+ infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead\n",
ip[0], ip[1], ip[2], ip[3],
conn->host.name);
ftpc->newhost = strdup(control_address(conn));
}
else
- ftpc->newhost = aprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+ ftpc->newhost = aprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
if(!ftpc->newhost)
return CURLE_OUT_OF_MEMORY;
"%04d%02d%02d %02d:%02d:%02d GMT",
year, month, day, hour, minute, second);
/* now, convert this into a time() value: */
- data->info.filetime = (long)curl_getdate(timebuf, &secs);
+ data->info.filetime = curl_getdate(timebuf, &secs);
}
#ifdef CURL_FTP_HTTPSTYLE_HEAD
data->set.get_filetime &&
(data->info.filetime >= 0) ) {
char headerbuf[128];
- time_t filetime = (time_t)data->info.filetime;
+ time_t filetime = data->info.filetime;
struct tm buffer;
const struct tm *tm = &buffer;
if(data->state.wildcardmatch) {
if(data->set.chunk_end && ftpc->file) {
+ Curl_set_in_callback(data, true);
data->set.chunk_end(data->wildcard.customptr);
+ Curl_set_in_callback(data, false);
}
ftpc->known_filesize = -1;
}
if(!result)
/* get the "raw" path */
- result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
+ result = Curl_urldecode(data, path_to_use, 0, &path, NULL, TRUE);
if(result) {
/* We can limp along anyway (and should try to since we may already be in
* the error path) */
#endif
/*
- Check if this is a range download, and if so, set the internal variables
- properly.
- */
-
-static CURLcode ftp_range(struct connectdata *conn)
-{
- curl_off_t from, to;
- char *ptr;
- struct Curl_easy *data = conn->data;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
-
- if(data->state.use_range && data->state.range) {
- CURLofft from_t;
- CURLofft to_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
- if(from_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
- ptr++;
- to_t = curlx_strtoofft(ptr, NULL, 0, &to);
- if(to_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- if((to_t == CURL_OFFT_INVAL) && !from_t) {
- /* X - */
- data->state.resume_from = from;
- DEBUGF(infof(conn->data, "FTP RANGE %" CURL_FORMAT_CURL_OFF_T
- " to end of file\n", from));
- }
- else if(!to_t && (from_t == CURL_OFFT_INVAL)) {
- /* -Y */
- data->req.maxdownload = to;
- data->state.resume_from = -to;
- DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T
- " bytes\n", to));
- }
- else {
- /* X-Y */
- data->req.maxdownload = (to - from) + 1; /* include last byte */
- data->state.resume_from = from;
- DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T
- " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- from, data->req.maxdownload));
- }
- DEBUGF(infof(conn->data, "range-download from %" CURL_FORMAT_CURL_OFF_T
- " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
- CURL_FORMAT_CURL_OFF_T " bytes\n",
- from, to, data->req.maxdownload));
- ftpc->dont_check = TRUE; /* don't check for successful transfer */
- }
- else
- data->req.maxdownload = -1;
- return CURLE_OK;
-}
-
-
-/*
* ftp_do_more()
*
* This function shall be called when the second FTP (data) connection is
/* download */
ftp->downloadsize = -1; /* unknown as of yet */
- result = ftp_range(conn);
+ result = Curl_range(conn);
+
+ if(result == CURLE_OK && data->req.maxdownload >= 0) {
+ /* Don't check for successful transfer */
+ ftpc->dont_check = TRUE;
+ }
+
if(result)
;
else if(data->set.ftp_list_only || !ftpc->file) {
static void wc_data_dtor(void *ptr)
{
- struct ftp_wc_tmpdata *tmp = ptr;
- if(tmp)
- Curl_ftp_parselist_data_free(&tmp->parser);
- free(tmp);
+ struct ftp_wc *ftpwc = ptr;
+ if(ftpwc && ftpwc->parser)
+ Curl_ftp_parselist_data_free(&ftpwc->parser);
+ free(ftpwc);
}
static CURLcode init_wc_data(struct connectdata *conn)
char *path = conn->data->state.path;
struct WildcardData *wildcard = &(conn->data->wildcard);
CURLcode result = CURLE_OK;
- struct ftp_wc_tmpdata *ftp_tmp;
+ struct ftp_wc *ftpwc = NULL;
last_slash = strrchr(conn->data->state.path, '/');
if(last_slash) {
/* program continues only if URL is not ending with slash, allocate needed
resources for wildcard transfer */
- /* allocate ftp protocol specific temporary wildcard data */
- ftp_tmp = calloc(1, sizeof(struct ftp_wc_tmpdata));
- if(!ftp_tmp) {
- Curl_safefree(wildcard->pattern);
- return CURLE_OUT_OF_MEMORY;
+ /* allocate ftp protocol specific wildcard data */
+ ftpwc = calloc(1, sizeof(struct ftp_wc));
+ if(!ftpwc) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
/* INITIALIZE parselist structure */
- ftp_tmp->parser = Curl_ftp_parselist_data_alloc();
- if(!ftp_tmp->parser) {
- Curl_safefree(wildcard->pattern);
- free(ftp_tmp);
- return CURLE_OUT_OF_MEMORY;
+ ftpwc->parser = Curl_ftp_parselist_data_alloc();
+ if(!ftpwc->parser) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
- wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */
- wildcard->tmp_dtor = wc_data_dtor;
+ wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */
+ wildcard->dtor = wc_data_dtor;
/* wildcard does not support NOCWD option (assert it?) */
if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
/* try to parse ftp url */
result = ftp_parse_url_path(conn);
if(result) {
- Curl_safefree(wildcard->pattern);
- wildcard->tmp_dtor(wildcard->tmp);
- wildcard->tmp_dtor = ZERO_NULL;
- wildcard->tmp = NULL;
- return result;
+ goto fail;
}
wildcard->path = strdup(conn->data->state.path);
if(!wildcard->path) {
- Curl_safefree(wildcard->pattern);
- wildcard->tmp_dtor(wildcard->tmp);
- wildcard->tmp_dtor = ZERO_NULL;
- wildcard->tmp = NULL;
- return CURLE_OUT_OF_MEMORY;
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
/* backup old write_function */
- ftp_tmp->backup.write_function = conn->data->set.fwrite_func;
+ ftpwc->backup.write_function = conn->data->set.fwrite_func;
/* parsing write function */
conn->data->set.fwrite_func = Curl_ftp_parselist;
/* backup old file descriptor */
- ftp_tmp->backup.file_descriptor = conn->data->set.out;
+ ftpwc->backup.file_descriptor = conn->data->set.out;
/* let the writefunc callback know what curl pointer is working with */
conn->data->set.out = conn;
infof(conn->data, "Wildcard - Parsing started\n");
return CURLE_OK;
+
+ fail:
+ if(ftpwc) {
+ Curl_ftp_parselist_data_free(&ftpwc->parser);
+ free(ftpwc);
+ }
+ Curl_safefree(wildcard->pattern);
+ wildcard->dtor = ZERO_NULL;
+ wildcard->protdata = NULL;
+ return result;
}
/* This is called recursively */
case CURLWC_MATCHING: {
/* In this state is LIST response successfully parsed, so lets restore
previous WRITEFUNCTION callback and WRITEDATA pointer */
- struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
- conn->data->set.fwrite_func = ftp_tmp->backup.write_function;
- conn->data->set.out = ftp_tmp->backup.file_descriptor;
- ftp_tmp->backup.write_function = ZERO_NULL;
- ftp_tmp->backup.file_descriptor = NULL;
+ struct ftp_wc *ftpwc = wildcard->protdata;
+ conn->data->set.fwrite_func = ftpwc->backup.write_function;
+ conn->data->set.out = ftpwc->backup.file_descriptor;
+ ftpwc->backup.write_function = ZERO_NULL;
+ ftpwc->backup.file_descriptor = NULL;
wildcard->state = CURLWC_DOWNLOADING;
- if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) {
+ if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
/* error found in LIST parsing */
wildcard->state = CURLWC_CLEAN;
return wc_statemach(conn);
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
if(conn->data->set.chunk_bgn) {
- long userresponse = conn->data->set.chunk_bgn(
+ long userresponse;
+ Curl_set_in_callback(conn->data, true);
+ userresponse = conn->data->set.chunk_bgn(
finfo, wildcard->customptr, (int)wildcard->filelist.size);
+ Curl_set_in_callback(conn->data, false);
switch(userresponse) {
case CURL_CHUNK_BGN_FUNC_SKIP:
infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
} break;
case CURLWC_SKIP: {
- if(conn->data->set.chunk_end)
+ if(conn->data->set.chunk_end) {
+ Curl_set_in_callback(conn->data, true);
conn->data->set.chunk_end(conn->data->wildcard.customptr);
+ Curl_set_in_callback(conn->data, false);
+ }
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
wildcard->state = (wildcard->filelist.size == 0) ?
CURLWC_CLEAN : CURLWC_DOWNLOADING;
}
case CURLWC_CLEAN: {
- struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
+ struct ftp_wc *ftpwc = wildcard->protdata;
result = CURLE_OK;
- if(ftp_tmp)
- result = Curl_ftp_parselist_geterror(ftp_tmp->parser);
+ if(ftpwc)
+ result = Curl_ftp_parselist_geterror(ftpwc->parser);
wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
} break;
case CURLWC_DONE:
case CURLWC_ERROR:
case CURLWC_CLEAR:
+ if(wildcard->dtor)
+ wildcard->dtor(wildcard->protdata);
break;
}
result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
slash_pos ? dirlen : 1,
&ftpc->dirs[0], NULL,
- FALSE);
+ TRUE);
if(result) {
freedirs(ftpc);
return result;
size_t dlen;
char *path;
CURLcode result =
- Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE);
+ Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, TRUE);
if(result) {
freedirs(ftpc);
return result;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
struct ftp_parselist_data; /* defined later in ftplistparser.c */
-struct ftp_wc_tmpdata {
+struct ftp_wc {
struct ftp_parselist_data *parser;
struct {
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "ftplistparser.h"
#include "curl_fnmatch.h"
#include "curl_memory.h"
+#include "multiif.h"
/* The last #include file should be: */
#include "memdebug.h"
}
-void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
+void Curl_ftp_parselist_data_free(struct ftp_parselist_data **parserp)
{
- free(*pl_data);
- *pl_data = NULL;
+ struct ftp_parselist_data *parser = *parserp;
+ if(parser)
+ Curl_fileinfo_cleanup(parser->file_data);
+ free(parser);
+ *parserp = NULL;
}
{
curl_fnmatch_callback compare;
struct WildcardData *wc = &conn->data->wildcard;
- struct ftp_wc_tmpdata *tmpdata = wc->tmp;
+ struct ftp_wc *ftpwc = wc->protdata;
struct curl_llist *llist = &wc->filelist;
- struct ftp_parselist_data *parser = tmpdata->parser;
+ struct ftp_parselist_data *parser = ftpwc->parser;
bool add = TRUE;
struct curl_fileinfo *finfo = &infop->info;
compare = Curl_fnmatch;
/* filter pattern-corresponding filenames */
+ Curl_set_in_callback(conn->data, true);
if(compare(conn->data->set.fnmatch_data, wc->pattern,
finfo->filename) == 0) {
/* discard symlink which is containing multiple " -> " */
else {
add = FALSE;
}
+ Curl_set_in_callback(conn->data, false);
if(add) {
Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
}
else {
- Curl_fileinfo_dtor(NULL, finfo);
+ Curl_fileinfo_cleanup(infop);
}
- tmpdata->parser->file_data = NULL;
+ ftpwc->parser->file_data = NULL;
return CURLE_OK;
}
{
size_t bufflen = size*nmemb;
struct connectdata *conn = (struct connectdata *)connptr;
- struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
- struct ftp_parselist_data *parser = tmpdata->parser;
+ struct ftp_wc *ftpwc = conn->data->wildcard.protdata;
+ struct ftp_parselist_data *parser = ftpwc->parser;
struct fileinfo *infop;
struct curl_fileinfo *finfo;
unsigned long i = 0;
finfo->b_data = tmp;
}
else {
- Curl_fileinfo_dtor(NULL, parser->file_data);
+ Curl_fileinfo_cleanup(parser->file_data);
parser->file_data = NULL;
parser->error = CURLE_OUT_OF_MEMORY;
goto fail;
i++;
}
+ return retsize;
fail:
/* Clean up any allocated memory. */
if(parser->file_data) {
- Curl_fileinfo_dtor(NULL, parser->file_data);
+ Curl_fileinfo_cleanup(parser->file_data);
parser->file_data = NULL;
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
*param_longp = data->info.httpproxycode;
break;
case CURLINFO_FILETIME:
- *param_longp = data->info.filetime;
+ if(data->info.filetime > LONG_MAX)
+ *param_longp = LONG_MAX;
+ else if(data->info.filetime < LONG_MIN)
+ *param_longp = LONG_MIN;
+ else
+ *param_longp = (long)data->info.filetime;
break;
case CURLINFO_HEADER_SIZE:
*param_longp = data->info.header_size;
curl_off_t *param_offt)
{
switch(info) {
+ case CURLINFO_FILETIME_T:
+ *param_offt = (curl_off_t)data->info.filetime;
+ break;
case CURLINFO_SIZE_UPLOAD_T:
*param_offt = data->progress.uploaded;
break;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
{
const char *key_str = (const char *) key;
const char *end = key_str + key_length;
- unsigned long h = 5381;
+ size_t h = 5381;
while(key_str < end) {
h += h << 5;
- h ^= (unsigned long) *key_str++;
+ h ^= *key_str++;
}
return (h % slots_num);
#if defined(USE_OPENSSL) \
|| defined(USE_AXTLS) \
|| defined(USE_GSKIT) \
- || (defined(USE_SCHANNEL) && defined(_WIN32_WCE))
+ || defined(USE_SCHANNEL)
/* these backends use functions from this file */
#ifdef HAVE_NETINET_IN_H
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
+#include "rand.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#include "inet_ntop.h"
+#include "multiif.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
}
/*
+ * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
+ * struct by re-linking its linked list.
+ *
+ * The addr argument should be the address of a pointer to the head node of a
+ * `Curl_addrinfo` list and it will be modified to point to the new head after
+ * shuffling.
+ *
+ * Not declared static only to make it easy to use in a unit test!
+ *
+ * @unittest: 1608
+ */
+CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr)
+{
+ CURLcode result = CURLE_OK;
+ const int num_addrs = Curl_num_addresses(*addr);
+
+ if(num_addrs > 1) {
+ Curl_addrinfo **nodes;
+ infof(data, "Shuffling %i addresses", num_addrs);
+
+ nodes = malloc(num_addrs*sizeof(*nodes));
+ if(nodes) {
+ int i;
+ unsigned int *rnd;
+ const size_t rnd_size = num_addrs * sizeof(*rnd);
+
+ /* build a plain array of Curl_addrinfo pointers */
+ nodes[0] = *addr;
+ for(i = 1; i < num_addrs; i++) {
+ nodes[i] = nodes[i-1]->ai_next;
+ }
+
+ rnd = malloc(rnd_size);
+ if(rnd) {
+ /* Fisher-Yates shuffle */
+ if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) {
+ Curl_addrinfo *swap_tmp;
+ for(i = num_addrs - 1; i > 0; i--) {
+ swap_tmp = nodes[rnd[i] % (i + 1)];
+ nodes[rnd[i] % (i + 1)] = nodes[i];
+ nodes[i] = swap_tmp;
+ }
+
+ /* relink list in the new order */
+ for(i = 1; i < num_addrs; i++) {
+ nodes[i-1]->ai_next = nodes[i];
+ }
+
+ nodes[num_addrs-1]->ai_next = NULL;
+ *addr = nodes[0];
+ }
+ free(rnd);
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ free(nodes);
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ return result;
+}
+
+/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
*
* When calling Curl_resolv() has resulted in a response with a returned
struct Curl_dns_entry *dns;
struct Curl_dns_entry *dns2;
+ /* shuffle addresses if requested */
+ if(data->set.dns_shuffle_addresses) {
+ CURLcode result = Curl_shuffle_addr(data, &addr);
+ if(!result)
+ return NULL;
+ }
+
/* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
if(!Curl_ipvalid(conn))
return CURLRESOLV_ERROR;
+ /* notify the resolver start callback */
+ if(data->set.resolver_start) {
+ int st;
+ Curl_set_in_callback(data, true);
+ st = data->set.resolver_start(data->state.resolver, NULL,
+ data->set.resolver_start_client);
+ Curl_set_in_callback(data, false);
+ if(st)
+ return CURLRESOLV_ERROR;
+ }
+
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
non-zero value indicating that we need to wait for the response to the
resolve call */
{
struct curl_slist *hostp;
char hostname[256];
- int port;
+ int port = 0;
for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
if(!hostp->data)
}
else {
struct Curl_dns_entry *dns;
- Curl_addrinfo *addr;
+ Curl_addrinfo *head = NULL, *tail = NULL;
char *entry_id;
size_t entry_len;
- char buffer[256];
- char *address = &buffer[0];
+ char address[64];
+ char *addresses = NULL;
+ char *addr_begin;
+ char *addr_end;
+ char *port_ptr;
+ char *end_ptr;
+ char *host_end;
+ unsigned long tmp_port;
+ bool error = true;
+
+ host_end = strchr(hostp->data, ':');
+ if(!host_end ||
+ ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname)))
+ goto err;
+
+ memcpy(hostname, hostp->data, host_end - hostp->data);
+ hostname[host_end - hostp->data] = '\0';
+
+ port_ptr = host_end + 1;
+ tmp_port = strtoul(port_ptr, &end_ptr, 10);
+ if(tmp_port > USHRT_MAX || end_ptr == port_ptr || *end_ptr != ':')
+ goto err;
+
+ port = (int)tmp_port;
+ addresses = end_ptr + 1;
+
+ while(*end_ptr) {
+ size_t alen;
+ Curl_addrinfo *ai;
+
+ addr_begin = end_ptr + 1;
+ addr_end = strchr(addr_begin, ',');
+ if(!addr_end)
+ addr_end = addr_begin + strlen(addr_begin);
+ end_ptr = addr_end;
+
+ /* allow IP(v6) address within [brackets] */
+ if(*addr_begin == '[') {
+ if(addr_end == addr_begin || *(addr_end - 1) != ']')
+ goto err;
+ ++addr_begin;
+ --addr_end;
+ }
- if(3 != sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port,
- address)) {
- infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n",
- hostp->data);
- continue;
- }
+ alen = addr_end - addr_begin;
+ if(!alen)
+ continue;
+
+ if(alen >= sizeof(address))
+ goto err;
- /* allow IP(v6) address within [brackets] */
- if(address[0] == '[') {
- size_t alen = strlen(address);
- if(address[alen-1] != ']')
- /* it needs to also end with ] to be valid */
+ memcpy(address, addr_begin, alen);
+ address[alen] = '\0';
+
+#ifndef ENABLE_IPV6
+ if(strchr(address, ':')) {
+ infof(data, "Ignoring resolve address '%s', missing IPv6 support.\n",
+ address);
continue;
- address[alen-1] = 0; /* zero terminate there */
- address++; /* pass the open bracket */
+ }
+#endif
+
+ ai = Curl_str2addr(address, port);
+ if(!ai) {
+ infof(data, "Resolve address '%s' found illegal!\n", address);
+ goto err;
+ }
+
+ if(tail) {
+ tail->ai_next = ai;
+ tail = tail->ai_next;
+ }
+ else {
+ head = tail = ai;
+ }
}
- addr = Curl_str2addr(address, port);
- if(!addr) {
- infof(data, "Address in '%s' found illegal!\n", hostp->data);
+ if(!head)
+ goto err;
+
+ error = false;
+ err:
+ if(error) {
+ infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n",
+ hostp->data);
+ Curl_freeaddrinfo(head);
continue;
}
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
if(!entry_id) {
- Curl_freeaddrinfo(addr);
+ Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
-
entry_len = strlen(entry_id);
if(data->share)
if(!dns) {
/* if not in the cache already, put this host in the cache */
- dns = Curl_cache_addr(data, addr, hostname, port);
+ dns = Curl_cache_addr(data, head, hostname, port);
if(dns) {
dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
/* release the returned reference; the cache itself will keep the
else {
/* this is a duplicate, free it again */
infof(data, "RESOLVE %s:%d is already cached, %s not stored!\n",
- hostname, port, address);
- Curl_freeaddrinfo(addr);
+ hostname, port, addresses);
+ Curl_freeaddrinfo(head);
}
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
if(!dns) {
- Curl_freeaddrinfo(addr);
+ Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
infof(data, "Added %s:%d:%s to DNS cache\n",
- hostname, port, address);
+ hostname, port, addresses);
}
}
data->change.resolve = NULL; /* dealt with now */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
Curl_fetch_addr(struct connectdata *conn,
const char *hostname,
int port);
+
+/*
+ * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
+ * struct by re-linking its linked list.
+ *
+ * The addr argument should be the address of a pointer to the head node of a
+ * `Curl_addrinfo` list and it will be modified to point to the new head after
+ * shuffling.
+ */
+CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr);
+
/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
*
int numsocks);
static int http_should_fail(struct connectdata *conn);
+static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
+
#ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done);
static int https_getsock(struct connectdata *conn,
* if proxy headers are not available, then it will lookup into http header
* link list
*
- * It takes a connectdata struct as input instead of the Curl_easy simply
- * to know if this is a proxy request or not, as it then might check a
- * different header list.
+ * It takes a connectdata struct as input instead of the Curl_easy simply to
+ * know if this is a proxy request or not, as it then might check a different
+ * header list. Provide the header prefix without colon!.
*/
char *Curl_checkProxyheaders(const struct connectdata *conn,
const char *thisheader)
for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers;
head; head = head->next) {
- if(strncasecompare(head->data, thisheader, thislen))
+ if(strncasecompare(head->data, thisheader, thislen) &&
+ Curl_headersep(head->data[thislen]))
return head->data;
}
char *value;
size_t len;
- DEBUGASSERT(header);
-
/* Find the end of the header name */
while(*header && (*header != ':'))
++header;
data left to send, keep on sending. */
/* rewind data when completely done sending! */
- if(!conn->bits.authneg) {
+ if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
conn->bits.rewindaftersend = TRUE;
infof(data, "Rewind stream after send\n");
}
if(authstatus->picked == CURLAUTH_BASIC) {
/* Basic */
if((proxy && conn->bits.proxy_user_passwd &&
- !Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
+ !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
(!proxy && conn->bits.user_passwd &&
- !Curl_checkheaders(conn, "Authorization:"))) {
+ !Curl_checkheaders(conn, "Authorization"))) {
auth = "Basic";
result = http_output_basic(conn, proxy);
if(result)
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
+ if(conn->data->set.haproxyprotocol) {
+ /* add HAProxy PROXY protocol header */
+ result = add_haproxy_protocol_header(conn);
+ if(result)
+ return result;
+ }
+
if(conn->given->protocol & CURLPROTO_HTTPS) {
/* perform SSL initialization */
result = https_connecting(conn, done);
return GETSOCK_WRITESOCK(0);
}
+static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
+{
+ char proxy_header[128];
+ Curl_send_buffer *req_buffer;
+ CURLcode result;
+ char tcp_version[5];
+
+ /* Emit the correct prefix for IPv6 */
+ if(conn->bits.ipv6) {
+ strcpy(tcp_version, "TCP6");
+ }
+ else {
+ strcpy(tcp_version, "TCP4");
+ }
+
+ snprintf(proxy_header,
+ sizeof proxy_header,
+ "PROXY %s %s %s %li %li\r\n",
+ tcp_version,
+ conn->data->info.conn_local_ip,
+ conn->data->info.conn_primary_ip,
+ conn->data->info.conn_local_port,
+ conn->data->info.conn_primary_port);
+
+ req_buffer = Curl_add_buffer_init();
+ if(!req_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_add_bufferf(req_buffer, proxy_header);
+ if(result)
+ return result;
+
+ result = Curl_add_buffer_send(req_buffer,
+ conn,
+ &conn->data->info.request_size,
+ 0,
+ FIRSTSOCKET);
+
+ return result;
+}
+
#ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done)
{
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
headers = h[i];
while(headers) {
+ char *semicolonp = NULL;
ptr = strchr(headers->data, ':');
+ if(!ptr) {
+ char *optr;
+ /* no colon, semicolon? */
+ ptr = strchr(headers->data, ';');
+ if(ptr) {
+ optr = ptr;
+ ptr++; /* pass the semicolon */
+ while(*ptr && ISSPACE(*ptr))
+ ptr++;
+
+ if(*ptr) {
+ /* this may be used for something else in the future */
+ optr = NULL;
+ }
+ else {
+ if(*(--ptr) == ';') {
+ /* send no-value custom header if terminated by semicolon */
+ *ptr = ':';
+ semicolonp = ptr;
+ }
+ }
+ ptr = optr;
+ }
+ }
if(ptr) {
/* we require a colon for this to be a true header */
while(*ptr && ISSPACE(*ptr))
ptr++;
- if(*ptr) {
- /* only send this if the contents was non-blank */
+ if(*ptr || semicolonp) {
+ /* only send this if the contents was non-blank or done special */
+ CURLcode result = CURLE_OK;
if(conn->allocptr.host &&
/* a Host: header was sent already, don't pass on any custom Host:
!strcasecompare(data->state.first_host, conn->host.name)))
;
else {
- CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
- headers->data);
- if(result)
- return result;
- }
- }
- }
- else {
- ptr = strchr(headers->data, ';');
- if(ptr) {
-
- ptr++; /* pass the semicolon */
- while(*ptr && ISSPACE(*ptr))
- ptr++;
-
- if(*ptr) {
- /* this may be used for something else in the future */
- }
- else {
- if(*(--ptr) == ';') {
- CURLcode result;
-
- /* send no-value custom header if terminated by semicolon */
- *ptr = ':';
- result = Curl_add_bufferf(req_buffer, "%s\r\n",
- headers->data);
-
- /* restore the previous value */
- *ptr = ';';
-
- if(result)
- return result;
- }
+ result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data);
}
+ if(semicolonp)
+ *semicolonp = ';'; /* put back the semicolon */
+ if(result)
+ return result;
}
}
headers = headers->next;
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent:")) {
+ if(Curl_checkheaders(conn, "User-Agent")) {
free(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
conn->bits.authneg = FALSE;
Curl_safefree(conn->allocptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) {
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer")) {
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
if(!conn->allocptr.ref)
return CURLE_OUT_OF_MEMORY;
conn->allocptr.ref = NULL;
#if !defined(CURL_DISABLE_COOKIES)
- if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:"))
+ if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie"))
addcookies = data->set.str[STRING_COOKIE];
#endif
- if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
#ifdef HAVE_LIBZ
/* we only consider transfer-encoding magic if libz support is built-in */
- if(!Curl_checkheaders(conn, "TE:") &&
+ if(!Curl_checkheaders(conn, "TE") &&
data->set.http_transfer_encoding) {
/* When we are to insert a TE: header in the request, we must also insert
TE in a Connection: header, so we need to merge the custom provided
Connection: header and prevent the original to get sent. Note that if
the user has inserted his/hers own TE: header we don't do this magic
but then assume that the user will handle it all! */
- char *cptr = Curl_checkheaders(conn, "Connection:");
+ char *cptr = Curl_checkheaders(conn, "Connection");
#define TE_HEADER "TE: gzip\r\n"
Curl_safefree(conn->allocptr.te);
+ if(cptr) {
+ cptr = Curl_copy_header_value(cptr);
+ if(!cptr)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
/* Create the (updated) Connection: header */
- conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
- strdup("Connection: TE\r\n" TE_HEADER);
+ conn->allocptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
+ cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
+ free(cptr);
if(!conn->allocptr.te)
return CURLE_OUT_OF_MEMORY;
}
}
if(http->sendit) {
- const char *cthdr = Curl_checkheaders(conn, "Content-Type:");
+ const char *cthdr = Curl_checkheaders(conn, "Content-Type");
/* Read and seek body only. */
http->sendit->flags |= MIME_BODY_ONLY;
http->postsize = Curl_mime_size(http->sendit);
}
- ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
+ ptr = Curl_checkheaders(conn, "Transfer-Encoding");
if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */
data->req.upload_chunky =
Curl_safefree(conn->allocptr.host);
- ptr = Curl_checkheaders(conn, "Host:");
+ ptr = Curl_checkheaders(conn, "Host");
if(ptr && (!data->state.this_is_a_follow ||
strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES)
#endif
if(strcmp("Host:", ptr)) {
- conn->allocptr.host = aprintf("%s\r\n", ptr);
+ conn->allocptr.host = aprintf("Host:%s\r\n", &ptr[5]);
if(!conn->allocptr.host)
return CURLE_OUT_OF_MEMORY;
}
host,
conn->bits.ipv6_ip?"]":"");
else
- conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
+ conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n",
conn->bits.ipv6_ip?"[":"",
host,
conn->bits.ipv6_ip?"]":"",
}
#endif /* CURL_DISABLE_PROXY */
- http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
+ http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n";
if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
data->state.resume_from) {
/* Now, let's read off the proper amount of bytes from the
input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
* ones if any such are specified.
*/
if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
- !Curl_checkheaders(conn, "Range:")) {
+ !Curl_checkheaders(conn, "Range")) {
/* if a line like this was already allocated, free the previous one */
free(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
data->state.range);
}
else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
- !Curl_checkheaders(conn, "Content-Range:")) {
+ !Curl_checkheaders(conn, "Content-Range")) {
/* if a line like this was already allocated, free the previous one */
free(conn->allocptr.rangeline);
conn->allocptr.ref:"" /* Referer: <data> */,
(conn->bits.httpproxy &&
!conn->bits.tunnel_proxy &&
- !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
+ !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
"Proxy-Connection: Keep-Alive\r\n":"",
te
);
postsize = data->state.infilesize;
if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
+ (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */
result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if(postsize != -1 && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
+ (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer,
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
+ (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer,
return result;
}
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/"
"x-www-form-urlencoded\r\n");
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
struct SingleRequest *k,
size_t length)
{
- if(k->hbuflen + length >= data->state.headersize) {
+ size_t newsize = k->hbuflen + length;
+ if(newsize > CURL_MAX_HTTP_HEADER) {
+ /* The reason to have a max limit for this is to avoid the risk of a bad
+ server feeding libcurl with a never-ending header that will cause
+ reallocs infinitely */
+ failf(data, "Rejected %zd bytes header (max is %d)!", newsize,
+ CURL_MAX_HTTP_HEADER);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(newsize >= data->state.headersize) {
/* We enlarge the header buffer as it is too small */
char *newbuff;
size_t hbufp_index;
- size_t newsize;
-
- if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
- /* The reason to have a max limit for this is to avoid the risk of a bad
- server feeding libcurl with a never-ending header that will cause
- reallocs infinitely */
- failf(data, "Avoided giant realloc for header (max is %d)!",
- CURL_MAX_HTTP_HEADER);
- return CURLE_OUT_OF_MEMORY;
- }
newsize = CURLMAX((k->hbuflen + length) * 3 / 2, data->state.headersize*2);
hbufp_index = k->hbufp - data->state.headerbuff;
{
CURLcode result;
struct SingleRequest *k = &data->req;
+ ssize_t onread = *nread;
+ char *ostr = k->str;
/* header line within buffer loop */
do {
else {
/* this was all we read so it's all a bad header */
k->badheader = HEADER_ALLBAD;
- *nread = (ssize_t)rest_length;
+ *nread = onread;
+ k->str = ostr;
+ return CURLE_OK;
}
break;
}
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_add(data,
- data->cookies, TRUE, k->p + 11,
+ data->cookies, TRUE, FALSE, k->p + 11,
/* If there is a custom-set Host: name, use it
here, or else use real peer host name. */
conn->allocptr.cookiehost?
k->timeofdoc = curl_getdate(k->p + strlen("Last-Modified:"),
&secs);
if(data->set.get_filetime)
- data->info.filetime = (long)k->timeofdoc;
+ data->info.filetime = k->timeofdoc;
}
else if((checkprefix("WWW-Authenticate:", k->p) &&
(401 == k->httpcode)) ||
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
This value used to be fairly big (100K), but we must take into account that
if the server rejects the POST due for authentication reasons, this data
- will always be uncondtionally sent and thus it may not be larger than can
+ will always be unconditionally sent and thus it may not be larger than can
always be afforded to send twice.
It must not be greater than 64K to work on VMS.
size_t pauselen; /* the number of bytes left in data */
bool closed; /* TRUE on HTTP2 stream close */
bool close_handled; /* TRUE if stream closure is handled by libcurl */
- uint32_t error_code; /* HTTP/2 error code */
-
char *mem; /* points to a buffer in memory to store received data */
size_t len; /* size of the buffer 'mem' points to */
size_t memlen; /* size of data copied to mem */
#endif
};
-typedef int (*sending)(void); /* Curl_send */
-typedef int (*recving)(void); /* Curl_recv */
-
#ifdef USE_NGHTTP2
/* h2 settings for this connection */
struct h2settings {
};
#endif
-
struct http_conn {
#ifdef USE_NGHTTP2
#define H2_BINSETTINGS_LEN 80
nghttp2_session *h2;
uint8_t binsettings[H2_BINSETTINGS_LEN];
size_t binlen; /* length of the binsettings data */
- sending send_underlying; /* underlying send Curl_send callback */
- recving recv_underlying; /* underlying recv Curl_recv callback */
+ Curl_send *send_underlying; /* underlying send Curl_send callback */
+ Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */
char *inbuf; /* buffer to receive data from underlying socket */
size_t inbuflen; /* number of bytes filled in inbuf */
size_t nread_inbuf; /* number of bytes read from in inbuf */
/* list of settings that will be sent */
nghttp2_settings_entry local_settings[3];
size_t local_settings_num;
+ uint32_t error_code; /* HTTP/2 error code */
#else
int unused; /* prevent a compiler warning */
#endif
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "curl_memory.h"
#include "memdebug.h"
+#define H2_BUFSIZE 32768
#define MIN(x,y) ((x)<(y)?(x):(y))
#if (NGHTTP2_VERSION_NUM < 0x010000)
#define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
+#ifdef DEBUG_HTTP2
+#define H2BUGF(x) x
+#else
+#define H2BUGF(x) do { } WHILE_FALSE
+#endif
+
+
+static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err);
+static bool http2_connisdead(struct connectdata *conn);
+static int h2_session_send(struct Curl_easy *data,
+ nghttp2_session *h2);
+static int h2_process_pending_input(struct connectdata *conn,
+ struct http_conn *httpc,
+ CURLcode *err);
+
/*
* Curl_http2_init_state() is called when the easy handle is created and
* allows for HTTP/2 specific init of state.
int numsocks)
{
const struct http_conn *c = &conn->proto.httpc;
+ struct SingleRequest *k = &conn->data->req;
int bitmap = GETSOCK_BLANK;
(void)numsocks;
always be ready for one */
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
- if(nghttp2_session_want_write(c->h2))
+ /* we're still uploading or the HTTP/2 layer wants to send data */
+ if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
+ nghttp2_session_want_write(c->h2))
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
return bitmap;
struct http_conn *c = &conn->proto.httpc;
(void)dead_connection;
- DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
+ H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
http2_stream_free(conn->data->req.protop);
+ conn->data->state.drain = 0;
- DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
+ H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
return CURLE_OK;
}
* Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
-static bool http2_connisdead(struct connectdata *check)
+static bool http2_connisdead(struct connectdata *conn)
{
int sval;
- bool ret_val = TRUE;
+ bool dead = TRUE;
- sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0);
+ if(conn->bits.close)
+ return TRUE;
+
+ sval = SOCKET_READABLE(conn->sock[FIRSTSOCKET], 0);
if(sval == 0) {
/* timeout */
- ret_val = FALSE;
+ dead = FALSE;
}
else if(sval & CURL_CSELECT_ERR) {
/* socket is in an error state */
- ret_val = TRUE;
+ dead = TRUE;
}
else if(sval & CURL_CSELECT_IN) {
/* readable with no error. could still be closed */
- ret_val = !Curl_connalive(check);
+ dead = !Curl_connalive(conn);
+ if(!dead) {
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other thransfer, there shouldn't be any data here,
+ only "protocol frames" */
+ CURLcode result;
+ struct http_conn *httpc = &conn->proto.httpc;
+ ssize_t nread = -1;
+ if(httpc->recv_underlying)
+ /* if called "too early", this pointer isn't setup yet! */
+ nread = ((Curl_recv *)httpc->recv_underlying)(
+ conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
+ if(nread != -1) {
+ infof(conn->data,
+ "%d bytes stray data read before trying h2 connection\n",
+ (int)nread);
+ httpc->nread_inbuf = 0;
+ httpc->inbuflen = nread;
+ (void)h2_process_pending_input(conn, httpc, &result);
+ }
+ else
+ /* the read failed so let's say this is dead anyway */
+ dead = TRUE;
+ }
}
- return ret_val;
+ return dead;
}
-
static unsigned int http2_conncheck(struct connectdata *check,
unsigned int checks_to_perform)
{
http->status_code = -1;
http->pausedata = NULL;
http->pauselen = 0;
- http->error_code = NGHTTP2_NO_ERROR;
http->closed = FALSE;
http->close_handled = FALSE;
http->mem = data->state.buffer;
{
conn->proto.httpc.settings.max_concurrent_streams =
DEFAULT_MAX_CONCURRENT_STREAMS;
+ conn->proto.httpc.error_code = NGHTTP2_NO_ERROR;
}
/*
const nghttp2_push_promise *frame)
{
int rv;
- DEBUGF(infof(data, "PUSH_PROMISE received, stream %u!\n",
+ H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n",
frame->promised_stream_id));
if(data->multi->push_cb) {
struct HTTP *stream;
heads.data = data;
heads.frame = frame;
/* ask the application */
- DEBUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
+ H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
stream = data->req.protop;
if(!stream) {
goto fail;
}
+ Curl_set_in_callback(data, true);
rv = data->multi->push_cb(data, newhandle,
stream->push_headers_used, &heads,
data->multi->push_userp);
+ Curl_set_in_callback(data, false);
/* free the headers again */
for(i = 0; i<stream->push_headers_used; i++)
frame->promised_stream_id, newhandle);
}
else {
- DEBUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
+ H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
rv = 1;
}
fail:
struct http_conn *httpc = &conn->proto.httpc;
struct Curl_easy *data_s = NULL;
struct HTTP *stream = NULL;
- static int lastStream = -1;
int rv;
size_t left, ncopy;
int32_t stream_id = frame->hd.stream_id;
/* stream ID zero is for connection-oriented stuff */
if(frame->hd.type == NGHTTP2_SETTINGS) {
uint32_t max_conn = httpc->settings.max_concurrent_streams;
- DEBUGF(infof(conn->data, "Got SETTINGS\n"));
+ H2BUGF(infof(conn->data, "Got SETTINGS\n"));
httpc->settings.max_concurrent_streams =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
httpc->settings.enable_push =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_ENABLE_PUSH);
- DEBUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
+ H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
httpc->settings.max_concurrent_streams));
- DEBUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
+ H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
httpc->settings.enable_push?"TRUE":"false"));
if(max_conn != httpc->settings.max_concurrent_streams) {
/* only signal change if the value actually changed */
infof(conn->data,
- "Connection state changed (MAX_CONCURRENT_STREAMS updated)!\n");
+ "Connection state changed (MAX_CONCURRENT_STREAMS == %d)!\n",
+ httpc->settings.max_concurrent_streams);
Curl_multi_connchanged(conn->data->multi);
}
}
return 0;
}
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
- if(lastStream != stream_id) {
- lastStream = stream_id;
- }
if(!data_s) {
- DEBUGF(infof(conn->data,
+ H2BUGF(infof(conn->data,
"No Curl_easy associated with stream: %x\n",
stream_id));
return 0;
stream = data_s->req.protop;
if(!stream) {
- DEBUGF(infof(conn->data, "No proto pointer for stream: %x\n",
+ H2BUGF(infof(data_s, "No proto pointer for stream: %x\n",
stream_id));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- DEBUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
+ H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
frame->hd.type, stream_id));
switch(frame->hd.type) {
}
/* nghttp2 guarantees that :status is received, and we store it to
- stream->status_code */
- DEBUGASSERT(stream->status_code != -1);
+ stream->status_code. Fuzzing has proven this can still be reached
+ without status code having been set. */
+ if(stream->status_code == -1)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
/* Only final status code signals the end of header */
if(stream->status_code / 100 != 1) {
ncopy);
stream->nread_header_recvbuf += ncopy;
- DEBUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n",
+ H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n",
ncopy, stream_id, stream->mem));
stream->len -= ncopy;
}
break;
default:
- DEBUGF(infof(conn->data, "Got frame type %x for stream %u!\n",
+ H2BUGF(infof(data_s, "Got frame type %x for stream %u!\n",
frame->hd.type, stream_id));
break;
}
{
struct Curl_easy *data_s = NULL;
(void)userp;
-#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if !defined(DEBUG_HTTP2) || defined(CURL_DISABLE_VERBOSE_STRINGS)
(void)lib_error_code;
#endif
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s,
+ H2BUGF(infof(data_s,
"on_invalid_frame_recv() was called, error=%d:%s\n",
lib_error_code, nghttp2_strerror(lib_error_code)));
}
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(infof(data_s, "%zu data received for stream %u "
+ H2BUGF(infof(data_s, "%zu data received for stream %u "
"(%zu left in buffer %p, total %zu)\n",
nread, stream_id,
stream->len, stream->mem,
if(nread < len) {
stream->pausedata = data + nread;
stream->pauselen = len - nread;
- DEBUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
+ H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
", stream %u\n",
len - nread, stream_id));
data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s, "before_frame_send() was called\n"));
+ H2BUGF(infof(data_s, "before_frame_send() was called\n"));
}
return 0;
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s, "on_frame_send() was called, length = %zd\n",
+ H2BUGF(infof(data_s, "on_frame_send() was called, length = %zd\n",
frame->hd.length));
}
return 0;
{
struct Curl_easy *data_s;
(void)userp;
-#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if !defined(DEBUG_HTTP2) || defined(CURL_DISABLE_VERBOSE_STRINGS)
(void)lib_error_code;
#endif
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s,
+ H2BUGF(infof(data_s,
"on_frame_not_send() was called, lib_error_code = %d\n",
lib_error_code));
}
(void)stream_id;
if(stream_id) {
+ struct http_conn *httpc;
/* get the stream from the hash based on Stream ID, stream ID zero is for
connection-oriented stuff */
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
decided to reject stream (e.g., PUSH_PROMISE). */
return 0;
}
- DEBUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
+ H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
Curl_http2_strerror(error_code), error_code, stream_id));
stream = data_s->req.protop;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream->error_code = error_code;
stream->closed = TRUE;
data_s->state.drain++;
- conn->proto.httpc.drain_total++;
+ httpc = &conn->proto.httpc;
+ httpc->drain_total++;
+ httpc->error_code = error_code;
/* remove the entry from the hash as the stream is now gone */
nghttp2_session_set_stream_user_data(session, stream_id, 0);
- DEBUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
+ H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
}
return 0;
}
return 0;
}
- DEBUGF(infof(data_s, "on_begin_headers() was called\n"));
+ H2BUGF(infof(data_s, "on_begin_headers() was called\n"));
if(frame->hd.type != NGHTTP2_HEADERS) {
return 0;
return 0;
}
- /* This is trailer HEADERS started. Allocate buffer for them. */
- DEBUGF(infof(data_s, "trailer field started\n"));
-
- DEBUGASSERT(stream->trailer_recvbuf == NULL);
-
- stream->trailer_recvbuf = Curl_add_buffer_init();
if(!stream->trailer_recvbuf) {
- return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ stream->trailer_recvbuf = Curl_add_buffer_init();
+ if(!stream->trailer_recvbuf) {
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
}
-
return 0;
}
/* 4 is for ": " and "\r\n". */
uint32_t n = (uint32_t)(namelen + valuelen + 4);
- DEBUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
+ H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
value));
Curl_add_buffer(stream->trailer_recvbuf, &n, sizeof(n));
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
+ H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
stream->status_code, data_s));
return 0;
}
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
+ H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
value));
return 0; /* 0 is successful */
else if(nread == 0)
return NGHTTP2_ERR_DEFERRED;
- DEBUGF(infof(data_s, "data_source_read_callback: "
+ H2BUGF(infof(data_s, "data_source_read_callback: "
"returns %zu bytes stream %u\n",
nread, stream_id));
return nread;
}
-#define H2_BUFSIZE 32768
-
#ifdef NGHTTP2_HAS_ERROR_CALLBACK
static int error_callback(nghttp2_session *session,
const char *msg,
struct http_conn *httpc = &conn->proto.httpc;
if(http->header_recvbuf) {
- DEBUGF(infof(data, "free header_recvbuf!!\n"));
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
Curl_add_buffer_free(http->trailer_recvbuf);
!nghttp2_session_want_write(httpc->h2);
}
-static int h2_session_send(struct Curl_easy *data,
- nghttp2_session *h2);
-
/*
* h2_process_pending_input() processes pending input left in
* httpc->inbuf. Then, call h2_session_send() to send pending data.
* This function returns 0 if it succeeds, or -1 and error code will
* be assigned to *err.
*/
-static int h2_process_pending_input(struct Curl_easy *data,
+static int h2_process_pending_input(struct connectdata *conn,
struct http_conn *httpc,
CURLcode *err)
{
ssize_t nread;
char *inbuf;
ssize_t rv;
+ struct Curl_easy *data = conn->data;
nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf;
}
if(nread == rv) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"h2_process_pending_input: All data in connection buffer "
"processed\n"));
httpc->inbuflen = 0;
}
else {
httpc->nread_inbuf += rv;
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"h2_process_pending_input: %zu bytes left in connection "
"buffer\n",
httpc->inbuflen - httpc->nread_inbuf));
}
if(should_close_session(httpc)) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"h2_process_pending_input: nothing to do in this session\n"));
- *err = CURLE_HTTP2;
+ if(httpc->error_code)
+ *err = CURLE_HTTP2;
+ else {
+ /* not an error per se, but should still close the connection */
+ connclose(conn, "GOAWAY received");
+ *err = CURLE_OK;
+ }
return -1;
}
that it can signal EOF to nghttp2 */
(void)nghttp2_session_resume_data(h2, stream->stream_id);
- (void)h2_process_pending_input(conn->data, httpc, &result);
+ (void)h2_process_pending_input(conn, httpc, &result);
}
}
return result;
data->state.drain = 0;
if(httpc->pause_stream_id == 0) {
- if(h2_process_pending_input(data, httpc, err) != 0) {
+ if(h2_process_pending_input(conn, httpc, err) != 0) {
return -1;
}
}
/* Reset to FALSE to prevent infinite loop in readwrite_data function. */
stream->closed = FALSE;
- if(stream->error_code != NGHTTP2_NO_ERROR) {
+ if(httpc->error_code == NGHTTP2_REFUSED_STREAM) {
+ H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n",
+ stream->stream_id));
+ connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
+ data->state.refused_stream = TRUE;
+ *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
+ return -1;
+ }
+ else if(httpc->error_code != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
- stream->stream_id, Curl_http2_strerror(stream->error_code),
- stream->error_code);
+ stream->stream_id, Curl_http2_strerror(httpc->error_code),
+ httpc->error_code);
*err = CURLE_HTTP2_STREAM;
return -1;
}
if(!stream->bodystarted) {
failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
- " all response header fields, teated as error",
+ " all response header fields, treated as error",
stream->stream_id);
*err = CURLE_HTTP2_STREAM;
return -1;
stream->close_handled = TRUE;
- DEBUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
+ H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
return 0;
}
h2_pri_spec(data, &pri_spec);
- DEBUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n",
+ H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n",
stream->stream_id, data));
rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id,
&pri_spec);
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
if(should_close_session(httpc)) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"http2_recv: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
ncopy);
stream->nread_header_recvbuf += ncopy;
- DEBUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
+ H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
(int)ncopy));
return ncopy;
}
- DEBUGF(infof(data, "http2_recv: easy %p (stream %u)\n",
+ H2BUGF(infof(data, "http2_recv: easy %p (stream %u)\n",
data, stream->stream_id));
if((data->state.drain) && stream->memlen) {
- DEBUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
+ H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
stream->memlen, stream->stream_id,
stream->mem, mem));
if(mem != stream->mem) {
/* We have paused nghttp2, but we have no pause data (see
on_data_chunk_recv). */
httpc->pause_stream_id = 0;
- if(h2_process_pending_input(data, httpc, &result) != 0) {
+ if(h2_process_pending_input(conn, httpc, &result) != 0) {
*err = result;
return -1;
}
infof(data, "%zu data bytes written\n", nread);
if(stream->pauselen == 0) {
- DEBUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
+ H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
httpc->pause_stream_id = 0;
frames, then we have to call it again with 0-length data.
Without this, on_stream_close callback will not be called,
and stream could be hanged. */
- if(h2_process_pending_input(data, httpc, &result) != 0) {
+ if(h2_process_pending_input(conn, httpc, &result) != 0) {
*err = result;
return -1;
}
}
- DEBUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
+ H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
nread, stream->stream_id));
return nread;
}
socket is not read. But it seems that usually streams are
notified with its drain property, and socket is read again
quickly. */
- DEBUGF(infof(data, "stream %x is paused, pause id: %x\n",
+ H2BUGF(infof(data, "stream %x is paused, pause id: %x\n",
stream->stream_id, httpc->pause_stream_id));
*err = CURLE_AGAIN;
return -1;
}
if(nread == 0) {
- failf(data, "Unexpected EOF");
- *err = CURLE_RECV_ERROR;
- return -1;
+ H2BUGF(infof(data, "end of stream\n"));
+ *err = CURLE_OK;
+ return 0;
}
- DEBUGF(infof(data, "nread=%zd\n", nread));
+ H2BUGF(infof(data, "nread=%zd\n", nread));
httpc->inbuflen = nread;
inbuf = httpc->inbuf;
nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf;
- DEBUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
+ H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
nread));
}
rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
*err = CURLE_RECV_ERROR;
return -1;
}
- DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
+ H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
if(nread == rv) {
- DEBUGF(infof(data, "All data in connection buffer processed\n"));
+ H2BUGF(infof(data, "All data in connection buffer processed\n"));
httpc->inbuflen = 0;
httpc->nread_inbuf = 0;
}
else {
httpc->nread_inbuf += rv;
- DEBUGF(infof(data, "%zu bytes left in connection buffer\n",
+ H2BUGF(infof(data, "%zu bytes left in connection buffer\n",
httpc->inbuflen - httpc->nread_inbuf));
}
/* Always send pending frames in nghttp2 session, because
}
if(should_close_session(httpc)) {
- DEBUGF(infof(data, "http2_recv: nothing to do in this session\n"));
+ H2BUGF(infof(data, "http2_recv: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
}
if(stream->memlen) {
ssize_t retlen = stream->memlen;
- DEBUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
+ H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
retlen, stream->stream_id));
stream->memlen = 0;
if(httpc->pause_stream_id == stream->stream_id) {
/* data for this stream is returned now, but this stream caused a pause
already so we need it called again asap */
- DEBUGF(infof(data, "Data returned for PAUSED stream %u\n",
+ H2BUGF(infof(data, "Data returned for PAUSED stream %u\n",
stream->stream_id));
}
else if(!stream->closed) {
return http2_handle_stream_close(conn, data, stream, err);
}
*err = CURLE_AGAIN;
- DEBUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
+ H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
stream->stream_id));
return -1;
}
(void)sockindex;
- DEBUGF(infof(conn->data, "http2_send len=%zu\n", len));
+ H2BUGF(infof(conn->data, "http2_send len=%zu\n", len));
if(stream->stream_id != -1) {
if(stream->close_handled) {
stream->upload_len = 0;
if(should_close_session(httpc)) {
- DEBUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
nghttp2_session_resume_data(h2, stream->stream_id);
}
- DEBUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
+ H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
stream->stream_id));
return len;
}
return -1;
}
- /* Extract :method, :path from request line */
- line_end = strstr(hdbuf, "\r\n");
+ /* Extract :method, :path from request line
+ We do line endings with CRLF so checking for CR is enough */
+ line_end = memchr(hdbuf, '\r', len);
+ if(!line_end)
+ goto fail;
/* Method does not contain spaces */
end = memchr(hdbuf, ' ', line_end - hdbuf);
hdbuf = line_end + 2;
- line_end = strstr(hdbuf, "\r\n");
- if(line_end == hdbuf)
+ /* check for next CR, but only within the piece of data left in the given
+ buffer */
+ line_end = memchr(hdbuf, '\r', len - (hdbuf - (char *)mem));
+ if(!line_end || (line_end == hdbuf))
goto fail;
/* header continuation lines are not supported */
for(i = 0; i < nheader; ++i) {
acc += nva[i].namelen + nva[i].valuelen;
- DEBUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
+ H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
nva[i].namelen, nva[i].name,
nva[i].valuelen, nva[i].value));
}
Curl_safefree(nva);
if(stream_id < 0) {
- DEBUGF(infof(conn->data, "http2_send() send error\n"));
+ H2BUGF(infof(conn->data, "http2_send() send error\n"));
*err = CURLE_SEND_ERROR;
return -1;
}
}
if(should_close_session(httpc)) {
- DEBUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
if(result)
return result;
- httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
- httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
+ httpc->recv_underlying = conn->recv[FIRSTSOCKET];
+ httpc->send_underlying = conn->send[FIRSTSOCKET];
conn->recv[FIRSTSOCKET] = http2_recv;
conn->send[FIRSTSOCKET] = http2_send;
return CURLE_HTTP2;
}
- DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
+ H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
if((ssize_t)nread == nproc) {
httpc->inbuflen = 0;
}
if(should_close_session(httpc)) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"nghttp2_session_send(): nothing to do in this session\n"));
return CURLE_HTTP2;
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
*/
+#ifdef CURL_DOES_CONVERSIONS
/* Check for an ASCII hex digit.
- We avoid the use of isxdigit to accommodate non-ASCII hosts. */
-static bool Curl_isxdigit(char digit)
+ We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */
+static bool Curl_isxdigit_ascii(char digit)
{
- return ( (digit >= 0x30 && digit <= 0x39) /* 0-9 */
+ return (digit >= 0x30 && digit <= 0x39) /* 0-9 */
|| (digit >= 0x41 && digit <= 0x46) /* A-F */
- || (digit >= 0x61 && digit <= 0x66) /* a-f */) ? TRUE : FALSE;
+ || (digit >= 0x61 && digit <= 0x66); /* a-f */
}
+#else
+#define Curl_isxdigit_ascii(x) Curl_isxdigit(x)
+#endif
void Curl_httpchunk_init(struct connectdata *conn)
{
while(length) {
switch(ch->state) {
case CHUNK_HEX:
- if(Curl_isxdigit(*datap)) {
+ if(Curl_isxdigit_ascii(*datap)) {
if(ch->hexindex < MAXNUM_SIZE) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
/* Write the data portion available */
- if(conn->data->set.http_ce_skip || !k->writer_stack) {
- if(!k->ignorebody)
+ if(!conn->data->set.http_te_skip && !k->ignorebody) {
+ if(!conn->data->set.http_ce_skip && k->writer_stack)
+ result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
+ else
result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece);
- }
- else
- result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
- if(result)
- return CHUNKE_WRITE_ERROR;
+ if(result)
+ return CHUNKE_WRITE_ERROR;
+ }
*wrote += piece;
ch->datasize -= piece; /* decrease amount left to expect */
}
}
- /* Initilise the security context and decode our challenge */
+ /* Initialize the security context and decode our challenge */
result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
host, header, neg_ctx);
server, which is for a plain host or for a HTTP proxy */
char **allocuserpwd;
- /* point to the name and password for this */
+ /* point to the username, password, service and host */
const char *userp;
const char *passwdp;
+ const char *service = NULL;
+ const char *hostname = NULL;
/* point to the correct struct with this */
struct ntlmdata *ntlm;
allocuserpwd = &conn->allocptr.proxyuserpwd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
+ service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
+ conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
+ hostname = conn->http_proxy.host.name;
ntlm = &conn->proxyntlm;
authp = &conn->data->state.authproxy;
}
allocuserpwd = &conn->allocptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
+ service = conn->data->set.str[STRING_SERVICE_NAME] ?
+ conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
+ hostname = conn->host.name;
ntlm = &conn->ntlm;
authp = &conn->data->state.authhost;
}
default: /* for the weird cases we (re)start here */
/* Create a type-1 message */
result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
- ntlm, &base64, &len);
+ service, hostname,
+ ntlm, &base64,
+ &len);
if(result)
return result;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
if(!req_buffer)
return CURLE_OUT_OF_MEMORY;
- host_port = aprintf("%s:%hu", hostname, remote_port);
+ host_port = aprintf("%s:%d", hostname, remote_port);
if(!host_port) {
Curl_add_buffer_free(req_buffer);
return CURLE_OUT_OF_MEMORY;
if(hostname != conn->host.name)
ipv6_ip = (strchr(hostname, ':') != NULL);
hostheader = /* host:port with IPv6 support */
- aprintf("%s%s%s:%hu", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
+ aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
remote_port);
if(!hostheader) {
Curl_add_buffer_free(req_buffer);
return CURLE_OUT_OF_MEMORY;
}
- if(!Curl_checkProxyheaders(conn, "Host:")) {
+ if(!Curl_checkProxyheaders(conn, "Host")) {
host = aprintf("Host: %s\r\n", hostheader);
if(!host) {
free(hostheader);
return CURLE_OUT_OF_MEMORY;
}
}
- if(!Curl_checkProxyheaders(conn, "Proxy-Connection:"))
+ if(!Curl_checkProxyheaders(conn, "Proxy-Connection"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
- if(!Curl_checkProxyheaders(conn, "User-Agent:") &&
+ if(!Curl_checkProxyheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent;
enc.value = buf;
enc.length = len;
- maj = gss_unseal(&min, *context, &enc, &dec, NULL, NULL);
+ maj = gss_unwrap(&min, *context, &enc, &dec, NULL, NULL);
if(maj != GSS_S_COMPLETE) {
if(len >= 4)
strcpy(buf, "599 ");
int len;
/* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal
- * libraries modify the input buffer in gss_seal()
+ * libraries modify the input buffer in gss_wrap()
*/
dec.value = (void *)from;
dec.length = length;
- maj = gss_seal(&min, *context,
+ maj = gss_wrap(&min, *context,
level == PROT_PRIVATE,
GSS_C_QOP_DEFAULT,
&dec, &state, &enc);
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#endif /* CRYPTO LIBS */
+/* Disable this picky gcc-8 compiler warning */
+#if defined(__GNUC__) && (__GNUC__ >= 8)
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
+
const HMAC_params Curl_HMAC_MD5[] = {
{
(HMAC_hinit_func) MD5_Init, /* Hash initialization function. */
#endif
-#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream"
-#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed"
-#define DISPOSITION_DEFAULT "attachment"
-
#define READ_ERROR ((size_t) -1)
/* Encoders. */
static char *Curl_basename(char *path)
{
/* Ignore all the details above for now and make a quick and simple
- implementaion here */
+ implementation here */
char *s1;
char *s2;
}
/* Duplicate other fields. */
- dst->encoder = src->encoder;
+ if(dst != NULL)
+ dst->encoder = src->encoder;
+ else
+ res = CURLE_WRITE_ERROR;
if(!res)
res = curl_mime_type(dst, src->mimetype);
if(!res)
res = curl_mime_filename(dst, src->filename);
/* If an error occurred, rollback. */
- if(res)
+ if(res && dst)
Curl_mime_cleanpart(dst);
return res;
boundary? boundary: "");
}
-
-static const char *ContentTypeForFilename(const char *filename)
+const char *Curl_mime_contenttype(const char *filename)
{
unsigned int i;
contenttype = MULTIPART_CONTENTTYPE_DEFAULT;
break;
case MIMEKIND_FILE:
- contenttype = ContentTypeForFilename(part->filename);
+ contenttype = Curl_mime_contenttype(part->filename);
if(!contenttype)
- contenttype = ContentTypeForFilename(part->data);
+ contenttype = Curl_mime_contenttype(part->data);
if(!contenttype && part->filename)
contenttype = FILE_CONTENTTYPE_DEFAULT;
break;
default:
- contenttype = ContentTypeForFilename(part->filename);
+ contenttype = Curl_mime_contenttype(part->filename);
break;
}
}
#define MIME_USERHEADERS_OWNER (1 << 0)
#define MIME_BODY_ONLY (1 << 1)
+#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream"
+#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed"
+#define DISPOSITION_DEFAULT "attachment"
+
/* Part source kinds. */
enum mimekind {
MIMEKIND_NONE = 0, /* Part not set. */
void *instream);
CURLcode Curl_mime_rewind(curl_mimepart *part);
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
+const char *Curl_mime_contenttype(const char *filename);
#endif /* HEADER_CURL_MIME_H */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
struct Curl_easy *d);
static CURLMcode multi_timeout(struct Curl_multi *multi,
long *timeout_ms);
+static void process_pending_handles(struct Curl_multi *multi);
#ifdef DEBUGBUILD
static const char * const statename[]={
if(data->multi)
return CURLM_ADDED_ALREADY;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
/* Initialize timeout list for this handle */
Curl_llist_init(&data->state.timeoutlist, NULL);
* potential multi's connection cache growing which won't be undone in this
* function no matter what.
*/
+ if(data->set.errorbuffer)
+ data->set.errorbuffer[0] = 0;
/* set the easy handle */
multistate(data, CURLM_STATE_INIT);
result = CURLE_ABORTED_BY_CALLBACK;
}
- if(conn->send_pipe.size + conn->recv_pipe.size != 0 &&
- !data->set.reuse_forbid &&
- !conn->bits.close) {
- /* Stop if pipeline is not empty and we do not have to close
- connection. */
+ process_pending_handles(data->multi); /* connection / multiplex */
+
+ if(conn->send_pipe.size || conn->recv_pipe.size) {
+ /* Stop if pipeline is not empty . */
data->easy_conn = NULL;
- DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n"));
+ DEBUGF(infof(data, "Connection still in use %d/%d, "
+ "no more multi_done now!\n",
+ conn->send_pipe.size, conn->recv_pipe.size));
return CURLE_OK;
}
if(!data->multi)
return CURLM_OK; /* it is already removed so let's say it is fine! */
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
TRUE : FALSE;
/* this handle is "alive" so we need to count down the total number of
alive connections when this is removed */
multi->num_alive--;
-
- /* When this handle gets removed, other handles may be able to get the
- connection */
- Curl_multi_process_pending_handles(multi);
}
if(data->easy_conn &&
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
data = multi->easyp;
while(data) {
bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
/* If the internally desired timeout is actually shorter than requested from
the outside, then use the shorter time! But only if the internal timer
is actually larger than -1! */
{
CURLMcode rc;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
rc = curl_multi_add_handle(multi, data);
if(!rc) {
struct SingleRequest *k = &data->req;
if(multi_ischanged(multi, TRUE)) {
DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
- Curl_multi_process_pending_handles(multi);
+ process_pending_handles(multi); /* pipelined/multiplexed */
}
if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
case CURLM_STATE_DO_DONE:
/* Move ourselves from the send to recv pipeline */
Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
- /* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
+
+ if(data->easy_conn->bits.multiplex || data->easy_conn->send_pipe.size)
+ /* Check if we can move pending requests to send pipe */
+ process_pending_handles(multi); /* pipelined/multiplexed */
/* Only perform the transfer if there's a good socket to work with.
Having both BAD is a signal to skip immediately to DONE */
if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
(data->easy_conn->writesockfd != CURL_SOCKET_BAD))
multistate(data, CURLM_STATE_WAITPERFORM);
- else
- {
+ else {
if(data->state.wildcardmatch &&
((data->easy_conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
data->wildcard.state = CURLWC_DONE;
if(!result) {
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
- send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
- data->progress.ul_limit_size,
- data->set.max_send_speed,
- data->progress.ul_limit_start,
- now);
+ send_timeout_ms =
+ Curl_pgrsLimitWaitTime(data->progress.uploaded,
+ data->progress.ul_limit_size,
+ data->set.max_send_speed,
+ data->progress.ul_limit_start,
+ now);
recv_timeout_ms = 0;
if(data->set.max_recv_speed > 0)
- recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
- data->progress.dl_limit_size,
- data->set.max_recv_speed,
- data->progress.dl_limit_start,
- now);
-
- if(send_timeout_ms <= 0 && recv_timeout_ms <= 0)
+ recv_timeout_ms =
+ Curl_pgrsLimitWaitTime(data->progress.downloaded,
+ data->progress.dl_limit_size,
+ data->set.max_recv_speed,
+ data->progress.dl_limit_start,
+ now);
+
+ if(!send_timeout_ms && !recv_timeout_ms) {
multistate(data, CURLM_STATE_PERFORM);
+ Curl_ratelimit(data, now);
+ }
else if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
else
data->progress.dl_limit_start,
now);
- if(send_timeout_ms > 0 || recv_timeout_ms > 0) {
+ if(send_timeout_ms || recv_timeout_ms) {
+ Curl_ratelimit(data, now);
multistate(data, CURLM_STATE_TOOFAST);
if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
if(data->easy_conn->recv_pipe.head)
Curl_expire(data->easy_conn->recv_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
- /* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
-
/* When we follow redirects or is set to retry the connection, we must
to go back to the CONNECT state */
if(data->req.newurl || retry) {
/* Remove ourselves from the receive pipeline, if we are there. */
Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe);
- /* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
+
+ if(data->easy_conn->bits.multiplex || data->easy_conn->send_pipe.size)
+ /* Check if we can move pending requests to connection */
+ process_pending_handles(multi); /* pipelined/multiplexing */
/* post-transfer command */
res = multi_done(&data->easy_conn, result, FALSE);
data->state.pipe_broke = FALSE;
/* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
+ process_pending_handles(multi); /* connection */
if(data->easy_conn) {
/* if this has a connection, unsubscribe from the pipelines */
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
data = multi->easyp;
while(data) {
CURLMcode result;
struct Curl_easy *nextdata;
if(GOOD_MULTI_HANDLE(multi)) {
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
multi->type = 0; /* not good anymore */
/* Firsrt remove all remaining easy handles */
*msgs_in_queue = 0; /* default to none */
- if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(&multi->msglist)) {
+ if(GOOD_MULTI_HANDLE(multi) &&
+ !multi->in_callback &&
+ Curl_llist_count(&multi->msglist)) {
/* there is one or more messages in the list */
struct curl_llist_element *e;
data->numsocks = num;
}
+void Curl_updatesocket(struct Curl_easy *data)
+{
+ singlesocket(data->multi, data);
+}
+
+
/*
* Curl_multi_closed()
*
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
va_start(param, option);
switch(option) {
CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
int *running_handles)
{
- CURLMcode result = multi_socket(multi, FALSE, s, 0, running_handles);
+ CURLMcode result;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+ result = multi_socket(multi, FALSE, s, 0, running_handles);
if(CURLM_OK >= result)
update_timer(multi);
return result;
CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
int ev_bitmask, int *running_handles)
{
- CURLMcode result = multi_socket(multi, FALSE, s,
- ev_bitmask, running_handles);
+ CURLMcode result;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+ result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
if(CURLM_OK >= result)
update_timer(multi);
return result;
CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
{
- CURLMcode result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0,
- running_handles);
+ CURLMcode result;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+ result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
if(CURLM_OK >= result)
update_timer(multi);
return result;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
return multi_timeout(multi, timeout_ms);
}
{
struct Curl_sh_entry *there = NULL;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
there = sh_getentry(&multi->sockhash, s);
if(!there)
return &multi->pipelining_server_bl;
}
-void Curl_multi_process_pending_handles(struct Curl_multi *multi)
+static void process_pending_handles(struct Curl_multi *multi)
{
struct curl_llist_element *e = multi->pending.head;
-
- while(e) {
+ if(e) {
struct Curl_easy *data = e->ptr;
- struct curl_llist_element *next = e->next;
- if(data->mstate == CURLM_STATE_CONNECT_PEND) {
- multistate(data, CURLM_STATE_CONNECT);
+ DEBUGASSERT(data->mstate == CURLM_STATE_CONNECT_PEND);
- /* Remove this node from the list */
- Curl_llist_remove(&multi->pending, e, NULL);
+ multistate(data, CURLM_STATE_CONNECT);
- /* Make sure that the handle will be processed soonish. */
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
- }
+ /* Remove this node from the list */
+ Curl_llist_remove(&multi->pending, e, NULL);
- e = next; /* operate on next handle */
+ /* Make sure that the handle will be processed soonish. */
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
+void Curl_set_in_callback(struct Curl_easy *easy, bool value)
+{
+ if(easy->multi_easy)
+ easy->multi_easy->in_callback = value;
+ else if(easy->multi)
+ easy->multi->in_callback = value;
+}
+
+bool Curl_is_in_callback(struct Curl_easy *easy)
+{
+ return ((easy->multi && easy->multi->in_callback) ||
+ (easy->multi_easy && easy->multi_easy->in_callback));
+}
+
#ifdef DEBUGBUILD
void Curl_multi_dump(struct Curl_multi *multi)
{
void *timer_userp;
struct curltime timer_lastcall; /* the fixed time for the timeout for the
previous callback */
+ bool in_callback; /* true while executing a callback */
};
#endif /* HEADER_CURL_MULTIHANDLE_H */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* Prototypes for library-wide functions provided by multi.c
*/
+void Curl_updatesocket(struct Curl_easy *data);
void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
void Curl_expire_clear(struct Curl_easy *data);
void Curl_expire_done(struct Curl_easy *data, expire_id id);
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
void Curl_multi_handlePipeBreak(struct Curl_easy *data);
+void Curl_set_in_callback(struct Curl_easy *data, bool value);
+bool Curl_is_in_callback(struct Curl_easy *easy);
/* Internal version of curl_multi_init() accepts size parameters for the
socket and connection hashes */
void Curl_multi_dump(struct Curl_multi *multi);
#endif
-void Curl_multi_process_pending_handles(struct Curl_multi *multi);
-
/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
#include "formdata.h"
#include "sendf.h"
#include "urldata.h"
+#include "multiif.h"
#include "curl_memory.h"
/* The last #include file should be: */
{
if(data && data->set.convtonetwork) {
/* use translation callback */
- CURLcode result = data->set.convtonetwork(buffer, length);
+ CURLcode result;
+ Curl_set_in_callback(data, true);
+ result = data->set.convtonetwork(buffer, length);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data,
"CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
{
if(data && data->set.convfromnetwork) {
/* use translation callback */
- CURLcode result = data->set.convfromnetwork(buffer, length);
+ CURLcode result;
+ Curl_set_in_callback(data, true);
+ result = data->set.convfromnetwork(buffer, length);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data,
"CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
{
if(data && data->set.convfromutf8) {
/* use translation callback */
- CURLcode result = data->set.convfromutf8(buffer, length);
+ CURLcode result;
+ Curl_set_in_callback(data, true);
+ result = data->set.convfromutf8(buffer, length);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data,
"CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
app_data = (libdata_t *) get_app_data(id);
if(!app_data) {
- app_data = malloc(sizeof(libdata_t));
+ app_data = calloc(1, sizeof(libdata_t));
if(app_data) {
- memset(app_data, 0, sizeof(libdata_t));
-
app_data->tenbytes = malloc(10);
app_data->lock = NXMutexAlloc(0, 0, &liblock);
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010, 2017, Howard Chu, <hyc@openldap.org>
- * Copyright (C) 2011 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
+ * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
if(conn->handler->flags & PROTOPT_SSL)
*ptr++ = 's';
snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
- conn->host.name, conn->remote_port);
+ conn->host.name, conn->remote_port);
#ifdef CURL_OPENLDAP_DEBUG
static int do_trace = 0;
tvp = &tv;
-retry:
+ retry:
if(!li->didbind) {
char *binddn;
struct berval passwd;
return ret;
for(ent = ldap_first_message(li->ld, msg); ent;
- ent = ldap_next_message(li->ld, ent)) {
- struct berval bv, *bvals, **bvp = &bvals;
+ ent = ldap_next_message(li->ld, ent)) {
+ struct berval bv, *bvals;
int binary = 0, msgtype;
CURLcode writeerr;
}
data->req.bytecount += bv.bv_len + 5;
- for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp);
- rc == LDAP_SUCCESS;
- rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) {
+ for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals);
+ rc == LDAP_SUCCESS;
+ rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) {
int i;
- if(bv.bv_val == NULL) break;
+ if(bv.bv_val == NULL)
+ break;
if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
binary = 1;
else
binary = 0;
+ if(bvals == NULL) {
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
+ data->req.bytecount += bv.bv_len + 3;
+ continue;
+ }
+
for(i = 0; bvals[i].bv_val != NULL; i++) {
int binval = 0;
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
- bv.bv_len);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
data->req.bytecount += bv.bv_len + 2;
if(!binary) {
/* check for leading or trailing whitespace */
if(ISSPACE(bvals[i].bv_val[0]) ||
- ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
+ ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
binval = 1;
else {
/* check for unprintable characters */
data->req.bytecount += 2;
if(val_b64_sz > 0) {
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
- val_b64_sz);
+ val_b64_sz);
if(writeerr) {
*err = writeerr;
return -1;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#define tDAYZONE -60 /* offset for daylight savings time */
static const struct tzinfo tz[]= {
{"GMT", 0}, /* Greenwich Mean */
+ {"UT", 0}, /* Universal Time */
{"UTC", 0}, /* Universal (Coordinated) */
{"WET", 0}, /* Western European */
{"BST", 0 tDAYZONE}, /* British Summer */
int tm_hour;
int tm_mday;
int tm_mon;
- int tm_year;
+ int tm_year; /* full year */
};
/* struct tm to time since epoch in GMT time zone.
* This is similar to the standard mktime function but for GMT only, and
* doesn't suffer from the various bugs and portability problems that
* some systems' implementations have.
+ *
+ * Returns 0 on success, otherwise non-zero.
*/
-static time_t my_timegm(struct my_tm *tm)
+static void my_timegm(struct my_tm *tm, time_t *t)
{
static const int month_days_cumulative [12] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
int month, year, leap_days;
- if(tm->tm_year < 70)
- /* we don't support years before 1970 as they will cause this function
- to return a negative value */
- return -1;
-
- year = tm->tm_year + 1900;
+ year = tm->tm_year;
month = tm->tm_mon;
if(month < 0) {
year += (11 - month) / 12;
leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400)
- (1969 / 4) + (1969 / 100) - (1969 / 400));
- return ((((time_t) (year - 1970) * 365
- + leap_days + month_days_cumulative [month] + tm->tm_mday - 1) * 24
- + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
+ *t = ((((time_t) (year - 1970) * 365
+ + leap_days + month_days_cumulative[month] + tm->tm_mday - 1) * 24
+ + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
}
/*
tzoff = (val/100 * 60 + val%100)*60;
/* the + and - prefix indicates the local time compared to GMT,
- this we need ther reversed math to get what we want */
+ this we need their reversed math to get what we want */
tzoff = date[-1]=='+'?-tzoff:tzoff;
}
if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) {
yearnum = val;
found = TRUE;
- if(yearnum < 1900) {
+ if(yearnum < 100) {
if(yearnum > 70)
yearnum += 1900;
else
/* lacks vital info, fail */
return PARSEDATE_FAIL;
-#if SIZEOF_TIME_T < 5
- /* 32 bit time_t can only hold dates to the beginning of 2038 */
- if(yearnum > 2037) {
- *output = 0x7fffffff;
- return PARSEDATE_LATER;
+#ifdef HAVE_TIME_T_UNSIGNED
+ if(yearnum < 1970) {
+ /* only positive numbers cannot return earlier */
+ *output = TIME_T_MIN;
+ return PARSEDATE_SOONER;
}
#endif
- if(yearnum < 1970) {
- *output = 0;
+#if (SIZEOF_TIME_T < 5)
+
+#ifdef HAVE_TIME_T_UNSIGNED
+ /* an unsigned 32 bit time_t can only hold dates to 2106 */
+ if(yearnum > 2105) {
+ *output = TIME_T_MAX;
+ return PARSEDATE_LATER;
+ }
+#else
+ /* a signed 32 bit time_t can only hold dates to the beginning of 2038 */
+ if(yearnum > 2037) {
+ *output = TIME_T_MAX;
+ return PARSEDATE_LATER;
+ }
+ if(yearnum < 1903) {
+ *output = TIME_T_MIN;
return PARSEDATE_SOONER;
}
+#endif
+
+#else
+ /* The Gregorian calendar was introduced 1582 */
+ if(yearnum < 1583)
+ return PARSEDATE_FAIL;
+#endif
if((mdaynum > 31) || (monnum > 11) ||
(hournum > 23) || (minnum > 59) || (secnum > 60))
tm.tm_hour = hournum;
tm.tm_mday = mdaynum;
tm.tm_mon = monnum;
- tm.tm_year = yearnum - 1900;
-
- /* my_timegm() returns a time_t. time_t is often 32 bits, even on many
- architectures that feature 64 bit 'long'.
+ tm.tm_year = yearnum;
- Some systems have 64 bit time_t and deal with years beyond 2038. However,
- even on some of the systems with 64 bit time_t mktime() returns -1 for
- dates beyond 03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06)
+ /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on
+ architectures that feature 64 bit 'long' but ultimately time_t is the
+ correct data type to use.
*/
- t = my_timegm(&tm);
-
- /* time zone adjust (cast t to int to compare to negative one) */
- if(-1 != (int)t) {
+ my_timegm(&tm, &t);
- /* Add the time zone diff between local time zone and GMT. */
- long delta = (long)(tzoff!=-1?tzoff:0);
+ /* Add the time zone diff between local time zone and GMT. */
+ if(tzoff == -1)
+ tzoff = 0;
- if((delta>0) && (t > LONG_MAX - delta)) {
- *output = 0x7fffffff;
- return PARSEDATE_LATER; /* time_t overflow */
- }
-
- t += delta;
+ if((tzoff > 0) && (t > TIME_T_MAX - tzoff)) {
+ *output = TIME_T_MAX;
+ return PARSEDATE_LATER; /* time_t overflow */
}
+ t += tzoff;
+
*output = t;
return PARSEDATE_OK;
int rc = parsedate(p, &parsed);
(void)now; /* legacy argument from the past that we ignore */
- switch(rc) {
- case PARSEDATE_OK:
- case PARSEDATE_LATER:
- case PARSEDATE_SOONER:
+ if(rc == PARSEDATE_OK) {
+ if(parsed == -1)
+ /* avoid returning -1 for a working scenario */
+ parsed++;
return parsed;
}
/* everything else is fail */
* it would have been populated with something of size int to begin
* with, even though its datatype may be larger than an int.
*/
- DEBUGASSERT((ptr + pp->cache_size) <= (buf + data->set.buffer_size + 1));
+ if((ptr + pp->cache_size) > (buf + data->set.buffer_size + 1)) {
+ failf(data, "cached response data too big to handle");
+ return CURLE_RECV_ERROR;
+ }
memcpy(ptr, pp->cache, pp->cache_size);
gotbytes = (ssize_t)pp->cache_size;
free(pp->cache); /* free the cache */
#include "urldata.h"
#include "sendf.h"
+#include "multiif.h"
#include "progress.h"
#include "curl_printf.h"
+/* check rate limits within this many recent milliseconds, at minimum. */
+#define MIN_RATE_LIMIT_PERIOD 3000
+
/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
byte) */
static void time2str(char *r, curl_off_t seconds)
data->progress.dl_limit_start.tv_usec = 0;
/* clear all bits except HIDE and HEADERS_OUT */
data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
+ Curl_ratelimit(data, data->progress.start);
}
/*
- * This is used to handle speed limits, calculating how much milliseconds we
- * need to wait until we're back under the speed limit, if needed.
+ * This is used to handle speed limits, calculating how many milliseconds to
+ * wait until we're back under the speed limit, if needed.
*
* The way it works is by having a "starting point" (time & amount of data
* transferred by then) used in the speed computation, to be used instead of
* the starting point, the limit (in bytes/s), the time of the starting point
* and the current time.
*
- * Returns -1 if no waiting is needed (not enough data transferred since
- * starting point yet), 0 when no waiting is needed but the starting point
- * should be reset (to current), or the number of milliseconds to wait to get
- * back under the speed limit.
+ * Returns 0 if no waiting is needed or when no waiting is needed but the
+ * starting point should be reset (to current); or the number of milliseconds
+ * to wait to get back under the speed limit.
*/
-long Curl_pgrsLimitWaitTime(curl_off_t cursize,
- curl_off_t startsize,
- curl_off_t limit,
- struct curltime start,
- struct curltime now)
+timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
+ curl_off_t startsize,
+ curl_off_t limit,
+ struct curltime start,
+ struct curltime now)
{
curl_off_t size = cursize - startsize;
time_t minimum;
time_t actual;
- /* we don't have a starting point yet -- return 0 so it gets (re)set */
- if(start.tv_sec == 0 && start.tv_usec == 0)
+ if(!limit || !size)
return 0;
- /* not enough data yet */
- if(size < limit)
- return -1;
+ /*
+ * 'minimum' is the number of milliseconds 'size' should take to download to
+ * stay below 'limit'.
+ */
+ if(size < CURL_OFF_T_MAX/1000)
+ minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ else {
+ minimum = (time_t) (size / limit);
+ if(minimum < TIME_T_MAX/1000)
+ minimum *= 1000;
+ else
+ minimum = TIME_T_MAX;
+ }
- minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ /*
+ * 'actual' is the time in milliseconds it took to actually download the
+ * last 'size' bytes.
+ */
actual = Curl_timediff(now, start);
-
- if(actual < minimum)
- /* this is a conversion on some systems (64bit time_t => 32bit long) */
- return (long)(minimum - actual);
+ if(actual < minimum) {
+ /* if it downloaded the data faster than the limit, make it wait the
+ difference */
+ return (minimum - actual);
+ }
return 0;
}
+/*
+ * Set the number of downloaded bytes so far.
+ */
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
- struct curltime now = Curl_now();
-
data->progress.downloaded = size;
+}
- /* download speed limit */
- if((data->set.max_recv_speed > 0) &&
- (Curl_pgrsLimitWaitTime(data->progress.downloaded,
- data->progress.dl_limit_size,
- data->set.max_recv_speed,
- data->progress.dl_limit_start,
- now) == 0)) {
- data->progress.dl_limit_start = now;
- data->progress.dl_limit_size = size;
+/*
+ * Update the timestamp and sizestamp to use for rate limit calculations.
+ */
+void Curl_ratelimit(struct Curl_easy *data, struct curltime now)
+{
+ /* don't set a new stamp unless the time since last update is long enough */
+ if(data->set.max_recv_speed > 0) {
+ if(Curl_timediff(now, data->progress.dl_limit_start) >=
+ MIN_RATE_LIMIT_PERIOD) {
+ data->progress.dl_limit_start = now;
+ data->progress.dl_limit_size = data->progress.downloaded;
+ }
+ }
+ if(data->set.max_send_speed > 0) {
+ if(Curl_timediff(now, data->progress.ul_limit_start) >=
+ MIN_RATE_LIMIT_PERIOD) {
+ data->progress.ul_limit_start = now;
+ data->progress.ul_limit_size = data->progress.uploaded;
+ }
}
}
+/*
+ * Set the number of uploaded bytes so far.
+ */
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
{
- struct curltime now = Curl_now();
-
data->progress.uploaded = size;
-
- /* upload speed limit */
- if((data->set.max_send_speed > 0) &&
- (Curl_pgrsLimitWaitTime(data->progress.uploaded,
- data->progress.ul_limit_size,
- data->set.max_send_speed,
- data->progress.ul_limit_start,
- now) == 0)) {
- data->progress.ul_limit_start = now;
- data->progress.ul_limit_size = size;
- }
}
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
if(data->set.fxferinfo) {
/* There's a callback set, call that */
+ Curl_set_in_callback(data, true);
result = data->set.fxferinfo(data->set.progress_client,
data->progress.size_dl,
data->progress.downloaded,
data->progress.size_ul,
data->progress.uploaded);
+ Curl_set_in_callback(data, false);
if(result)
failf(data, "Callback aborted");
return result;
}
if(data->set.fprogress) {
/* The older deprecated callback is set, call that */
+ Curl_set_in_callback(data, true);
result = data->set.fprogress(data->set.progress_client,
(double)data->progress.size_dl,
(double)data->progress.downloaded,
(double)data->progress.size_ul,
(double)data->progress.uploaded);
+ Curl_set_in_callback(data, false);
if(result)
failf(data, "Callback aborted");
return result;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
+void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
void Curl_pgrsTime(struct Curl_easy *data, timerid timer);
-long Curl_pgrsLimitWaitTime(curl_off_t cursize,
- curl_off_t startsize,
- curl_off_t limit,
- struct curltime start,
- struct curltime now);
+timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
+ curl_off_t startsize,
+ curl_off_t limit,
+ struct curltime start,
+ struct curltime now);
/* Don't show progress for sizes smaller than: */
#define LEAST_SIZE_PROGRESS BUFSIZE
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* -incoming server requests
* -server CSeq counter
* -digest authentication
- * -connect thru proxy
+ * -connect through proxy
* -pipelining?
*/
}
/* Transport Header for SETUP requests */
- p_transport = Curl_checkheaders(conn, "Transport:");
+ p_transport = Curl_checkheaders(conn, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
/* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */
- p_accept = Curl_checkheaders(conn, "Accept:")?
+ p_accept = Curl_checkheaders(conn, "Accept")?
NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */
- if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
+ if(Curl_checkheaders(conn, "User-Agent") && conn->allocptr.uagent) {
Curl_safefree(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
- else if(!Curl_checkheaders(conn, "User-Agent:") &&
+ else if(!Curl_checkheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT]) {
p_uagent = conn->allocptr.uagent;
}
/* Referrer */
Curl_safefree(conn->allocptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer:"))
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
conn->allocptr.ref = NULL;
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* Check to see if there is a range set in the custom headers */
- if(!Curl_checkheaders(conn, "Range:") && data->state.range) {
+ if(!Curl_checkheaders(conn, "Range") && data->state.range) {
Curl_safefree(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = conn->allocptr.rangeline;
/*
* Sanity check the custom headers
*/
- if(Curl_checkheaders(conn, "CSeq:")) {
+ if(Curl_checkheaders(conn, "CSeq")) {
failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR;
}
- if(Curl_checkheaders(conn, "Session:")) {
+ if(Curl_checkheaders(conn, "Session")) {
failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
if(putsize > 0 || postsize > 0) {
/* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */
- if(!Curl_checkheaders(conn, "Content-Length:")) {
+ if(!Curl_checkheaders(conn, "Content-Length")) {
result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
(data->set.upload ? putsize : postsize));
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: text/parameters\r\n");
if(result)
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/sdp\r\n");
if(result)
writeit = data->set.fwrite_rtp;
user_ptr = data->set.rtp_out;
}
- else
- {
+ else {
writeit = data->set.fwrite_func;
user_ptr = data->set.out;
}
+ Curl_set_in_callback(data, true);
wrote = writeit(ptr, 1, len, user_ptr);
+ Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
failf(data, "Cannot pause RTP");
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "connect.h"
#include "vtls/vtls.h"
#include "ssh.h"
+#include "easyif.h"
#include "multiif.h"
#include "non-ascii.h"
#include "strerror.h"
(WSAEWOULDBLOCK == err)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
- due to its inability to send off data without blocking. We therefor
+ due to its inability to send off data without blocking. We therefore
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
(EINPROGRESS == err)
(WSAEWOULDBLOCK == err)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
- due to its inability to send off data without blocking. We therefor
+ due to its inability to send off data without blocking. We therefore
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
}
-/* Curl_client_chop_write() writes chunks of data not larger than
- * CURL_MAX_WRITE_SIZE via client write callback(s) and
- * takes care of pause requests from the callbacks.
+/* chop_write() writes chunks of data not larger than CURL_MAX_WRITE_SIZE via
+ * client write callback(s) and takes care of pause requests from the
+ * callbacks.
*/
-CURLcode Curl_client_chop_write(struct connectdata *conn,
- int type,
- char *ptr,
- size_t len)
+static CURLcode chop_write(struct connectdata *conn,
+ int type,
+ char *optr,
+ size_t olen)
{
struct Curl_easy *data = conn->data;
curl_write_callback writeheader = NULL;
curl_write_callback writebody = NULL;
+ char *ptr = optr;
+ size_t len = olen;
if(!len)
return CURLE_OK;
}
}
- if(writeheader) {
- size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
-
- if(CURL_WRITEFUNC_PAUSE == wrote)
- /* here we pass in the HEADER bit only since if this was body as well
- then it was passed already and clearly that didn't trigger the
- pause, so this is saved for later with the HEADER bit only */
- return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
-
- if(wrote != chunklen) {
- failf(data, "Failed writing header");
- return CURLE_WRITE_ERROR;
- }
- }
-
ptr += chunklen;
len -= chunklen;
}
+ if(writeheader) {
+ size_t wrote;
+ ptr = optr;
+ len = olen;
+ Curl_set_in_callback(data, true);
+ wrote = writeheader(ptr, 1, len, data->set.writeheader);
+ Curl_set_in_callback(data, false);
+
+ if(CURL_WRITEFUNC_PAUSE == wrote)
+ /* here we pass in the HEADER bit only since if this was body as well
+ then it was passed already and clearly that didn't trigger the
+ pause, so this is saved for later with the HEADER bit only */
+ return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
+
+ if(wrote != len) {
+ failf(data, "Failed writing header");
+ return CURLE_WRITE_ERROR;
+ }
+ }
+
return CURLE_OK;
}
#endif /* CURL_DO_LINEEND_CONV */
}
- return Curl_client_chop_write(conn, type, ptr, len);
+ return chop_write(conn, type, ptr, len);
}
CURLcode Curl_read_plain(curl_socket_t sockfd,
}
#endif /* CURL_DOES_CONVERSIONS */
- if(data->set.fdebug)
+ if(data->set.fdebug) {
+ Curl_set_in_callback(data, true);
rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+ Curl_set_in_callback(data, false);
+ }
else {
switch(type) {
case CURLINFO_TEXT:
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#define CLIENTWRITE_HEADER (1<<1)
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
-CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr,
- size_t len) WARN_UNUSED_RESULT;
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
#include "sendf.h"
#include "http2.h"
#include "setopt.h"
+#include "multiif.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
data->set.timevalue = (time_t)va_arg(param, long);
break;
+ case CURLOPT_TIMEVALUE_LARGE:
+ /*
+ * This is the value to compare with the remote document with the
+ * method set with CURLOPT_TIMECONDITION
+ */
+ data->set.timevalue = (time_t)va_arg(param, curl_off_t);
+ break;
+
case CURLOPT_SSLVERSION:
case CURLOPT_PROXY_SSLVERSION:
/*
if(checkprefix("Set-Cookie:", argptr))
/* HTTP Header format line */
- Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
+ Curl_cookie_add(data, data->cookies, TRUE, FALSE, argptr + 11, NULL,
+ NULL);
else
/* Netscape format line */
- Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
+ Curl_cookie_add(data, data->cookies, FALSE, FALSE, argptr, NULL,
+ NULL);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
free(argptr);
*/
data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
+#endif
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
case CURLOPT_PROXY_SERVICE_NAME:
result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
va_arg(param, char *));
break;
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_SPNEGO)
case CURLOPT_SERVICE_NAME:
/*
* Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
va_arg(param, char *));
break;
-#endif
-
case CURLOPT_HEADERDATA:
/*
* Custom pointer to pass the header write callback function
data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
+ case CURLOPT_HAPROXYPROTOCOL:
+ /*
+ * Set to send the HAProxy Proxy Protocol header
+ */
+ data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
case CURLOPT_INTERFACE:
/*
* Set what interface or address/hostname to bind the socket to when
* Set a SSL_CTX callback
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ssl_ctx)
+ if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
else
#endif
* Set a SSL_CTX callback parameter pointer
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ssl_ctx)
+ if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
data->set.ssl.fsslctxp = va_arg(param, void *);
else
#endif
break;
case CURLOPT_CERTINFO:
#ifdef USE_SSL
- if(Curl_ssl->have_certinfo)
+ if(Curl_ssl->supports & SSLSUPP_CERTINFO)
data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
else
#endif
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_pinnedpubkey)
+ if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
va_arg(param, char *));
else
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_pinnedpubkey)
+ if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
va_arg(param, char *));
else
* certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ca_path)
+ if(Curl_ssl->supports & SSLSUPP_CA_PATH)
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
va_arg(param, char *));
* CA certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ca_path)
+ if(Curl_ssl->supports & SSLSUPP_CA_PATH)
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
va_arg(param, char *));
data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
break;
+ case CURLOPT_RESOLVER_START_FUNCTION:
+ /*
+ * resolver start callback function: called before a new resolver request
+ * is started
+ */
+ data->set.resolver_start = va_arg(param, curl_resolver_start_callback);
+ break;
+
+ case CURLOPT_RESOLVER_START_DATA:
+ /*
+ * resolver start callback data pointer. Might be NULL.
+ */
+ data->set.resolver_start_client = va_arg(param, void *);
+ break;
+
case CURLOPT_CLOSESOCKETDATA:
/*
* socket callback data pointer. Might be NULL.
case CURLOPT_SSH_COMPRESSION:
data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
break;
+ case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.happy_eyeballs_timeout = arg;
+ break;
+ case CURLOPT_DNS_SHUFFLE_ADDRESSES:
+ data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
+ break;
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
/*
* curl_easy_setopt() is the external interface for setting options on an
* easy handle.
+ *
+ * NOTE: This is one of few API functions that are allowed to be called from
+ * within a callback.
*/
#undef curl_easy_setopt
#if defined(USE_OPENSSL)
+#include <openssl/opensslv.h>
+
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
+#define USE_OPENSSL_SHA256
+#endif
+
+#endif
+
+#ifdef USE_OPENSSL_SHA256
/* When OpenSSL is available we use the SHA256-function from OpenSSL */
#include <openssl/sha.h>
-
#else
/* When no other crypto library is available we use this code segment */
sha256_compress(md, md->buf);
md->curlen = 0;
}
- /* pad upto 56 bytes of zeroes */
+ /* pad up to 56 bytes of zeroes */
while(md->curlen < 56) {
md->buf[md->curlen++] = (unsigned char)0;
}
}
/*
- * Convert a timestamp from the Windows world (100 nsec units from
- * 1 Jan 1601) to Posix time.
+ * Convert a timestamp from the Windows world (100 nsec units from 1 Jan 1601)
+ * to Posix time. Cap the output to fit within a time_t.
*/
-static void get_posix_time(long *out, curl_off_t timestamp)
+static void get_posix_time(time_t *out, curl_off_t timestamp)
{
timestamp -= 116444736000000000;
timestamp /= 10000000;
- *out = (long) timestamp;
+#if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T
+ if(timestamp > TIME_T_MAX)
+ *out = TIME_T_MAX;
+ else if(timestamp < TIME_T_MIN)
+ *out = TIME_T_MIN;
+ else
+#endif
+ *out = (time_t) timestamp;
}
static CURLcode smb_request_state(struct connectdata *conn, bool *done)
else {
smb_m = (const struct smb_nt_create_response*) msg;
conn->data->req.size = smb_swap64(smb_m->end_of_file);
- Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
- if(conn->data->set.get_filetime)
- get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
- next_state = SMB_DOWNLOAD;
+ if(conn->data->req.size < 0) {
+ req->result = CURLE_WEIRD_SERVER_REPLY;
+ next_state = SMB_CLOSE;
+ }
+ else {
+ Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
+ if(conn->data->set.get_filetime)
+ get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
+ next_state = SMB_DOWNLOAD;
+ }
}
break;
/* Store the first recipient (or NULL if not specified) */
smtp->rcpt = data->set.mail_rcpt;
+ /* Initial data character is the first character in line: it is implicitly
+ preceded by a virtual CRLF. */
+ smtp->trailing_crlf = TRUE;
+ smtp->eob = 2;
+
/* Start the first command in the DO phase */
if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
/* MAIL transfer */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017 Red Hat, Inc.
+ * Copyright (C) 2017 - 2018 Red Hat, Inc.
*
* Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
* Robert Kolcun, Andreas Schneider
}
/* we don't have anything equivalent to knownkey. Always NULL */
+ Curl_set_in_callback(data, true);
rc = func(data, NULL, &foundkey, /* from the remote host */
keymatch, data->set.ssh_keyfunc_userp);
+ Curl_set_in_callback(data, false);
switch(rc) {
case CURLKHSTAT_FINE_ADD_TO_FILE:
attrs = sftp_stat(sshc->sftp_session, protop->path);
if(attrs != 0) {
- data->info.filetime = (long)attrs->mtime;
+ data->info.filetime = attrs->mtime;
sftp_attributes_free(attrs);
}
if(data->state.resume_from > 0) {
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
ssize_t nread;
(void)sockindex;
- if(len >= (size_t)1<<32)
- len = (size_t)(1<<31)-1;
+ DEBUGASSERT(len < CURL_MAX_READ_SIZE);
switch(conn->proto.sshc.sftp_recv_state) {
case 0:
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
"SSH_AUTH_HOST",
"SSH_AUTH_KEY_INIT",
"SSH_AUTH_KEY",
+ "SSH_AUTH_GSSAPI",
"SSH_AUTH_DONE",
"SSH_SFTP_INIT",
"SSH_SFTP_REALPATH",
"SSH_SCP_TRANS_INIT",
"SSH_SCP_UPLOAD_INIT",
"SSH_SCP_DOWNLOAD_INIT",
+ "SSH_SCP_DOWNLOAD",
"SSH_SCP_DONE",
"SSH_SCP_SEND_EOF",
"SSH_SCP_WAIT_EOF",
"QUIT"
};
+ /* a precaution to make sure the lists are in sync */
+ DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
+
if(sshc->state != nowstate) {
infof(conn->data, "SFTP %p state change from %s to %s\n",
(void *)sshc, names[sshc->state], names[nowstate]);
keymatch = (enum curl_khmatch)keycheck;
/* Ask the callback how to behave */
+ Curl_set_in_callback(data, true);
rc = func(data, knownkeyp, /* from the knownhosts file */
&foundkey, /* from the remote host */
keymatch, data->set.ssh_keyfunc_userp);
+ Curl_set_in_callback(data, false);
}
else
/* no remotekey means failure! */
* This is done by simply passing sshc->rsa_pub = NULL.
*/
if(data->set.str[STRING_SSH_PUBLIC_KEY]
- /* treat empty string the same way as NULL */
- && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
+ /* treat empty string the same way as NULL */
+ && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
if(!sshc->rsa_pub)
out_of_memory = TRUE;
state(conn, SSH_AUTH_DONE);
}
else {
- char *err_msg;
+ char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
infof(data, "SSH public key authentication failed: %s\n", err_msg);
*/
sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
if(!sshc->sftp_session) {
- char *err_msg;
+ char *err_msg = NULL;
if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) {
rc = LIBSSH2_ERROR_EAGAIN;
break;
}
if(strncasecompare(cmd, "ln ", 3) ||
- strncasecompare(cmd, "symlink ", 8)) {
+ strncasecompare(cmd, "symlink ", 8)) {
/* symbolic linking */
/* sshc->quote_path1 is the source */
/* get the destination */
break;
}
if(rc == 0) {
- data->info.filetime = (long)attrs.mtime;
+ data->info.filetime = attrs.mtime;
}
state(conn, SSH_SFTP_TRANS_INIT);
if(data->state.resume_from > 0) {
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
(size_t)data->set.buffer_size :
curlx_sotouz(data->state.resume_from - passed);
- size_t actuallyread =
- data->state.fread_func(data->state.buffer, 1,
- readthisamountnow, data->state.in);
+ size_t actuallyread;
+ Curl_set_in_callback(data, true);
+ actuallyread = data->state.fread_func(data->state.buffer, 1,
+ readthisamountnow,
+ data->state.in);
+ Curl_set_in_callback(data, false);
passed += actuallyread;
if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
break;
}
if(rc ||
- !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
- (attrs.filesize == 0)) {
+ !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
+ (attrs.filesize == 0)) {
/*
* libssh2_sftp_open() didn't return an error, so maybe the server
* just doesn't support stat()
break;
}
if(rc < 0) {
- infof(data, "Failed to close libssh2 file\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
}
sshc->sftp_handle = NULL;
}
break;
}
if(rc < 0) {
- infof(data, "Failed to close libssh2 file\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
+ NULL, 0);
+ infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
}
sshc->sftp_handle = NULL;
}
data->state.infilesize);
if(!sshc->ssh_channel) {
int ssh_err;
- char *err_msg;
+ char *err_msg = NULL;
if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) {
* be set in sb
*/
- /*
- * If support for >2GB files exists, use it.
- */
+ /*
+ * If support for >2GB files exists, use it.
+ */
/* get a fresh new channel from the ssh layer */
#if LIBSSH2_VERSION_NUM < 0x010700
if(!sshc->ssh_channel) {
int ssh_err;
- char *err_msg;
+ char *err_msg = NULL;
if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) {
break;
}
if(rc) {
- infof(data, "Failed to send libssh2 channel EOF\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to send libssh2 channel EOF: %d %s\n",
+ rc, err_msg);
}
}
state(conn, SSH_SCP_WAIT_EOF);
break;
}
if(rc) {
- infof(data, "Failed to get channel EOF: %d\n", rc);
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg);
}
}
state(conn, SSH_SCP_WAIT_CLOSE);
break;
}
if(rc) {
- infof(data, "Channel failed to close: %d\n", rc);
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Channel failed to close: %d %s\n", rc, err_msg);
}
}
state(conn, SSH_SCP_CHANNEL_FREE);
break;
}
if(rc < 0) {
- infof(data, "Failed to free libssh2 scp subsystem\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
+ rc, err_msg);
}
sshc->ssh_channel = NULL;
}
break;
}
if(rc < 0) {
- infof(data, "Failed to free libssh2 scp subsystem\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
+ rc, err_msg);
}
sshc->ssh_channel = NULL;
}
break;
}
if(rc < 0) {
- infof(data, "Failed to disconnect libssh2 session\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to disconnect libssh2 session: %d %s\n",
+ rc, err_msg);
}
}
break;
}
if(rc < 0) {
- infof(data, "Failed to disconnect from libssh2 agent\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to disconnect from libssh2 agent: %d %s\n",
+ rc, err_msg);
}
libssh2_agent_free(sshc->ssh_agent);
sshc->ssh_agent = NULL;
break;
}
if(rc < 0) {
- infof(data, "Failed to free libssh2 session\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 session: %d %s\n", rc, err_msg);
}
sshc->ssh_session = NULL;
}
case CURLE_HTTP2_STREAM:
return "Stream error in the HTTP/2 framing layer";
+ case CURLE_RECURSIVE_API_CALL:
+ return "API function called from within callback";
+
/* error codes not used by current libcurl */
case CURLE_OBSOLETE20:
case CURLE_OBSOLETE24:
case CURLM_ADDED_ALREADY:
return "The easy handle is already added to a multi handle";
+ case CURLM_RECURSIVE_API_CALL:
+ return "API function called from within callback";
+
case CURLM_LAST:
break;
}
errno = 0;
*num = 0; /* clear by default */
- DEBUGASSERT(str);
-
while(*str && ISSPACE(*str))
str++;
if('-' == *str) {
CURL_SB_ACCUM(tn, c);
tn->telrcv_state = CURL_TS_SB;
}
- else
- {
+ else {
CURL_SB_ACCUM(tn, CURL_IAC);
CURL_SB_ACCUM(tn, CURL_SE);
tn->subpointer -= 2;
if(n == 0) /* no bytes */
break;
- readfile_read = (DWORD)n; /* fall thru with number of bytes read */
+ /* fall through with number of bytes read */
+ readfile_read = (DWORD)n;
}
else {
/* read from stdin */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
state->requested_blksize = blksize;
((struct sockaddr *)&state->local_addr)->sa_family =
- (unsigned short)(conn->ip_addr->ai_family);
+ (CURL_SA_FAMILY_T)(conn->ip_addr->ai_family);
tftp_set_timeouts(state);
usecs /= 1000;
cnow.tv_sec = usecs / 1000000;
- cnow.tv_usec = usecs % 1000000;
+ cnow.tv_usec = (int)(usecs % 1000000);
return cnow;
}
struct curltime ret;
(void)gettimeofday(&now, NULL);
ret.tv_sec = now.tv_sec;
- ret.tv_usec = now.tv_usec;
+ ret.tv_usec = (int)now.tv_usec;
return ret;
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
!defined(CURL_DISABLE_IMAP)
/*
* checkheaders() checks the linked list of custom headers for a
- * particular header (prefix).
+ * particular header (prefix). Provide the prefix without colon!
*
* Returns a pointer to the first matching header or NULL if none matched.
*/
struct Curl_easy *data = conn->data;
for(head = data->set.headers; head; head = head->next) {
- if(strncasecompare(head->data, thisheader, thislen))
+ if(strncasecompare(head->data, thisheader, thislen) &&
+ Curl_headersep(head->data[thislen]) )
return head->data;
}
/* this function returns a size_t, so we typecast to int to prevent warnings
with picky compilers */
+ Curl_set_in_callback(data, true);
nread = (int)data->state.fread_func(data->req.upload_fromhere, 1,
buffersize, data->state.in);
+ Curl_set_in_callback(data, false);
if(nread == CURL_READFUNC_ABORT) {
failf(data, "operation aborted by callback");
if(data->set.seek_func) {
int err;
+ Curl_set_in_callback(data, true);
err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
+ Curl_set_in_callback(data, false);
if(err) {
failf(data, "seek callback returned error %d", (int)err);
return CURLE_SEND_FAIL_REWIND;
else if(data->set.ioctl_func) {
curlioerr err;
+ Curl_set_in_callback(data, true);
err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
data->set.ioctl_client);
+ Curl_set_in_callback(data, false);
infof(data, "the ioctl callback returned %d\n", (int)err);
if(err) {
#endif /* CURL_DISABLE_HTTP */
/* Account for body content stored in the header buffer */
- if(k->badheader && !k->ignorebody) {
+ if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) {
DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n",
k->hbuflen));
k->bytecount += k->hbuflen;
} /* if(!header and data to read) */
- if(conn->handler->readwrite &&
- (excess > 0 && !conn->bits.stream_was_rewound)) {
+ if(conn->handler->readwrite && excess && !conn->bits.stream_was_rewound) {
/* Parse the excess data */
k->str += nread;
+
+ if(&k->str[excess] > &k->buf[data->set.buffer_size]) {
+ /* the excess amount was too excessive(!), make sure
+ it doesn't read out of buffer */
+ excess = &k->buf[data->set.buffer_size] - k->str;
+ }
nread = (ssize_t)excess;
result = conn->handler->readwrite(data, conn, &nread, &readmore);
}
/*
+ * Decide in an encoding-independent manner whether a character in an
+ * URL must be escaped. The same criterion must be used in strlen_url()
+ * and strcpy_url().
+ */
+static bool urlchar_needs_escaping(int c)
+{
+ return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
+}
+
+/*
* strlen_url() returns the length of the given URL if the spaces within the
* URL were properly URL encoded.
* URL encoding should be skipped for host names, otherwise IDN resolution
left = FALSE;
/* fall through */
default:
- if(*ptr >= 0x80)
+ if(urlchar_needs_escaping(*ptr))
newlen += 2;
newlen++;
break;
left = FALSE;
/* fall through */
default:
- if(*iptr >= 0x80) {
+ if(urlchar_needs_escaping(*iptr)) {
snprintf(optr, 4, "%%%02x", *iptr);
optr += 3;
}
char **url)
{
struct Curl_easy *data = conn->data;
-
+ bool retry = FALSE;
*url = NULL;
/* if we're talking upload, we can't do the checks below, unless the protocol
conn->bits.reuse &&
(!data->set.opt_no_body
|| (conn->handler->protocol & PROTO_FAMILY_HTTP)) &&
- (data->set.rtspreq != RTSPREQ_RECEIVE)) {
+ (data->set.rtspreq != RTSPREQ_RECEIVE))
/* We got no data, we attempted to re-use a connection. For HTTP this
can be a retry so we try again regardless if we expected a body.
For other protocols we only try again only if we expected a body.
This might happen if the connection was left alive when we were
done using it before, but that was closed when we wanted to read from
it again. Bad luck. Retry the same request on a fresh connect! */
+ retry = TRUE;
+ else if(data->state.refused_stream &&
+ (data->req.bytecount + data->req.headerbytecount == 0) ) {
+ /* This was sent on a refused stream, safe to rerun. A refused stream
+ error can typically only happen on HTTP/2 level if the stream is safe
+ to issue again, but the nghttp2 API can deliver the message to other
+ streams as well, which is why this adds the check the data counters
+ too. */
+ infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n");
+ data->state.refused_stream = FALSE; /* clear again */
+ retry = TRUE;
+ }
+ if(retry) {
infof(conn->data, "Connection died, retrying a fresh connect\n");
*url = strdup(conn->data->change.url);
if(!*url)
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- /* now copy all input parameters */
- conn->sockfd = sockindex == -1 ?
+ if(conn->bits.multiplex || conn->httpversion == 20) {
+ /* when multiplexing, the read/write sockets need to be the same! */
+ conn->sockfd = sockindex == -1 ?
+ ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
+ conn->sock[sockindex];
+ conn->writesockfd = conn->sockfd;
+ }
+ else {
+ conn->sockfd = sockindex == -1 ?
CURL_SOCKET_BAD : conn->sock[sockindex];
- conn->writesockfd = writesockindex == -1 ?
+ conn->writesockfd = writesockindex == -1 ?
CURL_SOCKET_BAD:conn->sock[writesockindex];
+ }
k->getheader = getheader;
k->size = size;
/* we want header and/or body, if neither then don't do this! */
if(k->getheader || !data->set.opt_no_body) {
- if(conn->sockfd != CURL_SOCKET_BAD)
+ if(sockindex != -1)
k->keepon |= KEEP_RECV;
- if(conn->writesockfd != CURL_SOCKET_BAD) {
+ if(writesockindex != -1) {
struct HTTP *http = data->req.protop;
/* HTTP 1.1 magic:
/* enable the write bit when we're not waiting for continue */
k->keepon |= KEEP_SEND;
}
- } /* if(conn->writesockfd != CURL_SOCKET_BAD) */
+ } /* if(writesockindex != -1) */
} /* if(k->getheader || !data->set.opt_no_body) */
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
*
***************************************************************************/
+#define Curl_headersep(x) ((((x)==':') || ((x)==';')))
char *Curl_checkheaders(const struct connectdata *conn,
const char *thisheader);
set->socks5_gssapi_nec = FALSE;
#endif
- /* This is our preferred CA cert bundle/path since install time */
+ /* Set the default CA cert bundle/path detected/specified at build time.
+ *
+ * If Schannel (WinSSL) is the selected SSL backend then these locations
+ * are ignored. We allow setting CA location for schannel only when
+ * explicitly specified by the user via CURLOPT_CAINFO / --cacert.
+ */
+ if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
#if defined(CURL_CA_BUNDLE)
- result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
+ if(result)
+ return result;
- result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
+ CURL_CA_BUNDLE);
+ if(result)
+ return result;
#endif
#if defined(CURL_CA_PATH)
- result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
+ if(result)
+ return result;
- result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
+ if(result)
+ return result;
#endif
+ }
set->wildcard_enabled = FALSE;
set->chunk_bgn = ZERO_NULL;
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
set->buffer_size = READBUFFER_SIZE;
+ set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
Curl_http2_init_userset(set);
return result;
return CURLE_URL_MALFORMAT;
}
- if(url_has_scheme && path[0] == '/' && path[1] == '/' &&
- path[2] == '/' && path[3] == '/') {
- /* This appears to be a UNC string (usually indicating a SMB share).
- * We don't do SMB in file: URLs. (TODO?)
- */
- failf(data, "SMB shares are not supported in file: URLs.");
- return CURLE_URL_MALFORMAT;
- }
-
/* Extra handling URLs with an authority component (i.e. that start with
* "file://")
*
ptr += 9; /* now points to the slash after the host */
}
- /*
- * RFC 8089, Appendix D, Section D.1, says:
- *
- * > In a POSIX file system, the root of the file system is represented
- * > as a directory with a zero-length name, usually written as "/"; the
- * > presence of this root in a file URI can be taken as given by the
- * > initial slash in the "path-absolute" rule.
- *
- * i.e. the first slash is part of the path.
- *
- * However in RFC 1738 the "/" between the host (or port) and the
- * URL-path was NOT part of the URL-path. Any agent that followed the
- * older spec strictly, and wanted to refer to a file with an absolute
- * path, would have included a second slash. So if there are two
- * slashes, swallow one.
- */
- if('/' == ptr[1]) /* note: the only way ptr[0]!='/' is if ptr[1]==':' */
- ptr++;
-
/* This cannot be done with strcpy, as the memory chunks overlap! */
memmove(path, ptr, strlen(ptr) + 1);
}
/* NO_PROXY was specified and it wasn't just an asterisk */
no_proxy_len = strlen(no_proxy);
- endptr = strchr(name, ':');
+ if(name[0] == '[') {
+ /* IPv6 numerical address */
+ endptr = strchr(name, ']');
+ if(!endptr)
+ return FALSE;
+ name++;
+ }
+ else
+ endptr = strchr(name, ':');
if(endptr)
namelen = endptr - name;
else
prox = curl_getenv(proxy_env);
}
- if(prox)
+ envp = proxy_env;
+ if(prox) {
proxy = prox; /* use this */
+ }
else {
- proxy = curl_getenv("all_proxy"); /* default proxy to use */
- if(!proxy)
- proxy = curl_getenv("ALL_PROXY");
+ envp = (char *)"all_proxy";
+ proxy = curl_getenv(envp); /* default proxy to use */
+ if(!proxy) {
+ envp = (char *)"ALL_PROXY";
+ proxy = curl_getenv(envp);
+ }
}
+ if(proxy)
+ infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
return proxy;
}
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
#ifdef USE_SSL
- if(!Curl_ssl->support_https_proxy)
+ if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
#endif
if(proxytype == CURLPROXY_HTTPS) {
failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
}
if(!data->set.str[STRING_NOPROXY]) {
- no_proxy = curl_getenv("no_proxy");
- if(!no_proxy)
- no_proxy = curl_getenv("NO_PROXY");
+ const char *p = "no_proxy";
+ no_proxy = curl_getenv(p);
+ if(!no_proxy) {
+ p = "NO_PROXY";
+ no_proxy = curl_getenv(p);
+ }
+ if(no_proxy) {
+ infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
+ }
}
if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
* stripped off. It would be better to work directly from the original
* URL and simply replace the port part of it.
*/
- url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme,
+ url = aprintf("%s://%s%s%s:%d%s%s%s", conn->given->scheme,
conn->bits.ipv6_ip?"[":"", conn->host.name,
conn->bits.ipv6_ip?"]":"", conn->remote_port,
data->state.slash_removed?"/":"", data->state.path,
*************************************************************/
if(prot_missing) {
/* We're guessing prefixes here and if we're told to use a proxy or if
- we're gonna follow a Location: later or... then we need the protocol
+ we're going to follow a Location: later or... then we need the protocol
part added so that we have a valid URL. */
char *reurl;
char *ch_lower;
#include "hash.h"
#include "splay.h"
+/* return the count of bytes sent, or -1 on error */
+typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ const void *buf, /* data to write */
+ size_t len, /* max amount to write */
+ CURLcode *err); /* error to return */
+
+/* return the count of bytes read, or -1 on error */
+typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ char *buf, /* store data here */
+ size_t len, /* max amount to read */
+ CURLcode *err); /* error to return */
+
#include "mime.h"
#include "imap.h"
#include "pop3.h"
BYTE *output_token;
BYTE *input_token;
size_t input_token_len;
+ TCHAR *spn;
#else
unsigned int flags;
unsigned char nonce[8];
#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
-/* return the count of bytes sent, or -1 on error */
-typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
- int sockindex, /* socketindex */
- const void *buf, /* data to write */
- size_t len, /* max amount to write */
- CURLcode *err); /* error to return */
-
-/* return the count of bytes read, or -1 on error */
-typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
- int sockindex, /* socketindex */
- char *buf, /* store data here */
- size_t len, /* max amount to read */
- CURLcode *err); /* error to return */
-
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
struct postponed_data {
char *buffer; /* Temporal store for received data during
well be the same we read from.
CURL_SOCKET_BAD disables */
- /** Dynamicly allocated strings, MUST be freed before this **/
+ /** Dynamically allocated strings, MUST be freed before this **/
/** struct is killed. **/
struct dynamically_allocated_data {
char *proxyuserpwd;
int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */
int httpproxycode; /* response code from proxy when received separate */
int httpversion; /* the http version number X.Y = X*10+Y */
- long filetime; /* If requested, this is might get set. Set to -1 if the time
- was unretrievable. We cannot have this of type time_t,
- since time_t is unsigned on several platforms such as
- OpenVMS. */
+ time_t filetime; /* If requested, this is might get set. Set to -1 if the
+ time was unretrievable. */
bool timecond; /* set to TRUE if the time condition didn't match, which
thus made the document NOT get fetched */
long header_size; /* size of read header(s) in bytes */
};
/*
- * This struct is for holding data that was attemped to get sent to the user's
+ * This struct is for holding data that was attempted to get sent to the user's
* callback but is held due to pausing. One instance per type (BOTH, HEADER,
* BODY).
*/
curl_off_t current_speed; /* the ProgressShow() function sets this,
bytes / second */
bool this_is_a_follow; /* this is a followed Location: request */
-
+ bool refused_stream; /* this was refused, try again */
char *first_host; /* host name of the first (not followed) request.
if set, this should be the host name that we will
sent authorization to, no else. Used to make Location:
STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */
#endif
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
STRING_PROXY_SERVICE_NAME, /* Proxy service name */
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_SPNEGO) || defined(HAVE_GSSAPI)
STRING_SERVICE_NAME, /* Service name */
-#endif
STRING_MAIL_FROM,
STRING_MAIL_AUTH,
long timeout; /* in milliseconds, 0 means no timeout */
long connecttimeout; /* in milliseconds, 0 means no timeout */
long accepttimeout; /* in milliseconds, 0 means no timeout */
+ long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */
long server_response_timeout; /* in milliseconds, 0 means no timeout */
long tftp_blksize; /* in bytes, 0 means use default */
bool tftp_no_options; /* do not send TFTP options requests */
bool suppress_connect_headers; /* suppress proxy CONNECT response headers
from user callbacks */
+ bool dns_shuffle_addresses; /* whether to shuffle addresses before use */
+
struct Curl_easy *stream_depends_on;
bool stream_depends_e; /* set or don't set the Exclusive bit */
int stream_weight;
+ bool haproxyprotocol; /* whether to send HAProxy PROXY protocol header */
+
struct Curl_http2_dep *stream_dependents;
bool abstract_unix_socket;
+
+ curl_resolver_start_callback resolver_start; /* optional callback called
+ before resolver start */
+ void *resolver_start_client; /* pointer to pass to resolver start callback */
};
struct Names {
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
ulen = strlen(userp);
plen = strlen(passwdp);
- /* Compute binary message length, checking for overflows. */
- plainlen = 2 * ulen;
- if(plainlen < ulen)
- return CURLE_OUT_OF_MEMORY;
- plainlen += plen;
- if(plainlen < plen)
- return CURLE_OUT_OF_MEMORY;
- plainlen += 2;
- if(plainlen < 2)
+ /* Compute binary message length. Check for overflows. */
+ if((ulen > SIZE_T_MAX/2) || (plen > (SIZE_T_MAX/2 - 2)))
return CURLE_OUT_OF_MEMORY;
+ plainlen = 2 * ulen + plen + 2;
plainauth = malloc(plainlen);
if(!plainauth)
}
if(!krb5->credentials) {
- /* Do we have credientials to use or are we using single sign-on? */
+ /* Do we have credentials to use or are we using single sign-on? */
if(userp && *userp) {
/* Populate our identity structure */
result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity);
krb5->p_identity = NULL;
/* Allocate our credentials handle */
- krb5->credentials = malloc(sizeof(CredHandle));
+ krb5->credentials = calloc(1, sizeof(CredHandle));
if(!krb5->credentials)
return CURLE_OUT_OF_MEMORY;
- memset(krb5->credentials, 0, sizeof(CredHandle));
-
/* Acquire our credentials handle */
status = s_pSecFn->AcquireCredentialsHandle(NULL,
(TCHAR *)
return CURLE_LOGIN_DENIED;
/* Allocate our new context handle */
- krb5->context = malloc(sizeof(CtxtHandle));
+ krb5->context = calloc(1, sizeof(CtxtHandle));
if(!krb5->context)
return CURLE_OUT_OF_MEMORY;
-
- memset(krb5->context, 0, sizeof(CtxtHandle));
}
if(chlg64 && *chlg64) {
/* "NTLMSSP" signature is always in ASCII regardless of the platform */
#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
-#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
-#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
- (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
+#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff))
+#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \
+ ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff))
#if DEBUG_ME
# define DEBUG_OUT(x) x
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
* passdwp [in] - The user's password.
+ * service [in] - The service type such as http, smtp, pop or imap.
+ * host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
+ const char *service,
+ const char *hostname,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
{
domain are empty */
(void)userp;
(void)passwdp;
+ (void)service,
+ (void)hostname,
/* Clean up any former leftovers and initialise to defaults */
Curl_auth_ntlm_cleanup(ntlm);
-#ifndef HEADER_CURL_NTLM_H
-#define HEADER_CURL_NTLM_H
+#ifndef HEADER_VAUTH_NTLM_H
+#define HEADER_VAUTH_NTLM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#endif /* USE_NTLM */
-#endif /* HEADER_CURL_NTLM_H */
+#endif /* HEADER_VAUTH_NTLM_H */
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
* passdwp [in] - The user's password.
+ * service [in] - The service type such as http, smtp, pop or imap.
+ * host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
+ const char *service,
+ const char *host,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
{
ntlm->p_identity = NULL;
/* Allocate our credentials handle */
- ntlm->credentials = malloc(sizeof(CredHandle));
+ ntlm->credentials = calloc(1, sizeof(CredHandle));
if(!ntlm->credentials)
return CURLE_OUT_OF_MEMORY;
- memset(ntlm->credentials, 0, sizeof(CredHandle));
-
/* Acquire our credentials handle */
status = s_pSecFn->AcquireCredentialsHandle(NULL,
(TCHAR *) TEXT(SP_NAME_NTLM),
return CURLE_LOGIN_DENIED;
/* Allocate our new context handle */
- ntlm->context = malloc(sizeof(CtxtHandle));
+ ntlm->context = calloc(1, sizeof(CtxtHandle));
if(!ntlm->context)
return CURLE_OUT_OF_MEMORY;
- memset(ntlm->context, 0, sizeof(CtxtHandle));
+ ntlm->spn = Curl_auth_build_spn(service, host, NULL);
+ if(!ntlm->spn)
+ return CURLE_OUT_OF_MEMORY;
/* Setup the type-1 "output" security buffer */
type_1_desc.ulVersion = SECBUFFER_VERSION;
/* Generate our type-1 message */
status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL,
- (TCHAR *) TEXT(""),
+ ntlm->spn,
0, 0, SECURITY_NETWORK_DREP,
NULL, 0,
ntlm->context, &type_1_desc,
/* Generate our type-3 message */
status = s_pSecFn->InitializeSecurityContext(ntlm->credentials,
ntlm->context,
- (TCHAR *) TEXT(""),
+ ntlm->spn,
0, 0, SECURITY_NETWORK_DREP,
&type_2_desc,
0, ntlm->context,
/* Reset any variables */
ntlm->token_max = 0;
+
+ Curl_safefree(ntlm->spn);
}
#endif /* USE_WINDOWS_SSPI && USE_NTLM */
}
if(!nego->credentials) {
- /* Do we have credientials to use or are we using single sign-on? */
+ /* Do we have credentials to use or are we using single sign-on? */
if(user && *user) {
/* Populate our identity structure */
result = Curl_create_sspi_identity(user, password, &nego->identity);
nego->p_identity = NULL;
/* Allocate our credentials handle */
- nego->credentials = malloc(sizeof(CredHandle));
+ nego->credentials = calloc(1, sizeof(CredHandle));
if(!nego->credentials)
return CURLE_OUT_OF_MEMORY;
- memset(nego->credentials, 0, sizeof(CredHandle));
-
/* Acquire our credentials handle */
nego->status =
s_pSecFn->AcquireCredentialsHandle(NULL,
return CURLE_LOGIN_DENIED;
/* Allocate our new context handle */
- nego->context = malloc(sizeof(CtxtHandle));
+ nego->context = calloc(1, sizeof(CtxtHandle));
if(!nego->context)
return CURLE_OUT_OF_MEMORY;
-
- memset(nego->context, 0, sizeof(CtxtHandle));
}
if(chlg64 && *chlg64) {
* User@Domain (User Principal Name)
*
* Note: The user name may be empty when using a GSS-API library or Windows SSPI
-* as the user and domain are either obtained from the credientals cache when
-* using GSS-API or via the currently logged in user's credientals when using
+* as the user and domain are either obtained from the credentials cache when
+* using GSS-API or via the currently logged in user's credentials when using
* Windows SSPI.
*
* Parameters:
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
else
- /* User and domain are obtained from the GSS-API credientials cache or the
+ /* User and domain are obtained from the GSS-API credentials cache or the
currently logged in user from Windows */
valid = TRUE;
#endif
CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
+ const char *service,
+ const char *host,
struct ntlmdata *ntlm,
char **outptr,
size_t *outlen);
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#ifdef USE_SSL
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
version_info.ssl_version = ssl_buffer;
- if(Curl_ssl->support_https_proxy)
+ if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
version_info.features |= CURL_VERSION_HTTPS_PROXY;
else
version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
const struct Curl_ssl Curl_ssl_axtls = {
{ CURLSSLBACKEND_AXTLS, "axtls" }, /* info */
-
- 0, /* have_ca_path */
- 0, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
-
+ 0, /* no fancy stuff */
sizeof(struct ssl_backend_data),
/*
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
use_sni(TRUE);
break;
case CURL_SSLVERSION_TLSv1_0:
+#ifdef WOLFSSL_ALLOW_TLSV10
req_method = TLSv1_client_method();
use_sni(TRUE);
+#else
+ failf(data, "CyaSSL does not support TLS 1.0");
+ return CURLE_NOT_BUILT_IN;
+#endif
break;
case CURL_SSLVERSION_TLSv1_1:
req_method = TLSv1_1_client_method();
use_sni(TRUE);
break;
case CURL_SSLVERSION_TLSv1_3:
+#ifdef WOLFSSL_TLS13
+ req_method = wolfTLSv1_3_client_method();
+ use_sni(TRUE);
+ break;
+#else
failf(data, "CyaSSL: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
+#endif
case CURL_SSLVERSION_SSLv3:
#ifdef WOLFSSL_ALLOW_SSLV3
req_method = SSLv3_client_method();
*/
if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) &&
(wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) &&
- (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)) {
+ (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)
+#ifdef WOLFSSL_TLS13
+ && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_3) != 1)
+#endif
+ ) {
failf(data, "SSL: couldn't set the minimum protocol version");
return CURLE_SSL_CONNECT_ERROR;
}
return CURLE_OK;
}
-static void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum /* output */,
size_t unused)
InitSha256(&SHA256pw);
Sha256Update(&SHA256pw, tmp, (word32)tmplen);
Sha256Final(&SHA256pw, sha256sum);
+ return CURLE_OK;
}
static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_cyassl = {
{ CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
- 0, /* have_ca_path */
- 0, /* have_certinfo */
#ifdef KEEP_PEER_CERT
- 1, /* have_pinnedpubkey */
-#else
- 0, /* have_pinnedpubkey */
+ SSLSUPP_PINNEDPUBKEY |
#endif
- 1, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_SSL_CTX,
sizeof(struct ssl_backend_data),
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
raise linker errors when used on that cat for some reason. */
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
- NULL, NULL, &status)) {
+ NULL, NULL, &status)) {
+ CFArrayRef items = NULL;
+
+ /* On iOS SecPKCS12Import will never add the client certificate to the
+ * Keychain.
+ *
+ * It gives us back a SecIdentityRef that we can use directly. */
+#if CURL_BUILD_IOS
const void *cKeys[] = {kSecImportExportPassphrase};
const void *cValues[] = {password};
CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
password ? 1L : 0L, NULL, NULL);
- CFArrayRef items = NULL;
- /* Here we go: */
- status = SecPKCS12Import(pkcs_data, options, &items);
- if(status == errSecSuccess && items && CFArrayGetCount(items)) {
- CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
- const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
- kSecImportItemIdentity);
+ if(options != NULL) {
+ status = SecPKCS12Import(pkcs_data, options, &items);
+ CFRelease(options);
+ }
+
+
+ /* On macOS SecPKCS12Import will always add the client certificate to
+ * the Keychain.
+ *
+ * As this doesn't match iOS, and apps may not want to see their client
+ * certificate saved in the the user's keychain, we use SecItemImport
+ * with a NULL keychain to avoid importing it.
+ *
+ * This returns a SecCertificateRef from which we can construct a
+ * SecIdentityRef.
+ */
+#elif CURL_BUILD_MAC_10_7
+ SecItemImportExportKeyParameters keyParams;
+ SecExternalFormat inputFormat = kSecFormatPKCS12;
+ SecExternalItemType inputType = kSecItemTypeCertificate;
- /* Retain the identity; we don't care about any other data... */
- CFRetain(temp_identity);
- *out_cert_and_key = (SecIdentityRef)temp_identity;
+ memset(&keyParams, 0x00, sizeof(keyParams));
+ keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+ keyParams.passphrase = password;
+
+ status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType,
+ 0, &keyParams, NULL, &items);
+#endif
+
+
+ /* Extract the SecIdentityRef */
+ if(status == errSecSuccess && items && CFArrayGetCount(items)) {
+ CFIndex i, count;
+ count = CFArrayGetCount(items);
+
+ for(i = 0; i < count; i++) {
+ CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i);
+ CFTypeID itemID = CFGetTypeID(item);
+
+ if(itemID == CFDictionaryGetTypeID()) {
+ CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue(
+ (CFDictionaryRef) item,
+ kSecImportItemIdentity);
+ CFRetain(identity);
+ *out_cert_and_key = (SecIdentityRef) identity;
+ break;
+ }
+#if CURL_BUILD_MAC_10_7
+ else if(itemID == SecCertificateGetTypeID()) {
+ status = SecIdentityCreateWithCertificate(NULL,
+ (SecCertificateRef) item,
+ out_cert_and_key);
+ break;
+ }
+#endif
+ }
}
if(items)
CFRelease(items);
- CFRelease(options);
CFRelease(pkcs_data);
}
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
#endif /* CURL_BUILD_MAC */
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(SSLCreateContext != NULL) { /* use the newer API if avaialble */
+ if(SSLCreateContext != NULL) { /* use the newer API if available */
if(BACKEND->ssl_ctx)
CFRelease(BACKEND->ssl_ctx);
BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
return CURLE_OK;
}
-static void Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t sha256len)
{
assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
(void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
+ return CURLE_OK;
}
static bool Curl_darwinssl_false_start(void)
const struct Curl_ssl Curl_ssl_darwinssl = {
{ CURLSSLBACKEND_DARWINSSL, "darwinssl" }, /* info */
- 0, /* have_ca_path */
- 0, /* have_certinfo */
#ifdef DARWIN_SSL_PINNEDPUBKEY
- 1, /* have_pinnedpubkey */
+ SSLSUPP_PINNEDPUBKEY,
#else
- 0, /* have_pinnedpubkey */
+ 0,
#endif /* DARWIN_SSL_PINNEDPUBKEY */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
sizeof(struct ssl_backend_data),
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
const struct Curl_ssl Curl_ssl_gskit = {
{ CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
- 0, /* have_ca_path */
- 1, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- /* TODO: convert to 1 and fix test #1014 (if need) */
- 0, /* support_https_proxy */
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
/* The last #include file should be: */
#include "memdebug.h"
-#ifndef GNUTLS_POINTER_TO_SOCKET_CAST
-#define GNUTLS_POINTER_TO_SOCKET_CAST(p) \
- ((curl_socket_t) ((char *)(p) - (char *)NULL))
-#endif
-#ifndef GNUTLS_SOCKET_TO_POINTER_CAST
-#define GNUTLS_SOCKET_TO_POINTER_CAST(s) \
- ((void *) ((char *)NULL + (s)))
-#endif
-
/* Enable GnuTLS debugging by defining GTLSDEBUG */
/*#define GTLSDEBUG */
static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
{
- ssize_t ret = swrite(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
+ curl_socket_t sock = *(curl_socket_t *)s;
+ ssize_t ret = swrite(sock, buf, len);
#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
if(ret < 0)
gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
{
- ssize_t ret = sread(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
+ curl_socket_t sock = *(curl_socket_t *)s;
+ ssize_t ret = sread(sock, buf, len);
#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
if(ret < 0)
gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
}
else {
/* file descriptor for the socket */
- transport_ptr = GNUTLS_SOCKET_TO_POINTER_CAST(conn->sock[sockindex]);
+ transport_ptr = &conn->sock[sockindex];
gnutls_transport_push = Curl_gtls_push;
gnutls_transport_pull = Curl_gtls_pull;
}
return CURLE_OK;
}
-static void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t sha256len)
memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
gcry_md_close(SHA256pw);
#endif
+ return CURLE_OK;
}
static bool Curl_gtls_cert_status_request(void)
const struct Curl_ssl Curl_ssl_gnutls = {
{ CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 1, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
static size_t Curl_mbedtls_version(char *buffer, size_t size)
{
unsigned int version = mbedtls_version_get_number();
- return snprintf(buffer, size, "mbedTLS/%d.%d.%d", version>>24,
+ return snprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
(version>>16)&0xff, (version>>8)&0xff);
}
return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0;
}
-static void Curl_mbedtls_sha256sum(const unsigned char *input,
+static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input,
size_t inputlen,
unsigned char *sha256sum,
size_t sha256len UNUSED_PARAM)
{
(void)sha256len;
+#if MBEDTLS_VERSION_NUMBER < 0x02070000
mbedtls_sha256(input, inputlen, sha256sum, 0);
+#else
+ /* returns 0 on success, otherwise failure */
+ if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#endif
+ return CURLE_OK;
}
static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_mbedtls = {
{ CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
- 1, /* have_ca_path */
- 0, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 1, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_SSL_CTX,
sizeof(struct ssl_backend_data),
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
}
- obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
+ /* PK11_CreateManagedGenericObject() was introduced in NSS 3.34 because
+ * PK11_DestroyGenericObject() does not release resources allocated by
+ * PK11_CreateGenericObject() early enough. */
+ obj =
+#ifdef HAVE_PK11_CREATEMANAGEDGENERICOBJECT
+ PK11_CreateManagedGenericObject
+#else
+ PK11_CreateGenericObject
+#endif
+ (slot, attrs, attr_cnt, PR_FALSE);
+
PK11_FreeSlot(slot);
if(!obj)
return result;
return CURLE_OK;
}
-static void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t sha256len)
PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
PK11_DestroyContext(SHA256pw, PR_TRUE);
+
+ return CURLE_OK;
}
static bool Curl_nss_cert_status_request(void)
const struct Curl_ssl Curl_ssl_nss = {
{ CURLSSLBACKEND_NSS, "nss" }, /* info */
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 1, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \
- !defined(LIBRESSL_VERSION_NUMBER)
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */
#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */
#define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */
#define CONST_EXTS const
#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1
+
+/* funny typecast define due to difference in API */
+#ifdef LIBRESSL_VERSION_NUMBER
+#define ARG2_X509_signature_print (X509_ALGOR *)
+#else
+#define ARG2_X509_signature_print
+#endif
+
#else
/* For OpenSSL before 1.1.0 */
#define ASN1_STRING_get0_data(x) ASN1_STRING_data(x)
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \
- !defined(LIBRESSL_VERSION_NUMBER)
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define HAVE_X509_GET0_SIGNATURE 1
#endif
* Whether SSL_CTX_set_keylog_callback is available.
* OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
* BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
- * LibreSSL: unsupported in at least 2.5.1 (explicitly check for it since it
+ * LibreSSL: unsupported in at least 2.7.2 (explicitly check for it since it
* lies and pretends to be OpenSSL 2.0.0).
*/
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
if(!session || !keylog_file_fp)
return;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
/* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that
* we have a valid SSL context if we have a non-NULL session. */
SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
case SSL_FILETYPE_PKCS12:
{
- FILE *f;
- PKCS12 *p12;
+ BIO *fp = NULL;
+ PKCS12 *p12 = NULL;
EVP_PKEY *pri;
STACK_OF(X509) *ca = NULL;
- f = fopen(cert_file, "rb");
- if(!f) {
+ fp = BIO_new(BIO_s_file());
+ if(fp == NULL) {
+ failf(data,
+ "BIO_new return NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ return 0;
+ }
+
+ if(BIO_read_filename(fp, cert_file) <= 0) {
failf(data, "could not open PKCS12 file '%s'", cert_file);
+ BIO_free(fp);
return 0;
}
- p12 = d2i_PKCS12_fp(f, NULL);
- fclose(f);
+ p12 = d2i_PKCS12_bio(fp, NULL);
+ BIO_free(fp);
if(!p12) {
failf(data, "error reading PKCS12 file '%s'", cert_file);
/* ====================================================== */
+/*
+ * Match subjectAltName against the host name. This requires a conversion
+ * in CURL_DOES_CONVERSIONS builds.
+ */
+static bool subj_alt_hostcheck(struct Curl_easy *data,
+ const char *match_pattern, const char *hostname,
+ const char *dispname)
+#ifdef CURL_DOES_CONVERSIONS
+{
+ bool res = FALSE;
+
+ /* Curl_cert_hostcheck uses host encoding, but we get ASCII from
+ OpenSSl.
+ */
+ char *match_pattern2 = strdup(match_pattern);
+
+ if(match_pattern2) {
+ if(Curl_convert_from_network(data, match_pattern2,
+ strlen(match_pattern2)) == CURLE_OK) {
+ if(Curl_cert_hostcheck(match_pattern2, hostname)) {
+ res = TRUE;
+ infof(data,
+ " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
+ dispname, match_pattern2);
+ }
+ }
+ free(match_pattern2);
+ }
+ else {
+ failf(data,
+ "SSL: out of memory when allocating temporary for subjectAltName");
+ }
+ return res;
+}
+#else
+{
+ if(Curl_cert_hostcheck(match_pattern, hostname)) {
+ infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
+ dispname, match_pattern);
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+
/* Quote from RFC2818 section 3.1 "Server Identity"
if((altlen == strlen(altptr)) &&
/* if this isn't true, there was an embedded zero in the name
string and we cannot match it. */
- Curl_cert_hostcheck(altptr, hostname)) {
+ subj_alt_hostcheck(data, altptr, hostname, dispname)) {
dnsmatched = TRUE;
- infof(data,
- " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
- dispname, altptr);
}
break;
case SSL3_MT_CERTIFICATE_STATUS:
return "Certificate Status";
#endif
+#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS
+ case SSL3_MT_ENCRYPTED_EXTENSIONS:
+ return "Encrypted Extensions";
+#endif
+#ifdef SSL3_MT_END_OF_EARLY_DATA
+ case SSL3_MT_END_OF_EARLY_DATA:
+ return "End of early data";
+#endif
+#ifdef SSL3_MT_KEY_UPDATE
+ case SSL3_MT_KEY_UPDATE:
+ return "Key update";
+#endif
+#ifdef SSL3_MT_NEXT_PROTO
+ case SSL3_MT_NEXT_PROTO:
+ return "Next protocol";
+#endif
+#ifdef SSL3_MT_MESSAGE_HASH
+ case SSL3_MT_MESSAGE_HASH:
+ return "Message hash";
+#endif
}
}
return "Unknown";
}
-static const char *tls_rt_type(int type)
+static const char *tls_rt_type(int type, const void *buf, size_t buflen)
{
+ (void)buf;
+ (void)buflen;
+#ifdef SSL3_RT_INNER_CONTENT_TYPE
+ if(type == SSL3_RT_INNER_CONTENT_TYPE && buf && buflen >= 1)
+ type = *(unsigned char *)buf;
+#endif
+
switch(type) {
#ifdef SSL3_RT_HEADER
case SSL3_RT_HEADER:
void *userp)
{
struct Curl_easy *data;
- const char *msg_name, *tls_rt_name;
- char ssl_buf[1024];
char unknown[32];
- int msg_type, txt_len;
const char *verstr = NULL;
struct connectdata *conn = userp;
}
if(ssl_ver) {
+ const char *msg_name, *tls_rt_name;
+ char ssl_buf[1024];
+ int msg_type, txt_len;
+
/* the info given when the version is zero is not that useful for us */
ssl_ver >>= 8; /* check the upper 8 bits only below */
* is at 'buf[0]'.
*/
if(ssl_ver == SSL3_VERSION_MAJOR && content_type)
- tls_rt_name = tls_rt_type(content_type);
+ tls_rt_name = tls_rt_type(content_type, buf, len);
else
tls_rt_name = "";
- msg_type = *(char *)buf;
- msg_name = ssl_msg_type(ssl_ver, msg_type);
+#ifdef SSL3_RT_INNER_CONTENT_TYPE
+ if(content_type == SSL3_RT_INNER_CONTENT_TYPE) {
+ msg_type = 0;
+ msg_name = "[no content]";
+ }
+ else
+#endif
+ {
+ msg_type = *(char *)buf;
+ msg_name = ssl_msg_type(ssl_ver, msg_type);
+ }
txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
verstr, direction?"OUT":"IN",
tls_rt_name, msg_name, msg_type);
- Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+ if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
+ Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+ }
}
Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
/* it will be handled later with the context options */
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
req_method = TLS_client_method();
#else
req_method = SSLv23_client_method();
ASN1_STRING *a = ASN1_STRING_new();
if(a) {
X509_get0_signature(&psig, &palg, x);
- X509_signature_print(mem, palg, a);
+ X509_signature_print(mem, ARG2_X509_signature_print palg, a);
ASN1_STRING_free(a);
if(palg) {
long lerr, len;
struct Curl_easy *data = conn->data;
X509 *issuer;
- FILE *fp;
+ BIO *fp = NULL;
+ char error_buffer[256]="";
char buffer[2048];
const char *ptr;
long * const certverifyresult = SSL_IS_PROXY() ?
/* we've been asked to gather certificate info! */
(void)get_cert_chain(conn, connssl);
+ fp = BIO_new(BIO_s_file());
+ if(fp == NULL) {
+ failf(data,
+ "BIO_new return NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ BIO_free(mem);
+ return 0;
+ }
+
BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
if(!BACKEND->server_cert) {
+ BIO_free(fp);
BIO_free(mem);
if(!strict)
return CURLE_OK;
if(SSL_CONN_CONFIG(verifyhost)) {
result = verifyhost(conn, BACKEND->server_cert);
if(result) {
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return result;
/* e.g. match issuer name with provided issuer certificate */
if(SSL_SET_OPTION(issuercert)) {
- fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT);
- if(!fp) {
+ if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
SSL_SET_OPTION(issuercert));
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
- issuer = PEM_read_X509(fp, NULL, ZERO_NULL, NULL);
+ issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL);
if(!issuer) {
if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)",
SSL_SET_OPTION(issuercert));
- X509_free(BACKEND->server_cert);
+ BIO_free(fp);
X509_free(issuer);
- fclose(fp);
+ X509_free(BACKEND->server_cert);
+ BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
- fclose(fp);
-
if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) {
if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)",
SSL_SET_OPTION(issuercert));
- X509_free(BACKEND->server_cert);
+ BIO_free(fp);
X509_free(issuer);
+ X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
if(SSL_CONN_CONFIG(verifystatus)) {
result = verifystatus(conn, connssl);
if(result) {
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return result;
failf(data, "SSL: public key does not match pinned public key!");
}
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
connssl->connecting_state = ssl_connect_done;
unsigned char *md5sum /* output */,
size_t unused)
{
- MD5_CTX MD5pw;
- (void)unused;
- MD5_Init(&MD5pw);
- MD5_Update(&MD5pw, tmp, tmplen);
- MD5_Final(md5sum, &MD5pw);
+ EVP_MD_CTX *mdctx;
+ unsigned int len = 0;
+ (void) unused;
+
+ mdctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
+ EVP_DigestUpdate(mdctx, tmp, tmplen);
+ EVP_DigestFinal_ex(mdctx, md5sum, &len);
+ EVP_MD_CTX_destroy(mdctx);
return CURLE_OK;
}
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-static void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum /* output */,
size_t unused)
{
- SHA256_CTX SHA256pw;
- (void)unused;
- SHA256_Init(&SHA256pw);
- SHA256_Update(&SHA256pw, tmp, tmplen);
- SHA256_Final(sha256sum, &SHA256pw);
+ EVP_MD_CTX *mdctx;
+ unsigned int len = 0;
+ (void) unused;
+
+ mdctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
+ EVP_DigestUpdate(mdctx, tmp, tmplen);
+ EVP_DigestFinal_ex(mdctx, sha256sum, &len);
+ EVP_MD_CTX_destroy(mdctx);
+ return CURLE_OK;
}
#endif
const struct Curl_ssl Curl_ssl_openssl = {
{ CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 1, /* have_ssl_ctx */
- 1, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_SSL_CTX |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
- our_ssl_sessionid = malloc(sizeof(ssl_session));
+ our_ssl_sessionid = calloc(1, sizeof(ssl_session));
if(!our_ssl_sessionid)
return CURLE_OUT_OF_MEMORY;
- memset(our_ssl_sessionid, 0, sizeof(ssl_session));
-
ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
if(ret) {
failf(data, "ssl_get_session returned -0x%x", -ret);
return ssl_get_bytes_avail(&BACKEND->ssl) != 0;
}
-static void Curl_polarssl_sha256sum(const unsigned char *input,
+static CURLcode Curl_polarssl_sha256sum(const unsigned char *input,
size_t inputlen,
unsigned char *sha256sum,
size_t sha256len UNUSED_PARAM)
{
(void)sha256len;
sha256(input, inputlen, sha256sum, 0);
+ return CURLE_OK;
}
static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_polarssl = {
{ CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */
- 1, /* have_ca_path */
- 0, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
*
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#ifdef USE_SCHANNEL
+#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+
#ifndef USE_WINDOWS_SSPI
# error "Can't compile SCHANNEL support without SSPI."
#endif
-#include <schnlsp.h>
-#include <schannel.h>
-#include "curl_sspi.h"
#include "schannel.h"
#include "vtls.h"
#include "sendf.h"
#include "x509asn1.h"
#include "curl_printf.h"
#include "system_win32.h"
-#include "hostcheck.h"
/* The last #include file should be: */
#include "curl_memory.h"
#endif
#endif
+#ifdef UNICODE
+#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
+#else
+#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_A
+#endif
+
#ifndef SP_PROT_SSL2_CLIENT
#define SP_PROT_SSL2_CLIENT 0x00000008
#endif
#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024
+#define CERT_THUMBPRINT_STR_LEN 40
+#define CERT_THUMBPRINT_DATA_LEN 20
+
/* Uncomment to force verbose output
* #define infof(x, y, ...) printf(y, __VA_ARGS__)
* #define failf(x, y, ...) printf(y, __VA_ARGS__)
*/
-/* Structs to store Schannel handles */
-struct curl_schannel_cred {
- CredHandle cred_handle;
- TimeStamp time_stamp;
- int refcount;
-};
-
-struct curl_schannel_ctxt {
- CtxtHandle ctxt_handle;
- TimeStamp time_stamp;
-};
-
-struct ssl_backend_data {
- struct curl_schannel_cred *cred;
- struct curl_schannel_ctxt *ctxt;
- SecPkgContext_StreamSizes stream_sizes;
- size_t encdata_length, decdata_length;
- size_t encdata_offset, decdata_offset;
- unsigned char *encdata_buffer, *decdata_buffer;
- /* encdata_is_incomplete: if encdata contains only a partial record that
- can't be decrypted without another Curl_read_plain (that is, status is
- SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
- more bytes into encdata then set this back to false. */
- bool encdata_is_incomplete;
- unsigned long req_flags, ret_flags;
- CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
- bool recv_sspi_close_notify; /* true if connection closed by close_notify */
- bool recv_connection_closed; /* true if connection closed, regardless how */
- bool use_alpn; /* true if ALPN is used for this connection */
-};
+#ifndef CALG_SHA_256
+# define CALG_SHA_256 0x0000800c
+#endif
#define BACKEND connssl->backend
static Curl_recv schannel_recv;
static Curl_send schannel_send;
-#ifdef _WIN32_WCE
-static CURLcode verify_certificate(struct connectdata *conn, int sockindex);
-#endif
+static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+ const char *pinnedpubkey);
static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
void *BufDataPtr, unsigned long BufByteSize)
}
static CURLcode
+get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
+ TCHAR **thumbprint)
+{
+ TCHAR *sep;
+ size_t store_name_len;
+
+ sep = _tcschr(path, TEXT('\\'));
+ if(sep == NULL)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ store_name_len = sep - path;
+
+ if(_tcsnccmp(path, TEXT("CurrentUser"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_CURRENT_USER;
+ else if(_tcsnccmp(path, TEXT("LocalMachine"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE;
+ else if(_tcsnccmp(path, TEXT("CurrentService"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE;
+ else if(_tcsnccmp(path, TEXT("Services"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_SERVICES;
+ else if(_tcsnccmp(path, TEXT("Users"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_USERS;
+ else if(_tcsnccmp(path, TEXT("CurrentUserGroupPolicy"),
+ store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY;
+ else if(_tcsnccmp(path, TEXT("LocalMachineGroupPolicy"),
+ store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY;
+ else if(_tcsnccmp(path, TEXT("LocalMachineEnterprise"),
+ store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
+ else
+ return CURLE_SSL_CONNECT_ERROR;
+
+ *store_path = sep + 1;
+
+ sep = _tcschr(*store_path, TEXT('\\'));
+ if(sep == NULL)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ *sep = 0;
+
+ *thumbprint = sep + 1;
+ if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ return CURLE_OK;
+}
+
+static CURLcode
schannel_connect_step1(struct connectdata *conn, int sockindex)
{
ssize_t written = -1;
unsigned char alpn_buffer[128];
#endif
SCHANNEL_CRED schannel_cred;
+ PCCERT_CONTEXT client_certs[1] = { NULL };
SECURITY_STATUS sspi_status = SEC_E_OK;
struct curl_schannel_cred *old_cred = NULL;
struct in_addr addr;
BACKEND->use_alpn = false;
#endif
+#ifdef _WIN32_WCE
+ /* certificate validation on CE doesn't seem to work right; we'll
+ * do it following a more manual process. */
+ BACKEND->use_manual_cred_validation = true;
+#else
+ if(SSL_CONN_CONFIG(CAfile)) {
+ if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+ BACKEND->use_manual_cred_validation = true;
+ }
+ else {
+ failf(data, "schannel: this version of Windows is too old to support "
+ "certificate verification via CA bundle file.");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else
+ BACKEND->use_manual_cred_validation = false;
+#endif
+
BACKEND->cred = NULL;
/* check for an existing re-usable credential handle */
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
if(conn->ssl_config.verifypeer) {
-#ifdef _WIN32_WCE
- /* certificate validation on CE doesn't seem to work right; we'll
- do it following a more manual process. */
- schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
- SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
- SCH_CRED_IGNORE_REVOCATION_OFFLINE;
-#else
- schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+ if(BACKEND->use_manual_cred_validation)
+ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
+ else
+ schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+
/* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
- if(data->set.ssl.no_revoke)
+ if(data->set.ssl.no_revoke) {
schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
- SCH_CRED_IGNORE_REVOCATION_OFFLINE;
- else
- schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
-#endif
- if(data->set.ssl.no_revoke)
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+
infof(data, "schannel: disabled server certificate revocation "
"checks\n");
- else
+ }
+ else {
+ schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
infof(data, "schannel: checking server certificate revocation\n");
+ }
}
else {
schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
return CURLE_SSL_CONNECT_ERROR;
}
+ /* client certificate */
+ if(data->set.ssl.cert) {
+ DWORD cert_store_name;
+ TCHAR *cert_store_path;
+ TCHAR *cert_thumbprint_str;
+ CRYPT_HASH_BLOB cert_thumbprint;
+ BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN];
+ HCERTSTORE cert_store;
+
+ TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert);
+ if(!cert_path)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = get_cert_location(cert_path, &cert_store_name,
+ &cert_store_path, &cert_thumbprint_str);
+ if(result != CURLE_OK) {
+ Curl_unicodefree(cert_path);
+ return result;
+ }
+
+ cert_store = CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
+ (HCRYPTPROV)NULL,
+ cert_store_name, cert_store_path);
+ if(!cert_store) {
+ Curl_unicodefree(cert_path);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ cert_thumbprint.pbData = cert_thumbprint_data;
+ cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN;
+
+ if(!CryptStringToBinary(cert_thumbprint_str, CERT_THUMBPRINT_STR_LEN,
+ CRYPT_STRING_HEX,
+ cert_thumbprint_data, &cert_thumbprint.cbData,
+ NULL, NULL)) {
+ Curl_unicodefree(cert_path);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ client_certs[0] = CertFindCertificateInStore(
+ cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
+ CERT_FIND_HASH, &cert_thumbprint, NULL);
+
+ Curl_unicodefree(cert_path);
+
+ if(client_certs[0]) {
+ schannel_cred.cCreds = 1;
+ schannel_cred.paCred = client_certs;
+ }
+
+ CertCloseStore(cert_store, 0);
+ }
+
/* allocate memory for the re-usable credential handle */
BACKEND->cred = (struct curl_schannel_cred *)
- malloc(sizeof(struct curl_schannel_cred));
+ calloc(1, sizeof(struct curl_schannel_cred));
if(!BACKEND->cred) {
failf(data, "schannel: unable to allocate memory");
+
+ if(client_certs[0])
+ CertFreeCertificateContext(client_certs[0]);
+
return CURLE_OUT_OF_MEMORY;
}
- memset(BACKEND->cred, 0, sizeof(struct curl_schannel_cred));
BACKEND->cred->refcount = 1;
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
&BACKEND->cred->cred_handle,
&BACKEND->cred->time_stamp);
+ if(client_certs[0])
+ CertFreeCertificateContext(client_certs[0]);
+
if(sspi_status != SEC_E_OK) {
if(sspi_status == SEC_E_WRONG_PRINCIPAL)
failf(data, "schannel: SNI or certificate check failed: %s",
InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
}
- else
- {
+ else {
InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
}
/* allocate memory for the security context handle */
BACKEND->ctxt = (struct curl_schannel_ctxt *)
- malloc(sizeof(struct curl_schannel_ctxt));
+ calloc(1, sizeof(struct curl_schannel_ctxt));
if(!BACKEND->ctxt) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
- memset(BACKEND->ctxt, 0, sizeof(struct curl_schannel_ctxt));
host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
bool doread;
char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+ const char *pubkey_ptr;
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
infof(data, "schannel: SSL/TLS handshake complete\n");
}
-#ifdef _WIN32_WCE
- /* Windows CE doesn't do any server certificate validation.
- We have to do it manually. */
- if(conn->ssl_config.verifypeer)
+ pubkey_ptr = SSL_IS_PROXY() ?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ if(pubkey_ptr) {
+ result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr);
+ if(result) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ return result;
+ }
+ }
+
+ if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
return verify_certificate(conn, sockindex);
-#endif
+ }
return CURLE_OK;
}
return CURLE_OK;
}
-#ifdef _WIN32_WCE
-static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+ const char *pinnedpubkey)
{
SECURITY_STATUS status;
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- CURLcode result = CURLE_OK;
CERT_CONTEXT *pCertContextServer = NULL;
- const CERT_CHAIN_CONTEXT *pChainContext = NULL;
- const char * const conn_hostname = SSL_IS_PROXY() ?
- conn->http_proxy.host.name :
- conn->host.name;
+ const char *x509_der;
+ DWORD x509_der_len;
+ curl_X509certificate x509_parsed;
+ curl_asn1Element *pubkey;
- status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
- SECPKG_ATTR_REMOTE_CERT_CONTEXT,
- &pCertContextServer);
+ /* Result is returned to caller */
+ CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
- failf(data, "schannel: Failed to read remote certificate context: %s",
- Curl_sspi_strerror(conn, status));
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+ /* if a path wasn't specified, don't pin */
+ if(!pinnedpubkey)
+ return CURLE_OK;
- if(result == CURLE_OK) {
- CERT_CHAIN_PARA ChainPara;
- memset(&ChainPara, 0, sizeof(ChainPara));
- ChainPara.cbSize = sizeof(ChainPara);
-
- if(!CertGetCertificateChain(NULL,
- pCertContextServer,
- NULL,
- pCertContextServer->hCertStore,
- &ChainPara,
- (data->set.ssl.no_revoke ? 0 :
- CERT_CHAIN_REVOCATION_CHECK_CHAIN),
- NULL,
- &pChainContext)) {
- failf(data, "schannel: CertGetCertificateChain failed: %s",
- Curl_sspi_strerror(conn, GetLastError()));
- pChainContext = NULL;
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+ do {
+ status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &pCertContextServer);
- if(result == CURLE_OK) {
- CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
- DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
- dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
- if(dwTrustErrorMask) {
- if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_REVOKED");
- else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_PARTIAL_CHAIN");
- else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_UNTRUSTED_ROOT");
- else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_NOT_TIME_VALID");
- else
- failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
- dwTrustErrorMask);
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+ if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ failf(data, "schannel: Failed to read remote certificate context: %s",
+ Curl_sspi_strerror(conn, status));
+ break; /* failed */
}
- }
- if(result == CURLE_OK) {
- if(conn->ssl_config.verifyhost) {
- TCHAR cert_hostname_buff[256];
- DWORD len;
-
- /* TODO: Fix this for certificates with multiple alternative names.
- Right now we're only asking for the first preferred alternative name.
- Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG
- (if WinCE supports that?) and run this section in a loop for each.
- https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx
- curl: (51) schannel: CertGetNameString() certificate hostname
- (.google.com) did not match connection (google.com)
- */
- len = CertGetNameString(pCertContextServer,
- CERT_NAME_DNS_TYPE,
- CERT_NAME_DISABLE_IE4_UTF8_FLAG,
- NULL,
- cert_hostname_buff,
- 256);
- if(len > 0) {
- const char *cert_hostname;
-
- /* Comparing the cert name and the connection hostname encoded as UTF-8
- * is acceptable since both values are assumed to use ASCII
- * (or some equivalent) encoding
- */
- cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname_buff);
- if(!cert_hostname) {
- result = CURLE_OUT_OF_MEMORY;
- }
- else{
- int match_result;
-
- match_result = Curl_cert_hostcheck(cert_hostname, conn->host.name);
- if(match_result == CURL_HOST_MATCH) {
- infof(data,
- "schannel: connection hostname (%s) validated "
- "against certificate name (%s)\n",
- conn->host.name,
- cert_hostname);
- result = CURLE_OK;
- }
- else{
- failf(data,
- "schannel: connection hostname (%s) "
- "does not match certificate name (%s)",
- conn->host.name,
- cert_hostname);
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- Curl_unicodefree(cert_hostname);
- }
- }
- else {
- failf(data,
- "schannel: CertGetNameString did not provide any "
- "certificate name information");
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+
+ if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
+ (pCertContextServer->cbCertEncoded > 0)))
+ break;
+
+ x509_der = (const char *)pCertContextServer->pbCertEncoded;
+ x509_der_len = pCertContextServer->cbCertEncoded;
+ memset(&x509_parsed, 0, sizeof x509_parsed);
+ if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
+ break;
+
+ pubkey = &x509_parsed.subjectPublicKeyInfo;
+ if(!pubkey->header || pubkey->end <= pubkey->header) {
+ failf(data, "SSL: failed retrieving public key from server certificate");
+ break;
}
- }
- if(pChainContext)
- CertFreeCertificateChain(pChainContext);
+ result = Curl_pin_peer_pubkey(data,
+ pinnedpubkey,
+ (const unsigned char *)pubkey->header,
+ (size_t)(pubkey->end - pubkey->header));
+ if(result) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ }
+ } while(0);
if(pCertContextServer)
CertFreeCertificateContext(pCertContextServer);
return result;
}
-#endif /* _WIN32_WCE */
+
+static void Curl_schannel_checksum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *checksum,
+ size_t checksumlen,
+ DWORD provType,
+ const unsigned int algId)
+{
+ HCRYPTPROV hProv = 0;
+ HCRYPTHASH hHash = 0;
+ DWORD cbHashSize = 0;
+ DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize);
+ DWORD dwChecksumLen = (DWORD)checksumlen;
+
+ /* since this can fail in multiple ways, zero memory first so we never
+ * return old data
+ */
+ memset(checksum, 0, checksumlen);
+
+ if(!CryptAcquireContext(&hProv, NULL, NULL, provType,
+ CRYPT_VERIFYCONTEXT))
+ return; /* failed */
+
+ do {
+ if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
+ break; /* failed */
+
+ if(!CryptHashData(hHash, (const BYTE*)input, (DWORD)inputlen, 0))
+ break; /* failed */
+
+ /* get hash size */
+ if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize,
+ &dwHashSizeLen, 0))
+ break; /* failed */
+
+ /* check hash size */
+ if(checksumlen < cbHashSize)
+ break; /* failed */
+
+ if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0))
+ break; /* failed */
+ } while(0);
+
+ if(hHash)
+ CryptDestroyHash(hHash);
+
+ if(hProv)
+ CryptReleaseContext(hProv, 0);
+}
+
+static CURLcode Curl_schannel_md5sum(unsigned char *input,
+ size_t inputlen,
+ unsigned char *md5sum,
+ size_t md5len)
+{
+ Curl_schannel_checksum(input, inputlen, md5sum, md5len,
+ PROV_RSA_FULL, CALG_MD5);
+ return CURLE_OK;
+}
+
+static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len)
+{
+ Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
+ PROV_RSA_AES, CALG_SHA_256);
+ return CURLE_OK;
+}
static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
const struct Curl_ssl Curl_ssl_schannel = {
{ CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
- 0, /* have_ca_path */
- 1, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
- NULL /* sha256sum */
+ Curl_schannel_md5sum, /* md5sum */
+ Curl_schannel_sha256sum /* sha256sum */
};
#endif /* USE_SCHANNEL */
#ifdef USE_SCHANNEL
+#include <schnlsp.h>
+#include <schannel.h>
+#include "curl_sspi.h"
+
#include "urldata.h"
extern const struct Curl_ssl Curl_ssl_schannel;
+CURLcode verify_certificate(struct connectdata *conn, int sockindex);
+
+/* structs to expose only in schannel.c and schannel_verify.c */
+#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+struct curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ int refcount;
+};
+
+struct curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+
+struct ssl_backend_data {
+ struct curl_schannel_cred *cred;
+ struct curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ /* encdata_is_incomplete: if encdata contains only a partial record that
+ can't be decrypted without another Curl_read_plain (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
+ more bytes into encdata then set this back to false. */
+ bool encdata_is_incomplete;
+ unsigned long req_flags, ret_flags;
+ CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
+ bool recv_sspi_close_notify; /* true if connection closed by close_notify */
+ bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool use_alpn; /* true if ALPN is used for this connection */
+ bool use_manual_cred_validation; /* true if manual cred validation is used */
+};
+#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
+
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_H */
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
+ * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for SChannel-specific certificate verification. This code should
+ * only be invoked by code in schannel.c.
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_SCHANNEL
+
+#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+
+#ifndef USE_WINDOWS_SSPI
+# error "Can't compile SCHANNEL support without SSPI."
+#endif
+
+#include "schannel.h"
+#include "vtls.h"
+#include "sendf.h"
+#include "strerror.h"
+#include "curl_multibyte.h"
+#include "curl_printf.h"
+#include "hostcheck.h"
+#include "system_win32.h"
+
+/* The last #include file should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define BACKEND connssl->backend
+
+#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
+#define BEGIN_CERT "-----BEGIN CERTIFICATE-----\n"
+#define END_CERT "\n-----END CERTIFICATE-----"
+
+typedef struct {
+ DWORD cbSize;
+ HCERTSTORE hRestrictedRoot;
+ HCERTSTORE hRestrictedTrust;
+ HCERTSTORE hRestrictedOther;
+ DWORD cAdditionalStore;
+ HCERTSTORE *rghAdditionalStore;
+ DWORD dwFlags;
+ DWORD dwUrlRetrievalTimeout;
+ DWORD MaximumCachedCertificates;
+ DWORD CycleDetectionModulus;
+ HCERTSTORE hExclusiveRoot;
+ HCERTSTORE hExclusiveTrustedPeople;
+} CERT_CHAIN_ENGINE_CONFIG_WIN7, *PCERT_CHAIN_ENGINE_CONFIG_WIN7;
+
+
+static CURLcode add_certs_to_store(HCERTSTORE trust_store,
+ const char *ca_file,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ struct Curl_easy *data = conn->data;
+ HANDLE ca_file_handle = INVALID_HANDLE_VALUE;
+ LARGE_INTEGER file_size;
+ char *ca_file_buffer = NULL;
+ char *current_ca_file_ptr = NULL;
+ const TCHAR *ca_file_tstr = NULL;
+ size_t ca_file_bufsize = 0;
+ DWORD total_bytes_read = 0;
+ bool more_certs = 0;
+ int num_certs = 0;
+ size_t END_CERT_LEN;
+
+ ca_file_tstr = Curl_convert_UTF8_to_tchar(ca_file);
+ if(!ca_file_tstr) {
+ failf(data,
+ "schannel: invalid path name for CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+
+ /*
+ * Read the CA file completely into memory before parsing it. This
+ * optimizes for the common case where the CA file will be relatively
+ * small ( < 1 MiB ).
+ */
+ ca_file_handle = CreateFile(ca_file_tstr,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if(ca_file_handle == INVALID_HANDLE_VALUE) {
+ failf(data,
+ "schannel: failed to open CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+
+ if(!GetFileSizeEx(ca_file_handle, &file_size)) {
+ failf(data,
+ "schannel: failed to determine size of CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+
+ if(file_size.QuadPart > MAX_CAFILE_SIZE) {
+ failf(data,
+ "schannel: CA file exceeds max size of %u bytes",
+ MAX_CAFILE_SIZE);
+ result = CURLE_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ ca_file_bufsize = (size_t)file_size.QuadPart;
+ ca_file_buffer = (char *)malloc(ca_file_bufsize + 1);
+ if(!ca_file_buffer) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ result = CURLE_OK;
+ while(total_bytes_read < ca_file_bufsize) {
+ DWORD bytes_to_read = (DWORD)(ca_file_bufsize - total_bytes_read);
+ DWORD bytes_read = 0;
+
+ if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read,
+ bytes_to_read, &bytes_read, NULL)) {
+
+ failf(data,
+ "schannel: failed to read from CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+ if(bytes_read == 0) {
+ /* Premature EOF -- adjust the bufsize to the new value */
+ ca_file_bufsize = total_bytes_read;
+ }
+ else {
+ total_bytes_read += bytes_read;
+ }
+ }
+
+ /* Null terminate the buffer */
+ ca_file_buffer[ca_file_bufsize] = '\0';
+
+ if(result != CURLE_OK) {
+ goto cleanup;
+ }
+
+ END_CERT_LEN = strlen(END_CERT);
+
+ more_certs = 1;
+ current_ca_file_ptr = ca_file_buffer;
+ while(more_certs && *current_ca_file_ptr != '\0') {
+ char *begin_cert_ptr = strstr(current_ca_file_ptr, BEGIN_CERT);
+ if(!begin_cert_ptr) {
+ more_certs = 0;
+ }
+ else {
+ char *end_cert_ptr = strstr(begin_cert_ptr, END_CERT);
+ if(!end_cert_ptr) {
+ failf(data,
+ "schannel: CA file '%s' is not correctly formatted",
+ ca_file);
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ CERT_BLOB cert_blob;
+ CERT_CONTEXT *cert_context = NULL;
+ BOOL add_cert_result = FALSE;
+ DWORD actual_content_type = 0;
+ DWORD cert_size = (DWORD)
+ ((end_cert_ptr + END_CERT_LEN) - begin_cert_ptr);
+
+ cert_blob.pbData = (BYTE *)begin_cert_ptr;
+ cert_blob.cbData = cert_size;
+ if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
+ &cert_blob,
+ CERT_QUERY_CONTENT_FLAG_CERT,
+ CERT_QUERY_FORMAT_FLAG_ALL,
+ 0,
+ NULL,
+ &actual_content_type,
+ NULL,
+ NULL,
+ NULL,
+ &cert_context)) {
+
+ failf(data,
+ "schannel: failed to extract certificate from CA file "
+ "'%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ current_ca_file_ptr = begin_cert_ptr + cert_size;
+
+ /* Sanity check that the cert_context object is the right type */
+ if(CERT_QUERY_CONTENT_CERT != actual_content_type) {
+ failf(data,
+ "schannel: unexpected content type '%d' when extracting "
+ "certificate from CA file '%s'",
+ actual_content_type, ca_file);
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ add_cert_result =
+ CertAddCertificateContextToStore(trust_store,
+ cert_context,
+ CERT_STORE_ADD_ALWAYS,
+ NULL);
+ CertFreeCertificateContext(cert_context);
+ if(!add_cert_result) {
+ failf(data,
+ "schannel: failed to add certificate from CA file '%s'"
+ "to certificate store: %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ num_certs++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ if(!num_certs) {
+ infof(data,
+ "schannel: did not add any certificates from CA file '%s'\n",
+ ca_file);
+ }
+ else {
+ infof(data,
+ "schannel: added %d certificate(s) from CA file '%s'\n",
+ num_certs, ca_file);
+ }
+ }
+
+cleanup:
+ if(ca_file_handle != INVALID_HANDLE_VALUE) {
+ CloseHandle(ca_file_handle);
+ }
+ Curl_safefree(ca_file_buffer);
+ Curl_unicodefree(ca_file_tstr);
+
+ return result;
+}
+
+static CURLcode verify_host(struct Curl_easy *data,
+ CERT_CONTEXT *pCertContextServer,
+ const char * const conn_hostname)
+{
+ CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
+ TCHAR *cert_hostname_buff = NULL;
+ size_t cert_hostname_buff_index = 0;
+ DWORD len = 0;
+ DWORD actual_len = 0;
+
+ /* CertGetNameString will provide the 8-bit character string without
+ * any decoding */
+ DWORD name_flags = CERT_NAME_DISABLE_IE4_UTF8_FLAG;
+
+#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
+ name_flags |= CERT_NAME_SEARCH_ALL_NAMES_FLAG;
+#endif
+
+ /* Determine the size of the string needed for the cert hostname */
+ len = CertGetNameString(pCertContextServer,
+ CERT_NAME_DNS_TYPE,
+ name_flags,
+ NULL,
+ NULL,
+ 0);
+ if(len == 0) {
+ failf(data,
+ "schannel: CertGetNameString() returned no "
+ "certificate name information");
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ goto cleanup;
+ }
+
+ /* CertGetNameString guarantees that the returned name will not contain
+ * embedded null bytes. This appears to be undocumented behavior.
+ */
+ cert_hostname_buff = (LPTSTR)malloc(len * sizeof(TCHAR));
+ actual_len = CertGetNameString(pCertContextServer,
+ CERT_NAME_DNS_TYPE,
+ name_flags,
+ NULL,
+ (LPTSTR) cert_hostname_buff,
+ len);
+
+ /* Sanity check */
+ if(actual_len != len) {
+ failf(data,
+ "schannel: CertGetNameString() returned certificate "
+ "name information of unexpected size");
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ goto cleanup;
+ }
+
+ /* If HAVE_CERT_NAME_SEARCH_ALL_NAMES is available, the output
+ * will contain all DNS names, where each name is null-terminated
+ * and the last DNS name is double null-terminated. Due to this
+ * encoding, use the length of the buffer to iterate over all names.
+ */
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ while(cert_hostname_buff_index < len &&
+ cert_hostname_buff[cert_hostname_buff_index] != TEXT('\0') &&
+ result == CURLE_PEER_FAILED_VERIFICATION) {
+
+ char *cert_hostname;
+
+ /* Comparing the cert name and the connection hostname encoded as UTF-8
+ * is acceptable since both values are assumed to use ASCII
+ * (or some equivalent) encoding
+ */
+ cert_hostname = Curl_convert_tchar_to_UTF8(
+ &cert_hostname_buff[cert_hostname_buff_index]);
+ if(!cert_hostname) {
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ int match_result;
+
+ match_result = Curl_cert_hostcheck(cert_hostname, conn_hostname);
+ if(match_result == CURL_HOST_MATCH) {
+ infof(data,
+ "schannel: connection hostname (%s) validated "
+ "against certificate name (%s)\n",
+ conn_hostname, cert_hostname);
+ result = CURLE_OK;
+ }
+ else {
+ size_t cert_hostname_len;
+
+ infof(data,
+ "schannel: connection hostname (%s) did not match "
+ "against certificate name (%s)\n",
+ conn_hostname, cert_hostname);
+
+ cert_hostname_len = _tcslen(
+ &cert_hostname_buff[cert_hostname_buff_index]);
+
+ /* Move on to next cert name */
+ cert_hostname_buff_index += cert_hostname_len + 1;
+
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ Curl_unicodefree(cert_hostname);
+ }
+ }
+
+ if(result == CURLE_PEER_FAILED_VERIFICATION) {
+ failf(data,
+ "schannel: CertGetNameString() failed to match "
+ "connection hostname (%s) against server certificate names",
+ conn_hostname);
+ }
+ else if(result != CURLE_OK)
+ failf(data, "schannel: server certificate name verification failed");
+
+cleanup:
+ Curl_unicodefree(cert_hostname_buff);
+
+ return result;
+}
+
+CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+{
+ SECURITY_STATUS status;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode result = CURLE_OK;
+ CERT_CONTEXT *pCertContextServer = NULL;
+ const CERT_CHAIN_CONTEXT *pChainContext = NULL;
+ HCERTCHAINENGINE cert_chain_engine = NULL;
+ HCERTSTORE trust_store = NULL;
+ const char * const conn_hostname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.name :
+ conn->host.name;
+
+ status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &pCertContextServer);
+
+ if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ failf(data, "schannel: Failed to read remote certificate context: %s",
+ Curl_sspi_strerror(conn, status));
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK && SSL_CONN_CONFIG(CAfile) &&
+ BACKEND->use_manual_cred_validation) {
+ /*
+ * Create a chain engine that uses the certificates in the CA file as
+ * trusted certificates. This is only supported on Windows 7+.
+ */
+
+ if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) {
+ failf(data, "schannel: this version of Windows is too old to support "
+ "certificate verification via CA bundle file.");
+ result = CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ /* Open the certificate store */
+ trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
+ 0,
+ (HCRYPTPROV)NULL,
+ CERT_STORE_CREATE_NEW_FLAG,
+ NULL);
+ if(!trust_store) {
+ failf(data, "schannel: failed to create certificate store: %s",
+ Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile),
+ conn);
+ }
+ }
+
+ if(result == CURLE_OK) {
+ CERT_CHAIN_ENGINE_CONFIG_WIN7 engine_config;
+ BOOL create_engine_result;
+
+ memset(&engine_config, 0, sizeof(engine_config));
+ engine_config.cbSize = sizeof(engine_config);
+ engine_config.hExclusiveRoot = trust_store;
+
+ /* CertCreateCertificateChainEngine will check the expected size of the
+ * CERT_CHAIN_ENGINE_CONFIG structure and fail if the specified size
+ * does not match the expected size. When this occurs, it indicates that
+ * CAINFO is not supported on the version of Windows in use.
+ */
+ create_engine_result =
+ CertCreateCertificateChainEngine(
+ (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine);
+ if(!create_engine_result) {
+ failf(data,
+ "schannel: failed to create certificate chain engine: %s",
+ Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ CERT_CHAIN_PARA ChainPara;
+
+ memset(&ChainPara, 0, sizeof(ChainPara));
+ ChainPara.cbSize = sizeof(ChainPara);
+
+ if(!CertGetCertificateChain(cert_chain_engine,
+ pCertContextServer,
+ NULL,
+ pCertContextServer->hCertStore,
+ &ChainPara,
+ (data->set.ssl.no_revoke ? 0 :
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN),
+ NULL,
+ &pChainContext)) {
+ failf(data, "schannel: CertGetCertificateChain failed: %s",
+ Curl_sspi_strerror(conn, GetLastError()));
+ pChainContext = NULL;
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK) {
+ CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
+ DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
+ dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
+ if(dwTrustErrorMask) {
+ if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_REVOKED");
+ else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_PARTIAL_CHAIN");
+ else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_UNTRUSTED_ROOT");
+ else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_NOT_TIME_VALID");
+ else if(dwTrustErrorMask & CERT_TRUST_REVOCATION_STATUS_UNKNOWN)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_REVOCATION_STATUS_UNKNOWN");
+ else
+ failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
+ dwTrustErrorMask);
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ if(SSL_CONN_CONFIG(verifyhost)) {
+ result = verify_host(conn->data, pCertContextServer, conn_hostname);
+ }
+ }
+
+ if(cert_chain_engine) {
+ CertFreeCertificateChainEngine(cert_chain_engine);
+ }
+
+ if(trust_store) {
+ CertCloseStore(trust_store, 0);
+ }
+
+ if(pChainContext)
+ CertFreeCertificateChain(pChainContext);
+
+ if(pCertContextServer)
+ CertFreeCertificateContext(pCertContextServer);
+
+ return result;
+}
+
+#endif /* USE_SCHANNEL */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
!conn->proxy_ssl[sockindex].use) {
struct ssl_backend_data *pbdata;
- if(!Curl_ssl->support_https_proxy)
+ if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
return CURLE_NOT_BUILT_IN;
/* The pointers to the ssl backend data, which is opaque here, are swapped
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
- defined(USE_MBEDTLS)
+ defined(USE_MBEDTLS) || defined(USE_CYASSL)
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks)
{
sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH);
if(!sha256sumdigest)
return CURLE_OUT_OF_MEMORY;
- Curl_ssl->sha256sum(pubkey, pubkeylen,
+ encode = Curl_ssl->sha256sum(pubkey, pubkeylen,
sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
+
+ if(encode != CURLE_OK)
+ return encode;
+
encode = Curl_base64_encode(data, (char *)sha256sumdigest,
CURL_SHA256_DIGEST_LENGTH, &encoded,
&encodedlen);
static const struct Curl_ssl Curl_ssl_multi = {
{ CURLSSLBACKEND_NONE, "multi" }, /* info */
-
- 0, /* have_ca_path */
- 0, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
-
+ 0, /* supports nothing */
(size_t)-1, /* something insanely large to be on the safe side */
Curl_multissl_init, /* init */
{
int i;
+ if(avail)
+ *avail = (const curl_ssl_backend **)&available_backends;
+
if(Curl_ssl != &Curl_ssl_multi)
return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;
}
}
- if(avail)
- *avail = (const curl_ssl_backend **)&available_backends;
return CURLSSLSET_UNKNOWN_BACKEND;
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
struct connectdata;
struct ssl_connect_data;
+#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */
+#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */
+#define SSLSUPP_PINNEDPUBKEY (1<<2) /* supports CURLOPT_PINNEDPUBLICKEY */
+#define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */
+#define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */
+
struct Curl_ssl {
/*
* This *must* be the first entry to allow returning the list of available
* backends in curl_global_sslset().
*/
curl_ssl_backend info;
-
- unsigned have_ca_path:1; /* supports CAPATH */
- unsigned have_certinfo:1; /* supports CURLOPT_CERTINFO */
- unsigned have_pinnedpubkey:1; /* supports CURLOPT_PINNEDPUBLICKEY */
- unsigned have_ssl_ctx:1; /* supports CURLOPT_SSL_CTX_* */
-
- unsigned support_https_proxy:1; /* supports access via HTTPS proxies */
-
+ unsigned int supports; /* bitfield, see above */
size_t sizeof_ssl_backend_data;
int (*init)(void);
CURLcode (*md5sum)(unsigned char *input, size_t inputlen,
unsigned char *md5sum, size_t md5sumlen);
- void (*sha256sum)(const unsigned char *input, size_t inputlen,
+ CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
unsigned char *sha256sum, size_t sha256sumlen);
};
#endif
#ifndef MD5_DIGEST_LENGTH
+#ifndef LIBWOLFSSL_VERSION_HEX /* because WolfSSL borks this */
#define MD5_DIGEST_LENGTH 16 /* fixed size */
#endif
+#endif
#ifndef CURL_SHA256_DIGEST_LENGTH
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "curl_memory.h"
#include "memdebug.h"
+static void fileinfo_dtor(void *user, void *element)
+{
+ (void)user;
+ Curl_fileinfo_cleanup(element);
+}
+
CURLcode Curl_wildcard_init(struct WildcardData *wc)
{
- Curl_llist_init(&wc->filelist, Curl_fileinfo_dtor);
+ Curl_llist_init(&wc->filelist, fileinfo_dtor);
wc->state = CURLWC_INIT;
return CURLE_OK;
if(!wc)
return;
- if(wc->tmp_dtor) {
- wc->tmp_dtor(wc->tmp);
- wc->tmp_dtor = ZERO_NULL;
- wc->tmp = NULL;
+ if(wc->dtor) {
+ wc->dtor(wc->protdata);
+ wc->dtor = ZERO_NULL;
+ wc->protdata = NULL;
}
- DEBUGASSERT(wc->tmp == NULL);
+ DEBUGASSERT(wc->protdata == NULL);
Curl_llist_destroy(&wc->filelist, NULL);
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
will end */
} curl_wildcard_states;
-typedef void (*curl_wildcard_tmp_dtor)(void *ptr);
+typedef void (*curl_wildcard_dtor)(void *ptr);
/* struct keeping information about wildcard download process */
struct WildcardData {
char *path; /* path to the directory, where we trying wildcard-match */
char *pattern; /* wildcard pattern */
struct curl_llist filelist; /* llist with struct Curl_fileinfo */
- void *tmp; /* pointer to protocol specific temporary data */
- curl_wildcard_tmp_dtor tmp_dtor;
+ void *protdata; /* pointer to protocol specific temporary data */
+ curl_wildcard_dtor dtor;
void *customptr; /* for CURLOPT_CHUNK_DATA pointer */
};
#define UV_ERRNO_H_
#include <errno.h>
+#if EDOM > 0
+# define UV__ERR(x) (-(x))
+#else
+# define UV__ERR(x) (x)
+#endif
#define UV__EOF (-4095)
#define UV__UNKNOWN (-4094)
* a fairly common practice for Windows programmers to redefine errno codes.
*/
#if defined(E2BIG) && !defined(_WIN32)
-# define UV__E2BIG (-E2BIG)
+# define UV__E2BIG UV__ERR(E2BIG)
#else
# define UV__E2BIG (-4093)
#endif
#if defined(EACCES) && !defined(_WIN32)
-# define UV__EACCES (-EACCES)
+# define UV__EACCES UV__ERR(EACCES)
#else
# define UV__EACCES (-4092)
#endif
#if defined(EADDRINUSE) && !defined(_WIN32)
-# define UV__EADDRINUSE (-EADDRINUSE)
+# define UV__EADDRINUSE UV__ERR(EADDRINUSE)
#else
# define UV__EADDRINUSE (-4091)
#endif
#if defined(EADDRNOTAVAIL) && !defined(_WIN32)
-# define UV__EADDRNOTAVAIL (-EADDRNOTAVAIL)
+# define UV__EADDRNOTAVAIL UV__ERR(EADDRNOTAVAIL)
#else
# define UV__EADDRNOTAVAIL (-4090)
#endif
#if defined(EAFNOSUPPORT) && !defined(_WIN32)
-# define UV__EAFNOSUPPORT (-EAFNOSUPPORT)
+# define UV__EAFNOSUPPORT UV__ERR(EAFNOSUPPORT)
#else
# define UV__EAFNOSUPPORT (-4089)
#endif
#if defined(EAGAIN) && !defined(_WIN32)
-# define UV__EAGAIN (-EAGAIN)
+# define UV__EAGAIN UV__ERR(EAGAIN)
#else
# define UV__EAGAIN (-4088)
#endif
#if defined(EALREADY) && !defined(_WIN32)
-# define UV__EALREADY (-EALREADY)
+# define UV__EALREADY UV__ERR(EALREADY)
#else
# define UV__EALREADY (-4084)
#endif
#if defined(EBADF) && !defined(_WIN32)
-# define UV__EBADF (-EBADF)
+# define UV__EBADF UV__ERR(EBADF)
#else
# define UV__EBADF (-4083)
#endif
#if defined(EBUSY) && !defined(_WIN32)
-# define UV__EBUSY (-EBUSY)
+# define UV__EBUSY UV__ERR(EBUSY)
#else
# define UV__EBUSY (-4082)
#endif
#if defined(ECANCELED) && !defined(_WIN32)
-# define UV__ECANCELED (-ECANCELED)
+# define UV__ECANCELED UV__ERR(ECANCELED)
#else
# define UV__ECANCELED (-4081)
#endif
#if defined(ECHARSET) && !defined(_WIN32)
-# define UV__ECHARSET (-ECHARSET)
+# define UV__ECHARSET UV__ERR(ECHARSET)
#else
# define UV__ECHARSET (-4080)
#endif
#if defined(ECONNABORTED) && !defined(_WIN32)
-# define UV__ECONNABORTED (-ECONNABORTED)
+# define UV__ECONNABORTED UV__ERR(ECONNABORTED)
#else
# define UV__ECONNABORTED (-4079)
#endif
#if defined(ECONNREFUSED) && !defined(_WIN32)
-# define UV__ECONNREFUSED (-ECONNREFUSED)
+# define UV__ECONNREFUSED UV__ERR(ECONNREFUSED)
#else
# define UV__ECONNREFUSED (-4078)
#endif
#if defined(ECONNRESET) && !defined(_WIN32)
-# define UV__ECONNRESET (-ECONNRESET)
+# define UV__ECONNRESET UV__ERR(ECONNRESET)
#else
# define UV__ECONNRESET (-4077)
#endif
#if defined(EDESTADDRREQ) && !defined(_WIN32)
-# define UV__EDESTADDRREQ (-EDESTADDRREQ)
+# define UV__EDESTADDRREQ UV__ERR(EDESTADDRREQ)
#else
# define UV__EDESTADDRREQ (-4076)
#endif
#if defined(EEXIST) && !defined(_WIN32)
-# define UV__EEXIST (-EEXIST)
+# define UV__EEXIST UV__ERR(EEXIST)
#else
# define UV__EEXIST (-4075)
#endif
#if defined(EFAULT) && !defined(_WIN32)
-# define UV__EFAULT (-EFAULT)
+# define UV__EFAULT UV__ERR(EFAULT)
#else
# define UV__EFAULT (-4074)
#endif
#if defined(EHOSTUNREACH) && !defined(_WIN32)
-# define UV__EHOSTUNREACH (-EHOSTUNREACH)
+# define UV__EHOSTUNREACH UV__ERR(EHOSTUNREACH)
#else
# define UV__EHOSTUNREACH (-4073)
#endif
#if defined(EINTR) && !defined(_WIN32)
-# define UV__EINTR (-EINTR)
+# define UV__EINTR UV__ERR(EINTR)
#else
# define UV__EINTR (-4072)
#endif
#if defined(EINVAL) && !defined(_WIN32)
-# define UV__EINVAL (-EINVAL)
+# define UV__EINVAL UV__ERR(EINVAL)
#else
# define UV__EINVAL (-4071)
#endif
#if defined(EIO) && !defined(_WIN32)
-# define UV__EIO (-EIO)
+# define UV__EIO UV__ERR(EIO)
#else
# define UV__EIO (-4070)
#endif
#if defined(EISCONN) && !defined(_WIN32)
-# define UV__EISCONN (-EISCONN)
+# define UV__EISCONN UV__ERR(EISCONN)
#else
# define UV__EISCONN (-4069)
#endif
#if defined(EISDIR) && !defined(_WIN32)
-# define UV__EISDIR (-EISDIR)
+# define UV__EISDIR UV__ERR(EISDIR)
#else
# define UV__EISDIR (-4068)
#endif
#if defined(ELOOP) && !defined(_WIN32)
-# define UV__ELOOP (-ELOOP)
+# define UV__ELOOP UV__ERR(ELOOP)
#else
# define UV__ELOOP (-4067)
#endif
#if defined(EMFILE) && !defined(_WIN32)
-# define UV__EMFILE (-EMFILE)
+# define UV__EMFILE UV__ERR(EMFILE)
#else
# define UV__EMFILE (-4066)
#endif
#if defined(EMSGSIZE) && !defined(_WIN32)
-# define UV__EMSGSIZE (-EMSGSIZE)
+# define UV__EMSGSIZE UV__ERR(EMSGSIZE)
#else
# define UV__EMSGSIZE (-4065)
#endif
#if defined(ENAMETOOLONG) && !defined(_WIN32)
-# define UV__ENAMETOOLONG (-ENAMETOOLONG)
+# define UV__ENAMETOOLONG UV__ERR(ENAMETOOLONG)
#else
# define UV__ENAMETOOLONG (-4064)
#endif
#if defined(ENETDOWN) && !defined(_WIN32)
-# define UV__ENETDOWN (-ENETDOWN)
+# define UV__ENETDOWN UV__ERR(ENETDOWN)
#else
# define UV__ENETDOWN (-4063)
#endif
#if defined(ENETUNREACH) && !defined(_WIN32)
-# define UV__ENETUNREACH (-ENETUNREACH)
+# define UV__ENETUNREACH UV__ERR(ENETUNREACH)
#else
# define UV__ENETUNREACH (-4062)
#endif
#if defined(ENFILE) && !defined(_WIN32)
-# define UV__ENFILE (-ENFILE)
+# define UV__ENFILE UV__ERR(ENFILE)
#else
# define UV__ENFILE (-4061)
#endif
#if defined(ENOBUFS) && !defined(_WIN32)
-# define UV__ENOBUFS (-ENOBUFS)
+# define UV__ENOBUFS UV__ERR(ENOBUFS)
#else
# define UV__ENOBUFS (-4060)
#endif
#if defined(ENODEV) && !defined(_WIN32)
-# define UV__ENODEV (-ENODEV)
+# define UV__ENODEV UV__ERR(ENODEV)
#else
# define UV__ENODEV (-4059)
#endif
#if defined(ENOENT) && !defined(_WIN32)
-# define UV__ENOENT (-ENOENT)
+# define UV__ENOENT UV__ERR(ENOENT)
#else
# define UV__ENOENT (-4058)
#endif
#if defined(ENOMEM) && !defined(_WIN32)
-# define UV__ENOMEM (-ENOMEM)
+# define UV__ENOMEM UV__ERR(ENOMEM)
#else
# define UV__ENOMEM (-4057)
#endif
#if defined(ENONET) && !defined(_WIN32)
-# define UV__ENONET (-ENONET)
+# define UV__ENONET UV__ERR(ENONET)
#else
# define UV__ENONET (-4056)
#endif
#if defined(ENOSPC) && !defined(_WIN32)
-# define UV__ENOSPC (-ENOSPC)
+# define UV__ENOSPC UV__ERR(ENOSPC)
#else
# define UV__ENOSPC (-4055)
#endif
#if defined(ENOSYS) && !defined(_WIN32)
-# define UV__ENOSYS (-ENOSYS)
+# define UV__ENOSYS UV__ERR(ENOSYS)
#else
# define UV__ENOSYS (-4054)
#endif
#if defined(ENOTCONN) && !defined(_WIN32)
-# define UV__ENOTCONN (-ENOTCONN)
+# define UV__ENOTCONN UV__ERR(ENOTCONN)
#else
# define UV__ENOTCONN (-4053)
#endif
#if defined(ENOTDIR) && !defined(_WIN32)
-# define UV__ENOTDIR (-ENOTDIR)
+# define UV__ENOTDIR UV__ERR(ENOTDIR)
#else
# define UV__ENOTDIR (-4052)
#endif
#if defined(ENOTEMPTY) && !defined(_WIN32)
-# define UV__ENOTEMPTY (-ENOTEMPTY)
+# define UV__ENOTEMPTY UV__ERR(ENOTEMPTY)
#else
# define UV__ENOTEMPTY (-4051)
#endif
#if defined(ENOTSOCK) && !defined(_WIN32)
-# define UV__ENOTSOCK (-ENOTSOCK)
+# define UV__ENOTSOCK UV__ERR(ENOTSOCK)
#else
# define UV__ENOTSOCK (-4050)
#endif
#if defined(ENOTSUP) && !defined(_WIN32)
-# define UV__ENOTSUP (-ENOTSUP)
+# define UV__ENOTSUP UV__ERR(ENOTSUP)
#else
# define UV__ENOTSUP (-4049)
#endif
#if defined(EPERM) && !defined(_WIN32)
-# define UV__EPERM (-EPERM)
+# define UV__EPERM UV__ERR(EPERM)
#else
# define UV__EPERM (-4048)
#endif
#if defined(EPIPE) && !defined(_WIN32)
-# define UV__EPIPE (-EPIPE)
+# define UV__EPIPE UV__ERR(EPIPE)
#else
# define UV__EPIPE (-4047)
#endif
#if defined(EPROTO) && !defined(_WIN32)
-# define UV__EPROTO (-EPROTO)
+# define UV__EPROTO UV__ERR(EPROTO)
#else
-# define UV__EPROTO (-4046)
+# define UV__EPROTO UV__ERR(4046)
#endif
#if defined(EPROTONOSUPPORT) && !defined(_WIN32)
-# define UV__EPROTONOSUPPORT (-EPROTONOSUPPORT)
+# define UV__EPROTONOSUPPORT UV__ERR(EPROTONOSUPPORT)
#else
# define UV__EPROTONOSUPPORT (-4045)
#endif
#if defined(EPROTOTYPE) && !defined(_WIN32)
-# define UV__EPROTOTYPE (-EPROTOTYPE)
+# define UV__EPROTOTYPE UV__ERR(EPROTOTYPE)
#else
# define UV__EPROTOTYPE (-4044)
#endif
#if defined(EROFS) && !defined(_WIN32)
-# define UV__EROFS (-EROFS)
+# define UV__EROFS UV__ERR(EROFS)
#else
# define UV__EROFS (-4043)
#endif
#if defined(ESHUTDOWN) && !defined(_WIN32)
-# define UV__ESHUTDOWN (-ESHUTDOWN)
+# define UV__ESHUTDOWN UV__ERR(ESHUTDOWN)
#else
# define UV__ESHUTDOWN (-4042)
#endif
#if defined(ESPIPE) && !defined(_WIN32)
-# define UV__ESPIPE (-ESPIPE)
+# define UV__ESPIPE UV__ERR(ESPIPE)
#else
# define UV__ESPIPE (-4041)
#endif
#if defined(ESRCH) && !defined(_WIN32)
-# define UV__ESRCH (-ESRCH)
+# define UV__ESRCH UV__ERR(ESRCH)
#else
# define UV__ESRCH (-4040)
#endif
#if defined(ETIMEDOUT) && !defined(_WIN32)
-# define UV__ETIMEDOUT (-ETIMEDOUT)
+# define UV__ETIMEDOUT UV__ERR(ETIMEDOUT)
#else
# define UV__ETIMEDOUT (-4039)
#endif
#if defined(ETXTBSY) && !defined(_WIN32)
-# define UV__ETXTBSY (-ETXTBSY)
+# define UV__ETXTBSY UV__ERR(ETXTBSY)
#else
# define UV__ETXTBSY (-4038)
#endif
#if defined(EXDEV) && !defined(_WIN32)
-# define UV__EXDEV (-EXDEV)
+# define UV__EXDEV UV__ERR(EXDEV)
#else
# define UV__EXDEV (-4037)
#endif
#if defined(EFBIG) && !defined(_WIN32)
-# define UV__EFBIG (-EFBIG)
+# define UV__EFBIG UV__ERR(EFBIG)
#else
# define UV__EFBIG (-4036)
#endif
#if defined(ENOPROTOOPT) && !defined(_WIN32)
-# define UV__ENOPROTOOPT (-ENOPROTOOPT)
+# define UV__ENOPROTOOPT UV__ERR(ENOPROTOOPT)
#else
# define UV__ENOPROTOOPT (-4035)
#endif
#if defined(ERANGE) && !defined(_WIN32)
-# define UV__ERANGE (-ERANGE)
+# define UV__ERANGE UV__ERR(ERANGE)
#else
# define UV__ERANGE (-4034)
#endif
#if defined(ENXIO) && !defined(_WIN32)
-# define UV__ENXIO (-ENXIO)
+# define UV__ENXIO UV__ERR(ENXIO)
#else
# define UV__ENXIO (-4033)
#endif
#if defined(EMLINK) && !defined(_WIN32)
-# define UV__EMLINK (-EMLINK)
+# define UV__EMLINK UV__ERR(EMLINK)
#else
# define UV__EMLINK (-4032)
#endif
* icky to hard-code it.
*/
#if defined(EHOSTDOWN) && !defined(_WIN32)
-# define UV__EHOSTDOWN (-EHOSTDOWN)
+# define UV__EHOSTDOWN UV__ERR(EHOSTDOWN)
#elif defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
#endif
#if defined(EREMOTEIO) && !defined(_WIN32)
-# define UV__EREMOTEIO (-EREMOTEIO)
+# define UV__EREMOTEIO UV__ERR(EREMOTEIO)
#else
# define UV__EREMOTEIO (-4030)
#endif
#if defined(ENOTTY) && !defined(_WIN32)
-# define UV__ENOTTY (-ENOTTY)
+# define UV__ENOTTY UV__ERR(ENOTTY)
#else
# define UV__ENOTTY (-4029)
#endif
+
#endif /* UV_ERRNO_H_ */
#ifndef UV_MVS_H
#define UV_MVS_H
-#define UV_PLATFORM_SEM_T int
+#define UV_PLATFORM_SEM_T long
#define UV_PLATFORM_LOOP_FIELDS \
void* ep; \
# include "uv-linux.h"
#elif defined (__MVS__)
# include "uv-os390.h"
-#elif defined(_PASE)
+#elif defined(__PASE__)
# include "uv-posix.h"
#elif defined(_AIX)
# include "uv-aix.h"
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 19
-#define UV_VERSION_PATCH 1
+#define UV_VERSION_MINOR 20
+#define UV_VERSION_PATCH 3
#define UV_VERSION_IS_RELEASE 0
#define UV_VERSION_SUFFIX "dev"
/* read-only */ \
uv_req_type type; \
/* private */ \
- void* active_queue[2]; \
- void* reserved[4]; \
+ void* reserved[6]; \
UV_REQ_PRIVATE_FIELDS \
/* Abstract base class of all requests. */
*/
uv_uid_t uid;
uv_gid_t gid;
+ /*
+ Libuv can set the child process' CPU affinity mask. This happens when
+ `cpumask` is non-NULL. It must point to an array of char values
+ of length `cpumask_size`, whose value must be at least that returned by
+ uv_cpumask_size(). Each byte in the mask can be either zero (false)
+ or non-zero (true) to indicate whether the corresponding processor at
+ that index is included.
+
+ If enabled on an unsupported platform, uv_spawn() will fail with
+ UV_ENOTSUP.
+ */
+ char* cpumask;
+ size_t cpumask_size;
} uv_process_options_t;
/*
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);
UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
int* count);
*/
#define UV_FS_COPYFILE_EXCL 0x0001
+/*
+ * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
+ * If copy-on-write is not supported, a fallback copy mechanism is used.
+ */
+#define UV_FS_COPYFILE_FICLONE 0x0002
+
+/*
+ * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
+ * If copy-on-write is not supported, an error is returned.
+ */
+#define UV_FS_COPYFILE_FICLONE_FORCE 0x0004
+
UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
/* Loop reference counting. */
unsigned int active_handles;
void* handle_queue[2];
- void* active_reqs[2];
+ union {
+ void* unused[2];
+ unsigned int count;
+ } active_reqs;
/* Internal flag to signal loop stop. */
unsigned int stop_flag;
UV_LOOP_PRIVATE_FIELDS
#undef UV_SIGNAL_PRIVATE_FIELDS
#undef UV_LOOP_PRIVATE_FIELDS
#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS
+#undef UV__ERR
#ifdef __cplusplus
}
struct procsinfo pi;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
pi.pi_pid = getpid();
res = getargs(&pi, sizeof(pi), args, sizeof(args));
if (res < 0)
- return -EINVAL;
+ return UV_EINVAL;
/*
* Possibilities for args:
/* Case i) and ii) absolute or relative paths */
if (strchr(args, '/') != NULL) {
if (realpath(args, abspath) != abspath)
- return -errno;
+ return UV__ERR(errno);
abspath_size = strlen(abspath);
char *path = getenv("PATH");
if (path == NULL)
- return -EINVAL;
+ return UV_EINVAL;
clonedpath = uv__strdup(path);
if (clonedpath == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
token = strtok(clonedpath, ":");
while (token != NULL) {
uv__free(clonedpath);
/* Out of tokens (path entries), and no match found */
- return -EINVAL;
+ return UV_EINVAL;
}
}
*count = 0;
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
- return -errno;
+ return UV__ERR(errno);
}
if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
ifc.ifc_req = (struct ifreq*)uv__malloc(size);
ifc.ifc_len = size;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
if (!(*addresses)) {
uv__close(sockfd);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -ENOSYS;
+ return UV_ENOSYS;
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) {
uv__close(sockfd);
- return -ENOSYS;
+ return UV_ENOSYS;
}
if (inet6)
pc.fd = fd;
if (pollset_ctl(loop->backend_fd, &pc, 1))
- return -errno;
+ return UV__ERR(errno);
pc.cmd = PS_DELETE;
if (pollset_ctl(loop->backend_fd, &pc, 1))
p = uv__malloc(siz);
if (p == NULL)
- return -errno;
+ return UV__ERR(errno);
/* Retrieve all mounted filesystems */
rv = mntctl(MCTL_QUERY, siz, (char*)p);
if (rv < 0)
- return -errno;
+ return UV__ERR(errno);
if (rv == 0) {
/* buffer was not large enough, reallocate to correct size */
siz = *(int*)p;
uv__free(p);
p = uv__malloc(siz);
if (p == NULL)
- return -errno;
+ return UV__ERR(errno);
rv = mntctl(MCTL_QUERY, siz, (char*)p);
if (rv < 0)
- return -errno;
+ return UV__ERR(errno);
}
/* Look for dev in filesystems mount info */
rc = uv__makedir_p(cmd);
if (rc == -1 && errno != EEXIST){
- return -errno;
+ return UV__ERR(errno);
}
return rc;
sprintf(mon_file, "/aha/fs/modFile.monFactory");
if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX)
- return -ENAMETOOLONG;
+ return UV_ENAMETOOLONG;
/* Make the necessary subdirectories for the monitor file */
rc = uv__make_subdirs_p(filename);
/* Open the monitor file, creating it if necessary */
*fd = open(mon_file, O_CREAT|O_RDWR);
if (*fd < 0)
- return -errno;
+ return UV__ERR(errno);
/* Write out the monitoring specifications.
* In this case, we are monitoring for a state change event type
rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1);
if (rc < 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
return 0;
#else
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
return 0;
#else
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
return 0;
#else
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
*/
new_title = uv__strdup(title);
if (new_title == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
size_t len;
len = strlen(process_argv[0]);
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
else if (size <= len)
- return -ENOBUFS;
+ return UV_ENOBUFS;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
fd = open(pp, O_RDONLY);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
/* FIXME(bnoordhuis) Handle EINTR. */
- err = -EINVAL;
+ err = UV_EINVAL;
if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) {
*rss = (size_t)psinfo.pr_rssize * 1024;
err = 0;
endutent();
if (boot_time == 0)
- return -ENOSYS;
+ return UV_ENOSYS;
*uptime = time(NULL) - boot_time;
return 0;
result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
if (result == -1) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
if (result == -1) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t));
if (!ps_cpus) {
- return -ENOMEM;
+ return UV_ENOMEM;
}
strcpy(cpu_id.name, FIRST_CPU);
result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus);
if (result == -1) {
uv__free(ps_cpus);
- return -ENOSYS;
+ return UV_ENOSYS;
}
*cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t));
if (!*cpu_infos) {
uv__free(ps_cpus);
- return -ENOMEM;
+ return UV_ENOMEM;
}
*count = ncpus;
pipefd[0] = err;
pipefd[1] = -1;
}
- else if (err == -ENOSYS) {
+ else if (err == UV_ENOSYS) {
err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
#if defined(__linux__)
/* Save a file descriptor by opening one of the pipe descriptors as
return fd;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_eventfd2 = 1;
}
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_eventfd = 1;
#endif
- return -ENOSYS;
+ return UV_ENOSYS;
}
int i;
if (getifaddrs(&addrs) != 0)
- return -errno;
+ return UV__ERR(errno);
*count = 0;
if (*addresses == NULL) {
freeifaddrs(addrs);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
#include <sys/uio.h> /* writev */
#include <sys/resource.h> /* getrusage */
#include <pwd.h>
+#include <sched.h>
#ifdef __sun
# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
+# include <sys/param.h>
+# include <sys/cpuset.h>
# define UV__O_CLOEXEC O_CLOEXEC
# if defined(__FreeBSD__) && __FreeBSD__ >= 10
# define uv__accept4 accept4
socklen_t len;
if (handle == NULL || value == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (handle->type == UV_TCP || handle->type == UV_NAMED_PIPE)
fd = uv__stream_fd((uv_stream_t*) handle);
else if (handle->type == UV_UDP)
fd = ((uv_udp_t *) handle)->io_watcher.fd;
else
- return -ENOTSUP;
+ return UV_ENOTSUP;
len = sizeof(*value);
r = setsockopt(fd, SOL_SOCKET, optname, (const void*) value, len);
if (r < 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
return sockfd;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
#endif
sockfd = socket(domain, type, protocol);
if (sockfd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__nonblock(sockfd, 1);
if (err == 0)
continue;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_accept4 = 1;
skip:
if (peerfd == -1) {
if (errno == EINTR)
continue;
- return -errno;
+ return UV__ERR(errno);
}
err = uv__cloexec(peerfd, 1);
saved_errno = errno;
rc = close(fd);
if (rc == -1) {
- rc = -errno;
- if (rc == -EINTR || rc == -EINPROGRESS)
+ rc = UV__ERR(errno);
+ if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS))
rc = 0; /* The close is in progress, not an error. */
errno = saved_errno;
}
int uv__close(int fd) {
assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */
#if defined(__MVS__)
- epoll_file_close(fd);
+ SAVE_ERRNO(epoll_file_close(fd));
#endif
return uv__close_nocheckstdio(fd);
}
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
while (r == -1 && errno == EINTR);
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
/* Bail out now if already set/clear. */
if (!!(r & O_NONBLOCK) == !!set)
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
while (r == -1 && errno == EINTR);
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
/* Bail out now if already set/clear. */
if (!!(r & FD_CLOEXEC) == !!set)
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
fd = dup(fd);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err) {
if (rc != -1)
return rc;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
rc = recvmsg(fd, msg, flags);
if (rc == -1)
- return -errno;
+ return UV__ERR(errno);
no_msg_cmsg_cloexec = 1;
} else {
rc = recvmsg(fd, msg, flags);
rc = recvmsg(fd, msg, flags);
#endif
if (rc == -1)
- return -errno;
+ return UV__ERR(errno);
if (msg->msg_controllen == 0)
return rc;
for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg))
int uv_cwd(char* buffer, size_t* size) {
if (buffer == NULL || size == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (getcwd(buffer, *size) == NULL)
- return -errno;
+ return UV__ERR(errno);
*size = strlen(buffer);
if (*size > 1 && buffer[*size - 1] == '/') {
int uv_chdir(const char* dir) {
if (chdir(dir))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
if (uv__is_closing(handle) || fd_out == -1)
- return -EBADF;
+ return UV_EBADF;
*fd = fd_out;
return 0;
struct rusage usage;
if (getrusage(RUSAGE_SELF, &usage))
- return -errno;
+ return UV__ERR(errno);
rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec;
rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec;
return fd;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
/* O_CLOEXEC not supported. */
no_cloexec = 1;
fd = open(path, flags);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err) {
#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
r = dup3(oldfd, newfd, O_CLOEXEC);
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
return r;
#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
if (r != -1)
return r;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
/* Fall through. */
#elif defined(__linux__)
static int no_dup3;
if (r != -1)
return r;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
/* Fall through. */
no_dup3 = 1;
}
#endif
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(newfd, 1);
if (err) {
int uv_os_homedir(char* buffer, size_t* size) {
uv_passwd_t pwd;
- char* buf;
size_t len;
int r;
- if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
-
- /* Check if the HOME environment variable is set first */
- buf = getenv("HOME");
-
- if (buf != NULL) {
- len = strlen(buf);
+ /* Check if the HOME environment variable is set first. The task of
+ performing input validation on buffer and size is taken care of by
+ uv_os_getenv(). */
+ r = uv_os_getenv("HOME", buffer, size);
- if (len >= *size) {
- *size = len + 1;
- return -ENOBUFS;
- }
-
- memcpy(buffer, buf, len + 1);
- *size = len;
-
- return 0;
- }
+ if (r != UV_ENOENT)
+ return r;
/* HOME is not set, so call uv__getpwuid_r() */
r = uv__getpwuid_r(&pwd);
if (len >= *size) {
*size = len + 1;
uv_os_free_passwd(&pwd);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, pwd.homedir, len + 1);
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
#define CHECK_ENV_VAR(name) \
do { \
if (len >= *size) {
*size = len + 1;
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
/* The returned directory should not have a trailing slash. */
getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r");
if (getpwuid_r == NULL)
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
if (pwd == NULL)
- return -EINVAL;
+ return UV_EINVAL;
initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
buf = uv__malloc(bufsize);
if (buf == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
r = getpwuid_r(uid, &pw, buf, bufsize, &result);
if (result == NULL) {
uv__free(buf);
- return -ENOENT;
+ return UV_ENOENT;
}
/* Allocate memory for the username, shell, and home directory */
if (pwd->username == NULL) {
uv__free(buf);
- return -ENOMEM;
+ return UV_ENOMEM;
}
/* Copy the username */
size_t len;
if (name == NULL || buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
var = getenv(name);
if (var == NULL)
- return -ENOENT;
+ return UV_ENOENT;
len = strlen(var);
if (len >= *size) {
*size = len + 1;
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, var, len + 1);
int uv_os_setenv(const char* name, const char* value) {
if (name == NULL || value == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (setenv(name, value, 1) != 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
int uv_os_unsetenv(const char* name) {
if (name == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (unsetenv(name) != 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
if (gethostname(buf, sizeof(buf)) != 0)
- return -errno;
+ return UV__ERR(errno);
buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
len = strlen(buf);
if (len >= *size) {
*size = len + 1;
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, buf, len + 1);
}
+int uv_cpumask_size(void) {
+#if defined(__linux__) || defined(__FreeBSD__)
+ return CPU_SETSIZE;
+#else
+ return UV_ENOTSUP;
+#endif
+}
+
+
uv_os_fd_t uv_get_osfhandle(int fd) {
return fd;
}
struct sysinfo info;
if (sysinfo(&info) < 0)
- return -errno;
+ return UV__ERR(errno);
*uptime = info.uptime;
return 0;
* IN THE SOFTWARE.
*/
+#include "uv.h"
+#include "internal.h"
+
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
dlsym(RTLD_DEFAULT, "pthread_setname_np");
if (dynamic_pthread_setname_np == NULL)
- return -ENOSYS;
+ return UV_ENOSYS;
strncpy(namebuf, name, sizeof(namebuf) - 1);
namebuf[sizeof(namebuf) - 1] = '\0';
err = dynamic_pthread_setname_np(namebuf);
if (err)
- return -err;
+ return UV__ERR(err);
return 0;
}
CFTypeRef asn;
int err;
- err = -ENOENT;
+ err = UV_ENOENT;
application_services_handle = dlopen("/System/Library/Frameworks/"
"ApplicationServices.framework/"
"Versions/A/ApplicationServices",
/* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
hi_services_bundle =
pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices"));
- err = -ENOENT;
+ err = UV_ENOENT;
if (hi_services_bundle == NULL)
goto out;
asn = pLSGetCurrentApplicationASN();
- err = -EINVAL;
+ err = UV_EINVAL;
if (pLSSetApplicationInformationItem(-2, /* Magic value. */
asn,
*display_name_key,
loop->cf_state = NULL;
if (uv__kqueue_init(loop))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
size_t abspath_size;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
exepath_size = sizeof(exepath);
if (_NSGetExecutablePath(exepath, &exepath_size))
- return -EIO;
+ return UV_EIO;
if (realpath(exepath, abspath) != abspath)
- return -errno;
+ return UV__ERR(errno);
abspath_size = strlen(abspath);
if (abspath_size == 0)
- return -EIO;
+ return UV_EIO;
*size -= 1;
if (*size > abspath_size)
if (host_statistics(mach_host_self(), HOST_VM_INFO,
(host_info_t)&info, &count) != KERN_SUCCESS) {
- return -EINVAL; /* FIXME(bnoordhuis) Translate error. */
+ return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */
}
return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE);
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
now = time(NULL);
*uptime = now - info.tv_sec;
size = sizeof(model);
if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) &&
sysctlbyname("hw.model", &model, &size, NULL, 0)) {
- return -errno;
+ return UV__ERR(errno);
}
size = sizeof(cpuspeed);
if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
(processor_info_array_t*)&info,
&msg_type) != KERN_SUCCESS) {
- return -EINVAL; /* FIXME(bnoordhuis) Translate error. */
+ return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */
}
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);
- return -ENOMEM;
+ return UV_ENOMEM;
}
*count = numcpus;
ssize_t abspath_size;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
abspath_size = readlink("/proc/curproc/file", abspath, sizeof(abspath));
if (abspath_size < 0)
- return -errno;
+ return UV__ERR(errno);
assert(abspath_size > 0);
*size -= 1;
size_t abspath_size;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
abspath_size = sizeof abspath;
if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
assert(abspath_size > 0);
abspath_size -= 1;
size_t size = sizeof(freecount);
if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) freecount * sysconf(_SC_PAGESIZE);
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
if (process_title == NULL) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOMEM;
+ return UV_ENOMEM;
}
uv__free(process_title);
size_t len;
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
if (size < len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, process_title, len);
kinfo_size = sizeof(kinfo);
if (sysctl(mib, 4, &kinfo, &kinfo_size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
page_size = getpagesize();
struct timespec sp;
r = clock_gettime(CLOCK_MONOTONIC, &sp);
if (r)
- return -errno;
+ return UV__ERR(errno);
*uptime = sp.tv_sec;
return 0;
size = sizeof(model);
if (sysctlbyname(model_key, &model, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
size = sizeof(numcpus);
if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
- return -ENOMEM;
+ return UV_ENOMEM;
*count = numcpus;
size = sizeof(maxcpus);
if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) {
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
size = maxcpus * CPUSTATES * sizeof(long);
cp_times = uv__malloc(size);
if (cp_times == NULL) {
uv__free(*cpu_infos);
- return -ENOMEM;
+ return UV_ENOMEM;
}
if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) {
uv__free(cp_times);
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
for (i = 0; i < numcpus; i++) {
#if defined(__APPLE__)
# include <copyfile.h>
+#elif defined(__linux__) && !defined(FICLONE)
+# include <sys/ioctl.h>
+# define FICLONE _IOW(0x94, 9, int)
#endif
#define INIT(subtype) \
do { \
if (req == NULL) \
- return -EINVAL; \
- req->type = UV_FS; \
- if (cb != NULL) \
- uv__req_init(loop, req, UV_FS); \
+ return UV_EINVAL; \
+ UV_REQ_INIT(req, UV_FS); \
req->fs_type = UV_FS_ ## subtype; \
req->result = 0; \
req->ptr = NULL; \
req->loop = loop; \
req->path = NULL; \
req->new_path = NULL; \
+ req->bufs = NULL; \
req->cb = cb; \
} \
while (0)
req->path = path; \
} else { \
req->path = uv__strdup(path); \
- if (req->path == NULL) { \
- uv__req_unregister(loop, req); \
- return -ENOMEM; \
- } \
+ if (req->path == NULL) \
+ return UV_ENOMEM; \
} \
} \
while (0)
path_len = strlen(path) + 1; \
new_path_len = strlen(new_path) + 1; \
req->path = uv__malloc(path_len + new_path_len); \
- if (req->path == NULL) { \
- uv__req_unregister(loop, req); \
- return -ENOMEM; \
- } \
+ if (req->path == NULL) \
+ return UV_ENOMEM; \
req->new_path = req->path + path_len; \
memcpy((void*) req->path, path, path_len); \
memcpy((void*) req->new_path, new_path, new_path_len); \
#define POST \
do { \
if (cb != NULL) { \
+ uv__req_register(loop, req); \
uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
return 0; \
} \
if (req->flags & UV_FS_COPYFILE_EXCL)
flags |= COPYFILE_EXCL;
+#ifdef COPYFILE_CLONE
+ if (req->flags & UV_FS_COPYFILE_FICLONE)
+ flags |= COPYFILE_CLONE;
+#endif
+
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+#ifdef COPYFILE_CLONE_FORCE
+ flags |= COPYFILE_CLONE_FORCE;
+#else
+ return UV_ENOSYS;
+#endif
+ }
+
return copyfile(req->path, req->new_path, NULL, flags);
#else
uv_fs_t fs_req;
/* Get the source file's mode. */
if (fstat(srcfd, &statsbuf)) {
- err = -errno;
+ err = UV__ERR(errno);
goto out;
}
}
if (fchmod(dstfd, statsbuf.st_mode) == -1) {
- err = -errno;
+ err = UV__ERR(errno);
+ goto out;
+ }
+
+#ifdef FICLONE
+ if (req->flags & UV_FS_COPYFILE_FICLONE ||
+ req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ if (ioctl(dstfd, FICLONE, srcfd) == -1) {
+ /* 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;
+ goto out;
+ }
+ } else {
+ goto out;
+ }
+ }
+#else
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ err = UV_ENOSYS;
goto out;
}
+#endif
bytes_to_send = statsbuf.st_size;
in_offset = 0;
} while (r == -1 && errno == EINTR && retry_on_eintr);
if (r == -1)
- req->result = -errno;
+ req->result = UV__ERR(errno);
else
req->result = r;
req = container_of(w, uv_fs_t, work_req);
uv__req_unregister(req->loop, req);
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->result == 0);
- req->result = -ECANCELED;
+ req->result = UV_ECANCELED;
}
req->cb(req);
uv_fs_cb cb) {
INIT(MKDTEMP);
req->path = uv__strdup(tpl);
- if (req->path == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->path == NULL)
+ return UV_ENOMEM;
POST;
}
INIT(READ);
if (bufs == NULL || nbufs == 0)
- return -EINVAL;
+ return UV_EINVAL;
req->file = file;
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->bufs == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
INIT(WRITE);
if (bufs == NULL || nbufs == 0)
- return -EINVAL;
+ return UV_EINVAL;
req->file = file;
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->bufs == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
uv__fs_scandir_cleanup(req);
+ if (req->bufs != req->bufsml)
+ uv__free(req->bufs);
+ req->bufs = NULL;
+
if (req->ptr != &req->statbuf)
uv__free(req->ptr);
req->ptr = NULL;
uv_fs_cb cb) {
INIT(COPYFILE);
- if (flags & ~UV_FS_COPYFILE_EXCL)
- return -EINVAL;
+ if (flags & ~(UV_FS_COPYFILE_EXCL |
+ UV_FS_COPYFILE_FICLONE |
+ UV_FS_COPYFILE_FICLONE_FORCE)) {
+ return UV_EINVAL;
+ }
PATH2;
req->flags = flags;
if (!pFSEventStreamStart(ref)) {
pFSEventStreamInvalidate(ref);
pFSEventStreamRelease(ref);
- return -EMFILE;
+ return UV_EMFILE;
}
state->fsevent_stream = ref;
uv__fsevents_destroy_stream(handle->loop);
/* Any failure below will be a memory failure */
- err = -ENOMEM;
+ err = UV_ENOMEM;
/* Create list of all watched paths */
uv_mutex_lock(&state->fsevent_mutex);
/* Create new FSEventStream */
cf_paths = pCFArrayCreate(NULL, (const void**) paths, path_count, NULL);
if (cf_paths == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto final;
}
err = uv__fsevents_create_stream(handle->loop, cf_paths);
* but if it ever becomes one, we can turn the dynamic library handles into
* per-event loop properties and have the dynamic linker keep track for us.
*/
- err = -ENOSYS;
+ err = UV_ENOSYS;
core_foundation_handle = dlopen("/System/Library/Frameworks/"
"CoreFoundation.framework/"
"Versions/A/CoreFoundation",
if (core_services_handle == NULL)
goto out;
- err = -ENOENT;
+ err = UV_ENOENT;
#define V(handle, symbol) \
do { \
*(void **)(&p ## symbol) = dlsym((handle), #symbol); \
state = uv__calloc(1, sizeof(*state));
if (state == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
err = uv_mutex_init(&loop->cf_mutex);
if (err)
ctx.perform = uv__cf_loop_cb;
state->signal_source = pCFRunLoopSourceCreate(NULL, 0, &ctx);
if (state->signal_source == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto fail_signal_source_create;
}
loop->cf_state = state;
/* uv_thread_t is an alias for pthread_t. */
- err = -pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop);
+ err = UV__ERR(pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop));
if (attr != NULL)
pthread_attr_destroy(attr);
item = uv__malloc(sizeof(*item));
if (item == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
item->handle = handle;
item->type = type;
/* Get absolute path to file */
handle->realpath = realpath(handle->path, NULL);
if (handle->realpath == NULL)
- return -errno;
+ return UV__ERR(errno);
handle->realpath_len = strlen(handle->realpath);
/* Initialize event queue */
*/
handle->cf_cb = uv__malloc(sizeof(*handle->cf_cb));
if (handle->cf_cb == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto fail_cf_cb_malloc;
}
uv__cf_loop_state_t* state;
if (handle->cf_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
/* Remove handle from the list */
state = handle->loop->cf_state;
assert(handle != NULL);
err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalClosing);
if (err)
- return -err;
+ return UV__ERR(err);
/* Wait for deinitialization */
uv_sem_wait(&state->fsevent_sem);
case EAI_SOCKTYPE: return UV_EAI_SOCKTYPE;
#endif
#if defined(EAI_SYSTEM)
- case EAI_SYSTEM: return -errno;
+ case EAI_SYSTEM: return UV__ERR(errno);
#endif
}
assert(!"unknown EAI_* error code");
req->service = NULL;
req->hostname = NULL;
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->retcode == 0);
req->retcode = UV_EAI_CANCELED;
}
char* buf;
if (req == NULL || (hostname == NULL && service == NULL))
- return -EINVAL;
+ return UV_EINVAL;
hostname_len = hostname ? strlen(hostname) + 1 : 0;
service_len = service ? strlen(service) + 1 : 0;
buf = uv__malloc(hostname_len + service_len + hints_len);
if (buf == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
uv__req_init(loop, req, UV_GETADDRINFO);
req->loop = loop;
return UV_EINVAL;
if (if_indextoname(ifindex, ifname_buf) == NULL)
- return -errno;
+ return UV__ERR(errno);
len = strnlen(ifname_buf, sizeof(ifname_buf));
uv__req_unregister(req->loop, req);
host = service = NULL;
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->retcode == 0);
req->retcode = UV_EAI_CANCELED;
} else if (req->retcode == 0) {
*cpu_infos = uv__malloc(numcpus * sizeof(uv_cpu_info_t));
if (!*cpu_infos) {
- return -ENOMEM;
+ return UV_ENOMEM;
}
cpu_info = *cpu_infos;
#include <string.h> /* strrchr */
#include <fcntl.h> /* O_CLOEXEC, may be */
#include <stdio.h>
+#include <errno.h>
#if defined(__STRICT_ANSI__)
# define inline __inline
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
- (defined(__linux__) && !defined(__sparc__)) || \
+ defined(__linux__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
#define uv__cloexec uv__cloexec_ioctl
#define uv__nonblock uv__nonblock_fcntl
#endif
+/* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute
+ * when O_NDELAY is not equal to O_NONBLOCK. Case in point: linux/sparc32
+ * and linux/sparc64, where O_NDELAY is O_NONBLOCK + another bit.
+ *
+ * Libuv uses uv__nonblock_fcntl() directly sometimes so ensure that it
+ * commutes with uv__nonblock().
+ */
+#if defined(__linux__) && O_NDELAY != O_NONBLOCK
+#undef uv__nonblock
+#define uv__nonblock uv__nonblock_fcntl
+#endif
+
/* core */
int uv__cloexec_ioctl(int fd, int set);
int uv__cloexec_fcntl(int fd, int set);
int uv__nonblock_ioctl(int fd, int set);
int uv__nonblock_fcntl(int fd, int set);
-int uv__close(int fd);
+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);
int uv__kqueue_init(uv_loop_t* loop) {
loop->backend_fd = kqueue();
if (loop->backend_fd == -1)
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(loop->backend_fd, 1);
rc = 0;
EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
- rc = -errno;
+ rc = UV__ERR(errno);
EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
if (rc == 0)
int fd;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
/* TODO open asynchronously - but how do we report back errors? */
fd = open(path, O_RDONLY);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
loop->inotify_watchers = NULL;
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
rc = 0;
if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e))
if (errno != EEXIST)
- rc = -errno;
+ rc = UV__ERR(errno);
if (rc == 0)
if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e))
while (fd == -1 && errno == EINTR);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
do
n = read(fd, buf, sizeof(buf) - 1);
uv__close(fd);
if (n == -1)
- return -errno;
+ return UV__ERR(errno);
buf[n] = '\0';
s = strchr(buf, ' ');
return 0;
err:
- return -EINVAL;
+ return UV_EINVAL;
}
}
if (r)
- return -errno;
+ return UV__ERR(errno);
*uptime = now.tv_sec;
return 0;
char buf[1024];
if (!fgets(buf, sizeof(buf), statfile_fp))
- return -EIO;
+ return UV_EIO;
num = 0;
while (fgets(buf, sizeof(buf), statfile_fp)) {
}
if (num == 0)
- return -EIO;
+ return UV_EIO;
*numcpus = num;
return 0;
statfile_fp = uv__open_file("/proc/stat");
if (statfile_fp == NULL)
- return -errno;
+ return UV__ERR(errno);
err = uv__cpu_num(statfile_fp, &numcpus);
if (err < 0)
goto out;
- err = -ENOMEM;
+ err = UV_ENOMEM;
ci = uv__calloc(numcpus, sizeof(*ci));
if (ci == NULL)
goto out;
defined(__x86_64__)
fp = uv__open_file("/proc/cpuinfo");
if (fp == NULL)
- return -errno;
+ return UV__ERR(errno);
while (fgets(buf, sizeof(buf), fp)) {
if (model_idx < numcpus) {
model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
if (model == NULL) {
fclose(fp);
- return -ENOMEM;
+ return UV_ENOMEM;
}
ci[model_idx++].model = model;
continue;
model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
if (model == NULL) {
fclose(fp);
- return -ENOMEM;
+ return UV_ENOMEM;
}
ci[model_idx++].model = model;
continue;
while (model_idx < numcpus) {
model = uv__strndup(inferred_model, strlen(inferred_model));
if (model == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
ci[model_idx++].model = model;
}
int uv_interface_addresses(uv_interface_address_t** addresses,
int* count) {
#ifndef HAVE_IFADDRS_H
- return -ENOSYS;
+ return UV_ENOSYS;
#else
struct ifaddrs *addrs, *ent;
uv_interface_address_t* address;
struct sockaddr_ll *sll;
if (getifaddrs(&addrs))
- return -errno;
+ return UV__ERR(errno);
*count = 0;
*addresses = NULL;
*addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) {
freeifaddrs(addrs);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
return fd;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
fd = uv__inotify_init();
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err == 0)
int wd;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
err = init_inotify(handle->loop);
if (err)
wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events);
if (wd == -1)
- return -errno;
+ return UV__ERR(errno);
w = find_watcher(handle->loop, wd);
if (w)
w = uv__malloc(sizeof(*w) + strlen(path) + 1);
if (w == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
w->wd = wd;
w->path = strcpy((char*)(w + 1), path);
\
int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \
if (uv__is_active(handle)) return 0; \
- if (cb == NULL) return -EINVAL; \
+ if (cb == NULL) return UV_EINVAL; \
QUEUE_INSERT_HEAD(&handle->loop->name##_handles, &handle->queue); \
handle->name##_cb = cb; \
uv__handle_start(handle); \
heap_init((struct heap*) &loop->timer_heap);
QUEUE_INIT(&loop->wq);
- QUEUE_INIT(&loop->active_reqs);
QUEUE_INIT(&loop->idle_handles);
QUEUE_INIT(&loop->async_handles);
QUEUE_INIT(&loop->check_handles);
QUEUE_INIT(&loop->prepare_handles);
QUEUE_INIT(&loop->handle_queue);
+ loop->active_handles = 0;
+ loop->active_reqs.count = 0;
loop->nfds = 0;
loop->watchers = NULL;
loop->nwatchers = 0;
int mib[4];
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
int_size = ARRAY_SIZE(int_buf);
if (sysctl(mib, 4, int_buf, &int_size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
/* Copy string from the intermediate buffer to outer one with appropriate
* length.
int which[] = {CTL_VM, VM_UVMEXP};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
}
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
if (process_title == NULL) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOMEM;
+ return UV_ENOMEM;
}
uv__free(process_title);
size_t len;
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
if (size < len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, process_title, len);
error:
if (kd) kvm_close(kd);
- return -EPERM;
+ return UV_EPERM;
}
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
now = time(NULL);
size = sizeof(model);
if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) &&
sysctlbyname("hw.model", &model, &size, NULL, 0)) {
- return -errno;
+ return UV__ERR(errno);
}
size = sizeof(numcpus);
if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*count = numcpus;
/* Only i386 and amd64 have machdep.tsc_freq */
size = numcpus * CPUSTATES * sizeof(*cp_times);
cp_times = uv__malloc(size);
if (cp_times == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
uv__free(cp_times);
uv__free(*cpu_infos);
- return -ENOMEM;
+ return UV_ENOMEM;
}
for (i = 0; i < numcpus; i++) {
#include <errno.h>
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
const char* filename, unsigned int flags) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
int uv_fs_event_stop(uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
void uv__fs_event_close(uv_fs_event_t* handle) {
int uv_get_process_title(char* buffer, size_t size) {
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
buffer[0] = '\0';
return 0;
int err;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
mypid = getpid();
for (;;) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
argsbuf_tmp = uv__realloc(argsbuf, argsbuf_size);
if (argsbuf_tmp == NULL)
goto out;
break;
}
if (errno != ENOMEM) {
- err = -errno;
+ err = UV__ERR(errno);
goto out;
}
argsbuf_size *= 2U;
}
if (argsbuf[0] == NULL) {
- err = -EINVAL; /* FIXME(bnoordhuis) More appropriate error. */
+ err = UV_EINVAL; /* FIXME(bnoordhuis) More appropriate error. */
goto out;
}
int which[] = {CTL_VM, VM_UVMEXP};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
}
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
if (process_title == NULL) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOMEM;
+ return UV_ENOMEM;
}
uv__free(process_title);
size_t len;
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
if (size < len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, process_title, len);
mib[5] = 1;
if (sysctl(mib, 6, &kinfo, &size, NULL, 0) < 0)
- return -errno;
+ return UV__ERR(errno);
*rss = kinfo.p_vm_rssize * page_size;
return 0;
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
now = time(NULL);
size = sizeof(model);
if (sysctl(which, 2, &model, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
which[1] = HW_NCPU;
size = sizeof(numcpus);
if (sysctl(which, 2, &numcpus, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
- return -ENOMEM;
+ return UV_ENOMEM;
*count = numcpus;
size = sizeof(cpuspeed);
if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) {
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
size = sizeof(info);
size = sizeof(info);
if (sysctl(which, 3, &info, &size, NULL, 0)) {
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
cpu_info = &(*cpu_infos)[i];
maybe_resize(lst, 1);
lst->items[lst->size - 1].fd = lst->msg_queue;
lst->items[lst->size - 1].events = POLLIN;
+ lst->items[lst->size - 1].revents = 0;
uv_once(&once, epoll_init);
uv_mutex_lock(&global_epoll_lock);
QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
}
lst->items[fd].fd = fd;
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) {
uv_mutex_unlock(&global_epoll_lock);
ep = epoll_create1(0);
loop->ep = ep;
if (ep == NULL)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
int pid;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
pid = getpid();
res = getexe(pid, args, sizeof(args));
if (res < 0)
- return -EINVAL;
+ return UV_EINVAL;
/*
* Possibilities for args:
/* Case i) and ii) absolute or relative paths */
if (strchr(args, '/') != NULL) {
if (realpath(args, abspath) != abspath)
- return -errno;
+ return UV__ERR(errno);
abspath_size = strlen(abspath);
char* path = getenv("PATH");
if (path == NULL)
- return -EINVAL;
+ return UV_EINVAL;
clonedpath = uv__strdup(path);
if (clonedpath == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
token = strtok(clonedpath, ":");
while (token != NULL) {
uv__free(clonedpath);
/* Out of tokens (path entries), and no match found */
- return -EINVAL;
+ return UV_EINVAL;
}
}
*cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t));
if (!*cpu_infos)
- return -ENOMEM;
+ return UV_ENOMEM;
cpu_info = *cpu_infos;
idx = 0;
maxsize = 16384;
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
- return -errno;
+ return UV__ERR(errno);
ifc.__nif6h_version = 1;
ifc.__nif6h_buflen = maxsize;
if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
if (!(*addresses)) {
uv__close(sockfd);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (0 > sockfd)
- return -errno;
+ return UV__ERR(errno);
ifc.ifc_req = uv__calloc(1, maxsize);
ifc.ifc_len = maxsize;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
#define MAX(a,b) (((a)>(b))?(a):(b))
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
if (!(*addresses)) {
uv__close(sockfd);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -ENOSYS;
+ return UV_ENOSYS;
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
int rc;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
ep = handle->loop->ep;
assert(ep->msg_queue != -1);
path = uv__strdup(filename);
if (path == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct);
if (rc != 0)
- return -errno;
+ return UV__ERR(errno);
uv__handle_start(handle);
handle->path = path;
/* Already bound? */
if (uv__stream_fd(handle) >= 0)
- return -EINVAL;
+ return UV_EINVAL;
/* Make a copy of the file name, it outlives this function's scope. */
pipe_fname = uv__strdup(name);
if (pipe_fname == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
/* We've got a copy, don't touch the original any more. */
name = NULL;
saddr.sun_family = AF_UNIX;
if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
- err = -errno;
+ err = UV__ERR(errno);
/* Convert ENOENT to EACCES for compatibility with Windows. */
- if (err == -ENOENT)
- err = -EACCES;
+ if (err == UV_ENOENT)
+ err = UV_EACCES;
uv__close(sockfd);
goto err_socket;
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
if (uv__stream_fd(handle) == -1)
- return -EINVAL;
+ return UV_EINVAL;
#if defined(__MVS__)
/* On zOS, backlog=0 has undefined behaviour */
#endif
if (listen(uv__stream_fd(handle), backlog))
- return -errno;
+ return UV__ERR(errno);
handle->connection_cb = cb;
handle->io_watcher.cb = uv__server_io;
while (r == -1 && errno == EINTR);
if (r == -1 && errno != EINPROGRESS) {
- err = -errno;
+ err = UV__ERR(errno);
#if defined(__CYGWIN__) || defined(__MSYS__)
/* EBADF is supposed to mean that the socket fd is bad, but
Cygwin reports EBADF instead of ENOTSOCK when the file is
not a socket. We do not expect to see a bad fd here
(e.g. due to new_sock), so translate the error. */
- if (err == -EBADF)
- err = -ENOTSOCK;
+ if (err == UV_EBADF)
+ err = UV_ENOTSOCK;
#endif
goto out;
}
err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
if (err < 0) {
*size = 0;
- return -errno;
+ return UV__ERR(errno);
}
#if defined(__linux__)
int r;
if (handle == NULL || uv__stream_fd(handle) == -1)
- return -EBADF;
+ return UV_EBADF;
if (mode != UV_READABLE &&
mode != UV_WRITABLE &&
mode != (UV_WRITABLE | UV_READABLE))
- return -EINVAL;
-
- if (fstat(uv__stream_fd(handle), &pipe_stat) == -1)
- return -errno;
-
- desired_mode = 0;
- if (mode & UV_READABLE)
- desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
- if (mode & UV_WRITABLE)
- desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-
- /* Exit early if pipe already has desired mode. */
- if ((pipe_stat.st_mode & desired_mode) == desired_mode)
- return 0;
-
- pipe_stat.st_mode |= desired_mode;
+ return UV_EINVAL;
/* Unfortunately fchmod does not work on all platforms, we will use chmod. */
name_len = 0;
return r;
}
+ /* stat must be used as fstat has a bug on Darwin */
+ if (stat(name_buffer, &pipe_stat) == -1) {
+ uv__free(name_buffer);
+ return -errno;
+ }
+
+ desired_mode = 0;
+ if (mode & UV_READABLE)
+ desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
+ if (mode & UV_WRITABLE)
+ desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+
+ /* Exit early if pipe already has desired mode. */
+ if ((pipe_stat.st_mode & desired_mode) == desired_mode) {
+ uv__free(name_buffer);
+ return 0;
+ }
+
+ pipe_stat.st_mode |= desired_mode;
+
r = chmod(name_buffer, pipe_stat.st_mode);
uv__free(name_buffer);
- return r != -1 ? 0 : -errno;
+ return r != -1 ? 0 : UV__ERR(errno);
}
if ((events & POLLERR) && !(events & UV__POLLPRI)) {
uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
uv__handle_stop(handle);
- handle->poll_cb(handle, -EBADF, 0);
+ handle->poll_cb(handle, UV_EBADF, 0);
return;
}
* Workaround for e.g. kqueue fds not supporting ioctls.
*/
err = uv__nonblock(fd, 1);
- if (err == -ENOTTY)
+ if (err == UV_ENOTTY)
if (uv__nonblock == uv__nonblock_ioctl)
err = uv__nonblock_fcntl(fd, 1);
static void uv__pollfds_del(uv_loop_t* loop, int fd) {
size_t i;
assert(!loop->poll_fds_iterating);
- for (i = 0; i < loop->poll_fds_used; ++i) {
+ for (i = 0; i < loop->poll_fds_used;) {
if (loop->poll_fds[i].fd == fd) {
/* swap to last position and remove */
--loop->poll_fds_used;
loop->poll_fds[loop->poll_fds_used].fd = -1;
loop->poll_fds[loop->poll_fds_used].events = 0;
loop->poll_fds[loop->poll_fds_used].revents = 0;
- return;
+ /* This method is called with an fd of -1 to purge the invalidated fds,
+ * so we may possibly have multiples to remove.
+ */
+ if (-1 != fd)
+ return;
+ } else {
+ /* We must only increment the loop counter when the fds do not match.
+ * Otherwise, when we are purging an invalidated fd, the value just
+ * swapped here from the previous end of the array will be skipped.
+ */
+ ++i;
}
}
}
while (rv == -1 && (errno == EINTR || errno == EAGAIN));
if (rv == -1)
- return -errno;
+ return UV__ERR(errno);
if (p[0].revents & POLLNVAL)
- return -EINVAL;
+ return UV_EINVAL;
return 0;
}
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
+#include <sched.h>
#if defined(__APPLE__) && !TARGET_OS_IPHONE
# include <crt_externs.h>
# include <grp.h>
#endif
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__)
+# define uv__cpu_set_t cpu_set_t
+#elif defined(__FreeBSD__)
+# include <sys/param.h>
+# include <sys/cpuset.h>
+# include <pthread_np.h>
+# define uv__cpu_set_t cpuset_t
+#endif
+#endif
static void uv__chld(uv_signal_t* handle, int signum) {
uv_process_t* process;
* Anything else is a genuine error.
*/
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
no_cloexec = 1;
#endif
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(fds[0], 1);
uv__cloexec(fds[1], 1);
return 0;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_pipe2 = 1;
#endif
if (pipe(fds))
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(fds[0], 1);
uv__cloexec(fds[1], 1);
case UV_CREATE_PIPE:
assert(container->data.stream != NULL);
if (container->data.stream->type != UV_NAMED_PIPE)
- return -EINVAL;
+ return UV_EINVAL;
else
return uv__make_socketpair(fds, 0);
fd = uv__stream_fd(container->data.stream);
if (fd == -1)
- return -EINVAL;
+ return UV_EINVAL;
fds[1] = fd;
return 0;
default:
assert(0 && "Unexpected flags");
- return -EINVAL;
+ return UV_EINVAL;
}
}
static int uv__process_open_stream(uv_stdio_container_t* container,
- int pipefds[2],
- int writable) {
+ int pipefds[2]) {
int flags;
int err;
pipefds[1] = -1;
uv__nonblock(pipefds[0], 1);
- if (container->data.stream->type == UV_NAMED_PIPE &&
- ((uv_pipe_t*)container->data.stream)->ipc)
- flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE;
- else if (writable)
- flags = UV_STREAM_WRITABLE;
- else
- flags = UV_STREAM_READABLE;
+ flags = 0;
+ if (container->flags & UV_WRITABLE_PIPE)
+ flags |= UV_STREAM_READABLE;
+ if (container->flags & UV_READABLE_PIPE)
+ flags |= UV_STREAM_WRITABLE;
return uv__stream_open(container->data.stream, pipefds[0], flags);
}
int err;
int fd;
int n;
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ int r;
+ int i;
+ int cpumask_size;
+ uv__cpu_set_t cpuset;
+#endif
+#endif
if (options->flags & UV_PROCESS_DETACHED)
setsid();
continue;
pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
if (pipes[fd][1] == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
close_fd = use_fd;
if (use_fd == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
fd = dup2(use_fd, fd);
if (fd == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
if (options->cwd != NULL && chdir(options->cwd)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ if (options->cpumask != NULL) {
+ cpumask_size = uv_cpumask_size();
+ assert(options->cpumask_size >= (size_t)cpumask_size);
+
+ CPU_ZERO(&cpuset);
+ for (i = 0; i < cpumask_size; ++i) {
+ if (options->cpumask[i]) {
+ CPU_SET(i, &cpuset);
+ }
+ }
+
+ r = -pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
+ if (r != 0) {
+ uv__write_int(error_fd, r);
+ _exit(127);
+ }
+ }
+#endif
+#endif
+
if (options->env != NULL) {
environ = options->env;
}
if (SIG_ERR != signal(n, SIG_DFL))
continue;
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
err = pthread_sigmask(SIG_SETMASK, &set, NULL);
if (err != 0) {
- uv__write_int(error_fd, -err);
+ uv__write_int(error_fd, UV__ERR(err));
_exit(127);
}
execvp(options->file, options->args);
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
#endif
const uv_process_options_t* options) {
#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
/* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
- return -ENOSYS;
+ return UV_ENOSYS;
#else
int signal_pipe[2] = { -1, -1 };
int pipes_storage[8][2];
int i;
int status;
+ if (options->cpumask != NULL) {
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ if (options->cpumask_size < (size_t)uv_cpumask_size()) {
+ return UV_EINVAL;
+ }
+#else
+ return UV_ENOTSUP;
+#endif
+#else
+ return UV_ENOTSUP;
+#endif
+ }
+
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
if (stdio_count < 3)
stdio_count = 3;
- err = -ENOMEM;
+ err = UV_ENOMEM;
pipes = pipes_storage;
if (stdio_count > (int) ARRAY_SIZE(pipes_storage))
pipes = uv__malloc(stdio_count * sizeof(*pipes));
pid = fork();
if (pid == -1) {
- err = -errno;
+ err = UV__ERR(errno);
uv_rwlock_wrunlock(&loop->cloexec_lock);
uv__close(signal_pipe[0]);
uv__close(signal_pipe[1]);
uv__close_nocheckstdio(signal_pipe[0]);
for (i = 0; i < options->stdio_count; i++) {
- err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0);
+ err = uv__process_open_stream(options->stdio + i, pipes[i]);
if (err == 0)
continue;
int uv_kill(int pid, int signum) {
if (kill(pid, signum))
- return -errno;
+ return UV__ERR(errno);
else
return 0;
}
ssize_t n;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
n = *size - 1;
if (n > 0)
n = readlink("/proc/self/exe", buffer, n);
if (n == -1)
- return -errno;
+ return UV__ERR(errno);
buffer[n] = '\0';
*size = n;
int uv_get_process_title(char* buffer, size_t size) {
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
if (size <= process_title.len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
if (process_title.len != 0)
/* XXX save old action so we can restore it later on? */
if (sigaction(signum, &sa, NULL))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
* eventually.
*/
if (signum == 0)
- return -EINVAL;
+ 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.
fd_set* swrite;
size_t swrite_sz;
};
+# define WRITE_RETRY_ON_ERROR(send_handle) \
+ (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \
+ (errno == EMSGSIZE && send_handle))
+#else
+# define WRITE_RETRY_ON_ERROR(send_handle) \
+ (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
#endif /* defined(__APPLE__) */
static void uv__stream_connect(uv_stream_t*);
kq = kqueue();
if (kq == -1) {
perror("(libuv) kqueue()");
- return -errno;
+ return UV__ERR(errno);
}
EV_SET(&filter[0], *fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
uv__close(kq);
if (ret == -1)
- return -errno;
+ return UV__ERR(errno);
if (ret == 0 || (events[0].flags & EV_ERROR) == 0 || events[0].data != EINVAL)
return 0;
* NOTE: do it ahead of malloc below to allocate enough space for fd_sets
*/
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
- return -errno;
+ return UV__ERR(errno);
max_fd = *fd;
if (fds[1] > max_fd)
s = uv__malloc(sizeof(*s) + sread_sz + swrite_sz);
if (s == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto failed_malloc;
}
#endif
if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd))
- return -EBUSY;
+ return UV_EBUSY;
assert(fd >= 0);
stream->flags |= flags;
if (stream->type == UV_TCP) {
if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1))
- return -errno;
+ return UV__ERR(errno);
/* TODO Use delay the user passed in. */
if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60))
- return -errno;
+ return UV__ERR(errno);
}
#if defined(__APPLE__)
if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
errno != ENOTSOCK &&
errno != EINVAL) {
- return -errno;
+ return UV__ERR(errno);
}
#endif
if (stream->connect_req) {
uv__req_unregister(stream->loop, stream->connect_req);
- stream->connect_req->cb(stream->connect_req, -ECANCELED);
+ stream->connect_req->cb(stream->connect_req, UV_ECANCELED);
stream->connect_req = NULL;
}
- uv__stream_flush_write_queue(stream, -ECANCELED);
+ uv__stream_flush_write_queue(stream, UV_ECANCELED);
uv__write_callbacks(stream);
if (stream->shutdown_req) {
* callee that the handle has been destroyed.
*/
uv__req_unregister(stream->loop, stream->shutdown_req);
- stream->shutdown_req->cb(stream->shutdown_req, -ECANCELED);
+ stream->shutdown_req->cb(stream->shutdown_req, UV_ECANCELED);
stream->shutdown_req = NULL;
}
int emfile_fd;
if (loop->emfile_fd == -1)
- return -EMFILE;
+ return UV_EMFILE;
uv__close(loop->emfile_fd);
loop->emfile_fd = -1;
err = uv__accept(accept_fd);
if (err >= 0)
uv__close(err);
- } while (err >= 0 || err == -EINTR);
+ } while (err >= 0 || err == UV_EINTR);
emfile_fd = uv__open_cloexec("/", O_RDONLY);
if (emfile_fd >= 0)
err = uv__accept(uv__stream_fd(stream));
if (err < 0) {
- if (err == -EAGAIN || err == -EWOULDBLOCK)
+ if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
return; /* Not an error. */
- if (err == -ECONNABORTED)
+ if (err == UV_ECONNABORTED)
continue; /* Ignore. Nothing we can do about that. */
- if (err == -EMFILE || err == -ENFILE) {
+ if (err == UV_EMFILE || err == UV_ENFILE) {
err = uv__emfile_trick(loop, uv__stream_fd(stream));
- if (err == -EAGAIN || err == -EWOULDBLOCK)
+ if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
break;
}
assert(server->loop == client->loop);
if (server->accepted_fd == -1)
- return -EAGAIN;
+ return UV_EAGAIN;
switch (client->type) {
case UV_NAMED_PIPE:
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
client->flags |= UV_HANDLE_BOUND;
break;
default:
- err = -EINVAL;
+ err = UV_EINVAL;
}
if (err == 0)
err = 0;
if (shutdown(uv__stream_fd(stream), SHUT_WR))
- err = -errno;
+ err = UV__ERR(errno);
if (err == 0)
stream->flags |= UV_STREAM_SHUT;
} scratch;
if (uv__is_closing(req->send_handle)) {
- err = -EBADF;
+ err = UV_EBADF;
goto error;
}
}
if (n < 0) {
- if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ENOBUFS) {
- err = -errno;
+ 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. */
queued_fds = uv__malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
sizeof(*queued_fds));
if (queued_fds == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
queued_fds->size = queue_size;
queued_fds->offset = 0;
stream->queued_fds = queued_fds;
* NOTE: if it is fatal - sockets will be closed in uv__stream_close
*/
if (queued_fds == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
queued_fds->size = queue_size;
stream->queued_fds = queued_fds;
}
#endif
} else {
/* Error. User should call uv_close(). */
- stream->read_cb(stream, -errno, &buf);
+ stream->read_cb(stream, UV__ERR(errno), &buf);
if (stream->flags & UV_STREAM_READING) {
stream->flags &= ~UV_STREAM_READING;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
stream->flags & UV_STREAM_SHUT ||
stream->flags & UV_STREAM_SHUTTING ||
uv__is_closing(stream)) {
- return -ENOTCONN;
+ return UV_ENOTCONN;
}
assert(uv__stream_fd(stream) >= 0);
SO_ERROR,
&error,
&errorsize);
- error = -error;
+ error = UV__ERR(error);
}
- if (error == -EINPROGRESS)
+ if (error == UV__ERR(EINPROGRESS))
return;
stream->connect_req = NULL;
return;
if (error < 0) {
- uv__stream_flush_write_queue(stream, -ECANCELED);
+ uv__stream_flush_write_queue(stream, UV_ECANCELED);
uv__write_callbacks(stream);
}
}
"uv_write (unix) does not yet support other types of streams");
if (uv__stream_fd(stream) < 0)
- return -EBADF;
+ return UV_EBADF;
+
+ if (!(stream->flags & UV_STREAM_WRITABLE))
+ return -EPIPE;
if (send_handle) {
if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc)
- return -EINVAL;
+ return UV_EINVAL;
/* XXX We abuse uv_write2() to send over UDP handles to child processes.
* Don't call uv__stream_fd() on those handles, it's a macro that on OS X
* which works but only by accident.
*/
if (uv__handle_fd((uv_handle_t*) send_handle) < 0)
- return -EBADF;
+ return UV_EBADF;
#if defined(__CYGWIN__) || defined(__MSYS__)
/* Cygwin recvmsg always sets msg_controllen to zero, so we cannot send it.
See https://github.com/mirror/newlib-cygwin/blob/86fc4bf0/winsup/cygwin/fhandler_socket.cc#L1736-L1743 */
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
if (req->bufs == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
req->nbufs = nbufs;
/* Connecting or already writing some data */
if (stream->connect_req != NULL || stream->write_queue_size != 0)
- return -EAGAIN;
+ return UV_EAGAIN;
has_pollout = uv__io_active(&stream->io_watcher, POLLOUT);
}
if (written == 0 && req_size != 0)
- return -EAGAIN;
+ return UV_EAGAIN;
else
return written;
}
stream->type == UV_TTY);
if (stream->flags & UV_CLOSING)
- return -EINVAL;
+ return UV_EINVAL;
+
+ if (!(stream->flags & UV_STREAM_READABLE))
+ return -ENOTCONN;
/* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just
* expresses the desired state of the user.
fd = port_create();
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err) {
int uv__io_check_fd(uv_loop_t* loop, int fd) {
if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
- return -errno;
+ return UV__ERR(errno);
if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
abort();
char buf[128];
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid());
res = readlink(buf, buffer, res);
if (res == -1)
- return -errno;
+ return UV__ERR(errno);
buffer[res] = '\0';
*size = res;
static int uv__fs_event_rearm(uv_fs_event_t *handle) {
if (handle->fd == -1)
- return -EBADF;
+ return UV_EBADF;
if (port_associate(handle->loop->fs_fd,
PORT_SOURCE_FILE,
(uintptr_t) &handle->fo,
FILE_ATTRIB | FILE_MODIFIED,
handle) == -1) {
- return -errno;
+ return UV__ERR(errno);
}
handle->fd = PORT_LOADED;
int err;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
first_run = 0;
if (handle->loop->fs_fd == -1) {
portfd = port_create();
if (portfd == -1)
- return -errno;
+ return UV__ERR(errno);
handle->loop->fs_fd = portfd;
first_run = 1;
}
#else /* !defined(PORT_SOURCE_FILE) */
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
uv_fs_event_cb cb,
const char* filename,
unsigned int flags) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
int uv_fs_event_stop(uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
fd = open("/proc/self/psinfo", O_RDONLY);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
/* FIXME(bnoordhuis) Handle EINTR. */
- err = -EINVAL;
+ err = UV_EINVAL;
if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) {
*rss = (size_t)psinfo.pr_rssize * 1024;
err = 0;
kc = kstat_open();
if (kc == NULL)
- return -EPERM;
+ return UV_EPERM;
ksp = kstat_lookup(kc, (char*) "unix", 0, (char*) "system_misc");
if (kstat_read(kc, ksp, NULL) == -1) {
kc = kstat_open();
if (kc == NULL)
- return -EPERM;
+ return UV_EPERM;
/* Get count of cpus */
lookup_instance = 0;
*cpu_infos = uv__malloc(lookup_instance * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
kstat_close(kc);
- return -ENOMEM;
+ return UV_ENOMEM;
}
*count = lookup_instance;
#ifdef SUNOS_NO_IFADDRS
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
#else /* SUNOS_NO_IFADDRS */
/*
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
- return -errno;
+ return UV__ERR(errno);
if (ioctl(sockfd, SIOCGARP, (char*)&arpreq) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
memcpy(address->phys_addr, arpreq.arp_ha.sa_data, sizeof(address->phys_addr));
uv__close(sockfd);
struct ifaddrs* ent;
if (getifaddrs(&addrs))
- return -errno;
+ return UV__ERR(errno);
*count = 0;
*addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) {
freeifaddrs(addrs);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
/* Bind this new socket to an arbitrary port */
slen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
- err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen);
- if (err) {
+ if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) {
uv__close(sockfd);
- return err;
+ return UV__ERR(errno);
}
- err = bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen);
- if (err) {
+ if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) {
uv__close(sockfd);
- return err;
+ return UV__ERR(errno);
}
}
slen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
- return -errno;
+ return UV__ERR(errno);
if ((saddr.ss_family == AF_INET6 &&
((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
/* Bind to arbitrary port */
if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
- return -errno;
+ return UV__ERR(errno);
}
handle->flags |= flags;
/* Use the lower 8 bits for the domain */
domain = flags & 0xFF;
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
- return -EINVAL;
+ return UV_EINVAL;
if (flags & ~0xFF)
- return -EINVAL;
+ return UV_EINVAL;
uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
/* Cannot set IPv6-only mode on non-IPv6 socket. */
if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
- return -EINVAL;
+ return UV_EINVAL;
- err = maybe_new_socket(tcp,
- addr->sa_family,
- UV_STREAM_READABLE | UV_STREAM_WRITABLE);
+ err = maybe_new_socket(tcp, addr->sa_family, 0);
if (err)
return err;
on = 1;
if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
- return -errno;
+ return UV__ERR(errno);
+#ifndef __OpenBSD__
#ifdef IPV6_V6ONLY
if (addr->sa_family == AF_INET6) {
on = (flags & UV_TCP_IPV6ONLY) != 0;
sizeof on) == -1) {
#if defined(__MVS__)
if (errno == EOPNOTSUPP)
- return -EINVAL;
+ return UV_EINVAL;
#endif
- return -errno;
+ return UV__ERR(errno);
}
}
#endif
+#endif
errno = 0;
if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
if (errno == EAFNOSUPPORT)
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
* socket created with AF_INET to an AF_INET6 address or vice versa. */
- return -EINVAL;
- return -errno;
+ return UV_EINVAL;
+ return UV__ERR(errno);
}
- tcp->delayed_error = -errno;
+ tcp->delayed_error = UV__ERR(errno);
tcp->flags |= UV_HANDLE_BOUND;
if (addr->sa_family == AF_INET6)
assert(handle->type == UV_TCP);
if (handle->connect_req != NULL)
- return -EALREADY; /* FIXME(bnoordhuis) -EINVAL or maybe -EBUSY. */
+ return UV_EALREADY; /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
err = maybe_new_socket(handle,
addr->sa_family,
* error. Solaris wants to report immediately--other unixes want to
* wait.
*/
- handle->delayed_error = -errno;
+ handle->delayed_error = UV__ERR(errno);
else
- return -errno;
+ return UV__ERR(errno);
}
uv__req_init(handle->loop, req, UV_CONNECT);
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
- return -EINVAL; /* FIXME(bnoordhuis) -EBADF */
+ return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getsockname(uv__stream_fd(handle), name, &socklen))
- return -errno;
+ return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
- return -EINVAL; /* FIXME(bnoordhuis) -EBADF */
+ return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getpeername(uv__stream_fd(handle), name, &socklen))
- return -errno;
+ return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
if (single_accept)
tcp->flags |= UV_TCP_SINGLE_ACCEPT;
- flags = UV_STREAM_READABLE;
+ flags = 0;
#if defined(__MVS__)
/* on zOS the listen call does not bind automatically
if the socket is unbound. Hence the manual binding to
an arbitrary port is required to be done manually
*/
flags |= UV_HANDLE_BOUND;
-#endif
+#endif
err = maybe_new_socket(tcp, AF_INET, flags);
if (err)
return err;
if (listen(tcp->io_watcher.fd, backlog))
- return -errno;
+ return UV__ERR(errno);
tcp->connection_cb = cb;
tcp->flags |= UV_HANDLE_BOUND;
int uv__tcp_nodelay(int fd, int on) {
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
- return -errno;
+ return UV__ERR(errno);
#ifdef TCP_KEEPIDLE
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
- return -errno;
+ return UV__ERR(errno);
#endif
/* Solaris/SmartOS, if you don't support keep-alive,
/* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
#if defined(TCP_KEEPALIVE) && !defined(__sun)
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
- return -errno;
+ return UV__ERR(errno);
#endif
return 0;
#include <sys/sem.h>
#endif
+#ifdef __GLIBC__
+#include <gnu/libc-version.h> /* gnu_get_libc_version() */
+#endif
+
#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)
if (attr != NULL)
pthread_attr_destroy(attr);
- return -err;
+ return UV__ERR(err);
}
}
int uv_thread_join(uv_thread_t *tid) {
- return -pthread_join(*tid, NULL);
+ return UV__ERR(pthread_join(*tid, NULL));
}
int uv_mutex_init(uv_mutex_t* mutex) {
#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
- return -pthread_mutex_init(mutex, NULL);
+ return UV__ERR(pthread_mutex_init(mutex, NULL));
#else
pthread_mutexattr_t attr;
int err;
if (pthread_mutexattr_destroy(&attr))
abort();
- return -err;
+ return UV__ERR(err);
#endif
}
if (pthread_mutexattr_destroy(&attr))
abort();
- return -err;
+ return UV__ERR(err);
}
if (err) {
if (err != EBUSY && err != EAGAIN)
abort();
- return -EBUSY;
+ return UV_EBUSY;
}
return 0;
int uv_rwlock_init(uv_rwlock_t* rwlock) {
- return -pthread_rwlock_init(rwlock, NULL);
+ return UV__ERR(pthread_rwlock_init(rwlock, NULL));
}
if (err) {
if (err != EBUSY && err != EAGAIN)
abort();
- return -EBUSY;
+ return UV_EBUSY;
}
return 0;
if (err) {
if (err != EBUSY && err != EAGAIN)
abort();
- return -EBUSY;
+ return UV_EBUSY;
}
return 0;
if (err == KERN_SUCCESS)
return 0;
if (err == KERN_INVALID_ARGUMENT)
- return -EINVAL;
+ return UV_EINVAL;
if (err == KERN_RESOURCE_SHORTAGE)
- return -ENOMEM;
+ return UV_ENOMEM;
abort();
- return -EINVAL; /* Satisfy the compiler. */
+ return UV_EINVAL; /* Satisfy the compiler. */
}
if (err == KERN_SUCCESS)
return 0;
if (err == KERN_OPERATION_TIMED_OUT)
- return -EAGAIN;
+ return UV_EAGAIN;
abort();
- return -EINVAL; /* Satisfy the compiler. */
+ return UV_EINVAL; /* Satisfy the compiler. */
+}
+
+#else /* !(defined(__APPLE__) && defined(__MACH__)) */
+
+#ifdef __GLIBC__
+
+/* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
+ * by providing a custom implementation for glibc < 2.21 in terms of other
+ * concurrency primitives.
+ * Refs: https://github.com/nodejs/node/issues/19903 */
+
+/* To preserve ABI compatibility, we treat the uv_sem_t as storage for
+ * a pointer to the actual struct we're using underneath. */
+
+static uv_once_t glibc_version_check_once = UV_ONCE_INIT;
+static int platform_needs_custom_semaphore = 0;
+
+static void glibc_version_check(void) {
+ const char* version = gnu_get_libc_version();
+ platform_needs_custom_semaphore =
+ version[0] == '2' && version[1] == '.' &&
+ atoi(version + 2) < 21;
}
#elif defined(__MVS__)
-int uv_sem_init(uv_sem_t* sem, unsigned int value) {
- uv_sem_t semid;
+#define platform_needs_custom_semaphore 1
+
+#else /* !defined(__GLIBC__) && !defined(__MVS__) */
+
+#define platform_needs_custom_semaphore 0
+
+#endif
+
+typedef struct uv_semaphore_s {
+ uv_mutex_t mutex;
+ uv_cond_t cond;
+ unsigned int value;
+} uv_semaphore_t;
+
+#if defined(__GLIBC__) || platform_needs_custom_semaphore
+STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
+#endif
+
+static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) {
int err;
- union {
- int val;
- struct semid_ds* buf;
- unsigned short* array;
- } arg;
+ uv_semaphore_t* sem;
+ sem = uv__malloc(sizeof(*sem));
+ if (sem == NULL)
+ return UV_ENOMEM;
- semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR);
- if (semid == -1)
- return -errno;
+ if ((err = uv_mutex_init(&sem->mutex)) != 0) {
+ uv__free(sem);
+ return err;
+ }
- arg.val = value;
- if (-1 == semctl(semid, 0, SETVAL, arg)) {
- err = errno;
- if (-1 == semctl(*sem, 0, IPC_RMID))
- abort();
- return -err;
+ if ((err = uv_cond_init(&sem->cond)) != 0) {
+ uv_mutex_destroy(&sem->mutex);
+ uv__free(sem);
+ return err;
}
- *sem = semid;
+ sem->value = value;
+ *(uv_semaphore_t**)sem_ = sem;
return 0;
}
-void uv_sem_destroy(uv_sem_t* sem) {
- if (-1 == semctl(*sem, 0, IPC_RMID))
- abort();
+
+static void uv__custom_sem_destroy(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
+
+ sem = *(uv_semaphore_t**)sem_;
+ uv_cond_destroy(&sem->cond);
+ uv_mutex_destroy(&sem->mutex);
+ uv__free(sem);
}
-void uv_sem_post(uv_sem_t* sem) {
- struct sembuf buf;
- buf.sem_num = 0;
- buf.sem_op = 1;
- buf.sem_flg = 0;
+static void uv__custom_sem_post(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
- if (-1 == semop(*sem, &buf, 1))
- abort();
+ sem = *(uv_semaphore_t**)sem_;
+ uv_mutex_lock(&sem->mutex);
+ sem->value++;
+ if (sem->value == 1)
+ uv_cond_signal(&sem->cond);
+ uv_mutex_unlock(&sem->mutex);
}
-void uv_sem_wait(uv_sem_t* sem) {
- struct sembuf buf;
- int op_status;
-
- buf.sem_num = 0;
- buf.sem_op = -1;
- buf.sem_flg = 0;
- do
- op_status = semop(*sem, &buf, 1);
- while (op_status == -1 && errno == EINTR);
+static void uv__custom_sem_wait(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
- if (op_status)
- abort();
+ sem = *(uv_semaphore_t**)sem_;
+ uv_mutex_lock(&sem->mutex);
+ while (sem->value == 0)
+ uv_cond_wait(&sem->cond, &sem->mutex);
+ sem->value--;
+ uv_mutex_unlock(&sem->mutex);
}
-int uv_sem_trywait(uv_sem_t* sem) {
- struct sembuf buf;
- int op_status;
- buf.sem_num = 0;
- buf.sem_op = -1;
- buf.sem_flg = IPC_NOWAIT;
+static int uv__custom_sem_trywait(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
- do
- op_status = semop(*sem, &buf, 1);
- while (op_status == -1 && errno == EINTR);
+ sem = *(uv_semaphore_t**)sem_;
+ if (uv_mutex_trylock(&sem->mutex) != 0)
+ return UV_EAGAIN;
- if (op_status) {
- if (errno == EAGAIN)
- return -EAGAIN;
- abort();
+ if (sem->value == 0) {
+ uv_mutex_unlock(&sem->mutex);
+ return UV_EAGAIN;
}
+ sem->value--;
+ uv_mutex_unlock(&sem->mutex);
+
return 0;
}
-#else /* !(defined(__APPLE__) && defined(__MACH__)) */
-
-int uv_sem_init(uv_sem_t* sem, unsigned int value) {
+static int uv__sem_init(uv_sem_t* sem, unsigned int value) {
if (sem_init(sem, 0, value))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
-void uv_sem_destroy(uv_sem_t* sem) {
+static void uv__sem_destroy(uv_sem_t* sem) {
if (sem_destroy(sem))
abort();
}
-void uv_sem_post(uv_sem_t* sem) {
+static void uv__sem_post(uv_sem_t* sem) {
if (sem_post(sem))
abort();
}
-void uv_sem_wait(uv_sem_t* sem) {
+static void uv__sem_wait(uv_sem_t* sem) {
int r;
do
}
-int uv_sem_trywait(uv_sem_t* sem) {
+static int uv__sem_trywait(uv_sem_t* sem) {
int r;
do
if (r) {
if (errno == EAGAIN)
- return -EAGAIN;
+ return UV_EAGAIN;
abort();
}
return 0;
}
+int uv_sem_init(uv_sem_t* sem, unsigned int value) {
+#ifdef __GLIBC__
+ uv_once(&glibc_version_check_once, glibc_version_check);
+#endif
+
+ if (platform_needs_custom_semaphore)
+ return uv__custom_sem_init(sem, value);
+ else
+ return uv__sem_init(sem, value);
+}
+
+
+void uv_sem_destroy(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ uv__custom_sem_destroy(sem);
+ else
+ uv__sem_destroy(sem);
+}
+
+
+void uv_sem_post(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ uv__custom_sem_post(sem);
+ else
+ uv__sem_post(sem);
+}
+
+
+void uv_sem_wait(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ uv__custom_sem_wait(sem);
+ else
+ uv__sem_wait(sem);
+}
+
+
+int uv_sem_trywait(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ return uv__custom_sem_trywait(sem);
+ else
+ return uv__sem_trywait(sem);
+}
+
#endif /* defined(__APPLE__) && defined(__MACH__) */
#if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__)
int uv_cond_init(uv_cond_t* cond) {
- return -pthread_cond_init(cond, NULL);
+ return UV__ERR(pthread_cond_init(cond, NULL));
}
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
err = pthread_condattr_init(&attr);
if (err)
- return -err;
+ return UV__ERR(err);
#if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21)
err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
pthread_cond_destroy(cond);
error2:
pthread_condattr_destroy(&attr);
- return -err;
+ return UV__ERR(err);
}
#endif /* defined(__APPLE__) && defined(__MACH__) */
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
int r;
struct timespec ts;
+#if defined(__MVS__)
+ struct timeval tv;
+#endif
#if defined(__APPLE__) && defined(__MACH__)
ts.tv_sec = timeout / NANOSEC;
ts.tv_nsec = timeout % NANOSEC;
r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
#else
+#if defined(__MVS__)
+ if (gettimeofday(&tv, NULL))
+ abort();
+ timeout += tv.tv_sec * NANOSEC + tv.tv_usec * 1e3;
+#else
timeout += uv__hrtime(UV_CLOCK_PRECISE);
+#endif
ts.tv_sec = timeout / NANOSEC;
ts.tv_nsec = timeout % NANOSEC;
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
return 0;
if (r == ETIMEDOUT)
- return -ETIMEDOUT;
+ return UV_ETIMEDOUT;
abort();
- return -EINVAL; /* Satisfy the compiler. */
+ return UV_EINVAL; /* Satisfy the compiler. */
}
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
- return -pthread_barrier_init(barrier, NULL, count);
+ return UV__ERR(pthread_barrier_init(barrier, NULL, count));
}
int uv_key_create(uv_key_t* key) {
- return -pthread_key_create(key, NULL);
+ return UV__ERR(pthread_key_create(key, NULL));
}
uint64_t clamped_timeout;
if (cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (uv__is_active(handle))
uv_timer_stop(handle);
int uv_timer_again(uv_timer_t* handle) {
if (handle->timer_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (handle->repeat) {
uv_timer_stop(handle);
*/
type = uv_guess_handle(fd);
if (type == UV_FILE || type == UV_UNKNOWN_HANDLE)
- return -EINVAL;
+ return UV_EINVAL;
/* 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
newfd = r;
r = uv__dup2_cloexec(newfd, fd);
- if (r < 0 && r != -EINVAL) {
+ if (r < 0 && r != UV_EINVAL) {
/* EINVAL means newfd == fd which could conceivably happen if another
* thread called close(fd) between our calls to isatty() and open().
* That's a rather unlikely event but let's handle it anyway.
if (saved_flags == -1) {
if (newfd != -1)
uv__close(newfd);
- return -errno;
+ return UV__ERR(errno);
}
#endif
fd = uv__stream_fd(tty);
if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) {
if (tcgetattr(fd, &tty->orig_termios))
- return -errno;
+ return UV__ERR(errno);
/* This is used for uv_tty_reset_mode() */
uv_spinlock_lock(&termios_spinlock);
/* Apply changes after draining */
if (tcsetattr(fd, TCSADRAIN, &tmp))
- return -errno;
+ return UV__ERR(errno);
tty->mode = mode;
return 0;
while (err == -1 && errno == EINTR);
if (err == -1)
- return -errno;
+ return UV__ERR(errno);
*width = ws.ws_col;
*height = ws.ws_row;
saved_errno = errno;
if (!uv_spinlock_trylock(&termios_spinlock))
- return -EBUSY; /* In uv_tty_set_mode(). */
+ return UV_EBUSY; /* In uv_tty_set_mode(). */
err = 0;
if (orig_termios_fd != -1)
if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios))
- err = -errno;
+ err = UV__ERR(errno);
uv_spinlock_unlock(&termios_spinlock);
errno = saved_errno;
QUEUE_REMOVE(q);
req = QUEUE_DATA(q, uv_udp_send_t, queue);
- req->status = -ECANCELED;
+ req->status = UV_ECANCELED;
QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
}
if (errno == EAGAIN || errno == EWOULDBLOCK)
handle->recv_cb(handle, 0, &buf, NULL, 0);
else
- handle->recv_cb(handle, -errno, &buf, NULL, 0);
+ handle->recv_cb(handle, UV__ERR(errno), &buf, NULL, 0);
}
else {
const struct sockaddr *addr;
break;
}
- req->status = (size == -1 ? -errno : size);
+ req->status = (size == -1 ? UV__ERR(errno) : size);
/* Sending a datagram is an atomic operation: either all data
* is written or nothing is (and EMSGSIZE is raised). That is
#if defined(SO_REUSEPORT) && !defined(__linux__)
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
- return -errno;
+ return UV__ERR(errno);
#else
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
- return -errno;
+ return UV__ERR(errno);
#endif
return 0;
/* Check for bad flags. */
if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR))
- return -EINVAL;
+ return UV_EINVAL;
/* Cannot set IPv6-only mode on non-IPv6 socket. */
if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6)
- return -EINVAL;
+ return UV_EINVAL;
fd = handle->io_watcher.fd;
if (fd == -1) {
#ifdef IPV6_V6ONLY
yes = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) {
- err = -errno;
+ err = UV__ERR(errno);
return err;
}
#else
- err = -ENOTSUP;
+ err = UV_ENOTSUP;
return err;
#endif
}
if (bind(fd, addr, addrlen)) {
- err = -errno;
+ err = UV__ERR(errno);
if (errno == EAFNOSUPPORT)
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
* socket created with AF_INET to an AF_INET6 address or vice versa. */
- err = -EINVAL;
+ err = UV_EINVAL;
return err;
}
if (req->bufs == NULL) {
uv__req_unregister(handle->loop, req);
- return -ENOMEM;
+ return UV_ENOMEM;
}
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
/* already sending a message */
if (handle->send_queue_count != 0)
- return -EAGAIN;
+ return UV_EAGAIN;
err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
if (err)
if (size == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
- return -EAGAIN;
+ return UV_EAGAIN;
else
- return -errno;
+ return UV__ERR(errno);
}
return size;
optname = IP_DROP_MEMBERSHIP;
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
if (setsockopt(handle->io_watcher.fd,
sizeof(mreq))) {
#if defined(__MVS__)
if (errno == ENXIO)
- return -ENODEV;
+ return UV_ENODEV;
#endif
- return -errno;
+ return UV__ERR(errno);
}
return 0;
if (interface_addr) {
if (uv_ip6_addr(interface_addr, 0, &addr6))
- return -EINVAL;
+ return UV_EINVAL;
mreq.ipv6mr_interface = addr6.sin6_scope_id;
} else {
mreq.ipv6mr_interface = 0;
optname = IPV6_DROP_MEMBERSHIP;
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
if (setsockopt(handle->io_watcher.fd,
sizeof(mreq))) {
#if defined(__MVS__)
if (errno == ENXIO)
- return -ENODEV;
+ return UV_ENODEV;
#endif
- return -errno;
+ return UV__ERR(errno);
}
return 0;
/* Use the lower 8 bits for the domain */
domain = flags & 0xFF;
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
- return -EINVAL;
+ return UV_EINVAL;
if (flags & ~0xFF)
- return -EINVAL;
+ return UV_EINVAL;
if (domain != AF_UNSPEC) {
err = uv__socket(domain, SOCK_DGRAM, 0);
/* Check for already active socket. */
if (handle->io_watcher.fd != -1)
- return -EBUSY;
+ return UV_EBUSY;
err = uv__nonblock(sock, 1);
if (err)
return err;
return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
} else {
- return -EINVAL;
+ return UV_EINVAL;
}
}
val,
size);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
#endif
if (val < 0 || val > 255)
- return -EINVAL;
+ return UV_EINVAL;
return uv__setsockopt(handle, option4, option6, &arg, sizeof(arg));
}
SO_BROADCAST,
&on,
sizeof(on))) {
- return -errno;
+ return UV__ERR(errno);
}
return 0;
int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
if (ttl < 1 || ttl > 255)
- return -EINVAL;
+ return UV_EINVAL;
#if defined(__MVS__)
if (!(handle->flags & UV_HANDLE_IPV6))
- return -ENOTSUP; /* zOS does not support setting ttl for IPv4 */
+ return UV_ENOTSUP; /* zOS does not support setting ttl for IPv4 */
#endif
/*
} else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
/* nothing, address was parsed */
} else {
- return -EINVAL;
+ return UV_EINVAL;
}
if (addr_st.ss_family == AF_INET) {
IP_MULTICAST_IF,
(void*) &addr4->sin_addr,
sizeof(addr4->sin_addr)) == -1) {
- return -errno;
+ return UV__ERR(errno);
}
} else if (addr_st.ss_family == AF_INET6) {
if (setsockopt(handle->io_watcher.fd,
IPV6_MULTICAST_IF,
&addr6->sin6_scope_id,
sizeof(addr6->sin6_scope_id)) == -1) {
- return -errno;
+ return UV__ERR(errno);
}
} else {
assert(0 && "unexpected address family");
socklen_t socklen;
if (handle->io_watcher.fd == -1)
- return -EINVAL; /* FIXME(bnoordhuis) -EBADF */
+ return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getsockname(handle->io_watcher.fd, name, &socklen))
- return -errno;
+ return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
int err;
if (alloc_cb == NULL || recv_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (uv__io_active(&handle->io_watcher, POLLIN))
- return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */
+ return UV_EALREADY; /* FIXME(bnoordhuis) Should be UV_EBUSY. */
err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0);
if (err)
void* saved_data;
#endif
- if (!QUEUE_EMPTY(&(loop)->active_reqs))
+ if (uv__has_active_reqs(loop))
return UV_EBUSY;
QUEUE_FOREACH(q, &loop->handle_queue) {
#include "tree.h"
#include "queue.h"
+#if EDOM > 0
+# define UV__ERR(x) (-(x))
+#else
+# define UV__ERR(x) (x)
+#endif
+
#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
extern int snprintf(char*, size_t, const char*, ...);
#endif
void uv__fs_scandir_cleanup(uv_fs_t* req);
#define uv__has_active_reqs(loop) \
- (QUEUE_EMPTY(&(loop)->active_reqs) == 0)
+ ((loop)->active_reqs.count > 0)
#define uv__req_register(loop, req) \
do { \
- QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue); \
+ (loop)->active_reqs.count++; \
} \
while (0)
#define uv__req_unregister(loop, req) \
do { \
assert(uv__has_active_reqs(loop)); \
- QUEUE_REMOVE(&(req)->active_queue); \
+ (loop)->active_reqs.count--; \
} \
while (0)
QUEUE_INIT(&loop->wq);
QUEUE_INIT(&loop->handle_queue);
- QUEUE_INIT(&loop->active_reqs);
+ loop->active_reqs.count = 0;
loop->active_handles = 0;
loop->pending_reqs_tail = NULL;
static int uv__loop_alive(const uv_loop_t* loop) {
- return loop->active_handles > 0 ||
- !QUEUE_EMPTY(&loop->active_reqs) ||
+ return uv__has_active_handles(loop) ||
+ uv__has_active_reqs(loop) ||
loop->endgame_handles != NULL;
}
return 0;
}
+
+int uv_cpumask_size(void) {
+ return (int)(sizeof(DWORD_PTR) * 8);
+}
size_t relpathlen;
size_t filenamelen = wcslen(filename);
size_t dirlen = wcslen(dir);
+ assert(!_wcsnicmp(filename, dir, dirlen));
if (dirlen > 0 && dir[dirlen - 1] == '\\')
dirlen--;
relpathlen = filenamelen - dirlen - 1;
uv_fs_event_cb cb,
const char* path,
unsigned int flags) {
- int name_size, is_path_dir;
+ int name_size, is_path_dir, size;
DWORD attr, last_error;
WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
WCHAR short_path_buffer[MAX_PATH];
- WCHAR* short_path;
+ WCHAR* short_path, *long_path;
if (uv__is_active(handle))
return UV_EINVAL;
if (is_path_dir) {
/* path is a directory, so that's the directory that we will watch. */
+
+ /* Convert to long path. */
+ size = GetLongPathNameW(pathw, NULL, 0);
+
+ if (size) {
+ long_path = (WCHAR*)uv__malloc(size * sizeof(WCHAR));
+ if (!long_path) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
+ }
+
+ size = GetLongPathNameW(pathw, long_path, size);
+ if (size) {
+ long_path[size] = '\0';
+ } else {
+ uv__free(long_path);
+ long_path = NULL;
+ }
+ }
+
+ if (long_path) {
+ uv__free(pathw);
+ pathw = long_path;
+ }
+
dir_to_watch = pathw;
} else {
/*
/* Remove read-only attribute */
FILE_BASIC_INFORMATION basic = { 0 };
- basic.FileAttributes = info.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY);
+ basic.FileAttributes = info.dwFileAttributes
+ & ~(FILE_ATTRIBUTE_READONLY)
+ | FILE_ATTRIBUTE_ARCHIVE;
status = pNtSetInformationFile(handle,
&iosb,
int overwrite;
flags = req->fs.info.file_flags;
+
+ if (flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
+ return;
+ }
+
overwrite = flags & UV_FS_COPYFILE_EXCL;
if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) {
INIT(UV_FS_COPYFILE);
- if (flags & ~UV_FS_COPYFILE_EXCL)
+ if (flags & ~(UV_FS_COPYFILE_EXCL |
+ UV_FS_COPYFILE_FICLONE |
+ UV_FS_COPYFILE_FICLONE_FORCE)) {
return UV_EINVAL;
+ }
err = fs__capture_path(req, path, new_path, cb != NULL);
DWORD bufsize;
int r;
+ uv__once_init();
+
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
- r = ConvertInterfaceIndexToLuid(ifindex, &luid);
+ if (pConvertInterfaceIndexToLuid == NULL)
+ return UV_ENOSYS;
+ r = pConvertInterfaceIndexToLuid(ifindex, &luid);
if (r != 0)
return uv_translate_sys_error(r);
- r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
+ if (pConvertInterfaceLuidToNameW == NULL)
+ return UV_ENOSYS;
+ r = pConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
if (r != 0)
return uv_translate_sys_error(r);
uv_req_t* req);
void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
uv_write_t* req);
-/* TODO: remove me */
+/*
+ * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* raw_req);
-/* TODO: remove me */
+/*
+ * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
uv_connect_t* req);
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);
+ }
handle->flags &= ~UV_HANDLE_READING;
uv__pipe_pause_read((uv_pipe_t*)handle);
uv__pipe_unpause_read((uv_pipe_t*)handle);
return;
}
+ /* Wait for completion via IOCP */
handle->reqs_pending++;
}
return UV_EINVAL;
}
+ if (options->cpumask != NULL) {
+ if (options->cpumask_size < (size_t)uv_cpumask_size()) {
+ return UV_EINVAL;
+ }
+ }
+
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
process_flags = CREATE_UNICODE_ENVIRONMENT;
if (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)
+ break;
+ if (i == options->stdio_count - 1)
+ process_flags |= CREATE_NO_WINDOW;
+ }
+
/* Use SW_HIDE to avoid any potential process window. */
startup.wShowWindow = SW_HIDE;
-
- /* Hide console windows. */
- process_flags |= CREATE_NO_WINDOW;
} else {
startup.wShowWindow = SW_SHOWDEFAULT;
}
process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
}
+ if (options->cpumask != NULL) {
+ /* Create the child in a suspended state so we have a chance to set
+ its process affinity before it runs. */
+ process_flags |= CREATE_SUSPENDED;
+ }
+
if (!CreateProcessW(application_path,
arguments,
NULL,
goto done;
}
+ if (options->cpumask != NULL) {
+ /* The child is currently suspended. Set its process affinity
+ or terminate it if we can't. */
+ int i;
+ int cpumasksize;
+ DWORD_PTR sysmask;
+ DWORD_PTR oldmask;
+ DWORD_PTR newmask;
+
+ cpumasksize = uv_cpumask_size();
+
+ if (!GetProcessAffinityMask(info.hProcess, &oldmask, &sysmask)) {
+ err = GetLastError();
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+
+ newmask = 0;
+ for (i = 0; i < cpumasksize; i++) {
+ if (options->cpumask[i]) {
+ if (oldmask & (((DWORD_PTR)1) << i)) {
+ newmask |= ((DWORD_PTR)1) << i;
+ } else {
+ err = UV_EINVAL;
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+ }
+ }
+
+ if (!SetProcessAffinityMask(info.hProcess, newmask)) {
+ err = GetLastError();
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+
+ /* The process affinity of the child is set. Let it run. */
+ if (ResumeThread(info.hThread) == ((DWORD)-1)) {
+ err = GetLastError();
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+ }
+
/* Spawn succeeded */
/* Beyond this point, failure is reported asynchronously. */
handle->write_queue_size = 0;
handle->activecnt = 0;
handle->stream.conn.shutdown_req = NULL;
-}
-
-
-INLINE static void uv_connection_init(uv_stream_t* handle) {
- handle->flags |= UV_HANDLE_CONNECTION;
handle->stream.conn.write_reqs_pending = 0;
UV_REQ_INIT(&handle->read_req, UV_READ);
}
+INLINE static void uv_connection_init(uv_stream_t* handle) {
+ handle->flags |= UV_HANDLE_CONNECTION;
+}
+
+
#endif /* UV_WIN_STREAM_INL_H_ */
INFINITE, WT_EXECUTEINWAITTHREAD)) {
SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req(loop, (uv_req_t*)req);
- handle->reqs_pending++;
- return;
}
} else {
/* Make this req pending reporting an error. */
err = 0;
if (REQ_SUCCESS(req)) {
- if (setsockopt(handle->socket,
- SOL_SOCKET,
- SO_UPDATE_CONNECT_CONTEXT,
- NULL,
- 0) == 0) {
+ if (handle->flags & UV__HANDLE_CLOSING) {
+ /* use UV_ECANCELED for consistency with Unix */
+ err = ERROR_OPERATION_ABORTED;
+ } else if (setsockopt(handle->socket,
+ SOL_SOCKET,
+ SO_UPDATE_CONNECT_CONTEXT,
+ NULL,
+ 0) == 0) {
uv_connection_init((uv_stream_t*)handle);
handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
loop->active_tcp_streams++;
}
-/* TODO: remove me */
+/*
+ * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* raw_req) {
abort();
}
-/* TODO: remove me */
+/*
+ * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
uv_connect_t* req) {
abort();
#include <tlhelp32.h>
#include <windows.h>
#include <userenv.h>
-
+#include <math.h>
/*
* Max title length; the only thing MSDN tells us about the maximum length
BYTE* address = (BYTE*) object_type + object_type->DefinitionLength +
counter_definition->CounterOffset;
uint64_t value = *((uint64_t*) address);
- *uptime = (double) (object_type->PerfTime.QuadPart - value) /
- (double) object_type->PerfFreq.QuadPart;
+ *uptime = floor((double) (object_type->PerfTime.QuadPart - value) /
+ (double) object_type->PerfFreq.QuadPart);
uv__free(malloced_buffer);
return 0;
}
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
DWORD sppi_size;
SYSTEM_INFO system_info;
- DWORD cpu_count, r, i;
+ DWORD cpu_count, i;
NTSTATUS status;
ULONG result_size;
int err;
assert(len > 0 && len < ARRAY_SIZE(key_name));
- r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- key_name,
- 0,
- KEY_QUERY_VALUE,
- &processor_key);
- if (r != ERROR_SUCCESS) {
- err = GetLastError();
+ err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ key_name,
+ 0,
+ KEY_QUERY_VALUE,
+ &processor_key);
+ if (err != ERROR_SUCCESS) {
goto error;
}
- if (RegQueryValueExW(processor_key,
- L"~MHz",
- NULL,
- NULL,
- (BYTE*) &cpu_speed,
- &cpu_speed_size) != ERROR_SUCCESS) {
- err = GetLastError();
+ err = RegQueryValueExW(processor_key,
+ L"~MHz",
+ NULL,
+ NULL,
+ (BYTE*)&cpu_speed,
+ &cpu_speed_size);
+ if (err != ERROR_SUCCESS) {
RegCloseKey(processor_key);
goto error;
}
- if (RegQueryValueExW(processor_key,
- L"ProcessorNameString",
- NULL,
- NULL,
- (BYTE*) &cpu_brand,
- &cpu_brand_size) != ERROR_SUCCESS) {
- err = GetLastError();
+ err = RegQueryValueExW(processor_key,
+ L"ProcessorNameString",
+ NULL,
+ NULL,
+ (BYTE*)&cpu_brand,
+ &cpu_brand_size);
+ if (err != ERROR_SUCCESS) {
RegCloseKey(processor_key);
goto error;
}
int uv_os_homedir(char* buffer, size_t* size) {
uv_passwd_t pwd;
- wchar_t path[MAX_PATH];
- DWORD bufsize;
size_t len;
int r;
- if (buffer == NULL || size == NULL || *size == 0)
- return UV_EINVAL;
-
- /* Check if the USERPROFILE environment variable is set first */
- len = GetEnvironmentVariableW(L"USERPROFILE", path, MAX_PATH);
+ /* Check if the USERPROFILE environment variable is set first. The task of
+ performing input validation on buffer and size is taken care of by
+ uv_os_getenv(). */
+ r = uv_os_getenv("USERPROFILE", buffer, size);
- if (len == 0) {
- r = GetLastError();
-
- /* Don't return an error if USERPROFILE was not found */
- if (r != ERROR_ENVVAR_NOT_FOUND)
- return uv_translate_sys_error(r);
- } else if (len > MAX_PATH) {
- /* This should not be possible */
- return UV_EIO;
- } else {
- /* Check how much space we need */
- bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
-
- if (bufsize == 0) {
- return uv_translate_sys_error(GetLastError());
- } else if (bufsize > *size) {
- *size = bufsize;
- return UV_ENOBUFS;
- }
-
- /* Convert to UTF-8 */
- bufsize = WideCharToMultiByte(CP_UTF8,
- 0,
- path,
- -1,
- buffer,
- *size,
- NULL,
- NULL);
-
- if (bufsize == 0)
- return uv_translate_sys_error(GetLastError());
-
- *size = bufsize - 1;
- return 0;
- }
+ /* Don't return an error if USERPROFILE was not found. */
+ if (r != UV_ENOENT)
+ return r;
/* USERPROFILE is not set, so call uv__getpwuid_r() */
r = uv__getpwuid_r(&pwd);
/* 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;
ntdll_module = GetModuleHandleA("ntdll.dll");
if (ntdll_module == NULL) {
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");
+ }
}
/* 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_ */
memcpy(dest6, addr, sizeof(*dest6));
if (memcmp(&dest6->sin6_addr,
&uv_addr_ip6_any_.sin6_addr,
- sizeof(uv_addr_ip6_any_.sin6_addr)) == 0)
- dest6->sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
+ sizeof(uv_addr_ip6_any_.sin6_addr)) == 0) {
+ struct in6_addr init_sin6_addr = IN6ADDR_LOOPBACK_INIT;
+ dest6->sin6_addr = init_sin6_addr;
+ }
return 0;
default:
return UV_EINVAL;
cmake_bootstrap_system_libs=""
cmake_bootstrap_qt_gui=""
cmake_bootstrap_qt_qmake=""
+cmake_sphinx_info=""
cmake_sphinx_man=""
cmake_sphinx_html=""
cmake_sphinx_qthelp=""
cmGlobalCommonGenerator \
cmGlobalGenerator \
cmGlobalUnixMakefileGenerator3 \
+ cmGlobVerificationManager \
cmHexFileConverter \
cmIfCommand \
cmIncludeCommand \
cmState \
cmStateDirectory \
cmStateSnapshot \
+ cmStringReplaceHelper \
cmStringCommand \
cmSubdirCommand \
cmSystemTools \
--no-qt-gui do not build the Qt-based GUI (default)
--qt-qmake=<qmake> use <qmake> as the qmake executable to find Qt
+ --sphinx-info build Info manual with Sphinx
--sphinx-man build man pages with Sphinx
--sphinx-html build html help with Sphinx
--sphinx-qthelp build qch help with Sphinx
--qt-gui) cmake_bootstrap_qt_gui="1" ;;
--no-qt-gui) cmake_bootstrap_qt_gui="0" ;;
--qt-qmake=*) cmake_bootstrap_qt_qmake=`cmake_arg "$1"` ;;
+ --sphinx-info) cmake_sphinx_info="1" ;;
--sphinx-man) cmake_sphinx_man="1" ;;
--sphinx-html) cmake_sphinx_html="1" ;;
--sphinx-qthelp) cmake_sphinx_qthelp="1" ;;
--version) cmake_version_display ; exit 2 ;;
--verbose) cmake_verbose=TRUE ;;
--enable-ccache) cmake_ccache_enabled=TRUE ;;
+ CC=*) CC=`cmake_arg "$1"` ;;
+ CXX=*) CXX=`cmake_arg "$1"` ;;
+ CFLAGS=*) CFLAGS=`cmake_arg "$1"` ;;
+ CXXFLAGS=*) CXXFLAGS=`cmake_arg "$1"` ;;
+ LDFLAGS=*) LDFLAGS=`cmake_arg "$1"` ;;
--) shift; break ;;
*) die "Unknown option: $1" ;;
esac
rm -f "${TMPFILE}.cxx"
if [ -z "${cmake_cxx_compiler}" ]; then
-cmake_error 7 "Cannot find a C++ compiler supporting C++11 on this system.
+cmake_error 7 "Cannot find a C++ compiler that supports both C++11 and the specified C++ flags.
Please specify one using environment variable CXX.
+The C++ flags are \"$cmake_cxx_flags\".
+They can be changed using the environment variable CXXFLAGS.
See cmake_bootstrap.log for compilers attempted."
fi
echo "C++ compiler on this system is: ${cmake_cxx_compiler} ${cmake_cxx_flags}"
echo "${cmake_cxx_compiler} does not have <ext/stdio_filebuf.h>"
fi
+if [ -n "${cmake_ccache_enabled}" ]; then
+ echo "Building CMake with ccache"
+ cmake_c_compiler="ccache ${cmake_c_compiler}"
+ cmake_cxx_compiler="ccache ${cmake_cxx_compiler}"
+fi
+
# Just to be safe, let us store compiler and flags to the header file
cmake_bootstrap_version='$Revision$'
set (QT_QMAKE_EXECUTABLE "'"${cmake_bootstrap_qt_qmake}"'" CACHE FILEPATH "Location of Qt qmake" FORCE)
' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
fi
+if [ "x${cmake_sphinx_info}" != "x" ]; then
+ echo '
+set (SPHINX_INFO "'"${cmake_sphinx_info}"'" CACHE BOOL "Build Info manual with Sphinx" FORCE)
+' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
+fi
if [ "x${cmake_sphinx_man}" != "x" ]; then
echo '
set (SPHINX_MAN "'"${cmake_sphinx_man}"'" CACHE BOOL "Build man pages with Sphinx" FORCE)
# build with same compiler and make
CC="${cmake_c_compiler}"
CXX="${cmake_cxx_compiler}"
-if [ -n "${cmake_ccache_enabled}" ]; then
- CC="ccache ${CC}"
- CXX="ccache ${CXX}"
-fi
MAKE="${cmake_make_processor}"
export CC
export CXX
export MAKE
+export CFLAGS
+export CXXFLAGS
+export LDFLAGS
# Run bootstrap CMake to configure real CMake
cmake_options="-DCMAKE_BOOTSTRAP=1"