Browse Source

Merge branch 'xcode-duplicate-flags-13354' into generator-toolset

Brad King 12 years ago
parent
commit
118c32f8f2
100 changed files with 3270 additions and 1260 deletions
  1. 2 4
      CMakeLists.txt
  2. 1 0
      Modules/CMakeCCompiler.cmake.in
  3. 1 0
      Modules/CMakeCXXCompiler.cmake.in
  4. 12 13
      Modules/CMakeDetermineCompilerABI.cmake
  5. 1 0
      Modules/CMakeFortranCompiler.cmake.in
  6. 1 5
      Modules/CMakeFortranCompilerId.F.in
  7. 5 0
      Modules/CMakePackageConfigHelpers.cmake
  8. 43 8
      Modules/CMakeParseImplicitLinkInfo.cmake
  9. 1 4
      Modules/CMakePlatformId.h.in
  10. 26 0
      Modules/CPackWIX.cmake
  11. 1 1
      Modules/CheckForPthreads.c
  12. 21 7
      Modules/FindGLUT.cmake
  13. 1 1
      Modules/FindLua51.cmake
  14. 21 9
      Modules/FindOpenGL.cmake
  15. 14 0
      Modules/FindQt.cmake
  16. 4 2
      Modules/FindQt3.cmake
  17. 92 11
      Modules/FindQt4.cmake
  18. 2 1
      Modules/FindSDL_image.cmake
  19. 2 1
      Modules/FindSDL_mixer.cmake
  20. 2 1
      Modules/FindSDL_net.cmake
  21. 2 1
      Modules/FindSDL_sound.cmake
  22. 2 1
      Modules/FindSDL_ttf.cmake
  23. 1 0
      Modules/Platform/Darwin-Clang.cmake
  24. 1 0
      Modules/Platform/Darwin-GNU.cmake
  25. 18 0
      Modules/Platform/Darwin.cmake
  26. 13 0
      Modules/WIX.template.in
  27. 1 1
      Source/CMakeVersion.cmake
  28. 3 0
      Source/CPack/WiX/cmCPackWIXGenerator.cxx
  29. 2 2
      Source/CPack/cmCPackGeneratorFactory.cxx
  30. 11 4
      Source/CTest/cmCTestCoverageHandler.cxx
  31. 6 1
      Source/CTest/cmCTestMultiProcessHandler.cxx
  32. 4 0
      Source/cmAddLibraryCommand.h
  33. 1 0
      Source/cmBootstrapCommands.cxx
  34. 1 1
      Source/cmCTest.cxx
  35. 2 2
      Source/cmCommandArgumentParser.cxx
  36. 5 0
      Source/cmCommands.cxx
  37. 6 5
      Source/cmComputeLinkDepends.cxx
  38. 2 1
      Source/cmComputeLinkDepends.h
  39. 32 8
      Source/cmComputeLinkInformation.cxx
  40. 3 1
      Source/cmComputeLinkInformation.h
  41. 92 6
      Source/cmComputeTargetDepends.cxx
  42. 5 1
      Source/cmComputeTargetDepends.h
  43. 2 2
      Source/cmCustomCommandGenerator.cxx
  44. 11 0
      Source/cmDocumentGeneratorExpressions.h
  45. 37 0
      Source/cmDocumentVariables.cxx
  46. 40 15
      Source/cmExportBuildFileGenerator.cxx
  47. 2 1
      Source/cmExportBuildFileGenerator.h
  48. 318 47
      Source/cmExportFileGenerator.cxx
  49. 43 2
      Source/cmExportFileGenerator.h
  50. 47 19
      Source/cmExportInstallFileGenerator.cxx
  51. 4 2
      Source/cmExportInstallFileGenerator.h
  52. 5 0
      Source/cmExtraCodeBlocksGenerator.cxx
  53. 57 0
      Source/cmFileCommand.cxx
  54. 9 0
      Source/cmFileCommand.h
  55. 219 38
      Source/cmGeneratorExpression.cxx
  56. 36 11
      Source/cmGeneratorExpression.h
  57. 10 8
      Source/cmGeneratorExpressionDAGChecker.cxx
  58. 9 3
      Source/cmGeneratorExpressionDAGChecker.h
  59. 151 9
      Source/cmGeneratorExpressionEvaluator.cxx
  60. 4 1
      Source/cmGeneratorExpressionEvaluator.h
  61. 2 40
      Source/cmGeneratorTarget.cxx
  62. 5 0
      Source/cmGlobalGenerator.cxx
  63. 26 33
      Source/cmGlobalXCodeGenerator.cxx
  64. 0 4
      Source/cmLoadCommandCommand.cxx
  65. 1 14
      Source/cmLoadCommandCommand.h
  66. 31 15
      Source/cmLocalGenerator.cxx
  67. 3 2
      Source/cmLocalGenerator.h
  68. 109 56
      Source/cmMakefile.cxx
  69. 11 1
      Source/cmMakefile.h
  70. 28 0
      Source/cmMakefileIncludeDirectoriesEntry.h
  71. 17 12
      Source/cmMakefileTargetGenerator.cxx
  72. 2 1
      Source/cmNinjaTargetGenerator.cxx
  73. 17 0
      Source/cmPolicies.cxx
  74. 1 0
      Source/cmPolicies.h
  75. 3 59
      Source/cmQtAutomoc.cxx
  76. 54 0
      Source/cmStringCommand.cxx
  77. 29 1
      Source/cmStringCommand.h
  78. 585 81
      Source/cmTarget.cxx
  79. 56 18
      Source/cmTarget.h
  80. 57 0
      Source/cmTargetCompileDefinitionsCommand.cxx
  81. 94 0
      Source/cmTargetCompileDefinitionsCommand.h
  82. 74 0
      Source/cmTargetIncludeDirectoriesCommand.cxx
  83. 98 0
      Source/cmTargetIncludeDirectoriesCommand.h
  84. 14 0
      Source/cmTargetLinkLibrariesCommand.cxx
  85. 7 0
      Source/cmTargetLinkLibrariesCommand.h
  86. 144 0
      Source/cmTargetPropCommandBase.cxx
  87. 58 0
      Source/cmTargetPropCommandBase.h
  88. 2 2
      Source/cmTestGenerator.cxx
  89. 134 0
      Source/cmTimestamp.cxx
  90. 40 0
      Source/cmTimestamp.h
  91. 20 5
      Source/cmVisualStudio10TargetGenerator.cxx
  92. 14 1
      Source/cmake.cxx
  93. 2 0
      Source/cmake.h
  94. 33 48
      Source/kwsys/CMakeLists.txt
  95. 8 0
      Source/kwsys/CPU.h.in
  96. 0 114
      Source/kwsys/EncodeExecutable.c
  97. 1 5
      Source/kwsys/IOStream.hxx.in
  98. 0 211
      Source/kwsys/ProcessFwd9x.c
  99. 3 6
      Source/kwsys/ProcessUNIX.c
  100. 17 270
      Source/kwsys/ProcessWin32.c

+ 2 - 4
CMakeLists.txt

@@ -234,8 +234,6 @@ macro (CMAKE_BUILD_UTILITIES)
   set(kwsys_folder "Utilities/KWSys")
   CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE} "${kwsys_folder}")
   CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}_c "${kwsys_folder}")
-  CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}EncodeExecutable "${kwsys_folder}")
-  CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}ProcessFwd9x "${kwsys_folder}")
   if(BUILD_TESTING)
     CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestDynload "${kwsys_folder}")
     CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestProcess "${kwsys_folder}")
@@ -590,10 +588,10 @@ if(NOT CMake_VERSION_IS_RELEASE)
       NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 4.2)
     set(C_FLAGS_LIST -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts
                      -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security
-                     -Wmissing-format-attribute -fno-common
+                     -Wmissing-format-attribute -fno-common -Wundef
     )
     set(CXX_FLAGS_LIST -Wnon-virtual-dtor -Wcast-align -Wchar-subscripts -Wall -W
-                       -Wshadow -Wpointer-arith -Wformat-security
+                       -Wshadow -Wpointer-arith -Wformat-security -Wundef
     )
 
     foreach(FLAG_LANG  C CXX)

+ 1 - 0
Modules/CMakeCCompiler.cmake.in

@@ -50,6 +50,7 @@ endif()
 
 set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "@CMAKE_C_IMPLICIT_LINK_LIBRARIES@")
 set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_DIRECTORIES@")
+set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")
 
 @SET_CMAKE_CMCLDEPS_EXECUTABLE@
 @SET_CMAKE_CL_SHOWINCLUDE_PREFIX@

+ 1 - 0
Modules/CMakeCXXCompiler.cmake.in

@@ -51,6 +51,7 @@ endif()
 
 set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_CXX_IMPLICIT_LINK_LIBRARIES@")
 set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@")
+set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")
 
 @SET_CMAKE_CMCLDEPS_EXECUTABLE@
 @SET_CMAKE_CL_SHOWINCLUDE_PREFIX@

+ 12 - 13
Modules/CMakeDetermineCompilerABI.cmake

@@ -72,19 +72,9 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
       # Parse implicit linker information for this language, if available.
       set(implicit_dirs "")
       set(implicit_libs "")
-      set(MULTI_ARCH FALSE)
-      if(DEFINED CMAKE_OSX_ARCHITECTURES)
-        if( "${CMAKE_OSX_ARCHITECTURES}" MATCHES ";" )
-          set(MULTI_ARCH TRUE)
-        endif()
-      endif()
-      if(CMAKE_${lang}_VERBOSE_FLAG
-          # Implicit link information cannot be used explicitly for
-          # multiple OS X architectures, so we skip it.
-          AND NOT MULTI_ARCH
-          # Skip this with Xcode for now.
-          AND NOT "${CMAKE_GENERATOR}" MATCHES Xcode)
-        CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs log
+      set(implicit_fwks "")
+      if(CMAKE_${lang}_VERBOSE_FLAG)
+        CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs implicit_fwks log
           "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}")
         file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
           "Parsed ${lang} implicit link information from above output:\n${log}\n\n")
@@ -112,8 +102,17 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
         message(STATUS "${_desc}")
       endif()
 
+      # Implicit link libraries cannot be used explicitly for multiple
+      # OS X architectures, so we skip it.
+      if(DEFINED CMAKE_OSX_ARCHITECTURES)
+        if("${CMAKE_OSX_ARCHITECTURES}" MATCHES ";")
+          set(implicit_libs "")
+        endif()
+      endif()
+
       set(CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES "${implicit_libs}" PARENT_SCOPE)
       set(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" PARENT_SCOPE)
+      set(CMAKE_${lang}_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "${implicit_fwks}" PARENT_SCOPE)
 
       # Detect library architecture directory name.
       if(CMAKE_LIBRARY_ARCHITECTURE_REGEX)

+ 1 - 0
Modules/CMakeFortranCompiler.cmake.in

@@ -52,3 +52,4 @@ endif()
 
 set(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES "@CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES@")
 set(CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES@")
+set(CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")

+ 1 - 5
Modules/CMakeFortranCompilerId.F.in

@@ -74,12 +74,8 @@
         PRINT *, 'INFO:platform[IRIX]'
 #elif defined(__hpux) || defined(__hpux__)
         PRINT *, 'INFO:platform[HP-UX]'
-#elif defined(__HAIKU) || defined(__HAIKU__) || defined(_HAIKU)
+#elif defined(__HAIKU__)
         PRINT *, 'INFO:platform[Haiku]'
-#       if 0
-!       Haiku also defines __BEOS__ so we must
-!       put it prior to the check for __BEOS__
-#       endif
 #elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
         PRINT *, 'INFO:platform[BeOS]'
 #elif defined(__QNX__) || defined(__QNXNTO__)

+ 5 - 0
Modules/CMakePackageConfigHelpers.cmake

@@ -188,8 +188,13 @@ function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile)
     endif()
   endforeach()
 
+  get_filename_component(inputFileName "${_inputFile}" NAME)
+
   set(PACKAGE_INIT "
 ####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
+####### Any changes to this file will be overwritten by the next CMake run ####
+####### The input file was ${inputFileName}                            ########
+
 get_filename_component(PACKAGE_PREFIX_DIR \"\${CMAKE_CURRENT_LIST_DIR}/${PACKAGE_RELATIVE_PATH}\" ABSOLUTE)
 ")
 

+ 43 - 8
Modules/CMakeParseImplicitLinkInfo.cmake

@@ -16,9 +16,10 @@
 # This is used internally by CMake and should not be included by user
 # code.
 
-function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex)
+function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj_regex)
   set(implicit_libs_tmp "")
   set(implicit_dirs_tmp)
+  set(implicit_fwks_tmp)
   set(log "")
 
   # Parse implicit linker arguments.
@@ -36,6 +37,16 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex)
     set(cmd)
     if("${line}" MATCHES "${linker_regex}" AND
         NOT "${line}" MATCHES "${linker_exclude_regex}")
+      if(XCODE)
+        # Xcode unconditionally adds a path under the project build tree and
+        # on older versions it is not reported with proper quotes.  Remove it.
+        string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" _dir_regex "${CMAKE_BINARY_DIR}")
+        string(REGEX REPLACE " -[FL]${_dir_regex}/([^ ]| [^-])+( |$)" " " xline "${line}")
+        if(NOT "x${xline}" STREQUAL "x${line}")
+          set(log "${log}  reduced line: [${line}]\n            to: [${xline}]\n")
+          set(line "${xline}")
+        endif()
+      endif()
       if(UNIX)
         separate_arguments(args UNIX_COMMAND "${line}")
       else()
@@ -97,6 +108,18 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex)
     endif()
   endforeach()
 
+  # Look for library search paths reported by linker.
+  if("${output_lines}" MATCHES ";Library search paths:((;\t[^;]+)+)")
+    string(REPLACE ";\t" ";" implicit_dirs_match "${CMAKE_MATCH_1}")
+    set(log "${log}  Library search paths: [${implicit_dirs_match}]\n")
+    list(APPEND implicit_dirs_tmp ${implicit_dirs_match})
+  endif()
+  if("${output_lines}" MATCHES ";Framework search paths:((;\t[^;]+)+)")
+    string(REPLACE ";\t" ";" implicit_fwks_match "${CMAKE_MATCH_1}")
+    set(log "${log}  Framework search paths: [${implicit_fwks_match}]\n")
+    list(APPEND implicit_fwks_tmp ${implicit_fwks_match})
+  endif()
+
   # Cleanup list of libraries and flags.
   # We remove items that are not language-specific.
   set(implicit_libs "")
@@ -108,21 +131,33 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var log_var obj_regex)
     endif()
   endforeach()
 
-  # Cleanup list of directories.
-  set(implicit_dirs "")
-  foreach(d IN LISTS implicit_dirs_tmp)
-    get_filename_component(dir "${d}" ABSOLUTE)
-    list(APPEND implicit_dirs "${dir}")
-    set(log "${log}  collapse dir [${d}] ==> [${dir}]\n")
+  # Cleanup list of library and framework directories.
+  set(desc_dirs "library")
+  set(desc_fwks "framework")
+  foreach(t dirs fwks)
+    set(implicit_${t} "")
+    foreach(d IN LISTS implicit_${t}_tmp)
+      get_filename_component(dir "${d}" ABSOLUTE)
+      string(FIND "${dir}" "${CMAKE_FILES_DIRECTORY}/" pos)
+      if(NOT pos LESS 0)
+        set(msg ", skipping non-system directory")
+      else()
+        set(msg "")
+        list(APPEND implicit_${t} "${dir}")
+      endif()
+      set(log "${log}  collapse ${desc_${t}} dir [${d}] ==> [${dir}]${msg}\n")
+    endforeach()
+    list(REMOVE_DUPLICATES implicit_${t})
   endforeach()
-  list(REMOVE_DUPLICATES implicit_dirs)
 
   # Log results.
   set(log "${log}  implicit libs: [${implicit_libs}]\n")
   set(log "${log}  implicit dirs: [${implicit_dirs}]\n")
+  set(log "${log}  implicit fwks: [${implicit_fwks}]\n")
 
   # Return results.
   set(${lib_var} "${implicit_libs}" PARENT_SCOPE)
   set(${dir_var} "${implicit_dirs}" PARENT_SCOPE)
+  set(${fwk_var} "${implicit_fwks}" PARENT_SCOPE)
   set(${log_var} "${log}" PARENT_SCOPE)
 endfunction()

+ 1 - 4
Modules/CMakePlatformId.h.in

@@ -35,11 +35,8 @@
 #elif defined(__hpux) || defined(__hpux__)
 # define PLATFORM_ID "HP-UX"
 
-#elif defined(__HAIKU) || defined(__HAIKU__) || defined(_HAIKU)
+#elif defined(__HAIKU__)
 # define PLATFORM_ID "Haiku"
-/* Haiku also defines __BEOS__ so we must
-   put it prior to the check for __BEOS__
-*/
 
 #elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
 # define PLATFORM_ID "BeOS"

+ 26 - 0
Modules/CPackWIX.cmake

@@ -49,6 +49,32 @@
 # by the WiX Generator in case CPACK_RESOURCE_FILE_LICENSE
 # is in an unsupported format or the .txt -> .rtf
 # conversion does not work as expected.
+#
+##end
+#
+##variable
+# CPACK_WIX_PRODUCT_ICON - The Icon shown next to the program name in Add/Remove programs.
+#
+# If set, this icon is used in place of the default icon.
+#
+##end
+#
+##variable
+# CPACK_WIX_UI_BANNER - The bitmap will appear at the top of all installer pages other than the welcome and completion dialogs.
+#
+# If set, this image will replace the default banner image.
+#
+# This image must be 493 by 58 pixels.
+#
+##end
+#
+##variable
+# CPACK_WIX_UI_DIALOG - Background bitmap used on the welcome and completion dialogs.
+#
+# If this variable is set, the installer will replace the default dialog image.
+#
+# This image must be 493 by 312 pixels.
+#
 ##end
 
 #=============================================================================

+ 1 - 1
Modules/CheckForPthreads.c

