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

This commit is contained in:
Brad King 2013-01-31 09:58:50 -05:00
commit 118c32f8f2
211 changed files with 5667 additions and 3065 deletions

View File

@ -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)

View File

@ -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@

View File

@ -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@

View File

@ -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)

View File

@ -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@")

View File

@ -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__)

View File

@ -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)
")

View File

@ -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()

View File

@ -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"

View File

@ -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
#=============================================================================

View File

@ -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

View File

@ -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 ()

View File

@ -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

View File

@ -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.

View File

@ -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 )

View File

@ -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

View File

@ -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()

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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)

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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

View File

@ -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" />

View File

@ -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)

View File

@ -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;
}

View File

@ -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",

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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>."
;
}

View File

@ -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"

View File

@ -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

View File

@ -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, \

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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$");

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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)

View File

@ -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. " \

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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";
}

View File

@ -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

View File

@ -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())
{

View File

@ -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,

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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();
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);
};

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}
// expand CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the
// include and library directories.
void cmMakefile::ExpandVariables()
static bool mightExpandVariablesCMP0019(const char* s)
{
// Now expand variables in the include and link strings
return s && *s && strstr(s,"${") && strchr(s,'}');
}
void cmMakefile::ExpandVariablesCMP0019()
{
// 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 =

View File

@ -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&);

View File

@ -0,0 +1,28 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2012 Stephen Kelly <steveire@gmail.com>
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

View File

@ -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;

View File

@ -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.
{

View File

@ -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()

View File

@ -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.
*

View File

@ -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");

View File

@ -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;
}

View File

@ -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 Load Diff

View File

@ -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;

View File

@ -0,0 +1,57 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
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());
}

View File

@ -0,0 +1,94 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
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

View File

@ -0,0 +1,74 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
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);
}

View File

@ -0,0 +1,98 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
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

View File

@ -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)

View File

@ -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
;
}

View File

@ -0,0 +1,144 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
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());
}
}
}

View File

@ -0,0 +1,58 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
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

View File

@ -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
Source/cmTimestamp.cxx Normal file
View File

@ -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
Source/cmTimestamp.h Normal file
View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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()

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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 );
}

View File

@ -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;
}

View File

@ -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)
for(i=0; i < cp->NumberOfCommands; ++i)
{
SetEvent(cp->Win9xResumeEvent);
}
else
{
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)
for(i=0; i < cp->NumberOfCommands; ++i)
{
/* Windows 9x. Tell the forwarding executable to kill the child. */
SetEvent(cp->Win9xKillEvent);
}
else
{
/* 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)
for(i=0; i < cp->NumberOfCommands; ++i)
{
SetEvent(cp->Win9xKillEvent);
}
else
{
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 have changed in this diff Show More