diff options
123 files changed, 3080 insertions, 2096 deletions
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index e3fb6b6..5f74c54 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -216,10 +216,9 @@ When the command will happen is determined by which of the following is specified: ``PRE_BUILD`` - Run before any other rules are executed within the target. - This is supported only on Visual Studio 9 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. diff --git a/Help/command/file.rst b/Help/command/file.rst index 43ce3d9..d4a6006 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -3,23 +3,44 @@ file 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: :: @@ -31,7 +52,7 @@ Read content from a file called ``<filename>`` and store it in a read at most ``<max-in>`` bytes. The ``HEX`` option causes data to be converted to a hexadecimal representation (useful for binary data). ------------------------------------------------------------------------------- +.. _STRINGS: :: @@ -82,7 +103,7 @@ For example, the code stores a list in the variable ``myfile`` in which each item is a line from the input file. ------------------------------------------------------------------------------- +.. _HASH: :: @@ -93,7 +114,108 @@ store it in a ``<variable>``. The supported ``<HASH>`` algorithm names 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: :: @@ -148,7 +270,7 @@ Examples of recursive globbing include:: /dir/*.py - match all python files in /dir and subdirectories ------------------------------------------------------------------------------- +.. _RENAME: :: @@ -157,7 +279,8 @@ Examples of recursive globbing include:: Move a file or directory within a filesystem from ``<oldname>`` to ``<newname>``, replacing the destination atomically. ------------------------------------------------------------------------------- +.. _REMOVE: +.. _REMOVE_RECURSE: :: @@ -168,7 +291,7 @@ Remove the given files. The ``REMOVE_RECURSE`` mode will remove the given files and directories, also non-empty directories. No error is emitted if a given file does not exist. ------------------------------------------------------------------------------- +.. _MAKE_DIRECTORY: :: @@ -176,7 +299,44 @@ given file does not exist. 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: :: @@ -185,7 +345,8 @@ Create the given directories and their parents as needed. Compute the relative path from a ``<directory>`` to a ``<file>`` and store it in the ``<variable>``. ------------------------------------------------------------------------------- +.. _TO_CMAKE_PATH: +.. _TO_NATIVE_PATH: :: @@ -203,7 +364,11 @@ path with platform-specific slashes (``\`` on Windows and ``/`` elsewhere). Always use double quotes around the ``<path>`` to be sure it is treated as a single argument to this command. ------------------------------------------------------------------------------- +Transfer +^^^^^^^^ + +.. _DOWNLOAD: +.. _UPLOAD: :: @@ -290,116 +455,10 @@ check certificates and/or use ``EXPECTED_HASH`` to verify downloaded content. If neither ``TLS`` option is given CMake will check variables ``CMAKE_TLS_VERIFY`` and ``CMAKE_TLS_CAINFO``, respectively. ------------------------------------------------------------------------------- - -:: - - 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. - ------------------------------------------------------------------------------- - -:: - - 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: :: diff --git a/Help/command/install.rst b/Help/command/install.rst index d3818d6..6cea996 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -1,11 +1,19 @@ 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 ^^^^^^^^^^^^ @@ -84,6 +92,8 @@ to control which messages are printed. Installing Targets ^^^^^^^^^^^^^^^^^^ +.. _TARGETS: + :: install(TARGETS targets... [EXPORT <export-name>] @@ -93,6 +103,7 @@ Installing Targets [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] + [NAMELINK_COMPONENT <component>] [OPTIONAL] [EXCLUDE_FROM_ALL] [NAMELINK_ONLY|NAMELINK_SKIP] ] [...] @@ -100,63 +111,144 @@ Installing Targets ) 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 @@ -178,11 +270,6 @@ the ``mySharedLib`` DLL will be installed to ``<prefix>/bin`` and ``/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 @@ -200,6 +287,9 @@ use "generator expressions" with the syntax ``$<...>``. See the Installing Files ^^^^^^^^^^^^^^^^ +.. _FILES: +.. _PROGRAMS: + :: install(<FILES|PROGRAMS> files... DESTINATION <dir> @@ -233,6 +323,8 @@ use "generator expressions" with the syntax ``$<...>``. See the Installing Directories ^^^^^^^^^^^^^^^^^^^^^^ +.. _DIRECTORY: + :: install(DIRECTORY dirs... DESTINATION <dir> @@ -314,6 +406,9 @@ manual for available expressions. Custom Installation Logic ^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _CODE: +.. _SCRIPT: + :: install([[SCRIPT <file>] [CODE <code>]] @@ -335,6 +430,8 @@ will print a message during installation. Installing Exports ^^^^^^^^^^^^^^^^^^ +.. _EXPORT: + :: install(EXPORT <export-name> DESTINATION <dir> @@ -361,11 +458,24 @@ generated import file will reference only the matching target 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. +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 diff --git a/Help/command/list.rst b/Help/command/list.rst index 67e9743..589e572 100644 --- a/Help/command/list.rst +++ b/Help/command/list.rst @@ -1,11 +1,37 @@ list ---- -.. only:: html +List operations. - .. contents:: +Synopsis +^^^^^^^^ -List operations. +.. 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 @@ -33,11 +59,10 @@ scope. To propagate the results of these operations upwards, use Be careful when counting with negative indices: they do not start from 0. -0 is equivalent to 0, the first list element. -Capacity and Element access -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Reading +^^^^^^^ -LENGTH -"""""" +.. _LENGTH: :: @@ -45,8 +70,7 @@ LENGTH Returns the list's length. -GET -""" +.. _GET: :: @@ -54,8 +78,7 @@ GET Returns the list of elements specified by indices from the list. -JOIN -"""" +.. _JOIN: :: @@ -65,8 +88,7 @@ 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 -""""""" +.. _SUBLIST: :: @@ -80,8 +102,7 @@ the remaining elements of the list starting at ``<begin>`` will be returned. Search ^^^^^^ -FIND -"""" +.. _FIND: :: @@ -93,8 +114,7 @@ if it wasn't found. Modification ^^^^^^^^^^^^ -APPEND -"""""" +.. _APPEND: :: @@ -102,8 +122,7 @@ APPEND Appends elements to the list. -FILTER -"""""" +.. _FILTER: :: @@ -115,8 +134,7 @@ 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 -"""""" +.. _INSERT: :: @@ -124,8 +142,7 @@ INSERT Inserts elements to the list to the specified location. -REMOVE_ITEM -""""""""""" +.. _REMOVE_ITEM: :: @@ -133,8 +150,7 @@ REMOVE_ITEM Removes the given items from the list. -REMOVE_AT -""""""""" +.. _REMOVE_AT: :: @@ -142,8 +158,7 @@ REMOVE_AT Removes items at given indices from the list. -REMOVE_DUPLICATES -""""""""""""""""" +.. _REMOVE_DUPLICATES: :: @@ -151,8 +166,7 @@ REMOVE_DUPLICATES Removes duplicated items in the list. -TRANSFORM -""""""""" +.. _TRANSFORM: :: @@ -224,11 +238,10 @@ expression will be transformed. :: list(TRANSFORM <list> <ACTION> REGEX <regular_expression> ...) -Sorting -^^^^^^^ +Ordering +^^^^^^^^ -REVERSE -""""""" +.. _REVERSE: :: @@ -236,8 +249,7 @@ REVERSE Reverses the contents of the list in-place. -SORT -"""" +.. _SORT: :: diff --git a/Help/command/project.rst b/Help/command/project.rst index e46dd69..c1de057 100644 --- a/Help/command/project.rst +++ b/Help/command/project.rst @@ -76,8 +76,9 @@ call exists CMake will implicitly add one to the top that enables the 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` and its homepage URL from -:variable:`CMAKE_PROJECT_HOMEPAGE_URL`. +: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 diff --git a/Help/command/string.rst b/Help/command/string.rst index e84f788..efa923b 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -1,17 +1,52 @@ 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: :: @@ -22,8 +57,7 @@ the supplied string. If the ``REVERSE`` flag was used, the command will 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: :: @@ -37,8 +71,7 @@ with ``replace_string`` and store the result in the output. Regular Expressions ^^^^^^^^^^^^^^^^^^^ -REGEX MATCH -""""""""""" +.. _`REGEX MATCH`: :: @@ -48,8 +81,7 @@ 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`: :: @@ -60,8 +92,7 @@ Match the regular expression as many times as possible and store the matches in the output variable as a list. All ``<input>`` arguments are concatenated before matching. -REGEX REPLACE -""""""""""""" +.. _`REGEX REPLACE`: :: @@ -123,8 +154,7 @@ expression ``^(ab|cd)$`` matches ``ab`` but not ``abd``. Manipulation ^^^^^^^^^^^^ -APPEND -"""""" +.. _APPEND: :: @@ -132,8 +162,7 @@ APPEND Append all the input arguments to the string. -PREPEND -""""""" +.. _PREPEND: :: @@ -141,8 +170,7 @@ PREPEND Prepend all the input arguments to the string. -CONCAT -"""""" +.. _CONCAT: :: @@ -151,8 +179,7 @@ CONCAT Concatenate all the input arguments together and store the result in the named output variable. -JOIN -"""" +.. _JOIN: :: @@ -165,8 +192,7 @@ 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 -""""""" +.. _TOLOWER: :: @@ -174,8 +200,7 @@ TOLOWER Convert string to lower characters. -TOUPPER -""""""" +.. _TOUPPER: :: @@ -183,8 +208,7 @@ TOUPPER Convert string to upper characters. -LENGTH -"""""" +.. _LENGTH: :: @@ -192,8 +216,7 @@ LENGTH Store in an output variable a given string's length. -SUBSTRING -""""""""" +.. _SUBSTRING: :: @@ -207,8 +230,7 @@ If string is shorter than length then end of string is used instead. CMake 3.1 and below reported an error if length pointed past the end of string. -STRIP -""""" +.. _STRIP: :: @@ -217,8 +239,7 @@ STRIP Store in an output variable a substring of a given string with leading and trailing spaces removed. -GENEX_STRIP -""""""""""" +.. _GENEX_STRIP: :: @@ -230,6 +251,8 @@ from the ``input string`` and store the result in the ``output variable``. Comparison ^^^^^^^^^^ +.. _COMPARE: + :: string(COMPARE LESS <string1> <string2> <output variable>) @@ -246,6 +269,8 @@ Compare the strings and store true or false in the output variable. Hashing ^^^^^^^ +.. _`HASH`: + :: string(<HASH> <output variable> <input>) @@ -277,8 +302,7 @@ The supported ``<HASH>`` algorithm names are: Generation ^^^^^^^^^^ -ASCII -""""" +.. _ASCII: :: @@ -286,8 +310,7 @@ ASCII Convert all numbers into corresponding ASCII characters. -CONFIGURE -""""""""" +.. _CONFIGURE: :: @@ -296,8 +319,7 @@ CONFIGURE Transform a string like :command:`configure_file` transforms a file. -MAKE_C_IDENTIFIER -""""""""""""""""" +.. _MAKE_C_IDENTIFIER: :: @@ -308,8 +330,7 @@ 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 -"""""" +.. _RANDOM: :: @@ -322,8 +343,7 @@ and default alphabet is all numbers and upper and lower case letters. If an integer ``RANDOM_SEED`` is given, its value will be used to seed the random number generator. -TIMESTAMP -""""""""" +.. _TIMESTAMP: :: @@ -378,8 +398,7 @@ If no explicit ``<format string>`` is given it will default to: its value will be used instead of the current time. See https://reproducible-builds.org/specs/source-date-epoch/ for details. -UUID -"""" +.. _UUID: :: diff --git a/Help/manual/cmake-server.7.rst b/Help/manual/cmake-server.7.rst index 0fed0b1..25d364c 100644 --- a/Help/manual/cmake-server.7.rst +++ b/Help/manual/cmake-server.7.rst @@ -49,10 +49,12 @@ Operation 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:: diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 44271c1..7636305 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -69,6 +69,11 @@ Variables that Provide Information /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 diff --git a/Help/prop_sf/COMPILE_FLAGS.rst b/Help/prop_sf/COMPILE_FLAGS.rst index be81cf6..c211b89 100644 --- a/Help/prop_sf/COMPILE_FLAGS.rst +++ b/Help/prop_sf/COMPILE_FLAGS.rst @@ -3,9 +3,9 @@ COMPILE_FLAGS Additional flags to be added when compiling this source file. -The ``COMPILE_FLAGS`` property sets additional compiler flags used to build -source files. Use :prop_sf:`COMPILE_DEFINITIONS` to pass additional -preprocessor definitions. +The ``COMPILE_FLAGS`` property, managed as a string, sets additional compiler +flags used to build source files. Use :prop_sf:`COMPILE_DEFINITIONS` to pass +additional preprocessor definitions. Contents of ``COMPILE_FLAGS`` may use "generator expressions" with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` @@ -13,3 +13,7 @@ manual for available expressions. However, :generator:`Xcode` does not support per-config per-source settings, so expressions that depend on the build configuration are not allowed with that generator. + +.. note:: + + This property has been superseded by the :prop_sf:`COMPILE_OPTIONS` property. diff --git a/Help/prop_sf/COMPILE_OPTIONS.rst b/Help/prop_sf/COMPILE_OPTIONS.rst index 157c0b0..3b2bc8d 100644 --- a/Help/prop_sf/COMPILE_OPTIONS.rst +++ b/Help/prop_sf/COMPILE_OPTIONS.rst @@ -15,3 +15,7 @@ for available expressions. However, :generator:`Xcode` does not support per-config per-source settings, so expressions that depend on the build configuration are not allowed with that generator. + +.. note:: + + This property should be preferred over the :prop_sf:`COMPILE_FLAGS` property. diff --git a/Help/release/dev/cpack-use-project-version.rst b/Help/release/dev/cpack-use-project-version.rst new file mode 100644 index 0000000..b17754a --- /dev/null +++ b/Help/release/dev/cpack-use-project-version.rst @@ -0,0 +1,10 @@ +cpack-use-project-version +------------------------- + +* Introduce :variable:`CMAKE_PROJECT_VERSION` and the corresponding components: + :variable:`CMAKE_PROJECT_VERSION_MAJOR`, :variable:`CMAKE_PROJECT_VERSION_MINOR`, + :variable:`CMAKE_PROJECT_VERSION_PATCH` and :variable:`CMAKE_PROJECT_VERSION_TWEAK`. + +* :module:`CPack` module use :variable:`CMAKE_PROJECT_VERSION_MAJOR`, + :variable:`CMAKE_PROJECT_VERSION_MINOR` and :variable:`CMAKE_PROJECT_VERSION_PATCH` + to initialize corresponding CPack variables. diff --git a/Help/release/dev/namelink-component.rst b/Help/release/dev/namelink-component.rst new file mode 100644 index 0000000..aaeb04f --- /dev/null +++ b/Help/release/dev/namelink-component.rst @@ -0,0 +1,7 @@ +namelink-component +------------------ + +* 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. diff --git a/Help/variable/CMAKE_PROJECT_VERSION.rst b/Help/variable/CMAKE_PROJECT_VERSION.rst new file mode 100644 index 0000000..4f8f556 --- /dev/null +++ b/Help/variable/CMAKE_PROJECT_VERSION.rst @@ -0,0 +1,35 @@ +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. diff --git a/Help/variable/CMAKE_PROJECT_VERSION_MAJOR.rst b/Help/variable/CMAKE_PROJECT_VERSION_MAJOR.rst new file mode 100644 index 0000000..f1001ac --- /dev/null +++ b/Help/variable/CMAKE_PROJECT_VERSION_MAJOR.rst @@ -0,0 +1,9 @@ +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. diff --git a/Help/variable/CMAKE_PROJECT_VERSION_MINOR.rst b/Help/variable/CMAKE_PROJECT_VERSION_MINOR.rst new file mode 100644 index 0000000..13202be --- /dev/null +++ b/Help/variable/CMAKE_PROJECT_VERSION_MINOR.rst @@ -0,0 +1,9 @@ +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. diff --git a/Help/variable/CMAKE_PROJECT_VERSION_PATCH.rst b/Help/variable/CMAKE_PROJECT_VERSION_PATCH.rst new file mode 100644 index 0000000..b8570d9 --- /dev/null +++ b/Help/variable/CMAKE_PROJECT_VERSION_PATCH.rst @@ -0,0 +1,9 @@ +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. diff --git a/Help/variable/CMAKE_PROJECT_VERSION_TWEAK.rst b/Help/variable/CMAKE_PROJECT_VERSION_TWEAK.rst new file mode 100644 index 0000000..e1ad4be --- /dev/null +++ b/Help/variable/CMAKE_PROJECT_VERSION_TWEAK.rst @@ -0,0 +1,9 @@ +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. diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index a71f84a..f6d74c5 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -80,15 +80,35 @@ # # .. variable:: CPACK_PACKAGE_VERSION_MAJOR # -# Package major Version. Default value is 0. +# 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. Default value is 1. +# 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. Default value is 1. +# 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_FILE # @@ -367,11 +387,28 @@ endfunction() # 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 diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index a0e4aa9..dc55e86 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -1769,7 +1769,7 @@ function(CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS output_file cuda_target options add_custom_command( OUTPUT ${output_file} DEPENDS ${object_files} - COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} -dlink ${object_files} ${CUDA_cublas_device_LIBRARY} -o ${output_file} + COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} -dlink ${object_files} -o ${output_file} ${flags} COMMENT "Building NVCC intermediate link file ${output_file_relative_path}" COMMAND_EXPAND_LISTS @@ -1782,7 +1782,7 @@ function(CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS output_file cuda_target options PRE_LINK COMMAND ${CMAKE_COMMAND} -E echo "Building NVCC intermediate link file ${output_file_relative_path}" COMMAND ${CMAKE_COMMAND} -E make_directory "${output_file_dir}" - COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} ${flags} -dlink ${object_files} ${CUDA_cublas_device_LIBRARY} -o "${output_file}" + COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} ${flags} -dlink ${object_files} -o "${output_file}" COMMAND_EXPAND_LISTS ${_verbatim} ) diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake index ff8d353..4913e05 100644 --- a/Modules/FindJNI.cmake +++ b/Modules/FindJNI.cmake @@ -128,7 +128,7 @@ if (WIN32) OUTPUT_VARIABLE _JNI_VERSIONS ERROR_QUIET) if (NOT _JNI_RESULT) - string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\JDK\\\\[0-9\.]+" _JNI_VERSIONS "${_JNI_VERSIONS}") + string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\JDK\\\\[0-9.]+" _JNI_VERSIONS "${_JNI_VERSIONS}") if (_JNI_VERSIONS) # sort versions. Most recent first ## handle version 9 apart from other versions to get correct ordering @@ -141,7 +141,7 @@ if (WIN32) list (REVERSE _JNI_V9) list (APPEND _JNI_VERSIONS ${_JNI_V9}) foreach (_JNI_HINT IN LISTS _JNI_VERSIONS) - list(APPEND _JNI_HINTS "[${_JNI_HINT}\\MSI;INSTALLDIR]") + list(APPEND _JNI_HINTS "[${_JNI_HINT};JavaHome]") endforeach() endif() endif() diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake index 95e551f..cddc5d2 100644 --- a/Modules/FindJava.cmake +++ b/Modules/FindJava.cmake @@ -97,7 +97,7 @@ if (WIN32) list (REVERSE _JAVA_V9) list (APPEND _JAVA_VERSIONS ${_JAVA_V9}) foreach (_JAVA_HINT IN LISTS _JAVA_VERSIONS) - list(APPEND _JAVA_HINTS "[${_JAVA_HINT}\\MSI;INSTALLDIR]/bin") + list(APPEND _JAVA_HINTS "[${_JAVA_HINT};JavaHome]/bin") endforeach() endif() endif() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 72ae68b..d57e52e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 11) -set(CMake_VERSION_PATCH 20180501) +set(CMake_VERSION_PATCH 20180508) #set(CMake_VERSION_RC 1) diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 1ec76ac..8e7e3ad 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -405,7 +405,8 @@ 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()); } @@ -664,7 +665,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, // 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 += "/"; @@ -691,7 +692,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, hname = pathname; hname += "."; hname += *ext; - if (cmSystemTools::FileExists(hname.c_str())) { + if (cmSystemTools::FileExists(hname)) { sf->SourceExtension = *ext; sf->FullPath = hname; return; @@ -704,7 +705,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, hname = pathname; hname += "."; hname += *ext; - if (cmSystemTools::FileExists(hname.c_str())) { + if (cmSystemTools::FileExists(hname)) { sf->SourceExtension = *ext; sf->FullPath = hname; return; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 399e894..7b35bce 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1013,16 +1013,7 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode 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 && diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index bf5ff65..799ae95 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -5510,12 +5510,14 @@ cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType( const std::string& config) const { // Only libraries and executables can be managed targets. - if (this->GetType() != cmStateEnums::SHARED_LIBRARY && - this->GetType() != cmStateEnums::STATIC_LIBRARY && - this->GetType() != cmStateEnums::EXECUTABLE) { + 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 = diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index b5291a1..b325b0c 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -33,16 +33,17 @@ class cmExecutionStatus; 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( @@ -313,6 +314,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) "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."); @@ -377,6 +392,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // any files of the given type. bool installsArchive = false; bool installsLibrary = false; + bool installsNamelink = false; bool installsRuntime = false; bool installsObject = false; bool installsFramework = false; @@ -391,6 +407,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) cmTarget& target = *ti; cmInstallTargetGenerator* archiveGenerator = nullptr; cmInstallTargetGenerator* libraryGenerator = nullptr; + cmInstallTargetGenerator* namelinkGenerator = nullptr; cmInstallTargetGenerator* runtimeGenerator = nullptr; cmInstallTargetGenerator* objectGenerator = nullptr; cmInstallTargetGenerator* frameworkGenerator = nullptr; @@ -453,9 +470,18 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } 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 { @@ -684,6 +710,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // 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; @@ -696,6 +723,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) this->Makefile->AddInstallGenerator(archiveGenerator); this->Makefile->AddInstallGenerator(libraryGenerator); + this->Makefile->AddInstallGenerator(namelinkGenerator); this->Makefile->AddInstallGenerator(runtimeGenerator); this->Makefile->AddInstallGenerator(objectGenerator); this->Makefile->AddInstallGenerator(frameworkGenerator); @@ -735,6 +763,10 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) 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()); diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx index 7b79ab5..2d6dc12 100644 --- a/Source/cmInstallCommandArguments.cxx +++ b/Source/cmInstallCommandArguments.cxx @@ -21,6 +21,7 @@ cmInstallCommandArguments::cmInstallCommandArguments( , 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) @@ -59,6 +60,14 @@ const std::string& cmInstallCommandArguments::GetComponent() const 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()) { @@ -125,6 +134,17 @@ bool cmInstallCommandArguments::GetNamelinkSkip() const 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 { diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h index a576e72..ee6e865 100644 --- a/Source/cmInstallCommandArguments.h +++ b/Source/cmInstallCommandArguments.h @@ -26,6 +26,7 @@ public: 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; @@ -33,6 +34,7 @@ public: 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 @@ -45,6 +47,7 @@ private: cmInstallCommandArguments(); // disabled cmCAString Destination; cmCAString Component; + cmCAString NamelinkComponent; cmCAEnabler ExcludeFromAll; cmCAString Rename; cmCAStringVector Permissions; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index b6bf08b..33e76b2 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1130,57 +1130,38 @@ cmTarget* cmMakefile::AddUtilityCommand( return target; } -void cmMakefile::AddDefineFlag(std::string const& flag) -{ - if (flag.empty()) { - return; - } - - // Update the string used for the old DEFINITIONS property. - this->AddDefineFlag(flag, this->DefineFlagsOrig); - - // If this is really a definition, update COMPILE_DEFINITIONS. - if (this->ParseDefineFlag(flag, false)) { - return; - } - - // Add this flag that does not look like a definition. - this->AddDefineFlag(flag, this->DefineFlags); -} - -void cmMakefile::AddDefineFlag(std::string const& flag, std::string& dflags) +static void s_AddDefineFlag(std::string const& flag, std::string& dflags) { // remove any \n\r std::string::size_type initSize = dflags.size(); - dflags += std::string(" ") + flag; + 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::RemoveDefineFlag(std::string const& flag) +void cmMakefile::AddDefineFlag(std::string const& flag) { - // Check the length of the flag to remove. 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_AddDefineFlag(flag, this->DefineFlagsOrig); // If this is really a definition, update COMPILE_DEFINITIONS. - if (this->ParseDefineFlag(flag, true)) { + if (this->ParseDefineFlag(flag, false)) { return; } - // Remove this flag that does not look like a definition. - this->RemoveDefineFlag(flag, len, this->DefineFlags); + // Add this flag that does not look like a definition. + s_AddDefineFlag(flag, this->DefineFlags); } -void cmMakefile::RemoveDefineFlag(std::string const& flag, - std::string::size_type len, - std::string& dflags) +static void s_RemoveDefineFlag(std::string const& flag, std::string& dflags) { + 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); @@ -1195,6 +1176,25 @@ void cmMakefile::RemoveDefineFlag(std::string const& flag, } } +void cmMakefile::RemoveDefineFlag(std::string const& flag) +{ + // Check the length of the flag to remove. + if (flag.empty()) { + return; + } + + // Update the string used for the old DEFINITIONS property. + s_RemoveDefineFlag(flag, this->DefineFlagsOrig); + + // If this is really a definition, update COMPILE_DEFINITIONS. + if (this->ParseDefineFlag(flag, true)) { + return; + } + + // Remove this flag that does not look like a definition. + s_RemoveDefineFlag(flag, this->DefineFlags); +} + void cmMakefile::AddCompileDefinition(std::string const& option) { this->AppendProperty("COMPILE_DEFINITIONS", option.c_str()); @@ -2412,12 +2412,13 @@ std::vector<std::string> cmMakefile::GetDefinitions() const 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 { @@ -2433,7 +2434,7 @@ const char* cmMakefile::ExpandVariablesInString( this->IssueMessage(cmake::INTERNAL_ERROR, "ExpandVariablesInString @ONLY called " "on something with escapes."); - return source.c_str(); + return source; } // Variables used in the WARN case. @@ -2515,7 +2516,7 @@ const char* cmMakefile::ExpandVariablesInString( this->IssueMessage(cmake::AUTHOR_WARNING, msg); } - return source.c_str(); + return source; } cmake::MessageType cmMakefile::ExpandVariablesInStringOld( diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 16b2047..9f32c4f 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -565,12 +565,11 @@ public: * 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 @@ -886,9 +885,6 @@ protected: 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) diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 6ddb0b8..a25bd6b 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -249,6 +249,12 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, 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; @@ -262,6 +268,13 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, 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); @@ -286,36 +299,14 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str()); this->Makefile->AddDefinition(projectName + "_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); - } + 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()); - // Set the CMAKE_PROJECT_HOMEPAGE_URL 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_HOMEPAGE_URL") || - (this->Makefile->IsRootMakefile())) { - this->Makefile->AddDefinition("CMAKE_PROJECT_HOMEPAGE_URL", - homepage.c_str()); - this->Makefile->AddCacheDefinition( - "CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str(), - "Value Computed by CMake", cmStateEnums::STATIC); - } + TopLevelCMakeVarCondSet("CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str()); } if (languages.empty()) { @@ -338,3 +329,18 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } 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); + } +} diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h index 80fa235..365d448 100644 --- a/Source/cmProjectCommand.h +++ b/Source/cmProjectCommand.h @@ -34,6 +34,9 @@ public: */ bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; + +private: + void TopLevelCMakeVarCondSet(const char* name, const char* value); }; #endif diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index 112be4d..d9e5bcb 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -34,11 +34,13 @@ cmRST::cmRST(std::ostream& os, std::string const& docroot) , 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_]|$)") @@ -245,18 +247,62 @@ void cmRST::OutputLine(std::string const& line_in, bool inlineMarkup) 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 { diff --git a/Source/cmRST.h b/Source/cmRST.h index d1a8e27..ee47867 100644 --- a/Source/cmRST.h +++ b/Source/cmRST.h @@ -85,6 +85,8 @@ private: cmsys::RegularExpression NoteDirective; cmsys::RegularExpression ModuleRST; cmsys::RegularExpression CMakeRole; + cmsys::RegularExpression InlineLink; + cmsys::RegularExpression InlineLiteral; cmsys::RegularExpression Substitution; cmsys::RegularExpression TocTreeLink; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 5497469..d1302fe 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -77,23 +77,14 @@ struct cmVisualStudio10TargetGenerator::Elem this->WriteString("<") << tag; return *this; } - template <typename T> - void WriteElem(const char* tag, const T& val) - { - this->WriteString("<") << tag << ">" << val << "</" << tag << ">\n"; - } void Element(const char* tag, const std::string& val) { - Elem(*this).WriteElem(tag, cmVS10EscapeXML(val)); - } - template <typename T> - void Attr(const char* an, const T& av) - { - this->S << " " << an << "=\"" << av << "\""; + Elem(*this).WriteString("<") << tag << ">" << cmVS10EscapeXML(val) << "</" + << tag << ">\n"; } Elem& Attribute(const char* an, const std::string& av) { - Attr(an, cmVS10EscapeAttr(av)); + this->S << " " << an << "=\"" << cmVS10EscapeAttr(av) << "\""; return *this; } // This method for now assumes that this->Tag has been set, e.g. by calling @@ -117,6 +108,7 @@ struct cmVisualStudio10TargetGenerator::Elem class cmVS10GeneratorOptions : public cmVisualStudioGeneratorOptions { public: + typedef cmVisualStudio10TargetGenerator::Elem Elem; cmVS10GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool, cmVS7FlagTable const* table, cmVisualStudio10TargetGenerator* g = nullptr) @@ -125,48 +117,50 @@ public: { } - void OutputFlag(std::ostream& fout, int indent, const char* tag, + 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 this->TargetGenerator->WritePlatformConfigTag( - tag, this->GetConfiguration(), indent); + tag, this->GetConfiguration(), *Parent, content); } else { - fout.fill(' '); - fout.width(indent * 2); - // write an empty string to get the fill level indent to print - fout << ""; - fout << "<" << tag << ">"; + Parent->Element(tag, content); } - fout << cmVS10EscapeXML(content); - fout << "</" << tag << ">\n"; } private: - cmVisualStudio10TargetGenerator* TargetGenerator; + cmVisualStudio10TargetGenerator* const TargetGenerator; + Elem* Parent = nullptr; + friend cmVisualStudio10TargetGenerator::OptionsHelper; }; -inline void cmVisualStudio10TargetGenerator::WriteElem(const char* tag, - const char* val, - int indentLevel) +struct cmVisualStudio10TargetGenerator::OptionsHelper { - Elem(*this->BuildFileStream, indentLevel).WriteElem(tag, val); -} - -inline void cmVisualStudio10TargetGenerator::WriteElem(const char* tag, - std::string const& val, - int indentLevel) -{ - Elem(*this->BuildFileStream, indentLevel).WriteElem(tag, val); -} + cmVS10GeneratorOptions& O; + OptionsHelper(cmVS10GeneratorOptions& o, Elem& e) + : O(o) + { + O.Parent = &e; + } + ~OptionsHelper() { O.Parent = nullptr; } -inline void cmVisualStudio10TargetGenerator::WriteElemEscapeXML( - const char* tag, std::string const& val, int indentLevel) -{ - this->WriteElem(tag, cmVS10EscapeXML(val), indentLevel); -} + 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) { @@ -275,24 +269,12 @@ std::string cmVisualStudio10TargetGenerator::CalcCondition( } void cmVisualStudio10TargetGenerator::WritePlatformConfigTag( - const char* tag, const std::string& config, int indentLevel, - const char* attribute) + const char* tag, const std::string& config, Elem& parent, + const std::string& content) { - std::ostream& stream = *this->BuildFileStream; - stream.fill(' '); - stream.width(indentLevel * 2); - stream << ""; // applies indentation - stream << "<" << tag << " Condition=\""; - stream << this->CalcCondition(config); - stream << "\""; - if (attribute) { - stream << attribute; - } - // close the tag - stream << ">"; - if (attribute) { - stream << "\n"; - } + Elem(parent, tag) + .Attribute("Condition", this->CalcCondition(config)) + .Content(content); } std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( @@ -339,6 +321,14 @@ void cmVisualStudio10TargetGenerator::Generate() this->ProjectType = vcxproj; this->Managed = false; } else if (this->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; } @@ -386,233 +376,236 @@ void cmVisualStudio10TargetGenerator::Generate() // Write the encoding header into the file char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; this->BuildFileStream->write(magic, 3); + (*this->BuildFileStream) << "<?xml version=\"1.0\" encoding=\"" + + this->GlobalGenerator->Encoding() + "\"?>\n"; + Elem e0(*this->BuildFileStream, 0); + e0.StartElement("Project"); + e0.Attribute("DefaultTargets", "Build"); // 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); + e0.Attribute("ToolsVersion", toolsVer); + e0.Attribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); + e0.SetHasElements(); if (this->NsightTegra) { - this->WriteString("<PropertyGroup Label=\"NsightTegraProject\">\n", 1); + 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) { - this->WriteString("<NsightTegraProjectRevisionNumber>", 2); if (nsightTegraMajorVersion > 3 || (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) { - (*this->BuildFileStream) << "11"; + e1.Element("NsightTegraProjectRevisionNumber", "11"); } else { // Nsight Tegra 2.0 uses project revision 9. - (*this->BuildFileStream) << "9"; + e1.Element("NsightTegraProjectRevisionNumber", "9"); } - (*this->BuildFileStream) << "</NsightTegraProjectRevisionNumber>\n"; // Tell newer versions to upgrade silently when loading. - this->WriteElem("NsightTegraUpgradeOnceWithoutPrompt", "true", 2); + e1.Element("NsightTegraUpgradeOnceWithoutPrompt", "true"); } else { // Require Nsight Tegra 1.6 for JCompile support. - this->WriteElem("NsightTegraProjectRevisionNumber", "7", 2); + e1.Element("NsightTegraProjectRevisionNumber", "7"); } - this->WriteString("</PropertyGroup>\n", 1); + e1.EndElement(); } if (const char* hostArch = this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) { - this->WriteString("<PropertyGroup>\n", 1); - this->WriteElemEscapeXML("PreferredToolArchitecture", hostArch, 2); - this->WriteString("</PropertyGroup>\n", 1); + Elem e1(e0, "PropertyGroup"); + e1.Element("PreferredToolArchitecture", hostArch); + e1.EndElement(); } if (this->ProjectType != csproj) { - this->WriteProjectConfigurations(); + this->WriteProjectConfigurations(e0); } - this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1); - this->WriteElem("ProjectGuid", "{" + this->GUID + "}", 2); - if (this->MSTools && - this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) { - this->WriteApplicationTypeSettings(); - this->VerifyNecessaryFiles(); - } - - const char* vsProjectTypes = - this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES"); - if (vsProjectTypes) { - std::string tagName = "ProjectTypes"; - if (this->ProjectType == csproj) { - tagName = "ProjectTypeGuids"; + { + 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"; + } + e1.Element(tagName.c_str(), vsProjectTypes); } - this->WriteString("", 2); - (*this->BuildFileStream) << "<" << tagName << ">" - << cmVS10EscapeXML(vsProjectTypes) << "</" - << tagName << ">\n"; - } - 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) { - this->WriteElemEscapeXML("SccProjectName", vsProjectName, 2); - this->WriteElemEscapeXML("SccLocalPath", vsLocalPath, 2); - this->WriteElemEscapeXML("SccProvider", vsProvider, 2); + 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) { - this->WriteElemEscapeXML("SccAuxPath", vsAuxPath, 2); + const char* vsAuxPath = + this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH"); + if (vsAuxPath) { + e1.Element("SccAuxPath", vsAuxPath); + } } - } - if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) { - this->WriteElem("WinMDAssembly", "true", 2); - } + if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) { + e1.Element("WinMDAssembly", "true"); + } - const char* vsGlobalKeyword = - this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD"); - if (!vsGlobalKeyword) { - this->WriteElem("Keyword", "Win32Proj", 2); - } else { - this->WriteElemEscapeXML("Keyword", vsGlobalKeyword, 2); - } + const char* vsGlobalKeyword = + this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD"); + if (!vsGlobalKeyword) { + e1.Element("Keyword", "Win32Proj"); + } else { + e1.Element("Keyword", vsGlobalKeyword); + } - const char* vsGlobalRootNamespace = - this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE"); - if (vsGlobalRootNamespace) { - this->WriteElemEscapeXML("RootNamespace", vsGlobalRootNamespace, 2); - } + const char* vsGlobalRootNamespace = + this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE"); + if (vsGlobalRootNamespace) { + e1.Element("RootNamespace", vsGlobalRootNamespace); + } - this->WriteElemEscapeXML("Platform", this->Platform, 2); - const char* projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL"); - if (!projLabel) { - projLabel = this->Name.c_str(); - } - this->WriteElemEscapeXML("ProjectName", projLabel, 2); - if (const char* targetFrameworkVersion = this->GeneratorTarget->GetProperty( - "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) { - this->WriteElemEscapeXML("TargetFrameworkVersion", targetFrameworkVersion, - 2); - } + e1.Element("Platform", this->Platform); + const char* projLabel = + this->GeneratorTarget->GetProperty("PROJECT_LABEL"); + if (!projLabel) { + projLabel = this->Name.c_str(); + } + e1.Element("ProjectName", projLabel); + if (const char* targetFrameworkVersion = + this->GeneratorTarget->GetProperty( + "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) { + 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) { - this->WriteElem("VCProjectUpgraderObjectName", "NoUpgrade", 2); - } + // 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; + 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); } - 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"; - } - break; - case cmStateEnums::UTILITY: - case cmStateEnums::GLOBAL_TARGET: - outputType += "Utility"; - break; - case cmStateEnums::UNKNOWN_LIBRARY: - case cmStateEnums::INTERFACE_LIBRARY: - break; + 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"); } - outputType += "</OutputType>\n"; - this->WriteString(outputType.c_str(), 2); - this->WriteElem("AppDesignerFolder", "Properties", 2); - } - this->WriteString("</PropertyGroup>\n", 1); + e1.EndElement(); + } switch (this->ProjectType) { case vcxproj: - this->WriteString("<Import Project=\"" VS10_CXX_DEFAULT_PROPS "\" />\n", - 1); + Elem(e0, "Import") + .Attribute("Project", VS10_CXX_DEFAULT_PROPS) + .EndElement(); break; case csproj: - this->WriteString("<Import Project=\"" VS10_CSharp_DEFAULT_PROPS "\" " - "Condition=\"Exists('" VS10_CSharp_DEFAULT_PROPS "')\"" - "/>\n", - 1); + Elem(e0, "Import") + .Attribute("Project", VS10_CSharp_DEFAULT_PROPS) + .Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')") + .EndElement(); break; } - this->WriteProjectConfigurationValues(); + this->WriteProjectConfigurationValues(e0); 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) - << cmVS10EscapeAttr( - 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=\"") + - cmVS10EscapeAttr(propsLocal) + "\" />\n"; - this->WriteString(import.c_str(), 2); - } - this->WriteString("</ImportGroup>\n", 1); - this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1); + Elem(e0, "Import").Attribute("Project", VS10_CXX_PROPS).EndElement(); + } + { + 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") + .EndElement(); + } + if (this->GlobalGenerator->IsMasmEnabled()) { + Elem(e1, "Import") + .Attribute("Project", + "$(VCTargetsPath)\\BuildCustomizations\\masm.props") + .EndElement(); + } + 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).EndElement(); + } + e1.EndElement(); + } { + Elem e1(e0, "ImportGroup"); + e1.Attribute("Label", "PropertySheets"); std::string props; switch (this->ProjectType) { case vcxproj: @@ -627,71 +620,75 @@ void cmVisualStudio10TargetGenerator::Generate() } if (!props.empty()) { ConvertToWindowsSlash(props); - this->WriteString("", 2); - (*this->BuildFileStream) - << "<Import Project=\"" << cmVS10EscapeAttr(props) << "\"" - << " Condition=\"exists('" << cmVS10EscapeAttr(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(); + Elem(e1, "Import") + .Attribute("Project", props) + .Attribute("Condition", "exists('" + props + "')") + .Attribute("Label", "LocalAppDataPlatform") + .EndElement(); + } + + this->WritePlatformExtensions(e1); + e1.EndElement(); + } + Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros").EndElement(); + 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: - this->WriteString("<Import Project=\"" VS10_CXX_TARGETS "\" />\n", 1); + Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS).EndElement(); break; case csproj: - this->WriteString("<Import Project=\"" VS10_CSharp_TARGETS "\" />\n", 1); + Elem(e0, "Import") + .Attribute("Project", VS10_CSharp_TARGETS) + .EndElement(); break; } - 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) - << cmVS10EscapeAttr( - 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 += cmVS10EscapeAttr(nasmTargets) + "\" />\n"; - this->WriteString(import.c_str(), 2); - } - this->WriteString("</ImportGroup>\n", 1); + 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") + .EndElement(); + } + if (this->GlobalGenerator->IsNasmEnabled()) { + std::string nasmTargets = + GetCMakeFilePath("Templates/MSBuild/nasm.targets"); + Elem(e1, "Import").Attribute("Project", nasmTargets).EndElement(); + } + e1.EndElement(); + } 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); + Elem e1(e0, "PropertyGroup"); + e1.Attribute("Condition", "'$(Configuration)' == '" + i + "'"); + e1.SetHasElements(); + this->WriteEvents(e1, i); + e1.EndElement(); } // make sure custom commands are executed before build (if necessary) - this->WriteString("<PropertyGroup>\n", 1); + Elem e1(e0, "PropertyGroup"); + e1.SetHasElements(); this->WriteString("<BuildDependsOn>\n", 2); for (std::string const& i : this->CSharpCustomCommandNames) { this->WriteString(i.c_str(), 3); @@ -699,14 +696,14 @@ void cmVisualStudio10TargetGenerator::Generate() } this->WriteString("$(BuildDependsOn)\n", 3); this->WriteString("</BuildDependsOn>\n", 2); - this->WriteString("</PropertyGroup>\n", 1); + e1.EndElement(); } 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; if (const char* vsDotNetReferences = @@ -730,7 +727,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences() } } if (!references.empty() || !this->DotNetHintReferences.empty()) { - this->WriteString("<ItemGroup>\n", 1); + 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 @@ -741,35 +738,34 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences() this->DotNetHintReferences[""].push_back( DotNetHintReference(name, path)); } else { - this->WriteDotNetReference(ri, "", ""); + this->WriteDotNetReference(e1, ri, "", ""); } } 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(i.first, i.second, h.first); + this->WriteDotNetReference(e1, i.first, i.second, h.first); } } - this->WriteString("</ItemGroup>\n", 1); + e1.EndElement(); } } void cmVisualStudio10TargetGenerator::WriteDotNetReference( - std::string const& ref, std::string const& hint, std::string const& config) + Elem& e1, std::string const& ref, std::string const& hint, + std::string const& config) { - std::string attr = " Include=\"" + cmVS10EscapeAttr(ref) + "\""; + 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()) { - this->WritePlatformConfigTag("Reference", config, 2, attr.c_str()); - } else { - this->WriteString("<Reference ", 2); - (*this->BuildFileStream) << attr << ">\n"; + e2.Attribute("Condition", this->CalcCondition(config)); } - this->WriteElem("CopyLocalSatelliteAssemblies", "true", 3); - this->WriteElem("ReferenceOutputAssembly", "true", 3); + 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( @@ -778,15 +774,15 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference( privateReference = "False"; } } - this->WriteElem("Private", privateReference, 3); - this->WriteElem("HintPath", hint, 3); + e2.Element("Private", privateReference); + e2.Element("HintPath", hint); } - this->WriteDotNetReferenceCustomTags(ref); - this->WriteString("</Reference>\n", 2); + this->WriteDotNetReferenceCustomTags(e2, ref); + e2.EndElement(); } void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags( - std::string const& ref) + Elem& e2, std::string const& ref) { static const std::string refpropPrefix = "VS_DOTNET_REFERENCEPROP_"; @@ -805,23 +801,20 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags( } } 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) { @@ -835,22 +828,22 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() useRelativePath = true; } } - (*this->BuildFileStream) << obj << "\">\n"; + Elem e2(e1, "EmbeddedResource"); + e2.Attribute("Include", obj); if (this->ProjectType != csproj) { std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h"; - this->WriteElem("DependentUpon", hFileName, 3); + e2.Element("DependentUpon", hFileName); for (std::string const& i : this->Configurations) { - this->WritePlatformConfigTag("LogicalName", i, 3); + 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"; + this->WritePlatformConfigTag("LogicalName", i, e2, s); } } else { std::string binDir = this->Makefile->GetCurrentBinaryDirectory(); @@ -867,7 +860,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() link = cmsys::SystemTools::GetFilenameName(obj); } if (!link.empty()) { - this->WriteElem("Link", link, 3); + e2.Element("Link", link); } } // Determine if this is a generated resource from a .Designer.cs file @@ -881,7 +874,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() generator = g; } if (!generator.empty()) { - this->WriteElemEscapeXML("Generator", generator, 3); + e2.Element("Generator", generator); if (designerResource.find(srcDir) == 0) { designerResource = designerResource.substr(srcDir.length() + 1); } else if (designerResource.find(binDir) == 0) { @@ -891,7 +884,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() cmsys::SystemTools::GetFilenameName(designerResource); } ConvertToWindowsSlash(designerResource); - this->WriteElem("LastGenOutput", designerResource, 3); + e2.Element("LastGenOutput", designerResource); } } const cmPropertyMap& props = oi->GetProperties(); @@ -902,28 +895,25 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() 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); + e2.EndElement(); } - this->WriteString("</ItemGroup>\n", 1); + e1.EndElement(); } } -void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup() +void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0) { std::vector<cmSourceFile const*> xamlObjs; this->GeneratorTarget->GetXamlSources(xamlObjs, ""); if (!xamlObjs.empty()) { - Elem e1(*this->BuildFileStream, 1); + Elem e1(e0); e1.StartElement("ItemGroup"); for (cmSourceFile const* oi : xamlObjs) { std::string obj = oi->GetFullPath(); @@ -962,43 +952,45 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup() } } -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") + .EndElement(); } } } -void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences() +void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences(Elem& e1) { for (TargetsFileAndConfigs const& tac : this->TargetsFileAndConfigsVec) { - this->WriteString("<Import Project=\"", 3); - (*this->BuildFileStream) << tac.File << "\" "; - (*this->BuildFileStream) << "Condition=\""; - (*this->BuildFileStream) << "Exists('" << tac.File << "')"; + 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()) + .EndElement(); } } -void cmVisualStudio10TargetGenerator::WriteWinRTReferences() +void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0) { std::vector<std::string> references; if (const char* vsWinRTReferences = @@ -1012,69 +1004,72 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences() references.push_back("platform.winmd"); } if (!references.empty()) { - this->WriteString("<ItemGroup>\n", 1); + Elem e1(e0, "ItemGroup"); for (std::string const& ri : references) { - this->WriteString("<Reference Include=\"", 2); - (*this->BuildFileStream) << cmVS10EscapeAttr(ri) << "\">\n"; - this->WriteElem("IsWinMDFile", "true", 3); - this->WriteString("</Reference>\n", 2); + Elem e2(e1, "Reference"); + e2.Attribute("Include", ri); + e2.Element("IsWinMDFile", "true"); + e2.EndElement(); } - this->WriteString("</ItemGroup>\n", 1); + e1.EndElement(); } } // ConfigurationType Application, Utility StaticLibrary DynamicLibrary -void cmVisualStudio10TargetGenerator::WriteProjectConfigurations() +void cmVisualStudio10TargetGenerator::WriteProjectConfigurations(Elem& e0) { - this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1); + Elem e1(e0, "ItemGroup"); + e1.Attribute("Label", "ProjectConfigurations"); for (std::string const& c : this->Configurations) { - this->WriteString("<ProjectConfiguration Include=\"", 2); - (*this->BuildFileStream) << c << "|" << this->Platform << "\">\n"; - this->WriteElem("Configuration", c, 3); - this->WriteElemEscapeXML("Platform", this->Platform, 3); - this->WriteString("</ProjectConfiguration>\n", 2); + Elem e2(e1, "ProjectConfiguration"); + e2.Attribute("Include", c + "|" + this->Platform); + e2.Element("Configuration", c); + e2.Element("Platform", this->Platform); + e2.EndElement(); } - this->WriteString("</ItemGroup>\n", 1); + e1.EndElement(); } -void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() +void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) { for (std::string const& c : this->Configurations) { - this->WritePlatformConfigTag("PropertyGroup", c, 1, - " Label=\"Configuration\""); + Elem e1(e0); + e1.StartElement("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 = cmVS10EscapeXML(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: @@ -1082,26 +1077,25 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() break; } } - configType += "</ConfigurationType>\n"; - this->WriteString(configType.c_str(), 2); + e1.Element("ConfigurationType", configType); } if (this->MSTools) { if (!this->Managed) { - this->WriteMSToolConfigurationValues(c); + this->WriteMSToolConfigurationValues(e1, c); } else { - this->WriteMSToolConfigurationValuesManaged(c); + this->WriteMSToolConfigurationValuesManaged(e1, c); } } else if (this->NsightTegra) { - this->WriteNsightTegraConfigurationValues(c); + this->WriteNsightTegraConfigurationValues(e1, c); } - this->WriteString("</PropertyGroup>\n", 1); + e1.EndElement(); } } void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( - std::string const& config) + Elem& e1, std::string const& config) { cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG"); @@ -1116,7 +1110,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( useOfMfcValue = "Dynamic"; } } - this->WriteElem("UseOfMfc", useOfMfcValue, 2); + e1.Element("UseOfMfc", useOfMfcValue); } if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY && @@ -1125,46 +1119,46 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( this->GlobalGenerator->TargetsWindowsPhone() || this->GlobalGenerator->TargetsWindowsStore() || this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) { - this->WriteElem("CharacterSet", "Unicode", 2); + e1.Element("CharacterSet", "Unicode"); } else if (this->GeneratorTarget->GetType() <= cmStateEnums::MODULE_LIBRARY && this->ClOptions[config]->UsingSBCS()) { - this->WriteElem("CharacterSet", "NotSet", 2); + e1.Element("CharacterSet", "NotSet"); } else { - this->WriteElem("CharacterSet", "MultiByte", 2); + e1.Element("CharacterSet", "MultiByte"); } if (const char* toolset = gg->GetPlatformToolset()) { - this->WriteElem("PlatformToolset", toolset, 2); + e1.Element("PlatformToolset", toolset); } if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") || this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) { - this->WriteElem("WindowsAppContainer", "true", 2); + e1.Element("WindowsAppContainer", "true"); } } void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( - std::string const& config) + Elem& e1, std::string const& config) { cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; Options& o = *(this->ClOptions[config]); if (o.IsDebug()) { - this->WriteElem("DebugSymbols", "true", 2); - this->WriteElem("DefineDebug", "true", 2); + e1.Element("DebugSymbols", "true"); + e1.Element("DefineDebug", "true"); } std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/"; ConvertToWindowsSlash(outDir); - this->WriteElemEscapeXML("OutputPath", outDir, 2); + e1.Element("OutputPath", outDir); if (o.HasFlag("Platform")) { - this->WriteElemEscapeXML("PlatformTarget", o.GetFlag("Platform"), 2); + e1.Element("PlatformTarget", o.GetFlag("Platform")); o.RemoveFlag("Platform"); } if (const char* toolset = gg->GetPlatformToolset()) { - this->WriteElemEscapeXML("PlatformToolset", toolset, 2); + e1.Element("PlatformToolset", toolset); } std::string postfixName = cmSystemTools::UpperCase(config); @@ -1174,55 +1168,50 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) { assemblyName += postfix; } - this->WriteElemEscapeXML("AssemblyName", assemblyName, 2); + e1.Element("AssemblyName", assemblyName); if (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType()) { - this->WriteElem("StartAction", "Program", 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, 2); + OptionsHelper oh(o, e1); + oh.OutputFlagMap(); } //---------------------------------------------------------------------------- void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues( - std::string const&) + Elem& e1, std::string const&) { 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->WriteElem("AndroidMinAPI", "android-" + cmVS10EscapeXML(minApi), 2); + e1.Element("AndroidMinAPI", "android-" + std::string(minApi)); } if (const char* api = this->GeneratorTarget->GetProperty("ANDROID_API")) { - this->WriteElem("AndroidTargetAPI", "android-" + cmVS10EscapeXML(api), 2); + e1.Element("AndroidTargetAPI", "android-" + std::string(api)); } if (const char* cpuArch = this->GeneratorTarget->GetProperty("ANDROID_ARCH")) { - this->WriteElemEscapeXML("AndroidArch", cpuArch, 2); + e1.Element("AndroidArch", cpuArch); } if (const char* stlType = this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) { - this->WriteElemEscapeXML("AndroidStlType", stlType, 2); + e1.Element("AndroidStlType", stlType); } } -void cmVisualStudio10TargetGenerator::WriteCustomCommands() +void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0) { this->CSharpCustomCommandNames.clear(); std::vector<cmSourceFile const*> customCommands; this->GeneratorTarget->GetCustomCommands(customCommands, ""); for (cmSourceFile const* si : customCommands) { - this->WriteCustomCommand(si); + this->WriteCustomCommand(e0, si); } // Add CMakeLists.txt file with rule to re-run CMake for user convenience. @@ -1230,13 +1219,13 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommands() 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->LocalGenerator->GetSourcesVisited(this->GeneratorTarget) .insert(sf) @@ -1244,18 +1233,18 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommand( if (std::vector<cmSourceFile*> const* depends = this->GeneratorTarget->GetSourceDepends(sf)) { for (cmSourceFile const* di : *depends) { - this->WriteCustomCommand(di); + this->WriteCustomCommand(e0, di); } } if (cmCustomCommand const* command = sf->GetCustomCommand()) { // C# projects write their <Target> within WriteCustomRule() - this->WriteCustomRule(sf, *command); + 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 @@ -1284,8 +1273,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( } cmLocalVisualStudio7Generator* lg = this->LocalGenerator; - Elem e1(*this->BuildFileStream, 1); - e1.StartElement("ItemGroup"); + Elem e1(e0, "ItemGroup"); Elem e2(e1); if (this->ProjectType != csproj) { this->WriteSource(e2, "CustomBuild", source); @@ -1328,8 +1316,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( if (this->ProjectType == csproj) { std::string name = "CustomCommand_" + c + "_" + cmSystemTools::ComputeStringMD5(sourcePath); - this->WriteCustomRuleCSharp(c, name, script, inputs.str(), outputs.str(), - comment); + this->WriteCustomRuleCSharp(e0, c, name, script, inputs.str(), + outputs.str(), comment); } else { this->WriteCustomRuleCpp(e2, c, script, inputs.str(), outputs.str(), comment); @@ -1361,24 +1349,20 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp( } 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); - Elem e1(*this->BuildFileStream, 1); - e1.StartElement("Target"); + 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()) { - Elem(e1) - .StartElement("Exec") - .Attribute("Command", "echo " + comment) - .EndElement(); + Elem(e1, "Exec").Attribute("Command", "echo " + comment).EndElement(); } - Elem(e1).StartElement("Exec").Attribute("Command", script).EndElement(); + Elem(e1, "Exec").Attribute("Command", script).EndElement(); e1.EndElement(); } @@ -1442,8 +1426,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups() Elem e0(fout, 0); e0.StartElement("Project"); - e0.Attr("ToolsVersion", toolsVer); - e0.Attr("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); + e0.Attribute("ToolsVersion", toolsVer); + e0.Attribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); e0.SetHasElements(); for (auto const& ti : this->Tools) { @@ -1459,24 +1443,24 @@ void cmVisualStudio10TargetGenerator::WriteGroups() cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(oi)); if (fileName == "wmappmanifest.xml") { Elem e2(e1, "XML"); - e2.Attr("Include", oi); - Elem(e2).WriteElem("Filter", "Resource Files"); + e2.Attribute("Include", oi); + e2.Element("Filter", "Resource Files"); e2.EndElement(); } else if (cmSystemTools::GetFilenameExtension(fileName) == ".appxmanifest") { Elem e2(e1, "AppxManifest"); - e2.Attr("Include", oi); - Elem(e2).WriteElem("Filter", "Resource Files"); + e2.Attribute("Include", oi); + e2.Element("Filter", "Resource Files"); e2.EndElement(); } else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") { Elem e2(e1, "None"); - e2.Attr("Include", oi); - Elem(e2).WriteElem("Filter", "Resource Files"); + e2.Attribute("Include", oi); + e2.Element("Filter", "Resource Files"); e2.EndElement(); } else { Elem e2(e1, "Image"); - e2.Attr("Include", oi); - Elem(e2).WriteElem("Filter", "Resource Files"); + e2.Attribute("Include", oi); + e2.Element("Filter", "Resource Files"); e2.EndElement(); } } @@ -1491,8 +1475,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups() std::string obj = oi->GetFullPath(); ConvertToWindowsSlash(obj); Elem e2(e1, "EmbeddedResource"); - e2.Attr("Include", cmVS10EscapeAttr(obj)); - Elem(e2).WriteElem("Filter", "Resource Files"); + e2.Attribute("Include", obj); + e2.Element("Filter", "Resource Files"); e2.EndElement(); } e1.EndElement(); @@ -1511,8 +1495,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups() std::string guidName = "SG_Filter_" + name; std::string guid = this->GlobalGenerator->GetGUID(guidName); Elem e2(e1, "Filter"); - e2.Attr("Include", name); - Elem(e2).WriteElem("UniqueIdentifier", "{" + guid + "}"); + e2.Attribute("Include", name); + e2.Element("UniqueIdentifier", "{" + guid + "}"); e2.EndElement(); } } @@ -1521,11 +1505,11 @@ void cmVisualStudio10TargetGenerator::WriteGroups() std::string guidName = "SG_Filter_Resource Files"; std::string guid = this->GlobalGenerator->GetGUID(guidName); Elem e2(e1, "Filter"); - e2.Attr("Include", "Resource Files"); - Elem(e2).WriteElem("UniqueIdentifier", "{" + guid + "}"); - Elem(e2).WriteElem("Extensions", - "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;" - "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms"); + 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"); e2.EndElement(); } @@ -1589,19 +1573,20 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources( std::string path = this->ConvertPath(source, s.RelativePath); ConvertToWindowsSlash(path); Elem e2(e1, name.c_str()); - e2.Attr("Include", cmVS10EscapeAttr(path)); + e2.Attribute("Include", path); if (!filter.empty()) { - Elem(e2).WriteElem("Filter", filter); + e2.Element("Filter", filter); } e2.EndElement(); } e1.EndElement(); } -void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf) +void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1, + cmSourceFile const* sf) { std::string const& fileName = sf->GetFullPath(); - Elem e2(*this->BuildFileStream, 2); + Elem e2(e1); this->WriteSource(e2, "ClInclude", sf); if (this->IsResxHeader(fileName)) { e2.Element("FileType", "CppForm"); @@ -1612,7 +1597,8 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf) e2.EndElement(); } -void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) +void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, + cmSourceFile const* sf) { bool toolHasSettings = false; const char* tool = "None"; @@ -1770,7 +1756,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) } } - Elem e2(*this->BuildFileStream, 2); + Elem e2(e1); this->WriteSource(e2, tool, sf); if (toolHasSettings) { e2.SetHasElements(); @@ -1781,60 +1767,47 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) 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); + Elem e3(e2, "DeploymentContent"); + e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" + + this->Configurations[i] + "|" + this->Platform + "'"); + e3.Content("true"); } else { - this->WriteString("<ExcludedFromBuild Condition=\"" - "'$(Configuration)|$(Platform)'=='", - 3); - (*this->BuildFileStream) << this->Configurations[i] << "|" - << this->Platform << "'\">true"; - this->WriteString("</ExcludedFromBuild>\n", 0); + Elem e3(e2, "ExcludedFromBuild"); + e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" + + this->Configurations[i] + "|" + this->Platform + "'"); + e3.Content("true"); } } } if (!shaderType.empty()) { - this->WriteElemEscapeXML("ShaderType", shaderType, 3); + e2.Element("ShaderType", shaderType); } if (!shaderEntryPoint.empty()) { - this->WriteElemEscapeXML("EntryPointName", shaderEntryPoint, 3); + e2.Element("EntryPointName", shaderEntryPoint); } if (!shaderModel.empty()) { - this->WriteElemEscapeXML("ShaderModel", shaderModel, 3); + 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); + Elem e3(e2, "HeaderFileOutput"); + e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" + + this->Configurations[i] + "|" + this->Platform + "'"); + e3.Content(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); + Elem e3(e2, "VariableName"); + e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" + + this->Configurations[i] + "|" + this->Platform + "'"); + e3.Content(variableName); } } if (!shaderEnableDebug.empty()) { @@ -1846,11 +1819,10 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) const char* enableDebug = cge->Evaluate(this->LocalGenerator, this->Configurations[i]); if (strlen(enableDebug) > 0) { - Elem el(*this->BuildFileStream, 3); - el.StartElement("EnableDebuggingInformation"); - el.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" + + Elem e3(e2, "EnableDebuggingInformation"); + e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] + "|" + this->Platform + "'"); - el.Content(cmSystemTools::IsOn(enableDebug) ? "true" : "false"); + e3.Content(cmSystemTools::IsOn(enableDebug) ? "true" : "false"); } } } @@ -1863,41 +1835,40 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) const char* disableOptimizations = cge->Evaluate(this->LocalGenerator, this->Configurations[i]); if (strlen(disableOptimizations) > 0) { - Elem el(*this->BuildFileStream, 3); - el.StartElement("DisableOptimizations"); - el.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" + + Elem e3(e2, "DisableOptimizations"); + e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] + "|" + this->Platform + "'"); - el.Content(cmSystemTools::IsOn(disableOptimizations) ? "true" + e3.Content(cmSystemTools::IsOn(disableOptimizations) ? "true" : "false"); } } } if (!shaderObjectFileName.empty()) { - this->WriteElemEscapeXML("ObjectFileOutput", shaderObjectFileName, 3); + e2.Element("ObjectFileOutput", shaderObjectFileName); } if (!shaderAdditionalFlags.empty()) { - this->WriteElemEscapeXML("AdditionalOptions", shaderAdditionalFlags, 3); + e2.Element("AdditionalOptions", shaderAdditionalFlags); } if (!settingsGenerator.empty()) { - this->WriteElemEscapeXML("Generator", settingsGenerator, 3); + e2.Element("Generator", settingsGenerator); } if (!settingsLastGenOutput.empty()) { - this->WriteElemEscapeXML("LastGenOutput", settingsLastGenOutput, 3); + e2.Element("LastGenOutput", settingsLastGenOutput); } if (!sourceLink.empty()) { - this->WriteElemEscapeXML("Link", sourceLink, 3); + e2.Element("Link", sourceLink); } if (!subType.empty()) { - this->WriteElemEscapeXML("SubType", subType, 3); + e2.Element("SubType", subType); } if (!copyToOutDir.empty()) { - this->WriteElemEscapeXML("CopyToOutputDirectory", copyToOutDir, 3); + e2.Element("CopyToOutputDirectory", copyToOutDir); } if (!includeInVsix.empty()) { - this->WriteElemEscapeXML("IncludeInVSIX", includeInVsix, 3); + e2.Element("IncludeInVSIX", includeInVsix); } // write source file specific tags - this->WriteCSharpSourceProperties(sourceFileTags); + this->WriteCSharpSourceProperties(e2, sourceFileTags); } e2.WriteEndTag(tool); } @@ -1946,12 +1917,12 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, 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"); std::vector<size_t> all_configs; for (size_t ci = 0; ci < this->Configurations.size(); ++ci) { @@ -1996,10 +1967,10 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() } 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"; @@ -2046,7 +2017,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() include_configs.begin(), include_configs.end(), std::back_inserter(exclude_configs)); - Elem e2(*this->BuildFileStream, 2); + Elem e2(e1); this->WriteSource(e2, tool, si.Source); if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) { this->OutputSourceSpecificFlags(e2, si.Source); @@ -2059,10 +2030,10 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() } if (this->IsMissingFiles) { - this->WriteMissingFiles(); + this->WriteMissingFiles(e1); } - this->WriteString("</ItemGroup>\n", 1); + e1.EndElement(); } void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( @@ -2131,9 +2102,9 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( if (!objectName.empty()) { e2.SetHasElements(); if (lang == "CUDA") { - this->WriteElem("CompileOut", "$(IntDir)/" + objectName, 3); + e2.Element("CompileOut", "$(IntDir)/" + objectName); } else { - this->WriteElem("ObjectFileName", "$(IntDir)/" + objectName, 3); + e2.Element("ObjectFileName", "$(IntDir)/" + objectName); } } for (std::string const& config : this->Configurations) { @@ -2153,7 +2124,6 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( // use them if (!flags.empty() || !options.empty() || !configDefines.empty() || !includes.empty() || compileAs || noWinRT) { - e2.SetHasElements(); cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; cmIDEFlagTable const* flagtable = nullptr; const std::string& srclang = source->GetLanguage(); @@ -2219,18 +2189,18 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } clOptions.AddIncludes(includeList); clOptions.SetConfiguration(config); - clOptions.PrependInheritedString("AdditionalOptions"); - clOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream, 3, - lang); - clOptions.OutputFlagMap(*this->BuildFileStream, 3); - clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, 3, lang); + OptionsHelper oh(clOptions, e2); + oh.PrependInheritedString("AdditionalOptions"); + oh.OutputAdditionalIncludeDirectories(lang); + oh.OutputFlagMap(); + oh.OutputPreprocessorDefinitions(lang); } } if (this->IsXamlSource(source->GetFullPath())) { e2.SetHasElements(); const std::string& fileName = source->GetFullPath(); std::string xamlFileName = fileName.substr(0, fileName.find_last_of(".")); - this->WriteElem("DependentUpon", xamlFileName, 3); + e2.Element("DependentUpon", xamlFileName); } if (this->ProjectType == csproj) { std::string f = source->GetFullPath(); @@ -2245,8 +2215,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( this->GetCSharpSourceProperties(&sf, sourceFileTags); // write source file specific tags if (!sourceFileTags.empty()) { - e2.SetHasElements(); - this->WriteCSharpSourceProperties(sourceFileTags); + this->WriteCSharpSourceProperties(e2, sourceFileTags); } } } @@ -2262,7 +2231,8 @@ void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild( } } -void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() +void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( + Elem& e0) { cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType(); if (ttype > cmStateEnums::GLOBAL_TARGET) { @@ -2272,14 +2242,13 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() return; } - this->WriteString("<PropertyGroup>\n", 1); - this->WriteElem("_ProjectFileVersion", "10.0.20506.1", 2); + Elem e1(e0, "PropertyGroup"); + e1.Element("_ProjectFileVersion", "10.0.20506.1"); for (std::string const& config : this->Configurations) { if (ttype >= cmStateEnums::UTILITY) { - this->WritePlatformConfigTag("IntDir", config, 2); - *this->BuildFileStream - << "$(Platform)\\$(Configuration)\\$(ProjectName)\\" - << "</IntDir>\n"; + this->WritePlatformConfigTag( + "IntDir", config, e1, + "$(Platform)\\$(Configuration)\\$(ProjectName)\\"); } else { std::string intermediateDir = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); @@ -2299,81 +2268,67 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() ConvertToWindowsSlash(intermediateDir); ConvertToWindowsSlash(outDir); - this->WritePlatformConfigTag("OutDir", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(outDir) << "</OutDir>\n"; + this->WritePlatformConfigTag("OutDir", config, e1, outDir); - this->WritePlatformConfigTag("IntDir", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(intermediateDir) - << "</IntDir>\n"; + this->WritePlatformConfigTag("IntDir", config, e1, intermediateDir); if (const char* sdkExecutableDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES")) { - this->WritePlatformConfigTag("ExecutablePath", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(sdkExecutableDirectories) - << "</ExecutablePath>\n"; + this->WritePlatformConfigTag("ExecutablePath", config, e1, + sdkExecutableDirectories); } if (const char* sdkIncludeDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_INCLUDE_DIRECTORIES")) { - this->WritePlatformConfigTag("IncludePath", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(sdkIncludeDirectories) - << "</IncludePath>\n"; + this->WritePlatformConfigTag("IncludePath", config, e1, + sdkIncludeDirectories); } if (const char* sdkReferenceDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_REFERENCE_DIRECTORIES")) { - this->WritePlatformConfigTag("ReferencePath", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(sdkReferenceDirectories) - << "</ReferencePath>\n"; + this->WritePlatformConfigTag("ReferencePath", config, e1, + sdkReferenceDirectories); } if (const char* sdkLibraryDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_LIBRARY_DIRECTORIES")) { - this->WritePlatformConfigTag("LibraryPath", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(sdkLibraryDirectories) - << "</LibraryPath>\n"; + this->WritePlatformConfigTag("LibraryPath", config, e1, + sdkLibraryDirectories); } if (const char* sdkLibraryWDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES")) { - this->WritePlatformConfigTag("LibraryWPath", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(sdkLibraryWDirectories) - << "</LibraryWPath>\n"; + this->WritePlatformConfigTag("LibraryWPath", config, e1, + sdkLibraryWDirectories); } if (const char* sdkSourceDirectories = this->Makefile->GetDefinition("CMAKE_VS_SDK_SOURCE_DIRECTORIES")) { - this->WritePlatformConfigTag("SourcePath", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(sdkSourceDirectories) - << "</SourcePath>\n"; + this->WritePlatformConfigTag("SourcePath", config, e1, + sdkSourceDirectories); } if (const char* sdkExcludeDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_EXCLUDE_DIRECTORIES")) { - this->WritePlatformConfigTag("ExcludePath", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(sdkExcludeDirectories) - << "</ExcludePath>\n"; + this->WritePlatformConfigTag("ExcludePath", config, e1, + sdkExcludeDirectories); } if (const char* workingDir = this->GeneratorTarget->GetProperty( "VS_DEBUGGER_WORKING_DIRECTORY")) { this->WritePlatformConfigTag("LocalDebuggerWorkingDirectory", config, - 2); - *this->BuildFileStream << cmVS10EscapeXML(workingDir) - << "</LocalDebuggerWorkingDirectory>\n"; + e1, workingDir); } if (const char* debuggerCommand = this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) { - this->WritePlatformConfigTag("LocalDebuggerCommand", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(debuggerCommand) - << "</LocalDebuggerCommand>\n"; + this->WritePlatformConfigTag("LocalDebuggerCommand", config, e1, + debuggerCommand); } std::string name = cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); - this->WritePlatformConfigTag("TargetName", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(name) << "</TargetName>\n"; + this->WritePlatformConfigTag("TargetName", config, e1, name); std::string ext = cmSystemTools::GetFilenameLastExtension(targetNameFull); @@ -2382,17 +2337,16 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() // A single "." appears to be treated as an empty extension. ext = "."; } - this->WritePlatformConfigTag("TargetExt", config, 2); - *this->BuildFileStream << cmVS10EscapeXML(ext) << "</TargetExt>\n"; + this->WritePlatformConfigTag("TargetExt", config, e1, ext); - this->OutputLinkIncremental(config); + this->OutputLinkIncremental(e1, config); } } - this->WriteString("</PropertyGroup>\n", 1); + e1.EndElement(); } void cmVisualStudio10TargetGenerator::OutputLinkIncremental( - std::string const& configName) + Elem& e1, std::string const& configName) { if (!this->MSTools) { return; @@ -2409,15 +2363,13 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( Options& linkOptions = *(this->LinkOptions[configName]); const char* incremental = linkOptions.GetFlag("LinkIncremental"); - this->WritePlatformConfigTag("LinkIncremental", configName, 2); - *this->BuildFileStream << (incremental ? incremental : "true") - << "</LinkIncremental>\n"; + this->WritePlatformConfigTag("LinkIncremental", configName, e1, + (incremental ? incremental : "true")); linkOptions.RemoveFlag("LinkIncremental"); const char* manifest = linkOptions.GetFlag("GenerateManifest"); - this->WritePlatformConfigTag("GenerateManifest", configName, 2); - *this->BuildFileStream << (manifest ? manifest : "true") - << "</GenerateManifest>\n"; + this->WritePlatformConfigTag("GenerateManifest", configName, e1, + (manifest ? manifest : "true")); linkOptions.RemoveFlag("GenerateManifest"); // Some link options belong here. Use them now and remove them so that @@ -2426,8 +2378,7 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( 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"; + this->WritePlatformConfigTag(flag, configName, e1, value); linkOptions.RemoveFlag(flag); } } @@ -2650,24 +2601,23 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } 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, 3, - this->LangForClCompile); - clOptions.OutputFlagMap(*this->BuildFileStream, 3); - clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, 3, - 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->WriteElemEscapeXML("ProcessMax", processMax, 3); + e2.Element("ProcessMax", processMax); } } @@ -2675,9 +2625,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*"); const char* toolset = this->GlobalGenerator->GetPlatformToolset(); if (toolset && clangToolset.find(toolset)) { - this->WriteElem("ObjectFileName", "$(IntDir)%(filename).obj", 3); + e2.Element("ObjectFileName", "$(IntDir)%(filename).obj"); } else { - this->WriteElem("ObjectFileName", "$(IntDir)", 3); + e2.Element("ObjectFileName", "$(IntDir)"); } // If not in debug mode, write the DebugInformationFormat field @@ -2685,15 +2635,16 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( // 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(); + e3.EndElement(); } // Specify the compiler program database file if configured. std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName); if (!pdb.empty()) { ConvertToWindowsSlash(pdb); - this->WriteElemEscapeXML("ProgramDataBaseFileName", pdb, 3); + e2.Element("ProgramDataBaseFileName", pdb); } // add AdditionalUsingDirectories @@ -2705,11 +2656,11 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( } dirs.append(u); } - this->WriteElemEscapeXML("AdditionalUsingDirectories", dirs, 3); + e2.Element("AdditionalUsingDirectories", dirs); } } - this->WriteString("</ClCompile>\n", 2); + e2.EndElement(); } bool cmVisualStudio10TargetGenerator::ComputeRcOptions() @@ -2751,21 +2702,20 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions( } 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, 3, "RC"); - rcOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream, 3, - "RC"); + OptionsHelper rcOptions(*(this->RcOptions[configName]), e2); + rcOptions.OutputPreprocessorDefinitions("RC"); + rcOptions.OutputAdditionalIncludeDirectories("RC"); rcOptions.PrependInheritedString("AdditionalOptions"); - rcOptions.OutputFlagMap(*this->BuildFileStream, 3); + rcOptions.OutputFlagMap(); - this->WriteString("</ResourceCompile>\n", 2); + e2.EndElement(); } bool cmVisualStudio10TargetGenerator::ComputeCudaOptions() @@ -2900,21 +2850,20 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( } 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, 3, - "CUDA"); - cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, 3, "CUDA"); + OptionsHelper cudaOptions(*(this->CudaOptions[configName]), e2); + cudaOptions.OutputAdditionalIncludeDirectories("CUDA"); + cudaOptions.OutputPreprocessorDefinitions("CUDA"); cudaOptions.PrependInheritedString("AdditionalOptions"); - cudaOptions.OutputFlagMap(*this->BuildFileStream, 3); + cudaOptions.OutputFlagMap(); - this->WriteString("</CudaCompile>\n", 2); + e2.EndElement(); } bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions() @@ -2969,7 +2918,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( } void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions( - std::string const& configName) + Elem& e1, std::string const& configName) { if (this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) { return; @@ -2979,10 +2928,10 @@ void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions( return; } - this->WriteString("<CudaLink>\n", 2); - Options& cudaLinkOptions = *(this->CudaLinkOptions[configName]); - cudaLinkOptions.OutputFlagMap(*this->BuildFileStream, 3); - this->WriteString("</CudaLink>\n", 2); + Elem e2(e1, "CudaLink"); + OptionsHelper cudaLinkOptions(*(this->CudaLinkOptions[configName]), e2); + cudaLinkOptions.OutputFlagMap(); + e2.EndElement(); } bool cmVisualStudio10TargetGenerator::ComputeMasmOptions() @@ -3023,25 +2972,23 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions( } 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, 3, - "ASM_MASM"); + OptionsHelper clOptions(*(this->ClOptions[configName]), e2); + clOptions.OutputPreprocessorDefinitions("ASM_MASM"); - Options& masmOptions = *(this->MasmOptions[configName]); - masmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream, 3, - "ASM_MASM"); + OptionsHelper masmOptions(*(this->MasmOptions[configName]), e2); + masmOptions.OutputAdditionalIncludeDirectories("ASM_MASM"); masmOptions.PrependInheritedString("AdditionalOptions"); - masmOptions.OutputFlagMap(*this->BuildFileStream, 3); + masmOptions.OutputFlagMap(); - this->WriteString("</MASM>\n", 2); + e2.EndElement(); } bool cmVisualStudio10TargetGenerator::ComputeNasmOptions() @@ -3083,33 +3030,30 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions( } 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, 3, - "ASM_NASM"); - nasmOptions.OutputFlagMap(*this->BuildFileStream, 3); + OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2); + nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM"); + nasmOptions.OutputFlagMap(); nasmOptions.PrependInheritedString("AdditionalOptions"); - nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, 3, - "ASM_NASM"); + nasmOptions.OutputPreprocessorDefinitions("ASM_NASM"); // Preprocessor definitions and includes are shared with clOptions. - Options& clOptions = *(this->ClOptions[configName]); - clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, 3, - "ASM_NASM"); + OptionsHelper clOptions(*(this->ClOptions[configName]), e2); + clOptions.OutputPreprocessorDefinitions("ASM_NASM"); - this->WriteString("</NASM>\n", 2); + e2.EndElement(); } 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) { @@ -3119,15 +3063,16 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions( this->LocalGenerator->GetStaticLibraryFlags( libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget); if (!libflags.empty()) { - this->WriteString("<Lib>\n", 2); + 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, 3); - this->WriteString("</Lib>\n", 2); + OptionsHelper oh(libOptions, e2); + oh.PrependInheritedString("AdditionalOptions"); + oh.OutputFlagMap(); + e2.EndElement(); } // We cannot generate metadata for static libraries. WindowsPhone @@ -3135,14 +3080,14 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions( // Link tool options even for static libraries. if (this->GlobalGenerator->TargetsWindowsPhone() || this->GlobalGenerator->TargetsWindowsStore()) { - this->WriteString("<Link>\n", 2); - this->WriteElem("GenerateWindowsMetadata", "false", 3); - this->WriteString("</Link>\n", 2); + Elem e2(e1, "Link"); + e2.Element("GenerateWindowsMetadata", "false"); + e2.EndElement(); } } 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 && @@ -3153,20 +3098,20 @@ void cmVisualStudio10TargetGenerator::WriteManifestOptions( 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()); + e2.EndElement(); } } 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. @@ -3183,32 +3128,30 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( } } + Elem e2(e1, "AntBuild"); // Tell MSBuild to launch Ant. { std::string antBuildPath = rootDir; - this->WriteString("<AntBuild>\n", 2); ConvertToWindowsSlash(antBuildPath); - this->WriteElemEscapeXML("AntBuildPath", antBuildPath, 3); + e2.Element("AntBuildPath", antBuildPath); } if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) { - this->WriteElem("SkipAntStep", "true", 3); + e2.Element("SkipAntStep", "true"); } if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_PROGUARD")) { - this->WriteElem("EnableProGuard", "true", 3); + e2.Element("EnableProGuard", "true"); } if (const char* proGuardConfigLocation = this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) { - this->WriteElemEscapeXML("ProGuardConfigLocation", proGuardConfigLocation, - 3); + e2.Element("ProGuardConfigLocation", proGuardConfigLocation); } if (const char* securePropertiesLocation = this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) { - this->WriteElemEscapeXML("SecurePropertiesLocation", - securePropertiesLocation, 3); + e2.Element("SecurePropertiesLocation", securePropertiesLocation); } if (const char* nativeLibDirectoriesExpression = @@ -3218,7 +3161,7 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( ge.Parse(nativeLibDirectoriesExpression); std::string nativeLibDirs = cge->Evaluate(this->LocalGenerator, configName); - this->WriteElemEscapeXML("NativeLibDirectories", nativeLibDirs, 3); + e2.Element("NativeLibDirectories", nativeLibDirs); } if (const char* nativeLibDependenciesExpression = @@ -3229,12 +3172,12 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( ge.Parse(nativeLibDependenciesExpression); std::string nativeLibDeps = cge->Evaluate(this->LocalGenerator, configName); - this->WriteElemEscapeXML("NativeLibDependencies", nativeLibDeps, 3); + e2.Element("NativeLibDependencies", nativeLibDeps); } if (const char* javaSourceDir = this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) { - this->WriteElemEscapeXML("JavaSourceDir", javaSourceDir, 3); + e2.Element("JavaSourceDir", javaSourceDir); } if (const char* jarDirectoriesExpression = @@ -3244,33 +3187,32 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( ge.Parse(jarDirectoriesExpression); std::string jarDirectories = cge->Evaluate(this->LocalGenerator, configName); - this->WriteElemEscapeXML("JarDirectories", jarDirectories, 3); + e2.Element("JarDirectories", jarDirectories); } if (const char* jarDeps = this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) { - this->WriteElemEscapeXML("JarDependencies", jarDeps, 3); + e2.Element("JarDependencies", jarDeps); } if (const char* assetsDirectories = this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) { - this->WriteElemEscapeXML("AssetsDirectories", assetsDirectories, 3); + e2.Element("AssetsDirectories", assetsDirectories); } { std::string manifest_xml = rootDir + "/AndroidManifest.xml"; ConvertToWindowsSlash(manifest_xml); - this->WriteElemEscapeXML("AndroidManifestLocation", manifest_xml, 3); + 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); + e2.EndElement(); } bool cmVisualStudio10TargetGenerator::ComputeLinkOptions() @@ -3550,7 +3492,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions( } 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) { @@ -3559,18 +3501,20 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions( if (this->ProjectType == csproj) { return; } - Options& linkOptions = *(this->LinkOptions[config]); - this->WriteString("<Link>\n", 2); - linkOptions.PrependInheritedString("AdditionalOptions"); - linkOptions.OutputFlagMap(*this->BuildFileStream, 3); + { + Elem e2(e1, "Link"); + OptionsHelper linkOptions(*(this->LinkOptions[config]), e2); + linkOptions.PrependInheritedString("AdditionalOptions"); + linkOptions.OutputFlagMap(); + e2.EndElement(); + } - this->WriteString("</Link>\n", 2); if (!this->GlobalGenerator->NeedLinkLibraryDependencies( this->GeneratorTarget)) { - this->WriteString("<ProjectReference>\n", 2); - this->WriteElem("LinkLibraryDependencies", "false", 3); - this->WriteString("</ProjectReference>\n", 2); + Elem e2(e1, "ProjectReference"); + e2.Element("LinkLibraryDependencies", "false"); + e2.EndElement(); } } @@ -3657,7 +3601,7 @@ void cmVisualStudio10TargetGenerator::AddTargetsFileAndConfigPair( } void cmVisualStudio10TargetGenerator::WriteMidlOptions( - std::string const& configName) + Elem& e1, std::string const& configName) { if (!this->MSTools) { return; @@ -3681,65 +3625,66 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions( // 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->WriteElem("OutputDirectory", "$(ProjectDir)/$(IntDir)", 3); - this->WriteElem("HeaderFileName", "%(Filename).h", 3); - this->WriteElem("TypeLibraryName", "%(Filename).tlb", 3); - this->WriteElem("InterfaceIdentifierFileName", "%(Filename)_i.c", 3); - this->WriteElem("ProxyFileName", "%(Filename)_p.c", 3); - this->WriteString("</Midl>\n", 2); + oss << i << ";"; + } + + Elem e2(e1, "Midl"); + e2.Element("AdditionalIncludeDirectories", + oss.str() + "%(AdditionalIncludeDirectories)"); + 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"); + e2.EndElement(); } -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"; + Elem e1(e0, "ItemDefinitionGroup"); + e1.Attribute("Condition", this->CalcCondition(i)); + // output cl compile flags <ClCompile></ClCompile> if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) { - this->WriteClOptions(i); + this->WriteClOptions(e1, i); // output rc compile flags <ResourceCompile></ResourceCompile> - this->WriteRCOptions(i); - this->WriteCudaOptions(i); - this->WriteMasmOptions(i); - this->WriteNasmOptions(i); + this->WriteRCOptions(e1, i); + this->WriteCudaOptions(e1, i); + this->WriteMasmOptions(e1, i); + this->WriteNasmOptions(e1, i); } // output midl flags <Midl></Midl> - this->WriteMidlOptions(i); + this->WriteMidlOptions(e1, i); // write events if (this->ProjectType != csproj) { - this->WriteEvents(i); + this->WriteEvents(e1, i); } // output link flags <Link></Link> - this->WriteLinkOptions(i); - this->WriteCudaLinkOptions(i); + this->WriteLinkOptions(e1, i); + this->WriteCudaLinkOptions(e1, i); // output lib flags <Lib></Lib> - this->WriteLibOptions(i); + this->WriteLibOptions(e1, i); // output manifest flags <Manifest></Manifest> - this->WriteManifestOptions(i); + this->WriteManifestOptions(e1, i); if (this->NsightTegra && this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE && this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) { - this->WriteAntBuildOptions(i); + this->WriteAntBuildOptions(e1, i); } - this->WriteString("</ItemDefinitionGroup>\n", 1); + e1.EndElement(); } } void cmVisualStudio10TargetGenerator::WriteEvents( - std::string const& configName) + Elem& e1, std::string const& configName) { bool addedPrelink = false; cmGeneratorTarget::ModuleDefinitionInfo const* mdi = @@ -3750,27 +3695,26 @@ void cmVisualStudio10TargetGenerator::WriteEvents( 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"; + Elem e2(e1, name); cmLocalVisualStudio7Generator* lg = this->LocalGenerator; std::string script; const char* pre = ""; @@ -3782,39 +3726,37 @@ void cmVisualStudio10TargetGenerator::WriteEvent( 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->WriteElemEscapeXML("Message", comment, 3); - this->WriteString("<Command>", 3); + e2.Element("Message", comment); + e2.Element("Command", script); + e2.EndElement(); } 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"; + e2.Content(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); + Elem e1(e0, "ItemGroup"); + e1.SetHasElements(); for (cmTargetDepend const& i : depends) { cmGeneratorTarget const* dt = i; if (dt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -3825,7 +3767,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() if (this->GlobalGenerator->TargetIsFortranOnly(dt)) { continue; } - this->WriteString("<ProjectReference Include=\"", 2); cmLocalGenerator* lg = dt->GetLocalGenerator(); std::string name = dt->GetName(); std::string path; @@ -3839,36 +3780,42 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() path += computeProjectFileExtension(dt, *this->Configurations.begin()); } ConvertToWindowsSlash(path); - (*this->BuildFileStream) << cmVS10EscapeAttr(path) << "\">\n"; - this->WriteElem("Project", - "{" + this->GlobalGenerator->GetGUID(name) + "}", 3); - this->WriteElem("Name", name, 3); - this->WriteDotNetReferenceCustomTags(name); + 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. - cmGeneratorTarget::ManagedType check = - cmGeneratorTarget::ManagedType::Mixed; - // FIXME: These (5) lines should be removed. They are here to allow - // manual setting of the /clr flag in compiler options. Setting - // /clr manually makes cmGeneratorTarget::GetManagedType() return - // 'Native' instead of 'Mixed' or 'Managed'. - check = cmGeneratorTarget::ManagedType::Native; - bool unmanagedStatic = false; - if (dt->GetType() == cmStateEnums::STATIC_LIBRARY) { - unmanagedStatic = !dt->HasLanguage("CSharp", ""); + 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 (dt->GetManagedType("") < check || unmanagedStatic) { - this->WriteElem("ReferenceOutputAssembly", "false", 3); + if (referenceNotManaged) { + e2.Element("ReferenceOutputAssembly", "false"); } } - this->WriteString("</ProjectReference>\n", 2); + e2.EndElement(); } - this->WriteString("</ItemGroup>\n", 1); + e1.EndElement(); } -void cmVisualStudio10TargetGenerator::WritePlatformExtensions() +void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1) { // This only applies to Windows 10 apps if (this->GlobalGenerator->TargetsWindowsStore() && @@ -3876,52 +3823,54 @@ void cmVisualStudio10TargetGenerator::WritePlatformExtensions() 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"; + Elem e2(e1, "Import"); + e2.Attribute( + "Project", "$([Microsoft.Build.Utilities.ToolLocationHelper]" + "::GetPlatformExtensionSDKLocation(`" + + extension + ", Version=" + version + + "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, " + "$(ExtensionSDKDirectoryRoot), null))" + "\\DesignTime\\CommonConfiguration\\Neutral\\" + + extension + ".props"); + e2.Attribute( + "Condition", "exists('$(" + "[Microsoft.Build.Utilities.ToolLocationHelper]" + "::GetPlatformExtensionSDKLocation(`" + + extension + ", Version=" + version + + "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, " + "$(ExtensionSDKDirectoryRoot), null))" + "\\DesignTime\\CommonConfiguration\\Neutral\\" + + extension + ".props')"); + e2.EndElement(); } -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) << cmVS10EscapeAttr(ri) << "\"/>\n"; + Elem(e1, "SDKReference").Attribute("Include", ri).EndElement(); } } @@ -3938,37 +3887,38 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences() if (desktopExtensionsVersion || mobileExtensionsVersion || iotExtensionsVersion) { if (!hasWrittenItemGroup) { - this->WriteString("<ItemGroup>\n", 1); + e1.StartElement("ItemGroup"); hasWrittenItemGroup = true; } 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); + e1.EndElement(); } } 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) + .EndElement(); } -void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile() +void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile( + Elem& e0) { if ((this->GlobalGenerator->TargetsWindowsStore() || this->GlobalGenerator->TargetsWindowsPhone()) && @@ -3989,13 +3939,12 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile() std::string artifactDir = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); ConvertToWindowsSlash(artifactDir); - this->WriteString("<PropertyGroup>\n", 1); - this->WriteElemEscapeXML("AppxPackageArtifactsDir", artifactDir + "\\", - 2); + Elem e1(e0, "PropertyGroup"); + e1.Element("AppxPackageArtifactsDir", artifactDir + "\\"); std::string resourcePriFile = this->DefaultArtifactDir + "/resources.pri"; ConvertToWindowsSlash(resourcePriFile); - this->WriteElem("ProjectPriFullPath", resourcePriFile, 2); + 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 @@ -4007,22 +3956,23 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile() pfxFile, false); ConvertToWindowsSlash(pfxFile); this->AddedFiles.push_back(pfxFile); + this->AddedDefaultCertificate = true; } - this->WriteElem("PackageCertificateKeyFile", pfxFile, 2); + e1.Element("PackageCertificateKeyFile", pfxFile); std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile); if (!thumb.empty()) { - this->WriteElem("PackageCertificateThumbprint", thumb, 2); + e1.Element("PackageCertificateThumbprint", thumb); } - this->WriteString("</PropertyGroup>\n", 1); + e1.EndElement(); } else if (!pfxFile.empty()) { - this->WriteString("<PropertyGroup>\n", 1); - this->WriteElem("PackageCertificateKeyFile", pfxFile, 2); + Elem e1(e0, "PropertyGroup"); + e1.Element("PackageCertificateKeyFile", pfxFile); std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile); if (!thumb.empty()) { - this->WriteElem("PackageCertificateThumbprint", thumb, 2); + e1.Element("PackageCertificateThumbprint", thumb); } - this->WriteString("</PropertyGroup>\n", 1); + e1.EndElement(); } } } @@ -4060,7 +4010,7 @@ bool cmVisualStudio10TargetGenerator::IsXamlSource( return it != expectedXamlSources.end(); } -void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() +void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1) { cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; bool isAppContainer = false; @@ -4068,29 +4018,29 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore(); std::string const& v = this->GlobalGenerator->GetSystemVersion(); if (isWindowsPhone || isWindowsStore) { - this->WriteElem("ApplicationType", - (isWindowsPhone ? "Windows Phone" : "Windows Store"), 2); - this->WriteElem("DefaultLanguage", "en-US", 2); + e1.Element("ApplicationType", + (isWindowsPhone ? "Windows Phone" : "Windows Store")); + e1.Element("DefaultLanguage", "en-US"); if (cmHasLiteralPrefix(v, "10.0")) { - this->WriteElemEscapeXML("ApplicationTypeRevision", "10.0", 2); + e1.Element("ApplicationTypeRevision", "10.0"); // Visual Studio 14.0 is necessary for building 10.0 apps - this->WriteElem("MinimumVisualStudioVersion", "14.0", 2); + e1.Element("MinimumVisualStudioVersion", "14.0"); if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) { isAppContainer = true; } } else if (v == "8.1") { - this->WriteElemEscapeXML("ApplicationTypeRevision", v, 2); + e1.Element("ApplicationTypeRevision", v); // Visual Studio 12.0 is necessary for building 8.1 apps - this->WriteElem("MinimumVisualStudioVersion", "12.0", 2); + e1.Element("MinimumVisualStudioVersion", "12.0"); if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) { isAppContainer = true; } } else if (v == "8.0") { - this->WriteElemEscapeXML("ApplicationTypeRevision", v, 2); + e1.Element("ApplicationTypeRevision", v); // Visual Studio 11.0 is necessary for building 8.0 apps - this->WriteElem("MinimumVisualStudioVersion", "11.0", 2); + e1.Element("MinimumVisualStudioVersion", "11.0"); if (isWindowsStore && this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) { @@ -4098,42 +4048,38 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() } else if (isWindowsPhone && this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - this->WriteElem("XapOutputs", "true", 2); - this->WriteElem("XapFilename", cmVS10EscapeXML(this->Name) + - "_$(Configuration)_$(Platform).xap", - 2); + e1.Element("XapOutputs", "true"); + e1.Element("XapFilename", + this->Name + "_$(Configuration)_$(Platform).xap"); } } } if (isAppContainer) { - this->WriteElem("AppContainerApplication", "true", 2); + e1.Element("AppContainerApplication", "true"); } else if (this->Platform == "ARM64") { - this->WriteElem("WindowsSDKDesktopARM64Support", "true", 2); + e1.Element("WindowsSDKDesktopARM64Support", "true"); } else if (this->Platform == "ARM") { - this->WriteElem("WindowsSDKDesktopARMSupport", "true", 2); + e1.Element("WindowsSDKDesktopARMSupport", "true"); } std::string const& targetPlatformVersion = gg->GetWindowsTargetPlatformVersion(); if (!targetPlatformVersion.empty()) { - this->WriteElemEscapeXML("WindowsTargetPlatformVersion", - targetPlatformVersion, 2); + e1.Element("WindowsTargetPlatformVersion", targetPlatformVersion); } const char* targetPlatformMinVersion = this->GeneratorTarget->GetProperty( "VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION"); if (targetPlatformMinVersion) { - this->WriteElemEscapeXML("WindowsTargetPlatformMinVersion", - targetPlatformMinVersion, 2); + 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->WriteElemEscapeXML("WindowsTargetPlatformMinVersion", - targetPlatformVersion, 2); + e1.Element("WindowsTargetPlatformMinVersion", targetPlatformVersion); } } // Added IoT Startup Task support if (this->GeneratorTarget->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) { - this->WriteElem("ContainsStartupTask", "true", 2); + e1.Element("ContainsStartupTask", "true"); } } @@ -4181,27 +4127,27 @@ void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles() } } -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"; @@ -4262,25 +4208,23 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80() std::string sourceFile = this->ConvertPath(manifestFile, false); ConvertToWindowsSlash(sourceFile); - this->WriteString("<Xml Include=\"", 2); - (*this->BuildFileStream) << cmVS10EscapeAttr(sourceFile) << "\">\n"; - this->WriteElem("SubType", "Designer", 3); - this->WriteString("</Xml>\n", 2); + Elem e2(e1, "Xml"); + e2.Attribute("Include", sourceFile); + e2.Element("SubType", "Designer"); + e2.EndElement(); 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) << cmVS10EscapeAttr(smallLogo) << "\" />\n"; + Elem(e1, "Image").Attribute("Include", smallLogo).EndElement(); 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) << cmVS10EscapeAttr(logo) << "\" />\n"; + Elem(e1, "Image").Attribute("Include", logo).EndElement(); this->AddedFiles.push_back(logo); std::string applicationIcon = @@ -4288,12 +4232,11 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80() cmSystemTools::CopyAFile(templateFolder + "/ApplicationIcon.png", applicationIcon, false); ConvertToWindowsSlash(applicationIcon); - this->WriteString("<Image Include=\"", 2); - (*this->BuildFileStream) << cmVS10EscapeAttr(applicationIcon) << "\" />\n"; + Elem(e1, "Image").Attribute("Include", applicationIcon).EndElement(); this->AddedFiles.push_back(applicationIcon); } -void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81() +void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81(Elem& e1) { std::string manifestFile = this->DefaultArtifactDir + "/package.appxManifest"; @@ -4353,10 +4296,10 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81() "</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"; @@ -4408,10 +4351,10 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80() "</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"; @@ -4468,10 +4411,10 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81() "</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"; @@ -4529,67 +4472,64 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0() "</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) << cmVS10EscapeAttr(sourceFile) << "\">\n"; - this->WriteElem("SubType", "Designer", 3); - this->WriteString("</AppxManifest>\n", 2); + Elem e2(e1, "AppxManifest"); + e2.Attribute("Include", sourceFile); + e2.Element("SubType", "Designer"); + e2.EndElement(); 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) << cmVS10EscapeAttr(smallLogo) << "\" />\n"; + Elem(e1, "Image").Attribute("Include", smallLogo).EndElement(); 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) << cmVS10EscapeAttr(smallLogo44) << "\" />\n"; + Elem(e1, "Image").Attribute("Include", smallLogo44).EndElement(); 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) << cmVS10EscapeAttr(logo) << "\" />\n"; + Elem(e1, "Image").Attribute("Include", logo).EndElement(); 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) << cmVS10EscapeAttr(storeLogo) << "\" />\n"; + Elem(e1, "Image").Attribute("Include", storeLogo).EndElement(); 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) << cmVS10EscapeAttr(splashScreen) << "\" />\n"; + Elem(e1, "Image").Attribute("Include", splashScreen).EndElement(); 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) << cmVS10EscapeAttr(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).EndElement(); + } } bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const @@ -4635,13 +4575,11 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties( } 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); } } } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index df87df3..38c7725 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -32,10 +32,6 @@ public: cmGlobalVisualStudio10Generator* gg); ~cmVisualStudio10TargetGenerator(); void Generate(); - // used by cmVisualStudioGeneratorOptions - std::string CalcCondition(const std::string& config) const; - void WritePlatformConfigTag(const char* tag, const std::string& config, - int indentLevel, const char* attribute = 0); private: struct ToolSource @@ -54,100 +50,103 @@ private: }; struct Elem; + struct OptionsHelper; std::string ConvertPath(std::string const& path, bool forceRelative); void WriteString(const char* line, int indentLevel); - void WriteElem(const char* tag, const char* val, int indentLevel); - void WriteElem(const char* tag, std::string const& val, int indentLevel); - void WriteElemEscapeXML(const char* tag, std::string const& val, - 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); + std::string CalcCondition(const std::string& config) const; + void WritePlatformConfigTag(const char* tag, const std::string& config, + Elem& parent, const std::string& content); + 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&, + void WriteExcludeFromBuild(Elem& e2, std::vector<size_t> const& exclude_configs); - void WriteAllSources(); - void WriteDotNetReferences(); - void WriteDotNetReference(std::string const& ref, std::string const& hint, + 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(std::string const& ref); - void WriteEmbeddedResourceGroup(); - void WriteWinRTReferences(); - void WriteWinRTPackageCertificateKeyFile(); - void WriteXamlFilesGroup(); - void WritePathAndIncrementalLinkOptions(); - void WriteItemDefinitionGroups(); + 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(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(); + void WriteProjectReferences(Elem& e0); + void WriteApplicationTypeSettings(Elem& e1); void OutputSourceSpecificFlags(Elem&, cmSourceFile const* source); void AddLibraries(const cmComputeLinkInformation& cli, std::vector<std::string>& libVec, @@ -155,10 +154,10 @@ private: 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(Elem& e0, std::string const& name, @@ -175,10 +174,11 @@ private: 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: + friend class cmVS10GeneratorOptions; typedef cmVS10GeneratorOptions Options; typedef std::map<std::string, std::unique_ptr<Options>> OptionsMap; OptionsMap ClOptions; @@ -216,6 +216,7 @@ private: 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; diff --git a/Tests/CMakeLib/testRST.expect b/Tests/CMakeLib/testRST.expect index fa436cb..1ffd6b9 100644 --- a/Tests/CMakeLib/testRST.expect +++ b/Tests/CMakeLib/testRST.expect @@ -16,7 +16,13 @@ Variable ``<PLACEHOLDER>_VARIABLE`` with leading placeholder. 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. diff --git a/Tests/CMakeLib/testRST.rst b/Tests/CMakeLib/testRST.rst index 54952dd..c8587c0 100644 --- a/Tests/CMakeLib/testRST.rst +++ b/Tests/CMakeLib/testRST.rst @@ -23,7 +23,13 @@ Variable :variable:`<PLACEHOLDER>_VARIABLE` with leading placeholder. 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 diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index b11cf03..ea64646 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -951,6 +951,44 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release 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) diff --git a/Tests/CMakeTests/CheckSourceTreeTest.cmake.in b/Tests/CMakeTests/CheckSourceTreeTest.cmake.in index 8145db7..4f2aaea 100644 --- a/Tests/CMakeTests/CheckSourceTreeTest.cmake.in +++ b/Tests/CMakeTests/CheckSourceTreeTest.cmake.in @@ -308,13 +308,11 @@ message("======================================================================= 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("") @@ -341,7 +339,7 @@ endif() # 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 diff --git a/Tests/CPackUseDefaultVersion/CMakeLists.txt b/Tests/CPackUseDefaultVersion/CMakeLists.txt new file mode 100644 index 0000000..9f21f3a --- /dev/null +++ b/Tests/CPackUseDefaultVersion/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.2) +project(CPackUseProjectVersion NONE) + +include(CPack) + +message("CPACK_PACKAGE_VERSION=${CPACK_PACKAGE_VERSION}") diff --git a/Tests/CPackUseProjectVersion/CMakeLists.txt b/Tests/CPackUseProjectVersion/CMakeLists.txt new file mode 100644 index 0000000..d4770ae --- /dev/null +++ b/Tests/CPackUseProjectVersion/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.2) +project(CPackUseProjectVersion VERSION 1.2.3 LANGUAGES NONE) + +include(CPack) + +message("CPACK_PACKAGE_VERSION=${CPACK_PACKAGE_VERSION}") diff --git a/Tests/CPackUseShortProjectVersion/CMakeLists.txt b/Tests/CPackUseShortProjectVersion/CMakeLists.txt new file mode 100644 index 0000000..855bc64 --- /dev/null +++ b/Tests/CPackUseShortProjectVersion/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.2) +project(CPackUseProjectVersion VERSION 2 LANGUAGES NONE) + +include(CPack) + +message("CPACK_PACKAGE_VERSION=${CPACK_PACKAGE_VERSION}") diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 6557cc4..690c5b4 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -338,7 +338,13 @@ add_RunCMake_test(CheckIPOSupported) 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) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-stderr.txt deleted file mode 100644 index 444da45..0000000 --- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-stderr.txt +++ /dev/null @@ -1,8 +0,0 @@ -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\) diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang.cmake index cec12a3..00dd290 100644 --- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang.cmake +++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang.cmake @@ -1,4 +1,4 @@ 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>>) diff --git a/Tests/RunCMake/VS10Project/VsCSharpCustomTags-stderr.txt b/Tests/RunCMake/VS10Project/VsCSharpCustomTags-stderr.txt new file mode 100644 index 0000000..1ea3b51 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpCustomTags-stderr.txt @@ -0,0 +1,3 @@ +^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.$ diff --git a/Tests/RunCMake/VS10Project/VsCSharpReferenceProps-stderr.txt b/Tests/RunCMake/VS10Project/VsCSharpReferenceProps-stderr.txt new file mode 100644 index 0000000..4402b8f --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpReferenceProps-stderr.txt @@ -0,0 +1,8 @@ +^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.$ diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 1a60f0c..f004ce9 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -21,6 +21,10 @@ function(run_install_test case) # 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() @@ -59,6 +63,8 @@ run_cmake(EXPORT-OldIFace) 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) @@ -67,3 +73,4 @@ endif() 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) diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake new file mode 100644 index 0000000..bc9ebd1 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake @@ -0,0 +1,73 @@ +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}$") diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-result.txt b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-all-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-unknown-lang-result.txt +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-all-result.txt diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-all-stderr.txt b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-all-stderr.txt new file mode 100644 index 0000000..187a826 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-all-stderr.txt @@ -0,0 +1,5 @@ +^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\)$ diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-all.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-all.cmake new file mode 100644 index 0000000..701d093 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-all.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +add_library(namelink-lib empty.c) + +install(TARGETS namelink-lib + DESTINATION lib + COMPONENT lib + NAMELINK_COMPONENT dev +) diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-exc-result.txt b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-exc-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-exc-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-exc-stderr.txt b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-exc-stderr.txt new file mode 100644 index 0000000..d1002ba --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-exc-stderr.txt @@ -0,0 +1,5 @@ +^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\)$ diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-exc.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-exc.cmake new file mode 100644 index 0000000..19c12d4 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-bad-exc.cmake @@ -0,0 +1,10 @@ +enable_language(C) + +add_executable(namelink-exc main.c) + +install(TARGETS namelink-exc + RUNTIME + DESTINATION bin + COMPONENT exc + NAMELINK_COMPONENT dev +) diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-dev-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-dev-check.cmake new file mode 100644 index 0000000..5396cdb --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-dev-check.cmake @@ -0,0 +1,11 @@ +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}$") diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake new file mode 100644 index 0000000..3f6be68 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake @@ -0,0 +1,50 @@ +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}$") diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake new file mode 100644 index 0000000..0033c88 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake @@ -0,0 +1,38 @@ +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}$") diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT.cmake new file mode 100644 index 0000000..0e684e1 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT.cmake @@ -0,0 +1,68 @@ +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 +) diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in index 7878ad2..f52ccd1 100644 --- a/Utilities/Sphinx/conf.py.in +++ b/Utilities/Sphinx/conf.py.in @@ -17,6 +17,7 @@ version = '@conf_version@' # feature version release = '@conf_release@' # full version string primary_domain = 'cmake' +highlight_language = 'none' exclude_patterns = [ 'dev', # ignore developer-only documentation diff --git a/Utilities/Sphinx/static/cmake.css b/Utilities/Sphinx/static/cmake.css index 2a326d4..b082ede 100644 --- a/Utilities/Sphinx/static/cmake.css +++ b/Utilities/Sphinx/static/cmake.css @@ -6,3 +6,13 @@ 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; +} diff --git a/Utilities/cmlibuv/include/uv-errno.h b/Utilities/cmlibuv/include/uv-errno.h index 8a41533..aa4d450 100644 --- a/Utilities/cmlibuv/include/uv-errno.h +++ b/Utilities/cmlibuv/include/uv-errno.h @@ -23,6 +23,11 @@ #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) @@ -46,355 +51,355 @@ * 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 @@ -404,7 +409,7 @@ * 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__) || \ @@ -417,15 +422,16 @@ #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_ */ diff --git a/Utilities/cmlibuv/include/uv-os390.h b/Utilities/cmlibuv/include/uv-os390.h index 39e7384..0267d74 100644 --- a/Utilities/cmlibuv/include/uv-os390.h +++ b/Utilities/cmlibuv/include/uv-os390.h @@ -22,7 +22,7 @@ #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; \ diff --git a/Utilities/cmlibuv/include/uv-unix.h b/Utilities/cmlibuv/include/uv-unix.h index d8d031f..455674d 100644 --- a/Utilities/cmlibuv/include/uv-unix.h +++ b/Utilities/cmlibuv/include/uv-unix.h @@ -50,7 +50,7 @@ # 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" diff --git a/Utilities/cmlibuv/include/uv-version.h b/Utilities/cmlibuv/include/uv-version.h index 1dc63e5..06c6711 100644 --- a/Utilities/cmlibuv/include/uv-version.h +++ b/Utilities/cmlibuv/include/uv-version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 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" diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h index 875e30a..74fa00d 100644 --- a/Utilities/cmlibuv/include/uv.h +++ b/Utilities/cmlibuv/include/uv.h @@ -382,8 +382,7 @@ UV_EXTERN const char* uv_err_name(int err); /* 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. */ @@ -1209,6 +1208,18 @@ UV_EXTERN int uv_fs_write(uv_loop_t* loop, */ #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, @@ -1549,7 +1560,10 @@ struct uv_loop_s { /* 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 @@ -1577,6 +1591,7 @@ UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data); #undef UV_SIGNAL_PRIVATE_FIELDS #undef UV_LOOP_PRIVATE_FIELDS #undef UV_LOOP_PRIVATE_PLATFORM_FIELDS +#undef UV__ERR #ifdef __cplusplus } diff --git a/Utilities/cmlibuv/src/unix/aix-common.c b/Utilities/cmlibuv/src/unix/aix-common.c index c2217fb..9c11c5d 100644 --- a/Utilities/cmlibuv/src/unix/aix-common.c +++ b/Utilities/cmlibuv/src/unix/aix-common.c @@ -83,12 +83,12 @@ int uv_exepath(char* buffer, size_t* size) { 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: @@ -101,7 +101,7 @@ int uv_exepath(char* buffer, size_t* size) { /* 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); @@ -121,11 +121,11 @@ int uv_exepath(char* buffer, size_t* size) { 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) { @@ -151,7 +151,7 @@ int uv_exepath(char* buffer, size_t* size) { uv__free(clonedpath); /* Out of tokens (path entries), and no match found */ - return -EINVAL; + return UV_EINVAL; } } @@ -177,19 +177,19 @@ int uv_interface_addresses(uv_interface_address_t** addresses, *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)) @@ -208,7 +208,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, 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)) @@ -221,7 +221,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, *addresses = uv__malloc(*count * sizeof(uv_interface_address_t)); if (!(*addresses)) { uv__close(sockfd); - return -ENOMEM; + return UV_ENOMEM; } address = *addresses; @@ -240,7 +240,7 @@ int uv_interface_addresses(uv_interface_address_t** 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)) @@ -260,7 +260,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) { uv__close(sockfd); - return -ENOSYS; + return UV_ENOSYS; } if (inet6) diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c index fd41309..92de814 100644 --- a/Utilities/cmlibuv/src/unix/aix.c +++ b/Utilities/cmlibuv/src/unix/aix.c @@ -119,7 +119,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { 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)) @@ -409,22 +409,22 @@ static int uv__is_ahafs_mounted(void){ 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 */ @@ -495,7 +495,7 @@ static int uv__make_subdirs_p(const char *filename) { rc = uv__makedir_p(cmd); if (rc == -1 && errno != EEXIST){ - return -errno; + return UV__ERR(errno); } return rc; @@ -522,7 +522,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) { 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); @@ -537,7 +537,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) { /* 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 @@ -558,7 +558,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) { rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1); if (rc < 0) - return -errno; + return UV__ERR(errno); return 0; } @@ -716,7 +716,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); return 0; #else - return -ENOSYS; + return UV_ENOSYS; #endif } @@ -771,7 +771,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, return 0; #else - return -ENOSYS; + return UV_ENOSYS; #endif } @@ -796,7 +796,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { return 0; #else - return -ENOSYS; + return UV_ENOSYS; #endif } @@ -861,7 +861,7 @@ int uv_set_process_title(const char* title) { */ 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); @@ -888,9 +888,9 @@ int uv_get_process_title(char* buffer, size_t size) { 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); @@ -919,10 +919,10 @@ int uv_resident_set_memory(size_t* rss) { 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; @@ -953,7 +953,7 @@ int uv_uptime(double* uptime) { endutent(); if (boot_time == 0) - return -ENOSYS; + return UV_ENOSYS; *uptime = time(NULL) - boot_time; return 0; @@ -969,30 +969,30 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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; diff --git a/Utilities/cmlibuv/src/unix/async.c b/Utilities/cmlibuv/src/unix/async.c index 45c088e..0b450ae 100644 --- a/Utilities/cmlibuv/src/unix/async.c +++ b/Utilities/cmlibuv/src/unix/async.c @@ -166,7 +166,7 @@ static int uv__async_start(uv_loop_t* loop) { 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 @@ -240,7 +240,7 @@ static int uv__async_eventfd(void) { return fd; if (errno != ENOSYS) - return -errno; + return UV__ERR(errno); no_eventfd2 = 1; @@ -257,7 +257,7 @@ skip_eventfd2: } if (errno != ENOSYS) - return -errno; + return UV__ERR(errno); no_eventfd = 1; @@ -265,5 +265,5 @@ skip_eventfd: #endif - return -ENOSYS; + return UV_ENOSYS; } diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c index ea3166c..0d02154 100644 --- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c +++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c @@ -70,7 +70,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { int i; if (getifaddrs(&addrs) != 0) - return -errno; + return UV__ERR(errno); *count = 0; @@ -85,7 +85,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { if (*addresses == NULL) { freeifaddrs(addrs); - return -ENOMEM; + return UV_ENOMEM; } address = *addresses; diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c index faaf697..a357ef3 100644 --- a/Utilities/cmlibuv/src/unix/core.c +++ b/Utilities/cmlibuv/src/unix/core.c @@ -194,14 +194,14 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { 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); @@ -211,7 +211,7 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { r = setsockopt(fd, SOL_SOCKET, optname, (const void*) value, len); if (r < 0) - return -errno; + return UV__ERR(errno); return 0; } @@ -421,12 +421,12 @@ int uv__socket(int domain, int type, int protocol) { 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) @@ -490,7 +490,7 @@ int uv__accept(int sockfd) { continue; if (errno != ENOSYS) - return -errno; + return UV__ERR(errno); no_accept4 = 1; skip: @@ -500,7 +500,7 @@ skip: if (peerfd == -1) { if (errno == EINTR) continue; - return -errno; + return UV__ERR(errno); } err = uv__cloexec(peerfd, 1); @@ -526,8 +526,8 @@ int uv__close_nocheckstdio(int fd) { 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; } @@ -539,7 +539,7 @@ int uv__close_nocheckstdio(int fd) { 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); } @@ -553,7 +553,7 @@ int uv__nonblock_ioctl(int fd, int set) { while (r == -1 && errno == EINTR); if (r) - return -errno; + return UV__ERR(errno); return 0; } @@ -568,7 +568,7 @@ int uv__cloexec_ioctl(int fd, int set) { while (r == -1 && errno == EINTR); if (r) - return -errno; + return UV__ERR(errno); return 0; } @@ -584,7 +584,7 @@ int uv__nonblock_fcntl(int fd, int set) { 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) @@ -600,7 +600,7 @@ int uv__nonblock_fcntl(int fd, int set) { while (r == -1 && errno == EINTR); if (r) - return -errno; + return UV__ERR(errno); return 0; } @@ -615,7 +615,7 @@ int uv__cloexec_fcntl(int fd, int set) { 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) @@ -631,7 +631,7 @@ int uv__cloexec_fcntl(int fd, int set) { while (r == -1 && errno == EINTR); if (r) - return -errno; + return UV__ERR(errno); return 0; } @@ -646,7 +646,7 @@ int uv__dup(int fd) { fd = dup(fd); if (fd == -1) - return -errno; + return UV__ERR(errno); err = uv__cloexec(fd, 1); if (err) { @@ -670,10 +670,10 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { 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); @@ -682,7 +682,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int 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)) @@ -698,10 +698,10 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { 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] == '/') { @@ -715,7 +715,7 @@ int uv_cwd(char* buffer, size_t* size) { int uv_chdir(const char* dir) { if (chdir(dir)) - return -errno; + return UV__ERR(errno); return 0; } @@ -752,11 +752,11 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { 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; @@ -934,7 +934,7 @@ int uv_getrusage(uv_rusage_t* rusage) { 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; @@ -976,7 +976,7 @@ int uv__open_cloexec(const char* path, int flags) { return fd; if (errno != EINVAL) - return -errno; + return UV__ERR(errno); /* O_CLOEXEC not supported. */ no_cloexec = 1; @@ -985,7 +985,7 @@ int uv__open_cloexec(const char* path, int flags) { fd = open(path, flags); if (fd == -1) - return -errno; + return UV__ERR(errno); err = uv__cloexec(fd, 1); if (err) { @@ -1002,14 +1002,14 @@ int uv__dup2_cloexec(int oldfd, int newfd) { #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; @@ -1020,7 +1020,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) { if (r != -1) return r; if (errno != ENOSYS) - return -errno; + return UV__ERR(errno); /* Fall through. */ no_dup3 = 1; } @@ -1036,7 +1036,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) { #endif if (r == -1) - return -errno; + return UV__ERR(errno); err = uv__cloexec(newfd, 1); if (err) { @@ -1051,29 +1051,16 @@ int uv__dup2_cloexec(int oldfd, int newfd) { 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); - - if (len >= *size) { - *size = len + 1; - return -ENOBUFS; - } - - memcpy(buffer, buf, len + 1); - *size = len; + /* 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); - return 0; - } + if (r != UV_ENOENT) + return r; /* HOME is not set, so call uv__getpwuid_r() */ r = uv__getpwuid_r(&pwd); @@ -1087,7 +1074,7 @@ int uv_os_homedir(char* buffer, size_t* size) { if (len >= *size) { *size = len + 1; uv_os_free_passwd(&pwd); - return -ENOBUFS; + return UV_ENOBUFS; } memcpy(buffer, pwd.homedir, len + 1); @@ -1103,7 +1090,7 @@ int uv_os_tmpdir(char* buffer, size_t* size) { size_t len; if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; + return UV_EINVAL; #define CHECK_ENV_VAR(name) \ do { \ @@ -1133,7 +1120,7 @@ return_buffer: if (len >= *size) { *size = len + 1; - return -ENOBUFS; + return UV_ENOBUFS; } /* The returned directory should not have a trailing slash. */ @@ -1165,11 +1152,11 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { 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); @@ -1186,7 +1173,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { buf = uv__malloc(bufsize); if (buf == NULL) - return -ENOMEM; + return UV_ENOMEM; r = getpwuid_r(uid, &pw, buf, bufsize, &result); @@ -1203,7 +1190,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { if (result == NULL) { uv__free(buf); - return -ENOENT; + return UV_ENOENT; } /* Allocate memory for the username, shell, and home directory */ @@ -1214,7 +1201,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { if (pwd->username == NULL) { uv__free(buf); - return -ENOMEM; + return UV_ENOMEM; } /* Copy the username */ @@ -1270,18 +1257,18 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) { 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); @@ -1293,10 +1280,10 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) { 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; } @@ -1304,10 +1291,10 @@ int uv_os_setenv(const char* name, const char* value) { 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; } @@ -1324,17 +1311,17 @@ int uv_os_gethostname(char* buffer, size_t* size) { 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); diff --git a/Utilities/cmlibuv/src/unix/cygwin.c b/Utilities/cmlibuv/src/unix/cygwin.c index 5a887dd..9fe4093 100644 --- a/Utilities/cmlibuv/src/unix/cygwin.c +++ b/Utilities/cmlibuv/src/unix/cygwin.c @@ -29,7 +29,7 @@ int uv_uptime(double* uptime) { struct sysinfo info; if (sysinfo(&info) < 0) - return -errno; + return UV__ERR(errno); *uptime = info.uptime; return 0; diff --git a/Utilities/cmlibuv/src/unix/darwin-proctitle.c b/Utilities/cmlibuv/src/unix/darwin-proctitle.c index 1142311..dabde22 100644 --- a/Utilities/cmlibuv/src/unix/darwin-proctitle.c +++ b/Utilities/cmlibuv/src/unix/darwin-proctitle.c @@ -18,6 +18,9 @@ * IN THE SOFTWARE. */ +#include "uv.h" +#include "internal.h" + #include <dlfcn.h> #include <errno.h> #include <stdlib.h> @@ -41,14 +44,14 @@ static int uv__pthread_setname_np(const char* name) { 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; } @@ -84,7 +87,7 @@ int uv__set_process_title(const char* title) { CFTypeRef asn; int err; - err = -ENOENT; + err = UV_ENOENT; application_services_handle = dlopen("/System/Library/Frameworks/" "ApplicationServices.framework/" "Versions/A/ApplicationServices", @@ -151,7 +154,7 @@ int uv__set_process_title(const char* title) { /* 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; @@ -182,7 +185,7 @@ int uv__set_process_title(const char* title) { asn = pLSGetCurrentApplicationASN(); - err = -EINVAL; + err = UV_EINVAL; if (pLSSetApplicationInformationItem(-2, /* Magic value. */ asn, *display_name_key, diff --git a/Utilities/cmlibuv/src/unix/darwin.c b/Utilities/cmlibuv/src/unix/darwin.c index df6dd1c..31ad8a9 100644 --- a/Utilities/cmlibuv/src/unix/darwin.c +++ b/Utilities/cmlibuv/src/unix/darwin.c @@ -37,7 +37,7 @@ int uv__platform_loop_init(uv_loop_t* loop) { loop->cf_state = NULL; if (uv__kqueue_init(loop)) - return -errno; + return UV__ERR(errno); return 0; } @@ -68,18 +68,18 @@ int uv_exepath(char* buffer, size_t* size) { 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) @@ -98,7 +98,7 @@ uint64_t uv_get_free_memory(void) { 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); @@ -111,7 +111,7 @@ uint64_t uv_get_total_memory(void) { size_t size = sizeof(info); if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; + return UV__ERR(errno); return (uint64_t) info; } @@ -158,7 +158,7 @@ int uv_uptime(double* uptime) { 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; @@ -181,23 +181,23 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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; diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c index f2b3f24..70ccb13 100644 --- a/Utilities/cmlibuv/src/unix/freebsd.c +++ b/Utilities/cmlibuv/src/unix/freebsd.c @@ -72,11 +72,11 @@ int uv_exepath(char* buffer, size_t* size) { 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; @@ -96,7 +96,7 @@ int uv_exepath(char* buffer, size_t* size) { size_t abspath_size; if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; + return UV_EINVAL; mib[0] = CTL_KERN; mib[1] = KERN_PROC; @@ -105,7 +105,7 @@ int uv_exepath(char* buffer, size_t* size) { 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; @@ -126,7 +126,7 @@ uint64_t uv_get_free_memory(void) { 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); @@ -140,7 +140,7 @@ uint64_t uv_get_total_memory(void) { size_t size = sizeof(info); if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; + return UV__ERR(errno); return (uint64_t) info; } @@ -176,7 +176,7 @@ int uv_set_process_title(const char* title) { if (process_title == NULL) { uv_mutex_unlock(&process_title_mutex); - return -ENOMEM; + return UV_ENOMEM; } uv__free(process_title); @@ -204,7 +204,7 @@ int uv_get_process_title(char* buffer, size_t size) { 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); @@ -214,7 +214,7 @@ int uv_get_process_title(char* buffer, size_t size) { if (size < len) { uv_mutex_unlock(&process_title_mutex); - return -ENOBUFS; + return UV_ENOBUFS; } memcpy(buffer, process_title, len); @@ -243,7 +243,7 @@ int uv_resident_set_memory(size_t* rss) { kinfo_size = sizeof(kinfo); if (sysctl(mib, 4, &kinfo, &kinfo_size, NULL, 0)) - return -errno; + return UV__ERR(errno); page_size = getpagesize(); @@ -262,7 +262,7 @@ int uv_uptime(double* uptime) { struct timespec sp; r = clock_gettime(CLOCK_MONOTONIC, &sp); if (r) - return -errno; + return UV__ERR(errno); *uptime = sp.tv_sec; return 0; @@ -309,15 +309,15 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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; @@ -327,7 +327,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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); @@ -335,13 +335,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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++) { diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c index 0a4c183..4545168 100644 --- a/Utilities/cmlibuv/src/unix/fs.c +++ b/Utilities/cmlibuv/src/unix/fs.c @@ -62,21 +62,23 @@ #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) @@ -88,10 +90,8 @@ 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) @@ -107,10 +107,8 @@ 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); \ @@ -121,6 +119,7 @@ #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; \ } \ @@ -804,6 +803,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { 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; @@ -828,7 +840,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { /* Get the source file's mode. */ if (fstat(srcfd, &statsbuf)) { - err = -errno; + err = UV__ERR(errno); goto out; } @@ -852,9 +864,32 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { } 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; @@ -1117,7 +1152,7 @@ static void uv__fs_work(struct uv__work* w) { } while (r == -1 && errno == EINTR && retry_on_eintr); if (r == -1) - req->result = -errno; + req->result = UV__ERR(errno); else req->result = r; @@ -1135,9 +1170,9 @@ static void uv__fs_done(struct uv__work* w, int status) { 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); @@ -1298,11 +1333,8 @@ int uv_fs_mkdtemp(uv_loop_t* loop, 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; } @@ -1330,7 +1362,7 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, INIT(READ); if (bufs == NULL || nbufs == 0) - return -EINVAL; + return UV_EINVAL; req->file = file; @@ -1339,11 +1371,8 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, 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)); @@ -1469,7 +1498,7 @@ int uv_fs_write(uv_loop_t* loop, INIT(WRITE); if (bufs == NULL || nbufs == 0) - return -EINVAL; + return UV_EINVAL; req->file = file; @@ -1478,11 +1507,8 @@ int uv_fs_write(uv_loop_t* loop, 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)); @@ -1509,6 +1535,10 @@ void uv_fs_req_cleanup(uv_fs_t* req) { 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; @@ -1523,8 +1553,11 @@ int uv_fs_copyfile(uv_loop_t* loop, 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; diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c index 3883740..47d8024 100644 --- a/Utilities/cmlibuv/src/unix/fsevents.c +++ b/Utilities/cmlibuv/src/unix/fsevents.c @@ -379,7 +379,7 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) { if (!pFSEventStreamStart(ref)) { pFSEventStreamInvalidate(ref); pFSEventStreamRelease(ref); - return -EMFILE; + return UV_EMFILE; } state->fsevent_stream = ref; @@ -440,7 +440,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle, 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); @@ -474,7 +474,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle, /* 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); @@ -528,7 +528,7 @@ static int uv__fsevents_global_init(void) { * 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", @@ -543,7 +543,7 @@ static int uv__fsevents_global_init(void) { if (core_services_handle == NULL) goto out; - err = -ENOENT; + err = UV_ENOENT; #define V(handle, symbol) \ do { \ *(void **)(&p ## symbol) = dlsym((handle), #symbol); \ @@ -607,7 +607,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { state = uv__calloc(1, sizeof(*state)); if (state == NULL) - return -ENOMEM; + return UV_ENOMEM; err = uv_mutex_init(&loop->cf_mutex); if (err) @@ -636,7 +636,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { 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; } @@ -655,7 +655,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { 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); @@ -787,7 +787,7 @@ int uv__cf_loop_signal(uv_loop_t* loop, item = uv__malloc(sizeof(*item)); if (item == NULL) - return -ENOMEM; + return UV_ENOMEM; item->handle = handle; item->type = type; @@ -817,7 +817,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { /* 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 */ @@ -830,7 +830,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { */ handle->cf_cb = uv__malloc(sizeof(*handle->cf_cb)); if (handle->cf_cb == NULL) { - err = -ENOMEM; + err = UV_ENOMEM; goto fail_cf_cb_malloc; } @@ -881,7 +881,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) { 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; @@ -895,7 +895,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) { 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); diff --git a/Utilities/cmlibuv/src/unix/getaddrinfo.c b/Utilities/cmlibuv/src/unix/getaddrinfo.c index 0185971..10e8afd 100644 --- a/Utilities/cmlibuv/src/unix/getaddrinfo.c +++ b/Utilities/cmlibuv/src/unix/getaddrinfo.c @@ -86,7 +86,7 @@ int uv__getaddrinfo_translate_error(int sys_err) { 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"); @@ -125,7 +125,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) { req->service = NULL; req->hostname = NULL; - if (status == -ECANCELED) { + if (status == UV_ECANCELED) { assert(req->retcode == 0); req->retcode = UV_EAI_CANCELED; } @@ -148,7 +148,7 @@ int uv_getaddrinfo(uv_loop_t* loop, 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; @@ -156,7 +156,7 @@ int uv_getaddrinfo(uv_loop_t* loop, 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; @@ -211,7 +211,7 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) { return UV_EINVAL; if (if_indextoname(ifindex, ifname_buf) == NULL) - return -errno; + return UV__ERR(errno); len = strnlen(ifname_buf, sizeof(ifname_buf)); diff --git a/Utilities/cmlibuv/src/unix/getnameinfo.c b/Utilities/cmlibuv/src/unix/getnameinfo.c index b2879d6..d9e6f79 100644 --- a/Utilities/cmlibuv/src/unix/getnameinfo.c +++ b/Utilities/cmlibuv/src/unix/getnameinfo.c @@ -61,7 +61,7 @@ static void uv__getnameinfo_done(struct uv__work* w, int status) { 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) { diff --git a/Utilities/cmlibuv/src/unix/ibmi.c b/Utilities/cmlibuv/src/unix/ibmi.c index c19e2fc..02e90fb 100644 --- a/Utilities/cmlibuv/src/unix/ibmi.c +++ b/Utilities/cmlibuv/src/unix/ibmi.c @@ -92,7 +92,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { *cpu_infos = uv__malloc(numcpus * sizeof(uv_cpu_info_t)); if (!*cpu_infos) { - return -ENOMEM; + return UV_ENOMEM; } cpu_info = *cpu_infos; diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h index 9cc87f0..89c6eb1 100644 --- a/Utilities/cmlibuv/src/unix/internal.h +++ b/Utilities/cmlibuv/src/unix/internal.h @@ -29,6 +29,7 @@ #include <string.h> /* strrchr */ #include <fcntl.h> /* O_CLOEXEC, may be */ #include <stdio.h> +#include <errno.h> #if defined(__STRICT_ANSI__) # define inline __inline @@ -194,12 +195,24 @@ struct uv__stream_queued_fds_s { #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); diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c index 5e89bdc..a30fd73 100644 --- a/Utilities/cmlibuv/src/unix/kqueue.c +++ b/Utilities/cmlibuv/src/unix/kqueue.c @@ -51,7 +51,7 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags); 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); @@ -98,7 +98,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { 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) @@ -458,12 +458,12 @@ int uv_fs_event_start(uv_fs_event_t* handle, 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); diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c index 4d480ce..b63c25f 100644 --- a/Utilities/cmlibuv/src/unix/linux-core.c +++ b/Utilities/cmlibuv/src/unix/linux-core.c @@ -101,7 +101,7 @@ int uv__platform_loop_init(uv_loop_t* loop) { loop->inotify_watchers = NULL; if (fd == -1) - return -errno; + return UV__ERR(errno); return 0; } @@ -175,7 +175,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { 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)) @@ -485,7 +485,7 @@ int uv_resident_set_memory(size_t* rss) { while (fd == -1 && errno == EINTR); if (fd == -1) - return -errno; + return UV__ERR(errno); do n = read(fd, buf, sizeof(buf) - 1); @@ -493,7 +493,7 @@ int uv_resident_set_memory(size_t* rss) { uv__close(fd); if (n == -1) - return -errno; + return UV__ERR(errno); buf[n] = '\0'; s = strchr(buf, ' '); @@ -525,7 +525,7 @@ int uv_resident_set_memory(size_t* rss) { return 0; err: - return -EINVAL; + return UV_EINVAL; } @@ -547,7 +547,7 @@ int uv_uptime(double* uptime) { } if (r) - return -errno; + return UV__ERR(errno); *uptime = now.tv_sec; return 0; @@ -559,7 +559,7 @@ static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) { char buf[1024]; if (!fgets(buf, sizeof(buf), statfile_fp)) - return -EIO; + return UV_EIO; num = 0; while (fgets(buf, sizeof(buf), statfile_fp)) { @@ -569,7 +569,7 @@ static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) { } if (num == 0) - return -EIO; + return UV_EIO; *numcpus = num; return 0; @@ -587,13 +587,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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; @@ -667,7 +667,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { 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) { @@ -676,7 +676,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { 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; @@ -695,7 +695,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { 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; @@ -725,7 +725,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { 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; } @@ -854,7 +854,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { 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; @@ -862,7 +862,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, struct sockaddr_ll *sll; if (getifaddrs(&addrs)) - return -errno; + return UV__ERR(errno); *count = 0; *addresses = NULL; @@ -881,7 +881,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, *addresses = uv__malloc(*count * sizeof(**addresses)); if (!(*addresses)) { freeifaddrs(addrs); - return -ENOMEM; + return UV_ENOMEM; } address = *addresses; diff --git a/Utilities/cmlibuv/src/unix/linux-inotify.c b/Utilities/cmlibuv/src/unix/linux-inotify.c index 5934c5d..bcad630 100644 --- a/Utilities/cmlibuv/src/unix/linux-inotify.c +++ b/Utilities/cmlibuv/src/unix/linux-inotify.c @@ -73,11 +73,11 @@ static int new_inotify_fd(void) { 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) @@ -283,7 +283,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, int wd; if (uv__is_active(handle)) - return -EINVAL; + return UV_EINVAL; err = init_inotify(handle->loop); if (err) @@ -300,7 +300,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, 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) @@ -308,7 +308,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, 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); diff --git a/Utilities/cmlibuv/src/unix/loop-watcher.c b/Utilities/cmlibuv/src/unix/loop-watcher.c index 340bb0d..b8c1c2a 100644 --- a/Utilities/cmlibuv/src/unix/loop-watcher.c +++ b/Utilities/cmlibuv/src/unix/loop-watcher.c @@ -31,7 +31,7 @@ \ 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); \ diff --git a/Utilities/cmlibuv/src/unix/loop.c b/Utilities/cmlibuv/src/unix/loop.c index 5b5b0e0..99ead6c 100644 --- a/Utilities/cmlibuv/src/unix/loop.c +++ b/Utilities/cmlibuv/src/unix/loop.c @@ -38,13 +38,14 @@ int uv_loop_init(uv_loop_t* loop) { 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; diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c index 7425072..2605c11 100644 --- a/Utilities/cmlibuv/src/unix/netbsd.c +++ b/Utilities/cmlibuv/src/unix/netbsd.c @@ -82,7 +82,7 @@ int uv_exepath(char* buffer, size_t* size) { int mib[4]; if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; + return UV_EINVAL; mib[0] = CTL_KERN; mib[1] = KERN_PROC_ARGS; @@ -91,7 +91,7 @@ int uv_exepath(char* buffer, size_t* size) { 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. @@ -111,7 +111,7 @@ uint64_t uv_get_free_memory(void) { 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); } @@ -128,7 +128,7 @@ uint64_t uv_get_total_memory(void) { size_t size = sizeof(info); if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; + return UV__ERR(errno); return (uint64_t) info; } @@ -150,7 +150,7 @@ int uv_set_process_title(const char* title) { if (process_title == NULL) { uv_mutex_unlock(&process_title_mutex); - return -ENOMEM; + return UV_ENOMEM; } uv__free(process_title); @@ -167,7 +167,7 @@ int uv_get_process_title(char* buffer, size_t size) { 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); @@ -177,7 +177,7 @@ int uv_get_process_title(char* buffer, size_t size) { if (size < len) { uv_mutex_unlock(&process_title_mutex); - return -ENOBUFS; + return UV_ENOBUFS; } memcpy(buffer, process_title, len); @@ -219,7 +219,7 @@ int uv_resident_set_memory(size_t* rss) { error: if (kd) kvm_close(kd); - return -EPERM; + return UV_EPERM; } @@ -230,7 +230,7 @@ int uv_uptime(double* uptime) { static int which[] = {CTL_KERN, KERN_BOOTTIME}; if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; + return UV__ERR(errno); now = time(NULL); @@ -254,12 +254,12 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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 */ @@ -270,16 +270,16 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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++) { diff --git a/Utilities/cmlibuv/src/unix/no-fsevents.c b/Utilities/cmlibuv/src/unix/no-fsevents.c index 38fb6ab..158643a 100644 --- a/Utilities/cmlibuv/src/unix/no-fsevents.c +++ b/Utilities/cmlibuv/src/unix/no-fsevents.c @@ -25,16 +25,16 @@ #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) { diff --git a/Utilities/cmlibuv/src/unix/no-proctitle.c b/Utilities/cmlibuv/src/unix/no-proctitle.c index a5c19fb..165740c 100644 --- a/Utilities/cmlibuv/src/unix/no-proctitle.c +++ b/Utilities/cmlibuv/src/unix/no-proctitle.c @@ -35,7 +35,7 @@ int uv_set_process_title(const char* title) { 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; diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c index c0ffa56..ce937cd 100644 --- a/Utilities/cmlibuv/src/unix/openbsd.c +++ b/Utilities/cmlibuv/src/unix/openbsd.c @@ -78,11 +78,11 @@ int uv_exepath(char* buffer, size_t* size) { 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; @@ -95,14 +95,14 @@ int uv_exepath(char* buffer, size_t* size) { 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; } @@ -128,7 +128,7 @@ uint64_t uv_get_free_memory(void) { 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); } @@ -140,7 +140,7 @@ uint64_t uv_get_total_memory(void) { size_t size = sizeof(info); if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; + return UV__ERR(errno); return (uint64_t) info; } @@ -162,7 +162,7 @@ int uv_set_process_title(const char* title) { if (process_title == NULL) { uv_mutex_unlock(&process_title_mutex); - return -ENOMEM; + return UV_ENOMEM; } uv__free(process_title); @@ -179,7 +179,7 @@ int uv_get_process_title(char* buffer, size_t size) { 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); @@ -189,7 +189,7 @@ int uv_get_process_title(char* buffer, size_t size) { if (size < len) { uv_mutex_unlock(&process_title_mutex); - return -ENOBUFS; + return UV_ENOBUFS; } memcpy(buffer, process_title, len); @@ -219,7 +219,7 @@ int uv_resident_set_memory(size_t* rss) { 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; @@ -233,7 +233,7 @@ int uv_uptime(double* uptime) { static int which[] = {CTL_KERN, KERN_BOOTTIME}; if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; + return UV__ERR(errno); now = time(NULL); @@ -255,16 +255,16 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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; @@ -272,7 +272,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { size = sizeof(cpuspeed); if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) { uv__free(*cpu_infos); - return -errno; + return UV__ERR(errno); } size = sizeof(info); @@ -283,7 +283,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 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]; diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c index 21558ea..a5dd344 100644 --- a/Utilities/cmlibuv/src/unix/os390-syscalls.c +++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c @@ -215,6 +215,7 @@ uv__os390_epoll* epoll_create1(int flags) { 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); @@ -252,6 +253,7 @@ int epoll_ctl(uv__os390_epoll* lst, } 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); diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c index 081438e..f766b39 100644 --- a/Utilities/cmlibuv/src/unix/os390.c +++ b/Utilities/cmlibuv/src/unix/os390.c @@ -122,7 +122,7 @@ int uv__platform_loop_init(uv_loop_t* loop) { ep = epoll_create1(0); loop->ep = ep; if (ep == NULL) - return -errno; + return UV__ERR(errno); return 0; } @@ -259,12 +259,12 @@ int uv_exepath(char* buffer, size_t* size) { 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: @@ -277,7 +277,7 @@ int uv_exepath(char* buffer, size_t* size) { /* 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); @@ -297,11 +297,11 @@ int uv_exepath(char* buffer, size_t* size) { 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) { @@ -327,7 +327,7 @@ int uv_exepath(char* buffer, size_t* size) { uv__free(clonedpath); /* Out of tokens (path entries), and no match found */ - return -EINVAL; + return UV_EINVAL; } } @@ -407,7 +407,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { *cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t)); if (!*cpu_infos) - return -ENOMEM; + return UV_ENOMEM; cpu_info = *cpu_infos; idx = 0; @@ -452,7 +452,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses, 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; @@ -460,7 +460,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses, if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) { uv__close(sockfd); - return -errno; + return UV__ERR(errno); } @@ -484,7 +484,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses, *addresses = uv__malloc(*count * sizeof(uv_interface_address_t)); if (!(*addresses)) { uv__close(sockfd); - return -ENOMEM; + return UV_ENOMEM; } address = *addresses; @@ -543,13 +543,13 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { 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)) @@ -569,7 +569,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { 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)) @@ -584,7 +584,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { if (!(*addresses)) { uv__close(sockfd); - return -ENOMEM; + return UV_ENOMEM; } address = *addresses; @@ -607,7 +607,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { 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)) @@ -706,7 +706,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, int rc; if (uv__is_active(handle)) - return -EINVAL; + return UV_EINVAL; ep = handle->loop->ep; assert(ep->msg_queue != -1); @@ -718,11 +718,11 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, 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; diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c index df3aad0..42846b9 100644 --- a/Utilities/cmlibuv/src/unix/pipe.c +++ b/Utilities/cmlibuv/src/unix/pipe.c @@ -48,12 +48,12 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { /* 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; @@ -69,10 +69,10 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { 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; @@ -92,7 +92,7 @@ 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 */ @@ -103,7 +103,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { #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; @@ -178,14 +178,14 @@ void uv_pipe_connect(uv_connect_t* req, 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; } @@ -232,7 +232,7 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle, err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen); if (err < 0) { *size = 0; - return -errno; + return UV__ERR(errno); } #if defined(__linux__) @@ -310,27 +310,12 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) { 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; @@ -348,8 +333,28 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) { 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); } diff --git a/Utilities/cmlibuv/src/unix/poll.c b/Utilities/cmlibuv/src/unix/poll.c index 816c7dc..f3b0bf4 100644 --- a/Utilities/cmlibuv/src/unix/poll.c +++ b/Utilities/cmlibuv/src/unix/poll.c @@ -47,7 +47,7 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { 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; } @@ -76,7 +76,7 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { * 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); diff --git a/Utilities/cmlibuv/src/unix/posix-poll.c b/Utilities/cmlibuv/src/unix/posix-poll.c index 3fba96e..f3181f9 100644 --- a/Utilities/cmlibuv/src/unix/posix-poll.c +++ b/Utilities/cmlibuv/src/unix/posix-poll.c @@ -107,7 +107,7 @@ static void uv__pollfds_add(uv_loop_t* loop, uv__io_t* w) { 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; @@ -115,7 +115,17 @@ static void uv__pollfds_del(uv_loop_t* loop, int fd) { 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; } } } @@ -315,10 +325,10 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { 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; } diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c index 47ab1dc..1bded8d 100644 --- a/Utilities/cmlibuv/src/unix/process.c +++ b/Utilities/cmlibuv/src/unix/process.c @@ -137,7 +137,7 @@ int uv__make_socketpair(int fds[2], int flags) { * Anything else is a genuine error. */ if (errno != EINVAL) - return -errno; + return UV__ERR(errno); no_cloexec = 1; @@ -145,7 +145,7 @@ skip: #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); @@ -170,7 +170,7 @@ int uv__make_pipe(int fds[2], int flags) { return 0; if (errno != ENOSYS) - return -errno; + return UV__ERR(errno); no_pipe2 = 1; @@ -178,7 +178,7 @@ skip: #endif if (pipe(fds)) - return -errno; + return UV__ERR(errno); uv__cloexec(fds[0], 1); uv__cloexec(fds[1], 1); @@ -209,7 +209,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { 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); @@ -221,21 +221,20 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { 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; @@ -249,13 +248,11 @@ static int uv__process_open_stream(uv_stdio_container_t* container, 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); } @@ -318,7 +315,7 @@ static void uv__process_child_init(const uv_process_options_t* options, 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); } } @@ -338,7 +335,7 @@ static void uv__process_child_init(const uv_process_options_t* options, close_fd = use_fd; if (use_fd == -1) { - uv__write_int(error_fd, -errno); + uv__write_int(error_fd, UV__ERR(errno)); _exit(127); } } @@ -350,7 +347,7 @@ static void uv__process_child_init(const uv_process_options_t* options, fd = dup2(use_fd, fd); if (fd == -1) { - uv__write_int(error_fd, -errno); + uv__write_int(error_fd, UV__ERR(errno)); _exit(127); } @@ -369,7 +366,7 @@ static void uv__process_child_init(const uv_process_options_t* options, } if (options->cwd != NULL && chdir(options->cwd)) { - uv__write_int(error_fd, -errno); + uv__write_int(error_fd, UV__ERR(errno)); _exit(127); } @@ -385,12 +382,12 @@ static void uv__process_child_init(const uv_process_options_t* options, } 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); } @@ -432,7 +429,7 @@ static void uv__process_child_init(const uv_process_options_t* options, if (SIG_ERR != signal(n, SIG_DFL)) continue; - uv__write_int(error_fd, -errno); + uv__write_int(error_fd, UV__ERR(errno)); _exit(127); } @@ -441,12 +438,12 @@ static void uv__process_child_init(const uv_process_options_t* options, 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 @@ -457,7 +454,7 @@ int uv_spawn(uv_loop_t* loop, 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]; @@ -498,7 +495,7 @@ int uv_spawn(uv_loop_t* loop, 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)); @@ -548,7 +545,7 @@ int uv_spawn(uv_loop_t* loop, 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]); @@ -588,7 +585,7 @@ int uv_spawn(uv_loop_t* loop, 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; @@ -640,7 +637,7 @@ int uv_process_kill(uv_process_t* process, int signum) { int uv_kill(int pid, int signum) { if (kill(pid, signum)) - return -errno; + return UV__ERR(errno); else return 0; } diff --git a/Utilities/cmlibuv/src/unix/procfs-exepath.c b/Utilities/cmlibuv/src/unix/procfs-exepath.c index 5fdb611..00dc021 100644 --- a/Utilities/cmlibuv/src/unix/procfs-exepath.c +++ b/Utilities/cmlibuv/src/unix/procfs-exepath.c @@ -29,14 +29,14 @@ int uv_exepath(char* buffer, size_t* size) { 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; diff --git a/Utilities/cmlibuv/src/unix/proctitle.c b/Utilities/cmlibuv/src/unix/proctitle.c index 1b3a798..1a8c7a7 100644 --- a/Utilities/cmlibuv/src/unix/proctitle.c +++ b/Utilities/cmlibuv/src/unix/proctitle.c @@ -105,14 +105,14 @@ int uv_set_process_title(const char* title) { 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) diff --git a/Utilities/cmlibuv/src/unix/signal.c b/Utilities/cmlibuv/src/unix/signal.c index 3759778..b9d0a56 100644 --- a/Utilities/cmlibuv/src/unix/signal.c +++ b/Utilities/cmlibuv/src/unix/signal.c @@ -225,7 +225,7 @@ static int uv__signal_register_handler(int signum, int oneshot) { /* XXX save old action so we can restore it later on? */ if (sigaction(signum, &sa, NULL)) - return -errno; + return UV__ERR(errno); return 0; } @@ -362,7 +362,7 @@ static int uv__signal_start(uv_signal_t* handle, * 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. diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c index 931e5f1..9bdd1c5 100644 --- a/Utilities/cmlibuv/src/unix/stream.c +++ b/Utilities/cmlibuv/src/unix/stream.c @@ -58,6 +58,12 @@ struct uv__stream_select_s { 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*); @@ -282,7 +288,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { 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); @@ -298,7 +304,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { 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; @@ -310,7 +316,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { * 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) @@ -321,7 +327,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { s = uv__malloc(sizeof(*s) + sread_sz + swrite_sz); if (s == NULL) { - err = -ENOMEM; + err = UV_ENOMEM; goto failed_malloc; } @@ -395,18 +401,18 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { #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__) @@ -414,7 +420,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) && errno != ENOTSOCK && errno != EINVAL) { - return -errno; + return UV__ERR(errno); } #endif @@ -445,11 +451,11 @@ void uv__stream_destroy(uv_stream_t* stream) { 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) { @@ -459,7 +465,7 @@ void uv__stream_destroy(uv_stream_t* stream) { * 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; } @@ -483,7 +489,7 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) { int emfile_fd; if (loop->emfile_fd == -1) - return -EMFILE; + return UV_EMFILE; uv__close(loop->emfile_fd); loop->emfile_fd = -1; @@ -492,7 +498,7 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) { 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) @@ -533,15 +539,15 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { 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; } @@ -577,7 +583,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) { assert(server->loop == client->loop); if (server->accepted_fd == -1) - return -EAGAIN; + return UV_EAGAIN; switch (client->type) { case UV_NAMED_PIPE: @@ -601,7 +607,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) { break; default: - return -EINVAL; + return UV_EINVAL; } client->flags |= UV_HANDLE_BOUND; @@ -649,7 +655,7 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { break; default: - err = -EINVAL; + err = UV_EINVAL; } if (err == 0) @@ -680,7 +686,7 @@ static void uv__drain(uv_stream_t* stream) { err = 0; if (shutdown(uv__stream_fd(stream), SHUT_WR)) - err = -errno; + err = UV__ERR(errno); if (err == 0) stream->flags |= UV_STREAM_SHUT; @@ -792,7 +798,7 @@ start: } scratch; if (uv__is_closing(req->send_handle)) { - err = -EBADF; + err = UV_EBADF; goto error; } @@ -859,8 +865,8 @@ start: } 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. */ @@ -1029,7 +1035,7 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { 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; @@ -1046,7 +1052,7 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { * 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; } @@ -1192,7 +1198,7 @@ static void uv__read(uv_stream_t* stream) { #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); @@ -1269,7 +1275,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { 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); @@ -1368,10 +1374,10 @@ static void uv__stream_connect(uv_stream_t* stream) { SO_ERROR, &error, &errorsize); - error = -error; + error = UV__ERR(error); } - if (error == -EINPROGRESS) + if (error == UV__ERR(EINPROGRESS)) return; stream->connect_req = NULL; @@ -1388,7 +1394,7 @@ static void uv__stream_connect(uv_stream_t* stream) { return; if (error < 0) { - uv__stream_flush_write_queue(stream, -ECANCELED); + uv__stream_flush_write_queue(stream, UV_ECANCELED); uv__write_callbacks(stream); } } @@ -1409,11 +1415,14 @@ int uv_write2(uv_write_t* req, "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 @@ -1422,12 +1431,12 @@ int uv_write2(uv_write_t* req, * 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 } @@ -1452,7 +1461,7 @@ int uv_write2(uv_write_t* req, 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; @@ -1516,7 +1525,7 @@ int uv_try_write(uv_stream_t* stream, /* 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); @@ -1547,7 +1556,7 @@ int uv_try_write(uv_stream_t* stream, } if (written == 0 && req_size != 0) - return -EAGAIN; + return UV_EAGAIN; else return written; } @@ -1560,7 +1569,10 @@ int uv_read_start(uv_stream_t* stream, 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. diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c index d6f9527..b92888e 100644 --- a/Utilities/cmlibuv/src/unix/sunos.c +++ b/Utilities/cmlibuv/src/unix/sunos.c @@ -77,7 +77,7 @@ int uv__platform_loop_init(uv_loop_t* loop) { fd = port_create(); if (fd == -1) - return -errno; + return UV__ERR(errno); err = uv__cloexec(fd, 1); if (err) { @@ -136,7 +136,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { 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(); @@ -346,7 +346,7 @@ int uv_exepath(char* buffer, size_t* size) { 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()); @@ -355,7 +355,7 @@ int uv_exepath(char* buffer, size_t* size) { res = readlink(buf, buffer, res); if (res == -1) - return -errno; + return UV__ERR(errno); buffer[res] = '\0'; *size = res; @@ -382,14 +382,14 @@ void uv_loadavg(double avg[3]) { 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; @@ -466,13 +466,13 @@ int uv_fs_event_start(uv_fs_event_t* handle, 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; } @@ -525,7 +525,7 @@ void uv__fs_event_close(uv_fs_event_t* handle) { #else /* !defined(PORT_SOURCE_FILE) */ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - return -ENOSYS; + return UV_ENOSYS; } @@ -533,12 +533,12 @@ 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; } @@ -556,10 +556,10 @@ int uv_resident_set_memory(size_t* rss) { 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; @@ -579,7 +579,7 @@ int uv_uptime(double* uptime) { 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) { @@ -603,7 +603,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { kc = kstat_open(); if (kc == NULL) - return -EPERM; + return UV_EPERM; /* Get count of cpus */ lookup_instance = 0; @@ -614,7 +614,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { *cpu_infos = uv__malloc(lookup_instance * sizeof(**cpu_infos)); if (!(*cpu_infos)) { kstat_close(kc); - return -ENOMEM; + return UV_ENOMEM; } *count = lookup_instance; @@ -696,7 +696,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { #ifdef SUNOS_NO_IFADDRS int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - return -ENOSYS; + return UV_ENOSYS; } #else /* SUNOS_NO_IFADDRS */ /* @@ -734,11 +734,11 @@ static int uv__set_phys_addr(uv_interface_address_t* address, 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); @@ -763,7 +763,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { struct ifaddrs* ent; if (getifaddrs(&addrs)) - return -errno; + return UV__ERR(errno); *count = 0; @@ -777,7 +777,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { *addresses = uv__malloc(*count * sizeof(**addresses)); if (!(*addresses)) { freeifaddrs(addrs); - return -ENOMEM; + return UV_ENOMEM; } address = *addresses; diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c index c7c8d21..9a46793 100644 --- a/Utilities/cmlibuv/src/unix/tcp.c +++ b/Utilities/cmlibuv/src/unix/tcp.c @@ -49,16 +49,14 @@ static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) { /* 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); } } @@ -89,7 +87,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) { 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) || @@ -102,7 +100,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) { /* Bind to arbitrary port */ if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) - return -errno; + return UV__ERR(errno); } handle->flags |= flags; @@ -119,10 +117,10 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int 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); @@ -156,18 +154,17 @@ int uv__tcp_bind(uv_tcp_t* 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; @@ -178,22 +175,23 @@ int uv__tcp_bind(uv_tcp_t* tcp, 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) @@ -214,7 +212,7 @@ int uv__tcp_connect(uv_connect_t* req, 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, @@ -242,9 +240,9 @@ int uv__tcp_connect(uv_connect_t* req, * 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); @@ -284,13 +282,13 @@ int uv_tcp_getsockname(const uv_tcp_t* handle, 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; @@ -306,13 +304,13 @@ int uv_tcp_getpeername(const uv_tcp_t* handle, 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; @@ -335,20 +333,20 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { 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; @@ -363,18 +361,18 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { 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, @@ -383,7 +381,7 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) { /* 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; diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c index abaca29..303bc6e 100644 --- a/Utilities/cmlibuv/src/unix/thread.c +++ b/Utilities/cmlibuv/src/unix/thread.c @@ -37,6 +37,10 @@ #include <sys/sem.h> #endif +#ifdef __GLIBC__ +#include <gnu/libc-version.h> /* gnu_get_libc_version() */ +#endif + #undef NANOSEC #define NANOSEC ((uint64_t) 1e9) @@ -200,7 +204,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { if (attr != NULL) pthread_attr_destroy(attr); - return -err; + return UV__ERR(err); } @@ -209,7 +213,7 @@ uv_thread_t uv_thread_self(void) { } int uv_thread_join(uv_thread_t *tid) { - return -pthread_join(*tid, NULL); + return UV__ERR(pthread_join(*tid, NULL)); } @@ -220,7 +224,7 @@ int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) { 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; @@ -236,7 +240,7 @@ int uv_mutex_init(uv_mutex_t* mutex) { if (pthread_mutexattr_destroy(&attr)) abort(); - return -err; + return UV__ERR(err); #endif } @@ -256,7 +260,7 @@ int uv_mutex_init_recursive(uv_mutex_t* mutex) { if (pthread_mutexattr_destroy(&attr)) abort(); - return -err; + return UV__ERR(err); } @@ -279,7 +283,7 @@ int uv_mutex_trylock(uv_mutex_t* mutex) { if (err) { if (err != EBUSY && err != EAGAIN) abort(); - return -EBUSY; + return UV_EBUSY; } return 0; @@ -293,7 +297,7 @@ void uv_mutex_unlock(uv_mutex_t* mutex) { int uv_rwlock_init(uv_rwlock_t* rwlock) { - return -pthread_rwlock_init(rwlock, NULL); + return UV__ERR(pthread_rwlock_init(rwlock, NULL)); } @@ -316,7 +320,7 @@ int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) { if (err) { if (err != EBUSY && err != EAGAIN) abort(); - return -EBUSY; + return UV_EBUSY; } return 0; @@ -342,7 +346,7 @@ int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) { if (err) { if (err != EBUSY && err != EAGAIN) abort(); - return -EBUSY; + return UV_EBUSY; } return 0; @@ -369,12 +373,12 @@ int uv_sem_init(uv_sem_t* sem, unsigned int value) { 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. */ } @@ -413,115 +417,151 @@ int uv_sem_trywait(uv_sem_t* sem) { 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 @@ -533,7 +573,7 @@ void uv_sem_wait(uv_sem_t* sem) { } -int uv_sem_trywait(uv_sem_t* sem) { +static int uv__sem_trywait(uv_sem_t* sem) { int r; do @@ -542,20 +582,63 @@ int uv_sem_trywait(uv_sem_t* sem) { 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__)) */ @@ -566,7 +649,7 @@ int uv_cond_init(uv_cond_t* cond) { 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); @@ -588,7 +671,7 @@ error: pthread_cond_destroy(cond); error2: pthread_condattr_destroy(&attr); - return -err; + return UV__ERR(err); } #endif /* defined(__APPLE__) && defined(__MACH__) */ @@ -646,13 +729,22 @@ void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { 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 @@ -672,15 +764,15 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { 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)); } @@ -699,7 +791,7 @@ int uv_barrier_wait(uv_barrier_t* barrier) { int uv_key_create(uv_key_t* key) { - return -pthread_key_create(key, NULL); + return UV__ERR(pthread_key_create(key, NULL)); } diff --git a/Utilities/cmlibuv/src/unix/timer.c b/Utilities/cmlibuv/src/unix/timer.c index f46bdf4..54dabfe 100644 --- a/Utilities/cmlibuv/src/unix/timer.c +++ b/Utilities/cmlibuv/src/unix/timer.c @@ -66,7 +66,7 @@ int uv_timer_start(uv_timer_t* handle, uint64_t clamped_timeout; if (cb == NULL) - return -EINVAL; + return UV_EINVAL; if (uv__is_active(handle)) uv_timer_stop(handle); @@ -105,7 +105,7 @@ int uv_timer_stop(uv_timer_t* 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); diff --git a/Utilities/cmlibuv/src/unix/tty.c b/Utilities/cmlibuv/src/unix/tty.c index fc8c3ab..e8ea302 100644 --- a/Utilities/cmlibuv/src/unix/tty.c +++ b/Utilities/cmlibuv/src/unix/tty.c @@ -106,7 +106,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { */ 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 @@ -139,7 +139,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { 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. @@ -160,7 +160,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { if (saved_flags == -1) { if (newfd != -1) uv__close(newfd); - return -errno; + return UV__ERR(errno); } #endif @@ -231,7 +231,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { 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); @@ -261,7 +261,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { /* Apply changes after draining */ if (tcsetattr(fd, TCSADRAIN, &tmp)) - return -errno; + return UV__ERR(errno); tty->mode = mode; return 0; @@ -277,7 +277,7 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { while (err == -1 && errno == EINTR); if (err == -1) - return -errno; + return UV__ERR(errno); *width = ws.ws_col; *height = ws.ws_row; @@ -355,12 +355,12 @@ int uv_tty_reset_mode(void) { 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; diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c index a475bf5..74d613b 100644 --- a/Utilities/cmlibuv/src/unix/udp.c +++ b/Utilities/cmlibuv/src/unix/udp.c @@ -72,7 +72,7 @@ void uv__udp_finish_close(uv_udp_t* handle) { 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); } @@ -189,7 +189,7 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { 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; @@ -242,7 +242,7 @@ static void uv__udp_sendmsg(uv_udp_t* handle) { 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 @@ -270,11 +270,11 @@ static int uv__set_reuse(int fd) { #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; @@ -291,11 +291,11 @@ int uv__udp_bind(uv_udp_t* handle, /* 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) { @@ -316,21 +316,21 @@ int uv__udp_bind(uv_udp_t* handle, #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; } @@ -418,7 +418,7 @@ int uv__udp_send(uv_udp_send_t* req, if (req->bufs == NULL) { uv__req_unregister(handle->loop, req); - return -ENOMEM; + return UV_ENOMEM; } memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0])); @@ -457,7 +457,7 @@ int uv__udp_try_send(uv_udp_t* handle, /* 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) @@ -475,9 +475,9 @@ int uv__udp_try_send(uv_udp_t* handle, if (size == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS) - return -EAGAIN; + return UV_EAGAIN; else - return -errno; + return UV__ERR(errno); } return size; @@ -512,7 +512,7 @@ static int uv__udp_set_membership4(uv_udp_t* handle, optname = IP_DROP_MEMBERSHIP; break; default: - return -EINVAL; + return UV_EINVAL; } if (setsockopt(handle->io_watcher.fd, @@ -522,9 +522,9 @@ static int uv__udp_set_membership4(uv_udp_t* handle, sizeof(mreq))) { #if defined(__MVS__) if (errno == ENXIO) - return -ENODEV; + return UV_ENODEV; #endif - return -errno; + return UV__ERR(errno); } return 0; @@ -543,7 +543,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle, 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; @@ -559,7 +559,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle, optname = IPV6_DROP_MEMBERSHIP; break; default: - return -EINVAL; + return UV_EINVAL; } if (setsockopt(handle->io_watcher.fd, @@ -569,9 +569,9 @@ static int uv__udp_set_membership6(uv_udp_t* handle, sizeof(mreq))) { #if defined(__MVS__) if (errno == ENXIO) - return -ENODEV; + return UV_ENODEV; #endif - return -errno; + return UV__ERR(errno); } return 0; @@ -586,10 +586,10 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int 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; if (domain != AF_UNSPEC) { err = uv__socket(domain, SOCK_DGRAM, 0); @@ -622,7 +622,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { /* Check for already active socket. */ if (handle->io_watcher.fd != -1) - return -EBUSY; + return UV_EBUSY; err = uv__nonblock(sock, 1); if (err) @@ -656,7 +656,7 @@ int uv_udp_set_membership(uv_udp_t* handle, return err; return uv__udp_set_membership6(handle, &addr6, interface_addr, membership); } else { - return -EINVAL; + return UV_EINVAL; } } @@ -680,7 +680,7 @@ static int uv__setsockopt(uv_udp_t* handle, val, size); if (r) - return -errno; + return UV__ERR(errno); return 0; } @@ -698,7 +698,7 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle, #endif if (val < 0 || val > 255) - return -EINVAL; + return UV_EINVAL; return uv__setsockopt(handle, option4, option6, &arg, sizeof(arg)); } @@ -710,7 +710,7 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int on) { SO_BROADCAST, &on, sizeof(on))) { - return -errno; + return UV__ERR(errno); } return 0; @@ -719,11 +719,11 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int on) { 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 /* @@ -817,7 +817,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) } 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) { @@ -826,7 +826,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) 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, @@ -834,7 +834,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) 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"); @@ -851,13 +851,13 @@ int uv_udp_getsockname(const uv_udp_t* handle, 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; @@ -870,10 +870,10 @@ int uv__udp_recv_start(uv_udp_t* handle, 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) diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c index fcb910f..15dec08 100644 --- a/Utilities/cmlibuv/src/uv-common.c +++ b/Utilities/cmlibuv/src/uv-common.c @@ -629,7 +629,7 @@ int uv_loop_close(uv_loop_t* loop) { 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) { diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h index 781a855..c497d01 100644 --- a/Utilities/cmlibuv/src/uv-common.h +++ b/Utilities/cmlibuv/src/uv-common.h @@ -41,6 +41,12 @@ #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 @@ -127,18 +133,18 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); 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) diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c index 8d121b3..b8aad11 100644 --- a/Utilities/cmlibuv/src/win/core.c +++ b/Utilities/cmlibuv/src/win/core.c @@ -239,7 +239,7 @@ int uv_loop_init(uv_loop_t* loop) { 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; @@ -470,8 +470,8 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) { 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; } diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c index 95f843a..14c9af9 100644 --- a/Utilities/cmlibuv/src/win/fs-event.c +++ b/Utilities/cmlibuv/src/win/fs-event.c @@ -69,6 +69,7 @@ static void uv_relative_path(const WCHAR* filename, 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; @@ -151,11 +152,11 @@ int uv_fs_event_start(uv_fs_event_t* handle, 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; @@ -197,6 +198,30 @@ int uv_fs_event_start(uv_fs_event_t* handle, 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 { /* diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c index 097b00e..30b87ac 100644 --- a/Utilities/cmlibuv/src/win/fs.c +++ b/Utilities/cmlibuv/src/win/fs.c @@ -783,7 +783,9 @@ void fs__unlink(uv_fs_t* req) { /* 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, @@ -1390,6 +1392,12 @@ static void fs__copyfile(uv_fs_t* req) { 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) { @@ -2334,8 +2342,11 @@ int uv_fs_copyfile(uv_loop_t* loop, 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); diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c index 282d919..5adc766 100644 --- a/Utilities/cmlibuv/src/win/getaddrinfo.c +++ b/Utilities/cmlibuv/src/win/getaddrinfo.c @@ -392,15 +392,21 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) { DWORD bufsize; int r; + uv__once_init(); + if (buffer == NULL || size == NULL || *size == 0) return UV_EINVAL; - 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); diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h index 9f28f77..849bc82 100644 --- a/Utilities/cmlibuv/src/win/internal.h +++ b/Utilities/cmlibuv/src/win/internal.h @@ -225,10 +225,16 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, 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); diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c index 1a7c4dc..83ee4f9 100644 --- a/Utilities/cmlibuv/src/win/pipe.c +++ b/Utilities/cmlibuv/src/win/pipe.c @@ -735,6 +735,13 @@ void uv__pipe_unpause_read(uv_pipe_t* handle) { 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); @@ -847,6 +854,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, return; } + /* Wait for completion via IOCP */ handle->reqs_pending++; } diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c index f5f05af..25cfe87 100644 --- a/Utilities/cmlibuv/src/win/process.c +++ b/Utilities/cmlibuv/src/win/process.c @@ -1067,11 +1067,16 @@ int uv_spawn(uv_loop_t* loop, 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; } diff --git a/Utilities/cmlibuv/src/win/stream-inl.h b/Utilities/cmlibuv/src/win/stream-inl.h index dba0374..40f5ddd 100644 --- a/Utilities/cmlibuv/src/win/stream-inl.h +++ b/Utilities/cmlibuv/src/win/stream-inl.h @@ -37,11 +37,6 @@ INLINE static void uv_stream_init(uv_loop_t* loop, 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); @@ -51,4 +46,9 @@ INLINE static void uv_connection_init(uv_stream_t* handle) { } +INLINE static void uv_connection_init(uv_stream_t* handle) { + handle->flags |= UV_HANDLE_CONNECTION; +} + + #endif /* UV_WIN_STREAM_INL_H_ */ diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c index fd6efba..39c1ff0 100644 --- a/Utilities/cmlibuv/src/win/tcp.c +++ b/Utilities/cmlibuv/src/win/tcp.c @@ -459,8 +459,6 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { 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. */ @@ -1173,11 +1171,14 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, 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++; diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c index 05a11e8..ecf7bc9 100644 --- a/Utilities/cmlibuv/src/win/tty.c +++ b/Utilities/cmlibuv/src/win/tty.c @@ -2235,14 +2235,20 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { } -/* 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(); diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c index 3100bc2..49b5bc7 100644 --- a/Utilities/cmlibuv/src/win/util.c +++ b/Utilities/cmlibuv/src/win/util.c @@ -37,7 +37,7 @@ #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 @@ -587,8 +587,8 @@ int uv_uptime(double* uptime) { 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; } @@ -615,7 +615,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { 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; @@ -670,34 +670,33 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { 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; } @@ -1148,53 +1147,17 @@ int uv_getrusage(uv_rusage_t *uv_rusage) { 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); diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c index 4ccdf0a..c330786 100644 --- a/Utilities/cmlibuv/src/win/winapi.c +++ b/Utilities/cmlibuv/src/win/winapi.c @@ -55,12 +55,16 @@ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; /* User32.dll function pointer */ sSetWinEventHook pSetWinEventHook; +/* iphlpapi.dll function pointer */ +sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid = NULL; +sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW = NULL; void uv_winapi_init(void) { HMODULE ntdll_module; HMODULE kernel32_module; HMODULE powrprof_module; HMODULE user32_module; + HMODULE iphlpapi_module; ntdll_module = GetModuleHandleA("ntdll.dll"); if (ntdll_module == NULL) { @@ -166,4 +170,11 @@ void uv_winapi_init(void) { GetProcAddress(user32_module, "SetWinEventHook"); } + iphlpapi_module = LoadLibraryA("iphlpapi.dll"); + if (iphlpapi_module != NULL) { + pConvertInterfaceIndexToLuid = (sConvertInterfaceIndexToLuid) + GetProcAddress(iphlpapi_module, "ConvertInterfaceIndexToLuid"); + pConvertInterfaceLuidToNameW = (sConvertInterfaceLuidToNameW) + GetProcAddress(iphlpapi_module, "ConvertInterfaceLuidToNameW"); + } } diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h index 8993c65..ae384b7 100644 --- a/Utilities/cmlibuv/src/win/winapi.h +++ b/Utilities/cmlibuv/src/win/winapi.h @@ -4784,4 +4784,19 @@ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotifi /* User32.dll function pointer */ extern sSetWinEventHook pSetWinEventHook; +/* iphlpapi.dll function pointer */ +union _NET_LUID_LH; +typedef DWORD (WINAPI *sConvertInterfaceIndexToLuid)( + ULONG InterfaceIndex, + union _NET_LUID_LH *InterfaceLuid); + +typedef DWORD (WINAPI *sConvertInterfaceLuidToNameW)( + const union _NET_LUID_LH *InterfaceLuid, + PWSTR InterfaceName, + size_t Length); + +extern sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid; +extern sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW; + + #endif /* UV_WIN_WINAPI_H_ */ diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c index 7cfa90f..8418895 100644 --- a/Utilities/cmlibuv/src/win/winsock.c +++ b/Utilities/cmlibuv/src/win/winsock.c @@ -580,8 +580,10 @@ int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr, 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; |