@@ -16,7 +16,7 @@ int main(int ac, char*av[]){
   pthread_create(&tid[0], 0, runner, (void*)1);
   pthread_create(&tid[1], 0, runner, (void*)2);
 
-#if defined(__BEOS__) && !defined(__ZETA__)  && !defined(__HAIKU__) // (no usleep on BeOS 5.)
+#if defined(__BEOS__) && !defined(__ZETA__) // (no usleep on BeOS 5.)
   usleep(1); // for strange behavior on single-processor sun
 #endif
 

+ 21 - 7
Modules/FindGLUT.cmake

@@ -40,25 +40,39 @@ else ()
     set(GLUT_cocoa_LIBRARY "-framework Cocoa" CACHE STRING "Cocoa framework for OSX")
   else ()
 
+    if (BEOS)
+
+      set(_GLUT_INC_DIR /boot/develop/headers/os/opengl)
+      set(_GLUT_glut_LIB_DIR /boot/develop/lib/x86)
+
+    else()
+
+      find_library( GLUT_Xi_LIBRARY Xi
+        /usr/openwin/lib
+        )
+
+      find_library( GLUT_Xmu_LIBRARY Xmu
+        /usr/openwin/lib
+        )
+
+    endif ()
+
     find_path( GLUT_INCLUDE_DIR GL/glut.h
       /usr/include/GL
       /usr/openwin/share/include
       /usr/openwin/include
       /opt/graphics/OpenGL/include
       /opt/graphics/OpenGL/contrib/libglut
+      ${_GLUT_INC_DIR}
       )
 
     find_library( GLUT_glut_LIBRARY glut
       /usr/openwin/lib
+      ${_GLUT_glut_LIB_DIR}
       )
 
-    find_library( GLUT_Xi_LIBRARY Xi
-      /usr/openwin/lib
-      )
-
-    find_library( GLUT_Xmu_LIBRARY Xmu
-      /usr/openwin/lib
-      )
+    unset(_GLUT_INC_DIR)
+    unset(_GLUT_glut_LIB_DIR)
 
   endif ()
 

+ 1 - 1
Modules/FindLua51.cmake

@@ -54,7 +54,7 @@ find_library(LUA_LIBRARY
 
 if(LUA_LIBRARY)
   # include the math library for Unix
-  if(UNIX AND NOT APPLE)
+  if(UNIX AND NOT APPLE AND NOT BEOS)
     find_library(LUA_MATH_LIBRARY m)
     set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries")
   # For Windows and Mac, don't need to explicitly include the math library

+ 21 - 9
Modules/FindOpenGL.cmake

@@ -58,14 +58,22 @@ else ()
     find_path(OPENGL_INCLUDE_DIR OpenGL/gl.h DOC "Include for OpenGL on OSX")
 
   else()
-    # Handle HP-UX cases where we only want to find OpenGL in either hpux64
-    # or hpux32 depending on if we're doing a 64 bit build.
-    if(CMAKE_SIZEOF_VOID_P EQUAL 4)
-      set(HPUX_IA_OPENGL_LIB_PATH /opt/graphics/OpenGL/lib/hpux32/)
-    else()
-      set(HPUX_IA_OPENGL_LIB_PATH
-        /opt/graphics/OpenGL/lib/hpux64/
-        /opt/graphics/OpenGL/lib/pa20_64)
+    if (CMAKE_SYSTEM_NAME MATCHES "HP-UX")
+      # Handle HP-UX cases where we only want to find OpenGL in either hpux64
+      # or hpux32 depending on if we're doing a 64 bit build.
+      if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+        set(_OPENGL_LIB_PATH
+          /opt/graphics/OpenGL/lib/hpux32/)
+      else()
+        set(_OPENGL_LIB_PATH
+          /opt/graphics/OpenGL/lib/hpux64/
+          /opt/graphics/OpenGL/lib/pa20_64)
+      endif()
+    elseif(CMAKE_SYSTEM_NAME STREQUAL Haiku)
+      set(_OPENGL_LIB_PATH
+        /boot/develop/lib/x86)
+      set(_OPENGL_INCLUDE_PATH
+        /boot/develop/headers/os/opengl)
     endif()
 
     # The first line below is to make sure that the proper headers
@@ -80,6 +88,7 @@ else ()
       /usr/share/doc/NVIDIA_GLX-1.0/include
       /usr/openwin/share/include
       /opt/graphics/OpenGL/include /usr/X11R6/include
+      ${_OPENGL_INCLUDE_PATH}
     )
 
     find_path(OPENGL_xmesa_INCLUDE_DIR GL/xmesa.h
@@ -93,9 +102,12 @@ else ()
       PATHS /opt/graphics/OpenGL/lib
             /usr/openwin/lib
             /usr/shlib /usr/X11R6/lib
-            ${HPUX_IA_OPENGL_LIB_PATH}
+            ${_OPENGL_LIB_PATH}
     )
 
+    unset(_OPENGL_INCLUDE_PATH)
+    unset(_OPENGL_LIB_PATH)
+
     # On Unix OpenGL most certainly always requires X11.
     # Feel free to tighten up these conditions if you don't
     # think this is always true.

+ 14 - 0
Modules/FindQt.cmake

@@ -43,6 +43,12 @@ if(GLOB_TEMP_VAR)
 endif()
 set(GLOB_TEMP_VAR)
 
+file(GLOB GLOB_TEMP_VAR /usr/local/lib/qt3/bin/qmake)
+if(GLOB_TEMP_VAR)
+  set(QT3_INSTALLED TRUE)
+endif()
+set(GLOB_TEMP_VAR)
+
 # look for qt4 installations
 file(GLOB GLOB_TEMP_VAR /usr/local/qt-x11-commercial-4*/bin/qmake)
 if(GLOB_TEMP_VAR)
@@ -56,6 +62,12 @@ if(GLOB_TEMP_VAR)
 endif()
 set(GLOB_TEMP_VAR)
 
+file(GLOB GLOB_TEMP_VAR /usr/local/lib/qt4/bin/qmake)
+if(GLOB_TEMP_VAR)
+  set(QT4_INSTALLED TRUE)
+endif()
+set(GLOB_TEMP_VAR)
+
 if (Qt_FIND_VERSION)
   set(DESIRED_QT_VERSION "${Qt_FIND_VERSION}")
 endif ()
@@ -91,6 +103,7 @@ find_file( QT4_QGLOBAL_H_FILE qglobal.h
   /usr/lib/qt/include/Qt
   /usr/include/Qt
   /usr/share/qt4/include/Qt
+  /usr/local/include/X11/qt4/Qt
   C:/Progra~1/qt/include/Qt )
 
 if(QT4_QGLOBAL_H_FILE)
@@ -110,6 +123,7 @@ find_file( QT3_QGLOBAL_H_FILE qglobal.h
   /usr/lib/qt/include
   /usr/include
   /usr/share/qt3/include
+  /usr/local/include/X11/qt3
   C:/Progra~1/qt/include
   /usr/include/qt3 )
 

+ 4 - 2
Modules/FindQt3.cmake

@@ -64,6 +64,7 @@ find_path(QT_INCLUDE_DIR qt.h
   /usr/share/qt3/include
   C:/Progra~1/qt/include
   /usr/include/qt3
+  /usr/local/include/X11/qt3
   )
 
 # if qglobal.h is not in the qt_include_dir then set
@@ -146,7 +147,7 @@ find_library(QT_QASSISTANTCLIENT_LIBRARY
 
 # Qt 3 should prefer QTDIR over the PATH
 find_program(QT_MOC_EXECUTABLE
-  NAMES moc-qt3 moc
+  NAMES moc-qt3 moc moc3 moc3-mt
   HINTS
     ENV QTDIR
   PATHS
@@ -154,6 +155,7 @@ find_program(QT_MOC_EXECUTABLE
   "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.2.0;InstallDir]/include/Qt"
   "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.1.0;InstallDir]/include/Qt"
   ${GLOB_PATHS_BIN}
+    /usr/local/lib/qt3
     /usr/local/qt
     /usr/lib/qt
     /usr/lib/qt3
@@ -170,7 +172,7 @@ endif()
 
 # Qt 3 should prefer QTDIR over the PATH
 find_program(QT_UIC_EXECUTABLE
-  NAMES uic-qt3 uic
+  NAMES uic-qt3 uic uic3 uic3-mt
   HINTS
     ENV QTDIR
   PATHS

+ 92 - 11
Modules/FindQt4.cmake

@@ -418,6 +418,15 @@ macro (_QT4_ADJUST_LIB_VARS _camelCaseBasename)
           set_property(TARGET Qt4::${_camelCaseBasename}        PROPERTY IMPORTED_LOCATION_DEBUG "${QT_${basename}_LIBRARY_DEBUG}" )
         endif()
       endif ()
+      set_property(TARGET Qt4::${_camelCaseBasename} PROPERTY
+        INTERFACE_INCLUDE_DIRECTORIES
+          "${QT_${basename}_INCLUDE_DIR}"
+      )
+      string(REGEX REPLACE "^QT" "" _stemname ${basename})
+      set_property(TARGET Qt4::${_camelCaseBasename} PROPERTY
+        INTERFACE_COMPILE_DEFINITIONS
+          "QT_${_stemname}_LIB"
+      )
     endif()
 
     # If QT_USE_IMPORTED_TARGETS is enabled, the QT_QTFOO_LIBRARY variables are set to point at these
@@ -538,6 +547,11 @@ endif ()
 
 if (QT_QMAKE_EXECUTABLE AND QTVERSION)
 
+  # set version variables
+  string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" QT_VERSION_MAJOR "${QTVERSION}")
+  string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" QT_VERSION_MINOR "${QTVERSION}")
+  string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" QT_VERSION_PATCH "${QTVERSION}")
+
   # ask qmake for the mkspecs directory
   # we do this first because QT_LIBINFIX might be set
   if (NOT QT_MKSPECS_DIR  OR  QT_QMAKE_CHANGED)
@@ -942,12 +956,49 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
   ############################################
 
 
+  macro(_qt4_add_target_depends_internal _QT_MODULE _PROPERTY)
+    if (TARGET Qt4::${_QT_MODULE})
+      foreach(_DEPEND ${ARGN})
+        if (NOT TARGET Qt4::Qt${_DEPEND})
+          message(FATAL_ERROR "_qt4_add_target_depends invoked with invalid arguments")
+        endif()
+        set_property(TARGET Qt4::${_QT_MODULE} APPEND PROPERTY
+          ${_PROPERTY}
+          "Qt4::Qt${_DEPEND}"
+        )
+        set_property(TARGET Qt4::${_QT_MODULE} APPEND PROPERTY
+          INTERFACE_INCLUDE_DIRECTORIES
+            "$<TARGET_PROPERTY:Qt4::Qt${_DEPEND},INTERFACE_INCLUDE_DIRECTORIES>"
+        )
+        set_property(TARGET Qt4::${_QT_MODULE} APPEND PROPERTY
+          INTERFACE_COMPILE_DEFINITIONS
+            "$<TARGET_PROPERTY:Qt4::Qt${_DEPEND},INTERFACE_COMPILE_DEFINITIONS>"
+        )
+      endforeach()
+    endif()
+  endmacro()
+
+  macro(_qt4_add_target_depends _QT_MODULE)
+    _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_INTERFACE_LIBRARIES ${ARGN})
+  endmacro()
+
+  macro(_qt4_add_target_private_depends _QT_MODULE)
+    _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_DEPENDENT_LIBRARIES ${ARGN})
+  endmacro()
+
+
   # Set QT_xyz_LIBRARY variable and add
   # library include path to QT_INCLUDES
   _QT4_ADJUST_LIB_VARS(QtCore)
+  set_property(TARGET Qt4::QtCore APPEND PROPERTY
+    INTERFACE_INCLUDE_DIRECTORIES
+      "${QT_MKSPECS_DIR}/default"
+      ${QT_INCLUDE_DIR}
+  )
 
   foreach(QT_MODULE ${QT_MODULES})
     _QT4_ADJUST_LIB_VARS(${QT_MODULE})
+    _qt4_add_target_depends(${QT_MODULE} Core)
   endforeach()
 
   _QT4_ADJUST_LIB_VARS(QtAssistant)
@@ -962,6 +1013,41 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
     _QT4_ADJUST_LIB_VARS(QAxContainer)
   endif()
 
+  # Only public dependencies are listed here.
+  # Eg, QtDBus links to QtXml, but users of QtDBus do not need to
+  # link to QtXml because QtDBus only uses it internally, not in public
+  # headers.
+  # Everything depends on QtCore, but that is covered above already
+  _qt4_add_target_depends(Qt3Support Sql Gui Network)
+  if (TARGET Qt4::Qt3Support)
+    # An additional define is required for QT3_SUPPORT
+    set_property(TARGET Qt4::Qt3Support APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS QT3_SUPPORT)
+  endif()
+  _qt4_add_target_depends(QtDeclarative Script Gui)
+  _qt4_add_target_depends(QtDesigner Gui)
+  _qt4_add_target_depends(QtHelp Gui)
+  _qt4_add_target_depends(QtMultimedia Gui)
+  _qt4_add_target_depends(QtOpenGL Gui)
+  _qt4_add_target_depends(QtSvg Gui)
+  _qt4_add_target_depends(QtWebKit Gui Network)
+
+  _qt4_add_target_private_depends(Qt3Support Xml)
+  _qt4_add_target_private_depends(QtSvg Xml)
+  _qt4_add_target_private_depends(QtDBus Xml)
+  _qt4_add_target_private_depends(QtUiTools Xml Gui)
+  _qt4_add_target_private_depends(QtHelp Sql Xml Network)
+  _qt4_add_target_private_depends(QtXmlPatterns Network)
+  _qt4_add_target_private_depends(QtScriptTools Gui)
+  _qt4_add_target_private_depends(QtWebKit XmlPatterns)
+  _qt4_add_target_private_depends(QtDeclarative XmlPatterns Svg Sql Gui)
+  _qt4_add_target_private_depends(QtMultimedia Gui)
+  _qt4_add_target_private_depends(QtOpenGL Gui)
+  _qt4_add_target_private_depends(QAxServer Gui)
+  _qt4_add_target_private_depends(QAxContainer Gui)
+  _qt4_add_target_private_depends(phonon Gui)
+  if(QT_QTDBUS_FOUND)
+    _qt4_add_target_private_depends(phonon DBus)
+  endif()
 
   #######################################
   #
@@ -986,13 +1072,13 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
   endif()
 
   find_program(QT_MOC_EXECUTABLE
-    NAMES moc-qt4 moc
+    NAMES moc-qt4 moc moc4
     PATHS ${QT_BINARY_DIR}
     NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH
     )
 
   find_program(QT_UIC_EXECUTABLE
-    NAMES uic-qt4 uic
+    NAMES uic-qt4 uic uic4
     PATHS ${QT_BINARY_DIR}
     NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH
     )
@@ -1022,13 +1108,13 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
     )
 
   find_program(QT_LUPDATE_EXECUTABLE
-    NAMES lupdate-qt4 lupdate
+    NAMES lupdate-qt4 lupdate lupdate4
     PATHS ${QT_BINARY_DIR}
     NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH
     )
 
   find_program(QT_LRELEASE_EXECUTABLE
-    NAMES lrelease-qt4 lrelease
+    NAMES lrelease-qt4 lrelease lrelease4
     PATHS ${QT_BINARY_DIR}
     NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH
     )
@@ -1040,13 +1126,13 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
     )
 
   find_program(QT_DESIGNER_EXECUTABLE
-    NAMES designer-qt4 designer
+    NAMES designer-qt4 designer designer4
     PATHS ${QT_BINARY_DIR}
     NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH
     )
 
   find_program(QT_LINGUIST_EXECUTABLE
-    NAMES linguist-qt4 linguist
+    NAMES linguist-qt4 linguist linguist4
     PATHS ${QT_BINARY_DIR}
     NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH
     )
@@ -1174,11 +1260,6 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
 
   include("${_qt4_current_dir}/Qt4Macros.cmake")
 
-  # set version variables
-  string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" QT_VERSION_MAJOR "${QTVERSION}")
-  string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" QT_VERSION_MINOR "${QTVERSION}")
-  string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" QT_VERSION_PATCH "${QTVERSION}")
-
 endif()
 
 #support old QT_MIN_VERSION if set, but not if version is supplied by find_package()

+ 2 - 1
Modules/FindSDL_image.cmake

@@ -40,7 +40,7 @@ find_path(SDL_IMAGE_INCLUDE_DIR SDL_image.h
   HINTS
     ENV SDLIMAGEDIR
     ENV SDLDIR
-  PATH_SUFFIXES SDL SDL12 SDL11
+  PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include
 )
 
 if(NOT SDL_IMAGE_LIBRARY AND SDLIMAGE_LIBRARY)
@@ -52,6 +52,7 @@ find_library(SDL_IMAGE_LIBRARY
   HINTS
     ENV SDLIMAGEDIR
     ENV SDLDIR
+  PATH_SUFFIXES lib
 )
 
 if(SDL_IMAGE_INCLUDE_DIR AND EXISTS "${SDL_IMAGE_INCLUDE_DIR}/SDL_image.h")

+ 2 - 1
Modules/FindSDL_mixer.cmake

@@ -40,7 +40,7 @@ find_path(SDL_MIXER_INCLUDE_DIR SDL_mixer.h
   HINTS
     ENV SDLMIXERDIR
     ENV SDLDIR
-  PATH_SUFFIXES SDL SDL12 SDL11
+  PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include
 )
 
 if(NOT SDL_MIXER_LIBRARY AND SDLMIXER_LIBRARY)
@@ -52,6 +52,7 @@ find_library(SDL_MIXER_LIBRARY
   HINTS
     ENV SDLMIXERDIR
     ENV SDLDIR
+  PATH_SUFFIXES lib
 )
 
 if(SDL_MIXER_INCLUDE_DIR AND EXISTS "${SDL_MIXER_INCLUDE_DIR}/SDL_mixer.h")

+ 2 - 1
Modules/FindSDL_net.cmake

@@ -40,7 +40,7 @@ find_path(SDL_NET_INCLUDE_DIR SDL_net.h
   HINTS
     ENV SDLNETDIR
     ENV SDLDIR
-  PATH_SUFFIXES SDL SDL12 SDL11
+  PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include
 )
 
 if(NOT SDL_NET_LIBRARY AND SDLNET_LIBRARY)
@@ -52,6 +52,7 @@ find_library(SDL_NET_LIBRARY
   HINTS
     ENV SDLNETDIR
     ENV SDLDIR
+  PATH_SUFFIXES lib
 )
 
 if(SDL_NET_INCLUDE_DIR AND EXISTS "${SDL_NET_INCLUDE_DIR}/SDL_net.h")

+ 2 - 1
Modules/FindSDL_sound.cmake

@@ -77,7 +77,7 @@ find_path(SDL_SOUND_INCLUDE_DIR SDL_sound.h
   HINTS
     ENV SDLSOUNDDIR
     ENV SDLDIR
-  PATH_SUFFIXES SDL SDL12 SDL11
+  PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include
   )
 
 find_library(SDL_SOUND_LIBRARY
@@ -85,6 +85,7 @@ find_library(SDL_SOUND_LIBRARY
   HINTS
     ENV SDLSOUNDDIR
     ENV SDLDIR
+  PATH_SUFFIXES lib
   )
 
 if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY)

+ 2 - 1
Modules/FindSDL_ttf.cmake

@@ -40,7 +40,7 @@ find_path(SDL_TTF_INCLUDE_DIR SDL_ttf.h
   HINTS
     ENV SDLTTFDIR
     ENV SDLDIR
-  PATH_SUFFIXES SDL SDL12 SDL11
+  PATH_SUFFIXES include/SDL include/SDL12 include/SDL11 include
 )
 
 if(NOT SDL_TTF_LIBRARY AND SDLTTF_LIBRARY)
@@ -52,6 +52,7 @@ find_library(SDL_TTF_LIBRARY
   HINTS
     ENV SDLTTFDIR
     ENV SDLDIR
+  PATH_SUFFIXES lib
 )
 
 if(SDL_TTF_INCLUDE_DIR AND EXISTS "${SDL_TTF_INCLUDE_DIR}/SDL_ttf.h")

+ 1 - 0
Modules/Platform/Darwin-Clang.cmake

@@ -19,6 +19,7 @@ endif()
 set(__DARWIN_COMPILER_CLANG 1)
 
 macro(__darwin_compiler_clang lang)
+  set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output
   set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names")
   set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names")
   set(CMAKE_${lang}_SYSROOT_FLAG "-isysroot")

+ 1 - 0
Modules/Platform/Darwin-GNU.cmake

@@ -19,6 +19,7 @@ endif()
 set(__DARWIN_COMPILER_GNU 1)
 
 macro(__darwin_compiler_gnu lang)
+  set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output
   # GNU does not have -shared on OS X
   set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names")
   set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names")

+ 18 - 0
Modules/Platform/Darwin.cmake

@@ -256,6 +256,24 @@ set(CMAKE_CXX_CREATE_MACOSX_FRAMEWORK
 if(NOT DEFINED CMAKE_FIND_FRAMEWORK)
   set(CMAKE_FIND_FRAMEWORK FIRST)
 endif()
+
+# Older OS X linkers do not report their framework search path
+# with -v but "man ld" documents the following locations.
+set(CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+  ${_CMAKE_OSX_SYSROOT_PATH}/Library/Frameworks
+  ${_CMAKE_OSX_SYSROOT_PATH}/System/Library/Frameworks
+  )
+if(_CMAKE_OSX_SYSROOT_PATH)
+  # Treat some paths as implicit so we do not override the SDK versions.
+  list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+    /System/Library/Frameworks)
+endif()
+if("${_CURRENT_OSX_VERSION}" VERSION_LESS "10.5")
+  # Older OS X tools had more implicit paths.
+  list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+    ${_CMAKE_OSX_SYSROOT_PATH}/Network/Library/Frameworks)
+endif()
+
 # set up the default search directories for frameworks
 set(CMAKE_SYSTEM_FRAMEWORK_PATH
   ~/Library/Frameworks

+ 13 - 0
Modules/WIX.template.in

@@ -24,6 +24,19 @@
         <WixVariable Id="WixUILicenseRtf" Value="$(var.CPACK_WIX_LICENSE_RTF)"/>
         <Property Id="WIXUI_INSTALLDIR" Value="INSTALL_ROOT"/>
 
+        <?ifdef CPACK_WIX_PRODUCT_ICON?>
+        <Property Id="ARPPRODUCTICON">ProductIcon.ico</Property>
+        <Icon Id="ProductIcon.ico" SourceFile="$(var.CPACK_WIX_PRODUCT_ICON)"/>
+        <?endif?>
+
+        <?ifdef CPACK_WIX_UI_BANNER?>
+        <WixVariable Id="WixUIBannerBmp" Value="$(var.CPACK_WIX_UI_BANNER)"/>
+        <?endif?>
+
+        <?ifdef CPACK_WIX_UI_DIALOG?>
+        <WixVariable Id="WixUIDialogBmp" Value="$(var.CPACK_WIX_UI_DIALOG)"/>
+        <?endif?>
+
         <FeatureRef Id="ProductFeature"/>
 
         <UIRef Id="WixUI_InstallDir" />

+ 1 - 1
Source/CMakeVersion.cmake

@@ -2,5 +2,5 @@
 set(CMake_VERSION_MAJOR 2)
 set(CMake_VERSION_MINOR 8)
 set(CMake_VERSION_PATCH 10)
-set(CMake_VERSION_TWEAK 20121210)
+set(CMake_VERSION_TWEAK 20130118)
 #set(CMake_VERSION_RC 1)

+ 3 - 0
Source/CPack/WiX/cmCPackWIXGenerator.cxx

@@ -221,6 +221,9 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
   CopyDefinition(includeFile, "CPACK_PACKAGE_NAME");
   CopyDefinition(includeFile, "CPACK_PACKAGE_VERSION");
   CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF");
+  CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON");
+  CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER");
+  CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG");
 
   return true;
 }

+ 2 - 2
Source/CPack/cmCPackGeneratorFactory.cxx

@@ -33,7 +33,7 @@
 #endif
 
 #if !defined(_WIN32) \
- && !defined(__QNXNTO__) && !defined(__BEOS__)
+ && !defined(__QNXNTO__) && !defined(__BEOS__) && !defined(__HAIKU__)
 #  include "cmCPackDebGenerator.h"
 #  include "cmCPackRPMGenerator.h"
 #endif
@@ -126,7 +126,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
     }
 #endif
 #if !defined(_WIN32) \
