diff options
162 files changed, 3139 insertions, 1508 deletions
diff --git a/CMakeCPackOptions.cmake.in b/CMakeCPackOptions.cmake.in index 3ff0188..aba404f 100644 --- a/CMakeCPackOptions.cmake.in +++ b/CMakeCPackOptions.cmake.in @@ -58,13 +58,11 @@ if("${CPACK_GENERATOR}" STREQUAL "WIX") endif() set(CPACK_PACKAGE_VERSION - "@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@.@CMake_VERSION_PATCH@") + "@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@") # WIX installers require at most a 4 component version number, where # each component is an integer between 0 and 65534 inclusive - set(tweak "@CMake_VERSION_TWEAK@") - if(tweak MATCHES "^[0-9]+$") - if(tweak GREATER 0 AND tweak LESS 65535) - set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}.${tweak}") - endif() + set(patch "@CMake_VERSION_PATCH@") + if(patch MATCHES "^[0-9]+$" AND patch LESS 65535) + set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}.${patch}") endif() endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 761ad20..9e1e7c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,8 +164,6 @@ macro(CMAKE_SETUP_TESTING) ${CMake_BINARY_DIR}/Modules/.NoDartCoverage) configure_file(${CMake_SOURCE_DIR}/CTestCustom.cmake.in ${CMake_BINARY_DIR}/CTestCustom.cmake @ONLY) - configure_file(${CMake_SOURCE_DIR}/CTestCustom.ctest.in - ${CMake_BINARY_DIR}/CTestCustom.ctest @ONLY) if(BUILD_TESTING AND DART_ROOT) configure_file(${CMake_SOURCE_DIR}/CMakeLogo.gif ${CMake_BINARY_DIR}/Testing/HTML/TestingResults/Icons/Logo.gif COPYONLY) diff --git a/CTestConfig.cmake b/CTestConfig.cmake index 92eacd8..819f9ba 100644 --- a/CTestConfig.cmake +++ b/CTestConfig.cmake @@ -18,8 +18,3 @@ set(CTEST_DROP_LOCATION "/CDash/submit.php?project=CMake") set(CTEST_DROP_SITE_CDASH TRUE) set(CTEST_CDASH_VERSION "1.6") set(CTEST_CDASH_QUERY_VERSION TRUE) - -# use old trigger stuff so that cmake 2.4 and below will not -# get errors on trigger -set (TRIGGER_SITE - "http://public.kitware.com/cgi-bin/Submit-CMake-TestingResults.cgi") diff --git a/CTestCustom.ctest.in b/CTestCustom.ctest.in deleted file mode 100644 index 6127843..0000000 --- a/CTestCustom.ctest.in +++ /dev/null @@ -1,3 +0,0 @@ -# This file is provided for compatibility with CMake 2.2 and lower. -# Just include the custom file by its new name. -INCLUDE("CTestCustom.cmake") diff --git a/Help/command/add_test.rst b/Help/command/add_test.rst index 5714559..7e7e6bd 100644 --- a/Help/command/add_test.rst +++ b/Help/command/add_test.rst @@ -1,69 +1,59 @@ add_test -------- -Add a test to the project with the specified arguments. +Add a test to the project to be run by :manual:`ctest(1)`. :: - add_test(testname Exename arg1 arg2 ... ) + add_test(NAME <name> COMMAND <command> [<arg>...] + [CONFIGURATIONS <config>...] + [WORKING_DIRECTORY <dir>]) -If the ENABLE_TESTING command has been run, this command adds a test -target to the current directory. If ENABLE_TESTING has not been run, -this command does nothing. The tests are run by the testing subsystem -by executing Exename with the specified arguments. Exename can be -either an executable built by this project or an arbitrary executable -on the system (like tclsh). The test will be run with the current -working directory set to the CMakeList.txt files corresponding -directory in the binary tree. Tests added using this signature do not -support generator expressions. +Add a test called ``<name>``. The test name may not contain spaces, +quotes, or other characters special in CMake syntax. The options are: +``COMMAND`` + Specify the test command-line. If ``<command>`` specifies an + executable target (created by :command:`add_executable`) it will + automatically be replaced by the location of the executable created + at build time. +``CONFIGURATIONS`` + Restrict execution of the test only to the named configurations. -:: - - add_test(NAME <name> [CONFIGURATIONS [Debug|Release|...]] - [WORKING_DIRECTORY dir] - COMMAND <command> [arg1 [arg2 ...]]) - -Add a test called <name>. The test name may not contain spaces, -quotes, or other characters special in CMake syntax. If COMMAND -specifies an executable target (created by add_executable) it will -automatically be replaced by the location of the executable created at -build time. If a CONFIGURATIONS option is given then the test will be -executed only when testing under one of the named configurations. If -a WORKING_DIRECTORY option is given then the test will be executed in -the given directory. - -Arguments after COMMAND may use "generator expressions" with the syntax -``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for -available expressions. +``WORKING_DIRECTORY`` + Set the :prop_test:`WORKING_DIRECTORY` test property to + specify the working directory in which to execute the test. + If not specified the test will be run with the current working + directory set to the build directory corresponding to the + current source directory. -Note that tgt is not added as a dependency of the target this -expression is evaluated on. +The ``COMMAND`` and ``WORKING_DIRECTORY`` options may use "generator +expressions" with the syntax ``$<...>``. See the +:manual:`cmake-generator-expressions(7)` manual for available expressions. -:: - - $<TARGET_POLICY:pol> = '1' if the policy was NEW when the 'head' target was created, else '0'. If the policy was not set, the warning message for the policy will be emitted. This generator expression only works for a subset of policies. - $<INSTALL_PREFIX> = Content of the install prefix when the target is exported via INSTALL(EXPORT) and empty otherwise. +Example usage:: -Boolean expressions: + add_test(NAME mytest + COMMAND testDriver --config $<CONFIGURATION> + --exe $<TARGET_FILE:myexe>) -:: +This creates a test ``mytest`` whose command runs a ``testDriver`` tool +passing the configuration name and the full path to the executable +file produced by target ``myexe``. - $<AND:?[,?]...> = '1' if all '?' are '1', else '0' - $<OR:?[,?]...> = '0' if all '?' are '0', else '1' - $<NOT:?> = '0' if '?' is '1', else '1' +.. note:: -where '?' is always either '0' or '1'. + CMake will generate tests only if the :command:`enable_testing` + command has been invoked. The :module:`CTest` module invokes the + command automatically when the ``BUILD_TESTING`` option is ``ON``. -Example usage: +--------------------------------------------------------------------- :: - add_test(NAME mytest - COMMAND testDriver --config $<CONFIGURATION> - --exe $<TARGET_FILE:myexe>) + add_test(<name> <command> [<arg>...]) -This creates a test "mytest" whose command runs a testDriver tool -passing the configuration name and the full path to the executable -file produced by target "myexe". +Add a test called ``<name>`` with the given command-line. Unlike +the above ``NAME`` signature no transformation is performed on the +command-line to support target names or generator expressions. diff --git a/Help/command/install.rst b/Help/command/install.rst index a463a60..47108f0 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -9,43 +9,50 @@ executed in order during installation. The order across directories is not defined. There are multiple signatures for this command. Some of them define -installation properties for files and targets. Properties common to +installation options for files and targets. Options common to multiple signatures are covered here but they are valid only for -signatures that specify them. - -DESTINATION arguments specify the directory on disk to which a file -will be installed. If a full path (with a leading slash or drive -letter) is given it is used directly. If a relative path is given it -is interpreted relative to the value of CMAKE_INSTALL_PREFIX. The -prefix can be relocated at install time using DESTDIR mechanism -explained in the CMAKE_INSTALL_PREFIX variable documentation. - -PERMISSIONS arguments specify permissions for installed files. Valid -permissions are OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, -GROUP_WRITE, GROUP_EXECUTE, WORLD_READ, WORLD_WRITE, WORLD_EXECUTE, -SETUID, and SETGID. Permissions that do not make sense on certain -platforms are ignored on those platforms. - -The CONFIGURATIONS argument specifies a list of build configurations -for which the install rule applies (Debug, Release, etc.). - -The COMPONENT argument specifies an installation component name with -which the install rule is associated, such as "runtime" or -"development". During component-specific installation only install -rules associated with the given component name will be executed. -During a full installation all components are installed. If COMPONENT -is not provided a default component "Unspecified" is created. The -default component name may be controlled with the -CMAKE_INSTALL_DEFAULT_COMPONENT_NAME variable. - -The RENAME argument specifies a name for an installed file that may be -different from the original file. Renaming is allowed only when a -single file is installed by the command. - -The OPTIONAL argument specifies that it is not an error if the file to -be installed does not exist. - -The TARGETS signature: +signatures that specify them. The common options are: + +``DESTINATION`` + Specify the directory on disk to which a file will be installed. + If a full path (with a leading slash or drive letter) is given + it is used directly. If a relative path is given it is interpreted + relative to the value of the :variable:`CMAKE_INSTALL_PREFIX` variable. + The prefix can be relocated at install time using the ``DESTDIR`` + mechanism explained in the :variable:`CMAKE_INSTALL_PREFIX` variable + documentation. + +``PERMISSIONS`` + Specify permissions for installed files. Valid permissions are + ``OWNER_READ``, ``OWNER_WRITE``, ``OWNER_EXECUTE``, ``GROUP_READ``, + ``GROUP_WRITE``, ``GROUP_EXECUTE``, ``WORLD_READ``, ``WORLD_WRITE``, + ``WORLD_EXECUTE``, ``SETUID``, and ``SETGID``. Permissions that do + not make sense on certain platforms are ignored on those platforms. + +``CONFIGURATIONS`` + Specify a list of build configurations for which the install rule + applies (Debug, Release, etc.). + +``COMPONENT`` + Specify an installation component name with which the install rule + is associated, such as "runtime" or "development". During + component-specific installation only install rules associated with + the given component name will be executed. During a full installation + all components are installed. If ``COMPONENT`` is not provided a + default component "Unspecified" is created. The default component + name may be controlled with the + :variable:`CMAKE_INSTALL_DEFAULT_COMPONENT_NAME` variable. + +``RENAME`` + Specify a name for an installed file that may be different from the + original file. Renaming is allowed only when a single file is + installed by the command. + +``OPTIONAL`` + Specify that it is not an error if the file to be installed does + not exist. + +------------------------------------------------------------------------------ :: @@ -60,118 +67,115 @@ The TARGETS signature: [OPTIONAL] [NAMELINK_ONLY|NAMELINK_SKIP] ] [...]) -The TARGETS form specifies rules for installing targets from a +The ``TARGETS`` form specifies rules for installing targets from a project. There are five kinds of target files that may be installed: -ARCHIVE, LIBRARY, RUNTIME, FRAMEWORK, and BUNDLE. Executables are -treated as RUNTIME targets, except that those marked with the -MACOSX_BUNDLE property are treated as BUNDLE targets on OS X. Static -libraries are always treated as ARCHIVE targets. Module libraries are -always treated as LIBRARY targets. For non-DLL platforms shared -libraries are treated as LIBRARY targets, except that those marked -with the FRAMEWORK property are treated as FRAMEWORK targets on OS X. -For DLL platforms the DLL part of a shared library is treated as a -RUNTIME target and the corresponding import library is treated as an -ARCHIVE target. All Windows-based systems including Cygwin are DLL -platforms. The ARCHIVE, LIBRARY, RUNTIME, and FRAMEWORK arguments +``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``FRAMEWORK``, and ``BUNDLE``. +Executables are treated as ``RUNTIME`` targets, except that those +marked with the ``MACOSX_BUNDLE`` property are treated as ``BUNDLE`` +targets on OS X. Static libraries are always treated as ``ARCHIVE`` +targets. Module libraries are always treated as ``LIBRARY`` targets. +For non-DLL platforms shared libraries are treated as ``LIBRARY`` +targets, except that those marked with the ``FRAMEWORK`` property are +treated as ``FRAMEWORK`` targets on OS X. For DLL platforms the DLL +part of a shared library is treated as a ``RUNTIME`` target and the +corresponding import library is treated as an ``ARCHIVE`` target. +All Windows-based systems including Cygwin are DLL platforms. +The ``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, and ``FRAMEWORK`` arguments change the type of target to which the subsequent properties apply. If none is given the installation properties apply to all target types. If only one is given then only targets of that type will be installed (which can be used to install just a DLL or just an import -library).The INCLUDES DESTINATION specifies a list of directories -which will be added to the INTERFACE_INCLUDE_DIRECTORIES of the -<targets> when exported by install(EXPORT). If a relative path is -specified, it is treated as relative to the $<INSTALL_PREFIX>. - -The PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE arguments cause -subsequent properties to be applied to installing a FRAMEWORK shared -library target's associated files on non-Apple platforms. Rules +library). The ``INCLUDES DESTINATION`` specifies a list of directories +which will be added to the :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` +target property of the ``<targets>`` when exported by the +:command:`install(EXPORT)` command. If a relative path is +specified, it is treated as relative to the ``$<INSTALL_PREFIX>``. + +The ``PRIVATE_HEADER``, ``PUBLIC_HEADER``, and ``RESOURCE`` arguments +cause subsequent properties to be applied to installing a ``FRAMEWORK`` +shared library target's associated files on non-Apple platforms. Rules defined by these arguments are ignored on Apple platforms because the associated files are installed into the appropriate locations inside -the framework folder. See documentation of the PRIVATE_HEADER, -PUBLIC_HEADER, and RESOURCE target properties for details. +the framework folder. See documentation of the +:prop_tgt:`PRIVATE_HEADER`, :prop_tgt:`PUBLIC_HEADER`, and +:prop_tgt:`RESOURCE` target properties for details. -Either NAMELINK_ONLY or NAMELINK_SKIP may be specified as a LIBRARY -option. On some platforms a versioned shared library has a symbolic -link such as - -:: +Either ``NAMELINK_ONLY`` or ``NAMELINK_SKIP`` may be specified as a +``LIBRARY`` option. On some platforms a versioned shared library +has a symbolic link such as:: lib<name>.so -> lib<name>.so.1 -where "lib<name>.so.1" is the soname of the library and "lib<name>.so" +where ``lib<name>.so.1`` is the soname of the library and ``lib<name>.so`` is a "namelink" allowing linkers to find the library when given -"-l<name>". The NAMELINK_ONLY option causes installation of only the -namelink when a library target is installed. The NAMELINK_SKIP option +``-l<name>``. The ``NAMELINK_ONLY`` option causes installation of only the +namelink when a library target is installed. The ``NAMELINK_SKIP`` option causes installation of library files other than the namelink when a library target is installed. When neither option is given both portions are installed. On platforms where versioned shared libraries do not have namelinks or when a library is not versioned the -NAMELINK_SKIP option installs the library and the NAMELINK_ONLY option -installs nothing. See the VERSION and SOVERSION target properties for -details on creating versioned shared libraries. +``NAMELINK_SKIP`` option installs the library and the ``NAMELINK_ONLY`` +option installs nothing. See the :prop_tgt:`VERSION` and +:prop_tgt:`SOVERSION` target properties for details on creating versioned +shared libraries. One or more groups of properties may be specified in a single call to -the TARGETS form of this command. A target may be installed more than -once to different locations. Consider hypothetical targets "myExe", -"mySharedLib", and "myStaticLib". The code +the ``TARGETS`` form of this command. A target may be installed more than +once to different locations. Consider hypothetical targets ``myExe``, +``mySharedLib``, and ``myStaticLib``. The code: -:: +.. code-block:: cmake - install(TARGETS myExe mySharedLib myStaticLib - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib/static) - install(TARGETS mySharedLib DESTINATION /some/full/path) + install(TARGETS myExe mySharedLib myStaticLib + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static) + install(TARGETS mySharedLib DESTINATION /some/full/path) -will install myExe to <prefix>/bin and myStaticLib to -<prefix>/lib/static. On non-DLL platforms mySharedLib will be -installed to <prefix>/lib and /some/full/path. On DLL platforms the -mySharedLib DLL will be installed to <prefix>/bin and /some/full/path -and its import library will be installed to <prefix>/lib/static and -/some/full/path. +will install ``myExe`` to ``<prefix>/bin`` and ``myStaticLib`` to +``<prefix>/lib/static``. On non-DLL platforms ``mySharedLib`` will be +installed to ``<prefix>/lib`` and ``/some/full/path``. On DLL platforms +the ``mySharedLib`` DLL will be installed to ``<prefix>/bin`` and +``/some/full/path`` and its import library will be installed to +``<prefix>/lib/static`` and ``/some/full/path``. -The EXPORT option associates the installed target files with an export -called <export-name>. It must appear before any RUNTIME, LIBRARY, or -ARCHIVE options. To actually install the export file itself, call -install(EXPORT). See documentation of the install(EXPORT ...) -signature below for details. +The ``EXPORT`` option associates the installed target files with an +export called ``<export-name>``. It must appear before any ``RUNTIME``, +``LIBRARY``, or ``ARCHIVE`` options. To actually install the export +file itself, call ``install(EXPORT)``, documented below. -Installing a target with EXCLUDE_FROM_ALL set to true has undefined -behavior. +Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property +set to ``TRUE`` has undefined behavior. -The FILES signature: +------------------------------------------------------------------------------ :: - install(FILES files... DESTINATION <dir> + install(<FILES|PROGRAMS> files... DESTINATION <dir> [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [RENAME <name>] [OPTIONAL]) -The FILES form specifies rules for installing files for a project. +The ``FILES`` form specifies rules for installing files for a project. File names given as relative paths are interpreted with respect to the current source directory. Files installed by this form are by default -given permissions OWNER_WRITE, OWNER_READ, GROUP_READ, and WORLD_READ -if no PERMISSIONS argument is given. - -The PROGRAMS signature: - -:: - - install(PROGRAMS files... DESTINATION <dir> - [PERMISSIONS permissions...] - [CONFIGURATIONS [Debug|Release|...]] - [COMPONENT <component>] - [RENAME <name>] [OPTIONAL]) +given permissions ``OWNER_WRITE``, ``OWNER_READ``, ``GROUP_READ``, and +``WORLD_READ`` if no ``PERMISSIONS`` argument is given. -The PROGRAMS form is identical to the FILES form except that the -default permissions for the installed file also include OWNER_EXECUTE, -GROUP_EXECUTE, and WORLD_EXECUTE. This form is intended to install -programs that are not targets, such as shell scripts. Use the TARGETS +The ``PROGRAMS`` form is identical to the ``FILES`` form except that the +default permissions for the installed file also include ``OWNER_EXECUTE``, +``GROUP_EXECUTE``, and ``WORLD_EXECUTE``. This form is intended to install +programs that are not targets, such as shell scripts. Use the ``TARGETS`` form to install targets built within the project. -The DIRECTORY signature: +The list of ``files...`` given to ``FILES`` or ``PROGRAMS`` may use +"generator expressions" with the syntax ``$<...>``. See the +:manual:`cmake-generator-expressions(7)` manual for available expressions. +However, if any item begins in a generator expression it must evaluate +to a full path. + +------------------------------------------------------------------------------ :: @@ -184,7 +188,7 @@ The DIRECTORY signature: [[PATTERN <pattern> | REGEX <regex>] [EXCLUDE] [PERMISSIONS permissions...]] [...]) -The DIRECTORY form installs contents of one or more directories to a +The ``DIRECTORY`` form installs contents of one or more directories to a given destination. The directory structure is copied verbatim to the destination. The last component of each directory name is appended to the destination directory but a trailing slash may be used to avoid @@ -192,45 +196,45 @@ this because it leaves the last component empty. Directory names given as relative paths are interpreted with respect to the current source directory. If no input directory names are given the destination directory will be created but nothing will be installed -into it. The FILE_PERMISSIONS and DIRECTORY_PERMISSIONS options +into it. The ``FILE_PERMISSIONS`` and ``DIRECTORY_PERMISSIONS`` options specify permissions given to files and directories in the destination. -If USE_SOURCE_PERMISSIONS is specified and FILE_PERMISSIONS is not, +If ``USE_SOURCE_PERMISSIONS`` is specified and ``FILE_PERMISSIONS`` is not, file permissions will be copied from the source directory structure. If no permissions are specified files will be given the default -permissions specified in the FILES form of the command, and the +permissions specified in the ``FILES`` form of the command, and the directories will be given the default permissions specified in the -PROGRAMS form of the command. +``PROGRAMS`` form of the command. Installation of directories may be controlled with fine granularity -using the PATTERN or REGEX options. These "match" options specify a +using the ``PATTERN`` or ``REGEX`` options. These "match" options specify a globbing pattern or regular expression to match directories or files encountered within input directories. They may be used to apply certain options (see below) to a subset of the files and directories encountered. The full path to each input file or directory (with -forward slashes) is matched against the expression. A PATTERN will +forward slashes) is matched against the expression. A ``PATTERN`` will match only complete file names: the portion of the full path matching the pattern must occur at the end of the file name and be preceded by -a slash. A REGEX will match any portion of the full path but it may -use '/' and '$' to simulate the PATTERN behavior. By default all +a slash. A ``REGEX`` will match any portion of the full path but it may +use ``/`` and ``$`` to simulate the ``PATTERN`` behavior. By default all files and directories are installed whether or not they are matched. -The FILES_MATCHING option may be given before the first match option +The ``FILES_MATCHING`` option may be given before the first match option to disable installation of files (but not directories) not matched by any expression. For example, the code -:: +.. code-block:: cmake install(DIRECTORY src/ DESTINATION include/myproj FILES_MATCHING PATTERN "*.h") will extract and install header files from a source tree. -Some options may follow a PATTERN or REGEX expression and are applied -only to files or directories matching them. The EXCLUDE option will -skip the matched file or directory. The PERMISSIONS option overrides +Some options may follow a ``PATTERN`` or ``REGEX`` expression and are applied +only to files or directories matching them. The ``EXCLUDE`` option will +skip the matched file or directory. The ``PERMISSIONS`` option overrides the permissions setting for the matched file or directory. For example the code -:: +.. code-block:: cmake install(DIRECTORY icons scripts/ DESTINATION share/myproj PATTERN "CVS" EXCLUDE @@ -238,31 +242,31 @@ example the code PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ) -will install the icons directory to share/myproj/icons and the scripts -directory to share/myproj. The icons will get default file -permissions, the scripts will be given specific permissions, and any -CVS directories will be excluded. +will install the ``icons`` directory to ``share/myproj/icons`` and the +``scripts`` directory to ``share/myproj``. The icons will get default +file permissions, the scripts will be given specific permissions, and any +``CVS`` directories will be excluded. -The SCRIPT and CODE signature: +------------------------------------------------------------------------------ :: install([[SCRIPT <file>] [CODE <code>]] [...]) -The SCRIPT form will invoke the given CMake script files during +The ``SCRIPT`` form will invoke the given CMake script files during installation. If the script file name is a relative path it will be -interpreted with respect to the current source directory. The CODE +interpreted with respect to the current source directory. The ``CODE`` form will invoke the given CMake code during installation. Code is specified as a single argument inside a double-quoted string. For example, the code -:: +.. code-block:: cmake install(CODE "MESSAGE(\"Sample install message.\")") will print a message during installation. -The EXPORT signature: +------------------------------------------------------------------------------ :: @@ -273,44 +277,47 @@ The EXPORT signature: [EXPORT_LINK_INTERFACE_LIBRARIES] [COMPONENT <component>]) -The EXPORT form generates and installs a CMake file containing code to +The ``EXPORT`` form generates and installs a CMake file containing code to import targets from the installation tree into another project. -Target installations are associated with the export <export-name> -using the EXPORT option of the install(TARGETS ...) signature -documented above. The NAMESPACE option will prepend <namespace> to +Target installations are associated with the export ``<export-name>`` +using the ``EXPORT`` option of the ``install(TARGETS)`` signature +documented above. The ``NAMESPACE`` option will prepend ``<namespace>`` to the target names as they are written to the import file. By default -the generated file will be called <export-name>.cmake but the FILE +the generated file will be called ``<export-name>.cmake`` but the ``FILE`` option may be used to specify a different name. The value given to -the FILE option must be a file name with the ".cmake" extension. If a -CONFIGURATIONS option is given then the file will only be installed +the ``FILE`` option must be a file name with the ``.cmake`` extension. +If a ``CONFIGURATIONS`` option is given then the file will only be installed when one of the named configurations is installed. Additionally, the generated import file will reference only the matching target -configurations. The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if +configurations. The ``EXPORT_LINK_INTERFACE_LIBRARIES`` keyword, if present, causes the contents of the properties matching ``(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?`` to be exported, when -policy CMP0022 is NEW. If a COMPONENT option is specified that does -not match that given to the targets associated with <export-name> the -behavior is undefined. If a library target is included in the export -but a target to which it links is not included the behavior is -unspecified. +policy :policy:`CMP0022` is ``NEW``. If a ``COMPONENT`` option is +specified that does not match that given to the targets associated with +``<export-name>`` the behavior is undefined. If a library target is +included in the export but a target to which it links is not included +the behavior is unspecified. -The EXPORT form is useful to help outside projects use targets built +The ``EXPORT`` form is useful to help outside projects use targets built and installed by the current project. For example, the code -:: +.. code-block:: cmake install(TARGETS myexe EXPORT myproj DESTINATION bin) install(EXPORT myproj NAMESPACE mp_ DESTINATION lib/myproj) -will install the executable myexe to <prefix>/bin and code to import -it in the file "<prefix>/lib/myproj/myproj.cmake". An outside project -may load this file with the include command and reference the myexe +will install the executable myexe to ``<prefix>/bin`` and code to import +it in the file ``<prefix>/lib/myproj/myproj.cmake``. An outside project +may load this file with the include command and reference the ``myexe`` executable from the installation tree using the imported target name -mp_myexe as if the target were built in its own tree. - -NOTE: This command supercedes the INSTALL_TARGETS command and the -target properties PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT. It also -replaces the FILES forms of the INSTALL_FILES and INSTALL_PROGRAMS -commands. The processing order of these install rules relative to -those generated by INSTALL_TARGETS, INSTALL_FILES, and -INSTALL_PROGRAMS commands is not defined. +``mp_myexe`` as if the target were built in its own tree. + +.. note:: + This command supercedes the :command:`install_targets` command and + the :prop_tgt:`PRE_INSTALL_SCRIPT` and :prop_tgt:`POST_INSTALL_SCRIPT` + target properties. It also replaces the ``FILES`` forms of the + :command:`install_files` and :command:`install_programs` commands. + The processing order of these install rules relative to + those generated by :command:`install_targets`, + :command:`install_files`, and :command:`install_programs` commands + is not defined. diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index d252473..501b924 100644 --- a/Help/manual/cmake-buildsystem.7.rst +++ b/Help/manual/cmake-buildsystem.7.rst @@ -820,6 +820,16 @@ This way, the build specification of ``exe1`` is expressed entirely as linked targets, and the complexity of compiler-specific flags is encapsulated in an ``INTERFACE`` library target. +The properties permitted to be set on or read from an ``INTERFACE`` library +are: + +* Properties matching ``INTERFACE_*`` +* Built-in properties matching ``COMPATIBLE_INTERFACE_*`` +* ``EXPORT_NAME`` +* ``IMPORTED`` +* ``NAME`` +* Properties matching ``MAP_IMPORTED_CONFIG_*`` + ``INTERFACE`` libraries may be installed and exported. Any content they refer to must be installed separately: diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 7a06be6..2bbe622 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -138,6 +138,7 @@ All Modules /module/FindMPEG /module/FindMPI /module/FindOpenAL + /module/FindOpenCL /module/FindOpenGL /module/FindOpenMP /module/FindOpenSceneGraph diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index d315fcb..6ea5839 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -100,6 +100,10 @@ Properties on Targets /prop_tgt/COMPILE_DEFINITIONS /prop_tgt/COMPILE_FLAGS /prop_tgt/COMPILE_OPTIONS + /prop_tgt/COMPILE_PDB_NAME + /prop_tgt/COMPILE_PDB_NAME_CONFIG + /prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY + /prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /prop_tgt/CONFIG_OUTPUT_NAME /prop_tgt/CONFIG_POSTFIX /prop_tgt/DEBUG_POSTFIX diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index c4ae193..5f2ba28 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -198,6 +198,8 @@ Variables that Control the Build /variable/CMAKE_AUTOUIC /variable/CMAKE_AUTOUIC_OPTIONS /variable/CMAKE_BUILD_WITH_INSTALL_RPATH + /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY + /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_CONFIG_POSTFIX /variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG diff --git a/Help/module/FindOpenCL.rst b/Help/module/FindOpenCL.rst new file mode 100644 index 0000000..e87e289 --- /dev/null +++ b/Help/module/FindOpenCL.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindOpenCL.cmake diff --git a/Help/prop_tgt/COMPILE_PDB_NAME.rst b/Help/prop_tgt/COMPILE_PDB_NAME.rst new file mode 100644 index 0000000..24a9f62 --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_NAME.rst @@ -0,0 +1,11 @@ +COMPILE_PDB_NAME +---------------- + +Output name for the MS debug symbol ``.pdb`` file generated by the +compiler while building source files. + +This property specifies the base name for the debug symbols file. +If not set, the default is unspecified. + +.. |PDB_XXX| replace:: :prop_tgt:`PDB_NAME` +.. include:: COMPILE_PDB_NOTE.txt diff --git a/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst b/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst new file mode 100644 index 0000000..e4077f5 --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst @@ -0,0 +1,10 @@ +COMPILE_PDB_NAME_<CONFIG> +------------------------- + +Per-configuration output name for the MS debug symbol ``.pdb`` file +generated by the compiler while building source files. + +This is the configuration-specific version of :prop_tgt:`COMPILE_PDB_NAME`. + +.. |PDB_XXX| replace:: :prop_tgt:`PDB_NAME_<CONFIG>` +.. include:: COMPILE_PDB_NOTE.txt diff --git a/Help/prop_tgt/COMPILE_PDB_NOTE.txt b/Help/prop_tgt/COMPILE_PDB_NOTE.txt new file mode 100644 index 0000000..5941d72 --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_NOTE.txt @@ -0,0 +1,8 @@ +.. note:: + The compiler-generated program database files are specified by the + ``/Fd`` compiler flag and are not the same as linker-generated + program database files specified by the ``/pdb`` linker flag. + Use the |PDB_XXX| property to specify the latter. + + This property is not implemented by the :generator:`Visual Studio 6` + generator. diff --git a/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst new file mode 100644 index 0000000..34f49be --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst @@ -0,0 +1,13 @@ +COMPILE_PDB_OUTPUT_DIRECTORY +---------------------------- + +Output directory for the MS debug symbol ``.pdb`` file +generated by the compiler while building source files. + +This property specifies the directory into which the MS debug symbols +will be placed by the compiler. This property is initialized by the +value of the :variable:`CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY` variable +if it is set when a target is created. + +.. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY` +.. include:: COMPILE_PDB_NOTE.txt diff --git a/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst new file mode 100644 index 0000000..52ef013 --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst @@ -0,0 +1,16 @@ +COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG> +------------------------------------- + +Per-configuration output directory for the MS debug symbol ``.pdb`` file +generated by the compiler while building source files. + +This is a per-configuration version of +:prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY`, +but multi-configuration generators (VS, Xcode) do NOT append a +per-configuration subdirectory to the specified directory. This +property is initialized by the value of the +:variable:`CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>` variable +if it is set when a target is created. + +.. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY_<CONFIG>` +.. include:: COMPILE_PDB_NOTE.txt diff --git a/Help/prop_tgt/PDB_NAME.rst b/Help/prop_tgt/PDB_NAME.rst index e8fc3be..479dec3 100644 --- a/Help/prop_tgt/PDB_NAME.rst +++ b/Help/prop_tgt/PDB_NAME.rst @@ -7,7 +7,5 @@ linker for an executable or shared library target. This property specifies the base name for the debug symbols file. If not set, the logical target name is used by default. +.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_NAME` .. include:: PDB_NOTE.txt - -This property is not implemented by the :generator:`Visual Studio 6` -generator. diff --git a/Help/prop_tgt/PDB_NAME_CONFIG.rst b/Help/prop_tgt/PDB_NAME_CONFIG.rst index c846b57..cb3121c 100644 --- a/Help/prop_tgt/PDB_NAME_CONFIG.rst +++ b/Help/prop_tgt/PDB_NAME_CONFIG.rst @@ -6,5 +6,5 @@ generated by the linker for an executable or shared library target. This is the configuration-specific version of :prop_tgt:`PDB_NAME`. -This property is not implemented by the :generator:`Visual Studio 6` -generator. +.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_NAME_<CONFIG>` +.. include:: PDB_NOTE.txt diff --git a/Help/prop_tgt/PDB_NOTE.txt b/Help/prop_tgt/PDB_NOTE.txt index e55aba2..f90ea81 100644 --- a/Help/prop_tgt/PDB_NOTE.txt +++ b/Help/prop_tgt/PDB_NOTE.txt @@ -3,6 +3,10 @@ is invoked to produce them so they have no linker-generated ``.pdb`` file containing debug symbols. - The compiler-generated program database files specified by the MSVC - ``/Fd`` flag are not the same as linker-generated program database - files and so are not influenced by this property. + The linker-generated program database files are specified by the + ``/pdb`` linker flag and are not the same as compiler-generated + program database files specified by the ``/Fd`` compiler flag. + Use the |COMPILE_PDB_XXX| property to specify the latter. + + This property is not implemented by the :generator:`Visual Studio 6` + generator. diff --git a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst index 9a863a1..730cf57 100644 --- a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst +++ b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst @@ -9,7 +9,5 @@ will be placed by the linker. This property is initialized by the value of the :variable:`CMAKE_PDB_OUTPUT_DIRECTORY` variable if it is set when a target is created. +.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY` .. include:: PDB_NOTE.txt - -This property is not implemented by the :generator:`Visual Studio 6` -generator. diff --git a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst index caec2de..6037fa0 100644 --- a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst +++ b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst @@ -11,5 +11,5 @@ property is initialized by the value of the :variable:`CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG>` variable if it is set when a target is created. -This property is not implemented by the :generator:`Visual Studio 6` -generator. +.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>` +.. include:: PDB_NOTE.txt diff --git a/Help/release/3.0.rst b/Help/release/3.0.0.rst index 45f7635..ee8417c 100644 --- a/Help/release/3.0.rst +++ b/Help/release/3.0.0.rst @@ -1,5 +1,5 @@ -CMake 3.0 Release Notes -*********************** +CMake 3.0.0 Release Notes +************************* .. only:: html @@ -39,7 +39,7 @@ Documentation Changes - :manual:`cmake-toolchains(7)` - :manual:`cmake-variables(7)`, replacing ``cmakevars(1)`` -* Release notes for CMake 3.0 and above will now be included with +* Release notes for CMake 3.0.0 and above will now be included with the html documentation. New Features @@ -102,6 +102,10 @@ Commands configuration because it will not be available. Use :ref:`Alias Targets` instead. See policy :policy:`CMP0024`. +* The :command:`install(FILES)` command learned to support + :manual:`generator expressions <cmake-generator-expressions(7)>` + in the list of files. + * The :command:`project` command learned to set some version variables to values specified by the new ``VERSION`` option or to empty strings. See policy :policy:`CMP0048`. @@ -216,6 +220,9 @@ Modules * A new :module:`FindLua` module has been added to support :command:`find_package(Lua)` calls. +* The :module:`FindBoost` module learned a new ``Boost_NAMESPACE`` + option to change the ``boost`` prefix on library names. + * The :module:`FindBoost` module learned to control search for libraies with the ``g`` tag (for MS debug runtime) with a new ``Boost_USE_DEBUG_RUNTIME`` option. It is ``ON`` by @@ -387,6 +394,11 @@ Deprecated and Removed Features Other Changes ============= +* The version scheme was changed to use only two components for + the feature level instead of three. The third component will + now be used for bug-fix releases or the date of development versions. + See the :variable:`CMAKE_VERSION` variable documentation for details. + * The default install locations of CMake itself on Windows and OS X no longer contain the CMake version number. This allows for easy replacement without re-generating local build trees diff --git a/Help/release/dev/Boost_NAMESPACE.rst b/Help/release/dev/Boost_NAMESPACE.rst deleted file mode 100644 index 434db29..0000000 --- a/Help/release/dev/Boost_NAMESPACE.rst +++ /dev/null @@ -1,5 +0,0 @@ -Boost_NAMESPACE ---------------- - -* The :module:`FindBoost` module learned a new ``Boost_NAMESPACE`` - option to change the ``boost`` prefix on library names. diff --git a/Help/release/dev/ExternalProject-BUILD_ALWAYS.rst b/Help/release/dev/ExternalProject-BUILD_ALWAYS.rst new file mode 100644 index 0000000..5384671 --- /dev/null +++ b/Help/release/dev/ExternalProject-BUILD_ALWAYS.rst @@ -0,0 +1,6 @@ +ExternalProject-BUILD_ALWAYS +---------------------------- + +* The :module:`ExternalProject` module ``ExternalProject_Add`` command + learned a new ``BUILD_ALWAYS`` option to cause the external project + build step to run every time the host project is built. diff --git a/Help/release/dev/FindGTest-AUTO-SOURCES.rst b/Help/release/dev/FindGTest-AUTO-SOURCES.rst new file mode 100644 index 0000000..17b2a1b --- /dev/null +++ b/Help/release/dev/FindGTest-AUTO-SOURCES.rst @@ -0,0 +1,7 @@ +FindGTest-AUTO-SOURCES +---------------------- + +* The :module:`FindGTest` module ``gtest_add_tests`` macro learned + a new ``AUTO`` option to automatically read the :prop_tgt:`SOURCES` + target property of the test executable and scan the source files + for tests to be added. diff --git a/Help/release/dev/FindHg-WC_INFO.rst b/Help/release/dev/FindHg-WC_INFO.rst new file mode 100644 index 0000000..0caf2b3 --- /dev/null +++ b/Help/release/dev/FindHg-WC_INFO.rst @@ -0,0 +1,5 @@ +FindHg-WC_INFO +-------------- + +* The :module:`FindHg` module gained a new ``Hg_WC_INFO`` macro to + help run ``hg`` to extract information about a Mercurial work copy. diff --git a/Help/release/dev/FindPkgConfig-PKG_CONFIG.rst b/Help/release/dev/FindPkgConfig-PKG_CONFIG.rst new file mode 100644 index 0000000..c0f6471 --- /dev/null +++ b/Help/release/dev/FindPkgConfig-PKG_CONFIG.rst @@ -0,0 +1,5 @@ +FindPkgConfig-PKG_CONFIG +------------------------ + +* The :module:`FindPkgConfig` module learned to use the ``PKG_CONFIG`` + environment variable value as the ``pkg-config`` executable, if set. diff --git a/Help/release/dev/FindRuby-2.rst b/Help/release/dev/FindRuby-2.rst new file mode 100644 index 0000000..50d9a48 --- /dev/null +++ b/Help/release/dev/FindRuby-2.rst @@ -0,0 +1,4 @@ +FindRuby-2 +---------- + +* The :module:`FindRuby` module learned to search for Ruby 2.0 and 2.1. diff --git a/Help/release/dev/add-FindOpenCL.rst b/Help/release/dev/add-FindOpenCL.rst new file mode 100644 index 0000000..e1e30d1 --- /dev/null +++ b/Help/release/dev/add-FindOpenCL.rst @@ -0,0 +1,4 @@ +add-FindOpenCL +-------------- + +* The :module:`FindOpenCL` module was introduced. diff --git a/Help/release/dev/faster-parsers.rst b/Help/release/dev/faster-parsers.rst new file mode 100644 index 0000000..c2a8bfb --- /dev/null +++ b/Help/release/dev/faster-parsers.rst @@ -0,0 +1,6 @@ +faster-parsers +-------------- + +* The :manual:`cmake-language(7)` internal implementation of generator + expression and list expansion parsers have been optimized and shows + non-trivial speedup on large projects. diff --git a/Help/release/dev/msvc-compiler-pdb-files.rst b/Help/release/dev/msvc-compiler-pdb-files.rst new file mode 100644 index 0000000..d06d202 --- /dev/null +++ b/Help/release/dev/msvc-compiler-pdb-files.rst @@ -0,0 +1,10 @@ +msvc-compiler-pdb-files +----------------------- + +* New :prop_tgt:`COMPILE_PDB_NAME` and + :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY` target properties + were introduced to specify the MSVC compiler program database + file location (``cl /Fd``). This complements the existing + :prop_tgt:`PDB_NAME` and :prop_tgt:`PDB_OUTPUT_DIRECTORY` + target properties that specify the linker program database + file location (``link /pdb``). diff --git a/Help/release/index.rst b/Help/release/index.rst index 5c3a771..15ce065 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -13,4 +13,4 @@ Releases .. toctree:: :maxdepth: 1 - 3.0 <3.0> + 3.0.0 <3.0.0> diff --git a/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY.rst b/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY.rst new file mode 100644 index 0000000..ea33c7d --- /dev/null +++ b/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY.rst @@ -0,0 +1,8 @@ +CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY +---------------------------------- + +Output directory for MS debug symbol ``.pdb`` files +generated by the compiler while building source files. + +This variable is used to initialize the +:prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY` property on all the targets. diff --git a/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst b/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst new file mode 100644 index 0000000..fdeb9ab --- /dev/null +++ b/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst @@ -0,0 +1,11 @@ +CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG> +------------------------------------------- + +Per-configuration output directory for MS debug symbol ``.pdb`` files +generated by the compiler while building source files. + +This is a per-configuration version of +:variable:`CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY`. +This variable is used to initialize the +:prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>` +property on all the targets. diff --git a/Help/variable/CMAKE_TWEAK_VERSION.rst b/Help/variable/CMAKE_TWEAK_VERSION.rst index a2c8f35..be2e050 100644 --- a/Help/variable/CMAKE_TWEAK_VERSION.rst +++ b/Help/variable/CMAKE_TWEAK_VERSION.rst @@ -1,5 +1,11 @@ CMAKE_TWEAK_VERSION ------------------- -Fourth version number component of the :variable:`CMAKE_VERSION` -variable. +Defined to ``0`` for compatibility with code written for older +CMake versions that may have defined higher values. + +.. note:: + + In CMake versions 2.8.2 through 2.8.12, this variable holds + the fourth version number component of the + :variable:`CMAKE_VERSION` variable. diff --git a/Help/variable/CMAKE_VERSION.rst b/Help/variable/CMAKE_VERSION.rst index 6184f08..bbb1d91 100644 --- a/Help/variable/CMAKE_VERSION.rst +++ b/Help/variable/CMAKE_VERSION.rst @@ -1,24 +1,23 @@ CMAKE_VERSION ------------- -The CMake version string as up to four non-negative integer components +The CMake version string as three non-negative integer components separated by ``.`` and possibly followed by ``-`` and other information. -The first three components represent the feature level and the fourth +The first two components represent the feature level and the third component represents either a bug-fix level or development date. Release versions and release candidate versions of CMake use the format:: - <major>.<minor>.<patch>[.<tweak>][-rc<n>] + <major>.<minor>.<patch>[-rc<n>] -where the ``<tweak>`` component is less than ``20000000``. Development +where the ``<patch>`` component is less than ``20000000``. Development versions of CMake use the format:: - <major>.<minor>.<patch>.<date>[-<id>] + <major>.<minor>.<date>[-<id>] where the ``<date>`` component is of format ``CCYYMMDD`` and ``<id>`` may contain arbitrary text. This represents development as of a -particular date following the ``<major>.<minor>.<patch>`` feature -release. +particular date following the ``<major>.<minor>`` feature release. Individual component values are also available in variables: @@ -35,6 +34,12 @@ strings as floating-point numbers. .. note:: + CMake versions 2.8.2 through 2.8.12 used three components for the + feature level. Release versions represented the bug-fix level in a + fourth component, i.e. ``<major>.<minor>.<patch>[.<tweak>][-rc<n>]``. + Development versions represented the development date in the fourth + component, i.e. ``<major>.<minor>.<patch>.<date>[-<id>]``. + CMake versions prior to 2.8.2 used three components for the feature level and had no bug-fix component. Release versions used an even-valued second component, i.e. diff --git a/Modules/CMakeFindDependencyMacro.cmake b/Modules/CMakeFindDependencyMacro.cmake index 0f1f56d..9334ba3 100644 --- a/Modules/CMakeFindDependencyMacro.cmake +++ b/Modules/CMakeFindDependencyMacro.cmake @@ -29,29 +29,34 @@ macro(find_dependency dep) if (NOT ${dep}_FOUND) - if (${ARGV1}) - set(version ${ARGV1}) + set(cmake_fd_version) + if (${ARGC} GREATER 1) + set(cmake_fd_version ${ARGV1}) endif() - set(exact_arg) + set(cmake_fd_exact_arg) if(${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION_EXACT) - set(exact_arg EXACT) + set(cmake_fd_exact_arg EXACT) endif() - set(quiet_arg) + set(cmake_fd_quiet_arg) if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) - set(quiet_arg QUIET) + set(cmake_fd_quiet_arg QUIET) endif() - set(required_arg) + set(cmake_fd_required_arg) if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) - set(required_arg REQUIRED) + set(cmake_fd_required_arg REQUIRED) endif() - get_property(alreadyTransitive GLOBAL PROPERTY + get_property(cmake_fd_alreadyTransitive GLOBAL PROPERTY _CMAKE_${dep}_TRANSITIVE_DEPENDENCY ) - find_package(${dep} ${version} ${exact_arg} ${quiet_arg} ${required_arg}) + find_package(${dep} ${cmake_fd_version} + ${cmake_fd_exact_arg} + ${cmake_fd_quiet_arg} + ${cmake_fd_required_arg} + ) - if(NOT DEFINED alreadyTransitive OR alreadyTransitive) + if(NOT DEFINED cmake_fd_alreadyTransitive OR cmake_fd_alreadyTransitive) set_property(GLOBAL PROPERTY _CMAKE_${dep}_TRANSITIVE_DEPENDENCY TRUE) endif() @@ -60,8 +65,9 @@ macro(find_dependency dep) set(${CMAKE_FIND_PACKAGE_NAME}_FOUND False) return() endif() - set(required_arg) - set(quiet_arg) - set(exact_arg) + set(cmake_fd_version) + set(cmake_fd_required_arg) + set(cmake_fd_quiet_arg) + set(cmake_fd_exact_arg) endif() endmacro() diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake index 39183c6..0a47e19 100644 --- a/Modules/CPackWIX.cmake +++ b/Modules/CPackWIX.cmake @@ -216,9 +216,24 @@ # allow other CMake projects to find your package with # the :command:`find_package` command. # +# .. variable:: CPACK_WIX_PROPERTY_<PROPERTY> +# +# This variable can be used to provide a value for +# the Windows Installer property ``<PROPERTY>`` +# +# The follwing list contains some example properties that can be used to +# customize information under +# "Programs and Features" (also known as "Add or Remove Programs") +# +# * ARPCOMMENTS - Comments +# * ARPHELPLINK - Help and support information URL +# * ARPURLINFOABOUT - General information URL +# * URLUPDATEINFO - Update information URL +# * ARPHELPTELEPHONE - Help and support telephone number +# * ARPSIZE - Size (in kilobytes) of the application #============================================================================= -# Copyright 2013 Kitware, Inc. +# Copyright 2014 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 0df51a8..1e83163 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -54,6 +54,7 @@ # [BINARY_DIR dir] # Specify build dir location # [BUILD_COMMAND cmd...] # Command to drive the native build # [BUILD_IN_SOURCE 1] # Use source dir for build dir +# [BUILD_ALWAYS 1] # No stamp file, build step always runs # #--Install step--------------- # [INSTALL_DIR dir] # Installation prefix # [INSTALL_COMMAND cmd...] # Command to drive install after build @@ -1716,10 +1717,18 @@ function(_ep_add_build_command name) set(log "") endif() + get_property(build_always TARGET ${name} PROPERTY _EP_BUILD_ALWAYS) + if(build_always) + set(always 1) + else() + set(always 0) + endif() + ExternalProject_Add_Step(${name} build COMMAND ${cmd} WORKING_DIRECTORY ${binary_dir} DEPENDEES configure + ALWAYS ${always} ${log} ) endfunction() diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake index bc66337..a91da33 100644 --- a/Modules/FindGTK2.cmake +++ b/Modules/FindGTK2.cmake @@ -108,7 +108,7 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -# Version 1.6 (CMake 2.8.13) +# Version 1.6 (CMake 3.0) # * Create targets for each library # * Do not link libfreetype # Version 1.5 (CMake 2.8.12) diff --git a/Modules/FindGTest.cmake b/Modules/FindGTest.cmake index c00a750..aa3c235 100644 --- a/Modules/FindGTest.cmake +++ b/Modules/FindGTest.cmake @@ -79,7 +79,7 @@ # extra_args = Pass a list of extra arguments to be passed to # executable enclosed in quotes (or "" for none) # ARGN = A list of source files to search for tests & test -# fixtures. +# fixtures. Or AUTO to find them from executable target. # # # @@ -88,7 +88,7 @@ # Example: # set(FooTestArgs --foo 1 --bar 2) # add_executable(FooTest FooUnitTest.cc) -# GTEST_ADD_TESTS(FooTest "${FooTestArgs}" FooUnitTest.cc) +# GTEST_ADD_TESTS(FooTest "${FooTestArgs}" AUTO) #============================================================================= # Copyright 2009 Kitware, Inc. @@ -111,6 +111,10 @@ function(GTEST_ADD_TESTS executable extra_args) if(NOT ARGN) message(FATAL_ERROR "Missing ARGN: Read the documentation for GTEST_ADD_TESTS") endif() + if(ARGN STREQUAL "AUTO") + # obtain sources used for building that executable + get_property(ARGN TARGET ${executable} PROPERTY SOURCES) + endif() foreach(source ${ARGN}) file(READ "${source}" contents) string(REGEX MATCHALL "TEST_?F?\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents}) diff --git a/Modules/FindHg.cmake b/Modules/FindHg.cmake index a1fb33f..c418afd 100644 --- a/Modules/FindHg.cmake +++ b/Modules/FindHg.cmake @@ -2,7 +2,7 @@ # FindHg # ------ # -# +# Extract information from a mercurial working copy. # # The module defines the following variables: # @@ -12,6 +12,20 @@ # HG_FOUND - true if the command line client was found # HG_VERSION_STRING - the version of mercurial found # +# If the command line client executable is found the following macro is defined: +# +# :: +# +# HG_WC_INFO(<dir> <var-prefix>) +# +# Hg_WC_INFO extracts information of a mercurial working copy +# at a given location. This macro defines the following variables: +# +# :: +# +# <var-prefix>_WC_CHANGESET - current changeset +# <var-prefix>_WC_REVISION - current revision +# # Example usage: # # :: @@ -19,11 +33,15 @@ # find_package(Hg) # if(HG_FOUND) # message("hg found: ${HG_EXECUTABLE}") +# HG_WC_INFO(${PROJECT_SOURCE_DIR} Project) +# message("Current revision is ${Project_WC_REVISION}") +# message("Current changeset is ${Project_WC_CHANGESET}") # endif() #============================================================================= # Copyright 2010-2012 Kitware, Inc. # Copyright 2012 Rolf Eike Beer <eike@sf-mail.de> +# Copyright 2014 Matthaeus G. Chajdas # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. @@ -37,6 +55,8 @@ find_program(HG_EXECUTABLE NAMES hg + PATHS + [HKEY_LOCAL_MACHINE\\Software\\TortoiseHG] PATH_SUFFIXES Mercurial DOC "hg command line client" ) @@ -51,6 +71,21 @@ if(HG_EXECUTABLE) set(HG_VERSION_STRING "${CMAKE_MATCH_1}") endif() unset(hg_version) + + macro(HG_WC_INFO dir prefix) + execute_process(COMMAND ${HG_EXECUTABLE} id -i -n + WORKING_DIRECTORY ${dir} + RESULT_VARIABLE hg_id_result + ERROR_VARIABLE hg_id_error + OUTPUT_VARIABLE ${prefix}_WC_DATA + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT ${hg_id_result} EQUAL 0) + message(SEND_ERROR "Command \"${HG_EXECUTBALE} id -n\" in directory ${dir} failed with output:\n${hg_id_error}") + endif() + + string(REGEX REPLACE "([0-9a-f]+)\\+? [0-9]+\\+?" "\\1" ${prefix}_WC_CHANGESET ${${prefix}_WC_DATA}) + string(REGEX REPLACE "[0-9a-f]+\\+? ([0-9]+)\\+?" "\\1" ${prefix}_WC_REVISION ${${prefix}_WC_DATA}) + endmacro(HG_WC_INFO) endif() # Handle the QUIETLY and REQUIRED arguments and set HG_FOUND to TRUE if diff --git a/Modules/FindOpenCL.cmake b/Modules/FindOpenCL.cmake new file mode 100644 index 0000000..eee06bf --- /dev/null +++ b/Modules/FindOpenCL.cmake @@ -0,0 +1,134 @@ +#.rst: +# FindOpenCL +# ---------- +# +# Try to find OpenCL +# +# Once done this will define:: +# +# OpenCL_FOUND - True if OpenCL was found +# OpenCL_INCLUDE_DIRS - include directories for OpenCL +# OpenCL_LIBRARIES - link against this library to use OpenCL +# OpenCL_VERSION_STRING - Highest supported OpenCL version (eg. 1.2) +# OpenCL_VERSION_MAJOR - The major version of the OpenCL implementation +# OpenCL_VERSION_MINOR - The minor version of the OpenCL implementation +# +# The module will also define two cache variables:: +# +# OpenCL_INCLUDE_DIR - the OpenCL include directory +# OpenCL_LIBRARY - the path to the OpenCL library +# + +#============================================================================= +# Copyright 2014 Matthaeus G. Chajdas +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +function(_FIND_OPENCL_VERSION) + include(CheckSymbolExists) + include(CMakePushCheckState) + + CMAKE_PUSH_CHECK_STATE() + foreach(VERSION "2_0" "1_2" "1_1" "1_0") + set(CMAKE_REQUIRED_INCLUDES "${OpenCL_INCLUDE_DIR}") + + if(APPLE) + CHECK_SYMBOL_EXISTS( + CL_VERSION_${VERSION} + "${OpenCL_INCLUDE_DIR}/OpenCL/cl.h" + OPENCL_VERSION_${VERSION}) + else() + CHECK_SYMBOL_EXISTS( + CL_VERSION_${VERSION} + "${OpenCL_INCLUDE_DIR}/CL/cl.h" + OPENCL_VERSION_${VERSION}) + endif() + + if(OPENCL_VERSION_${VERSION}) + string(REPLACE "_" "." VERSION "${VERSION}") + set(OpenCL_VERSION_STRING ${VERSION} PARENT_SCOPE) + string(REGEX MATCHALL "[0-9]+" version_components "${VERSION}") + list(GET version_components 0 major_version) + list(GET version_components 1 minor_version) + set(OpenCL_VERSION_MAJOR ${major_version} PARENT_SCOPE) + set(OpenCL_VERSION_MINOR ${minor_version} PARENT_SCOPE) + break() + endif() + endforeach() + CMAKE_POP_CHECK_STATE() +endfunction() + +find_path(OpenCL_INCLUDE_DIR + NAMES + CL/cl.h OpenCL/cl.h + PATHS ENV + "PROGRAMFILES(X86)" + AMDAPPSDKROOT + INTELOCLSDKROOT + NVSDKCOMPUTE_ROOT + CUDA_PATH + ATISTREAMSDKROOT + PATH_SUFFIXES + OpenCL/common/inc + "AMD APP/include") + +_FIND_OPENCL_VERSION() + +if(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + find_library(OpenCL_LIBRARY + NAMES OpenCL + PATHS ENV + "PROGRAMFILES(X86)" + AMDAPPSDKROOT + INTELOCLSDKROOT + CUDA_PATH + NVSDKCOMPUTE_ROOT + ATISTREAMSDKROOT + PATH_SUFFIXES + "AMD APP/lib/x86" + lib/x86 + lib/Win32 + OpenCL/common/lib/Win32) + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + find_library(OpenCL_LIBRARY + NAMES OpenCL + PATHS ENV + "PROGRAMFILES(X86)" + AMDAPPSDKROOT + INTELOCLSDKROOT + CUDA_PATH + NVSDKCOMPUTE_ROOT + ATISTREAMSDKROOT + PATH_SUFFIXES + "AMD APP/lib/x86_64" + lib/x86_64 + lib/x64 + OpenCL/common/lib/x64) + endif() +else() + find_library(OpenCL_LIBRARY + NAMES OpenCL) +endif() + +set(OpenCL_LIBRARIES ${OpenCL_LIBRARY}) +set(OpenCL_INCLUDE_DIRS ${OpenCL_INCLUDE_DIR}) + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +find_package_handle_standard_args( + OpenCL + FOUND_VAR OpenCL_FOUND + REQUIRED_VARS OpenCL_LIBRARY OpenCL_INCLUDE_DIR + VERSION_VAR OpenCL_VERSION_STRING) + +mark_as_advanced( + OpenCL_INCLUDE_DIR + OpenCL_LIBRARY) diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index e6fdefe..7179d17 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -6,6 +6,11 @@ # # # +# To find the pkg-config executable, it uses the variable +# PKG_CONFIG_EXECUTABLE or the environment variable PKG_CONFIG first. +# +# +# # Usage: # # :: @@ -134,8 +139,9 @@ # pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2) #============================================================================= -# Copyright 2006-2009 Kitware, Inc. -# Copyright 2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> +# Copyright 2006-2014 Kitware, Inc. +# Copyright 2014 Christoph Grüninger <foss@grueninger.de> +# Copyright 2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. @@ -150,6 +156,10 @@ ### Common stuff #### set(PKG_CONFIG_VERSION 1) +# find pkg-config, use PKG_CONFIG if set +if((NOT PKG_CONFIG_EXECUTABLE) AND (NOT "$ENV{PKG_CONFIG}" STREQUAL "")) + set(PKG_CONFIG_EXECUTABLE "$ENV{PKG_CONFIG}" CACHE FILEPATH "pkg-config executable") +endif() find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config DOC "pkg-config executable") mark_as_advanced(PKG_CONFIG_EXECUTABLE) diff --git a/Modules/FindPythonLibs.cmake b/Modules/FindPythonLibs.cmake index 0749efc..27d9e45 100644 --- a/Modules/FindPythonLibs.cmake +++ b/Modules/FindPythonLibs.cmake @@ -80,10 +80,15 @@ endif() # Set up the versions we know about, in the order we will search. Always add # the user supplied additional versions to the front. -set(_Python_VERSIONS - ${Python_ADDITIONAL_VERSIONS} - ${_PYTHON_FIND_OTHER_VERSIONS} - ) +# If FindPythonInterp has already found the major and minor version, +# insert that version between the user supplied versions and the stock +# version list. +find_package(PythonInterp QUIET) +set(_Python_VERSIONS ${Python_ADDITIONAL_VERSIONS}) +if(DEFINED PYTHON_VERSION_MAJOR AND DEFINED PYTHON_VERSION_MINOR) + list(APPEND _Python_VERSIONS ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}) +endif() +list(APPEND _Python_VERSIONS ${_PYTHON_FIND_OTHER_VERSIONS}) unset(_PYTHON_FIND_OTHER_VERSIONS) unset(_PYTHON1_VERSIONS) diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake index 9d9383d..aafdc09 100644 --- a/Modules/FindRuby.cmake +++ b/Modules/FindRuby.cmake @@ -5,7 +5,8 @@ # Find Ruby # # This module finds if Ruby is installed and determines where the -# include files and libraries are. Ruby 1.8 and 1.9 are supported. +# include files and libraries are. Ruby 1.8, 1.9, 2.0 and 2.1 are +# supported. # # The minimum required version of Ruby can be specified using the # standard syntax, e.g. find_package(Ruby 1.8) @@ -67,6 +68,8 @@ else() endif() if(NOT Ruby_FIND_VERSION_EXACT) + list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.1 ruby21) + list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.0 ruby20) list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby1.9 ruby19) # if we want a version below 1.9, also look for ruby 1.8 @@ -79,7 +82,6 @@ endif() find_program(RUBY_EXECUTABLE NAMES ${_RUBY_POSSIBLE_EXECUTABLE_NAMES}) - if(RUBY_EXECUTABLE AND NOT RUBY_VERSION_MAJOR) function(_RUBY_CONFIG_VAR RBVAR OUTVAR) execute_process(COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "print RbConfig::CONFIG['${RBVAR}']" @@ -105,6 +107,7 @@ if(RUBY_EXECUTABLE AND NOT RUBY_VERSION_MAJOR) _RUBY_CONFIG_VAR("archdir" RUBY_ARCH_DIR) _RUBY_CONFIG_VAR("arch" RUBY_ARCH) _RUBY_CONFIG_VAR("rubyhdrdir" RUBY_HDR_DIR) + _RUBY_CONFIG_VAR("rubyarchhdrdir" RUBY_ARCHHDR_DIR) _RUBY_CONFIG_VAR("libdir" RUBY_POSSIBLE_LIB_DIR) _RUBY_CONFIG_VAR("rubylibdir" RUBY_RUBY_LIB_DIR) @@ -126,7 +129,8 @@ if(RUBY_EXECUTABLE AND NOT RUBY_VERSION_MAJOR) set(RUBY_VERSION_MINOR ${RUBY_VERSION_MINOR} CACHE PATH "The Ruby minor version" FORCE) set(RUBY_VERSION_PATCH ${RUBY_VERSION_PATCH} CACHE PATH "The Ruby patch version" FORCE) set(RUBY_ARCH_DIR ${RUBY_ARCH_DIR} CACHE PATH "The Ruby arch dir" FORCE) - set(RUBY_HDR_DIR ${RUBY_HDR_DIR} CACHE PATH "The Ruby header dir (1.9)" FORCE) + set(RUBY_HDR_DIR ${RUBY_HDR_DIR} CACHE PATH "The Ruby header dir (1.9+)" FORCE) + set(RUBY_ARCHHDR_DIR ${RUBY_ARCHHDR_DIR} CACHE PATH "The Ruby arch header dir (2.0+)" FORCE) set(RUBY_POSSIBLE_LIB_DIR ${RUBY_POSSIBLE_LIB_DIR} CACHE PATH "The Ruby lib dir" FORCE) set(RUBY_RUBY_LIB_DIR ${RUBY_RUBY_LIB_DIR} CACHE PATH "The Ruby ruby-lib dir" FORCE) set(RUBY_SITEARCH_DIR ${RUBY_SITEARCH_DIR} CACHE PATH "The Ruby site arch dir" FORCE) @@ -139,6 +143,7 @@ if(RUBY_EXECUTABLE AND NOT RUBY_VERSION_MAJOR) RUBY_ARCH_DIR RUBY_ARCH RUBY_HDR_DIR + RUBY_ARCHHDR_DIR RUBY_POSSIBLE_LIB_DIR RUBY_RUBY_LIB_DIR RUBY_SITEARCH_DIR @@ -160,10 +165,20 @@ if(RUBY_EXECUTABLE AND NOT RUBY_VERSION_MAJOR) set(RUBY_VERSION_MINOR 8) set(RUBY_VERSION_PATCH 0) # check whether we found 1.9.x - if(${RUBY_EXECUTABLE} MATCHES "ruby1.?9" OR RUBY_HDR_DIR) + if(${RUBY_EXECUTABLE} MATCHES "ruby1.?9") set(RUBY_VERSION_MAJOR 1) set(RUBY_VERSION_MINOR 9) endif() + # check whether we found 2.0.x + if(${RUBY_EXECUTABLE} MATCHES "ruby2.?0") + set(RUBY_VERSION_MAJOR 2) + set(RUBY_VERSION_MINOR 0) + endif() + # check whether we found 2.1.x + if(${RUBY_EXECUTABLE} MATCHES "ruby2.?1") + set(RUBY_VERSION_MAJOR 2) + set(RUBY_VERSION_MINOR 1) + endif() endif() if(RUBY_VERSION_MAJOR) @@ -189,6 +204,7 @@ if( "${Ruby_FIND_VERSION_SHORT_NODOT}" GREATER 18 OR "${_RUBY_VERSION_SHORT_NO HINTS ${RUBY_HDR_DIR}/${RUBY_ARCH} ${RUBY_ARCH_DIR} + ${RUBY_ARCHHDR_DIR} ) set(RUBY_INCLUDE_DIRS ${RUBY_INCLUDE_DIRS} ${RUBY_CONFIG_INCLUDE_DIR} ) diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index e29aaf4..5732170 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -241,7 +241,7 @@ macro(__windows_compiler_msvc lang) set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_LINKER> /lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ") set(CMAKE_${lang}_COMPILE_OBJECT - "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> /Fo<OBJECT> /Fd<OBJECT_DIR>/${_FS_${lang}} -c <SOURCE>${CMAKE_END_TEMP_FILE}") + "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> /Fo<OBJECT> /Fd<TARGET_COMPILE_PDB>${_FS_${lang}} -c <SOURCE>${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> > <PREPROCESSED_SOURCE> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> -E <SOURCE>${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE diff --git a/Modules/Platform/Windows-wcl386.cmake b/Modules/Platform/Windows-wcl386.cmake index 8a03b29..d40d718 100644 --- a/Modules/Platform/Windows-wcl386.cmake +++ b/Modules/Platform/Windows-wcl386.cmake @@ -40,7 +40,7 @@ set (CMAKE_C_STANDARD_LIBRARIES_INIT "library clbrdll.lib library plbrdll.lib l set (CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") set(CMAKE_C_CREATE_IMPORT_LIBRARY - "wlib -c -q -n -b <TARGET_IMPLIB> +'<TARGET_UNQUOTED>'") + "wlib -c -q -n -b <TARGET_IMPLIB> +<TARGET_QUOTED>") set(CMAKE_CXX_CREATE_IMPORT_LIBRARY ${CMAKE_C_CREATE_IMPORT_LIBRARY}) set(CMAKE_C_LINK_EXECUTABLE @@ -65,11 +65,10 @@ set(CMAKE_C_CREATE_PREPROCESSED_SOURCE set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_WCL_QUIET} <FLAGS> -dWIN32 -d+ <DEFINES> -fo<PREPROCESSED_SOURCE> -pl -cc++ <SOURCE>${CMAKE_END_TEMP_FILE}") -set(CMAKE_CXX_CREATE_SHARED_MODULE - "wlink ${CMAKE_START_TEMP_FILE} system nt_dll ${CMAKE_WLINK_QUIET} name '<TARGET_UNQUOTED>' <LINK_FLAGS> option caseexact file {<OBJECTS>} <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}") set(CMAKE_CXX_CREATE_SHARED_LIBRARY - ${CMAKE_CXX_CREATE_SHARED_MODULE} - ${CMAKE_CXX_CREATE_IMPORT_LIBRARY}) + "wlink ${CMAKE_START_TEMP_FILE} system nt_dll ${CMAKE_WLINK_QUIET} name '<TARGET_UNQUOTED>' <LINK_FLAGS> option implib=<TARGET_IMPLIB> option caseexact file {<OBJECTS>} <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}") +string(REPLACE " option implib=<TARGET_IMPLIB>" "" + CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_LIBRARY}") # create a C shared library set(CMAKE_C_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY}) @@ -78,7 +77,7 @@ set(CMAKE_C_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY}) set(CMAKE_C_CREATE_SHARED_MODULE ${CMAKE_CXX_CREATE_SHARED_MODULE}) # create a C++ static library -set(CMAKE_CXX_CREATE_STATIC_LIBRARY "wlib ${CMAKE_LIB_QUIET} -c -n -b '<TARGET_UNQUOTED>' <LINK_FLAGS> <OBJECTS> ") +set(CMAKE_CXX_CREATE_STATIC_LIBRARY "wlib ${CMAKE_LIB_QUIET} -c -n -b <TARGET_QUOTED> <LINK_FLAGS> <OBJECTS> ") # create a C static library set(CMAKE_C_CREATE_STATIC_LIBRARY ${CMAKE_CXX_CREATE_STATIC_LIBRARY}) diff --git a/Modules/UseQt4.cmake b/Modules/UseQt4.cmake index 7478310..cba22af 100644 --- a/Modules/UseQt4.cmake +++ b/Modules/UseQt4.cmake @@ -98,7 +98,9 @@ foreach(module QT3SUPPORT QTOPENGL QTASSISTANT QTDESIGNER QTMOTIF QTNSPLUGIN include_directories(SYSTEM ${QT_${module}_INCLUDE_DIR}) endif(QT_INCLUDE_DIRS_NO_SYSTEM) endif() - set(QT_LIBRARIES ${QT_LIBRARIES} ${QT_${module}_LIBRARY}) + if(QT_USE_${module} OR QT_IS_STATIC) + set(QT_LIBRARIES ${QT_LIBRARIES} ${QT_${module}_LIBRARY}) + endif() set(QT_LIBRARIES_PLUGINS ${QT_LIBRARIES_PLUGINS} ${QT_${module}_PLUGINS}) if(QT_IS_STATIC) set(QT_LIBRARIES ${QT_LIBRARIES} ${QT_${module}_LIB_DEPENDENCIES}) diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 11ca205..4ae6f81 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -85,9 +85,6 @@ macro(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile) set(${outfiles} "") get_source_file_property(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename ${infile} SWIG_MODULE_NAME) - if(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND") - get_filename_component(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${infile}" NAME_WE) - endif() foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSION}) set(${outfiles} ${${outfiles}} "${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}.${it}") @@ -103,6 +100,10 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) get_source_file_property(swig_source_file_generated ${infile} GENERATED) get_source_file_property(swig_source_file_cplusplus ${infile} CPLUSPLUS) get_source_file_property(swig_source_file_flags ${infile} SWIG_FLAGS) + get_source_file_property(_SWIG_MODULE_NAME ${infile} SWIG_MODULE_NAME) + if ( NOT _SWIG_MODULE_NAME ) + set_source_files_properties(${infile} PROPERTIES SWIG_MODULE_NAME ${name}) + endif () if("${swig_source_file_flags}" STREQUAL "NOTFOUND") set(swig_source_file_flags "") endif() diff --git a/Modules/WIX.template.in b/Modules/WIX.template.in index 59a75c7..bbb7c88 100644 --- a/Modules/WIX.template.in +++ b/Modules/WIX.template.in @@ -40,5 +40,7 @@ <FeatureRef Id="ProductFeature"/> <UIRef Id="$(var.CPACK_WIX_UI_REF)" /> + + <?include "properties.wxi"?> </Product> </Wix> diff --git a/Source/CMakeInstallDestinations.cmake b/Source/CMakeInstallDestinations.cmake index 3e93d41..99c86ca 100644 --- a/Source/CMakeInstallDestinations.cmake +++ b/Source/CMakeInstallDestinations.cmake @@ -1,15 +1,15 @@ # Keep formatting here consistent with bootstrap script expectations. if(BEOS) - set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") # HAIKU + set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # HAIKU set(CMAKE_MAN_DIR_DEFAULT "documentation/man") # HAIKU - set(CMAKE_DOC_DIR_DEFAULT "documentation/doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") # HAIKU + set(CMAKE_DOC_DIR_DEFAULT "documentation/doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # HAIKU elseif(CYGWIN) set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION}") # CYGWIN set(CMAKE_DOC_DIR_DEFAULT "share/doc/cmake-${CMake_VERSION}") # CYGWIN set(CMAKE_MAN_DIR_DEFAULT "share/man") # CYGWIN else() - set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") # OTHER - set(CMAKE_DOC_DIR_DEFAULT "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") # OTHER + set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # OTHER + set(CMAKE_DOC_DIR_DEFAULT "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # OTHER set(CMAKE_MAN_DIR_DEFAULT "man") # OTHER endif() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 175a034..966e0f6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -562,7 +562,11 @@ if(WIN32) set(CPACK_SRCS ${CPACK_SRCS} CPack/WiX/cmCPackWIXGenerator.cxx CPack/WiX/cmWIXSourceWriter.cxx + CPack/WiX/cmWIXDirectoriesSourceWriter.cxx + CPack/WiX/cmWIXFeaturesSourceWriter.cxx + CPack/WiX/cmWIXFilesSourceWriter.cxx CPack/WiX/cmWIXRichTextFormatWriter.cxx + CPack/WiX/cmWIXPatch.cxx CPack/WiX/cmWIXPatchParser.cxx ) endif() diff --git a/Source/CMakeVersion.bash b/Source/CMakeVersion.bash index 4794e60..853b0ca 100755 --- a/Source/CMakeVersion.bash +++ b/Source/CMakeVersion.bash @@ -3,5 +3,5 @@ if test "x$1" = "x-f"; then shift ; n='*' ; else n='\{8\}' ; fi if test "$#" -gt 0; then echo 1>&2 "usage: CMakeVersion.bash [-f]"; exit 1; fi sed -i -e ' -s/\(^set(CMake_VERSION_TWEAK\) [0-9]'"$n"'\(.*\)/\1 '"$(date +%Y%m%d)"'\2/ +s/\(^set(CMake_VERSION_PATCH\) [0-9]'"$n"'\(.*\)/\1 '"$(date +%Y%m%d)"'\2/ ' "${BASH_SOURCE%/*}/CMakeVersion.cmake" diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9e60e71..3262d09 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,6 +1,5 @@ # CMake version number components. -set(CMake_VERSION_MAJOR 2) -set(CMake_VERSION_MINOR 8) -set(CMake_VERSION_PATCH 12) -set(CMake_VERSION_TWEAK 20140219) +set(CMake_VERSION_MAJOR 3) +set(CMake_VERSION_MINOR 0) +set(CMake_VERSION_PATCH 20140303) #set(CMake_VERSION_RC 1) diff --git a/Source/CMakeVersionCompute.cmake b/Source/CMakeVersionCompute.cmake index a166334..496d6cf 100644 --- a/Source/CMakeVersionCompute.cmake +++ b/Source/CMakeVersionCompute.cmake @@ -1,8 +1,8 @@ # Load version number components. include(${CMake_SOURCE_DIR}/Source/CMakeVersion.cmake) -# Releases define a small tweak level. -if("${CMake_VERSION_TWEAK}" VERSION_LESS 20000000) +# Releases define a small patch level. +if("${CMake_VERSION_PATCH}" VERSION_LESS 20000000) set(CMake_VERSION_IS_RELEASE 1) set(CMake_VERSION_SOURCE "") else() @@ -12,9 +12,6 @@ endif() # Compute the full version string. set(CMake_VERSION ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}) -if(${CMake_VERSION_TWEAK} GREATER 0) - set(CMake_VERSION ${CMake_VERSION}.${CMake_VERSION_TWEAK}) -endif() if(CMake_VERSION_RC) set(CMake_VERSION ${CMake_VERSION}-rc${CMake_VERSION_RC}) endif() diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 43119d6..a385e40 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -1,6 +1,6 @@ /*============================================================================ CMake - Cross Platform Makefile Generator - Copyright 2000-2013 Kitware, Inc., Insight Software Consortium + Copyright 2000-2014 Kitware, Inc., Insight Software Consortium Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. @@ -19,6 +19,9 @@ #include <CPack/cmCPackComponentGroup.h> #include "cmWIXSourceWriter.h" +#include "cmWIXDirectoriesSourceWriter.h" +#include "cmWIXFeaturesSourceWriter.h" +#include "cmWIXFilesSourceWriter.h" #include "cmWIXRichTextFormatWriter.h" #include <cmsys/SystemTools.hxx> @@ -28,11 +31,9 @@ #include <rpc.h> // for GUID generation -#include <sys/types.h> -#include <sys/stat.h> - cmCPackWIXGenerator::cmCPackWIXGenerator(): - HasDesktopShortcuts(false) + HasDesktopShortcuts(false), + Patch(Logger) { } @@ -44,15 +45,9 @@ int cmCPackWIXGenerator::InitializeInternal() return this->Superclass::InitializeInternal(); } -bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command) +bool cmCPackWIXGenerator::RunWiXCommand(std::string const& command) { - std::string cpackTopLevel; - if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) - { - return false; - } - - std::string logFileName = cpackTopLevel + "/wix.log"; + std::string logFileName = this->CPackTopLevel + "/wix.log"; cmCPackLogger(cmCPackLog::LOG_DEBUG, "Running WiX command: " << command << std::endl); @@ -81,7 +76,7 @@ bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command) } bool cmCPackWIXGenerator::RunCandleCommand( - const std::string& sourceFile, const std::string& objectFile) + std::string const& sourceFile, std::string const& objectFile) { std::string executable; if(!RequireOption("CPACK_WIX_CANDLE_EXECUTABLE", executable)) @@ -108,7 +103,7 @@ bool cmCPackWIXGenerator::RunCandleCommand( return RunWiXCommand(command.str()); } -bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles) +bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles) { std::string executable; if(!RequireOption("CPACK_WIX_LIGHT_EXECUTABLE", executable)) @@ -121,8 +116,8 @@ bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles) command << " -nologo"; command << " -out " << QuotePath(packageFileNames.at(0)); - for(extension_set_t::const_iterator i = LightExtensions.begin(); - i != LightExtensions.end(); ++i) + for(extension_set_t::const_iterator i = this->LightExtensions.begin(); + i != this->LightExtensions.end(); ++i) { command << " -ext " << QuotePath(*i); } @@ -182,15 +177,14 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() "you might want to set this explicitly." << std::endl); } - std::string cpackTopLevel; - if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) + if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", this->CPackTopLevel)) { return false; } if(GetOption("CPACK_WIX_LICENSE_RTF") == 0) { - std::string licenseFilename = cpackTopLevel + "/License.rtf"; + std::string licenseFilename = this->CPackTopLevel + "/License.rtf"; SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str()); if(!CreateLicenseFile()) @@ -213,7 +207,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() { std::string defaultRef = "WixUI_InstallDir"; - if(Components.size()) + if(this->Components.size()) { defaultRef = "WixUI_FeatureTree"; } @@ -221,17 +215,24 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() SetOption("CPACK_WIX_UI_REF", defaultRef.c_str()); } - CollectExtensions("CPACK_WIX_EXTENSIONS", CandleExtensions); - CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", CandleExtensions); + const char* packageContact = GetOption("CPACK_PACKAGE_CONTACT"); + if(packageContact != 0 && + GetOption("CPACK_WIX_PROPERTY_ARPCONTACT") == 0) + { + SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact); + } + + CollectExtensions("CPACK_WIX_EXTENSIONS", this->CandleExtensions); + CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", this->CandleExtensions); - LightExtensions.insert("WixUIExtension"); - CollectExtensions("CPACK_WIX_EXTENSIONS", LightExtensions); - CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", LightExtensions); + this->LightExtensions.insert("WixUIExtension"); + CollectExtensions("CPACK_WIX_EXTENSIONS", this->LightExtensions); + CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions); const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); if(patchFilePath) { - LoadPatchFragments(patchFilePath); + this->Patch.LoadFragments(patchFilePath); } return true; @@ -244,10 +245,8 @@ bool cmCPackWIXGenerator::PackageFilesImpl() return false; } - if(!CreateWiXVariablesIncludeFile()) - { - return false; - } + CreateWiXVariablesIncludeFile(); + CreateWiXPropertiesIncludeFile(); if(!CreateWiXSourceFiles()) { @@ -257,9 +256,9 @@ bool cmCPackWIXGenerator::PackageFilesImpl() AppendUserSuppliedExtraSources(); std::stringstream objectFiles; - for(size_t i = 0; i < WixSources.size(); ++i) + for(size_t i = 0; i < this->WixSources.size(); ++i) { - const std::string& sourceFilename = WixSources[i]; + std::string const& sourceFilename = this->WixSources[i]; std::string objectFilename = cmSystemTools::GetFilenameWithoutExtension(sourceFilename) + ".wixobj"; @@ -282,7 +281,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() const char *cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES"); if(!cpackWixExtraSources) return; - cmSystemTools::ExpandListArgument(cpackWixExtraSources, WixSources); + cmSystemTools::ExpandListArgument(cpackWixExtraSources, this->WixSources); } void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) @@ -297,22 +296,18 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) for(size_t i = 0; i < expandedExtraObjects.size(); ++i) { - stream << " " << QuotePath(expandedExtraObjects[i]); + stream << " " << QuotePath(expandedExtraObjects[i]); } } -bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() +void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() { - std::string cpackTopLevel; - if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) - { - return false; - } - std::string includeFilename = - cpackTopLevel + "/cpack_variables.wxi"; + this->CPackTopLevel + "/cpack_variables.wxi"; + + cmWIXSourceWriter includeFile( + this->Logger, includeFilename, true); - cmWIXSourceWriter includeFile(Logger, includeFilename, true); CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_GUID"); CopyDefinition(includeFile, "CPACK_WIX_UPGRADE_GUID"); CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR"); @@ -326,12 +321,39 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() GetOption("CPACK_PACKAGE_NAME")); CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER"); CopyDefinition(includeFile, "CPACK_WIX_UI_REF"); +} - return true; +void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile() +{ + std::string includeFilename = + this->CPackTopLevel + "/properties.wxi"; + + cmWIXSourceWriter includeFile( + this->Logger, includeFilename, true); + + std::string prefix = "CPACK_WIX_PROPERTY_"; + std::vector<std::string> options = GetOptions(); + + for(size_t i = 0; i < options.size(); ++i) + { + std::string const& name = options[i]; + + if(name.length() > prefix.length() && + name.substr(0, prefix.length()) == prefix) + { + std::string id = name.substr(prefix.length()); + std::string value = GetOption(name.c_str()); + + includeFile.BeginElement("Property"); + includeFile.AddAttribute("Id", id); + includeFile.AddAttribute("Value", value); + includeFile.EndElement("Property"); + } + } } void cmCPackWIXGenerator::CopyDefinition( - cmWIXSourceWriter &source, const std::string &name) + cmWIXSourceWriter &source, std::string const& name) { const char* value = GetOption(name.c_str()); if(value) @@ -341,7 +363,7 @@ void cmCPackWIXGenerator::CopyDefinition( } void cmCPackWIXGenerator::AddDefinition(cmWIXSourceWriter& source, - const std::string& name, const std::string& value) + std::string const& name, std::string const& value) { std::stringstream tmp; tmp << name << "=\"" << value << '"'; @@ -352,81 +374,47 @@ void cmCPackWIXGenerator::AddDefinition(cmWIXSourceWriter& source, bool cmCPackWIXGenerator::CreateWiXSourceFiles() { - std::string cpackTopLevel; - if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) - { - return false; - } - std::string directoryDefinitionsFilename = - cpackTopLevel + "/directories.wxs"; + this->CPackTopLevel + "/directories.wxs"; - WixSources.push_back(directoryDefinitionsFilename); + this->WixSources.push_back(directoryDefinitionsFilename); - cmWIXSourceWriter directoryDefinitions(Logger, directoryDefinitionsFilename); + cmWIXDirectoriesSourceWriter directoryDefinitions( + this->Logger, directoryDefinitionsFilename); directoryDefinitions.BeginElement("Fragment"); - directoryDefinitions.BeginElement("Directory"); - directoryDefinitions.AddAttribute("Id", "TARGETDIR"); - directoryDefinitions.AddAttribute("Name", "SourceDir"); - - directoryDefinitions.BeginElement("Directory"); - if(GetArchitecture() == "x86") - { - directoryDefinitions.AddAttribute("Id", "ProgramFilesFolder"); - } - else - { - directoryDefinitions.AddAttribute("Id", "ProgramFiles64Folder"); - } - - std::vector<std::string> install_root; - - std::string tmp; - if(!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", tmp)) + std::string installRoot; + if(!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", installRoot)) { return false; } - cmSystemTools::SplitPath(tmp.c_str(), install_root); - - if(!install_root.empty() && install_root.back().empty()) - { - install_root.pop_back(); - } - - for(size_t i = 1; i < install_root.size(); ++i) - { - directoryDefinitions.BeginElement("Directory"); - - if(i == install_root.size() - 1) - { - directoryDefinitions.AddAttribute("Id", "INSTALL_ROOT"); - } - else - { - std::stringstream ss; - ss << "INSTALL_PREFIX_" << i; - directoryDefinitions.AddAttribute("Id", ss.str()); - } + directoryDefinitions.BeginElement("Directory"); + directoryDefinitions.AddAttribute("Id", "TARGETDIR"); + directoryDefinitions.AddAttribute("Name", "SourceDir"); - directoryDefinitions.AddAttribute("Name", install_root[i]); - } + size_t installRootSize = + directoryDefinitions.BeginInstallationPrefixDirectory( + GetProgramFilesFolderId(), installRoot); std::string fileDefinitionsFilename = - cpackTopLevel + "/files.wxs"; + this->CPackTopLevel + "/files.wxs"; + + this->WixSources.push_back(fileDefinitionsFilename); - WixSources.push_back(fileDefinitionsFilename); + cmWIXFilesSourceWriter fileDefinitions( + this->Logger, fileDefinitionsFilename); - cmWIXSourceWriter fileDefinitions(Logger, fileDefinitionsFilename); fileDefinitions.BeginElement("Fragment"); std::string featureDefinitionsFilename = - cpackTopLevel +"/features.wxs"; + this->CPackTopLevel +"/features.wxs"; - WixSources.push_back(featureDefinitionsFilename); + this->WixSources.push_back(featureDefinitionsFilename); + + cmWIXFeaturesSourceWriter featureDefinitions( + this->Logger, featureDefinitionsFilename); - cmWIXSourceWriter featureDefinitions(Logger, featureDefinitionsFilename); featureDefinitions.BeginElement("Fragment"); featureDefinitions.BeginElement("Feature"); @@ -439,13 +427,15 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() { return false; } - featureDefinitions.AddAttribute("Title", cpackPackageName); + featureDefinitions.AddAttribute("Title", cpackPackageName); featureDefinitions.AddAttribute("Level", "1"); - if(!CreateCMakePackageRegistryEntry(featureDefinitions)) + const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); + if(package) { - return false; + featureDefinitions.CreateCMakePackageRegistryEntry( + package, GetOption("CPACK_WIX_UPGRADE_GUID")); } if(!CreateFeatureHierarchy(featureDefinitions)) @@ -471,7 +461,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() else { for(std::map<std::string, cmCPackComponent>::const_iterator - i = Components.begin(); i != Components.end(); ++i) + i = this->Components.begin(); i != this->Components.end(); ++i) { cmCPackComponent const& component = i->second; @@ -513,31 +503,51 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() featureDefinitions.EndElement("Fragment"); fileDefinitions.EndElement("Fragment"); - for(size_t i = 1; i < install_root.size(); ++i) - { - directoryDefinitions.EndElement("Directory"); - } - - directoryDefinitions.EndElement("Directory"); + directoryDefinitions.EndInstallationPrefixDirectory( + installRootSize); if(hasShortcuts) { - CreateStartMenuFolder(directoryDefinitions); + directoryDefinitions.EmitStartMenuFolder( + GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER")); } if(this->HasDesktopShortcuts) { - CreateDesktopFolder(directoryDefinitions); + directoryDefinitions.EmitDesktopFolder(); } directoryDefinitions.EndElement("Directory"); directoryDefinitions.EndElement("Fragment"); + if(!GenerateMainSourceFileFromTemplate()) + { + return false; + } + + return this->Patch.CheckForUnappliedFragments(); +} + +std::string cmCPackWIXGenerator::GetProgramFilesFolderId() const +{ + if(GetArchitecture() == "x86") + { + return "ProgramFilesFolder"; + } + else + { + return "ProgramFiles64Folder"; + } +} + +bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate() +{ std::string wixTemplate = FindTemplate("WIX.template.in"); if(GetOption("CPACK_WIX_TEMPLATE") != 0) { wixTemplate = GetOption("CPACK_WIX_TEMPLATE"); } + if(wixTemplate.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -545,7 +555,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() return false; } - std::string mainSourceFilePath = cpackTopLevel + "/main.wxs"; + std::string mainSourceFilePath = this->CPackTopLevel + "/main.wxs"; if(!ConfigureFile(wixTemplate.c_str(), mainSourceFilePath .c_str())) { @@ -556,68 +566,13 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() return false; } - WixSources.push_back(mainSourceFilePath); - - std::string fragmentList; - for(cmWIXPatchParser::fragment_map_t::const_iterator - i = Fragments.begin(); i != Fragments.end(); ++i) - { - if(!fragmentList.empty()) - { - fragmentList += ", "; - } - - fragmentList += "'"; - fragmentList += i->first; - fragmentList += "'"; - } - - if(fragmentList.size()) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Some XML patch fragments did not have matching IDs: " << - fragmentList << std::endl); - return false; - } - - return true; -} - -bool cmCPackWIXGenerator::CreateCMakePackageRegistryEntry( - cmWIXSourceWriter& featureDefinitions) -{ - const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); - if(!package) - { - return true; - } - - featureDefinitions.BeginElement("Component"); - featureDefinitions.AddAttribute("Id", "CM_PACKAGE_REGISTRY"); - featureDefinitions.AddAttribute("Directory", "TARGETDIR"); - featureDefinitions.AddAttribute("Guid", "*"); - - std::string registryKey = - std::string("Software\\Kitware\\CMake\\Packages\\") + package; - - std::string upgradeGuid = GetOption("CPACK_WIX_UPGRADE_GUID"); - - featureDefinitions.BeginElement("RegistryValue"); - featureDefinitions.AddAttribute("Root", "HKLM"); - featureDefinitions.AddAttribute("Key", registryKey); - featureDefinitions.AddAttribute("Name", upgradeGuid); - featureDefinitions.AddAttribute("Type", "string"); - featureDefinitions.AddAttribute("Value", "[INSTALL_ROOT]"); - featureDefinitions.AddAttribute("KeyPath", "yes"); - featureDefinitions.EndElement("RegistryValue"); - - featureDefinitions.EndElement("Component"); + this->WixSources.push_back(mainSourceFilePath); return true; } bool cmCPackWIXGenerator::CreateFeatureHierarchy( - cmWIXSourceWriter& featureDefinitions) + cmWIXFeaturesSourceWriter& featureDefinitions) { for(std::map<std::string, cmCPackComponentGroup>::const_iterator i = ComponentGroups.begin(); i != ComponentGroups.end(); ++i) @@ -625,105 +580,30 @@ bool cmCPackWIXGenerator::CreateFeatureHierarchy( cmCPackComponentGroup const& group = i->second; if(group.ParentGroup == 0) { - if(!EmitFeatureForComponentGroup(featureDefinitions, group)) - { - return false; - } + featureDefinitions.EmitFeatureForComponentGroup(group); } } for(std::map<std::string, cmCPackComponent>::const_iterator - i = Components.begin(); i != Components.end(); ++i) + i = this->Components.begin(); i != this->Components.end(); ++i) { cmCPackComponent const& component = i->second; if(!component.Group) { - if(!EmitFeatureForComponent(featureDefinitions, component)) - { - return false; - } - } - } - - return true; -} - -bool cmCPackWIXGenerator::EmitFeatureForComponentGroup( - cmWIXSourceWriter& featureDefinitions, - cmCPackComponentGroup const& group) -{ - featureDefinitions.BeginElement("Feature"); - featureDefinitions.AddAttribute("Id", "CM_G_" + group.Name); - - if(group.IsExpandedByDefault) - { - featureDefinitions.AddAttribute("Display", "expand"); - } - - featureDefinitions.AddAttributeUnlessEmpty( - "Title", group.DisplayName); - - featureDefinitions.AddAttributeUnlessEmpty( - "Description", group.Description); - - for(std::vector<cmCPackComponentGroup*>::const_iterator - i = group.Subgroups.begin(); i != group.Subgroups.end(); ++i) - { - if(!EmitFeatureForComponentGroup(featureDefinitions, **i)) - { - return false; - } - } - - for(std::vector<cmCPackComponent*>::const_iterator - i = group.Components.begin(); i != group.Components.end(); ++i) - { - if(!EmitFeatureForComponent(featureDefinitions, **i)) - { - return false; + featureDefinitions.EmitFeatureForComponent(component); } } - featureDefinitions.EndElement("Feature"); - - return true; -} - -bool cmCPackWIXGenerator::EmitFeatureForComponent( - cmWIXSourceWriter& featureDefinitions, - cmCPackComponent const& component) -{ - featureDefinitions.BeginElement("Feature"); - featureDefinitions.AddAttribute("Id", "CM_C_" + component.Name); - - featureDefinitions.AddAttributeUnlessEmpty( - "Title", component.DisplayName); - - featureDefinitions.AddAttributeUnlessEmpty( - "Description", component.Description); - - if(component.IsRequired) - { - featureDefinitions.AddAttribute("Absent", "disallow"); - } - - if(component.IsHidden) - { - featureDefinitions.AddAttribute("Display", "hidden"); - } - - featureDefinitions.EndElement("Feature"); - return true; } bool cmCPackWIXGenerator::AddComponentsToFeature( std::string const& rootPath, std::string const& featureId, - cmWIXSourceWriter& directoryDefinitions, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions, + cmWIXDirectoriesSourceWriter& directoryDefinitions, + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions, shortcut_map_t& shortcutMap) { featureDefinitions.BeginElement("FeatureRef"); @@ -768,8 +648,8 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( std::string const& cpackComponentName, std::string const& featureId, shortcut_map_t& shortcutMap, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions) + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions) { bool thisHasDesktopShortcuts = false; @@ -799,6 +679,7 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( fileDefinitions.BeginElement("DirectoryRef"); fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + fileDefinitions.BeginElement("Component"); fileDefinitions.AddAttribute("Id", componentId); fileDefinitions.AddAttribute("Guid", "*"); @@ -809,63 +690,34 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( std::string const& id = i->first; cmWIXShortcut const& shortcut = i->second; - std::string shortcutId = std::string("CM_S") + id; - std::string fileId = std::string("CM_F") + id; - - fileDefinitions.BeginElement("Shortcut"); - fileDefinitions.AddAttribute("Id", shortcutId); - fileDefinitions.AddAttribute("Name", shortcut.textLabel); - std::string target = "[#" + fileId + "]"; - fileDefinitions.AddAttribute("Target", target); - fileDefinitions.AddAttribute("WorkingDirectory", - shortcut.workingDirectoryId); - fileDefinitions.EndElement("Shortcut"); + fileDefinitions.EmitShortcut(id, shortcut, false); - if (shortcut.desktop) + if(shortcut.desktop) { - thisHasDesktopShortcuts = true; + thisHasDesktopShortcuts = true; } } if(cpackComponentName.empty()) { - CreateUninstallShortcut(cpackPackageName, fileDefinitions); + fileDefinitions.EmitUninstallShortcut(cpackPackageName); } - fileDefinitions.BeginElement("RemoveFolder"); - fileDefinitions.AddAttribute("Id", + fileDefinitions.EmitRemoveFolder( "CM_REMOVE_PROGRAM_MENU_FOLDER" + idSuffix); - fileDefinitions.AddAttribute("On", "uninstall"); - fileDefinitions.EndElement("RemoveFolder"); std::string registryKey = std::string("Software\\") + cpackVendor + "\\" + cpackPackageName; - fileDefinitions.BeginElement("RegistryValue"); - fileDefinitions.AddAttribute("Root", "HKCU"); - fileDefinitions.AddAttribute("Key", registryKey); - - std::string valueName; - if(!cpackComponentName.empty()) - { - valueName = cpackComponentName + "_"; - } - valueName += "installed"; - - fileDefinitions.AddAttribute("Name", valueName); - fileDefinitions.AddAttribute("Type", "integer"); - fileDefinitions.AddAttribute("Value", "1"); - fileDefinitions.AddAttribute("KeyPath", "yes"); - fileDefinitions.EndElement("RegistryValue"); + fileDefinitions.EmitStartMenuShortcutRegistryValue( + registryKey, cpackComponentName); fileDefinitions.EndElement("Component"); fileDefinitions.EndElement("DirectoryRef"); - featureDefinitions.BeginElement("ComponentRef"); - featureDefinitions.AddAttribute("Id", componentId); - featureDefinitions.EndElement("ComponentRef"); + featureDefinitions.EmitComponentRef(componentId); - if (thisHasDesktopShortcuts) + if(thisHasDesktopShortcuts) { this->HasDesktopShortcuts = true; componentId = "CM_DESKTOP_SHORTCUT" + idSuffix; @@ -876,7 +728,7 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( fileDefinitions.AddAttribute("Id", componentId); fileDefinitions.AddAttribute("Guid", "*"); - for (shortcut_map_t::const_iterator + for(shortcut_map_t::const_iterator i = shortcutMap.begin(); i != shortcutMap.end(); ++i) { std::string const& id = i->first; @@ -885,34 +737,16 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( if (!shortcut.desktop) continue; - std::string shortcutId = std::string("CM_DS") + id; - std::string fileId = std::string("CM_F") + id; - - fileDefinitions.BeginElement("Shortcut"); - fileDefinitions.AddAttribute("Id", shortcutId); - fileDefinitions.AddAttribute("Name", shortcut.textLabel); - std::string target = "[#" + fileId + "]"; - fileDefinitions.AddAttribute("Target", target); - fileDefinitions.AddAttribute("WorkingDirectory", - shortcut.workingDirectoryId); - fileDefinitions.EndElement("Shortcut"); + fileDefinitions.EmitShortcut(id, shortcut, true); } - fileDefinitions.BeginElement("RegistryValue"); - fileDefinitions.AddAttribute("Root", "HKCU"); - fileDefinitions.AddAttribute("Key", registryKey); - fileDefinitions.AddAttribute("Name", valueName + "_desktop"); - fileDefinitions.AddAttribute("Type", "integer"); - fileDefinitions.AddAttribute("Value", "1"); - fileDefinitions.AddAttribute("KeyPath", "yes"); - fileDefinitions.EndElement("RegistryValue"); + fileDefinitions.EmitDesktopShortcutRegistryValue( + registryKey, cpackComponentName); fileDefinitions.EndElement("Component"); fileDefinitions.EndElement("DirectoryRef"); - featureDefinitions.BeginElement("ComponentRef"); - featureDefinitions.AddAttribute("Id", componentId); - featureDefinitions.EndElement("ComponentRef"); + featureDefinitions.EmitComponentRef(componentId); } featureDefinitions.EndElement("FeatureRef"); @@ -920,19 +754,6 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( return true; } -void cmCPackWIXGenerator::CreateUninstallShortcut( - std::string const& packageName, - cmWIXSourceWriter& fileDefinitions) -{ - fileDefinitions.BeginElement("Shortcut"); - fileDefinitions.AddAttribute("Id", "UNINSTALL"); - fileDefinitions.AddAttribute("Name", "Uninstall " + packageName); - fileDefinitions.AddAttribute("Description", "Uninstalls " + packageName); - fileDefinitions.AddAttribute("Target", "[SystemFolder]msiexec.exe"); - fileDefinitions.AddAttribute("Arguments", "/x [ProductCode]"); - fileDefinitions.EndElement("Shortcut"); -} - bool cmCPackWIXGenerator::CreateLicenseFile() { std::string licenseSourceFilename; @@ -981,11 +802,11 @@ bool cmCPackWIXGenerator::CreateLicenseFile() } void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( - const std::string& topdir, - const std::string& directoryId, - cmWIXSourceWriter& directoryDefinitions, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions, + std::string const& topdir, + std::string const& directoryId, + cmWIXDirectoriesSourceWriter& directoryDefinitions, + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions, const std::vector<std::string>& packageExecutables, const std::vector<std::string>& desktopExecutables, shortcut_map_t& shortcutMap) @@ -993,6 +814,16 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( cmsys::Directory dir; dir.Load(topdir.c_str()); + if(dir.GetNumberOfFiles() == 2) + { + std::string componentId = fileDefinitions.EmitComponentCreateFolder( + directoryId, GenerateGUID()); + + featureDefinitions.EmitComponentRef(componentId); + + return; + } + for(size_t i = 0; i < dir.GetNumberOfFiles(); ++i) { std::string fileName = dir.GetFile(static_cast<unsigned long>(i)); @@ -1026,44 +857,15 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( desktopExecutables, shortcutMap); - ApplyPatchFragment(subDirectoryId, directoryDefinitions); + this->Patch.ApplyFragment(subDirectoryId, directoryDefinitions); directoryDefinitions.EndElement("Directory"); } else { - std::string componentId = std::string("CM_C") + id; - std::string fileId = std::string("CM_F") + id; - - fileDefinitions.BeginElement("DirectoryRef"); - fileDefinitions.AddAttribute("Id", directoryId); - - fileDefinitions.BeginElement("Component"); - fileDefinitions.AddAttribute("Id", componentId); - fileDefinitions.AddAttribute("Guid", "*"); + std::string componentId = fileDefinitions.EmitComponentFile( + directoryId, id, fullPath, this->Patch); - fileDefinitions.BeginElement("File"); - fileDefinitions.AddAttribute("Id", fileId); - fileDefinitions.AddAttribute("Source", fullPath); - fileDefinitions.AddAttribute("KeyPath", "yes"); - - mode_t fileMode = 0; - cmSystemTools::GetPermissions(fullPath.c_str(), fileMode); - - if(!(fileMode & S_IWRITE)) - { - fileDefinitions.AddAttribute("ReadOnly", "yes"); - } - - ApplyPatchFragment(fileId, fileDefinitions); - fileDefinitions.EndElement("File"); - - ApplyPatchFragment(componentId, fileDefinitions); - fileDefinitions.EndElement("Component"); - fileDefinitions.EndElement("DirectoryRef"); - - featureDefinitions.BeginElement("ComponentRef"); - featureDefinitions.AddAttribute("Id", componentId); - featureDefinitions.EndElement("ComponentRef"); + featureDefinitions.EmitComponentRef(componentId); for(size_t j = 0; j < packageExecutables.size(); ++j) { @@ -1092,7 +894,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( } bool cmCPackWIXGenerator::RequireOption( - const std::string& name, std::string &value) const + std::string const& name, std::string &value) const { const char* tmp = GetOption(name.c_str()); if(tmp) @@ -1140,13 +942,13 @@ std::string cmCPackWIXGenerator::GenerateGUID() return cmSystemTools::UpperCase(result); } -std::string cmCPackWIXGenerator::QuotePath(const std::string& path) +std::string cmCPackWIXGenerator::QuotePath(std::string const& path) { return std::string("\"") + path + '"'; } std::string cmCPackWIXGenerator::GetRightmostExtension( - const std::string& filename) + std::string const& filename) { std::string extension; @@ -1159,7 +961,7 @@ std::string cmCPackWIXGenerator::GetRightmostExtension( return cmSystemTools::LowerCase(extension); } -std::string cmCPackWIXGenerator::PathToId(const std::string& path) +std::string cmCPackWIXGenerator::PathToId(std::string const& path) { id_map_t::const_iterator i = PathToIdMap.find(path); if(i != PathToIdMap.end()) return i->second; @@ -1168,7 +970,7 @@ std::string cmCPackWIXGenerator::PathToId(const std::string& path) return id; } -std::string cmCPackWIXGenerator::CreateNewIdForPath(const std::string& path) +std::string cmCPackWIXGenerator::CreateNewIdForPath(std::string const& path) { std::vector<std::string> components; cmSystemTools::SplitPath(path.c_str(), components, false); @@ -1222,7 +1024,7 @@ std::string cmCPackWIXGenerator::CreateNewIdForPath(const std::string& path) } std::string cmCPackWIXGenerator::CreateHashedId( - const std::string& path, const std::string& normalizedFilename) + std::string const& path, std::string const& normalizedFilename) { cmsys::auto_ptr<cmCryptoHash> sha1 = cmCryptoHash::New("SHA1"); std::string hash = sha1->HashString(path.c_str()); @@ -1245,7 +1047,7 @@ std::string cmCPackWIXGenerator::CreateHashedId( } std::string cmCPackWIXGenerator::NormalizeComponentForId( - const std::string& component, size_t& replacementCount) + std::string const& component, size_t& replacementCount) { std::string result; result.resize(component.size()); @@ -1276,7 +1078,7 @@ bool cmCPackWIXGenerator::IsLegalIdCharacter(char c) } void cmCPackWIXGenerator::CollectExtensions( - const std::string& variableName, extension_set_t& extensions) + std::string const& variableName, extension_set_t& extensions) { const char *variableContent = GetOption(variableName.c_str()); if(!variableContent) return; @@ -1292,7 +1094,7 @@ void cmCPackWIXGenerator::CollectExtensions( } void cmCPackWIXGenerator::AddCustomFlags( - const std::string& variableName, std::ostream& stream) + std::string const& variableName, std::ostream& stream) { const char *variableContent = GetOption(variableName.c_str()); if(!variableContent) return; @@ -1306,69 +1108,3 @@ void cmCPackWIXGenerator::AddCustomFlags( stream << " " << QuotePath(*i); } } - -void cmCPackWIXGenerator::CreateStartMenuFolder( - cmWIXSourceWriter& directoryDefinitions) -{ - directoryDefinitions.BeginElement("Directory"); - directoryDefinitions.AddAttribute("Id", "ProgramMenuFolder"); - - directoryDefinitions.BeginElement("Directory"); - directoryDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); - const char *startMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); - directoryDefinitions.AddAttribute("Name", startMenuFolder); - directoryDefinitions.EndElement("Directory"); - - directoryDefinitions.EndElement("Directory"); -} - -void cmCPackWIXGenerator::CreateDesktopFolder( - cmWIXSourceWriter& directoryDefinitions) -{ - directoryDefinitions.BeginElement("Directory"); - directoryDefinitions.AddAttribute("Id", "DesktopFolder"); - directoryDefinitions.AddAttribute("Name", "Desktop"); - directoryDefinitions.EndElement("Directory"); -} - -void cmCPackWIXGenerator::LoadPatchFragments(const std::string& patchFilePath) -{ - cmWIXPatchParser parser(Fragments, Logger); - parser.ParseFile(patchFilePath.c_str()); -} - -void cmCPackWIXGenerator::ApplyPatchFragment( - const std::string& id, cmWIXSourceWriter& writer) -{ - cmWIXPatchParser::fragment_map_t::iterator i = Fragments.find(id); - if(i == Fragments.end()) return; - - const cmWIXPatchElement& fragment = i->second; - for(cmWIXPatchElement::child_list_t::const_iterator - j = fragment.children.begin(); j != fragment.children.end(); ++j) - { - ApplyPatchElement(**j, writer); - } - - Fragments.erase(i); -} - -void cmCPackWIXGenerator::ApplyPatchElement( - const cmWIXPatchElement& element, cmWIXSourceWriter& writer) -{ - writer.BeginElement(element.name); - - for(cmWIXPatchElement::attributes_t::const_iterator - i = element.attributes.begin(); i != element.attributes.end(); ++i) - { - writer.AddAttribute(i->first, i->second); - } - - for(cmWIXPatchElement::child_list_t::const_iterator - i = element.children.begin(); i != element.children.end(); ++i) - { - ApplyPatchElement(**i, writer); - } - - writer.EndElement(element.name); -} diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index 1de4810..4c9f8c7 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -13,25 +13,18 @@ #ifndef cmCPackWIXGenerator_h #define cmCPackWIXGenerator_h -#include "cmWIXPatchParser.h" +#include "cmWIXPatch.h" +#include "cmWIXShortcut.h" #include <CPack/cmCPackGenerator.h> #include <string> #include <map> -struct cmWIXShortcut -{ - cmWIXShortcut() - :desktop(false) - {} - - std::string textLabel; - std::string workingDirectoryId; - bool desktop; -}; - class cmWIXSourceWriter; +class cmWIXDirectoriesSourceWriter; +class cmWIXFilesSourceWriter; +class cmWIXFeaturesSourceWriter; /** \class cmCPackWIXGenerator * \brief A generator for WIX files @@ -78,48 +71,39 @@ private: bool PackageFilesImpl(); - bool CreateWiXVariablesIncludeFile(); + void CreateWiXVariablesIncludeFile(); + + void CreateWiXPropertiesIncludeFile(); void CopyDefinition( - cmWIXSourceWriter &source, const std::string &name); + cmWIXSourceWriter &source, std::string const& name); void AddDefinition(cmWIXSourceWriter& source, - const std::string& name, const std::string& value); + std::string const& name, std::string const& value); bool CreateWiXSourceFiles(); - bool CreateCMakePackageRegistryEntry( - cmWIXSourceWriter& featureDefinitions); + std::string GetProgramFilesFolderId() const; - bool CreateFeatureHierarchy( - cmWIXSourceWriter& featureDefinitions); - - bool EmitFeatureForComponentGroup( - cmWIXSourceWriter& featureDefinitions, - cmCPackComponentGroup const& group); + bool GenerateMainSourceFileFromTemplate(); - bool EmitFeatureForComponent( - cmWIXSourceWriter& featureDefinitions, - cmCPackComponent const& component); + bool CreateFeatureHierarchy( + cmWIXFeaturesSourceWriter& featureDefinitions); bool AddComponentsToFeature( std::string const& rootPath, std::string const& featureId, - cmWIXSourceWriter& directoryDefinitions, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions, + cmWIXDirectoriesSourceWriter& directoryDefinitions, + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions, shortcut_map_t& shortcutMap); bool CreateStartMenuShortcuts( std::string const& cpackComponentName, std::string const& featureId, shortcut_map_t& shortcutMap, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions); - - void CreateUninstallShortcut( - std::string const& packageName, - cmWIXSourceWriter& fileDefinitions); + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions); void AppendUserSuppliedExtraSources(); @@ -127,60 +111,49 @@ private: bool CreateLicenseFile(); - bool RunWiXCommand(const std::string& command); + bool RunWiXCommand(std::string const& command); bool RunCandleCommand( - const std::string& sourceFile, const std::string& objectFile); + std::string const& sourceFile, std::string const& objectFile); - bool RunLightCommand(const std::string& objectFiles); + bool RunLightCommand(std::string const& objectFiles); - void AddDirectoryAndFileDefinitons(const std::string& topdir, - const std::string& directoryId, - cmWIXSourceWriter& directoryDefinitions, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions, + void AddDirectoryAndFileDefinitons(std::string const& topdir, + std::string const& directoryId, + cmWIXDirectoriesSourceWriter& directoryDefinitions, + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions, const std::vector<std::string>& pkgExecutables, const std::vector<std::string>& desktopExecutables, shortcut_map_t& shortcutMap); - bool RequireOption(const std::string& name, std::string& value) const; + bool RequireOption(std::string const& name, std::string& value) const; std::string GetArchitecture() const; static std::string GenerateGUID(); - static std::string QuotePath(const std::string& path); + static std::string QuotePath(std::string const& path); - static std::string GetRightmostExtension(const std::string& filename); + static std::string GetRightmostExtension(std::string const& filename); - std::string PathToId(const std::string& path); + std::string PathToId(std::string const& path); - std::string CreateNewIdForPath(const std::string& path); + std::string CreateNewIdForPath(std::string const& path); static std::string CreateHashedId( - const std::string& path, const std::string& normalizedFilename); + std::string const& path, std::string const& normalizedFilename); std::string NormalizeComponentForId( - const std::string& component, size_t& replacementCount); + std::string const& component, size_t& replacementCount); static bool IsLegalIdCharacter(char c); void CollectExtensions( - const std::string& variableName, extension_set_t& extensions); + std::string const& variableName, extension_set_t& extensions); void AddCustomFlags( - const std::string& variableName, std::ostream& stream); - - void CreateStartMenuFolder(cmWIXSourceWriter& directoryDefinitions); - - void CreateDesktopFolder(cmWIXSourceWriter& directoryDefinitions); - - void LoadPatchFragments(const std::string& patchFilePath); - - void ApplyPatchFragment(const std::string& id, cmWIXSourceWriter& writer); - - void ApplyPatchElement(const cmWIXPatchElement& element, - cmWIXSourceWriter& writer); + std::string const& variableName, std::ostream& stream); std::vector<std::string> WixSources; id_map_t PathToIdMap; @@ -189,9 +162,11 @@ private: extension_set_t CandleExtensions; extension_set_t LightExtensions; - cmWIXPatchParser::fragment_map_t Fragments; - bool HasDesktopShortcuts; + + std::string CPackTopLevel; + + cmWIXPatch Patch; }; #endif diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx new file mode 100644 index 0000000..a93f89b --- /dev/null +++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx @@ -0,0 +1,87 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmWIXDirectoriesSourceWriter.h" + +cmWIXDirectoriesSourceWriter::cmWIXDirectoriesSourceWriter(cmCPackLog* logger, + std::string const& filename): + cmWIXSourceWriter(logger, filename) +{ + +} + +void cmWIXDirectoriesSourceWriter::EmitStartMenuFolder( + std::string const& startMenuFolder) +{ + BeginElement("Directory"); + AddAttribute("Id", "ProgramMenuFolder"); + + BeginElement("Directory"); + AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + AddAttribute("Name", startMenuFolder); + EndElement("Directory"); + + EndElement("Directory"); +} + +void cmWIXDirectoriesSourceWriter::EmitDesktopFolder() +{ + BeginElement("Directory"); + AddAttribute("Id", "DesktopFolder"); + AddAttribute("Name", "Desktop"); + EndElement("Directory"); +} + +size_t cmWIXDirectoriesSourceWriter::BeginInstallationPrefixDirectory( + std::string const& programFilesFolderId, + std::string const& installRootString) +{ + BeginElement("Directory"); + AddAttribute("Id", programFilesFolderId); + + std::vector<std::string> installRoot; + + cmSystemTools::SplitPath(installRootString.c_str(), installRoot); + + if(!installRoot.empty() && installRoot.back().empty()) + { + installRoot.pop_back(); + } + + for(size_t i = 1; i < installRoot.size(); ++i) + { + BeginElement("Directory"); + + if(i == installRoot.size() - 1) + { + AddAttribute("Id", "INSTALL_ROOT"); + } + else + { + std::stringstream tmp; + tmp << "INSTALL_PREFIX_" << i; + AddAttribute("Id", tmp.str()); + } + + AddAttribute("Name", installRoot[i]); + } + + return installRoot.size(); +} + +void cmWIXDirectoriesSourceWriter::EndInstallationPrefixDirectory(size_t size) +{ + for(size_t i = 0; i < size; ++i) + { + EndElement("Directory"); + } +} diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h new file mode 100644 index 0000000..f51fdb4 --- /dev/null +++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h @@ -0,0 +1,42 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXDirectoriesSourceWriter_h +#define cmWIXDirectoriesSourceWriter_h + +#include "cmWIXSourceWriter.h" + +#include <CPack/cmCPackGenerator.h> + +#include <string> + +/** \class cmWIXDirectoriesSourceWriter + * \brief Helper class to generate directories.wxs + */ +class cmWIXDirectoriesSourceWriter : public cmWIXSourceWriter +{ +public: + cmWIXDirectoriesSourceWriter(cmCPackLog* logger, + std::string const& filename); + + void EmitStartMenuFolder(std::string const& startMenuFolder); + + void EmitDesktopFolder(); + + size_t BeginInstallationPrefixDirectory( + std::string const& programFilesFolderId, + std::string const& installRootString); + + void EndInstallationPrefixDirectory(size_t size); +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx new file mode 100644 index 0000000..0bcfc38 --- /dev/null +++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx @@ -0,0 +1,102 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmWIXFeaturesSourceWriter.h" + +cmWIXFeaturesSourceWriter::cmWIXFeaturesSourceWriter(cmCPackLog* logger, + std::string const& filename): + cmWIXSourceWriter(logger, filename) +{ + +} + +void cmWIXFeaturesSourceWriter::CreateCMakePackageRegistryEntry( + std::string const& package, + std::string const& upgradeGuid) +{ + BeginElement("Component"); + AddAttribute("Id", "CM_PACKAGE_REGISTRY"); + AddAttribute("Directory", "TARGETDIR"); + AddAttribute("Guid", "*"); + + std::string registryKey = + std::string("Software\\Kitware\\CMake\\Packages\\") + package; + + BeginElement("RegistryValue"); + AddAttribute("Root", "HKLM"); + AddAttribute("Key", registryKey); + AddAttribute("Name", upgradeGuid); + AddAttribute("Type", "string"); + AddAttribute("Value", "[INSTALL_ROOT]"); + AddAttribute("KeyPath", "yes"); + EndElement("RegistryValue"); + + EndElement("Component"); +} + +void cmWIXFeaturesSourceWriter::EmitFeatureForComponentGroup( + cmCPackComponentGroup const& group) +{ + BeginElement("Feature"); + AddAttribute("Id", "CM_G_" + group.Name); + + if(group.IsExpandedByDefault) + { + AddAttribute("Display", "expand"); + } + + AddAttributeUnlessEmpty("Title", group.DisplayName); + AddAttributeUnlessEmpty("Description", group.Description); + + for(std::vector<cmCPackComponentGroup*>::const_iterator + i = group.Subgroups.begin(); i != group.Subgroups.end(); ++i) + { + EmitFeatureForComponentGroup(**i); + } + + for(std::vector<cmCPackComponent*>::const_iterator + i = group.Components.begin(); i != group.Components.end(); ++i) + { + EmitFeatureForComponent(**i); + } + + EndElement("Feature"); +} + +void cmWIXFeaturesSourceWriter::EmitFeatureForComponent( + cmCPackComponent const& component) +{ + BeginElement("Feature"); + AddAttribute("Id", "CM_C_" + component.Name); + + AddAttributeUnlessEmpty("Title", component.DisplayName); + AddAttributeUnlessEmpty("Description", component.Description); + + if(component.IsRequired) + { + AddAttribute("Absent", "disallow"); + } + + if(component.IsHidden) + { + AddAttribute("Display", "hidden"); + } + + EndElement("Feature"); +} + +void cmWIXFeaturesSourceWriter::EmitComponentRef(std::string const& id) +{ + BeginElement("ComponentRef"); + AddAttribute("Id", id); + EndElement("ComponentRef"); +} diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h new file mode 100644 index 0000000..7670417 --- /dev/null +++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h @@ -0,0 +1,39 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXFeaturesSourceWriter_h +#define cmWIXFeaturesSourceWriter_h + +#include "cmWIXSourceWriter.h" +#include <CPack/cmCPackGenerator.h> + +/** \class cmWIXFeaturesSourceWriter + * \brief Helper class to generate features.wxs + */ +class cmWIXFeaturesSourceWriter : public cmWIXSourceWriter +{ +public: + cmWIXFeaturesSourceWriter(cmCPackLog* logger, + std::string const& filename); + + void CreateCMakePackageRegistryEntry( + std::string const& package, + std::string const& upgradeGuid); + + void EmitFeatureForComponentGroup(const cmCPackComponentGroup& group); + + void EmitFeatureForComponent(const cmCPackComponent& component); + + void EmitComponentRef(std::string const& id); +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx new file mode 100644 index 0000000..3fd959e --- /dev/null +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx @@ -0,0 +1,171 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmWIXFilesSourceWriter.h" + +#include <sys/types.h> +#include <sys/stat.h> + +cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger, + std::string const& filename): + cmWIXSourceWriter(logger, filename) +{ + +} + +void cmWIXFilesSourceWriter::EmitShortcut( + std::string const& id, + cmWIXShortcut const& shortcut, + bool desktop) +{ + std::string shortcutId; + + if(desktop) + { + shortcutId = "CM_DS"; + } + else + { + shortcutId = "CM_S"; + } + + shortcutId += id; + + std::string fileId = std::string("CM_F") + id; + + BeginElement("Shortcut"); + AddAttribute("Id", shortcutId); + AddAttribute("Name", shortcut.textLabel); + std::string target = "[#" + fileId + "]"; + AddAttribute("Target", target); + AddAttribute("WorkingDirectory", shortcut.workingDirectoryId); + EndElement("Shortcut"); +} + +void cmWIXFilesSourceWriter::EmitRemoveFolder(std::string const& id) +{ + BeginElement("RemoveFolder"); + AddAttribute("Id", id); + AddAttribute("On", "uninstall"); + EndElement("RemoveFolder"); +} + +void cmWIXFilesSourceWriter::EmitStartMenuShortcutRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName) +{ + EmitInstallRegistryValue(registryKey, cpackComponentName, std::string()); +} + +void cmWIXFilesSourceWriter::EmitDesktopShortcutRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName) +{ + EmitInstallRegistryValue(registryKey, cpackComponentName, "_desktop"); +} + +void cmWIXFilesSourceWriter::EmitInstallRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName, + std::string const& suffix) +{ + std::string valueName; + if(!cpackComponentName.empty()) + { + valueName = cpackComponentName + "_"; + } + + valueName += "installed"; + valueName += suffix; + + BeginElement("RegistryValue"); + AddAttribute("Root", "HKCU"); + AddAttribute("Key", registryKey); + AddAttribute("Name", valueName); + AddAttribute("Type", "integer"); + AddAttribute("Value", "1"); + AddAttribute("KeyPath", "yes"); + EndElement("RegistryValue"); +} + +void cmWIXFilesSourceWriter::EmitUninstallShortcut( + std::string const& packageName) +{ + BeginElement("Shortcut"); + AddAttribute("Id", "UNINSTALL"); + AddAttribute("Name", "Uninstall " + packageName); + AddAttribute("Description", "Uninstalls " + packageName); + AddAttribute("Target", "[SystemFolder]msiexec.exe"); + AddAttribute("Arguments", "/x [ProductCode]"); + EndElement("Shortcut"); +} + +std::string cmWIXFilesSourceWriter::EmitComponentCreateFolder( + std::string const& directoryId, std::string const& guid) +{ + std::string componentId = + std::string("CM_C_EMPTY_") + directoryId; + + BeginElement("DirectoryRef"); + AddAttribute("Id", directoryId); + + BeginElement("Component"); + AddAttribute("Id", componentId); + AddAttribute("Guid", guid); + + BeginElement("CreateFolder"); + + EndElement("CreateFolder"); + EndElement("Component"); + EndElement("DirectoryRef"); + + return componentId; +} + +std::string cmWIXFilesSourceWriter::EmitComponentFile( + std::string const& directoryId, + std::string const& id, + std::string const& filePath, + cmWIXPatch &patch) +{ + std::string componentId = std::string("CM_C") + id; + std::string fileId = std::string("CM_F") + id; + + BeginElement("DirectoryRef"); + AddAttribute("Id", directoryId); + + BeginElement("Component"); + AddAttribute("Id", componentId); + AddAttribute("Guid", "*"); + + BeginElement("File"); + AddAttribute("Id", fileId); + AddAttribute("Source", filePath); + AddAttribute("KeyPath", "yes"); + + mode_t fileMode = 0; + cmSystemTools::GetPermissions(filePath.c_str(), fileMode); + + if(!(fileMode & S_IWRITE)) + { + AddAttribute("ReadOnly", "yes"); + } + + patch.ApplyFragment(fileId, *this); + EndElement("File"); + + patch.ApplyFragment(componentId, *this); + EndElement("Component"); + EndElement("DirectoryRef"); + + return componentId; +} diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.h b/Source/CPack/WiX/cmWIXFilesSourceWriter.h new file mode 100644 index 0000000..13122c2 --- /dev/null +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.h @@ -0,0 +1,66 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXFilesSourceWriter_h +#define cmWIXFilesSourceWriter_h + +#include "cmWIXSourceWriter.h" +#include "cmWIXShortcut.h" +#include "cmWIXPatch.h" + +#include <CPack/cmCPackGenerator.h> + +/** \class cmWIXFilesSourceWriter + * \brief Helper class to generate files.wxs + */ +class cmWIXFilesSourceWriter : public cmWIXSourceWriter +{ +public: + cmWIXFilesSourceWriter(cmCPackLog* logger, + std::string const& filename); + + void EmitShortcut( + std::string const& id, + cmWIXShortcut const& shortcut, + bool desktop); + + void EmitRemoveFolder(std::string const& id); + + void EmitStartMenuShortcutRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName); + + void EmitDesktopShortcutRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName); + + void EmitUninstallShortcut(std::string const& packageName); + + std::string EmitComponentCreateFolder( + std::string const& directoryId, + std::string const& guid); + + std::string EmitComponentFile( + std::string const& directoryId, + std::string const& id, + std::string const& filePath, + cmWIXPatch &patch); + +private: + void EmitInstallRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName, + std::string const& suffix); +}; + + +#endif diff --git a/Source/CPack/WiX/cmWIXPatch.cxx b/Source/CPack/WiX/cmWIXPatch.cxx new file mode 100644 index 0000000..b5202e0 --- /dev/null +++ b/Source/CPack/WiX/cmWIXPatch.cxx @@ -0,0 +1,91 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmWIXPatch.h" + +#include <CPack/cmCPackGenerator.h> + +cmWIXPatch::cmWIXPatch(cmCPackLog* logger): + Logger(logger) +{ + +} + +void cmWIXPatch::LoadFragments(std::string const& patchFilePath) +{ + cmWIXPatchParser parser(Fragments, Logger); + parser.ParseFile(patchFilePath.c_str()); +} + +void cmWIXPatch::ApplyFragment( + std::string const& id, cmWIXSourceWriter& writer) +{ + cmWIXPatchParser::fragment_map_t::iterator i = Fragments.find(id); + if(i == Fragments.end()) return; + + const cmWIXPatchElement& fragment = i->second; + for(cmWIXPatchElement::child_list_t::const_iterator + j = fragment.children.begin(); j != fragment.children.end(); ++j) + { + ApplyElement(**j, writer); + } + + Fragments.erase(i); +} + +void cmWIXPatch::ApplyElement( + const cmWIXPatchElement& element, cmWIXSourceWriter& writer) +{ + writer.BeginElement(element.name); + + for(cmWIXPatchElement::attributes_t::const_iterator + i = element.attributes.begin(); i != element.attributes.end(); ++i) + { + writer.AddAttribute(i->first, i->second); + } + + for(cmWIXPatchElement::child_list_t::const_iterator + i = element.children.begin(); i != element.children.end(); ++i) + { + ApplyElement(**i, writer); + } + + writer.EndElement(element.name); +} + + +bool cmWIXPatch::CheckForUnappliedFragments() +{ + std::string fragmentList; + for(cmWIXPatchParser::fragment_map_t::const_iterator + i = Fragments.begin(); i != Fragments.end(); ++i) + { + if(!fragmentList.empty()) + { + fragmentList += ", "; + } + + fragmentList += "'"; + fragmentList += i->first; + fragmentList += "'"; + } + + if(fragmentList.size()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Some XML patch fragments did not have matching IDs: " << + fragmentList << std::endl); + return false; + } + + return true; +} diff --git a/Source/CPack/WiX/cmWIXPatch.h b/Source/CPack/WiX/cmWIXPatch.h new file mode 100644 index 0000000..7b7b2f1 --- /dev/null +++ b/Source/CPack/WiX/cmWIXPatch.h @@ -0,0 +1,45 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXPatch_h +#define cmWIXPatch_h + +#include "cmWIXSourceWriter.h" +#include "cmWIXPatchParser.h" + +#include <string> + +/** \class cmWIXPatch + * \brief Class that maintains and applies patch fragments + */ +class cmWIXPatch +{ +public: + cmWIXPatch(cmCPackLog* logger); + + void LoadFragments(std::string const& patchFilePath); + + void ApplyFragment(std::string const& id, cmWIXSourceWriter& writer); + + bool CheckForUnappliedFragments(); + +private: + void ApplyElement(const cmWIXPatchElement& element, + cmWIXSourceWriter& writer); + + cmCPackLog* Logger; + + cmWIXPatchParser::fragment_map_t Fragments; +}; + + +#endif diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx index 7ceaf1f..10af1f6 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.cxx +++ b/Source/CPack/WiX/cmWIXPatchParser.cxx @@ -132,7 +132,7 @@ void cmWIXPatchParser::ReportError(int line, int column, const char* msg) Valid = false; } -void cmWIXPatchParser::ReportValidationError(const std::string& message) +void cmWIXPatchParser::ReportValidationError(std::string const& message) { ReportError(XML_GetCurrentLineNumber(Parser), XML_GetCurrentColumnNumber(Parser), diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h index 91b3b66..da3adf5 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.h +++ b/Source/CPack/WiX/cmWIXPatchParser.h @@ -50,7 +50,7 @@ private: virtual void EndElement(const char *name); virtual void ReportError(int line, int column, const char* msg); - void ReportValidationError(const std::string& message); + void ReportValidationError(std::string const& message); bool IsValid() const; diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx index ddc1d71..f27caa9 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx @@ -15,7 +15,7 @@ #include <cmVersion.h> cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter( - const std::string& filename): + std::string const& filename): File(filename.c_str(), std::ios::binary) { StartGroup(); @@ -33,7 +33,7 @@ cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter() File.put(0); } -void cmWIXRichTextFormatWriter::AddText(const std::string& text) +void cmWIXRichTextFormatWriter::AddText(std::string const& text) { typedef unsigned char rtf_byte_t; @@ -167,12 +167,12 @@ void cmWIXRichTextFormatWriter::WriteDocumentPrefix() ControlWord("fs20"); } -void cmWIXRichTextFormatWriter::ControlWord(const std::string& keyword) +void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword) { File << "\\" << keyword; } -void cmWIXRichTextFormatWriter::NewControlWord(const std::string& keyword) +void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword) { File << "\\*\\" << keyword; } diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h index 2b665d47..f6327fb 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h @@ -22,10 +22,10 @@ class cmWIXRichTextFormatWriter { public: - cmWIXRichTextFormatWriter(const std::string& filename); + cmWIXRichTextFormatWriter(std::string const& filename); ~cmWIXRichTextFormatWriter(); - void AddText(const std::string& text); + void AddText(std::string const& text); private: void WriteHeader(); @@ -35,8 +35,8 @@ private: void WriteDocumentPrefix(); - void ControlWord(const std::string& keyword); - void NewControlWord(const std::string& keyword); + void ControlWord(std::string const& keyword); + void NewControlWord(std::string const& keyword); void StartGroup(); void EndGroup(); diff --git a/Source/CPack/WiX/cmWIXShortcut.h b/Source/CPack/WiX/cmWIXShortcut.h new file mode 100644 index 0000000..93095e0 --- /dev/null +++ b/Source/CPack/WiX/cmWIXShortcut.h @@ -0,0 +1,29 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXFilesShortcut_h +#define cmWIXFilesShortcut_h + +#include <string> + +struct cmWIXShortcut +{ + cmWIXShortcut() + :desktop(false) + {} + + std::string textLabel; + std::string workingDirectoryId; + bool desktop; +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx index e83c226..aad19da 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx @@ -17,7 +17,7 @@ #include <windows.h> cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger, - const std::string& filename, + std::string const& filename, bool isIncludeFile): Logger(logger), File(filename.c_str()), @@ -51,7 +51,7 @@ cmWIXSourceWriter::~cmWIXSourceWriter() EndElement(Elements.back()); } -void cmWIXSourceWriter::BeginElement(const std::string& name) +void cmWIXSourceWriter::BeginElement(std::string const& name) { if(State == BEGIN) { @@ -101,7 +101,7 @@ void cmWIXSourceWriter::EndElement(std::string const& name) } void cmWIXSourceWriter::AddProcessingInstruction( - const std::string& target, const std::string& content) + std::string const& target, std::string const& content) { if(State == BEGIN) { @@ -116,7 +116,7 @@ void cmWIXSourceWriter::AddProcessingInstruction( } void cmWIXSourceWriter::AddAttribute( - const std::string& key, const std::string& value) + std::string const& key, std::string const& value) { std::string utf8 = WindowsCodepageToUtf8(value); @@ -124,7 +124,7 @@ void cmWIXSourceWriter::AddAttribute( } void cmWIXSourceWriter::AddAttributeUnlessEmpty( - const std::string& key, const std::string& value) + std::string const& key, std::string const& value) { if(value.size()) { @@ -132,7 +132,7 @@ void cmWIXSourceWriter::AddAttributeUnlessEmpty( } } -std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value) +std::string cmWIXSourceWriter::WindowsCodepageToUtf8(std::string const& value) { if(value.empty()) { @@ -184,7 +184,7 @@ void cmWIXSourceWriter::Indent(size_t count) } std::string cmWIXSourceWriter::EscapeAttributeValue( - const std::string& value) + std::string const& value) { std::string result; result.reserve(value.size()); diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h index 894ad78..65b7240 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.h +++ b/Source/CPack/WiX/cmWIXSourceWriter.h @@ -26,24 +26,24 @@ class cmWIXSourceWriter { public: cmWIXSourceWriter(cmCPackLog* logger, - const std::string& filename, bool isIncludeFile = false); + std::string const& filename, bool isIncludeFile = false); ~cmWIXSourceWriter(); - void BeginElement(const std::string& name); + void BeginElement(std::string const& name); - void EndElement(const std::string& name); + void EndElement(std::string const& name); void AddProcessingInstruction( - const std::string& target, const std::string& content); + std::string const& target, std::string const& content); void AddAttribute( - const std::string& key, const std::string& value); + std::string const& key, std::string const& value); void AddAttributeUnlessEmpty( - const std::string& key, const std::string& value); + std::string const& key, std::string const& value); - static std::string WindowsCodepageToUtf8(const std::string& value); + static std::string WindowsCodepageToUtf8(std::string const& value); private: enum State @@ -56,7 +56,7 @@ private: void Indent(size_t count); - static std::string EscapeAttributeValue(const std::string& value); + static std::string EscapeAttributeValue(std::string const& value); cmCPackLog* Logger; diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 96491aa..e1dd4e9 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -1202,6 +1202,12 @@ const char* cmCPackGenerator::GetOption(const char* op) const } //---------------------------------------------------------------------- +std::vector<std::string> cmCPackGenerator::GetOptions() const +{ + return this->MakefileMap->GetDefinitions(); +} + +//---------------------------------------------------------------------- int cmCPackGenerator::PackageFiles() { return 0; diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index bb33aa0..b1a7840 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -102,6 +102,7 @@ public: void SetOption(const char* op, const char* value); void SetOptionIfNotSet(const char* op, const char* value); const char* GetOption(const char* op) const; + std::vector<std::string> GetOptions() const; bool IsSet(const char* name) const; bool IsOn(const char* name) const; diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 3c65c55..0503d94 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -871,6 +871,12 @@ int cmCTestCoverageHandler::HandleGCovCoverage( { std::string gcovCommand = this->CTest->GetCTestConfiguration("CoverageCommand"); + if (gcovCommand.empty()) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Could not find gcov." << std::endl); + return 0; + } std::string gcovExtraFlags = this->CTest->GetCTestConfiguration("CoverageExtraFlags"); diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 7d9c034..cd3bd57 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -587,8 +587,7 @@ void cmCTestLaunch::DumpFileToXML(std::ostream& fxml, while(cmSystemTools::GetLineFromStream(fin, line)) { - if(OptionFilterPrefix.size() && cmSystemTools::StringStartsWith( - line.c_str(), OptionFilterPrefix.c_str())) + if(MatchesFilterPrefix(line)) { continue; } @@ -676,6 +675,11 @@ bool cmCTestLaunch::ScrapeLog(std::string const& fname) std::string line; while(cmSystemTools::GetLineFromStream(fin, line)) { + if(MatchesFilterPrefix(line)) + { + continue; + } + if(this->Match(line.c_str(), this->RegexWarning) && !this->Match(line.c_str(), this->RegexWarningSuppress)) { @@ -701,6 +705,17 @@ bool cmCTestLaunch::Match(std::string const& line, } //---------------------------------------------------------------------------- +bool cmCTestLaunch::MatchesFilterPrefix(std::string const& line) const +{ + if(this->OptionFilterPrefix.size() && cmSystemTools::StringStartsWith( + line.c_str(), this->OptionFilterPrefix.c_str())) + { + return true; + } + return false; +} + +//---------------------------------------------------------------------------- int cmCTestLaunch::Main(int argc, const char* const argv[]) { if(argc == 2) diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h index a86a9df..f680d19 100644 --- a/Source/CTest/cmCTestLaunch.h +++ b/Source/CTest/cmCTestLaunch.h @@ -88,6 +88,7 @@ private: bool ScrapeLog(std::string const& fname); bool Match(std::string const& line, std::vector<cmsys::RegularExpression>& regexps); + bool MatchesFilterPrefix(std::string const& line) const; // Methods to generate the xml fragment. void WriteXML(); diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index a77bc68..308956a 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -52,7 +52,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) } if (te->GetType() == cmTarget::INTERFACE_LIBRARY) { - this->GenerateRequiredCMakeVersion(os, DEVEL_CMAKE_VERSION(3, 0, 0)); + this->GenerateRequiredCMakeVersion(os, "3.0.0"); } } diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 8be4bbf..57ab378 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -21,14 +21,13 @@ #define STRINGIFY_HELPER(X) #X #define STRINGIFY(X) STRINGIFY_HELPER(X) -#define DEVEL_CMAKE_VERSION(maj, min, patch) \ - (CMake_VERSION_ENCODE(maj, min, patch) > \ - CMake_VERSION_ENCODE(CMake_VERSION_MAJOR, CMake_VERSION_MINOR, \ - CMake_VERSION_PATCH) \ - ) ? \ +#define DEVEL_CMAKE_VERSION(major, minor) ( \ + CMake_VERSION_ENCODE(major, minor, 0) > \ + CMake_VERSION_ENCODE(CMake_VERSION_MAJOR, CMake_VERSION_MINOR, 0) ? \ STRINGIFY(CMake_VERSION_MAJOR) "." STRINGIFY(CMake_VERSION_MINOR) "." \ - STRINGIFY(CMake_VERSION_PATCH) "." STRINGIFY(CMake_VERSION_TWEAK) \ - : #maj "." #min "." #patch + STRINGIFY(CMake_VERSION_PATCH) \ + : #major "." #minor ".0" \ + ) class cmTargetExport; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 8b59665..b579963 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -176,7 +176,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) if (require3_0_0) { - this->GenerateRequiredCMakeVersion(os, DEVEL_CMAKE_VERSION(3, 0, 0)); + this->GenerateRequiredCMakeVersion(os, "3.0.0"); } else if (require2_8_12) { diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 2e66d78..cd30546 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -157,17 +157,24 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() std::string cmGeneratorExpression::StripEmptyListElements( const std::string &input) { + if (input.find(';') == input.npos) + { + return input; + } std::string result; + result.reserve(input.size()); const char *c = input.c_str(); + const char *last = c; bool skipSemiColons = true; for ( ; *c; ++c) { - if(c[0] == ';') + if(*c == ';') { if(skipSemiColons) { - continue; + result.append(last, c - last); + last = c + 1; } skipSemiColons = true; } @@ -175,8 +182,8 @@ std::string cmGeneratorExpression::StripEmptyListElements( { skipSemiColons = false; } - result += *c; } + result.append(last); if (!result.empty() && *(result.end() - 1) == ';') { diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 7036992..bdefcfb 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -800,7 +800,7 @@ static const char* targetPropertyTransitiveWhitelist[] = { #undef TRANSITIVE_PROPERTY_NAME -std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, +std::string getLinkedTargetsContent(const std::vector<cmTarget*> &targets, cmTarget const* target, cmTarget const* headTarget, cmGeneratorExpressionContext *context, @@ -811,23 +811,21 @@ std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, std::string sep; std::string depString; - for (std::vector<std::string>::const_iterator - it = libraries.begin(); - it != libraries.end(); ++it) + for (std::vector<cmTarget*>::const_iterator + it = targets.begin(); + it != targets.end(); ++it) { - if (*it == target->GetName()) + if (*it == target) { // Broken code can have a target in its own link interface. // Don't follow such link interface entries so as not to create a // self-referencing loop. continue; } - if (context->Makefile->FindTargetToUse(*it)) - { - depString += - sep + "$<TARGET_PROPERTY:" + *it + "," + interfacePropertyName + ">"; - sep = ";"; - } + depString += + sep + "$<TARGET_PROPERTY:" + + (*it)->GetName() + "," + interfacePropertyName + ">"; + sep = ";"; } cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString); std::string linkedTargetsContent = cge->Evaluate(context->Makefile, @@ -843,6 +841,27 @@ std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, return linkedTargetsContent; } +std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, + cmTarget const* target, + cmTarget const* headTarget, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string &interfacePropertyName) +{ + std::vector<cmTarget*> tgts; + for (std::vector<std::string>::const_iterator + it = libraries.begin(); + it != libraries.end(); ++it) + { + if (cmTarget *tgt = context->Makefile->FindTargetToUse(*it)) + { + tgts.push_back(tgt); + } + } + return getLinkedTargetsContent(tgts, target, headTarget, context, + dagChecker, interfacePropertyName); +} + //---------------------------------------------------------------------------- static const struct TargetPropertyNode : public cmGeneratorExpressionNode { @@ -1065,13 +1084,13 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode cmStrCmp(propertyName)) != transEnd) { - std::vector<std::string> libs; - target->GetTransitivePropertyLinkLibraries(context->Config, - headTarget, libs); - if (!libs.empty()) + std::vector<cmTarget*> tgts; + target->GetTransitivePropertyTargets(context->Config, + headTarget, tgts); + if (!tgts.empty()) { linkedTargetsContent = - getLinkedTargetsContent(libs, target, + getLinkedTargetsContent(tgts, target, headTarget, context, &dagChecker, interfacePropertyName); @@ -1080,9 +1099,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode else if (std::find_if(transBegin, transEnd, cmStrCmp(interfacePropertyName)) != transEnd) { - const cmTarget::LinkImplementation *impl = target->GetLinkImplementation( - context->Config, - headTarget); + const cmTarget::LinkImplementation *impl + = target->GetLinkImplementationLibraries(context->Config, + headTarget); if(impl) { linkedTargetsContent = diff --git a/Source/cmGeneratorExpressionLexer.cxx b/Source/cmGeneratorExpressionLexer.cxx index cd71ec0..117a24e 100644 --- a/Source/cmGeneratorExpressionLexer.cxx +++ b/Source/cmGeneratorExpressionLexer.cxx @@ -42,42 +42,42 @@ cmGeneratorExpressionLexer::Tokenize(const char *input) const char *upto = c; for ( ; *c; ++c) - { - if(c[0] == '$' && c[1] == '<') { - InsertText(upto, c, result); - upto = c; - result.push_back(cmGeneratorExpressionToken( - cmGeneratorExpressionToken::BeginExpression, upto, 2)); - upto = c + 2; - ++c; - SawBeginExpression = true; - } - else if(c[0] == '>') - { - InsertText(upto, c, result); - upto = c; - result.push_back(cmGeneratorExpressionToken( - cmGeneratorExpressionToken::EndExpression, upto, 1)); - upto = c + 1; - SawGeneratorExpression = SawBeginExpression; - } - else if(c[0] == ':') - { - InsertText(upto, c, result); - upto = c; - result.push_back(cmGeneratorExpressionToken( - cmGeneratorExpressionToken::ColonSeparator, upto, 1)); - upto = c + 1; - } - else if(c[0] == ',') - { - InsertText(upto, c, result); - upto = c; - result.push_back(cmGeneratorExpressionToken( - cmGeneratorExpressionToken::CommaSeparator, upto, 1)); - upto = c + 1; - } + switch(*c) + { + case '$': + if(c[1] == '<') + { + InsertText(upto, c, result); + result.push_back(cmGeneratorExpressionToken( + cmGeneratorExpressionToken::BeginExpression, c, 2)); + upto = c + 2; + ++c; + SawBeginExpression = true; + } + break; + case '>': + InsertText(upto, c, result); + result.push_back(cmGeneratorExpressionToken( + cmGeneratorExpressionToken::EndExpression, c, 1)); + upto = c + 1; + SawGeneratorExpression = SawBeginExpression; + break; + case ':': + InsertText(upto, c, result); + result.push_back(cmGeneratorExpressionToken( + cmGeneratorExpressionToken::ColonSeparator, c, 1)); + upto = c + 1; + break; + case ',': + InsertText(upto, c, result); + result.push_back(cmGeneratorExpressionToken( + cmGeneratorExpressionToken::CommaSeparator, c, 1)); + upto = c + 1; + break; + default: + break; + } } InsertText(upto, c, result); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 175bb0e..a7b2fb6 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -25,7 +25,196 @@ #include "assert.h" //---------------------------------------------------------------------------- -cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) +void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib, + cmTarget *target, cmake *cm) +{ + if(!badObjLib.empty()) + { + cmOStringStream e; + e << "OBJECT library \"" << target->GetName() << "\" contains:\n"; + for(std::vector<cmSourceFile*>::const_iterator i = badObjLib.begin(); + i != badObjLib.end(); ++i) + { + e << " " << (*i)->GetLocation().GetName() << "\n"; + } + e << "but may contain only headers and sources that compile."; + cm->IssueMessage(cmake::FATAL_ERROR, e.str(), + target->GetBacktrace()); + } +} + +struct ObjectSourcesTag {}; +struct CustomCommandsTag {}; +struct ExtraSourcesTag {}; +struct HeaderSourcesTag {}; +struct ExternalObjectsTag {}; +struct IDLSourcesTag {}; +struct ResxTag {}; +struct ModuleDefinitionFileTag {}; + +#if !defined(_MSC_VER) || _MSC_VER >= 1310 +template<typename Tag, typename OtherTag> +struct IsSameTag +{ + enum { + Result = false + }; +}; + +template<typename Tag> +struct IsSameTag<Tag, Tag> +{ + enum { + Result = true + }; +}; +#else +struct IsSameTagBase +{ + typedef char (&no_type)[1]; + typedef char (&yes_type)[2]; + template<typename T> struct Check; + template<typename T> static yes_type check(Check<T>*, Check<T>*); + static no_type check(...); +}; +template<typename Tag1, typename Tag2> +struct IsSameTag: public IsSameTagBase +{ + enum { + Result = (sizeof(check(static_cast< Check<Tag1>* >(0), + static_cast< Check<Tag2>* >(0))) == + sizeof(yes_type)) + }; +}; +#endif + +template<bool> +struct DoAccept +{ + template <typename T> static void Do(T&, cmSourceFile*) {} +}; + +template<> +struct DoAccept<true> +{ + static void Do(std::vector<cmSourceFile*>& files, cmSourceFile* f) + { + files.push_back(f); + } + static void Do(cmGeneratorTarget::ResxData& data, cmSourceFile* f) + { + // Build and save the name of the corresponding .h file + // This relationship will be used later when building the project files. + // Both names would have been auto generated from Visual Studio + // where the user supplied the file name and Visual Studio + // appended the suffix. + std::string resx = f->GetFullPath(); + std::string hFileName = resx.substr(0, resx.find_last_of(".")) + ".h"; + data.ExpectedResxHeaders.insert(hFileName); + data.ResxSources.push_back(f); + } + static void Do(std::string& data, cmSourceFile* f) + { + data = f->GetFullPath(); + } +}; + +//---------------------------------------------------------------------------- +template<typename Tag, typename DataType = std::vector<cmSourceFile*> > +struct TagVisitor +{ + DataType& Data; + std::vector<cmSourceFile*> BadObjLibFiles; + cmTarget *Target; + cmGlobalGenerator *GlobalGenerator; + cmsys::RegularExpression Header; + bool IsObjLib; + + TagVisitor(cmTarget *target, DataType& data) + : Data(data), Target(target), + GlobalGenerator(target->GetMakefile() + ->GetLocalGenerator()->GetGlobalGenerator()), + Header(CM_HEADER_REGEX), + IsObjLib(target->GetType() == cmTarget::OBJECT_LIBRARY) + { + } + + ~TagVisitor() + { + reportBadObjLib(this->BadObjLibFiles, this->Target, + this->GlobalGenerator->GetCMakeInstance()); + } + + void Accept(cmSourceFile *sf) + { + std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); + if(sf->GetCustomCommand()) + { + DoAccept<IsSameTag<Tag, CustomCommandsTag>::Result>::Do(this->Data, sf); + } + else if(this->Target->GetType() == cmTarget::UTILITY) + { + DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf); + } + else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY")) + { + DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf); + } + else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT")) + { + DoAccept<IsSameTag<Tag, ExternalObjectsTag>::Result>::Do(this->Data, sf); + if(this->IsObjLib) + { + this->BadObjLibFiles.push_back(sf); + } + } + else if(sf->GetLanguage()) + { + DoAccept<IsSameTag<Tag, ObjectSourcesTag>::Result>::Do(this->Data, sf); + } + else if(ext == "def") + { + DoAccept<IsSameTag<Tag, ModuleDefinitionFileTag>::Result>::Do(this->Data, + sf); + if(this->IsObjLib) + { + this->BadObjLibFiles.push_back(sf); + } + } + else if(ext == "idl") + { + DoAccept<IsSameTag<Tag, IDLSourcesTag>::Result>::Do(this->Data, sf); + if(this->IsObjLib) + { + this->BadObjLibFiles.push_back(sf); + } + } + else if(ext == "resx") + { + DoAccept<IsSameTag<Tag, ResxTag>::Result>::Do(this->Data, sf); + } + else if(this->Header.find(sf->GetFullPath().c_str())) + { + DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf); + } + else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) + { + DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf); + } + else + { + DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf); + if(this->IsObjLib && ext != "txt") + { + this->BadObjLibFiles.push_back(sf); + } + } + } +}; + +//---------------------------------------------------------------------------- +cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t), + SourceFileFlagsConstructed(false) { this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); @@ -62,19 +251,12 @@ cmGeneratorTarget::GetSourceDepends(cmSourceFile* sf) const return 0; } -static void handleSystemIncludesDep(cmMakefile *mf, const std::string &name, +static void handleSystemIncludesDep(cmMakefile *mf, cmTarget* depTgt, const char *config, cmTarget *headTarget, cmGeneratorExpressionDAGChecker *dagChecker, std::vector<std::string>& result, bool excludeImported) { - cmTarget* depTgt = mf->FindTargetToUse(name); - - if (!depTgt) - { - return; - } - cmListFileBacktrace lfbt; if (const char* dirs = @@ -102,11 +284,34 @@ static void handleSystemIncludesDep(cmMakefile *mf, const std::string &name, } } +#define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE) \ + { \ + std::vector<cmSourceFile*> sourceFiles; \ + this->Target->GetSourceFiles(sourceFiles); \ + TagVisitor<DATA ## Tag DATATYPE> visitor(this->Target, data); \ + for(std::vector<cmSourceFile*>::const_iterator si = sourceFiles.begin(); \ + si != sourceFiles.end(); ++si) \ + { \ + visitor.Accept(*si); \ + } \ + } \ + + +#define IMPLEMENT_VISIT(DATA) \ + IMPLEMENT_VISIT_IMPL(DATA, EMPTY) \ + +#define EMPTY +#define COMMA , + //---------------------------------------------------------------------------- void -cmGeneratorTarget::GetObjectSources(std::vector<cmSourceFile*> &objs) const +cmGeneratorTarget::GetObjectSources(std::vector<cmSourceFile*> &data) const { - objs = this->ObjectSources; + IMPLEMENT_VISIT(ObjectSources); + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY) + { + this->ObjectSources = data; + } } //---------------------------------------------------------------------------- @@ -135,49 +340,53 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const } //---------------------------------------------------------------------------- -void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile*>& srcs) const +void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile*>& data) const { - srcs = this->ResxSources; + IMPLEMENT_VISIT(IDLSources); } //---------------------------------------------------------------------------- -void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile*>& srcs) const +void +cmGeneratorTarget::GetHeaderSources(std::vector<cmSourceFile*>& data) const { - srcs = this->IDLSources; + IMPLEMENT_VISIT(HeaderSources); } //---------------------------------------------------------------------------- -void -cmGeneratorTarget::GetHeaderSources(std::vector<cmSourceFile*>& srcs) const +void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile*>& data) const { - srcs = this->HeaderSources; + IMPLEMENT_VISIT(ExtraSources); } //---------------------------------------------------------------------------- -void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile*>& srcs) const +void +cmGeneratorTarget::GetCustomCommands(std::vector<cmSourceFile*>& data) const { - srcs = this->ExtraSources; + IMPLEMENT_VISIT(CustomCommands); } //---------------------------------------------------------------------------- void -cmGeneratorTarget::GetCustomCommands(std::vector<cmSourceFile*>& srcs) const +cmGeneratorTarget::GetExternalObjects(std::vector<cmSourceFile*>& data) const { - srcs = this->CustomCommands; + IMPLEMENT_VISIT(ExternalObjects); } //---------------------------------------------------------------------------- void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& srcs) const { - srcs = this->ExpectedResxHeaders; + ResxData data; + IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) + srcs = data.ExpectedResxHeaders; } //---------------------------------------------------------------------------- -void -cmGeneratorTarget::GetExternalObjects(std::vector<cmSourceFile*>& srcs) const +void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile*>& srcs) const { - srcs = this->ExternalObjects; + ResxData data; + IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) + srcs = data.ResxSources; } //---------------------------------------------------------------------------- @@ -224,26 +433,25 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir, &dagChecker), result); } - std::set<cmStdString> uniqueDeps; + std::set<cmTarget*> uniqueDeps; for(std::vector<std::string>::const_iterator li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { - if (uniqueDeps.insert(*li).second) + cmTarget* tgt = this->Makefile->FindTargetToUse(*li); + if (!tgt) { - cmTarget* tgt = this->Makefile->FindTargetToUse(*li); - - if (!tgt) - { - continue; - } + continue; + } - handleSystemIncludesDep(this->Makefile, *li, config, this->Target, + if (uniqueDeps.insert(tgt).second) + { + handleSystemIncludesDep(this->Makefile, tgt, config, this->Target, &dagChecker, result, excludeImported); - std::vector<std::string> deps; - tgt->GetTransitivePropertyLinkLibraries(config, this->Target, deps); + std::vector<cmTarget*> deps; + tgt->GetTransitivePropertyTargets(config, this->Target, deps); - for(std::vector<std::string>::const_iterator di = deps.begin(); + for(std::vector<cmTarget*>::const_iterator di = deps.begin(); di != deps.end(); ++di) { if (uniqueDeps.insert(*di).second) @@ -290,102 +498,6 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const } //---------------------------------------------------------------------------- -void cmGeneratorTarget::ClassifySources() -{ - cmsys::RegularExpression header(CM_HEADER_REGEX); - - cmTarget::TargetType targetType = this->Target->GetType(); - bool isObjLib = targetType == cmTarget::OBJECT_LIBRARY; - - std::vector<cmSourceFile*> badObjLib; - std::vector<cmSourceFile*> sources; - this->Target->GetSourceFiles(sources); - for(std::vector<cmSourceFile*>::const_iterator si = sources.begin(); - si != sources.end(); ++si) - { - cmSourceFile* sf = *si; - std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); - if(sf->GetCustomCommand()) - { - this->CustomCommands.push_back(sf); - } - else if(targetType == cmTarget::UTILITY) - { - this->ExtraSources.push_back(sf); - } - else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY")) - { - this->HeaderSources.push_back(sf); - } - else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT")) - { - this->ExternalObjects.push_back(sf); - if(isObjLib) { badObjLib.push_back(sf); } - } - else if(sf->GetLanguage()) - { - this->ObjectSources.push_back(sf); - } - else if(ext == "def") - { - this->ModuleDefinitionFile = sf->GetFullPath(); - if(isObjLib) { badObjLib.push_back(sf); } - } - else if(ext == "idl") - { - this->IDLSources.push_back(sf); - if(isObjLib) { badObjLib.push_back(sf); } - } - else if(ext == "resx") - { - // Build and save the name of the corresponding .h file - // This relationship will be used later when building the project files. - // Both names would have been auto generated from Visual Studio - // where the user supplied the file name and Visual Studio - // appended the suffix. - std::string resx = sf->GetFullPath(); - std::string hFileName = resx.substr(0, resx.find_last_of(".")) + ".h"; - this->ExpectedResxHeaders.insert(hFileName); - this->ResxSources.push_back(sf); - } - else if(header.find(sf->GetFullPath().c_str())) - { - this->HeaderSources.push_back(sf); - } - else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) - { - // We only get here if a source file is not an external object - // and has an extension that is listed as an ignored file type. - // No message or diagnosis should be given. - this->ExtraSources.push_back(sf); - } - else - { - this->ExtraSources.push_back(sf); - if(isObjLib && ext != "txt") - { - badObjLib.push_back(sf); - } - } - } - - if(!badObjLib.empty()) - { - cmOStringStream e; - e << "OBJECT library \"" << this->Target->GetName() << "\" contains:\n"; - for(std::vector<cmSourceFile*>::iterator i = badObjLib.begin(); - i != badObjLib.end(); ++i) - { - e << " " << (*i)->GetLocation().GetName() << "\n"; - } - e << "but may contain only headers and sources that compile."; - this->GlobalGenerator->GetCMakeInstance() - ->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Target->GetBacktrace()); - } -} - -//---------------------------------------------------------------------------- void cmGeneratorTarget::LookupObjectLibraries() { std::vector<std::string> const& objLibs = @@ -438,6 +550,14 @@ void cmGeneratorTarget::LookupObjectLibraries() } //---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetModuleDefinitionFile() const +{ + std::string data; + IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile, COMMA std::string) + return data; +} + +//---------------------------------------------------------------------------- void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs) const { @@ -876,3 +996,97 @@ bool cmStrictTargetComparison::operator()(cmTarget const* t1, } return nameResult < 0; } + +//---------------------------------------------------------------------------- +struct cmGeneratorTarget::SourceFileFlags +cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const +{ + struct SourceFileFlags flags; + this->ConstructSourceFileFlags(); + std::map<cmSourceFile const*, SourceFileFlags>::iterator si = + this->SourceFlagsMap.find(sf); + if(si != this->SourceFlagsMap.end()) + { + flags = si->second; + } + else + { + // Handle the MACOSX_PACKAGE_LOCATION property on source files that + // were not listed in one of the other lists. + if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) + { + flags.MacFolder = location; + if(strcmp(location, "Resources") == 0) + { + flags.Type = cmGeneratorTarget::SourceFileTypeResource; + } + else + { + flags.Type = cmGeneratorTarget::SourceFileTypeMacContent; + } + } + } + return flags; +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::ConstructSourceFileFlags() const +{ + if(this->SourceFileFlagsConstructed) + { + return; + } + this->SourceFileFlagsConstructed = true; + + // Process public headers to mark the source files. + if(const char* files = this->Target->GetProperty("PUBLIC_HEADER")) + { + std::vector<std::string> relFiles; + cmSystemTools::ExpandListArgument(files, relFiles); + for(std::vector<std::string>::iterator it = relFiles.begin(); + it != relFiles.end(); ++it) + { + if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) + { + SourceFileFlags& flags = this->SourceFlagsMap[sf]; + flags.MacFolder = "Headers"; + flags.Type = cmGeneratorTarget::SourceFileTypePublicHeader; + } + } + } + + // Process private headers after public headers so that they take + // precedence if a file is listed in both. + if(const char* files = this->Target->GetProperty("PRIVATE_HEADER")) + { + std::vector<std::string> relFiles; + cmSystemTools::ExpandListArgument(files, relFiles); + for(std::vector<std::string>::iterator it = relFiles.begin(); + it != relFiles.end(); ++it) + { + if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) + { + SourceFileFlags& flags = this->SourceFlagsMap[sf]; + flags.MacFolder = "PrivateHeaders"; + flags.Type = cmGeneratorTarget::SourceFileTypePrivateHeader; + } + } + } + + // Mark sources listed as resources. + if(const char* files = this->Target->GetProperty("RESOURCE")) + { + std::vector<std::string> relFiles; + cmSystemTools::ExpandListArgument(files, relFiles); + for(std::vector<std::string>::iterator it = relFiles.begin(); + it != relFiles.end(); ++it) + { + if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) + { + SourceFileFlags& flags = this->SourceFlagsMap[sf]; + flags.MacFolder = "Resources"; + flags.Type = cmGeneratorTarget::SourceFileTypeResource; + } + } + } +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index a4caba1..1e6ce64 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -52,7 +52,7 @@ public: cmLocalGenerator* LocalGenerator; cmGlobalGenerator const* GlobalGenerator; - std::string ModuleDefinitionFile; + std::string GetModuleDefinitionFile() const; /** Full path with trailing slash to the top-level directory holding object files for this target. Includes the build @@ -82,31 +82,56 @@ public: */ void TraceDependencies(); - void ClassifySources(); void LookupObjectLibraries(); /** Get sources that must be built before the given source. */ std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile* sf) const; + /** + * Flags for a given source file as used in this target. Typically assigned + * via SET_TARGET_PROPERTIES when the property is a list of source files. + */ + enum SourceFileType + { + SourceFileTypeNormal, + SourceFileTypePrivateHeader, // is in "PRIVATE_HEADER" target property + SourceFileTypePublicHeader, // is in "PUBLIC_HEADER" target property + SourceFileTypeResource, // is in "RESOURCE" target property *or* + // has MACOSX_PACKAGE_LOCATION=="Resources" + SourceFileTypeMacContent // has MACOSX_PACKAGE_LOCATION!="Resources" + }; + struct SourceFileFlags + { + SourceFileFlags(): Type(SourceFileTypeNormal), MacFolder(0) {} + SourceFileFlags(SourceFileFlags const& r): + Type(r.Type), MacFolder(r.MacFolder) {} + SourceFileType Type; + const char* MacFolder; // location inside Mac content folders + }; + + struct SourceFileFlags + GetTargetSourceFileFlags(const cmSourceFile* sf) const; + + struct ResxData { + mutable std::set<std::string> ExpectedResxHeaders; + mutable std::vector<cmSourceFile*> ResxSources; + }; private: friend class cmTargetTraceDependencies; struct SourceEntry { std::vector<cmSourceFile*> Depends; }; typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType; SourceEntriesType SourceEntries; - std::vector<cmSourceFile*> CustomCommands; - std::vector<cmSourceFile*> ExtraSources; - std::vector<cmSourceFile*> HeaderSources; - std::vector<cmSourceFile*> ExternalObjects; - std::vector<cmSourceFile*> IDLSources; - std::vector<cmSourceFile*> ResxSources; std::map<cmSourceFile const*, std::string> Objects; std::set<cmSourceFile const*> ExplicitObjectName; - std::set<std::string> ExpectedResxHeaders; - std::vector<cmSourceFile*> ObjectSources; + mutable std::vector<cmSourceFile*> ObjectSources; std::vector<cmTarget*> ObjectLibraries; mutable std::map<std::string, std::vector<std::string> > SystemIncludesCache; + void ConstructSourceFileFlags() const; + mutable bool SourceFileFlagsConstructed; + mutable std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap; + cmGeneratorTarget(cmGeneratorTarget const&); void operator=(cmGeneratorTarget const&); }; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 4f3328d..f76c6d1 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1148,12 +1148,6 @@ void cmGlobalGenerator::Generate() return; } - // Check that all targets are valid. - if(!this->CheckTargets()) - { - return; - } - this->FinalizeTargetCompileInfo(); #ifdef CMAKE_BUILD_WITH_CMAKE @@ -1306,35 +1300,6 @@ bool cmGlobalGenerator::ComputeTargetDepends() } //---------------------------------------------------------------------------- -bool cmGlobalGenerator::CheckTargets() -{ - // Make sure all targets can find their source files. - for(unsigned int i=0; i < this->LocalGenerators.size(); ++i) - { - cmTargets& targets = - this->LocalGenerators[i]->GetMakefile()->GetTargets(); - for(cmTargets::iterator ti = targets.begin(); - ti != targets.end(); ++ti) - { - cmTarget& target = ti->second; - if(target.GetType() == cmTarget::EXECUTABLE || - target.GetType() == cmTarget::STATIC_LIBRARY || - target.GetType() == cmTarget::SHARED_LIBRARY || - target.GetType() == cmTarget::MODULE_LIBRARY || - target.GetType() == cmTarget::OBJECT_LIBRARY || - target.GetType() == cmTarget::UTILITY) - { - if(!target.FindSourceFiles()) - { - return false; - } - } - } - } - return true; -} - -//---------------------------------------------------------------------------- void cmGlobalGenerator::CreateQtAutoGeneratorsTargets(AutogensType &autogens) { #ifdef CMAKE_BUILD_WITH_CMAKE @@ -1474,7 +1439,6 @@ void cmGlobalGenerator::ComputeGeneratorTargetObjects() continue; } cmGeneratorTarget* gt = ti->second; - gt->ClassifySources(); gt->LookupObjectLibraries(); this->ComputeTargetObjects(gt); } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 753eebf..b66f01e 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -340,7 +340,6 @@ protected: virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const; - bool CheckTargets(); typedef std::vector<std::pair<cmQtAutoGenerators, cmTarget const*> > AutogensType; void CreateQtAutoGeneratorsTargets(AutogensType& autogens); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 484b28f..004f7ac 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -713,22 +713,23 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, // Is this a resource file in this target? Add it to the resources group... // - cmTarget::SourceFileFlags tsFlags = cmtarget.GetTargetSourceFileFlags(sf); - bool isResource = (tsFlags.Type == cmTarget::SourceFileTypeResource); + cmGeneratorTarget::SourceFileFlags tsFlags = + this->GetGeneratorTarget(&cmtarget)->GetTargetSourceFileFlags(sf); + bool isResource = tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource; // Is this a "private" or "public" framework header file? // Set the ATTRIBUTES attribute appropriately... // if(cmtarget.IsFrameworkOnApple()) { - if(tsFlags.Type == cmTarget::SourceFileTypePrivateHeader) + if(tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) { cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); attrs->AddObject(this->CreateString("Private")); settings->AddAttribute("ATTRIBUTES", attrs); isResource = true; } - else if(tsFlags.Type == cmTarget::SourceFileTypePublicHeader) + else if(tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader) { cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); attrs->AddObject(this->CreateString("Public")); @@ -973,6 +974,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) { cmTarget& cmtarget = l->second; + cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&cmtarget); // make sure ALL_BUILD, INSTALL, etc are only done once if(this->SpecialTargetEmitted(l->first.c_str())) @@ -1011,8 +1013,8 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); - cmTarget::SourceFileFlags tsFlags = - cmtarget.GetTargetSourceFileFlags(*i); + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(*i); if(filetype && strcmp(filetype->GetString(), "compiled.mach-o.objfile") == 0) @@ -1020,12 +1022,12 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, externalObjFiles.push_back(xsf); } else if(this->IsHeaderFile(*i) || - (tsFlags.Type == cmTarget::SourceFileTypePrivateHeader) || - (tsFlags.Type == cmTarget::SourceFileTypePublicHeader)) + (tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) || + (tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader)) { headerFiles.push_back(xsf); } - else if(tsFlags.Type == cmTarget::SourceFileTypeResource) + else if(tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { resourceFiles.push_back(xsf); } @@ -1048,7 +1050,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, // the externalObjFiles above, except each one is not a cmSourceFile // within the target.) std::vector<std::string> objs; - this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs); + gtgt->UseObjectLibraries(objs); for(std::vector<std::string>::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { @@ -1138,9 +1140,9 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); i != classes.end(); ++i) { - cmTarget::SourceFileFlags tsFlags = - cmtarget.GetTargetSourceFileFlags(*i); - if(tsFlags.Type == cmTarget::SourceFileTypeMacContent) + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(*i); + if(tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { bundleFiles[tsFlags.MacFolder].push_back(*i); } diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 6f2dd65..0878aae 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -32,10 +32,12 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target, } static cmInstallFilesGenerator* CreateInstallFilesGenerator( + cmMakefile* mf, const std::vector<std::string>& absFiles, const cmInstallCommandArguments& args, bool programs) { - return new cmInstallFilesGenerator(absFiles, args.GetDestination().c_str(), + return new cmInstallFilesGenerator(mf, + absFiles, args.GetDestination().c_str(), programs, args.GetPermissions().c_str(), args.GetConfigurations(), args.GetComponent().c_str(), args.GetRename().c_str(), args.GetOptional()); @@ -668,7 +670,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if (!privateHeaderArgs.GetDestination().empty()) { privateHeaderGenerator = - CreateInstallFilesGenerator(absFiles, privateHeaderArgs, false); + CreateInstallFilesGenerator(this->Makefile, absFiles, + privateHeaderArgs, false); } else { @@ -694,7 +697,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if (!publicHeaderArgs.GetDestination().empty()) { publicHeaderGenerator = - CreateInstallFilesGenerator(absFiles, publicHeaderArgs, false); + CreateInstallFilesGenerator(this->Makefile, absFiles, + publicHeaderArgs, false); } else { @@ -719,8 +723,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Create the files install generator. if (!resourceArgs.GetDestination().empty()) { - resourceGenerator = CreateInstallFilesGenerator(absFiles, - resourceArgs, false); + resourceGenerator = CreateInstallFilesGenerator( + this->Makefile, absFiles, resourceArgs, false); } else { @@ -888,7 +892,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) // Create the files install generator. this->Makefile->AddInstallGenerator( - CreateInstallFilesGenerator(absFiles, ica, programs)); + CreateInstallFilesGenerator(this->Makefile, absFiles, ica, programs)); //Tell the global generator about any installation component names specified. this->Makefile->GetLocalGenerator()->GetGlobalGenerator() @@ -1351,7 +1355,8 @@ bool cmInstallCommand::MakeFilesFullPath(const char* modeName, ++fileIt) { std::string file = (*fileIt); - if(!cmSystemTools::FileIsFullPath(file.c_str())) + std::string::size_type gpos = cmGeneratorExpression::Find(file); + if(gpos != 0 && !cmSystemTools::FileIsFullPath(file.c_str())) { file = this->Makefile->GetCurrentDirectory(); file += "/"; @@ -1359,7 +1364,7 @@ bool cmInstallCommand::MakeFilesFullPath(const char* modeName, } // Make sure the file is not a directory. - if(cmSystemTools::FileIsDirectory(file.c_str())) + if(gpos == file.npos && cmSystemTools::FileIsDirectory(file.c_str())) { cmOStringStream e; e << modeName << " given directory \"" << (*fileIt) << "\" to install."; diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index cc62c4b..488d486 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -133,7 +133,7 @@ void cmInstallFilesCommand::CreateInstallGenerator() const "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); std::vector<std::string> no_configurations; this->Makefile->AddInstallGenerator( - new cmInstallFilesGenerator(this->Files, + new cmInstallFilesGenerator(this->Makefile, this->Files, destination.c_str(), false, no_permissions, no_configurations, no_component.c_str(), no_rename)); @@ -148,7 +148,8 @@ void cmInstallFilesCommand::CreateInstallGenerator() const */ std::string cmInstallFilesCommand::FindInstallSource(const char* name) const { - if(cmSystemTools::FileIsFullPath(name)) + if(cmSystemTools::FileIsFullPath(name) || + cmGeneratorExpression::Find(name) == 0) { // This is a full path. return name; diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index ec02bc7..ec15044 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -11,9 +11,13 @@ ============================================================================*/ #include "cmInstallFilesGenerator.h" +#include "cmGeneratorExpression.h" +#include "cmSystemTools.h" + //---------------------------------------------------------------------------- cmInstallFilesGenerator -::cmInstallFilesGenerator(std::vector<std::string> const& files, +::cmInstallFilesGenerator(cmMakefile* mf, + std::vector<std::string> const& files, const char* dest, bool programs, const char* file_permissions, std::vector<std::string> const& configurations, @@ -21,10 +25,20 @@ cmInstallFilesGenerator const char* rename, bool optional): cmInstallGenerator(dest, configurations, component), + Makefile(mf), Files(files), Programs(programs), FilePermissions(file_permissions), Rename(rename), Optional(optional) { + // We need per-config actions if any files have generator expressions. + for(std::vector<std::string>::const_iterator i = files.begin(); + !this->ActionsPerConfig && i != files.end(); ++i) + { + if(cmGeneratorExpression::Find(*i) != std::string::npos) + { + this->ActionsPerConfig = true; + } + } } //---------------------------------------------------------------------------- @@ -34,8 +48,9 @@ cmInstallFilesGenerator } //---------------------------------------------------------------------------- -void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os, - Indent const& indent) +void cmInstallFilesGenerator::AddFilesInstallRule( + std::ostream& os, Indent const& indent, + std::vector<std::string> const& files) { // Write code to install the files. const char* no_dir_permissions = 0; @@ -43,8 +58,40 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os, (this->Programs ? cmInstallType_PROGRAMS : cmInstallType_FILES), - this->Files, + files, this->Optional, this->FilePermissions.c_str(), no_dir_permissions, this->Rename.c_str(), 0, indent); } + +//---------------------------------------------------------------------------- +void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os, + Indent const& indent) +{ + if(this->ActionsPerConfig) + { + this->cmInstallGenerator::GenerateScriptActions(os, indent); + } + else + { + this->AddFilesInstallRule(os, indent, this->Files); + } +} + +//---------------------------------------------------------------------------- +void cmInstallFilesGenerator::GenerateScriptForConfig(std::ostream& os, + const char* config, + Indent const& indent) +{ + std::vector<std::string> files; + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + for(std::vector<std::string>::const_iterator i = this->Files.begin(); + i != this->Files.end(); ++i) + { + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*i); + cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile, config), + files); + } + this->AddFilesInstallRule(os, indent, files); +} diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index 871335c..9dea296 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -14,13 +14,16 @@ #include "cmInstallGenerator.h" +class cmMakefile; + /** \class cmInstallFilesGenerator * \brief Generate file installation rules. */ class cmInstallFilesGenerator: public cmInstallGenerator { public: - cmInstallFilesGenerator(std::vector<std::string> const& files, + cmInstallFilesGenerator(cmMakefile* mf, + std::vector<std::string> const& files, const char* dest, bool programs, const char* file_permissions, std::vector<std::string> const& configurations, @@ -31,6 +34,13 @@ public: protected: virtual void GenerateScriptActions(std::ostream& os, Indent const& indent); + virtual void GenerateScriptForConfig(std::ostream& os, + const char* config, + Indent const& indent); + void AddFilesInstallRule(std::ostream& os, Indent const& indent, + std::vector<std::string> const& files); + + cmMakefile* Makefile; std::vector<std::string> Files; bool Programs; std::string FilePermissions; diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index 3a0a322..54d903a 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -94,7 +94,7 @@ void cmInstallProgramsCommand::FinalPass() "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); std::vector<std::string> no_configurations; this->Makefile->AddInstallGenerator( - new cmInstallFilesGenerator(this->Files, + new cmInstallFilesGenerator(this->Makefile, this->Files, destination.c_str(), true, no_permissions, no_configurations, no_component.c_str(), no_rename)); @@ -109,7 +109,8 @@ void cmInstallProgramsCommand::FinalPass() std::string cmInstallProgramsCommand ::FindInstallSource(const char* name) const { - if(cmSystemTools::FileIsFullPath(name)) + if(cmSystemTools::FileIsFullPath(name) || + cmGeneratorExpression::Find(name) == 0) { // This is a full path. return name; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index aca195c..4266dd0 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -901,6 +901,13 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable, return replaceValues.TargetPDB; } } + if(replaceValues.TargetCompilePDB) + { + if(variable == "TARGET_COMPILE_PDB") + { + return replaceValues.TargetCompilePDB; + } + } if(replaceValues.DependencyFile ) { if(variable == "DEP_FILE") diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 9764813..0f7fd25 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -245,6 +245,7 @@ public: } cmTarget* CMTarget; const char* TargetPDB; + const char* TargetCompilePDB; const char* TargetVersionMajor; const char* TargetVersionMinor; const char* Language; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 212b06b..d11bf55 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -660,7 +660,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, switch(target.GetType()) { case cmTarget::OBJECT_LIBRARY: - targetBuilds = false; // TODO: PDB for object library? + targetBuilds = false; // no manifest tool for object library case cmTarget::STATIC_LIBRARY: projectType = "typeStaticLibrary"; configType = "4"; @@ -846,6 +846,17 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, targetOptions.OutputFlagMap(fout, "\t\t\t\t"); targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX"); fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n"; + if(target.GetType() <= cmTarget::OBJECT_LIBRARY) + { + // Specify the compiler program database file if configured. + std::string pdb = target.GetCompilePDBPath(configName); + if(!pdb.empty()) + { + fout << "\t\t\t\tProgramDataBaseFileName=\"" + << this->ConvertToXMLOutputPathSingle(pdb.c_str()) + << "\"\n"; + } + } fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool tool = "VCCustomBuildTool"; if(this->FortranProject) @@ -1033,7 +1044,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, fout << "\t\t\t<Tool\n" << "\t\t\t\tName=\"" << tool << "\"\n"; - if(this->GetVersion() < VS8) + if(this->GetVersion() < VS8 || this->FortranProject) { cmOStringStream libdeps; this->Internal->OutputObjects(libdeps, &target); @@ -1093,7 +1104,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); - if(this->GetVersion() < VS8) + if(this->GetVersion() < VS8 || this->FortranProject) { this->Internal->OutputObjects(fout, &target, " "); } @@ -1191,7 +1202,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); - if(this->GetVersion() < VS8) + if(this->GetVersion() < VS8 || this->FortranProject) { this->Internal->OutputObjects(fout, &target, " "); } @@ -1412,7 +1423,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, this->WriteGroup(&sg, target, fout, libName, configs); } - if(this->GetVersion() >= VS8) + if(this->GetVersion() >= VS8 && !this->FortranProject) { // VS >= 8 support per-config source locations so we // list object library content as external objects. diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 69b8092..03fdda2 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -129,7 +129,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } } - std::string pdbOutputPath = this->Target->GetPDBDirectory(); + std::string compilePdbOutputPath = + this->Target->GetCompilePDBDirectory(this->ConfigName); + cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str()); + + std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName); cmSystemTools::MakeDirectory(pdbOutputPath.c_str()); pdbOutputPath += "/"; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index d6a0cd4..807aca8 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -321,7 +321,11 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules } } - std::string pdbOutputPath = this->Target->GetPDBDirectory(); + std::string compilePdbOutputPath = + this->Target->GetCompilePDBDirectory(this->ConfigName); + cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str()); + + std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName); cmSystemTools::MakeDirectory(pdbOutputPath.c_str()); pdbOutputPath += "/"; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index c3ca85d..e8a9fd1 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -624,9 +624,11 @@ cmMakefileTargetGenerator std::string targetOutPathReal; std::string targetOutPathPDB; + std::string targetOutPathCompilePDB; { std::string targetFullPathReal; std::string targetFullPathPDB; + std::string targetFullPathCompilePDB; if(this->Target->GetType() == cmTarget::EXECUTABLE || this->Target->GetType() == cmTarget::STATIC_LIBRARY || this->Target->GetType() == cmTarget::SHARED_LIBRARY || @@ -638,12 +640,26 @@ cmMakefileTargetGenerator targetFullPathPDB += "/"; targetFullPathPDB += this->Target->GetPDBName(this->ConfigName); } + if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) + { + targetFullPathCompilePDB = + this->Target->GetCompilePDBPath(this->ConfigName); + if(targetFullPathCompilePDB.empty()) + { + targetFullPathCompilePDB = this->Target->GetSupportDirectory() + "/"; + } + } + targetOutPathReal = this->Convert(targetFullPathReal.c_str(), cmLocalGenerator::START_OUTPUT, cmLocalGenerator::SHELL); targetOutPathPDB = this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE, cmLocalGenerator::SHELL); + targetOutPathCompilePDB = + this->Convert(targetFullPathCompilePDB.c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); } cmLocalGenerator::RuleVariables vars; vars.RuleLauncher = "RULE_LAUNCH_COMPILE"; @@ -651,6 +667,7 @@ cmMakefileTargetGenerator vars.Language = lang; vars.Target = targetOutPathReal.c_str(); vars.TargetPDB = targetOutPathPDB.c_str(); + vars.TargetCompilePDB = targetOutPathCompilePDB.c_str(); vars.Source = sourceFile.c_str(); std::string shellObj = this->Convert(obj.c_str(), @@ -1650,9 +1667,10 @@ void cmMakefileTargetGenerator this->AppendTargetDepends(depends); // Add a dependency on the link definitions file, if any. - if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + if(!def.empty()) { - depends.push_back(this->GeneratorTarget->ModuleDefinitionFile); + depends.push_back(def); } // Add user-specified dependencies. @@ -2019,7 +2037,8 @@ void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags) //---------------------------------------------------------------------------- void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags) { - if(this->GeneratorTarget->ModuleDefinitionFile.empty()) + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + if(def.empty()) { return; } @@ -2035,8 +2054,7 @@ void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags) // Append the flag and value. Use ConvertToLinkReference to help // vs6's "cl -link" pass it to the linker. std::string flag = defFileFlag; - flag += (this->LocalGenerator->ConvertToLinkReference( - this->GeneratorTarget->ModuleDefinitionFile.c_str())); + flag += (this->LocalGenerator->ConvertToLinkReference(def.c_str())); this->LocalGenerator->AppendFlags(flags, flag.c_str()); } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 900af8d..00b0441 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -320,6 +320,7 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID")) { std::string pdbPath; + std::string compilePdbPath; if(this->Target->GetType() == cmTarget::EXECUTABLE || this->Target->GetType() == cmTarget::STATIC_LIBRARY || this->Target->GetType() == cmTarget::SHARED_LIBRARY || @@ -329,11 +330,25 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const pdbPath += "/"; pdbPath += this->Target->GetPDBName(this->GetConfigName()); } + if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) + { + compilePdbPath = this->Target->GetCompilePDBPath(this->GetConfigName()); + if(compilePdbPath.empty()) + { + compilePdbPath = this->Target->GetSupportDirectory() + "/"; + } + } vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat( ConvertToNinjaPath(pdbPath.c_str()).c_str(), cmLocalGenerator::SHELL); + vars["TARGET_COMPILE_PDB"] = + this->GetLocalGenerator()->ConvertToOutputFormat( + ConvertToNinjaPath(compilePdbPath.c_str()).c_str(), + cmLocalGenerator::SHELL); + EnsureParentDirectoryExists(pdbPath); + EnsureParentDirectoryExists(compilePdbPath); return true; } return false; @@ -362,6 +377,7 @@ cmNinjaTargetGenerator vars.Object = "$out"; vars.Defines = "$DEFINES"; vars.TargetPDB = "$TARGET_PDB"; + vars.TargetCompilePDB = "$TARGET_COMPILE_PDB"; vars.ObjectDir = "$OBJECT_DIR"; cmMakefile* mf = this->GetMakefile(); @@ -498,10 +514,10 @@ cmNinjaTargetGenerator { this->WriteObjectBuildStatement(*si); } - if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + if(!def.empty()) { - this->ModuleDefinitionFile = this->ConvertToNinjaPath( - this->GeneratorTarget->ModuleDefinitionFile.c_str()); + this->ModuleDefinitionFile = this->ConvertToNinjaPath(def.c_str()); } { diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 9a340dc..78b59b3 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -20,7 +20,7 @@ cmOSXBundleGenerator:: cmOSXBundleGenerator(cmGeneratorTarget* target, const char* configName) - : Target(target->Target) + : GT(target) , Makefile(target->Target->GetMakefile()) , LocalGenerator(Makefile->GetLocalGenerator()) , ConfigName(configName) @@ -34,7 +34,7 @@ cmOSXBundleGenerator(cmGeneratorTarget* target, //---------------------------------------------------------------------------- bool cmOSXBundleGenerator::MustSkip() { - return !this->Target->HaveWellDefinedOutputFiles(); + return !this->GT->Target->HaveWellDefinedOutputFiles(); } //---------------------------------------------------------------------------- @@ -47,7 +47,7 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, // Compute bundle directory names. std::string out = outpath; out += "/"; - out += this->Target->GetAppBundleDirectory(this->ConfigName, false); + out += this->GT->Target->GetAppBundleDirectory(this->ConfigName, false); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); @@ -57,9 +57,9 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, // to be set. std::string plist = outpath; plist += "/"; - plist += this->Target->GetAppBundleDirectory(this->ConfigName, true); + plist += this->GT->Target->GetAppBundleDirectory(this->ConfigName, true); plist += "/Info.plist"; - this->LocalGenerator->GenerateAppleInfoPList(this->Target, + this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target, targetName.c_str(), plist.c_str()); this->Makefile->AddCMakeOutputFile(plist); @@ -77,20 +77,20 @@ void cmOSXBundleGenerator::CreateFramework( // Compute the location of the top-level foo.framework directory. std::string contentdir = outpath + "/" + - this->Target->GetFrameworkDirectory(this->ConfigName, true); + this->GT->Target->GetFrameworkDirectory(this->ConfigName, true); contentdir += "/"; std::string newoutpath = outpath + "/" + - this->Target->GetFrameworkDirectory(this->ConfigName, false); + this->GT->Target->GetFrameworkDirectory(this->ConfigName, false); - std::string frameworkVersion = this->Target->GetFrameworkVersion(); + std::string frameworkVersion = this->GT->Target->GetFrameworkVersion(); // Configure the Info.plist file into the Resources directory. this->MacContentFolders->insert("Resources"); std::string plist = newoutpath; plist += "/Resources/Info.plist"; std::string name = cmSystemTools::GetFilenameName(targetName); - this->LocalGenerator->GenerateFrameworkInfoPList(this->Target, + this->LocalGenerator->GenerateFrameworkInfoPList(this->GT->Target, name.c_str(), plist.c_str()); @@ -172,16 +172,16 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, // Compute bundle directory names. std::string out = root; out += "/"; - out += this->Target->GetCFBundleDirectory(this->ConfigName, false); + out += this->GT->Target->GetCFBundleDirectory(this->ConfigName, false); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. std::string plist = - this->Target->GetCFBundleDirectory(this->ConfigName, true); + this->GT->Target->GetCFBundleDirectory(this->ConfigName, true); plist += "/Info.plist"; - this->LocalGenerator->GenerateAppleInfoPList(this->Target, + this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target, targetName.c_str(), plist.c_str()); this->Makefile->AddCMakeOutputFile(plist); @@ -199,9 +199,9 @@ GenerateMacOSXContentStatements(std::vector<cmSourceFile*> const& sources, for(std::vector<cmSourceFile*>::const_iterator si = sources.begin(); si != sources.end(); ++si) { - cmTarget::SourceFileFlags tsFlags = - this->Target->GetTargetSourceFileFlags(*si); - if(tsFlags.Type != cmTarget::SourceFileTypeNormal) + cmGeneratorTarget::SourceFileFlags tsFlags = + this->GT->GetTargetSourceFileFlags(*si); + if(tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) { (*generator)(**si, tsFlags.MacFolder); } @@ -215,7 +215,7 @@ cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc) // Construct the full path to the content subdirectory. std::string macdir = - this->Target->GetMacContentDirectory(this->ConfigName, + this->GT->Target->GetMacContentDirectory(this->ConfigName, /*implib*/ false); macdir += "/"; macdir += pkgloc; diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 29b7611..2f36394 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -59,7 +59,7 @@ private: bool MustSkip(); private: - cmTarget* Target; + cmGeneratorTarget* GT; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; const char* ConfigName; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index ff05975..7cc63bb 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1044,7 +1044,7 @@ void cmSystemTools::ExpandListArgument(const std::string& arg, bool emptyArgs) { // If argument is empty, it is an empty list. - if(arg.length() == 0 && !emptyArgs) + if(!emptyArgs && arg.empty()) { return; } @@ -1054,10 +1054,11 @@ void cmSystemTools::ExpandListArgument(const std::string& arg, newargs.push_back(arg); return; } - std::vector<char> newArgVec; + std::string newArg; + const char *last = arg.c_str(); // Break the string at non-escaped semicolons not nested in []. int squareNesting = 0; - for(const char* c = arg.c_str(); *c; ++c) + for(const char* c = last; *c; ++c) { switch(*c) { @@ -1065,34 +1066,21 @@ void cmSystemTools::ExpandListArgument(const std::string& arg, { // We only want to allow escaping of semicolons. Other // escapes should not be processed here. - ++c; - if(*c == ';') - { - newArgVec.push_back(*c); - } - else + const char* next = c + 1; + if(*next == ';') { - newArgVec.push_back('\\'); - if(*c) - { - newArgVec.push_back(*c); - } - else - { - // Terminate the loop properly. - --c; - } + newArg.append(last, c - last); + // Skip over the escape character + last = c = next; } } break; case '[': { ++squareNesting; - newArgVec.push_back(*c); } break; case ']': { --squareNesting; - newArgVec.push_back(*c); } break; case ';': { @@ -1100,31 +1088,28 @@ void cmSystemTools::ExpandListArgument(const std::string& arg, // brackets. if(squareNesting == 0) { - if ( newArgVec.size() || emptyArgs ) + newArg.append(last, c - last); + // Skip over the semicolon + last = c + 1; + if ( !newArg.empty() || emptyArgs ) { // Add the last argument if the string is not empty. - newArgVec.push_back(0); - newargs.push_back(&*newArgVec.begin()); - newArgVec.clear(); + newargs.push_back(newArg); + newArg = ""; } } - else - { - newArgVec.push_back(*c); - } } break; default: { // Just append this character. - newArgVec.push_back(*c); } break; } } - if ( newArgVec.size() || emptyArgs ) + newArg.append(last); + if ( !newArg.empty() || emptyArgs ) { // Add the last argument if the string is not empty. - newArgVec.push_back(0); - newargs.push_back(&*newArgVec.begin()); + newargs.push_back(newArg); } } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index db34bd8..1c2b27a 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -71,6 +71,12 @@ struct cmTarget::ImportInfo cmTarget::LinkInterface LinkInterface; }; +//---------------------------------------------------------------------------- +struct cmTarget::CompileInfo +{ + std::string CompilePdbDir; +}; + struct TargetConfigPair : public std::pair<cmTarget const* , std::string> { TargetConfigPair(cmTarget const* tgt, const std::string &config) : std::pair<cmTarget const* , std::string>(tgt, config) {} @@ -83,17 +89,12 @@ public: cmTargetInternals() { this->PolicyWarnedCMP0022 = false; - this->SourceFileFlagsConstructed = false; } cmTargetInternals(cmTargetInternals const&) { this->PolicyWarnedCMP0022 = false; - this->SourceFileFlagsConstructed = false; } ~cmTargetInternals(); - typedef cmTarget::SourceFileFlags SourceFileFlags; - mutable std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap; - mutable bool SourceFileFlagsConstructed; // The backtrace when the target was created. cmListFileBacktrace Backtrace; @@ -101,9 +102,17 @@ public: // Cache link interface computation from each configuration. struct OptionalLinkInterface: public cmTarget::LinkInterface { - OptionalLinkInterface(): Exists(false) {} + OptionalLinkInterface(): + Exists(false), Complete(false), ExplicitLibraries(0) {} bool Exists; + bool Complete; + const char* ExplicitLibraries; }; + void ComputeLinkInterface(cmTarget const* thisTarget, + const char* config, OptionalLinkInterface& iface, + cmTarget const* head, + const char *explicitLibraries) const; + typedef std::map<TargetConfigPair, OptionalLinkInterface> LinkInterfaceMapType; LinkInterfaceMapType LinkInterfaceMap; @@ -116,6 +125,9 @@ public: ImportInfoMapType; ImportInfoMapType ImportInfoMap; + typedef std::map<std::string, cmTarget::CompileInfo> CompileInfoMapType; + CompileInfoMapType CompileInfoMap; + // Cache link implementation computation from each configuration. typedef std::map<TargetConfigPair, cmTarget::LinkImplementation> LinkImplMapType; @@ -267,6 +279,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0); + this->SetPropertyDefault("COMPILE_PDB_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("Fortran_FORMAT", 0); this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0); this->SetPropertyDefault("GNUtoMS", 0); @@ -295,6 +308,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) "LIBRARY_OUTPUT_DIRECTORY_", "RUNTIME_OUTPUT_DIRECTORY_", "PDB_OUTPUT_DIRECTORY_", + "COMPILE_PDB_OUTPUT_DIRECTORY_", "MAP_IMPORTED_CONFIG_", 0}; for(std::vector<std::string>::iterator ci = configNames.begin(); @@ -527,10 +541,11 @@ bool cmTarget::IsBundleOnApple() const } //---------------------------------------------------------------------------- -bool cmTarget::FindSourceFiles() +void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const { + assert(this->GetType() != INTERFACE_LIBRARY); for(std::vector<cmSourceFile*>::const_iterator - si = this->SourceFiles.begin(); + si = this->SourceFiles.begin(); si != this->SourceFiles.end(); ++si) { std::string e; @@ -542,16 +557,9 @@ bool cmTarget::FindSourceFiles() cm->IssueMessage(cmake::FATAL_ERROR, e, this->GetBacktrace()); } - return false; + return; } } - return true; -} - -//---------------------------------------------------------------------------- -void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const -{ - assert(this->GetType() != INTERFACE_LIBRARY); files = this->SourceFiles; } @@ -648,109 +656,6 @@ void cmTarget::ProcessSourceExpression(std::string const& expr) } //---------------------------------------------------------------------------- -struct cmTarget::SourceFileFlags -cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const -{ - struct SourceFileFlags flags; - this->ConstructSourceFileFlags(); - std::map<cmSourceFile const*, SourceFileFlags>::iterator si = - this->Internal->SourceFlagsMap.find(sf); - if(si != this->Internal->SourceFlagsMap.end()) - { - flags = si->second; - } - return flags; -} - -//---------------------------------------------------------------------------- -void cmTarget::ConstructSourceFileFlags() const -{ - if(this->Internal->SourceFileFlagsConstructed) - { - return; - } - this->Internal->SourceFileFlagsConstructed = true; - - // Process public headers to mark the source files. - if(const char* files = this->GetProperty("PUBLIC_HEADER")) - { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); - for(std::vector<std::string>::iterator it = relFiles.begin(); - it != relFiles.end(); ++it) - { - if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) - { - SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf]; - flags.MacFolder = "Headers"; - flags.Type = cmTarget::SourceFileTypePublicHeader; - } - } - } - - // Process private headers after public headers so that they take - // precedence if a file is listed in both. - if(const char* files = this->GetProperty("PRIVATE_HEADER")) - { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); - for(std::vector<std::string>::iterator it = relFiles.begin(); - it != relFiles.end(); ++it) - { - if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) - { - SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf]; - flags.MacFolder = "PrivateHeaders"; - flags.Type = cmTarget::SourceFileTypePrivateHeader; - } - } - } - - // Mark sources listed as resources. - if(const char* files = this->GetProperty("RESOURCE")) - { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); - for(std::vector<std::string>::iterator it = relFiles.begin(); - it != relFiles.end(); ++it) - { - if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str())) - { - SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf]; - flags.MacFolder = "Resources"; - flags.Type = cmTarget::SourceFileTypeResource; - } - } - } - - // Handle the MACOSX_PACKAGE_LOCATION property on source files that - // were not listed in one of the other lists. - std::vector<cmSourceFile*> sources; - this->GetSourceFiles(sources); - for(std::vector<cmSourceFile*>::const_iterator si = sources.begin(); - si != sources.end(); ++si) - { - cmSourceFile* sf = *si; - if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) - { - SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf]; - if(flags.Type == cmTarget::SourceFileTypeNormal) - { - flags.MacFolder = location; - if(strcmp(location, "Resources") == 0) - { - flags.Type = cmTarget::SourceFileTypeResource; - } - else - { - flags.Type = cmTarget::SourceFileTypeMacContent; - } - } - } - } -} - -//---------------------------------------------------------------------------- void cmTarget::MergeLinkLibraries( cmMakefile& mf, const char *selfname, const LinkLibraryVectorType& libs ) @@ -2467,7 +2372,7 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config) const OutputInfo info; this->ComputeOutputDir(config, false, info.OutDir); this->ComputeOutputDir(config, true, info.ImpDir); - if(!this->ComputePDBOutputDir(config, info.PdbDir)) + if(!this->ComputePDBOutputDir("PDB", config, info.PdbDir)) { info.PdbDir = info.OutDir; } @@ -2478,6 +2383,45 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config) const } //---------------------------------------------------------------------------- +cmTarget::CompileInfo const* cmTarget::GetCompileInfo(const char* config) const +{ + // There is no compile information for imported targets. + if(this->IsImported()) + { + return 0; + } + + if(this->GetType() > cmTarget::OBJECT_LIBRARY) + { + std::string msg = "cmTarget::GetCompileInfo called for "; + msg += this->GetName(); + msg += " which has type "; + msg += cmTarget::GetTargetTypeName(this->GetType()); + this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg); + abort(); + return 0; + } + + // Lookup/compute/cache the compile information for this configuration. + std::string config_upper; + if(config && *config) + { + config_upper = cmSystemTools::UpperCase(config); + } + typedef cmTargetInternals::CompileInfoMapType CompileInfoMapType; + CompileInfoMapType::const_iterator i = + this->Internal->CompileInfoMap.find(config_upper); + if(i == this->Internal->CompileInfoMap.end()) + { + CompileInfo info; + this->ComputePDBOutputDir("COMPILE_PDB", config, info.CompilePdbDir); + CompileInfoMapType::value_type entry(config_upper, info); + i = this->Internal->CompileInfoMap.insert(entry).first; + } + return &i->second; +} + +//---------------------------------------------------------------------------- std::string cmTarget::GetDirectory(const char* config, bool implib) const { if (this->IsImported()) @@ -2507,6 +2451,16 @@ std::string cmTarget::GetPDBDirectory(const char* config) const } //---------------------------------------------------------------------------- +std::string cmTarget::GetCompilePDBDirectory(const char* config) const +{ + if(CompileInfo const* info = this->GetCompileInfo(config)) + { + return info->CompilePdbDir; + } + return ""; +} + +//---------------------------------------------------------------------------- const char* cmTarget::GetLocation(const char* config) const { if (this->IsImported()) @@ -3167,6 +3121,49 @@ std::string cmTarget::GetPDBName(const char* config) const } //---------------------------------------------------------------------------- +std::string cmTarget::GetCompilePDBName(const char* config) const +{ + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, false, prefix, base, suffix); + + // Check for a per-configuration output directory target property. + std::string configUpper = cmSystemTools::UpperCase(config? config : ""); + std::string configProp = "COMPILE_PDB_NAME_"; + configProp += configUpper; + const char* config_name = this->GetProperty(configProp.c_str()); + if(config_name && *config_name) + { + return prefix + config_name + ".pdb"; + } + + const char* name = this->GetProperty("COMPILE_PDB_NAME"); + if(name && *name) + { + return prefix + name + ".pdb"; + } + + return ""; +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetCompilePDBPath(const char* config) const +{ + std::string dir = this->GetCompilePDBDirectory(config); + std::string name = this->GetCompilePDBName(config); + if(dir.empty() && !name.empty()) + { + dir = this->GetPDBDirectory(config); + } + if(!dir.empty()) + { + dir += "/"; + } + return dir + name; +} + +//---------------------------------------------------------------------------- bool cmTarget::HasSOName(const char* config) const { // soname is supported only for shared libraries and modules, @@ -4111,13 +4108,13 @@ bool cmTarget::ComputeOutputDir(const char* config, } //---------------------------------------------------------------------------- -bool cmTarget::ComputePDBOutputDir(const char* config, std::string& out) const +bool cmTarget::ComputePDBOutputDir(const char* kind, const char* config, + std::string& out) const { // Look for a target property defining the target output directory // based on the target type. - std::string targetTypeName = "PDB"; const char* propertyName = 0; - std::string propertyNameStr = targetTypeName; + std::string propertyNameStr = kind; if(!propertyNameStr.empty()) { propertyNameStr += "_OUTPUT_DIRECTORY"; @@ -4127,7 +4124,7 @@ bool cmTarget::ComputePDBOutputDir(const char* config, std::string& out) const // Check for a per-configuration output directory target property. std::string configUpper = cmSystemTools::UpperCase(config? config : ""); const char* configProp = 0; - std::string configPropStr = targetTypeName; + std::string configPropStr = kind; if(!configPropStr.empty()) { configPropStr += "_OUTPUT_DIRECTORY_"; @@ -4530,12 +4527,13 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet)); - cmComputeLinkInformation *info = tgt->GetLinkInformation(config); - if(!info) + std::vector<cmTarget*> deps; + tgt->GetTransitiveTargetClosure(config, tgt, deps); + + if(deps.empty()) { return propContent; } - const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); bool propInitialized = explicitlySet; std::string report = " * Target \""; @@ -4555,7 +4553,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, report += "\" property not set.\n"; } - for(cmComputeLinkInformation::ItemVector::const_iterator li = + for(std::vector<cmTarget*>::const_iterator li = deps.begin(); li != deps.end(); ++li) { @@ -4565,23 +4563,20 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, // target itself has a POSITION_INDEPENDENT_CODE which disagrees // with a dependency. - if (!li->Target) - { - continue; - } + cmTarget const* theTarget = *li; - const bool ifaceIsSet = li->Target->GetProperties() + const bool ifaceIsSet = theTarget->GetProperties() .find("INTERFACE_" + p) - != li->Target->GetProperties().end(); + != theTarget->GetProperties().end(); PropertyType ifacePropContent = - getTypedProperty<PropertyType>(li->Target, + getTypedProperty<PropertyType>(theTarget, ("INTERFACE_" + p).c_str(), 0); std::string reportEntry; if (ifaceIsSet) { reportEntry += " * Target \""; - reportEntry += li->Target->GetName(); + reportEntry += theTarget->GetName(); reportEntry += "\" property value \""; reportEntry += valueAsString<PropertyType>(ifacePropContent); reportEntry += "\" "; @@ -4602,7 +4597,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, e << "Property " << p << " on target \"" << tgt->GetName() << "\" does\nnot match the " "INTERFACE_" << p << " property requirement\nof " - "dependency \"" << li->Target->GetName() << "\".\n"; + "dependency \"" << theTarget->GetName() << "\".\n"; cmSystemTools::Error(e.str().c_str()); break; } @@ -4636,7 +4631,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, << tgt->GetName() << "\" is\nimplied to be " << defaultValue << " because it was used to determine the link libraries\n" "already. The INTERFACE_" << p << " property on\ndependency \"" - << li->Target->GetName() << "\" is in conflict.\n"; + << theTarget->GetName() << "\" is in conflict.\n"; cmSystemTools::Error(e.str().c_str()); break; } @@ -4667,7 +4662,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, { cmOStringStream e; e << "The INTERFACE_" << p << " property of \"" - << li->Target->GetName() << "\" does\nnot agree with the value " + << theTarget->GetName() << "\" does\nnot agree with the value " "of " << p << " already determined\nfor \"" << tgt->GetName() << "\".\n"; cmSystemTools::Error(e.str().c_str()); @@ -4748,23 +4743,19 @@ bool isLinkDependentProperty(cmTarget const* tgt, const std::string &p, const char *interfaceProperty, const char *config) { - cmComputeLinkInformation *info = tgt->GetLinkInformation(config); - if(!info) + std::vector<cmTarget*> deps; + tgt->GetTransitiveTargetClosure(config, tgt, deps); + + if(deps.empty()) { return false; } - const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); - - for(cmComputeLinkInformation::ItemVector::const_iterator li = + for(std::vector<cmTarget*>::const_iterator li = deps.begin(); li != deps.end(); ++li) { - if (!li->Target) - { - continue; - } - const char *prop = li->Target->GetProperty(interfaceProperty); + const char *prop = (*li)->GetProperty(interfaceProperty); if (!prop) { continue; @@ -5316,24 +5307,124 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config, { // Compute the link interface for this configuration. cmTargetInternals::OptionalLinkInterface iface; - iface.Exists = this->ComputeLinkInterface(config, iface, head); + iface.ExplicitLibraries = + this->ComputeLinkInterfaceLibraries(config, iface, head, iface.Exists); + if (iface.Exists) + { + this->Internal->ComputeLinkInterface(this, config, iface, + head, iface.ExplicitLibraries); + } // Store the information for this configuration. cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); i = this->Internal->LinkInterfaceMap.insert(entry).first; } + else if(!i->second.Complete && i->second.Exists) + { + this->Internal->ComputeLinkInterface(this, config, i->second, head, + i->second.ExplicitLibraries); + } - return i->second.Exists? &i->second : 0; + return i->second.Exists ? &i->second : 0; } //---------------------------------------------------------------------------- -void cmTarget::GetTransitivePropertyLinkLibraries( - const char* config, +cmTarget::LinkInterface const* +cmTarget::GetLinkInterfaceLibraries(const char* config, + cmTarget const* head) const +{ + // Imported targets have their own link interface. + if(this->IsImported()) + { + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head)) + { + return &info->LinkInterface; + } + return 0; + } + + // Link interfaces are not supported for executables that do not + // export symbols. + if(this->GetType() == cmTarget::EXECUTABLE && + !this->IsExecutableWithExports()) + { + return 0; + } + + // Lookup any existing link interface for this configuration. + TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : "")); + + cmTargetInternals::LinkInterfaceMapType::iterator + i = this->Internal->LinkInterfaceMap.find(key); + if(i == this->Internal->LinkInterfaceMap.end()) + { + // Compute the link interface for this configuration. + cmTargetInternals::OptionalLinkInterface iface; + iface.ExplicitLibraries = this->ComputeLinkInterfaceLibraries(config, + iface, + head, + iface.Exists); + + // Store the information for this configuration. + cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); + i = this->Internal->LinkInterfaceMap.insert(entry).first; + } + + return i->second.Exists ? &i->second : 0; +} + +//---------------------------------------------------------------------------- +void processILibs(const char* config, + cmTarget const* headTarget, + std::string const& name, + std::vector<cmTarget*>& tgts, std::set<cmTarget*>& emitted) +{ + if (cmTarget* tgt = headTarget->GetMakefile() + ->FindTargetToUse(name.c_str())) + { + if (emitted.insert(tgt).second) + { + tgts.push_back(tgt); + std::vector<std::string> ilibs; + cmTarget::LinkInterface const* iface = + tgt->GetLinkInterfaceLibraries(config, headTarget); + if (iface) + { + for(std::vector<std::string>::const_iterator + it = iface->Libraries.begin(); + it != iface->Libraries.end(); ++it) + { + processILibs(config, headTarget, *it, tgts, emitted); + } + } + } + } +} + +//---------------------------------------------------------------------------- +void cmTarget::GetTransitiveTargetClosure(const char* config, cmTarget const* headTarget, - std::vector<std::string> &libs) const + std::vector<cmTarget*> &tgts) const { - cmTarget::LinkInterface const* iface = this->GetLinkInterface(config, - headTarget); + std::set<cmTarget*> emitted; + + cmTarget::LinkImplementation const* impl + = this->GetLinkImplementationLibraries(config, headTarget); + + for(std::vector<std::string>::const_iterator it = impl->Libraries.begin(); + it != impl->Libraries.end(); ++it) + { + processILibs(config, headTarget, *it, tgts, emitted); + } +} + +//---------------------------------------------------------------------------- +void cmTarget::GetTransitivePropertyTargets(const char* config, + cmTarget const* headTarget, + std::vector<cmTarget*> &tgts) const +{ + cmTarget::LinkInterface const* iface + = this->GetLinkInterfaceLibraries(config, headTarget); if (!iface) { return; @@ -5342,7 +5433,15 @@ void cmTarget::GetTransitivePropertyLinkLibraries( || this->GetPolicyStatusCMP0022() == cmPolicies::WARN || this->GetPolicyStatusCMP0022() == cmPolicies::OLD) { - libs = iface->Libraries; + for(std::vector<std::string>::const_iterator it = iface->Libraries.begin(); + it != iface->Libraries.end(); ++it) + { + if (cmTarget* tgt = headTarget->GetMakefile() + ->FindTargetToUse(it->c_str())) + { + tgts.push_back(tgt); + } + } return; } @@ -5360,17 +5459,30 @@ void cmTarget::GetTransitivePropertyLinkLibraries( cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), linkIfaceProp, 0, 0); dagChecker.SetTransitivePropertiesOnly(); + std::vector<std::string> libs; cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate( this->Makefile, config, false, headTarget, this, &dagChecker), libs); + + for(std::vector<std::string>::const_iterator it = libs.begin(); + it != libs.end(); ++it) + { + if (cmTarget* tgt = headTarget->GetMakefile() + ->FindTargetToUse(it->c_str())) + { + tgts.push_back(tgt); + } + } } //---------------------------------------------------------------------------- -bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, - cmTarget const* headTarget) const +const char* cmTarget::ComputeLinkInterfaceLibraries(const char* config, + LinkInterface& iface, + cmTarget const* headTarget, + bool &exists) const { // Construct the property name suffix for this configuration. std::string suffix = "_"; @@ -5446,8 +5558,10 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, (this->GetType() == cmTarget::EXECUTABLE || (this->GetType() == cmTarget::MODULE_LIBRARY))) { - return false; + exists = false; + return 0; } + exists = true; if(explicitLibraries) { @@ -5462,52 +5576,6 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, false, headTarget, this, &dagChecker), iface.Libraries); - - if(this->GetType() == cmTarget::SHARED_LIBRARY - || this->GetType() == cmTarget::STATIC_LIBRARY - || this->GetType() == cmTarget::INTERFACE_LIBRARY) - { - // Shared libraries may have runtime implementation dependencies - // on other shared libraries that are not in the interface. - std::set<cmStdString> emitted; - for(std::vector<std::string>::const_iterator - li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li) - { - emitted.insert(*li); - } - if (this->GetType() != cmTarget::INTERFACE_LIBRARY) - { - LinkImplementation const* impl = this->GetLinkImplementation(config, - headTarget); - for(std::vector<std::string>::const_iterator - li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) - { - if(emitted.insert(*li).second) - { - if(cmTarget* tgt = this->Makefile->FindTargetToUse(*li)) - { - // This is a runtime dependency on another shared library. - if(tgt->GetType() == cmTarget::SHARED_LIBRARY) - { - iface.SharedDeps.push_back(*li); - } - } - else - { - // TODO: Recognize shared library file names. Perhaps this - // should be moved to cmComputeLinkInformation, but that creates - // a chicken-and-egg problem since this list is needed for its - // construction. - } - } - } - if(this->LinkLanguagePropagatesToDependents()) - { - // Targets using this archive need its language runtime libraries. - iface.Languages = impl->Languages; - } - } - } } else if (this->PolicyStatusCMP0022 == cmPolicies::WARN || this->PolicyStatusCMP0022 == cmPolicies::OLD) @@ -5517,17 +5585,9 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, // to the link implementation. { // The link implementation is the default link interface. - LinkImplementation const* impl = this->GetLinkImplementation(config, - headTarget); - iface.ImplementationIsInterface = true; + LinkImplementation const* impl = + this->GetLinkImplementationLibraries(config, headTarget); iface.Libraries = impl->Libraries; - iface.WrongConfigLibraries = impl->WrongConfigLibraries; - if(this->LinkLanguagePropagatesToDependents()) - { - // Targets using this archive need its language runtime libraries. - iface.Languages = impl->Languages; - } - if(this->PolicyStatusCMP0022 == cmPolicies::WARN && !this->Internal->PolicyWarnedCMP0022) { @@ -5592,25 +5652,107 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, } } } + return explicitLibraries; +} - if(this->GetType() == cmTarget::STATIC_LIBRARY) +//---------------------------------------------------------------------------- +void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, + const char* config, + OptionalLinkInterface& iface, + cmTarget const* headTarget, + const char* explicitLibraries) const +{ + if(explicitLibraries) { + if(thisTarget->GetType() == cmTarget::SHARED_LIBRARY + || thisTarget->GetType() == cmTarget::STATIC_LIBRARY + || thisTarget->GetType() == cmTarget::INTERFACE_LIBRARY) + { + // Shared libraries may have runtime implementation dependencies + // on other shared libraries that are not in the interface. + std::set<cmStdString> emitted; + for(std::vector<std::string>::const_iterator + li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li) + { + emitted.insert(*li); + } + if (thisTarget->GetType() != cmTarget::INTERFACE_LIBRARY) + { + cmTarget::LinkImplementation const* impl = + thisTarget->GetLinkImplementation(config, headTarget); + for(std::vector<std::string>::const_iterator + li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) + { + if(emitted.insert(*li).second) + { + if(cmTarget* tgt = thisTarget->Makefile->FindTargetToUse(*li)) + { + // This is a runtime dependency on another shared library. + if(tgt->GetType() == cmTarget::SHARED_LIBRARY) + { + iface.SharedDeps.push_back(*li); + } + } + else + { + // TODO: Recognize shared library file names. Perhaps this + // should be moved to cmComputeLinkInformation, but that creates + // a chicken-and-egg problem since this list is needed for its + // construction. + } + } + } + if(thisTarget->LinkLanguagePropagatesToDependents()) + { + // Targets using this archive need its language runtime libraries. + iface.Languages = impl->Languages; + } + } + } + } + else if (thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN + || thisTarget->PolicyStatusCMP0022 == cmPolicies::OLD) + { + // The link implementation is the default link interface. + cmTarget::LinkImplementation const* + impl = thisTarget->GetLinkImplementation(config, headTarget); + iface.ImplementationIsInterface = true; + iface.WrongConfigLibraries = impl->WrongConfigLibraries; + if(thisTarget->LinkLanguagePropagatesToDependents()) + { + // Targets using this archive need its language runtime libraries. + iface.Languages = impl->Languages; + } + } + + if(thisTarget->GetType() == cmTarget::STATIC_LIBRARY) + { + // Construct the property name suffix for this configuration. + std::string suffix = "_"; + if(config && *config) + { + suffix += cmSystemTools::UpperCase(config); + } + else + { + suffix += "NOCONFIG"; + } + // How many repetitions are needed if this library has cyclic // dependencies? std::string propName = "LINK_INTERFACE_MULTIPLICITY"; propName += suffix; - if(const char* config_reps = this->GetProperty(propName.c_str())) + if(const char* config_reps = thisTarget->GetProperty(propName.c_str())) { sscanf(config_reps, "%u", &iface.Multiplicity); } else if(const char* reps = - this->GetProperty("LINK_INTERFACE_MULTIPLICITY")) + thisTarget->GetProperty("LINK_INTERFACE_MULTIPLICITY")) { sscanf(reps, "%u", &iface.Multiplicity); } } - - return true; + iface.Complete = true; } //---------------------------------------------------------------------------- @@ -5633,6 +5775,41 @@ cmTarget::GetLinkImplementation(const char* config, cmTarget const* head) const // Compute the link implementation for this configuration. LinkImplementation impl; this->ComputeLinkImplementation(config, impl, head); + this->ComputeLinkImplementationLanguages(impl); + + // Store the information for this configuration. + cmTargetInternals::LinkImplMapType::value_type entry(key, impl); + i = this->Internal->LinkImplMap.insert(entry).first; + } + else if (i->second.Languages.empty()) + { + this->ComputeLinkImplementationLanguages(i->second); + } + + return &i->second; +} + +//---------------------------------------------------------------------------- +cmTarget::LinkImplementation const* +cmTarget::GetLinkImplementationLibraries(const char* config, + cmTarget const* head) const +{ + // There is no link implementation for imported targets. + if(this->IsImported()) + { + return 0; + } + + // Lookup any existing link implementation for this configuration. + TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : "")); + + cmTargetInternals::LinkImplMapType::iterator + i = this->Internal->LinkImplMap.find(key); + if(i == this->Internal->LinkImplMap.end()) + { + // Compute the link implementation for this configuration. + LinkImplementation impl; + this->ComputeLinkImplementation(config, impl, head); // Store the information for this configuration. cmTargetInternals::LinkImplMapType::value_type entry(key, impl); @@ -5715,7 +5892,12 @@ void cmTarget::ComputeLinkImplementation(const char* config, impl.WrongConfigLibraries.push_back(item); } } +} +//---------------------------------------------------------------------------- +void +cmTarget::ComputeLinkImplementationLanguages(LinkImplementation& impl) const +{ // This target needs runtime libraries for its source languages. std::set<cmStdString> languages; // Get languages used in our source files. diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 271824b..471ea94 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -140,34 +140,6 @@ public: } /** - * Flags for a given source file as used in this target. Typically assigned - * via SET_TARGET_PROPERTIES when the property is a list of source files. - */ - enum SourceFileType - { - SourceFileTypeNormal, - SourceFileTypePrivateHeader, // is in "PRIVATE_HEADER" target property - SourceFileTypePublicHeader, // is in "PUBLIC_HEADER" target property - SourceFileTypeResource, // is in "RESOURCE" target property *or* - // has MACOSX_PACKAGE_LOCATION=="Resources" - SourceFileTypeMacContent // has MACOSX_PACKAGE_LOCATION!="Resources" - }; - struct SourceFileFlags - { - SourceFileFlags(): Type(SourceFileTypeNormal), MacFolder(0) {} - SourceFileFlags(SourceFileFlags const& r): - Type(r.Type), MacFolder(r.MacFolder) {} - SourceFileType Type; - const char* MacFolder; // location inside Mac content folders - }; - - /** - * Get the flags for a given source file as used in this target - */ - struct SourceFileFlags - GetTargetSourceFileFlags(const cmSourceFile* sf) const; - - /** * Add sources to the target. */ void AddSources(std::vector<std::string> const& srcs); @@ -292,9 +264,14 @@ public: if the target cannot be linked. */ LinkInterface const* GetLinkInterface(const char* config, cmTarget const* headTarget) const; - void GetTransitivePropertyLinkLibraries(const char* config, + LinkInterface const* GetLinkInterfaceLibraries(const char* config, + cmTarget const* headTarget) const; + void GetTransitivePropertyTargets(const char* config, + cmTarget const* headTarget, + std::vector<cmTarget*> &libs) const; + void GetTransitiveTargetClosure(const char* config, cmTarget const* headTarget, - std::vector<std::string> &libs) const; + std::vector<cmTarget*> &libs) const; /** The link implementation specifies the direct library dependencies needed by the object files of the target. */ @@ -313,6 +290,9 @@ public: LinkImplementation const* GetLinkImplementation(const char* config, cmTarget const* head) const; + LinkImplementation const* GetLinkImplementationLibraries(const char* config, + cmTarget const* head) const; + /** Link information from the transitive closure of the link implementation and the interfaces of its dependencies. */ struct LinkClosure @@ -340,7 +320,13 @@ public: If the configuration name is given then the generator will add its subdirectory for that configuration. Otherwise just the canonical pdb output directory is given. */ - std::string GetPDBDirectory(const char* config = 0) const; + std::string GetPDBDirectory(const char* config) const; + + /** Get the directory in which to place the target compiler .pdb file. + If the configuration name is given then the generator will add its + subdirectory for that configuration. Otherwise just the canonical + compiler pdb output directory is given. */ + std::string GetCompilePDBDirectory(const char* config = 0) const; /** Get the location of the target in the build tree for the given configuration. This location is suitable for use as the LOCATION @@ -358,11 +344,6 @@ public: void GetTargetVersion(bool soversion, int& major, int& minor, int& patch) const; - /** - * Make sure the full path to all source files is known. - */ - bool FindSourceFiles(); - ///! Return the preferred linker language for this target const char* GetLinkerLanguage(const char* config = 0, cmTarget const* head = 0) const; @@ -375,7 +356,13 @@ public: const char* config=0, bool implib = false) const; /** Get the name of the pdb file for the target. */ - std::string GetPDBName(const char* config=0) const; + std::string GetPDBName(const char* config) const; + + /** Get the name of the compiler pdb file for the target. */ + std::string GetCompilePDBName(const char* config=0) const; + + /** Get the path for the MSVC /Fd option for this target. */ + std::string GetCompilePDBPath(const char* config=0) const; /** Whether this library has soname enabled and platform supports it. */ bool HasSOName(const char* config) const; @@ -710,7 +697,8 @@ private: OutputInfo const* GetOutputInfo(const char* config) const; bool ComputeOutputDir(const char* config, bool implib, std::string& out) const; - bool ComputePDBOutputDir(const char* config, std::string& out) const; + bool ComputePDBOutputDir(const char* kind, const char* config, + std::string& out) const; // Cache import information from properties for each configuration. struct ImportInfo; @@ -719,16 +707,23 @@ private: void ComputeImportInfo(std::string const& desired_config, ImportInfo& info, cmTarget const* head) const; + // Cache target compile paths for each configuration. + struct CompileInfo; + CompileInfo const* GetCompileInfo(const char* config) const; + mutable cmTargetLinkInformationMap LinkInformation; void CheckPropertyCompatibility(cmComputeLinkInformation *info, const char* config) const; - bool ComputeLinkInterface(const char* config, LinkInterface& iface, - cmTarget const* head) const; + const char* ComputeLinkInterfaceLibraries(const char* config, + LinkInterface& iface, + cmTarget const* head, + bool &exists) const; void ComputeLinkImplementation(const char* config, LinkImplementation& impl, cmTarget const* head) const; + void ComputeLinkImplementationLanguages(LinkImplementation& impl) const; void ComputeLinkClosure(const char* config, LinkClosure& lc, cmTarget const* head) const; @@ -756,7 +751,6 @@ private: friend class cmTargetTraceDependencies; cmTargetInternalPointer Internal; - void ConstructSourceFileFlags() const; void ComputeVersionedName(std::string& vName, std::string const& prefix, std::string const& base, diff --git a/Source/cmVersion.cxx b/Source/cmVersion.cxx index 047d24d..9cb0cd6 100644 --- a/Source/cmVersion.cxx +++ b/Source/cmVersion.cxx @@ -16,7 +16,7 @@ unsigned int cmVersion::GetMajorVersion() { return CMake_VERSION_MAJOR; } unsigned int cmVersion::GetMinorVersion() { return CMake_VERSION_MINOR; } unsigned int cmVersion::GetPatchVersion() { return CMake_VERSION_PATCH; } -unsigned int cmVersion::GetTweakVersion() { return CMake_VERSION_TWEAK; } +unsigned int cmVersion::GetTweakVersion() { return 0; } const char* cmVersion::GetCMakeVersion() { diff --git a/Source/cmVersionConfig.h.in b/Source/cmVersionConfig.h.in index 76bc8fe..16aeabe 100644 --- a/Source/cmVersionConfig.h.in +++ b/Source/cmVersionConfig.h.in @@ -12,5 +12,4 @@ #define CMake_VERSION_MAJOR @CMake_VERSION_MAJOR@ #define CMake_VERSION_MINOR @CMake_VERSION_MINOR@ #define CMake_VERSION_PATCH @CMake_VERSION_PATCH@ -#define CMake_VERSION_TWEAK @CMake_VERSION_TWEAK@ #define CMake_VERSION "@CMake_VERSION@" diff --git a/Source/cmVersionMacros.h b/Source/cmVersionMacros.h index 67f58ca..cf7f678 100644 --- a/Source/cmVersionMacros.h +++ b/Source/cmVersionMacros.h @@ -14,8 +14,8 @@ #include "cmVersionConfig.h" -#define CMake_VERSION_TWEAK_IS_RELEASE(tweak) ((tweak) < 20000000) -#if CMake_VERSION_TWEAK_IS_RELEASE(CMake_VERSION_TWEAK) +#define CMake_VERSION_PATCH_IS_RELEASE(patch) ((patch) < 20000000) +#if CMake_VERSION_PATCH_IS_RELEASE(CMake_VERSION_PATCH) # define CMake_VERSION_IS_RELEASE 1 #endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index ed7e243..2d21a3d 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1427,6 +1427,17 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", "CXX"); this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3); + + // Specify the compiler program database file if configured. + std::string pdb = this->Target->GetCompilePDBPath(configName.c_str()); + if(!pdb.empty()) + { + this->ConvertToWindowsSlash(pdb); + this->WriteString("<ProgramDataBaseFileName>", 3); + *this->BuildFileStream << cmVS10EscapeXML(pdb) + << "</ProgramDataBaseFileName>\n"; + } + this->WriteString("</ClCompile>\n", 2); } @@ -1666,10 +1677,10 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) linkOptions.AddFlag("ImportLibrary", imLib.c_str()); linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str()); linkOptions.Parse(flags.c_str()); - if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + if(!def.empty()) { - linkOptions.AddFlag("ModuleDefinitionFile", - this->GeneratorTarget->ModuleDefinitionFile.c_str()); + linkOptions.AddFlag("ModuleDefinitionFile", def.c_str()); } this->LinkOptions[config] = pOptions.release(); diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt index 9727930..a875f07 100644 --- a/Tests/BuildDepends/CMakeLists.txt +++ b/Tests/BuildDepends/CMakeLists.txt @@ -68,6 +68,8 @@ file(WRITE ${BuildDepends_BINARY_DIR}/Project/link_depends_no_shared_exe.h "#define link_depends_no_shared_exe_value 0\n") set(link_depends_no_shared_check_txt ${BuildDepends_BINARY_DIR}/Project/link_depends_no_shared_check.txt) +file(WRITE ${BuildDepends_BINARY_DIR}/Project/external.in "external original\n") + help_xcode_depends() message("Building project first time") @@ -166,6 +168,19 @@ else() "Targets link_depends_no_shared_lib and link_depends_no_shared_exe not both built.") endif() +if(EXISTS ${BuildDepends_BINARY_DIR}/Project/external.out) + file(STRINGS ${BuildDepends_BINARY_DIR}/Project/external.out external_out) + if("${external_out}" STREQUAL "external original") + message(STATUS "external.out contains '${external_out}'") + else() + message(SEND_ERROR "Project did not initially build properly: " + "external.out contains '${external_out}'") + endif() +else() + message(SEND_ERROR "Project did not initially build properly: " + "external.out is missing") +endif() + message("Waiting 3 seconds...") # any additional argument will cause ${bar} to wait forever execute_process(COMMAND ${bar} -infinite TIMEOUT 3 OUTPUT_VARIABLE out) @@ -191,6 +206,8 @@ if(TEST_LINK_DEPENDS) file(WRITE ${TEST_LINK_DEPENDS} "2") endif() +file(WRITE ${BuildDepends_BINARY_DIR}/Project/external.in "external changed\n") + help_xcode_depends() message("Building project second time") @@ -294,3 +311,16 @@ else() message(SEND_ERROR "Project did not rebuild properly. " "Targets link_depends_no_shared_lib and link_depends_no_shared_exe not both built.") endif() + +if(EXISTS ${BuildDepends_BINARY_DIR}/Project/external.out) + file(STRINGS ${BuildDepends_BINARY_DIR}/Project/external.out external_out) + if("${external_out}" STREQUAL "external changed") + message(STATUS "external.out contains '${external_out}'") + else() + message(SEND_ERROR "Project did not rebuild properly: " + "external.out contains '${external_out}'") + endif() +else() + message(SEND_ERROR "Project did not rebuild properly: " + "external.out is missing") +endif() diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt index 8806ecd..9ee4a43 100644 --- a/Tests/BuildDepends/Project/CMakeLists.txt +++ b/Tests/BuildDepends/Project/CMakeLists.txt @@ -139,3 +139,15 @@ add_custom_target(header_tgt DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dir/header.h) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_executable(ninjadep ninjadep.cpp) add_dependencies(ninjadep header_tgt) + +include(ExternalProject) +ExternalProject_Add(ExternalBuild + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/External + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/External + STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/External/Stamp + BUILD_ALWAYS 1 + CMAKE_ARGS + -Dexternal_in=${CMAKE_CURRENT_BINARY_DIR}/external.in + -Dexternal_out=${CMAKE_CURRENT_BINARY_DIR}/external.out + INSTALL_COMMAND "" + ) diff --git a/Tests/BuildDepends/Project/External/CMakeLists.txt b/Tests/BuildDepends/Project/External/CMakeLists.txt new file mode 100644 index 0000000..c6015b6 --- /dev/null +++ b/Tests/BuildDepends/Project/External/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.0) +project(BuildDependsExternal NONE) +if(NOT DEFINED external_in) + message(FATAL_ERROR "Define external_in") +endif() +if(NOT DEFINED external_out) + message(FATAL_ERROR "Define external_out") +endif() +add_custom_command( + OUTPUT ${external_out} + COMMAND ${CMAKE_COMMAND} -E copy ${external_in} ${external_out} + DEPENDS ${external_in} + ) +add_custom_target(drive ALL DEPENDS ${external_out}) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 8074a01..c414850 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -381,6 +381,7 @@ if(BUILD_TESTING) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Module/ExternalData") ADD_TEST_MACRO(Module.GenerateExportHeader GenerateExportHeader) + ADD_TEST_MACRO(Module.FindDependency FindDependency) if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") include(CheckCXXCompilerFlag) diff --git a/Tests/CPackWiXGenerator/CMakeLists.txt b/Tests/CPackWiXGenerator/CMakeLists.txt index d673d14..638e788 100644 --- a/Tests/CPackWiXGenerator/CMakeLists.txt +++ b/Tests/CPackWiXGenerator/CMakeLists.txt @@ -9,6 +9,11 @@ target_link_libraries(my-libapp mylib) add_executable(my-other-app myotherapp.cpp) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/empty) +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/empty + DESTINATION extras + COMPONENT extras) + install(TARGETS mylib ARCHIVE DESTINATION lib @@ -58,6 +63,9 @@ set(CPACK_WIX_PATCH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/patch.xml") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt") +set(CPACK_WIX_PROPERTY_ARPCOMMENTS "My Custom ARPCOMMENTS") +set(CPACK_WIX_PROPERTY_ARPHELPLINK "http://www.cmake.org") + include(CPack) cpack_add_install_type(Full DISPLAY_NAME "Everything") @@ -69,6 +77,12 @@ cpack_add_component_group(Development EXPANDED DESCRIPTION "All of the tools you'll ever need to develop software") +cpack_add_component(extras + DISPLAY_NAME "Extras" + DESCRIPTION "Extras" + GROUP Runtime + INSTALL_TYPES Full) + cpack_add_component(applications REQUIRED DISPLAY_NAME "MyLib Application" diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 0e2828e..febdfe6 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -23,6 +23,22 @@ add_library(testLib1 STATIC testLib1.c) add_library(testLib2 STATIC testLib2.c) target_link_libraries(testLib2 testLib1) +# Test install(FILES) with generator expressions referencing testLib1. +add_custom_command(TARGET testLib1 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:testLib1> + $<TARGET_FILE:testLib1>.genex + ) +install(FILES $<TARGET_FILE:testLib1>.genex + DESTINATION lib + ) +set_property(TARGET testLib1 PROPERTY MY_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/testLib1file1.txt + ${CMAKE_CURRENT_SOURCE_DIR}/testLib1file2.txt + ) +install(FILES $<TARGET_PROPERTY:testLib1,MY_FILES> + DESTINATION doc + ) + # Test library with empty link interface. Link it to an implementation # dependency that itself links to dependencies publicly. add_library(testLib3ImpDep SHARED testLib3ImpDep.c) diff --git a/Tests/ExportImport/Export/testLib1file1.txt b/Tests/ExportImport/Export/testLib1file1.txt new file mode 100644 index 0000000..73601df --- /dev/null +++ b/Tests/ExportImport/Export/testLib1file1.txt @@ -0,0 +1 @@ +testLib1file1 diff --git a/Tests/ExportImport/Export/testLib1file2.txt b/Tests/ExportImport/Export/testLib1file2.txt new file mode 100644 index 0000000..4874ed1 --- /dev/null +++ b/Tests/ExportImport/Export/testLib1file2.txt @@ -0,0 +1 @@ +testLib1file2 diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index ebe4af2..eb0bbf8 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -68,6 +68,12 @@ target_link_libraries(imp_testExe1b bld_testLibCycleA ) +add_custom_target(check_testLib1_genex ALL + COMMAND ${CMAKE_COMMAND} -DtestLib1=$<TARGET_FILE:exp_testLib1> + -Dprefix=${CMAKE_INSTALL_PREFIX} + -P ${CMAKE_CURRENT_SOURCE_DIR}/check_testLib1_genex.cmake + ) + add_executable(cmp0022OLD_test cmp0022OLD_test_vs6_1.cpp) target_link_libraries(cmp0022OLD_test bld_cmp0022OLD) add_executable(cmp0022NEW_test cmp0022NEW_test_vs6_1.cpp) diff --git a/Tests/ExportImport/Import/A/check_testLib1_genex.cmake b/Tests/ExportImport/Import/A/check_testLib1_genex.cmake new file mode 100644 index 0000000..7c02652 --- /dev/null +++ b/Tests/ExportImport/Import/A/check_testLib1_genex.cmake @@ -0,0 +1,11 @@ +foreach(f + "${testLib1}.genex" + "${prefix}/doc/testLib1file1.txt" + "${prefix}/doc/testLib1file2.txt" + ) + if(EXISTS "${f}") + message(STATUS "'${f}' exists!") + else() + message(FATAL_ERROR "Missing file:\n ${f}") + endif() +endforeach() diff --git a/Tests/Module/FindDependency/CMakeLists.txt b/Tests/Module/FindDependency/CMakeLists.txt new file mode 100644 index 0000000..b13f48a --- /dev/null +++ b/Tests/Module/FindDependency/CMakeLists.txt @@ -0,0 +1,10 @@ + +cmake_minimum_required(VERSION 3.0) +project(FindDependency) + +set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/packages") + +find_package(Pack1 REQUIRED) + +add_executable(FindDependency main.cpp) +target_link_libraries(FindDependency Pack1::Lib) diff --git a/Tests/Module/FindDependency/main.cpp b/Tests/Module/FindDependency/main.cpp new file mode 100644 index 0000000..d635b31 --- /dev/null +++ b/Tests/Module/FindDependency/main.cpp @@ -0,0 +1,17 @@ + +#ifndef HAVE_PACK1 +#error Expected HAVE_PACK1 +#endif + +#ifndef HAVE_PACK2 +#error Expected HAVE_PACK2 +#endif + +#ifndef HAVE_PACK3 +#error Expected HAVE_PACK3 +#endif + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/Tests/Module/FindDependency/packages/Pack1/Pack1Config.cmake b/Tests/Module/FindDependency/packages/Pack1/Pack1Config.cmake new file mode 100644 index 0000000..ff533c2 --- /dev/null +++ b/Tests/Module/FindDependency/packages/Pack1/Pack1Config.cmake @@ -0,0 +1,9 @@ + +include(CMakeFindDependencyMacro) + +find_dependency(Pack2 2.3) +find_dependency(Pack3) + +add_library(Pack1::Lib INTERFACE IMPORTED) +set_property(TARGET Pack1::Lib PROPERTY INTERFACE_COMPILE_DEFINITIONS HAVE_PACK1) +set_property(TARGET Pack1::Lib PROPERTY INTERFACE_LINK_LIBRARIES Pack2::Lib Pack3::Lib) diff --git a/Tests/Module/FindDependency/packages/Pack1/Pack1ConfigVersion.cmake b/Tests/Module/FindDependency/packages/Pack1/Pack1ConfigVersion.cmake new file mode 100644 index 0000000..dfb7b6c --- /dev/null +++ b/Tests/Module/FindDependency/packages/Pack1/Pack1ConfigVersion.cmake @@ -0,0 +1,11 @@ + +set(PACKAGE_VERSION "1.3") + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/Tests/Module/FindDependency/packages/Pack2/Pack2Config.cmake b/Tests/Module/FindDependency/packages/Pack2/Pack2Config.cmake new file mode 100644 index 0000000..672288e --- /dev/null +++ b/Tests/Module/FindDependency/packages/Pack2/Pack2Config.cmake @@ -0,0 +1,5 @@ + +set(PACK2_VAR ON) + +add_library(Pack2::Lib INTERFACE IMPORTED) +set_property(TARGET Pack2::Lib PROPERTY INTERFACE_COMPILE_DEFINITIONS HAVE_PACK2) diff --git a/Tests/Module/FindDependency/packages/Pack2/Pack2ConfigVersion.cmake b/Tests/Module/FindDependency/packages/Pack2/Pack2ConfigVersion.cmake new file mode 100644 index 0000000..42f58c0 --- /dev/null +++ b/Tests/Module/FindDependency/packages/Pack2/Pack2ConfigVersion.cmake @@ -0,0 +1,11 @@ + +set(PACKAGE_VERSION "2.4") + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/Tests/Module/FindDependency/packages/Pack3/Pack3Config.cmake b/Tests/Module/FindDependency/packages/Pack3/Pack3Config.cmake new file mode 100644 index 0000000..25c32f3 --- /dev/null +++ b/Tests/Module/FindDependency/packages/Pack3/Pack3Config.cmake @@ -0,0 +1,5 @@ + +set(PACK3_VAR ON) + +add_library(Pack3::Lib INTERFACE IMPORTED) +set_property(TARGET Pack3::Lib PROPERTY INTERFACE_COMPILE_DEFINITIONS HAVE_PACK3) diff --git a/Tests/Module/FindDependency/packages/Pack3/Pack3ConfigVersion.cmake b/Tests/Module/FindDependency/packages/Pack3/Pack3ConfigVersion.cmake new file mode 100644 index 0000000..870f747 --- /dev/null +++ b/Tests/Module/FindDependency/packages/Pack3/Pack3ConfigVersion.cmake @@ -0,0 +1,11 @@ + +set(PACKAGE_VERSION "1.4") + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt index 28e46b1..90af600 100644 --- a/Tests/PDBDirectoryAndName/CMakeLists.txt +++ b/Tests/PDBDirectoryAndName/CMakeLists.txt @@ -6,6 +6,13 @@ if(NOT MSVC AND NOT "${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$") message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC or Intel") endif() +# Intel 11.1 does not support /Fd but Intel 14.0 does. +# TODO: Did a version in between these add it? +if(CMAKE_C_COMPILER_ID STREQUAL Intel AND + CMAKE_C_COMPILER_VERSION VERSION_LESS 14.0) + set(NO_COMPILE_PDB 1) +endif() + set(my_targets "") add_library(mylibA SHARED mylibA.c) @@ -17,12 +24,12 @@ list(APPEND my_targets mylibA) add_library(mylibB STATIC mylibB.c) set_target_properties(mylibB PROPERTIES - PDB_NAME "mylibB_Special" - PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB" + COMPILE_PDB_NAME "mylibB_Special" + COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB" ) -# TODO: The only .pdb available for a static library is that generated -# by the compiler /Fd option which is not the same as the linker /pdb. -# list(APPEND my_targets mylibB) +if(NOT NO_COMPILE_PDB) + list(APPEND my_targets mylibB) +endif() add_library(mylibC SHARED mylibC.c) set_target_properties(mylibC PROPERTIES @@ -32,10 +39,11 @@ list(APPEND my_targets mylibC) add_library(mylibD STATIC mylibD.c) set_target_properties(mylibD PROPERTIES - PDB_NAME "mylibD_Special" + COMPILE_PDB_NAME "mylibD_Special" ) -# TODO: See comment for mylibB. -# list(APPEND my_targets mylibD) +if(NOT NO_COMPILE_PDB) + list(APPEND my_targets mylibD) +endif() add_executable(myexe myexe.c) set_target_properties(myexe PROPERTIES @@ -66,6 +74,12 @@ set(pdbs "") foreach(t ${my_targets}) get_property(pdb_name TARGET ${t} PROPERTY PDB_NAME) get_property(pdb_dir TARGET ${t} PROPERTY PDB_OUTPUT_DIRECTORY) + if(NOT pdb_name) + get_property(pdb_name TARGET ${t} PROPERTY COMPILE_PDB_NAME) + endif() + if(NOT pdb_dir) + get_property(pdb_dir TARGET ${t} PROPERTY COMPILE_PDB_OUTPUT_DIRECTORY) + endif() if(NOT pdb_dir) set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}) endif() diff --git a/Tests/RunCMake/CompatibleInterface/DebugProperties-stderr.txt b/Tests/RunCMake/CompatibleInterface/DebugProperties-stderr.txt index 17b8a5c..82a34d5 100644 --- a/Tests/RunCMake/CompatibleInterface/DebugProperties-stderr.txt +++ b/Tests/RunCMake/CompatibleInterface/DebugProperties-stderr.txt @@ -1,4 +1,11 @@ CMake Debug Log: + Boolean compatibility of property "BOOL_PROP7" for target + "CompatibleInterface" \(result: "FALSE"\): + + \* Target "CompatibleInterface" property is implied by use. + \* Target "iface1" property value "FALSE" \(Agree\) ++ +CMake Debug Log: Boolean compatibility of property "BOOL_PROP1" for target "CompatibleInterface" \(result: "TRUE"\): @@ -40,13 +47,6 @@ CMake Debug Log: \* Target "iface2" property value "FALSE" \(Agree\) + CMake Debug Log: - Boolean compatibility of property "BOOL_PROP7" for target - "CompatibleInterface" \(result: "FALSE"\): - - \* Target "CompatibleInterface" property is implied by use. - \* Target "iface1" property value "FALSE" \(Agree\) -+ -CMake Debug Log: String compatibility of property "STRING_PROP1" for target "CompatibleInterface" \(result: "prop1"\): diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index 1d1c523..ed3afc5 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -53,6 +53,7 @@ function(run_cmake test) -G "${RunCMake_GENERATOR}" -T "${RunCMake_GENERATOR_TOOLSET}" -DRunCMake_TEST=${test} + --no-warn-unused-cli ${RunCMake_TEST_OPTIONS} WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}" OUTPUT_VARIABLE actual_stdout diff --git a/Tests/RunCMake/Syntax/AtWithVariable-stderr.txt b/Tests/RunCMake/Syntax/AtWithVariable-stderr.txt new file mode 100644 index 0000000..5dcd4d7 --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariable-stderr.txt @@ -0,0 +1 @@ +-->wrong<-- diff --git a/Tests/RunCMake/Syntax/AtWithVariable.cmake b/Tests/RunCMake/Syntax/AtWithVariable.cmake new file mode 100644 index 0000000..2bbf61d --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariable.cmake @@ -0,0 +1,9 @@ +set(right "wrong") +set(var "\${right}") +# Expanded here. +set(ref "@var@") + +# 'right' is dereferenced because 'var' was dereferenced when +# assigning to 'ref' above. +string(CONFIGURE "${ref}" output) +message("-->${output}<--") diff --git a/Tests/RunCMake/Syntax/AtWithVariableAtOnly-stderr.txt b/Tests/RunCMake/Syntax/AtWithVariableAtOnly-stderr.txt new file mode 100644 index 0000000..cbd1be4 --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableAtOnly-stderr.txt @@ -0,0 +1 @@ +-->\${right}<-- diff --git a/Tests/RunCMake/Syntax/AtWithVariableAtOnly.cmake b/Tests/RunCMake/Syntax/AtWithVariableAtOnly.cmake new file mode 100644 index 0000000..e06484c --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableAtOnly.cmake @@ -0,0 +1,8 @@ +set(right "wrong") +set(var "\${right}") +# Expanded here. +set(ref "@var@") + +# No dereference done at all. +string(CONFIGURE "${ref}" output @ONLY) +message("-->${output}<--") diff --git a/Tests/RunCMake/Syntax/AtWithVariableAtOnlyFile-stderr.txt b/Tests/RunCMake/Syntax/AtWithVariableAtOnlyFile-stderr.txt new file mode 100644 index 0000000..90bffb6 --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableAtOnlyFile-stderr.txt @@ -0,0 +1,5 @@ +-->==>\${right}<== +==><== +==>\${var}<== +==>\${empty}<== +<-- diff --git a/Tests/RunCMake/Syntax/AtWithVariableAtOnlyFile.cmake b/Tests/RunCMake/Syntax/AtWithVariableAtOnlyFile.cmake new file mode 100644 index 0000000..bdd7bcd --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableAtOnlyFile.cmake @@ -0,0 +1,9 @@ +set(right "wrong") +set(var "\${right}") + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/atfile.txt.in" + "${CMAKE_CURRENT_BINARY_DIR}/atfile.txt" + @ONLY) +file(READ "${CMAKE_CURRENT_BINARY_DIR}/atfile.txt" output) +message("-->${output}<--") diff --git a/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansion-stderr.txt b/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansion-stderr.txt new file mode 100644 index 0000000..cbd1be4 --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansion-stderr.txt @@ -0,0 +1 @@ +-->\${right}<-- diff --git a/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansion.cmake b/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansion.cmake new file mode 100644 index 0000000..840c7f0 --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansion.cmake @@ -0,0 +1,8 @@ +# Literal since 'var' is not defined. +set(ref "@var@") +set(right "wrong") +set(var "\${right}") + +# 'var' is dereferenced here. +string(CONFIGURE "${ref}" output) +message("-->${output}<--") diff --git a/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansionAtOnly-stderr.txt b/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansionAtOnly-stderr.txt new file mode 100644 index 0000000..cbd1be4 --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansionAtOnly-stderr.txt @@ -0,0 +1 @@ +-->\${right}<-- diff --git a/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansionAtOnly.cmake b/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansionAtOnly.cmake new file mode 100644 index 0000000..b657506 --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableEmptyExpansionAtOnly.cmake @@ -0,0 +1,8 @@ +# Literal since 'var' is not defined. +set(ref "@var@") +set(right "wrong") +set(var "\${right}") + +# 'var' is dereferenced, but now 'right' +string(CONFIGURE "${ref}" output @ONLY) +message("-->${output}<--") diff --git a/Tests/RunCMake/Syntax/AtWithVariableFile-stderr.txt b/Tests/RunCMake/Syntax/AtWithVariableFile-stderr.txt new file mode 100644 index 0000000..43f029f --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableFile-stderr.txt @@ -0,0 +1,5 @@ +-->==>\${right}<== +==><== +==>\${right}<== +==><== +<-- diff --git a/Tests/RunCMake/Syntax/AtWithVariableFile.cmake b/Tests/RunCMake/Syntax/AtWithVariableFile.cmake new file mode 100644 index 0000000..c709099 --- /dev/null +++ b/Tests/RunCMake/Syntax/AtWithVariableFile.cmake @@ -0,0 +1,8 @@ +set(right "wrong") +set(var "\${right}") + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/atfile.txt.in" + "${CMAKE_CURRENT_BINARY_DIR}/atfile.txt") +file(READ "${CMAKE_CURRENT_BINARY_DIR}/atfile.txt" output) +message("-->${output}<--") diff --git a/Tests/RunCMake/Syntax/EscapeQuotes-stderr.txt b/Tests/RunCMake/Syntax/EscapeQuotes-stderr.txt new file mode 100644 index 0000000..077272d --- /dev/null +++ b/Tests/RunCMake/Syntax/EscapeQuotes-stderr.txt @@ -0,0 +1 @@ +-->"<-- diff --git a/Tests/RunCMake/Syntax/EscapeQuotes.cmake b/Tests/RunCMake/Syntax/EscapeQuotes.cmake new file mode 100644 index 0000000..46d2b6f --- /dev/null +++ b/Tests/RunCMake/Syntax/EscapeQuotes.cmake @@ -0,0 +1,9 @@ +set(var "\"") +set(ref "@var@") +set(rref "\${var}") + +string(CONFIGURE "${ref}" output ESCAPE_QUOTES) +message("-->${output}<--") + +string(CONFIGURE "${rref}" output ESCAPE_QUOTES) +message("-->${output}<--") diff --git a/Tests/RunCMake/Syntax/EscapedAt-stderr.txt b/Tests/RunCMake/Syntax/EscapedAt-stderr.txt new file mode 100644 index 0000000..a51c0d3 --- /dev/null +++ b/Tests/RunCMake/Syntax/EscapedAt-stderr.txt @@ -0,0 +1 @@ +-->\\n<-- diff --git a/Tests/RunCMake/Syntax/EscapedAt.cmake b/Tests/RunCMake/Syntax/EscapedAt.cmake new file mode 100644 index 0000000..1ced620 --- /dev/null +++ b/Tests/RunCMake/Syntax/EscapedAt.cmake @@ -0,0 +1,5 @@ +set(var "n") +set(ref "\\@var@") + +string(CONFIGURE "${ref}" output) +message("-->${output}<--") diff --git a/Tests/RunCMake/Syntax/ExpandInAt-stderr.txt b/Tests/RunCMake/Syntax/ExpandInAt-stderr.txt new file mode 100644 index 0000000..5da8b60 --- /dev/null +++ b/Tests/RunCMake/Syntax/ExpandInAt-stderr.txt @@ -0,0 +1 @@ +-->@foo@<-- diff --git a/Tests/RunCMake/Syntax/ExpandInAt.cmake b/Tests/RunCMake/Syntax/ExpandInAt.cmake new file mode 100644 index 0000000..98f0277 --- /dev/null +++ b/Tests/RunCMake/Syntax/ExpandInAt.cmake @@ -0,0 +1,6 @@ +set("\${varname}" bar) +set(var foo) +set(ref "@\${var}@") + +string(CONFIGURE "${ref}" output) +message("-->${output}<--") diff --git a/Tests/RunCMake/Syntax/ParenInENV-result.txt b/Tests/RunCMake/Syntax/ParenInENV-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/ParenInENV-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/ParenInENV-stderr.txt b/Tests/RunCMake/Syntax/ParenInENV-stderr.txt new file mode 100644 index 0000000..7ecfe11 --- /dev/null +++ b/Tests/RunCMake/Syntax/ParenInENV-stderr.txt @@ -0,0 +1,20 @@ +CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): + Syntax Warning in cmake code at + + .*/Tests/RunCMake/Syntax/ParenInENV.cmake:2:21 + + Argument not separated from preceding token by whitespace. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error at ParenInENV.cmake:2 \(message\): + Syntax error in cmake code at + + .*/Tests/RunCMake/Syntax/ParenInENV.cmake:2 + + when parsing string + + -->\$ENV{e + + syntax error, unexpected \$end, expecting } \(9\) +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Syntax/ParenInENV.cmake b/Tests/RunCMake/Syntax/ParenInENV.cmake new file mode 100644 index 0000000..148f726 --- /dev/null +++ b/Tests/RunCMake/Syntax/ParenInENV.cmake @@ -0,0 +1,2 @@ +set("ENV{e(x)}" value) +message(-->$ENV{e(x)}<--) diff --git a/Tests/RunCMake/Syntax/ParenInQuotedENV-stderr.txt b/Tests/RunCMake/Syntax/ParenInQuotedENV-stderr.txt new file mode 100644 index 0000000..7020c7e --- /dev/null +++ b/Tests/RunCMake/Syntax/ParenInQuotedENV-stderr.txt @@ -0,0 +1 @@ +-->value<-- diff --git a/Tests/RunCMake/Syntax/ParenInQuotedENV.cmake b/Tests/RunCMake/Syntax/ParenInQuotedENV.cmake new file mode 100644 index 0000000..6333717 --- /dev/null +++ b/Tests/RunCMake/Syntax/ParenInQuotedENV.cmake @@ -0,0 +1,2 @@ +set("ENV{e(x)}" value) +message("-->$ENV{e(x)}<--") diff --git a/Tests/RunCMake/Syntax/RunCMakeTest.cmake b/Tests/RunCMake/Syntax/RunCMakeTest.cmake index 5f05cfc..dcabd8a 100644 --- a/Tests/RunCMake/Syntax/RunCMakeTest.cmake +++ b/Tests/RunCMake/Syntax/RunCMakeTest.cmake @@ -52,3 +52,16 @@ run_cmake(UnterminatedString) run_cmake(UnterminatedBracket0) run_cmake(UnterminatedBracket1) run_cmake(UnterminatedBracketComment) + +# Variable expansion tests +run_cmake(ExpandInAt) +run_cmake(EscapedAt) +run_cmake(EscapeQuotes) +run_cmake(AtWithVariable) +run_cmake(AtWithVariableEmptyExpansion) +run_cmake(AtWithVariableAtOnly) +run_cmake(AtWithVariableEmptyExpansionAtOnly) +run_cmake(AtWithVariableFile) +run_cmake(AtWithVariableAtOnlyFile) +run_cmake(ParenInENV) +run_cmake(ParenInQuotedENV) diff --git a/Tests/RunCMake/Syntax/atfile.txt.in b/Tests/RunCMake/Syntax/atfile.txt.in new file mode 100644 index 0000000..3775919 --- /dev/null +++ b/Tests/RunCMake/Syntax/atfile.txt.in @@ -0,0 +1,4 @@ +==>@var@<== +==>@empty@<== +==>${var}<== +==>${empty}<== diff --git a/Utilities/Release/create-cmake-release.cmake b/Utilities/Release/create-cmake-release.cmake index 95428b6..841aba5 100644 --- a/Utilities/Release/create-cmake-release.cmake +++ b/Utilities/Release/create-cmake-release.cmake @@ -10,7 +10,7 @@ set(RELEASE_SCRIPTS_BATCH_1 dashmacmini2_release.cmake # Mac Darwin universal ppc;i386 dashmacmini5_release.cmake # Mac Darwin64 universal x86_64;i386 magrathea_release.cmake # Linux - v20n250_aix_release.cmake # AIX 5.3 + ibm_aix_release.cmake # AIX ferrari_sgi64_release.cmake # IRIX 64 ferrari_sgi_release.cmake # IRIX ) diff --git a/Utilities/Release/v20n250_aix_release.cmake b/Utilities/Release/ibm_aix_release.cmake index cc8cd05..5a6efe6 100644 --- a/Utilities/Release/v20n250_aix_release.cmake +++ b/Utilities/Release/ibm_aix_release.cmake @@ -1,8 +1,7 @@ set(CMAKE_RELEASE_DIRECTORY "/bench1/noibm34/CMakeReleaseDirectory") -set(FINAL_PATH /u/noibm34/cmake-release) -set(PROCESSORS 2) -set(HOST "sshserv.centers.ihost.com") -set(EXTRA_HOP "rsh p90n03") +set(PROCESSORS 64) +set(HOST "ibm-backend") +set(SCRIPT_NAME aix) set(MAKE_PROGRAM "make") set(CC "xlc_r") set(CXX "xlC_r") @@ -12,11 +11,5 @@ set(INITIAL_CACHE " CMAKE_BUILD_TYPE:STRING=Release CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE ") -set(EXTRA_COPY " -rm -rf ~/cmake-release -mkdir ~/cmake-release -mv *.sh ~/cmake-release -mv *.Z ~/cmake-release -mv *.gz ~/cmake-release") get_filename_component(path "${CMAKE_CURRENT_LIST_FILE}" PATH) include(${path}/release_cmake.cmake) diff --git a/Utilities/Release/release_cmake.cmake b/Utilities/Release/release_cmake.cmake index 630f54f..7a1652d 100644 --- a/Utilities/Release/release_cmake.cmake +++ b/Utilities/Release/release_cmake.cmake @@ -4,9 +4,6 @@ get_filename_component(SCRIPT_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH) if(NOT DEFINED CPACK_BINARY_GENERATORS) set(CPACK_BINARY_GENERATORS "STGZ TGZ TZ") endif() -if(DEFINED EXTRA_COPY) - set(HAS_EXTRA_COPY 1) -endif() if(NOT DEFINED CMAKE_RELEASE_DIRECTORY) set(CMAKE_RELEASE_DIRECTORY "~/CMakeReleaseDirectory") endif() @@ -55,11 +52,11 @@ message("Creating CMake release ${CMAKE_CREATE_VERSION} on ${HOST} with parallel macro(remote_command comment command) message("${comment}") if(${ARGC} GREATER 2) - message("ssh ${HOST} ${EXTRA_HOP} ${command}") - execute_process(COMMAND ssh ${HOST} ${EXTRA_HOP} ${command} RESULT_VARIABLE result INPUT_FILE ${ARGV2}) + message("ssh ${HOST} ${command}") + execute_process(COMMAND ssh ${HOST} ${command} RESULT_VARIABLE result INPUT_FILE ${ARGV2}) else() - message("ssh ${HOST} ${EXTRA_HOP} ${command}") - execute_process(COMMAND ssh ${HOST} ${EXTRA_HOP} ${command} RESULT_VARIABLE result) + message("ssh ${HOST} ${command}") + execute_process(COMMAND ssh ${HOST} ${command} RESULT_VARIABLE result) endif() if(${result} GREATER 0) message(FATAL_ERROR "Error running command: ${command}, return value = ${result}") @@ -67,14 +64,15 @@ macro(remote_command comment command) endmacro() if(CMAKE_DOC_TARBALL) - message("scp '${CMAKE_DOC_TARBALL}' '${HOST}:'") + get_filename_component(CMAKE_DOC_TARBALL_NAME "${CMAKE_DOC_TARBALL}" NAME) + string(REPLACE ".tar.gz" "-${SCRIPT_NAME}.tar.gz" CMAKE_DOC_TARBALL_STAGED "${CMAKE_DOC_TARBALL_NAME}") + message("scp '${CMAKE_DOC_TARBALL}' '${HOST}:${CMAKE_DOC_TARBALL_STAGED}'") execute_process(COMMAND - scp ${CMAKE_DOC_TARBALL} ${HOST}: + scp ${CMAKE_DOC_TARBALL} ${HOST}:${CMAKE_DOC_TARBALL_STAGED} RESULT_VARIABLE result) if(${result} GREATER 0) - message("error sending doc tarball with scp '${CMAKE_DOC_TARBALL}' '${HOST}:'") + message("error sending doc tarball with scp '${CMAKE_DOC_TARBALL}' '${HOST}:${CMAKE_DOC_TARBALL_STAGED}'") endif() - get_filename_component(CMAKE_DOC_TARBALL_NAME "${CMAKE_DOC_TARBALL}" NAME) endif() # set this so configure file will work from script mode diff --git a/Utilities/Release/release_cmake.sh.in b/Utilities/Release/release_cmake.sh.in index f41bda8..76fdb3a 100755 --- a/Utilities/Release/release_cmake.sh.in +++ b/Utilities/Release/release_cmake.sh.in @@ -18,7 +18,7 @@ check_exit_value() CMAKE_DOC_TARBALL="" if [ ! -z "@CMAKE_DOC_TARBALL_NAME@" ] ; then CMAKE_DOC_TARBALL=@CMAKE_RELEASE_DIRECTORY@/@CMAKE_DOC_TARBALL_NAME@ - mv "$HOME/@CMAKE_DOC_TARBALL_NAME@" "$CMAKE_DOC_TARBALL" + mv "$HOME/@CMAKE_DOC_TARBALL_STAGED@" "$CMAKE_DOC_TARBALL" check_exit_value $? "mv doc tarball" || exit 1 fi @@ -155,11 +155,6 @@ done -# need to add an extra copy thing here -if [ ! -z "@EXTRA_COPY@" ]; then - @EXTRA_COPY@ - check_exit_value $? "Extra copy step @EXTRA_COPY@" || exit 1 -fi echo "End release" date echo "" diff --git a/Utilities/Release/upload_release.cmake b/Utilities/Release/upload_release.cmake index 9bf3523..613d73d 100644 --- a/Utilities/Release/upload_release.cmake +++ b/Utilities/Release/upload_release.cmake @@ -1,9 +1,9 @@ set(CTEST_RUN_CURRENT_SCRIPT 0) -if(NOT DEFINED PROJECT_PREFIX) - set(PROJECT_PREFIX cmake-) -endif() if(NOT VERSION) - set(VERSION 2.8) + set(VERSION 3.0) +endif() +if(NOT DEFINED PROJECT_PREFIX) + set(PROJECT_PREFIX cmake-${VERSION}) endif() set(dir "v${VERSION}") if("${VERSION}" MATCHES "master") @@ -53,10 +53,6 @@ cmake_version_major="`cmake_version_component MAJOR`" cmake_version_minor="`cmake_version_component MINOR`" cmake_version_patch="`cmake_version_component PATCH`" cmake_version="${cmake_version_major}.${cmake_version_minor}.${cmake_version_patch}" -cmake_version_tweak="`cmake_version_component TWEAK`" -if [ "$cmake_version_tweak" != "0" ]; then - cmake_version="${cmake_version}.${cmake_version_tweak}" -fi cmake_version_rc="`cmake_version_component RC`" if [ "$cmake_version_rc" != "" ]; then cmake_version="${cmake_version}-rc${cmake_version_rc}" @@ -1464,7 +1460,6 @@ fi cmake_report cmVersionConfig.h${_tmp} "#define CMake_VERSION_MAJOR ${cmake_version_major}" cmake_report cmVersionConfig.h${_tmp} "#define CMake_VERSION_MINOR ${cmake_version_minor}" cmake_report cmVersionConfig.h${_tmp} "#define CMake_VERSION_PATCH ${cmake_version_patch}" -cmake_report cmVersionConfig.h${_tmp} "#define CMake_VERSION_TWEAK ${cmake_version_tweak}" cmake_report cmVersionConfig.h${_tmp} "#define CMake_VERSION \"${cmake_version}\"" cmake_report cmConfigure.h${_tmp} "#define CMAKE_ROOT_DIR \"${cmake_root_dir}\"" cmake_report cmConfigure.h${_tmp} "#define CMAKE_DATA_DIR \"/bootstrap-not-insalled\"" |