diff options
157 files changed, 2924 insertions, 1003 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 472c6ab..ed5de10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -806,6 +806,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) PATTERN "*.sh*" PERMISSIONS OWNER_READ OWNER_EXECUTE OWNER_WRITE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + REGEX "Help/dev($|/)" EXCLUDE ) # Install auxiliary files integrating with other tools. diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 921ba7c..434f0f4 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,6 +1,11 @@ Contributing to CMake ********************* +The following summarizes the process for contributing changes. +See documentation on `CMake Development`_ for more information. + +.. _`CMake Development`: Help/dev/README.rst + Community ========= @@ -19,13 +24,18 @@ CMake uses `Kitware's GitLab Instance`_ to manage development and code review. To contribute patches: #. Fork the upstream `CMake Repository`_ into a personal account. +#. Run `Utilities/SetupForDevelopment.sh`_ for local configuration. #. Base all new work on the upstream ``master`` branch. #. Create commits making incremental, distinct, logically complete changes. #. Push a topic branch to a personal repository fork on GitLab. #. Create a GitLab Merge Request targeting the upstream ``master`` branch. +The merge request will enter the `CMake Review Process`_ for consideration. + .. _`Kitware's GitLab Instance`: https://gitlab.kitware.com .. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake +.. _`Utilities/SetupForDevelopment.sh`: Utilities/SetupForDevelopment.sh +.. _`CMake Review Process`: Help/dev/review.rst Code Style ========== diff --git a/Help/dev/README.rst b/Help/dev/README.rst new file mode 100644 index 0000000..0dc512a --- /dev/null +++ b/Help/dev/README.rst @@ -0,0 +1,31 @@ +CMake Development +***************** + +This directory contains documentation about development of CMake itself. +It is not part of the user documentation distributed with CMake. + +Contributor Instructions +======================== + +See `CONTRIBUTING.rst`_ for instructions to contribute changes. + +The process for contributing changes is the same whether or not one +has been invited to participate directly in upstream development. + +.. _`CONTRIBUTING.rst`: ../../CONTRIBUTING.rst + +Upstream Development +==================== + +CMake uses `Kitware's GitLab Instance`_ to manage development, review, and +integration of changes. The `CMake Repository`_ holds the integration +branches and tags. Upstream development processes are covered by the +following documents: + +* The `CMake Review Process`_ manages integration of changes. +* The `CMake Testing Process`_ drives integration testing. + +.. _`Kitware's GitLab Instance`: https://gitlab.kitware.com +.. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake +.. _`CMake Review Process`: review.rst +.. _`CMake Testing Process`: testing.rst diff --git a/Help/dev/review.rst b/Help/dev/review.rst new file mode 100644 index 0000000..e23c0fb --- /dev/null +++ b/Help/dev/review.rst @@ -0,0 +1,306 @@ +CMake Review Process +******************** + +The following documents the process for reviewing and integrating changes. +See `CONTRIBUTING.rst`_ for instructions to contribute changes. +See documentation on `CMake Development`_ for more information. + +.. _`CONTRIBUTING.rst`: ../../CONTRIBUTING.rst +.. _`CMake Development`: README.rst + +.. contents:: The review process consists of the following steps: + +Merge Request +============= + +A user initiates the review process for a change by pushing a *topic +branch* to his or her own fork of the `CMake Repository`_ on GitLab and +creating a *merge request* ("MR"). The new MR will appear on the +`CMake Merge Requests Page`_. The rest of the review and integration +process is managed by the merge request page for the change. + +During the review process, the MR submitter should address review comments +or test failures by updating the MR with a (force-)push of the topic +branch. The update initiates a new round of review. + +We recommend that users enable the "Remove source branch when merge +request is accepted" option when creating the MR or by editing it. +This will cause the MR topic branch to be automatically removed from +the user's fork during the `Merge`_ step. + +.. _`CMake Merge Requests Page`: https://gitlab.kitware.com/cmake/cmake/merge_requests +.. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake + +Workflow Status +--------------- + +`CMake GitLab Project Developers`_ may set one of the following labels +in GitLab to track the state of a MR: + +* ``workflow:wip`` indicates that the MR needs additional updates from + the MR submitter before further review. Use this label after making + comments that require such updates. + +* ``workflow:in-review`` indicates that the MR awaits feedback from a + human reviewer or from `Topic Testing`_. Use this label after making + comments requesting such feedback. + +* ``workflow:nightly-testing`` indicates that the MR awaits results + of `Integration Testing`_. Use this label after making comments + requesting such staging. + +* ``workflow:expired`` indicates that the MR has been closed due + to a period of inactivity. See the `Expire`_ step. Use this label + after closing a MR for this reason. + +The workflow status labels are intended to be mutually exclusive, +so please remove any existing workflow label when adding one. + +.. _`CMake GitLab Project Developers`: https://gitlab.kitware.com/cmake/cmake/settings/members + +Robot Review +============ + +The "Kitware Robot" (``@kwrobot``) automatically performs basic checks on +the commits proposed in a MR. If all is well the robot silently reports +a successful "build" status to GitLab. Otherwise the robot posts a comment +with its diagnostics. **A topic may not be merged until the automatic +review succeeds.** The MR submitter is expected to address the robot's +comments by *rewriting* the commits named by the robot's diagnostics +(e.g. via ``git rebase -i``). + +The automatic check is repeated whenever the topic branch is updated. +One may explicitly request a re-check by adding a comment with the +following command among the `comment trailing lines`_:: + + Do: check + +``@kwrobot`` will add an award emoji to the comment to indicate that it +was processed and also run its checks again. + +Human Review +============ + +Anyone is welcome to review merge requests and make comments! + +Reviewers may add comments providing feedback or to acknowledge their +approval. Lines of specific forms will be extracted during the `merge`_ +step and included as trailing lines of the generated merge commit message. +Each review comment consists of up to two parts which must be specified +in the following order: `comment body`_, then `comment trailing lines`_. +Each part is optional, but they must be specified in this order. + +Comment Body +------------ + +The body of a comment may be free-form `GitLab Flavored Markdown`_. +See GitLab documentation on `Special GitLab References`_ to add links to +things like issues, commits, or other merge requests (even across projects). + +Additionally, a line in the comment body may start with one of the +following votes: + +* ``-1`` or ``:-1:`` indicates "the change is not ready for integration". + +* ``+1`` or ``:+1:`` indicates "I like the change". + This adds an ``Acked-by:`` trailer to the `merge`_ commit message. + +* ``+2`` indicates "the change is ready for integration". + This adds a ``Reviewed-by:`` trailer to the `merge`_ commit message. + +* ``+3`` indicates "I have tested the change and verified it works". + This adds a ``Tested-by:`` trailer to the `merge`_ commit message. + +.. _`GitLab Flavored Markdown`: https://gitlab.kitware.com/help/user/markdown.md +.. _`Special GitLab References`: https://gitlab.kitware.com/help/user/markdown.md#special-gitlab-references + +Comment Trailing Lines +---------------------- + +Zero or more *trailing* lines in the last section of a comment may appear +with the form ``Key: Value``. The first such line should be separated +from a preceding `comment body`_ by a blank line. Any key-value pair(s) +may be specified for human reference. A few specific keys have meaning to +``@kwrobot`` as follows. + +Comment Trailer Votes +^^^^^^^^^^^^^^^^^^^^^ + +Among the `comment trailing lines`_ one may cast a vote using one of the +following pairs followed by nothing but whitespace before the end of the line: + +* ``Rejected-by: me`` indicates "the change is not ready for integration". +* ``Acked-by: me`` indicates "I like the change". + This adds an ``Acked-by:`` trailer to the `merge`_ commit message. +* ``Reviewed-by: me`` indicates "the change is ready for integration". + This adds a ``Reviewed-by:`` trailer to the `merge`_ commit message. +* ``Tested-by: me`` indicates "I have tested the change and verified it works". + This adds a ``Tested-by:`` trailer to the `merge`_ commit message. + +Each ``me`` reference may instead be an ``@username`` reference or a full +``Real Name <user@domain>`` reference to credit someone else for performing +the review. References to ``me`` and ``@username`` will automatically be +transformed into a real name and email address according to the user's +GitLab account profile. + +Comment Trailer Commands +^^^^^^^^^^^^^^^^^^^^^^^^ + +Among the `comment trailing lines`_ authorized users may issue special +commands to ``@kwrobot`` using the form ``Do: ...``: + +* ``Do: check`` explicitly re-runs `Robot Review`_ checks. +* ``Do: test`` submits the MR for `Topic Testing`_. +* ``Do: stage`` submits the MR for `Integration Testing`_. +* ``Do: merge`` submits the MR for `Merge`_. + +See the corresponding sections for details on permissions and options +for each command. + +Topic Testing +============= + +CMake has a `buildbot`_ instance watching for merge requests to test. +`CMake GitLab Project Developers`_ may activate buildbot on a MR by +adding a comment with a command among the `comment trailing lines`_:: + + Do: test + +``@kwrobot`` will add an award emoji to the comment to indicate that it +was processed and also inform buildbot about the request. The buildbot +user (``@buildbot``) will schedule builds and respond with a comment +linking to the `CMake CDash Page`_ with a filter for results associated +with the topic test request. If the MR topic branch is updated by a +push a new ``Do: test`` command is needed to activate testing again. + +The ``Do: test`` command accepts the following arguments: + +* ``--stop``: clear the list of commands for the merge request +* ``--clear``: clear previous commands before adding this command +* ``--regex-include <arg>`` or ``-i <arg>``: only build on builders + matching ``<arg>`` (a Python regular expression) +* ``--regex-exclude <arg>`` or ``-e <arg>``: exclude builds on builders + matching ``<arg>`` (a Python regular expression) + +Builder names follow the pattern ``project-host-os-buildtype-generator``: + +* ``project``: always ``cmake`` for CMake builds +* ``host``: the buildbot host +* ``os``: one of ``windows``, ``osx``, or ``linux`` +* ``buildtype``: ``release`` or ``debug`` +* ``generator``: ``ninja``, ``makefiles``, or ``vs<year>`` + +.. _`buildbot`: http://buildbot.net +.. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake + +Integration Testing +=================== + +The above `topic testing`_ tests the MR topic independent of other +merge requests and on only a few key platforms and configurations. +The `CMake Testing Process`_ also has a large number of machines +provided by Kitware and generous volunteers that cover nearly all +supported platforms, generators, and configurations. In order to +avoid overwhelming these resources, they do not test every MR +individually. Instead, these machines follow an *integration branch*, +run tests on a nightly basis (or continuously during the day), and +post to the `CMake CDash Page`_. Some follow ``master``. Most follow +a special integration branch, the *topic stage*. + +The topic stage is a special branch maintained by the "Kitware Robot" +(``@kwrobot``). It consists of the head of the MR target integration +branch (e.g. ``master``) branch followed by a sequence of merges each +integrating changes from an open MR that has been staged for integration +testing. Each time the target integration branch is updated the stage +is rebuilt automatically by merging the staged MR topics again. + +`CMake GitLab Project Developers`_ may stage a MR for integration testing +by adding a comment with a command among the `comment trailing lines`_:: + + Do: stage + +``@kwrobot`` will add an award emoji to the comment to indicate that it +was processed and also attempt to add the MR topic branch to the topic +stage. If the MR cannot be added (e.g. due to conflicts) the robot will +post a comment explaining what went wrong. + +Once a MR has been added to the topic stage it will remain on the stage +until one of the following occurs: + +* The MR topic branch is updated by a push. + +* The MR target integration branch (e.g. ``master``) branch is updated + and the MR cannot be merged into the topic stage again due to conflicts. + +* A developer or the submitter posts an explicit ``Do: unstage`` command. + +* The MR is closed. + +* The MR is merged. + +Once a MR has been removed from the topic stage a new ``Do: stage`` +command is needed to stage it again. + +.. _`CMake Testing Process`: testing.rst + +Resolve +======= + +A MR may be resolved in one of the following ways. + +Merge +----- + +Once review has concluded that the MR topic is ready for integration, +`CMake GitLab Project Masters`_ may merge the topic by adding a comment +with a command among the `comment trailing lines`_:: + + Do: merge + +``@kwrobot`` will add an award emoji to the comment to indicate that it +was processed and also attempt to merge the MR topic branch to the MR +target integration branch (e.g. ``master``). If the MR cannot be merged +(e.g. due to conflicts) the robot will post a comment explaining what +went wrong. If the MR is merged the robot will also remove the source +branch from the user's fork if the corresponding MR option was checked. + +The robot automatically constructs a merge commit message of the following +form:: + + Merge topic 'mr-topic-branch-name' + + 00000000 commit message subject line (one line per commit) + + Acked-by: Kitware Robot <kwrobot@kitware.com> + Merge-request: !0000 + +Mention of the commit short sha1s and MR number helps GitLab link the +commits back to the merge request and indicates when they were merged. +The ``Acked-by:`` trailer shown indicates that `Robot Review`_ passed. +Additional ``Acked-by:``, ``Reviewed-by:``, and similar trailers may be +collected from `Human Review`_ comments that have been made since the +last time the MR topic branch was updated with a push. + +The ``Do: merge`` command accepts the following arguments: + +* ``-t <topic>``: substitute ``<topic>`` for the name of the MR topic + branch in the constructed merge commit message. + +.. _`CMake GitLab Project Masters`: https://gitlab.kitware.com/cmake/cmake/settings/members + +Close +----- + +If review has concluded that the MR should not be integrated then it +may be closed through GitLab. + +Expire +------ + +If progress on a MR has stalled for a while, it may be closed with a +``workflow:expired`` label and a comment indicating that the MR has +been closed due to inactivity. + +Contributors are welcome to re-open an expired MR when they are ready +to continue work. Please re-open *before* pushing an update to the +MR topic branch to ensure GitLab will still act on the association. diff --git a/Help/dev/testing.rst b/Help/dev/testing.rst new file mode 100644 index 0000000..731930c --- /dev/null +++ b/Help/dev/testing.rst @@ -0,0 +1,42 @@ +CMake Testing Process +********************* + +The following documents the process for running integration testing builds. +See documentation on `CMake Development`_ for more information. + +.. _`CMake Development`: README.rst + +CMake Dashboard Scripts +======================= + +The *integration testing* step of the `CMake Review Process`_ uses a set of +testing machines that follow an integration branch on their own schedule to +drive testing and submit results to the `CMake CDash Page`_. Anyone is +welcome to provide testing machines in order to help keep support for their +platforms working. + +The `CMake Dashboard Scripts Repository`_ provides CTest scripts to drive +nightly, continous, and experimental testing of CMake. Use the following +commands to set up a new integration testing client: + +.. code-block:: console + + $ mkdir -p ~/Dashboards + $ cd ~/Dashboards + $ git clone https://gitlab.kitware.com/cmake/dashboard-scripts.git CMakeScripts + $ cd CMakeScripts + +The ``cmake_common.cmake`` script contains comments at the top with +instructions to set up a testing client. As it instructs, create a +CTest script with local settings and include ``cmake_common.cmake``. + +.. _`CMake Review Process`: review.rst +.. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake +.. _`CMake Dashboard Scripts Repository`: https://gitlab.kitware.com/cmake/dashboard-scripts + +Nightly Start Time +------------------ + +The ``cmake_common.cmake`` script expects its includer to be run from a +nightly scheduled task (cron job). Schedule such tasks for sometime after +``1:00am UTC``, the time at which our nightly testing branches fast-forward. diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 2157ba5..e07150a 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -46,7 +46,6 @@ Properties of Global Scope /prop_gbl/TARGET_SUPPORTS_SHARED_LIBS /prop_gbl/USE_FOLDERS /prop_gbl/XCODE_EMIT_EFFECTIVE_PLATFORM_NAME - /prop_gbl/XCODE_GENERATE_SCHEME .. _`Directory Properties`: diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 79c7cd8..9d8d596 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -13,9 +13,9 @@ Variables that Provide Information .. toctree:: :maxdepth: 1 + /variable/CMAKE_AR /variable/CMAKE_ARGC /variable/CMAKE_ARGV0 - /variable/CMAKE_AR /variable/CMAKE_BINARY_DIR /variable/CMAKE_BUILD_TOOL /variable/CMAKE_CACHEFILE_DIR @@ -40,6 +40,8 @@ Variables that Provide Information /variable/CMAKE_FIND_PACKAGE_NAME /variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION /variable/CMAKE_FIND_PACKAGE_SORT_ORDER + /variable/CMAKE_GCC_AR + /variable/CMAKE_GCC_RANLIB /variable/CMAKE_GENERATOR /variable/CMAKE_GENERATOR_PLATFORM /variable/CMAKE_GENERATOR_TOOLSET @@ -82,18 +84,20 @@ Variables that Provide Information /variable/CMAKE_VS_NsightTegra_VERSION /variable/CMAKE_VS_PLATFORM_NAME /variable/CMAKE_VS_PLATFORM_TOOLSET + /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION + /variable/CMAKE_XCODE_GENERATE_SCHEME /variable/CMAKE_XCODE_PLATFORM_TOOLSET - /variable/PROJECT_BINARY_DIR /variable/PROJECT-NAME_BINARY_DIR - /variable/PROJECT_NAME /variable/PROJECT-NAME_SOURCE_DIR /variable/PROJECT-NAME_VERSION /variable/PROJECT-NAME_VERSION_MAJOR /variable/PROJECT-NAME_VERSION_MINOR /variable/PROJECT-NAME_VERSION_PATCH /variable/PROJECT-NAME_VERSION_TWEAK + /variable/PROJECT_BINARY_DIR + /variable/PROJECT_NAME /variable/PROJECT_SOURCE_DIR /variable/PROJECT_VERSION /variable/PROJECT_VERSION_MAJOR @@ -127,7 +131,6 @@ Variables that Change Behavior /variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION /variable/CMAKE_EXPORT_COMPILE_COMMANDS /variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY - /variable/CMAKE_SYSROOT /variable/CMAKE_FIND_APPBUNDLE /variable/CMAKE_FIND_FRAMEWORK /variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX @@ -144,9 +147,9 @@ Variables that Change Behavior /variable/CMAKE_FIND_ROOT_PATH_MODE_PROGRAM /variable/CMAKE_FRAMEWORK_PATH /variable/CMAKE_IGNORE_PATH - /variable/CMAKE_INCLUDE_PATH /variable/CMAKE_INCLUDE_DIRECTORIES_BEFORE /variable/CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE + /variable/CMAKE_INCLUDE_PATH /variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME /variable/CMAKE_INSTALL_MESSAGE /variable/CMAKE_INSTALL_PREFIX @@ -164,6 +167,7 @@ Variables that Change Behavior /variable/CMAKE_STAGING_PREFIX /variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS /variable/CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE + /variable/CMAKE_SYSROOT /variable/CMAKE_SYSTEM_APPBUNDLE_PATH /variable/CMAKE_SYSTEM_FRAMEWORK_PATH /variable/CMAKE_SYSTEM_IGNORE_PATH @@ -188,23 +192,24 @@ Variables that Describe the System /variable/CMAKE_COMPILER_2005 /variable/CMAKE_HOST_APPLE /variable/CMAKE_HOST_SOLARIS + /variable/CMAKE_HOST_SYSTEM /variable/CMAKE_HOST_SYSTEM_NAME /variable/CMAKE_HOST_SYSTEM_PROCESSOR - /variable/CMAKE_HOST_SYSTEM /variable/CMAKE_HOST_SYSTEM_VERSION /variable/CMAKE_HOST_UNIX /variable/CMAKE_HOST_WIN32 - /variable/CMAKE_LIBRARY_ARCHITECTURE_REGEX /variable/CMAKE_LIBRARY_ARCHITECTURE + /variable/CMAKE_LIBRARY_ARCHITECTURE_REGEX /variable/CMAKE_OBJECT_PATH_MAX + /variable/CMAKE_SYSTEM /variable/CMAKE_SYSTEM_NAME /variable/CMAKE_SYSTEM_PROCESSOR - /variable/CMAKE_SYSTEM /variable/CMAKE_SYSTEM_VERSION /variable/CYGWIN /variable/ENV /variable/GHS-MULTI /variable/MINGW + /variable/MSVC /variable/MSVC10 /variable/MSVC11 /variable/MSVC12 @@ -215,7 +220,6 @@ Variables that Describe the System /variable/MSVC80 /variable/MSVC90 /variable/MSVC_IDE - /variable/MSVC /variable/MSVC_VERSION /variable/UNIX /variable/WIN32 @@ -257,9 +261,9 @@ Variables that Control the Build /variable/CMAKE_ANDROID_STL_TYPE /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY_CONFIG + /variable/CMAKE_AUTOMOC /variable/CMAKE_AUTOMOC_DEPEND_FILTERS /variable/CMAKE_AUTOMOC_MOC_OPTIONS - /variable/CMAKE_AUTOMOC /variable/CMAKE_AUTORCC /variable/CMAKE_AUTORCC_OPTIONS /variable/CMAKE_AUTOUIC @@ -273,18 +277,19 @@ Variables that Control the Build /variable/CMAKE_CONFIG_POSTFIX /variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_ENABLE_EXPORTS + /variable/CMAKE_EXE_LINKER_FLAGS /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT - /variable/CMAKE_EXE_LINKER_FLAGS /variable/CMAKE_EXE_LINKER_FLAGS_INIT /variable/CMAKE_Fortran_FORMAT /variable/CMAKE_Fortran_MODULE_DIRECTORY /variable/CMAKE_GNUtoMS - /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE /variable/CMAKE_INCLUDE_CURRENT_DIR + /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE /variable/CMAKE_INSTALL_NAME_DIR /variable/CMAKE_INSTALL_RPATH /variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH + /variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION /variable/CMAKE_IOS_INSTALL_COMBINED /variable/CMAKE_LANG_CLANG_TIDY /variable/CMAKE_LANG_COMPILER_LAUNCHER @@ -303,9 +308,9 @@ Variables that Control the Build /variable/CMAKE_MACOSX_BUNDLE /variable/CMAKE_MACOSX_RPATH /variable/CMAKE_MAP_IMPORTED_CONFIG_CONFIG + /variable/CMAKE_MODULE_LINKER_FLAGS /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG_INIT - /variable/CMAKE_MODULE_LINKER_FLAGS /variable/CMAKE_MODULE_LINKER_FLAGS_INIT /variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX /variable/CMAKE_NO_BUILTIN_CHRPATH @@ -318,15 +323,15 @@ Variables that Control the Build /variable/CMAKE_POSITION_INDEPENDENT_CODE /variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY /variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY_CONFIG + /variable/CMAKE_SHARED_LINKER_FLAGS /variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG /variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG_INIT - /variable/CMAKE_SHARED_LINKER_FLAGS /variable/CMAKE_SHARED_LINKER_FLAGS_INIT /variable/CMAKE_SKIP_BUILD_RPATH /variable/CMAKE_SKIP_INSTALL_RPATH + /variable/CMAKE_STATIC_LINKER_FLAGS /variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG /variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG_INIT - /variable/CMAKE_STATIC_LINKER_FLAGS /variable/CMAKE_STATIC_LINKER_FLAGS_INIT /variable/CMAKE_TRY_COMPILE_CONFIGURATION /variable/CMAKE_TRY_COMPILE_PLATFORM_VARIABLES @@ -335,8 +340,8 @@ Variables that Control the Build /variable/CMAKE_VISIBILITY_INLINES_HIDDEN /variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD /variable/CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD - /variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS /variable/CMAKE_WIN32_EXECUTABLE + /variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS /variable/CMAKE_XCODE_ATTRIBUTE_an-attribute /variable/EXECUTABLE_OUTPUT_PATH /variable/LIBRARY_OUTPUT_PATH @@ -350,10 +355,6 @@ Variables for Languages /variable/CMAKE_COMPILER_IS_GNUCC /variable/CMAKE_COMPILER_IS_GNUCXX /variable/CMAKE_COMPILER_IS_GNUG77 - /variable/CMAKE_C_COMPILE_FEATURES - /variable/CMAKE_C_EXTENSIONS - /variable/CMAKE_C_STANDARD - /variable/CMAKE_C_STANDARD_REQUIRED /variable/CMAKE_CUDA_EXTENSIONS /variable/CMAKE_CUDA_STANDARD /variable/CMAKE_CUDA_STANDARD_REQUIRED @@ -362,6 +363,10 @@ Variables for Languages /variable/CMAKE_CXX_EXTENSIONS /variable/CMAKE_CXX_STANDARD /variable/CMAKE_CXX_STANDARD_REQUIRED + /variable/CMAKE_C_COMPILE_FEATURES + /variable/CMAKE_C_EXTENSIONS + /variable/CMAKE_C_STANDARD + /variable/CMAKE_C_STANDARD_REQUIRED /variable/CMAKE_Fortran_MODDIR_DEFAULT /variable/CMAKE_Fortran_MODDIR_FLAG /variable/CMAKE_Fortran_MODOUT_FLAG @@ -372,27 +377,27 @@ Variables for Languages /variable/CMAKE_LANG_ARCHIVE_APPEND /variable/CMAKE_LANG_ARCHIVE_CREATE /variable/CMAKE_LANG_ARCHIVE_FINISH - /variable/CMAKE_LANG_COMPILE_OBJECT + /variable/CMAKE_LANG_COMPILER /variable/CMAKE_LANG_COMPILER_ABI + /variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN /variable/CMAKE_LANG_COMPILER_ID /variable/CMAKE_LANG_COMPILER_LOADED - /variable/CMAKE_LANG_COMPILER - /variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN /variable/CMAKE_LANG_COMPILER_TARGET /variable/CMAKE_LANG_COMPILER_VERSION + /variable/CMAKE_LANG_COMPILE_OBJECT /variable/CMAKE_LANG_CREATE_SHARED_LIBRARY /variable/CMAKE_LANG_CREATE_SHARED_MODULE /variable/CMAKE_LANG_CREATE_STATIC_LIBRARY + /variable/CMAKE_LANG_FLAGS /variable/CMAKE_LANG_FLAGS_DEBUG /variable/CMAKE_LANG_FLAGS_DEBUG_INIT + /variable/CMAKE_LANG_FLAGS_INIT /variable/CMAKE_LANG_FLAGS_MINSIZEREL /variable/CMAKE_LANG_FLAGS_MINSIZEREL_INIT /variable/CMAKE_LANG_FLAGS_RELEASE /variable/CMAKE_LANG_FLAGS_RELEASE_INIT /variable/CMAKE_LANG_FLAGS_RELWITHDEBINFO /variable/CMAKE_LANG_FLAGS_RELWITHDEBINFO_INIT - /variable/CMAKE_LANG_FLAGS - /variable/CMAKE_LANG_FLAGS_INIT /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE @@ -403,8 +408,8 @@ Variables for Languages /variable/CMAKE_LANG_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES /variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES /variable/CMAKE_LANG_LIBRARY_ARCHITECTURE - /variable/CMAKE_LANG_LINKER_PREFERENCE_PROPAGATES /variable/CMAKE_LANG_LINKER_PREFERENCE + /variable/CMAKE_LANG_LINKER_PREFERENCE_PROPAGATES /variable/CMAKE_LANG_LINK_EXECUTABLE /variable/CMAKE_LANG_OUTPUT_EXTENSION /variable/CMAKE_LANG_PLATFORM_ID diff --git a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst index effa3b0..3f68c31 100644 --- a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst +++ b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst @@ -5,3 +5,7 @@ Enable interprocedural optimization for a target. If set to true, enables interprocedural optimizations if they are known to be supported by the compiler. + +This property is initialized by the +:variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable if it is set when a +target is created. diff --git a/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst b/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst index 4da855b..266ccf0 100644 --- a/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst +++ b/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst @@ -23,3 +23,48 @@ is ignored for non-imported targets. This property is initialized by the value of the :variable:`CMAKE_MAP_IMPORTED_CONFIG_<CONFIG>` variable if it is set when a target is created. + +Example +^^^^^^^ + +For example creating imported C++ library ``foo``: + +.. code-block:: cmake + + add_library(foo STATIC IMPORTED) + +Use ``foo_debug`` path for ``Debug`` build type: + +.. code-block:: cmake + + set_property( + TARGET foo APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG + ) + + set_target_properties(foo PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX" + IMPORTED_LOCATION_DEBUG "${foo_debug}" + ) + +Use ``foo_release`` path for ``Release`` build type: + +.. code-block:: cmake + + set_property( + TARGET foo APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE + ) + + set_target_properties(foo PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX" + IMPORTED_LOCATION_RELEASE "${foo_release}" + ) + +Use ``Release`` version of library for ``MinSizeRel`` and ``RelWithDebInfo`` +build types: + +.. code-block:: cmake + + set_target_properties(foo PROPERTIES + MAP_IMPORTED_CONFIG_MINSIZEREL Release + MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release + ) diff --git a/Help/release/dev/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst b/Help/release/dev/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst new file mode 100644 index 0000000..fc4f733 --- /dev/null +++ b/Help/release/dev/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst @@ -0,0 +1,6 @@ +CMAKE_INTERPROCEDURAL_OPTIMIZATION +---------------------------------- + +* A :variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable was added to + initialize the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` property on all + targets. diff --git a/Help/release/dev/cmake-xcode-schemes.rst b/Help/release/dev/cmake-xcode-schemes.rst index 27c19d7..81068ae 100644 --- a/Help/release/dev/cmake-xcode-schemes.rst +++ b/Help/release/dev/cmake-xcode-schemes.rst @@ -3,4 +3,4 @@ cmake-xcode-schemes * The :generator:`Xcode` generator got the ability to create schema files. This is still an experimental feature and can be activated by setting the - :prop_gbl:`XCODE_GENERATE_SCHEME` global property to a ``TRUE`` value. + :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable to a ``TRUE`` value. diff --git a/Help/release/dev/cpack-sign-uninstaller.rst b/Help/release/dev/cpack-sign-uninstaller.rst new file mode 100644 index 0000000..ff2b402 --- /dev/null +++ b/Help/release/dev/cpack-sign-uninstaller.rst @@ -0,0 +1,5 @@ +cpack-sign_uninstaller +---------------------- + +* The :module:`CPackNSIS` module learned to sign the uninstaller + when using :variable:`CPACK_NSIS_SIGN_UNINSTALLER` variable. diff --git a/Help/release/dev/gcc_archiving_tools.rst b/Help/release/dev/gcc_archiving_tools.rst new file mode 100644 index 0000000..b3cc7d6 --- /dev/null +++ b/Help/release/dev/gcc_archiving_tools.rst @@ -0,0 +1,8 @@ +gcc_archiving_tools +------------------- + +* The :variable:`CMAKE_GCC_AR` variable with the path to GCC wrapper of ``ar`` + utility was added. + +* The :variable:`CMAKE_GCC_RANLIB` variable with the path to GCC wrapper of + ``ranlib`` utility was added. diff --git a/Help/variable/CMAKE_GCC_AR.rst b/Help/variable/CMAKE_GCC_AR.rst new file mode 100644 index 0000000..ac90b46 --- /dev/null +++ b/Help/variable/CMAKE_GCC_AR.rst @@ -0,0 +1,7 @@ +CMAKE_GCC_AR +------------ + +A wrapper around ``ar`` adding the appropriate ``--plugin`` option for the +GCC compiler. For other compilers variable is not defined. + +See also :variable:`CMAKE_AR`. diff --git a/Help/variable/CMAKE_GCC_RANLIB.rst b/Help/variable/CMAKE_GCC_RANLIB.rst new file mode 100644 index 0000000..3d42aba --- /dev/null +++ b/Help/variable/CMAKE_GCC_RANLIB.rst @@ -0,0 +1,7 @@ +CMAKE_GCC_RANLIB +---------------- + +A wrapper around ``ranlib`` adding the appropriate ``--plugin`` option for the +GCC compiler. For other compilers variable is not defined. + +See also :variable:`CMAKE_RANLIB`. diff --git a/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst new file mode 100644 index 0000000..b0cbb62 --- /dev/null +++ b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst @@ -0,0 +1,8 @@ +CMAKE_INTERPROCEDURAL_OPTIMIZATION +---------------------------------- + +Default value for :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` of targets. + +This variable is used to initialize the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` +property on all the targets. See that target property for additional +information. diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst new file mode 100644 index 0000000..1604a76 --- /dev/null +++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst @@ -0,0 +1,12 @@ +CMAKE_VS_PLATFORM_TOOLSET_CUDA +------------------------------ + +NVIDIA CUDA Toolkit version whose Visual Studio toolset to use. + +The :ref:`Visual Studio Generators` for VS 2010 and above support using +a CUDA toolset provided by a CUDA Toolkit. The toolset version number +may be specified by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of +the form ``cuda=8.0``. If none is specified CMake will choose a default +version. CMake provides the selected CUDA toolset version in this variable. +The value may be empty if no CUDA Toolkit with Visual Studio integration +is installed. diff --git a/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst index be8b5b0..c9fcc92 100644 --- a/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst +++ b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst @@ -1,5 +1,5 @@ -XCODE_GENERATE_SCHEME ---------------------- +CMAKE_XCODE_GENERATE_SCHEME +--------------------------- If enabled, the Xcode generator will generate schema files. Those are are useful to invoke analyze, archive, build-for-testing and test diff --git a/Help/variable/MSVC_VERSION.rst b/Help/variable/MSVC_VERSION.rst index e2aff3c9..8932147 100644 --- a/Help/variable/MSVC_VERSION.rst +++ b/Help/variable/MSVC_VERSION.rst @@ -13,4 +13,5 @@ Known version numbers are:: 1600 = VS 10.0 1700 = VS 11.0 1800 = VS 12.0 - 1900 = VS 14.0, 15.0 + 1900 = VS 14.0 + 1910 = VS 15.0 diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 5d6f402..121a8f0 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -432,6 +432,16 @@ function(get_item_rpaths item rpaths_var) endif() endif() + if(UNIX AND NOT APPLE) + file(READ_ELF ${item} RPATH rpath_var RUNPATH runpath_var CAPTURE_ERROR error_var) + get_filename_component(item_dir ${item} DIRECTORY) + foreach(rpath ${rpath_var} ${runpath_var}) + # Substitute $ORIGIN with the exepath and add to the found rpaths + string(REPLACE "$ORIGIN" "${item_dir}" rpath "${rpath}") + gp_append_unique(${rpaths_var} "${rpath}") + endforeach() + endif() + set(${rpaths_var} ${${rpaths_var}} PARENT_SCOPE) endfunction() @@ -998,7 +1008,8 @@ function(verify_bundle_prerequisites bundle result_var info_var) endif() if(NOT ignoreFile) - get_prerequisites("${f}" prereqs 1 1 "${exepath}" "") + get_item_rpaths(${f} _main_exe_rpaths) + get_prerequisites("${f}" prereqs 1 1 "${exepath}" "${_main_exe_rpaths}") # On the Mac, # "embedded" and "system" prerequisites are fine... anything else means diff --git a/Modules/CMakeASMCompiler.cmake.in b/Modules/CMakeASMCompiler.cmake.in index 8e58307..ad65698 100644 --- a/Modules/CMakeASMCompiler.cmake.in +++ b/Modules/CMakeASMCompiler.cmake.in @@ -1,7 +1,9 @@ set(CMAKE_ASM@ASM_DIALECT@_COMPILER "@_CMAKE_ASM_COMPILER@") set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ARG1 "@_CMAKE_ASM_COMPILER_ARG1@") set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_GCC_AR "@CMAKE_GCC_AR@") set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_GCC_RANLIB "@CMAKE_GCC_RANLIB@") set(CMAKE_LINKER "@CMAKE_LINKER@") set(CMAKE_ASM@ASM_DIALECT@_COMPILER_LOADED 1) set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ID "@_CMAKE_ASM_COMPILER_ID@") diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 50b12f2..ab068a2 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -14,7 +14,9 @@ set(CMAKE_C_SIMULATE_ID "@CMAKE_C_SIMULATE_ID@") set(CMAKE_C_SIMULATE_VERSION "@CMAKE_C_SIMULATE_VERSION@") @SET_MSVC_C_ARCHITECTURE_ID@ set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_GCC_AR "@CMAKE_GCC_AR@") set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_GCC_RANLIB "@CMAKE_GCC_RANLIB@") set(CMAKE_LINKER "@CMAKE_LINKER@") set(CMAKE_COMPILER_IS_GNUCC @CMAKE_COMPILER_IS_GNUCC@) set(CMAKE_C_COMPILER_LOADED 1) diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 6d56488..27c8881 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -15,7 +15,9 @@ set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@") set(CMAKE_CXX_SIMULATE_VERSION "@CMAKE_CXX_SIMULATE_VERSION@") @SET_MSVC_CXX_ARCHITECTURE_ID@ set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_GCC_AR "@CMAKE_GCC_AR@") set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_GCC_RANLIB "@CMAKE_GCC_RANLIB@") set(CMAKE_LINKER "@CMAKE_LINKER@") set(CMAKE_COMPILER_IS_GNUCXX @CMAKE_COMPILER_IS_GNUCXX@) set(CMAKE_CXX_COMPILER_LOADED 1) diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index 4a315e0..5d9850d 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -166,6 +166,10 @@ if (CMAKE_CROSSCOMPILING AND NOT _CMAKE_TOOLCHAIN_PREFIX) endif () include(CMakeFindBinUtils) +set(_CMAKE_PROCESSING_LANGUAGE "C") +include(Compiler/${CMAKE_C_COMPILER_ID}-FindBinUtils OPTIONAL) +unset(_CMAKE_PROCESSING_LANGUAGE) + if(MSVC_C_ARCHITECTURE_ID) set(SET_MSVC_C_ARCHITECTURE_ID "set(MSVC_C_ARCHITECTURE_ID ${MSVC_C_ARCHITECTURE_ID})") diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 375e230..55a6f0c 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -5,36 +5,40 @@ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) include(${CMAKE_ROOT}/Modules//CMakeParseImplicitLinkInfo.cmake) if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR - ("${CMAKE_GENERATOR}" MATCHES "Ninja") ) ) + ("${CMAKE_GENERATOR}" MATCHES "Ninja") OR + ("${CMAKE_GENERATOR}" MATCHES "Visual Studio (1|[7-9][0-9])") ) ) message(FATAL_ERROR "CUDA language not currently supported by \"${CMAKE_GENERATOR}\" generator") endif() -if(NOT CMAKE_CUDA_COMPILER) - set(CMAKE_CUDA_COMPILER_INIT NOTFOUND) - - # prefer the environment variable CUDACXX - if(NOT $ENV{CUDACXX} STREQUAL "") - get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT) - if(CMAKE_CUDA_FLAGS_ENV_INIT) - set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler") - endif() - if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT}) - message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}") +if(${CMAKE_GENERATOR} MATCHES "Visual Studio") +else() + if(NOT CMAKE_CUDA_COMPILER) + set(CMAKE_CUDA_COMPILER_INIT NOTFOUND) + + # prefer the environment variable CUDACXX + if(NOT $ENV{CUDACXX} STREQUAL "") + get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT) + if(CMAKE_CUDA_FLAGS_ENV_INIT) + set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler") + endif() + if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT}) + message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}") + endif() endif() + + # finally list compilers to try + if(NOT CMAKE_CUDA_COMPILER_INIT) + set(CMAKE_CUDA_COMPILER_LIST nvcc) endif() - # finally list compilers to try - if(NOT CMAKE_CUDA_COMPILER_INIT) - set(CMAKE_CUDA_COMPILER_LIST nvcc) + _cmake_find_compiler(CUDA) + else() + _cmake_find_compiler_path(CUDA) endif() - _cmake_find_compiler(CUDA) -else() - _cmake_find_compiler_path(CUDA) + mark_as_advanced(CMAKE_CUDA_COMPILER) endif() -mark_as_advanced(CMAKE_CUDA_COMPILER) - #Allow the user to specify a host compiler set(CMAKE_CUDA_HOST_COMPILER "" CACHE FILEPATH "Host compiler to be used by nvcc") if(NOT $ENV{CUDAHOSTCXX} STREQUAL "") @@ -75,7 +79,12 @@ if(MSVC_CUDA_ARCHITECTURE_ID) "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})") endif() -if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) +if(${CMAKE_GENERATOR} MATCHES "Visual Studio") + set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}") + set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "") + set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "") + set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") +elseif(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) set(_nvcc_log "") string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n") diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index f2e0bb2..4d85150 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -161,6 +161,10 @@ if (CMAKE_CROSSCOMPILING AND NOT _CMAKE_TOOLCHAIN_PREFIX) endif () include(CMakeFindBinUtils) +set(_CMAKE_PROCESSING_LANGUAGE "CXX") +include(Compiler/${CMAKE_CXX_COMPILER_ID}-FindBinUtils OPTIONAL) +unset(_CMAKE_PROCESSING_LANGUAGE) + if(MSVC_CXX_ARCHITECTURE_ID) set(SET_MSVC_CXX_ARCHITECTURE_ID "set(MSVC_CXX_ARCHITECTURE_ID ${MSVC_CXX_ARCHITECTURE_ID})") diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index ae485bf..6fce8e2 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -235,6 +235,26 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} endif() set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR}) set(id_src "${src}") + set(id_compile "ClCompile") + set(id_PostBuildEvent_Command "for %%i in (${id_cl}) do %40echo CMAKE_${lang}_COMPILER=%%~$PATH:i") + set(id_Import_props "") + set(id_Import_targets "") + set(id_ItemDefinitionGroup_entry "") + set(id_Link_AdditionalDependencies "") + if(lang STREQUAL CUDA) + if(NOT CMAKE_VS_PLATFORM_TOOLSET_CUDA) + message(FATAL_ERROR "No CUDA toolset found.") + endif() + set(cuda_tools "CUDA ${CMAKE_VS_PLATFORM_TOOLSET_CUDA}") + set(id_compile "CudaCompile") + set(id_PostBuildEvent_Command [[echo CMAKE_CUDA_COMPILER=$(CudaToolkitBinDir)\nvcc.exe]]) + string(CONCAT id_Import_props [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.props" />]]) + string(CONCAT id_Import_targets [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.targets" />]]) + if(CMAKE_VS_PLATFORM_NAME STREQUAL x64) + set(id_ItemDefinitionGroup_entry "<CudaCompile><TargetMachinePlatform>64</TargetMachinePlatform></CudaCompile>") + endif() + set(id_Link_AdditionalDependencies "<AdditionalDependencies>cudart.lib</AdditionalDependencies>") + endif() configure_file(${CMAKE_ROOT}/Modules/CompilerId/VS-${v}.${ext}.in ${id_dir}/CompilerId${lang}.${ext} @ONLY) if(CMAKE_VS_MSBUILD_COMMAND AND NOT lang STREQUAL "Fortran") diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index 484fa66..9e9770a 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -255,6 +255,9 @@ if (CMAKE_CROSSCOMPILING AND NOT _CMAKE_TOOLCHAIN_PREFIX) endif () include(CMakeFindBinUtils) +set(_CMAKE_PROCESSING_LANGUAGE "Fortran") +include(Compiler/${CMAKE_Fortran_COMPILER_ID}-FindBinUtils OPTIONAL) +unset(_CMAKE_PROCESSING_LANGUAGE) if(MSVC_Fortran_ARCHITECTURE_ID) set(SET_MSVC_Fortran_ARCHITECTURE_ID diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index 69800d7..c49621b 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -8,7 +8,9 @@ set(CMAKE_Fortran_SIMULATE_ID "@CMAKE_Fortran_SIMULATE_ID@") set(CMAKE_Fortran_SIMULATE_VERSION "@CMAKE_Fortran_SIMULATE_VERSION@") @SET_MSVC_Fortran_ARCHITECTURE_ID@ set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_GCC_AR "@CMAKE_GCC_AR@") set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_GCC_RANLIB "@CMAKE_GCC_RANLIB@") set(CMAKE_COMPILER_IS_GNUG77 @CMAKE_COMPILER_IS_GNUG77@) set(CMAKE_Fortran_COMPILER_LOADED 1) set(CMAKE_Fortran_COMPILER_WORKS @CMAKE_Fortran_COMPILER_WORKS@) diff --git a/Modules/CPackNSIS.cmake b/Modules/CPackNSIS.cmake index 18d1871..37fedf3 100644 --- a/Modules/CPackNSIS.cmake +++ b/Modules/CPackNSIS.cmake @@ -133,6 +133,10 @@ # "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake.html" # "CMake Help" "https://cmake.org" "CMake Web Site") # +# .. variable:: CPACK_NSIS_SIGN_UNINSTALLER +# +# Specify a command to use for signing the uninstaller. The command will +# be invoked a path to the uninstaller as its only argument. #FIXME we should put NSIS specific code here #FIXME but I'm not doing it because I'm not able to test it... diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake index 6b4a9e4..1ea91d2 100644 --- a/Modules/CheckLanguage.cmake +++ b/Modules/CheckLanguage.cmake @@ -46,6 +46,8 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" execute_process( WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang} COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR} + -A "${CMAKE_GENERATOR_PLATFORM}" + -T "${CMAKE_GENERATOR_TOOLSET}" OUTPUT_VARIABLE output ERROR_VARIABLE output RESULT_VARIABLE result diff --git a/Modules/Compiler/GNU-FindBinUtils.cmake b/Modules/Compiler/GNU-FindBinUtils.cmake new file mode 100644 index 0000000..466d4cf --- /dev/null +++ b/Modules/Compiler/GNU-FindBinUtils.cmake @@ -0,0 +1,25 @@ +if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "") + message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set") +endif() + +string(REGEX MATCH "^([0-9]+\\.[0-9]+)" __version_x_y + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}") + +# Try to find tools in the same directory as GCC itself +get_filename_component(__gcc_hints "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY) + +# http://manpages.ubuntu.com/manpages/wily/en/man1/gcc-ar.1.html +find_program(CMAKE_GCC_AR NAMES + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x_y}" + HINTS ${__gcc_hints} + DOC "A wrapper around 'ar' adding the appropriate '--plugin' option for the GCC compiler" +) + +# http://manpages.ubuntu.com/manpages/wily/en/man1/gcc-ranlib.1.html +find_program(CMAKE_GCC_RANLIB NAMES + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x_y}" + HINTS ${__gcc_hints} + DOC "A wrapper around 'ranlib' adding the appropriate '--plugin' option for the GCC compiler" +) diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in index 50be9cb..6b9b361 100644 --- a/Modules/CompilerId/VS-10.vcxproj.in +++ b/Modules/CompilerId/VS-10.vcxproj.in @@ -25,6 +25,9 @@ <CharacterSet>MultiByte</CharacterSet> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + @id_Import_props@ + </ImportGroup> <PropertyGroup> <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">.\</OutDir> @@ -44,16 +47,21 @@ <DebugInformationFormat> </DebugInformationFormat> </ClCompile> + @id_ItemDefinitionGroup_entry@ <Link> <GenerateDebugInformation>false</GenerateDebugInformation> <SubSystem>Console</SubSystem> + @id_Link_AdditionalDependencies@ </Link> <PostBuildEvent> - <Command>for %%i in (@id_cl@) do %40echo CMAKE_@id_lang@_COMPILER=%%~$PATH:i</Command> + <Command>@id_PostBuildEvent_Command@</Command> </PostBuildEvent> </ItemDefinitionGroup> <ItemGroup> - <ClCompile Include="@id_src@" /> + <@id_compile@ Include="@id_src@" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + @id_Import_targets@ + </ImportGroup> </Project> diff --git a/Modules/FindGit.cmake b/Modules/FindGit.cmake index b830c08..fae31eb 100644 --- a/Modules/FindGit.cmake +++ b/Modules/FindGit.cmake @@ -43,12 +43,26 @@ if(CMAKE_HOST_WIN32) endif() endif() +# First search the PATH and specific locations. find_program(GIT_EXECUTABLE NAMES ${git_names} PATHS ${github_path} ${_git_sourcetree_path} - PATH_SUFFIXES Git/cmd Git/bin DOC "Git command line client" ) + +if(CMAKE_HOST_WIN32) + # Now look for installations in Git/ directories under typical installation + # prefixes on Windows. Exclude PATH from this search because VS 2017's + # command prompt happens to have a PATH entry with a Git/ subdirectory + # containing a minimal git not meant for general use. + find_program(GIT_EXECUTABLE + NAMES ${git_names} + PATH_SUFFIXES Git/cmd Git/bin + NO_SYSTEM_ENVIRONMENT_PATH + DOC "Git command line client" + ) +endif() + mark_as_advanced(GIT_EXECUTABLE) unset(git_names) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 927ec64..4884174 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -69,6 +69,9 @@ # HDF5_C_DEFINITIONS -- Required compiler definitions for HDF5 C bindings # HDF5_CXX_DEFINITIONS -- Required compiler definitions for HDF5 C++ bindings # HDF5_Fortran_DEFINITIONS -- Required compiler definitions for HDF5 Fortran bindings +# HDF5_C_INCLUDE_DIRS -- Required include directories for HDF5 C bindings +# HDF5_CXX_INCLUDE_DIRS -- Required include directories for HDF5 C++ bindings +# HDF5_Fortran_INCLUDE_DIRS -- Required include directories for HDF5 Fortran bindings # HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings # HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings # HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings @@ -358,7 +361,7 @@ macro( _HDF5_parse_compile_line list(APPEND ${include_paths} "${CMAKE_MATCH_1}") elseif("${arg}" MATCHES "^-D(.*)$") # compile definition - list(APPEND ${definitions} "${CMAKE_MATCH_1}") + list(APPEND ${definitions} "-D${CMAKE_MATCH_1}") elseif("${arg}" MATCHES "^-L(.*)$") # library search path list(APPEND ${library_paths} "${CMAKE_MATCH_1}") @@ -696,6 +699,8 @@ if( NOT HDF5_FOUND ) ${_HDF5_SEARCH_OPTS} ) mark_as_advanced(HDF5_${__lang}_INCLUDE_DIR) + # set the _DIRS variable as this is what the user will normally use + set(HDF5_${__lang}_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR}) list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR}) # find the HDF5 libraries diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake index 39e504f..cebba10 100644 --- a/Modules/FindJNI.cmake +++ b/Modules/FindJNI.cmake @@ -145,6 +145,9 @@ JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_LIBRARY_DIRECTORIES /usr/lib/jvm/default-java/jre/lib/{libarch} /usr/lib/jvm/default-java/jre/lib /usr/lib/jvm/default-java/lib + # Arch Linux specific paths for default JVM + /usr/lib/jvm/default/jre/lib/{libarch} + /usr/lib/jvm/default/lib/{libarch} # Ubuntu specific paths for default JVM /usr/lib/jvm/java-8-openjdk-{libarch}/jre/lib/{libarch} # Ubuntu 15.10 /usr/lib/jvm/java-7-openjdk-{libarch}/jre/lib/{libarch} # Ubuntu 15.10 @@ -200,6 +203,8 @@ JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_INCLUDE_DIRECTORIES /opt/sun-jdk-1.5.0.04/include # Debian specific path for default JVM /usr/lib/jvm/default-java/include + # Arch specific path for default JVM + /usr/lib/jvm/default/include # OpenBSD specific path for default JVM /usr/local/jdk-1.7.0/include /usr/local/jdk-1.6.0/include diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake index 820e0eb..1f4c8ad 100644 --- a/Modules/FindVulkan.cmake +++ b/Modules/FindVulkan.cmake @@ -39,12 +39,17 @@ if(WIN32) find_library(Vulkan_LIBRARY NAMES vulkan-1 PATHS - "$ENV{VULKAN_SDK}/Bin") + "$ENV{VULKAN_SDK}/Lib" + "$ENV{VULKAN_SDK}/Bin" + ) elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) find_library(Vulkan_LIBRARY NAMES vulkan-1 PATHS - "$ENV{VULKAN_SDK}/Bin32") + "$ENV{VULKAN_SDK}/Lib32" + "$ENV{VULKAN_SDK}/Bin32" + NO_SYSTEM_ENVIRONMENT_PATH + ) endif() else() find_path(Vulkan_INCLUDE_DIR diff --git a/Modules/NSIS.template.in b/Modules/NSIS.template.in index 9001888..ffa6277 100644 --- a/Modules/NSIS.template.in +++ b/Modules/NSIS.template.in @@ -29,6 +29,33 @@ ;-------------------------------- ;General +!ifdef INNER + OutFile "$%TEMP%\tempinstaller.exe" + SetCompress off ; for speed +!else + ; Call makensis again, defining INNER. This writes an installer for us which, when + ; it is invoked, will just write the uninstaller to some location, and then exit. + ; Be sure to substitute the name of this script here. + + !system "$\"${NSISDIR}\makensis$\" /DINNER $\"@CPACK_TEMPORARY_DIRECTORY@/../project.nsi$\"" = 0 + + ; So now run that installer we just created as %TEMP%\tempinstaller.exe. Since it + ; calls quit the return value isn't zero. + + !system "$%TEMP%\tempinstaller.exe" = 2 + + ; That will have written an uninstaller binary for us. Now we sign it with your + ; favourite code signing tool. + + !tempfile INCEXIST + !system 'if exist "@CPACK_NSIS_SIGN_UNINSTALLER@" echo !define HAVE_SIGN_UNINST > "${INCEXIST}"' + !include "${INCEXIST}" + !delfile "${INCEXIST}" + !ifdef HAVE_SIGN_UNINST + !system '"@CPACK_NSIS_SIGN_UNINSTALLER@" "$%TEMP%\Uninstall.exe"' = 0 + !endif + + ; Good. Now we can carry on writing the real installer. ;Name and file Name "@CPACK_NSIS_PACKAGE_NAME@" @@ -36,6 +63,7 @@ ;Set compression SetCompressor @CPACK_NSIS_COMPRESSOR@ +!endif ;Require administrator access RequestExecutionLevel admin @@ -559,8 +587,10 @@ FunctionEnd !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH +!ifdef INNER !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES +!endif ;-------------------------------- ;Languages @@ -642,7 +672,10 @@ Section "-Core installation" WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR ;Create uninstaller - WriteUninstaller "$INSTDIR\Uninstall.exe" +!ifndef INNER + ; this packages the signed uninstaller + File "$%TEMP%\Uninstall.exe" +!endif Push "DisplayName" Push "@CPACK_NSIS_DISPLAY_NAME@" Call ConditionalAddToRegisty @@ -801,6 +834,7 @@ FunctionEnd ;-------------------------------- ;Uninstaller Section +!ifdef INNER Section "Uninstall" ReadRegStr $START_MENU SHCTX \ "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" @@ -886,6 +920,7 @@ Section "Uninstall" Call un.RemoveFromPath doNotRemoveFromPath: SectionEnd +!endif ;-------------------------------- ; determine admin versus local install @@ -898,6 +933,14 @@ SectionEnd ; "Program Files" for AllUsers, "My Documents" for JustMe... Function .onInit +!ifdef INNER + ; If INNER is defined, then we aren't supposed to do anything except write out + ; the installer. This is better than processing a command line option as it means + ; this entire code path is not present in the final (real) installer. + + WriteUninstaller "$%TEMP%\Uninstall.exe" + Quit ; just bail out quickly when running the "inner" installer +!endif StrCmp "@CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL@" "ON" 0 inst ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString" diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake index 0b16aa4..362099e 100644 --- a/Modules/WriteCompilerDetectionHeader.cmake +++ b/Modules/WriteCompilerDetectionHeader.cmake @@ -503,10 +503,19 @@ function(write_compiler_detection_header if (feature STREQUAL cxx_static_assert) set(def_value "${prefix_arg}_STATIC_ASSERT(X)") set(def_value_msg "${prefix_arg}_STATIC_ASSERT_MSG(X, MSG)") - set(static_assert_struct "template<bool> struct ${prefix_arg}StaticAssert;\ntemplate<> struct ${prefix_arg}StaticAssert<true>{};\n") - set(def_standard "# define ${def_value} static_assert(X, #X)\n# define ${def_value_msg} static_assert(X, MSG)") - set(def_alternative "${static_assert_struct}# define ${def_value} sizeof(${prefix_arg}StaticAssert<X>)\n# define ${def_value_msg} sizeof(${prefix_arg}StaticAssert<X>)") - string(APPEND file_content "# if defined(${def_name}) && ${def_name}\n${def_standard}\n# else\n${def_alternative}\n# endif\n\n") + set(def_fallback "enum { ${prefix_arg}_STATIC_ASSERT_JOIN(${prefix_arg}StaticAssertEnum, __LINE__) = sizeof(${prefix_arg}StaticAssert<X>) }") + string(APPEND file_content "# if defined(${def_name}) && ${def_name} +# define ${def_value} static_assert(X, #X) +# define ${def_value_msg} static_assert(X, MSG) +# else +# define ${prefix_arg}_STATIC_ASSERT_JOIN(X, Y) ${prefix_arg}_STATIC_ASSERT_JOIN_IMPL(X, Y) +# define ${prefix_arg}_STATIC_ASSERT_JOIN_IMPL(X, Y) X##Y +template<bool> struct ${prefix_arg}StaticAssert; +template<> struct ${prefix_arg}StaticAssert<true>{}; +# define ${def_value} ${def_fallback} +# define ${def_value_msg} ${def_fallback} +# endif +\n") endif() if (feature STREQUAL cxx_alignas) set(def_value "${prefix_arg}_ALIGNAS(X)") diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 76b98fc..59920f8 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -344,6 +344,8 @@ set(SRCS cmPropertyDefinitionMap.h cmPropertyMap.cxx cmPropertyMap.h + cmQtAutoGeneratorCommon.cxx + cmQtAutoGeneratorCommon.h cmQtAutoGeneratorInitializer.cxx cmQtAutoGeneratorInitializer.h cmQtAutoGenerators.cxx @@ -381,6 +383,8 @@ set(SRCS cmVariableWatch.h cmVersion.cxx cmVersion.h + cmWorkingDirectory.cxx + cmWorkingDirectory.h cmXMLParser.cxx cmXMLParser.h cmXMLSafe.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 62324e8..ffc0041 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 8) -set(CMake_VERSION_PATCH 20170302) +set(CMake_VERSION_PATCH 20170313) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx index b159e64..aeabde9 100644 --- a/Source/CPack/OSXScriptLauncher.cxx +++ b/Source/CPack/OSXScriptLauncher.cxx @@ -20,7 +20,6 @@ int main(int argc, char* argv[]) { // if ( cmsys::SystemTools::FileExists( - std::string cwd = cmsys::SystemTools::GetCurrentWorkingDirectory(); cmsys::ofstream ofs("/tmp/output.txt"); CFStringRef fileName; diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index 9d9cd66..cc01b0c 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -7,6 +7,7 @@ #include "cmCPackLog.h" #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include <map> #include <ostream> @@ -37,9 +38,8 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( // Add the files of this component to the archive std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); localToplevel += "/" + component->Name; - std::string dir = cmSystemTools::GetCurrentWorkingDirectory(); // Change to local toplevel - cmSystemTools::ChangeDirectory(localToplevel); + cmWorkingDirectory workdir(localToplevel); std::string filePrefix; if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME"); @@ -64,8 +64,6 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( return 0; } } - // Go back to previous dir - cmSystemTools::ChangeDirectory(dir); return 1; } @@ -227,8 +225,7 @@ int cmCPackArchiveGenerator::PackageFiles() // CASE 3 : NON COMPONENT package. DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive); std::vector<std::string>::const_iterator fileIt; - std::string dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(toplevel); + cmWorkingDirectory workdir(toplevel); for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) { // Get the relative path to the file std::string rp = @@ -241,7 +238,6 @@ int cmCPackArchiveGenerator::PackageFiles() return 0; } } - cmSystemTools::ChangeDirectory(dir); // The destructor of cmArchiveWrite will close and finish the write return 1; } diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index e1a4a2a..f6ea8cf 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -16,6 +16,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmStateSnapshot.h" +#include "cmWorkingDirectory.h" #include "cmXMLSafe.h" #include "cm_auto_ptr.hxx" #include "cmake.h" @@ -383,7 +384,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( goToDir += "/" + subdir; cmCPackLogger(cmCPackLog::LOG_DEBUG, "Change dir to: " << goToDir << std::endl); - cmSystemTools::ChangeDirectory(goToDir); + cmWorkingDirectory workdir(goToDir); for (symlinkedIt = symlinkedFiles.begin(); symlinkedIt != symlinkedFiles.end(); ++symlinkedIt) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Will create a symlink: " @@ -408,7 +409,6 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( } cmCPackLogger(cmCPackLog::LOG_DEBUG, "Going back to: " << curDir << std::endl); - cmSystemTools::ChangeDirectory(curDir); } } } diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 6780a0e..6f81429 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -6,6 +6,7 @@ #include "cmCTestTestHandler.h" #include "cmGlobalGenerator.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include "cmake.h" #include <cmsys/Process.h> @@ -42,7 +43,7 @@ int cmCTestBuildAndTestHandler::ProcessHandler() int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, std::ostringstream& out, std::string& cmakeOutString, - std::string& cwd, cmake* cm) + cmake* cm) { unsigned int k; std::vector<std::string> args; @@ -85,8 +86,6 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, if (cm->Run(args) != 0) { out << "Error: cmake execution failed\n"; out << cmakeOutString << "\n"; - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); if (outstring) { *outstring = out.str(); } else { @@ -99,8 +98,6 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, if (cm->Run(args) != 0) { out << "Error: cmake execution failed\n"; out << cmakeOutString << "\n"; - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); if (outstring) { *outstring = out.str(); } else { @@ -199,13 +196,12 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) double clock_start = cmSystemTools::GetTime(); // make sure the binary dir is there - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); out << "Internal cmake changing into directory: " << this->BinaryDir << std::endl; if (!cmSystemTools::FileIsDirectory(this->BinaryDir)) { cmSystemTools::MakeDirectory(this->BinaryDir.c_str()); } - cmSystemTools::ChangeDirectory(this->BinaryDir); + cmWorkingDirectory workdir(this->BinaryDir); if (this->BuildNoCMake) { // Make the generator available for the Build call below. @@ -217,7 +213,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) cm.LoadCache(this->BinaryDir); } else { // do the cmake step, no timeout here since it is not a sub process - if (this->RunCMake(outstring, out, cmakeOutString, cwd, &cm)) { + if (this->RunCMake(outstring, out, cmakeOutString, &cm)) { return 1; } } @@ -304,8 +300,6 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) } else { cmCTestLog(this->CTest, ERROR_MESSAGE, out.str()); } - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); return 1; } diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h index 5885738..af082a3 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.h +++ b/Source/CTest/cmCTestBuildAndTestHandler.h @@ -46,7 +46,7 @@ protected: ///! Run CMake and build a test and then run it as a single test. int RunCMakeAndTest(std::string* output); int RunCMake(std::string* outstring, std::ostringstream& out, - std::string& cmakeOutString, std::string& cwd, cmake* cm); + std::string& cmakeOutString, cmake* cm); std::string Output; diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 989c096..120c5d9 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -12,6 +12,7 @@ #include "cmParseJacocoCoverage.h" #include "cmParsePHPCoverage.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -969,9 +970,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( std::string testingDir = this->CTest->GetBinaryDir() + "/Testing"; std::string tempDir = testingDir + "/CoverageInfo"; - std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory(); cmSystemTools::MakeDirectory(tempDir.c_str()); - cmSystemTools::ChangeDirectory(tempDir); + cmWorkingDirectory workdir(tempDir); int gcovStyle = 0; @@ -1294,7 +1294,6 @@ int cmCTestCoverageHandler::HandleGCovCoverage( } } - cmSystemTools::ChangeDirectory(currentDirectory); return file_count; } @@ -1340,7 +1339,6 @@ int cmCTestCoverageHandler::HandleLCovCoverage( return 0; } std::string testingDir = this->CTest->GetBinaryDir(); - std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory(); std::set<std::string> missingFiles; @@ -1362,7 +1360,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage( cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "." << std::flush, this->Quiet); std::string fileDir = cmSystemTools::GetFilenamePath(*it); - cmSystemTools::ChangeDirectory(fileDir); + cmWorkingDirectory workdir(fileDir); std::string command = "\"" + lcovCommand + "\" " + lcovExtraFlags + " "; cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, @@ -1552,7 +1550,6 @@ int cmCTestCoverageHandler::HandleLCovCoverage( } } - cmSystemTools::ChangeDirectory(currentDirectory); return file_count; } @@ -1591,13 +1588,8 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files) gl.RecurseOff(); // No need of recurse if -prof_dir${BUILD_DIR} flag is // used while compiling. gl.RecurseThroughSymlinksOff(); - std::string prevBinaryDir; std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory"); - if (cmSystemTools::ChangeDirectory(buildDir)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Error changing directory to " - << buildDir << std::endl); - return false; - } + cmWorkingDirectory workdir(buildDir); // Run profmerge to merge all *.dyn files into dpi files if (!cmSystemTools::RunSingleCommand("profmerge")) { @@ -1605,11 +1597,9 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files) return false; } - prevBinaryDir = cmSystemTools::GetCurrentWorkingDirectory(); - // DPI file should appear in build directory std::string daGlob; - daGlob = prevBinaryDir; + daGlob = buildDir; daGlob += "/*.dpi"; cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " looking for dpi files in: " << daGlob << std::endl, @@ -1646,11 +1636,7 @@ int cmCTestCoverageHandler::HandleTracePyCoverage( std::string testingDir = this->CTest->GetBinaryDir() + "/Testing"; std::string tempDir = testingDir + "/CoverageInfo"; - std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory(); cmSystemTools::MakeDirectory(tempDir.c_str()); - cmSystemTools::ChangeDirectory(tempDir); - - cmSystemTools::ChangeDirectory(currentDirectory); std::vector<std::string>::iterator fileIt; int file_count = 0; @@ -1737,7 +1723,6 @@ int cmCTestCoverageHandler::HandleTracePyCoverage( } ++file_count; } - cmSystemTools::ChangeDirectory(currentDirectory); return file_count; } diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 2a67d47..c99e450 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -6,6 +6,7 @@ #include "cmCTestGenericHandler.h" #include "cmMakefile.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include "cmake.h" #include <sstream> @@ -216,8 +217,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX])); } } - std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory( + cmWorkingDirectory workdir( this->CTest->GetCTestConfiguration("BuildDirectory")); int res = handler->ProcessHandler(); if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) { @@ -243,7 +243,6 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], returnString); } - cmSystemTools::ChangeDirectory(current_dir); return true; } diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index c1724ab..ff465ab 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -7,6 +7,7 @@ #include "cmCTestScriptHandler.h" #include "cmCTestTestHandler.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include <algorithm> #include <cmsys/FStream.hxx> @@ -138,8 +139,7 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test) } } - std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(this->Properties[test]->Directory); + cmWorkingDirectory workdir(this->Properties[test]->Directory); // Lock the resources we'll be using this->LockResources(test); @@ -166,7 +166,6 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test) this->Failed->push_back(this->Properties[test]->Name); delete testRun; } - cmSystemTools::ChangeDirectory(current_dir); } void cmCTestMultiProcessHandler::LockResources(int index) @@ -683,9 +682,7 @@ void cmCTestMultiProcessHandler::PrintTestList() count++; cmCTestTestHandler::cmCTestTestProperties& p = *it->second; - // push working dir - std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(p.Directory); + cmWorkingDirectory workdir(p.Directory); cmCTestRunTest testRun(this->TestHandler); testRun.SetIndex(p.Index); @@ -724,8 +721,6 @@ void cmCTestMultiProcessHandler::PrintTestList() cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, p.Name << std::endl, this->Quiet); - // pop working dir - cmSystemTools::ChangeDirectory(current_dir); } cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index ac1644f..f148f30 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -7,6 +7,7 @@ #include "cmCTestTestHandler.h" #include "cmProcess.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include <cmConfigure.h> #include <cm_curl.h> @@ -270,14 +271,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) *this->TestHandler->LogFile << "Test time = " << buf << std::endl; } - // Set the working directory to the tests directory - std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(this->TestProperties->Directory); - - this->DartProcessing(); - - // restore working directory - cmSystemTools::ChangeDirectory(oldpath); + // Set the working directory to the tests directory to process Dart files. + { + cmWorkingDirectory workdir(this->TestProperties->Directory); + this->DartProcessing(); + } // if this is doing MemCheck then all the output needs to be put into // Output since that is what is parsed by cmCTestMemCheckHandler @@ -356,11 +354,8 @@ bool cmCTestRunTest::StartAgain() } this->RunAgain = false; // reset // change to tests directory - std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(this->TestProperties->Directory); + cmWorkingDirectory workdir(this->TestProperties->Directory); this->StartTest(this->TotalNumberOfTests); - // change back - cmSystemTools::ChangeDirectory(current_dir); return true; } diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 5e5119d..cc399b0 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -19,6 +19,7 @@ #include "cmState.h" #include "cmSystemTools.h" #include "cmThirdParty.h" +#include "cmWorkingDirectory.h" #include "cmXMLParser.h" #include "cmake.h" @@ -1519,7 +1520,6 @@ int cmCTestSubmitHandler::ProcessHandler() #endif } else if (dropMethod == "scp") { std::string url; - std::string oldWorkingDirectory; if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) { url += this->CTest->GetCTestConfiguration("DropSiteUser") + "@"; } @@ -1528,19 +1528,16 @@ int cmCTestSubmitHandler::ProcessHandler() // change to the build directory so that we can uses a relative path // on windows since scp dosn't support "c:" a drive in the path - oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(buildDirectory); + cmWorkingDirectory workdir(buildDirectory); if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"), "Testing/" + this->CTest->GetCurrentTag(), files, prefix, url)) { - cmSystemTools::ChangeDirectory(oldWorkingDirectory); cmCTestLog(this->CTest, ERROR_MESSAGE, " Problems when submitting via SCP" << std::endl); ofs << " Problems when submitting via SCP" << std::endl; return -1; } - cmSystemTools::ChangeDirectory(oldWorkingDirectory); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Submission successful" << std::endl, this->Quiet); ofs << " Submission successful" << std::endl; @@ -1550,22 +1547,18 @@ int cmCTestSubmitHandler::ProcessHandler() // change to the build directory so that we can uses a relative path // on windows since scp dosn't support "c:" a drive in the path - std::string oldWorkingDirectory = - cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(buildDirectory); + cmWorkingDirectory workdir(buildDirectory); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Change directory: " << buildDirectory << std::endl, this->Quiet); if (!this->SubmitUsingCP("Testing/" + this->CTest->GetCurrentTag(), files, prefix, location)) { - cmSystemTools::ChangeDirectory(oldWorkingDirectory); cmCTestLog(this->CTest, ERROR_MESSAGE, " Problems when submitting via CP" << std::endl); ofs << " Problems when submitting via cp" << std::endl; return -1; } - cmSystemTools::ChangeDirectory(oldWorkingDirectory); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Submission successful" << std::endl, this->Quiet); ofs << " Submission successful" << std::endl; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 6175e50..9d22065 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -27,6 +27,7 @@ #include "cmState.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include "cmXMLWriter.h" #include "cm_auto_ptr.hxx" #include "cm_utf8.h" @@ -86,22 +87,24 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args, // No subdirectory? So what... continue; } - cmSystemTools::ChangeDirectory(fname); - const char* testFilename; - if (cmSystemTools::FileExists("CTestTestfile.cmake")) { - // does the CTestTestfile.cmake exist ? - testFilename = "CTestTestfile.cmake"; - } else if (cmSystemTools::FileExists("DartTestfile.txt")) { - // does the DartTestfile.txt exist ? - testFilename = "DartTestfile.txt"; - } else { - // No CTestTestfile? Who cares... - continue; + bool readit = false; + { + cmWorkingDirectory workdir(fname); + const char* testFilename; + if (cmSystemTools::FileExists("CTestTestfile.cmake")) { + // does the CTestTestfile.cmake exist ? + testFilename = "CTestTestfile.cmake"; + } else if (cmSystemTools::FileExists("DartTestfile.txt")) { + // does the DartTestfile.txt exist ? + testFilename = "DartTestfile.txt"; + } else { + // No CTestTestfile? Who cares... + continue; + } + fname += "/"; + fname += testFilename; + readit = this->Makefile->ReadDependentFile(fname.c_str()); } - fname += "/"; - fname += testFilename; - bool readit = this->Makefile->ReadDependentFile(fname.c_str()); - cmSystemTools::ChangeDirectory(cwd); if (!readit) { std::string m = "Could not find include file: "; m += fname; @@ -109,7 +112,6 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args, return false; } } - cmSystemTools::ChangeDirectory(cwd); return true; } @@ -149,9 +151,7 @@ bool cmCTestAddSubdirectoryCommand::InitialPass( return false; } - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(cwd); - std::string fname = cwd; + std::string fname = cmSystemTools::GetCurrentWorkingDirectory(); fname += "/"; fname += args[0]; @@ -159,23 +159,23 @@ bool cmCTestAddSubdirectoryCommand::InitialPass( // No subdirectory? So what... return true; } - cmSystemTools::ChangeDirectory(fname); - const char* testFilename; - if (cmSystemTools::FileExists("CTestTestfile.cmake")) { - // does the CTestTestfile.cmake exist ? - testFilename = "CTestTestfile.cmake"; - } else if (cmSystemTools::FileExists("DartTestfile.txt")) { - // does the DartTestfile.txt exist ? - testFilename = "DartTestfile.txt"; - } else { - // No CTestTestfile? Who cares... - cmSystemTools::ChangeDirectory(cwd); - return true; + bool readit = false; + { + const char* testFilename; + if (cmSystemTools::FileExists("CTestTestfile.cmake")) { + // does the CTestTestfile.cmake exist ? + testFilename = "CTestTestfile.cmake"; + } else if (cmSystemTools::FileExists("DartTestfile.txt")) { + // does the DartTestfile.txt exist ? + testFilename = "DartTestfile.txt"; + } else { + // No CTestTestfile? Who cares... + return true; + } + fname += "/"; + fname += testFilename; + readit = this->Makefile->ReadDependentFile(fname.c_str()); } - fname += "/"; - fname += testFilename; - bool readit = this->Makefile->ReadDependentFile(fname.c_str()); - cmSystemTools::ChangeDirectory(cwd); if (!readit) { std::string m = "Could not find include file: "; m += fname; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 559275e..e6e50e9 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1122,7 +1122,6 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, if (log) { *log << "* Run internal CTest" << std::endl; } - std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory(); CM_AUTO_PTR<cmSystemTools::SaveRestoreEnvironment> saveEnv; if (modifyEnv) { @@ -1137,7 +1136,6 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, if (log && output) { *log << *output; } - cmSystemTools::ChangeDirectory(oldpath); if (output) { cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Internal cmCTest object used to run test." << std::endl diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 239582f..fd1ad36 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -26,7 +26,6 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt) , GlobalGenerator(static_cast<cmGlobalCommonGenerator*>( gt->LocalGenerator->GetGlobalGenerator())) , ConfigName(LocalGenerator->GetConfigName()) - , ModuleDefinitionFile(GeneratorTarget->GetModuleDefinitionFile(ConfigName)) { } @@ -63,14 +62,9 @@ void cmCommonTargetGenerator::AddFeatureFlags(std::string& flags, void cmCommonTargetGenerator::AddModuleDefinitionFlag( cmLinkLineComputer* linkLineComputer, std::string& flags) { - // A module definition file only makes sense on certain target types. - if (this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY && - this->GeneratorTarget->GetType() != cmStateEnums::MODULE_LIBRARY && - this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE) { - return; - } - - if (!this->ModuleDefinitionFile) { + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName()); + if (!mdi || mdi->DefFile.empty()) { return; } @@ -85,8 +79,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag( // vs6's "cl -link" pass it to the linker. std::string flag = defFileFlag; flag += this->LocalGenerator->ConvertToOutputFormat( - linkLineComputer->ConvertToLinkReference( - this->ModuleDefinitionFile->GetFullPath()), + linkLineComputer->ConvertToLinkReference(mdi->DefFile), cmOutputConverter::SHELL); this->LocalGenerator->AppendFlags(flags, flag); } diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index d67fefb..8d68123 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -44,9 +44,6 @@ protected: cmGlobalCommonGenerator* GlobalGenerator; std::string ConfigName; - // The windows module definition source file (.def), if any. - cmSourceFile const* ModuleDefinitionFile; - void AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source); diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index c189419..b8c76b9 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -7,6 +7,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include <cmsys/FStream.hxx> #include <sstream> @@ -75,13 +76,7 @@ bool cmDepends::Check(const char* makeFile, const char* internalFile, std::map<std::string, DependencyVector>& validDeps) { // Dependency checks must be done in proper working directory. - std::string oldcwd = "."; - if (this->CompileDirectory != ".") { - // Get the CWD but do not call CollapseFullPath because - // we only need it to cd back, and the form does not matter - oldcwd = cmSystemTools::GetCurrentWorkingDirectory(false); - cmSystemTools::ChangeDirectory(this->CompileDirectory); - } + cmWorkingDirectory workdir(this->CompileDirectory); // Check whether dependencies must be regenerated. bool okay = true; @@ -93,11 +88,6 @@ bool cmDepends::Check(const char* makeFile, const char* internalFile, okay = false; } - // Restore working directory. - if (oldcwd != ".") { - cmSystemTools::ChangeDirectory(oldcwd); - } - return okay; } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 91cecb3..957b4cb 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -42,6 +42,10 @@ #include "cmFileLockResult.h" #endif +#if defined(CMAKE_USE_ELF_PARSER) +#include "cmELF.h" +#endif + class cmSystemToolsFileTime; // Table of permissions flags. @@ -166,6 +170,9 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args, if (subCommand == "RPATH_REMOVE") { return this->HandleRPathRemoveCommand(args); } + if (subCommand == "READ_ELF") { + return this->HandleReadElfCommand(args); + } if (subCommand == "RELATIVE_PATH") { return this->HandleRelativePathCommand(args); } @@ -2177,6 +2184,68 @@ bool cmFileCommand::HandleRPathCheckCommand( return true; } +bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args) +{ + if (args.size() < 4) { + this->SetError("READ_ELF must be called with at least three additional " + "arguments."); + return false; + } + + cmCommandArgumentsHelper argHelper; + cmCommandArgumentGroup group; + + cmCAString readArg(&argHelper, "READ_ELF"); + cmCAString fileNameArg(&argHelper, CM_NULLPTR); + + cmCAString rpathArg(&argHelper, "RPATH", &group); + cmCAString runpathArg(&argHelper, "RUNPATH", &group); + cmCAString errorArg(&argHelper, "CAPTURE_ERROR", &group); + + readArg.Follows(CM_NULLPTR); + fileNameArg.Follows(&readArg); + group.Follows(&fileNameArg); + argHelper.Parse(&args, CM_NULLPTR); + + if (!cmSystemTools::FileExists(fileNameArg.GetString(), true)) { + std::ostringstream e; + e << "READ_ELF given FILE \"" << fileNameArg.GetString() + << "\" that does not exist."; + this->SetError(e.str()); + return false; + } + +#if defined(CMAKE_USE_ELF_PARSER) + cmELF elf(fileNameArg.GetCString()); + + if (!rpathArg.GetString().empty()) { + if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) { + std::string rpath(se_rpath->Value); + std::replace(rpath.begin(), rpath.end(), ':', ';'); + this->Makefile->AddDefinition(rpathArg.GetString(), rpath.c_str()); + } + } + if (!runpathArg.GetString().empty()) { + if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) { + std::string runpath(se_runpath->Value); + std::replace(runpath.begin(), runpath.end(), ':', ';'); + this->Makefile->AddDefinition(runpathArg.GetString(), runpath.c_str()); + } + } + + return true; +#else + std::string error = "ELF parser not available on this platform."; + if (errorArg.GetString().empty()) { + this->SetError(error); + return false; + } else { + this->Makefile->AddDefinition(errorArg.GetString(), error.c_str()); + return true; + } +#endif +} + bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args) { cmFileInstaller installer(this); diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 319864c..2d82a23 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -53,6 +53,7 @@ protected: bool HandleRelativePathCommand(std::vector<std::string> const& args); bool HandleCMakePathCommand(std::vector<std::string> const& args, bool nativePath); + bool HandleReadElfCommand(std::vector<std::string> const& args); bool HandleRPathChangeCommand(std::vector<std::string> const& args); bool HandleRPathCheckCommand(std::vector<std::string> const& args); bool HandleRPathRemoveCommand(std::vector<std::string> const& args); diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h index 48169b8..2957328 100644 --- a/Source/cmFileMonitor.h +++ b/Source/cmFileMonitor.h @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include <cmConfigure.h> // IWYU pragma: keep + #include <functional> #include <string> #include <vector> diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 47d685d..29698cf 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -112,7 +112,7 @@ struct IDLSourcesTag struct ResxTag { }; -struct ModuleDefinitionFileTag +struct ModuleDefinitionSourcesTag { }; struct AppManifestTag @@ -236,8 +236,8 @@ struct TagVisitor } else if (!sf->GetLanguage().empty()) { DoAccept<IsSameTag<Tag, ObjectSourcesTag>::Result>::Do(this->Data, sf); } else if (ext == "def") { - DoAccept<IsSameTag<Tag, ModuleDefinitionFileTag>::Result>::Do(this->Data, - sf); + DoAccept<IsSameTag<Tag, ModuleDefinitionSourcesTag>::Result>::Do( + this->Data, sf); if (this->IsObjLib) { this->BadObjLibFiles.push_back(sf); } @@ -681,6 +681,12 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const return it != this->ExplicitObjectName.end(); } +void cmGeneratorTarget::GetModuleDefinitionSources( + std::vector<cmSourceFile const*>& data, const std::string& config) const +{ + IMPLEMENT_VISIT(ModuleDefinitionSources); +} + void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile const*>& data, const std::string& config) const { @@ -1938,17 +1944,45 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo( return &i->second; } -cmSourceFile const* cmGeneratorTarget::GetModuleDefinitionFile( - const std::string& config) const +cmGeneratorTarget::ModuleDefinitionInfo const* +cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const { - std::vector<cmSourceFile const*> data; - IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile, - COMMA std::vector<cmSourceFile const*>) - if (!data.empty()) { - return data.front(); + // A module definition file only makes sense on certain target types. + if (this->GetType() != cmStateEnums::SHARED_LIBRARY && + this->GetType() != cmStateEnums::MODULE_LIBRARY && + !this->IsExecutableWithExports()) { + return CM_NULLPTR; } - return CM_NULLPTR; + // Lookup/compute/cache the compile information for this configuration. + std::string config_upper; + if (!config.empty()) { + config_upper = cmSystemTools::UpperCase(config); + } + ModuleDefinitionInfoMapType::const_iterator i = + this->ModuleDefinitionInfoMap.find(config_upper); + if (i == this->ModuleDefinitionInfoMap.end()) { + ModuleDefinitionInfo info; + this->ComputeModuleDefinitionInfo(config, info); + ModuleDefinitionInfoMapType::value_type entry(config_upper, info); + i = this->ModuleDefinitionInfoMap.insert(entry).first; + } + return &i->second; +} + +void cmGeneratorTarget::ComputeModuleDefinitionInfo( + std::string const& config, ModuleDefinitionInfo& info) const +{ + std::vector<cmSourceFile const*> sources; + this->GetModuleDefinitionSources(sources, config); + info.WindowsExportAllSymbols = + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") && + this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"); + if (info.WindowsExportAllSymbols) { + info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def"; + } else if (!sources.empty()) { + info.DefFile = sources.front()->GetFullPath(); + } } bool cmGeneratorTarget::IsDLLPlatform() const diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index e72e0a6..92285f3 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -77,6 +77,8 @@ public: bool HasExplicitObjectName(cmSourceFile const* file) const; void AddExplicitObjectName(cmSourceFile const* sf); + void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&, + const std::string& config) const; void GetResxSources(std::vector<cmSourceFile const*>&, const std::string& config) const; void GetIDLSources(std::vector<cmSourceFile const*>&, @@ -233,7 +235,13 @@ public: cmLocalGenerator* LocalGenerator; cmGlobalGenerator const* GlobalGenerator; - cmSourceFile const* GetModuleDefinitionFile(const std::string& config) const; + struct ModuleDefinitionInfo + { + std::string DefFile; + bool WindowsExportAllSymbols; + }; + ModuleDefinitionInfo const* GetModuleDefinitionInfo( + std::string const& config) const; /** Return whether or not the target is for a DLL platform. */ bool IsDLLPlatform() const; @@ -721,6 +729,12 @@ private: typedef std::map<std::string, OutputInfo> OutputInfoMapType; mutable OutputInfoMapType OutputInfoMap; + typedef std::map<std::string, ModuleDefinitionInfo> + ModuleDefinitionInfoMapType; + mutable ModuleDefinitionInfoMapType ModuleDefinitionInfoMap; + void ComputeModuleDefinitionInfo(std::string const& config, + ModuleDefinitionInfo& info) const; + typedef std::pair<std::string, bool> OutputNameKey; typedef std::map<OutputNameKey, std::string> OutputNameMapType; mutable OutputNameMapType OutputNameMap; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index b6b7d9e..1f5e624 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -42,6 +42,7 @@ #include "cmStateDirectory.h" #include "cmStateTypes.h" #include "cmVersion.h" +#include "cmWorkingDirectory.h" #include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -1763,8 +1764,7 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/, /** * Run an executable command and put the stdout in output. */ - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(bindir); + cmWorkingDirectory workdir(bindir); output += "Change Dir: "; output += bindir; output += "\n"; @@ -1804,8 +1804,6 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/, output += *outputPtr; output += "\nGenerator: execution of make clean failed.\n"; - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); return 1; } output += *outputPtr; @@ -1828,8 +1826,6 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/, output += "\nGenerator: execution of make failed. Make command was: " + makeCommandStr + "\n"; - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); return 1; } output += *outputPtr; @@ -1842,7 +1838,6 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/, retVal = 1; } - cmSystemTools::ChangeDirectory(cwd); return retVal; } diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index b1285ac..ca98e6c 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -10,15 +10,25 @@ #include "cmSourceFile.h" #include "cmVS10CLFlagTable.h" #include "cmVS10CSharpFlagTable.h" +#include "cmVS10CudaFlagTable.h" +#include "cmVS10CudaHostFlagTable.h" #include "cmVS10LibFlagTable.h" #include "cmVS10LinkFlagTable.h" #include "cmVS10MASMFlagTable.h" #include "cmVS10NASMFlagTable.h" #include "cmVS10RCFlagTable.h" +#include "cmVersion.h" #include "cmVisualStudioSlnData.h" #include "cmVisualStudioSlnParser.h" +#include "cmXMLWriter.h" #include "cmake.h" +#include <cmsys/FStream.hxx> +#include <cmsys/Glob.hxx> +#include <cmsys/RegularExpression.hxx> + +#include <algorithm> + static const char vs10generatorName[] = "Visual Studio 10 2010"; // Map generator name without year to name with year. @@ -95,6 +105,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;" "ProductDir", vc10Express, cmSystemTools::KeyWOW64_32); + this->CudaEnabled = false; this->SystemIsWindowsCE = false; this->SystemIsWindowsPhone = false; this->SystemIsWindowsStore = false; @@ -113,6 +124,8 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( this->DefaultCSharpFlagTable = cmVS10CSharpFlagTable; this->DefaultLibFlagTable = cmVS10LibFlagTable; this->DefaultLinkFlagTable = cmVS10LinkFlagTable; + this->DefaultCudaFlagTable = cmVS10CudaFlagTable; + this->DefaultCudaHostFlagTable = cmVS10CudaHostFlagTable; this->DefaultMasmFlagTable = cmVS10MASMFlagTable; this->DefaultNasmFlagTable = cmVS10NASMFlagTable; this->DefaultRcFlagTable = cmVS10RCFlagTable; @@ -155,6 +168,13 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorPlatform( return true; } +static void cmCudaToolVersion(std::string& s) +{ + // "CUDA x.y.props" => "x.y" + s = s.substr(5); + s = s.substr(0, s.size() - 6); +} + bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( std::string const& ts, cmMakefile* mf) { @@ -170,12 +190,37 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( if (!this->ParseGeneratorToolset(ts, mf)) { return false; } + + if (!this->FindVCTargetsPath(mf)) { + return false; + } + + if (this->GeneratorToolsetCuda.empty()) { + // Find the highest available version of the CUDA tools. + std::vector<std::string> cudaTools; + std::string const bcDir = this->VCTargetsPath + "/BuildCustomizations"; + cmsys::Glob gl; + gl.SetRelative(bcDir.c_str()); + if (gl.FindFiles(bcDir + "/CUDA *.props")) { + cudaTools = gl.GetFiles(); + } + if (!cudaTools.empty()) { + std::for_each(cudaTools.begin(), cudaTools.end(), cmCudaToolVersion); + std::sort(cudaTools.begin(), cudaTools.end(), + cmSystemTools::VersionCompareGreater); + this->GeneratorToolsetCuda = cudaTools.at(0); + } + } + if (const char* toolset = this->GetPlatformToolset()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset); } if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch); } + if (const char* cuda = this->GetPlatformToolsetCuda()) { + mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA", cuda); + } return true; } @@ -251,8 +296,10 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( std::string const& key, std::string const& value) { - static_cast<void>(key); - static_cast<void>(value); + if (key == "cuda") { + this->GeneratorToolsetCuda = value; + return true; + } return false; } @@ -417,6 +464,9 @@ void cmGlobalVisualStudio10Generator::EnableLanguage( if (*it == "ASM_NASM") { this->NasmEnabled = true; } + if (*it == "CUDA") { + this->CudaEnabled = true; + } } this->AddPlatformDefinitions(mf); cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); @@ -453,6 +503,20 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const return CM_NULLPTR; } +const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const +{ + if (!this->GeneratorToolsetCuda.empty()) { + return this->GeneratorToolsetCuda.c_str(); + } + return CM_NULLPTR; +} + +std::string const& +cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const +{ + return this->GeneratorToolsetCuda; +} + bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf) { if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) { @@ -507,6 +571,208 @@ std::string cmGlobalVisualStudio10Generator::FindDevEnvCommand() return this->cmGlobalVisualStudio71Generator::FindDevEnvCommand(); } +bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) +{ + // Skip this in special cases within our own test suite. + if (this->GetPlatformName() == "Test Platform" || + this->GetPlatformToolsetString() == "Test Toolset") { + return true; + } + + std::string wd; + if (!this->ConfiguredFilesPath.empty()) { + // In a try-compile we are given the outer CMakeFiles directory. + wd = this->ConfiguredFilesPath; + } else { + wd = this->GetCMakeInstance()->GetHomeOutputDirectory(); + wd += cmake::GetCMakeFilesDirectory(); + } + wd += "/"; + wd += cmVersion::GetCMakeVersion(); + + // We record the result persistently in a file. + std::string const txt = wd + "/VCTargetsPath.txt"; + + // If we have a recorded result, use it. + { + cmsys::ifstream fin(txt.c_str()); + if (fin && cmSystemTools::GetLineFromStream(fin, this->VCTargetsPath) && + cmSystemTools::FileIsDirectory(this->VCTargetsPath)) { + cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath); + return true; + } + } + + // Prepare the work directory. + if (!cmSystemTools::MakeDirectory(wd)) { + std::string e = "Failed to make directory:\n " + wd; + mf->IssueMessage(cmake::FATAL_ERROR, e.c_str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + // Generate a project file for MSBuild to tell us the VCTargetsPath value. + std::string const vcxproj = "VCTargetsPath.vcxproj"; + { + std::string const vcxprojAbs = wd + "/" + vcxproj; + cmsys::ofstream fout(vcxprojAbs.c_str()); + cmXMLWriter xw(fout); + + /* clang-format off */ + xw.StartDocument(); + xw.StartElement("Project"); + xw.Attribute("DefaultTargets", "Build"); + xw.Attribute("ToolsVersion", "4.0"); + xw.Attribute("xmlns", + "http://schemas.microsoft.com/developer/msbuild/2003"); + if (this->IsNsightTegra()) { + xw.StartElement("PropertyGroup"); + xw.Attribute("Label", "NsightTegraProject"); + xw.StartElement("NsightTegraProjectRevisionNumber"); + xw.Content("6"); + xw.EndElement(); // NsightTegraProjectRevisionNumber + xw.EndElement(); // PropertyGroup + } + xw.StartElement("ItemGroup"); + xw.Attribute("Label", "ProjectConfigurations"); + xw.StartElement("ProjectConfiguration"); + xw.Attribute("Include", "Debug|" + this->GetPlatformName()); + xw.StartElement("Configuration"); + xw.Content("Debug"); + xw.EndElement(); // Configuration + xw.StartElement("Platform"); + xw.Content(this->GetPlatformName()); + xw.EndElement(); // Platform + xw.EndElement(); // ProjectConfiguration + xw.EndElement(); // ItemGroup + xw.StartElement("PropertyGroup"); + xw.Attribute("Label", "Globals"); + xw.StartElement("ProjectGUID"); + xw.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}"); + xw.EndElement(); // ProjectGUID + xw.StartElement("Keyword"); + xw.Content("Win32Proj"); + xw.EndElement(); // Keyword + xw.StartElement("Platform"); + xw.Content(this->GetPlatformName()); + xw.EndElement(); // Platform + if (this->GetSystemName() == "WindowsPhone") { + xw.StartElement("ApplicationType"); + xw.Content("Windows Phone"); + xw.EndElement(); // ApplicationType + xw.StartElement("ApplicationTypeRevision"); + xw.Content(this->GetSystemVersion()); + xw.EndElement(); // ApplicationTypeRevision + } else if (this->GetSystemName() == "WindowsStore") { + xw.StartElement("ApplicationType"); + xw.Content("Windows Store"); + xw.EndElement(); // ApplicationType + xw.StartElement("ApplicationTypeRevision"); + xw.Content(this->GetSystemVersion()); + xw.EndElement(); // ApplicationTypeRevision + } + if (!this->WindowsTargetPlatformVersion.empty()) { + xw.StartElement("WindowsTargetPlatformVersion"); + xw.Content(this->WindowsTargetPlatformVersion); + xw.EndElement(); // WindowsTargetPlatformVersion + } + if (this->GetPlatformName() == "ARM") { + xw.StartElement("WindowsSDKDesktopARMSupport"); + xw.Content("true"); + xw.EndElement(); // WindowsSDKDesktopARMSupport + } + xw.EndElement(); // PropertyGroup + xw.StartElement("Import"); + xw.Attribute("Project", + "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); + xw.EndElement(); // Import + if (!this->GeneratorToolsetHostArchitecture.empty()) { + xw.StartElement("PropertyGroup"); + xw.StartElement("PreferredToolArchitecture"); + xw.Content(this->GeneratorToolsetHostArchitecture); + xw.EndElement(); // PreferredToolArchitecture + xw.EndElement(); // PropertyGroup + } + xw.StartElement("PropertyGroup"); + xw.Attribute("Label", "Configuration"); + xw.StartElement("ConfigurationType"); + if (this->IsNsightTegra()) { + // Tegra-Android platform does not understand "Utility". + xw.Content("StaticLibrary"); + } else { + xw.Content("Utility"); + } + xw.EndElement(); // ConfigurationType + xw.StartElement("CharacterSet"); + xw.Content("MultiByte"); + xw.EndElement(); // CharacterSet + if (this->IsNsightTegra()) { + xw.StartElement("NdkToolchainVersion"); + xw.Content(this->GetPlatformToolsetString()); + xw.EndElement(); // NdkToolchainVersion + } else { + xw.StartElement("PlatformToolset"); + xw.Content(this->GetPlatformToolsetString()); + xw.EndElement(); // PlatformToolset + } + xw.EndElement(); // PropertyGroup + xw.StartElement("Import"); + xw.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); + xw.EndElement(); // Import + xw.StartElement("ItemDefinitionGroup"); + xw.StartElement("PostBuildEvent"); + xw.StartElement("Command"); + xw.Content("echo VCTargetsPath=$(VCTargetsPath)"); + xw.EndElement(); // Command + xw.EndElement(); // PostBuildEvent + xw.EndElement(); // ItemDefinitionGroup + xw.StartElement("Import"); + xw.Attribute("Project", + "$(VCTargetsPath)\\Microsoft.Cpp.targets"); + xw.EndElement(); // Import + xw.EndElement(); // Project + xw.EndDocument(); + /* clang-format on */ + } + + std::vector<std::string> cmd; + cmd.push_back(this->GetMSBuildCommand()); + cmd.push_back(vcxproj); + cmd.push_back(std::string("/p:VisualStudioVersion=") + + this->GetIDEVersion()); + std::string out; + int ret = 0; + cmsys::RegularExpression regex("\n *VCTargetsPath=([^%\r\n]+)[\r\n]"); + if (!cmSystemTools::RunSingleCommand(cmd, &out, &out, &ret, wd.c_str(), + cmSystemTools::OUTPUT_NONE) || + ret != 0 || !regex.find(out)) { + cmSystemTools::ReplaceString(out, "\n", "\n "); + std::ostringstream e; + /* clang-format off */ + e << + "Failed to run MSBuild command:\n" + " " << cmd[0] << "\n" + "to get the value of VCTargetsPath:\n" + " " << out << "\n" + ; + /* clang-format on */ + if (ret != 0) { + e << "Exit code: " << ret << "\n"; + } + mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + this->VCTargetsPath = regex.match(1); + cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath); + + { + cmsys::ofstream fout(txt.c_str()); + fout << this->VCTargetsPath << "\n"; + } + return true; +} + void cmGlobalVisualStudio10Generator::GenerateBuildCommand( std::vector<std::string>& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, @@ -721,6 +987,17 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const return (table != CM_NULLPTR) ? table : this->DefaultLinkFlagTable; } +cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const +{ + return this->DefaultCudaFlagTable; +} + +cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() + const +{ + return this->DefaultCudaHostFlagTable; +} + cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { cmIDEFlagTable const* table = this->ToolsetOptions.GetMasmFlagTable( diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index c5e4bcd..20f992a 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -42,6 +42,8 @@ public: cmMakefile*, bool optional); virtual void WriteSLNHeader(std::ostream& fout); + bool IsCudaEnabled() const { return this->CudaEnabled; } + /** Generating for Nsight Tegra VS plugin? */ bool IsNsightTegra() const; std::string GetNsightTegraVersion() const; @@ -53,6 +55,10 @@ public: /** The toolset host architecture name (e.g. x64 for 64-bit host tools). */ const char* GetPlatformToolsetHostArchitecture() const; + /** The cuda toolset version. */ + const char* GetPlatformToolsetCuda() const; + std::string const& GetPlatformToolsetCudaString() const; + /** Return the CMAKE_SYSTEM_NAME. */ std::string const& GetSystemName() const { return this->SystemName; } @@ -94,6 +100,8 @@ public: cmIDEFlagTable const* GetRcFlagTable() const; cmIDEFlagTable const* GetLibFlagTable() const; cmIDEFlagTable const* GetLinkFlagTable() const; + cmIDEFlagTable const* GetCudaFlagTable() const; + cmIDEFlagTable const* GetCudaHostFlagTable() const; cmIDEFlagTable const* GetMasmFlagTable() const; cmIDEFlagTable const* GetNasmFlagTable() const; @@ -118,6 +126,7 @@ protected: std::string GeneratorToolset; std::string GeneratorToolsetHostArchitecture; + std::string GeneratorToolsetCuda; std::string DefaultPlatformToolset; std::string WindowsTargetPlatformVersion; std::string SystemName; @@ -127,6 +136,8 @@ protected: cmIDEFlagTable const* DefaultCSharpFlagTable; cmIDEFlagTable const* DefaultLibFlagTable; cmIDEFlagTable const* DefaultLinkFlagTable; + cmIDEFlagTable const* DefaultCudaFlagTable; + cmIDEFlagTable const* DefaultCudaHostFlagTable; cmIDEFlagTable const* DefaultMasmFlagTable; cmIDEFlagTable const* DefaultNasmFlagTable; cmIDEFlagTable const* DefaultRcFlagTable; @@ -160,6 +171,11 @@ private: bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + std::string VCTargetsPath; + bool FindVCTargetsPath(cmMakefile* mf); + + bool CudaEnabled; + // We do not use the reload macros for VS >= 10. virtual std::string GetUserMacrosDirectory() { return ""; } }; diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index cc2536c..a073426 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -750,6 +750,10 @@ bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly( if (!gt->GetConfigCommonSourceFiles(sources)) { return false; } + // Only "real" targets are allowed to be C# targets. + if (gt->Target->GetType() > cmStateEnums::OBJECT_LIBRARY) { + return false; + } } gt->GetLanguages(languages, ""); if (languages.size() == 1) { @@ -810,10 +814,14 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( cmGeneratorTarget* gt, std::vector<cmCustomCommand>& commands, std::string const& configName) { + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + gt->GetModuleDefinitionInfo(configName); + if (!mdi || !mdi->WindowsExportAllSymbols) { + return; + } + std::vector<std::string> outputs; - std::string deffile = gt->ObjectDirectory; - deffile += "/exportall.def"; - outputs.push_back(deffile); + outputs.push_back(mdi->DefFile); std::vector<std::string> empty; std::vector<cmSourceFile const*> objectSources; gt->GetObjectSources(objectSources, configName); @@ -831,7 +839,7 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( cmdl.push_back(cmakeCommand); cmdl.push_back("-E"); cmdl.push_back("__create_def"); - cmdl.push_back(deffile); + cmdl.push_back(mdi->DefFile); std::string obj_dir_expanded = obj_dir; cmSystemTools::ReplaceString(obj_dir_expanded, this->GetCMakeCFGIntDir(), configName.c_str()); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index b023d5c..77f3408 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3341,8 +3341,7 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( // Since the lowest available Xcode version for testing was 7.0, // I'm setting this as a limit then - if (this->GetCMakeInstance()->GetState()->GetGlobalPropertyAsBool( - "XCODE_GENERATE_SCHEME") && + if (root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME") && this->XcodeVersion >= 70) { this->OutputXCodeSharedSchemes(xcodeDir); this->OutputXCodeWorkspaceSettings(xcodeDir); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 07d712c..82bf0b9 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -213,14 +213,7 @@ void cmLocalGenerator::TraceDependencies() void cmLocalGenerator::GenerateTestFiles() { - std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary(); - file += "/"; - file += "CTestTestfile.cmake"; - if (!this->Makefile->IsOn("CMAKE_TESTING_ENABLED")) { - if (cmSystemTools::FileExists(file)) { - cmSystemTools::RemoveFile(file); - } return; } @@ -229,6 +222,10 @@ void cmLocalGenerator::GenerateTestFiles() const std::string& config = this->Makefile->GetConfigurations(configurationTypes, false); + std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary(); + file += "/"; + file += "CTestTestfile.cmake"; + cmGeneratedFileStream fout(file.c_str()); fout.SetCopyIfDifferent(true); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 6e976e1..8026de9 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -996,19 +996,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( linkOptions.AddTable(cmLocalVisualStudio7GeneratorLinkFlagTable); linkOptions.Parse(extraLinkOptions.c_str()); - if (!this->ModuleDefinitionFile.empty()) { - std::string defFile = this->ConvertToOutputFormat( - this->ModuleDefinitionFile, cmOutputConverter::SHELL); + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + target->GetModuleDefinitionInfo(configName); + if (mdi && !mdi->DefFile.empty()) { + std::string defFile = + this->ConvertToOutputFormat(mdi->DefFile, cmOutputConverter::SHELL); linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); } - if ((target->GetType() == cmStateEnums::SHARED_LIBRARY || - target->IsExecutableWithExports()) && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)/exportall.def"); - } - } switch (target->GetType()) { case cmStateEnums::UNKNOWN_LIBRARY: break; @@ -1362,7 +1357,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); // get the classes from the source lists then add them to the groups - this->ModuleDefinitionFile = ""; std::vector<cmSourceFile*> classes; if (!target->GetConfigCommonSourceFiles(classes)) { return; @@ -1374,9 +1368,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, } // Add the file to the list of sources. std::string source = (*i)->GetFullPath(); - if (cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF") { - this->ModuleDefinitionFile = (*i)->GetFullPath(); - } cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(source.c_str(), sourceGroups); sourceGroup->AssignSource(*i); @@ -1825,17 +1816,15 @@ void cmLocalVisualStudio7Generator::OutputTargetRules( tool = this->FortranProject ? "VFPreLinkEventTool" : "VCPreLinkEventTool"; event.Start(tool); bool addedPrelink = false; - if ((target->GetType() == cmStateEnums::SHARED_LIBRARY || - target->IsExecutableWithExports()) && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - addedPrelink = true; - std::vector<cmCustomCommand> commands = target->GetPreLinkCommands(); - cmGlobalVisualStudioGenerator* gg = - static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); - gg->AddSymbolExportCommand(target, commands, configName); - event.Write(commands); - } + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + target->GetModuleDefinitionInfo(configName); + if (mdi && mdi->WindowsExportAllSymbols) { + addedPrelink = true; + std::vector<cmCustomCommand> commands = target->GetPreLinkCommands(); + cmGlobalVisualStudioGenerator* gg = + static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); + gg->AddSymbolExportCommand(target, commands, configName); + event.Write(commands); } if (!addedPrelink) { event.Write(target->GetPreLinkCommands()); diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index d69cce1..ae6e2ed 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -128,7 +128,6 @@ private: friend class EventWriter; - std::string ModuleDefinitionFile; bool FortranProject; bool WindowsCEProject; cmLocalVisualStudio7GeneratorInternals* Internal; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index da32dd7..c4a488f 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -36,6 +36,7 @@ #include "cmTest.h" #include "cmTestGenerator.h" // IWYU pragma: keep #include "cmVersion.h" +#include "cmWorkingDirectory.h" #include "cm_auto_ptr.hxx" #include "cmake.h" @@ -3164,8 +3165,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, // change to the tests directory and run cmake // use the cmake object instead of calling cmake - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(bindir); + cmWorkingDirectory workdir(bindir); // make sure the same generator is used // use this program as the cmake to be run, it should not @@ -3179,8 +3179,6 @@ int cmMakefile::TryCompile(const std::string& srcdir, this->GetGlobalGenerator()->GetName() + "' could not be created."); cmSystemTools::SetFatalErrorOccured(); - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; return 1; } @@ -3244,8 +3242,6 @@ int cmMakefile::TryCompile(const std::string& srcdir, this->IssueMessage(cmake::FATAL_ERROR, "Failed to configure test project build system."); cmSystemTools::SetFatalErrorOccured(); - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; return 1; } @@ -3254,8 +3250,6 @@ int cmMakefile::TryCompile(const std::string& srcdir, this->IssueMessage(cmake::FATAL_ERROR, "Failed to generate test project build system."); cmSystemTools::SetFatalErrorOccured(); - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; return 1; } @@ -3264,7 +3258,6 @@ int cmMakefile::TryCompile(const std::string& srcdir, int ret = this->GetGlobalGenerator()->TryCompile( srcdir, bindir, projectName, targetName, fast, output, this); - cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; return ret; } diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 8ed5051..493f474 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -556,10 +556,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } // maybe create .def file from list of objects - if (this->GeneratorTarget->IsExecutableWithExports() && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - this->GenDefFile(real_link_commands, linkFlags); - } + this->GenDefFile(real_link_commands); std::string manifests = this->GetManifests(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index bc456cf..e5fae13 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -750,10 +750,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } // maybe create .def file from list of objects - if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - this->GenDefFile(real_link_commands, linkFlags); - } + this->GenDefFile(real_link_commands); std::string manifests = this->GetManifests(); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 54b3f36..1fa8702 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1414,8 +1414,10 @@ void cmMakefileTargetGenerator::AppendLinkDepends( this->AppendTargetDepends(depends); // Add a dependency on the link definitions file, if any. - if (this->ModuleDefinitionFile) { - depends.push_back(this->ModuleDefinitionFile->GetFullPath()); + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName()); + if (mdi && !mdi->WindowsExportAllSymbols && !mdi->DefFile.empty()) { + depends.push_back(mdi->DefFile); } // Add a dependency on user-specified manifest files, if any. @@ -1718,49 +1720,39 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, } void cmMakefileTargetGenerator::GenDefFile( - std::vector<std::string>& real_link_commands, std::string& linkFlags) + std::vector<std::string>& real_link_commands) { - if (this->GeneratorTarget->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - std::string name_of_def_file = - this->GeneratorTarget->GetSupportDirectory(); - name_of_def_file += std::string("/") + this->GeneratorTarget->GetName(); - name_of_def_file += ".def"; - std::string cmd = cmSystemTools::GetCMakeCommand(); - cmd = this->LocalGenerator->ConvertToOutputFormat( - cmd, cmOutputConverter::SHELL); - cmd += " -E __create_def "; - cmd += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file), - cmOutputConverter::SHELL); - cmd += " "; - std::string objlist_file = name_of_def_file; - objlist_file += ".objs"; - cmd += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file), - cmOutputConverter::SHELL); - real_link_commands.insert(real_link_commands.begin(), cmd); - // create a list of obj files for the -E __create_def to read - cmGeneratedFileStream fout(objlist_file.c_str()); - for (std::vector<std::string>::const_iterator i = this->Objects.begin(); - i != this->Objects.end(); ++i) { - if (cmHasLiteralSuffix(*i, ".obj")) { - fout << *i << "\n"; - } - } - for (std::vector<std::string>::const_iterator i = - this->ExternalObjects.begin(); - i != this->ExternalObjects.end(); ++i) { + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName()); + if (!mdi || !mdi->WindowsExportAllSymbols) { + return; + } + std::string cmd = cmSystemTools::GetCMakeCommand(); + cmd = + this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL); + cmd += " -E __create_def "; + cmd += this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile), + cmOutputConverter::SHELL); + cmd += " "; + std::string objlist_file = mdi->DefFile + ".objs"; + cmd += this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file), + cmOutputConverter::SHELL); + real_link_commands.insert(real_link_commands.begin(), cmd); + // create a list of obj files for the -E __create_def to read + cmGeneratedFileStream fout(objlist_file.c_str()); + for (std::vector<std::string>::const_iterator i = this->Objects.begin(); + i != this->Objects.end(); ++i) { + if (cmHasLiteralSuffix(*i, ".obj")) { fout << *i << "\n"; } - // now add the def file link flag - linkFlags += " "; - linkFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); - linkFlags += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file), - cmOutputConverter::SHELL); - linkFlags += " "; + } + for (std::vector<std::string>::const_iterator i = + this->ExternalObjects.begin(); + i != this->ExternalObjects.end(); ++i) { + fout << *i << "\n"; } } diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 347f9f2..07b8005 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -166,8 +166,7 @@ protected: bool useWatcomQuote); /** Add commands for generate def files */ - void GenDefFile(std::vector<std::string>& real_link_commands, - std::string& linkFlags); + void GenDefFile(std::vector<std::string>& real_link_commands); void AddIncludeFlags(std::string& flags, const std::string& lang) CM_OVERRIDE; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 9bf0ccd..300618f 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -860,19 +860,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"], vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget); - if (this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") && - (gt.GetType() == cmStateEnums::SHARED_LIBRARY || - gt.IsExecutableWithExports())) { - if (gt.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - std::string name_of_def_file = gt.GetSupportDirectory(); - name_of_def_file += "/" + gt.GetName(); - name_of_def_file += ".def "; - vars["LINK_FLAGS"] += " /DEF:"; - vars["LINK_FLAGS"] += this->GetLocalGenerator()->ConvertToOutputFormat( - name_of_def_file, cmOutputConverter::SHELL); - } - } - // Add OS X version flags, if any. if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { @@ -989,33 +976,27 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } // maybe create .def file from list of objects - if ((gt.GetType() == cmStateEnums::SHARED_LIBRARY || - gt.IsExecutableWithExports()) && - this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (gt.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - std::string cmakeCommand = - this->GetLocalGenerator()->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); - std::string name_of_def_file = gt.GetSupportDirectory(); - name_of_def_file += "/" + gt.GetName(); - name_of_def_file += ".def"; - std::string cmd = cmakeCommand; - cmd += " -E __create_def "; - cmd += this->GetLocalGenerator()->ConvertToOutputFormat( - name_of_def_file, cmOutputConverter::SHELL); - cmd += " "; - cmNinjaDeps objs = this->GetObjects(); - std::string obj_list_file = name_of_def_file; - obj_list_file += ".objs"; - cmd += this->GetLocalGenerator()->ConvertToOutputFormat( - obj_list_file, cmOutputConverter::SHELL); - preLinkCmdLines.push_back(cmd); - // create a list of obj files for the -E __create_def to read - cmGeneratedFileStream fout(obj_list_file.c_str()); - for (cmNinjaDeps::iterator i = objs.begin(); i != objs.end(); ++i) { - if (cmHasLiteralSuffix(*i, ".obj")) { - fout << *i << "\n"; - } + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + gt.GetModuleDefinitionInfo(this->GetConfigName()); + if (mdi && mdi->WindowsExportAllSymbols) { + std::string cmakeCommand = + this->GetLocalGenerator()->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); + std::string cmd = cmakeCommand; + cmd += " -E __create_def "; + cmd += this->GetLocalGenerator()->ConvertToOutputFormat( + mdi->DefFile, cmOutputConverter::SHELL); + cmd += " "; + cmNinjaDeps objs = this->GetObjects(); + std::string obj_list_file = mdi->DefFile + ".objs"; + cmd += this->GetLocalGenerator()->ConvertToOutputFormat( + obj_list_file, cmOutputConverter::SHELL); + preLinkCmdLines.push_back(cmd); + // create a list of obj files for the -E __create_def to read + cmGeneratedFileStream fout(obj_list_file.c_str()); + for (cmNinjaDeps::iterator i = objs.begin(); i != objs.end(); ++i) { + if (cmHasLiteralSuffix(*i, ".obj")) { + fout << *i << "\n"; } } } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index b1f26e4..917383d 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -212,9 +212,10 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath()); // Add a dependency on the link definitions file, if any. - if (this->ModuleDefinitionFile) { - result.push_back( - this->ConvertToNinjaPath(this->ModuleDefinitionFile->GetFullPath())); + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName()); + if (mdi && !mdi->WindowsExportAllSymbols && !mdi->DefFile.empty()) { + result.push_back(this->ConvertToNinjaPath(mdi->DefFile)); } // Add a dependency on user-specified manifest files, if any. diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 7744a5a..d48eb53 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -287,8 +287,7 @@ void cmOrderDirectories::AddRuntimeLibrary(std::string const& fullPath, } } - if (this->ImplicitDirectories.find(dir) != - this->ImplicitDirectories.end()) { + if (this->IsImplicitDirectory(dir)) { this->ImplicitDirEntries.push_back( new cmOrderDirectoriesConstraintSOName(this, fullPath, soname)); return; @@ -316,8 +315,7 @@ void cmOrderDirectories::AddLinkLibrary(std::string const& fullPath) // Implicit link directories need special handling. if (!this->ImplicitDirectories.empty()) { std::string dir = cmSystemTools::GetFilenamePath(fullPath); - if (this->ImplicitDirectories.find(dir) != - this->ImplicitDirectories.end()) { + if (this->IsImplicitDirectory(dir)) { this->ImplicitDirEntries.push_back( new cmOrderDirectoriesConstraintLibrary(this, fullPath)); return; @@ -347,7 +345,18 @@ void cmOrderDirectories::AddLanguageDirectories( void cmOrderDirectories::SetImplicitDirectories( std::set<std::string> const& implicitDirs) { - this->ImplicitDirectories = implicitDirs; + this->ImplicitDirectories.clear(); + for (std::set<std::string>::const_iterator i = implicitDirs.begin(); + i != implicitDirs.end(); ++i) { + this->ImplicitDirectories.insert(this->GetRealPath(*i)); + } +} + +bool cmOrderDirectories::IsImplicitDirectory(std::string const& dir) +{ + std::string const& real = this->GetRealPath(dir); + return this->ImplicitDirectories.find(real) != + this->ImplicitDirectories.end(); } void cmOrderDirectories::SetLinkExtensionInfo( @@ -394,8 +403,7 @@ void cmOrderDirectories::AddOriginalDirectories( for (std::vector<std::string>::const_iterator di = dirs.begin(); di != dirs.end(); ++di) { // We never explicitly specify implicit link directories. - if (this->ImplicitDirectories.find(*di) != - this->ImplicitDirectories.end()) { + if (this->IsImplicitDirectory(*di)) { continue; } diff --git a/Source/cmOrderDirectories.h b/Source/cmOrderDirectories.h index 90a67e7..d9e0126 100644 --- a/Source/cmOrderDirectories.h +++ b/Source/cmOrderDirectories.h @@ -82,6 +82,8 @@ private: // Compare directories after resolving symlinks. bool IsSameDirectory(std::string const& l, std::string const& r); + bool IsImplicitDirectory(std::string const& dir); + std::string const& GetRealPath(std::string const& dir); std::map<std::string, std::string> RealPaths; diff --git a/Source/cmQtAutoGeneratorCommon.cxx b/Source/cmQtAutoGeneratorCommon.cxx new file mode 100644 index 0000000..dcd61a3 --- /dev/null +++ b/Source/cmQtAutoGeneratorCommon.cxx @@ -0,0 +1,215 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoGeneratorCommon.h" +#include "cmAlgorithms.h" +#include "cmSystemTools.h" + +#include <cmsys/FStream.hxx> +#include <cmsys/RegularExpression.hxx> + +#include <sstream> + +// - Static functions + +static std::string utilStripCR(std::string const& line) +{ + // Strip CR characters rcc may have printed (possibly more than one!). + std::string::size_type cr = line.find('\r'); + if (cr != line.npos) { + return line.substr(0, cr); + } + return line; +} + +/// @brief Reads the resource files list from from a .qrc file - Qt4 version +/// @return True if the .qrc file was successfully parsed +static bool RccListInputsQt4(const std::string& fileName, + std::vector<std::string>& files, + std::string* errorMessage) +{ + bool allGood = true; + // Read qrc file content into string + std::string qrcContents; + { + cmsys::ifstream ifs(fileName.c_str()); + if (ifs) { + std::ostringstream osst; + osst << ifs.rdbuf(); + qrcContents = osst.str(); + } else { + if (errorMessage != CM_NULLPTR) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc file not readable:\n" + << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n"; + *errorMessage = ost.str(); + } + allGood = false; + } + } + if (allGood) { + // qrc file directory + std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName)); + if (!qrcDir.empty()) { + qrcDir += '/'; + } + + cmsys::RegularExpression fileMatchRegex("(<file[^<]+)"); + cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)"); + + size_t offset = 0; + while (fileMatchRegex.find(qrcContents.c_str() + offset)) { + std::string qrcEntry = fileMatchRegex.match(1); + offset += qrcEntry.size(); + { + fileReplaceRegex.find(qrcEntry); + std::string tag = fileReplaceRegex.match(1); + qrcEntry = qrcEntry.substr(tag.size()); + } + if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { + qrcEntry = qrcDir + qrcEntry; + } + files.push_back(qrcEntry); + } + } + return allGood; +} + +/// @brief Reads the resource files list from from a .qrc file - Qt5 version +/// @return True if the .qrc file was successfully parsed +static bool RccListInputsQt5(const std::string& rccCommand, + const std::string& fileName, + std::vector<std::string>& files, + std::string* errorMessage) +{ + if (rccCommand.empty()) { + cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n"); + return false; + } + + // Read rcc features + bool hasDashDashList = false; + { + std::vector<std::string> command; + command.push_back(rccCommand); + command.push_back("--help"); + std::string rccStdOut; + std::string rccStdErr; + int retVal = 0; + bool result = + cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, + CM_NULLPTR, cmSystemTools::OUTPUT_NONE); + if (result && retVal == 0 && + rccStdOut.find("--list") != std::string::npos) { + hasDashDashList = true; + } + } + + // Run rcc list command + bool result = false; + int retVal = 0; + std::string rccStdOut; + std::string rccStdErr; + { + std::vector<std::string> command; + command.push_back(rccCommand); + command.push_back(hasDashDashList ? "--list" : "-list"); + command.push_back(fileName); + result = + cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, + CM_NULLPTR, cmSystemTools::OUTPUT_NONE); + } + if (!result || retVal) { + if (errorMessage != CM_NULLPTR) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc list process for " << fileName + << " failed:\n" + << rccStdOut << "\n" + << rccStdErr << "\n"; + *errorMessage = ost.str(); + } + return false; + } + + // Parse rcc std output + { + std::istringstream ostr(rccStdOut); + std::string oline; + while (std::getline(ostr, oline)) { + oline = utilStripCR(oline); + if (!oline.empty()) { + files.push_back(oline); + } + } + } + // Parse rcc error output + { + std::istringstream estr(rccStdErr); + std::string eline; + while (std::getline(estr, eline)) { + eline = utilStripCR(eline); + if (cmHasLiteralPrefix(eline, "RCC: Error in")) { + static std::string searchString = "Cannot find file '"; + + std::string::size_type pos = eline.find(searchString); + if (pos == std::string::npos) { + if (errorMessage != CM_NULLPTR) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc lists unparsable output:\n" + << cmQtAutoGeneratorCommon::Quoted(eline) << "\n"; + *errorMessage = ost.str(); + } + return false; + } + pos += searchString.length(); + std::string::size_type sz = eline.size() - pos - 1; + files.push_back(eline.substr(pos, sz)); + } + } + } + + return true; +} + +// - Class definitions + +const char* cmQtAutoGeneratorCommon::listSep = "@LSEP@"; + +std::string cmQtAutoGeneratorCommon::Quoted(const std::string& text) +{ + static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", + "\b", "\\b", "\f", "\\f", "\n", "\\n", + "\r", "\\r", "\t", "\\t", "\v", "\\v" }; + + std::string res = text; + for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep); + it += 2) { + cmSystemTools::ReplaceString(res, *it, *(it + 1)); + } + res = '"' + res; + res += '"'; + return res; +} + +bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion, + const std::string& rccCommand, + const std::string& fileName, + std::vector<std::string>& files, + std::string* errorMessage) +{ + bool allGood = false; + if (cmsys::SystemTools::FileExists(fileName.c_str())) { + if (qtMajorVersion == "4") { + allGood = RccListInputsQt4(fileName, files, errorMessage); + } else { + allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage); + } + } else { + if (errorMessage != CM_NULLPTR) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc file does not exist:\n" + << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n"; + *errorMessage = ost.str(); + } + } + return allGood; +} diff --git a/Source/cmQtAutoGeneratorCommon.h b/Source/cmQtAutoGeneratorCommon.h new file mode 100644 index 0000000..ee97b71 --- /dev/null +++ b/Source/cmQtAutoGeneratorCommon.h @@ -0,0 +1,34 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmQtAutoGeneratorCommon_h +#define cmQtAutoGeneratorCommon_h + +#include <cmConfigure.h> // IWYU pragma: keep +#include <string> +#include <vector> + +class cmGeneratorTarget; +class cmLocalGenerator; + +class cmQtAutoGeneratorCommon +{ + // - Types and statics +public: + static const char* listSep; + +public: + /// @brief Returns a the string escaped and enclosed in quotes + /// + static std::string Quoted(const std::string& text); + + /// @brief Reads the resource files list from from a .qrc file + /// @arg fileName Must be the absolute path of the .qrc file + /// @return True if the rcc file was successfully parsed + static bool RccListInputs(const std::string& qtMajorVersion, + const std::string& rccCommand, + const std::string& fileName, + std::vector<std::string>& files, + std::string* errorMessage = CM_NULLPTR); +}; + +#endif diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index a45b3d5..94cc981 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -1,6 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGeneratorInitializer.h" +#include "cmQtAutoGeneratorCommon.h" #include "cmAlgorithms.h" #include "cmCustomCommandLines.h" @@ -44,14 +45,9 @@ static void utilCopyTargetProperty(cmTarget* destinationTarget, } } -static std::string utilStripCR(std::string const& line) +inline static bool PropertyEnabled(cmSourceFile* sourceFile, const char* key) { - // Strip CR characters rcc may have printed (possibly more than one!). - std::string::size_type cr = line.find('\r'); - if (cr != line.npos) { - return line.substr(0, cr); - } - return line; + return cmSystemTools::IsOn(sourceFile->GetPropertyForUser(key)); } static std::string GetSafeProperty(cmGeneratorTarget const* target, @@ -138,21 +134,17 @@ static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str()); } -static void SetupSourceFiles(cmGeneratorTarget const* target, +static void AcquireScanFiles(cmGeneratorTarget const* target, std::vector<std::string>& mocUicSources, std::vector<std::string>& mocUicHeaders, std::vector<std::string>& mocSkipList, std::vector<std::string>& uicSkipList) { - cmMakefile* makefile = target->Target->GetMakefile(); - - std::vector<cmSourceFile*> srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); - const bool mocTarget = target->GetPropertyAsBool("AUTOMOC"); const bool uicTarget = target->GetPropertyAsBool("AUTOUIC"); - cmFilePathChecksum fpathCheckSum(makefile); + std::vector<cmSourceFile*> srcFiles; + target->GetConfigCommonSourceFiles(srcFiles); for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; @@ -163,18 +155,12 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { continue; } - if (cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - continue; - } const std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); // Skip flags - const bool skipAll = - cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")); - const bool mocSkip = - skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); - const bool uicSkip = - skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC")); + const bool skipAll = PropertyEnabled(sf, "SKIP_AUTOGEN"); + const bool mocSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOMOC"); + const bool uicSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOUIC"); // Add file name to skip lists. // Do this even when the file is not added to the sources/headers lists // because the file name may be extracted from an other file when @@ -361,7 +347,8 @@ static void UicSetupAutoTarget( uiFileFiles.push_back(absFile); { std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); - cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); + cmSystemTools::ReplaceString(opts, ";", + cmQtAutoGeneratorCommon::listSep); uiFileOptions.push_back(opts); } } @@ -469,146 +456,12 @@ static void RccMergeOptions(std::vector<std::string>& opts, opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); } -/// @brief Reads the resource files list from from a .qrc file - Qt5 version -/// @return True if the .qrc file was successfully parsed -static bool RccListInputsQt5(cmSourceFile* sf, cmGeneratorTarget const* target, - std::vector<std::string>& depends) -{ - const std::string rccCommand = RccGetExecutable(target, "5"); - if (rccCommand.empty()) { - cmSystemTools::Error("AUTOGEN: error: rcc executable not available\n"); - return false; - } - - bool hasDashDashList = false; - // Read rcc features - { - std::vector<std::string> command; - command.push_back(rccCommand); - command.push_back("--help"); - std::string rccStdOut; - std::string rccStdErr; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, - CM_NULLPTR, cmSystemTools::OUTPUT_NONE); - if (result && retVal == 0 && - rccStdOut.find("--list") != std::string::npos) { - hasDashDashList = true; - } - } - // Run rcc list command - std::vector<std::string> command; - command.push_back(rccCommand); - command.push_back(hasDashDashList ? "--list" : "-list"); - - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - command.push_back(absFile); - - std::string rccStdOut; - std::string rccStdErr; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, - CM_NULLPTR, cmSystemTools::OUTPUT_NONE); - if (!result || retVal) { - std::ostringstream err; - err << "AUTOGEN: error: Rcc list process for " << sf->GetFullPath() - << " failed:\n" - << rccStdOut << "\n" - << rccStdErr << std::endl; - cmSystemTools::Error(err.str().c_str()); - return false; - } - - // Parse rcc list output - { - std::istringstream ostr(rccStdOut); - std::string oline; - while (std::getline(ostr, oline)) { - oline = utilStripCR(oline); - if (!oline.empty()) { - depends.push_back(oline); - } - } - } - - { - std::istringstream estr(rccStdErr); - std::string eline; - while (std::getline(estr, eline)) { - eline = utilStripCR(eline); - if (cmHasLiteralPrefix(eline, "RCC: Error in")) { - static std::string searchString = "Cannot find file '"; - - std::string::size_type pos = eline.find(searchString); - if (pos == std::string::npos) { - std::ostringstream err; - err << "AUTOGEN: error: Rcc lists unparsable output " << eline - << std::endl; - cmSystemTools::Error(err.str().c_str()); - return false; - } - pos += searchString.length(); - std::string::size_type sz = eline.size() - pos - 1; - depends.push_back(eline.substr(pos, sz)); - } - } - } - - return true; -} - -/// @brief Reads the resource files list from from a .qrc file - Qt4 version -/// @return True if the .qrc file was successfully parsed -static bool RccListInputsQt4(cmSourceFile* sf, - std::vector<std::string>& depends) -{ - // Read file into string - std::string qrcContents; - { - std::ostringstream stream; - stream << cmsys::ifstream(sf->GetFullPath().c_str()).rdbuf(); - qrcContents = stream.str(); - } - - cmsys::RegularExpression fileMatchRegex("(<file[^<]+)"); - cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)"); - - size_t offset = 0; - while (fileMatchRegex.find(qrcContents.c_str() + offset)) { - std::string qrcEntry = fileMatchRegex.match(1); - offset += qrcEntry.size(); - { - fileReplaceRegex.find(qrcEntry); - std::string tag = fileReplaceRegex.match(1); - qrcEntry = qrcEntry.substr(tag.size()); - } - if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { - qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry; - } - depends.push_back(qrcEntry); - } - return true; -} - -/// @brief Reads the resource files list from from a .qrc file -/// @return True if the rcc file was successfully parsed -static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf, - cmGeneratorTarget const* target, - std::vector<std::string>& depends) -{ - if (qtMajorVersion == "5") { - return RccListInputsQt5(sf, target, depends); - } - return RccListInputsQt4(sf, depends); -} - static void RccSetupAutoTarget(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { cmMakefile* makefile = target->Target->GetMakefile(); const bool qtMajorVersion5 = (qtMajorVersion == "5"); + const std::string rccCommand = RccGetExecutable(target, qtMajorVersion); std::vector<std::string> _rcc_files; std::vector<std::string> _rcc_inputs; std::vector<std::string> rccFileFiles; @@ -623,53 +476,54 @@ static void RccSetupAutoTarget(cmGeneratorTarget const* target, for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; - if (sf->GetExtension() == "qrc") { - const bool skip = - cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) || - cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); - if (!skip) { - const std::string absFile = - cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - // qrc file - _rcc_files.push_back(absFile); - // qrc file entries - { - std::string entriesList; - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - std::vector<std::string> depends; - if (RccListInputs(qtMajorVersion, sf, target, depends)) { - entriesList = cmJoin(depends, "@list_sep@"); - } else { - return; - } + if ((sf->GetExtension() == "qrc") && + !PropertyEnabled(sf, "SKIP_AUTOGEN") && + !PropertyEnabled(sf, "SKIP_AUTORCC")) { + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + // qrc file + _rcc_files.push_back(absFile); + // qrc file entries + { + std::string entriesList = "{"; + // Read input file list only for non generated .qrc files. + if (!PropertyEnabled(sf, "GENERATED")) { + std::string error; + std::vector<std::string> files; + if (cmQtAutoGeneratorCommon::RccListInputs( + qtMajorVersion, rccCommand, absFile, files, &error)) { + entriesList += cmJoin(files, cmQtAutoGeneratorCommon::listSep); + } else { + cmSystemTools::Error(error.c_str()); } - _rcc_inputs.push_back(entriesList); } - // rcc options for this qrc file - { - // Merged target and file options - std::vector<std::string> rccOptions(rccOptionsTarget); - if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { - std::vector<std::string> optsVec; - cmSystemTools::ExpandListArgument(prop, optsVec); - RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); - } - // Only store non empty options lists - if (!rccOptions.empty()) { - rccFileFiles.push_back(absFile); - rccFileOptions.push_back(cmJoin(rccOptions, "@list_sep@")); - } + entriesList += "}"; + _rcc_inputs.push_back(entriesList); + } + // rcc options for this qrc file + { + // Merged target and file options + std::vector<std::string> rccOptions(rccOptionsTarget); + if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { + std::vector<std::string> optsVec; + cmSystemTools::ExpandListArgument(prop, optsVec); + RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); + } + // Only store non empty options lists + if (!rccOptions.empty()) { + rccFileFiles.push_back(absFile); + rccFileOptions.push_back( + cmJoin(rccOptions, cmQtAutoGeneratorCommon::listSep)); } } } } + AddDefinitionEscaped(makefile, "_qt_rcc_executable", rccCommand); AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files); AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs); AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles); AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions); - AddDefinitionEscaped(makefile, "_qt_rcc_executable", - RccGetExecutable(target, qtMajorVersion)); } void cmQtAutoGeneratorInitializer::InitializeAutogenSources( @@ -691,12 +545,17 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( cmMakefile* makefile = target->Target->GetMakefile(); // Create a custom target for running generators at buildtime + const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC"); + const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC"); + const bool rccEnabled = target->GetPropertyAsBool("AUTORCC"); const std::string autogenTargetName = GetAutogenTargetName(target); const std::string autogenBuildDir = GetAutogenTargetBuildDir(target); const std::string workingDirectory = cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory()); const std::string qtMajorVersion = GetQtMajorVersion(target); - std::vector<std::string> autogenOutputFiles; + const std::string rccCommand = RccGetExecutable(target, qtMajorVersion); + std::vector<std::string> autogenDepends; + std::vector<std::string> autogenProvides; // Remove old settings on cleanup { @@ -706,32 +565,6 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( false); } - // Create autogen target build directory and add it to the clean files - cmSystemTools::MakeDirectory(autogenBuildDir); - makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", - autogenBuildDir.c_str(), false); - - if (target->GetPropertyAsBool("AUTOMOC") || - target->GetPropertyAsBool("AUTOUIC")) { - // Create autogen target includes directory and - // add it to the origin target INCLUDE_DIRECTORIES - const std::string incsDir = autogenBuildDir + "include"; - cmSystemTools::MakeDirectory(incsDir); - target->AddIncludeDirectory(incsDir, true); - } - - if (target->GetPropertyAsBool("AUTOMOC")) { - // Register moc compilation file as generated - autogenOutputFiles.push_back(autogenBuildDir + "moc_compilation.cpp"); - } - - // Initialize autogen target dependencies - std::vector<std::string> depends; - if (const char* autogenDepends = - target->GetProperty("AUTOGEN_TARGET_DEPENDS")) { - cmSystemTools::ExpandListArgument(autogenDepends, depends); - } - // Compose command lines cmCustomCommandLines commandLines; { @@ -748,13 +581,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( std::string autogenComment; { std::vector<std::string> toolNames; - if (target->GetPropertyAsBool("AUTOMOC")) { + if (mocEnabled) { toolNames.push_back("MOC"); } - if (target->GetPropertyAsBool("AUTOUIC")) { + if (uicEnabled) { toolNames.push_back("UIC"); } - if (target->GetPropertyAsBool("AUTORCC")) { + if (rccEnabled) { toolNames.push_back("RCC"); } @@ -770,6 +603,24 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( autogenComment = "Automatic " + tools + " for target " + target->GetName(); } + // Create autogen target build directory and add it to the clean files + cmSystemTools::MakeDirectory(autogenBuildDir); + makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", + autogenBuildDir.c_str(), false); + + // Create autogen target includes directory and + // add it to the origin target INCLUDE_DIRECTORIES + if (mocEnabled || uicEnabled) { + const std::string incsDir = autogenBuildDir + "include"; + cmSystemTools::MakeDirectory(incsDir); + target->AddIncludeDirectory(incsDir, true); + } + + // Register moc compilation file as generated + if (mocEnabled) { + autogenProvides.push_back(autogenBuildDir + "moc_compilation.cpp"); + } + #if defined(_WIN32) && !defined(__CYGWIN__) bool usePRE_BUILD = false; cmGlobalGenerator* gg = lg->GetGlobalGenerator(); @@ -781,65 +632,100 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( // This also works around a VS 11 bug that may skip updating the target: // https://connect.microsoft.com/VisualStudio/feedback/details/769495 usePRE_BUILD = vsgg->GetVersion() >= cmGlobalVisualStudioGenerator::VS7; - if (usePRE_BUILD) { - // If the autogen target depends on an other target - // don't use PRE_BUILD - for (std::vector<std::string>::iterator it = depends.begin(); - it != depends.end(); ++it) { - if (!makefile->FindTargetToUse(it->c_str())) { - usePRE_BUILD = false; - break; - } - } - } } #endif - if (target->GetPropertyAsBool("AUTORCC")) { + // Initialize autogen target dependencies + if (const char* deps = target->GetProperty("AUTOGEN_TARGET_DEPENDS")) { + cmSystemTools::ExpandListArgument(deps, autogenDepends); + } + // Add link library targets to the autogen dependencies + { + const cmTarget::LinkLibraryVectorType& libVec = + target->Target->GetOriginalLinkLibraries(); + for (cmTarget::LinkLibraryVectorType::const_iterator it = libVec.begin(); + it != libVec.end(); ++it) { + const std::string& libName = it->first; + if (makefile->FindTargetToUse(libName) != CM_NULLPTR) { + autogenDepends.push_back(libName); + } + } + } + { cmFilePathChecksum fpathCheckSum(makefile); + // Iterate over all source files std::vector<cmSourceFile*> srcFiles; target->GetConfigCommonSourceFiles(srcFiles); for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; - if (sf->GetExtension() == "qrc" && - !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) && - !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) { - { + if (!PropertyEnabled(sf, "SKIP_AUTOGEN")) { + const std::string ext = sf->GetExtension(); + // Add generated file that will be scanned by moc or uic to + // the dependencies + if (mocEnabled || uicEnabled) { + const cmSystemTools::FileFormat fileType = + cmSystemTools::GetFileFormat(ext.c_str()); + if ((fileType == cmSystemTools::CXX_FILE_FORMAT) || + (fileType == cmSystemTools::HEADER_FILE_FORMAT)) { + if (PropertyEnabled(sf, "GENERATED")) { + if ((mocEnabled && !PropertyEnabled(sf, "SKIP_AUTOMOC")) || + (uicEnabled && !PropertyEnabled(sf, "SKIP_AUTOUIC"))) { + autogenDepends.push_back( + cmsys::SystemTools::GetRealPath(sf->GetFullPath())); +#if defined(_WIN32) && !defined(__CYGWIN__) + // Cannot use PRE_BUILD with generated files + usePRE_BUILD = false; +#endif + } + } + } + } + // Process rcc enabled files + if (rccEnabled && (ext == "qrc") && + !PropertyEnabled(sf, "SKIP_AUTORCC")) { const std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - // Run cmake again when .qrc file changes - makefile->AddCMakeDependFile(absFile); - - std::string rccOutputFile = autogenBuildDir; - rccOutputFile += fpathCheckSum.getPart(absFile); - rccOutputFile += "/qrc_"; - rccOutputFile += - cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile); - rccOutputFile += ".cpp"; - - // Add rcc output file to origin target sources - cmSourceFile* gf = makefile->GetOrCreateSource(rccOutputFile, true); - gf->SetProperty("SKIP_AUTOGEN", "On"); - target->AddSource(rccOutputFile); - // Register rcc output file as generated - autogenOutputFiles.push_back(rccOutputFile); - } - if (lg->GetGlobalGenerator()->GetName() == "Ninja" -#if defined(_WIN32) && !defined(__CYGWIN__) - || usePRE_BUILD -#endif - ) { - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - RccListInputs(qtMajorVersion, sf, target, depends); + // Compose rcc output file name + { + std::string rccOut = autogenBuildDir; + rccOut += fpathCheckSum.getPart(absFile); + rccOut += "/qrc_"; + rccOut += + cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile); + rccOut += ".cpp"; + + // Register rcc output file as generated + autogenProvides.push_back(rccOut); + + // Add rcc output file to origin target sources + cmSourceFile* gf = makefile->GetOrCreateSource(rccOut, true); + gf->SetProperty("SKIP_AUTOGEN", "On"); + target->AddSource(rccOut); + } + + if (PropertyEnabled(sf, "GENERATED")) { + // Add generated qrc file to the dependencies + autogenDepends.push_back(absFile); + } else { + // Run cmake again when .qrc file changes + makefile->AddCMakeDependFile(absFile); + + // Add the qrc input files to the dependencies + std::string error; + if (!cmQtAutoGeneratorCommon::RccListInputs( + qtMajorVersion, rccCommand, absFile, autogenDepends, + &error)) { + cmSystemTools::Error(error.c_str()); + } + } #if defined(_WIN32) && !defined(__CYGWIN__) - // Cannot use PRE_BUILD because the resource files themselves - // may not be sources within the target so VS may not know the - // target needs to re-build at all. - usePRE_BUILD = false; + // Cannot use PRE_BUILD because the resource files themselves + // may not be sources within the target so VS may not know the + // target needs to re-build at all. + usePRE_BUILD = false; #endif - } } } } @@ -847,12 +733,21 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( #if defined(_WIN32) && !defined(__CYGWIN__) if (usePRE_BUILD) { + // If the autogen target depends on an other target don't use PRE_BUILD + for (std::vector<std::string>::iterator it = autogenDepends.begin(); + it != autogenDepends.end(); ++it) { + if (makefile->FindTargetToUse(*it) != CM_NULLPTR) { + usePRE_BUILD = false; + break; + } + } + } + if (usePRE_BUILD) { // Add the pre-build command directly to bypass the OBJECT_LIBRARY // rejection in cmMakefile::AddCustomCommandToTarget because we know // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. std::vector<std::string> no_output; - std::vector<std::string> no_byproducts; - cmCustomCommand cc(makefile, no_output, no_byproducts, depends, + cmCustomCommand cc(makefile, no_output, autogenProvides, autogenDepends, commandLines, autogenComment.c_str(), workingDirectory.c_str()); cc.SetEscapeOldStyle(false); @@ -863,7 +758,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( { cmTarget* autogenTarget = makefile->AddUtilityCommand( autogenTargetName, true, workingDirectory.c_str(), - /*byproducts=*/autogenOutputFiles, depends, commandLines, false, + /*byproducts=*/autogenProvides, autogenDepends, commandLines, false, autogenComment.c_str()); cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg); @@ -900,38 +795,37 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( std::map<std::string, std::string> configMocDefines; std::map<std::string, std::string> configUicOptions; { - // create a custom target for running generators at buildtime: + const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC"); + const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC"); + const bool rccEnabled = target->GetPropertyAsBool("AUTORCC"); const std::string autogenTargetName = GetAutogenTargetName(target); const std::string qtMajorVersion = GetQtMajorVersion(target); - AddDefinitionEscaped(makefile, "_autogen_target_name", autogenTargetName); - AddDefinitionEscaped(makefile, "_origin_target_name", target->GetName()); - AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion); - std::vector<std::string> _sources; std::vector<std::string> _headers; - std::vector<std::string> mocSkipList; - std::vector<std::string> uicSkipList; - if (target->GetPropertyAsBool("AUTOMOC") || - target->GetPropertyAsBool("AUTOUIC") || - target->GetPropertyAsBool("AUTORCC")) { - SetupSourceFiles(target, _sources, _headers, mocSkipList, uicSkipList); + if (mocEnabled || uicEnabled || rccEnabled) { + std::vector<std::string> mocSkipList; + std::vector<std::string> uicSkipList; + AcquireScanFiles(target, _sources, _headers, mocSkipList, uicSkipList); + if (mocEnabled) { + MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, + mocSkipList, configMocIncludes, configMocDefines); + } + if (uicEnabled) { + UicSetupAutoTarget(target, qtMajorVersion, uicSkipList, + configUicOptions); + } + if (rccEnabled) { + RccSetupAutoTarget(target, qtMajorVersion); + } } + + AddDefinitionEscaped(makefile, "_autogen_target_name", autogenTargetName); + AddDefinitionEscaped(makefile, "_origin_target_name", target->GetName()); + AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion); AddDefinitionEscaped(makefile, "_sources", _sources); AddDefinitionEscaped(makefile, "_headers", _headers); - - if (target->GetPropertyAsBool("AUTOMOC")) { - MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, - mocSkipList, configMocIncludes, configMocDefines); - } - if (target->GetPropertyAsBool("AUTOUIC")) { - UicSetupAutoTarget(target, qtMajorVersion, uicSkipList, - configUicOptions); - } - if (target->GetPropertyAsBool("AUTORCC")) { - RccSetupAutoTarget(target, qtMajorVersion); - } } // Generate config file diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index c83f9a9..246dd8d 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1,6 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGenerators.h" +#include "cmQtAutoGeneratorCommon.h" #include <algorithm> #include <assert.h> @@ -36,23 +37,9 @@ static const char* SettingsKeyRcc = "AM_RCC_OLD_SETTINGS"; // -- Static functions -/** - * @brief Returns a the string escaped and enclosed in quotes - */ -static std::string Quoted(const std::string& text) +inline static std::string Quoted(const std::string& text) { - static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", - "\b", "\\b", "\f", "\\f", "\n", "\\n", - "\r", "\\r", "\t", "\\t", "\v", "\\v" }; - - std::string res = text; - for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep); - it += 2) { - cmSystemTools::ReplaceString(res, *it, *(it + 1)); - } - res = '"' + res; - res += '"'; - return res; + return cmQtAutoGeneratorCommon::Quoted(text); } static void InfoGet(cmMakefile* makefile, const char* key, std::string& value) @@ -138,13 +125,19 @@ static bool FileNameIsUnique(const std::string& filePath, return true; } -static std::string ReadAll(const std::string& filename) +static bool ReadAll(std::string& content, const std::string& filename) { - cmsys::ifstream file(filename.c_str()); - std::ostringstream stream; - stream << file.rdbuf(); - file.close(); - return stream.str(); + bool success = false; + { + cmsys::ifstream ifs(filename.c_str()); + if (ifs) { + std::ostringstream osst; + osst << ifs.rdbuf(); + content = osst.str(); + success = true; + } + } + return success; } /** @@ -178,7 +171,7 @@ static std::string JoinOptionsMap( for (std::map<std::string, std::string>::const_iterator it = opts.begin(); it != opts.end(); ++it) { if (it != opts.begin()) { - result += "@list_sep@"; + result += cmQtAutoGeneratorCommon::listSep; } result += it->first; result += "==="; @@ -402,7 +395,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } else { this->LogError( "AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not " - "a multiple of 2"); + "a multiple of 2 in:\n" + + Quoted(filename)); return false; } } @@ -424,13 +418,14 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( fileIt = uicFilesVec.begin(), optionIt = uicOptionsVec.begin(); fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) { - cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); + cmSystemTools::ReplaceString(*optionIt, + cmQtAutoGeneratorCommon::listSep, ";"); this->UicOptions[*fileIt] = *optionIt; } } else { this->LogError( - "AutoGen: Error: Uic files/options lists size missmatch in: " + - filename); + "AutoGen: Error: Uic files/options lists size missmatch in:\n" + + Quoted(filename)); return false; } } @@ -439,47 +434,53 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // - Rcc if (this->RccEnabled()) { InfoGet(makefile, "AM_RCC_SOURCES", this->RccSources); + // File options { std::vector<std::string> rccFilesVec; std::vector<std::string> rccOptionsVec; InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec); InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec); - if (rccFilesVec.size() != rccOptionsVec.size()) { + if (rccFilesVec.size() == rccOptionsVec.size()) { + for (std::vector<std::string>::iterator + fileIt = rccFilesVec.begin(), + optionIt = rccOptionsVec.begin(); + fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) { + // Replace item separator + cmSystemTools::ReplaceString(*optionIt, + cmQtAutoGeneratorCommon::listSep, ";"); + this->RccOptions[*fileIt] = *optionIt; + } + } else { this->LogError( - "AutoGen: Error: RCC files/options lists size missmatch in: " + - filename); + "AutoGen: Error: RCC files/options lists size missmatch in:\n" + + Quoted(filename)); return false; } - for (std::vector<std::string>::iterator fileIt = rccFilesVec.begin(), - optionIt = rccOptionsVec.begin(); - fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) { - cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); - this->RccOptions[*fileIt] = *optionIt; - } } + // File lists { std::vector<std::string> rccInputLists; InfoGet(makefile, "AM_RCC_INPUTS", rccInputLists); - - // qrc files in the end of the list may have been empty - if (rccInputLists.size() < this->RccSources.size()) { - rccInputLists.resize(this->RccSources.size()); - } - if (this->RccSources.size() != rccInputLists.size()) { + if (this->RccSources.size() == rccInputLists.size()) { + for (std::vector<std::string>::iterator + fileIt = this->RccSources.begin(), + inputIt = rccInputLists.begin(); + fileIt != this->RccSources.end(); ++fileIt, ++inputIt) { + // Remove braces + *inputIt = inputIt->substr(1, inputIt->size() - 2); + // Replace item separator + cmSystemTools::ReplaceString(*inputIt, + cmQtAutoGeneratorCommon::listSep, ";"); + std::vector<std::string> rccInputFiles; + cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles); + this->RccInputs[*fileIt] = rccInputFiles; + } + } else { this->LogError( - "AutoGen: Error: RCC sources/inputs lists size missmatch in: " + - filename); + "AutoGen: Error: RCC sources/inputs lists size missmatch in:\n" + + Quoted(filename)); return false; } - for (std::vector<std::string>::iterator - fileIt = this->RccSources.begin(), - inputIt = rccInputLists.begin(); - fileIt != this->RccSources.end(); ++fileIt, ++inputIt) { - cmSystemTools::ReplaceString(*inputIt, "@list_sep@", ";"); - std::vector<std::string> rccInputFiles; - cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles); - this->RccInputs[*fileIt] = rccInputFiles; - } } } @@ -687,8 +688,10 @@ bool cmQtAutoGenerators::RunAutogen() uicHeaderFiles.insert(headerName); } } - this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded, - mocsNotIncluded, mocDepends, uisIncluded); + if (!this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded, + mocsNotIncluded, mocDepends, uisIncluded)) { + return false; + }; // Generate files if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded, mocDepends)) { @@ -804,23 +807,29 @@ bool cmQtAutoGenerators::ParseSourceFile( std::map<std::string, std::set<std::string> >& mocDepends, std::map<std::string, std::vector<std::string> >& uisIncluded, bool relaxed) { - bool success = true; - const std::string contentText = ReadAll(absFilename); - if (contentText.empty()) { - std::ostringstream ost; - ost << "AutoGen: Warning: " << absFilename << "\n" - << "The file is empty\n"; - this->LogWarning(ost.str()); - } else { - // Parse source contents for MOC - if (success && !this->MocSkip(absFilename)) { - success = this->MocParseSourceContent(absFilename, contentText, - mocsIncluded, mocDepends, relaxed); - } - // Parse source contents for UIC - if (success && !this->UicSkip(absFilename)) { - this->UicParseContent(absFilename, contentText, uisIncluded); + std::string contentText; + bool success = ReadAll(contentText, absFilename); + if (success) { + if (!contentText.empty()) { + // Parse source contents for MOC + if (success && !this->MocSkip(absFilename)) { + success = this->MocParseSourceContent( + absFilename, contentText, mocsIncluded, mocDepends, relaxed); + } + // Parse source contents for UIC + if (success && !this->UicSkip(absFilename)) { + this->UicParseContent(absFilename, contentText, uisIncluded); + } + } else { + std::ostringstream ost; + ost << "AutoGen: Warning: The file is empty:\n" + << Quoted(absFilename) << "\n"; + this->LogWarning(ost.str()); } + } else { + std::ostringstream ost; + ost << "AutoGen: Error: Could not read file:\n" << Quoted(absFilename); + this->LogError(ost.str()); } return success; } @@ -1083,7 +1092,7 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( } } -void cmQtAutoGenerators::ParseHeaders( +bool cmQtAutoGenerators::ParseHeaders( const std::set<std::string>& mocHeaderFiles, const std::set<std::string>& uicHeaderFiles, const std::map<std::string, std::string>& mocsIncluded, @@ -1091,6 +1100,7 @@ void cmQtAutoGenerators::ParseHeaders( std::map<std::string, std::set<std::string> >& mocDepends, std::map<std::string, std::vector<std::string> >& uisIncluded) { + bool success = true; // Merged header files list to read files only once std::set<std::string> headerFiles; headerFiles.insert(mocHeaderFiles.begin(), mocHeaderFiles.end()); @@ -1099,20 +1109,28 @@ void cmQtAutoGenerators::ParseHeaders( for (std::set<std::string>::const_iterator hIt = headerFiles.begin(); hIt != headerFiles.end(); ++hIt) { const std::string& headerName = *hIt; - const std::string contentText = ReadAll(headerName); - - // Parse header content for MOC - if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) && - (mocsIncluded.find(headerName) == mocsIncluded.end())) { - this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded, - mocDepends); - } - - // Parse header content for UIC - if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) { - this->UicParseContent(headerName, contentText, uisIncluded); + std::string contentText; + if (ReadAll(contentText, headerName)) { + // Parse header content for MOC + if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) && + (mocsIncluded.find(headerName) == mocsIncluded.end())) { + this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded, + mocDepends); + } + // Parse header content for UIC + if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) { + this->UicParseContent(headerName, contentText, uisIncluded); + } + } else { + std::ostringstream ost; + ost << "AutoGen: Error: Could not read header file:\n" + << Quoted(headerName); + this->LogError(ost.str()); + success = false; + break; } } + return success; } bool cmQtAutoGenerators::MocGenerateAll( @@ -1195,8 +1213,12 @@ bool cmQtAutoGenerators::MocGenerateAll( // Check if the content of moc_compilation.cpp changed { - const std::string oldContents = ReadAll(this->MocCppFilenameAbs); - mocCompChanged = (oldContents != automocSource); + std::string oldContents; + if (ReadAll(oldContents, this->MocCppFilenameAbs)) { + mocCompChanged = (oldContents != automocSource); + } else { + mocCompChanged = true; + } } bool success = true; @@ -1290,18 +1312,12 @@ bool cmQtAutoGenerators::MocGenerateFile( cmd.push_back(mocFileAbs); cmd.push_back(sourceFile); - // Log moc command - if (this->Verbose) { - this->LogCommand(cmd); - } - // Execute moc command - bool res = false; - int retVal = 0; std::string output; - res = cmSystemTools::RunSingleCommand(cmd, &output, &output, &retVal); - - if (!res || (retVal != 0)) { + if (this->RunCommand(cmd, output)) { + // Success + mocGenerated = true; + } else { // Command failed { std::ostringstream ost; @@ -1313,9 +1329,6 @@ bool cmQtAutoGenerators::MocGenerateFile( } cmSystemTools::RemoveFile(mocFileAbs); this->RunMocFailed = true; - } else { - // Success - mocGenerated = true; } } else { // Parent directory creation failed @@ -1470,18 +1483,11 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, cmd.push_back(uicFileAbs); cmd.push_back(uiInputFile); - // Log command - if (this->Verbose) { - this->LogCommand(cmd); - } - - // Execute command - bool res = false; - int retVal = 0; std::string output; - res = cmSystemTools::RunSingleCommand(cmd, &output, &output, &retVal); - - if (!res || (retVal != 0)) { + if (this->RunCommand(cmd, output)) { + // Success + uicGenerated = true; + } else { // Command failed { std::ostringstream ost; @@ -1494,9 +1500,6 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, } cmSystemTools::RemoveFile(uicFileAbs); this->RunUicFailed = true; - } else { - // Success - uicGenerated = true; } } else { // Parent directory creation failed @@ -1566,13 +1569,30 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, // Test if the resources list file is newer than build file generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile); if (!generateRcc) { - // Test if any resource file is newer than the build file - const std::vector<std::string>& files = this->RccInputs[rccInputFile]; - for (std::vector<std::string>::const_iterator it = files.begin(); - it != files.end(); ++it) { - if (FileAbsentOrOlder(rccBuildFile, *it)) { - generateRcc = true; - break; + // Acquire input file list + std::vector<std::string> readFiles; + const std::vector<std::string>* files = &this->RccInputs[rccInputFile]; + if (files->empty()) { + // Read input file list from qrc file + std::string error; + if (cmQtAutoGeneratorCommon::RccListInputs( + this->QtMajorVersion, this->RccExecutable, rccInputFile, + readFiles, &error)) { + files = &readFiles; + } else { + files = CM_NULLPTR; + this->LogError(error); + this->RunRccFailed = true; + } + } + // Test if any input file is newer than the build file + if (files != CM_NULLPTR) { + for (std::vector<std::string>::const_iterator it = files->begin(); + it != files->end(); ++it) { + if (FileAbsentOrOlder(rccBuildFile, *it)) { + generateRcc = true; + break; + } } } } @@ -1610,17 +1630,11 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, cmd.push_back(rccBuildFile); cmd.push_back(rccInputFile); - // Log command - if (this->Verbose) { - this->LogCommand(cmd); - } - - // Execute command - bool res = false; - int retVal = 0; std::string output; - res = cmSystemTools::RunSingleCommand(cmd, &output, &output, &retVal); - if (!res || (retVal != 0)) { + if (this->RunCommand(cmd, output)) { + // Success + rccGenerated = true; + } else { // Command failed { std::ostringstream ost; @@ -1632,9 +1646,6 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, } cmSystemTools::RemoveFile(rccBuildFile); this->RunRccFailed = true; - } else { - // Success - rccGenerated = true; } } else { // Parent directory creation failed @@ -1712,7 +1723,18 @@ void cmQtAutoGenerators::LogError(const std::string& message) const void cmQtAutoGenerators::LogCommand( const std::vector<std::string>& command) const { - this->LogInfo(cmJoin(command, " ")); + std::vector<std::string> cmdEscaped; + typedef std::vector<std::string>::const_iterator Iter; + for (Iter cit = command.begin(); cit != command.end(); ++cit) { + const std::string cesc = Quoted(*cit); + if ((cesc.size() > (cit->size() + 2)) || + (cesc.find(' ') != std::string::npos)) { + cmdEscaped.push_back(cesc); + } else { + cmdEscaped.push_back(*cit); + } + } + this->LogInfo(cmJoin(cmdEscaped, " ")); } /** @@ -1762,6 +1784,41 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile, } /** + * @brief Generates the parent directory of the given file on demand + * @return True on success + */ +bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) const +{ + bool success = true; + const std::string dirName = cmSystemTools::GetFilenamePath(filename); + if (!dirName.empty()) { + success = cmsys::SystemTools::MakeDirectory(dirName); + if (!success) { + this->LogError("AutoGen: Error: Directory creation failed: " + dirName); + } + } + return success; +} + +/** + * @brief Runs a command and returns true on success + * @return True on success + */ +bool cmQtAutoGenerators::RunCommand(const std::vector<std::string>& command, + std::string& output) const +{ + // Log command + if (this->Verbose) { + this->LogCommand(command); + } + // Execute command + int retVal = 0; + bool res = + cmSystemTools::RunSingleCommand(command, &output, &output, &retVal); + return (res && (retVal == 0)); +} + +/** * @brief Tries to find the header file to the given file base path by * appending different header extensions * @return True on success @@ -1835,20 +1892,3 @@ bool cmQtAutoGenerators::MocFindIncludedFile( } return success; } - -/** - * @brief Generates the parent directory of the given file on demand - * @return True on success - */ -bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) const -{ - bool success = true; - const std::string dirName = cmSystemTools::GetFilenamePath(filename); - if (!dirName.empty()) { - success = cmsys::SystemTools::MakeDirectory(dirName); - if (!success) { - this->LogError("AutoGen: Error: Directory creation failed: " + dirName); - } - } - return success; -} diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 3bff2b2..ee046de 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -78,7 +78,7 @@ private: std::set<std::string>& mocHeaderFiles, std::set<std::string>& uicHeaderFiles) const; - void ParseHeaders( + bool ParseHeaders( const std::set<std::string>& mocHeaderFiles, const std::set<std::string>& uicHeaderFiles, const std::map<std::string, std::string>& mocsIncluded, @@ -142,6 +142,8 @@ private: const char* basePrefix, const char* baseSuffix) const; bool MakeParentDirectory(const std::string& filename) const; + bool RunCommand(const std::vector<std::string>& command, + std::string& output) const; bool FindHeader(std::string& header, const std::string& testBasePath) const; diff --git a/Source/cmStateTypes.h b/Source/cmStateTypes.h index 2c974c1..da14cdb 100644 --- a/Source/cmStateTypes.h +++ b/Source/cmStateTypes.h @@ -27,6 +27,9 @@ enum SnapshotType VariableScopeType }; +// There are multiple overlapping ranges represented here. Be aware that adding +// a value to this enumeration may cause failures in numerous places which +// assume details about the ordering. enum TargetType { EXECUTABLE, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index c360c19..e3c7b63 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -230,6 +230,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("INSTALL_NAME_DIR", CM_NULLPTR); this->SetPropertyDefault("INSTALL_RPATH", ""); this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF"); + this->SetPropertyDefault("INTERPROCEDURAL_OPTIMIZATION", CM_NULLPTR); this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF"); this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF"); this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", CM_NULLPTR); diff --git a/Source/cmVS10CudaFlagTable.h b/Source/cmVS10CudaFlagTable.h new file mode 100644 index 0000000..da19d64 --- /dev/null +++ b/Source/cmVS10CudaFlagTable.h @@ -0,0 +1,51 @@ +static cmVS7FlagTable cmVS10CudaFlagTable[] = { + // Collect options meant for the host compiler. + { "AdditionalCompilerOptions", "Xcompiler=", "Host compiler options", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SpaceAppendable }, + { "AdditionalCompilerOptions", "Xcompiler", "Host compiler options", "", + cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SpaceAppendable }, + + // Select the CUDA runtime library. + { "CudaRuntime", "cudart=none", "No CUDA runtime library", "None", 0 }, + { "CudaRuntime", "cudart=shared", "Shared/dynamic CUDA runtime library", + "Shared", 0 }, + { "CudaRuntime", "cudart=static", "Static CUDA runtime library", "Static", + 0 }, + { "CudaRuntime", "cudart", "CUDA runtime library", "", + cmVS7FlagTable::UserFollowing }, + + // Capture arch/code arguments into temporaries for post-processing. + { "cmake-temp-gencode", "gencode=", "", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "cmake-temp-gencode", "gencode", "", "", + cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable }, + { "cmake-temp-gencode", "-generate-code=", "", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "cmake-temp-gencode", "-generate-code", "", "", + cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable }, + + { "cmake-temp-code", "code=", "", "", cmVS7FlagTable::UserValue }, + { "cmake-temp-code", "code", "", "", cmVS7FlagTable::UserFollowing }, + { "cmake-temp-code", "-gpu-code=", "", "", cmVS7FlagTable::UserValue }, + { "cmake-temp-code", "-gpu-code", "", "", cmVS7FlagTable::UserFollowing }, + + { "cmake-temp-arch", "arch=", "", "", cmVS7FlagTable::UserValue }, + { "cmake-temp-arch", "arch", "", "", cmVS7FlagTable::UserFollowing }, + { "cmake-temp-arch", "-gpu-architecture=", "", "", + cmVS7FlagTable::UserValue }, + { "cmake-temp-arch", "-gpu-architecture", "", "", + cmVS7FlagTable::UserFollowing }, + + // Other flags. + + { "FastMath", "use_fast_math", "", "true", 0 }, + { "FastMath", "-use_fast_math", "", "true", 0 }, + + { "GPUDebugInfo", "G", "", "true", 0 }, + { "GPUDebugInfo", "-device-debug", "", "true", 0 }, + + { "HostDebugInfo", "g", "", "true", 0 }, + { "HostDebugInfo", "-debug", "", "true", 0 }, + + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVS10CudaHostFlagTable.h b/Source/cmVS10CudaHostFlagTable.h new file mode 100644 index 0000000..5b61066 --- /dev/null +++ b/Source/cmVS10CudaHostFlagTable.h @@ -0,0 +1,35 @@ +static cmVS7FlagTable cmVS10CudaHostFlagTable[] = { + //{"Optimization", "", "<inherit from host>", "InheritFromHost", 0}, + { "Optimization", "Od", "Disabled", "Od", 0 }, + { "Optimization", "O1", "Minimize Size", "O1", 0 }, + { "Optimization", "O2", "Maximize Speed", "O2", 0 }, + { "Optimization", "Ox", "Full Optimization", "O3", 0 }, + + //{"Runtime", "", "<inherit from host>", "InheritFromHost", 0}, + { "Runtime", "MT", "Multi-Threaded", "MT", 0 }, + { "Runtime", "MTd", "Multi-Threaded Debug", "MTd", 0 }, + { "Runtime", "MD", "Multi-Threaded DLL", "MD", 0 }, + { "Runtime", "MDd", "Multi-threaded Debug DLL", "MDd", 0 }, + { "Runtime", "ML", "Single-Threaded", "ML", 0 }, + { "Runtime", "MLd", "Single-Threaded Debug", "MLd", 0 }, + + //{"RuntimeChecks", "", "<inherit from host>", "InheritFromHost", 0}, + //{"RuntimeChecks", "", "Default", "Default", 0}, + { "RuntimeChecks", "RTCs", "Stack Frames", "RTCs", 0 }, + { "RuntimeChecks", "RTCu", "Uninitialized Variables", "RTCu", 0 }, + { "RuntimeChecks", "RTC1", "Both", "RTC1", 0 }, + + //{"TypeInfo", "", "<inherit from host>", "InheritFromHost", 0}, + { "TypeInfo", "GR", "Yes", "true", 0 }, + { "TypeInfo", "GR-", "No", "false", 0 }, + + //{"Warning", "", "<inherit from host>", "InheritFromHost", 0}, + { "Warning", "W0", "Off: Turn Off All Warnings", "W0", 0 }, + { "Warning", "W1", "Level 1", "W1", 0 }, + { "Warning", "W2", "Level 2", "W2", 0 }, + { "Warning", "W3", "Level 3", "W3", 0 }, + { "Warning", "W4", "Level 4", "W4", 0 }, + { "Warning", "Wall", "Enable All Warnings", "Wall", 0 }, + + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index fbf7447..052cc7f 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -112,6 +112,10 @@ cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() i != this->LinkOptions.end(); ++i) { delete i->second; } + for (OptionsMap::iterator i = this->CudaOptions.begin(); + i != this->CudaOptions.end(); ++i) { + delete i->second; + } if (!this->BuildFileStream) { return; } @@ -206,6 +210,9 @@ void cmVisualStudio10TargetGenerator::Generate() if (!this->ComputeRcOptions()) { return; } + if (!this->ComputeCudaOptions()) { + return; + } if (!this->ComputeMasmOptions()) { return; } @@ -454,6 +461,14 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1); } this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1); + if (this->GlobalGenerator->IsCudaEnabled()) { + this->WriteString("<Import Project=\"$(VCTargetsPath)\\" + "BuildCustomizations\\CUDA ", + 2); + (*this->BuildFileStream) + << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString()) + << ".props\" />\n"; + } if (this->GlobalGenerator->IsMasmEnabled()) { this->WriteString("<Import Project=\"$(VCTargetsPath)\\" "BuildCustomizations\\masm.props\" />\n", @@ -524,6 +539,14 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteTargetSpecificReferences(); this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1); this->WriteTargetsFileReferences(); + if (this->GlobalGenerator->IsCudaEnabled()) { + this->WriteString("<Import Project=\"$(VCTargetsPath)\\" + "BuildCustomizations\\CUDA ", + 2); + (*this->BuildFileStream) + << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString()) + << ".targets\" />\n"; + } if (this->GlobalGenerator->IsMasmEnabled()) { this->WriteString("<Import Project=\"$(VCTargetsPath)\\" "BuildCustomizations\\masm.targets\" />\n", @@ -1694,8 +1717,10 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool, // // and fail if this exceeds the maximum allowed path length. Our path // conversion uses full paths when possible to allow deeper trees. - bool forceRelative = false; - std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false); + // However, CUDA 8.0 msbuild rules fail on absolute paths so for CUDA + // we must use relative paths. + bool forceRelative = sf->GetLanguage() == "CUDA"; + std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative); if (this->LocalGenerator->GetVersion() == cmGlobalVisualStudioGenerator::VS10 && cmSystemTools::FileIsFullPath(sourceFile.c_str())) { @@ -1772,6 +1797,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() tool = "ResourceCompile"; } else if (lang == "CSharp") { tool = "Compile"; + } else if (lang == "CUDA" && this->GlobalGenerator->IsCudaEnabled()) { + tool = "CudaCompile"; } if (!tool.empty()) { @@ -1841,10 +1868,9 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\" />\n"; } - if (cmSourceFile const* defsrc = - this->GeneratorTarget->GetModuleDefinitionFile("")) { - this->WriteSource("None", defsrc); - } + std::vector<cmSourceFile const*> defSources; + this->GeneratorTarget->GetModuleDefinitionSources(defSources, ""); + this->WriteSources("None", defSources); if (this->IsMissingFiles) { this->WriteMissingFiles(); @@ -2208,8 +2234,10 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( if (linkLanguage == "CXX") { clOptions.AddFlag("CompileAs", "CompileAsCpp"); } - this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, - linkLanguage, configName.c_str()); + if (linkLanguage != "CUDA") { + this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, + linkLanguage, configName.c_str()); + } // Get preprocessor definitions for this directory. std::string defineFlags = @@ -2401,6 +2429,99 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions( this->WriteString("</ResourceCompile>\n", 2); } +bool cmVisualStudio10TargetGenerator::ComputeCudaOptions() +{ + if (!this->GlobalGenerator->IsCudaEnabled()) { + return true; + } + for (std::vector<std::string>::const_iterator i = + this->Configurations.begin(); + i != this->Configurations.end(); ++i) { + if (!this->ComputeCudaOptions(*i)) { + return false; + } + } + return true; +} + +bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( + std::string const& configName) +{ + cmGlobalVisualStudio10Generator* gg = + static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + CM_AUTO_PTR<Options> pOptions(new Options( + this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable())); + Options& cudaOptions = *pOptions; + + // Get compile flags for CUDA in this directory. + std::string CONFIG = cmSystemTools::UpperCase(configName); + std::string configFlagsVar = std::string("CMAKE_CUDA_FLAGS_") + CONFIG; + std::string flags = + std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) + + std::string(" ") + + std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + + // Get preprocessor definitions for this directory. + std::string defineFlags = + this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags(); + + cudaOptions.Parse(flags.c_str()); + cudaOptions.Parse(defineFlags.c_str()); + cudaOptions.ParseFinish(); + + if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) { + cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true"); + } + + // Convert the host compiler options to the toolset's abstractions + // using a secondary flag table. + cudaOptions.ClearTables(); + cudaOptions.AddTable(gg->GetCudaHostFlagTable()); + cudaOptions.Reparse("AdditionalCompilerOptions"); + + // `CUDA 8.0.targets` places these before nvcc! Just drop whatever + // did not parse and hope it works. + cudaOptions.RemoveFlag("AdditionalCompilerOptions"); + + cudaOptions.FixCudaCodeGeneration(); + + std::vector<std::string> targetDefines; + this->GeneratorTarget->GetCompileDefinitions(targetDefines, + configName.c_str(), "CUDA"); + cudaOptions.AddDefines(targetDefines); + + // Add a definition for the configuration name. + std::string configDefine = "CMAKE_INTDIR=\""; + configDefine += configName; + configDefine += "\""; + cudaOptions.AddDefine(configDefine); + if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) { + cudaOptions.AddDefine(exportMacro); + } + + this->CudaOptions[configName] = pOptions.release(); + return true; +} + +void cmVisualStudio10TargetGenerator::WriteCudaOptions( + std::string const& configName, std::vector<std::string> const& includes) +{ + if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) { + return; + } + this->WriteString("<CudaCompile>\n", 2); + + Options& cudaOptions = *(this->CudaOptions[configName]); + cudaOptions.AppendFlag("Include", includes); + cudaOptions.AppendFlag("Include", "%(Include)"); + cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", + "\n", "CUDA"); + cudaOptions.PrependInheritedString("AdditionalOptions"); + cudaOptions.OutputFlagMap(*this->BuildFileStream, " "); + + this->WriteString("</CudaCompile>\n", 2); +} + bool cmVisualStudio10TargetGenerator::ComputeMasmOptions() { if (!this->GlobalGenerator->IsMasmEnabled()) { @@ -2739,8 +2860,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), 0, this)); Options& linkOptions = *pOptions; - const std::string& linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(config.c_str()); + cmGeneratorTarget::LinkClosure const* linkClosure = + this->GeneratorTarget->GetLinkClosure(config); + + const std::string& linkLanguage = linkClosure->LinkerLanguage; if (linkLanguage.empty()) { cmSystemTools::Error( "CMake can not determine linker language for target: ", @@ -2795,6 +2918,19 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( std::vector<std::string> libVec; std::vector<std::string> vsTargetVec; this->AddLibraries(cli, libVec, vsTargetVec); + if (std::find(linkClosure->Languages.begin(), linkClosure->Languages.end(), + "CUDA") != linkClosure->Languages.end()) { + switch (this->CudaOptions[config]->GetCudaRuntime()) { + case cmVisualStudioGeneratorOptions::CudaRuntimeStatic: + libVec.push_back("cudart_static.lib"); + break; + case cmVisualStudioGeneratorOptions::CudaRuntimeShared: + libVec.push_back("cudart.lib"); + break; + case cmVisualStudioGeneratorOptions::CudaRuntimeNone: + break; + } + } std::string standardLibsVar = "CMAKE_"; standardLibsVar += linkLanguage; standardLibsVar += "_STANDARD_LIBRARIES"; @@ -2915,24 +3051,15 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( linkOptions.Parse(flags.c_str()); if (this->MSTools) { - if (cmSourceFile const* defsrc = - this->GeneratorTarget->GetModuleDefinitionFile("")) { - linkOptions.AddFlag("ModuleDefinitionFile", - defsrc->GetFullPath().c_str()); + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(config); + if (mdi && !mdi->DefFile.empty()) { + linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile.c_str()); } linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "%(IgnoreSpecificDefaultLibraries)"); } - if ((this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || - this->GeneratorTarget->IsExecutableWithExports()) && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (this->GeneratorTarget->GetPropertyAsBool( - "WINDOWS_EXPORT_ALL_SYMBOLS")) { - linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)exportall.def"); - } - } - // Hack to fix flag version selection in a common use case. // FIXME: Select flag table based on toolset instead of VS version. if (this->LocalGenerator->GetVersion() >= @@ -3142,6 +3269,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->WriteClOptions(*i, includes); // output rc compile flags <ResourceCompile></ResourceCompile> this->WriteRCOptions(*i, includes); + this->WriteCudaOptions(*i, includes); this->WriteMasmOptions(*i, includes); this->WriteNasmOptions(*i, includes); } @@ -3170,18 +3298,15 @@ void cmVisualStudio10TargetGenerator::WriteEvents( std::string const& configName) { bool addedPrelink = false; - if ((this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || - this->GeneratorTarget->IsExecutableWithExports()) && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (this->GeneratorTarget->GetPropertyAsBool( - "WINDOWS_EXPORT_ALL_SYMBOLS")) { - addedPrelink = true; - std::vector<cmCustomCommand> commands = - this->GeneratorTarget->GetPreLinkCommands(); - this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget, - commands, configName); - this->WriteEvent("PreLinkEvent", commands, configName); - } + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(configName); + if (mdi && mdi->WindowsExportAllSymbols) { + addedPrelink = true; + std::vector<cmCustomCommand> commands = + this->GeneratorTarget->GetPreLinkCommands(); + this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget, + commands, configName); + this->WriteEvent("PreLinkEvent", commands, configName); } if (!addedPrelink) { this->WriteEvent("PreLinkEvent", diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 0ebb4e4..52d5550 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -98,6 +98,10 @@ private: bool ComputeRcOptions(std::string const& config); void WriteRCOptions(std::string const& config, std::vector<std::string> const& includes); + bool ComputeCudaOptions(); + bool ComputeCudaOptions(std::string const& config); + void WriteCudaOptions(std::string const& config, + std::vector<std::string> const& includes); bool ComputeMasmOptions(); bool ComputeMasmOptions(std::string const& config); void WriteMasmOptions(std::string const& config, @@ -150,6 +154,7 @@ private: typedef std::map<std::string, Options*> OptionsMap; OptionsMap ClOptions; OptionsMap RcOptions; + OptionsMap CudaOptions; OptionsMap MasmOptions; OptionsMap NasmOptions; OptionsMap LinkOptions; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index dfe5ce6..1ca6b9c 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -43,6 +43,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions( this->FortranRuntimeDebug = false; this->FortranRuntimeDLL = false; this->FortranRuntimeMT = false; + + this->UnknownFlagField = "AdditionalOptions"; } cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions( @@ -67,6 +69,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions( this->FortranRuntimeDebug = false; this->FortranRuntimeDLL = false; this->FortranRuntimeMT = false; + + this->UnknownFlagField = "AdditionalOptions"; } void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table) @@ -81,6 +85,13 @@ void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table) } } +void cmVisualStudioGeneratorOptions::ClearTables() +{ + for (int i = 0; i < FlagTableCount; ++i) { + this->FlagTable[i] = CM_NULLPTR; + } +} + void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() { // Exception handling is on by default because the platform file has @@ -176,6 +187,78 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const return false; } +cmVisualStudioGeneratorOptions::CudaRuntime +cmVisualStudioGeneratorOptions::GetCudaRuntime() const +{ + std::map<std::string, FlagValue>::const_iterator i = + this->FlagMap.find("CudaRuntime"); + if (i != this->FlagMap.end() && i->second.size() == 1) { + std::string const& cudaRuntime = i->second[0]; + if (cudaRuntime == "Static") { + return CudaRuntimeStatic; + } + if (cudaRuntime == "Shared") { + return CudaRuntimeShared; + } + if (cudaRuntime == "None") { + return CudaRuntimeNone; + } + } + // nvcc default is static + return CudaRuntimeStatic; +} + +void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() +{ + // Extract temporary values stored by our flag table. + FlagValue arch = this->TakeFlag("cmake-temp-arch"); + FlagValue code = this->TakeFlag("cmake-temp-code"); + FlagValue gencode = this->TakeFlag("cmake-temp-gencode"); + + // No -code allowed without -arch. + if (arch.empty()) { + code.clear(); + } + + if (arch.empty() && gencode.empty()) { + return; + } + + // Create a CodeGeneration field with [arch],[code] syntax in each entry. + // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`. + FlagValue& result = this->FlagMap["CodeGeneration"]; + + // First entries for the -arch=<arch> [-code=<code>,...] pair. + if (!arch.empty()) { + std::string arch_name = arch[0]; + std::vector<std::string> codes; + if (!code.empty()) { + codes = cmSystemTools::tokenize(code[0], ","); + } + if (codes.empty()) { + codes.push_back(arch_name); + // nvcc -arch=<arch> has a special case that allows a real + // architecture to be specified instead of a virtual arch. + // It translates to -arch=<virtual> -code=<real>. + cmSystemTools::ReplaceString(arch_name, "sm_", "compute_"); + } + for (std::vector<std::string>::iterator ci = codes.begin(); + ci != codes.end(); ++ci) { + std::string entry = arch_name + "," + *ci; + result.push_back(entry); + } + } + + // Now add entries for the -gencode=<arch>,<code> pairs. + for (std::vector<std::string>::iterator ei = gencode.begin(); + ei != gencode.end(); ++ei) { + std::string entry = *ei; + cmSystemTools::ReplaceString(entry, "arch=", ""); + cmSystemTools::ReplaceString(entry, "code=", ""); + result.push_back(entry); + } +} + void cmVisualStudioGeneratorOptions::Parse(const char* flags) { // Parse the input string as a windows command line since the string @@ -209,6 +292,21 @@ void cmVisualStudioGeneratorOptions::ParseFinish() rl += this->FortranRuntimeDLL ? "DLL" : ""; this->FlagMap["RuntimeLibrary"] = rl; } + + if (this->CurrentTool == CudaCompiler) { + std::map<std::string, FlagValue>::iterator i = + this->FlagMap.find("CudaRuntime"); + if (i != this->FlagMap.end() && i->second.size() == 1) { + std::string& cudaRuntime = i->second[0]; + if (cudaRuntime == "static") { + cudaRuntime = "Static"; + } else if (cudaRuntime == "shared") { + cudaRuntime = "Shared"; + } else if (cudaRuntime == "none") { + cudaRuntime = "None"; + } + } + } } void cmVisualStudioGeneratorOptions::PrependInheritedString( @@ -222,6 +320,18 @@ void cmVisualStudioGeneratorOptions::PrependInheritedString( value = "%(" + key + ") " + value; } +void cmVisualStudioGeneratorOptions::Reparse(std::string const& key) +{ + std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key); + if (i == this->FlagMap.end() || i->second.size() != 1) { + return; + } + std::string const original = i->second[0]; + i->second[0] = ""; + this->UnknownFlagField = key; + this->Parse(original.c_str()); +} + void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) { // Look for Intel Fortran flags that do not map well in the flag table. @@ -248,7 +358,19 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) std::string const opts = cmOutputConverter::EscapeWindowsShellArgument( flag, cmOutputConverter::Shell_Flag_AllowMakeVariables | cmOutputConverter::Shell_Flag_VSIDE); - this->AppendFlagString("AdditionalOptions", opts); + this->AppendFlagString(this->UnknownFlagField, opts); +} + +cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag( + std::string const& key) +{ + FlagValue value; + std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key); + if (i != this->FlagMap.end()) { + value = i->second; + this->FlagMap.erase(i); + } + return value; } void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config) @@ -264,6 +386,9 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( return; } const char* tag = "PreprocessorDefinitions"; + if (lang == "CUDA") { + tag = "Defines"; + } if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { // if there are configuration specific flags, then // use the configuration specific tag for PreprocessorDefinitions diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 8c49470..52689e0 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -26,6 +26,7 @@ public: { Compiler, ResourceCompiler, + CudaCompiler, MasmCompiler, NasmCompiler, Linker, @@ -43,12 +44,19 @@ public: // Add a table of flags. void AddTable(cmVS7FlagTable const* table); + // Clear the flag tables. + void ClearTables(); + // Store options from command line flags. void Parse(const char* flags); void ParseFinish(); void PrependInheritedString(std::string const& key); + // Parse the content of the given flag table entry again to extract + // known flags and leave the rest in the original entry. + void Reparse(std::string const& key); + // Fix the ExceptionHandling option to default to off. void FixExceptionHandlingDefault(); @@ -59,6 +67,16 @@ public: bool UsingUnicode() const; bool UsingSBCS() const; + enum CudaRuntime + { + CudaRuntimeStatic, + CudaRuntimeShared, + CudaRuntimeNone + }; + CudaRuntime GetCudaRuntime() const; + + void FixCudaCodeGeneration(); + bool IsDebug() const; bool IsWinRt() const; bool IsManaged() const; @@ -81,7 +99,11 @@ private: bool FortranRuntimeDLL; bool FortranRuntimeMT; + std::string UnknownFlagField; + virtual void StoreUnknownFlag(const char* flag); + + FlagValue TakeFlag(std::string const& key); }; #endif diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx new file mode 100644 index 0000000..99c9ba8 --- /dev/null +++ b/Source/cmWorkingDirectory.cxx @@ -0,0 +1,24 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmWorkingDirectory.h" + +#include "cmSystemTools.h" + +cmWorkingDirectory::cmWorkingDirectory(std::string const& newdir) +{ + this->OldDir = cmSystemTools::GetCurrentWorkingDirectory(); + cmSystemTools::ChangeDirectory(newdir); +} + +cmWorkingDirectory::~cmWorkingDirectory() +{ + this->Pop(); +} + +void cmWorkingDirectory::Pop() +{ + if (!this->OldDir.empty()) { + cmSystemTools::ChangeDirectory(this->OldDir); + this->OldDir.clear(); + } +} diff --git a/Source/cmWorkingDirectory.h b/Source/cmWorkingDirectory.h new file mode 100644 index 0000000..af0fd44 --- /dev/null +++ b/Source/cmWorkingDirectory.h @@ -0,0 +1,25 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmWorkingDirectory_h +#define cmWorkingDirectory_h + +#include <cmConfigure.h> // IWYU pragma: keep + +#include <string> + +/** \class cmWorkingDirectory + * \brief An RAII class to manipulate the working directory. + */ +class cmWorkingDirectory +{ +public: + cmWorkingDirectory(std::string const& newdir); + ~cmWorkingDirectory(); + + void Pop(); + +private: + std::string OldDir; +}; + +#endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index b2384cd..3af3be6 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -23,6 +23,7 @@ #include "cmTargetLinkLibraryType.h" #include "cmUtils.hxx" #include "cmVersionConfig.h" +#include "cmWorkingDirectory.h" #include "cm_auto_ptr.hxx" #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -2199,24 +2200,23 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) resultFile += "/__cmake_systeminformation/results.txt"; } - // now run cmake on the CMakeLists file - cmSystemTools::ChangeDirectory(destPath); - std::vector<std::string> args2; - args2.push_back(args[0]); - args2.push_back(destPath); - std::string resultArg = "-DRESULT_FILE="; - resultArg += resultFile; - args2.push_back(resultArg); - int res = this->Run(args2, false); + { + // now run cmake on the CMakeLists file + cmWorkingDirectory workdir(destPath); + std::vector<std::string> args2; + args2.push_back(args[0]); + args2.push_back(destPath); + std::string resultArg = "-DRESULT_FILE="; + resultArg += resultFile; + args2.push_back(resultArg); + int res = this->Run(args2, false); - if (res != 0) { - std::cerr << "Error: --system-information failed on internal CMake!\n"; - return res; + if (res != 0) { + std::cerr << "Error: --system-information failed on internal CMake!\n"; + return res; + } } - // change back to the original directory - cmSystemTools::ChangeDirectory(cwd); - // echo results to stdout if needed if (writeToStdout) { FILE* fin = cmsys::SystemTools::Fopen(resultFile, "r"); diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 86f7552..93312e9 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -539,6 +539,7 @@ protected: std::string OSRelease; std::string OSVersion; std::string OSPlatform; + bool OSIs64Bit; }; SystemInformation::SystemInformation() @@ -1499,6 +1500,7 @@ SystemInformationImplementation::SystemInformationImplementation() this->OSRelease = ""; this->OSVersion = ""; this->OSPlatform = ""; + this->OSIs64Bit = (sizeof(void*) == 8); } SystemInformationImplementation::~SystemInformationImplementation() @@ -5320,10 +5322,20 @@ bool SystemInformationImplementation::QueryOSInformation() this->Hostname = name; const char* arch = getenv("PROCESSOR_ARCHITECTURE"); + const char* wow64 = getenv("PROCESSOR_ARCHITEW6432"); if (arch) { this->OSPlatform = arch; } + if (wow64) { + // the PROCESSOR_ARCHITEW6432 is only defined when running 32bit programs + // on 64bit OS + this->OSIs64Bit = true; + } else if (arch) { + // all values other than x86 map to 64bit architectures + this->OSIs64Bit = (strncmp(arch, "x86", 3) != 0); + } + #else struct utsname unameInfo; @@ -5334,6 +5346,12 @@ bool SystemInformationImplementation::QueryOSInformation() this->OSRelease = unameInfo.release; this->OSVersion = unameInfo.version; this->OSPlatform = unameInfo.machine; + + // This is still insufficient to capture 64bit architecture such + // powerpc and possible mips and sparc + if (this->OSPlatform.find_first_of("64") != std::string::npos) { + this->OSIs64Bit = true; + } } #ifdef __APPLE__ @@ -5387,6 +5405,6 @@ void SystemInformationImplementation::TrimNewline(std::string& output) /** Return true if the machine is 64 bits */ bool SystemInformationImplementation::Is64Bits() { - return (sizeof(void*) == 8); + return this->OSIs64Bit; } } diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in index cc09393..54e7fc1 100644 --- a/Source/kwsys/SystemInformation.hxx.in +++ b/Source/kwsys/SystemInformation.hxx.in @@ -65,6 +65,7 @@ public: // on this system. std::string GetOSDescription(); + // returns if the operating system is 64bit or not. bool Is64Bits(); unsigned int GetNumberOfLogicalCPU(); diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 8c82ec1..65b7b26 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -3331,7 +3331,7 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path, SystemTools::SplitPath(in_path, path_components); // If the input path is relative, start with a base path. - if (path_components[0].length() == 0) { + if (path_components[0].empty()) { std::vector<std::string> base_components; if (in_base) { // Use the given base path. diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx index 86a1e1e..3a9217f 100644 --- a/Source/kwsys/testSystemInformation.cxx +++ b/Source/kwsys/testSystemInformation.cxx @@ -52,6 +52,7 @@ int testSystemInformation(int, char* []) printMethod(info, GetOSRelease); printMethod(info, GetOSVersion); printMethod(info, GetOSPlatform); + printMethod(info, Is64Bits); printMethod(info, GetVendorString); printMethod(info, GetVendorID); printMethod(info, GetTypeID); @@ -63,7 +64,6 @@ int testSystemInformation(int, char* []) printMethod2(info, GetProcessorCacheSize, "KB"); printMethod(info, GetLogicalProcessorsPerPhysical); printMethod2(info, GetProcessorClockFrequency, "MHz"); - printMethod(info, Is64Bits); printMethod(info, GetNumberOfLogicalCPU); printMethod(info, GetNumberOfPhysicalCPU); printMethod(info, DoesCPUSupportCPUID); diff --git a/Tests/CPackComponents/CMakeLists.txt b/Tests/CPackComponents/CMakeLists.txt index 3c8ae35..5b03c9e 100644 --- a/Tests/CPackComponents/CMakeLists.txt +++ b/Tests/CPackComponents/CMakeLists.txt @@ -79,7 +79,7 @@ set(CPACK_NSIS_MENU_LINKS ) # Suggested default root for end users of the installer: -set(CPACK_NSIS_INSTALL_ROOT "C:\\Program Files\\CMake Tests Install Root") +set(CPACK_NSIS_INSTALL_ROOT "C:/Program Files/CMake Tests Install Root") # Include CPack to introduce the appropriate targets include(CPack) diff --git a/Tests/CheckFortran.cmake b/Tests/CheckFortran.cmake index 93990ad..b1652ba 100644 --- a/Tests/CheckFortran.cmake +++ b/Tests/CheckFortran.cmake @@ -18,6 +18,8 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" execute_process( WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckFortran COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR} + -A "${CMAKE_GENERATOR_PLATFORM}" + -T "${CMAKE_GENERATOR_TOOLSET}" OUTPUT_VARIABLE output ERROR_VARIABLE output RESULT_VARIABLE result diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt index d134b96..420d7a9 100644 --- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt +++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt @@ -12,22 +12,22 @@ project (CudaOnlySeparateCompilation CUDA) string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(CMAKE_CXX_STANDARD 11) set(CMAKE_CUDA_STANDARD 11) -add_library(CUDASerarateLibA STATIC file1.cu file2.cu file3.cu) +add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu) #Having file4/file5 in a shared library causes serious problems #with the nvcc linker and it will generate bad entries that will #cause a segv when trying to run the executable # -add_library(CUDASerarateLibB STATIC file4.cu file5.cu) -target_link_libraries(CUDASerarateLibB PRIVATE CUDASerarateLibA) +add_library(CUDASeparateLibB STATIC file4.cu file5.cu) +target_link_libraries(CUDASeparateLibB PRIVATE CUDASeparateLibA) add_executable(CudaOnlySeparateCompilation main.cu) -target_link_libraries(CudaOnlySeparateCompilation PRIVATE CUDASerarateLibB) +target_link_libraries(CudaOnlySeparateCompilation PRIVATE CUDASeparateLibB) -set_target_properties( CUDASerarateLibA - CUDASerarateLibB +set_target_properties( CUDASeparateLibA + CUDASeparateLibB PROPERTIES CUDA_SEPARABLE_COMPILATION ON) -set_target_properties( CUDASerarateLibA - CUDASerarateLibB +set_target_properties( CUDASeparateLibA + CUDASeparateLibB PROPERTIES POSITION_INDEPENDENT_CODE ON) diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt index 2646d29..38f2a44 100644 --- a/Tests/CudaOnly/WithDefs/CMakeLists.txt +++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt @@ -16,8 +16,15 @@ set(release_compile_defs DEFREL) #build a executable that needs to be passed a complex define through add_defintions #this verifies we can pass things such as '_','(' to nvcc add_definitions("-DPACKED_DEFINE=__attribute__((packed))") -set_source_files_properties(main.notcu PROPERTIES LANGUAGE CUDA) -add_executable(CudaOnlyWithDefs main.notcu) + +if(CMAKE_GENERATOR MATCHES "Visual Studio") + # CUDA MSBuild rules do not pass '-x cu' to nvcc + set(main main_for_vs.cu) +else() + set(main main.notcu) + set_source_files_properties(main.notcu PROPERTIES LANGUAGE CUDA) +endif() +add_executable(CudaOnlyWithDefs ${main}) target_compile_options(CudaOnlyWithDefs PRIVATE diff --git a/Tests/CudaOnly/WithDefs/main_for_vs.cu b/Tests/CudaOnly/WithDefs/main_for_vs.cu new file mode 100644 index 0000000..56078e7 --- /dev/null +++ b/Tests/CudaOnly/WithDefs/main_for_vs.cu @@ -0,0 +1 @@ +#include "main.notcu" diff --git a/Tests/Module/WriteCompilerDetectionHeader/main.cpp b/Tests/Module/WriteCompilerDetectionHeader/main.cpp index 192094c..9979cba 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/main.cpp +++ b/Tests/Module/WriteCompilerDetectionHeader/main.cpp @@ -8,6 +8,9 @@ #error Expect no C features defined #endif +TEST_STATIC_ASSERT(true); +TEST_STATIC_ASSERT_MSG(true, "msg"); + int main() { return 0; diff --git a/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp b/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp index 1635091..d1f178f 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp +++ b/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp @@ -8,6 +8,9 @@ #error Expect no C features defined #endif +MULTI_STATIC_ASSERT(true); +MULTI_STATIC_ASSERT_MSG(true, "msg"); + int main() { return 0; diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 4960472..86af746 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -83,62 +83,92 @@ target_compile_features(empty PRIVATE ${QT_COMPILE_FEATURES}) # -- Test # When a file listed in a .qrc file changes the target must be rebuilt try_compile(RCC_DEPENDS - "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" - "${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends" - autorcc_depends + "${CMAKE_CURRENT_BINARY_DIR}/rccDepends" + "${CMAKE_CURRENT_SOURCE_DIR}/rccDepends" + rccDepends CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) if (NOT RCC_DEPENDS) - message(SEND_ERROR "Initial build of autorcc_depends failed. Output: ${output}") + message(SEND_ERROR "Initial build of rccDepends failed. Output: ${output}") endif() -file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends/info_file.txt" qrc_files) - -list(GET qrc_files 0 qrc_file1) - +# Get name and timestamp of the output binary +file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/rccDepends/target1.txt" target1List) +list(GET target1List 0 binFile) set(timeformat "%Y%j%H%M%S") +file(TIMESTAMP "${binFile}" timeBegin "${timeformat}") -file(TIMESTAMP "${qrc_file1}" file1_before "${timeformat}") - +# Touch first qrc input file and rebuild execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends/res1/input.txt") - +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/rccDepends/res1/input.txt") execute_process(COMMAND "${CMAKE_COMMAND}" --build . - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/rccDepends" + RESULT_VARIABLE rccDepends_result ) +if (rccDepends_result) + message(SEND_ERROR "Second build of rccDepends failed.") +endif() +# Compare timestamps +file(TIMESTAMP "${binFile}" timeStep1 "${timeformat}") +if (NOT timeStep1 GREATER timeBegin) + message(SEND_ERROR "File (${binFile}) should have changed in the first step!") +endif() -file(TIMESTAMP "${qrc_file1}" file1_step1 "${timeformat}") - -if (NOT file1_step1 GREATER file1_before) - message(SEND_ERROR "file1 (${qrc_file1}) should have changed in the first step!") +# Touch second qrc input file and rebuild +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/rccDepends/res2/input.txt") +execute_process(COMMAND "${CMAKE_COMMAND}" --build . + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/rccDepends" + RESULT_VARIABLE rccDepends_result +) +if (rccDepends_result) + message(SEND_ERROR "Third build of rccDepends failed.") +endif() +# Compare timestamps +file(TIMESTAMP "${binFile}" timeStep2 "${timeformat}") +if (NOT timeStep2 GREATER timeStep1) + message(SEND_ERROR "File (${binFile}) should have changed in the second step!") endif() # -- Test # Ensure a repeated build succeeds when a header containing a QObject changes try_compile(MOC_RERUN - "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" - "${CMAKE_CURRENT_SOURCE_DIR}/automoc_rerun" - automoc_rerun + "${CMAKE_CURRENT_BINARY_DIR}/mocRerun" + "${CMAKE_CURRENT_SOURCE_DIR}/mocRerun" + mocRerun CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) if (NOT MOC_RERUN) - message(SEND_ERROR "Initial build of automoc_rerun failed. Output: ${output}") + message(SEND_ERROR "Initial build of mocRerun failed. Output: ${output}") endif() -configure_file(automoc_rerun/test1.h.in2 automoc_rerun/test1.h COPYONLY) +# Get name and timestamp of the output binary +file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/mocRerun/target1.txt" target1List) +list(GET target1List 0 binFile) +set(timeformat "%Y%j%H%M%S") +file(TIMESTAMP "${binFile}" timeBegin "${timeformat}") +# Change file content and rebuild +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) +configure_file(mocRerun/test1b.h.in mocRerun/test1.h COPYONLY) execute_process(COMMAND "${CMAKE_COMMAND}" --build . - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" - RESULT_VARIABLE automoc_rerun_result + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocRerun" + RESULT_VARIABLE mocRerun_result ) -if (automoc_rerun_result) - message(SEND_ERROR "Second build of automoc_rerun failed.") +if (mocRerun_result) + message(SEND_ERROR "Second build of mocRerun failed.") +endif() + +# Compare timestamps +file(TIMESTAMP "${binFile}" timeStep1 "${timeformat}") +if (NOT timeStep1 GREATER timeBegin) + message(SEND_ERROR "File (${binFile}) should have changed in the first step!") endif() # -- Test @@ -209,6 +239,10 @@ target_link_libraries(skipRccB ${QT_LIBRARIES}) add_subdirectory(sameName) # -- Test +# Tests AUTOMOC with generated sources +add_subdirectory(mocDepends) + +# -- Test # Tests various include moc patterns add_subdirectory(mocIncludeStrict) diff --git a/Tests/QtAutogen/automoc_rerun/CMakeLists.txt b/Tests/QtAutogen/automoc_rerun/CMakeLists.txt deleted file mode 100644 index 92a682b..0000000 --- a/Tests/QtAutogen/automoc_rerun/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -cmake_minimum_required(VERSION 3.7) -project(automoc_rerun CXX) - -if (QT_TEST_VERSION STREQUAL 4) - find_package(Qt4 REQUIRED) - set(QT_CORE_TARGET Qt4::QtCore) -else() - if (NOT QT_TEST_VERSION STREQUAL 5) - message(SEND_ERROR "Invalid Qt version specified.") - endif() - - find_package(Qt5Core REQUIRED) - set(QT_CORE_TARGET Qt5::Core) -endif() - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) - -configure_file(test1.h.in1 test1.h COPYONLY) - -add_executable(test1 - ${CMAKE_CURRENT_BINARY_DIR}/test1.h - test1.cpp - res1.qrc - ) -target_include_directories(test1 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -target_link_libraries(test1 ${QT_CORE_TARGET}) diff --git a/Tests/QtAutogen/automoc_rerun/test1.cpp b/Tests/QtAutogen/automoc_rerun/test1.cpp deleted file mode 100644 index 4316a91..0000000 --- a/Tests/QtAutogen/automoc_rerun/test1.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "test1.h" -int main() -{ - return 0; -} diff --git a/Tests/QtAutogen/automoc_rerun/test1.h.in1 b/Tests/QtAutogen/automoc_rerun/test1.h.in1 deleted file mode 100644 index fee2c09..0000000 --- a/Tests/QtAutogen/automoc_rerun/test1.h.in1 +++ /dev/null @@ -1,8 +0,0 @@ -#include <QObject> -class test1 : public QObject -{ - Q_OBJECT - public slots: - void onTst1() {} - void onTst2() {} -}; diff --git a/Tests/QtAutogen/automoc_rerun/test1.h.in2 b/Tests/QtAutogen/automoc_rerun/test1.h.in2 deleted file mode 100644 index 6531d10..0000000 --- a/Tests/QtAutogen/automoc_rerun/test1.h.in2 +++ /dev/null @@ -1,7 +0,0 @@ -#include <QObject> -class test1 : public QObject -{ - Q_OBJECT - public slots: - void onTst1() {} -}; diff --git a/Tests/QtAutogen/autorcc_depends/CMakeLists.txt b/Tests/QtAutogen/autorcc_depends/CMakeLists.txt deleted file mode 100644 index 7b51e11..0000000 --- a/Tests/QtAutogen/autorcc_depends/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -cmake_minimum_required(VERSION 3.7) -project(autorcc_depends) - -set(CMAKE_AUTORCC ON) - -if (QT_TEST_VERSION STREQUAL 4) - find_package(Qt4 REQUIRED) - set(QT_CORE_TARGET Qt4::QtCore) -else() - if (NOT QT_TEST_VERSION STREQUAL 5) - message(SEND_ERROR "Invalid Qt version specified.") - endif() - - find_package(Qt5Core REQUIRED) - set(QT_CORE_TARGET Qt5::Core) -endif() - -configure_file(res1.qrc.in res1.qrc @ONLY) -configure_file(res1/input.txt.in res1/input.txt @ONLY) - -add_executable(test_res1 - test_res1.cpp - ${CMAKE_CURRENT_BINARY_DIR}/res1.qrc -) -target_link_libraries(test_res1 ${QT_CORE_TARGET}) -add_custom_command(TARGET test_res1 POST_BUILD COMMAND - ${CMAKE_COMMAND} -E echo "$<TARGET_FILE:test_res1>" > info_file.txt) diff --git a/Tests/QtAutogen/mocDepends/CMakeLists.txt b/Tests/QtAutogen/mocDepends/CMakeLists.txt new file mode 100644 index 0000000..8bd72eb --- /dev/null +++ b/Tests/QtAutogen/mocDepends/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.7) +project(mocDepends) + +if (QT_TEST_VERSION STREQUAL 4) + find_package(Qt4 REQUIRED) + set(QT_CORE_TARGET Qt4::QtCore) +else() + if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") + endif() + + find_package(Qt5Core REQUIRED) + set(QT_CORE_TARGET Qt5::Core) +endif() + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# -- Test 1 using generated header +# This tests the dependency of AUTOMOC of mocDepends1 to the generated object.hpp +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/object.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/object.hpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/object.hpp + ) + +add_executable(mocDepends1 test1.cpp + ${CMAKE_CURRENT_BINARY_DIR}/object.hpp +) +target_link_libraries(mocDepends1 ${QT_CORE_TARGET}) +set_target_properties(mocDepends1 PROPERTIES AUTOMOC TRUE) + +# -- Test 2 using generated library +# This tests the dependency of AUTOMOC of mocDepends2 to the +# generated simpleLib.hpp which belongs to a linked library of mocDepends2 +add_custom_command(OUTPUT simpleLib.hpp simpleLib.cpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp + ) +add_library(SimpleLib STATIC simpleLib.hpp simpleLib.cpp) + +add_executable(mocDepends2 test2.cpp ) +target_link_libraries(mocDepends2 SimpleLib ${QT_CORE_TARGET}) +set_target_properties(mocDepends2 PROPERTIES AUTOMOC TRUE) diff --git a/Tests/QtAutogen/mocDepends/invalid.hpp.in b/Tests/QtAutogen/mocDepends/invalid.hpp.in new file mode 100644 index 0000000..854d9a1 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/invalid.hpp.in @@ -0,0 +1 @@ +#ifndef diff --git a/Tests/QtAutogen/mocDepends/object.hpp.in b/Tests/QtAutogen/mocDepends/object.hpp.in new file mode 100644 index 0000000..f364f7c --- /dev/null +++ b/Tests/QtAutogen/mocDepends/object.hpp.in @@ -0,0 +1,14 @@ +#ifndef OBJECT_HPP +#define OBJECT_HPP + +#include <QObject> + +class Object : public QObject +{ + Q_OBJECT +public: + Q_SLOT + void aSlot(){}; +}; + +#endif diff --git a/Tests/QtAutogen/mocDepends/simpleLib.cpp.in b/Tests/QtAutogen/mocDepends/simpleLib.cpp.in new file mode 100644 index 0000000..fa33bd3 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/simpleLib.cpp.in @@ -0,0 +1,9 @@ +#include "simpleLib.hpp" + +SimpleLib::SimpleLib() +{ +} + +SimpleLib::~SimpleLib() +{ +} diff --git a/Tests/QtAutogen/mocDepends/simpleLib.hpp.in b/Tests/QtAutogen/mocDepends/simpleLib.hpp.in new file mode 100644 index 0000000..758f1f6 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/simpleLib.hpp.in @@ -0,0 +1,11 @@ +#ifndef SIMPLE_LIB_H +#define SIMPLE_LIB_H + +class SimpleLib +{ +public: + SimpleLib(); + ~SimpleLib(); +}; + +#endif diff --git a/Tests/QtAutogen/mocDepends/test1.cpp b/Tests/QtAutogen/mocDepends/test1.cpp new file mode 100644 index 0000000..92c259c --- /dev/null +++ b/Tests/QtAutogen/mocDepends/test1.cpp @@ -0,0 +1,9 @@ + +#include "object.hpp" + +int main() +{ + Object obj; + + return 0; +} diff --git a/Tests/QtAutogen/mocDepends/test2.cpp b/Tests/QtAutogen/mocDepends/test2.cpp new file mode 100644 index 0000000..155b19b --- /dev/null +++ b/Tests/QtAutogen/mocDepends/test2.cpp @@ -0,0 +1,10 @@ + +#include "test2.hpp" + +int main() +{ + SimpleLib obj; + LObject lobject; + + return 0; +} diff --git a/Tests/QtAutogen/mocDepends/test2.hpp b/Tests/QtAutogen/mocDepends/test2.hpp new file mode 100644 index 0000000..0125f07 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/test2.hpp @@ -0,0 +1,16 @@ +#ifndef TEST2_HPP +#define TEST2_HPP + +#include "simpleLib.hpp" +#include <QObject> + +// This object triggers the AUTOMOC on this file +class LObject : public QObject +{ + Q_OBJECT +public: + Q_SLOT + void aSlot(){}; +}; + +#endif diff --git a/Tests/QtAutogen/mocRerun/CMakeLists.txt b/Tests/QtAutogen/mocRerun/CMakeLists.txt new file mode 100644 index 0000000..6689f50 --- /dev/null +++ b/Tests/QtAutogen/mocRerun/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.7) +project(mocRerun CXX) + +if (QT_TEST_VERSION STREQUAL 4) + find_package(Qt4 REQUIRED) + set(QT_CORE_TARGET Qt4::QtCore) +else() + if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") + endif() + + find_package(Qt5Core REQUIRED) + set(QT_CORE_TARGET Qt5::Core) +endif() + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +configure_file(test1a.h.in test1.h COPYONLY) +# Generated source file +add_custom_command(OUTPUT main.cpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/main.cpp + ) + +add_executable(mocRerun + ${CMAKE_CURRENT_BINARY_DIR}/test1.h + ${CMAKE_CURRENT_BINARY_DIR}/main.cpp + res1.qrc + ) +target_include_directories(mocRerun PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +target_link_libraries(mocRerun ${QT_CORE_TARGET}) +# Write target name to text file +add_custom_command(TARGET mocRerun POST_BUILD COMMAND + ${CMAKE_COMMAND} -E echo "$<TARGET_FILE:mocRerun>" > target1.txt) diff --git a/Tests/QtAutogen/automoc_rerun/input.txt b/Tests/QtAutogen/mocRerun/input.txt index da62762..da62762 100644 --- a/Tests/QtAutogen/automoc_rerun/input.txt +++ b/Tests/QtAutogen/mocRerun/input.txt diff --git a/Tests/QtAutogen/mocRerun/main.cpp.in b/Tests/QtAutogen/mocRerun/main.cpp.in new file mode 100644 index 0000000..b37ff61 --- /dev/null +++ b/Tests/QtAutogen/mocRerun/main.cpp.in @@ -0,0 +1,18 @@ +#include "test1.h" + +class Test2 : public QObject +{ + Q_OBJECT +public slots: + void onTst1() {} +}; + +int main() +{ + Test1 test1; + Test2 test2; + + return 0; +} + +#include "main.moc" diff --git a/Tests/QtAutogen/automoc_rerun/res1.qrc b/Tests/QtAutogen/mocRerun/res1.qrc index fb804b5..fb804b5 100644 --- a/Tests/QtAutogen/automoc_rerun/res1.qrc +++ b/Tests/QtAutogen/mocRerun/res1.qrc diff --git a/Tests/QtAutogen/mocRerun/test1a.h.in b/Tests/QtAutogen/mocRerun/test1a.h.in new file mode 100644 index 0000000..a335046 --- /dev/null +++ b/Tests/QtAutogen/mocRerun/test1a.h.in @@ -0,0 +1,8 @@ +#include <QObject> +class Test1 : public QObject +{ + Q_OBJECT +public slots: + void onTst1() {} + void onTst2() {} +}; diff --git a/Tests/QtAutogen/mocRerun/test1b.h.in b/Tests/QtAutogen/mocRerun/test1b.h.in new file mode 100644 index 0000000..6128eeb --- /dev/null +++ b/Tests/QtAutogen/mocRerun/test1b.h.in @@ -0,0 +1,7 @@ +#include <QObject> +class Test1 : public QObject +{ + Q_OBJECT +public slots: + void onTst1() {} +}; diff --git a/Tests/QtAutogen/rccDepends/CMakeLists.txt b/Tests/QtAutogen/rccDepends/CMakeLists.txt new file mode 100644 index 0000000..de98573 --- /dev/null +++ b/Tests/QtAutogen/rccDepends/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.7) +project(rccDepends) + +set(CMAKE_AUTORCC ON) + +if (QT_TEST_VERSION STREQUAL 4) + find_package(Qt4 REQUIRED) + set(QT_CORE_TARGET Qt4::QtCore) +else() + if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") + endif() + + find_package(Qt5Core REQUIRED) + set(QT_CORE_TARGET Qt5::Core) +endif() + +configure_file(res/input1.txt.in res1/input.txt @ONLY) +configure_file(res/input2.txt.in res2/input.txt @ONLY) +# Configure time generated qrc file +configure_file(res1.qrc.in res1.qrc @ONLY) +# Dependency generated qrc file +add_custom_command(OUTPUT res2.qrc + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/res2.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc + ) + + +add_executable(rccDepends + main.cpp + ${CMAKE_CURRENT_BINARY_DIR}/res1.qrc + ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc +) +target_link_libraries(rccDepends ${QT_CORE_TARGET}) +add_custom_command(TARGET rccDepends POST_BUILD COMMAND + ${CMAKE_COMMAND} -E echo "$<TARGET_FILE:rccDepends>" > target1.txt) diff --git a/Tests/QtAutogen/autorcc_depends/test_res1.cpp b/Tests/QtAutogen/rccDepends/main.cpp index 766b775..766b775 100644 --- a/Tests/QtAutogen/autorcc_depends/test_res1.cpp +++ b/Tests/QtAutogen/rccDepends/main.cpp diff --git a/Tests/QtAutogen/autorcc_depends/res1/input.txt.in b/Tests/QtAutogen/rccDepends/res/input1.txt.in index da62762..da62762 100644 --- a/Tests/QtAutogen/autorcc_depends/res1/input.txt.in +++ b/Tests/QtAutogen/rccDepends/res/input1.txt.in diff --git a/Tests/QtAutogen/rccDepends/res/input2.txt.in b/Tests/QtAutogen/rccDepends/res/input2.txt.in new file mode 100644 index 0000000..08e14b7 --- /dev/null +++ b/Tests/QtAutogen/rccDepends/res/input2.txt.in @@ -0,0 +1 @@ +Res2 input. diff --git a/Tests/QtAutogen/autorcc_depends/res1.qrc.in b/Tests/QtAutogen/rccDepends/res1.qrc.in index 2a5417b..2a5417b 100644 --- a/Tests/QtAutogen/autorcc_depends/res1.qrc.in +++ b/Tests/QtAutogen/rccDepends/res1.qrc.in diff --git a/Tests/QtAutogen/rccDepends/res2.qrc.in b/Tests/QtAutogen/rccDepends/res2.qrc.in new file mode 100644 index 0000000..18b916a --- /dev/null +++ b/Tests/QtAutogen/rccDepends/res2.qrc.in @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>res2/input.txt</file> + </qresource> +</RCC> diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 6423bfd..5157b9f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -156,6 +156,9 @@ add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(LinkStatic) add_RunCMake_test(ObjectLibrary) +if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + add_RunCMake_test(RuntimePath) +endif() add_RunCMake_test(Swift) add_RunCMake_test(TargetObjects) add_RunCMake_test(TargetSources) diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index 44c67a2..f6449f2 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -6,6 +6,12 @@ run_cmake(NoToolset) if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset") run_cmake(TestToolset) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,cuda=Test Cuda") + run_cmake(TestToolsetCudaBoth) + set(RunCMake_GENERATOR_TOOLSET ",cuda=Test Cuda") + run_cmake(TestToolsetCudaOnly) + set(RunCMake_GENERATOR_TOOLSET "cuda=Test Cuda") + run_cmake(TestToolsetCudaOnly) if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[245]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(TestToolsetHostArchBoth) diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt new file mode 100644 index 0000000..90503e2 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt @@ -0,0 +1,2 @@ +-- CMAKE_VS_PLATFORM_TOOLSET='Test Toolset' +-- CMAKE_VS_PLATFORM_TOOLSET_CUDA='Test Cuda' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake new file mode 100644 index 0000000..befa0af --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake @@ -0,0 +1,2 @@ +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_CUDA='${CMAKE_VS_PLATFORM_TOOLSET_CUDA}'") diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt new file mode 100644 index 0000000..94e1e43 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt @@ -0,0 +1,2 @@ +-- CMAKE_VS_PLATFORM_TOOLSET='(v[0-9]+|Windows7.1SDK)' +-- CMAKE_VS_PLATFORM_TOOLSET_CUDA='Test Cuda' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake new file mode 100644 index 0000000..befa0af --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake @@ -0,0 +1,2 @@ +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_CUDA='${CMAKE_VS_PLATFORM_TOOLSET_CUDA}'") diff --git a/Tests/RunCMake/RuntimePath/A.c b/Tests/RunCMake/RuntimePath/A.c new file mode 100644 index 0000000..e9d4195 --- /dev/null +++ b/Tests/RunCMake/RuntimePath/A.c @@ -0,0 +1,4 @@ +int libA(void) +{ + return 0; +} diff --git a/Tests/RunCMake/RuntimePath/CMakeLists.txt b/Tests/RunCMake/RuntimePath/CMakeLists.txt new file mode 100644 index 0000000..a640c56 --- /dev/null +++ b/Tests/RunCMake/RuntimePath/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.7) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake new file mode 100644 index 0000000..a9a7f05 --- /dev/null +++ b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake @@ -0,0 +1,18 @@ +include(RunCMake) + + +function(run_SymlinkImplicit) + # Use a single build tree for a few tests without cleaning. + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SymlinkImplicit-build) + set(RunCMake_TEST_NO_CLEAN 1) + if(RunCMake_GENERATOR MATCHES "Make|Ninja") + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + endif() + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(SymlinkImplicit) + run_cmake_command(SymlinkImplicit-build ${CMAKE_COMMAND} --build . --config Debug) + run_cmake_command(SymlinkImplicitCheck + ${CMAKE_COMMAND} -Ddir=${RunCMake_TEST_BINARY_DIR} -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake) +endfunction() +run_SymlinkImplicit() diff --git a/Tests/RunCMake/RuntimePath/SymlinkImplicit.cmake b/Tests/RunCMake/RuntimePath/SymlinkImplicit.cmake new file mode 100644 index 0000000..6578f8f --- /dev/null +++ b/Tests/RunCMake/RuntimePath/SymlinkImplicit.cmake @@ -0,0 +1,17 @@ +enable_language(C) + +set(lib_dir ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(lib_link ${CMAKE_CURRENT_BINARY_DIR}/libLink) +set(lib_always ${CMAKE_CURRENT_BINARY_DIR}/libAlways) +file(MAKE_DIRECTORY ${lib_dir}) +execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink lib ${lib_link}) +execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink lib ${lib_always}) + +add_library(A SHARED A.c) +list(APPEND CMAKE_C_IMPLICIT_LINK_DIRECTORIES ${lib_dir}) +set_property(TARGET A PROPERTY LIBRARY_OUTPUT_DIRECTORY ${lib_link}) + +add_executable(exe main.c) +target_link_libraries(exe A) +set_property(TARGET exe PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) +set_property(TARGET exe PROPERTY BUILD_RPATH ${lib_always}) diff --git a/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck-result.txt b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck-stderr.txt b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck-stderr.txt new file mode 100644 index 0000000..b0ede70 --- /dev/null +++ b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck-stderr.txt @@ -0,0 +1,22 @@ +^CMake Error at .*/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake:[0-9]+ \(file\): + file RPATH_CHANGE could not write new RPATH: + + old-should-not-exist + + to the file: + + [^ +]*/Tests/RunCMake/RuntimePath/SymlinkImplicit-build/exe + + The current (RPATH|RUNPATH) is: + + [^ +]*/Tests/RunCMake/RuntimePath/SymlinkImplicit-build/libAlways(:[^ +]*)? + + which does not contain: + + [^ +]*/Tests/RunCMake/RuntimePath/SymlinkImplicit-build/libLink + + as was expected\.$ diff --git a/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake new file mode 100644 index 0000000..d34742e --- /dev/null +++ b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake @@ -0,0 +1,2 @@ +file(COPY ${dir}/bin/exe DESTINATION ${dir}) +file(RPATH_CHANGE FILE "${dir}/exe" OLD_RPATH "${dir}/libLink" NEW_RPATH "old-should-not-exist") diff --git a/Tests/RunCMake/RuntimePath/main.c b/Tests/RunCMake/RuntimePath/main.c new file mode 100644 index 0000000..8488f4e --- /dev/null +++ b/Tests/RunCMake/RuntimePath/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index f51a107..5f4bdc3 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -187,3 +187,19 @@ if(NOT XCODE_VERSION VERSION_LESS 5) unset(RunCMake_TEST_NO_CLEAN) unset(RunCMake_TEST_OPTIONS) endif() + +function(XcodeSchemaGeneration) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeSchemaGeneration-build) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_OPTIONS "-DCMAKE_XCODE_GENERATE_SCHEME=ON") + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake(XcodeSchemaGeneration) + run_cmake_command(XcodeSchemaGeneration-build xcodebuild -scheme foo build) +endfunction() + +if(NOT XCODE_VERSION VERSION_LESS 7) + XcodeSchemaGeneration() +endif() diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake new file mode 100644 index 0000000..2fe5a9f --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.7) + +project(XcodeSchemaGeneration CXX) + +add_executable(foo main.cpp) diff --git a/Tests/RunCMake/file/READ_ELF-result.txt b/Tests/RunCMake/file/READ_ELF-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/READ_ELF-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/READ_ELF-stderr.txt b/Tests/RunCMake/file/READ_ELF-stderr.txt new file mode 100644 index 0000000..7b32804 --- /dev/null +++ b/Tests/RunCMake/file/READ_ELF-stderr.txt @@ -0,0 +1,2 @@ +.*file READ_ELF must be called with at least three additional arguments\. +.*file READ_ELF given FILE "XXX" that does not exist\. diff --git a/Tests/RunCMake/file/READ_ELF.cmake b/Tests/RunCMake/file/READ_ELF.cmake new file mode 100644 index 0000000..cd02c9b --- /dev/null +++ b/Tests/RunCMake/file/READ_ELF.cmake @@ -0,0 +1,2 @@ +file(READ_ELF XXX) +file(READ_ELF XXX RPATH YYY) diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 7497544..3f3c0da 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -25,6 +25,7 @@ run_cmake(LOCK-error-no-timeout) run_cmake(LOCK-error-timeout) run_cmake(LOCK-error-unknown-option) run_cmake(LOCK-lowercase) +run_cmake(READ_ELF) run_cmake(GLOB) run_cmake(GLOB_RECURSE) # test is valid both for GLOB and GLOB_RECURSE diff --git a/Utilities/GitSetup/config b/Utilities/GitSetup/config index d69a679..2b4f037 100644 --- a/Utilities/GitSetup/config +++ b/Utilities/GitSetup/config @@ -1,9 +1,2 @@ [hooks] - url = https://cmake.org/cmake.git -[ssh] - host = cmake.org - key = id_git_cmake - request-url = https://www.kitware.com/Admin/SendPassword.cgi -[stage] - url = git://cmake.org/stage/cmake.git - pushurl = git@cmake.org:stage/cmake.git + url = https://gitlab.kitware.com/utils/gitsetup.git diff --git a/Utilities/Release/release_cmake.cmake b/Utilities/Release/release_cmake.cmake index 0db89b5..ee1a0dc 100644 --- a/Utilities/Release/release_cmake.cmake +++ b/Utilities/Release/release_cmake.cmake @@ -32,9 +32,15 @@ if(NOT DEFINED GIT_COMMAND) set(GIT_COMMAND git) endif() -if(${CMAKE_CREATE_VERSION} MATCHES "^(release|maint|next|nightly)$") +if(CMAKE_CREATE_VERSION MATCHES "^(master|release)$") + set(GIT_FETCH "") set(GIT_BRANCH origin/${CMAKE_CREATE_VERSION}) +elseif(CMAKE_CREATE_VERSION STREQUAL "nightly") + set(nightly stage/master/nightly/latest) + set(GIT_FETCH "${GIT_COMMAND} fetch origin refs/${nightly}:refs/remotes/origin/${nightly}") + set(GIT_BRANCH origin/${nightly}) else() + set(GIT_FETCH "") set(GIT_BRANCH ${CMAKE_CREATE_VERSION}) endif() diff --git a/Utilities/Release/release_cmake.sh.in b/Utilities/Release/release_cmake.sh.in index 1465129..f363b3d 100755 --- a/Utilities/Release/release_cmake.sh.in +++ b/Utilities/Release/release_cmake.sh.in @@ -94,13 +94,15 @@ cd @CMAKE_RELEASE_DIRECTORY@ if [ ! -z "@GIT_COMMAND@" ]; then # clone the repo without creating any source files in the directory # matching the branch being built (i.e. master CMake-2-8, etc) - @GIT_COMMAND@ clone -n git://cmake.org/cmake.git @CMAKE_CREATE_VERSION@ - check_exit_value $? "Checkout git cmake source" || exit 1 + @GIT_COMMAND@ clone -n https://gitlab.kitware.com/cmake/cmake.git @CMAKE_CREATE_VERSION@ + check_exit_value $? "git clone cmake source" || exit 1 # go into the git directory cd @CMAKE_CREATE_VERSION@ # run any extra commands if they exist @GIT_EXTRA@ check_exit_value $? "git extra cmake source" || exit 1 + @GIT_FETCH@ + check_exit_value $? "git extra fetch" || exit 1 # now checkout a copy on the local branch working @GIT_COMMAND@ checkout -b working @GIT_BRANCH@ check_exit_value $? "git checkout" || exit 1 diff --git a/Utilities/SetupForDevelopment.sh b/Utilities/SetupForDevelopment.sh index 39152bc..ff64a84 100755 --- a/Utilities/SetupForDevelopment.sh +++ b/Utilities/SetupForDevelopment.sh @@ -3,9 +3,6 @@ cd "${BASH_SOURCE%/*}/.." && Utilities/GitSetup/setup-user && echo && Utilities/GitSetup/setup-hooks && echo && -Utilities/GitSetup/setup-stage && echo && -(Utilities/GitSetup/setup-ssh || - echo 'Failed to setup SSH. Run this again to retry.') && echo && Utilities/GitSetup/tips # Rebase master by default @@ -13,5 +10,5 @@ git config rebase.stat true git config branch.master.rebase true # Record the version of this setup so Git/pre-commit can check it. -SetupForDevelopment_VERSION=1 +SetupForDevelopment_VERSION=2 git config hooks.SetupForDevelopment ${SetupForDevelopment_VERSION} diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in index 9581458..e3afc78 100644 --- a/Utilities/Sphinx/conf.py.in +++ b/Utilities/Sphinx/conf.py.in @@ -18,7 +18,9 @@ release = '@conf_release@' # full version string primary_domain = 'cmake' -exclude_patterns = [] +exclude_patterns = [ + 'dev', # ignore developer-only documentation + ] extensions = ['cmake'] templates_path = ['@conf_path@/templates'] @@ -404,6 +404,7 @@ CMAKE_CXX_SOURCES="\ cmUnsetCommand \ cmVersion \ cmWhileCommand \ + cmWorkingDirectory \ cmake \ cmakemain \ cmcmd \ |