-  && !defined(__QNXNTO__) && !defined(__BEOS__)
+  && !defined(__QNXNTO__) && !defined(__BEOS__) && !defined(__HAIKU__)
   if (cmCPackDebGenerator::CanGenerate())
     {
     this->RegisterGenerator("DEB", "Debian packages",

+ 11 - 4
Source/CTest/cmCTestCoverageHandler.cxx

@@ -1097,10 +1097,17 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
         }
       else
         {
-        cmCTestLog(this->CTest, ERROR_MESSAGE,
-          "Unknown gcov output line: [" << line->c_str() << "]" << std::endl);
-        cont->Error ++;
-        //abort();
+        // gcov 4.7 can have output lines saying "No executable lines" and
+        // "Removing 'filename.gcov'"... Don't log those as "errors."
+        if(*line != "No executable lines" &&
+           !cmSystemTools::StringStartsWith(line->c_str(), "Removing "))
+          {
+          cmCTestLog(this->CTest, ERROR_MESSAGE,
+            "Unknown gcov output line: [" << line->c_str() << "]"
+            << std::endl);
+          cont->Error ++;
+          //abort();
+          }
         }
 
 

+ 6 - 1
Source/CTest/cmCTestMultiProcessHandler.cxx

@@ -248,7 +248,12 @@ bool cmCTestMultiProcessHandler::StartTest(int test)
 //---------------------------------------------------------
 void cmCTestMultiProcessHandler::StartNextTests()
 {
-  size_t numToStart = this->ParallelLevel - this->RunningCount;
+  size_t numToStart = 0;
+  if(this->RunningCount < this->ParallelLevel)
+    {
+    numToStart = this->ParallelLevel - this->RunningCount;
+    }
+
   if(numToStart == 0)
     {
     return;

+ 4 - 0
Source/cmAddLibraryCommand.h

@@ -134,6 +134,10 @@ public:
       "They may contain custom commands generating such sources, but not "
       "PRE_BUILD, PRE_LINK, or POST_BUILD commands.  "
       "Object libraries cannot be imported, exported, installed, or linked."
+      "  "
+      "Some native build systems may not like targets that have only "
+      "object files, so consider adding at least one real source file "
+      "to any target that references $<TARGET_OBJECTS:objlib>."
       ;
     }
 

+ 1 - 0
Source/cmBootstrapCommands.cxx

@@ -89,6 +89,7 @@
 #include "cmStringCommand.cxx"
 #include "cmSubdirCommand.cxx"
 #include "cmTargetLinkLibrariesCommand.cxx"
+#include "cmTimestamp.cxx"
 #include "cmTryCompileCommand.cxx"
 #include "cmTryRunCommand.cxx"
 #include "cmUnsetCommand.cxx"

+ 1 - 1
Source/cmCTest.cxx

@@ -53,7 +53,7 @@
 #include <cm_zlib.h>
 #include <cmsys/Base64.h>
 
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__)
 #include <be/kernel/OS.h>   /* disable_debugger() API. */
 #endif
 

+ 2 - 2
Source/cmCommandArgumentParser.cxx

@@ -279,7 +279,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -701,7 +701,7 @@ while (YYID (0))
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)                  \
      fprintf (File, "%d.%d-%d.%d",                      \
               (Loc).first_line, (Loc).first_column,     \

+ 5 - 0
Source/cmCommands.cxx

@@ -28,6 +28,9 @@
 #include "cmRemoveDefinitionsCommand.cxx"
 #include "cmSourceGroupCommand.cxx"
 #include "cmSubdirDependsCommand.cxx"
+#include "cmTargetCompileDefinitionsCommand.cxx"
+#include "cmTargetIncludeDirectoriesCommand.cxx"
+#include "cmTargetPropCommandBase.cxx"
 #include "cmUseMangledMesaCommand.cxx"
 #include "cmUtilitySourceCommand.cxx"
 #include "cmVariableRequiresCommand.cxx"
@@ -66,6 +69,8 @@ void GetPredefinedCommands(std::list<cmCommand*>&
   commands.push_back(new cmRemoveDefinitionsCommand);
   commands.push_back(new cmSourceGroupCommand);
   commands.push_back(new cmSubdirDependsCommand);
+  commands.push_back(new cmTargetIncludeDirectoriesCommand);
+  commands.push_back(new cmTargetCompileDefinitionsCommand);
   commands.push_back(new cmUseMangledMesaCommand);
   commands.push_back(new cmUtilitySourceCommand);
   commands.push_back(new cmVariableRequiresCommand);

+ 6 - 5
Source/cmComputeLinkDepends.cxx

@@ -172,10 +172,11 @@ satisfy dependencies.
 
 //----------------------------------------------------------------------------
 cmComputeLinkDepends
-::cmComputeLinkDepends(cmTarget* target, const char* config)
+::cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget* head)
 {
   // Store context information.
   this->Target = target;
+  this->HeadTarget = head;
   this->Makefile = this->Target->GetMakefile();
   this->LocalGenerator = this->Makefile->GetLocalGenerator();
   this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
@@ -352,7 +353,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
     {
     // Follow the target dependencies.
     if(cmTarget::LinkInterface const* iface =
-       entry.Target->GetLinkInterface(this->Config))
+       entry.Target->GetLinkInterface(this->Config, this->HeadTarget))
       {
       // This target provides its own link interface information.
       this->AddLinkEntries(depender_index, iface->Libraries);
@@ -444,7 +445,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
   if(entry.Target)
     {
     if(cmTarget::LinkInterface const* iface =
-       entry.Target->GetLinkInterface(this->Config))
+       entry.Target->GetLinkInterface(this->Config, this->HeadTarget))
       {
       // Follow public and private dependencies transitively.
       this->FollowSharedDeps(index, iface, true);
@@ -533,7 +534,7 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
 {
   // Add direct link dependencies in this configuration.
   cmTarget::LinkImplementation const* impl =
-    this->Target->GetLinkImplementation(this->Config);
+    this->Target->GetLinkImplementation(this->Config, this->HeadTarget);
   this->AddLinkEntries(-1, impl->Libraries);
   for(std::vector<std::string>::const_iterator
         wi = impl->WrongConfigLibraries.begin();
@@ -944,7 +945,7 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
     if(cmTarget* target = this->EntryList[*ni].Target)
       {
       if(cmTarget::LinkInterface const* iface =
-         target->GetLinkInterface(this->Config))
+         target->GetLinkInterface(this->Config, this->HeadTarget))
         {
         if(iface->Multiplicity > count)
           {

+ 2 - 1
Source/cmComputeLinkDepends.h

@@ -32,7 +32,7 @@ class cmake;
 class cmComputeLinkDepends
 {
 public:
-  cmComputeLinkDepends(cmTarget* target, const char* config);
+  cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget *head);
   ~cmComputeLinkDepends();
 
   // Basic information about each link item.
@@ -59,6 +59,7 @@ private:
 
   // Context information.
   cmTarget* Target;
+  cmTarget* HeadTarget;
   cmMakefile* Makefile;
   cmLocalGenerator* LocalGenerator;
   cmGlobalGenerator* GlobalGenerator;

+ 32 - 8
Source/cmComputeLinkInformation.cxx

@@ -239,10 +239,12 @@ because this need be done only for shared libraries without soname-s.
 
 //----------------------------------------------------------------------------
 cmComputeLinkInformation
-::cmComputeLinkInformation(cmTarget* target, const char* config)
+::cmComputeLinkInformation(cmTarget* target, const char* config,
+                           cmTarget *headTarget)
 {
   // Store context information.
   this->Target = target;
+  this->HeadTarget = headTarget;
   this->Makefile = this->Target->GetMakefile();
   this->LocalGenerator = this->Makefile->GetLocalGenerator();
   this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
@@ -265,7 +267,7 @@ cmComputeLinkInformation
   this->OrderDependentRPath = 0;
 
   // Get the language used for linking this target.
-  this->LinkLanguage = this->Target->GetLinkerLanguage(config);
+  this->LinkLanguage = this->Target->GetLinkerLanguage(config, headTarget);
   if(!this->LinkLanguage)
     {
     // The Compute method will do nothing, so skip the rest of the
@@ -503,7 +505,7 @@ bool cmComputeLinkInformation::Compute()
     }
 
   // Compute the ordered link line items.
-  cmComputeLinkDepends cld(this->Target, this->Config);
+  cmComputeLinkDepends cld(this->Target, this->Config, this->HeadTarget);
   cld.SetOldLinkDirMode(this->OldLinkDirMode);
   cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute();
 
@@ -569,7 +571,8 @@ bool cmComputeLinkInformation::Compute()
 void cmComputeLinkInformation::AddImplicitLinkInfo()
 {
   // The link closure lists all languages whose implicit info is needed.
-  cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config);
+  cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config,
+                                                          this->HeadTarget);
   for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
       li != lc->Languages.end(); ++li)
     {
@@ -1376,10 +1379,31 @@ void cmComputeLinkInformation::DropDirectoryItem(std::string const& item)
 //----------------------------------------------------------------------------
 void cmComputeLinkInformation::ComputeFrameworkInfo()
 {
-  // Avoid adding system framework paths.  See "man ld" on OS X.
-  this->FrameworkPathsEmmitted.insert("/Library/Frameworks");
-  this->FrameworkPathsEmmitted.insert("/Network/Library/Frameworks");
-  this->FrameworkPathsEmmitted.insert("/System/Library/Frameworks");
+  // Avoid adding implicit framework paths.
+  std::vector<std::string> implicitDirVec;
+
+  // Get platform-wide implicit directories.
+  if(const char* implicitLinks = this->Makefile->GetDefinition
+     ("CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"))
+    {
+    cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec);
+    }
+
+  // Get language-specific implicit directories.
+  std::string implicitDirVar = "CMAKE_";
+  implicitDirVar += this->LinkLanguage;
+  implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES";
+  if(const char* implicitDirs =
+     this->Makefile->GetDefinition(implicitDirVar.c_str()))
+    {
+    cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec);
+    }
+
+  for(std::vector<std::string>::const_iterator i = implicitDirVec.begin();
+      i != implicitDirVec.end(); ++i)
+    {
+    this->FrameworkPathsEmmitted.insert(*i);
+    }
 
   // Regular expression to extract a framework path and name.
   this->SplitFramework.compile("(.*)/(.*)\\.framework$");

+ 3 - 1
Source/cmComputeLinkInformation.h

@@ -29,7 +29,8 @@ class cmOrderDirectories;
 class cmComputeLinkInformation
 {
 public:
-  cmComputeLinkInformation(cmTarget* target, const char* config);
+  cmComputeLinkInformation(cmTarget* target, const char* config,
+                           cmTarget* headTarget);
   ~cmComputeLinkInformation();
   bool Compute();
 
@@ -74,6 +75,7 @@ private:
 
   // Context information.
   cmTarget* Target;
+  cmTarget* HeadTarget;
   cmMakefile* Makefile;
   cmLocalGenerator* LocalGenerator;
   cmGlobalGenerator* GlobalGenerator;

+ 92 - 6
Source/cmComputeTargetDepends.cxx

@@ -200,20 +200,48 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
   // Get the depender.
   cmTarget* depender = this->Targets[depender_index];
 
-  // Loop over all targets linked directly.
+  // Loop over all targets linked directly in all configs.
+  // We need to make targets depend on the union of all config-specific
+  // dependencies in all targets, because the generated build-systems can't
+  // deal with config-specific dependencies.
   {
-  cmTarget::LinkLibraryVectorType const& tlibs =
-    depender->GetOriginalLinkLibraries();
   std::set<cmStdString> emitted;
+  {
+  std::vector<std::string> tlibs;
+  depender->GetDirectLinkLibraries(0, tlibs, depender);
   // A target should not depend on itself.
   emitted.insert(depender->GetName());
-  for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
+  for(std::vector<std::string>::const_iterator lib = tlibs.begin();
       lib != tlibs.end(); ++lib)
     {
     // Don't emit the same library twice for this target.
-    if(emitted.insert(lib->first).second)
+    if(emitted.insert(*lib).second)
       {
-      this->AddTargetDepend(depender_index, lib->first.c_str(), true);
+      this->AddTargetDepend(depender_index, lib->c_str(), true);
+      this->AddInterfaceDepends(depender_index, lib->c_str(),
+                                true, emitted);
+      }
+    }
+  }
+  std::vector<std::string> configs;
+  depender->GetMakefile()->GetConfigurations(configs);
+  for (std::vector<std::string>::const_iterator it = configs.begin();
+    it != configs.end(); ++it)
+    {
+    std::vector<std::string> tlibs;
+    depender->GetDirectLinkLibraries(it->c_str(), tlibs, depender);
+    // A target should not depend on itself.
+    emitted.insert(depender->GetName());
+    for(std::vector<std::string>::const_iterator lib = tlibs.begin();
+        lib != tlibs.end(); ++lib)
+      {
+      // Don't emit the same library twice for this target.
+      if(emitted.insert(*lib).second)
+        {
+        this->AddTargetDepend(depender_index, lib->c_str(), true);
+        this->AddInterfaceDepends(depender_index, lib->c_str(),
+                                  true, emitted);
+        }
       }
     }
   }
@@ -236,6 +264,64 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
   }
 }
 
+//----------------------------------------------------------------------------
+void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
+                                                 cmTarget* dependee,
+                                                 const char *config,
+                                               std::set<cmStdString> &emitted)
+{
+  cmTarget* depender = this->Targets[depender_index];
+  if(cmTarget::LinkInterface const* iface =
+                                dependee->GetLinkInterface(config, depender))
+    {
+    for(std::vector<std::string>::const_iterator
+        lib = iface->Libraries.begin();
+        lib != iface->Libraries.end(); ++lib)
+      {
+      // Don't emit the same library twice for this target.
+      if(emitted.insert(*lib).second)
+        {
+        this->AddTargetDepend(depender_index, lib->c_str(), true);
+        }
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
+                                             const char* dependee_name,
+                                             bool linking,
+                                             std::set<cmStdString> &emitted)
+{
+  cmTarget* depender = this->Targets[depender_index];
+  cmTarget* dependee =
+    depender->GetMakefile()->FindTargetToUse(dependee_name);
+  // Skip targets that will not really be linked.  This is probably a
+  // name conflict between an external library and an executable
+  // within the project.
+  if(linking && dependee &&
+     dependee->GetType() == cmTarget::EXECUTABLE &&
+     !dependee->IsExecutableWithExports())
+    {
+    dependee = 0;
+    }
+
+  if(dependee)
+    {
+    this->AddInterfaceDepends(depender_index, dependee, 0, emitted);
+    std::vector<std::string> configs;
+    depender->GetMakefile()->GetConfigurations(configs);
+    for (std::vector<std::string>::const_iterator it = configs.begin();
+      it != configs.end(); ++it)
+      {
+      // A target should not depend on itself.
+      emitted.insert(depender->GetName());
+      this->AddInterfaceDepends(depender_index, dependee,
+                                it->c_str(), emitted);
+      }
+    }
+}
+
 //----------------------------------------------------------------------------
 void cmComputeTargetDepends::AddTargetDepend(int depender_index,
                                              const char* dependee_name,

+ 5 - 1
Source/cmComputeTargetDepends.h

@@ -48,7 +48,11 @@ private:
                        bool linking);
   void AddTargetDepend(int depender_index, cmTarget* dependee, bool linking);
   bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
-
+  void AddInterfaceDepends(int depender_index, const char* dependee_name,
+                           bool linking, std::set<cmStdString> &emitted);
+  void AddInterfaceDepends(int depender_index, cmTarget* dependee,
+                           const char *config,
+                           std::set<cmStdString> &emitted);
   cmGlobalGenerator* GlobalGenerator;
   bool DebugMode;
   bool NoCycles;

+ 2 - 2
Source/cmCustomCommandGenerator.cxx

@@ -47,7 +47,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
     {
     return target->GetLocation(this->Config);
     }
-  return this->GE->Parse(argv0).Evaluate(this->Makefile, this->Config);
+  return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config);
 }
 
 //----------------------------------------------------------------------------
@@ -58,7 +58,7 @@ cmCustomCommandGenerator
   cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c];
   for(unsigned int j=1;j < commandLine.size(); ++j)
     {
-    std::string arg = this->GE->Parse(commandLine[j]).Evaluate(this->Makefile,
+    std::string arg = this->GE->Parse(commandLine[j])->Evaluate(this->Makefile,
                                                                this->Config);
     cmd += " ";
     if(this->OldStyle)

+ 11 - 0
Source/cmDocumentGeneratorExpressions.h

@@ -26,7 +26,18 @@
   "strings which contain a '>' for example.\n"                          \
   "  $<COMMA>                  = A literal ','. Used to compare "       \
   "strings which contain a ',' for example.\n"                          \
+  "  $<TARGET_NAME:...>        = Marks ... as being the name of a "     \
+  "target.  This is required if exporting targets to multiple "         \
+  "dependent export sets.  The '...' must be a literal name of a "      \
+  "target- it may not contain generator expressions.\n"                 \
+  "  $<INSTALL_INTERFACE:...>  = content of \"...\" when the property " \
+  "is exported using install(EXPORT), and empty otherwise.\n"           \
+  "  $<BUILD_INTERFACE:...>    = content of \"...\" when the property " \
+  "is exported using export(), or when the target is used by another "  \
+  "target in the same buildsystem. Expands to the empty string "        \
+  "otherwise.\n"                                                        \
   "  $<TARGET_FILE:tgt>        = main file (.exe, .so.1.2, .a)\n"       \
+  "  $<TARGET_DEFINED:tgt>     = '1' if tgt is a target, else '0'\n"    \
   "  $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n"   \
   "  $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n"            \
   "where \"tgt\" is the name of a target.  "                            \

+ 37 - 0
Source/cmDocumentVariables.cxx

@@ -896,6 +896,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
       " script, it may get fatal error messages from the script.",false,
       "Variables That Change Behavior");
 
+  cm->DefineProperty
+    ("CMAKE_DEBUG_TARGET_PROPERTIES", cmProperty::VARIABLE,
+     "Enables tracing output for target properties.",
+     "This variable can be populated with a list of properties to generate "
+     "debug output for when evaluating target properties.  Currently it can "
+     "only be used when evaluating the INCLUDE_DIRECTORIES target property.  "
+     "In that case, it outputs a backtrace for each include directory in "
+     "the build.  Default is unset.",false,"Variables That Change Behavior");
+
   // Variables defined by CMake that describe the system
 
   cm->DefineProperty
@@ -1137,6 +1146,17 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
      false,
      "Variables that Control the Build");
 
+  cm->DefineProperty
+    ("CMAKE_BUILD_INTERFACE_INCLUDES", cmProperty::VARIABLE,
+     "Automatically add the current source- and build directories "
+     "to the INTERFACE_INCLUDE_DIRECTORIES.",
+     "If this variable is enabled, CMake automatically adds for each "
+     "target ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} "
+     "to the INTERFACE_INCLUDE_DIRECTORIES."
+     "By default CMAKE_BUILD_INTERFACE_INCLUDES is OFF.",
+     false,
+     "Variables that Control the Build");
+
   cm->DefineProperty
     ("CMAKE_INSTALL_RPATH", cmProperty::VARIABLE,
      "The rpath to use for installed targets.",
@@ -1621,6 +1641,23 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
      "These paths are implicit linker search directories for the compiler's "
      "language.  "
      "CMake automatically detects these directories for each language and "
+     "reports the results in this variable."
+     "\n"
+     "When a library in one of these directories is given by full path to "
+     "target_link_libraries() CMake will generate the -l<name> form on "
+     "link lines to ensure the linker searches its implicit directories "
+     "for the library.  "
+     "Note that some toolchains read implicit directories from an "
+     "environment variable such as LIBRARY_PATH so keep its value "
+     "consistent when operating in a given build tree.",false,
+     "Variables for Languages");
+
+  cm->DefineProperty
+    ("CMAKE_<LANG>_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES", cmProperty::VARIABLE,
+     "Implicit linker framework search path detected for language <LANG>.",
+     "These paths are implicit linker framework search directories for "
+     "the compiler's language.  "
+     "CMake automatically detects these directories for each language and "
      "reports the results in this variable.", false,
      "Variables for Languages");
 

+ 40 - 15
Source/cmExportBuildFileGenerator.cxx

@@ -22,6 +22,7 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator()
 //----------------------------------------------------------------------------
 bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
 {
+  std::vector<cmTarget*> allTargets;
   {
   std::string expectedTargets;
   std::string sep;
@@ -31,20 +32,10 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
     {
     expectedTargets += sep + this->Namespace + (*tei)->GetName();
     sep = " ";
-    }
-
-  this->GenerateExpectedTargetsCode(os, expectedTargets);
-  }
-
-  // Create all the imported targets.
-  for(std::vector<cmTarget*>::const_iterator
-        tei = this->Exports->begin();
-      tei != this->Exports->end(); ++tei)
-    {
     cmTarget* te = *tei;
     if(this->ExportedTargets.insert(te).second)
       {
-      this->GenerateImportTargetCode(os, te);
+      allTargets.push_back(te);
       }
     else
       {
@@ -58,14 +49,45 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
       }
     }
 
+  this->GenerateExpectedTargetsCode(os, expectedTargets);
+  }
+
+  std::vector<std::string> missingTargets;
+
+  // Create all the imported targets.
+  for(std::vector<cmTarget*>::const_iterator
+        tei = allTargets.begin();
+      tei != allTargets.end(); ++tei)
+    {
+    cmTarget* te = *tei;
+    this->GenerateImportTargetCode(os, te);
+
+    te->AppendBuildInterfaceIncludes();
+
+    ImportPropertyMap properties;
+
+    this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te,
+                                    cmGeneratorExpression::BuildInterface,
+                                    properties, missingTargets);
+    this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te,
+                                    cmGeneratorExpression::BuildInterface,
+                                    properties, missingTargets);
+    this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
+                                  te, properties);
+
+    this->GenerateInterfaceProperties(te, os, properties);
+    }
+
   // Generate import file content for each configuration.
   for(std::vector<std::string>::const_iterator
         ci = this->Configurations.begin();
       ci != this->Configurations.end(); ++ci)
     {
-    this->GenerateImportConfig(os, ci->c_str());
+    this->GenerateImportConfig(os, ci->c_str(), missingTargets);
     }
 
+  this->GenerateMissingTargetsCheckCode(os, missingTargets);
+
   return true;
 }
 
@@ -73,7 +95,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
 void
 cmExportBuildFileGenerator
 ::GenerateImportTargetsConfig(std::ostream& os,
-                              const char* config, std::string const& suffix)
+                              const char* config, std::string const& suffix,
+                            std::vector<std::string> &missingTargets)
 {
   for(std::vector<cmTarget*>::const_iterator
         tei = this->Exports->begin();
@@ -86,9 +109,12 @@ cmExportBuildFileGenerator
     if(!properties.empty())
       {
       // Get the rest of the target details.
-      std::vector<std::string> missingTargets;
       this->SetImportDetailProperties(config, suffix,
                                       target, properties, missingTargets);
+      this->SetImportLinkInterface(config, suffix,
+                                   cmGeneratorExpression::BuildInterface,
+                                   target, properties, missingTargets);
+
 
       // TOOD: PUBLIC_HEADER_LOCATION
       // This should wait until the build feature propagation stuff
@@ -97,7 +123,6 @@ cmExportBuildFileGenerator
       //                              properties);
 
       // Generate code in the export file.
-      this->GenerateMissingTargetsCheckCode(os, missingTargets);
       this->GenerateImportPropertyCode(os, config, target, properties);
       }
     }

+ 2 - 1
Source/cmExportBuildFileGenerator.h

@@ -44,7 +44,8 @@ protected:
   virtual bool GenerateMainFile(std::ostream& os);
   virtual void GenerateImportTargetsConfig(std::ostream& os,
                                            const char* config,
-                                           std::string const& suffix);
+                                           std::string const& suffix,
+                            std::vector<std::string> &missingTargets);
   virtual void HandleMissingTarget(std::string& link_libs,
                                    std::vector<std::string>& missingTargets,
                                    cmMakefile* mf,

+ 318 - 47
Source/cmExportFileGenerator.cxx

@@ -107,7 +107,8 @@ bool cmExportFileGenerator::GenerateImportFile()
 
 //----------------------------------------------------------------------------
 void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
-                                                 const char* config)
+                                    const char* config,
+                                    std::vector<std::string> &missingTargets)
 {
   // Construct the property configuration suffix.
   std::string suffix = "_";
@@ -121,7 +122,297 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
     }
 
   // Generate the per-config target information.
-  this->GenerateImportTargetsConfig(os, config, suffix);
+  this->GenerateImportTargetsConfig(os, config, suffix, missingTargets);
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+                                              cmTarget *target,
+                                              ImportPropertyMap &properties)
+{
+  const char *input = target->GetProperty(propName);
+  if (input)
+    {
+    properties[propName] = input;
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+                      const char *outputName,
+                      cmTarget *target,
+                      cmGeneratorExpression::PreprocessContext preprocessRule,
+                      ImportPropertyMap &properties,
+                      std::vector<std::string> &missingTargets)
+{
+  const char *input = target->GetProperty(propName);
+  if (input)
+    {
+    if (!*input)
+      {
+      // Set to empty
+      properties[outputName] = "";
+      return;
+      }
+
+    std::string prepro = cmGeneratorExpression::Preprocess(input,
+                                                           preprocessRule);
+    if (!prepro.empty())
+      {
+      this->ResolveTargetsInGeneratorExpressions(prepro, target,
+                                                 missingTargets);
+      properties[outputName] = prepro;
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+                      cmTarget *target,
+                      cmGeneratorExpression::PreprocessContext preprocessRule,
+                      ImportPropertyMap &properties,
+                      std::vector<std::string> &missingTargets)
+{
+  this->PopulateInterfaceProperty(propName, propName, target, preprocessRule,
+                            properties, missingTargets);
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
+                                        std::ostream& os,
+                                        const ImportPropertyMap &properties)
+{
+  if (!properties.empty())
+    {
+    std::string targetName = this->Namespace;
+    targetName += target->GetName();
+    os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
+    for(ImportPropertyMap::const_iterator pi = properties.begin();
+        pi != properties.end(); ++pi)
+      {
+      os << "  " << pi->first << " \"" << pi->second << "\"\n";
+      }
+    os << ")\n\n";
+    }
+}
+
+//----------------------------------------------------------------------------
+bool
+cmExportFileGenerator::AddTargetNamespace(std::string &input,
+                                    cmTarget* target,
+                                    std::vector<std::string> &missingTargets)
+{
+  cmMakefile *mf = target->GetMakefile();
+
+  cmTarget *tgt = mf->FindTargetToUse(input.c_str());
+  if (!tgt)
+    {
+    return false;
+    }
+
+  if(tgt->IsImported())
+    {
+    return true;
+    }
+  if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
+    {
+    input = this->Namespace + input;
+    }
+  else
+    {
+    std::string namespacedTarget;
+    this->HandleMissingTarget(namespacedTarget, missingTargets,
+                              mf, target, tgt);
+    if (!namespacedTarget.empty())
+      {
+      input = namespacedTarget;
+      }
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+static bool isGeneratorExpression(const std::string &lib)
+{
+  const std::string::size_type openpos = lib.find("$<");
+  return (openpos != std::string::npos)
+      && (lib.find(">", openpos) != std::string::npos);
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
+                                    std::string &input,
+                                    cmTarget* target,
+                                    std::vector<std::string> &missingTargets,
+                                    FreeTargetsReplace replace)
+{
+  if (replace == NoReplaceFreeTargets)
+    {
+    this->ResolveTargetsInGeneratorExpression(input, target, missingTargets);
+    return;
+    }
+  std::vector<std::string> parts;
+  cmGeneratorExpression::Split(input, parts);
+
+  std::string sep;
+  input = "";
+  for(std::vector<std::string>::iterator li = parts.begin();
+      li != parts.end(); ++li)
+    {
+    if (!isGeneratorExpression(*li))
+      {
+      this->AddTargetNamespace(*li, target, missingTargets);
+      }
+    else
+      {
+      this->ResolveTargetsInGeneratorExpression(
+                                    *li,
+                                    target,
+                                    missingTargets);
+      }
+    input += sep + *li;
+    sep = ";";
+    }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
+                                    std::string &input,
+                                    cmTarget* target,
+                                    std::vector<std::string> &missingTargets)
+{
+  std::string::size_type pos = 0;
+  std::string::size_type lastPos = pos;
+
+  cmMakefile *mf = target->GetMakefile();
+  std::string errorString;
+
+  while((pos = input.find("$<TARGET_PROPERTY:", lastPos)) != input.npos)
+    {
+    std::string::size_type nameStartPos = pos +
+                                            sizeof("$<TARGET_PROPERTY:") - 1;
+    std::string::size_type closePos = input.find(">", nameStartPos);
+    std::string::size_type commaPos = input.find(",", nameStartPos);
+    std::string::size_type nextOpenPos = input.find("$<", nameStartPos);
+    if (commaPos == input.npos // Implied 'this' target
+        || closePos == input.npos // Imcomplete expression.
+        || closePos < commaPos // Implied 'this' target
+        || nextOpenPos < commaPos) // Non-literal
+      {
+      lastPos = nameStartPos;
+      continue;
+      }
+
+    std::string targetName = input.substr(nameStartPos,
+                                                commaPos - nameStartPos);
+
+    if (!this->AddTargetNamespace(targetName, target, missingTargets))
+      {
+      errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires "
+                    "its first parameter to be a reachable target.";
+      break;
+      }
+    input.replace(nameStartPos, commaPos - nameStartPos, targetName);
+    lastPos = pos + targetName.size();
+    }
+  if (!errorString.empty())
+    {
+    mf->IssueMessage(cmake::FATAL_ERROR, errorString);
+    return;
+    }
+
+  pos = 0;
+  lastPos = pos;
+  while((pos = input.find("$<TARGET_NAME:", lastPos)) != input.npos)
+    {
+    std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1;
+    std::string::size_type endPos = input.find(">", nameStartPos);
+    if (endPos == input.npos)
+      {
+      errorString = "$<TARGET_NAME:...> expression incomplete";
+      break;
+      }
+    std::string targetName = input.substr(nameStartPos,
+                                                endPos - nameStartPos);
+    if(targetName.find("$<") != input.npos)
+      {
+      errorString = "$<TARGET_NAME:...> requires its parameter to be a "
+                    "literal.";
+      break;
+      }
+    if (!this->AddTargetNamespace(targetName, target, missingTargets))
+      {
+      errorString = "$<TARGET_NAME:...> requires its parameter to be a "
+                    "reachable target.";
+      break;
+      }
+    input.replace(pos, endPos - pos + 1, targetName);
+    lastPos = endPos;
+    }
+  if (!errorString.empty())
+    {
+    mf->IssueMessage(cmake::FATAL_ERROR, errorString);
+    }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator
+::SetImportLinkInterface(const char* config, std::string const& suffix,
+                    cmGeneratorExpression::PreprocessContext preprocessRule,
+                    cmTarget* target, ImportPropertyMap& properties,
+                    std::vector<std::string>& missingTargets)
+{
+  // Add the transitive link dependencies for this configuration.
+  cmTarget::LinkInterface const* iface = target->GetLinkInterface(config,
+                                                                  target);
+  if (!iface)
+    {
+    return;
+    }
+
+  if (iface->ImplementationIsInterface)
+    {
+    this->SetImportLinkProperty(suffix, target,
+                                "IMPORTED_LINK_INTERFACE_LIBRARIES",
+                                iface->Libraries, properties, missingTargets);
+    return;
+    }
+
+  const char *propContent;
+
+  if (const char *prop_suffixed = target->GetProperty(
+                    ("LINK_INTERFACE_LIBRARIES" + suffix).c_str()))
+    {
+    propContent = prop_suffixed;
+    }
+  else if (const char *prop = target->GetProperty(
+                    "LINK_INTERFACE_LIBRARIES"))
+    {
+    propContent = prop;
+    }
+  else
+    {
+    return;
+    }
+
+  if (!*propContent)
+    {
+    properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = "";
+    return;
+    }
+
+  std::string prepro = cmGeneratorExpression::Preprocess(propContent,
+                                                         preprocessRule);
+  if (!prepro.empty())
+    {
+    this->ResolveTargetsInGeneratorExpressions(prepro, target,
+                                               missingTargets,
+                                               ReplaceFreeTargets);
+    properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
+    }
 }
 
 //----------------------------------------------------------------------------
@@ -162,14 +453,13 @@ cmExportFileGenerator
     }
 
   // Add the transitive link dependencies for this configuration.
-  if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config))
+  if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config,
+                                                                     target))
     {
     this->SetImportLinkProperty(suffix, target,
                                 "IMPORTED_LINK_INTERFACE_LANGUAGES",
                                 iface->Languages, properties, missingTargets);
-    this->SetImportLinkProperty(suffix, target,
-                                "IMPORTED_LINK_INTERFACE_LIBRARIES",
-                                iface->Libraries, properties, missingTargets);
+
     this->SetImportLinkProperty(suffix, target,
                                 "IMPORTED_LINK_DEPENDENT_LIBRARIES",
                                 iface->SharedDeps, properties, missingTargets);
@@ -201,9 +491,6 @@ cmExportFileGenerator
     return;
     }
 
-  // Get the makefile in which to lookup target information.
-  cmMakefile* mf = target->GetMakefile();
-
   // Construct the property value.
   std::string link_libs;
   const char* sep = "";
@@ -214,33 +501,9 @@ cmExportFileGenerator
     link_libs += sep;
     sep = ";";
 
-    // Append this entry.
-    if(cmTarget* tgt = mf->FindTargetToUse(li->c_str()))
-      {
-      // This is a target.
-      if(tgt->IsImported())
-        {
-        // The target is imported (and therefore is not in the
-        // export).  Append the raw name.
-        link_libs += *li;
-        }
-      else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
-        {
-        // The target is in the export.  Append it with the export
-        // namespace.
-        link_libs += this->Namespace;
-        link_libs += *li;
-        }
-      else
-        {
-        this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt);
-        }
-      }
-    else
-      {
-      // Append the raw name.
-      link_libs += *li;
-      }
+    std::string temp = *li;
+    this->AddTargetNamespace(temp, target, missingTargets);
+    link_libs += temp;
     }
 
   // Store the property.
@@ -415,21 +678,29 @@ cmExportFileGenerator
 void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
                                 const std::vector<std::string>& missingTargets)
 {
+  if (missingTargets.empty())
+    {
+    return;
+    }
   os << "# Make sure the targets which have been exported in some other \n"
         "# export set exist.\n";
+  std::set<std::string> emitted;
   for(unsigned int i=0; i<missingTargets.size(); ++i)
     {
-    os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n"
-       << "  IF(CMAKE_FIND_PACKAGE_NAME)\n"
-       << "    SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
-       << "    SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
-       << "\"Required imported target \\\"" << missingTargets[i]
-       << "\\\" not found ! \")\n"
-       << "  ELSE()\n"
-       << "    MESSAGE(FATAL_ERROR \"Required imported target \\\""
-       << missingTargets[i] << "\\\" not found ! \")\n"
-       << "  ENDIF()\n"
-       << "ENDIF()\n";
+    if (emitted.insert(missingTargets[i]).second)
+      {
+      os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n"
+        << "  IF(CMAKE_FIND_PACKAGE_NAME)\n"
+        << "    SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
+        << "    SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
+        << "\"Required imported target \\\"" << missingTargets[i]
+        << "\\\" not found ! \")\n"
+        << "  ELSE()\n"
+        << "    MESSAGE(FATAL_ERROR \"Required imported target \\\""
+        << missingTargets[i] << "\\\" not found ! \")\n"
+        << "  ENDIF()\n"
+        << "ENDIF()\n";
+      }
     }
   os << "\n";
 }

+ 43 - 2
Source/cmExportFileGenerator.h

@@ -13,6 +13,7 @@
 #define cmExportFileGenerator_h
 
 #include "cmCommand.h"
+#include "cmGeneratorExpression.h"
 
 /** \class cmExportFileGenerator
  * \brief Generate a file exporting targets from a build or install tree.
@@ -46,7 +47,8 @@ protected:
 
   // Generate per-configuration target information to the given output
   // stream.
-  void GenerateImportConfig(std::ostream& os, const char* config);
+  void GenerateImportConfig(std::ostream& os, const char* config,
+                            std::vector<std::string> &missingTargets);
 
   // Methods to implement export file code generation.
   void GenerateImportHeaderCode(std::ostream& os, const char* config = 0);
@@ -84,7 +86,8 @@ protected:
   /** Each subclass knows where the target files are located.  */
   virtual void GenerateImportTargetsConfig(std::ostream& os,
                                            const char* config,
-                                           std::string const& suffix) = 0;
+                                           std::string const& suffix,
+                            std::vector<std::string> &missingTargets) = 0;
 
   /** Each subclass knows how to deal with a target that is  missing from an
    *  export set.  */
