diff options
75 files changed, 1443 insertions, 584 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/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 4ab4298..80e7edf 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -21,7 +21,8 @@ The first signature is for adding a custom command to produce an output:: [WORKING_DIRECTORY dir] [COMMENT comment] [DEPFILE depfile] - [VERBATIM] [APPEND] [USES_TERMINAL]) + [VERBATIM] [APPEND] [USES_TERMINAL] + [COMMAND_EXPAND_LISTS]) This defines a command to generate specified ``OUTPUT`` file(s). A target created in the same directory (``CMakeLists.txt`` file) @@ -122,6 +123,14 @@ The options are: Arguments to ``DEPENDS`` may use :manual:`generator expressions <cmake-generator-expressions(7)>`. +``COMMAND_EXPAND_LISTS`` + Lists in ``COMMAND`` arguments will be expanded, including those + created with + :manual:`generator expressions <cmake-generator-expressions(7)>`, + allowing ``COMMAND`` arguments such as + ``${CC} "-I$<JOIN:$<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>,;-I>" foo.cc`` + to be properly expanded. + ``IMPLICIT_DEPENDS`` Request scanning of implicit dependencies of an input file. The language given specifies the programming language whose diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst index 6980d61..bd61c8b 100644 --- a/Help/command/add_custom_target.rst +++ b/Help/command/add_custom_target.rst @@ -12,6 +12,7 @@ Add a target with no output so it will always be built. [WORKING_DIRECTORY dir] [COMMENT comment] [VERBATIM] [USES_TERMINAL] + [COMMAND_EXPAND_LISTS] [SOURCES src1 [src2...]]) Adds a target with the given name that executes the given commands. @@ -88,6 +89,14 @@ The options are: Use the :command:`add_dependencies` command to add dependencies on other targets. +``COMMAND_EXPAND_LISTS`` + Lists in ``COMMAND`` arguments will be expanded, including those + created with + :manual:`generator expressions <cmake-generator-expressions(7)>`, + allowing ``COMMAND`` arguments such as + ``${CC} "-I$<JOIN:$<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>,;-I>" foo.cc`` + to be properly expanded. + ``SOURCES`` Specify additional source files to be included in the custom target. Specified source files will be added to IDE project files for 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/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index c93ace1..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 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/expand_custom_commands.rst b/Help/release/dev/expand_custom_commands.rst new file mode 100644 index 0000000..c8cd897 --- /dev/null +++ b/Help/release/dev/expand_custom_commands.rst @@ -0,0 +1,7 @@ +expand_custom_commands +---------------------- + +* The commands :command:`add_custom_command` and :command:`add_custom_target` + learned the option ``COMMAND_EXPAND_LISTS`` which causes lists in the + ``COMMAND`` argument to be expanded, including lists created by generator + expressions. 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/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in index 1ba42d9..7e8efa7 100644 --- a/Modules/CMakeCUDACompiler.cmake.in +++ b/Modules/CMakeCUDACompiler.cmake.in @@ -13,6 +13,8 @@ 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/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index abc4b66..13b1789 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -187,7 +187,7 @@ if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY) endif() if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE) 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>") + "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") endif() mark_as_advanced( 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/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/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index 80ecfbc..809ee06 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -33,7 +33,7 @@ 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> <CMAKE_CUDA_LINK_FLAGS> -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<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") 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/CMakeLists.txt b/Source/CMakeLists.txt index 57b7b25..2835ee6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -787,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 5ac4cf1..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 20170113) +set(CMake_VERSION_PATCH 20170117) #set(CMake_VERSION_RC 1) 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/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/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 620de31..a100617 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -36,6 +36,7 @@ bool cmAddCustomCommandCommand::InitialPass( bool verbatim = false; bool append = false; bool uses_terminal = false; + bool command_expand_lists = false; std::string implicit_depends_lang; cmCustomCommand::ImplicitDependsList implicit_depends; @@ -92,6 +93,8 @@ bool cmAddCustomCommandCommand::InitialPass( append = true; } else if (copy == "USES_TERMINAL") { uses_terminal = true; + } else if (copy == "COMMAND_EXPAND_LISTS") { + command_expand_lists = true; } else if (copy == "TARGET") { doing = doing_target; } else if (copy == "ARGS") { @@ -281,12 +284,14 @@ bool cmAddCustomCommandCommand::InitialPass( std::vector<std::string> no_depends; this->Makefile->AddCustomCommandToTarget( target, byproducts, no_depends, commandLines, cctype, comment, - working.c_str(), escapeOldStyle, uses_terminal, depfile); + working.c_str(), escapeOldStyle, uses_terminal, depfile, + command_expand_lists); } else if (target.empty()) { // Target is empty, use the output. this->Makefile->AddCustomCommandToOutput( output, byproducts, depends, main_dependency, commandLines, comment, - working.c_str(), false, escapeOldStyle, uses_terminal, depfile); + working.c_str(), false, escapeOldStyle, uses_terminal, + command_expand_lists, depfile); // Add implicit dependency scanning requests if any were given. if (!implicit_depends.empty()) { diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index 56f33b4..0d01493 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -47,6 +47,7 @@ bool cmAddCustomTargetCommand::InitialPass( std::string working_directory; bool verbatim = false; bool uses_terminal = false; + bool command_expand_lists = false; std::string comment_buffer; const char* comment = CM_NULLPTR; std::vector<std::string> sources; @@ -90,6 +91,9 @@ bool cmAddCustomTargetCommand::InitialPass( } else if (copy == "USES_TERMINAL") { doing = doing_nothing; uses_terminal = true; + } else if (copy == "COMMAND_EXPAND_LISTS") { + doing = doing_nothing; + command_expand_lists = true; } else if (copy == "COMMENT") { doing = doing_comment; } else if (copy == "COMMAND") { @@ -221,12 +225,19 @@ bool cmAddCustomTargetCommand::InitialPass( "USES_TERMINAL may not be specified without any COMMAND"); return true; } + if (commandLines.empty() && command_expand_lists) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "COMMAND_EXPAND_LISTS may not be specified without any COMMAND"); + return true; + } // Add the utility target to the makefile. bool escapeOldStyle = !verbatim; cmTarget* target = this->Makefile->AddUtilityCommand( targetName, excludeFromAll, working_directory.c_str(), byproducts, depends, - commandLines, escapeOldStyle, comment, uses_terminal); + commandLines, escapeOldStyle, comment, uses_terminal, + command_expand_lists); // Add additional user-specified source files to the target. target->AddSources(sources); 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/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx index 6645b8e..050de17 100644 --- a/Source/cmCustomCommand.cxx +++ b/Source/cmCustomCommand.cxx @@ -13,6 +13,7 @@ cmCustomCommand::cmCustomCommand() this->EscapeOldStyle = true; this->EscapeAllowMakeVars = false; this->UsesTerminal = false; + this->CommandExpandLists = false; } cmCustomCommand::cmCustomCommand(cmMakefile const* mf, @@ -32,6 +33,7 @@ cmCustomCommand::cmCustomCommand(cmMakefile const* mf, , HaveComment(comment != CM_NULLPTR) , EscapeAllowMakeVars(false) , EscapeOldStyle(true) + , CommandExpandLists(false) { if (mf) { this->Backtrace = mf->GetBacktrace(); @@ -127,6 +129,16 @@ void cmCustomCommand::SetUsesTerminal(bool b) this->UsesTerminal = b; } +bool cmCustomCommand::GetCommandExpandLists() const +{ + return this->CommandExpandLists; +} + +void cmCustomCommand::SetCommandExpandLists(bool b) +{ + this->CommandExpandLists = b; +} + const std::string& cmCustomCommand::GetDepfile() const { return this->Depfile; diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index 66f8fa9..73d53ff 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -85,6 +85,10 @@ public: bool GetUsesTerminal() const; void SetUsesTerminal(bool b); + /** Set/Get whether lists in command lines should be expanded. */ + bool GetCommandExpandLists() const; + void SetCommandExpandLists(bool b); + /** Set/Get the depfile (used by the Ninja generator) */ const std::string& GetDepfile() const; void SetDepfile(const std::string& depfile); @@ -103,6 +107,7 @@ private: bool EscapeAllowMakeVars; bool EscapeOldStyle; bool UsesTerminal; + bool CommandExpandLists; }; #endif diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 8bd3a89..8f4ff4b 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -26,6 +26,24 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, , GE(new cmGeneratorExpression(cc.GetBacktrace())) , DependsDone(false) { + const cmCustomCommandLines& cmdlines = this->CC.GetCommandLines(); + for (cmCustomCommandLines::const_iterator cmdline = cmdlines.begin(); + cmdline != cmdlines.end(); ++cmdline) { + cmCustomCommandLine argv; + for (cmCustomCommandLine::const_iterator clarg = cmdline->begin(); + clarg != cmdline->end(); ++clarg) { + CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = this->GE->Parse(*clarg); + std::string parsed_arg = cge->Evaluate(this->LG, this->Config); + if (this->CC.GetCommandExpandLists()) { + std::vector<std::string> ExpandedArg; + cmSystemTools::ExpandListArgument(parsed_arg, ExpandedArg); + argv.insert(argv.end(), ExpandedArg.begin(), ExpandedArg.end()); + } else { + argv.push_back(parsed_arg); + } + } + this->CommandLines.push_back(argv); + } } cmCustomCommandGenerator::~cmCustomCommandGenerator() @@ -44,7 +62,7 @@ const char* cmCustomCommandGenerator::GetCrossCompilingEmulator( if (!this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING")) { return CM_NULLPTR; } - std::string const& argv0 = this->CC.GetCommandLines()[c][0]; + std::string const& argv0 = this->CommandLines[c][0]; cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0); if (target && target->GetType() == cmStateEnums::EXECUTABLE && !target->IsImported()) { @@ -55,7 +73,7 @@ const char* cmCustomCommandGenerator::GetCrossCompilingEmulator( const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const { - std::string const& argv0 = this->CC.GetCommandLines()[c][0]; + std::string const& argv0 = this->CommandLines[c][0]; cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0); if (target && target->GetType() == cmStateEnums::EXECUTABLE && (target->IsImported() || @@ -75,11 +93,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const return std::string(location); } - std::string const& argv0 = this->CC.GetCommandLines()[c][0]; - CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = this->GE->Parse(argv0); - std::string exe = cge->Evaluate(this->LG, this->Config); - - return exe; + return this->CommandLines[c][0]; } std::string escapeForShellOldStyle(const std::string& str) @@ -114,7 +128,7 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, if (this->GetCrossCompilingEmulator(c) != CM_NULLPTR) { offset = 0; } - cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c]; + cmCustomCommandLine const& commandLine = this->CommandLines[c]; for (unsigned int j = offset; j < commandLine.size(); ++j) { std::string arg; if (const char* location = @@ -123,7 +137,7 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, // so transform the latter now. arg = location; } else { - arg = this->GE->Parse(commandLine[j])->Evaluate(this->LG, this->Config); + arg = commandLine[j]; } cmd += " "; if (this->OldStyle) { diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 8983c54..286aaf3 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -3,6 +3,7 @@ #ifndef cmCustomCommandGenerator_h #define cmCustomCommandGenerator_h +#include "cmCustomCommandLines.h" #include <cmConfigure.h> // IWYU pragma: keep #include <string> @@ -22,6 +23,7 @@ class cmCustomCommandGenerator cmGeneratorExpression* GE; mutable bool DependsDone; mutable std::vector<std::string> Depends; + cmCustomCommandLines CommandLines; const char* GetCrossCompilingEmulator(unsigned int c) const; const char* GetArgv0Location(unsigned int c) const; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index d10c886..91cecb3 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -788,7 +788,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, this->SetError("LIST_DIRECTORIES missing bool value."); return false; } - ++i; + continue; } if (recurse && (*i == "FOLLOW_SYMLINKS")) { 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/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/cmMakefile.cxx b/Source/cmMakefile.cxx index cfc0495..bfe46ae 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -692,7 +692,7 @@ void cmMakefile::AddCustomCommandToTarget( const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle, - bool uses_terminal, const std::string& depfile) + bool uses_terminal, const std::string& depfile, bool command_expand_lists) { // Find the target to which to add the custom command. cmTargets::iterator ti = this->Targets.find(target); @@ -764,6 +764,7 @@ void cmMakefile::AddCustomCommandToTarget( cc.SetEscapeOldStyle(escapeOldStyle); cc.SetEscapeAllowMakeVars(true); cc.SetUsesTerminal(uses_terminal); + cc.SetCommandExpandLists(command_expand_lists); cc.SetDepfile(depfile); switch (type) { case cmTarget::PRE_BUILD: @@ -784,7 +785,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput( const std::vector<std::string>& depends, const std::string& main_dependency, const cmCustomCommandLines& commandLines, const char* comment, const char* workingDir, bool replace, bool escapeOldStyle, - bool uses_terminal, const std::string& depfile) + bool uses_terminal, bool command_expand_lists, const std::string& depfile) { // Make sure there is at least one output. if (outputs.empty()) { @@ -878,6 +879,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput( cc->SetEscapeOldStyle(escapeOldStyle); cc->SetEscapeAllowMakeVars(true); cc->SetUsesTerminal(uses_terminal); + cc->SetCommandExpandLists(command_expand_lists); cc->SetDepfile(depfile); file->SetCustomCommand(cc); this->UpdateOutputToSourceMap(outputs, file); @@ -916,14 +918,16 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput( const std::string& output, const std::vector<std::string>& depends, const std::string& main_dependency, const cmCustomCommandLines& commandLines, const char* comment, const char* workingDir, bool replace, - bool escapeOldStyle, bool uses_terminal, const std::string& depfile) + bool escapeOldStyle, bool uses_terminal, bool command_expand_lists, + const std::string& depfile) { std::vector<std::string> outputs; outputs.push_back(output); std::vector<std::string> no_byproducts; return this->AddCustomCommandToOutput( outputs, no_byproducts, depends, main_dependency, commandLines, comment, - workingDir, replace, escapeOldStyle, uses_terminal, depfile); + workingDir, replace, escapeOldStyle, uses_terminal, command_expand_lists, + depfile); } void cmMakefile::AddCustomCommandOldStyle( @@ -1018,12 +1022,13 @@ cmTarget* cmMakefile::AddUtilityCommand( const std::string& utilityName, bool excludeFromAll, const char* workingDirectory, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle, - const char* comment, bool uses_terminal) + const char* comment, bool uses_terminal, bool command_expand_lists) { std::vector<std::string> no_byproducts; return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory, no_byproducts, depends, commandLines, - escapeOldStyle, comment, uses_terminal); + escapeOldStyle, comment, uses_terminal, + command_expand_lists); } cmTarget* cmMakefile::AddUtilityCommand( @@ -1031,7 +1036,7 @@ cmTarget* cmMakefile::AddUtilityCommand( const char* workingDirectory, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle, - const char* comment, bool uses_terminal) + const char* comment, bool uses_terminal, bool command_expand_lists) { // Create a target instance for this utility. cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName); @@ -1055,7 +1060,8 @@ cmTarget* cmMakefile::AddUtilityCommand( bool no_replace = false; this->AddCustomCommandToOutput( forced, byproducts, depends, no_main_dependency, commandLines, comment, - workingDirectory, no_replace, escapeOldStyle, uses_terminal); + workingDirectory, no_replace, escapeOldStyle, uses_terminal, + command_expand_lists); cmSourceFile* sf = target->AddSourceCMP0049(force); // The output is not actually created so mark it symbolic. diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 3484e5a..9d9e90a 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -125,7 +125,8 @@ public: const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle = true, - bool uses_terminal = false, const std::string& depfile = ""); + bool uses_terminal = false, const std::string& depfile = "", + bool command_expand_lists = false); cmSourceFile* AddCustomCommandToOutput( const std::vector<std::string>& outputs, const std::vector<std::string>& byproducts, @@ -133,13 +134,15 @@ public: const std::string& main_dependency, const cmCustomCommandLines& commandLines, const char* comment, const char* workingDir, bool replace = false, bool escapeOldStyle = true, - bool uses_terminal = false, const std::string& depfile = ""); + bool uses_terminal = false, bool command_expand_lists = false, + const std::string& depfile = ""); cmSourceFile* AddCustomCommandToOutput( const std::string& output, const std::vector<std::string>& depends, const std::string& main_dependency, const cmCustomCommandLines& commandLines, const char* comment, const char* workingDir, bool replace = false, bool escapeOldStyle = true, - bool uses_terminal = false, const std::string& depfile = ""); + bool uses_terminal = false, bool command_expand_lists = false, + const std::string& depfile = ""); void AddCustomCommandOldStyle(const std::string& target, const std::vector<std::string>& outputs, const std::vector<std::string>& depends, @@ -182,13 +185,15 @@ public: const std::string& utilityName, bool excludeFromAll, const char* workingDirectory, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle = true, - const char* comment = CM_NULLPTR, bool uses_terminal = false); + const char* comment = CM_NULLPTR, bool uses_terminal = false, + bool command_expand_lists = false); cmTarget* AddUtilityCommand( const std::string& utilityName, bool excludeFromAll, const char* workingDirectory, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle = true, - const char* comment = CM_NULLPTR, bool uses_terminal = false); + const char* comment = CM_NULLPTR, bool uses_terminal = false, + bool command_expand_lists = false); /** * Add a subdirectory to the build. diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 4bc706c..b76ddeb 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -157,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; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index bc8d8ff..b172478 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -663,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"]); diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 6d4c302..825eba0 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -674,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", diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index f5c33fe..c84fe4f 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -27,7 +27,39 @@ #include <unistd.h> #endif -static std::string findMatchingHeader( +// -- Static variables + +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; + } + const char* valueConf = makefile->GetDefinition(keyConf); + if (valueConf != CM_NULLPTR) { + return valueConf; + } + return makefile->GetSafeDefinition(key); +} + +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) @@ -53,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; @@ -89,44 +121,60 @@ static std::string ReadAll(const std::string& filename) return stream.str(); } +/** + * @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()); } -cmQtAutoGenerators::cmQtAutoGenerators() - : Verbose(cmsys::SystemTools::HasEnv("VERBOSE")) - , ColorOutput(true) - , RunMocFailed(false) - , RunUicFailed(false) - , RunRccFailed(false) - , GenerateAll(false) +static std::string JoinOptions(const std::map<std::string, std::string>& opts) { - - std::string colorEnv; - cmsys::SystemTools::GetEnv("COLOR", colorEnv); - if (!colorEnv.empty()) { - if (cmSystemTools::IsOn(colorEnv.c_str())) { - this->ColorOutput = true; - } else { - this->ColorOutput = false; + 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; +} - // 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)[\">]"); +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", @@ -158,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) { @@ -177,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( @@ -235,55 +321,30 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // - Moc cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), this->SkipMoc); - { - 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); - } + 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 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(), @@ -295,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(), @@ -317,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()) { @@ -328,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"); @@ -356,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; } @@ -462,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; @@ -493,11 +615,6 @@ void cmQtAutoGenerators::Init() 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 @@ -548,22 +665,70 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) notIncludedMocs, includedUis); // Generate files - if (!this->MocExecutable.empty()) { - if (!this->GenerateMocFiles(includedMocs, notIncludedMocs)) { - return false; + if (!this->MocGenerateAll(includedMocs, notIncludedMocs)) { + return false; + } + if (!this->UicGenerateAll(includedUis)) { + return false; + } + if (!this->QrcGenerateAll()) { + return false; + } + + return true; +} + +/** + * @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; } @@ -597,25 +762,6 @@ bool cmQtAutoGenerators::ParseSourceFile( return success; } -bool cmQtAutoGenerators::requiresMocing(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 (strstr(text.c_str(), "Q_GADGET") != CM_NULLPTR) { - if (this->RegExpQGadget.find(text)) { - macroName = "Q_GADGET"; - return true; - } - } - return false; -} - void cmQtAutoGenerators::ParseContentForUic( const std::string& absFilename, const std::string& contentsString, std::map<std::string, std::vector<std::string> >& includedUis) @@ -665,7 +811,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); std::string macroName; - const bool requiresMoc = this->requiresMocing(contentsString, macroName); + const bool requiresMoc = this->MocRequired(contentsString, macroName); bool ownDotMocIncluded = false; bool ownMocUnderscoreIncluded = false; std::string ownMocUnderscoreFile; @@ -694,8 +840,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( // finding the correct header, so we need to remove the moc_ part basename = basename.substr(4); const std::string mocSubDir = - extractSubDir(scannedFileAbsPath, currentMoc); - const std::string headerToMoc = findMatchingHeader( + ExtractSubDir(scannedFileAbsPath, currentMoc); + const std::string headerToMoc = FindMatchingHeader( scannedFileAbsPath, mocSubDir, basename, headerExtensions); if (!headerToMoc.empty()) { @@ -710,7 +856,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << currentMoc << "\", but could not find header \"" << basename << '{' - << this->JoinExts(headerExtensions) << "}\" "; + << JoinExts(headerExtensions) << "}\" "; if (mocSubDir.empty()) { err << "in " << scannedFileAbsPath << "\n"; } else { @@ -727,8 +873,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Mode: Relaxed if (!requiresMoc || basename != scannedFileBasename) { const std::string mocSubDir = - extractSubDir(scannedFileAbsPath, currentMoc); - const std::string headerToMoc = findMatchingHeader( + ExtractSubDir(scannedFileAbsPath, currentMoc); + const std::string headerToMoc = FindMatchingHeader( scannedFileAbsPath, mocSubDir, basename, headerExtensions); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: @@ -771,7 +917,11 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } else { // Mode: Strict - if (basename != scannedFileBasename) { + 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 << "AutoMoc: Error: " << absFilename << "\n" @@ -782,10 +932,6 @@ bool cmQtAutoGenerators::ParseContentForMoc( << ".moc\" to run moc on this source file.\n"; this->LogError(err.str()); return false; - } else { - // Include self - fileToMoc = absFilename; - ownDotMocIncluded = true; } } if (!fileToMoc.empty()) { @@ -906,7 +1052,7 @@ void cmQtAutoGenerators::ParseHeaders( this->LogInfo(err.str()); } std::string macroName; - if (this->requiresMocing(contents, macroName)) { + if (this->MocRequired(contents, macroName)) { notIncludedMocs[headerName] = fpathCheckSum.getPart(headerName) + "/moc_" + cmsys::SystemTools::GetFilenameWithoutLastExtension(headerName) + @@ -921,10 +1067,14 @@ void cmQtAutoGenerators::ParseHeaders( } } -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; @@ -951,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; } @@ -966,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) { @@ -1045,17 +1195,20 @@ 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); @@ -1104,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; @@ -1152,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; } @@ -1166,18 +1323,20 @@ 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); @@ -1196,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()); @@ -1229,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(); @@ -1278,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; } @@ -1290,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); @@ -1306,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; @@ -1365,67 +1520,6 @@ bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile, 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; -} - -/** - * @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) @@ -1485,6 +1579,36 @@ 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 */ @@ -1502,22 +1626,3 @@ bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) } 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 d0c7066..7891eb9 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -22,32 +22,26 @@ 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); - - 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); + // - Content analysis + bool MocRequired(const std::string& text, std::string& macroName); + bool MocSkipTest(const std::string& absFilename); + bool UicSkipTest(const std::string& absFilename); bool ParseSourceFile( const std::string& absFilename, @@ -55,6 +49,7 @@ private: std::map<std::string, std::string>& includedMocs, std::map<std::string, std::vector<std::string> >& includedUis, bool relaxed); + void SearchHeadersForSourceFile( const std::string& absFilename, const std::vector<std::string>& headerExtensions, @@ -68,8 +63,6 @@ private: std::map<std::string, std::string>& notIncludedMocs, std::map<std::string, std::vector<std::string> >& includedUis); - bool requiresMocing(const std::string& text, std::string& macroName); - void ParseContentForUic( const std::string& fileName, const std::string& contentsString, std::map<std::string, std::vector<std::string> >& includedUis); @@ -80,18 +73,27 @@ private: std::map<std::string, std::string>& includedMocs, bool relaxed); - void ParseForUic( - const std::string& fileName, - std::map<std::string, std::vector<std::string> >& includedUis); - - 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 MocSkipTest(const std::string& absFilename); - bool UicSkipTest(const std::string& absFilename); + // - 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); - bool NameCollisionTest(const std::map<std::string, std::string>& genFiles, - std::multimap<std::string, std::string>& collisions); + // - 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); @@ -101,17 +103,11 @@ private: void LogError(const std::string& message); void LogCommand(const std::vector<std::string>& command); + // - Utility + bool NameCollisionTest(const std::map<std::string, std::string>& genFiles, + std::multimap<std::string, std::string>& collisions); 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); - // - Target names std::string OriginTargetName; std::string AutogenTargetName; @@ -139,17 +135,17 @@ private: std::list<std::string> MocIncludes; std::list<std::string> MocDefinitions; std::vector<std::string> MocOptions; + std::string MocSettingsString; // - Uic 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; @@ -163,7 +159,9 @@ private: bool RunMocFailed; bool RunUicFailed; bool RunRccFailed; - bool GenerateAll; + bool GenerateMocAll; + bool GenerateUicAll; + bool GenerateRccAll; bool MocRelaxedMode; }; 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 index d675a2c..c2ff664 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -73,42 +73,19 @@ cmVSSetupAPIHelper::~cmVSSetupAPIHelper() bool cmVSSetupAPIHelper::IsVS2017Installed() { - bool ret = false; - if (chosenInstanceInfo.VSInstallLocation.compare(L"") == 0) { - ret = EnumerateAndChooseVSInstance(); - } - - return ret; + return this->EnumerateAndChooseVSInstance(); } bool cmVSSetupAPIHelper::IsWin10SDKInstalled() { - bool isWin10SDKInstalled = false; - if (chosenInstanceInfo.VSInstallLocation.compare(L"") == 0) { - if (EnumerateAndChooseVSInstance() && - chosenInstanceInfo.VSInstallLocation.compare(L"") != 0) { - isWin10SDKInstalled = chosenInstanceInfo.IsWin10SDKInstalled; - } - } else { - isWin10SDKInstalled = chosenInstanceInfo.IsWin10SDKInstalled; - } - - return isWin10SDKInstalled; + return (this->EnumerateAndChooseVSInstance() && + chosenInstanceInfo.IsWin10SDKInstalled); } bool cmVSSetupAPIHelper::IsWin81SDKInstalled() { - bool isWin81SDKInstalled = false; - if (chosenInstanceInfo.VSInstallLocation.compare(L"") == 0) { - if (EnumerateAndChooseVSInstance() && - chosenInstanceInfo.VSInstallLocation.compare(L"") != 0) { - isWin81SDKInstalled = chosenInstanceInfo.IsWin81SDKInstalled; - } - } else { - isWin81SDKInstalled = chosenInstanceInfo.IsWin81SDKInstalled; - } - - return isWin81SDKInstalled; + return (this->EnumerateAndChooseVSInstance() && + chosenInstanceInfo.IsWin81SDKInstalled); } bool cmVSSetupAPIHelper::CheckInstalledComponent( @@ -241,18 +218,12 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo( bool cmVSSetupAPIHelper::GetVSInstanceInfo(std::string& vsInstallLocation) { vsInstallLocation = ""; - bool isInstalled = false; + bool isInstalled = this->EnumerateAndChooseVSInstance(); - if (chosenInstanceInfo.VSInstallLocation.compare(L"") == 0) { - isInstalled = EnumerateAndChooseVSInstance(); - } - - // Enumerate and choose best VS instance - if (chosenInstanceInfo.VSInstallLocation.compare(L"") != 0) { + if (isInstalled) { std::string str(chosenInstanceInfo.VSInstallLocation.begin(), chosenInstanceInfo.VSInstallLocation.end()); vsInstallLocation = str; - isInstalled = true; } return isInstalled; 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/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/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/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/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/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt index db57e19..e9a9f52 100644 --- a/Tests/CustomCommand/CMakeLists.txt +++ b/Tests/CustomCommand/CMakeLists.txt @@ -513,3 +513,24 @@ add_custom_target(UseConsoleTarget ALL VERBATIM USES_TERMINAL ) + +# Test COMMAND_EXPAND_LISTS +set(cmp_args "1ARG=COMMAND_EXPAND_LISTS" "2ARG=test" "3ARG=outfile" + "4ARG=content") +set(AARGS "") +foreach(arg IN LISTS cmp_args) + list(APPEND AARGS "-DA${arg}") +endforeach() + +set(gen_file "expand_custom_command.phony") +add_custom_command( + OUTPUT "${gen_file}" + COMMAND ${CMAKE_COMMAND} ${AARGS} + "-DB$<JOIN:$<TARGET_PROPERTY:command_expand_lists,CMPARGS>,;-DB>" + "-P" "${CMAKE_CURRENT_SOURCE_DIR}/compare_options.cmake" + COMMAND_EXPAND_LISTS + VERBATIM +) +set_property(SOURCE "${gen_file}" PROPERTY SYMBOLIC ON) +add_custom_target(command_expand_lists ALL DEPENDS "${gen_file}") +set_property(TARGET command_expand_lists PROPERTY CMPARGS "${cmp_args}") diff --git a/Tests/CustomCommand/compare_options.cmake b/Tests/CustomCommand/compare_options.cmake new file mode 100644 index 0000000..a32e579 --- /dev/null +++ b/Tests/CustomCommand/compare_options.cmake @@ -0,0 +1,14 @@ +set(range 1 2 3 4 5 6 7 8 9 10) +set(aargs "") +set(bargs "") +foreach(n IN LISTS range) + set(aval "${A${n}ARG}") + set(bval "${B${n}ARG}") + if(aval OR bval) + list(APPEND aargs "\"${aval}\"") + list(APPEND bargs "\"${bval}\"") + endif() +endforeach() +if(NOT "${aargs}" STREQUAL "${bargs}") + message(FATAL_ERROR "COMPARE_OPTIONS: \n\t${aargs} != \n\t${bargs}") +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/file/GLOB-noexp-LIST_DIRECTORIES.cmake b/Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES.cmake new file mode 100644 index 0000000..37a9d54 --- /dev/null +++ b/Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES.cmake @@ -0,0 +1 @@ +file(GLOB CONTENT_LIST LIST_DIRECTORIES false) diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 48fa757..7497544 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -31,6 +31,7 @@ run_cmake(GLOB_RECURSE) run_cmake(GLOB-error-LIST_DIRECTORIES-not-boolean) # test is valid both for GLOB and GLOB_RECURSE run_cmake(GLOB-error-LIST_DIRECTORIES-no-arg) +run_cmake(GLOB-noexp-LIST_DIRECTORIES) if(NOT WIN32 OR CYGWIN) run_cmake(GLOB_RECURSE-cyclic-recursion) 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; +} |