diff options
230 files changed, 4668 insertions, 1224 deletions
diff --git a/CMakeCPack.cmake b/CMakeCPack.cmake index ba858bd..a0aacb4 100644 --- a/CMakeCPack.cmake +++ b/CMakeCPack.cmake @@ -54,6 +54,9 @@ if(${CPACK_SYSTEM_NAME} MATCHES Windows) endif() endif() +# Command for configure IFW script templates +include(${CMake_SOURCE_DIR}/Modules/CPackIFWConfigureFile.cmake) + # Advanced IFW configuration set(_cpifwrc CPACK_IFW_COMPONENT_GROUP_CMAKE_) set(_cpifwrcconf _CPACK_IFW_COMPONENT_GROUP_CMAKE) @@ -85,8 +88,6 @@ _cmifwarg("Package <Default> tag (values: TRUE, FALSE, SCRIPT)" _cmifwarg("Package <Version> tag" STRING VERSION "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") -_cmifwarg("Package <Script> tag" - FILEPATH SCRIPT "${CMake_BINARY_DIR}/installscript.qs") _cmifwarg("Package <SortingPriority> tag" STRING PRIORITY "100") _cmifwarg("Package <ForsedInstallation> tag" @@ -148,33 +149,22 @@ if(CMake_INSTALL_COMPONENTS) set(CPACK_COMPONENTS_ALL \"${_CPACK_IFW_COMPONENTS_ALL}\") set(CPACK_COMPONENTS_GROUPING IGNORE) ") + _cmifwarg("Package <Script> template" + FILEPATH SCRIPT_TEMPLATE "${CMake_SOURCE_DIR}/Source/QtIFW/CMake.qs.in") else() if(BUILD_QtDialog AND USE_LGPL) set(${_cpifwrc}LICENSES_DEFAULT "${${_cpifwrc}LICENSES_DEFAULT};LGPLv${USE_LGPL};${CMake_SOURCE_DIR}/Licenses/LGPLv${USE_LGPL}.txt") endif() + _cmifwarg("Package <Script> template" + FILEPATH SCRIPT_TEMPLATE "${CMake_SOURCE_DIR}/Source/QtIFW/installscript.qs.in") endif() +_cmifwarg("Package <Script> generated" + FILEPATH SCRIPT_GENERATED "${CMake_BINARY_DIR}/CMake.qs") _cmifwarg("Package <Licenses> tag (pairs of <display_name> <file_path>)" STRING LICENSES "${${_cpifwrc}LICENSES_DEFAULT}") -# Components scripts configuration -if(CMake_INSTALL_COMPONENTS) - configure_file("${CMake_SOURCE_DIR}/Source/QtIFW/CMake.qs.in" - "${CMake_BINARY_DIR}/installscript.qs" @ONLY - ) -else() - configure_file("${CMake_SOURCE_DIR}/Source/QtIFW/installscript.qs.in" - "${CMake_BINARY_DIR}/installscript.qs" @ONLY - ) -endif() -foreach(_script - CMake.Documentation.SphinxHTML - CMake.DeveloperReference.HTML) - configure_file("${CMake_SOURCE_DIR}/Source/QtIFW/${_script}.qs.in" - "${CMake_BINARY_DIR}/${_script}.qs" @ONLY) -endforeach() - if(${CMAKE_SYSTEM_NAME} MATCHES Windows) set(_CPACK_IFW_PACKAGE_ICON "set(CPACK_IFW_PACKAGE_ICON \"${CMake_SOURCE_DIR}/Source/QtDialog/CMakeSetup.ico\")") @@ -199,6 +189,23 @@ if(${CMAKE_SYSTEM_NAME} MATCHES Linux) set(CPACK_IFW_ADMIN_TARGET_DIRECTORY "@ApplicationsDir@/${CMAKE_PROJECT_NAME}") endif() +# Components scripts configuration +if((EXISTS "${CMake_IFW_ROOT_COMPONENT_SCRIPT_TEMPLATE}") + AND (NOT "${CMake_IFW_ROOT_COMPONENT_SCRIPT_GENERATED}" STREQUAL "") + AND (NOT "${CMake_IFW_ROOT_COMPONENT_SCRIPT}")) + cpack_ifw_configure_file("${CMake_IFW_ROOT_COMPONENT_SCRIPT_TEMPLATE}" + "${CMake_IFW_ROOT_COMPONENT_SCRIPT_GENERATED}") + _cmifwarg("Package <Script> tag" + FILEPATH SCRIPT "${CMake_IFW_ROOT_COMPONENT_SCRIPT_GENERATED}") +endif() +foreach(_script + CMake.Dialogs.QtGUI + CMake.Documentation.SphinxHTML + CMake.DeveloperReference.HTML) + cpack_ifw_configure_file("${CMake_SOURCE_DIR}/Source/QtIFW/${_script}.qs.in" + "${CMake_BINARY_DIR}/${_script}.qs") +endforeach() + if(NOT DEFINED CPACK_PACKAGE_FILE_NAME) # if the CPACK_PACKAGE_FILE_NAME is not defined by the cache # default to source package - system, on cygwin system is not diff --git a/CMakeCPackOptions.cmake.in b/CMakeCPackOptions.cmake.in index 99746b0..ad0c245 100644 --- a/CMakeCPackOptions.cmake.in +++ b/CMakeCPackOptions.cmake.in @@ -132,7 +132,7 @@ if(CPACK_GENERATOR MATCHES "IFW") set(CPACK_COMPONENT_CMAKE-GUI_GROUP Dialogs) set(CPACK_IFW_COMPONENT_CMAKE-GUI_NAME "QtGUI") set(CPACK_IFW_COMPONENT_CMAKE-GUI_SCRIPT - "@CMake_SOURCE_DIR@/Source/QtIFW/CMake.Dialogs.QtGUI.qs") + "@CMake_BINARY_DIR@/CMake.Dialogs.QtGUI.qs") set(CPACK_IFW_COMPONENT_CMAKE-GUI_VERSION "@CMake_IFW_ROOT_COMPONENT_VERSION@") @_CPACK_IFW_COMPONENT_CMAKE-GUI_LICENSES@ diff --git a/CMakeLists.txt b/CMakeLists.txt index 7aa8010..bec81a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -510,6 +510,9 @@ int main(void) { return 0; } elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "sparc") # Disable until it can be ported. set(CMAKE_USE_LIBUV 0) + elseif(CMAKE_SYSTEM STREQUAL "SunOS-5.10") + # Disable until it can be ported. + set(CMAKE_USE_LIBUV 0) endif() endif() if(CMAKE_USE_LIBUV) diff --git a/Copyright.txt b/Copyright.txt index aa91102..daaa1d1 100644 --- a/Copyright.txt +++ b/Copyright.txt @@ -37,6 +37,7 @@ The following individuals and institutions are among the Contributors: * Aleksey Avdeev <solo@altlinux.ru> * Alexander Neundorf <neundorf@kde.org> * Alexander Smorkalov <alexander.smorkalov@itseez.com> +* Alexey Sokolov <sokolov@google.com> * Alex Turbov <i.zaufi@gmail.com> * Andreas Pakulat <apaku@gmx.de> * Andreas Schneider <asn@cryptomilk.org> @@ -54,6 +55,7 @@ The following individuals and institutions are among the Contributors: * Eran Ifrah <eran.ifrah@gmail.com> * Esben Mose Hansen, Ange Optimization ApS * Geoffrey Viola <geoffrey.viola@asirobots.com> +* Google Inc * Gregor Jasny * Helio Chissini de Castro <helio@kde.org> * Ilya Lavrenov <ilya.lavrenov@itseez.com> diff --git a/Help/command/source_group.rst b/Help/command/source_group.rst index 6e3829c..938ca40 100644 --- a/Help/command/source_group.rst +++ b/Help/command/source_group.rst @@ -2,15 +2,27 @@ source_group ------------ Define a grouping for source files in IDE project generation. +There are two different signatures to create source groups. -.. code-block:: cmake +:: source_group(<name> [FILES <src>...] [REGULAR_EXPRESSION <regex>]) + source_group(TREE <root> [PREFIX <prefix>] [FILES <src>...]) Defines a group into which sources will be placed in project files. This is intended to set up file tabs in Visual Studio. The options are: +``TREE`` + CMake will automatically detect, from ``<src>`` files paths, source groups + it needs to create, to keep structure of source groups analogically to the + actual files and directories structure in the project. Paths of ``<src>`` + files will be cut to be relative to ``<root>``. + +``PREFIX`` + Source group and files located directly in ``<root>`` path, will be placed + in ``<prefix>`` source groups. + ``FILES`` Any source file specified explicitly will be placed in group ``<name>``. Relative paths are interpreted with respect to the @@ -25,11 +37,13 @@ explicitly lists the file with ``FILES`` will be favored, if any. If no group explicitly lists the file, the *last* group whose regular expression matches the file will be favored. -The ``<name>`` of the group may contain backslashes to specify subgroups: +The ``<name>`` of the group and ``<prefix>`` argument may contain backslashes +to specify subgroups: .. code-block:: cmake source_group(outer\\inner ...) + source_group(TREE <root> PREFIX sources\\inc ...) For backwards compatibility, the short-hand signature diff --git a/Help/generator/CodeBlocks.rst b/Help/generator/CodeBlocks.rst index 01798c7..d03cb0c 100644 --- a/Help/generator/CodeBlocks.rst +++ b/Help/generator/CodeBlocks.rst @@ -18,6 +18,9 @@ This "extra" generator may be specified as: ``CodeBlocks - NMake Makefiles`` Generate with :generator:`NMake Makefiles`. +``CodeBlocks - NMake Makefiles JOM`` + Generate with :generator:`NMake Makefiles JOM`. + ``CodeBlocks - Ninja`` Generate with :generator:`Ninja`. diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 015e36e..d4712ba 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -59,6 +59,7 @@ All Modules /module/CPackDeb /module/CPackDMG /module/CPackIFW + /module/CPackIFWConfigureFile /module/CPackNSIS /module/CPackPackageMaker /module/CPackProductBuild diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 971834e..864d1dc 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -291,7 +291,7 @@ Properties on Targets /prop_tgt/VS_SCC_PROJECTNAME /prop_tgt/VS_SCC_PROVIDER /prop_tgt/VS_SDK_REFERENCES - /prop_tgt/VS_USER_PROPS_CXX + /prop_tgt/VS_USER_PROPS /prop_tgt/VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION /prop_tgt/VS_WINRT_COMPONENT /prop_tgt/VS_WINRT_EXTENSIONS @@ -357,6 +357,10 @@ Properties on Source Files /prop_sf/MACOSX_PACKAGE_LOCATION /prop_sf/OBJECT_DEPENDS /prop_sf/OBJECT_OUTPUTS + /prop_sf/SKIP_AUTOGEN + /prop_sf/SKIP_AUTOMOC + /prop_sf/SKIP_AUTORCC + /prop_sf/SKIP_AUTOUIC /prop_sf/SYMBOLIC /prop_sf/VS_DEPLOYMENT_CONTENT /prop_sf/VS_DEPLOYMENT_LOCATION diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index 80b0f49..56d4ca7 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -83,6 +83,9 @@ following targets by setting the :variable:`CMAKE_AUTOMOC` variable. The options to pass to ``moc``. The :variable:`CMAKE_AUTOMOC_MOC_OPTIONS` variable may be populated to pre-set the options for all following targets. +Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by +enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`. + .. _`Qt AUTOUIC`: AUTOUIC @@ -149,6 +152,9 @@ result of linking with the :prop_tgt:`IMPORTED` target: Qt5::Widgets ) +Source files can be excluded from :prop_tgt:`AUTOUIC` processing by +enabling :prop_sf:`SKIP_AUTOUIC` or the broader :prop_sf:`SKIP_AUTOGEN`. + .. _`Qt AUTORCC`: AUTORCC @@ -171,6 +177,9 @@ populated to pre-set the options for all following targets. The ``<name>.qrc`` file to set particular options for the file. This overrides options from the :prop_tgt:`AUTORCC_OPTIONS` target property. +Source files can be excluded from :prop_tgt:`AUTORCC` processing by +enabling :prop_sf:`SKIP_AUTORCC` or the broader :prop_sf:`SKIP_AUTOGEN`. + qtmain.lib on Windows ===================== diff --git a/Help/module/CPackIFWConfigureFile.rst b/Help/module/CPackIFWConfigureFile.rst new file mode 100644 index 0000000..e88517c --- /dev/null +++ b/Help/module/CPackIFWConfigureFile.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CPackIFWConfigureFile.cmake diff --git a/Help/prop_sf/SKIP_AUTOGEN.rst b/Help/prop_sf/SKIP_AUTOGEN.rst new file mode 100644 index 0000000..6bf2409 --- /dev/null +++ b/Help/prop_sf/SKIP_AUTOGEN.rst @@ -0,0 +1,8 @@ +SKIP_AUTOGEN +------------ + +Exclude the source file from :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTOUIC` and +:prop_tgt:`AUTORCC` processing (for Qt projects). + +For finer control see :prop_sf:`SKIP_AUTOMOC`, :prop_sf:`SKIP_AUTOUIC` and +:prop_sf:`SKIP_AUTORCC`. diff --git a/Help/prop_sf/SKIP_AUTOMOC.rst b/Help/prop_sf/SKIP_AUTOMOC.rst new file mode 100644 index 0000000..2245ca6 --- /dev/null +++ b/Help/prop_sf/SKIP_AUTOMOC.rst @@ -0,0 +1,6 @@ +SKIP_AUTOMOC +------------ + +Exclude the source file from :prop_tgt:`AUTOMOC` processing (for Qt projects). + +For broader control see :prop_sf:`SKIP_AUTOGEN` diff --git a/Help/prop_sf/SKIP_AUTORCC.rst b/Help/prop_sf/SKIP_AUTORCC.rst new file mode 100644 index 0000000..394d8f8 --- /dev/null +++ b/Help/prop_sf/SKIP_AUTORCC.rst @@ -0,0 +1,6 @@ +SKIP_AUTORCC +------------ + +Exclude the source file from :prop_tgt:`AUTORCC` processing (for Qt projects). + +For broader control see :prop_sf:`SKIP_AUTOGEN` diff --git a/Help/prop_sf/SKIP_AUTOUIC.rst b/Help/prop_sf/SKIP_AUTOUIC.rst new file mode 100644 index 0000000..50f78ef --- /dev/null +++ b/Help/prop_sf/SKIP_AUTOUIC.rst @@ -0,0 +1,6 @@ +SKIP_AUTOUIC +------------ + +Exclude the source file from :prop_tgt:`AUTOUIC` processing (for Qt projects). + +For broader control see :prop_sf:`SKIP_AUTOGEN` diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index 30a39b1..b42643f 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -47,5 +47,8 @@ See the documentation for this variable for more details. The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group the automoc targets together in an IDE, e.g. in MSVS. +Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by +enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`. + See the :manual:`cmake-qt(7)` manual for more information on using CMake with Qt. diff --git a/Help/prop_tgt/AUTORCC.rst b/Help/prop_tgt/AUTORCC.rst index 158fdf8..1ad0895 100644 --- a/Help/prop_tgt/AUTORCC.rst +++ b/Help/prop_tgt/AUTORCC.rst @@ -24,5 +24,8 @@ generate unspecified unique names for ``rcc``. Therefore if ``Q_INIT_RESOURCE()`` or ``Q_CLEANUP_RESOURCE()`` need to be used the ``.qrc`` file name must be unique. +Source files can be excluded from :prop_tgt:`AUTORCC` processing by +enabling :prop_sf:`SKIP_AUTORCC` or the broader :prop_sf:`SKIP_AUTOGEN`. + See the :manual:`cmake-qt(7)` manual for more information on using CMake with Qt. diff --git a/Help/prop_tgt/AUTOUIC.rst b/Help/prop_tgt/AUTOUIC.rst index 4e60ec3..fbf24c3 100644 --- a/Help/prop_tgt/AUTOUIC.rst +++ b/Help/prop_tgt/AUTOUIC.rst @@ -20,5 +20,8 @@ Additional command line options for ``uic`` can be set via the The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group the autouic targets together in an IDE, e.g. in MSVS. +Source files can be excluded from :prop_tgt:`AUTOUIC` processing by +enabling :prop_sf:`SKIP_AUTOUIC` or the broader :prop_sf:`SKIP_AUTOGEN`. + See the :manual:`cmake-qt(7)` manual for more information on using CMake with Qt. diff --git a/Help/prop_tgt/VS_USER_PROPS_CXX.rst b/Help/prop_tgt/VS_USER_PROPS.rst index 083ce03..1be222b 100644 --- a/Help/prop_tgt/VS_USER_PROPS_CXX.rst +++ b/Help/prop_tgt/VS_USER_PROPS.rst @@ -1,5 +1,5 @@ -VS_USER_PROPS_CXX ------------------ +VS_USER_PROPS +------------- Sets the user props file to be included in the visual studio C++ project file. The standard path is diff --git a/Help/release/dev/QtAutogen_Skip.rst b/Help/release/dev/QtAutogen_Skip.rst new file mode 100644 index 0000000..37f795c --- /dev/null +++ b/Help/release/dev/QtAutogen_Skip.rst @@ -0,0 +1,12 @@ +QtAutogen_Skip +-------------- + +* The source file properties + :prop_sf:`SKIP_AUTOMOC`, + :prop_sf:`SKIP_AUTOUIC`, + :prop_sf:`SKIP_AUTORCC` and + :prop_sf:`SKIP_AUTOGEN` + allow to exclude files from + :prop_tgt:`AUTOMOC`, + :prop_tgt:`AUTOUIC` and + :prop_tgt:`AUTORCC` processing. diff --git a/Help/release/dev/SublimeText-no-VERBOSE.rst b/Help/release/dev/SublimeText-no-VERBOSE.rst new file mode 100644 index 0000000..70dfa2b --- /dev/null +++ b/Help/release/dev/SublimeText-no-VERBOSE.rst @@ -0,0 +1,6 @@ +SublimeText-no-VERBOSE +---------------------- + +* The :generator:`Sublime Text 2` generator no longer runs the native + build command (e.g. ``ninja`` or ``make``) with verbose build output + enabled. diff --git a/Help/release/dev/codeblocks-nmake-makefiles-jom.rst b/Help/release/dev/codeblocks-nmake-makefiles-jom.rst new file mode 100644 index 0000000..f5612f0 --- /dev/null +++ b/Help/release/dev/codeblocks-nmake-makefiles-jom.rst @@ -0,0 +1,5 @@ +codeblocks-nmake-makefiles-jom +------------------------------ + +* The :generator:`CodeBlocks` now can generate with + :generator:`NMake Makefiles JOM`. diff --git a/Help/release/dev/cpack-ifw-configure-file.rst b/Help/release/dev/cpack-ifw-configure-file.rst new file mode 100644 index 0000000..c9a1220 --- /dev/null +++ b/Help/release/dev/cpack-ifw-configure-file.rst @@ -0,0 +1,9 @@ +cpack-ifw-configure-file +------------------------ + +* The :command:`cpack_ifw_configure_file` command was added + (in :module:`CPackIFWConfigureFile`) to configure file templates prepared + in QtIFW/SDK/Creator style. + +* The :module:`CPackIFWConfigureFile` module was added to define + :command:`cpack_ifw_configure_file` command. diff --git a/Help/release/dev/ctest_memcheck-leak_sanitizer.rst b/Help/release/dev/ctest_memcheck-leak_sanitizer.rst new file mode 100644 index 0000000..3fa5c49 --- /dev/null +++ b/Help/release/dev/ctest_memcheck-leak_sanitizer.rst @@ -0,0 +1,19 @@ +ctest_memcheck-leak_sanitizer +============================= + +* The :command:`ctest_memcheck` command learned to support ``LeakSanitizer`` + independently from ``AddressSanitizer``. + +* The :command:`ctest_memcheck` command no longer automatically adds + ``leak_check=1`` to the options used by ``AddressSanitizer``. The default + behavior of ``AddressSanitizer`` is to run `LeakSanitizer` to check leaks + unless ``leak_check=0``. + +* The :command:`ctest_memcheck` command learned to read the location of + suppressions files for sanitizers from the + :variable:`CTEST_MEMORYCHECK_SUPPRESSIONS_FILE` variable. + +* The :command:`ctest_memcheck` command was fixed to correctly append extra + sanitizer options read from the + :variable:`CTEST_MEMORYCHECK_SANITIZER_OPTIONS` variable to the environment + variables used internally by the sanitizers. diff --git a/Help/release/dev/source_group-tree.rst b/Help/release/dev/source_group-tree.rst new file mode 100644 index 0000000..c5fec1d --- /dev/null +++ b/Help/release/dev/source_group-tree.rst @@ -0,0 +1,5 @@ +source_group-tree +----------------- + +* The :command:`source_group` command gained ``TREE`` and ``PREFIX`` + options to add groups following source tree directory structure. diff --git a/Help/release/dev/vs-csharp-support.rst b/Help/release/dev/vs-csharp-support.rst new file mode 100644 index 0000000..26d8574 --- /dev/null +++ b/Help/release/dev/vs-csharp-support.rst @@ -0,0 +1,25 @@ +vs-native-csharp-support +------------------------ + +* The :ref:`Visual Studio Generators` for VS 2010 and above + learned to support the C# language. C# assemblies and + programs can be added just like common C++ targets using + the :command:`add_library` and :command:`add_executable` + commands. Referencing between several C# targets in the same + source tree is done by :command:`target_link_libraries` like + for C++. Referencing to system or 3rd party assemblies is + done by the target properties :prop_tgt:`VS_DOTNET_REFERENCE_<refname>` + and :prop_tgt:`VS_DOTNET_REFERENCES`. + +* C# as a language can be enabled using :command:`enable_language` + or :command:`project` with ``CSharp``. It is not enabled by + default. + +* Flag variables, target properties and other configuration + that specifically targets C# contains ``CSharp`` as a part of + their names. + +* More finetuning of C# targets can be done using target + properties. Specifically the Visual Studio related target + properties (``VS_*``) are worth a look (for setting toolset + versions, root namespaces, assembly icons, ...). diff --git a/Help/release/dev/vs-custom-msbuild-props.rst b/Help/release/dev/vs-custom-msbuild-props.rst index 15a5b0a..68dae42 100644 --- a/Help/release/dev/vs-custom-msbuild-props.rst +++ b/Help/release/dev/vs-custom-msbuild-props.rst @@ -3,7 +3,7 @@ vs-custom-msbuild-props * The :ref:`Visual Studio Generators` for VS 2010 and above can now be fine tuned using custom msbuild .props files. - :prop_tgt:`VS_USER_PROPS_CXX` can be + :prop_tgt:`VS_USER_PROPS` can be used to change the default path of the user .props file from ``$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props`` to an arbitrary filename. diff --git a/Help/variable/CTEST_MEMORYCHECK_TYPE.rst b/Help/variable/CTEST_MEMORYCHECK_TYPE.rst index b963293..b8b4c30 100644 --- a/Help/variable/CTEST_MEMORYCHECK_TYPE.rst +++ b/Help/variable/CTEST_MEMORYCHECK_TYPE.rst @@ -4,5 +4,5 @@ CTEST_MEMORYCHECK_TYPE Specify the CTest ``MemoryCheckType`` setting in a :manual:`ctest(1)` dashboard client script. Valid values are ``Valgrind``, ``Purify``, ``BoundsChecker``, and -``ThreadSanitizer``, ``AddressSanitizer``, ``MemorySanitizer``, and +``ThreadSanitizer``, ``AddressSanitizer``, ``LeakSanitizer``, ``MemorySanitizer``, and ``UndefinedBehaviorSanitizer``. diff --git a/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake b/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake index f5f2564..d8ca730 100644 --- a/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake +++ b/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake @@ -117,7 +117,7 @@ function(android_push_test_files_to_device) check_device_file_exists(${_ptd_DEV_TEST_DIR} test_dir_exists) if(test_dir_exists) # This is protected in the SetupProjectTests module. - execute_adb_command(shell echo rm -r ${_ptd_DEV_TEST_DIR} | su) + execute_adb_command(shell rm -r ${_ptd_DEV_TEST_DIR}) endif() execute_adb_command(shell mkdir -p ${_ptd_DEV_TEST_DIR}) diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 84b0f4d..3fafaff 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,7 +1,7 @@ -set(AM_SOURCES @_cpp_files@ ) -set(AM_SKIP_MOC @_skip_moc@ ) -set(AM_SKIP_UIC @_skip_uic@ ) -set(AM_HEADERS @_moc_headers@ ) +set(AM_SOURCES @_moc_uic_sources@) +set(AM_HEADERS @_moc_uic_headers@) +set(AM_SKIP_MOC @_skip_moc@) +set(AM_SKIP_UIC @_skip_uic@) set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) set(AM_MOC_INCLUDES @_moc_incs@) set(AM_MOC_OPTIONS @_moc_options@) diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index b1610e2..5d6f402 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -624,6 +624,33 @@ function(get_bundle_keys app libs dirs keys_var) endif() endforeach() + # preserve library symlink structure + foreach(key ${${keys_var}}) + if("${${key}_COPYFLAG}" STREQUAL 1) + if(IS_SYMLINK "${${key}_RESOLVED_ITEM}") + get_filename_component(target "${${key}_RESOLVED_ITEM}" REALPATH) + set_bundle_key_values(${keys_var} "${exe}" "${target}" "${exepath}" "${dirs}" 1 "${exe_rpaths}") + get_item_key("${target}" targetkey) + + if(WIN32) + # ignore case on Windows + string(TOLOWER "${${key}_RESOLVED_ITEM}" resolved_item_compare) + string(TOLOWER "${${targetkey}_RESOLVED_EMBEDDED_ITEM}" resolved_embedded_item_compare) + else() + set(resolved_item_compare "${${key}_RESOLVED_ITEM}") + set(resolved_embedded_item_compare "${${targetkey}_RESOLVED_EMBEDDED_ITEM}") + endif() + get_filename_component(resolved_item_compare "${resolved_item_compare}" NAME) + get_filename_component(resolved_embedded_item_compare "${resolved_embedded_item_compare}" NAME) + + if(NOT "${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}") + set(${key}_COPYFLAG "2") + set(${key}_RESOLVED_ITEM "${${targetkey}_RESOLVED_EMBEDDED_ITEM}") + endif() + + endif() + endif() + endforeach() # Propagate values to caller's scope: # set(${keys_var} ${${keys_var}} PARENT_SCOPE) @@ -640,6 +667,24 @@ function(get_bundle_keys app libs dirs keys_var) endif() endfunction() +function(link_resolved_item_into_bundle resolved_item resolved_embedded_item) + if(WIN32) + # ignore case on Windows + string(TOLOWER "${resolved_item}" resolved_item_compare) + string(TOLOWER "${resolved_embedded_item}" resolved_embedded_item_compare) + else() + set(resolved_item_compare "${resolved_item}") + set(resolved_embedded_item_compare "${resolved_embedded_item}") + endif() + + if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}") + message(STATUS "warning: resolved_item == resolved_embedded_item - not linking...") + else() + get_filename_component(target_dir "${resolved_embedded_item}" DIRECTORY) + file(RELATIVE_PATH symlink_target "${target_dir}" "${resolved_item}") + execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${symlink_target}" "${resolved_embedded_item}") + endif() +endfunction() function(copy_resolved_item_into_bundle resolved_item resolved_embedded_item) if(WIN32) @@ -854,7 +899,9 @@ function(fixup_bundle app libs dirs) set(i 0) foreach(key ${keys}) math(EXPR i ${i}+1) - if(${${key}_COPYFLAG}) + if("${${key}_COPYFLAG}" STREQUAL "2") + message(STATUS "${i}/${n}: linking '${${key}_RESOLVED_ITEM}' -> '${${key}_RESOLVED_EMBEDDED_ITEM}'") + elseif(${${key}_COPYFLAG}) message(STATUS "${i}/${n}: copying '${${key}_RESOLVED_ITEM}'") else() message(STATUS "${i}/${n}: *NOT* copying '${${key}_RESOLVED_ITEM}'") @@ -872,7 +919,10 @@ function(fixup_bundle app libs dirs) message(STATUS "") endif() - if(${${key}_COPYFLAG}) + if("${${key}_COPYFLAG}" STREQUAL "2") + link_resolved_item_into_bundle("${${key}_RESOLVED_ITEM}" + "${${key}_RESOLVED_EMBEDDED_ITEM}") + elseif(${${key}_COPYFLAG}) set(item "${${key}_ITEM}") if(item MATCHES "[^/]+\\.framework/") copy_resolved_framework_into_bundle("${${key}_RESOLVED_ITEM}" @@ -889,7 +939,9 @@ function(fixup_bundle app libs dirs) math(EXPR i ${i}+1) if(APPLE) message(STATUS "${i}/${n}: fixing up '${${key}_RESOLVED_EMBEDDED_ITEM}'") - fixup_bundle_item("${${key}_RESOLVED_EMBEDDED_ITEM}" "${exepath}" "${dirs}") + if(NOT "${${key}_COPYFLAG}" STREQUAL "2") + fixup_bundle_item("${${key}_RESOLVED_EMBEDDED_ITEM}" "${exepath}" "${dirs}") + endif() else() message(STATUS "${i}/${n}: fix-up not required on this platform '${${key}_RESOLVED_EMBEDDED_ITEM}'") endif() diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake index 3b39bce..4649f35 100644 --- a/Modules/CMakeAddFortranSubdirectory.cmake +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -45,7 +45,6 @@ set(_MS_MINGW_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) include(CheckLanguage) include(ExternalProject) -include(CMakeParseArguments) function(_setup_mingw_config_and_build source_dir build_dir) # Look for a MinGW gfortran. diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in index 8a6c0bc..7e8efa7 100644 --- a/Modules/CMakeCUDACompiler.cmake.in +++ b/Modules/CMakeCUDACompiler.cmake.in @@ -4,12 +4,17 @@ set(CMAKE_CUDA_HOST_LINK_LAUNCHER "@CMAKE_CUDA_HOST_LINK_LAUNCHER@") set(CMAKE_CUDA_COMPILER_ID "@CMAKE_CUDA_COMPILER_ID@") set(CMAKE_CUDA_COMPILER_VERSION "@CMAKE_CUDA_COMPILER_VERSION@") set(CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT "@CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_CUDA_SIMULATE_ID "@CMAKE_CUDA_SIMULATE_ID@") +set(CMAKE_CUDA_SIMULATE_VERSION "@CMAKE_CUDA_SIMULATE_VERSION@") +@SET_MSVC_CUDA_ARCHITECTURE_ID@ set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX") set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX") set(CMAKE_CUDA_COMPILER_ID_RUN 1) set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu) +set(CMAKE_CUDA_LINKER_PREFERENCE 10) +set(CMAKE_CUDA_LINKER_PREFERENCE_PROPAGATES 1) set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "@CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES@") diff --git a/Modules/CMakeCUDACompilerId.cu.in b/Modules/CMakeCUDACompilerId.cu.in index a20f1b1..018bab7 100644 --- a/Modules/CMakeCUDACompilerId.cu.in +++ b/Modules/CMakeCUDACompilerId.cu.in @@ -9,6 +9,9 @@ because some compilers will just produce instructions to fill the array rather than assigning a pointer to a static array. */ char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif @CMAKE_CUDA_COMPILER_ID_PLATFORM_CONTENT@ @CMAKE_CUDA_COMPILER_ID_ERROR_FOR_TEST@ @@ -35,6 +38,12 @@ int main(int argc, char* argv[]) #ifdef COMPILER_VERSION_MAJOR require += info_version[argc]; #endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif require += info_language_dialect_default[argc]; (void)argv; return require; diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index 202a7a6..13b1789 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -1,7 +1,11 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -set(CMAKE_CUDA_OUTPUT_EXTENSION .o) +if(UNIX) + set(CMAKE_CUDA_OUTPUT_EXTENSION .o) +else() + set(CMAKE_CUDA_OUTPUT_EXTENSION .obj) +endif() set(CMAKE_INCLUDE_FLAG_CUDA "-I") # Load compiler-specific information. @@ -177,11 +181,14 @@ if(NOT CMAKE_CUDA_LINK_EXECUTABLE) endif() #These are used when linking relocatable (dc) cuda code -set(CMAKE_CUDA_DEVICE_LINK_LIBRARY - "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") -set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE - "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") - +if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY) + set(CMAKE_CUDA_DEVICE_LINK_LIBRARY + "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") +endif() +if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE) + set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE + "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") +endif() mark_as_advanced( CMAKE_CUDA_FLAGS diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index 484e1f0..7ca79bd 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -11,8 +11,6 @@ function(_readFile file) set(_compiler_id_pp_test_${CompilerId} ${_compiler_id_pp_test} PARENT_SCOPE) endfunction() -include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) - function(compiler_id_detection outvar lang) if (NOT lang STREQUAL Fortran AND NOT lang STREQUAL CSharp) diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index e03de7e..bef6d0e 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -60,7 +60,7 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdCUDA/(\\./)?(CompilerIdCUDA.xctest/)?CompilerIdCUDA[ \t\n\\\"]") set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_INDEX 2) - set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-v") + set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS -v --keep --keep-dir tmp) if(CMAKE_CUDA_HOST_COMPILER) list(APPEND CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-ccbin=${CMAKE_CUDA_HOST_COMPILER}") endif() @@ -70,6 +70,10 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) endif() include(CMakeFindBinUtils) +if(MSVC_CUDA_ARCHITECTURE_ID) + set(SET_MSVC_CUDA_ARCHITECTURE_ID + "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})") +endif() #if this compiler vendor is matches NVIDIA we can determine #what the host compiler is. This only needs to be done if the CMAKE_CUDA_HOST_COMPILER @@ -102,6 +106,14 @@ if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) if("${_nvcc_output_line}" MATCHES "^ *nvlink") string(APPEND _nvcc_log " ignoring nvlink line\n") elseif(_nvcc_libraries) + if("${_nvcc_output_line}" MATCHES "(@\"?tmp/a\\.exe\\.res\"?)") + set(_nvcc_link_res_arg "${CMAKE_MATCH_1}") + set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/tmp/a.exe.res") + if(EXISTS "${_nvcc_link_res}") + file(READ "${_nvcc_link_res}" _nvcc_link_res_content) + string(REPLACE "${_nvcc_link_res_arg}" "${_nvcc_link_res_content}" _nvcc_output_line "${_nvcc_output_line}") + endif() + endif() string(FIND "${_nvcc_output_line}" "${_nvcc_libraries}" _nvcc_libraries_pos) if(NOT _nvcc_libraries_pos EQUAL -1) set(_nvcc_link_line "${_nvcc_output_line}") @@ -112,9 +124,13 @@ if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) endif() if(_nvcc_link_line) - #extract the compiler that is being used for linking - separate_arguments(_nvcc_link_line_args UNIX_COMMAND "${_nvcc_link_line}") - list(GET _nvcc_link_line_args 0 CMAKE_CUDA_HOST_LINK_LAUNCHER) + if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") + set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}") + else() + #extract the compiler that is being used for linking + separate_arguments(_nvcc_link_line_args UNIX_COMMAND "${_nvcc_link_line}") + list(GET _nvcc_link_line_args 0 CMAKE_CUDA_HOST_LINK_LAUNCHER) + endif() #prefix the line with cuda-fake-ld so that implicit link info believes it is #a link line diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index eae139d..bb34de5 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -131,6 +131,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src) # Create a clean working directory. file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR}) file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}) + file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}/tmp) CMAKE_DETERMINE_COMPILER_ID_WRITE("${lang}" "${src}") # Construct a description of this test case. diff --git a/Modules/CMakeExpandImportedTargets.cmake b/Modules/CMakeExpandImportedTargets.cmake index add0c6d..ad065f0 100644 --- a/Modules/CMakeExpandImportedTargets.cmake +++ b/Modules/CMakeExpandImportedTargets.cmake @@ -37,9 +37,6 @@ # LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} # CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}" ) - -include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) - function(CMAKE_EXPAND_IMPORTED_TARGETS _RESULT ) set(options ) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 75a031e..4c0486e 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -25,6 +25,7 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" OR "x${CMAKE_Fortran_SIMULATE_ID}" STREQUAL "xMSVC" OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC" OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" + OR "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC" OR (CMAKE_GENERATOR MATCHES "Visual Studio" AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android")) diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake index 8415641..3210222 100644 --- a/Modules/CMakePackageConfigHelpers.cmake +++ b/Modules/CMakePackageConfigHelpers.cmake @@ -201,9 +201,6 @@ # # check_required_components(Foo) - -include(CMakeParseArguments) - include(WriteBasicConfigVersionFile) macro(WRITE_BASIC_PACKAGE_VERSION_FILE) diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index 2031ba5..3469d34 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -45,6 +45,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj endif() list(GET args 0 cmd) endif() + set(is_msvc 0) if("${cmd}" MATCHES "${linker_regex}") string(APPEND log " link line: [${line}]\n") string(REGEX REPLACE ";-([LYz]);" ";-\\1" args "${args}") @@ -54,6 +55,17 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj string(REGEX REPLACE "^-L" "" dir "${arg}") list(APPEND implicit_dirs_tmp ${dir}) string(APPEND log " arg [${arg}] ==> dir [${dir}]\n") + elseif("${arg}" MATCHES "^[-/]LIBPATH:(.+)") + # MSVC search path. + set(dir "${CMAKE_MATCH_1}") + list(APPEND implicit_dirs_tmp ${dir}) + string(APPEND log " arg [${arg}] ==> dir [${dir}]\n") + elseif(is_msvc AND "${arg}" STREQUAL "-link") + string(APPEND log " arg [${arg}] ==> ignore MSVC cl option\n") + elseif(is_msvc AND "${arg}" MATCHES "^(.*\\.[Ll][Ii][Bb])$") + set(lib "${CMAKE_MATCH_1}") + list(APPEND implicit_libs_tmp ${lib}) + string(APPEND log " arg [${arg}] ==> lib [${lib}]\n") elseif("${arg}" MATCHES "^-l([^:].*)$") # Unix library. set(lib "${CMAKE_MATCH_1}") @@ -82,6 +94,9 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj # Link editor option. list(APPEND implicit_libs_tmp ${arg}) string(APPEND log " arg [${arg}] ==> opt [${arg}]\n") + elseif("${arg}" STREQUAL "cl.exe") + string(APPEND log " arg [${arg}] ==> recognize MSVC cl\n") + set(is_msvc 1) else() string(APPEND log " arg [${arg}] ==> ignore\n") endif() diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake index bf98a42..21c333e 100644 --- a/Modules/CMakePrintHelpers.cmake +++ b/Modules/CMakePrintHelpers.cmake @@ -39,8 +39,6 @@ # # -- CMAKE_C_COMPILER="/usr/bin/gcc" ; CMAKE_MAJOR_VERSION="2" ; DOES_NOT_EXIST="" -include(CMakeParseArguments) - function(CMAKE_PRINT_VARIABLES) set(msg "") foreach(var ${ARGN}) diff --git a/Modules/CMakeTestCSharpCompiler.cmake b/Modules/CMakeTestCSharpCompiler.cmake index 21b7236..1a8bf32 100644 --- a/Modules/CMakeTestCSharpCompiler.cmake +++ b/Modules/CMakeTestCSharpCompiler.cmake @@ -34,10 +34,6 @@ if(NOT CMAKE_CSharp_COMPILER_WORKS) # Move result from cache to normal variable. set(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_CSharp_COMPILER_WORKS}) unset(CMAKE_CSharp_COMPILER_WORKS CACHE) - if(NOT CMAKE_CSharp_COMPILER_WORKS) - message("forcing compiler works to true (will be removed once C# support is integrated)") - set(CMAKE_CSharp_COMPILER_WORKS 1) - endif() set(CSharp_TEST_WAS_RUN 1) endif() diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake index 670b31d..80113cb 100644 --- a/Modules/CMakeTestCUDACompiler.cmake +++ b/Modules/CMakeTestCUDACompiler.cmake @@ -58,6 +58,11 @@ else() include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) CMAKE_DETERMINE_COMPILER_ABI(CUDA ${CMAKE_ROOT}/Modules/CMakeCUDACompilerABI.cu) + if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") + set(CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES "${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES}") + set(CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES "${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}") + endif() + # Re-configure to save learned information. configure_file( ${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake index d0d24ba..b3ab055 100644 --- a/Modules/CPackIFW.cmake +++ b/Modules/CPackIFW.cmake @@ -630,10 +630,6 @@ if(NOT CPackComponent_CMake_INCLUDED) include(CPackComponent) endif() -if(NOT __CMAKE_PARSE_ARGUMENTS_INCLUDED) - include(CMakeParseArguments) -endif() - # Resolve full filename for script file macro(_cpack_ifw_resolve_script _variable) set(_ifw_script_macro ${_variable}) diff --git a/Modules/CPackIFWConfigureFile.cmake b/Modules/CPackIFWConfigureFile.cmake new file mode 100644 index 0000000..790574a --- /dev/null +++ b/Modules/CPackIFWConfigureFile.cmake @@ -0,0 +1,65 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# CPackIFWConfigureFile +# --------------------- +# +# The module defines :command:`configure_file` similar command to +# configure file templates prepared in QtIFW/SDK/Creator style. +# +# +# Commands +# ^^^^^^^^ +# +# The module defines the following commands: +# +# .. command:: cpack_ifw_configure_file +# +# Copy a file to another location and modify its contents. +# +# :: +# +# cpack_ifw_configure_file(<input> <output>) +# +# Copies an ``<input>`` file to an ``<output>`` file and substitutes variable +# values referenced as ``%{VAR}`` or ``%VAR%`` in the input file content. +# Each variable reference will be replaced with the current value of the +# variable, or the empty string if the variable is not defined. +# + +# NOTE: This file used to himself packaging via CPack IFW generator and +# should be compatible with minimal CMake version defined in +# ../CMakeLists.txt file. + +if(NOT DEFINED CPackIFWConfigureFile_CMake_INCLUDED) +set(CPackIFWConfigureFile_CMake_INCLUDED 1) + +macro(cpack_ifw_configure_file INPUT OUTPUT) + file(READ "${INPUT}" _tmp) + foreach(_tmp_regex "%{([^%}]+)}" "%([^%]+)%") + string(REGEX MATCHALL "${_tmp_regex}" _tmp_vars "${_tmp}") + while(_tmp_vars) + foreach(_tmp_var ${_tmp_vars}) + string(REGEX REPLACE "${_tmp_regex}" "\\1" + _tmp_var_name "${_tmp_var}") + if(DEFINED ${_tmp_var_name}) + set(_tmp_var_value "${${_tmp_var_name}}") + elseif(NOT "$ENV{${_tmp_var_name}}" STREQUAL "") + set(_tmp_var_value "$ENV{${_tmp_var_name}}") + else() + set(_tmp_var_value "") + endif() + string(REPLACE "${_tmp_var}" "${_tmp_var_value}" _tmp "${_tmp}") + endforeach() + string(REGEX MATCHALL "${_tmp_regex}" _tmp_vars "${_tmp}") + endwhile() + endforeach() + if(IS_ABSOLUTE "${OUTPUT}") + file(WRITE "${OUTPUT}" "${_tmp}") + else() + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT}" "${_tmp}") + endif() +endmacro() + +endif() # NOT DEFINED CPackIFWConfigureFile_CMake_INCLUDED diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake index 5021c41..722ee15 100644 --- a/Modules/CPackRPM.cmake +++ b/Modules/CPackRPM.cmake @@ -2473,8 +2473,8 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ # We should generate a USER spec file template: # - either because the user asked for it : CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE # - or the user did not provide one : NOT CPACK_RPM_USER_BINARY_SPECFILE + set(RPMBUILD_FLAGS "-bb") if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE OR NOT CPACK_RPM_USER_BINARY_SPECFILE) - set(RPMBUILD_FLAGS "-bb") file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in "# -*- rpm-spec -*- diff --git a/Modules/CTestCoverageCollectGCOV.cmake b/Modules/CTestCoverageCollectGCOV.cmake index 8451a6a..1203be4 100644 --- a/Modules/CTestCoverageCollectGCOV.cmake +++ b/Modules/CTestCoverageCollectGCOV.cmake @@ -65,7 +65,6 @@ # Suppress non-error messages that otherwise would have been # printed out by this function. -include(CMakeParseArguments) function(ctest_coverage_collect_gcov) set(options QUIET GLOB DELETE) set(oneValueArgs TARBALL SOURCE BUILD GCOV_COMMAND) diff --git a/Modules/CheckFunctionExists.cmake b/Modules/CheckFunctionExists.cmake index 5f049e7..ef08062 100644 --- a/Modules/CheckFunctionExists.cmake +++ b/Modules/CheckFunctionExists.cmake @@ -5,18 +5,16 @@ # CheckFunctionExists # ------------------- # -# Check if a C function can be linked +# Check if a C function can be linked:: # -# CHECK_FUNCTION_EXISTS(<function> <variable>) +# check_function_exists(<function> <variable>) # -# Check that the <function> is provided by libraries on the system and -# store the result in a <variable>. This does not verify that any -# system header file declares the function, only that it can be found at -# link time (consider using CheckSymbolExists). -# <variable> will be created as an internal cache variable. +# Check that the ``<function>`` is provided by libraries on the system and store +# the result in a ``<variable>``. ``<variable>`` will be created as an internal +# cache variable. # -# The following variables may be set before calling this macro to modify -# the way the check is run: +# The following variables may be set before calling this macro to modify the +# way the check is run: # # :: # @@ -25,6 +23,20 @@ # CMAKE_REQUIRED_INCLUDES = list of include directories # CMAKE_REQUIRED_LIBRARIES = list of libraries to link # CMAKE_REQUIRED_QUIET = execute quietly without messages +# +# .. note:: +# +# Prefer using :Module:`CheckSymbolExists` instead of this module, +# for the following reasons: +# +# * ``check_function_exists()`` can't detect functions that are inlined +# in headers or specified as a macro. +# +# * ``check_function_exists()`` can't detect anything in the 32-bit +# versions of the Win32 API, because of a mismatch in calling conventions. +# +# * ``check_function_exists()`` only verifies linking, it does not verify +# that the function is declared in system headers. macro(CHECK_FUNCTION_EXISTS FUNCTION VARIABLE) if(NOT DEFINED "${VARIABLE}" OR "x${${VARIABLE}}" STREQUAL "x${VARIABLE}") diff --git a/Modules/Compiler/Clang-CXX-FeatureTests.cmake b/Modules/Compiler/Clang-CXX-FeatureTests.cmake index df2e1a8..cd04190 100644 --- a/Modules/Compiler/Clang-CXX-FeatureTests.cmake +++ b/Modules/Compiler/Clang-CXX-FeatureTests.cmake @@ -2,7 +2,7 @@ # Reference: http://clang.llvm.org/cxx_status.html # http://clang.llvm.org/docs/LanguageExtensions.html -set(_cmake_oldestSupported "((__clang_major__ * 100) + __clang_minor__) >= 304") +set(_cmake_oldestSupported "((__clang_major__ * 100) + __clang_minor__) >= 301") include("${CMAKE_CURRENT_LIST_DIR}/Clang-CXX-TestableFeatures.cmake") @@ -15,7 +15,6 @@ set(_cmake_feature_test_cxx_digit_separators "${Clang34_CXX14}") # http://llvm.org/bugs/show_bug.cgi?id=19674 set(_cmake_feature_test_cxx_generic_lambdas "${Clang34_CXX14}") -# TODO: Should be supported by Clang 3.1 set(Clang31_CXX11 "${_cmake_oldestSupported} && __cplusplus >= 201103L") set(_cmake_feature_test_cxx_enum_forward_declarations "${Clang31_CXX11}") set(_cmake_feature_test_cxx_sizeof_member "${Clang31_CXX11}") diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index d0e2521..8ed3695 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -36,7 +36,7 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() -if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1) if (NOT CMAKE_CXX_COMPILER_FORCED) if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT) message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}") @@ -50,14 +50,14 @@ endif() macro(cmake_record_cxx_compile_features) set(_result 0) - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1) if(_result EQUAL 0 AND CMAKE_CXX17_STANDARD_COMPILE_OPTION) _record_compiler_features_cxx(17) endif() if(_result EQUAL 0 AND CMAKE_CXX14_STANDARD_COMPILE_OPTION) _record_compiler_features_cxx(14) endif() - if (_result EQUAL 0) + if (_result EQUAL 0 AND CMAKE_CXX11_STANDARD_COMPILE_OPTION) _record_compiler_features_cxx(11) endif() if (_result EQUAL 0) diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index 605d555..ae35132 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -1,14 +1,15 @@ set(CMAKE_CUDA_VERBOSE_FLAG "-v") - -set(CMAKE_CUDA_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE) -set(CMAKE_CUDA_COMPILE_OPTIONS_PIC -Xcompiler=-fPIC) -#CMAKE_SHARED_LIBRARY_CUDA_FLAGS is sent to the host linker so we don' need -#to forward it through nvcc -set(CMAKE_SHARED_LIBRARY_CUDA_FLAGS -fPIC) +if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") + set(CMAKE_CUDA_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE) + set(CMAKE_CUDA_COMPILE_OPTIONS_PIC -Xcompiler=-fPIC) + set(CMAKE_CUDA_COMPILE_OPTIONS_VISIBILITY -Xcompiler=-fvisibility=) + # CMAKE_SHARED_LIBRARY_CUDA_FLAGS is sent to the host linker so we + # don't need to forward it through nvcc. + set(CMAKE_SHARED_LIBRARY_CUDA_FLAGS -fPIC) +endif() set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS -shared) set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=) -set(CMAKE_CUDA_COMPILE_OPTIONS_VISIBILITY -Xcompiler=-fvisibility=) string(APPEND CMAKE_CUDA_FLAGS_INIT " ") string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -g") @@ -16,9 +17,12 @@ string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG") string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") -set(CMAKE_CUDA98_STANDARD_COMPILE_OPTION "") -set(CMAKE_CUDA98_EXTENSION_COMPILE_OPTION "") -set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "-std=c++11") -set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "-std=c++11") - -set(CMAKE_CUDA_STANDARD_DEFAULT 98) +if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") + set(CMAKE_CUDA_STANDARD_DEFAULT "") +else() + set(CMAKE_CUDA_STANDARD_DEFAULT 98) + set(CMAKE_CUDA98_STANDARD_COMPILE_OPTION "") + set(CMAKE_CUDA98_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "-std=c++11") + set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "-std=c++11") +endif() diff --git a/Modules/Compiler/NVIDIA-DetermineCompiler.cmake b/Modules/Compiler/NVIDIA-DetermineCompiler.cmake index 32ccf8a..cb0beaf 100644 --- a/Modules/Compiler/NVIDIA-DetermineCompiler.cmake +++ b/Modules/Compiler/NVIDIA-DetermineCompiler.cmake @@ -4,4 +4,14 @@ set(_compiler_id_pp_test "defined(__NVCC__)") set(_compiler_id_version_compute " # define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__CUDACC_VER_MAJOR__) # define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__CUDACC_VER_MINOR__) -# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__CUDACC_VER_BUILD__)") +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__CUDACC_VER_BUILD__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define @PREFIX@SIMULATE_VERSION_MAJOR @MACRO_DEC@(_MSC_VER / 100) +# define @PREFIX@SIMULATE_VERSION_MINOR @MACRO_DEC@(_MSC_VER % 100) +# endif") + +set(_compiler_id_simulate " +# if defined(_MSC_VER) +# define @PREFIX@SIMULATE_ID \"MSVC\" +# endif") diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake index 88bc1c8..78d9df3 100644 --- a/Modules/FeatureSummary.cmake +++ b/Modules/FeatureSummary.cmake @@ -26,9 +26,6 @@ Functions #]=======================================================================] -include("${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake") - - function(_FS_GET_FEATURE_SUMMARY _property _var _includeQuiet) set(_type "ANY") diff --git a/Modules/FindBISON.cmake b/Modules/FindBISON.cmake index 0ebd465..d684ccd 100644 --- a/Modules/FindBISON.cmake +++ b/Modules/FindBISON.cmake @@ -84,8 +84,6 @@ find_program(BISON_EXECUTABLE NAMES bison win_bison DOC "path to the bison executable") mark_as_advanced(BISON_EXECUTABLE) -include(CMakeParseArguments) - if(BISON_EXECUTABLE) # the bison commands should be executed with the C locale, otherwise # the message (which are parsed) may be translated diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index e6bf3dc..266d135 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -742,6 +742,21 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) + elseif(NOT Boost_VERSION VERSION_LESS 106300 AND Boost_VERSION VERSION_LESS 106400) + set(_Boost_CHRONO_DEPENDENCIES system) + set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) + set(_Boost_COROUTINE_DEPENDENCIES context system) + set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) + set(_Boost_FILESYSTEM_DEPENDENCIES system) + set(_Boost_IOSTREAMS_DEPENDENCIES regex) + set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) + set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) + set(_Boost_MPI_DEPENDENCIES serialization) + set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) + set(_Boost_RANDOM_DEPENDENCIES system) + set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) + set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) + set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) else() message(WARNING "Imported targets not available for Boost version ${Boost_VERSION}") set(_Boost_IMPORTED_TARGETS FALSE) @@ -877,7 +892,7 @@ endfunction() # This function would append corresponding directories if MSVC is a current compiler, # so having `BOOST_ROOT` would be enough to specify to find everything. # -macro(_Boost_UPDATE_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir) +macro(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir) if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_arch_suffix 64) @@ -885,19 +900,19 @@ macro(_Boost_UPDATE_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar base set(_arch_suffix 32) endif() if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) - list(APPEND ${componentlibvar} ${${basedir}}/lib${_arch_suffix}-msvc-15.0) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-15.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19) - list(APPEND ${componentlibvar} ${${basedir}}/lib${_arch_suffix}-msvc-14.0) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18) - list(APPEND ${componentlibvar} ${${basedir}}/lib${_arch_suffix}-msvc-12.0) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-12.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17) - list(APPEND ${componentlibvar} ${${basedir}}/lib${_arch_suffix}-msvc-11.0) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-11.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) - list(APPEND ${componentlibvar} ${${basedir}}/lib${_arch_suffix}-msvc-10.0) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-10.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15) - list(APPEND ${componentlibvar} ${${basedir}}/lib${_arch_suffix}-msvc-9.0) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-9.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14) - list(APPEND ${componentlibvar} ${${basedir}}/lib${_arch_suffix}-msvc-8.0) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-8.0) endif() endif() endmacro() @@ -948,7 +963,7 @@ else() # _Boost_COMPONENT_HEADERS. See the instructions at the top of # _Boost_COMPONENT_DEPENDENCIES. set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" + "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" @@ -1361,10 +1376,10 @@ foreach(c DEBUG RELEASE) if(BOOST_ROOT) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) - _Boost_UPDATE_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} BOOST_ROOT) + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${BOOST_ROOT}") elseif(_ENV_BOOST_ROOT) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) - _Boost_UPDATE_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} _ENV_BOOST_ROOT) + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${_ENV_BOOST_ROOT}") endif() list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} @@ -1372,6 +1387,7 @@ foreach(c DEBUG RELEASE) ${Boost_INCLUDE_DIR}/../lib ${Boost_INCLUDE_DIR}/stage/lib ) + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}/..") if( Boost_NO_SYSTEM_PATHS ) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) else() @@ -1380,6 +1396,7 @@ foreach(c DEBUG RELEASE) C:/boost /sw/local/lib ) + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost") endif() endif() endforeach() diff --git a/Modules/FindFLEX.cmake b/Modules/FindFLEX.cmake index 214873c..fef7fb4 100644 --- a/Modules/FindFLEX.cmake +++ b/Modules/FindFLEX.cmake @@ -107,8 +107,6 @@ find_path(FLEX_INCLUDE_DIR FlexLexer.h mark_as_advanced(FL_LIBRARY FLEX_INCLUDE_DIR) -include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) - set(FLEX_INCLUDE_DIRS ${FLEX_INCLUDE_DIR}) set(FLEX_LIBRARIES ${FL_LIBRARY}) diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake index 1f447f1..e1b22b6 100644 --- a/Modules/FindGTK2.cmake +++ b/Modules/FindGTK2.cmake @@ -165,7 +165,6 @@ #============================================================= include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) function(_GTK2_GET_VERSION _OUT_major _OUT_minor _OUT_micro _gtkversion_hdr) file(STRINGS ${_gtkversion_hdr} _contents REGEX "#define GTK_M[A-Z]+_VERSION[ \t]+") diff --git a/Modules/FindGTest.cmake b/Modules/FindGTest.cmake index 76ab716..6540171 100644 --- a/Modules/FindGTest.cmake +++ b/Modules/FindGTest.cmake @@ -49,8 +49,8 @@ # The root directory of the Google Test installation (may also be # set as an environment variable) # ``GTEST_MSVC_SEARCH`` -# If compiling with MSVC, this variable can be set to ``MD`` or -# ``MT`` (the default) to enable searching a GTest build tree +# If compiling with MSVC, this variable can be set to ``MT`` or +# ``MD`` (the default) to enable searching a GTest build tree # # # Example usage @@ -160,11 +160,17 @@ if(MSVC) if(GTEST_MSVC_SEARCH STREQUAL "MD") list(APPEND _gtest_libpath_suffixes msvc/gtest-md/Debug - msvc/gtest-md/Release) + msvc/gtest-md/Release + msvc/x64/Debug + msvc/x64/Release + ) elseif(GTEST_MSVC_SEARCH STREQUAL "MT") list(APPEND _gtest_libpath_suffixes msvc/gtest/Debug - msvc/gtest/Release) + msvc/gtest/Release + msvc/x64/Debug + msvc/x64/Release + ) endif() endif() diff --git a/Modules/FindGettext.cmake b/Modules/FindGettext.cmake index 7718468..8035507 100644 --- a/Modules/FindGettext.cmake +++ b/Modules/FindGettext.cmake @@ -77,8 +77,6 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(Gettext REQUIRED_VARS GETTEXT_MSGMERGE_EXECUTABLE GETTEXT_MSGFMT_EXECUTABLE VERSION_VAR GETTEXT_VERSION_STRING) -include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) - function(_GETTEXT_GET_UNIQUE_TARGET_NAME _name _unique_name) set(propertyName "_GETTEXT_UNIQUE_COUNTER_${_name}") get_property(currentCounter GLOBAL PROPERTY "${propertyName}") diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake index 5c0abb0..4265a97 100644 --- a/Modules/FindJava.cmake +++ b/Modules/FindJava.cmake @@ -86,6 +86,14 @@ list(APPEND _JAVA_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/bin" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\2.0;JavaHome]/bin" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.9;JavaHome]/bin" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.8;JavaHome]/bin" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.7;JavaHome]/bin" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\2.6;JavaHome]/bin" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.5;JavaHome]/bin" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.4;JavaHome]/bin" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.3;JavaHome]/bin" ) # Hard-coded guesses should still go in PATHS. This ensures that the user # environment can always override hard guesses. diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index 30fc5c6..6259ce1 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -204,7 +204,6 @@ if(WIN32 AND NOT CYGWIN) SSL_EAY_LIBRARY_DEBUG SSL_EAY_LIBRARY_RELEASE) set(OPENSSL_SSL_LIBRARY ${SSL_EAY_LIBRARY} ) set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY_LIBRARY} ) - set(OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY} ) elseif(MINGW) # same player, for MinGW set(LIB_EAY_NAMES crypto libeay32) @@ -232,7 +231,6 @@ if(WIN32 AND NOT CYGWIN) mark_as_advanced(SSL_EAY LIB_EAY) set(OPENSSL_SSL_LIBRARY ${SSL_EAY} ) set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} ) - set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} ) unset(LIB_EAY_NAMES) unset(SSL_EAY_NAMES) else() @@ -264,7 +262,6 @@ if(WIN32 AND NOT CYGWIN) mark_as_advanced(SSL_EAY LIB_EAY) set(OPENSSL_SSL_LIBRARY ${SSL_EAY} ) set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} ) - set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} ) endif() else() @@ -298,8 +295,6 @@ else() set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY}) set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) - set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY}) - endif() function(from_hex HEX DEC) @@ -371,10 +366,13 @@ endif () include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ) + if (OPENSSL_VERSION) find_package_handle_standard_args(OpenSSL REQUIRED_VARS - OPENSSL_LIBRARIES + OPENSSL_SSL_LIBRARY + OPENSSL_CRYPTO_LIBRARY OPENSSL_INCLUDE_DIR VERSION_VAR OPENSSL_VERSION @@ -383,7 +381,8 @@ if (OPENSSL_VERSION) ) else () find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR" - OPENSSL_LIBRARIES + OPENSSL_SSL_LIBRARY + OPENSSL_CRYPTO_LIBRARY OPENSSL_INCLUDE_DIR ) endif () diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake index 7b46877..b77925d 100644 --- a/Modules/FindPackageHandleStandardArgs.cmake +++ b/Modules/FindPackageHandleStandardArgs.cmake @@ -130,7 +130,6 @@ message. #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) # internal helper macro macro(_FPHSA_FAILURE_MESSAGE _msg) diff --git a/Modules/FindPostgreSQL.cmake b/Modules/FindPostgreSQL.cmake index 874128c..9e2194c 100644 --- a/Modules/FindPostgreSQL.cmake +++ b/Modules/FindPostgreSQL.cmake @@ -88,8 +88,13 @@ foreach(suffix ${PostgreSQL_KNOWN_VERSIONS}) "PostgreSQL/${suffix}/include/server") endif() if(UNIX) + list(APPEND PostgreSQL_LIBRARY_ADDITIONAL_SEARCH_SUFFIXES + "pgsql-${suffix}/lib") + list(APPEND PostgreSQL_INCLUDE_ADDITIONAL_SEARCH_SUFFIXES + "pgsql-${suffix}/include") list(APPEND PostgreSQL_TYPE_ADDITIONAL_SEARCH_SUFFIXES - "postgresql/${suffix}/server") + "postgresql/${suffix}/server" + "pgsql-${suffix}/include/server") endif() endforeach() diff --git a/Modules/FindSquish.cmake b/Modules/FindSquish.cmake index 6c8813c..09bdf1f 100644 --- a/Modules/FindSquish.cmake +++ b/Modules/FindSquish.cmake @@ -119,9 +119,6 @@ # # This is deprecated. Use SQUISH_V3_ADD_TEST() if you are using Squish 3.x instead. - -include(CMakeParseArguments) - set(SQUISH_INSTALL_DIR_STRING "Directory containing the bin, doc, and lib directories for Squish; this should be the root of the installation directory.") set(SQUISH_SERVER_EXECUTABLE_STRING "The squishserver executable program.") set(SQUISH_CLIENT_EXECUTABLE_STRING "The squishclient executable program.") diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake index c201714..6d1b4ed 100644 --- a/Modules/GenerateExportHeader.cmake +++ b/Modules/GenerateExportHeader.cmake @@ -184,7 +184,6 @@ # :prop_tgt:`CXX_VISIBILITY_PRESET <<LANG>_VISIBILITY_PRESET>` and # :prop_tgt:`VISIBILITY_INLINES_HIDDEN` instead. -include(CMakeParseArguments) include(CheckCXXCompilerFlag) # TODO: Install this macro separately? diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index 72775ce..1b23800 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -654,6 +654,8 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa if(NOT EXISTS "${target}") message("warning: target '${target}' does not exist...") + set(${prerequisites_var} "" PARENT_SCOPE) + return() endif() set(gp_cmd_paths ${gp_cmd_paths} @@ -810,6 +812,20 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa OUTPUT_VARIABLE gp_cmd_ov ERROR_VARIABLE gp_ev ) + + if(gp_tool STREQUAL "dumpbin") + # Exclude delay load dependencies under windows (they are listed in dumpbin output after the message below) + string(FIND "${gp_cmd_ov}" "Image has the following delay load dependencies" gp_delayload_pos) + if (${gp_delayload_pos} GREATER -1) + string(SUBSTRING "${gp_cmd_ov}" 0 ${gp_delayload_pos} gp_cmd_ov_no_delayload_deps) + string(SUBSTRING "${gp_cmd_ov}" ${gp_delayload_pos} -1 gp_cmd_ov_delayload_deps) + if (verbose) + message(STATUS "GetPrequisites(${target}) : ignoring the following delay load dependencies :\n ${gp_cmd_ov_delayload_deps}") + endif() + set(gp_cmd_ov ${gp_cmd_ov_no_delayload_deps}) + endif() + endif() + if(NOT gp_rv STREQUAL "0") if(gp_tool STREQUAL "dumpbin") # dumpbin error messages seem to go to stdout diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index b0446c9..7975bd4 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -182,7 +182,10 @@ if(MSVC) "${MSVC${v}_CRT_DIR}/msvcp${v}0.dll" ) if(NOT v VERSION_LESS 14) - list(APPEND __install__libs "${MSVC${v}_CRT_DIR}/vcruntime${v}0.dll") + list(APPEND __install__libs + "${MSVC${v}_CRT_DIR}/vcruntime${v}0.dll" + "${MSVC${v}_CRT_DIR}/concrt${v}0.dll" + ) else() list(APPEND __install__libs "${MSVC${v}_CRT_DIR}/msvcr${v}0.dll") endif() @@ -197,28 +200,37 @@ if(MSVC) "${MSVC${v}_CRT_DIR}/msvcp${v}0d.dll" ) if(NOT v VERSION_LESS 14) - list(APPEND __install__libs "${MSVC${v}_CRT_DIR}/vcruntime${v}0d.dll") + list(APPEND __install__libs + "${MSVC${v}_CRT_DIR}/vcruntime${v}0d.dll" + "${MSVC${v}_CRT_DIR}/concrt${v}0d.dll" + ) else() list(APPEND __install__libs "${MSVC${v}_CRT_DIR}/msvcr${v}0d.dll") endif() endif() if(CMAKE_INSTALL_UCRT_LIBRARIES AND NOT v VERSION_LESS 14) - # Find the Windows Universal CRT redistribution directory. + # Find the Windows Kits directory. get_filename_component(windows_kits_dir "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots;KitsRoot10]" ABSOLUTE) set(programfilesx86 "ProgramFiles(x86)") - find_path(WINDOWS_KITS_REDIST_DIR NAMES ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll + find_path(WINDOWS_KITS_DIR NAMES Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll PATHS - "${windows_kits_dir}/Redist" - "$ENV{ProgramFiles}/Windows Kits/10/Redist" - "$ENV{${programfilesx86}}/Windows Kits/10/Redist" + "${windows_kits_dir}" + "$ENV{ProgramFiles}/Windows Kits/10" + "$ENV{${programfilesx86}}/Windows Kits/10" ) - mark_as_advanced(WINDOWS_KITS_REDIST_DIR) + mark_as_advanced(WINDOWS_KITS_DIR) # Glob the list of UCRT DLLs. - file(GLOB __ucrt_dlls "${WINDOWS_KITS_REDIST_DIR}/ucrt/DLLs/${CMAKE_MSVC_ARCH}/*.dll") - list(APPEND __install__libs ${__ucrt_dlls}) + if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) + file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/*.dll") + list(APPEND __install__libs ${__ucrt_dlls}) + endif() + if(CMAKE_INSTALL_DEBUG_LIBRARIES) + file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/bin/${CMAKE_MSVC_ARCH}/ucrt/*.dll") + list(APPEND __install__libs ${__ucrt_dlls}) + endif() endif() endmacro() diff --git a/Modules/Platform/Android-Clang-ASM.cmake b/Modules/Platform/Android-Clang-ASM.cmake new file mode 100644 index 0000000..6448da6 --- /dev/null +++ b/Modules/Platform/Android-Clang-ASM.cmake @@ -0,0 +1,2 @@ +include(Platform/Android-Clang) +__android_compiler_clang(ASM) diff --git a/Modules/Platform/Android-Clang.cmake b/Modules/Platform/Android-Clang.cmake index f0cf4a5..f739ab1 100644 --- a/Modules/Platform/Android-Clang.cmake +++ b/Modules/Platform/Android-Clang.cmake @@ -35,7 +35,9 @@ include(Platform/Android-Common) include(Platform/Android/abi-${CMAKE_ANDROID_ARCH_ABI}-Clang) macro(__android_compiler_clang lang) - __android_compiler_common(${lang}) + if(NOT "x${lang}" STREQUAL "xASM") + __android_compiler_common(${lang}) + endif() if(NOT CMAKE_${lang}_COMPILER_TARGET) set(CMAKE_${lang}_COMPILER_TARGET "${_ANDROID_ABI_CLANG_TARGET}") endif() diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index f506500..0e90d35 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -54,6 +54,8 @@ if(NOT MSVC_VERSION) set(_compiler_version ${CMAKE_CXX_SIMULATE_VERSION}) elseif(CMAKE_Fortran_SIMULATE_VERSION) set(_compiler_version ${CMAKE_Fortran_SIMULATE_VERSION}) + elseif(CMAKE_CUDA_SIMULATE_VERSION) + set(_compiler_version ${CMAKE_CUDA_SIMULATE_VERSION}) elseif(CMAKE_C_COMPILER_VERSION) set(_compiler_version ${CMAKE_C_COMPILER_VERSION}) else() diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake new file mode 100644 index 0000000..809ee06 --- /dev/null +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -0,0 +1,42 @@ +include(Platform/Windows-MSVC) + +set(CMAKE_CUDA_COMPILE_PTX_COMPILATION + "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") +set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION + "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") +set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION + "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + +set(__IMPLICT_LINKS ) +foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) + string(APPEND __IMPLICT_LINKS " -LIBPATH:\"${dir}\"") +endforeach() +foreach(lib ${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES}) + string(APPEND __IMPLICT_LINKS " \"${lib}\"") +endforeach() +set(CMAKE_CUDA_LINK_EXECUTABLE + "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_LIBRARIES>${__IMPLICT_LINKS}") + +set(_CMAKE_VS_LINK_DLL "<CMAKE_COMMAND> -E vs_link_dll --intdir=<OBJECT_DIR> --manifests <MANIFESTS> -- ") +set(_CMAKE_VS_LINK_EXE "<CMAKE_COMMAND> -E vs_link_exe --intdir=<OBJECT_DIR> --manifests <MANIFESTS> -- ") +set(CMAKE_CUDA_CREATE_SHARED_LIBRARY + "${_CMAKE_VS_LINK_DLL}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /dll /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}") + +set(CMAKE_CUDA_CREATE_SHARED_MODULE ${CMAKE_CUDA_CREATE_SHARED_LIBRARY}) +set(CMAKE_CUDA_CREATE_STATIC_LIBRARY "<CMAKE_LINKER> /lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ") +set(CMAKE_CUDA_LINKER_SUPPORTS_PDB ON) +set(CMAKE_CUDA_LINK_EXECUTABLE + "${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}") +unset(_CMAKE_VS_LINK_EXE) +unset(_CMAKE_VS_LINK_EXE) + +set(CMAKE_CUDA_DEVICE_LINK_LIBRARY + "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") +set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE + "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + +string(APPEND CMAKE_CUDA_FLAGS_INIT " -Xcompiler=-GR,-EHsc") +string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=-MDd,-Zi,-RTC1") +string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=-MD") +string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=-MD") +string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=-MD") diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 6b34c8f..93255ae 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -403,8 +403,6 @@ # Sets the directory where the header files will be generated. Same behavior as option # '-d' of javah tool. If not specified, ${CMAKE_CURRENT_BINARY_DIR} is used as output directory. -include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) - function (__java_copy_file src dest comment) add_custom_command( OUTPUT ${dest} diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 651f9f1..277f4ca 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -212,6 +212,7 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) "${swig_source_file_fullname}" MAIN_DEPENDENCY "${swig_source_file_fullname}" DEPENDS ${SWIG_MODULE_${name}_EXTRA_DEPS} + IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}" COMMENT "Swig source") set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files} PROPERTIES GENERATED 1) @@ -231,8 +232,6 @@ endmacro() macro(SWIG_ADD_LIBRARY name) - - include(CMakeParseArguments) set(options "") set(oneValueArgs LANGUAGE TYPE) @@ -340,4 +339,3 @@ macro(SWIG_LINK_LIBRARIES name) message(SEND_ERROR "Cannot find Swig library \"${name}\".") endif() endmacro() - diff --git a/Modules/WriteBasicConfigVersionFile.cmake b/Modules/WriteBasicConfigVersionFile.cmake index 20c769e..7c9467a 100644 --- a/Modules/WriteBasicConfigVersionFile.cmake +++ b/Modules/WriteBasicConfigVersionFile.cmake @@ -18,8 +18,6 @@ # # Deprecated, see WRITE_BASIC_PACKAGE_VERSION_FILE(), it is identical. -include(CMakeParseArguments) - function(WRITE_BASIC_CONFIG_VERSION_FILE _filename) set(options ) diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake index a390f4b..ba249e1 100644 --- a/Modules/WriteCompilerDetectionHeader.cmake +++ b/Modules/WriteCompilerDetectionHeader.cmake @@ -216,7 +216,6 @@ # CompatSupport_DEPRECATED= # ) -include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) include(${CMAKE_CURRENT_LIST_DIR}/CMakeCompilerIdDetection.cmake) function(_load_compiler_variables CompilerId lang) diff --git a/Packaging/QtSDK/ToolsCMakeXX.cmake b/Packaging/QtSDK/ToolsCMakeXX.cmake index e227b73..c5f8f34 100644 --- a/Packaging/QtSDK/ToolsCMakeXX.cmake +++ b/Packaging/QtSDK/ToolsCMakeXX.cmake @@ -3,38 +3,29 @@ # CMake version include("${CMAKE_CURRENT_LIST_DIR}/../../Source/CMakeVersion.cmake") -set(CM_VER_XY ${CMake_VERSION_MAJOR}${CMake_VERSION_MINOR}) -set(CM_VER_X_Y ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}) -set(CM_VER_X_Y_Z ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATH}) -# Destiantion -set(CM_INST_PREF "Tools/CMake/${CM_VER_X_Y}") -set(CMAKE_BIN_DIR "${CM_INST_PREF}/bin" - CACHE STRING "Location under install bin") -set(CMAKE_DATA_DIR "${CM_INST_PREF}/share/cmake-${CM_VER_X_Y}" - CACHE STRING "Location under install data") -set(CMAKE_DOC_DIR "${CM_INST_PREF}/doc/cmake-${CM_VER_X_Y}" - CACHE STRING "Location under install docs") -set(CMAKE_MAN_DIR "${CM_INST_PREF}/man" - CACHE STRING "Location under install man pages") -set(CMAKE_XDGDATA_DIR "${CM_INST_PREF}/share" - CACHE STRING "Location under install XDG specific files") +# Install destinations +set(CMake_INSTALL_INFIX "Tools/CMake/${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}/" + CACHE STRING "Location under install CMake tools") # Package set(CMake_IFW_ROOT_COMPONENT_NAME - "qt.tools.cmake.${CM_VER_XY}" + "qt.tools.cmake.${CMake_VERSION_MAJOR}${CMake_VERSION_MINOR}" CACHE STRING "QtSDK CMake tools component name") set(CMake_IFW_ROOT_COMPONENT_DISPLAY_NAME - "CMake ${CM_VER_X_Y}" + "CMake ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}" CACHE STRING "QtSDK CMake tools component display name") set(CMake_IFW_ROOT_COMPONENT_DESCRIPTION - "CMake Build Tools ${CM_VER_X_Y_Z}" + "CMake Build Tools ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATH}" CACHE STRING "QtSDK CMake tools component description") -set(CMake_IFW_ROOT_COMPONENT_SCRIPT - "${CMAKE_CURRENT_BINARY_DIR}/qt.tools.cmake.${CM_VER_XY}.qs" - CACHE STRING "QtSDK CMake tools component display name") +set(CMake_IFW_ROOT_COMPONENT_SCRIPT_TEMPLATE + "${CMAKE_CURRENT_LIST_DIR}/qt.tools.cmake.xx.qs.in" + CACHE FILEPATH "QtSDK CMake tools script template") +set(CMake_IFW_ROOT_COMPONENT_SCRIPT_GENERATED + "${CMAKE_CURRENT_BINARY_DIR}/qt.tools.cmake.${CMake_VERSION_MAJOR}${CMake_VERSION_MINOR}.qs" + CACHE FILEPATH "QtSDK CMake tools script generated") set(CMake_IFW_ROOT_COMPONENT_PRIORITY - "${CM_VER_XY}" + "${CMake_VERSION_MAJOR}${CMake_VERSION_MINOR}" CACHE STRING "QtSDK CMake tools component sorting priority") set(CMake_IFW_ROOT_COMPONENT_DEFAULT "" CACHE STRING "QtSDK CMake tools component default") @@ -52,17 +43,3 @@ set(CPACK_IFW_DOWNLOAD_ALL "TRUE" CACHE STRING "All QtSDK components is downloaded") set(CPACK_DOWNLOAD_SITE "file:///${CMAKE_CURRENT_BINARY_DIR}/QtSDK/IFW/CMake/repository" CACHE STRING "Local repository for testing") - -# Script -set(SDKToolBinary "@SDKToolBinary@") -set(CM_VER_XY_DIR "@CMAKE${CM_VER_XY}_DIR@") -configure_file("${CMAKE_CURRENT_LIST_DIR}/qt.tools.cmake.xx.qs.in" - "${CMAKE_CURRENT_BINARY_DIR}/qt.tools.cmake.${CM_VER_XY}.qs" - @ONLY) - -# Unset temporary variables -unset(CM_VER_XY) -unset(CM_VER_X_Y) -unset(CM_VER_X_Y_Z) -unset(CM_INST_PREF) -unset(SDKToolBinary) diff --git a/Packaging/QtSDK/qt.tools.cmake.xx.qs.in b/Packaging/QtSDK/qt.tools.cmake.xx.qs.in index cb42a71..81ce157 100644 --- a/Packaging/QtSDK/qt.tools.cmake.xx.qs.in +++ b/Packaging/QtSDK/qt.tools.cmake.xx.qs.in @@ -9,15 +9,15 @@ function Component() { installer.valueChanged.connect( this, Component.prototype.reactOnTargetDirChange ); - // set the default values to CMAKE@CM_VER_XY@_DIR + // set the default values to CMAKE%CMake_VERSION_MAJOR%%CMake_VERSION_MINOR%_BIN_DIR Component.prototype.reactOnTargetDirChange("TargetDir", installer.value("TargetDir")); } Component.prototype.reactOnTargetDirChange = function(key, value) { if (key == "TargetDir") { - var path = value + "/@CM_INST_PREF@"; - installer.setValue("CMAKE@CM_VER_XY@_DIR", path.replace(/\\/g, "/")); + var path = value + "/%CMAKE_BIN_DIR%"; + installer.setValue("CMAKE%CMake_VERSION_MAJOR%%CMake_VERSION_MINOR%_BIN_DIR", path.replace(/\\/g, "/")); } } @@ -31,13 +31,13 @@ Component.prototype.createOperations = function() return; var cmId = component.name; - installer.setValue("CMAKE@CM_VER_XY@_ID", cmId); + installer.setValue("CMAKE%CMake_VERSION_MAJOR%%CMake_VERSION_MINOR%_ID", cmId); component.addOperation("Execute", ["{0,2}", "@SDKToolBinary@", "addCMake", "--id", cmId, - "--name", "@CMake_IFW_ROOT_COMPONENT_DISPLAY_NAME@", - "--path", "@CM_VER_XY_DIR@/bin/cmake.exe", + "--name", "%CMake_IFW_ROOT_COMPONENT_DISPLAY_NAME%", + "--path", "@CMAKE%CMake_VERSION_MAJOR%%CMake_VERSION_MINOR%_BIN_DIR@/cmake.exe", "UNDOEXECUTE", "@SDKToolBinary@", "rmCMake", "--id", cmId]); diff --git a/Source/CMakeInstallDestinations.cmake b/Source/CMakeInstallDestinations.cmake index 023f6c0..28f4e87 100644 --- a/Source/CMakeInstallDestinations.cmake +++ b/Source/CMakeInstallDestinations.cmake @@ -25,6 +25,12 @@ set(CMAKE_DOC_DIR_DESC "docs") set(CMAKE_MAN_DIR_DESC "man pages") set(CMAKE_XDGDATA_DIR_DESC "XDG specific files") +set(CMake_INSTALL_INFIX "" CACHE STRING "") +set_property(CACHE CMake_INSTALL_INFIX PROPERTY HELPSTRING + "Intermediate installation path (empty by default)" + ) +mark_as_advanced(CMake_INSTALL_INFIX) + foreach(v CMAKE_BIN_DIR CMAKE_DATA_DIR @@ -41,7 +47,7 @@ foreach(v # Use the default when the user did not set this variable. if(NOT ${v}) - set(${v} "${${v}_DEFAULT}") + set(${v} "${CMake_INSTALL_INFIX}${${v}_DEFAULT}") endif() # Remove leading slash to treat as relative to install prefix. string(REGEX REPLACE "^/" "" ${v} "${${v}}") diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index d15fdbe..2835ee6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -710,6 +710,8 @@ if (WIN32) cmGhsMultiTargetGenerator.h cmGhsMultiGpj.cxx cmGhsMultiGpj.h + cmVSSetupHelper.cxx + cmVSSetupHelper.h ) # Add a manifest file to executables on Windows to allow for @@ -785,6 +787,15 @@ target_link_libraries(CMakeLib cmsys ${CMake_KWIML_LIBRARIES} ) +if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "sparc") + # the atomic instructions are implemented using libatomic on some platforms, + # so linking to that may be required + check_library_exists(atomic __atomic_fetch_add_4 "" LIBATOMIC_NEEDED) + if(LIBATOMIC_NEEDED) + target_link_libraries(CMakeLib atomic) + endif() +endif() + # On Apple we need CoreFoundation if(APPLE) target_link_libraries(CMakeLib "-framework CoreFoundation") diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6b0bfe4..d1054cf 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 7) -set(CMake_VERSION_PATCH 20170109) +set(CMake_VERSION_PATCH 20170117) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 36566a4..5c50da8 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -173,7 +173,11 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + this->GetOutputExtension()); // all GROUP in one vs all COMPONENT in one - localToplevel += "/" + compInstDirName; + // if must be here otherwise non component paths have a trailing / while + // components don't + if (!compInstDirName.empty()) { + localToplevel += "/" + compInstDirName; + } /* replace the TEMP DIRECTORY with the component one */ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str()); diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 2c31f60..a062e64 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -305,6 +305,9 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) case cmCTestMemCheckHandler::ADDRESS_SANITIZER: xml.Attribute("Checker", "AddressSanitizer"); break; + case cmCTestMemCheckHandler::LEAK_SANITIZER: + xml.Attribute("Checker", "LeakSanitizer"); + break; case cmCTestMemCheckHandler::THREAD_SANITIZER: xml.Attribute("Checker", "ThreadSanitizer"); break; @@ -459,6 +462,12 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->LogWithPID = true; // even if we give the log file the pid is added } if (this->CTest->GetCTestConfiguration("MemoryCheckType") == + "LeakSanitizer") { + this->MemoryTester = this->CTest->GetCTestConfiguration("CMakeCommand"); + this->MemoryTesterStyle = cmCTestMemCheckHandler::LEAK_SANITIZER; + this->LogWithPID = true; // even if we give the log file the pid is added + } + if (this->CTest->GetCTestConfiguration("MemoryCheckType") == "ThreadSanitizer") { this->MemoryTester = this->CTest->GetCTestConfiguration("CMakeCommand"); this->MemoryTesterStyle = cmCTestMemCheckHandler::THREAD_SANITIZER; @@ -586,6 +595,7 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() } // these are almost the same but the env var used is different case cmCTestMemCheckHandler::ADDRESS_SANITIZER: + case cmCTestMemCheckHandler::LEAK_SANITIZER: case cmCTestMemCheckHandler::THREAD_SANITIZER: case cmCTestMemCheckHandler::MEMORY_SANITIZER: case cmCTestMemCheckHandler::UB_SANITIZER: { @@ -597,12 +607,20 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterDynamicOptions.push_back("-E"); this->MemoryTesterDynamicOptions.push_back("env"); std::string envVar; - std::string extraOptions = + std::string extraOptions = ":" + this->CTest->GetCTestConfiguration("MemoryCheckSanitizerOptions"); + std::string suppressionsOption; + if (!this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile") + .empty()) { + suppressionsOption = ":suppressions=" + + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile"); + } if (this->MemoryTesterStyle == cmCTestMemCheckHandler::ADDRESS_SANITIZER) { envVar = "ASAN_OPTIONS"; - extraOptions += " detect_leaks=1"; + } else if (this->MemoryTesterStyle == + cmCTestMemCheckHandler::LEAK_SANITIZER) { + envVar = "LSAN_OPTIONS"; } else if (this->MemoryTesterStyle == cmCTestMemCheckHandler::THREAD_SANITIZER) { envVar = "TSAN_OPTIONS"; @@ -614,8 +632,9 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() envVar = "UBSAN_OPTIONS"; } std::string outputFile = - envVar + "=log_path=\"" + this->MemoryTesterOutputFile + "\" "; - this->MemoryTesterEnvironmentVariable = outputFile + extraOptions; + envVar + "=log_path=\"" + this->MemoryTesterOutputFile + "\""; + this->MemoryTesterEnvironmentVariable = + outputFile + suppressionsOption + extraOptions; break; } default: @@ -644,6 +663,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str, case cmCTestMemCheckHandler::PURIFY: return this->ProcessMemCheckPurifyOutput(str, log, results); case cmCTestMemCheckHandler::ADDRESS_SANITIZER: + case cmCTestMemCheckHandler::LEAK_SANITIZER: case cmCTestMemCheckHandler::THREAD_SANITIZER: case cmCTestMemCheckHandler::MEMORY_SANITIZER: case cmCTestMemCheckHandler::UB_SANITIZER: @@ -680,6 +700,9 @@ bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput( case cmCTestMemCheckHandler::ADDRESS_SANITIZER: regex = "ERROR: AddressSanitizer: (.*) on.*"; break; + case cmCTestMemCheckHandler::LEAK_SANITIZER: + // use leakWarning regex + break; case cmCTestMemCheckHandler::THREAD_SANITIZER: regex = "WARNING: ThreadSanitizer: (.*) \\(pid=.*\\)"; break; diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index 5faace0..ff8b593 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -47,6 +47,7 @@ private: BOUNDS_CHECKER, // checkers after here do not use the standard error list ADDRESS_SANITIZER, + LEAK_SANITIZER, THREAD_SANITIZER, MEMORY_SANITIZER, UB_SANITIZER diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 5c45fe5..ac1644f 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -134,6 +134,7 @@ void cmCTestRunTest::CompressOutput() size_t rlen = cmsysBase64_Encode(out, strm.total_out, encoded_buffer, 1); + this->CompressedOutput.clear(); for (size_t i = 0; i < rlen; i++) { this->CompressedOutput += encoded_buffer[i]; } @@ -416,6 +417,7 @@ bool cmCTestRunTest::StartTest(size_t total) << std::setw(getNumWidth(this->TestHandler->GetMaxIndex())) << this->TestProperties->Index << ": " << this->TestProperties->Name << std::endl); + this->ProcessOutput.clear(); this->ComputeArguments(); std::vector<std::string>& args = this->TestProperties->Args; this->TestResult.Properties = this->TestProperties; diff --git a/Source/QtDialog/RegexExplorer.cxx b/Source/QtDialog/RegexExplorer.cxx index 1512166..abed70e 100644 --- a/Source/QtDialog/RegexExplorer.cxx +++ b/Source/QtDialog/RegexExplorer.cxx @@ -64,10 +64,32 @@ void RegexExplorer::on_inputText_textChanged() return; } + std::string matchingText; + + if (matchAll->isChecked()) { + const char* p = m_text.c_str(); + while (m_regexParser.find(p)) { + std::string::size_type l = m_regexParser.start(); + std::string::size_type r = m_regexParser.end(); + if (r - l == 0) { + // matched empty string + clearMatch(); + return; + } + if (!matchingText.empty()) { + matchingText += ";"; + } + matchingText += std::string(p + l, r - l); + p += r; + } + } else { + matchingText = m_regexParser.match(0); + } + #ifdef QT_NO_STL - QString matchText = m_regexParser.match(0).c_str(); + QString matchText = matchingText.c_str(); #else - QString matchText = QString::fromStdString(m_regexParser.match(0)); + QString matchText = QString::fromStdString(matchingText); #endif match0->setPlainText(matchText); @@ -95,8 +117,16 @@ void RegexExplorer::on_matchNumber_currentIndexChanged(int index) matchN->setPlainText(match); } +void RegexExplorer::on_matchAll_toggled(bool checked) +{ + Q_UNUSED(checked); + + on_inputText_textChanged(); +} + void RegexExplorer::clearMatch() { + m_matched = false; match0->clear(); matchN->clear(); } diff --git a/Source/QtDialog/RegexExplorer.h b/Source/QtDialog/RegexExplorer.h index f1c1e5f..caef975 100644 --- a/Source/QtDialog/RegexExplorer.h +++ b/Source/QtDialog/RegexExplorer.h @@ -22,6 +22,7 @@ private slots: void on_regularExpression_textChanged(const QString& text); void on_inputText_textChanged(); void on_matchNumber_currentIndexChanged(int index); + void on_matchAll_toggled(bool checked); private: static void setStatusColor(QWidget* widget, bool successful); diff --git a/Source/QtDialog/RegexExplorer.ui b/Source/QtDialog/RegexExplorer.ui index 2c2d761..0af6999 100644 --- a/Source/QtDialog/RegexExplorer.ui +++ b/Source/QtDialog/RegexExplorer.ui @@ -104,11 +104,38 @@ <widget class="QLineEdit" name="regularExpression"/> </item> <item> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Complete Match</string> - </property> - </widget> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Complete Match</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="matchAll"> + <property name="text"> + <string>Match All</string> + </property> + </widget> + </item> + </layout> </item> <item> <widget class="QPlainTextEdit" name="match0"> diff --git a/Source/QtIFW/CMake.DeveloperReference.HTML.qs.in b/Source/QtIFW/CMake.DeveloperReference.HTML.qs.in index e3d8554..8cc5835 100644 --- a/Source/QtIFW/CMake.DeveloperReference.HTML.qs.in +++ b/Source/QtIFW/CMake.DeveloperReference.HTML.qs.in @@ -11,8 +11,8 @@ Component.prototype.createOperations = function() if (installer.value("os") === "win") { component.addOperation("CreateShortcut", - installer.value("TargetDir") + "/@CMAKE_DOC_DIR@/developer-reference/html/index.html", - installer.value("StartMenuDir") + "/CMake Developer Reference.lnk"); + "@TargetDir@/%CMAKE_DOC_DIR%/developer-reference/html/index.html", + "@StartMenuDir@/CMake Developer Reference.lnk"); } diff --git a/Source/QtIFW/CMake.Dialogs.QtGUI.qs b/Source/QtIFW/CMake.Dialogs.QtGUI.qs.in index 219a0a9..71f395a 100644 --- a/Source/QtIFW/CMake.Dialogs.QtGUI.qs +++ b/Source/QtIFW/CMake.Dialogs.QtGUI.qs.in @@ -11,8 +11,8 @@ Component.prototype.createOperations = function() if (installer.value("os") === "win") { component.addOperation("CreateShortcut", - installer.value("TargetDir") + "/bin/cmake-gui.exe", - installer.value("StartMenuDir") + "/CMake (cmake-gui).lnk"); + "@TargetDir@/%CMAKE_BIN_DIR%/cmake-gui.exe", + "@StartMenuDir@/CMake (cmake-gui).lnk"); } diff --git a/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in b/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in index 5c929e8..54bc14a 100644 --- a/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in +++ b/Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in @@ -11,8 +11,8 @@ Component.prototype.createOperations = function() if (installer.value("os") === "win") { component.addOperation("CreateShortcut", - installer.value("TargetDir") + "/@CMAKE_DOC_DIR@/html/index.html", - installer.value("StartMenuDir") + "/CMake Documentation.lnk"); + "@TargetDir@/%CMAKE_DOC_DIR%/html/index.html", + "@StartMenuDir@/CMake Documentation.lnk"); } diff --git a/Source/QtIFW/CMake.qs.in b/Source/QtIFW/CMake.qs.in index 828cc7c..1f3166e 100644 --- a/Source/QtIFW/CMake.qs.in +++ b/Source/QtIFW/CMake.qs.in @@ -1,3 +1,5 @@ +// Component: CMake + function Component() { // Default constructor @@ -9,12 +11,12 @@ Component.prototype.createOperations = function() if (installer.value("os") === "win") { component.addOperation("CreateShortcut", - installer.value("TargetDir") + "/@CMAKE_DOC_DIR@/cmake.org.html", - installer.value("StartMenuDir") + "/CMake Web Site.lnk"); + "@TargetDir@/%CMAKE_DOC_DIR%/cmake.org.html", + "@StartMenuDir@/CMake Web Site.lnk"); component.addOperation("CreateShortcut", - installer.value("TargetDir") + "/cmake-maintenance.exe", - installer.value("StartMenuDir") + "/CMake Maintenance Tool.lnk"); + "@TargetDir@/cmake-maintenance.exe", + "@StartMenuDir@/CMake Maintenance Tool.lnk"); } // Call default implementation diff --git a/Source/QtIFW/installscript.qs.in b/Source/QtIFW/installscript.qs.in index 39a8795..72d49e8 100644 --- a/Source/QtIFW/installscript.qs.in +++ b/Source/QtIFW/installscript.qs.in @@ -1,3 +1,5 @@ +// Component: CMake + function Component() { // Do not show component selection page @@ -9,15 +11,15 @@ Component.prototype.createOperations = function() // Create shortcut if (installer.value("os") === "win") { -@_CPACK_IFW_SHORTCUT_OPTIONAL@ +%_CPACK_IFW_SHORTCUT_OPTIONAL% component.addOperation("CreateShortcut", - installer.value("TargetDir") + "/@CMAKE_DOC_DIR@/cmake.org.html", - installer.value("StartMenuDir") + "/CMake Web Site.lnk"); + "@TargetDir@/%CMAKE_DOC_DIR%/cmake.org.html", + "@StartMenuDir@/CMake Web Site.lnk"); component.addOperation("CreateShortcut", - installer.value("TargetDir") + "/cmake-maintenance.exe", - installer.value("StartMenuDir") + "/CMake Maintenance Tool.lnk"); + "@TargetDir@/cmake-maintenance.exe", + "@StartMenuDir@/CMake Maintenance Tool.lnk"); } // Call default implementation diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 7e113ab..239582f 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -63,6 +63,13 @@ 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) { return; } diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index e6000db..9d4b9cc 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -12,7 +12,7 @@ #include "cmSystemTools.h" #define INCLUDE_REGEX_LINE \ - "^[ \t]*#[ \t]*(include|import)[ \t]*[<\"]([^\">]+)([\">])" + "^[ \t]*[#%][ \t]*(include|import)[ \t]*[<\"]([^\">]+)([\">])" #define INCLUDE_REGEX_LINE_MARKER "#IncludeRegexLine: " #define INCLUDE_REGEX_SCAN_MARKER "#IncludeRegexScan: " @@ -420,7 +420,7 @@ void cmDependsC::SetupTransforms() if (!this->TransformRules.empty()) { // Construct the regular expression to match lines to be // transformed. - std::string xform = "^([ \t]*#[ \t]*(include|import)[ \t]*)("; + std::string xform = "^([ \t]*[#%][ \t]*(include|import)[ \t]*)("; const char* sep = ""; for (TransformRulesType::const_iterator tri = this->TransformRules.begin(); tri != this->TransformRules.end(); ++tri) { diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index f544e8a..2dffcaa 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -48,6 +48,7 @@ cmExtraCodeBlocksGenerator::GetFactory() #if defined(_WIN32) factory.AddSupportedGlobalGenerator("MinGW Makefiles"); factory.AddSupportedGlobalGenerator("NMake Makefiles"); + factory.AddSupportedGlobalGenerator("NMake Makefiles JOM"); // disable until somebody actually tests it: // this->AddSupportedGlobalGenerator("MSYS Makefiles"); #endif @@ -741,7 +742,7 @@ std::string cmExtraCodeBlocksGenerator::BuildMakeCommand( } std::string generator = this->GlobalGenerator->GetName(); - if (generator == "NMake Makefiles") { + if (generator == "NMake Makefiles" || generator == "NMake Makefiles JOM") { // For Windows ConvertToOutputPath already adds quotes when required. // These need to be escaped, see // https://gitlab.kitware.com/cmake/cmake/issues/13952 diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index dfefefe..36ba520 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -323,16 +323,12 @@ std::string cmExtraSublimeTextGenerator::BuildMakeCommand( std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); command += ", \"/NOLOGO\", \"/f\", \""; command += makefileName + "\""; - command += ", \"VERBOSE=1\", \""; - command += target; - command += "\""; + command += ", \"" + target + "\""; } else if (generator == "Ninja") { std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); command += ", \"-f\", \""; command += makefileName + "\""; - command += ", \"-v\", \""; - command += target; - command += "\""; + command += ", \"" + target + "\""; } else { std::string makefileName; if (generator == "MinGW Makefiles") { @@ -344,9 +340,7 @@ std::string cmExtraSublimeTextGenerator::BuildMakeCommand( } command += ", \"-f\", \""; command += makefileName + "\""; - command += ", \"VERBOSE=1\", \""; - command += target; - command += "\""; + command += ", \"" + target + "\""; } return command; } diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx index 03bbf42..909be78 100644 --- a/Source/cmFileMonitor.cxx +++ b/Source/cmFileMonitor.cxx @@ -334,6 +334,9 @@ void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths, rootSegment)); // Can not be both filename and root part of the path! const std::string& currentSegment = pathSegments[i]; + if (currentSegment.empty()) { + continue; + } cmIBaseWatcher* nextWatcher = currentWatcher->Find(currentSegment); if (!nextWatcher) { diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index dde6e82..e27615a 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -425,20 +425,6 @@ std::string cmGlobalVisualStudio10Generator::FindMSBuildCommand() } } - // Search where VS15Preview places it. - mskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7;"; - mskey += this->GetIDEVersion(); - if (cmSystemTools::ReadRegistryValue(mskey.c_str(), msbuild, - cmSystemTools::KeyWOW64_32)) { - cmSystemTools::ConvertToUnixSlashes(msbuild); - msbuild += "/MSBuild/"; - msbuild += this->GetIDEVersion(); - msbuild += "/Bin/MSBuild.exe"; - if (cmSystemTools::FileExists(msbuild, true)) { - return msbuild; - } - } - msbuild = "MSBuild.exe"; return msbuild; } diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index 20d30bc..d11ee7c 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -8,6 +8,7 @@ #include "cmMakefile.h" #include "cmVS141CLFlagTable.h" #include "cmVS141CSharpFlagTable.h" +#include "cmVSSetupHelper.h" static const char vs15generatorName[] = "Visual Studio 15 2017"; @@ -80,11 +81,7 @@ cmGlobalVisualStudio15Generator::cmGlobalVisualStudio15Generator( cmake* cm, const std::string& name, const std::string& platformName) : cmGlobalVisualStudio14Generator(cm, name, platformName) { - std::string vc15Express; - this->ExpressEdition = cmSystemTools::ReadRegistryValue( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\15.0\\Setup\\VC;" - "ProductDir", - vc15Express, cmSystemTools::KeyWOW64_32); + this->ExpressEdition = false; this->DefaultPlatformToolset = "v141"; this->DefaultClFlagTable = cmVS141CLFlagTable; this->DefaultCSharpFlagTable = cmVS141CSharpFlagTable; @@ -118,7 +115,7 @@ bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { if (this->IsWindowsStoreToolsetInstalled() && this->IsWindowsDesktopToolsetInstalled()) { - toolset = "v140"; // VS 15 uses v140 toolset + toolset = "v141"; // VS 15 uses v141 toolset return true; } else { return false; @@ -130,21 +127,44 @@ bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( bool cmGlobalVisualStudio15Generator::IsWindowsDesktopToolsetInstalled() const { - const char desktop10Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" - "VisualStudio\\15.0\\VC\\Runtimes"; - - std::vector<std::string> vc15; - return cmSystemTools::GetRegistrySubKeys(desktop10Key, vc15, - cmSystemTools::KeyWOW64_32); + return vsSetupAPIHelper.IsVS2017Installed(); } bool cmGlobalVisualStudio15Generator::IsWindowsStoreToolsetInstalled() const { - const char universal10Key[] = - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" - "VisualStudio\\15.0\\Setup\\Build Tools for Windows 10;SrcPath"; + return vsSetupAPIHelper.IsWin10SDKInstalled(); +} + +std::string cmGlobalVisualStudio15Generator::FindMSBuildCommand() +{ + std::string msbuild; + + // Ask Visual Studio Installer tool. + std::string vs; + if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } + } + + msbuild = "MSBuild.exe"; + return msbuild; +} + +std::string cmGlobalVisualStudio15Generator::FindDevEnvCommand() +{ + std::string devenv; + + // Ask Visual Studio Installer tool. + std::string vs; + if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + devenv = vs + "/Common7/IDE/devenv.com"; + if (cmSystemTools::FileExists(devenv)) { + return devenv; + } + } - std::string win10SDK; - return cmSystemTools::ReadRegistryValue(universal10Key, win10SDK, - cmSystemTools::KeyWOW64_32); + devenv = "devenv.com"; + return devenv; } diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index 59eb11a..781b41e 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -9,6 +9,7 @@ #include <string> #include "cmGlobalVisualStudio14Generator.h" +#include "cmVSSetupHelper.h" class cmGlobalGeneratorFactory; class cmake; @@ -39,7 +40,11 @@ protected: // of the toolset is installed bool IsWindowsStoreToolsetInstalled() const; + std::string FindMSBuildCommand() CM_OVERRIDE; + std::string FindDevEnvCommand() CM_OVERRIDE; + private: class Factory; + mutable cmVSSetupAPIHelper vsSetupAPIHelper; }; #endif diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index cf0cf88..e728632 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -184,3 +184,9 @@ std::string cmLinkLineComputer::ComputeLinkLibraries( return fout.str(); } + +std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target, + std::string const& config) +{ + return target->GetLinkerLanguage(config); +} diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h index bb13717..57a70bc 100644 --- a/Source/cmLinkLineComputer.h +++ b/Source/cmLinkLineComputer.h @@ -11,6 +11,7 @@ #include "cmStateDirectory.h" class cmComputeLinkInformation; +class cmGeneratorTarget; class cmOutputConverter; class cmLinkLineComputer @@ -36,6 +37,9 @@ public: virtual std::string ComputeLinkLibraries(cmComputeLinkInformation& cli, std::string const& stdLibString); + virtual std::string GetLinkerLanguage(cmGeneratorTarget* target, + std::string const& config); + protected: std::string ComputeLinkLibs(cmComputeLinkInformation& cli); std::string ComputeRPath(cmComputeLinkInformation& cli); diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 75e5ef5..6a700ff 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -59,6 +59,12 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( return fout.str(); } +std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*, + std::string const&) +{ + return "CUDA"; +} + cmNinjaLinkLineDeviceComputer::cmNinjaLinkLineDeviceComputer( cmOutputConverter* outputConverter, cmStateDirectory stateDir, cmGlobalNinjaGenerator const* gg) diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h index d1079d7..f4bb3eb 100644 --- a/Source/cmLinkLineDeviceComputer.h +++ b/Source/cmLinkLineDeviceComputer.h @@ -17,6 +17,9 @@ public: std::string ComputeLinkLibraries(cmComputeLinkInformation& cli, std::string const& stdLibString) CM_OVERRIDE; + + std::string GetLinkerLanguage(cmGeneratorTarget* target, + std::string const& config) CM_OVERRIDE; }; class cmNinjaLinkLineDeviceComputer : public cmLinkLineDeviceComputer diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c index 31faca1..56559f6 100644 --- a/Source/cmListFileLexer.c +++ b/Source/cmListFileLexer.c @@ -2518,7 +2518,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer) } /*--------------------------------------------------------------------------*/ -cmListFileLexer* cmListFileLexer_New() +cmListFileLexer* cmListFileLexer_New(void) { cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer)); if (!lexer) { diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h index dfbad5e..c9fb6da 100644 --- a/Source/cmListFileLexer.h +++ b/Source/cmListFileLexer.h @@ -46,7 +46,7 @@ typedef struct cmListFileLexer_s cmListFileLexer; extern "C" { #endif -cmListFileLexer* cmListFileLexer_New(); +cmListFileLexer* cmListFileLexer_New(void); int cmListFileLexer_SetFileName(cmListFileLexer*, const char*, cmListFileLexer_BOM* bom); int cmListFileLexer_SetString(cmListFileLexer*, const char*); diff --git a/Source/cmListFileLexer.in.l b/Source/cmListFileLexer.in.l index 4b389b9..dd64923 100644 --- a/Source/cmListFileLexer.in.l +++ b/Source/cmListFileLexer.in.l @@ -398,7 +398,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer) } /*--------------------------------------------------------------------------*/ -cmListFileLexer* cmListFileLexer_New() +cmListFileLexer* cmListFileLexer_New(void) { cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer)); if (!lexer) { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index ead1e72..44c390c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -13,6 +13,7 @@ #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" +#include "cmLinkLineDeviceComputer.h" #include "cmMakefile.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" @@ -979,7 +980,9 @@ void cmLocalGenerator::GetTargetFlags( linkFlags += this->Makefile->GetSafeDefinition(build); linkFlags += " "; } - std::string linkLanguage = target->GetLinkerLanguage(buildType); + + const std::string linkLanguage = + linkLineComputer->GetLinkerLanguage(target, buildType); if (linkLanguage.empty()) { cmSystemTools::Error( "CMake can not determine linker language for target: ", diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index ba17f81..41a4caf 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1592,8 +1592,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( // Provide a "/fast" version of the target. depends.clear(); - if ((targetName == "install") || (targetName == "install_local") || - (targetName == "install_strip")) { + if ((targetName == "install") || (targetName == "install/local") || + (targetName == "install/strip")) { // Provide a fast install target that does not depend on all // but has the same command. depends.push_back("preinstall/fast"); diff --git a/Source/cmLocale.h b/Source/cmLocale.h index e8e751d..cca7cf5 100644 --- a/Source/cmLocale.h +++ b/Source/cmLocale.h @@ -6,10 +6,11 @@ #include <cmConfigure.h> #include <locale.h> +#include <string> class cmLocaleRAII { - const char* OldLocale; + std::string OldLocale; public: cmLocaleRAII() @@ -17,7 +18,7 @@ public: { setlocale(LC_CTYPE, ""); } - ~cmLocaleRAII() { setlocale(LC_CTYPE, this->OldLocale); } + ~cmLocaleRAII() { setlocale(LC_CTYPE, this->OldLocale.c_str()); } }; #endif diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 069011d..b76ddeb 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -104,10 +104,12 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( // Get the language to use for linking this library. std::string linkLanguage = "CUDA"; + std::string const objExt = + this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); // Get the name of the device object to generate. std::string const targetOutputReal = - this->GeneratorTarget->ObjectDirectory + "cmake_device_link.o"; + this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt; this->DeviceLinkObject = targetOutputReal; this->NumberOfProgressActions++; @@ -155,15 +157,6 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( this->LocalGenerator->AppendFlags( linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig)); - { - CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer( - this->CreateLinkLineComputer( - this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); - - this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags); - } - // Construct a list of files associated with this executable that // may need to be cleaned. std::vector<std::string> exeCleanFiles; @@ -228,6 +221,11 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal), output); + std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetOutPathCompilePDB = + this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB, + cmOutputConverter::SHELL); + vars.Language = linkLanguage.c_str(); vars.Objects = buildObjs.c_str(); vars.ObjectDir = objectDir.c_str(); @@ -235,6 +233,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( vars.LinkLibraries = linkLibs.c_str(); vars.Flags = flags.c_str(); vars.LinkFlags = linkFlags.c_str(); + vars.TargetCompilePDB = targetOutPathCompilePDB.c_str(); std::string launcher; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 2b0e1b1..27b7c21 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -281,6 +281,8 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( // Get the language to use for linking this library. std::string linkLanguage = "CUDA"; + std::string const objExt = + this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); // Create set of linking flags. std::string linkFlags; @@ -288,7 +290,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( // Get the name of the device object to generate. std::string const targetOutputReal = - this->GeneratorTarget->ObjectDirectory + "cmake_device_link.o"; + this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt; this->DeviceLinkObject = targetOutputReal; this->NumberOfProgressActions++; @@ -364,12 +366,18 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal), output); + std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetOutPathCompilePDB = + this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB, + cmOutputConverter::SHELL); + vars.Objects = buildObjs.c_str(); vars.ObjectDir = objectDir.c_str(); vars.Target = target.c_str(); vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); vars.LinkFlags = linkFlags.c_str(); + vars.TargetCompilePDB = targetOutPathCompilePDB.c_str(); // Add language feature flags. std::string langFlags; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 0db5687..b172478 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -229,6 +229,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) vars.SONameFlag = "$SONAME_FLAG"; vars.TargetSOName = "$SONAME"; vars.TargetPDB = "$TARGET_PDB"; + vars.TargetCompilePDB = "$TARGET_COMPILE_PDB"; vars.Flags = "$FLAGS"; vars.LinkFlags = "$LINK_FLAGS"; @@ -602,10 +603,12 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // First and very important step is to make sure while inside this // step our link language is set to CUDA std::string cudaLinkLanguage = "CUDA"; + std::string const objExt = + this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); std::string const cfgName = this->GetConfigName(); - std::string const targetOutputReal = - ConvertToNinjaPath(genTarget.ObjectDirectory + "cmake_device_link.o"); + std::string const targetOutputReal = ConvertToNinjaPath( + genTarget.ObjectDirectory + "cmake_device_link" + objExt); std::string const targetOutputImplib = ConvertToNinjaPath(genTarget.GetFullPath(cfgName, @@ -660,7 +663,6 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() this->addPoolNinjaVariable("JOB_POOL_LINK", &genTarget, vars); - this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"]); vars["LINK_FLAGS"] = cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]); @@ -714,6 +716,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL); EnsureDirectoryExists(objPath); + this->SetMsvcTargetPdbVariable(vars); + if (this->GetGlobalGenerator()->IsGCCOnWindows()) { // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) std::string& linkLibraries = vars["LINK_LIBRARIES"]; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 23caead..8ad2efe 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -344,7 +344,8 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const { cmMakefile* mf = this->GetMakefile(); if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") || - mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID")) { + mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") || + mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID")) { std::string pdbPath; std::string compilePdbPath = this->ComputeTargetCompilePDB(); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE || diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index f0847b1..825eba0 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -99,39 +99,64 @@ static std::string GetQtMajorVersion(cmGeneratorTarget const* target) } static void SetupSourceFiles(cmGeneratorTarget const* target, - std::vector<std::string>& skipMoc, - std::vector<std::string>& mocSources, - std::vector<std::string>& mocHeaders, - std::vector<std::string>& skipUic) + std::vector<std::string>& mocUicSources, + std::vector<std::string>& mocUicHeaders, + std::vector<std::string>& skipMocList, + std::vector<std::string>& skipUicList) { cmMakefile* makefile = target->Target->GetMakefile(); std::vector<cmSourceFile*> srcFiles; target->GetConfigCommonSourceFiles(srcFiles); + const bool targetMoc = target->GetPropertyAsBool("AUTOMOC"); + const bool targetUic = target->GetPropertyAsBool("AUTOUIC"); + cmFilePathChecksum fpathCheckSum(makefile); for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; + const cmSystemTools::FileFormat fileType = + cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); + + if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && + !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { + continue; + } + if (cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { + continue; + } const std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - const std::string ext = sf->GetExtension(); - - if (cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC"))) { - skipUic.push_back(absFile); - } - - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - if (cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC"))) { - skipMoc.push_back(absFile); - } else { - cmSystemTools::FileFormat fileType = - cmSystemTools::GetFileFormat(ext.c_str()); - if (fileType == cmSystemTools::CXX_FILE_FORMAT) { - mocSources.push_back(absFile); - } else if (fileType == cmSystemTools::HEADER_FILE_FORMAT) { - mocHeaders.push_back(absFile); - } + // Skip flags + const bool skipAll = + cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")); + const bool skipMoc = + skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); + const bool skipUic = + skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("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 + // processing + if (skipMoc) { + skipMocList.push_back(absFile); + } + if (skipUic) { + skipUicList.push_back(absFile); + } + + if ((targetMoc && !skipMoc) || (targetUic && !skipUic)) { + // Add file name to sources or headers list + switch (fileType) { + case cmSystemTools::CXX_FILE_FORMAT: + mocUicSources.push_back(absFile); + break; + case cmSystemTools::HEADER_FILE_FORMAT: + mocUicHeaders.push_back(absFile); + break; + default: + break; } } } @@ -158,7 +183,6 @@ static void GetCompileDefinitionsAndDirectories( static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, std::vector<std::string> const& skipMoc, - std::vector<std::string> const& mocHeaders, std::map<std::string, std::string>& configIncludes, std::map<std::string, std::string>& configDefines) { @@ -172,9 +196,6 @@ static void MocSetupAutoTarget( makefile->AddDefinition( "_skip_moc", cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); - makefile->AddDefinition( - "_moc_headers", - cmOutputConverter::EscapeForCMake(cmJoin(mocHeaders, ";")).c_str()); bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); @@ -569,7 +590,9 @@ static void RccSetupAutoTarget(cmGeneratorTarget const* target, std::string ext = sf->GetExtension(); if (ext == "qrc") { std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); + const bool skip = + cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) || + cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); if (!skip) { _rcc_files += sepRccFiles; @@ -632,7 +655,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenSources( cmMakefile* makefile = target->Target->GetMakefile(); const std::string mocCppFile = GetAutogenTargetBuildDir(target) + "moc_compilation.cpp"; - makefile->GetOrCreateSource(mocCppFile, true); + cmSourceFile* gf = makefile->GetOrCreateSource(mocCppFile, true); + gf->SetProperty("SKIP_AUTOGEN", "On"); target->AddSource(mocCppFile); } } @@ -650,6 +674,14 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( const std::string qtMajorVersion = GetQtMajorVersion(target); std::vector<std::string> autogenOutputFiles; + // Remove old settings on cleanup + { + std::string fname = GetAutogenTargetFilesDir(target); + fname += "/AutogenOldSettings.cmake"; + makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fname.c_str(), + false); + } + // Create autogen target build directory and add it to the clean files cmSystemTools::MakeDirectory(autogenBuildDir); makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", @@ -747,6 +779,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; if (sf->GetExtension() == "qrc" && + !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) { { const std::string absFile = @@ -763,7 +796,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( rccOutputFile += ".cpp"; // Add rcc output file to origin target sources - makefile->GetOrCreateSource(rccOutputFile, true); + cmSourceFile* gf = makefile->GetOrCreateSource(rccOutputFile, true); + gf->SetProperty("SKIP_AUTOGEN", "On"); target->AddSource(rccOutputFile); // Register rcc output file as generated autogenOutputFiles.push_back(rccOutputFile); @@ -850,10 +884,10 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str()); - std::vector<std::string> skipUic; + std::vector<std::string> mocUicSources; + std::vector<std::string> mocUicHeaders; std::vector<std::string> skipMoc; - std::vector<std::string> mocSources; - std::vector<std::string> mocHeaders; + std::vector<std::string> skipUic; std::map<std::string, std::string> configMocIncludes; std::map<std::string, std::string> configMocDefines; std::map<std::string, std::string> configUicOptions; @@ -861,14 +895,18 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( if (target->GetPropertyAsBool("AUTOMOC") || target->GetPropertyAsBool("AUTOUIC") || target->GetPropertyAsBool("AUTORCC")) { - SetupSourceFiles(target, skipMoc, mocSources, mocHeaders, skipUic); + SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); } makefile->AddDefinition( - "_cpp_files", - cmOutputConverter::EscapeForCMake(cmJoin(mocSources, ";")).c_str()); + "_moc_uic_sources", + cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); + makefile->AddDefinition( + "_moc_uic_headers", + cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); + if (target->GetPropertyAsBool("AUTOMOC")) { - MocSetupAutoTarget(target, autogenTargetName, skipMoc, mocHeaders, - configMocIncludes, configMocDefines); + MocSetupAutoTarget(target, autogenTargetName, skipMoc, configMocIncludes, + configMocDefines); } if (target->GetPropertyAsBool("AUTOUIC")) { UicSetupAutoTarget(target, skipUic, configUicOptions); diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a9a9c49..c84fe4f 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -6,7 +6,6 @@ #include <assert.h> #include <cmConfigure.h> #include <cmsys/FStream.hxx> -#include <cmsys/RegularExpression.hxx> #include <cmsys/Terminal.h> #include <iostream> #include <sstream> @@ -28,28 +27,39 @@ #include <unistd.h> #endif -static bool requiresMocing(const std::string& text, std::string& macroName) -{ - // this simple check is much much faster than the regexp - if (strstr(text.c_str(), "Q_OBJECT") == CM_NULLPTR && - strstr(text.c_str(), "Q_GADGET") == CM_NULLPTR) { - return false; - } +// -- Static variables - cmsys::RegularExpression qObjectRegExp("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); - if (qObjectRegExp.find(text)) { - macroName = "Q_OBJECT"; - return true; +static const char* MocOldSettingsKey = "AM_MOC_OLD_SETTINGS"; +static const char* UicOldSettingsKey = "AM_UIC_OLD_SETTINGS"; +static const char* RccOldSettingsKey = "AM_RCC_OLD_SETTINGS"; + +// -- Static functions + +static std::string GetConfigDefinition(cmMakefile* makefile, + const std::string& key, + const std::string& config) +{ + std::string keyConf = key; + if (!config.empty()) { + keyConf += "_"; + keyConf += config; } - cmsys::RegularExpression qGadgetRegExp("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); - if (qGadgetRegExp.find(text)) { - macroName = "Q_GADGET"; - return true; + const char* valueConf = makefile->GetDefinition(keyConf); + if (valueConf != CM_NULLPTR) { + return valueConf; } - return false; + return makefile->GetSafeDefinition(key); } -static std::string findMatchingHeader( +static std::string OldSettingsFile(const std::string& targetDirectory) +{ + std::string filename(cmSystemTools::CollapseFullPath(targetDirectory)); + cmSystemTools::ConvertToUnixSlashes(filename); + filename += "/AutogenOldSettings.cmake"; + return filename; +} + +static std::string FindMatchingHeader( const std::string& absPath, const std::string& mocSubDir, const std::string& basename, const std::vector<std::string>& headerExtensions) @@ -62,6 +72,7 @@ static std::string findMatchingHeader( header = sourceFilePath; break; } + // Try subdirectory instead if (!mocSubDir.empty()) { sourceFilePath = mocSubDir + basename + "." + (*ext); if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) { @@ -74,7 +85,7 @@ static std::string findMatchingHeader( return header; } -static std::string extractSubDir(const std::string& absPath, +static std::string ExtractSubDir(const std::string& absPath, const std::string& currentMoc) { std::string subDir; @@ -101,29 +112,69 @@ static bool FileNameIsUnique(const std::string& filePath, return true; } -cmQtAutoGenerators::cmQtAutoGenerators() - : Verbose(cmsys::SystemTools::HasEnv("VERBOSE")) - , ColorOutput(true) - , RunMocFailed(false) - , RunUicFailed(false) - , RunRccFailed(false) - , GenerateAll(false) +static std::string ReadAll(const std::string& filename) { + cmsys::ifstream file(filename.c_str()); + std::ostringstream stream; + stream << file.rdbuf(); + file.close(); + return stream.str(); +} - std::string colorEnv; - cmsys::SystemTools::GetEnv("COLOR", colorEnv); - if (!colorEnv.empty()) { - if (cmSystemTools::IsOn(colorEnv.c_str())) { - this->ColorOutput = true; - } else { - this->ColorOutput = false; +/** + * @brief Tests if buildFile doesn't exist or is older than sourceFile + * @return True if buildFile doesn't exist or is older than sourceFile + */ +static bool FileAbsentOrOlder(const std::string& buildFile, + const std::string& sourceFile) +{ + int result = 0; + bool success = + cmsys::SystemTools::FileTimeCompare(buildFile, sourceFile, &result); + return (!success || (result <= 0)); +} + +static bool ListContains(const std::vector<std::string>& list, + const std::string& entry) +{ + return (std::find(list.begin(), list.end(), entry) != list.end()); +} + +static std::string JoinOptions(const std::map<std::string, std::string>& opts) +{ + std::string result; + for (std::map<std::string, std::string>::const_iterator it = opts.begin(); + it != opts.end(); ++it) { + if (it != opts.begin()) { + result += "%%%"; + } + result += it->first; + result += "==="; + result += it->second; + } + return result; +} + +static std::string JoinExts(const std::vector<std::string>& lst) +{ + std::string result; + if (!lst.empty()) { + const std::string separator = ","; + for (std::vector<std::string>::const_iterator it = lst.begin(); + it != lst.end(); ++it) { + if (it != lst.begin()) { + result += separator; + } + result += '.'; + result += *it; } } + return result; } -void cmQtAutoGenerators::MergeUicOptions( - std::vector<std::string>& opts, const std::vector<std::string>& fileOpts, - bool isQt5) +static void UicMergeOptions(std::vector<std::string>& opts, + const std::vector<std::string>& fileOpts, + bool isQt5) { static const char* valueOptions[] = { "tr", "translate", "postfix", "generator", @@ -155,6 +206,39 @@ void cmQtAutoGenerators::MergeUicOptions( opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); } +// -- Class methods + +cmQtAutoGenerators::cmQtAutoGenerators() + : Verbose(cmsys::SystemTools::HasEnv("VERBOSE")) + , ColorOutput(true) + , RunMocFailed(false) + , RunUicFailed(false) + , RunRccFailed(false) + , GenerateMocAll(false) + , GenerateUicAll(false) + , GenerateRccAll(false) +{ + + std::string colorEnv; + cmsys::SystemTools::GetEnv("COLOR", colorEnv); + if (!colorEnv.empty()) { + if (cmSystemTools::IsOn(colorEnv.c_str())) { + this->ColorOutput = true; + } else { + this->ColorOutput = false; + } + } + + // Precompile regular expressions + this->RegExpQObject.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); + this->RegExpQGadget.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); + this->RegExpMocInclude.compile( + "[\n][ \t]*#[ \t]*include[ \t]+" + "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]"); + this->RegExpUicInclude.compile("[\n][ \t]*#[ \t]*include[ \t]+" + "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); +} + bool cmQtAutoGenerators::Run(const std::string& targetDirectory, const std::string& config) { @@ -174,15 +258,20 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, if (!this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) { return false; } - this->ReadOldMocDefinitionsFile(mf.get(), targetDirectory); + // Read old settings + this->OldSettingsReadFile(mf.get(), targetDirectory); + // Init and run this->Init(); - if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") { if (!this->RunAutogen(mf.get())) { return false; } } - return this->WriteOldMocDefinitionsFile(targetDirectory); + // Write latest settings + if (!this->OldSettingsWriteFile(targetDirectory)) { + return false; + } + return true; } bool cmQtAutoGenerators::ReadAutogenInfoFile( @@ -195,7 +284,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( if (!makefile->ReadListFile(filename.c_str())) { std::ostringstream err; - err << "AUTOGEN: error processing file: " << filename << std::endl; + err << "AutoGen: error processing file: " << filename << std::endl; this->LogError(err.str()); return false; } @@ -224,59 +313,38 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( this->RccExecutable = makefile->GetSafeDefinition("AM_QT_RCC_EXECUTABLE"); // - File Lists - this->Sources = makefile->GetSafeDefinition("AM_SOURCES"); - this->Headers = makefile->GetSafeDefinition("AM_HEADERS"); + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SOURCES"), + this->Sources); + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_HEADERS"), + this->Headers); // - Moc - this->SkipMoc = makefile->GetSafeDefinition("AM_SKIP_MOC"); - { - std::string compileDefsPropOrig = "AM_MOC_COMPILE_DEFINITIONS"; - std::string compileDefsProp = compileDefsPropOrig; - if (!config.empty()) { - compileDefsProp += "_"; - compileDefsProp += config; - } - const char* compileDefs = makefile->GetDefinition(compileDefsProp); - this->MocCompileDefinitionsStr = compileDefs - ? compileDefs - : makefile->GetSafeDefinition(compileDefsPropOrig); - } - { - std::string includesPropOrig = "AM_MOC_INCLUDES"; - std::string includesProp = includesPropOrig; - if (!config.empty()) { - includesProp += "_"; - includesProp += config; - } - const char* includes = makefile->GetDefinition(includesProp); - this->MocIncludesStr = - includes ? includes : makefile->GetSafeDefinition(includesPropOrig); - } + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), + this->SkipMoc); + this->MocCompileDefinitionsStr = + GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config); + this->MocIncludesStr = + GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config); this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS"); // - Uic - this->SkipUic = makefile->GetSafeDefinition("AM_SKIP_UIC"); + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"), + this->SkipUic); + cmSystemTools::ExpandListArgument( + GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config), + this->UicTargetOptions); { - const char* uicOptionsFiles = - makefile->GetSafeDefinition("AM_UIC_OPTIONS_FILES"); - std::string uicOptionsPropOrig = "AM_UIC_TARGET_OPTIONS"; - std::string uicOptionsProp = uicOptionsPropOrig; - if (!config.empty()) { - uicOptionsProp += "_"; - uicOptionsProp += config; - } - const char* uicTargetOptions = makefile->GetSafeDefinition(uicOptionsProp); - cmSystemTools::ExpandListArgument( - uicTargetOptions ? uicTargetOptions - : makefile->GetSafeDefinition(uicOptionsPropOrig), - this->UicTargetOptions); - const char* uicOptionsOptions = - makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS"); std::vector<std::string> uicFilesVec; - cmSystemTools::ExpandListArgument(uicOptionsFiles, uicFilesVec); std::vector<std::string> uicOptionsVec; - cmSystemTools::ExpandListArgument(uicOptionsOptions, uicOptionsVec); + cmSystemTools::ExpandListArgument( + makefile->GetSafeDefinition("AM_UIC_OPTIONS_FILES"), uicFilesVec); + cmSystemTools::ExpandListArgument( + makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS"), uicOptionsVec); if (uicFilesVec.size() != uicOptionsVec.size()) { + std::ostringstream err; + err << "AutoGen: Error: Uic files/options lists size missmatch in: " + << filename << std::endl; + this->LogError(err.str()); return false; } for (std::vector<std::string>::iterator fileIt = uicFilesVec.begin(), @@ -288,20 +356,20 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } // - Rcc + cmSystemTools::ExpandListArgument( + makefile->GetSafeDefinition("AM_RCC_SOURCES"), this->RccSources); { - std::string rccSources = makefile->GetSafeDefinition("AM_RCC_SOURCES"); - cmSystemTools::ExpandListArgument(rccSources, this->RccSources); - } - { - const char* rccOptionsFiles = - makefile->GetSafeDefinition("AM_RCC_OPTIONS_FILES"); - const char* rccOptionsOptions = - makefile->GetSafeDefinition("AM_RCC_OPTIONS_OPTIONS"); std::vector<std::string> rccFilesVec; - cmSystemTools::ExpandListArgument(rccOptionsFiles, rccFilesVec); std::vector<std::string> rccOptionsVec; - cmSystemTools::ExpandListArgument(rccOptionsOptions, rccOptionsVec); + cmSystemTools::ExpandListArgument( + makefile->GetSafeDefinition("AM_RCC_OPTIONS_FILES"), rccFilesVec); + cmSystemTools::ExpandListArgument( + makefile->GetSafeDefinition("AM_RCC_OPTIONS_OPTIONS"), rccOptionsVec); if (rccFilesVec.size() != rccOptionsVec.size()) { + std::ostringstream err; + err << "AutoGen: Error: RCC files/options lists size missmatch in: " + << filename << std::endl; + this->LogError(err.str()); return false; } for (std::vector<std::string>::iterator fileIt = rccFilesVec.begin(), @@ -310,10 +378,11 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); this->RccOptions[*fileIt] = *optionIt; } - - const char* rccInputs = makefile->GetSafeDefinition("AM_RCC_INPUTS"); + } + { std::vector<std::string> rccInputLists; - cmSystemTools::ExpandListArgument(rccInputs, rccInputLists); + cmSystemTools::ExpandListArgument( + makefile->GetSafeDefinition("AM_RCC_INPUTS"), rccInputLists); // qrc files in the end of the list may have been empty if (rccInputLists.size() < this->RccSources.size()) { @@ -321,26 +390,21 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } if (this->RccSources.size() != rccInputLists.size()) { std::ostringstream err; - err << "AUTOGEN: RCC sources lists size missmatch in: " << filename; - err << std::endl; + err << "AutoGen: Error: RCC sources/inputs lists size missmatch in: " + << filename << std::endl; this->LogError(err.str()); 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; } } - // - Settings - this->CurrentCompileSettingsStr = this->MakeCompileSettingsString(makefile); - // - Flags this->IncludeProjectDirsBefore = makefile->IsOn("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"); @@ -349,58 +413,124 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( return true; } -std::string cmQtAutoGenerators::MakeCompileSettingsString(cmMakefile* makefile) +std::string cmQtAutoGenerators::MocSettingsStringCompose() { - std::string s; - s += makefile->GetSafeDefinition("AM_MOC_COMPILE_DEFINITIONS"); - s += " ~~~ "; - s += makefile->GetSafeDefinition("AM_MOC_INCLUDES"); - s += " ~~~ "; - s += makefile->GetSafeDefinition("AM_MOC_OPTIONS"); - s += " ~~~ "; - s += makefile->IsOn("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE") ? "TRUE" - : "FALSE"; - s += " ~~~ "; - - return s; + std::string res; + res += this->MocCompileDefinitionsStr; + res += " ~~~ "; + res += this->MocIncludesStr; + res += " ~~~ "; + res += this->MocOptionsStr; + res += " ~~~ "; + res += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; + res += " ~~~ "; + return res; } -void cmQtAutoGenerators::ReadOldMocDefinitionsFile( - cmMakefile* makefile, const std::string& targetDirectory) +std::string cmQtAutoGenerators::UicSettingsStringCompose() { - std::string filename(cmSystemTools::CollapseFullPath(targetDirectory)); - cmSystemTools::ConvertToUnixSlashes(filename); - filename += "/AutomocOldMocDefinitions.cmake"; + std::string res; + res += cmJoin(this->UicTargetOptions, "@osep@"); + res += " ~~~ "; + res += JoinOptions(this->UicOptions); + res += " ~~~ "; + return res; +} + +std::string cmQtAutoGenerators::RccSettingsStringCompose() +{ + std::string res; + res += JoinOptions(this->RccOptions); + res += " ~~~ "; + return res; +} - if (makefile->ReadListFile(filename.c_str())) { - this->OldCompileSettingsStr = - makefile->GetSafeDefinition("AM_OLD_COMPILE_SETTINGS"); +void cmQtAutoGenerators::OldSettingsReadFile( + cmMakefile* makefile, const std::string& targetDirectory) +{ + if (!this->MocExecutable.empty() || !this->UicExecutable.empty() || + !this->RccExecutable.empty()) { + // Compose current settings strings + this->MocSettingsString = this->MocSettingsStringCompose(); + this->UicSettingsString = this->UicSettingsStringCompose(); + this->RccSettingsString = this->RccSettingsStringCompose(); + + // Read old settings + const std::string filename = OldSettingsFile(targetDirectory); + if (makefile->ReadListFile(filename.c_str())) { + if (!this->MocExecutable.empty()) { + const std::string sol = makefile->GetSafeDefinition(MocOldSettingsKey); + if (sol != this->MocSettingsString) { + this->GenerateMocAll = true; + } + } + if (!this->UicExecutable.empty()) { + const std::string sol = makefile->GetSafeDefinition(UicOldSettingsKey); + if (sol != this->UicSettingsString) { + this->GenerateUicAll = true; + } + } + if (!this->RccExecutable.empty()) { + const std::string sol = makefile->GetSafeDefinition(RccOldSettingsKey); + if (sol != this->RccSettingsString) { + this->GenerateRccAll = true; + } + } + // In case any setting changed remove the old settings file. + // This triggers a full rebuild on the next run if the current + // build is aborted before writing the current settings in the end. + if (this->GenerateMocAll || this->GenerateUicAll || + this->GenerateRccAll) { + cmSystemTools::RemoveFile(filename); + } + } else { + // If the file could not be read re-generate everythiung. + this->GenerateMocAll = true; + this->GenerateUicAll = true; + this->GenerateRccAll = true; + } } } -bool cmQtAutoGenerators::WriteOldMocDefinitionsFile( +bool cmQtAutoGenerators::OldSettingsWriteFile( const std::string& targetDirectory) { bool success = true; - - std::string filename(cmSystemTools::CollapseFullPath(targetDirectory)); - cmSystemTools::ConvertToUnixSlashes(filename); - filename += "/AutomocOldMocDefinitions.cmake"; - - { + // Only write if any setting changed + if (this->GenerateMocAll || this->GenerateUicAll || this->GenerateRccAll) { + const std::string filename = OldSettingsFile(targetDirectory); cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); if (outfile) { - outfile << "set(AM_OLD_COMPILE_SETTINGS " - << cmOutputConverter::EscapeForCMake( - this->CurrentCompileSettingsStr) - << ")\n"; + if (!this->MocExecutable.empty()) { + outfile << "set(" << MocOldSettingsKey << " " + << cmOutputConverter::EscapeForCMake(this->MocSettingsString) + << ")\n"; + } + if (!this->UicExecutable.empty()) { + outfile << "set(" << UicOldSettingsKey << " " + << cmOutputConverter::EscapeForCMake(this->UicSettingsString) + << ")\n"; + } + if (!this->RccExecutable.empty()) { + outfile << "set(" << RccOldSettingsKey << " " + << cmOutputConverter::EscapeForCMake(this->RccSettingsString) + << ")\n"; + } success = outfile.good(); + outfile.close(); } else { success = false; + // Remove old settings file to trigger full rebuild on next run + cmSystemTools::RemoveFile(filename); + { + std::ostringstream err; + err << "AutoGen: Error: Writing old settings file failed: " << filename + << std::endl; + this->LogError(err.str()); + } } } - return success; } @@ -455,7 +585,6 @@ void cmQtAutoGenerators::Init() if (this->IncludeProjectDirsBefore) { const std::string binDir = "-I" + this->ProjectBinaryDir; - const std::string srcDir = "-I" + this->ProjectSourceDir; std::list<std::string> sortedMocIncludes; @@ -484,22 +613,8 @@ void cmQtAutoGenerators::Init() } } -static std::string ReadAll(const std::string& filename) -{ - cmsys::ifstream file(filename.c_str()); - std::ostringstream stream; - stream << file.rdbuf(); - file.close(); - return stream.str(); -} - bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) { - // If settings changed everything needs to be re-generated. - if (this->OldCompileSettingsStr != this->CurrentCompileSettingsStr) { - this->GenerateAll = true; - } - // the program goes through all .cpp files to see which moc files are // included. It is not really interesting how the moc file is named, but // what file the moc is created from. Once a moc is included the same moc @@ -510,269 +625,353 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) // key = moc source filepath, value = moc output filepath std::map<std::string, std::string> includedMocs; - // collect all headers which may need to be mocced - std::set<std::string> headerFiles; - - std::vector<std::string> sourceFiles; - cmSystemTools::ExpandListArgument(this->Sources, sourceFiles); - - const std::vector<std::string>& headerExtensions = - makefile->GetCMakeInstance()->GetHeaderExtensions(); - + std::map<std::string, std::string> notIncludedMocs; std::map<std::string, std::vector<std::string> > includedUis; - std::map<std::string, std::vector<std::string> > skippedUis; - std::vector<std::string> uicSkipped; - cmSystemTools::ExpandListArgument(this->SkipUic, uicSkipped); - - for (std::vector<std::string>::const_iterator it = sourceFiles.begin(); - it != sourceFiles.end(); ++it) { - const bool skipUic = - std::find(uicSkipped.begin(), uicSkipped.end(), *it) != uicSkipped.end(); - std::map<std::string, std::vector<std::string> >& uiFiles = - skipUic ? skippedUis : includedUis; - const std::string& absFilename = *it; - if (this->Verbose) { - std::ostringstream err; - err << "AUTOGEN: Checking " << absFilename << std::endl; - this->LogInfo(err.str()); - } - if (this->MocRelaxedMode) { - if (!this->ParseCppFile(absFilename, headerExtensions, includedMocs, - uiFiles)) { - return false; - } - } else { - if (!this->StrictParseCppFile(absFilename, headerExtensions, - includedMocs, uiFiles)) { + // collects all headers which may need to be mocced + std::set<std::string> headerFilesMoc; + std::set<std::string> headerFilesUic; + + // Parse sources + { + const std::vector<std::string>& headerExtensions = + makefile->GetCMakeInstance()->GetHeaderExtensions(); + + for (std::vector<std::string>::const_iterator it = this->Sources.begin(); + it != this->Sources.end(); ++it) { + const std::string& absFilename = *it; + // Parse source file for MOC/UIC + if (!this->ParseSourceFile(absFilename, headerExtensions, includedMocs, + includedUis, this->MocRelaxedMode)) { return false; } + // Find additional headers + this->SearchHeadersForSourceFile(absFilename, headerExtensions, + headerFilesMoc, headerFilesUic); } - this->SearchHeadersForCppFile(absFilename, headerExtensions, headerFiles); } - { - std::vector<std::string> mocSkipped; - cmSystemTools::ExpandListArgument(this->SkipMoc, mocSkipped); - for (std::vector<std::string>::const_iterator it = mocSkipped.begin(); - it != mocSkipped.end(); ++it) { - if (std::find(uicSkipped.begin(), uicSkipped.end(), *it) != - uicSkipped.end()) { - const std::string& absFilename = *it; - if (this->Verbose) { - std::ostringstream err; - err << "AUTOGEN: Checking " << absFilename << std::endl; - this->LogInfo(err.str()); - } - this->ParseForUic(absFilename, includedUis); - } + // Parse headers + for (std::vector<std::string>::const_iterator it = this->Headers.begin(); + it != this->Headers.end(); ++it) { + const std::string& headerName = *it; + if (!this->MocSkipTest(headerName)) { + headerFilesMoc.insert(this->Headers.begin(), this->Headers.end()); + } + if (!this->UicSkipTest(headerName)) { + headerFilesUic.insert(this->Headers.begin(), this->Headers.end()); } } + this->ParseHeaders(headerFilesMoc, headerFilesUic, includedMocs, + notIncludedMocs, includedUis); - std::vector<std::string> headerFilesVec; - cmSystemTools::ExpandListArgument(this->Headers, headerFilesVec); - headerFiles.insert(headerFilesVec.begin(), headerFilesVec.end()); + // Generate files + if (!this->MocGenerateAll(includedMocs, notIncludedMocs)) { + return false; + } + if (!this->UicGenerateAll(includedUis)) { + return false; + } + if (!this->QrcGenerateAll()) { + return false; + } - // key = moc source filepath, value = moc output filename - std::map<std::string, std::string> notIncludedMocs; - this->ParseHeaders(headerFiles, includedMocs, notIncludedMocs, includedUis); + return true; +} - if (!this->MocExecutable.empty()) { - if (!this->GenerateMocFiles(includedMocs, notIncludedMocs)) { - return false; +/** + * @brief Tests if the C++ content requires moc processing + * @return True if moc is required + */ +bool cmQtAutoGenerators::MocRequired(const std::string& text, + std::string& macroName) +{ + // Run a simple check before an expensive regular expression check + if (strstr(text.c_str(), "Q_OBJECT") != CM_NULLPTR) { + if (this->RegExpQObject.find(text)) { + macroName = "Q_OBJECT"; + return true; } } - if (!this->UicExecutable.empty()) { - if (!this->GenerateUiFiles(includedUis)) { - return false; + if (strstr(text.c_str(), "Q_GADGET") != CM_NULLPTR) { + if (this->RegExpQGadget.find(text)) { + macroName = "Q_GADGET"; + return true; } } - if (!this->RccExecutable.empty()) { - if (!this->GenerateQrcFiles()) { + return false; +} + +/** + * @brief Tests if the file should be ignored for moc scanning + * @return True if the file should be ignored + */ +bool cmQtAutoGenerators::MocSkipTest(const std::string& absFilename) +{ + // Test if moc scanning is enabled + if (!this->MocExecutable.empty()) { + // Test if the file name is on the skip list + if (!ListContains(this->SkipMoc, absFilename)) { return false; } } + return true; +} +/** + * @brief Tests if the file name is in the skip list + */ +bool cmQtAutoGenerators::UicSkipTest(const std::string& absFilename) +{ + // Test if uic scanning is enabled + if (!this->UicExecutable.empty()) { + // Test if the file name is on the skip list + if (!ListContains(this->SkipUic, absFilename)) { + return false; + } + } return true; } /** * @return True on success */ -bool cmQtAutoGenerators::ParseCppFile( +bool cmQtAutoGenerators::ParseSourceFile( const std::string& absFilename, const std::vector<std::string>& headerExtensions, std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::vector<std::string> >& includedUis) + std::map<std::string, std::vector<std::string> >& includedUis, bool relaxed) { - cmsys::RegularExpression mocIncludeRegExp( - "[\n][ \t]*#[ \t]*include[ \t]+" - "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]"); - + bool success = true; const std::string contentsString = ReadAll(absFilename); if (contentsString.empty()) { std::ostringstream err; - err << "AUTOGEN: warning: " << absFilename << ": file is empty\n" - << std::endl; + err << "AutoGen: Warning: " << absFilename << "\n" + << "The file is empty\n"; this->LogWarning(err.str()); - return true; + } else { + // Parse source contents for MOC + if (success && !this->MocSkipTest(absFilename)) { + success = this->ParseContentForMoc( + absFilename, contentsString, headerExtensions, includedMocs, relaxed); + } + // Parse source contents for UIC + if (success && !this->UicSkipTest(absFilename)) { + this->ParseContentForUic(absFilename, contentsString, includedUis); + } } - this->ParseForUic(absFilename, contentsString, includedUis); - if (this->MocExecutable.empty()) { - return true; + return success; +} + +void cmQtAutoGenerators::ParseContentForUic( + const std::string& absFilename, const std::string& contentsString, + std::map<std::string, std::vector<std::string> >& includedUis) +{ + // Process + if (this->Verbose) { + std::ostringstream err; + err << "AutoUic: Checking " << absFilename << "\n"; + this->LogInfo(err.str()); + } + + const std::string realName = cmsys::SystemTools::GetRealPath(absFilename); + const char* contentChars = contentsString.c_str(); + if (strstr(contentChars, "ui_") != CM_NULLPTR) { + while (this->RegExpUicInclude.find(contentChars)) { + const std::string currentUi = this->RegExpUicInclude.match(1); + const std::string basename = + cmsys::SystemTools::GetFilenameWithoutLastExtension(currentUi); + // basename should be the part of the ui filename used for + // finding the correct header, so we need to remove the ui_ part + includedUis[realName].push_back(basename.substr(3)); + contentChars += this->RegExpUicInclude.end(); + } + } +} + +/** + * @return True on success + */ +bool cmQtAutoGenerators::ParseContentForMoc( + const std::string& absFilename, const std::string& contentsString, + const std::vector<std::string>& headerExtensions, + std::map<std::string, std::string>& includedMocs, bool relaxed) +{ + // Process + if (this->Verbose) { + std::ostringstream err; + err << "AutoMoc: Checking " << absFilename << "\n"; + this->LogInfo(err.str()); } - const std::string absPath = cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)) + + const std::string scannedFileAbsPath = + cmsys::SystemTools::GetFilenamePath( + cmsys::SystemTools::GetRealPath(absFilename)) + '/'; const std::string scannedFileBasename = cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); + std::string macroName; - const bool requiresMoc = requiresMocing(contentsString, macroName); - bool dotMocIncluded = false; - bool mocUnderscoreIncluded = false; + const bool requiresMoc = this->MocRequired(contentsString, macroName); + bool ownDotMocIncluded = false; + bool ownMocUnderscoreIncluded = false; std::string ownMocUnderscoreFile; - std::string ownDotMocFile; std::string ownMocHeaderFile; - std::string::size_type matchOffset = 0; // first a simple string check for "moc" is *much* faster than the regexp, // and if the string search already fails, we don't have to try the // expensive regexp - if ((strstr(contentsString.c_str(), "moc") != CM_NULLPTR) && - (mocIncludeRegExp.find(contentsString))) { - // for every moc include in the file - do { - const std::string currentMoc = mocIncludeRegExp.match(1); - + const char* contentChars = contentsString.c_str(); + if (strstr(contentChars, "moc") != CM_NULLPTR) { + // Iterate over all included moc files + while (this->RegExpMocInclude.find(contentChars)) { + const std::string currentMoc = this->RegExpMocInclude.match(1); + // Basename of the current moc include std::string basename = cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc); - const bool moc_style = cmHasLiteralPrefix(basename, "moc_"); // If the moc include is of the moc_foo.cpp style we expect // the Q_OBJECT class declaration in a header file. // If the moc include is of the foo.moc style we need to look for // a Q_OBJECT macro in the current source file, if it contains the // macro we generate the moc file from the source file. - // Q_OBJECT - if (moc_style) { + if (cmHasLiteralPrefix(basename, "moc_")) { + // Include: moc_FOO.cxx // basename should be the part of the moc filename used for // finding the correct header, so we need to remove the moc_ part basename = basename.substr(4); - std::string mocSubDir = extractSubDir(absPath, currentMoc); - std::string headerToMoc = - findMatchingHeader(absPath, mocSubDir, basename, headerExtensions); + const std::string mocSubDir = + ExtractSubDir(scannedFileAbsPath, currentMoc); + const std::string headerToMoc = FindMatchingHeader( + scannedFileAbsPath, mocSubDir, basename, headerExtensions); if (!headerToMoc.empty()) { includedMocs[headerToMoc] = currentMoc; - if (basename == scannedFileBasename) { - mocUnderscoreIncluded = true; + if (relaxed && (basename == scannedFileBasename)) { + ownMocUnderscoreIncluded = true; ownMocUnderscoreFile = currentMoc; ownMocHeaderFile = headerToMoc; } } else { std::ostringstream err; - err << "AUTOGEN: error: " << absFilename << ": The file " - << "includes the moc file \"" << currentMoc << "\", " - << "but could not find header \"" << basename << '{' - << this->JoinExts(headerExtensions) << "}\" "; + err << "AutoMoc: Error: " << absFilename << "\n" + << "The file includes the moc file \"" << currentMoc + << "\", but could not find header \"" << basename << '{' + << JoinExts(headerExtensions) << "}\" "; if (mocSubDir.empty()) { - err << "in " << absPath << "\n" << std::endl; + err << "in " << scannedFileAbsPath << "\n"; } else { - err << "neither in " << absPath << " nor in " << mocSubDir << "\n" - << std::endl; + err << "neither in " << scannedFileAbsPath << " nor in " + << mocSubDir << "\n"; } this->LogError(err.str()); return false; } } else { - std::string fileToMoc = absFilename; - if (!requiresMoc || basename != scannedFileBasename) { - std::string mocSubDir = extractSubDir(absPath, currentMoc); - std::string headerToMoc = - findMatchingHeader(absPath, mocSubDir, basename, headerExtensions); - if (!headerToMoc.empty()) { - // this is for KDE4 compatibility: - fileToMoc = headerToMoc; - if (!requiresMoc && basename == scannedFileBasename) { - std::ostringstream err; - err << "AUTOGEN: warning: " << absFilename - << ": The file " - "includes the moc file \"" - << currentMoc << "\", but does not contain a " << macroName - << " macro. Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename - << ".cpp\" for a compatibility with " - "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n" - << std::endl; - this->LogWarning(err.str()); + // Include: FOO.moc + std::string fileToMoc; + if (relaxed) { + // Mode: Relaxed + if (!requiresMoc || basename != scannedFileBasename) { + const std::string mocSubDir = + ExtractSubDir(scannedFileAbsPath, currentMoc); + const std::string headerToMoc = FindMatchingHeader( + scannedFileAbsPath, mocSubDir, basename, headerExtensions); + if (!headerToMoc.empty()) { + // This is for KDE4 compatibility: + fileToMoc = headerToMoc; + if (!requiresMoc && basename == scannedFileBasename) { + std::ostringstream err; + err << "AutoMoc: Warning: " << absFilename << "\n" + << "The file includes the moc file \"" << currentMoc + << "\", but does not contain a " << macroName + << " macro. Running moc on " + << "\"" << headerToMoc << "\" ! Include \"moc_" << basename + << ".cpp\" for a compatibility with " + "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; + this->LogWarning(err.str()); + } else { + std::ostringstream err; + err << "AutoMoc: Warning: " << absFilename << "\n" + << "The file includes the moc file \"" << currentMoc + << "\" instead of \"moc_" << basename + << ".cpp\". Running moc on " + << "\"" << headerToMoc << "\" ! Include \"moc_" << basename + << ".cpp\" for compatibility with " + "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; + this->LogWarning(err.str()); + } } else { std::ostringstream err; - err << "AUTOGEN: warning: " << absFilename - << ": The file " - "includes the moc file \"" - << currentMoc << "\" instead of \"moc_" << basename - << ".cpp\". " - "Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename - << ".cpp\" for compatibility with " - "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n" - << std::endl; - this->LogWarning(err.str()); + err << "AutoMoc: Error: " << absFilename << "\n" + << "The file includes the moc file \"" << currentMoc + << "\", which seems to be the moc file from a different " + "source file. CMake also could not find a matching " + "header.\n"; + this->LogError(err.str()); + return false; } } else { + // Include self + fileToMoc = absFilename; + ownDotMocIncluded = true; + } + } else { + // Mode: Strict + if (basename == scannedFileBasename) { + // Include self + fileToMoc = absFilename; + ownDotMocIncluded = true; + } else { + // Don't allow FOO.moc include other than self in strict mode std::ostringstream err; - err << "AUTOGEN: error: " << absFilename - << ": The file " - "includes the moc file \"" - << currentMoc + err << "AutoMoc: Error: " << absFilename << "\n" + << "The file includes the moc file \"" << currentMoc << "\", which seems to be the moc file from a different " - "source file. CMake also could not find a matching " - "header.\n" - << std::endl; + "source file. This is not supported. Include \"" + << scannedFileBasename + << ".moc\" to run moc on this source file.\n"; this->LogError(err.str()); return false; } - } else { - dotMocIncluded = true; - ownDotMocFile = currentMoc; } - includedMocs[fileToMoc] = currentMoc; + if (!fileToMoc.empty()) { + includedMocs[fileToMoc] = currentMoc; + } } - matchOffset += mocIncludeRegExp.end(); - } while (mocIncludeRegExp.find(contentsString.c_str() + matchOffset)); + // Forward content pointer + contentChars += this->RegExpMocInclude.end(); + } } // In this case, check whether the scanned file itself contains a Q_OBJECT. // If this is the case, the moc_foo.cpp should probably be generated from // foo.cpp instead of foo.h, because otherwise it won't build. // But warn, since this is not how it is supposed to be used. - if (!dotMocIncluded && requiresMoc) { - if (mocUnderscoreIncluded) { - // this is for KDE4 compatibility: + if (requiresMoc && !ownDotMocIncluded) { + if (relaxed && ownMocUnderscoreIncluded) { + // This is for KDE4 compatibility: std::ostringstream err; - err << "AUTOGEN: warning: " << absFilename << ": The file " - << "contains a " << macroName << " macro, but does not " - "include " - << "\"" << scannedFileBasename << ".moc\", but instead " - "includes " + err << "AutoMoc: Warning: " << absFilename << "\n" + << "The file contains a " << macroName + << " macro, but does not include " + << "\"" << scannedFileBasename << ".moc\", but instead includes " << "\"" << ownMocUnderscoreFile << "\". Running moc on " << "\"" << absFilename << "\" ! Better include \"" << scannedFileBasename << ".moc\" for compatibility with " - "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n" - << std::endl; + "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); + // Use scanned source file instead of scanned header file as moc source includedMocs[absFilename] = ownMocUnderscoreFile; includedMocs.erase(ownMocHeaderFile); } else { - // otherwise always error out since it will not compile: + // Otherwise always error out since it will not compile: std::ostringstream err; - err << "AUTOGEN: error: " << absFilename << ": The file " - << "contains a " << macroName << " macro, but does not " - "include " - << "\"" << scannedFileBasename << ".moc\" !\n" - << std::endl; + err << "AutoMoc: Error: " << absFilename << "\n" + << "The file contains a " << macroName + << " macro, but does not include " + << "\"" << scannedFileBasename << ".moc\" !\n"; this->LogError(err.str()); return false; } @@ -781,244 +980,101 @@ bool cmQtAutoGenerators::ParseCppFile( return true; } -/** - * @return True on success - */ -bool cmQtAutoGenerators::StrictParseCppFile( +void cmQtAutoGenerators::SearchHeadersForSourceFile( const std::string& absFilename, const std::vector<std::string>& headerExtensions, - std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::vector<std::string> >& includedUis) -{ - cmsys::RegularExpression mocIncludeRegExp( - "[\n][ \t]*#[ \t]*include[ \t]+" - "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]"); - - const std::string contentsString = ReadAll(absFilename); - if (contentsString.empty()) { - std::ostringstream err; - err << "AUTOGEN: warning: " << absFilename << ": file is empty\n" - << std::endl; - this->LogWarning(err.str()); - return true; - } - this->ParseForUic(absFilename, contentsString, includedUis); - if (this->MocExecutable.empty()) { - return true; - } - - const std::string absPath = cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)) + - '/'; - const std::string scannedFileBasename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); - - bool dotMocIncluded = false; - - std::string::size_type matchOffset = 0; - // first a simple string check for "moc" is *much* faster than the regexp, - // and if the string search already fails, we don't have to try the - // expensive regexp - if ((strstr(contentsString.c_str(), "moc") != CM_NULLPTR) && - (mocIncludeRegExp.find(contentsString))) { - // for every moc include in the file - do { - const std::string currentMoc = mocIncludeRegExp.match(1); - - std::string basename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc); - const bool mocUnderscoreStyle = cmHasLiteralPrefix(basename, "moc_"); - - // If the moc include is of the moc_foo.cpp style we expect - // the Q_OBJECT class declaration in a header file. - // If the moc include is of the foo.moc style we need to look for - // a Q_OBJECT macro in the current source file, if it contains the - // macro we generate the moc file from the source file. - if (mocUnderscoreStyle) { - // basename should be the part of the moc filename used for - // finding the correct header, so we need to remove the moc_ part - basename = basename.substr(4); - std::string mocSubDir = extractSubDir(absPath, currentMoc); - std::string headerToMoc = - findMatchingHeader(absPath, mocSubDir, basename, headerExtensions); - - if (!headerToMoc.empty()) { - includedMocs[headerToMoc] = currentMoc; - } else { - std::ostringstream err; - err << "AUTOGEN: error: " << absFilename << " The file " - << "includes the moc file \"" << currentMoc << "\", " - << "but could not find header \"" << basename << '{' - << this->JoinExts(headerExtensions) << "}\" "; - if (mocSubDir.empty()) { - err << "in " << absPath << "\n" << std::endl; - } else { - err << "neither in " << absPath << " nor in " << mocSubDir << "\n" - << std::endl; - } - this->LogError(err.str()); - return false; - } - } else { - if (basename != scannedFileBasename) { - std::ostringstream err; - err << "AUTOGEN: error: " << absFilename - << ": The file " - "includes the moc file \"" - << currentMoc - << "\", which seems to be the moc file from a different " - "source file. This is not supported. " - "Include \"" - << scannedFileBasename << ".moc\" to run " - "moc on this source file.\n" - << std::endl; - this->LogError(err.str()); - return false; - } - dotMocIncluded = true; - includedMocs[absFilename] = currentMoc; - } - matchOffset += mocIncludeRegExp.end(); - } while (mocIncludeRegExp.find(contentsString.c_str() + matchOffset)); - } - - // In this case, check whether the scanned file itself contains a Q_OBJECT. - // If this is the case, the moc_foo.cpp should probably be generated from - // foo.cpp instead of foo.h, because otherwise it won't build. - // But warn, since this is not how it is supposed to be used. - std::string macroName; - if (!dotMocIncluded && requiresMocing(contentsString, macroName)) { - // otherwise always error out since it will not compile: - std::ostringstream err; - err << "AUTOGEN: error: " << absFilename << ": The file " - << "contains a " << macroName << " macro, but does not include " - << "\"" << scannedFileBasename << ".moc\" !\n" - << std::endl; - this->LogError(err.str()); - return false; - } - - return true; -} - -void cmQtAutoGenerators::ParseForUic( - const std::string& absFilename, - std::map<std::string, std::vector<std::string> >& includedUis) -{ - if (this->UicExecutable.empty()) { - return; - } - const std::string contentsString = ReadAll(absFilename); - if (contentsString.empty()) { - std::ostringstream err; - err << "AUTOGEN: warning: " << absFilename << ": file is empty\n" - << std::endl; - this->LogWarning(err.str()); - return; - } - this->ParseForUic(absFilename, contentsString, includedUis); -} - -void cmQtAutoGenerators::ParseForUic( - const std::string& absFilename, const std::string& contentsString, - std::map<std::string, std::vector<std::string> >& includedUis) -{ - if (this->UicExecutable.empty()) { - return; - } - cmsys::RegularExpression uiIncludeRegExp( - "[\n][ \t]*#[ \t]*include[ \t]+" - "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); - - std::string::size_type matchOffset = 0; - - const std::string realName = cmsys::SystemTools::GetRealPath(absFilename); - - matchOffset = 0; - if ((strstr(contentsString.c_str(), "ui_") != CM_NULLPTR) && - (uiIncludeRegExp.find(contentsString))) { - do { - const std::string currentUi = uiIncludeRegExp.match(1); - - std::string basename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(currentUi); - - // basename should be the part of the ui filename used for - // finding the correct header, so we need to remove the ui_ part - basename = basename.substr(3); - - includedUis[realName].push_back(basename); - - matchOffset += uiIncludeRegExp.end(); - } while (uiIncludeRegExp.find(contentsString.c_str() + matchOffset)); - } -} - -void cmQtAutoGenerators::SearchHeadersForCppFile( - const std::string& absFilename, - const std::vector<std::string>& headerExtensions, - std::set<std::string>& absHeaders) + std::set<std::string>& absHeadersMoc, std::set<std::string>& absHeadersUic) { // search for header files and private header files we may need to moc: - const std::string basename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); - const std::string absPath = cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)) + - '/'; + std::string basepath = cmsys::SystemTools::GetFilenamePath( + cmsys::SystemTools::GetRealPath(absFilename)); + basepath += '/'; + basepath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); + // Search for regular header for (std::vector<std::string>::const_iterator ext = headerExtensions.begin(); ext != headerExtensions.end(); ++ext) { - const std::string headerName = absPath + basename + "." + (*ext); + const std::string headerName = basepath + "." + (*ext); if (cmsys::SystemTools::FileExists(headerName.c_str())) { - absHeaders.insert(headerName); + // Moc headers + if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(headerName)) { + absHeadersMoc.insert(headerName); + } + // Uic headers + if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(headerName)) { + absHeadersUic.insert(headerName); + } break; } } + // Search for private header for (std::vector<std::string>::const_iterator ext = headerExtensions.begin(); ext != headerExtensions.end(); ++ext) { - const std::string privateHeaderName = absPath + basename + "_p." + (*ext); - if (cmsys::SystemTools::FileExists(privateHeaderName.c_str())) { - absHeaders.insert(privateHeaderName); + const std::string headerName = basepath + "_p." + (*ext); + if (cmsys::SystemTools::FileExists(headerName.c_str())) { + // Moc headers + if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(headerName)) { + absHeadersMoc.insert(headerName); + } + // Uic headers + if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(headerName)) { + absHeadersUic.insert(headerName); + } break; } } } void cmQtAutoGenerators::ParseHeaders( - const std::set<std::string>& absHeaders, + const std::set<std::string>& absHeadersMoc, + const std::set<std::string>& absHeadersUic, const std::map<std::string, std::string>& includedMocs, std::map<std::string, std::string>& notIncludedMocs, std::map<std::string, std::vector<std::string> >& includedUis) { - for (std::set<std::string>::const_iterator hIt = absHeaders.begin(); - hIt != absHeaders.end(); ++hIt) { + // Merged header files list to read files only once + std::set<std::string> headerFiles; + headerFiles.insert(absHeadersMoc.begin(), absHeadersMoc.end()); + headerFiles.insert(absHeadersUic.begin(), absHeadersUic.end()); + + for (std::set<std::string>::const_iterator hIt = headerFiles.begin(); + hIt != headerFiles.end(); ++hIt) { const std::string& headerName = *hIt; const std::string contents = ReadAll(headerName); - if (!this->MocExecutable.empty() && - includedMocs.find(headerName) == includedMocs.end()) { + // Parse header content for MOC + if ((absHeadersMoc.find(headerName) != absHeadersMoc.end()) && + (includedMocs.find(headerName) == includedMocs.end())) { + // Process if (this->Verbose) { std::ostringstream err; - err << "AUTOGEN: Checking " << headerName << std::endl; + err << "AutoMoc: Checking " << headerName << "\n"; this->LogInfo(err.str()); } - std::string macroName; - if (requiresMocing(contents, macroName)) { + if (this->MocRequired(contents, macroName)) { notIncludedMocs[headerName] = fpathCheckSum.getPart(headerName) + "/moc_" + cmsys::SystemTools::GetFilenameWithoutLastExtension(headerName) + ".cpp"; } } - this->ParseForUic(headerName, contents, includedUis); + + // Parse header content for UIC + if (absHeadersUic.find(headerName) != absHeadersUic.end()) { + this->ParseContentForUic(headerName, contents, includedUis); + } } } -bool cmQtAutoGenerators::GenerateMocFiles( +bool cmQtAutoGenerators::MocGenerateAll( const std::map<std::string, std::string>& includedMocs, const std::map<std::string, std::string>& notIncludedMocs) { + if (this->MocExecutable.empty()) { + return true; + } + // look for name collisions { std::multimap<std::string, std::string> collisions; @@ -1027,7 +1083,7 @@ bool cmQtAutoGenerators::GenerateMocFiles( mergedMocs.insert(notIncludedMocs.begin(), notIncludedMocs.end()); if (this->NameCollisionTest(mergedMocs, collisions)) { std::ostringstream err; - err << "AUTOGEN: error: " + err << "AutoMoc: Error: " "The same moc file will be generated " "from different sources." << std::endl @@ -1045,7 +1101,7 @@ bool cmQtAutoGenerators::GenerateMocFiles( for (std::map<std::string, std::string>::const_iterator it = includedMocs.begin(); it != includedMocs.end(); ++it) { - if (!this->GenerateMoc(it->first, it->second, subDirPrefix)) { + if (!this->MocGenerateFile(it->first, it->second, subDirPrefix)) { if (this->RunMocFailed) { return false; } @@ -1060,7 +1116,7 @@ bool cmQtAutoGenerators::GenerateMocFiles( for (std::map<std::string, std::string>::const_iterator it = notIncludedMocs.begin(); it != notIncludedMocs.end(); ++it) { - if (this->GenerateMoc(it->first, it->second, subDirPrefix)) { + if (this->MocGenerateFile(it->first, it->second, subDirPrefix)) { automocCppChanged = true; } else { if (this->RunMocFailed) { @@ -1098,7 +1154,7 @@ bool cmQtAutoGenerators::GenerateMocFiles( // nothing changed: don't touch the moc_compilation.cpp file if (this->Verbose) { std::ostringstream err; - err << "AUTOGEN: " << this->OutMocCppFilenameRel << " still up to date" + err << "AutoMoc: " << this->OutMocCppFilenameRel << " still up to date" << std::endl; this->LogInfo(err.str()); } @@ -1113,14 +1169,14 @@ bool cmQtAutoGenerators::GenerateMocFiles( this->LogBold(msg); } // Make sure the parent directory exists - bool success = this->makeParentDirectory(this->OutMocCppFilenameAbs); + bool success = this->MakeParentDirectory(this->OutMocCppFilenameAbs); if (success) { cmsys::ofstream outfile; outfile.open(this->OutMocCppFilenameAbs.c_str(), std::ios::trunc); if (!outfile) { success = false; std::ostringstream err; - err << "AUTOGEN: error opening " << this->OutMocCppFilenameAbs << "\n"; + err << "AutoMoc: error opening " << this->OutMocCppFilenameAbs << "\n"; this->LogError(err.str()); } else { outfile << automocSource; @@ -1128,7 +1184,7 @@ bool cmQtAutoGenerators::GenerateMocFiles( if (!outfile.good()) { success = false; std::ostringstream err; - err << "AUTOGEN: error writing " << this->OutMocCppFilenameAbs << "\n"; + err << "AutoMoc: error writing " << this->OutMocCppFilenameAbs << "\n"; this->LogError(err.str()); } } @@ -1139,22 +1195,25 @@ bool cmQtAutoGenerators::GenerateMocFiles( /** * @return True if a moc file was created. False may indicate an error. */ -bool cmQtAutoGenerators::GenerateMoc(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix) +bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, + const std::string& mocFileName, + const std::string& subDirPrefix) { const std::string mocFileRel = this->AutogenBuildSubDir + subDirPrefix + mocFileName; const std::string mocFileAbs = this->CurrentBinaryDir + mocFileRel; - int sourceNewerThanMoc = 0; - bool success = cmsys::SystemTools::FileTimeCompare(sourceFile, mocFileAbs, - &sourceNewerThanMoc); - if (this->GenerateAll || !success || sourceNewerThanMoc >= 0) { + + bool generateMoc = this->GenerateMocAll; + // Test if the source file is newer that the build file + if (!generateMoc) { + generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile); + } + if (generateMoc) { // Log this->LogBold("Generating MOC source " + mocFileRel); // Make sure the parent directory exists - if (!this->makeParentDirectory(mocFileAbs)) { + if (!this->MakeParentDirectory(mocFileAbs)) { this->RunMocFailed = true; return false; } @@ -1185,7 +1244,7 @@ bool cmQtAutoGenerators::GenerateMoc(const std::string& sourceFile, if (!result || retVal) { { std::ostringstream err; - err << "AUTOGEN: error: moc process for " << mocFileRel << " failed:\n" + err << "AutoMoc: Error: moc process for " << mocFileRel << " failed:\n" << output << std::endl; this->LogError(err.str()); } @@ -1198,9 +1257,13 @@ bool cmQtAutoGenerators::GenerateMoc(const std::string& sourceFile, return false; } -bool cmQtAutoGenerators::GenerateUiFiles( +bool cmQtAutoGenerators::UicGenerateAll( const std::map<std::string, std::vector<std::string> >& includedUis) { + if (this->UicExecutable.empty()) { + return true; + } + // single map with input / output names std::map<std::string, std::map<std::string, std::string> > uiGenMap; std::map<std::string, std::string> testMap; @@ -1228,7 +1291,7 @@ bool cmQtAutoGenerators::GenerateUiFiles( std::multimap<std::string, std::string> collisions; if (this->NameCollisionTest(testMap, collisions)) { std::ostringstream err; - err << "AUTOGEN: error: The same ui_NAME.h file will be generated " + err << "AutoUic: Error: The same ui_NAME.h file will be generated " "from different sources." << std::endl << "To avoid this error rename the source files." << std::endl; @@ -1246,7 +1309,7 @@ bool cmQtAutoGenerators::GenerateUiFiles( for (std::map<std::string, std::string>::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit) { - if (!this->GenerateUi(it->first, sit->first, sit->second)) { + if (!this->UicGenerateFile(it->first, sit->first, sit->second)) { if (this->RunUicFailed) { return false; } @@ -1260,23 +1323,25 @@ bool cmQtAutoGenerators::GenerateUiFiles( /** * @return True if a uic file was created. False may indicate an error. */ -bool cmQtAutoGenerators::GenerateUi(const std::string& realName, - const std::string& uiInputFile, - const std::string& uiOutputFile) +bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, + const std::string& uiInputFile, + const std::string& uiOutputFile) { const std::string uicFileRel = this->AutogenBuildSubDir + "include/" + uiOutputFile; const std::string uicFileAbs = this->CurrentBinaryDir + uicFileRel; - int sourceNewerThanUi = 0; - bool success = cmsys::SystemTools::FileTimeCompare(uiInputFile, uicFileAbs, - &sourceNewerThanUi); - if (this->GenerateAll || !success || sourceNewerThanUi >= 0) { + bool generateUic = this->GenerateUicAll; + // Test if the source file is newer that the build file + if (!generateUic) { + generateUic = FileAbsentOrOlder(uicFileAbs, uiInputFile); + } + if (generateUic) { // Log this->LogBold("Generating UIC header " + uicFileRel); // Make sure the parent directory exists - if (!this->makeParentDirectory(uicFileAbs)) { + if (!this->MakeParentDirectory(uicFileAbs)) { this->RunUicFailed = true; return false; } @@ -1290,8 +1355,7 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& realName, if (optionIt != this->UicOptions.end()) { std::vector<std::string> fileOpts; cmSystemTools::ExpandListArgument(optionIt->second, fileOpts); - cmQtAutoGenerators::MergeUicOptions(opts, fileOpts, - this->QtMajorVersion == "5"); + UicMergeOptions(opts, fileOpts, this->QtMajorVersion == "5"); } command.insert(command.end(), opts.begin(), opts.end()); @@ -1309,7 +1373,7 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& realName, if (!result || retVal) { { std::ostringstream err; - err << "AUTOUIC: error: uic process for " << uicFileRel + err << "AutoUic: Error: uic process for " << uicFileRel << " needed by\n \"" << realName << "\"\nfailed:\n" << output << std::endl; this->LogError(err.str()); @@ -1323,24 +1387,12 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& realName, return false; } -bool cmQtAutoGenerators::InputFilesNewerThanQrc(const std::string& qrcFile, - const std::string& rccOutput) +bool cmQtAutoGenerators::QrcGenerateAll() { - std::vector<std::string> const& files = this->RccInputs[qrcFile]; - for (std::vector<std::string>::const_iterator it = files.begin(); - it != files.end(); ++it) { - int inputNewerThanQrc = 0; - bool success = - cmsys::SystemTools::FileTimeCompare(*it, rccOutput, &inputNewerThanQrc); - if (!success || inputNewerThanQrc >= 0) { - return true; - } + if (this->RccExecutable.empty()) { + return true; } - return false; -} -bool cmQtAutoGenerators::GenerateQrcFiles() -{ // generate single map with input / output names std::map<std::string, std::string> qrcGenMap; for (std::vector<std::string>::const_iterator si = this->RccSources.begin(); @@ -1358,7 +1410,7 @@ bool cmQtAutoGenerators::GenerateQrcFiles() std::multimap<std::string, std::string> collisions; if (this->NameCollisionTest(qrcGenMap, collisions)) { std::ostringstream err; - err << "AUTOGEN: error: The same qrc_NAME.cpp file" + err << "AutoRcc: Error: The same qrc_NAME.cpp file" " will be generated from different sources." << std::endl << "To avoid this error rename the source .qrc files." << std::endl; @@ -1372,7 +1424,7 @@ bool cmQtAutoGenerators::GenerateQrcFiles() qrcGenMap.begin(); si != qrcGenMap.end(); ++si) { bool unique = FileNameIsUnique(si->first, qrcGenMap); - if (!this->GenerateQrc(si->first, si->second, unique)) { + if (!this->QrcGenerateFile(si->first, si->second, unique)) { if (this->RunRccFailed) { return false; } @@ -1384,9 +1436,9 @@ bool cmQtAutoGenerators::GenerateQrcFiles() /** * @return True if a rcc file was created. False may indicate an error. */ -bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile, - const std::string& qrcOutputFile, - bool unique_n) +bool cmQtAutoGenerators::QrcGenerateFile(const std::string& qrcInputFile, + const std::string& qrcOutputFile, + bool unique_n) { std::string symbolName = cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile); @@ -1400,14 +1452,23 @@ bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile, const std::string qrcBuildFile = this->CurrentBinaryDir + qrcOutputFile; - int sourceNewerThanQrc = 0; - bool generateQrc = !cmsys::SystemTools::FileTimeCompare( - qrcInputFile, qrcBuildFile, &sourceNewerThanQrc); - generateQrc = generateQrc || (sourceNewerThanQrc >= 0); - generateQrc = - generateQrc || this->InputFilesNewerThanQrc(qrcInputFile, qrcBuildFile); - - if (this->GenerateAll || generateQrc) { + bool generateQrc = this->GenerateRccAll; + // Test if the resources list file is newer than build file + if (!generateQrc) { + generateQrc = FileAbsentOrOlder(qrcBuildFile, qrcInputFile); + } + // Test if any resource file is newer than the build file + if (!generateQrc) { + const std::vector<std::string>& files = this->RccInputs[qrcInputFile]; + for (std::vector<std::string>::const_iterator it = files.begin(); + it != files.end(); ++it) { + if (FileAbsentOrOlder(qrcBuildFile, *it)) { + generateQrc = true; + break; + } + } + } + if (generateQrc) { { std::string msg = "Generating RCC source "; msg += qrcOutputFile; @@ -1415,7 +1476,7 @@ bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile, } // Make sure the parent directory exists - if (!this->makeParentDirectory(qrcOutputFile)) { + if (!this->MakeParentDirectory(qrcOutputFile)) { this->RunRccFailed = true; return false; } @@ -1445,7 +1506,7 @@ bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile, if (!result || retVal) { { std::ostringstream err; - err << "AUTORCC: error: rcc process for " << qrcOutputFile + err << "AutoRcc: Error: rcc process for " << qrcOutputFile << " failed:\n" << output << std::endl; this->LogError(err.str()); @@ -1459,36 +1520,6 @@ bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile, return false; } -/** - * @brief Collects name collisions as output/input pairs - * @return True if there were collisions - */ -bool cmQtAutoGenerators::NameCollisionTest( - const std::map<std::string, std::string>& genFiles, - std::multimap<std::string, std::string>& collisions) -{ - typedef std::map<std::string, std::string>::const_iterator Iter; - typedef std::map<std::string, std::string>::value_type VType; - for (Iter ait = genFiles.begin(); ait != genFiles.end(); ++ait) { - bool first_match(true); - for (Iter bit = (++Iter(ait)); bit != genFiles.end(); ++bit) { - if (ait->second == bit->second) { - if (first_match) { - if (collisions.find(ait->second) != collisions.end()) { - // We already know of this collision from before - break; - } - collisions.insert(VType(ait->second, ait->first)); - first_match = false; - } - collisions.insert(VType(bit->second, bit->first)); - } - } - } - - return !collisions.empty(); -} - void cmQtAutoGenerators::LogErrorNameCollision( const std::string& message, const std::multimap<std::string, std::string>& collisions) @@ -1548,10 +1579,40 @@ void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command) } /** + * @brief Collects name collisions as output/input pairs + * @return True if there were collisions + */ +bool cmQtAutoGenerators::NameCollisionTest( + const std::map<std::string, std::string>& genFiles, + std::multimap<std::string, std::string>& collisions) +{ + typedef std::map<std::string, std::string>::const_iterator Iter; + typedef std::map<std::string, std::string>::value_type VType; + for (Iter ait = genFiles.begin(); ait != genFiles.end(); ++ait) { + bool first_match(true); + for (Iter bit = (++Iter(ait)); bit != genFiles.end(); ++bit) { + if (ait->second == bit->second) { + if (first_match) { + if (collisions.find(ait->second) != collisions.end()) { + // We already know of this collision from before + break; + } + collisions.insert(VType(ait->second, ait->first)); + first_match = false; + } + collisions.insert(VType(bit->second, bit->first)); + } + } + } + + return !collisions.empty(); +} + +/** * @brief Generates the parent directory of the given file on demand * @return True on success */ -bool cmQtAutoGenerators::makeParentDirectory(const std::string& filename) +bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) { bool success = true; const std::string dirName = cmSystemTools::GetFilenamePath(filename); @@ -1559,28 +1620,9 @@ bool cmQtAutoGenerators::makeParentDirectory(const std::string& filename) success = cmsys::SystemTools::MakeDirectory(dirName); if (!success) { std::ostringstream err; - err << "AUTOGEN: Directory creation failed: " << dirName << std::endl; + err << "AutoGen: Directory creation failed: " << dirName << std::endl; this->LogError(err.str()); } } return success; } - -std::string cmQtAutoGenerators::JoinExts(const std::vector<std::string>& lst) -{ - if (lst.empty()) { - return ""; - } - - std::string result; - std::string separator = ","; - for (std::vector<std::string>::const_iterator it = lst.begin(); - it != lst.end(); ++it) { - if (it != lst.begin()) { - result += separator; - } - result += '.' + (*it); - } - result.erase(result.end() - 1); - return result; -} diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index c241579..7891eb9 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -5,6 +5,7 @@ #include <cmConfigure.h> // IWYU pragma: keep #include <cmFilePathChecksum.h> +#include <cmsys/RegularExpression.hxx> #include <list> #include <map> @@ -21,67 +22,78 @@ public: bool Run(const std::string& targetDirectory, const std::string& config); private: + // - Configuration bool ReadAutogenInfoFile(cmMakefile* makefile, const std::string& targetDirectory, const std::string& config); - void ReadOldMocDefinitionsFile(cmMakefile* makefile, - const std::string& targetDirectory); - bool WriteOldMocDefinitionsFile(const std::string& targetDirectory); - std::string MakeCompileSettingsString(cmMakefile* makefile); + std::string MocSettingsStringCompose(); + std::string UicSettingsStringCompose(); + std::string RccSettingsStringCompose(); + void OldSettingsReadFile(cmMakefile* makefile, + const std::string& targetDirectory); + bool OldSettingsWriteFile(const std::string& targetDirectory); + // - Init and run + void Init(); bool RunAutogen(cmMakefile* makefile); - bool GenerateMocFiles( - const std::map<std::string, std::string>& includedMocs, - const std::map<std::string, std::string>& notIncludedMocs); - bool GenerateMoc(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix); + // - Content analysis + bool MocRequired(const std::string& text, std::string& macroName); + bool MocSkipTest(const std::string& absFilename); + bool UicSkipTest(const std::string& absFilename); - bool GenerateUiFiles( - const std::map<std::string, std::vector<std::string> >& includedUis); - bool GenerateUi(const std::string& realName, const std::string& uiInputFile, - const std::string& uiOutputFile); - - bool GenerateQrcFiles(); - bool GenerateQrc(const std::string& qrcInputFile, - const std::string& qrcOutputFile, bool unique_n); - - bool ParseCppFile( + bool ParseSourceFile( const std::string& absFilename, const std::vector<std::string>& headerExtensions, std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::vector<std::string> >& includedUis); - bool StrictParseCppFile( - const std::string& absFilename, - const std::vector<std::string>& headerExtensions, - std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::vector<std::string> >& includedUis); - void SearchHeadersForCppFile( + std::map<std::string, std::vector<std::string> >& includedUis, + bool relaxed); + + void SearchHeadersForSourceFile( const std::string& absFilename, const std::vector<std::string>& headerExtensions, - std::set<std::string>& absHeaders); + std::set<std::string>& absHeadersMoc, + std::set<std::string>& absHeadersUic); void ParseHeaders( - const std::set<std::string>& absHeaders, + const std::set<std::string>& absHeadersMoc, + const std::set<std::string>& absHeadersUic, const std::map<std::string, std::string>& includedMocs, std::map<std::string, std::string>& notIncludedMocs, std::map<std::string, std::vector<std::string> >& includedUis); - void ParseForUic( + void ParseContentForUic( const std::string& fileName, const std::string& contentsString, std::map<std::string, std::vector<std::string> >& includedUis); - void ParseForUic( - const std::string& fileName, - std::map<std::string, std::vector<std::string> >& includedUis); + bool ParseContentForMoc(const std::string& absFilename, + const std::string& contentsString, + const std::vector<std::string>& headerExtensions, + std::map<std::string, std::string>& includedMocs, + bool relaxed); - void Init(); + // - Moc file generation + bool MocGenerateAll( + const std::map<std::string, std::string>& includedMocs, + const std::map<std::string, std::string>& notIncludedMocs); + bool MocGenerateFile(const std::string& sourceFile, + const std::string& mocFileName, + const std::string& subDirPrefix); - bool NameCollisionTest(const std::map<std::string, std::string>& genFiles, - std::multimap<std::string, std::string>& collisions); + // - Uic file generation + bool UicGenerateAll( + const std::map<std::string, std::vector<std::string> >& includedUis); + bool UicGenerateFile(const std::string& realName, + const std::string& uiInputFile, + const std::string& uiOutputFile); + + // - Qrc file generation + bool QrcGenerateAll(); + bool QrcGenerateFile(const std::string& qrcInputFile, + const std::string& qrcOutputFile, bool unique_n); + // - Logging void LogErrorNameCollision( const std::string& message, const std::multimap<std::string, std::string>& collisions); @@ -91,16 +103,10 @@ private: void LogError(const std::string& message); void LogCommand(const std::vector<std::string>& command); - bool makeParentDirectory(const std::string& filename); - - std::string JoinExts(const std::vector<std::string>& lst); - - static void MergeUicOptions(std::vector<std::string>& opts, - const std::vector<std::string>& fileOpts, - bool isQt5); - - bool InputFilesNewerThanQrc(const std::string& qrcFile, - const std::string& rccOutput); + // - Utility + bool NameCollisionTest(const std::map<std::string, std::string>& genFiles, + std::multimap<std::string, std::string>& collisions); + bool MakeParentDirectory(const std::string& filename); // - Target names std::string OriginTargetName; @@ -117,10 +123,10 @@ private: std::string UicExecutable; std::string RccExecutable; // - File lists - std::string Sources; - std::string Headers; + std::vector<std::string> Sources; + std::vector<std::string> Headers; // - Moc - std::string SkipMoc; + std::vector<std::string> SkipMoc; std::string MocCompileDefinitionsStr; std::string MocIncludesStr; std::string MocOptionsStr; @@ -129,19 +135,23 @@ private: std::list<std::string> MocIncludes; std::list<std::string> MocDefinitions; std::vector<std::string> MocOptions; + std::string MocSettingsString; // - Uic - std::string SkipUic; + std::vector<std::string> SkipUic; std::vector<std::string> UicTargetOptions; std::map<std::string, std::string> UicOptions; + std::string UicSettingsString; // - Rcc std::vector<std::string> RccSources; std::map<std::string, std::string> RccOptions; std::map<std::string, std::vector<std::string> > RccInputs; - // - Settings - std::string CurrentCompileSettingsStr; - std::string OldCompileSettingsStr; + std::string RccSettingsString; // - Utility cmFilePathChecksum fpathCheckSum; + cmsys::RegularExpression RegExpQObject; + cmsys::RegularExpression RegExpQGadget; + cmsys::RegularExpression RegExpMocInclude; + cmsys::RegularExpression RegExpUicInclude; // - Flags bool IncludeProjectDirsBefore; bool Verbose; @@ -149,7 +159,9 @@ private: bool RunMocFailed; bool RunUicFailed; bool RunRccFailed; - bool GenerateAll; + bool GenerateMocAll; + bool GenerateUicAll; + bool GenerateRccAll; bool MocRelaxedMode; }; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index a86236c..334a05a 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -731,12 +731,16 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, Json::Value result = Json::objectValue; result[kNAME_KEY] = target->GetName(); - result[kTYPE_KEY] = typeName; - result[kFULL_NAME_KEY] = target->GetFullName(config); result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory(); result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory(); + if (type == cmStateEnums::INTERFACE_LIBRARY) { + return result; + } + + result[kFULL_NAME_KEY] = target->GetFullName(config); + if (target->HaveWellDefinedOutputFiles()) { Json::Value artifacts = Json::arrayValue; artifacts.append(target->GetFullPath(config, false)); diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index 3f20d4e..5555199 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -8,6 +8,99 @@ #include "cmSourceGroup.h" #include "cmSystemTools.h" +namespace { +const size_t RootIndex = 1; +const size_t FilesWithoutPrefixKeywordIndex = 2; +const size_t FilesWithPrefixKeywordIndex = 4; +const size_t PrefixKeywordIdex = 2; + +std::vector<std::string> tokenizePath(const std::string& path) +{ + return cmSystemTools::tokenize(path, "\\/"); +} + +std::string getFullFilePath(const std::string& currentPath, + const std::string& path) +{ + std::string fullPath = path; + + if (!cmSystemTools::FileIsFullPath(path.c_str())) { + fullPath = currentPath; + fullPath += "/"; + fullPath += path; + } + + return cmSystemTools::CollapseFullPath(fullPath); +} + +std::set<std::string> getSourceGroupFilesPaths( + const std::string& currentPath, const std::string& root, + const std::vector<std::string>& files) +{ + std::set<std::string> ret; + const std::string::size_type rootLength = root.length(); + + for (size_t i = 0; i < files.size(); ++i) { + const std::string fullPath = getFullFilePath(currentPath, files[i]); + + ret.insert(fullPath.substr(rootLength + 1)); // +1 to also omnit last '/' + } + + return ret; +} + +cmSourceGroup* addSourceGroup(const std::vector<std::string>& tokenizedPath, + cmMakefile& makefile) +{ + cmSourceGroup* sg; + + sg = makefile.GetSourceGroup(tokenizedPath); + if (!sg) { + makefile.AddSourceGroup(tokenizedPath); + sg = makefile.GetSourceGroup(tokenizedPath); + if (!sg) { + return CM_NULLPTR; + } + } + + return sg; +} + +bool addFilesToItsSourceGroups(const std::set<std::string>& sgFilesPaths, + const std::string& prefix, cmMakefile& makefile, + std::string& errorMsg) +{ + cmSourceGroup* sg; + + for (std::set<std::string>::const_iterator it = sgFilesPaths.begin(); + it != sgFilesPaths.end(); ++it) { + + std::vector<std::string> tokenizedPath; + if (!prefix.empty()) { + tokenizedPath = tokenizePath(prefix + '/' + *it); + } else { + tokenizedPath = tokenizePath(*it); + } + + if (tokenizedPath.size() > 1) { + tokenizedPath.pop_back(); + + sg = addSourceGroup(tokenizedPath, makefile); + + if (!sg) { + errorMsg = "Could not create source group for file: " + *it; + return false; + } + const std::string fullPath = + getFullFilePath(makefile.GetCurrentSourceDirectory(), *it); + sg->AddGroupFile(fullPath); + } + } + + return true; +} +} + class cmExecutionStatus; // cmSourceGroupCommand @@ -19,6 +112,17 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args, return false; } + if (args[0] == "TREE") { + std::string error; + + if (!processTree(args, error)) { + this->SetError(error); + return false; + } + + return true; + } + std::string delimiter = "\\"; if (this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER")) { delimiter = this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER"); @@ -82,3 +186,64 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args, return true; } + +bool cmSourceGroupCommand::checkTreeArgumentsPreconditions( + const std::vector<std::string>& args, std::string& errorMsg) const +{ + if (args.size() == 1) { + errorMsg = "TREE argument given without a root."; + return false; + } + + if (args.size() < 3) { + errorMsg = "Missing FILES arguments."; + return false; + } + + if (args[FilesWithoutPrefixKeywordIndex] != "FILES" && + args[PrefixKeywordIdex] != "PREFIX") { + errorMsg = "Unknown argument \"" + args[2] + + "\". Perhaps the FILES keyword is missing.\n"; + return false; + } + + if (args[PrefixKeywordIdex] == "PREFIX" && + (args.size() < 5 || args[FilesWithPrefixKeywordIndex] != "FILES")) { + errorMsg = "Missing FILES arguments."; + return false; + } + + return true; +} + +bool cmSourceGroupCommand::processTree(const std::vector<std::string>& args, + std::string& errorMsg) +{ + if (!checkTreeArgumentsPreconditions(args, errorMsg)) { + return false; + } + + const std::string root = cmSystemTools::CollapseFullPath(args[RootIndex]); + std::string prefix; + size_t filesBegin = FilesWithoutPrefixKeywordIndex + 1; + if (args[PrefixKeywordIdex] == "PREFIX") { + prefix = args[PrefixKeywordIdex + 1]; + filesBegin = FilesWithPrefixKeywordIndex + 1; + } + + const std::vector<std::string> filesVector(args.begin() + filesBegin, + args.end()); + + std::set<std::string> sourceGroupPaths = getSourceGroupFilesPaths( + this->Makefile->GetCurrentSourceDirectory(), root, filesVector); + + addFilesToItsSourceGroups(sourceGroupPaths, prefix, *(this->Makefile), + errorMsg); + + if (!errorMsg.empty()) { + this->SetError(errorMsg); + return false; + } + + return true; +} diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h index f533be1..5549096 100644 --- a/Source/cmSourceGroupCommand.h +++ b/Source/cmSourceGroupCommand.h @@ -36,6 +36,12 @@ public: * The name of the command as specified in CMakeList.txt. */ std::string GetName() const CM_OVERRIDE { return "source_group"; } + +private: + bool processTree(const std::vector<std::string>& args, + std::string& errorMsg); + bool checkTreeArgumentsPreconditions(const std::vector<std::string>& args, + std::string& errorMsg) const; }; #endif diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx new file mode 100644 index 0000000..c2ff664 --- /dev/null +++ b/Source/cmVSSetupHelper.cxx @@ -0,0 +1,366 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmVSSetupHelper.h" + +#ifndef VSSetupConstants +#define VSSetupConstants +/* clang-format off */ +const IID IID_ISetupConfiguration = { + 0x42843719, 0xDB4C, 0x46C2, + { 0x8E, 0x7C, 0x64, 0xF1, 0x81, 0x6E, 0xFD, 0x5B } +}; +const IID IID_ISetupConfiguration2 = { + 0x26AAB78C, 0x4A60, 0x49D6, + { 0xAF, 0x3B, 0x3C, 0x35, 0xBC, 0x93, 0x36, 0x5D } +}; +const IID IID_ISetupPackageReference = { + 0xda8d8a16, 0xb2b6, 0x4487, + { 0xa2, 0xf1, 0x59, 0x4c, 0xcc, 0xcd, 0x6b, 0xf5 } +}; +const IID IID_ISetupHelper = { + 0x42b21b78, 0x6192, 0x463e, + { 0x87, 0xbf, 0xd5, 0x77, 0x83, 0x8f, 0x1d, 0x5c } +}; +const IID IID_IEnumSetupInstances = { + 0x6380BCFF, 0x41D3, 0x4B2E, + { 0x8B, 0x2E, 0xBF, 0x8A, 0x68, 0x10, 0xC8, 0x48 } +}; +const IID IID_ISetupInstance2 = { + 0x89143C9A, 0x05AF, 0x49B0, + { 0xB7, 0x17, 0x72, 0xE2, 0x18, 0xA2, 0x18, 0x5C } +}; +const IID IID_ISetupInstance = { + 0xB41463C3, 0x8866, 0x43B5, + { 0xBC, 0x33, 0x2B, 0x06, 0x76, 0xF7, 0xF4, 0x2E } +}; +const CLSID CLSID_SetupConfiguration = { + 0x177F0C4A, 0x1CD3, 0x4DE7, + { 0xA3, 0x2C, 0x71, 0xDB, 0xBB, 0x9F, 0xA3, 0x6D } +}; +/* clang-format on */ +#endif + +const WCHAR* VCToolsetComponent = + L"Microsoft.VisualStudio.Component.VC.Tools.x86.x64"; +const WCHAR* Win10SDKComponent = + L"Microsoft.VisualStudio.Component.Windows10SDK"; +const WCHAR* Win81SDKComponent = + L"Microsoft.VisualStudio.Component.Windows81SDK"; +const WCHAR* ComponentType = L"Component"; + +cmVSSetupAPIHelper::cmVSSetupAPIHelper() + : setupConfig(NULL) + , setupConfig2(NULL) + , setupHelper(NULL) + , initializationFailure(false) +{ + comInitialized = CoInitializeEx(NULL, 0); + if (SUCCEEDED(comInitialized)) { + Initialize(); + } else { + initializationFailure = true; + } +} + +cmVSSetupAPIHelper::~cmVSSetupAPIHelper() +{ + setupHelper = NULL; + setupConfig2 = NULL; + setupConfig = NULL; + if (SUCCEEDED(comInitialized)) + CoUninitialize(); +} + +bool cmVSSetupAPIHelper::IsVS2017Installed() +{ + return this->EnumerateAndChooseVSInstance(); +} + +bool cmVSSetupAPIHelper::IsWin10SDKInstalled() +{ + return (this->EnumerateAndChooseVSInstance() && + chosenInstanceInfo.IsWin10SDKInstalled); +} + +bool cmVSSetupAPIHelper::IsWin81SDKInstalled() +{ + return (this->EnumerateAndChooseVSInstance() && + chosenInstanceInfo.IsWin81SDKInstalled); +} + +bool cmVSSetupAPIHelper::CheckInstalledComponent( + SmartCOMPtr<ISetupPackageReference> package, bool& bVCToolset, + bool& bWin10SDK, bool& bWin81SDK) +{ + bool ret = false; + bVCToolset = bWin10SDK = bWin81SDK = false; + SmartBSTR bstrId; + if (FAILED(package->GetId(&bstrId))) { + return ret; + } + + SmartBSTR bstrType; + if (FAILED(package->GetType(&bstrType))) { + return ret; + } + + std::wstring id = std::wstring(bstrId); + std::wstring type = std::wstring(bstrType); + if (id.compare(VCToolsetComponent) == 0 && + type.compare(ComponentType) == 0) { + bVCToolset = true; + ret = true; + } + + // Checks for any version of Win10 SDK. The version is appended at the end of + // the + // component name ex: Microsoft.VisualStudio.Component.Windows10SDK.10240 + if (id.find(Win10SDKComponent) != std::wstring::npos && + type.compare(ComponentType) == 0) { + bWin10SDK = true; + ret = true; + } + + if (id.compare(Win81SDKComponent) == 0 && type.compare(ComponentType) == 0) { + bWin81SDK = true; + ret = true; + } + + return ret; +} + +// Gather additional info such as if VCToolset, WinSDKs are installed, location +// of VS and version information. +bool cmVSSetupAPIHelper::GetVSInstanceInfo( + SmartCOMPtr<ISetupInstance2> pInstance, VSInstanceInfo& vsInstanceInfo) +{ + bool isVCToolSetInstalled = false; + if (pInstance == NULL) + return false; + + SmartBSTR bstrId; + if (SUCCEEDED(pInstance->GetInstanceId(&bstrId))) { + vsInstanceInfo.InstanceId = std::wstring(bstrId); + } else { + return false; + } + + InstanceState state; + if (FAILED(pInstance->GetState(&state))) { + return false; + } + + ULONGLONG ullVersion = 0; + SmartBSTR bstrVersion; + if (FAILED(pInstance->GetInstallationVersion(&bstrVersion))) { + return false; + } else { + vsInstanceInfo.Version = std::wstring(bstrVersion); + if (FAILED(setupHelper->ParseVersion(bstrVersion, &ullVersion))) { + vsInstanceInfo.ullVersion = 0; + } else { + vsInstanceInfo.ullVersion = ullVersion; + } + } + + // Reboot may have been required before the installation path was created. + SmartBSTR bstrInstallationPath; + if ((eLocal & state) == eLocal) { + if (FAILED(pInstance->GetInstallationPath(&bstrInstallationPath))) { + return false; + } else { + vsInstanceInfo.VSInstallLocation = std::wstring(bstrInstallationPath); + } + } + + // Reboot may have been required before the product package was registered + // (last). + if ((eRegistered & state) == eRegistered) { + SmartCOMPtr<ISetupPackageReference> product; + if (FAILED(pInstance->GetProduct(&product)) || !product) { + return false; + } + + LPSAFEARRAY lpsaPackages; + if (FAILED(pInstance->GetPackages(&lpsaPackages)) || + lpsaPackages == NULL) { + return false; + } + + int lower = lpsaPackages->rgsabound[0].lLbound; + int upper = lpsaPackages->rgsabound[0].cElements + lower; + + IUnknown** ppData = (IUnknown**)lpsaPackages->pvData; + for (int i = lower; i < upper; i++) { + SmartCOMPtr<ISetupPackageReference> package = NULL; + if (FAILED(ppData[i]->QueryInterface(IID_ISetupPackageReference, + (void**)&package)) || + package == NULL) + continue; + + bool vcToolsetInstalled = false, win10SDKInstalled = false, + win81SDkInstalled = false; + bool ret = CheckInstalledComponent(package, vcToolsetInstalled, + win10SDKInstalled, win81SDkInstalled); + if (ret) { + isVCToolSetInstalled |= vcToolsetInstalled; + vsInstanceInfo.IsWin10SDKInstalled |= win10SDKInstalled; + vsInstanceInfo.IsWin81SDKInstalled |= win81SDkInstalled; + } + } + + SafeArrayDestroy(lpsaPackages); + } + + return isVCToolSetInstalled; +} + +bool cmVSSetupAPIHelper::GetVSInstanceInfo(std::string& vsInstallLocation) +{ + vsInstallLocation = ""; + bool isInstalled = this->EnumerateAndChooseVSInstance(); + + if (isInstalled) { + std::string str(chosenInstanceInfo.VSInstallLocation.begin(), + chosenInstanceInfo.VSInstallLocation.end()); + vsInstallLocation = str; + } + + return isInstalled; +} + +bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() +{ + bool isVSInstanceExists = false; + if (chosenInstanceInfo.VSInstallLocation.compare(L"") != 0) { + return true; + } + + if (initializationFailure || setupConfig == NULL || setupConfig2 == NULL || + setupHelper == NULL) + return false; + + std::vector<VSInstanceInfo> vecVSInstances; + SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL; + if (FAILED( + setupConfig2->EnumInstances((IEnumSetupInstances**)&enumInstances)) || + !enumInstances) { + return false; + } + + SmartCOMPtr<ISetupInstance> instance; + while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { + SmartCOMPtr<ISetupInstance2> instance2 = NULL; + if (FAILED( + instance->QueryInterface(IID_ISetupInstance2, (void**)&instance2)) || + !instance2) { + instance = NULL; + continue; + } + + VSInstanceInfo instanceInfo; + bool isInstalled = GetVSInstanceInfo(instance2, instanceInfo); + instance = instance2 = NULL; + + if (isInstalled) { + vecVSInstances.push_back(instanceInfo); + } + } + + if (vecVSInstances.size() > 0) { + isVSInstanceExists = true; + int index = ChooseVSInstance(vecVSInstances); + chosenInstanceInfo = vecVSInstances[index]; + } + + return isVSInstanceExists; +} + +int cmVSSetupAPIHelper::ChooseVSInstance( + const std::vector<VSInstanceInfo>& vecVSInstances) +{ + if (vecVSInstances.size() == 0) + return -1; + + if (vecVSInstances.size() == 1) + return 0; + + unsigned int chosenIndex = 0; + for (unsigned int i = 1; i < vecVSInstances.size(); i++) { + // If the current has Win10 SDK but not the chosen one, then choose the + // current VS instance + if (!vecVSInstances[chosenIndex].IsWin10SDKInstalled && + vecVSInstances[i].IsWin10SDKInstalled) { + chosenIndex = i; + continue; + } + + // If the chosen one has Win10 SDK but the current one is not, then look at + // the next VS instance even the current + // instance version may be higher + if (vecVSInstances[chosenIndex].IsWin10SDKInstalled && + !vecVSInstances[i].IsWin10SDKInstalled) { + continue; + } + + // If both chosen one and current one doesn't have Win10 SDK but the + // current one has Win8.1 SDK installed, + // then choose the current one + if (!vecVSInstances[chosenIndex].IsWin10SDKInstalled && + !vecVSInstances[i].IsWin10SDKInstalled && + !vecVSInstances[chosenIndex].IsWin81SDKInstalled && + vecVSInstances[i].IsWin81SDKInstalled) { + chosenIndex = i; + continue; + } + + // If there is no difference in WinSDKs then look for the highest version + // of installed VS + if ((vecVSInstances[chosenIndex].IsWin10SDKInstalled == + vecVSInstances[i].IsWin10SDKInstalled) && + (vecVSInstances[chosenIndex].IsWin81SDKInstalled == + vecVSInstances[i].IsWin81SDKInstalled) && + vecVSInstances[chosenIndex].Version < vecVSInstances[i].Version) { + chosenIndex = i; + continue; + } + } + + return chosenIndex; +} + +bool cmVSSetupAPIHelper::Initialize() +{ + if (initializationFailure) + return false; + + if (FAILED(comInitialized)) { + initializationFailure = true; + return false; + } + + if (FAILED(setupConfig.CoCreateInstance(CLSID_SetupConfiguration, NULL, + IID_ISetupConfiguration, + CLSCTX_INPROC_SERVER)) || + setupConfig == NULL) { + initializationFailure = true; + return false; + } + + if (FAILED(setupConfig.QueryInterface(IID_ISetupConfiguration2, + (void**)&setupConfig2)) || + setupConfig2 == NULL) { + initializationFailure = true; + return false; + } + + if (FAILED( + setupConfig.QueryInterface(IID_ISetupHelper, (void**)&setupHelper)) || + setupHelper == NULL) { + initializationFailure = true; + return false; + } + + initializationFailure = false; + return true; +} diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h new file mode 100644 index 0000000..d2f514c --- /dev/null +++ b/Source/cmVSSetupHelper.h @@ -0,0 +1,154 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmVSSetupHelper_h +#define cmVSSetupHelper_h + +#ifndef NOMINMAX +#define NOMINMAX // Undefine min and max defined by windows.h +#endif + +// Published by Visual Studio Setup team +#include "cmvssetup/Setup.Configuration.h" + +#include <string> +#include <vector> + +#include <windows.h> + +template <class T> +class SmartCOMPtr +{ +public: + SmartCOMPtr() { ptr = NULL; } + SmartCOMPtr(T* p) + { + ptr = p; + if (ptr != NULL) + ptr->AddRef(); + } + SmartCOMPtr(const SmartCOMPtr<T>& sptr) + { + ptr = sptr.ptr; + if (ptr != NULL) + ptr->AddRef(); + } + T** operator&() { return &ptr; } + T* operator->() { return ptr; } + T* operator=(T* p) + { + if (*this != p) { + ptr = p; + if (ptr != NULL) + ptr->AddRef(); + } + return *this; + } + operator T*() const { return ptr; } + template <class I> + HRESULT QueryInterface(REFCLSID rclsid, I** pp) + { + if (pp != NULL) { + return ptr->QueryInterface(rclsid, (void**)pp); + } else { + return E_FAIL; + } + } + HRESULT CoCreateInstance(REFCLSID clsid, IUnknown* pUnknown, + REFIID interfaceId, DWORD dwClsContext = CLSCTX_ALL) + { + HRESULT hr = ::CoCreateInstance(clsid, pUnknown, dwClsContext, interfaceId, + (void**)&ptr); + return hr; + } + ~SmartCOMPtr() + { + if (ptr != NULL) + ptr->Release(); + } + +private: + T* ptr; +}; + +class SmartBSTR +{ +public: + SmartBSTR() { str = NULL; } + SmartBSTR(const SmartBSTR& src) + { + if (src.str != NULL) { + str = ::SysAllocStringByteLen((char*)str, ::SysStringByteLen(str)); + } else { + str = ::SysAllocStringByteLen(NULL, 0); + } + } + SmartBSTR& operator=(const SmartBSTR& src) + { + if (str != src.str) { + ::SysFreeString(str); + if (src.str != NULL) { + str = ::SysAllocStringByteLen((char*)str, ::SysStringByteLen(str)); + } else { + str = ::SysAllocStringByteLen(NULL, 0); + } + } + return *this; + } + operator BSTR() const { return str; } + BSTR* operator&() throw() { return &str; } + ~SmartBSTR() throw() { ::SysFreeString(str); } +private: + BSTR str; +}; + +struct VSInstanceInfo +{ + std::wstring InstanceId; + std::wstring VSInstallLocation; + std::wstring Version; + ULONGLONG ullVersion; + bool IsWin10SDKInstalled; + bool IsWin81SDKInstalled; + + VSInstanceInfo() + { + InstanceId = VSInstallLocation = Version = L""; + ullVersion = 0; + IsWin10SDKInstalled = IsWin81SDKInstalled = false; + } +}; + +class cmVSSetupAPIHelper +{ +public: + cmVSSetupAPIHelper(); + ~cmVSSetupAPIHelper(); + + bool IsVS2017Installed(); + bool GetVSInstanceInfo(std::string& vsInstallLocation); + bool IsWin10SDKInstalled(); + bool IsWin81SDKInstalled(); + +private: + bool Initialize(); + bool GetVSInstanceInfo(SmartCOMPtr<ISetupInstance2> instance2, + VSInstanceInfo& vsInstanceInfo); + bool CheckInstalledComponent(SmartCOMPtr<ISetupPackageReference> package, + bool& bVCToolset, bool& bWin10SDK, + bool& bWin81SDK); + int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances); + bool EnumerateAndChooseVSInstance(); + + // COM ptrs to query about VS instances + SmartCOMPtr<ISetupConfiguration> setupConfig; + SmartCOMPtr<ISetupConfiguration2> setupConfig2; + SmartCOMPtr<ISetupHelper> setupHelper; + // used to indicate failure in Initialize(), so we don't have to call again + bool initializationFailure; + // indicated if COM initialization is successful + HRESULT comInitialized; + // current best instance of VS selected + VSInstanceInfo chosenInstanceInfo; +}; + +#endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 49274c0..89380eb 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -130,9 +130,18 @@ void cmVisualStudio10TargetGenerator::WritePlatformConfigTag( } stream->fill(' '); stream->width(indentLevel * 2); - (*stream) << ""; - (*stream) << "<" << tag << " Condition=\"'$(Configuration)|$(Platform)'=='"; - (*stream) << config << "|" << this->Platform << "'\""; + (*stream) << "<" << tag << " Condition=\""; + (*stream) << "'$(Configuration)|$(Platform)'=='"; + (*stream) << config << "|" << this->Platform; + (*stream) << "'"; + // handle special case for 32 bit C# targets + if (csproj == this->ProjectType && this->Platform == "Win32") { + (*stream) << " Or "; + (*stream) << "'$(Configuration)|$(Platform)'=='"; + (*stream) << config << "|x86"; + (*stream) << "'"; + } + (*stream) << "\""; if (attribute) { (*stream) << attribute; } @@ -159,6 +168,14 @@ void cmVisualStudio10TargetGenerator::WriteString(const char* line, "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" #define VS10_CXX_TARGETS "$(VCTargetsPath)\\Microsoft.Cpp.targets" +#define VS10_CSharp_DEFAULT_PROPS \ + "$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props" +// This does not seem to exist by default, it's just provided for consistency +// in case users want to have default custom props for C# targets +#define VS10_CSharp_USER_PROPS \ + "$(UserRootDir)\\Microsoft.CSharp.$(Platform).user.props" +#define VS10_CSharp_TARGETS "$(MSBuildToolsPath)\\Microsoft.CSharp.targets" + void cmVisualStudio10TargetGenerator::Generate() { // do not generate external ms projects @@ -257,7 +274,9 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteString("</PropertyGroup>\n", 1); } - this->WriteProjectConfigurations(); + if (csproj != this->ProjectType) { + this->WriteProjectConfigurations(); + } this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1); this->WriteString("<ProjectGUID>", 2); (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGUID>\n"; @@ -271,9 +290,14 @@ void cmVisualStudio10TargetGenerator::Generate() const char* vsProjectTypes = this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES"); if (vsProjectTypes) { - this->WriteString("<ProjectTypes>", 2); - (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectTypes) - << "</ProjectTypes>\n"; + std::string tagName = "ProjectTypes"; + if (csproj == this->ProjectType) { + tagName = "ProjectTypeGuids"; + } + this->WriteString("", 2); + (*this->BuildFileStream) << "<" << tagName << ">" + << cmVS10EscapeXML(vsProjectTypes) << "</" + << tagName << ">\n"; } const char* vsProjectName = @@ -371,10 +395,59 @@ void cmVisualStudio10TargetGenerator::Generate() << "</" << globalKey << ">\n"; } + if (this->Managed) { + std::string outputType = "<OutputType>"; + switch (this->GeneratorTarget->GetType()) { + case cmStateEnums::OBJECT_LIBRARY: + case cmStateEnums::STATIC_LIBRARY: + case cmStateEnums::SHARED_LIBRARY: + outputType += "Library"; + break; + case cmStateEnums::MODULE_LIBRARY: + outputType += "Module"; + break; + case cmStateEnums::EXECUTABLE: + if (this->GeneratorTarget->Target->GetPropertyAsBool( + "WIN32_EXECUTABLE")) { + outputType += "WinExe"; + } else { + outputType += "Exe"; + } + break; + case cmStateEnums::UTILITY: + case cmStateEnums::GLOBAL_TARGET: + outputType += "Utility"; + break; + case cmStateEnums::UNKNOWN_LIBRARY: + case cmStateEnums::INTERFACE_LIBRARY: + break; + } + outputType += "</OutputType>\n"; + this->WriteString(outputType.c_str(), 2); + this->WriteString("<AppDesignerFolder>Properties</AppDesignerFolder>\n", + 2); + } + this->WriteString("</PropertyGroup>\n", 1); - this->WriteString("<Import Project=\"" VS10_CXX_DEFAULT_PROPS "\" />\n", 1); + + switch (this->ProjectType) { + case vcxproj: + this->WriteString("<Import Project=\"" VS10_CXX_DEFAULT_PROPS "\" />\n", + 1); + break; + case csproj: + this->WriteString("<Import Project=\"" VS10_CSharp_DEFAULT_PROPS "\" " + "Condition=\"Exists('" VS10_CSharp_DEFAULT_PROPS "')\"" + "/>\n", + 1); + break; + } + this->WriteProjectConfigurationValues(); - this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1); + + if (vcxproj == this->ProjectType) { + this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1); + } this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1); if (this->GlobalGenerator->IsMasmEnabled()) { this->WriteString("<Import Project=\"$(VCTargetsPath)\\" @@ -384,17 +457,26 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteString("</ImportGroup>\n", 1); this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1); { - std::string props = VS10_CXX_USER_PROPS; - if (const char* p = - this->GeneratorTarget->GetProperty("VS_USER_PROPS_CXX")) { + std::string props; + switch (this->ProjectType) { + case vcxproj: + props = VS10_CXX_USER_PROPS; + break; + case csproj: + props = VS10_CSharp_USER_PROPS; + break; + } + if (const char* p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) { props = p; + } + if (!props.empty()) { this->ConvertToWindowsSlash(props); + this->WriteString("", 2); + (*this->BuildFileStream) + << "<Import Project=\"" << cmVS10EscapeXML(props) << "\"" + << " Condition=\"exists('" << cmVS10EscapeXML(props) << "')\"" + << " Label=\"LocalAppDataPlatform\" />\n"; } - this->WriteString("", 2); - (*this->BuildFileStream) - << "<Import Project=\"" << cmVS10EscapeXML(props) << "\"" - << " Condition=\"exists('" << cmVS10EscapeXML(props) << "')\"" - << " Label=\"LocalAppDataPlatform\" />\n"; } this->WritePlatformExtensions(); this->WriteString("</ImportGroup>\n", 1); @@ -410,7 +492,14 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteWinRTReferences(); this->WriteProjectReferences(); this->WriteSDKReferences(); - this->WriteString("<Import Project=\"" VS10_CXX_TARGETS "\" />\n", 1); + switch (this->ProjectType) { + case vcxproj: + this->WriteString("<Import Project=\"" VS10_CXX_TARGETS "\" />\n", 1); + break; + case csproj: + this->WriteString("<Import Project=\"" VS10_CSharp_TARGETS "\" />\n", 1); + break; + } this->WriteTargetSpecificReferences(); this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1); @@ -421,6 +510,17 @@ void cmVisualStudio10TargetGenerator::Generate() 2); } this->WriteString("</ImportGroup>\n", 1); + if (csproj == this->ProjectType) { + for (std::vector<std::string>::const_iterator i = + this->Configurations.begin(); + i != this->Configurations.end(); ++i) { + this->WriteString("<PropertyGroup Condition=\"'$(Configuration)' == '", + 1); + (*this->BuildFileStream) << *i << "'\">\n"; + this->WriteEvents(*i); + this->WriteString("</PropertyGroup>\n", 1); + } + } this->WriteString("</Project>", 0); // The groups are stored in a separate file for VS 10 this->WriteGroups(); @@ -661,48 +761,55 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() i != this->Configurations.end(); ++i) { this->WritePlatformConfigTag("PropertyGroup", i->c_str(), 1, " Label=\"Configuration\"", "\n"); - std::string configType = "<ConfigurationType>"; - if (const char* vsConfigurationType = - this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) { - configType += cmVS10EscapeXML(vsConfigurationType); - } else { - switch (this->GeneratorTarget->GetType()) { - case cmStateEnums::SHARED_LIBRARY: - case cmStateEnums::MODULE_LIBRARY: - configType += "DynamicLibrary"; - break; - case cmStateEnums::OBJECT_LIBRARY: - case cmStateEnums::STATIC_LIBRARY: - configType += "StaticLibrary"; - break; - case cmStateEnums::EXECUTABLE: - if (this->NsightTegra && - !this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) { - // Android executables are .so too. + + if (csproj != this->ProjectType) { + std::string configType = "<ConfigurationType>"; + if (const char* vsConfigurationType = + this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) { + configType += cmVS10EscapeXML(vsConfigurationType); + } else { + switch (this->GeneratorTarget->GetType()) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: configType += "DynamicLibrary"; - } else { - configType += "Application"; - } - break; - case cmStateEnums::UTILITY: - case cmStateEnums::GLOBAL_TARGET: - if (this->NsightTegra) { - // Tegra-Android platform does not understand "Utility". + break; + case cmStateEnums::OBJECT_LIBRARY: + case cmStateEnums::STATIC_LIBRARY: configType += "StaticLibrary"; - } else { - configType += "Utility"; - } - break; - case cmStateEnums::UNKNOWN_LIBRARY: - case cmStateEnums::INTERFACE_LIBRARY: - break; + break; + case cmStateEnums::EXECUTABLE: + if (this->NsightTegra && + !this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) { + // Android executables are .so too. + configType += "DynamicLibrary"; + } else { + configType += "Application"; + } + break; + case cmStateEnums::UTILITY: + case cmStateEnums::GLOBAL_TARGET: + if (this->NsightTegra) { + // Tegra-Android platform does not understand "Utility". + configType += "StaticLibrary"; + } else { + configType += "Utility"; + } + break; + case cmStateEnums::UNKNOWN_LIBRARY: + case cmStateEnums::INTERFACE_LIBRARY: + break; + } } + configType += "</ConfigurationType>\n"; + this->WriteString(configType.c_str(), 2); } - configType += "</ConfigurationType>\n"; - this->WriteString(configType.c_str(), 2); if (this->MSTools) { - this->WriteMSToolConfigurationValues(*i); + if (!this->Managed) { + this->WriteMSToolConfigurationValues(*i); + } else { + this->WriteMSToolConfigurationValuesManaged(*i); + } } else if (this->NsightTegra) { this->WriteNsightTegraConfigurationValues(*i); } @@ -761,6 +868,61 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( } } +void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( + std::string const& config) +{ + cmGlobalVisualStudio10Generator* gg = + static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + + Options& o = *(this->ClOptions[config]); + + if (o.IsDebug()) { + this->WriteString("<DebugSymbols>true</DebugSymbols>\n", 2); + this->WriteString("<DefineDebug>true</DefineDebug>\n", 2); + } + + std::string outDir = + this->GeneratorTarget->GetDirectory(config.c_str()) + "/"; + this->ConvertToWindowsSlash(outDir); + this->WriteString("<OutputPath>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(outDir) << "</OutputPath>\n"; + + if (o.HasFlag("Platform")) { + this->WriteString("<PlatformTarget>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(o.GetFlag("Platform")) + << "</PlatformTarget>\n"; + o.RemoveFlag("Platform"); + } + + if (const char* toolset = gg->GetPlatformToolset()) { + this->WriteString("<PlatformToolset>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(toolset) + << "</PlatformToolset>\n"; + } + + std::string postfixName = cmSystemTools::UpperCase(config); + postfixName += "_POSTFIX"; + std::string assemblyName = + this->GeneratorTarget->GetOutputName(config, false); + if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) { + assemblyName += postfix; + } + this->WriteString("<AssemblyName>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(assemblyName) + << "</AssemblyName>\n"; + + if (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType()) { + this->WriteString("<StartAction>Program</StartAction>\n", 2); + this->WriteString("<StartProgram>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(outDir) + << cmVS10EscapeXML(assemblyName) + << ".exe</StartProgram>\n"; + } + + o.OutputFlagMap(*this->BuildFileStream, " "); +} + +//---------------------------------------------------------------------------- void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues( std::string const&) { @@ -924,6 +1086,10 @@ void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s) } void cmVisualStudio10TargetGenerator::WriteGroups() { + if (csproj == this->ProjectType) { + return; + } + // collect up group information std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); std::vector<cmSourceFile*> classes; @@ -1182,7 +1348,33 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) std::string shaderEntryPoint; std::string shaderModel; std::string shaderAdditionalFlags; + std::string sourceLink; std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); + if (csproj == this->ProjectType) { + // EVERY extra source file must have a <Link>, otherwise it might not + // be visible in Visual Studio at all. The path relative to current + // source- or binary-dir is used within the link, if the file is + // in none of these paths, it is added with the plain filename without + // any path. This means the file will show up at root-level of the csproj + // (where CMakeLists.txt etc. are). + if (!this->InSourceBuild) { + toolHasSettings = true; + std::string fullFileName = sf->GetFullPath(); + std::string srcDir = this->Makefile->GetCurrentSourceDirectory(); + std::string binDir = this->Makefile->GetCurrentBinaryDirectory(); + if (fullFileName.find(binDir) != std::string::npos) { + sourceLink = ""; + } else if (fullFileName.find(srcDir) != std::string::npos) { + sourceLink = fullFileName.substr(srcDir.length() + 1); + } else { + // fallback: add plain filename without any path + sourceLink = cmsys::SystemTools::GetFilenameName(fullFileName); + } + if (!sourceLink.empty()) { + this->ConvertToWindowsSlash(sourceLink); + } + } + } if (ext == "hlsl") { tool = "FXCompile"; // Figure out the type of shader compiler to use. @@ -1303,6 +1495,10 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) (*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags) << "</AdditionalOptions>\n"; } + if (!sourceLink.empty()) { + this->WriteString("<Link>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(sourceLink) << "</Link>\n"; + } this->WriteString("</", 2); (*this->BuildFileStream) << tool << ">\n"; } else { @@ -1344,6 +1540,12 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool, this->GlobalGenerator->PathTooLong(this->GeneratorTarget, sf, sourceRel); } } + if (csproj == this->ProjectType && this->InSourceBuild) { + std::string srcdir = this->Makefile->GetCurrentSourceDirectory(); + if (sourceFile.find(srcdir) != std::string::npos) { + sourceFile = sourceFile.substr(srcdir.size() + 1); + } + } this->ConvertToWindowsSlash(sourceFile); this->WriteString("<", 2); (*this->BuildFileStream) << tool << " Include=\"" @@ -1394,6 +1596,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() tool = "MASM"; } else if (lang == "RC") { tool = "ResourceCompile"; + } else if (lang == "CSharp") { + tool = "Compile"; } if (!tool.empty()) { @@ -1597,6 +1801,37 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( std::string xamlFileName = fileName.substr(0, fileName.find_last_of(".")); (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n"; } + if (csproj == this->ProjectType) { + std::string f = source->GetFullPath(); + typedef std::map<std::string, std::string> CsPropMap; + CsPropMap sourceFileTags; + // set <Link> tag if necessary + if (!this->InSourceBuild) { + const std::string stripFromPath = + this->Makefile->GetCurrentSourceDirectory(); + if (f.find(stripFromPath) != std::string::npos) { + std::string link = f.substr(stripFromPath.length() + 1); + this->ConvertToWindowsSlash(link); + sourceFileTags["Link"] = link; + } + } + // + // NOTE: in future commits additional props will be added! + // + // write source file specific tags + if (!sourceFileTags.empty()) { + hasFlags = true; + (*this->BuildFileStream) << firstString; + firstString = ""; + for (CsPropMap::const_iterator i = sourceFileTags.begin(); + i != sourceFileTags.end(); ++i) { + this->WriteString("<", 2); + (*this->BuildFileStream) + << i->first << ">" << cmVS10EscapeXML(i->second) << "</" << i->first + << ">\n"; + } + } + } return hasFlags; } @@ -1607,6 +1842,9 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() if (ttype > cmStateEnums::GLOBAL_TARGET) { return; } + if (csproj == this->ProjectType) { + return; + } this->WriteString("<PropertyGroup>\n", 2); this->WriteString("<_ProjectFileVersion>10.0.20506.1" @@ -1681,6 +1919,9 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( if (!this->MSTools) { return; } + if (csproj == this->ProjectType) { + return; + } // static libraries and things greater than modules do not need // to set this option if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || @@ -1735,8 +1976,18 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( cmGlobalVisualStudio10Generator* gg = static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); - CM_AUTO_PTR<Options> pOptions(new Options( - this->LocalGenerator, Options::Compiler, gg->GetClFlagTable())); + CM_AUTO_PTR<Options> pOptions; + switch (this->ProjectType) { + case vcxproj: + pOptions = CM_AUTO_PTR<Options>(new Options( + this->LocalGenerator, Options::Compiler, gg->GetClFlagTable())); + break; + case csproj: + pOptions = CM_AUTO_PTR<Options>(new Options(this->LocalGenerator, + Options::CSharpCompiler, + gg->GetCSharpFlagTable())); + break; + } Options& clOptions = *pOptions; std::string flags; @@ -1749,7 +2000,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( return false; } if (linkLanguage == "C" || linkLanguage == "CXX" || - linkLanguage == "Fortran") { + linkLanguage == "Fortran" || linkLanguage == "CSharp") { std::string baseFlagVar = "CMAKE_"; baseFlagVar += linkLanguage; baseFlagVar += "_FLAGS"; @@ -1777,16 +2028,26 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( std::string defineFlags = this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags(); if (this->MSTools) { - clOptions.FixExceptionHandlingDefault(); - clOptions.AddFlag("PrecompiledHeader", "NotUsing"); - std::string asmLocation = configName + "/"; - clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str()); + if (vcxproj == this->ProjectType) { + clOptions.FixExceptionHandlingDefault(); + clOptions.AddFlag("PrecompiledHeader", "NotUsing"); + std::string asmLocation = configName + "/"; + clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str()); + } } clOptions.Parse(flags.c_str()); clOptions.Parse(defineFlags.c_str()); std::vector<std::string> targetDefines; - this->GeneratorTarget->GetCompileDefinitions(targetDefines, - configName.c_str(), "CXX"); + switch (this->ProjectType) { + case vcxproj: + this->GeneratorTarget->GetCompileDefinitions(targetDefines, + configName.c_str(), "CXX"); + break; + case csproj: + this->GeneratorTarget->GetCompileDefinitions( + targetDefines, configName.c_str(), "CSharp"); + break; + } clOptions.AddDefines(targetDefines); if (this->MSTools) { clOptions.SetVerboseMakefile( @@ -1841,6 +2102,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( std::string const& configName, std::vector<std::string> const& includes) { Options& clOptions = *(this->ClOptions[configName]); + if (this->ProjectType == csproj) { + return; + } this->WriteString("<ClCompile>\n", 2); clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); clOptions.AppendFlag("AdditionalIncludeDirectories", includes); @@ -2509,6 +2773,9 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions( this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) { return; } + if (csproj == this->ProjectType) { + return; + } Options& linkOptions = *(this->LinkOptions[config]); this->WriteString("<Link>\n", 2); @@ -2576,6 +2843,9 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions( if (!this->MSTools) { return; } + if (csproj == this->ProjectType) { + return; + } // This processes *any* of the .idl files specified in the project's file // list (and passed as the item metadata %(Filename) expressing the rule @@ -2637,7 +2907,9 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() // output midl flags <Midl></Midl> this->WriteMidlOptions(*i, includes); // write events - this->WriteEvents(*i); + if (csproj != this->ProjectType) { + this->WriteEvents(*i); + } // output link flags <Link></Link> this->WriteLinkOptions(*i); // output lib flags <Lib></Lib> @@ -2703,12 +2975,20 @@ void cmVisualStudio10TargetGenerator::WriteEvent( script += cmVS10EscapeXML(lg->ConstructScript(ccg)); } comment = cmVS10EscapeComment(comment); - this->WriteString("<Message>", 3); - (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n"; - this->WriteString("<Command>", 3); + if (csproj != this->ProjectType) { + this->WriteString("<Message>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n"; + this->WriteString("<Command>", 3); + } else { + if (!comment.empty()) { + (*this->BuildFileStream) << "echo " << cmVS10EscapeXML(comment) << "\n"; + } + } (*this->BuildFileStream) << script; - (*this->BuildFileStream) << "</Command>" - << "\n"; + if (csproj != this->ProjectType) { + (*this->BuildFileStream) << "</Command>"; + } + (*this->BuildFileStream) << "\n"; this->WriteString("</", 2); (*this->BuildFileStream) << name << ">\n"; } @@ -2733,6 +3013,10 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() ->TargetIsFortranOnly(dt)) { continue; } + if (csproj == this->ProjectType && + !this->GlobalGenerator->TargetIsCSharpOnly(dt)) { + continue; + } this->WriteString("<ProjectReference Include=\"", 2); cmLocalGenerator* lg = dt->GetLocalGenerator(); std::string name = dt->GetName(); @@ -2749,8 +3033,16 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() this->ConvertToWindowsSlash(path); (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n"; this->WriteString("<Project>", 3); - (*this->BuildFileStream) << this->GlobalGenerator->GetGUID(name.c_str()) - << "</Project>\n"; + if (csproj == this->ProjectType) { + (*this->BuildFileStream) << "{"; + } + (*this->BuildFileStream) << this->GlobalGenerator->GetGUID(name.c_str()); + if (csproj == this->ProjectType) { + (*this->BuildFileStream) << "}"; + } + (*this->BuildFileStream) << "</Project>\n"; + this->WriteString("<Name>", 3); + (*this->BuildFileStream) << name << "</Name>\n"; this->WriteString("</ProjectReference>\n", 2); } this->WriteString("</ItemGroup>\n", 1); diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 027761e..45464c0 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -56,6 +56,7 @@ private: void WriteProjectConfigurations(); void WriteProjectConfigurationValues(); void WriteMSToolConfigurationValues(std::string const& config); + void WriteMSToolConfigurationValuesManaged(std::string const& config); void WriteHeaderSource(cmSourceFile const* sf); void WriteExtraSource(cmSourceFile const* sf); void WriteNsightTegraConfigurationValues(std::string const& config); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 733e0e4..6141f50 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -64,6 +64,7 @@ #include "cmGlobalVisualStudio71Generator.h" #include "cmGlobalVisualStudio8Generator.h" #include "cmGlobalVisualStudio9Generator.h" +#include "cmVSSetupHelper.h" #define CMAKE_HAVE_VS_GENERATORS #endif @@ -1470,18 +1471,23 @@ void cmake::CreateDefaultGlobalGenerator() "\\Setup\\VC;ProductDir", // ";InstallDir" // }; - for (VSVersionedGenerator const* g = cmArrayBegin(vsGenerators); - found.empty() && g != cmArrayEnd(vsGenerators); ++g) { - for (const char* const* v = cmArrayBegin(vsVariants); - found.empty() && v != cmArrayEnd(vsVariants); ++v) { - for (const char* const* e = cmArrayBegin(vsEntries); - found.empty() && e != cmArrayEnd(vsEntries); ++e) { - std::string const reg = vsregBase + *v + g->MSVersion + *e; - std::string dir; - if (cmSystemTools::ReadRegistryValue(reg, dir, - cmSystemTools::KeyWOW64_32) && - cmSystemTools::PathExists(dir)) { - found = g->GeneratorName; + cmVSSetupAPIHelper vsSetupAPIHelper; + if (vsSetupAPIHelper.IsVS2017Installed()) { + found = "Visual Studio 15 2017"; + } else { + for (VSVersionedGenerator const* g = cmArrayBegin(vsGenerators); + found.empty() && g != cmArrayEnd(vsGenerators); ++g) { + for (const char* const* v = cmArrayBegin(vsVariants); + found.empty() && v != cmArrayEnd(vsVariants); ++v) { + for (const char* const* e = cmArrayBegin(vsEntries); + found.empty() && e != cmArrayEnd(vsEntries); ++e) { + std::string const reg = vsregBase + *v + g->MSVersion + *e; + std::string dir; + if (cmSystemTools::ReadRegistryValue(reg, dir, + cmSystemTools::KeyWOW64_32) && + cmSystemTools::PathExists(dir)) { + found = g->GeneratorName; + } } } } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 73eef9a..4945b31 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -325,6 +325,9 @@ if(BUILD_TESTING) endif() endif() + if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^789]|[789][0-9])") + ADD_TEST_MACRO(CSharpOnly CSharpOnly) + endif() ADD_TEST_MACRO(COnly COnly) ADD_TEST_MACRO(CxxOnly CxxOnly) diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index 1313dbf..d6d2357 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -518,6 +518,13 @@ set(msys_g77_libs "frtbegin;g2c;mingw32;moldname;mingwex;msvcrt;user32;kernel32; set(msys_g77_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib") list(APPEND platforms msys_g77) +#----------------------------------------------------------------------------- +# MSVC from NVIDIA CUDA + +set(nvcc_msvc_text [[cuda-fake-ld cl.exe -nologo "tmp/a_dlink.obj" "tmp/CMakeCUDACompilerId.obj" -link -INCREMENTAL:NO "/LIBPATH:C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/bin/../lib/x64" cudadevrt.lib cudart_static.lib -Fe"a.exe"]]) +set(nvcc_msvc_libs "cudadevrt.lib;cudart_static.lib") +set(nvcc_msvc_dirs "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/lib/x64") +list(APPEND platforms nvcc_msvc) #----------------------------------------------------------------------------- # Test parsing for all above examples. diff --git a/Tests/CSharpOnly/CMakeLists.txt b/Tests/CSharpOnly/CMakeLists.txt new file mode 100644 index 0000000..0e3e39e --- /dev/null +++ b/Tests/CSharpOnly/CMakeLists.txt @@ -0,0 +1,10 @@ +# a simple CSharp only test case +project (CSharpOnly CSharp) + +# C# does not make any difference between STATIC and SHARED libs +add_library(lib1 STATIC lib1.cs) +add_library(lib2 SHARED lib2.cs) + +add_executable(CSharpOnly csharponly.cs) + +target_link_libraries(CSharpOnly lib1 lib2) diff --git a/Tests/CSharpOnly/csharponly.cs b/Tests/CSharpOnly/csharponly.cs new file mode 100644 index 0000000..ad4641a --- /dev/null +++ b/Tests/CSharpOnly/csharponly.cs @@ -0,0 +1,15 @@ +namespace CSharpOnly +{ + class CSharpOnly + { + public static void Main(string[] args) + { + int val = Lib1.getResult(); + + Lib2 l = new Lib2(); + val = l.myVal; + + return; + } + } +} diff --git a/Tests/CSharpOnly/lib1.cs b/Tests/CSharpOnly/lib1.cs new file mode 100644 index 0000000..7a7ae10 --- /dev/null +++ b/Tests/CSharpOnly/lib1.cs @@ -0,0 +1,10 @@ +namespace CSharpOnly +{ + public class Lib1 + { + public static int getResult() + { + return 23; + } + } +} diff --git a/Tests/CSharpOnly/lib2.cs b/Tests/CSharpOnly/lib2.cs new file mode 100644 index 0000000..b4b38ce --- /dev/null +++ b/Tests/CSharpOnly/lib2.cs @@ -0,0 +1,10 @@ +namespace CSharpOnly +{ + public class Lib2 + { + public int myVal = 42; + + public Lib2() + {} + } +} diff --git a/Tests/CTestTestLaunchers/launcher_compiler_test_project/CMakeLists.txt b/Tests/CTestTestLaunchers/launcher_compiler_test_project/CMakeLists.txt new file mode 100644 index 0000000..7376a40 --- /dev/null +++ b/Tests/CTestTestLaunchers/launcher_compiler_test_project/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.8.12) + +project(launcher_compiler_test_project) + +include(CTest) + +add_executable(build_error build_error.cxx) diff --git a/Tests/CTestTestLaunchers/launcher_test_project/CTestConfig.cmake b/Tests/CTestTestLaunchers/launcher_compiler_test_project/CTestConfig.cmake index 669b0fb..669b0fb 100644 --- a/Tests/CTestTestLaunchers/launcher_test_project/CTestConfig.cmake +++ b/Tests/CTestTestLaunchers/launcher_compiler_test_project/CTestConfig.cmake diff --git a/Tests/CTestTestLaunchers/launcher_compiler_test_project/build_error.cxx b/Tests/CTestTestLaunchers/launcher_compiler_test_project/build_error.cxx new file mode 100644 index 0000000..2d51693 --- /dev/null +++ b/Tests/CTestTestLaunchers/launcher_compiler_test_project/build_error.cxx @@ -0,0 +1,5 @@ +int main() +{ + int = 3; + return; +} diff --git a/Tests/CTestTestLaunchers/launcher_test_project/CMakeLists.txt b/Tests/CTestTestLaunchers/launcher_custom_command_test_project/CMakeLists.txt index 06c5725..b31f587 100644 --- a/Tests/CTestTestLaunchers/launcher_test_project/CMakeLists.txt +++ b/Tests/CTestTestLaunchers/launcher_custom_command_test_project/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8.12) -project(launcher_test_project) +project(launcher_custom_command_test_project) include(CTest) diff --git a/Tests/CTestTestLaunchers/launcher_custom_command_test_project/CTestConfig.cmake b/Tests/CTestTestLaunchers/launcher_custom_command_test_project/CTestConfig.cmake new file mode 100644 index 0000000..669b0fb --- /dev/null +++ b/Tests/CTestTestLaunchers/launcher_custom_command_test_project/CTestConfig.cmake @@ -0,0 +1,8 @@ +set(CTEST_USE_LAUNCHERS 1) +set(CTEST_PROJECT_NAME "CTestTestLaunchers") +set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT") +set(CTEST_DART_SERVER_VERSION "2") +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "open.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=PublicDashboard") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestLaunchers/launcher_test_project/command.cmake b/Tests/CTestTestLaunchers/launcher_custom_command_test_project/command.cmake index 7f31af9..7f31af9 100644 --- a/Tests/CTestTestLaunchers/launcher_test_project/command.cmake +++ b/Tests/CTestTestLaunchers/launcher_custom_command_test_project/command.cmake diff --git a/Tests/CTestTestLaunchers/launcher_linker_test_project/CMakeLists.txt b/Tests/CTestTestLaunchers/launcher_linker_test_project/CMakeLists.txt new file mode 100644 index 0000000..38980aa --- /dev/null +++ b/Tests/CTestTestLaunchers/launcher_linker_test_project/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.8.12) + +project(launcher_linker_test_project) + +include(CTest) + +add_executable(link_error link_error.cxx) diff --git a/Tests/CTestTestLaunchers/launcher_linker_test_project/CTestConfig.cmake b/Tests/CTestTestLaunchers/launcher_linker_test_project/CTestConfig.cmake new file mode 100644 index 0000000..669b0fb --- /dev/null +++ b/Tests/CTestTestLaunchers/launcher_linker_test_project/CTestConfig.cmake @@ -0,0 +1,8 @@ +set(CTEST_USE_LAUNCHERS 1) +set(CTEST_PROJECT_NAME "CTestTestLaunchers") +set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT") +set(CTEST_DART_SERVER_VERSION "2") +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "open.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=PublicDashboard") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestLaunchers/launcher_linker_test_project/link_error.cxx b/Tests/CTestTestLaunchers/launcher_linker_test_project/link_error.cxx new file mode 100644 index 0000000..c879be1 --- /dev/null +++ b/Tests/CTestTestLaunchers/launcher_linker_test_project/link_error.cxx @@ -0,0 +1,6 @@ +extern int foo(); + +int main() +{ + return foo(); +} diff --git a/Tests/CTestTestLaunchers/test.cmake.in b/Tests/CTestTestLaunchers/test.cmake.in index 03a118a..2db1ddd 100644 --- a/Tests/CTestTestLaunchers/test.cmake.in +++ b/Tests/CTestTestLaunchers/test.cmake.in @@ -1,39 +1,51 @@ cmake_minimum_required(VERSION 2.8.12) -# Settings: -set(CTEST_DASHBOARD_SOURCE "@CMake_SOURCE_DIR@/Tests/CTestTestLaunchers") -set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTestLaunchers") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "Launchers-@BUILDNAME@-CTestTestLaunchers") - -set(CTEST_SOURCE_DIRECTORY "${CTEST_DASHBOARD_SOURCE}/launcher_test_project") -set(CTEST_BINARY_DIRECTORY "${CTEST_DASHBOARD_ROOT}/launcher_test_project-bin") -set(CTEST_CMAKE_GENERATOR "@CMAKE_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_PLATFORM "@CMAKE_GENERATOR_PLATFORM@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") - -ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) - -file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" " -CMAKE_CXX_FLAGS:STRING=@CMAKE_CXX_FLAGS@ -CMAKE_C_FLAGS:STRING=@CMAKE_C_FLAGS@ -CMAKE_C_COMPILER:STRING=@CMAKE_C_COMPILER@ -CMAKE_CXX_COMPILER:STRING=@CMAKE_CXX_COMPILER@ -CMAKE_C_COMPILER_ARG1:STRING=@CMAKE_C_COMPILER_ARG1@ -CMAKE_CXX_COMPILER_ARG1:STRING=@CMAKE_CXX_COMPILER_ARG1@ -") - -set(TEST_SUCCESS FALSE) - -ctest_start(Experimental) -ctest_configure(OPTIONS "-DCTEST_USE_LAUNCHERS=1") -ctest_build(NUMBER_ERRORS error_count) - -if("${error_count}" STREQUAL "1") - set(TEST_SUCCESS TRUE) -endif() +set(TEST_SUCCESS TRUE) + +function(run_test_case NAME WHAT) + set(_message "Testing that launchers are used when running ${WHAT}") + message(STATUS "${_message}...") + + # Settings: + set(CTEST_DASHBOARD_SOURCE "@CMake_SOURCE_DIR@/Tests/CTestTestLaunchers") + set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTestLaunchers") + set(CTEST_SITE "@SITE@") + set(CTEST_BUILD_NAME "Launchers-@BUILDNAME@-CTestTestLaunchers") + + set(CTEST_SOURCE_DIRECTORY "${CTEST_DASHBOARD_SOURCE}/${NAME}") + set(CTEST_BINARY_DIRECTORY "${CTEST_DASHBOARD_ROOT}/${NAME}-bin") + set(CTEST_CMAKE_GENERATOR "@CMAKE_GENERATOR@") + set(CTEST_CMAKE_GENERATOR_PLATFORM "@CMAKE_GENERATOR_PLATFORM@") + set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_GENERATOR_TOOLSET@") + set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") + set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") + + ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) + + file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" " + CMAKE_CXX_FLAGS:STRING=@CMAKE_CXX_FLAGS@ + CMAKE_C_FLAGS:STRING=@CMAKE_C_FLAGS@ + CMAKE_C_COMPILER:STRING=@CMAKE_C_COMPILER@ + CMAKE_CXX_COMPILER:STRING=@CMAKE_CXX_COMPILER@ + CMAKE_C_COMPILER_ARG1:STRING=@CMAKE_C_COMPILER_ARG1@ + CMAKE_CXX_COMPILER_ARG1:STRING=@CMAKE_CXX_COMPILER_ARG1@ + ") + + ctest_start(Experimental) + ctest_configure(OPTIONS "-DCTEST_USE_LAUNCHERS=1") + ctest_build(NUMBER_ERRORS error_count) + + if("${error_count}" STREQUAL "0") + set(TEST_SUCCESS FALSE PARENT_SCOPE) + message(STATUS "${_message}... FAIL") + else() + message(STATUS "${_message}... PASS") + endif() +endfunction() + +run_test_case(launcher_compiler_test_project "the compiler") +run_test_case(launcher_linker_test_project "the linker") +run_test_case(launcher_custom_command_test_project "a custom command") if(TEST_SUCCESS) message("CTEST_TEST_LAUNCHER_SUCCESS") diff --git a/Tests/Cuda/CMakeLists.txt b/Tests/Cuda/CMakeLists.txt index 5772fcf..40c9675 100644 --- a/Tests/Cuda/CMakeLists.txt +++ b/Tests/Cuda/CMakeLists.txt @@ -2,3 +2,4 @@ ADD_TEST_MACRO(Cuda.Complex CudaComplex) ADD_TEST_MACRO(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures) ADD_TEST_MACRO(Cuda.ObjectLibrary CudaObjectLibrary) +ADD_TEST_MACRO(Cuda.ProperLinkFlags ProperLinkFlags) diff --git a/Tests/Cuda/Complex/dynamic.cpp b/Tests/Cuda/Complex/dynamic.cpp index d579f1e..3848ce7 100644 --- a/Tests/Cuda/Complex/dynamic.cpp +++ b/Tests/Cuda/Complex/dynamic.cpp @@ -1,5 +1,11 @@ -int dynamic_base_func(int x) +#ifdef _WIN32 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT int dynamic_base_func(int x) { return x * x; } diff --git a/Tests/Cuda/Complex/dynamic.cu b/Tests/Cuda/Complex/dynamic.cu index ea52acb..a23dc25 100644 --- a/Tests/Cuda/Complex/dynamic.cu +++ b/Tests/Cuda/Complex/dynamic.cu @@ -3,9 +3,15 @@ #include <cuda.h> #include <iostream> +#ifdef _WIN32 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + int dynamic_base_func(int); -int __host__ cuda_dynamic_host_func(int x) +EXPORT int __host__ cuda_dynamic_host_func(int x) { return dynamic_base_func(x); } @@ -16,7 +22,7 @@ void DetermineIfValidCudaDevice() { } -void cuda_dynamic_lib_func() +EXPORT void cuda_dynamic_lib_func() { DetermineIfValidCudaDevice <<<1,1>>> (); cudaError_t err = cudaGetLastError(); diff --git a/Tests/Cuda/Complex/main.cpp b/Tests/Cuda/Complex/main.cpp index 32312d0..5a3f820 100644 --- a/Tests/Cuda/Complex/main.cpp +++ b/Tests/Cuda/Complex/main.cpp @@ -3,8 +3,14 @@ #include "file1.h" #include "file2.h" -int call_cuda_seperable_code(int x); -int mixed_launch_kernel(int x); +#ifdef _WIN32 +#define IMPORT __declspec(dllimport) +#else +#define IMPORT +#endif + +IMPORT int call_cuda_seperable_code(int x); +IMPORT int mixed_launch_kernel(int x); int main(int argc, char** argv) { diff --git a/Tests/Cuda/Complex/mixed.cpp b/Tests/Cuda/Complex/mixed.cpp index 205f091..bd32e51 100644 --- a/Tests/Cuda/Complex/mixed.cpp +++ b/Tests/Cuda/Complex/mixed.cpp @@ -1,6 +1,14 @@ +#ifdef _WIN32 +#define EXPORT __declspec(dllexport) +#define IMPORT __declspec(dllimport) +#else +#define EXPORT +#define IMPORT +#endif + int dynamic_base_func(int); -int cuda_dynamic_host_func(int); +IMPORT int cuda_dynamic_host_func(int); int file3_launch_kernel(int); int dynamic_final_func(int x) @@ -8,7 +16,7 @@ int dynamic_final_func(int x) return cuda_dynamic_host_func(dynamic_base_func(x)); } -int call_cuda_seperable_code(int x) +EXPORT int call_cuda_seperable_code(int x) { return file3_launch_kernel(x); } diff --git a/Tests/Cuda/Complex/mixed.cu b/Tests/Cuda/Complex/mixed.cu index 45b412f..7051de0 100644 --- a/Tests/Cuda/Complex/mixed.cu +++ b/Tests/Cuda/Complex/mixed.cu @@ -4,10 +4,18 @@ #include "file1.h" #include "file2.h" +#ifdef _WIN32 +#define EXPORT __declspec(dllexport) +#define IMPORT __declspec(dllimport) +#else +#define EXPORT +#define IMPORT +#endif + result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); -void __host__ cuda_dynamic_lib_func(); +IMPORT void __host__ cuda_dynamic_lib_func(); static __global__ @@ -17,7 +25,7 @@ void mixed_kernel(result_type& r, int x) result_type_dynamic rd = file2_func(x); } -int mixed_launch_kernel(int x) +EXPORT int mixed_launch_kernel(int x) { cuda_dynamic_lib_func(); diff --git a/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt b/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt index 8361b9e..9fda2d0 100644 --- a/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt +++ b/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt @@ -11,7 +11,7 @@ project (CudaConsumeCompileFeatures CXX CUDA) add_library(CudaConsumeLib STATIC static.cpp static.cu) -target_compile_features(CudaConsumeLib PUBLIC cxx_constexpr) +target_compile_features(CudaConsumeLib PUBLIC cxx_nullptr) add_executable(CudaConsumeCompileFeatures main.cu) target_link_libraries(CudaConsumeCompileFeatures PRIVATE CudaConsumeLib) diff --git a/Tests/Cuda/ProperLinkFlags/CMakeLists.txt b/Tests/Cuda/ProperLinkFlags/CMakeLists.txt new file mode 100644 index 0000000..a9eb8bd --- /dev/null +++ b/Tests/Cuda/ProperLinkFlags/CMakeLists.txt @@ -0,0 +1,20 @@ + +cmake_minimum_required(VERSION 3.7) +project (ProperLinkFlags CUDA CXX) + +#Goal for this example: +#Verify that when we have CXX and CUDA enabled and we link an executable that +#has CUDA and CXX we use the CUDA link flags when doing the device link +#step + +#Specify a set of valid CUDA flags and an invalid set of CXX flags ( for CUDA ) +#to make sure we don't use the CXX flags when linking CUDA executables +set(CMAKE_CUDA_FLAGS "-arch=sm_35 --use_fast_math") +set(CMAKE_CXX_FLAGS "-Wall") + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CUDA_STANDARD 11) +add_executable(ProperLinkFlags file1.cu main.cxx) + +set_target_properties( ProperLinkFlags + PROPERTIES CUDA_SEPARABLE_COMPILATION ON) diff --git a/Tests/Cuda/ProperLinkFlags/file1.cu b/Tests/Cuda/ProperLinkFlags/file1.cu new file mode 100644 index 0000000..d93dc9f --- /dev/null +++ b/Tests/Cuda/ProperLinkFlags/file1.cu @@ -0,0 +1,11 @@ + +#include "file1.h" + +result_type __device__ file1_func(int x) +{ + __ldg(&x); + result_type r; + r.input = x; + r.sum = x*x; + return r; +} diff --git a/Tests/Cuda/ProperLinkFlags/file1.h b/Tests/Cuda/ProperLinkFlags/file1.h new file mode 100644 index 0000000..ff1945c --- /dev/null +++ b/Tests/Cuda/ProperLinkFlags/file1.h @@ -0,0 +1,7 @@ + +#pragma once +struct result_type +{ + int input; + int sum; +}; diff --git a/Tests/Cuda/ProperLinkFlags/main.cxx b/Tests/Cuda/ProperLinkFlags/main.cxx new file mode 100644 index 0000000..7c0ee9e --- /dev/null +++ b/Tests/Cuda/ProperLinkFlags/main.cxx @@ -0,0 +1,9 @@ + +#include <iostream> + +#include "file1.h" + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/Tests/CudaOnly/EnableStandard/main.cu b/Tests/CudaOnly/EnableStandard/main.cu index 83e9dfd..f7144e6 100644 --- a/Tests/CudaOnly/EnableStandard/main.cu +++ b/Tests/CudaOnly/EnableStandard/main.cu @@ -1,8 +1,14 @@ #include <iostream> +#ifdef _WIN32 +#define IMPORT __declspec(dllimport) +#else +#define IMPORT +#endif + int static_cuda11_func(int); -int shared_cuda11_func(int); +IMPORT int shared_cuda11_func(int); void test_functions() { diff --git a/Tests/CudaOnly/EnableStandard/shared.cu b/Tests/CudaOnly/EnableStandard/shared.cu index 28555b3..ccdd0b2 100644 --- a/Tests/CudaOnly/EnableStandard/shared.cu +++ b/Tests/CudaOnly/EnableStandard/shared.cu @@ -1,9 +1,15 @@ #include <type_traits> +#ifdef _WIN32 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + using tt = std::true_type; using ft = std::false_type; -int __host__ shared_cuda11_func(int x) +EXPORT int __host__ shared_cuda11_func(int x) { return x * x + std::integral_constant<int, 17>::value; } diff --git a/Tests/CudaOnly/SeparateCompilation/main.cu b/Tests/CudaOnly/SeparateCompilation/main.cu index d4520ae..5c8e150 100644 --- a/Tests/CudaOnly/SeparateCompilation/main.cu +++ b/Tests/CudaOnly/SeparateCompilation/main.cu @@ -4,12 +4,12 @@ #include "file1.h" #include "file2.h" -// result_type file4_launch_kernel(int x); -// result_type file5_launch_kernel(int x); +int file4_launch_kernel(int x); +int file5_launch_kernel(int x); int main(int argc, char **argv) { - // file4_launch_kernel(42); - // file5_launch_kernel(42); + file4_launch_kernel(42); + file5_launch_kernel(42); return 0; } diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt index c4ca8b9..6c4011c 100644 --- a/Tests/CudaOnly/WithDefs/CMakeLists.txt +++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt @@ -4,7 +4,12 @@ project (CudaOnlyWithDefs CUDA) #verify that we can pass explicit cuda arch flags set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") -set(debug_compile_flags --generate-code arch=compute_20,code=sm_20 -Xcompiler=-Werror) +set(debug_compile_flags --generate-code arch=compute_20,code=sm_20) +if(CMAKE_CUDA_SIMULATE_ID STREQUAL "MSVC") + list(APPEND debug_compile_flags -Xcompiler=-WX) +else() + list(APPEND debug_compile_flags -Xcompiler=-Werror) +endif() set(release_compile_defs DEFREL) #Goal for this example: diff --git a/Tests/CudaOnly/WithDefs/main.notcu b/Tests/CudaOnly/WithDefs/main.notcu index 33a49d2..67bf10c 100644 --- a/Tests/CudaOnly/WithDefs/main.notcu +++ b/Tests/CudaOnly/WithDefs/main.notcu @@ -2,12 +2,21 @@ #include <cuda_runtime.h> #include <iostream> +#ifndef PACKED_DEFINE +#error "PACKED_DEFINE not defined!" +#endif + static __global__ void DetermineIfValidCudaDevice() { } +#ifdef _MSC_VER +#pragma pack(push,1) +#undef PACKED_DEFINE +#define PACKED_DEFINE +#endif struct PACKED_DEFINE result_type { bool valid; @@ -16,6 +25,9 @@ struct PACKED_DEFINE result_type #error missing DEFREL flag #endif }; +#ifdef _MSC_VER +#pragma pack(pop) +#endif result_type can_launch_kernel() { diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 6d4e2c4..4b90ad8 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -139,6 +139,69 @@ if (automoc_rerun_result) message(SEND_ERROR "Second build of automoc_rerun failed.") endif() +# -- Test: AUTOMOC, SKIP_AUTOMOC +# Test for SKIP_AUTOMOC and SKIP_AUTOGEN on an AUTOMOC enabled target +qtx_wrap_cpp(skipMocWrapMoc + skipSource/qItemA.hpp + skipSource/qItemB.hpp) +set(skipMocSources + skipMoc.cpp + skipSource/qItemA.cpp + skipSource/qItemB.cpp + skipSource/qItemC.cpp) +set_property(SOURCE skipSource/qItemA.cpp PROPERTY SKIP_AUTOMOC ON) +set_property(SOURCE skipSource/qItemB.cpp PROPERTY SKIP_AUTOGEN ON) +# AUTOMOC enabled only +add_executable(skipMocA ${skipMocSources} ${skipMocWrapMoc}) +set_property(TARGET skipMocA PROPERTY AUTOMOC ON) +target_link_libraries(skipMocA ${QT_LIBRARIES}) +# AUTOMOC and AUTOUIC enabled +add_executable(skipMocB ${skipMocSources} ${skipMocWrapMoc}) +set_property(TARGET skipMocB PROPERTY AUTOMOC ON) +set_property(TARGET skipMocB PROPERTY AUTOUIC ON) +target_link_libraries(skipMocB ${QT_LIBRARIES}) + +# -- Test: AUTOUIC, SKIP_AUTOUIC +# Test for SKIP_AUTOUIC and SKIP_AUTOGEN on an AUTOUIC enabled target +set(skipUicSources + skipUic.cpp + skipSource/skipUicGen.cpp + skipSource/skipUicNoGen1.cpp + skipSource/skipUicNoGen2.cpp +) +set_property(SOURCE skipSource/skipUicNoGen1.cpp PROPERTY SKIP_AUTOUIC ON) +set_property(SOURCE skipSource/skipUicNoGen2.cpp PROPERTY SKIP_AUTOGEN ON) +# AUTOUIC enabled +add_executable(skipUicA ${skipUicSources}) +set_property(TARGET skipUicA PROPERTY AUTOUIC ON) +target_link_libraries(skipUicA ${QT_LIBRARIES}) +# AUTOUIC and AUTOMOC enabled +add_executable(skipUicB ${skipUicSources}) +set_property(TARGET skipUicB PROPERTY AUTOUIC ON) +set_property(TARGET skipUicB PROPERTY AUTOMOC ON) +target_link_libraries(skipUicB ${QT_LIBRARIES}) + +# -- Test: AUTORCC, SKIP_AUTORCC +# Test for SKIP_AUTORCC and SKIP_AUTOGEN on an AUTORCC enabled target +set(skipRccSources + skipRcc.cpp + skipSource/skipRccBad1.qrc + skipSource/skipRccBad2.qrc + skipSource/skipRccGood.qrc +) +set_property(SOURCE skipSource/skipRccBad1.qrc PROPERTY SKIP_AUTORCC ON) +set_property(SOURCE skipSource/skipRccBad2.qrc PROPERTY SKIP_AUTOGEN ON) +# AUTORCC enabled +add_executable(skipRccA ${skipRccSources}) +set_property(TARGET skipRccA PROPERTY AUTORCC ON) +target_link_libraries(skipRccA ${QT_LIBRARIES}) +# AUTORCC, AUTOUIC and AUTOMOC enabled +add_executable(skipRccB ${skipRccSources}) +set_property(TARGET skipRccB PROPERTY AUTORCC ON) +set_property(TARGET skipRccB PROPERTY AUTOUIC ON) +set_property(TARGET skipRccB PROPERTY AUTOMOC ON) +target_link_libraries(skipRccB ${QT_LIBRARIES}) + # -- Test: AUTOMOC AUTORCC # Source files with the same basename in different subdirectories add_subdirectory(sameName) diff --git a/Tests/QtAutogen/skipMoc.cpp b/Tests/QtAutogen/skipMoc.cpp new file mode 100644 index 0000000..85305f5 --- /dev/null +++ b/Tests/QtAutogen/skipMoc.cpp @@ -0,0 +1,14 @@ + +#include "skipSource/qItemA.hpp" +#include "skipSource/qItemB.hpp" +#include "skipSource/qItemC.hpp" + +int main(int, char**) +{ + QItemA itemA; + QItemA itemB; + QItemA itemC; + + // Fails to link if the symbol is not present. + return 0; +} diff --git a/Tests/QtAutogen/skipRcc.cpp b/Tests/QtAutogen/skipRcc.cpp new file mode 100644 index 0000000..ec57110 --- /dev/null +++ b/Tests/QtAutogen/skipRcc.cpp @@ -0,0 +1,9 @@ + +extern int qInitResources_skipRccGood(); + +int main(int, char**) +{ + // Fails to link if the symbol is not present. + qInitResources_skipRccGood(); + return 0; +} diff --git a/Tests/QtAutogen/skipSource/qItemA.cpp b/Tests/QtAutogen/skipSource/qItemA.cpp new file mode 100644 index 0000000..522c2c7 --- /dev/null +++ b/Tests/QtAutogen/skipSource/qItemA.cpp @@ -0,0 +1,5 @@ +#include "qItemA.hpp" + +void QItemA::go() +{ +} diff --git a/Tests/QtAutogen/skipSource/qItemA.hpp b/Tests/QtAutogen/skipSource/qItemA.hpp new file mode 100644 index 0000000..d295faf --- /dev/null +++ b/Tests/QtAutogen/skipSource/qItemA.hpp @@ -0,0 +1,13 @@ +#ifndef QITEMA_HPP +#define QITEMA_HPP + +#include <QObject> + +class QItemA : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/skipSource/qItemB.cpp b/Tests/QtAutogen/skipSource/qItemB.cpp new file mode 100644 index 0000000..636e15d --- /dev/null +++ b/Tests/QtAutogen/skipSource/qItemB.cpp @@ -0,0 +1,5 @@ +#include "qItemB.hpp" + +void QItemB::go() +{ +} diff --git a/Tests/QtAutogen/skipSource/qItemB.hpp b/Tests/QtAutogen/skipSource/qItemB.hpp new file mode 100644 index 0000000..1775915 --- /dev/null +++ b/Tests/QtAutogen/skipSource/qItemB.hpp @@ -0,0 +1,13 @@ +#ifndef QITEMB_HPP +#define QITEMB_HPP + +#include <QObject> + +class QItemB : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/skipSource/qItemC.cpp b/Tests/QtAutogen/skipSource/qItemC.cpp new file mode 100644 index 0000000..700abd6 --- /dev/null +++ b/Tests/QtAutogen/skipSource/qItemC.cpp @@ -0,0 +1,5 @@ +#include "qItemC.hpp" + +void QItemC::go() +{ +} diff --git a/Tests/QtAutogen/skipSource/qItemC.hpp b/Tests/QtAutogen/skipSource/qItemC.hpp new file mode 100644 index 0000000..f06bda2 --- /dev/null +++ b/Tests/QtAutogen/skipSource/qItemC.hpp @@ -0,0 +1,13 @@ +#ifndef QITEMC_HPP +#define QITEMC_HPP + +#include <QObject> + +class QItemC : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/skipSource/skipRccBad1.qrc b/Tests/QtAutogen/skipSource/skipRccBad1.qrc new file mode 100644 index 0000000..6cbd9ed --- /dev/null +++ b/Tests/QtAutogen/skipSource/skipRccBad1.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>skipRccGood.cpp</file>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</qresource> +</RCC> diff --git a/Tests/QtAutogen/skipSource/skipRccBad2.qrc b/Tests/QtAutogen/skipSource/skipRccBad2.qrc new file mode 100644 index 0000000..b32c589 --- /dev/null +++ b/Tests/QtAutogen/skipSource/skipRccBad2.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>< +<qresource> + <file>skipRccGood.cpp</file> +</qresource> +</RCC> diff --git a/Tests/QtAutogen/skipSource/skipRccGood.qrc b/Tests/QtAutogen/skipSource/skipRccGood.qrc new file mode 100644 index 0000000..21a94b0 --- /dev/null +++ b/Tests/QtAutogen/skipSource/skipRccGood.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>skipRccBad1.qrc</file> + <file>skipRccBad2.qrc</file> +</qresource> +</RCC> diff --git a/Tests/QtAutogen/skipSource/skipUicGen.cpp b/Tests/QtAutogen/skipSource/skipUicGen.cpp new file mode 100644 index 0000000..d2a55a6 --- /dev/null +++ b/Tests/QtAutogen/skipSource/skipUicGen.cpp @@ -0,0 +1,7 @@ + +#include "skipUicGen.hpp" +#include "ui_uigen2.h" + +void skipGen() +{ +} diff --git a/Tests/QtAutogen/skipSource/skipUicGen.hpp b/Tests/QtAutogen/skipSource/skipUicGen.hpp new file mode 100644 index 0000000..3669f0e --- /dev/null +++ b/Tests/QtAutogen/skipSource/skipUicGen.hpp @@ -0,0 +1,8 @@ +#ifndef SKIPUICGEN_HPP +#define SKIPUICGEN_HPP + +#include "ui_uigen1.h" + +void skipGen(); + +#endif diff --git a/Tests/QtAutogen/skipSource/skipUicNoGen1.cpp b/Tests/QtAutogen/skipSource/skipUicNoGen1.cpp new file mode 100644 index 0000000..f591a42 --- /dev/null +++ b/Tests/QtAutogen/skipSource/skipUicNoGen1.cpp @@ -0,0 +1,7 @@ + +#include "skipUicNoGen1.hpp" +#include "ui_nogen2.h" + +void skipNoGen1() +{ +} diff --git a/Tests/QtAutogen/skipSource/skipUicNoGen1.hpp b/Tests/QtAutogen/skipSource/skipUicNoGen1.hpp new file mode 100644 index 0000000..2864695 --- /dev/null +++ b/Tests/QtAutogen/skipSource/skipUicNoGen1.hpp @@ -0,0 +1,8 @@ +#ifndef SKIPUICNOGEN1_H +#define SKIPUICNOGEN1_H + +#include "ui_nogen1.h" + +void skipNoGen1(); + +#endif diff --git a/Tests/QtAutogen/skipSource/skipUicNoGen2.cpp b/Tests/QtAutogen/skipSource/skipUicNoGen2.cpp new file mode 100644 index 0000000..8c1c324 --- /dev/null +++ b/Tests/QtAutogen/skipSource/skipUicNoGen2.cpp @@ -0,0 +1,7 @@ + +#include "skipUicNoGen2.hpp" +#include "ui_nogen2.h" + +void skipNoGen2() +{ +} diff --git a/Tests/QtAutogen/skipSource/skipUicNoGen2.hpp b/Tests/QtAutogen/skipSource/skipUicNoGen2.hpp new file mode 100644 index 0000000..7c38193 --- /dev/null +++ b/Tests/QtAutogen/skipSource/skipUicNoGen2.hpp @@ -0,0 +1,8 @@ +#ifndef SKIPUICNOGEN2_H +#define SKIPUICNOGEN2_H + +#include "ui_nogen1.h" + +void skipNoGen2(); + +#endif diff --git a/Tests/QtAutogen/skipSource/ui_nogen1.h b/Tests/QtAutogen/skipSource/ui_nogen1.h new file mode 100644 index 0000000..a7be52b --- /dev/null +++ b/Tests/QtAutogen/skipSource/ui_nogen1.h @@ -0,0 +1,6 @@ +#ifndef UI_NOGEN1_H +#define UI_NOGEN1_H + +void ui_nogen1(); + +#endif diff --git a/Tests/QtAutogen/skipSource/ui_nogen2.h b/Tests/QtAutogen/skipSource/ui_nogen2.h new file mode 100644 index 0000000..5d547d4 --- /dev/null +++ b/Tests/QtAutogen/skipSource/ui_nogen2.h @@ -0,0 +1,6 @@ +#ifndef UI_NOGEN2_H +#define UI_NOGEN2_H + +void ui_nogen2(); + +#endif
\ No newline at end of file diff --git a/Tests/QtAutogen/skipSource/uigen1.ui b/Tests/QtAutogen/skipSource/uigen1.ui new file mode 100644 index 0000000..fc7cb82 --- /dev/null +++ b/Tests/QtAutogen/skipSource/uigen1.ui @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UiGen1</class> + <widget class="QWidget" name="UiGen1"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QTreeView" name="treeView"/> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Tests/QtAutogen/skipSource/uigen2.ui b/Tests/QtAutogen/skipSource/uigen2.ui new file mode 100644 index 0000000..01f08d2 --- /dev/null +++ b/Tests/QtAutogen/skipSource/uigen2.ui @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UiGen2</class> + <widget class="QWidget" name="UiGen2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QTreeView" name="treeView"/> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Tests/QtAutogen/skipUic.cpp b/Tests/QtAutogen/skipUic.cpp new file mode 100644 index 0000000..0adf011 --- /dev/null +++ b/Tests/QtAutogen/skipUic.cpp @@ -0,0 +1,22 @@ + +#include "skipSource/skipUicGen.hpp" +#include "skipSource/skipUicNoGen1.hpp" +#include "skipSource/skipUicNoGen2.hpp" + +int main(int, char**) +{ + skipGen(); + skipNoGen1(); + skipNoGen2(); + + return 0; +} + +// -- Function definitions +void ui_nogen1() +{ +} + +void ui_nogen2() +{ +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index adfd37d..d2465c4 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -345,7 +345,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") add_RunCMake_test(CompilerLauncher) endif() -add_RunCMake_test_group(CPack "DEB;RPM;TGZ") +add_RunCMake_test_group(CPack "DEB;RPM;7Z;TBZ2;TGZ;TXZ;TZ;ZIP") # add a test to make sure symbols are exported from a shared library # for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used add_RunCMake_test(AutoExportDll) diff --git a/Tests/RunCMake/CPack/7Z/Helpers.cmake b/Tests/RunCMake/CPack/7Z/Helpers.cmake new file mode 100644 index 0000000..f256a42 --- /dev/null +++ b/Tests/RunCMake/CPack/7Z/Helpers.cmake @@ -0,0 +1,3 @@ +set(cpack_archive_extension_ "7z") + +include("${CMAKE_CURRENT_LIST_DIR}/../ArchiveCommon/common_helpers.cmake") diff --git a/Tests/RunCMake/CPack/7Z/Prerequirements.cmake b/Tests/RunCMake/CPack/7Z/Prerequirements.cmake new file mode 100644 index 0000000..dbaf682 --- /dev/null +++ b/Tests/RunCMake/CPack/7Z/Prerequirements.cmake @@ -0,0 +1,4 @@ +function(get_test_prerequirements found_var config_file) + file(WRITE "${config_file}" "") + set(${found_var} true PARENT_SCOPE) +endfunction() diff --git a/Tests/RunCMake/CPack/7Z/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/7Z/packaging_COMPONENT_default.cmake new file mode 100644 index 0000000..81a5035 --- /dev/null +++ b/Tests/RunCMake/CPack/7Z/packaging_COMPONENT_default.cmake @@ -0,0 +1 @@ +set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON") diff --git a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake new file mode 100644 index 0000000..ce039f5 --- /dev/null +++ b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake @@ -0,0 +1,62 @@ +set(ALL_FILES_GLOB "*.${cpack_archive_extension_}") + +function(getPackageContent FILE RESULT_VAR) + # TODO for some types this only works because libarchive handles it... (not + # part of for e.g. gnu tar) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar -xtf ${FILE} + OUTPUT_VARIABLE package_content_ + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + + set(${RESULT_VAR} "${package_content_}" PARENT_SCOPE) +endfunction() + +function(getPackageNameGlobexpr NAME COMPONENT VERSION REVISION FILE_NO RESULT_VAR) + if(COMPONENT) + set(COMPONENT "-${COMPONENT}") + endif() + + set(${RESULT_VAR} + "${NAME}-${VERSION}-*${COMPONENT}.${cpack_archive_extension_}" PARENT_SCOPE) +endfunction() + +function(getPackageContentList FILE RESULT_VAR) + getPackageContent("${FILE}" package_content_) + + string(REPLACE "\n" ";" package_content_ "${package_content_}") + foreach(i_ IN LISTS package_content_) + string(REGEX REPLACE "/$" "" result_ "${i_}") + list(APPEND items_ "${result_}") + endforeach() + + set(${RESULT_VAR} "${items_}" PARENT_SCOPE) +endfunction() + +function(toExpectedContentList FILE_NO CONTENT_VAR) + findExpectedFile("${FILE_NO}" "file_") + + # component and monolithic packages differ for some reason by either having + # package filename prefix in path or not + if(PACKAGING_TYPE STREQUAL "MONOLITHIC") + get_filename_component(prefix_ "${file_}" NAME) + # NAME_WE removes everything after the dot and dot is in version so replace instead + string(REPLACE ".${cpack_archive_extension_}" "/" prefix_ "${prefix_}") + else() + unset(prefix_) + endif() + + if(NOT DEFINED TEST_MAIN_INSTALL_PREFIX_PATH) + set(TEST_MAIN_INSTALL_PREFIX_PATH "/usr") + endif() + + unset(filtered_) + foreach(part_ IN LISTS ${CONTENT_VAR}) + string(REGEX REPLACE "^${TEST_MAIN_INSTALL_PREFIX_PATH}(/|$)" "" part_ "${part_}") + + if(part_) + list(APPEND filtered_ "${prefix_}${part_}") + endif() + endforeach() + + set(${CONTENT_VAR} "${filtered_}" PARENT_SCOPE) +endfunction() diff --git a/Tests/RunCMake/CPack/CPackTestHelpers.cmake b/Tests/RunCMake/CPack/CPackTestHelpers.cmake index 89da610..f883c69 100644 --- a/Tests/RunCMake/CPack/CPackTestHelpers.cmake +++ b/Tests/RunCMake/CPack/CPackTestHelpers.cmake @@ -60,7 +60,11 @@ function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACK ) foreach(o out err) - if(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/${TEST_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt) + if(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/${TEST_TYPE}-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt) + set(RunCMake-std${o}-file "tests/${TEST_NAME}/${TEST_TYPE}-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt") + elseif(EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/${TEST_TYPE}-${PACKAGING_TYPE}-std${o}.txt) + set(RunCMake-std${o}-file "tests/${TEST_NAME}/${TEST_TYPE}-${PACKAGING_TYPE}-std${o}.txt") + elseif(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/${TEST_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt) set(RunCMake-std${o}-file "tests/${TEST_NAME}/${TEST_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt") elseif(EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/${TEST_TYPE}-std${o}.txt) set(RunCMake-std${o}-file "tests/${TEST_NAME}/${TEST_TYPE}-std${o}.txt") diff --git a/Tests/RunCMake/CPack/README.txt b/Tests/RunCMake/CPack/README.txt index f51d254..7c98f69 100644 --- a/Tests/RunCMake/CPack/README.txt +++ b/Tests/RunCMake/CPack/README.txt @@ -155,8 +155,18 @@ VerifyResult.cmake script also automatically prints out standard output and standard error from CPack execution phase that is compared with '<test_name>/<generator_name>-stdout.txt' regular expression and and '<test_name>/<generator_name>-stderr.txt' regular expresson respectively. -NOTE: For subtests generator name can also be suffixed with subtest name and in - such case subtest file is preferred. +NOTE: For subtests generator name can also be suffixed with subtest name and/or + packaging type (MONOLITHIC, COMPONENT, GROUP) and in such cases the + preferences of which file will be used are as follows: + - generator name + packaging type + subtest name + - generator name + packaging type + - generator name + subtest name + - generator name + - default generator + File name format: '<generator_name>-<packaging_type>-<subtest_name>-std<type>.txt' + where <type> can either be 'out' or 'err'. + File name format: '<generator_name>-<packaging_type>-std<type>.txt' + where <type> can either be 'out' or 'err'. File name format: '<generator_name>-<subtest_name>-std<type>.txt' where <type> can either be 'out' or 'err'. NOTE: If none of the comparison files are present then the default generator @@ -223,3 +233,4 @@ To add a new generator we must - if needed add 'default_expected_std<type>.txt' files where <type> is either 'out' or 'err' which will contain default expected output of package generation regular expression. +- add generator to list of other CPack generators in RunCMake/CMakeLists.txt diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 3077340..ebaf792 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -4,6 +4,7 @@ include(RunCMake) include("${RunCMake_SOURCE_DIR}/CPackTestHelpers.cmake") # run_cpack_test args: TEST_NAME "GENERATORS" RUN_CMAKE_BUILD_STEP "PACKAGING_TYPES" +run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM" false "MONOLITHIC;COMPONENT") run_cpack_test(CUSTOM_NAMES "RPM;DEB" true "COMPONENT") run_cpack_test(DEBUGINFO "RPM" true "COMPONENT") run_cpack_test(DEPENDENCIES "RPM;DEB" true "COMPONENT") @@ -15,7 +16,7 @@ run_cpack_test(GENERATE_SHLIBS_LDCONFIG "DEB" true "COMPONENT") run_cpack_test(INSTALL_SCRIPTS "RPM" false "COMPONENT") run_cpack_test(LONG_FILENAMES "DEB" false "MONOLITHIC") run_cpack_test_subtests(MAIN_COMPONENT "invalid;found" "RPM" false "COMPONENT") -run_cpack_test(MINIMAL "RPM;DEB;TGZ" false "MONOLITHIC") +run_cpack_test(MINIMAL "RPM;DEB;7Z;TBZ2;TGZ;TXZ;TZ;ZIP" false "MONOLITHIC;COMPONENT") run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;SHA512" "TGZ" false "MONOLITHIC") run_cpack_test(PARTIALLY_RELOCATABLE_WARNING "RPM" false "COMPONENT") run_cpack_test(PER_COMPONENT_FIELDS "RPM;DEB" false "COMPONENT") @@ -23,3 +24,4 @@ run_cpack_test_subtests(SINGLE_DEBUGINFO "no_main_component;one_component;one_co run_cpack_source_test(SOURCE_PACKAGE "RPM") run_cpack_test(SUGGESTS "RPM" false "MONOLITHIC") run_cpack_test(USER_FILELIST "RPM" false "MONOLITHIC") +run_cpack_test(MD5SUMS "DEB" false "MONOLITHIC;COMPONENT") diff --git a/Tests/RunCMake/CPack/TBZ2/Helpers.cmake b/Tests/RunCMake/CPack/TBZ2/Helpers.cmake new file mode 100644 index 0000000..292b691 --- /dev/null +++ b/Tests/RunCMake/CPack/TBZ2/Helpers.cmake @@ -0,0 +1,3 @@ +set(cpack_archive_extension_ "tar.bz2") + +include("${CMAKE_CURRENT_LIST_DIR}/../ArchiveCommon/common_helpers.cmake") diff --git a/Tests/RunCMake/CPack/TBZ2/Prerequirements.cmake b/Tests/RunCMake/CPack/TBZ2/Prerequirements.cmake new file mode 100644 index 0000000..dbaf682 --- /dev/null +++ b/Tests/RunCMake/CPack/TBZ2/Prerequirements.cmake @@ -0,0 +1,4 @@ +function(get_test_prerequirements found_var config_file) + file(WRITE "${config_file}" "") + set(${found_var} true PARENT_SCOPE) +endfunction() diff --git a/Tests/RunCMake/CPack/TBZ2/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/TBZ2/packaging_COMPONENT_default.cmake new file mode 100644 index 0000000..81a5035 --- /dev/null +++ b/Tests/RunCMake/CPack/TBZ2/packaging_COMPONENT_default.cmake @@ -0,0 +1 @@ +set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON") diff --git a/Tests/RunCMake/CPack/TGZ/Helpers.cmake b/Tests/RunCMake/CPack/TGZ/Helpers.cmake index 4a194c6..4357a59 100644 --- a/Tests/RunCMake/CPack/TGZ/Helpers.cmake +++ b/Tests/RunCMake/CPack/TGZ/Helpers.cmake @@ -1,62 +1,3 @@ -set(ALL_FILES_GLOB "*.tar.gz") +set(cpack_archive_extension_ "tar.gz") -function(getPackageContent FILE RESULT_VAR) - execute_process(COMMAND ${CMAKE_COMMAND} -E tar -ztvf ${FILE} - OUTPUT_VARIABLE package_content_ - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - - set(${RESULT_VAR} "${package_content_}" PARENT_SCOPE) -endfunction() - -function(getPackageNameGlobexpr NAME COMPONENT VERSION REVISION FILE_NO RESULT_VAR) - if(COMPONENT) - set(COMPONENT "-${COMPONENT}") - endif() - - set(${RESULT_VAR} "${NAME}-${VERSION}-*${COMPONENT}.tar.gz" PARENT_SCOPE) -endfunction() - -function(getPackageContentList FILE RESULT_VAR) - execute_process(COMMAND ${CMAKE_COMMAND} -E tar -ztf ${FILE} - OUTPUT_VARIABLE package_content_ - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - - string(REPLACE "\n" ";" package_content_ "${package_content_}") - foreach(i_ IN LISTS package_content_) - string(REGEX REPLACE "/$" "" result_ "${i_}") - list(APPEND items_ "${result_}") - endforeach() - - set(${RESULT_VAR} "${items_}" PARENT_SCOPE) -endfunction() - -function(toExpectedContentList FILE_NO CONTENT_VAR) - findExpectedFile("${FILE_NO}" "file_") - - # component and monolithic packages differ for some reason by either having - # package filename prefix in path or not - if(PACKAGING_TYPE STREQUAL "MONOLITHIC") - get_filename_component(prefix_ "${file_}" NAME) - # NAME_WE removes everything after the dot and dot is in version so replace instead - string(REPLACE ".tar.gz" "/" prefix_ "${prefix_}") - else() - unset(prefix_) - endif() - - if(NOT DEFINED TEST_MAIN_INSTALL_PREFIX_PATH) - set(TEST_MAIN_INSTALL_PREFIX_PATH "/usr") - endif() - - unset(filtered_) - foreach(part_ IN LISTS ${CONTENT_VAR}) - string(REGEX REPLACE "^${TEST_MAIN_INSTALL_PREFIX_PATH}(/|$)" "" part_ "${part_}") - - if(part_) - list(APPEND filtered_ "${prefix_}${part_}") - endif() - endforeach() - - set(${CONTENT_VAR} "${filtered_}" PARENT_SCOPE) -endfunction() +include("${CMAKE_CURRENT_LIST_DIR}/../ArchiveCommon/common_helpers.cmake") diff --git a/Tests/RunCMake/CPack/TXZ/Helpers.cmake b/Tests/RunCMake/CPack/TXZ/Helpers.cmake new file mode 100644 index 0000000..f390cb4 --- /dev/null +++ b/Tests/RunCMake/CPack/TXZ/Helpers.cmake @@ -0,0 +1,3 @@ +set(cpack_archive_extension_ "tar.xz") + +include("${CMAKE_CURRENT_LIST_DIR}/../ArchiveCommon/common_helpers.cmake") diff --git a/Tests/RunCMake/CPack/TXZ/Prerequirements.cmake b/Tests/RunCMake/CPack/TXZ/Prerequirements.cmake new file mode 100644 index 0000000..dbaf682 --- /dev/null +++ b/Tests/RunCMake/CPack/TXZ/Prerequirements.cmake @@ -0,0 +1,4 @@ +function(get_test_prerequirements found_var config_file) + file(WRITE "${config_file}" "") + set(${found_var} true PARENT_SCOPE) +endfunction() diff --git a/Tests/RunCMake/CPack/TXZ/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/TXZ/packaging_COMPONENT_default.cmake new file mode 100644 index 0000000..81a5035 --- /dev/null +++ b/Tests/RunCMake/CPack/TXZ/packaging_COMPONENT_default.cmake @@ -0,0 +1 @@ +set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON") diff --git a/Tests/RunCMake/CPack/TZ/Helpers.cmake b/Tests/RunCMake/CPack/TZ/Helpers.cmake new file mode 100644 index 0000000..117cd24 --- /dev/null +++ b/Tests/RunCMake/CPack/TZ/Helpers.cmake @@ -0,0 +1,3 @@ +set(cpack_archive_extension_ "tar.Z") + +include("${CMAKE_CURRENT_LIST_DIR}/../ArchiveCommon/common_helpers.cmake") diff --git a/Tests/RunCMake/CPack/TZ/Prerequirements.cmake b/Tests/RunCMake/CPack/TZ/Prerequirements.cmake new file mode 100644 index 0000000..dbaf682 --- /dev/null +++ b/Tests/RunCMake/CPack/TZ/Prerequirements.cmake @@ -0,0 +1,4 @@ +function(get_test_prerequirements found_var config_file) + file(WRITE "${config_file}" "") + set(${found_var} true PARENT_SCOPE) +endfunction() diff --git a/Tests/RunCMake/CPack/TZ/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/TZ/packaging_COMPONENT_default.cmake new file mode 100644 index 0000000..81a5035 --- /dev/null +++ b/Tests/RunCMake/CPack/TZ/packaging_COMPONENT_default.cmake @@ -0,0 +1 @@ +set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON") diff --git a/Tests/RunCMake/CPack/ZIP/Helpers.cmake b/Tests/RunCMake/CPack/ZIP/Helpers.cmake new file mode 100644 index 0000000..3710bcf --- /dev/null +++ b/Tests/RunCMake/CPack/ZIP/Helpers.cmake @@ -0,0 +1,3 @@ +set(cpack_archive_extension_ "zip") + +include("${CMAKE_CURRENT_LIST_DIR}/../ArchiveCommon/common_helpers.cmake") diff --git a/Tests/RunCMake/CPack/ZIP/Prerequirements.cmake b/Tests/RunCMake/CPack/ZIP/Prerequirements.cmake new file mode 100644 index 0000000..dbaf682 --- /dev/null +++ b/Tests/RunCMake/CPack/ZIP/Prerequirements.cmake @@ -0,0 +1,4 @@ +function(get_test_prerequirements found_var config_file) + file(WRITE "${config_file}" "") + set(${found_var} true PARENT_SCOPE) +endfunction() diff --git a/Tests/RunCMake/CPack/ZIP/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/ZIP/packaging_COMPONENT_default.cmake new file mode 100644 index 0000000..81a5035 --- /dev/null +++ b/Tests/RunCMake/CPack/ZIP/packaging_COMPONENT_default.cmake @@ -0,0 +1 @@ +set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON") diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake new file mode 100644 index 0000000..694dc00 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake @@ -0,0 +1,9 @@ +set(EXPECTED_FILES_COUNT "1") +set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") + +if(PACKAGING_TYPE STREQUAL "COMPONENT") + set(EXPECTED_FILES_COUNT "2") + set(EXPECTED_FILE_1_COMPONENT "test") + set(EXPECTED_FILE_2_COMPONENT "test2") + set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt") +endif() diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/RPM-COMPONENT-stderr.txt b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/RPM-COMPONENT-stderr.txt new file mode 100644 index 0000000..e6d86d0 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/RPM-COMPONENT-stderr.txt @@ -0,0 +1,2 @@ +^CPackRPM: Will use USER specified spec file: (/[^/]*)*/CUSTOM_BINARY_SPEC_FILE/custom\.spec\.in +CPackRPM: Will use GENERATED spec file:.*/Tests/RunCMake/RPM/CPack/CUSTOM_BINARY_SPEC_FILE-build/_CPack_Packages/.*/RPM/SPECS/custom_binary_spec_file-test2\.spec$ diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/RPM-MONOLITHIC-stderr.txt b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/RPM-MONOLITHIC-stderr.txt new file mode 100644 index 0000000..d7bb7af --- /dev/null +++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/RPM-MONOLITHIC-stderr.txt @@ -0,0 +1 @@ +CPackRPM: Will use USER specified spec file: (/[^/]*)*/CUSTOM_BINARY_SPEC_FILE/custom\.spec\.in diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/custom.spec.in b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/custom.spec.in new file mode 100644 index 0000000..db0ac6f --- /dev/null +++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/custom.spec.in @@ -0,0 +1,80 @@ +# -*- rpm-spec -*- +BuildRoot: %_topdir/@CPACK_PACKAGE_FILE_NAME@@CPACK_RPM_PACKAGE_COMPONENT_PART_PATH@ +Summary: @CPACK_RPM_PACKAGE_SUMMARY@ +Name: @CPACK_RPM_PACKAGE_NAME@ +Version: @CPACK_RPM_PACKAGE_VERSION@ +Release: @CPACK_RPM_PACKAGE_RELEASE@ +License: @CPACK_RPM_PACKAGE_LICENSE@ +Group: @CPACK_RPM_PACKAGE_GROUP@ +Vendor: @CPACK_RPM_PACKAGE_VENDOR@ + +@TMP_RPM_URL@ +@TMP_RPM_REQUIRES@ +@TMP_RPM_REQUIRES_PRE@ +@TMP_RPM_REQUIRES_POST@ +@TMP_RPM_REQUIRES_PREUN@ +@TMP_RPM_REQUIRES_POSTUN@ +@TMP_RPM_PROVIDES@ +@TMP_RPM_OBSOLETES@ +@TMP_RPM_CONFLICTS@ +@TMP_RPM_SUGGESTS@ +@TMP_RPM_AUTOPROV@ +@TMP_RPM_AUTOREQ@ +@TMP_RPM_AUTOREQPROV@ +@TMP_RPM_BUILDARCH@ +@TMP_RPM_PREFIXES@ + +@TMP_RPM_DEBUGINFO@ + +%define _rpmdir %_topdir/RPMS +%define _srcrpmdir %_topdir/SRPMS +@FILE_NAME_DEFINE@ +%define _unpackaged_files_terminate_build 0 +@TMP_RPM_SPEC_INSTALL_POST@ +@CPACK_RPM_SPEC_MORE_DEFINE@ +@CPACK_RPM_COMPRESSION_TYPE_TMP@ + +%description +@CPACK_RPM_PACKAGE_DESCRIPTION@ + +# This is a shortcutted spec file generated by CMake RPM generator +# we skip _install step because CPack does that for us. +# We do only save CPack installed tree in _prepr +# and then restore it in build. +%prep +mv $RPM_BUILD_ROOT %_topdir/tmpBBroot + +%install +if [ -e $RPM_BUILD_ROOT ]; +then + rm -rf $RPM_BUILD_ROOT +fi +mv %_topdir/tmpBBroot $RPM_BUILD_ROOT + +@TMP_RPM_DEBUGINFO_INSTALL@ + +%clean + +%post +@RPM_SYMLINK_POSTINSTALL@ +@CPACK_RPM_SPEC_POSTINSTALL@ + +%postun +@CPACK_RPM_SPEC_POSTUNINSTALL@ + +%pre +@CPACK_RPM_SPEC_PREINSTALL@ + +%preun +@CPACK_RPM_SPEC_PREUNINSTALL@ + +%files +%defattr(@TMP_DEFAULT_FILE_PERMISSIONS@,@TMP_DEFAULT_USER@,@TMP_DEFAULT_GROUP@,@TMP_DEFAULT_DIR_PERMISSIONS@) +@CPACK_RPM_INSTALL_FILES@ +@CPACK_RPM_ABSOLUTE_INSTALL_FILES@ +@CPACK_RPM_USER_INSTALL_FILES@ + +%changelog +@CPACK_RPM_SPEC_CHANGELOG@ + +@TMP_OTHER_COMPONENTS@ diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/test.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/test.cmake new file mode 100644 index 0000000..a604863 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/test.cmake @@ -0,0 +1,9 @@ +install(FILES CMakeLists.txt DESTINATION foo COMPONENT test) + +if(PACKAGING_TYPE STREQUAL "MONOLITHIC") + set(CPACK_RPM_USER_BINARY_SPECFILE "${CMAKE_CURRENT_LIST_DIR}/custom.spec.in") +elseif(PACKAGING_TYPE STREQUAL "COMPONENT") + install(FILES CMakeLists.txt DESTINATION bar COMPONENT test2) + set(CPACK_RPM_TEST_USER_BINARY_SPECFILE + "${CMAKE_CURRENT_LIST_DIR}/custom.spec.in") +endif() diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake new file mode 100644 index 0000000..6142eb3 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake @@ -0,0 +1,2 @@ +set(EXPECTED_FILES_COUNT "1") +set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake new file mode 100644 index 0000000..fbdda9c --- /dev/null +++ b/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake @@ -0,0 +1,3 @@ +set(whitespaces_ "[\t\n\r ]*") +set(md5sums_md5sums "^.* usr/foo/CMakeLists\.txt${whitespaces_}$") +verifyDebControl("${FOUND_FILE_1}" "md5sums" "md5sums") diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake new file mode 100644 index 0000000..15c5892 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake @@ -0,0 +1,5 @@ +install(FILES CMakeLists.txt DESTINATION foo COMPONENT test) + +if(PACKAGING_TYPE STREQUAL "COMPONENT") + set(CPACK_COMPONENTS_ALL test) +endif() diff --git a/Tests/RunCMake/CPack/tests/MINIMAL/test.cmake b/Tests/RunCMake/CPack/tests/MINIMAL/test.cmake index 83ed0f2..15c5892 100644 --- a/Tests/RunCMake/CPack/tests/MINIMAL/test.cmake +++ b/Tests/RunCMake/CPack/tests/MINIMAL/test.cmake @@ -1 +1,5 @@ install(FILES CMakeLists.txt DESTINATION foo COMPONENT test) + +if(PACKAGING_TYPE STREQUAL "COMPONENT") + set(CPACK_COMPONENTS_ALL test) +endif() diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-cmake.cmake b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-cmake.cmake index 4654416..ecb9a64 100644 --- a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-cmake.cmake +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-cmake.cmake @@ -12,4 +12,6 @@ add_test(NAME test1 set_tests_properties(test1 PROPERTIES DEPENDS "initialization") add_test(hello ${CMAKE_COMMAND} -E echo hello) +set_tests_properties(hello PROPERTIES FAIL_REGULAR_EXPRESSION "hello.*hello") + add_test(goodbye ${CMAKE_COMMAND} -E echo goodbye) diff --git a/Tests/RunCMake/VS10Project/VsCustomProps.cmake b/Tests/RunCMake/VS10Project/VsCustomProps.cmake index af52a3e..fbbcfcf 100644 --- a/Tests/RunCMake/VS10Project/VsCustomProps.cmake +++ b/Tests/RunCMake/VS10Project/VsCustomProps.cmake @@ -4,4 +4,4 @@ add_library(foo foo.cpp) set(props_file "${CMAKE_CURRENT_SOURCE_DIR}/my.props") set_target_properties(foo PROPERTIES - VS_USER_PROPS_CXX "${props_file}") + VS_USER_PROPS "${props_file}") diff --git a/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-result.txt b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stderr.txt b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stderr.txt new file mode 100644 index 0000000..327bd5c --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stderr.txt @@ -0,0 +1 @@ +Cannot find memory tester output file: .*/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-build/Testing/Temporary/MemoryChecker.1.log\.\* diff --git a/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stdout.txt new file mode 100644 index 0000000..97a8a9b --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stdout.txt @@ -0,0 +1,3 @@ +Memory checking results: +Direct leak - 2 +Indirect leak - 1 diff --git a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake index 212bfdb..352a381 100644 --- a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake @@ -30,22 +30,22 @@ unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) #----------------------------------------------------------------------------- -# add LeakSanitizer test +# add standalone LeakSanitizer test set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE "add_test(NAME TestSan COMMAND \"${CMAKE_COMMAND}\" -P \"${RunCMake_SOURCE_DIR}/testLeakSanitizer.cmake\") ") -run_mc_test(DummyLeakSanitizer "" -DMEMCHECK_TYPE=AddressSanitizer) +run_mc_test(DummyLeakSanitizer "" -DMEMCHECK_TYPE=LeakSanitizer) unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) #----------------------------------------------------------------------------- # add AddressSanitizer test set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE "add_test(NAME TestSan COMMAND \"\${CMAKE_COMMAND}\" @@ -56,9 +56,22 @@ unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) #----------------------------------------------------------------------------- +# add AddressSanitizer/LeakSanitizer test +set(CTEST_EXTRA_CODE +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") +") +set(CMAKELISTS_EXTRA_CODE +"add_test(NAME TestSan COMMAND \"${CMAKE_COMMAND}\" +-P \"${RunCMake_SOURCE_DIR}/testAddressLeakSanitizer.cmake\") +") +run_mc_test(DummyAddressLeakSanitizer "" -DMEMCHECK_TYPE=AddressSanitizer) +unset(CMAKELISTS_EXTRA_CODE) +unset(CTEST_EXTRA_CODE) + +#----------------------------------------------------------------------------- # add MemorySanitizer test set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE "add_test(NAME TestSan COMMAND \"\${CMAKE_COMMAND}\" @@ -151,13 +164,13 @@ unset(CTEST_SUFFIX_CODE) set(CTEST_SUFFIX_CODE "message(\"Defect count: \${defect_count}\")") set(CTEST_MEMCHECK_ARGS "DEFECT_COUNT defect_count") set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE "add_test(NAME TestSan COMMAND \"${CMAKE_COMMAND}\" -P \"${RunCMake_SOURCE_DIR}/testLeakSanitizer.cmake\") ") -run_mc_test(DummyLeakSanitizerPrintDefects "" -DMEMCHECK_TYPE=AddressSanitizer) +run_mc_test(DummyLeakSanitizerPrintDefects "" -DMEMCHECK_TYPE=LeakSanitizer) unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) unset(CTEST_MEMCHECK_ARGS) diff --git a/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake new file mode 100644 index 0000000..2a57b11 --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake @@ -0,0 +1,47 @@ +# this file simulates a program that has been built with AddressSanitizer +# options + +message("ASAN_OPTIONS = [$ENV{ASAN_OPTIONS}]") +string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{ASAN_OPTIONS}") +message("LOG_FILE=[${LOG_FILE}]") + +# if we are not asked to simulate AddressSanitizer don't do it +if(NOT "$ENV{ASAN_OPTIONS}]" MATCHES "simulate_sanitizer.1") + return() +endif() + +# clear the log files +file(REMOVE "${LOG_FILE}.2343") +file(REMOVE "${LOG_FILE}.2344") + +# create an error of each type of LeakSanitizer + +file(APPEND "${LOG_FILE}.2343" +"================================================================= +==25308==ERROR: LeakSanitizer: detected memory leaks + +Direct leak of 4360 byte(s) in 1 object(s) allocated from: + #0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669) + #1 0x4823b4 in main /home/kitware/msan/memcheck.cxx:12 + #2 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 + +SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s). +") +file(APPEND "${LOG_FILE}.2342" +"================================================================= +==25308==ERROR: LeakSanitizer: detected memory leaks + +Direct leak of 76 byte(s) in 1 object(s) allocated from: + #0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669) + #1 0x4821b8 in foo() /home/kitware/msan/memcheck.cxx:4 + #2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14 + #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 + +Indirect leak of 76 byte(s) in 1 object(s) allocated from: + #0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669) + #1 0x4821b8 in foo() /home/kitware/msan/memcheck.cxx:4 + #2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14 + #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 + +SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s). +") diff --git a/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake index 02030be..af214c8 100644 --- a/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake +++ b/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake @@ -1,20 +1,20 @@ -# this file simulates a program that has been built with thread sanitizer +# this file simulates a program that has been built with LeakSanitizer # options -message("ASAN_OPTIONS = [$ENV{ASAN_OPTIONS}]") -string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{ASAN_OPTIONS}") +message("LSAN_OPTIONS = [$ENV{LSAN_OPTIONS}]") +string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{LSAN_OPTIONS}") message("LOG_FILE=[${LOG_FILE}]") -# if we are not asked to simulate leak sanitizer don't do it -if(NOT "$ENV{ASAN_OPTIONS}]" MATCHES "simulate_sanitizer.1") + +# if we are not asked to simulate LeakSanitizer don't do it +if(NOT "$ENV{LSAN_OPTIONS}]" MATCHES "simulate_sanitizer.1") return() endif() -# clear the log file +# clear the log files file(REMOVE "${LOG_FILE}.2343") file(REMOVE "${LOG_FILE}.2344") -# create an error of each type of thread santizer -# these names come from tsan_report.cc in llvm +# create an error of each type of LeakSanitizer file(APPEND "${LOG_FILE}.2343" "================================================================= @@ -25,7 +25,7 @@ Direct leak of 4360 byte(s) in 1 object(s) allocated from: #1 0x4823b4 in main /home/kitware/msan/memcheck.cxx:12 #2 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 -SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s). +SUMMARY: LeakSanitizer: 4436 byte(s) leaked in 2 allocation(s). ") file(APPEND "${LOG_FILE}.2342" "================================================================= @@ -43,5 +43,5 @@ Indirect leak of 76 byte(s) in 1 object(s) allocated from: #2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14 #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 -SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s). +SUMMARY: LeakSanitizer: 4436 byte(s) leaked in 2 allocation(s). ") diff --git a/Tests/RunCMake/try_compile/CudaStandardNoDefault.cmake b/Tests/RunCMake/try_compile/CudaStandardNoDefault.cmake new file mode 100644 index 0000000..ea22152 --- /dev/null +++ b/Tests/RunCMake/try_compile/CudaStandardNoDefault.cmake @@ -0,0 +1,9 @@ +enable_language(CUDA) +try_compile(result ${CMAKE_CURRENT_BINARY_DIR} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cu + CUDA_STANDARD 3 # bogus, but not used + OUTPUT_VARIABLE out + ) +if(NOT result) + message(FATAL_ERROR "try_compile failed:\n${out}") +endif() diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake index 5452e6d..6a1bc64 100644 --- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake @@ -36,7 +36,11 @@ elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT) run_cmake(CxxStandardNoDefault) endif() if(CMake_TEST_CUDA) - run_cmake(CudaStandard) + if(CMAKE_HOST_WIN32) + run_cmake(CudaStandardNoDefault) + else() + run_cmake(CudaStandard) + endif() endif() if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) run_cmake(CStandardGNU) diff --git a/Tests/SourceGroups/CMakeLists.txt b/Tests/SourceGroups/CMakeLists.txt index 6573c82..9289e84 100644 --- a/Tests/SourceGroups/CMakeLists.txt +++ b/Tests/SourceGroups/CMakeLists.txt @@ -30,6 +30,17 @@ source_group(Base\\Sub1\\Base FILES bar.c) # a group without files, is currently not created source_group(EmptyGroup) +set(root ${CMAKE_CURRENT_SOURCE_DIR}) -add_executable(SourceGroups main.c bar.c foo.c sub1/foo.c sub1/foobar.c baz.c README.txt) +set(tree_files_without_prefix ${root}/sub1/tree_bar.c + ${root}/sub1/tree_baz.c + ${root}/sub1/tree_subdir/tree_foobar.c) +set(tree_files_with_prefix ${root}/tree_foo.c) + +source_group(TREE ${root} FILES ${tree_files_without_prefix}) + +source_group(TREE ${root} PREFIX tree_root/subgroup FILES ${tree_files_with_prefix}) + +add_executable(SourceGroups main.c bar.c foo.c sub1/foo.c sub1/foobar.c baz.c + ${tree_files_with_prefix} ${tree_files_without_prefix} README.txt) diff --git a/Tests/SourceGroups/main.c b/Tests/SourceGroups/main.c index f259f98..b88f2f8 100644 --- a/Tests/SourceGroups/main.c +++ b/Tests/SourceGroups/main.c @@ -5,10 +5,17 @@ extern int bar(void); extern int foobar(void); extern int barbar(void); extern int baz(void); +extern int tree_foo(void); +extern int tree_bar(void); +extern int tree_foobar(void); +extern int tree_baz(void); int main() { printf("foo: %d bar: %d foobar: %d barbar: %d baz: %d\n", foo(), bar(), foobar(), barbar(), baz()); + + printf("tree_foo: %d tree_bar: %d tree_foobar: %d tree_baz: %d\n", + tree_foo(), tree_bar(), tree_foobar(), tree_baz()); return 0; } diff --git a/Tests/SourceGroups/sub1/tree_bar.c b/Tests/SourceGroups/sub1/tree_bar.c new file mode 100644 index 0000000..6b79239 --- /dev/null +++ b/Tests/SourceGroups/sub1/tree_bar.c @@ -0,0 +1,4 @@ +int tree_bar(void) +{ + return 8; +} diff --git a/Tests/SourceGroups/sub1/tree_baz.c b/Tests/SourceGroups/sub1/tree_baz.c new file mode 100644 index 0000000..27ff5ab --- /dev/null +++ b/Tests/SourceGroups/sub1/tree_baz.c @@ -0,0 +1,4 @@ +int tree_baz(void) +{ + return 9; +} diff --git a/Tests/SourceGroups/sub1/tree_subdir/tree_foobar.c b/Tests/SourceGroups/sub1/tree_subdir/tree_foobar.c new file mode 100644 index 0000000..e955e04 --- /dev/null +++ b/Tests/SourceGroups/sub1/tree_subdir/tree_foobar.c @@ -0,0 +1,4 @@ +int tree_foobar(void) +{ + return 7; +} diff --git a/Tests/SourceGroups/tree_foo.c b/Tests/SourceGroups/tree_foo.c new file mode 100644 index 0000000..d392e41 --- /dev/null +++ b/Tests/SourceGroups/tree_foo.c @@ -0,0 +1,4 @@ +int tree_foo(void) +{ + return 6; +} diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index 1b384b5..a8e25ba 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -218,8 +218,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") ) list(APPEND uv_defines __EXTENSIONS__ - _XOPEN_SOURCE=500 ) + if(CMAKE_SYSTEM_VERSION STREQUAL "5.10") + list(APPEND uv_defines + _XOPEN_SOURCE=500 + ) + else() + list(APPEND uv_defines + _XOPEN_SOURCE=600 + ) + endif() list(APPEND uv_sources src/unix/sunos.c ) diff --git a/Utilities/cmvssetup/.gitattributes b/Utilities/cmvssetup/.gitattributes new file mode 100644 index 0000000..562b12e --- /dev/null +++ b/Utilities/cmvssetup/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/Utilities/cmvssetup/Setup.Configuration.h b/Utilities/cmvssetup/Setup.Configuration.h new file mode 100644 index 0000000..6c9d8f9 --- /dev/null +++ b/Utilities/cmvssetup/Setup.Configuration.h @@ -0,0 +1,991 @@ +// <copyright file="Setup.Configuration.h" company="Microsoft Corporation"> +// Copyright (C) Microsoft Corporation. All rights reserved. +// </copyright> + +// This file is licensed under "The MIT License(MIT)". +// This file is released by Visual Studio setup team for consumption by external applications. +// For more information please look at this git repo https://github.com/microsoft/vs-setup-samples + +#ifndef SetupConfiguration_h +#define SetupConfiguration_h + +#include <objbase.h> + +// Constants +// +#ifndef E_NOTFOUND +#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND) +#endif + +#ifndef E_FILENOTFOUND +#define E_FILENOTFOUND HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) +#endif + +#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) + +#ifndef _Outptr_result_maybenull_ +#define _Outptr_result_maybenull_ +#endif +#ifndef _Out_writes_to_ +#define _Out_writes_to_(x,y) +#endif +#ifndef _Reserved_ +#define _Reserved_ +#endif +#ifndef MAXUINT +#define MAXUINT ((UINT)~((UINT)0)) +#endif + +// Enumerations +// +/// <summary> +/// The state of an instance. +/// </summary> +enum InstanceState +{ + /// <summary> + /// The instance state has not been determined. + /// </summary> + eNone = 0, + + /// <summary> + /// The instance installation path exists. + /// </summary> + eLocal = 1, + + /// <summary> + /// A product is registered to the instance. + /// </summary> + eRegistered = 2, + + /// <summary> + /// No reboot is required for the instance. + /// </summary> + eNoRebootRequired = 4, + + /// <summary> + /// The instance represents a complete install. + /// </summary> + eComplete = MAXUINT, +}; + +// Forward interface declarations +// +#ifndef __ISetupInstance_FWD_DEFINED__ +#define __ISetupInstance_FWD_DEFINED__ +typedef struct ISetupInstance ISetupInstance; +#endif + +#ifndef __ISetupInstance2_FWD_DEFINED__ +#define __ISetupInstance2_FWD_DEFINED__ +typedef struct ISetupInstance2 ISetupInstance2; +#endif + +#ifndef __IEnumSetupInstances_FWD_DEFINED__ +#define __IEnumSetupInstances_FWD_DEFINED__ +typedef struct IEnumSetupInstances IEnumSetupInstances; +#endif + +#ifndef __ISetupConfiguration_FWD_DEFINED__ +#define __ISetupConfiguration_FWD_DEFINED__ +typedef struct ISetupConfiguration ISetupConfiguration; +#endif + +#ifndef __ISetupConfiguration2_FWD_DEFINED__ +#define __ISetupConfiguration2_FWD_DEFINED__ +typedef struct ISetupConfiguration2 ISetupConfiguration2; +#endif + +#ifndef __ISetupPackageReference_FWD_DEFINED__ +#define __ISetupPackageReference_FWD_DEFINED__ +typedef struct ISetupPackageReference ISetupPackageReference; +#endif + +#ifndef __ISetupHelper_FWD_DEFINED__ +#define __ISetupHelper_FWD_DEFINED__ +typedef struct ISetupHelper ISetupHelper; +#endif + +// Forward class declarations +// +#ifndef __SetupConfiguration_FWD_DEFINED__ +#define __SetupConfiguration_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class SetupConfiguration SetupConfiguration; +#endif + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// Interface definitions +// +EXTERN_C const IID IID_ISetupInstance; + +#if defined(__cplusplus) && !defined(CINTERFACE) +/// <summary> +/// Information about an instance of a product. +/// </summary> +struct DECLSPEC_UUID("B41463C3-8866-43B5-BC33-2B0676F7F42E") DECLSPEC_NOVTABLE ISetupInstance : public IUnknown +{ + /// <summary> + /// Gets the instance identifier (should match the name of the parent instance directory). + /// </summary> + /// <param name="pbstrInstanceId">The instance identifier.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns> + STDMETHOD(GetInstanceId)( + _Out_ BSTR* pbstrInstanceId + ) = 0; + + /// <summary> + /// Gets the local date and time when the installation was originally installed. + /// </summary> + /// <param name="pInstallDate">The local date and time when the installation was originally installed.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetInstallDate)( + _Out_ LPFILETIME pInstallDate + ) = 0; + + /// <summary> + /// Gets the unique name of the installation, often indicating the branch and other information used for telemetry. + /// </summary> + /// <param name="pbstrInstallationName">The unique name of the installation, often indicating the branch and other information used for telemetry.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetInstallationName)( + _Out_ BSTR* pbstrInstallationName + ) = 0; + + /// <summary> + /// Gets the path to the installation root of the product. + /// </summary> + /// <param name="pbstrInstallationPath">The path to the installation root of the product.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetInstallationPath)( + _Out_ BSTR* pbstrInstallationPath + ) = 0; + + /// <summary> + /// Gets the version of the product installed in this instance. + /// </summary> + /// <param name="pbstrInstallationVersion">The version of the product installed in this instance.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetInstallationVersion)( + _Out_ BSTR* pbstrInstallationVersion + ) = 0; + + /// <summary> + /// Gets the display name (title) of the product installed in this instance. + /// </summary> + /// <param name="lcid">The LCID for the display name.</param> + /// <param name="pbstrDisplayName">The display name (title) of the product installed in this instance.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetDisplayName)( + _In_ LCID lcid, + _Out_ BSTR* pbstrDisplayName + ) = 0; + + /// <summary> + /// Gets the description of the product installed in this instance. + /// </summary> + /// <param name="lcid">The LCID for the description.</param> + /// <param name="pbstrDescription">The description of the product installed in this instance.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetDescription)( + _In_ LCID lcid, + _Out_ BSTR* pbstrDescription + ) = 0; + + /// <summary> + /// Resolves the optional relative path to the root path of the instance. + /// </summary> + /// <param name="pwszRelativePath">A relative path within the instance to resolve, or NULL to get the root path.</param> + /// <param name="pbstrAbsolutePath">The full path to the optional relative path within the instance. If the relative path is NULL, the root path will always terminate in a backslash.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(ResolvePath)( + _In_opt_z_ LPCOLESTR pwszRelativePath, + _Out_ BSTR* pbstrAbsolutePath + ) = 0; +}; +#endif + +EXTERN_C const IID IID_ISetupInstance2; + +#if defined(__cplusplus) && !defined(CINTERFACE) +/// <summary> +/// Information about an instance of a product. +/// </summary> +struct DECLSPEC_UUID("89143C9A-05AF-49B0-B717-72E218A2185C") DECLSPEC_NOVTABLE ISetupInstance2 : public ISetupInstance +{ + /// <summary> + /// Gets the state of the instance. + /// </summary> + /// <param name="pState">The state of the instance.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns> + STDMETHOD(GetState)( + _Out_ InstanceState* pState + ) = 0; + + /// <summary> + /// Gets an array of package references registered to the instance. + /// </summary> + /// <param name="ppsaPackages">Pointer to an array of <see cref="ISetupPackageReference"/>.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the packages property is not defined.</returns> + STDMETHOD(GetPackages)( + _Out_ LPSAFEARRAY* ppsaPackages + ) = 0; + + /// <summary> + /// Gets a pointer to the <see cref="ISetupPackageReference"/> that represents the registered product. + /// </summary> + /// <param name="ppPackage">Pointer to an instance of <see cref="ISetupPackageReference"/>. This may be NULL if <see cref="GetState"/> does not return <see cref="eComplete"/>.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the packages property is not defined.</returns> + STDMETHOD(GetProduct)( + _Outptr_result_maybenull_ ISetupPackageReference** ppPackage + ) = 0; + + /// <summary> + /// Gets the relative path to the product application, if available. + /// </summary> + /// <param name="pbstrProductPath">The relative path to the product application, if available.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns> + STDMETHOD(GetProductPath)( + _Outptr_result_maybenull_ BSTR* pbstrProductPath + ) = 0; +}; +#endif + +EXTERN_C const IID IID_IEnumSetupInstances; + +#if defined(__cplusplus) && !defined(CINTERFACE) +/// <summary> +/// A enumerator of installed <see cref="ISetupInstance"/> objects. +/// </summary> +struct DECLSPEC_UUID("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848") DECLSPEC_NOVTABLE IEnumSetupInstances : public IUnknown +{ + /// <summary> + /// Retrieves the next set of product instances in the enumeration sequence. + /// </summary> + /// <param name="celt">The number of product instances to retrieve.</param> + /// <param name="rgelt">A pointer to an array of <see cref="ISetupInstance"/>.</param> + /// <param name="pceltFetched">A pointer to the number of product instances retrieved. If celt is 1 this parameter may be NULL.</param> + /// <returns>S_OK if the number of elements were fetched, S_FALSE if nothing was fetched (at end of enumeration), E_INVALIDARG if celt is greater than 1 and pceltFetched is NULL, or E_OUTOFMEMORY if an <see cref="ISetupInstance"/> could not be allocated.</returns> + STDMETHOD(Next)( + _In_ ULONG celt, + _Out_writes_to_(celt, *pceltFetched) ISetupInstance** rgelt, + _Out_opt_ _Deref_out_range_(0, celt) ULONG* pceltFetched + ) = 0; + + /// <summary> + /// Skips the next set of product instances in the enumeration sequence. + /// </summary> + /// <param name="celt">The number of product instances to skip.</param> + /// <returns>S_OK if the number of elements could be skipped; otherwise, S_FALSE;</returns> + STDMETHOD(Skip)( + _In_ ULONG celt + ) = 0; + + /// <summary> + /// Resets the enumeration sequence to the beginning. + /// </summary> + /// <returns>Always returns S_OK;</returns> + STDMETHOD(Reset)(void) = 0; + + /// <summary> + /// Creates a new enumeration object in the same state as the current enumeration object: the new object points to the same place in the enumeration sequence. + /// </summary> + /// <param name="ppenum">A pointer to a pointer to a new <see cref="IEnumSetupInstances"/> interface. If the method fails, this parameter is undefined.</param> + /// <returns>S_OK if a clone was returned; otherwise, E_OUTOFMEMORY.</returns> + STDMETHOD(Clone)( + _Deref_out_opt_ IEnumSetupInstances** ppenum + ) = 0; +}; +#endif + +EXTERN_C const IID IID_ISetupConfiguration; + +#if defined(__cplusplus) && !defined(CINTERFACE) +/// <summary> +/// Gets information about product instances set up on the machine. +/// </summary> +struct DECLSPEC_UUID("42843719-DB4C-46C2-8E7C-64F1816EFD5B") DECLSPEC_NOVTABLE ISetupConfiguration : public IUnknown +{ + /// <summary> + /// Enumerates all completed product instances installed. + /// </summary> + /// <param name="ppEnumInstances">An enumeration of completed, installed product instances.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(EnumInstances)( + _Out_ IEnumSetupInstances** ppEnumInstances + ) = 0; + + /// <summary> + /// Gets the instance for the current process path. + /// </summary> + /// <param name="ppInstance">The instance for the current process path.</param> + /// <returns>The instance for the current process path, or E_NOTFOUND if not found.</returns> + STDMETHOD(GetInstanceForCurrentProcess)( + _Out_ ISetupInstance** ppInstance + ) = 0; + + /// <summary> + /// Gets the instance for the given path. + /// </summary> + /// <param name="ppInstance">The instance for the given path.</param> + /// <returns>The instance for the given path, or E_NOTFOUND if not found.</returns> + STDMETHOD(GetInstanceForPath)( + _In_z_ LPCWSTR wzPath, + _Out_ ISetupInstance** ppInstance + ) = 0; +}; +#endif + +EXTERN_C const IID IID_ISetupConfiguration2; + +#if defined(__cplusplus) && !defined(CINTERFACE) +/// <summary> +/// Gets information about product instances. +/// </summary> +struct DECLSPEC_UUID("26AAB78C-4A60-49D6-AF3B-3C35BC93365D") DECLSPEC_NOVTABLE ISetupConfiguration2 : public ISetupConfiguration +{ + /// <summary> + /// Enumerates all product instances. + /// </summary> + /// <param name="ppEnumInstances">An enumeration of all product instances.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(EnumAllInstances)( + _Out_ IEnumSetupInstances** ppEnumInstances + ) = 0; +}; +#endif + +EXTERN_C const IID IID_ISetupPackageReference; + +#if defined(__cplusplus) && !defined(CINTERFACE) +/// <summary> +/// A reference to a package. +/// </summary> +struct DECLSPEC_UUID("da8d8a16-b2b6-4487-a2f1-594ccccd6bf5") DECLSPEC_NOVTABLE ISetupPackageReference : public IUnknown +{ + /// <summary> + /// Gets the general package identifier. + /// </summary> + /// <param name="pbstrId">The general package identifier.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetId)( + _Out_ BSTR* pbstrId + ) = 0; + + /// <summary> + /// Gets the version of the package. + /// </summary> + /// <param name="pbstrVersion">The version of the package.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetVersion)( + _Out_ BSTR* pbstrVersion + ) = 0; + + /// <summary> + /// Gets the target process architecture of the package. + /// </summary> + /// <param name="pbstrChip">The target process architecture of the package.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetChip)( + _Out_ BSTR* pbstrChip + ) = 0; + + /// <summary> + /// Gets the language and optional region identifier. + /// </summary> + /// <param name="pbstrLanguage">The language and optional region identifier.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetLanguage)( + _Out_ BSTR* pbstrLanguage + ) = 0; + + /// <summary> + /// Gets the build branch of the package. + /// </summary> + /// <param name="pbstrBranch">The build branch of the package.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetBranch)( + _Out_ BSTR* pbstrBranch + ) = 0; + + /// <summary> + /// Gets the type of the package. + /// </summary> + /// <param name="pbstrType">The type of the package.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetType)( + _Out_ BSTR* pbstrType + ) = 0; + + /// <summary> + /// Gets the unique identifier consisting of all defined tokens. + /// </summary> + /// <param name="pbstrUniqueId">The unique identifier consisting of all defined tokens.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_UNEXPECTED if no Id was defined (required).</returns> + STDMETHOD(GetUniqueId)( + _Out_ BSTR* pbstrUniqueId + ) = 0; +}; +#endif + +EXTERN_C const IID IID_ISetupHelper; + +#if defined(__cplusplus) && !defined(CINTERFACE) +/// <summary> +/// Helper functions. +/// </summary> +/// <remarks> +/// You can query for this interface from the <see cref="SetupConfiguration"/> class. +/// </remarks> +struct DECLSPEC_UUID("42b21b78-6192-463e-87bf-d577838f1d5c") DECLSPEC_NOVTABLE ISetupHelper : public IUnknown +{ + /// <summary> + /// Parses a dotted quad version string into a 64-bit unsigned integer. + /// </summary> + /// <param name="pwszVersion">The dotted quad version string to parse, e.g. 1.2.3.4.</param> + /// <param name="pullVersion">A 64-bit unsigned integer representing the version. You can compare this to other versions.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(ParseVersion)( + _In_ LPCOLESTR pwszVersion, + _Out_ PULONGLONG pullVersion + ) = 0; + + /// <summary> + /// Parses a dotted quad version string into a 64-bit unsigned integer. + /// </summary> + /// <param name="pwszVersionRange">The string containing 1 or 2 dotted quad version strings to parse, e.g. [1.0,) that means 1.0.0.0 or newer.</param> + /// <param name="pullMinVersion">A 64-bit unsigned integer representing the minimum version, which may be 0. You can compare this to other versions.</param> + /// <param name="pullMaxVersion">A 64-bit unsigned integer representing the maximum version, which may be MAXULONGLONG. You can compare this to other versions.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(ParseVersionRange)( + _In_ LPCOLESTR pwszVersionRange, + _Out_ PULONGLONG pullMinVersion, + _Out_ PULONGLONG pullMaxVersion + ) = 0; +}; +#endif + +// Class declarations +// +EXTERN_C const CLSID CLSID_SetupConfiguration; + +#ifdef __cplusplus +/// <summary> +/// This class implements <see cref="ISetupConfiguration"/>, <see cref="ISetupConfiguration2"/>, and <see cref="ISetupHelper"/>. +/// </summary> +class DECLSPEC_UUID("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D") SetupConfiguration; +#endif + +// Function declarations +// +/// <summary> +/// Gets an <see cref="ISetupConfiguration"/> that provides information about product instances installed on the machine. +/// </summary> +/// <param name="ppConfiguration">The <see cref="ISetupConfiguration"/> that provides information about product instances installed on the machine.</param> +/// <param name="pReserved">Reserved for future use.</param> +/// <returns>Standard HRESULT indicating success or failure.</returns> +STDMETHODIMP GetSetupConfiguration( + _Out_ ISetupConfiguration** ppConfiguration, + _Reserved_ LPVOID pReserved +); + +#ifdef __cplusplus +} +#endif + +#else + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#define VS_SETUP_GCC_DIAGNOSTIC_PUSHED +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + +#ifndef MAXUINT +#define MAXUINT ((UINT)~((UINT)0)) +#endif + +#ifndef DECLSPEC_NOVTABLE +#if (_MSC_VER >= 1100) && defined(__cplusplus) +#define DECLSPEC_NOVTABLE __declspec(novtable) +#else +#define DECLSPEC_NOVTABLE +#endif +#endif + +// Enumerations +// +/// <summary> +/// The state of an instance. +/// </summary> +enum InstanceState +{ + /// <summary> + /// The instance state has not been determined. + /// </summary> + eNone = 0, + + /// <summary> + /// The instance installation path exists. + /// </summary> + eLocal = 1, + + /// <summary> + /// A product is registered to the instance. + /// </summary> + eRegistered = 2, + + /// <summary> + /// No reboot is required for the instance. + /// </summary> + eNoRebootRequired = 4, + + /// <summary> + /// The instance represents a complete install. + /// </summary> + eComplete = MAXUINT, +}; + +// Forward interface declarations +// +#ifndef __ISetupInstance_FWD_DEFINED__ +#define __ISetupInstance_FWD_DEFINED__ +typedef struct ISetupInstance ISetupInstance; +#endif + +#ifndef __ISetupInstance2_FWD_DEFINED__ +#define __ISetupInstance2_FWD_DEFINED__ +typedef struct ISetupInstance2 ISetupInstance2; +#endif + +#ifndef __IEnumSetupInstances_FWD_DEFINED__ +#define __IEnumSetupInstances_FWD_DEFINED__ +typedef struct IEnumSetupInstances IEnumSetupInstances; +#endif + +#ifndef __ISetupConfiguration_FWD_DEFINED__ +#define __ISetupConfiguration_FWD_DEFINED__ +typedef struct ISetupConfiguration ISetupConfiguration; +#endif + +#ifndef __ISetupConfiguration2_FWD_DEFINED__ +#define __ISetupConfiguration2_FWD_DEFINED__ +typedef struct ISetupConfiguration2 ISetupConfiguration2; +#endif + +#ifndef __ISetupPackageReference_FWD_DEFINED__ +#define __ISetupPackageReference_FWD_DEFINED__ +typedef struct ISetupPackageReference ISetupPackageReference; +#endif + +#ifndef __ISetupHelper_FWD_DEFINED__ +#define __ISetupHelper_FWD_DEFINED__ +typedef struct ISetupHelper ISetupHelper; +#endif + +// Forward class declarations +// +#ifndef __SetupConfiguration_FWD_DEFINED__ +#define __SetupConfiguration_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class SetupConfiguration SetupConfiguration; +#endif + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + // Interface definitions + // + EXTERN_C const IID IID_ISetupInstance; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// <summary> + /// Information about an instance of a product. + /// </summary> + struct DECLSPEC_UUID("B41463C3-8866-43B5-BC33-2B0676F7F42E") DECLSPEC_NOVTABLE ISetupInstance : public IUnknown + { + /// <summary> + /// Gets the instance identifier (should match the name of the parent instance directory). + /// </summary> + /// <param name="pbstrInstanceId">The instance identifier.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns> + STDMETHOD(GetInstanceId)( + BSTR* pbstrInstanceId + ) = 0; + + /// <summary> + /// Gets the local date and time when the installation was originally installed. + /// </summary> + /// <param name="pInstallDate">The local date and time when the installation was originally installed.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetInstallDate)( + LPFILETIME pInstallDate + ) = 0; + + /// <summary> + /// Gets the unique name of the installation, often indicating the branch and other information used for telemetry. + /// </summary> + /// <param name="pbstrInstallationName">The unique name of the installation, often indicating the branch and other information used for telemetry.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetInstallationName)( + BSTR* pbstrInstallationName + ) = 0; + + /// <summary> + /// Gets the path to the installation root of the product. + /// </summary> + /// <param name="pbstrInstallationPath">The path to the installation root of the product.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetInstallationPath)( + BSTR* pbstrInstallationPath + ) = 0; + + /// <summary> + /// Gets the version of the product installed in this instance. + /// </summary> + /// <param name="pbstrInstallationVersion">The version of the product installed in this instance.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetInstallationVersion)( + BSTR* pbstrInstallationVersion + ) = 0; + + /// <summary> + /// Gets the display name (title) of the product installed in this instance. + /// </summary> + /// <param name="lcid">The LCID for the display name.</param> + /// <param name="pbstrDisplayName">The display name (title) of the product installed in this instance.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetDisplayName)( + LCID lcid, + BSTR* pbstrDisplayName + ) = 0; + + /// <summary> + /// Gets the description of the product installed in this instance. + /// </summary> + /// <param name="lcid">The LCID for the description.</param> + /// <param name="pbstrDescription">The description of the product installed in this instance.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(GetDescription)( + LCID lcid, + BSTR* pbstrDescription + ) = 0; + + /// <summary> + /// Resolves the optional relative path to the root path of the instance. + /// </summary> + /// <param name="pwszRelativePath">A relative path within the instance to resolve, or NULL to get the root path.</param> + /// <param name="pbstrAbsolutePath">The full path to the optional relative path within the instance. If the relative path is NULL, the root path will always terminate in a backslash.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns> + STDMETHOD(ResolvePath)( + LPCOLESTR pwszRelativePath, + BSTR* pbstrAbsolutePath + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupInstance2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// <summary> + /// Information about an instance of a product. + /// </summary> + struct DECLSPEC_UUID("89143C9A-05AF-49B0-B717-72E218A2185C") DECLSPEC_NOVTABLE ISetupInstance2 : public ISetupInstance + { + /// <summary> + /// Gets the state of the instance. + /// </summary> + /// <param name="pState">The state of the instance.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns> + STDMETHOD(GetState)( + InstanceState* pState + ) = 0; + + /// <summary> + /// Gets an array of package references registered to the instance. + /// </summary> + /// <param name="ppsaPackages">Pointer to an array of <see cref="ISetupPackageReference"/>.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the packages property is not defined.</returns> + STDMETHOD(GetPackages)( + LPSAFEARRAY* ppsaPackages + ) = 0; + + /// <summary> + /// Gets a pointer to the <see cref="ISetupPackageReference"/> that represents the registered product. + /// </summary> + /// <param name="ppPackage">Pointer to an instance of <see cref="ISetupPackageReference"/>. This may be NULL if <see cref="GetState"/> does not return <see cref="eComplete"/>.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the packages property is not defined.</returns> + STDMETHOD(GetProduct)( + ISetupPackageReference** ppPackage + ) = 0; + + /// <summary> + /// Gets the relative path to the product application, if available. + /// </summary> + /// <param name="pbstrProductPath">The relative path to the product application, if available.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns> + STDMETHOD(GetProductPath)( + BSTR* pbstrProductPath + ) = 0; + }; +#endif + + EXTERN_C const IID IID_IEnumSetupInstances; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// <summary> + /// A enumerator of installed <see cref="ISetupInstance"/> objects. + /// </summary> + struct DECLSPEC_UUID("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848") DECLSPEC_NOVTABLE IEnumSetupInstances : public IUnknown + { + /// <summary> + /// Retrieves the next set of product instances in the enumeration sequence. + /// </summary> + /// <param name="celt">The number of product instances to retrieve.</param> + /// <param name="rgelt">A pointer to an array of <see cref="ISetupInstance"/>.</param> + /// <param name="pceltFetched">A pointer to the number of product instances retrieved. If celt is 1 this parameter may be NULL.</param> + /// <returns>S_OK if the number of elements were fetched, S_FALSE if nothing was fetched (at end of enumeration), E_INVALIDARG if celt is greater than 1 and pceltFetched is NULL, or E_OUTOFMEMORY if an <see cref="ISetupInstance"/> could not be allocated.</returns> + STDMETHOD(Next)( + ULONG celt, + ISetupInstance** rgelt, + ULONG* pceltFetched + ) = 0; + + /// <summary> + /// Skips the next set of product instances in the enumeration sequence. + /// </summary> + /// <param name="celt">The number of product instances to skip.</param> + /// <returns>S_OK if the number of elements could be skipped; otherwise, S_FALSE;</returns> + STDMETHOD(Skip)( + ULONG celt + ) = 0; + + /// <summary> + /// Resets the enumeration sequence to the beginning. + /// </summary> + /// <returns>Always returns S_OK;</returns> + STDMETHOD(Reset)(void) = 0; + + /// <summary> + /// Creates a new enumeration object in the same state as the current enumeration object: the new object points to the same place in the enumeration sequence. + /// </summary> + /// <param name="ppenum">A pointer to a pointer to a new <see cref="IEnumSetupInstances"/> interface. If the method fails, this parameter is undefined.</param> + /// <returns>S_OK if a clone was returned; otherwise, E_OUTOFMEMORY.</returns> + STDMETHOD(Clone)( + IEnumSetupInstances** ppenum + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupConfiguration; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// <summary> + /// Gets information about product instances set up on the machine. + /// </summary> + struct DECLSPEC_UUID("42843719-DB4C-46C2-8E7C-64F1816EFD5B") DECLSPEC_NOVTABLE ISetupConfiguration : public IUnknown + { + /// <summary> + /// Enumerates all completed product instances installed. + /// </summary> + /// <param name="ppEnumInstances">An enumeration of completed, installed product instances.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(EnumInstances)( + IEnumSetupInstances** ppEnumInstances + ) = 0; + + /// <summary> + /// Gets the instance for the current process path. + /// </summary> + /// <param name="ppInstance">The instance for the current process path.</param> + /// <returns>The instance for the current process path, or E_NOTFOUND if not found.</returns> + STDMETHOD(GetInstanceForCurrentProcess)( + ISetupInstance** ppInstance + ) = 0; + + /// <summary> + /// Gets the instance for the given path. + /// </summary> + /// <param name="ppInstance">The instance for the given path.</param> + /// <returns>The instance for the given path, or E_NOTFOUND if not found.</returns> + STDMETHOD(GetInstanceForPath)( + LPCWSTR wzPath, + ISetupInstance** ppInstance + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupConfiguration2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// <summary> + /// Gets information about product instances. + /// </summary> + struct DECLSPEC_UUID("26AAB78C-4A60-49D6-AF3B-3C35BC93365D") DECLSPEC_NOVTABLE ISetupConfiguration2 : public ISetupConfiguration + { + /// <summary> + /// Enumerates all product instances. + /// </summary> + /// <param name="ppEnumInstances">An enumeration of all product instances.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(EnumAllInstances)( + IEnumSetupInstances** ppEnumInstances + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupPackageReference; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// <summary> + /// A reference to a package. + /// </summary> + struct DECLSPEC_UUID("da8d8a16-b2b6-4487-a2f1-594ccccd6bf5") DECLSPEC_NOVTABLE ISetupPackageReference : public IUnknown + { + /// <summary> + /// Gets the general package identifier. + /// </summary> + /// <param name="pbstrId">The general package identifier.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetId)( + BSTR* pbstrId + ) = 0; + + /// <summary> + /// Gets the version of the package. + /// </summary> + /// <param name="pbstrVersion">The version of the package.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetVersion)( + BSTR* pbstrVersion + ) = 0; + + /// <summary> + /// Gets the target process architecture of the package. + /// </summary> + /// <param name="pbstrChip">The target process architecture of the package.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetChip)( + BSTR* pbstrChip + ) = 0; + + /// <summary> + /// Gets the language and optional region identifier. + /// </summary> + /// <param name="pbstrLanguage">The language and optional region identifier.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetLanguage)( + BSTR* pbstrLanguage + ) = 0; + + /// <summary> + /// Gets the build branch of the package. + /// </summary> + /// <param name="pbstrBranch">The build branch of the package.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetBranch)( + BSTR* pbstrBranch + ) = 0; + + /// <summary> + /// Gets the type of the package. + /// </summary> + /// <param name="pbstrType">The type of the package.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(GetType)( + BSTR* pbstrType + ) = 0; + + /// <summary> + /// Gets the unique identifier consisting of all defined tokens. + /// </summary> + /// <param name="pbstrUniqueId">The unique identifier consisting of all defined tokens.</param> + /// <returns>Standard HRESULT indicating success or failure, including E_UNEXPECTED if no Id was defined (required).</returns> + STDMETHOD(GetUniqueId)( + BSTR* pbstrUniqueId + ) = 0; + }; +#endif + + EXTERN_C const IID IID_ISetupHelper; + +#if defined(__cplusplus) && !defined(CINTERFACE) + /// <summary> + /// Helper functions. + /// </summary> + /// <remarks> + /// You can query for this interface from the <see cref="SetupConfiguration"/> class. + /// </remarks> + struct DECLSPEC_UUID("42b21b78-6192-463e-87bf-d577838f1d5c") DECLSPEC_NOVTABLE ISetupHelper : public IUnknown + { + /// <summary> + /// Parses a dotted quad version string into a 64-bit unsigned integer. + /// </summary> + /// <param name="pwszVersion">The dotted quad version string to parse, e.g. 1.2.3.4.</param> + /// <param name="pullVersion">A 64-bit unsigned integer representing the version. You can compare this to other versions.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(ParseVersion)( + LPCOLESTR pwszVersion, + PULONGLONG pullVersion + ) = 0; + + /// <summary> + /// Parses a dotted quad version string into a 64-bit unsigned integer. + /// </summary> + /// <param name="pwszVersionRange">The string containing 1 or 2 dotted quad version strings to parse, e.g. [1.0,) that means 1.0.0.0 or newer.</param> + /// <param name="pullMinVersion">A 64-bit unsigned integer representing the minimum version, which may be 0. You can compare this to other versions.</param> + /// <param name="pullMaxVersion">A 64-bit unsigned integer representing the maximum version, which may be MAXULONGLONG. You can compare this to other versions.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHOD(ParseVersionRange)( + LPCOLESTR pwszVersionRange, + PULONGLONG pullMinVersion, + PULONGLONG pullMaxVersion + ) = 0; + }; +#endif + + // Class declarations + // + EXTERN_C const CLSID CLSID_SetupConfiguration; + +#ifdef __cplusplus + /// <summary> + /// This class implements <see cref="ISetupConfiguration"/>, <see cref="ISetupConfiguration2"/>, and <see cref="ISetupHelper"/>. + /// </summary> + class DECLSPEC_UUID("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D") SetupConfiguration; +#endif + + // Function declarations + // + /// <summary> + /// Gets an <see cref="ISetupConfiguration"/> that provides information about product instances installed on the machine. + /// </summary> + /// <param name="ppConfiguration">The <see cref="ISetupConfiguration"/> that provides information about product instances installed on the machine.</param> + /// <param name="pReserved">Reserved for future use.</param> + /// <returns>Standard HRESULT indicating success or failure.</returns> + STDMETHODIMP GetSetupConfiguration( + ISetupConfiguration** ppConfiguration, + LPVOID pReserved + ); + +#ifdef __cplusplus +} +#endif + +#ifdef VS_SETUP_GCC_DIAGNOSTIC_PUSHED +#pragma GCC diagnostic pop +#undef VS_SETUP_GCC_DIAGNOSTIC_PUSHED +#endif + +#endif +#endif |