@@ -93,6 +96,30 @@ protected:
                                    cmMakefile* mf,
                                    cmTarget* depender,
                                    cmTarget* dependee) = 0;
+  void PopulateInterfaceProperty(const char *,
+                                 cmTarget *target,
+                                 cmGeneratorExpression::PreprocessContext,
+                                 ImportPropertyMap &properties,
+                                 std::vector<std::string> &missingTargets);
+  void PopulateInterfaceProperty(const char *propName, cmTarget *target,
+                                 ImportPropertyMap &properties);
+  void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
+                                   const ImportPropertyMap &properties);
+
+  void SetImportLinkInterface(const char* config, std::string const& suffix,
+                    cmGeneratorExpression::PreprocessContext preprocessRule,
+                    cmTarget* target, ImportPropertyMap& properties,
+                    std::vector<std::string>& missingTargets);
+
+  enum FreeTargetsReplace {
+    ReplaceFreeTargets,
+    NoReplaceFreeTargets
+  };
+
+  void ResolveTargetsInGeneratorExpressions(std::string &input,
+                          cmTarget* target,
+                          std::vector<std::string> &missingTargets,
+                          FreeTargetsReplace replace = NoReplaceFreeTargets);
 
   // The namespace in which the exports are placed in the generated file.
   std::string Namespace;
@@ -109,6 +136,20 @@ protected:
 
   // The set of targets included in the export.
   std::set<cmTarget*> ExportedTargets;
+
+private:
+  void PopulateInterfaceProperty(const char *, const char *,
+                                 cmTarget *target,
+                                 cmGeneratorExpression::PreprocessContext,
+                                 ImportPropertyMap &properties,
+                                 std::vector<std::string> &missingTargets);
+
+  bool AddTargetNamespace(std::string &input, cmTarget* target,
+                          std::vector<std::string> &missingTargets);
+
+  void ResolveTargetsInGeneratorExpression(std::string &input,
+                                    cmTarget* target,
+                                    std::vector<std::string> &missingTargets);
 };
 
 #endif

+ 47 - 19
Source/cmExportInstallFileGenerator.cxx

@@ -39,6 +39,7 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
 //----------------------------------------------------------------------------
 bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
 {
+  std::vector<cmTarget*> allTargets;
   {
   std::string expectedTargets;
   std::string sep;
@@ -48,20 +49,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
     {
     expectedTargets += sep + this->Namespace + (*tei)->Target->GetName();
     sep = " ";
-    }
-
-  this->GenerateExpectedTargetsCode(os, expectedTargets);
-  }
-
-  // Create all the imported targets.
-  for(std::vector<cmTargetExport*>::const_iterator
-        tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
-      tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
-    {
     cmTargetExport const* te = *tei;
     if(this->ExportedTargets.insert(te->Target).second)
       {
-      this->GenerateImportTargetCode(os, te->Target);
+      allTargets.push_back(te->Target);
       }
     else
       {
@@ -75,6 +66,36 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
       }
     }
 
+  this->GenerateExpectedTargetsCode(os, expectedTargets);
+  }
+
+  std::vector<std::string> missingTargets;
+
+  // Create all the imported targets.
+  for(std::vector<cmTarget*>::const_iterator
+        tei = allTargets.begin();
+      tei != allTargets.end(); ++tei)
+    {
+    cmTarget* te = *tei;
+    this->GenerateImportTargetCode(os, te);
+
+    ImportPropertyMap properties;
+
+    this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES",
+                                  te,
+                                  cmGeneratorExpression::InstallInterface,
+                                  properties, missingTargets);
+    this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS",
+                                  te,
+                                  cmGeneratorExpression::InstallInterface,
+                                  properties, missingTargets);
+    this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
+                                  te, properties);
+
+    this->GenerateInterfaceProperties(te, os, properties);
+    }
+
+
   // Now load per-configuration properties for them.
   os << "# Load information for each installed configuration.\n"
      << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
@@ -85,23 +106,29 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
      << "ENDFOREACH(f)\n"
      << "\n";
 
+  this->GenerateImportedFileCheckLoop(os);
+
   // Generate an import file for each configuration.
   bool result = true;
   for(std::vector<std::string>::const_iterator
         ci = this->Configurations.begin();
       ci != this->Configurations.end(); ++ci)
     {
-    if(!this->GenerateImportFileConfig(ci->c_str()))
+    if(!this->GenerateImportFileConfig(ci->c_str(), missingTargets))
       {
       result = false;
       }
     }
+
+  this->GenerateMissingTargetsCheckCode(os, missingTargets);
+
   return result;
 }
 
 //----------------------------------------------------------------------------
 bool
-cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
+cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config,
+                                    std::vector<std::string> &missingTargets)
 {
   // Skip configurations not enabled for this export.
   if(!this->IEGen->InstallsForConfig(config))
@@ -141,7 +168,7 @@ cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
   this->GenerateImportHeaderCode(os, config);
 
   // Generate the per-config target information.
-  this->GenerateImportConfig(os, config);
+  this->GenerateImportConfig(os, config, missingTargets);
 
   // End with the import file footer.
   this->GenerateImportFooterCode(os);
@@ -156,7 +183,8 @@ cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
 void
 cmExportInstallFileGenerator
 ::GenerateImportTargetsConfig(std::ostream& os,
-                              const char* config, std::string const& suffix)
+                              const char* config, std::string const& suffix,
+                              std::vector<std::string> &missingTargets)
 {
   // Add code to compute the installation prefix relative to the
   // import file location.
@@ -205,10 +233,13 @@ cmExportInstallFileGenerator
     if(!properties.empty())
       {
       // Get the rest of the target details.
-      std::vector<std::string> missingTargets;
       this->SetImportDetailProperties(config, suffix,
                                       te->Target, properties, missingTargets);
 
+      this->SetImportLinkInterface(config, suffix,
+                                   cmGeneratorExpression::InstallInterface,
+                                   te->Target, properties, missingTargets);
+
       // TOOD: PUBLIC_HEADER_LOCATION
       // This should wait until the build feature propagation stuff
       // is done.  Then this can be a propagated include directory.
@@ -216,15 +247,12 @@ cmExportInstallFileGenerator
       //                              properties);
 
       // Generate code in the export file.
-      this->GenerateMissingTargetsCheckCode(os, missingTargets);
       this->GenerateImportPropertyCode(os, config, te->Target, properties);
       this->GenerateImportedFileChecksCode(os, te->Target, properties,
                                            importedLocations);
       }
     }
 
-  this->GenerateImportedFileCheckLoop(os);
-
   // Cleanup the import prefix variable.
   if(!this->ImportPrefix.empty())
     {

+ 4 - 2
Source/cmExportInstallFileGenerator.h

@@ -56,7 +56,8 @@ protected:
   virtual bool GenerateMainFile(std::ostream& os);
   virtual void GenerateImportTargetsConfig(std::ostream& os,
                                            const char* config,
-                                           std::string const& suffix);
+                                           std::string const& suffix,
+                            std::vector<std::string> &missingTargets);
   virtual void HandleMissingTarget(std::string& link_libs,
                                    std::vector<std::string>& missingTargets,
                                    cmMakefile* mf,
@@ -72,7 +73,8 @@ protected:
 
 
   /** Generate a per-configuration file for the targets.  */
-  bool GenerateImportFileConfig(const char* config);
+  bool GenerateImportFileConfig(const char* config,
+                            std::vector<std::string> &missingTargets);
 
   /** Fill in properties indicating installed file locations.  */
   void SetImportLocationProperty(const char* config,

+ 5 - 0
Source/cmExtraCodeBlocksGenerator.cxx

@@ -811,6 +811,11 @@ std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
     command += " VERBOSE=1 ";
     command += target;
     }
+  else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
+    {
+    command += " -v ";
+    command += target;
+    }
   else
     {
     std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);

+ 57 - 0
Source/cmFileCommand.cxx

@@ -17,6 +17,8 @@
 #include "cmFileTimeComparison.h"
 #include "cmCryptoHash.h"
 
+#include "cmTimestamp.h"
+
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cm_curl.h"
 #endif
@@ -161,6 +163,10 @@ bool cmFileCommand
     {
     return this->HandleCMakePathCommand(args, true);
     }
+  else if ( subCommand == "TIMESTAMP" )
+    {
+    return this->HandleTimestampCommand(args);
+    }
 
   std::string e = "does not recognize sub-command "+subCommand;
   this->SetError(e.c_str());
@@ -3241,3 +3247,54 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
   return false;
 #endif
 }
+
+//----------------------------------------------------------------------------
+bool cmFileCommand::HandleTimestampCommand(
+  std::vector<std::string> const& args)
+{
+  if(args.size() < 3)
+    {
+    this->SetError("sub-command TIMESTAMP requires at least two arguments.");
+    return false;
+    }
+  else if(args.size() > 5)
+    {
+    this->SetError("sub-command TIMESTAMP takes at most four arguments.");
+    return false;
+    }
+
+  unsigned int argsIndex = 1;
+
+  const std::string& filename = args[argsIndex++];
+
+  const std::string& outputVariable = args[argsIndex++];
+
+  std::string formatString;
+  if(args.size() > argsIndex && args[argsIndex] != "UTC")
+    {
+    formatString = args[argsIndex++];
+    }
+
+  bool utcFlag = false;
+  if(args.size() > argsIndex)
+    {
+    if(args[argsIndex] == "UTC")
+      {
+      utcFlag = true;
+      }
+    else
+      {
+      std::string e = " TIMESTAMP sub-command does not recognize option " +
+          args[argsIndex] + ".";
+      this->SetError(e.c_str());
+      return false;
+      }
+    }
+
+  cmTimestamp timestamp;
+  std::string result = timestamp.FileModificationTime(
+    filename.c_str(), formatString, utcFlag);
+  this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str());
+
+  return true;
+}

+ 9 - 0
Source/cmFileCommand.h

@@ -87,6 +87,7 @@ public:
       "       [TLS_VERIFY on|off] [TLS_CAINFO file])\n"
       "  file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n"
       "       [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n"
+      "  file(TIMESTAMP filename variable [<format string>] [UTC])\n"
       "WRITE will write a message into a file called 'filename'. It "
       "overwrites the file if it already exists, and creates the file "
       "if it does not exist. (If the file is a build input, use "
@@ -200,6 +201,12 @@ public:
       "If SHOW_PROGRESS is specified, progress information will be printed "
       "as status messages until the operation is complete."
       "\n"
+      "TIMESTAMP will write a string representation of "
+      "the modification time of filename to variable.\n"
+      "Should the command be unable to obtain a timestamp "
+      "variable will be set to the empty string \"\".\n"
+      "See documentation of the string TIMESTAMP sub-command for more details."
+      "\n"
       "The file() command also provides COPY and INSTALL signatures:\n"
       "  file(<COPY|INSTALL> files... DESTINATION <dir>\n"
       "       [FILE_PERMISSIONS permissions...]\n"
@@ -260,6 +267,8 @@ protected:
   bool HandleInstallCommand(std::vector<std::string> const& args);
   bool HandleDownloadCommand(std::vector<std::string> const& args);
   bool HandleUploadCommand(std::vector<std::string> const& args);
+
+  bool HandleTimestampCommand(std::vector<std::string> const& args);
 };
 
 

+ 219 - 38
Source/cmGeneratorExpression.cxx

@@ -25,55 +25,55 @@
 //----------------------------------------------------------------------------
 cmGeneratorExpression::cmGeneratorExpression(
   cmListFileBacktrace const& backtrace):
-  Backtrace(backtrace), CompiledExpression(0)
+  Backtrace(backtrace)
 {
 }
 
 //----------------------------------------------------------------------------
-const cmCompiledGeneratorExpression &
+cmsys::auto_ptr<cmCompiledGeneratorExpression>
 cmGeneratorExpression::Parse(std::string const& input)
 {
   return this->Parse(input.c_str());
 }
 
 //----------------------------------------------------------------------------
-const cmCompiledGeneratorExpression &
+cmsys::auto_ptr<cmCompiledGeneratorExpression>
 cmGeneratorExpression::Parse(const char* input)
 {
-  cmGeneratorExpressionLexer l;
-  std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(input);
-  bool needsParsing = l.GetSawGeneratorExpression();
-  std::vector<cmGeneratorExpressionEvaluator*> evaluators;
-
-  if (needsParsing)
-    {
-    cmGeneratorExpressionParser p(tokens);
-    p.Parse(evaluators);
-    }
-
-  delete this->CompiledExpression;
-  this->CompiledExpression = new cmCompiledGeneratorExpression(
-                                      this->Backtrace,
-                                      evaluators,
-                                      input,
-                                      needsParsing);
-  return *this->CompiledExpression;
+  return cmsys::auto_ptr<cmCompiledGeneratorExpression>(
+                                      new cmCompiledGeneratorExpression(
+                                        this->Backtrace,
+                                        input));
 }
 
 cmGeneratorExpression::~cmGeneratorExpression()
 {
-  delete this->CompiledExpression;
 }
 
 //----------------------------------------------------------------------------
 const char *cmCompiledGeneratorExpression::Evaluate(
   cmMakefile* mf, const char* config, bool quiet,
-  cmTarget *target,
+  cmTarget *headTarget,
+  cmGeneratorExpressionDAGChecker *dagChecker) const
+{
+  return this->Evaluate(mf,
+                        config,
+                        quiet,
+                        headTarget,
+                        headTarget,
+                        dagChecker);
+}
+
+//----------------------------------------------------------------------------
+const char *cmCompiledGeneratorExpression::Evaluate(
+  cmMakefile* mf, const char* config, bool quiet,
+  cmTarget *headTarget,
+  cmTarget *currentTarget,
   cmGeneratorExpressionDAGChecker *dagChecker) const
 {
   if (!this->NeedsParsing)
     {
-    return this->Input;
+    return this->Input.c_str();
     }
 
   this->Output = "";
@@ -88,12 +88,21 @@ const char *cmCompiledGeneratorExpression::Evaluate(
   context.Config = config;
   context.Quiet = quiet;
   context.HadError = false;
-  context.Target = target;
+  context.HeadTarget = headTarget;
+  context.CurrentTarget = currentTarget ? currentTarget : headTarget;
   context.Backtrace = this->Backtrace;
 
   for ( ; it != end; ++it)
     {
-    this->Output += (*it)->Evaluate(&context, dagChecker);
+    const std::string result = (*it)->Evaluate(&context, dagChecker);
+    this->Output += result;
+
+    for(std::set<cmStdString>::const_iterator
+          p = context.SeenTargetProperties.begin();
+          p != context.SeenTargetProperties.end(); ++p)
+      {
+      this->SeenTargetProperties[*p] += result + ";";
+      }
     if (context.HadError)
       {
       this->Output = "";
@@ -108,12 +117,19 @@ const char *cmCompiledGeneratorExpression::Evaluate(
 
 cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
               cmListFileBacktrace const& backtrace,
-              const std::vector<cmGeneratorExpressionEvaluator*> &evaluators,
-              const char *input, bool needsParsing)
-  : Backtrace(backtrace), Evaluators(evaluators), Input(input),
-    NeedsParsing(needsParsing)
+              const char *input)
+  : Backtrace(backtrace), Input(input ? input : "")
 {
+  cmGeneratorExpressionLexer l;
+  std::vector<cmGeneratorExpressionToken> tokens =
+                                              l.Tokenize(this->Input.c_str());
+  this->NeedsParsing = l.GetSawGeneratorExpression();
 
+  if (this->NeedsParsing)
+    {
+    cmGeneratorExpressionParser p(tokens);
+    p.Parse(this->Evaluators);
+    }
 }
 
 
@@ -131,15 +147,41 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
     }
 }
 
-std::string cmGeneratorExpression::Preprocess(const std::string &input,
-                                              PreprocessContext context)
+//----------------------------------------------------------------------------
+static std::string stripEmptyListElements(const std::string &input)
 {
-  if (context != StripAllGeneratorExpressions)
-  {
-    assert(!"cmGeneratorExpression::Preprocess called with invalid args");
-    return std::string();
-  }
+  std::string result;
+
+  const char *c = input.c_str();
+  bool skipSemiColons = true;
+  for ( ; *c; ++c)
+    {
+    if(c[0] == ';')
+      {
+      if(skipSemiColons)
+        {
+        continue;
+        }
+      skipSemiColons = true;
+      }
+    else
+      {
+      skipSemiColons = false;
+      }
+    result += *c;
+    }
+
+  if (!result.empty() && *(result.end() - 1) == ';')
+    {
+    result.resize(result.size() - 1);
+    }
+
+  return result;
+}
 
+//----------------------------------------------------------------------------
+static std::string stripAllGeneratorExpressions(const std::string &input)
+{
   std::string result;
   std::string::size_type pos = 0;
   std::string::size_type lastPos = pos;
@@ -176,5 +218,144 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input,
     lastPos = pos;
     }
   result += input.substr(lastPos);
-  return result;
+  return stripEmptyListElements(result);
+}
+
+//----------------------------------------------------------------------------
+static std::string stripExportInterface(const std::string &input,
+                          cmGeneratorExpression::PreprocessContext context)
+{
+  std::string result;
+
+  std::string::size_type pos = 0;
+  std::string::size_type lastPos = pos;
+  while((pos = input.find("$<BUILD_INTERFACE:", lastPos)) != input.npos
+    || (pos = input.find("$<INSTALL_INTERFACE:", lastPos)) != input.npos)
+    {
+    result += input.substr(lastPos, pos - lastPos);
+    const bool gotInstallInterface = input[pos + 2] == 'I';
+    pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1
+                               : sizeof("$<BUILD_INTERFACE:") - 1;
+    int nestingLevel = 1;
+    const char *c = input.c_str() + pos;
+    const char * const cStart = c;
+    for ( ; *c; ++c)
+      {
+      if(c[0] == '$' && c[1] == '<')
+        {
+        ++nestingLevel;
+        ++c;
+        continue;
+        }
+      if(c[0] == '>')
+        {
+        --nestingLevel;
+        if (nestingLevel != 0)
+          {
+          continue;
+          }
+        if(context == cmGeneratorExpression::BuildInterface
+            && !gotInstallInterface)
+          {
+          result += input.substr(pos, c - cStart);
+          }
+        else if(context == cmGeneratorExpression::InstallInterface
+            && gotInstallInterface)
+          {
+          result += input.substr(pos, c - cStart);
+          }
+        break;
+        }
+      }
+    const std::string::size_type traversed = (c - cStart) + 1;
+    if (!*c)
+      {
+      result += std::string(gotInstallInterface ? "$<INSTALL_INTERFACE:"
+                                                : "$<BUILD_INTERFACE:")
+             + input.substr(pos, traversed);
+      }
+    pos += traversed;
+    lastPos = pos;
+    }
+  result += input.substr(lastPos);
+
+  return stripEmptyListElements(result);
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorExpression::Split(const std::string &input,
+                                  std::vector<std::string> &output)
+{
+  std::string::size_type pos = 0;
+  std::string::size_type lastPos = pos;
+  while((pos = input.find("$<", lastPos)) != input.npos)
+    {
+    std::string part = input.substr(lastPos, pos - lastPos);
+    std::string preGenex;
+    if (!part.empty())
+      {
+      std::string::size_type startPos = input.rfind(";", pos);
+      if (startPos != pos - 1 && startPos >= lastPos)
+        {
+        part = input.substr(lastPos, startPos - lastPos);
+        preGenex = input.substr(startPos + 1, pos - startPos - 1);
+        }
+      cmSystemTools::ExpandListArgument(part.c_str(), output);
+      }
+    pos += 2;
+    int nestingLevel = 1;
+    const char *c = input.c_str() + pos;
+    const char * const cStart = c;
+    for ( ; *c; ++c)
+      {
+      if(c[0] == '$' && c[1] == '<')
+        {
+        ++nestingLevel;
+        ++c;
+        continue;
+        }
+      if(c[0] == '>')
+        {
+        --nestingLevel;
+        if (nestingLevel == 0)
+          {
+          break;
+          }
+        }
+      }
+    for ( ; *c; ++c)
+      {
+      // Capture the part after the genex and before the next ';'
+      if(c[0] == ';')
+        {
+        --c;
+        break;
+        }
+      }
+    const std::string::size_type traversed = (c - cStart) + 1;
+    output.push_back(preGenex + "$<" + input.substr(pos, traversed));
+    pos += traversed;
+    lastPos = pos;
+    }
+  if (lastPos < input.size())
+    {
+    cmSystemTools::ExpandListArgument(input.substr(lastPos), output);
+    }
+}
+
+//----------------------------------------------------------------------------
+std::string cmGeneratorExpression::Preprocess(const std::string &input,
+                                              PreprocessContext context)
+{
+  if (context == StripAllGeneratorExpressions)
+    {
+    return stripAllGeneratorExpressions(input);
+    }
+  else if (context == BuildInterface || context == InstallInterface)
+    {
+    return stripExportInterface(input, context);
+    }
+
+  assert(!"cmGeneratorExpression::Preprocess called with invalid args");
+  return std::string();
 }

+ 36 - 11
Source/cmGeneratorExpression.h

@@ -14,10 +14,12 @@
 #define cmGeneratorExpression_h
 
 #include "cmStandardIncludes.h"
+#include "cmListFileCache.h"
 
 #include <stack>
 
 #include <cmsys/RegularExpression.hxx>
+#include <cmsys/auto_ptr.hxx>
 
 class cmTarget;
 class cmMakefile;
@@ -44,22 +46,27 @@ public:
   cmGeneratorExpression(cmListFileBacktrace const& backtrace);
   ~cmGeneratorExpression();
 
-  const cmCompiledGeneratorExpression& Parse(std::string const& input);
-  const cmCompiledGeneratorExpression& Parse(const char* input);
+  cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(
+                                                std::string const& input);
+  cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(const char* input);
 
   enum PreprocessContext {
-    StripAllGeneratorExpressions
+    StripAllGeneratorExpressions,
+    BuildInterface,
+    InstallInterface
   };
 
   static std::string Preprocess(const std::string &input,
                                 PreprocessContext context);
 
+  static void Split(const std::string &input,
+                    std::vector<std::string> &output);
+
 private:
   cmGeneratorExpression(const cmGeneratorExpression &);
   void operator=(const cmGeneratorExpression &);
 
   cmListFileBacktrace const& Backtrace;
-  cmCompiledGeneratorExpression *CompiledExpression;
 };
 
 class cmCompiledGeneratorExpression
@@ -67,31 +74,49 @@ class cmCompiledGeneratorExpression
 public:
   const char* Evaluate(cmMakefile* mf, const char* config,
                        bool quiet = false,
-                       cmTarget *target = 0,
+                       cmTarget *headTarget = 0,
+                       cmTarget *currentTarget = 0,
                        cmGeneratorExpressionDAGChecker *dagChecker = 0) const;
+  const char* Evaluate(cmMakefile* mf, const char* config,
+                       bool quiet,
+                       cmTarget *headTarget,
+                       cmGeneratorExpressionDAGChecker *dagChecker) const;
 
   /** Get set of targets found during evaluations.  */
   std::set<cmTarget*> const& GetTargets() const
     { return this->Targets; }
 
+  std::map<cmStdString, cmStdString> const& GetSeenTargetProperties() const
+    { return this->SeenTargetProperties; }
+
   ~cmCompiledGeneratorExpression();
 
+  std::string GetInput() const
+  {
+    return this->Input;
+  }
+
+  cmListFileBacktrace GetBacktrace() const
+  {
+    return this->Backtrace;
+  }
+
 private:
   cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
-              const std::vector<cmGeneratorExpressionEvaluator*> &evaluators,
-              const char *input, bool needsParsing);
+              const char *input);
 
   friend class cmGeneratorExpression;
 
   cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression &);
   void operator=(const cmCompiledGeneratorExpression &);
 
-  cmListFileBacktrace const& Backtrace;
-  const std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
-  const char* const Input;
-  const bool NeedsParsing;
+  cmListFileBacktrace Backtrace;
+  std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
+  const std::string Input;
+  bool NeedsParsing;
 
   mutable std::set<cmTarget*> Targets;
+  mutable std::map<cmStdString, cmStdString> SeenTargetProperties;
   mutable std::string Output;
 };
 

+ 10 - 8
Source/cmGeneratorExpressionDAGChecker.cxx

@@ -24,13 +24,14 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
   : Parent(parent), Target(target), Property(property),
     Content(content), Backtrace(backtrace)
 {
-  this->IsDAG = this->isDAG();
+  this->CheckResult = this->checkGraph();
 }
 
 //----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::check() const
+cmGeneratorExpressionDAGChecker::Result
+cmGeneratorExpressionDAGChecker::check() const
 {
-  return this->IsDAG;
+  return this->CheckResult;
 }
 
 //----------------------------------------------------------------------------
@@ -38,7 +39,7 @@ void cmGeneratorExpressionDAGChecker::reportError(
                   cmGeneratorExpressionContext *context,
                   const std::string &expr)
 {
-  if (this->IsDAG)
+  if (this->CheckResult == DAG)
     {
     return;
     }
@@ -57,7 +58,7 @@ void cmGeneratorExpressionDAGChecker::reportError(
     e << "Error evaluating generator expression:\n"
       << "  " << expr << "\n"
       << "Self reference on target \""
-      << context->Target->GetName() << "\".\n";
+      << context->HeadTarget->GetName() << "\".\n";
     context->Makefile->GetCMakeInstance()
       ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
                       parent->Backtrace);
@@ -91,16 +92,17 @@ void cmGeneratorExpressionDAGChecker::reportError(
 }
 
 //----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::isDAG() const
+cmGeneratorExpressionDAGChecker::Result
+cmGeneratorExpressionDAGChecker::checkGraph() const
 {
   const cmGeneratorExpressionDAGChecker *parent = this->Parent;
   while (parent)
     {
     if (this->Target == parent->Target && this->Property == parent->Property)
       {
-      return false;
+      return parent->Parent ? CYCLIC_REFERENCE : SELF_REFERENCE;
       }
     parent = parent->Parent;
     }
-  return true;
+  return DAG;
 }

+ 9 - 3
Source/cmGeneratorExpressionDAGChecker.h

@@ -25,12 +25,18 @@ struct cmGeneratorExpressionDAGChecker
                                   const GeneratorExpressionContent *content,
                                   cmGeneratorExpressionDAGChecker *parent);
 
-  bool check() const;
+  enum Result {
+    DAG,
+    SELF_REFERENCE,
+    CYCLIC_REFERENCE
+  };
+
+  Result check() const;
 
   void reportError(cmGeneratorExpressionContext *context,
                    const std::string &expr);
 private:
-  bool isDAG() const;
+  Result checkGraph() const;
 
 private:
   const cmGeneratorExpressionDAGChecker * const Parent;
@@ -38,7 +44,7 @@ private:
   const std::string Property;
   const GeneratorExpressionContent * const Content;
   const cmListFileBacktrace Backtrace;
-  bool IsDAG;
+  Result CheckResult;
 };
 
 #endif

+ 151 - 9
Source/cmGeneratorExpressionEvaluator.cxx

@@ -18,6 +18,8 @@
 
 #include <cmsys/String.h>
 
+#include <assert.h>
+
 //----------------------------------------------------------------------------
 #if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x510
 static
@@ -47,6 +49,8 @@ struct cmGeneratorExpressionNode
 
   virtual bool GeneratesContent() const { return true; }
 
+  virtual bool RequiresLiteralInput() const { return false; }
+
   virtual bool AcceptsSingleArbitraryContentParameter() const
     { return false; }
 
@@ -95,6 +99,12 @@ static const struct OneNode : public cmGeneratorExpressionNode
   }
 } oneNode;
 
+//----------------------------------------------------------------------------
+static const struct OneNode buildInterfaceNode;
+
+//----------------------------------------------------------------------------
+static const struct ZeroNode installInterfaceNode;
+
 //----------------------------------------------------------------------------
 #define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
 static const struct OP ## Node : public cmGeneratorExpressionNode \
@@ -257,11 +267,50 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
       return parameters.front().empty() ? "1" : "0";
       }
 
-    return cmsysString_strcasecmp(parameters.begin()->c_str(),
-                                  context->Config) == 0 ? "1" : "0";
+    if (cmsysString_strcasecmp(parameters.begin()->c_str(),
+                                  context->Config) == 0)
+      {
+      return "1";
+      }
+
+    if (context->CurrentTarget
+        && context->CurrentTarget->IsImported())
+      {
+      const char* loc = 0;
+      const char* imp = 0;
+      std::string suffix;
+      return context->CurrentTarget->GetMappedConfig(context->Config,
+                                                  &loc,
+                                                  &imp,
+                                                  suffix) ? "1" : "0";
+      }
+    return "0";
   }
 } configurationTestNode;
 
+
+static const struct TargetDefinedNode : public cmGeneratorExpressionNode
+{
+  TargetDefinedNode() {}
+
+  virtual int NumExpectedParameters() const { return 1; }
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *context,
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
+  {
+    return context->Makefile->FindTargetToUse(parameters.front().c_str())
+      ? "1" : "0";
+  }
+} targetDefinedNode;
+
+//----------------------------------------------------------------------------
+static const char* targetPropertyTransitiveWhitelist[] = {
+    "INTERFACE_INCLUDE_DIRECTORIES"
+  , "INTERFACE_COMPILE_DEFINITIONS"
+};
+
 //----------------------------------------------------------------------------
 static const struct TargetPropertyNode : public cmGeneratorExpressionNode
 {
@@ -289,8 +338,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
     cmsys::RegularExpression propertyNameValidator;
     propertyNameValidator.compile("^[A-Za-z0-9_]+$");
 
-    cmTarget* target = context->Target;
+    cmTarget* target = context->HeadTarget;
     std::string propertyName = *parameters.begin();
+
+    if (!target && parameters.size() == 1)
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<TARGET_PROPERTY:prop> may only be used with targets.  It may not "
+          "be used with add_custom_command.  Specify the target to read a "
+          "property from using the $<TARGET_PROPERTY:tgt,prop> signature "
+          "instead.");
+      return std::string();
+      }
+
     if (parameters.size() == 2)
       {
       if (parameters.begin()->empty() && parameters[1].empty())
@@ -336,6 +396,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
         }
       }
 
+    if (target == context->HeadTarget)
+      {
+      // Keep track of the properties seen while processing.
+      // The evaluation of the LINK_LIBRARIES generator expressions
+      // will check this to ensure that properties form a DAG.
+      context->SeenTargetProperties.insert(propertyName);
+      }
+
     if (propertyName.empty())
       {
       reportError(context, content->GetOriginalExpression(),
@@ -351,23 +419,74 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
       return std::string();
       }
 
+    assert(target);
+
     cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
                                                target->GetName(),
                                                propertyName,
                                                content,
                                                dagCheckerParent);
 
-    if (!dagChecker.check())
+    switch (dagChecker.check())
       {
+    case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
       dagChecker.reportError(context, content->GetOriginalExpression());
       return std::string();
+    case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+      // No error. We just skip cyclic references.
+      return std::string();
+    case cmGeneratorExpressionDAGChecker::DAG:
+      break;
       }
 
     const char *prop = target->GetProperty(propertyName.c_str());
-    return prop ? prop : "";
+    if (!prop)
+      {
+      return std::string();
+      }
+
+    for (size_t i = 0;
+         i < (sizeof(targetPropertyTransitiveWhitelist) /
+              sizeof(*targetPropertyTransitiveWhitelist));
+         ++i)
+      {
+      if (targetPropertyTransitiveWhitelist[i] == propertyName)
+        {
+        cmGeneratorExpression ge(context->Backtrace);
+        return ge.Parse(prop)->Evaluate(context->Makefile,
+                            context->Config,
+                            context->Quiet,
+                            context->HeadTarget,
+                            target,
+                            &dagChecker);
+        }
+      }
+    return prop;
   }
 } targetPropertyNode;
 
+//----------------------------------------------------------------------------
+static const struct TargetNameNode : public cmGeneratorExpressionNode
+{
+  TargetNameNode() {}
+
+  virtual bool GeneratesContent() const { return true; }
+
+  virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+  virtual bool RequiresLiteralInput() const { return true; }
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *,
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
+  {
+    return parameters.front();
+  }
+
+  virtual int NumExpectedParameters() const { return 1; }
+
+} targetNameNode;
+
 //----------------------------------------------------------------------------
 template<bool linker, bool soname>
 struct TargetFilesystemArtifactResultCreator
@@ -553,13 +672,13 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
 {
   if (identifier == "0")
     return &zeroNode;
-  if (identifier == "1")
+  else if (identifier == "1")
     return &oneNode;
-  if (identifier == "AND")
+  else if (identifier == "AND")
     return &andNode;
-  if (identifier == "OR")
+  else if (identifier == "OR")
     return &orNode;
-  if (identifier == "NOT")
+  else if (identifier == "NOT")
     return &notNode;
   else if (identifier == "CONFIGURATION")
     return &configurationNode;
@@ -593,6 +712,14 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     return &commaNode;
   else if (identifier == "TARGET_PROPERTY")
     return &targetPropertyNode;
+  else if (identifier == "TARGET_NAME")
+    return &targetNameNode;
+  else if (identifier == "BUILD_INTERFACE")
+    return &buildInterfaceNode;
+  else if (identifier == "INSTALL_INTERFACE")
+    return &installInterfaceNode;
+  else if (identifier == "TARGET_DEFINED")
+    return &targetDefinedNode;
   return 0;
 
 }
@@ -682,6 +809,15 @@ std::string GeneratorExpressionContent::Evaluate(
                                                                 = pit->end();
       for ( ; it != end; ++it)
         {
+        if (node->RequiresLiteralInput())
+          {
+          if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text)
+            {
+            reportError(context, this->GetOriginalExpression(),
+                  "$<" + identifier + "> expression requires literal input.");
+            return std::string();
+            }
+          }
         result += (*it)->Evaluate(context, dagChecker);
         if (context->HadError)
           {
@@ -689,6 +825,12 @@ std::string GeneratorExpressionContent::Evaluate(
           }
         }
       }
+    if (node->RequiresLiteralInput())
+      {
+      std::vector<std::string> parameters;
+      parameters.push_back(result);
+      return node->Evaluate(parameters, context, this, dagChecker);
+      }
     return result;
     }
 

+ 4 - 1
Source/cmGeneratorExpressionEvaluator.h

@@ -24,9 +24,12 @@ struct cmGeneratorExpressionContext
 {
   cmListFileBacktrace Backtrace;
   std::set<cmTarget*> Targets;
+  std::set<cmStdString> SeenTargetProperties;
   cmMakefile *Makefile;
   const char *Config;
-  cmTarget *Target;
+  cmTarget *HeadTarget; // The target whose property is being evaluated.
+  cmTarget *CurrentTarget; // The dependent of HeadTarget which appears
+                           // directly or indirectly in the property.
   bool Quiet;
   bool HadError;
 };

+ 2 - 40
Source/cmGeneratorTarget.cxx

@@ -252,45 +252,7 @@ const char* cmGeneratorTarget::GetCreateRuleVariable()
 std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
                                                           const char *config)
 {
-  std::vector<std::string> includes;
-  const char *prop = this->Target->GetProperty("INCLUDE_DIRECTORIES");
-  if(!prop)
-    {
-    return includes;
-    }
-
-  cmListFileBacktrace lfbt;
-  cmGeneratorExpression ge(lfbt);
-
-  cmGeneratorExpressionDAGChecker dagChecker(lfbt,
-                                              this->GetName(),
-                                              "INCLUDE_DIRECTORIES", 0, 0);
-
-  cmSystemTools::ExpandListArgument(ge.Parse(prop)
-                                    .Evaluate(this->Makefile,
-                                              config,
-                                              false,
-                                              this->Target,
-                                              &dagChecker),
-                                    includes);
-
-  std::set<std::string> uniqueIncludes;
-  std::vector<std::string> orderedAndUniqueIncludes;
-  for(std::vector<std::string>::const_iterator
-      li = includes.begin(); li != includes.end(); ++li)
-    {
-    std::string inc = *li;
-    if (!cmSystemTools::IsOff(inc.c_str()))
-      {
-      cmSystemTools::ConvertToUnixSlashes(inc);
-      }
-    if(uniqueIncludes.insert(inc).second)
-      {
-      orderedAndUniqueIncludes.push_back(inc);
-      }
-    }
-
-  return orderedAndUniqueIncludes;
+  return this->Target->GetIncludeDirectories(config);
 }
 
 //----------------------------------------------------------------------------
@@ -315,7 +277,7 @@ std::string cmGeneratorTarget::GetCompileDefinitions(const char *config)
   cmGeneratorExpressionDAGChecker dagChecker(lfbt,
                                              this->GetName(),
                                              defPropName, 0, 0);
-  return ge.Parse(prop).Evaluate(this->Makefile,
+  return ge.Parse(prop)->Evaluate(this->Makefile,
                                  config,
                                  false,
                                  this->Target,

+ 5 - 0
Source/cmGlobalGenerator.cxx

@@ -938,6 +938,11 @@ void cmGlobalGenerator::Generate()
       (*targets)[tit->first] = tit->second;
       (*targets)[tit->first].SetMakefile(mf);
       }
+
+    for ( tit = targets->begin(); tit != targets->end(); ++ tit )
+      {
+        tit->second.AppendBuildInterfaceIncludes();
+      }
     }
 
   // Add generator specific helper commands

+ 26 - 33
Source/cmGlobalXCodeGenerator.cxx

@@ -1206,7 +1206,7 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget)
 
   // If the language is compiled as a source trust Xcode to link with it.
   cmTarget::LinkImplementation const* impl =
-    cmtarget.GetLinkImplementation("NOCONFIG");
+    cmtarget.GetLinkImplementation("NOCONFIG", &cmtarget);
   for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
       li != impl->Languages.end(); ++li)
     {
@@ -1367,16 +1367,18 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
 }
 
 //----------------------------------------------------------------------------
-// This function removes each occurence of the flag and returns the last one
+// This function removes each occurrence of the flag and returns the last one
 // (i.e., the dominant flag in GCC)
 std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
                                                 std::string& flags)
 {
   std::string retFlag;
-  std::string::size_type pos = flags.rfind(flag);
+  std::string::size_type lastOccurancePos = flags.rfind(flag);
   bool saved = false;
-  while(pos != flags.npos)
+  while(lastOccurancePos != flags.npos)
     {
+    //increment pos, we use lastOccurancePos to reduce search space on next inc
+    std::string::size_type pos = lastOccurancePos;
     if(pos == 0 || flags[pos-1]==' ')
       {
       while(pos < flags.size() && flags[pos] != ' ')
@@ -1388,9 +1390,12 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
         flags[pos] = ' ';
         pos++;
         }
-      }
       saved = true;
-      pos = flags.rfind(flag);
+      }
+    //decrement lastOccurancePos while making sure we don't loop around
+    //and become a very large positive number since size_type is unsigned
+    lastOccurancePos = lastOccurancePos == 0 ? 0 : lastOccurancePos-1;
+    lastOccurancePos = flags.rfind(flag,lastOccurancePos);
     }
   return retFlag;
 }
@@ -1639,14 +1644,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
     if(strcmp(lang, "CXX") == 0)
       {
       this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName);
-      this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, "C");
+      this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target,
+                                                   "C", configName);
       }
 
     // Add language-specific flags.
     this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName);
 
     // Add shared-library flags if needed.
-    this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, lang);
+    this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target,
+                                                 lang, configName);
     }
   else if(binary)
   {
@@ -1997,15 +2004,20 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
       dirs.Add(incpath.c_str());
       }
     }
-  std::vector<std::string>& frameworks = target.GetFrameworks();
-  if(frameworks.size())
+  if(target.GetType() != cmTarget::OBJECT_LIBRARY &&
+     target.GetType() != cmTarget::STATIC_LIBRARY)
     {
-    for(std::vector<std::string>::iterator fmIt = frameworks.begin();
-        fmIt != frameworks.end(); ++fmIt)
+    // Add framework search paths needed for linking.
+    if(cmComputeLinkInformation* cli = target.GetLinkInformation(configName))
       {
-      if(emitted.insert(*fmIt).second)
+      std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths();
+      for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
+          fdi != fwDirs.end(); ++fdi)
         {
-        fdirs.Add(this->XCodeEscapePath(fmIt->c_str()).c_str());
+        if(emitted.insert(*fdi).second)
+          {
+          fdirs.Add(this->XCodeEscapePath(fdi->c_str()).c_str());
+          }
         }
       }
     }
@@ -2691,25 +2703,6 @@ void cmGlobalXCodeGenerator
                                       linkDirs.c_str(), configName);
     }
 
-    // add the framework search paths
-    {
-    const char* sep = "";
-    std::string fdirs;
-    std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
-    for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
-        fdi != fwDirs.end(); ++fdi)
-      {
-      fdirs += sep;
-      sep = " ";
-      fdirs += this->XCodeEscapePath(fdi->c_str());
-      }
-    if(!fdirs.empty())
-      {
-      this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
-                                        fdirs.c_str(), configName);
-      }
-    }
-
     // now add the link libraries
     {
     std::string linkLibs;

+ 0 - 4
Source/cmLoadCommandCommand.cxx

@@ -224,10 +224,6 @@ cmLoadedCommand::~cmLoadedCommand()
 bool cmLoadCommandCommand
 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
 {
-  this->Makefile->IssueMessage(
-    cmake::AUTHOR_WARNING,
-    "The \"load_command\" command will be removed in CMake 3.0.  "
-    "See command documentation for details.");
   if(args.size() < 1 )
     {
     return true;

+ 1 - 14
Source/cmLoadCommandCommand.h

@@ -47,7 +47,7 @@ public:
    */
   virtual const char* GetTerseDocumentation() const
     {
-    return "Deprecated.  Use macro() or function() instead.";
+    return "Load a command into a running CMake.";
     }
 
   /**
@@ -56,13 +56,6 @@ public:
   virtual const char* GetFullDocumentation() const
     {
     return
-      "This command will be removed in CMake 3.0.  "
-      "It works only when the target architecture matches the "
-      "running CMake binary.  "
-      "Use macro() or function() to add commands.  "
-      "Use execute_process() to run advanced computations "
-      "in external processes."
-      "\n"
       "  load_command(COMMAND_NAME <loc1> [loc2 ...])\n"
       "The given locations are searched for a library whose name is "
       "cmCOMMAND_NAME.  If found, it is loaded as a module and the command "
@@ -74,12 +67,6 @@ public:
       "Otherwise the variable will not be set.";
     }
 
-  /** This command is kept for compatibility with older CMake versions. */
-  virtual bool IsDiscouraged() const
-    {
-    return true;
-    }
-
   cmTypeMacro(cmLoadCommandCommand, cmCommand);
 };
 

+ 31 - 15
Source/cmLocalGenerator.cxx

@@ -1329,7 +1329,9 @@ std::string cmLocalGenerator::GetIncludeFlags(
 void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
                                              cmGeneratorTarget* target,
                                              const char* lang,
-                                             const char *config)
+                                             const char *config,
+                                             bool stripImplicitInclDirs
+                                            )
 {
   // Need to decide whether to automatically include the source and
   // binary directories at the beginning of the include path.
@@ -1404,18 +1406,21 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
     return;
     }
 
-  // Load implicit include directories for this language.
-  std::string impDirVar = "CMAKE_";
-  impDirVar += lang;
-  impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES";
-  if(const char* value = this->Makefile->GetDefinition(impDirVar.c_str()))
+  if (stripImplicitInclDirs)
     {
-    std::vector<std::string> impDirVec;
-    cmSystemTools::ExpandListArgument(value, impDirVec);
-    for(std::vector<std::string>::const_iterator i = impDirVec.begin();
-        i != impDirVec.end(); ++i)
+    // Load implicit include directories for this language.
+    std::string impDirVar = "CMAKE_";
+    impDirVar += lang;
+    impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES";
+    if(const char* value = this->Makefile->GetDefinition(impDirVar.c_str()))
       {
-      emitted.insert(*i);
+      std::vector<std::string> impDirVec;
+      cmSystemTools::ExpandListArgument(value, impDirVec);
+      for(std::vector<std::string>::const_iterator i = impDirVec.begin();
+          i != impDirVec.end(); ++i)
+        {
+        emitted.insert(*i);
+        }
       }
     }
 
@@ -1703,7 +1708,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
   for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
       fdi != fwDirs.end(); ++fdi)
     {
-    frameworkPath = " -F";
+    frameworkPath += "-F";
     frameworkPath += this->Convert(fdi->c_str(), NONE, SHELL, false);
     frameworkPath += " ";
     }
@@ -1979,7 +1984,8 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
 
 //----------------------------------------------------------------------------
 void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
-                                       std::string const& lang)
+                                       std::string const& lang,
+                                       const char *config)
 {
   int targetType = target->GetType();
 
@@ -1992,8 +1998,18 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
     }
   else
     {
-    // Add position independendent flags, if needed.
-    if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE"))
+    if (target->GetType() == cmTarget::OBJECT_LIBRARY)
+    {
+      if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE"))
+        {
+        this->AddPositionIndependentFlags(flags, lang, targetType);
+        }
+      return;
+    }
+
+    if (target->GetLinkInterfaceDependentBoolProperty(
+                                                "POSITION_INDEPENDENT_CODE",
+                                                config))
       {
       this->AddPositionIndependentFlags(flags, lang, targetType);
       }

+ 3 - 2
Source/cmLocalGenerator.h

@@ -142,7 +142,7 @@ public:
   void AddLanguageFlags(std::string& flags, const char* lang,
                         const char* config);
   void AddCMP0018Flags(std::string &flags, cmTarget* target,
-                       std::string const& lang);
+                       std::string const& lang, const char *config);
   void AddConfigVariableFlags(std::string& flags, const char* var,
                               const char* config);
   ///! Append flags to a string.
@@ -212,7 +212,8 @@ public:
   /** Get the include flags for the current makefile and language.  */
   void GetIncludeDirectories(std::vector<std::string>& dirs,
                              cmGeneratorTarget* target,
-                             const char* lang = "C", const char *config = 0);
+                             const char* lang = "C", const char *config = 0,
+                             bool stripImplicitInclDirs = true);
 
   /** Compute the language used to compile the given source file.  */
   const char* GetSourceFileLanguage(const cmSourceFile& source);

+ 109 - 56
Source/cmMakefile.cxx

@@ -814,7 +814,7 @@ bool cmMakefile::NeedBackwardsCompatibility(unsigned int major,
 void cmMakefile::FinalPass()
 {
   // do all the variable expansions here
-  this->ExpandVariables();
+  this->ExpandVariablesCMP0019();
 
   // give all the commands a chance to do something
   // after the file has been parsed before generation
@@ -1485,9 +1485,12 @@ void cmMakefile::InitializeFromParent()
   // Initialize definitions with the closure of the parent scope.
   this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure();
 
-  // copy include paths
-  this->SetProperty("INCLUDE_DIRECTORIES",
-                    parent->GetProperty("INCLUDE_DIRECTORIES"));
+  const std::vector<IncludeDirectoriesEntry> parentIncludes =
+                                        parent->GetIncludeDirectoriesEntries();
+  this->IncludeDirectoriesEntries.insert(this->IncludeDirectoriesEntries.end(),
+                                       parentIncludes.begin(),
+                                       parentIncludes.end());
+
   this->SystemIncludeDirectories = parent->SystemIncludeDirectories;
 
   // define flags
@@ -1612,41 +1615,6 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath,
     }
 }
 
-//----------------------------------------------------------------------------
-void AddStringToProperty(cmProperty *prop, const char* name, const char* s,
-                         bool before)
-{
-  if (!prop)
-    {
-    return;
-    }
-
-  // Don't worry about duplicates at this point. We eliminate them when
-  // we convert the property to a vector in GetIncludeDirectories.
-
-  if (before)
-    {
-    const char *val = prop->GetValue();
-    cmOStringStream oss;
-
-    if(val && *val)
-      {
-      oss << s << ";" << val;
-      }
-    else
-      {
-      oss << s;
-      }
-
-    std::string newVal = oss.str();
-    prop->Set(name, newVal.c_str());
-    }
-  else
-    {
-    prop->Append(name, s);
-    }
-}
-
 //----------------------------------------------------------------------------
 void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
 {
@@ -1655,18 +1623,21 @@ void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
     return;
     }
 
-  // Directory property:
-  cmProperty *prop =
-    this->GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES");
-  AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before);
+  std::vector<IncludeDirectoriesEntry>::iterator position =
+                               before ? this->IncludeDirectoriesEntries.begin()
+                                      : this->IncludeDirectoriesEntries.end();
+
+  cmListFileBacktrace lfbt;
+  this->GetBacktrace(lfbt);
+  IncludeDirectoriesEntry entry(inc, lfbt);
+  this->IncludeDirectoriesEntries.insert(position, entry);
 
   // Property on each target:
   for (cmTargets::iterator l = this->Targets.begin();
        l != this->Targets.end(); ++l)
     {
     cmTarget &t = l->second;
-    prop = t.GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES");
-    AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before);
+    t.InsertInclude(entry, before);
     }
 }
 
@@ -2122,21 +2093,33 @@ void cmMakefile::AddExtraDirectory(const char* dir)
   this->AuxSourceDirectories.push_back(dir);
 }
 
+static bool mightExpandVariablesCMP0019(const char* s)
+{
+  return s && *s && strstr(s,"${") && strchr(s,'}');
+}
 
-// expand CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the
-// include and library directories.
-
-void cmMakefile::ExpandVariables()
+void cmMakefile::ExpandVariablesCMP0019()
 {
-  // Now expand variables in the include and link strings
+  // Drop this ancient compatibility behavior with a policy.
+  cmPolicies::PolicyStatus pol = this->GetPolicyStatus(cmPolicies::CMP0019);
+  if(pol != cmPolicies::OLD && pol != cmPolicies::WARN)
+    {
+    return;
+    }
+  cmOStringStream w;
 
-  // May not be necessary anymore... But may need a policy for strict
-  // backwards compatibility
   const char *includeDirs = this->GetProperty("INCLUDE_DIRECTORIES");
-  if (includeDirs)
+  if(mightExpandVariablesCMP0019(includeDirs))
     {
     std::string dirs = includeDirs;
     this->ExpandVariablesInString(dirs, true, true);
+    if(pol == cmPolicies::WARN && dirs != includeDirs)
+      {
+      w << "Evaluated directory INCLUDE_DIRECTORIES\n"
+        << "  " << includeDirs << "\n"
+        << "as\n"
+        << "  " << dirs << "\n";
+      }
     this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
     }
 
@@ -2146,10 +2129,17 @@ void cmMakefile::ExpandVariables()
     {
     cmTarget &t = l->second;
     includeDirs = t.GetProperty("INCLUDE_DIRECTORIES");
-    if (includeDirs)
+    if(mightExpandVariablesCMP0019(includeDirs))
       {
       std::string dirs = includeDirs;
       this->ExpandVariablesInString(dirs, true, true);
+      if(pol == cmPolicies::WARN && dirs != includeDirs)
+        {
+        w << "Evaluated target " << t.GetName() << " INCLUDE_DIRECTORIES\n"
+          << "  " << includeDirs << "\n"
+          << "as\n"
+          << "  " << dirs << "\n";
+        }
       t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
       }
     }
@@ -2157,13 +2147,45 @@ void cmMakefile::ExpandVariables()
   for(std::vector<std::string>::iterator d = this->LinkDirectories.begin();
       d != this->LinkDirectories.end(); ++d)
     {
-    this->ExpandVariablesInString(*d, true, true);
+    if(mightExpandVariablesCMP0019(d->c_str()))
+      {
+      std::string orig = *d;
+      this->ExpandVariablesInString(*d, true, true);
+      if(pol == cmPolicies::WARN && *d != orig)
+        {
+        w << "Evaluated link directory\n"
+          << "  " << orig << "\n"
+          << "as\n"
+          << "  " << *d << "\n";
+        }
+      }
     }
   for(cmTarget::LinkLibraryVectorType::iterator l =
         this->LinkLibraries.begin();
       l != this->LinkLibraries.end(); ++l)
     {
-    this->ExpandVariablesInString(l->first, true, true);
+    if(mightExpandVariablesCMP0019(l->first.c_str()))
+      {
+      std::string orig = l->first;
+      this->ExpandVariablesInString(l->first, true, true);
+      if(pol == cmPolicies::WARN && l->first != orig)
+        {
+        w << "Evaluated link library\n"
+          << "  " << orig << "\n"
+          << "as\n"
+          << "  " << l->first << "\n";
+        }
+      }
+    }
+
+  if(!w.str().empty())
+    {
+    cmOStringStream m;
+    m << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0019)
+      << "\n"
+      << "The following variable evaluations were encountered:\n"
+      << w.str();
+    this->IssueMessage(cmake::AUTHOR_WARNING, m.str());
     }
 }
 
@@ -3400,6 +3422,15 @@ void cmMakefile::SetProperty(const char* prop, const char* value)
     this->SetLinkDirectories(varArgsExpanded);
     return;
     }
+  if (propname == "INCLUDE_DIRECTORIES")
+    {
+    this->IncludeDirectoriesEntries.clear();
+    cmListFileBacktrace lfbt;
+    this->GetBacktrace(lfbt);
+    this->IncludeDirectoriesEntries.push_back(
+                                        IncludeDirectoriesEntry(value, lfbt));
+    return;
+    }
 
   if ( propname == "INCLUDE_REGULAR_EXPRESSION" )
     {
@@ -3431,6 +3462,14 @@ void cmMakefile::AppendProperty(const char* prop, const char* value,
   // handle special props
   std::string propname = prop;
 
+  if (propname == "INCLUDE_DIRECTORIES")
+    {
+    cmListFileBacktrace lfbt;
+    this->GetBacktrace(lfbt);
+    this->IncludeDirectoriesEntries.push_back(
+                                        IncludeDirectoriesEntry(value, lfbt));
+    return;
+    }
   if ( propname == "LINK_DIRECTORIES" )
     {
     std::vector<std::string> varArgsExpanded;
@@ -3542,6 +3581,20 @@ const char *cmMakefile::GetProperty(const char* prop,
     output = str.str();
     return output.c_str();
     }
+  else if (!strcmp("INCLUDE_DIRECTORIES",prop))
+    {
+    std::string sep;
+    for (std::vector<IncludeDirectoriesEntry>::const_iterator
+        it = this->IncludeDirectoriesEntries.begin(),
+        end = this->IncludeDirectoriesEntries.end();
+        it != end; ++it)
+      {
+      output += sep;
+      output += it->Value;
+      sep = ";";
+      }
+    return output.c_str();
+    }
 
   bool chain = false;
   const char *retVal =

+ 11 - 1
Source/cmMakefile.h

@@ -22,6 +22,7 @@
 #include "cmNewLineStyle.h"
 #include "cmGeneratorTarget.h"
 #include "cmake.h"
+#include "cmMakefileIncludeDirectoriesEntry.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmSourceGroup.h"
@@ -693,7 +694,7 @@ public:
   /**
    * Expand variables in the makefiles ivars such as link directories etc
    */
-  void ExpandVariables();
+  void ExpandVariablesCMP0019();
 
   /**
    * Replace variables and #cmakedefine lines in the given string.
@@ -861,6 +862,13 @@ public:
   /** Set whether or not to report a CMP0000 violation.  */
   void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }
 
+  typedef cmMakefileIncludeDirectoriesEntry IncludeDirectoriesEntry;
+
+  std::vector<IncludeDirectoriesEntry> GetIncludeDirectoriesEntries() const
+  {
+    return this->IncludeDirectoriesEntries;
+  }
+
 protected:
   // add link libraries and directories to the target
   void AddGlobalLinkInformation(const char* name, cmTarget& target);
@@ -909,6 +917,8 @@ protected:
   std::vector<std::string> HeaderFileExtensions;
   std::string DefineFlags;
 
+  std::vector<IncludeDirectoriesEntry> IncludeDirectoriesEntries;
+
   // Track the value of the computed DEFINITIONS property.
   void AddDefineFlag(const char*, std::string&);
   void RemoveDefineFlag(const char*, std::string::size_type, std::string&);

+ 28 - 0
Source/cmMakefileIncludeDirectoriesEntry.h

@@ -0,0 +1,28 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2012 Stephen Kelly <[email protected]>
+
+  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 cmMakefileIncludeDirectoriesEntry_h
+#define cmMakefileIncludeDirectoriesEntry_h
+
+#include <string>
+#include "cmListFileCache.h"
+
+struct cmMakefileIncludeDirectoriesEntry {
+  cmMakefileIncludeDirectoriesEntry(const std::string &value,
+                          const cmListFileBacktrace &bt)
+    : Value(value), Backtrace(bt)
+  {}
+  std::string Value;
+  cmListFileBacktrace Backtrace;
+};
+
+#endif

+ 17 - 12
Source/cmMakefileTargetGenerator.cxx

@@ -268,7 +268,8 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l)
       this->AddFortranFlags(flags);
       }
 
-    this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang);
+    this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
+                                          lang, this->ConfigName);
 
     // Add include directory flags.
     this->AddIncludeFlags(flags, lang);
@@ -1550,10 +1551,10 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags()
   this->LocalGenerator->GetIncludeDirectories(includes,
                                               this->GeneratorTarget,
                                               "C", config);
-  std::vector<std::string>::iterator i;
   // check all include directories for frameworks as this
   // will already have added a -F for the framework
-  for(i = includes.begin(); i != includes.end(); ++i)
+  for(std::vector<std::string>::iterator i = includes.begin();
+      i != includes.end(); ++i)
     {
     if(this->Target->NameResolvesToFramework(i->c_str()))
       {
@@ -1565,17 +1566,21 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags()
     }
 
   std::string flags;
-  std::vector<std::string>& frameworks = this->Target->GetFrameworks();
-  for(i = frameworks.begin();
-      i != frameworks.end(); ++i)
+  const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
+  if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
     {
-    if(emitted.insert(*i).second)
+    std::vector<std::string> const& frameworks = cli->GetFrameworkPaths();
+    for(std::vector<std::string>::const_iterator i = frameworks.begin();
+        i != frameworks.end(); ++i)
       {
-      flags += "-F";
-      flags += this->Convert(i->c_str(),
-                             cmLocalGenerator::START_OUTPUT,
-                             cmLocalGenerator::SHELL, true);
-      flags += " ";
+      if(emitted.insert(*i).second)
+        {
+        flags += "-F";
+        flags += this->Convert(i->c_str(),
+                               cmLocalGenerator::START_OUTPUT,
+                               cmLocalGenerator::SHELL, true);
+        flags += " ";
+        }
       }
     }
   return flags;

+ 2 - 1
Source/cmNinjaTargetGenerator.cxx

@@ -147,7 +147,8 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
 
   // Add shared-library flags if needed.
   this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
-                                        language.c_str());
+                                        language.c_str(),
+                                        this->GetConfigName());
 
   // Add include directory flags.
   {

+ 17 - 0
Source/cmPolicies.cxx

@@ -491,6 +491,23 @@ cmPolicies::cmPolicies()
     "CMAKE_SHARED_LIBRARY_<Lang>_FLAGS whether it is modified or not and "
     "honor the POSITION_INDEPENDENT_CODE target property.",
     2,8,9,0, cmPolicies::WARN);
+
+  this->DefinePolicy(
+    CMP0019, "CMP0019",
+    "Do not re-expand variables in include and link information.",
+    "CMake 2.8.10 and lower re-evaluated values given to the "
+    "include_directories, link_directories, and link_libraries "
+    "commands to expand any leftover variable references at the "
+    "end of the configuration step.  "
+    "This was for strict compatibility with VERY early CMake versions "
+    "because all variable references are now normally evaluated during "
+    "CMake language processing.  "
+    "CMake 2.8.11 and higher prefer to skip the extra evaluation."
+    "\n"
+    "The OLD behavior for this policy is to re-evaluate the values "
+    "for strict compatibility.  "
+    "The NEW behavior for this policy is to leave the values untouched.",
+    2,8,11,0, cmPolicies::WARN);
 }
 
 cmPolicies::~cmPolicies()

+ 1 - 0
Source/cmPolicies.h

@@ -68,6 +68,7 @@ public:
     CMP0018, ///< Ignore language flags for shared libs, and adhere to
     /// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
     /// instead.
+    CMP0019, ///< No variable re-expansion in include and link info
 
     /** \brief Always the last entry.
      *

+ 3 - 59
Source/cmQtAutomoc.cxx

@@ -212,36 +212,11 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
     }
 
 
-  const char* qtIncDir = 0;
-  const char* qtCoreIncDir = 0;
-
-  // check whether ${QT_INCLUDE_DIR} is part of the implicit include dirs,
-  // see http://public.kitware.com/Bug/view.php?id=13667
-  bool qtIncludeDirMayHaveBeenRemoved = false;
-  if (makefile->IsSet("QT_INCLUDE_DIR"))
-    {
-    qtIncDir = makefile->GetDefinition("QT_INCLUDE_DIR");
-    std::string s =
-         makefile->GetSafeDefinition("CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES");
-    std::vector<std::string> implIncDirs;
-    cmSystemTools::ExpandListArgument(s, implIncDirs);
-    if (std::find(implIncDirs.begin(), implIncDirs.end(),std::string(qtIncDir))
-                                                          != implIncDirs.end())
-      {
-      qtIncludeDirMayHaveBeenRemoved = true;
-      if (makefile->IsSet("QT_QTCORE_INCLUDE_DIR"))
-        {
-        qtCoreIncDir = makefile->GetDefinition("QT_QTCORE_INCLUDE_DIR");
-        }
-      }
-    }
-
-  bool haveQtCoreIncDir = false;
-  bool haveQtIncDir = false;
-
   std::vector<std::string> includeDirs;
   cmGeneratorTarget gtgt(target);
-  localGen->GetIncludeDirectories(includeDirs, &gtgt, "CXX");
+  // Get the include dirs for this target, without stripping the implicit
+  // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667
+  localGen->GetIncludeDirectories(includeDirs, &gtgt, "CXX", 0, false);
   std::string _moc_incs = "";
   const char* sep = "";
   for(std::vector<std::string>::const_iterator incDirIt = includeDirs.begin();
@@ -251,37 +226,6 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
     _moc_incs += sep;
     sep = ";";
     _moc_incs += *incDirIt;
-
-    if (qtIncludeDirMayHaveBeenRemoved && qtCoreIncDir && qtIncDir) // #13667
-      {
-      if (*incDirIt == qtIncDir)
-        {
-        haveQtIncDir = true;
-        qtIncludeDirMayHaveBeenRemoved = false; // it's here, i.e. not removed
-        }
-      if (*incDirIt == qtCoreIncDir)
-        {
-        haveQtCoreIncDir = true;
-        }
-      }
-    }
-
-  // Some projects (kdelibs, phonon) query the compiler for its default
-  // include search dirs, and add those to
-  // CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES.
-  // These may include e.g./usr/lib/qt/include . This is typically also part
-  // of ${QT_INCLUDES}. If this directory is then contained in the implicit
-  // include dirs, it is removed from the include dirs returned from the
-  // target above. So we add ${QT_INCLUDE_DIR} manually for moc if we detected
-  // that ${QT_QTCORE_INCLUDE_DIR} is among the include dirs (there shouldn't
-  // be a way to use Qt4 without using ${QT_QTCORE_INCLUDE_DIR} I think.
-  // See #13646 and #13667.
-  if (qtIncludeDirMayHaveBeenRemoved && qtCoreIncDir && qtIncDir
-      && (haveQtCoreIncDir == true) && (haveQtIncDir == false))
-    {
-    _moc_incs += sep;
-    sep = ";";
-    _moc_incs += qtIncDir;
     }
 
   const char* tmp = target->GetProperty("COMPILE_DEFINITIONS");

+ 54 - 0
Source/cmStringCommand.cxx

@@ -19,6 +19,8 @@
 #include <ctype.h>
 #include <time.h>
 
+#include <cmTimestamp.h>
+
 //----------------------------------------------------------------------------
 bool cmStringCommand
 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
@@ -87,6 +89,10 @@ bool cmStringCommand
     {
     return this->HandleFindCommand(args);
     }
+  else if(subCommand == "TIMESTAMP")
+    {
+    return this->HandleTimestampCommand(args);
+    }
 
   std::string e = "does not recognize sub-command "+subCommand;
   this->SetError(e.c_str());
@@ -879,3 +885,51 @@ bool cmStringCommand
   this->Makefile->AddDefinition(variableName.c_str(), &*result.begin());
   return true;
 }
+
+//----------------------------------------------------------------------------
+bool cmStringCommand
+::HandleTimestampCommand(std::vector<std::string> const& args)
+{
+  if(args.size() < 2)
+    {
+    this->SetError("sub-command TIMESTAMP requires at least one argument.");
+    return false;
+    }
+  else if(args.size() > 4)
+    {
+    this->SetError("sub-command TIMESTAMP takes at most three arguments.");
+    return false;
+    }
+
+  unsigned int argsIndex = 1;
+
+  const std::string &outputVariable = args[argsIndex++];
+
+  std::string formatString;
+  if(args.size() > argsIndex && args[argsIndex] != "UTC")
+    {
+    formatString = args[argsIndex++];
+    }
+
+  bool utcFlag = false;
+  if(args.size() > argsIndex)
+    {
+    if(args[argsIndex] == "UTC")
+      {
+      utcFlag = true;
+      }
+    else
+      {
+      std::string e = " TIMESTAMP sub-command does not recognize option " +
+          args[argsIndex] + ".";
+      this->SetError(e.c_str());
+      return false;
+      }
+    }
+
+  cmTimestamp timestamp;
+  std::string result = timestamp.CurrentTime(formatString, utcFlag);
+  this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str());
+
+  return true;
+}

+ 29 - 1
Source/cmStringCommand.h

@@ -93,6 +93,7 @@ public:
       "  string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>]\n"
       "         [RANDOM_SEED <seed>] <output variable>)\n"
       "  string(FIND <string> <substring> <output variable> [REVERSE])\n"
+      "  string(TIMESTAMP <output variable> [<format string>] [UTC])\n"
       "REGEX MATCH will match the regular expression once and store the "
       "match in the output variable.\n"
       "REGEX MATCHALL will match the regular expression as many times as "
@@ -142,7 +143,33 @@ public:
       "   ()        Saves a matched subexpression, which can be referenced \n"
       "             in the REGEX REPLACE operation. Additionally it is saved\n"
       "             by all regular expression-related commands, including \n"
-      "             e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).";
+      "             e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).\n"
+      "TIMESTAMP will write a string representation of "
+      "the current date and/or time to the output variable.\n"
+      "Should the command be unable to obtain a timestamp "
+      "the output variable will be set to the empty string \"\".\n"
+      "The optional UTC flag requests the current date/time "
+      "representation to be in Coordinated Universal Time (UTC) "
+      "rather than local time.\n"
+      "The optional <format string> may contain the following "
+      "format specifiers: \n"
+      "   %d        The day of the current month (01-31).\n"
+      "   %H        The hour on a 24-hour clock (00-23).\n"
+      "   %I        The hour on a 12-hour clock (01-12).\n"
+      "   %j        The day of the current year (001-366).\n"
+      "   %m        The month of the current year (01-12).\n"
+      "   %M        The minute of the current hour (00-59).\n"
+      "   %S        The second of the current minute.\n"
+      "             60 represents a leap second. (00-60)\n"
+      "   %U        The week number of the current year (00-53).\n"
+      "   %w        The day of the current week. 0 is Sunday. (0-6)\n"
+      "   %y        The last two digits of the current year (00-99)\n"
+      "   %Y        The current year. \n"
+      "Unknown format specifiers will be ignored "
+      "and copied to the output as-is.\n"
+      "If no explicit <format string> is given it will default to:\n"
+      "   %Y-%m-%dT%H:%M:%S    for local time.\n"
+      "   %Y-%m-%dT%H:%M:%SZ   for UTC.";
     }
 
   cmTypeMacro(cmStringCommand, cmCommand);
@@ -165,6 +192,7 @@ protected:
   bool HandleStripCommand(std::vector<std::string> const& args);
   bool HandleRandomCommand(std::vector<std::string> const& args);
   bool HandleFindCommand(std::vector<std::string> const& args);
+  bool HandleTimestampCommand(std::vector<std::string> const& args);
 
   class RegexReplacement
   {

File diff suppressed because it is too large
+ 585 - 81
Source/cmTarget.cxx


+ 56 - 18
Source/cmTarget.h

@@ -15,6 +15,7 @@
 #include "cmCustomCommand.h"
 #include "cmPropertyMap.h"
 #include "cmPolicies.h"
+#include "cmMakefileIncludeDirectoriesEntry.h"
 
 #include <cmsys/auto_ptr.hxx>
 
@@ -24,11 +25,13 @@ class cmSourceFile;
 class cmGlobalGenerator;
 class cmComputeLinkInformation;
 class cmListFileBacktrace;
+class cmTarget;
 
 struct cmTargetLinkInformationMap:
-  public std::map<cmStdString, cmComputeLinkInformation*>
+  public std::map<std::pair<cmTarget*, std::string>, cmComputeLinkInformation*>
 {
-  typedef std::map<cmStdString, cmComputeLinkInformation*> derived;
+  typedef std::map<std::pair<cmTarget*, std::string>,
+                   cmComputeLinkInformation*> derived;
   cmTargetLinkInformationMap() {}
   cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r);
   ~cmTargetLinkInformationMap();
@@ -109,9 +112,6 @@ public:
   std::vector<cmCustomCommand> &GetPostBuildCommands()
     {return this->PostBuildCommands;}
 
-  ///! Return the list of frameworks being linked to this target
-  std::vector<std::string> &GetFrameworks() {return this->Frameworks;}
-
   /**
    * Get the list of the source files used by this target
    */
@@ -168,6 +168,9 @@ public:
   return this->LinkLibraries;}
   const LinkLibraryVectorType &GetOriginalLinkLibraries() const
     {return this->OriginalLinkLibraries;}
+  void GetDirectLinkLibraries(const char *config,
+                              std::vector<std::string> &,
+                              cmTarget *head);
 
   /** Compute the link type to use for the given configuration.  */
   LinkLibraryType ComputeLinkType(const char* config);
@@ -179,7 +182,6 @@ public:
 
   // Check to see if a library is a framework and treat it different on Mac
   bool NameResolvesToFramework(const std::string& libname);
-  bool AddFramework(const std::string& lib, LinkLibraryType llt);
   void AddLinkLibrary(cmMakefile& mf,
                       const char *target, const char* lib,
                       LinkLibraryType llt);
@@ -256,12 +258,15 @@ public:
     // Needed only for OLD behavior of CMP0003.
     std::vector<std::string> WrongConfigLibraries;
 
-    LinkInterface(): Multiplicity(0) {}
+    bool ImplementationIsInterface;
+
+    LinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {}
   };
 
   /** Get the link interface for the given configuration.  Returns 0
       if the target cannot be linked.  */
-  LinkInterface const* GetLinkInterface(const char* config);
+  LinkInterface const* GetLinkInterface(const char* config,
+                                        cmTarget *headTarget);
 
   /** The link implementation specifies the direct library
       dependencies needed by the object files of the target.  */
@@ -277,7 +282,8 @@ public:
     // Needed only for OLD behavior of CMP0003.
     std::vector<std::string> WrongConfigLibraries;
   };
-  LinkImplementation const* GetLinkImplementation(const char* config);
+  LinkImplementation const* GetLinkImplementation(const char* config,
+                                                  cmTarget *head);
 
   /** Link information from the transitive closure of the link
       implementation and the interfaces of its dependencies.  */
@@ -289,7 +295,7 @@ public:
     // Languages whose runtime libraries must be linked.
     std::vector<std::string> Languages;
   };
-  LinkClosure const* GetLinkClosure(const char* config);
+  LinkClosure const* GetLinkClosure(const char* config, cmTarget *head);
 
   /** Strip off leading and trailing whitespace from an item named in
       the link dependencies of this target.  */
@@ -334,7 +340,7 @@ public:
   bool FindSourceFiles();
 
   ///! Return the preferred linker language for this target
-  const char* GetLinkerLanguage(const char* config = 0);
+  const char* GetLinkerLanguage(const char* config = 0, cmTarget *head = 0);
 
   /** Get the full name of the target according to the settings in its
       makefile.  */
@@ -402,11 +408,17 @@ public:
   std::string GetInstallNameDirForInstallTree(const char* config,
                                               bool for_xcode = false);
 
-  cmComputeLinkInformation* GetLinkInformation(const char* config);
+  cmComputeLinkInformation* GetLinkInformation(const char* config,
+                                               cmTarget *head = 0);
 
   // Get the properties
   cmPropertyMap &GetProperties() { return this->Properties; };
 
+  bool GetMappedConfig(std::string const& desired_config,
+                       const char** loc,
+                       const char** imp,
+                       std::string& suffix);
+
   // Define the properties
   static void DefineProperties(cmake *cm);
 
@@ -474,6 +486,21 @@ public:
   /** @return the Mac framework directory without the base. */
   std::string GetFrameworkDirectory(const char* config = 0);
 
+  std::vector<std::string> GetIncludeDirectories(const char *config);
+  void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry,
+                     bool before = false);
+
+  void AppendBuildInterfaceIncludes();
+
+  void GetLinkDependentTargetsForProperty(const std::string &p,
+                                       std::set<std::string> &targets);
+  bool IsNullImpliedByLinkLibraries(const std::string &p);
+
+  void AddLinkDependentTargetsForProperties(
+          const std::map<cmStdString, cmStdString> &map);
+
+  bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
+                                             const char *config);
 private:
   /**
    * A list of direct dependencies. Use in conjunction with DependencyMap.
@@ -569,7 +596,6 @@ private:
   LinkLibraryVectorType LinkLibraries;
   LinkLibraryVectorType PrevLinkedLibraries;
   bool LinkLibrariesAnalyzed;
-  std::vector<std::string> Frameworks;
   std::vector<std::string> LinkDirectories;
   std::set<cmStdString> LinkDirectoriesEmmitted;
   bool HaveInstallRule;
@@ -584,6 +610,10 @@ private:
   bool DLLPlatform;
   bool IsApple;
   bool IsImportedTarget;
+  mutable std::map<cmStdString, std::set<std::string> >
+                                                      LinkDependentProperties;
+  mutable std::set<std::string> LinkImplicitNullProperties;
+  bool BuildInterfaceIncludesAppended;
 
   // Cache target output paths for each configuration.
   struct OutputInfo;
@@ -593,16 +623,21 @@ private:
 
   // Cache import information from properties for each configuration.
   struct ImportInfo;
-  ImportInfo const* GetImportInfo(const char* config);
-  void ComputeImportInfo(std::string const& desired_config, ImportInfo& info);
+  ImportInfo const* GetImportInfo(const char* config,
+                                        cmTarget *workingTarget);
+  void ComputeImportInfo(std::string const& desired_config, ImportInfo& info,
+                                        cmTarget *head);
 
   cmTargetLinkInformationMap LinkInformation;
+  void CheckPropertyCompatibility(cmComputeLinkInformation *info,
+                                  const char* config);
 
-  bool ComputeLinkInterface(const char* config, LinkInterface& iface);
+  bool ComputeLinkInterface(const char* config, LinkInterface& iface,
+                                        cmTarget *head);
 
   void ComputeLinkImplementation(const char* config,
-                                 LinkImplementation& impl);
-  void ComputeLinkClosure(const char* config, LinkClosure& lc);
+                                 LinkImplementation& impl, cmTarget *head);
+  void ComputeLinkClosure(const char* config, LinkClosure& lc, cmTarget *head);
 
   void ClearLinkMaps();
 
@@ -610,6 +645,9 @@ private:
 
   void ProcessSourceExpression(std::string const& expr);
 
+  std::string GetDebugGeneratorExpressions(const std::string &value,
+                                  cmTarget::LinkLibraryType llt);
+
   // The cmMakefile instance that owns this target.  This should
   // always be set.
   cmMakefile* Makefile;

+ 57 - 0
Source/cmTargetCompileDefinitionsCommand.cxx

@@ -0,0 +1,57 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <[email protected]>
+
+  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 "cmTargetCompileDefinitionsCommand.h"
+
+#include "cmMakefileIncludeDirectoriesEntry.h"
+
+bool cmTargetCompileDefinitionsCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+  return this->HandleArguments(args, "COMPILE_DEFINITIONS");
+}
+
+void cmTargetCompileDefinitionsCommand
+::HandleImportedTargetInvalidScope(const std::string &scope,
+                                   const std::string &tgt)
+{
+  cmOStringStream e;
+  e << "Cannot specify " << scope << " compile definitions for imported "
+       "target \"" << tgt << "\".  Compile definitions can only be "
+       "specified for an imported target in the INTERFACE mode.";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+void cmTargetCompileDefinitionsCommand
+::HandleMissingTarget(const std::string &name)
+{
+  cmOStringStream e;
+  e << "Cannot specify compile definitions for target \"" << name << "\" "
+       "which is not built by this project.";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+bool cmTargetCompileDefinitionsCommand
+::HandleNonTargetArg(std::string &content,
+                   const std::string &sep,
+                   const std::string &entry,
+                   const std::string &)
+{
+  content += sep + entry;
+  return true;
+}
+
+void cmTargetCompileDefinitionsCommand
+::HandleDirectContent(cmTarget *tgt, const std::string &content,
+                                   bool)
+{
+  tgt->AppendProperty("COMPILE_DEFINITIONS", content.c_str());
+}

+ 94 - 0
Source/cmTargetCompileDefinitionsCommand.h

@@ -0,0 +1,94 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <[email protected]>
+
+  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 cmTargetCompileDefinitionsCommand_h
+#define cmTargetCompileDefinitionsCommand_h
+
+#include "cmTargetPropCommandBase.h"
+
+class cmTargetCompileDefinitionsCommand : public cmTargetPropCommandBase
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone()
+    {
+    return new cmTargetCompileDefinitionsCommand;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const& args,
+                           cmExecutionStatus &status);
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() const { return "target_compile_definitions";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() const
+    {
+    return
+      "Add compile definitions to a target.";
+    }
+
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation() const
+    {
+    return
+      "  target_compile_definitions(<target> "
+      "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
+      "    [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
+      "Specify compile definitions or targets to use when compiling a given "
+      "target.  "
+      "The named <target> must have been created by a command such as "
+      "add_executable or add_library.  "
+      "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
+      "the scope of the following arguments.  PRIVATE and PUBLIC items will "
+      "populate the COMPILE_DEFINITIONS property of <target>.  PUBLIC and "
+      "INTERFACE items will populate the INTERFACE_COMPILE_DEFINITIONS "
+      "property of <target>.   "
+      "The non-scope arguments specify compile definitions or targets to use "
+      "INTERFACE_COMPILE_DEFINITIONS from.  "
+      "Repeated calls for the same <target> append items in the order called."
+      "\n"
+      "Arguments to target_compile_definitions may use \"generator "
+      "expressions\" with the syntax \"$<...>\".  "
+      CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+      ;
+    }
+
+  cmTypeMacro(cmTargetCompileDefinitionsCommand, cmCommand);
+
+private:
+  virtual void HandleImportedTargetInvalidScope(const std::string &scope,
+                                   const std::string &tgt);
+  virtual void HandleMissingTarget(const std::string &name);
+
+  virtual bool HandleNonTargetArg(std::string &content,
+                          const std::string &sep,
+                          const std::string &entry,
+                          const std::string &tgt);
+
+  virtual void HandleDirectContent(cmTarget *tgt, const std::string &content,
+                                   bool prepend);
+};
+
+#endif

+ 74 - 0
Source/cmTargetIncludeDirectoriesCommand.cxx

@@ -0,0 +1,74 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <[email protected]>
+
+  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 "cmTargetIncludeDirectoriesCommand.h"
+
+#include "cmMakefileIncludeDirectoriesEntry.h"
+
+//----------------------------------------------------------------------------
+bool cmTargetIncludeDirectoriesCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+  return this->HandleArguments(args, "INCLUDE_DIRECTORIES", PROCESS_BEFORE);
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleImportedTargetInvalidScope(const std::string &tgt,
+                                   const std::string &scope)
+{
+  cmOStringStream e;
+  e << "Cannot specify " << scope << " include directories for imported "
+       "target \"" << tgt << "\".  Include directories can only be "
+       "specified for an imported target in the INTERFACE mode.";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleMissingTarget(const std::string &name)
+{
+  cmOStringStream e;
+  e << "Cannot specify include directories for target \"" << name << "\" "
+       "which is not built by this project.";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+bool cmTargetIncludeDirectoriesCommand
+::HandleNonTargetArg(std::string &content,
+                   const std::string &sep,
+                   const std::string &entry,
+                   const std::string &tgt)
+{
+  if (!cmSystemTools::FileIsFullPath(entry.c_str()))
+    {
+    cmOStringStream e;
+    e << "Cannot specify relative include directory \"" << entry << "\" for "
+         "target \"" << tgt << "\". Only absolute paths are permitted";
+    this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+    return false;
+    }
+
+  content += sep + entry;
+  return true;
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleDirectContent(cmTarget *tgt, const std::string &content,
+                      bool prepend)
+{
+  cmListFileBacktrace lfbt;
+  this->Makefile->GetBacktrace(lfbt);
+  cmMakefileIncludeDirectoriesEntry entry(content, lfbt);
+  tgt->InsertInclude(entry, prepend);
+}

+ 98 - 0
Source/cmTargetIncludeDirectoriesCommand.h

@@ -0,0 +1,98 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <[email protected]>
+
+  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 cmTargetIncludeDirectoriesCommand_h
+#define cmTargetIncludeDirectoriesCommand_h
+
+#include "cmTargetPropCommandBase.h"
+
+//----------------------------------------------------------------------------
+class cmTargetIncludeDirectoriesCommand : public cmTargetPropCommandBase
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone()
+    {
+    return new cmTargetIncludeDirectoriesCommand;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const& args,
+                           cmExecutionStatus &status);
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() const { return "target_include_directories";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() const
+    {
+    return
+      "Add include directories to a target.";
+    }
+
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation() const
+    {
+    return
+      "  target_include_directories(<target> [BEFORE] "
+      "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
+      "    [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
+      "Specify include directories or targets to use when compiling a given "
+      "target.  "
+      "The named <target> must have been created by a command such as "
+      "add_executable or add_library.\n"
+      "If BEFORE is specified, the content will be prepended to the property "
+      "instead of being appended.\n"
+      "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
+      "the scope of the following arguments.  PRIVATE and PUBLIC items will "
+      "populate the INCLUDE_DIRECTORIES property of <target>.  PUBLIC and "
+      "INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES "
+      "property of <target>.   "
+      "The non-scope arguments specify either include directories or targets "
+      "to use INTERFACE_INCLUDE_DIRECTORIES from.  Any specified include "
+      "directories must be absolute paths, not relative paths.  "
+      "Repeated calls for the same <target> append items in the order called."
+      "\n"
+      "Arguments to target_include_directories may use \"generator "
+      "expressions\" with the syntax \"$<...>\".  "
+      CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+      ;
+    }
+
+  cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmCommand);
+
+private:
+  virtual void HandleImportedTargetInvalidScope(const std::string &tgt,
+                                   const std::string &scope);
+  virtual void HandleMissingTarget(const std::string &name);
+
+  virtual bool HandleNonTargetArg(std::string &content,
+                          const std::string &sep,
+                          const std::string &entry,
+                          const std::string &tgt);
+
+  virtual void HandleDirectContent(cmTarget *tgt, const std::string &content,
+                                   bool prepend);
+};
+
+#endif

+ 14 - 0
Source/cmTargetLinkLibrariesCommand.cxx

@@ -33,6 +33,10 @@ bool cmTargetLinkLibrariesCommand
   this->Target =
     this->Makefile->GetCMakeInstance()
     ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
+  if(!this->Target)
+    {
+    this->Target = this->Makefile->FindTargetToUse(args[0].c_str());
+    }
   if(!this->Target)
     {
     cmake::MessageType t = cmake::FATAL_ERROR;  // fail by default
@@ -257,6 +261,16 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
   // Handle normal case first.
   if(this->CurrentProcessingState != ProcessingLinkInterface)
     {
+    if (this->Target->IsImported())
+      {
+      cmOStringStream e;
+      e << "Imported targets may only be used with the "
+          "LINK_INTERFACE_LIBRARIES specifier to target_link_libraries.";
+      this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return;
+      }
+
+
     this->Makefile
       ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
     if (this->CurrentProcessingState != ProcessingPublicInterface)

+ 7 - 0
Source/cmTargetLinkLibrariesCommand.h

@@ -13,6 +13,7 @@
 #define cmTargetLinkLibrariesCommand_h
 
 #include "cmCommand.h"
+#include "cmDocumentGeneratorExpressions.h"
 
 /** \class cmTargetLinkLibrariesCommand
  * \brief Specify a list of libraries to link into executables.
@@ -141,6 +142,12 @@ public:
       "However, if two archives are really so interdependent they should "
       "probably be combined into a single archive."
       ")"
+      "\n"
+      "Arguments to target_link_libraries may use \"generator expressions\" "
+      "with the syntax \"$<...>\".  Note however, that generator expressions "
+      "will not be used in OLD handling of CMP0003 or CMP0004."
+      "\n"
+      CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
       ;
     }
 

+ 144 - 0
Source/cmTargetPropCommandBase.cxx

@@ -0,0 +1,144 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <[email protected]>
+
+  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 "cmTargetPropCommandBase.h"
+
+#include "cmGlobalGenerator.h"
+
+//----------------------------------------------------------------------------
+bool cmTargetPropCommandBase
+::HandleArguments(std::vector<std::string> const& args, const char *prop,
+                 ArgumentFlags flags)
+{
+  if(args.size() < 3)
+    {
+    this->SetError("called with incorrect number of arguments");
+    return false;
+    }
+
+  // Lookup the target for which libraries are specified.
+  this->Target =
+    this->Makefile->GetCMakeInstance()
+    ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
+  if(!this->Target)
+    {
+    this->Target = this->Makefile->FindTargetToUse(args[0].c_str());
+    }
+  if(!this->Target)
+    {
+    this->HandleMissingTarget(args[0]);
+    return false;
+    }
+
+  unsigned int argIndex = 1;
+
+  bool prepend = false;
+  if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE")
+    {
+    if (args.size() < 4)
+      {
+      this->SetError("called with incorrect number of arguments");
+      return false;
+      }
+    prepend = true;
+    ++argIndex;
+    }
+
+  this->Property = prop;
+
+  while (argIndex < args.size())
+    {
+    if (!this->ProcessContentArgs(args, argIndex, prepend))
+      {
+      return false;
+      }
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmTargetPropCommandBase
+::ProcessContentArgs(std::vector<std::string> const& args,
+                     unsigned int &argIndex, bool prepend)
+{
+  const std::string scope = args[argIndex];
+
+  if(scope != "PUBLIC"
+      && scope != "PRIVATE"
+      && scope != "INTERFACE" )
+    {
+    this->SetError("called with invalid arguments");
+    return false;
+    }
+
+  if(this->Target->IsImported() && scope != "INTERFACE")
+    {
+    this->HandleImportedTargetInvalidScope(args[0], scope);
+    return false;
+    }
+
+  ++argIndex;
+
+  std::string content;
+
+  std::string sep;
+  for(unsigned int i=argIndex; i < args.size(); ++i, ++argIndex)
+    {
+    if(args[i] == "PUBLIC"
+        || args[i] == "PRIVATE"
+        || args[i] == "INTERFACE" )
+      {
+      this->PopulateTargetProperies(scope, content, prepend);
+      return true;
+      }
+    if (this->Makefile->FindTargetToUse(args[i].c_str()))
+      {
+      content += sep + "$<TARGET_PROPERTY:" + args[i]
+                      + ",INTERFACE_" + this->Property + ">";
+      }
+    else if (!this->HandleNonTargetArg(content, sep, args[i], args[0]))
+      {
+      return false;
+      }
+    sep = ";";
+    }
+  this->PopulateTargetProperies(scope, content, prepend);
+  return true;
+}
+
+//----------------------------------------------------------------------------
+void cmTargetPropCommandBase
+::PopulateTargetProperies(const std::string &scope,
+                          const std::string &content, bool prepend)
+{
+  if (scope == "PRIVATE" || scope == "PUBLIC")
+    {
+    this->HandleDirectContent(this->Target, content, prepend);
+    }
+  if (scope == "INTERFACE" || scope == "PUBLIC")
+    {
+    if (prepend)
+      {
+      const std::string propName = std::string("INTERFACE_") + this->Property;
+      const char *propValue = this->Target->GetProperty(propName.c_str());
+      const std::string totalContent = content + (propValue
+                                                ? std::string(";") + propValue
+                                                : std::string());
+      this->Target->SetProperty(propName.c_str(), totalContent.c_str());
+      }
+    else
+      {
+      this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(),
+                            content.c_str());
+      }
+    }
+}

+ 58 - 0
Source/cmTargetPropCommandBase.h

@@ -0,0 +1,58 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <[email protected]>
+
+  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 cmTargetPropCommandBase_h
+#define cmTargetPropCommandBase_h
+
+#include "cmCommand.h"
+#include "cmDocumentGeneratorExpressions.h"
+
+class cmTarget;
+
+//----------------------------------------------------------------------------
+class cmTargetPropCommandBase : public cmCommand
+{
+public:
+
+  enum ArgumentFlags {
+    NO_FLAGS = 0,
+    PROCESS_BEFORE = 1
+  };
+
+  bool HandleArguments(std::vector<std::string> const& args,
+                           const char *prop, ArgumentFlags flags = NO_FLAGS);
+
+private:
+  virtual void HandleImportedTargetInvalidScope(const std::string &tgt,
+                                   const std::string &scope) = 0;
+  virtual void HandleMissingTarget(const std::string &name) = 0;
+
+  virtual bool HandleNonTargetArg(std::string &content,
+                          const std::string &sep,
+                          const std::string &entry,
+                          const std::string &tgt) = 0;
+
+  virtual void HandleDirectContent(cmTarget *tgt,
+                                   const std::string &content,
+                                   bool prepend) = 0;
+
+  bool ProcessContentArgs(std::vector<std::string> const& args,
+                          unsigned int &argIndex, bool prepend);
+  void PopulateTargetProperies(const std::string &scope,
+                               const std::string &content, bool prepend);
+
+private:
+  cmTarget *Target;
+  std::string Property;
+};
+
+#endif

+ 2 - 2
Source/cmTestGenerator.cxx

@@ -112,7 +112,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
   else
     {
     // Use the command name given.
-    exe = ge.Parse(exe.c_str()).Evaluate(mf, config);
+    exe = ge.Parse(exe.c_str())->Evaluate(mf, config);
     cmSystemTools::ConvertToUnixSlashes(exe);
     }
 
@@ -122,7 +122,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
   for(std::vector<std::string>::const_iterator ci = command.begin()+1;
       ci != command.end(); ++ci)
     {
-    os << " " << lg->EscapeForCMake(ge.Parse(*ci).Evaluate(mf, config));
+    os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config));
     }
 
   // Finish the test command.

+ 134 - 0
Source/cmTimestamp.cxx

@@ -0,0 +1,134 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2012 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 "cmTimestamp.h"
+
+#include <cstring>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+//----------------------------------------------------------------------------
+std::string cmTimestamp::CurrentTime(
+  const std::string& formatString, bool utcFlag)
+{
+  time_t currentTimeT = time(0);
+  if(currentTimeT == time_t(-1))
+    {
+    return std::string();
+    }
+
+  return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag);
+}
+
+//----------------------------------------------------------------------------
+std::string cmTimestamp::FileModificationTime(const char* path,
+  const std::string& formatString, bool utcFlag)
+{
+  struct stat info;
+  memset(&info, 0, sizeof(info));
+
+  if(stat(path, &info) != 0)
+    {
+    return std::string();
+    }
+
+  return CreateTimestampFromTimeT(info.st_mtime, formatString, utcFlag);
+}
+
+//----------------------------------------------------------------------------
+std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
+    std::string formatString, bool utcFlag)
+{
+  if(formatString.empty())
+    {
+    formatString = "%Y-%m-%dT%H:%M:%S";
+    if(utcFlag)
+      {
+      formatString += "Z";
+      }
+    }
+
+  struct tm timeStruct;
+  memset(&timeStruct, 0, sizeof(timeStruct));
+
+  struct tm* ptr = (struct tm*) 0;
+  if(utcFlag)
+    {
+    ptr = gmtime(&timeT);
+    }
+  else
+    {
+    ptr = localtime(&timeT);
+    }
+
+  if(ptr == 0)
+    {
+    return std::string();
+    }
+
+  timeStruct = *ptr;
+
+  std::string result;
+  for(std::string::size_type i = 0; i < formatString.size(); ++i)
+    {
+    char c1 = formatString[i];
+    char c2 = (i+1 < formatString.size()) ?
+      formatString[i+1] : static_cast<char>(0);
+
+    if(c1 == '%' && c2 != 0)
+      {
+      result += AddTimestampComponent(c2, timeStruct);
+      ++i;
+      }
+    else
+      {
+      result += c1;
+      }
+    }
+
+  return result;
+}
+
+//----------------------------------------------------------------------------
+std::string cmTimestamp::AddTimestampComponent(
+  char flag, struct tm& timeStruct)
+{
+  std::string formatString = "%";
+  formatString += flag;
+
+  switch(flag)
+    {
+    case 'd':
+    case 'H':
+    case 'I':
+    case 'j':
+    case 'm':
+    case 'M':
+    case 'S':
+    case 'U':
+    case 'w':
+    case 'y':
+    case 'Y':
+      break;
+    default:
+      {
+      return formatString;
+      }
+    }
+
+  char buffer[16];
+
+  size_t size = strftime(buffer, sizeof(buffer),
+    formatString.c_str(), &timeStruct);
+
+  return std::string(buffer, size);
+}

+ 40 - 0
Source/cmTimestamp.h

@@ -0,0 +1,40 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2012 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.
+============================================================================*/
+#ifndef cmTimestamp_h
+#define cmTimestamp_h
+
+#include <string>
+#include <time.h>
+
+/** \class cmTimestamp
+ * \brief Utility class to generate sting representation of a timestamp
+ *
+ */
+class cmTimestamp
+{
+public:
+  cmTimestamp() {}
+
+  std::string CurrentTime(const std::string& formatString, bool utcFlag);
+
+  std::string FileModificationTime(const char* path,
+    const std::string& formatString, bool utcFlag);
+
+private:
+  std::string CreateTimestampFromTimeT(time_t timeT,
+      std::string formatString, bool utcFlag);
+
+  std::string AddTimestampComponent(char flag, struct tm& timeStruct);
+};
+
+
+#endif

+ 20 - 5
Source/cmVisualStudio10TargetGenerator.cxx

@@ -572,6 +572,12 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
       sep = ";";
       }
     (*this->BuildFileStream ) << "</Outputs>\n";
+    if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10)
+      {
+      // VS >= 11 let us turn off linking of custom command outputs.
+      this->WritePlatformConfigTag("LinkObjects", i->c_str(), 3);
+      (*this->BuildFileStream ) << "false</LinkObjects>\n";
+      }
     }
   this->WriteString("</CustomBuild>\n", 2);
 }
@@ -879,14 +885,23 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
       }
     }
 
-  for(std::vector<cmSourceFile*>::const_iterator
-        si = this->GeneratorTarget->ExternalObjects.begin();
-      si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+  if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10)
+    {
+    // For VS >= 11 we use LinkObjects to avoid linking custom command
+    // outputs.  Use Object for all external objects, generated or not.
+    this->WriteSources("Object", this->GeneratorTarget->ExternalObjects);
+    }
+  else
     {
     // If an object file is generated in this target, then vs10 will use
     // it in the build, and we have to list it as None instead of Object.
-    std::vector<cmSourceFile*> const* d = this->Target->GetSourceDepends(*si);
-    this->WriteSource((d && !d->empty())? "None":"Object", *si);
+    for(std::vector<cmSourceFile*>::const_iterator
+          si = this->GeneratorTarget->ExternalObjects.begin();
+        si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+      {
+      std::vector<cmSourceFile*> const* d=this->Target->GetSourceDepends(*si);
+      this->WriteSource((d && !d->empty())? "None":"Object", *si);
+      }
     }
 
   this->WriteSources("None", this->GeneratorTarget->ExtraSources);

+ 14 - 1
Source/cmake.cxx

@@ -953,7 +953,7 @@ int cmake::AddCMakePaths()
   cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
   cMakeSelf += "/cmake";
   cMakeSelf += cmSystemTools::GetExecutableExtension();
-#if __APPLE__
+#ifdef __APPLE__
   // on the apple this might be the gui bundle
   if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
     {
@@ -3299,6 +3299,12 @@ int cmake::ExecuteLinkScript(std::vector<std::string>& args)
   int result = 0;
   while(result == 0 && cmSystemTools::GetLineFromStream(fin, command))
     {
+    // Skip empty command lines.
+    if(command.find_first_not_of(" \t") == command.npos)
+      {
+      continue;
+      }
+
     // Setup this command line.
     const char* cmd[2] = {command.c_str(), 0};
     cmsysProcess_SetCommand(cp, cmd);
@@ -3552,6 +3558,13 @@ void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope,
                                                   chained);
 }
 
+bool cmake::GetIsPropertyDefined(const char *name,
+                                 cmProperty::ScopeType scope)
+{
+  return this->PropertyDefinitions[scope].find(name) !=
+                                      this->PropertyDefinitions[scope].end();
+}
+
 cmPropertyDefinition *cmake
 ::GetPropertyDefinition(const char *name,
                         cmProperty::ScopeType scope)

+ 2 - 0
Source/cmake.h

@@ -341,6 +341,8 @@ class cmake
                       bool chain = false,
                       const char *variableGroup = 0);
 
+  bool GetIsPropertyDefined(const char *name, cmProperty::ScopeType scope);
+
   // get property definition
   cmPropertyDefinition *GetPropertyDefinition
   (const char *name, cmProperty::ScopeType scope);

+ 33 - 48
Source/kwsys/CMakeLists.txt

@@ -116,7 +116,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
   SET(KWSYS_USE_MD5 1)
   SET(KWSYS_USE_Process 1)
   SET(KWSYS_USE_RegularExpression 1)
-  SET(KWSYS_USE_Registry 1)
   SET(KWSYS_USE_System 1)
   SET(KWSYS_USE_SystemTools 1)
   SET(KWSYS_USE_CommandLineArguments 1)
@@ -575,6 +574,8 @@ IF(KWSYS_USE_SystemTools)
 ENDIF()
 
 IF(KWSYS_USE_SystemInformation)
+  SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+    COMPILE_DEFINITIONS SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P})
   IF(NOT CYGWIN)
     INCLUDE(CheckIncludeFiles)
     CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" KWSYS_SYS_HAS_IFADDRS_H)
@@ -597,6 +598,20 @@ IF(KWSYS_USE_SystemInformation)
       ENDIF()
     ENDIF()
   ENDIF()
+  IF(CMAKE_SYSTEM MATCHES "HP-UX")
+    CHECK_INCLUDE_FILES("sys/mpctl.h" KWSYS_SYS_HAS_MPCTL_H)
+    IF(KWSYS_SYS_HAS_MPCTL_H)
+      SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+        COMPILE_DEFINITIONS KWSYS_SYS_HAS_MPCTL_H=1)
+    ENDIF()
+  ENDIF()
+  IF(CMAKE_SYSTEM MATCHES "BSD")
+    CHECK_INCLUDE_FILES("machine/cpu.h" KWSYS_SYS_HAS_MACHINE_CPU_H)
+    IF(KWSYS_SYS_HAS_MACHINE_CPU_H)
+      SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+        COMPILE_DEFINITIONS KWSYS_SYS_HAS_MACHINE_CPU_H=1)
+    ENDIF()
+  ENDIF()
   IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE)
     SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1)
   ENDIF()
@@ -625,6 +640,20 @@ IF(KWSYS_USE_SystemInformation)
     SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
       COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1)
   ENDIF()
+  IF(BORLAND)
+    KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM
+      "Checking whether Borland CXX compiler supports assembler instructions" DIRECT)
+    IF(KWSYS_CXX_HAS_BORLAND_ASM)
+      SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+        COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM=1)
+      KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM_CPUID
+        "Checking whether Borland CXX compiler supports CPUID assembler instruction" DIRECT)
+      IF(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
+        SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+          COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM_CPUID=1)
+      ENDIF()
+    ENDIF()
+  ENDIF()
   IF(KWSYS_USE___INT64)
     SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
       COMPILE_DEFINITIONS KWSYS_USE___INT64=1)
@@ -762,7 +791,7 @@ SET(KWSYS_HXX_FILES Configure String
 # Add selected C++ classes.
 SET(cppclasses
   Directory DynamicLoader Glob RegularExpression SystemTools
-  CommandLineArguments Registry IOStream SystemInformation
+  CommandLineArguments IOStream SystemInformation
   )
 FOREACH(cpp ${cppclasses})
   IF(KWSYS_USE_${cpp})
@@ -800,12 +829,8 @@ SET(KWSYS_CXX_SRCS)
 # Add the proper sources for this platform's Process implementation.
 IF(KWSYS_USE_Process)
   IF(NOT UNIX)
-    # Use the Windows implementation.  We need the encoded forwarding executable.
-    SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c
-      ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c)
-    SET_SOURCE_FILES_PROPERTIES(
-      ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
-      PROPERTIES GENERATED 1)
+    # Use the Windows implementation.
+    SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c)
   ELSE(NOT UNIX)
     # Use the UNIX implementation.
     SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c)
@@ -937,43 +962,6 @@ IF(KWSYS_USE_String)
     COMPILE_FLAGS "-DKWSYS_STRING_C")
 ENDIF(KWSYS_USE_String)
 
-#-----------------------------------------------------------------------------
-# Process execution on windows needs to build a forwarding executable
-# that works around a Win9x bug.  We encode the executable into a C
-# file and build it into the library.  Win9x platforms reproduce the
-# executable into a temporary directory when it is needed.
-IF(KWSYS_USE_Process)
-  IF(NOT UNIX)
-    # Build the forwarding executable itself and a program that will
-    # encode it into a C file.
-    ADD_EXECUTABLE(${KWSYS_NAMESPACE}ProcessFwd9x ProcessFwd9x.c)
-    ADD_EXECUTABLE(${KWSYS_NAMESPACE}EncodeExecutable EncodeExecutable.c)
-    SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
-    SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
-    SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY LABELS ${KWSYS_LABELS_EXE})
-    SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY LABELS ${KWSYS_LABELS_EXE})
-
-    SET(CFG_INTDIR "/${CMAKE_CFG_INTDIR}")
-    IF(CMAKE_BUILD_TOOL MATCHES "make")
-      SET(CFG_INTDIR "")
-    ENDIF(CMAKE_BUILD_TOOL MATCHES "make")
-
-    # Take advantage of a better custom command syntax if possible.
-    SET(CMD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}EncodeExecutable.exe)
-    SET(FWD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}ProcessFwd9x.exe)
-    ADD_CUSTOM_COMMAND(
-      OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
-      COMMAND ${CMD}
-      ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
-           ${KWSYS_NAMESPACE} ProcessFwd9x
-      DEPENDS ${CMD} ${FWD})
-
-    # Make sure build occurs in proper order.
-    ADD_DEPENDENCIES(${KWSYS_NAMESPACE} ${KWSYS_NAMESPACE}ProcessFwd9x
-                     ${KWSYS_NAMESPACE}EncodeExecutable)
-  ENDIF(NOT UNIX)
-ENDIF(KWSYS_USE_Process)
-
 #-----------------------------------------------------------------------------
 # Setup testing if not being built as part of another project.
 IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
@@ -1012,7 +1000,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
         )
     ENDIF(NOT WATCOM)
     SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
-      testRegistry
       testIOS
       testSystemTools
       testCommandLineArguments
@@ -1116,8 +1103,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
       # We expect test to fail
       SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON)
       GET_TEST_PROPERTY(kwsys.testFail WILL_FAIL wfv)
-      SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES FAIL_REGULAR_EXPRESSION "ERROR_NOT_VALGRIND;FAIL;Test failed")
-      SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES PASS_REGULAR_EXPRESSION "Test passed")
       SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value")
       MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}")
     ENDIF()

+ 8 - 0
Source/kwsys/CPU.h.in

@@ -98,6 +98,14 @@
 #elif defined(__SYSC_ZARCH__)
 # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
 
+/* Aarch64 */
+#elif defined(__aarch64__)
+# if !defined(__AARCH64EB__)
+#  define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
+# else
+#  define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
+# endif
+
 /* Unknown CPU */
 #else
 # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID 0

+ 0 - 114
Source/kwsys/EncodeExecutable.c

@@ -1,114 +0,0 @@
-/*============================================================================
-  KWSys - Kitware System Library
-  Copyright 2000-2009 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 <stdio.h>
-#ifdef __WATCOMC__
-#define _unlink unlink
-#endif
-int main(int argc, char* argv[])
-{
-  FILE* ifp;
-  FILE* ofp;
-  int i;
-  int n;
-  int count = 0;
-  unsigned char buffer[1024];
-  
-  /* Check arguments.  */
-  if(argc != 5)
-    {
-    fprintf(stderr, "Usage: %s <input> <output> <kwsys-name> <array>\n",
-            argv[0]);
-    return 1;
-    }
-  
-  /* Open the input file.  */
-  ifp = fopen(argv[1], "rb");
-  if(!ifp)
-    {
-    fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]);
-    return 2;
-    }
-  ofp = fopen(argv[2], "w");
-  if(!ofp)
-    {
-    fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]);
-    fclose(ifp);
-    return 2;
-    }
-  
-  /* Prepend header comment.  */
-  fprintf(ofp, "/*\n * DO NOT EDIT\n * This file is generated by:\n");
-  fprintf(ofp, " * %s\n */\n\n", argv[0]);
-  fprintf(ofp, "#include \"kwsysPrivate.h\"\n");
-  fprintf(ofp, "#include KWSYS_HEADER(Configure.h)\n\n");
-  fprintf(ofp, "#include <stdio.h>\n\n");
-  fprintf(ofp, "#if defined(_WIN32)\n");
-  fprintf(ofp, "# include <io.h>\n");
-  fprintf(ofp, "#else\n");
-  fprintf(ofp, "# include <unistd.h>\n");
-  fprintf(ofp, "#endif\n");
-  fprintf(ofp, "\n");
-  fprintf(ofp, "static void kwsys_unlink(const char* fname)\n");
-  fprintf(ofp, "{\n");
-  fprintf(ofp, "#if defined(__WATCOMC__)\n");
-  fprintf(ofp, "  unlink(fname);\n");
-  fprintf(ofp, "#else\n");
-  fprintf(ofp, "  _unlink(fname);\n");
-  fprintf(ofp, "#endif\n");
-  fprintf(ofp, "}\n");
-  fprintf(ofp, "\n");
-  
-  /* Split file up in 1024-byte chunks.  */
-  while((n = (int)fread(buffer, 1, 1024, ifp)) > 0)
-    {
-    fprintf(ofp, "static unsigned char kwsysEncodedArray%s_%d[%d] = {\n", 
-            argv[4], count++, n);
-    for(i=0; i < n-1; ++i)
-      {
-      fprintf(ofp, "0x%02X", buffer[i]);
-      if(i%10 == 9)
-        {
-        fprintf(ofp, ",\n");
-        }
-      else
-        {
-        fprintf(ofp, ", ");
-        }
-      }
-    fprintf(ofp, "0x%02X};\n\n", buffer[n-1]);
-    }
-  fclose(ifp);
-  
-  /* Provide a function to write the data to a file.  */
-  fprintf(ofp, "extern %s_EXPORT int %sEncodedWriteArray%s(const char* fname)\n",
-          argv[3], argv[3], argv[4]);
-  fprintf(ofp, "{\n");
-  fprintf(ofp, "  FILE* ofp = fopen(fname, \"wb\");\n");
-  fprintf(ofp, "  if(!ofp) { return 0; }\n");
-  for(i=0; i < count; ++i)
-    {
-    fprintf(ofp, "  if(fwrite(kwsysEncodedArray%s_%d, 1,\n"
-                 "            sizeof(kwsysEncodedArray%s_%d), ofp) !=\n"
-                 "       sizeof(kwsysEncodedArray%s_%d))\n",
-            argv[4], i, argv[4], i, argv[4], i);
-    fprintf(ofp, "    {\n");
-    fprintf(ofp, "    fclose(ofp);\n");
-    fprintf(ofp, "    kwsys_unlink(fname);\n");
-    fprintf(ofp, "    return 0;\n");
-    fprintf(ofp, "    }\n");
-    }
-  fprintf(ofp, "  fclose(ofp);\n");
-  fprintf(ofp, "  return 1;\n");
-  fprintf(ofp, "}\n");
-  fclose(ofp);
-  return 0;
-}

+ 1 - 5
Source/kwsys/IOStream.hxx.in

@@ -26,12 +26,9 @@
 /* Whether ostream supports long long.  */
 #define @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_IOS_HAS_OSTREAM_LONG_LONG@
 
-/* Size of type long long and 0 if not available.  */
-#define @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG @KWSYS_SIZEOF_LONG_LONG@
-
 /* Determine whether we need to define the streaming operators for
    long long or __int64.  */
-#if @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG
+#if @KWSYS_USE_LONG_LONG@
 # if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG || \
      !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
 # define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
@@ -136,7 +133,6 @@ operator<<(kwsys_ios::ostream& os, @KWSYS_NAMESPACE@::IOStreamULL value)
 /* If building a C++ file in kwsys itself, give the source file
    access to the macros without a configured namespace.  */
 #if defined(KWSYS_NAMESPACE)
-# define KWSYS_IOS_SIZEOF_LONG_LONG      @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG
 # define KWSYS_IOS_HAS_ISTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
 # define KWSYS_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
 # define KWSYS_IOS_NEED_OPERATORS_LL     @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL

+ 0 - 211
Source/kwsys/ProcessFwd9x.c

@@ -1,211 +0,0 @@
-/*============================================================================
-  KWSys - Kitware System Library
-  Copyright 2000-2009 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.
-============================================================================*/
-
-/*
-  On Windows9x platforms, this executable is spawned between a parent
-  process and the child it is invoking to work around a bug.  See the
-  Win32 implementation file for details.
-
-  Future Work: This executable must be linked statically against the C
-  runtime library before being encoded into the library.  Building it
-  in this way may be hard because CMake has limited abilities to build
-  different targets with different configurations in the same
-  directory.  We may just have to create and encode the executable
-  once instead of generating it during the build.  This would be an
-  acceptable solution because the forwarding executable should not
-  change very often and is pretty simple.
-*/
-
-#ifdef _MSC_VER
-#pragma warning (push, 1)
-#endif
-#include <windows.h>
-#include <stdio.h>
-
-void ReportLastError(HANDLE errorPipe);
-
-int main()
-{
-  /* Process startup information for the real child.  */
-  STARTUPINFO si;
-  PROCESS_INFORMATION pi;
-
-  /* The result of waiting for the child to exit.  */
-  DWORD waitResult;
-
-  /* The child's process return code.  */
-  DWORD retVal;
-
-  /* The command line used to invoke this process.  */
-  LPSTR commandLine = GetCommandLine();
-
-  /* Pointer that will be advanced to the beginning of the command
-     line of the real child process.  */
-  LPSTR cmdLine = commandLine;
-
-  /* Handle to the error reporting pipe provided by the parent.  This
-     is parsed off the command line.  */
-  HANDLE errorPipe = 0;
-  HANDLE errorPipeOrig = 0;
-
-  /* Handle to the event the parent uses to tell us to resume the child.
-     This is parsed off the command line.  */
-  HANDLE resumeEvent = 0;
-
-  /* Handle to the event the parent uses to tell us to kill the child.
-     This is parsed off the command line.  */
-  HANDLE killEvent = 0;
-
-  /* Flag for whether to hide window of child process.  */
-  int hideWindow = 0;
-
-  /* An array of the handles on which we wait when the child is
-     running.  */
-  HANDLE waitHandles[2] = {0, 0};
-
-  /* Move the pointer past the name of this executable.  */
-  if(*cmdLine == '"')
-    {
-    ++cmdLine;
-    while(*cmdLine && *cmdLine != '"') { ++cmdLine; }
-    if(*cmdLine) { ++cmdLine; }
-    }
-  else
-    {
-    while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
-    }
-
-  /* Parse the error pipe handle.  */
-  while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
-  sscanf(cmdLine, "%p", &errorPipeOrig);
-
-  /* Parse the resume event handle.  */
-  while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
-  while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
-  sscanf(cmdLine, "%p", &resumeEvent);
-
-  /* Parse the kill event handle.  */
-  while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
-  while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
-  sscanf(cmdLine, "%p", &killEvent);
-
-  /* Parse the hide window flag.  */
-  while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
-  while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
-  sscanf(cmdLine, "%d", &hideWindow);
-
-  /* Skip to the beginning of the command line of the real child.  */
-  while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
-  while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
-
-  /* Create a non-inherited copy of the error pipe.  We do not want
-     the child to get it.  */
-  if(DuplicateHandle(GetCurrentProcess(), errorPipeOrig,
-                     GetCurrentProcess(), &errorPipe,
-                     0, FALSE, DUPLICATE_SAME_ACCESS))
-    {
-    /* Have a non-inherited duplicate.  Close the inherited one.  */
-    CloseHandle(errorPipeOrig);
-    }
-  else
-    {
-    /* Could not duplicate handle.  Report the error.  */
-    ReportLastError(errorPipeOrig);
-    return 1;
-    }
-
-  /* Create the subprocess.  */
-  ZeroMemory(&si, sizeof(si));
-  ZeroMemory(&pi, sizeof(pi));
-  si.cb = sizeof(si);
-  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
-  si.wShowWindow = hideWindow?SW_HIDE:SW_SHOWDEFAULT;
-  si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
-  si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
-  si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-  if(CreateProcess(0, cmdLine, 0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &si, &pi))
-    {
-    /* Process created successfully.  Close the error reporting pipe
-       to notify the parent of success.  */
-    CloseHandle(errorPipe);
-    }
-  else
-    {
-    /* Error creating the process.  Report the error to the parent
-       process through the special error reporting pipe.  */
-    ReportLastError(errorPipe);
-    return 1;
-    }
-
-  /* Wait for resume or kill event from parent.  */
-  waitHandles[0] = killEvent;
-  waitHandles[1] = resumeEvent;
-  waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
-
-  /* Check what happened.  */
-  if(waitResult == WAIT_OBJECT_0)
-    {
-    /* We were asked to kill the child.  */
-    TerminateProcess(pi.hProcess, 255);
-    WaitForSingleObject(pi.hProcess, INFINITE);
-    CloseHandle(pi.hProcess);
-    CloseHandle(pi.hThread);
-    return 1;
-    }
-  else
-    {
-    /* We were asked to resume the child.  */
-    ResumeThread(pi.hThread);
-    CloseHandle(pi.hThread);
-    }
-
-  /* Wait for subprocess to exit or for kill event from parent.  */
-  waitHandles[0] = killEvent;
-  waitHandles[1] = pi.hProcess;
-  waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
-
-  /* Check what happened.  */
-  if(waitResult == WAIT_OBJECT_0)
-    {
-    /* We were asked to kill the child.  */
-    TerminateProcess(pi.hProcess, 255);
-    WaitForSingleObject(pi.hProcess, INFINITE);
-    CloseHandle(pi.hProcess);
-    return 1;
-    }
-  else
-    {
-    /* The child exited.  Get the return code.  */
-    GetExitCodeProcess(pi.hProcess, &retVal);
-    CloseHandle(pi.hProcess);
-    return retVal;
-    }
-}
-
-void ReportLastError(HANDLE errorPipe)
-{
-  LPVOID lpMsgBuf;
-  DWORD n;
-  FormatMessage(
-    FORMAT_MESSAGE_ALLOCATE_BUFFER |
-    FORMAT_MESSAGE_FROM_SYSTEM |
-    FORMAT_MESSAGE_IGNORE_INSERTS,
-    NULL,
-    GetLastError(),
-    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
-    (LPTSTR) &lpMsgBuf,
-    0,
-    NULL
-    );
-  WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0);
-  LocalFree( lpMsgBuf );
-}

+ 3 - 6
Source/kwsys/ProcessUNIX.c

@@ -63,10 +63,6 @@ do.
 #include <dirent.h>    /* DIR, dirent */
 #include <ctype.h>     /* isspace */
 
-#ifdef __HAIKU__
-#undef __BEOS__
-#endif
-
 #if defined(__VMS)
 # define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK
 #else
@@ -422,9 +418,10 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
        parse it.  */
     newCommands[cp->NumberOfCommands] =
       kwsysSystem_Parse_CommandForUnix(*command, 0);
-    if(!newCommands[cp->NumberOfCommands])
+    if(!newCommands[cp->NumberOfCommands] ||
+       !newCommands[cp->NumberOfCommands][0])
       {
-      /* Out of memory.  */
+      /* Out of memory or no command parsed.  */
       free(newCommands);
       return 0;
       }

+ 17 - 270
Source/kwsys/ProcessWin32.c

@@ -28,14 +28,6 @@ On windows, a thread is created to wait for data on each pipe.  The
 threads are synchronized with the main thread to simulate the use of
 a UNIX-style select system call.
 
-On Windows9x platforms, a small WIN32 console application is spawned
-in-between the calling process and the actual child to be executed.
-This is to work-around a problem with connecting pipes from WIN16
-console applications to WIN32 applications.
-
-For more information, please check Microsoft Knowledge Base Articles
-Q190351 and Q150956.
-
 */
 
 #ifdef _MSC_VER
@@ -91,18 +83,12 @@ Q190351 and Q150956.
 # define KWSYSPE_DEBUG(x) (void)1
 #endif
 
-#define kwsysEncodedWriteArrayProcessFwd9x kwsys_ns(EncodedWriteArrayProcessFwd9x)
-
 typedef LARGE_INTEGER kwsysProcessTime;
 
 typedef struct kwsysProcessCreateInformation_s
 {
   /* Windows child startup control data.  */
   STARTUPINFO StartupInfo;
-
-  /* Special error reporting pipe for Win9x forwarding executable.  */
-  HANDLE ErrorPipeRead;
-  HANDLE ErrorPipeWrite;
 } kwsysProcessCreateInformation;
 
 /*--------------------------------------------------------------------------*/
@@ -146,7 +132,6 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
 static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
 static void kwsysProcessKillTree(int pid);
 static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
-extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
 
 /*--------------------------------------------------------------------------*/
 /* A structure containing synchronization data for each thread.  */
@@ -233,15 +218,6 @@ struct kwsysProcess_s
   /* Whether to treat command lines as verbatim.  */
   int Verbatim;
 
-  /* On Win9x platforms, the path to the forwarding executable.  */
-  char* Win9x;
-
-  /* On Win9x platforms, the resume event for the forwarding executable.  */
-  HANDLE Win9xResumeEvent;
-
-  /* On Win9x platforms, the kill event for the forwarding executable.  */
-  HANDLE Win9xKillEvent;
-
   /* Mutex to protect the shared index used by threads to report data.  */
   HANDLE SharedIndexMutex;
 
@@ -269,9 +245,6 @@ struct kwsysProcess_s
   HANDLE PipeNativeSTDOUT[2];
   HANDLE PipeNativeSTDERR[2];
 
-  /* Handle to automatically delete the Win9x forwarding executable.  */
-  HANDLE Win9xHandle;
-
   /* ------------- Data managed per call to Execute ------------- */
 
   /* The exceptional behavior that terminated the process, if any.  */
@@ -311,7 +284,7 @@ struct kwsysProcess_s
      for pipes to close after process termination.  */
   int PipesLeft;
 
-  /* Buffer for error messages (possibly from Win9x child).  */
+  /* Buffer for error messages.  */
   char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
 
   /* Description for the ExitException.  */
@@ -337,9 +310,6 @@ kwsysProcess* kwsysProcess_New(void)
   /* Process control structure.  */
   kwsysProcess* cp;
 
-  /* Path to Win9x forwarding executable.  */
-  char* win9x = 0;
-
   /* Windows version number data.  */
   OSVERSIONINFO osv;
 
@@ -365,73 +335,11 @@ kwsysProcess* kwsysProcess_New(void)
   GetVersionEx(&osv);
   if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
     {
-    /* This is Win9x.  We need the console forwarding executable to
-       work-around a Windows 9x bug.  */
-    char fwdName[_MAX_FNAME+1] = "";
-    char tempDir[_MAX_PATH+1] = "";
-
-    /* We will try putting the executable in the system temp
-       directory.  Note that the returned path already has a trailing
-       slash.  */
-    DWORD length = GetTempPath(_MAX_PATH+1, tempDir);
-
-    /* Construct the executable name from the process id and kwsysProcess
-       instance.  This should be unique.  */
-    sprintf(fwdName, KWSYS_NAMESPACE_STRING "pew9xfwd_%ld_%p.exe",
-            GetCurrentProcessId(), cp);
-
-    /* If we have a temp directory, use it.  */
-    if(length > 0 && length <= _MAX_PATH)
-      {
-      /* Allocate a buffer to hold the forwarding executable path.  */
-      size_t tdlen = strlen(tempDir);
-      win9x = (char*)malloc(tdlen + strlen(fwdName) + 2);
-      if(!win9x)
-        {
-        kwsysProcess_Delete(cp);
-        return 0;
-        }
-
-      /* Construct the full path to the forwarding executable.  */
-      sprintf(win9x, "%s%s", tempDir, fwdName);
-      }
-
-    /* If we found a place to put the forwarding executable, try to
-       write it. */
-    if(win9x)
-      {
-      if(!kwsysEncodedWriteArrayProcessFwd9x(win9x))
-        {
-        /* Failed to create forwarding executable.  Give up.  */
-        free(win9x);
-        kwsysProcess_Delete(cp);
-        return 0;
-        }
-
-      /* Get a handle to the file that will delete it when closed.  */
-      cp->Win9xHandle = CreateFile(win9x, GENERIC_READ, FILE_SHARE_READ, 0,
-                                   OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
-      if(cp->Win9xHandle == INVALID_HANDLE_VALUE)
-        {
-        /* We were not able to get a read handle for the forwarding
-           executable.  It will not be deleted properly.  Give up.  */
-        _unlink(win9x);
-        free(win9x);
-        kwsysProcess_Delete(cp);
-        return 0;
-        }
-      }
-    else
-      {
-      /* Failed to find a place to put forwarding executable.  */
-      kwsysProcess_Delete(cp);
-      return 0;
-      }
+    /* Win9x no longer supported.  */
+    kwsysProcess_Delete(cp);
+    return 0;
     }
 
-  /* Save the path to the forwarding executable.  */
-  cp->Win9x = win9x;
-
   /* Initially no thread owns the mutex.  Initialize semaphore to 1.  */
   if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
     {
@@ -446,30 +354,6 @@ kwsysProcess* kwsysProcess_New(void)
     return 0;
     }
 
-  if(cp->Win9x)
-    {
-    SECURITY_ATTRIBUTES sa;
-    ZeroMemory(&sa, sizeof(sa));
-    sa.nLength = sizeof(sa);
-    sa.bInheritHandle = TRUE;
-
-    /* Create an event to tell the forwarding executable to resume the
-       child.  */
-    if(!(cp->Win9xResumeEvent = CreateEvent(&sa, TRUE, 0, 0)))
-      {
-      kwsysProcess_Delete(cp);
-      return 0;
-      }
-
-    /* Create an event to tell the forwarding executable to kill the
-       child.  */
-    if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0)))
-      {
-      kwsysProcess_Delete(cp);
-      return 0;
-      }
-    }
-
   /* Create the thread to read each pipe.  */
   for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
     {
@@ -620,13 +504,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
   kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
   kwsysProcessCleanupHandle(&cp->Full);
 
-  /* Close the Win9x resume and kill event handles.  */
-  if(cp->Win9x)
-    {
-    kwsysProcessCleanupHandle(&cp->Win9xResumeEvent);
-    kwsysProcessCleanupHandle(&cp->Win9xKillEvent);
-    }
-
   /* Free memory.  */
   kwsysProcess_SetCommand(cp, 0);
   kwsysProcess_SetWorkingDirectory(cp, 0);
@@ -637,12 +514,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
     {
     free(cp->CommandExitCodes);
     }
-  if(cp->Win9x)
-    {
-    /* Close our handle to the forwarding executable file.  This will
-       cause it to be deleted.  */
-    kwsysProcessCleanupHandle(&cp->Win9xHandle);
-    }
   free(cp);
 }
 
@@ -1017,21 +888,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
     SetCurrentDirectory(cp->WorkingDirectory);
     }
 
-  /* Reset the Win9x resume and kill events.  */
-  if(cp->Win9x)
-    {
-    if(!ResetEvent(cp->Win9xResumeEvent))
-      {
-      kwsysProcessCleanup(cp, 1);
-      return;
-      }
-    if(!ResetEvent(cp->Win9xKillEvent))
-      {
-      kwsysProcessCleanup(cp, 1);
-      return;
-      }
-    }
-
   /* Initialize startup info data.  */
   ZeroMemory(&si, sizeof(si));
   si.StartupInfo.cb = sizeof(si.StartupInfo);
@@ -1130,8 +986,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
                                     STD_OUTPUT_HANDLE);
       kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
                                     STD_ERROR_HANDLE);
-      kwsysProcessCleanupHandle(&si.ErrorPipeRead);
-      kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
       return;
       }
     }
@@ -1160,16 +1014,9 @@ void kwsysProcess_Execute(kwsysProcess* cp)
 
   /* All processes in the pipeline have been started in suspended
      mode.  Resume them all now.  */
-  if(cp->Win9x)
-    {
-    SetEvent(cp->Win9xResumeEvent);
-    }
-  else
+  for(i=0; i < cp->NumberOfCommands; ++i)
     {
-    for(i=0; i < cp->NumberOfCommands; ++i)
-      {
-      ResumeThread(cp->ProcessInformation[i].hThread);
-      }
+    ResumeThread(cp->ProcessInformation[i].hThread);
     }
 
   /* ---- It is no longer safe to call kwsysProcessCleanup. ----- */
@@ -1480,21 +1327,12 @@ void kwsysProcess_Kill(kwsysProcess* cp)
 
   /* Kill the children.  */
   cp->Killed = 1;
-  if(cp->Win9x)
-    {
-    /* Windows 9x.  Tell the forwarding executable to kill the child.  */
-    SetEvent(cp->Win9xKillEvent);
-    }
-  else
+  for(i=0; i < cp->NumberOfCommands; ++i)
     {
-    /* Not Windows 9x.  Just terminate the children.  */
-    for(i=0; i < cp->NumberOfCommands; ++i)
-      {
-      kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId); 
-      // close the handle if we kill it
-      kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
-      kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
-      }
+    kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
+    // close the handle if we kill it
+    kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
+    kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
     }
 
   /* We are killing the children and ignoring all data.  Do not wait
@@ -1815,97 +1653,13 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
       }
     }
 
-  /* Create the child process.  */
-  {
-  BOOL r;
-  char* realCommand;
-  if(cp->Win9x)
-    {
-    /* Create an error reporting pipe for the forwarding executable.
-       Neither end is directly inherited.  */
-    if(!CreatePipe(&si->ErrorPipeRead, &si->ErrorPipeWrite, 0, 0))
-      {
-      return 0;
-      }
-
-    /* Create an inherited duplicate of the write end.  This also closes
-       the non-inherited version. */
-    if(!DuplicateHandle(GetCurrentProcess(), si->ErrorPipeWrite,
-                        GetCurrentProcess(), &si->ErrorPipeWrite,
-                        0, TRUE, (DUPLICATE_CLOSE_SOURCE |
-                                  DUPLICATE_SAME_ACCESS)))
-      {
-      return 0;
-      }
-
-    /* The forwarding executable is given a handle to the error pipe
-       and resume and kill events.  */
-    realCommand = (char*)malloc(strlen(cp->Win9x)+strlen(cp->Commands[index])+100);
-    if(!realCommand)
-      {
-      return 0;
-      }
-    sprintf(realCommand, "%s %p %p %p %d %s", cp->Win9x,
-            si->ErrorPipeWrite, cp->Win9xResumeEvent, cp->Win9xKillEvent,
-            cp->HideWindow, cp->Commands[index]);
-    }
-  else
-    {
-    realCommand = cp->Commands[index];
-    }
-
   /* Create the child in a suspended state so we can wait until all
      children have been created before running any one.  */
-  r = CreateProcess(0, realCommand, 0, 0, TRUE,
-                    cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0,
-                    &si->StartupInfo, &cp->ProcessInformation[index]);
-  if(cp->Win9x)
-    {
-    /* Free memory.  */
-    free(realCommand);
-
-    /* Close the error pipe write end so we can detect when the
-       forwarding executable closes it.  */
-    kwsysProcessCleanupHandle(&si->ErrorPipeWrite);
-    if(r)
-      {
-      /* Wait for the forwarding executable to report an error or
-         close the error pipe to report success.  */
-      DWORD total = 0;
-      DWORD n = 1;
-      while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0)
-        {
-        if(ReadFile(si->ErrorPipeRead, cp->ErrorMessage+total,
-                    KWSYSPE_PIPE_BUFFER_SIZE-total, &n, 0))
-          {
-          total += n;
-          }
-        else
-          {
-          n = 0;
-          }
-        }
-      if(total > 0 || GetLastError() != ERROR_BROKEN_PIPE)
-        {
-        /* The forwarding executable could not run the process, or
-           there was an error reading from its error pipe.  Preserve
-           the last error while cleaning up the forwarding executable
-           so the cleanup our caller does reports the proper error.  */
-        DWORD error = GetLastError();
-        kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread);
-        kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess);
-        SetLastError(error);
-        return 0;
-        }
-      }
-    kwsysProcessCleanupHandle(&si->ErrorPipeRead);
-    }
-
-  if(!r)
+  if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
+                    0, &si->StartupInfo, &cp->ProcessInformation[index]))
     {
     return 0;
     }
-  }
 
   /* Successfully created this child process.  Close the current
      process's copies of the inherited stdout and stdin handles.  The
@@ -2152,19 +1906,12 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
     /* Cleanup any processes already started in a suspended state.  */
     if(cp->ProcessInformation)
       {
-      if(cp->Win9x)
-        {
-        SetEvent(cp->Win9xKillEvent);
-        }
-      else
+      for(i=0; i < cp->NumberOfCommands; ++i)
         {
-        for(i=0; i < cp->NumberOfCommands; ++i)
+        if(cp->ProcessInformation[i].hProcess)
           {
-          if(cp->ProcessInformation[i].hProcess)
-            {
-            TerminateProcess(cp->ProcessInformation[i].hProcess, 255);
-            WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
-            }
+          TerminateProcess(cp->ProcessInformation[i].hProcess, 255);
+          WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
           }
         }
       for(i=0; i < cp->NumberOfCommands; ++i)

Some files were not shown because too many files changed in this diff