Merge branch 'master' into generator-toolset

We need the latest Tests/CMakeLists.txt so we can refactor all tests.
This commit is contained in:
Brad King 2013-02-05 14:54:02 -05:00
commit c0debb1f89
289 changed files with 3681 additions and 609 deletions

View File

@ -9,6 +9,8 @@
# configure_file() command when creating the <Name>Config.cmake or <Name>-config.cmake
# file for installing a project or library. It helps making the resulting package
# relocatable by avoiding hardcoded paths in the installed Config.cmake file.
# <Name>Config.cmake files installed under UNIX into /lib(64) or /usr/lib(64) are
# considered system packages and are not relocatable.
#
# In a FooConfig.cmake file there may be code like this to make the
# install destinations know to the using project:
@ -173,11 +175,26 @@ function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile)
else()
set(absInstallDir "${CMAKE_INSTALL_PREFIX}/${CCF_INSTALL_DESTINATION}")
endif()
# with the /usr-move, /lib(64) is a symlink to /usr/lib on Fedora, ArchLinux, Mageira and others.
# If we are installed to such a location, force using absolute paths.
set(forceAbsolutePaths FALSE)
if("${absInstallDir}" MATCHES "^(/usr)?/lib(64)?/.+")
set(forceAbsolutePaths TRUE)
endif()
file(RELATIVE_PATH PACKAGE_RELATIVE_PATH "${absInstallDir}" "${CMAKE_INSTALL_PREFIX}" )
foreach(var ${CCF_PATH_VARS})
if(NOT DEFINED ${var})
message(FATAL_ERROR "Variable ${var} does not exist")
else()
if(forceAbsolutePaths)
if(IS_ABSOLUTE "${${var}}")
set(PACKAGE_${var} "${${var}}")
else()
set(PACKAGE_${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
endif()
else()
if(IS_ABSOLUTE "${${var}}")
string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${PACKAGE_PREFIX_DIR}"
@ -186,6 +203,7 @@ function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile)
set(PACKAGE_${var} "\${PACKAGE_PREFIX_DIR}/${${var}}")
endif()
endif()
endif()
endforeach()
get_filename_component(inputFileName "${_inputFile}" NAME)

761
Modules/ExternalData.cmake Normal file
View File

@ -0,0 +1,761 @@
# - Manage data files stored outside source tree
# Use this module to unambiguously reference data files stored outside the
# source tree and fetch them at build time from arbitrary local and remote
# content-addressed locations. Functions provided by this module recognize
# arguments with the syntax "DATA{<name>}" as references to external data,
# replace them with full paths to local copies of those data, and create build
# rules to fetch and update the local copies.
#
# The DATA{} syntax is literal and the <name> is a full or relative path
# within the source tree. The source tree must contain either a real data
# file at <name> or a "content link" at <name><ext> containing a hash of the
# real file using a hash algorithm corresponding to <ext>. For example, the
# argument "DATA{img.png}" may be satisfied by either a real "img.png" file in
# the current source directory or a "img.png.md5" file containing its MD5 sum.
#
# The 'ExternalData_Expand_Arguments' function evaluates DATA{} references
# in its arguments and constructs a new list of arguments:
# ExternalData_Expand_Arguments(
# <target> # Name of data management target
# <outVar> # Output variable
# [args...] # Input arguments, DATA{} allowed
# )
# It replaces each DATA{} reference in an argument with the full path of a
# real data file on disk that will exist after the <target> builds.
#
# The 'ExternalData_Add_Test' function wraps around the CMake add_test()
# command but supports DATA{} references in its arguments:
# ExternalData_Add_Test(
# <target> # Name of data management target
# ... # Arguments of add_test(), DATA{} allowed
# )
# It passes its arguments through ExternalData_Expand_Arguments and then
# invokes add_test() using the results.
#
# The 'ExternalData_Add_Target' function creates a custom target to manage
# local instances of data files stored externally:
# ExternalData_Add_Target(
# <target> # Name of data management target
# )
# It creates custom commands in the target as necessary to make data files
# available for each DATA{} reference previously evaluated by other functions
# provided by this module. A list of URL templates must be provided in the
# variable ExternalData_URL_TEMPLATES using the placeholders "%(algo)" and
# "%(hash)" in each template. Data fetch rules try each URL template in order
# by substituting the hash algorithm name for "%(algo)" and the hash value for
# "%(hash)".
#
# The following hash algorithms are supported:
# %(algo) <ext> Description
# ------- ----- -----------
# MD5 .md5 Message-Digest Algorithm 5, RFC 1321
# SHA1 .sha1 US Secure Hash Algorithm 1, RFC 3174
# SHA224 .sha224 US Secure Hash Algorithms, RFC 4634
# SHA256 .sha256 US Secure Hash Algorithms, RFC 4634
# SHA384 .sha384 US Secure Hash Algorithms, RFC 4634
# SHA512 .sha512 US Secure Hash Algorithms, RFC 4634
# Note that the hashes are used only for unique data identification and
# download verification. This is not security software.
#
# Example usage:
# include(ExternalData)
# set(ExternalData_URL_TEMPLATES "file:///local/%(algo)/%(hash)"
# "http://data.org/%(algo)/%(hash)")
# ExternalData_Add_Test(MyData
# NAME MyTest
# COMMAND MyExe DATA{MyInput.png}
# )
# ExternalData_Add_Target(MyData)
# When test "MyTest" runs the "DATA{MyInput.png}" argument will be replaced by
# the full path to a real instance of the data file "MyInput.png" on disk. If
# the source tree contains a content link such as "MyInput.png.md5" then the
# "MyData" target creates a real "MyInput.png" in the build tree.
#
# The DATA{} syntax can be told to fetch a file series using the form
# "DATA{<name>,:}", where the ":" is literal. If the source tree contains a
# group of files or content links named like a series then a reference to one
# member adds rules to fetch all of them. Although all members of a series
# are fetched, only the file originally named by the DATA{} argument is
# substituted for it. The default configuration recognizes file series names
# ending with "#.ext", "_#.ext", ".#.ext", or "-#.ext" where "#" is a sequence
# of decimal digits and ".ext" is any single extension. Configure it with a
# regex that parses <number> and <suffix> parts from the end of <name>:
# ExternalData_SERIES_PARSE = regex of the form (<number>)(<suffix>)$
# For more complicated cases set:
# ExternalData_SERIES_PARSE = regex with at least two () groups
# ExternalData_SERIES_PARSE_PREFIX = <prefix> regex group number, if any
# ExternalData_SERIES_PARSE_NUMBER = <number> regex group number
# ExternalData_SERIES_PARSE_SUFFIX = <suffix> regex group number
# Configure series number matching with a regex that matches the
# <number> part of series members named <prefix><number><suffix>:
# ExternalData_SERIES_MATCH = regex matching <number> in all series members
# Note that the <suffix> of a series does not include a hash-algorithm
# extension.
#
# The DATA{} syntax can alternatively match files associated with the named
# file and contained in the same directory. Associated files may be specified
# by options using the syntax DATA{<name>,<opt1>,<opt2>,...}. Each option may
# specify one file by name or specify a regular expression to match file names
# using the syntax REGEX:<regex>. For example, the arguments
# DATA{MyData/MyInput.mhd,MyInput.img} # File pair
# DATA{MyData/MyFrames00.png,REGEX:MyFrames[0-9]+\\.png} # Series
# will pass MyInput.mha and MyFrames00.png on the command line but ensure
# that the associated files are present next to them.
#
# The DATA{} syntax may reference a directory using a trailing slash and a
# list of associated files. The form DATA{<name>/,<opt1>,<opt2>,...} adds
# rules to fetch any files in the directory that match one of the associated
# file options. For example, the argument DATA{MyDataDir/,REGEX:.*} will pass
# the full path to a MyDataDir directory on the command line and ensure that
# the directory contains files corresponding to every file or content link in
# the MyDataDir source directory.
#
# The variable ExternalData_LINK_CONTENT may be set to the name of a supported
# hash algorithm to enable automatic conversion of real data files referenced
# by the DATA{} syntax into content links. For each such <file> a content
# link named "<file><ext>" is created. The original file is renamed to the
# form ".ExternalData_<algo>_<hash>" to stage it for future transmission to
# one of the locations in the list of URL templates (by means outside the
# scope of this module). The data fetch rule created for the content link
# will use the staged object if it cannot be found using any URL template.
#
# The variable ExternalData_OBJECT_STORES may be set to a list of local
# directories that store objects using the layout <dir>/%(algo)/%(hash).
# These directories will be searched first for a needed object. If the object
# is not available in any store then it will be fetched remotely using the URL
# templates and added to the first local store listed. If no stores are
# specified the default is a location inside the build tree.
#
# The variable ExternalData_SOURCE_ROOT may be set to the highest source
# directory containing any path named by a DATA{} reference. The default is
# CMAKE_SOURCE_DIR. ExternalData_SOURCE_ROOT and CMAKE_SOURCE_DIR must refer
# to directories within a single source distribution (e.g. they come together
# in one tarball).
#
# The variable ExternalData_BINARY_ROOT may be set to the directory to hold
# the real data files named by expanded DATA{} references. The default is
# CMAKE_BINARY_DIR. The directory layout will mirror that of content links
# under ExternalData_SOURCE_ROOT.
#
# Variables ExternalData_TIMEOUT_INACTIVITY and ExternalData_TIMEOUT_ABSOLUTE
# set the download inactivity and absolute timeouts, in seconds. The defaults
# are 60 seconds and 300 seconds, respectively. Set either timeout to 0
# seconds to disable enforcement.
#=============================================================================
# Copyright 2010-2013 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
function(ExternalData_add_test target)
ExternalData_expand_arguments("${target}" testArgs ${ARGN})
add_test(${testArgs})
endfunction()
function(ExternalData_add_target target)
if(NOT ExternalData_URL_TEMPLATES)
message(FATAL_ERROR "ExternalData_URL_TEMPLATES is not set!")
endif()
if(NOT ExternalData_OBJECT_STORES)
set(ExternalData_OBJECT_STORES ${CMAKE_BINARY_DIR}/ExternalData/Objects)
endif()
set(config ${CMAKE_CURRENT_BINARY_DIR}/${target}_config.cmake)
configure_file(${_ExternalData_SELF_DIR}/ExternalData_config.cmake.in ${config} @ONLY)
set(files "")
# Set "_ExternalData_FILE_${file}" for each output file to avoid duplicate
# rules. Use local data first to prefer real files over content links.
# Custom commands to copy or link local data.
get_property(data_local GLOBAL PROPERTY _ExternalData_${target}_LOCAL)
foreach(entry IN LISTS data_local)
string(REPLACE "|" ";" tuple "${entry}")
list(GET tuple 0 file)
list(GET tuple 1 name)
if(NOT DEFINED "_ExternalData_FILE_${file}")
set("_ExternalData_FILE_${file}" 1)
add_custom_command(
COMMENT "Generating ${file}"
OUTPUT "${file}"
COMMAND ${CMAKE_COMMAND} -Drelative_top=${CMAKE_BINARY_DIR}
-Dfile=${file} -Dname=${name}
-DExternalData_ACTION=local
-DExternalData_CONFIG=${config}
-P ${_ExternalData_SELF}
MAIN_DEPENDENCY "${name}"
)
list(APPEND files "${file}")
endif()
endforeach()
# Custom commands to fetch remote data.
get_property(data_fetch GLOBAL PROPERTY _ExternalData_${target}_FETCH)
foreach(entry IN LISTS data_fetch)
string(REPLACE "|" ";" tuple "${entry}")
list(GET tuple 0 file)
list(GET tuple 1 name)
list(GET tuple 2 ext)
set(stamp "${ext}-stamp")
if(NOT DEFINED "_ExternalData_FILE_${file}")
set("_ExternalData_FILE_${file}" 1)
add_custom_command(
# Users care about the data file, so hide the hash/timestamp file.
COMMENT "Generating ${file}"
# The hash/timestamp file is the output from the build perspective.
# List the real file as a second output in case it is a broken link.
# The files must be listed in this order so CMake can hide from the
# make tool that a symlink target may not be newer than the input.
OUTPUT "${file}${stamp}" "${file}"
# Run the data fetch/update script.
COMMAND ${CMAKE_COMMAND} -Drelative_top=${CMAKE_BINARY_DIR}
-Dfile=${file} -Dname=${name} -Dext=${ext}
-DExternalData_ACTION=fetch
-DExternalData_CONFIG=${config}
-P ${_ExternalData_SELF}
# Update whenever the object hash changes.
MAIN_DEPENDENCY "${name}${ext}"
)
list(APPEND files "${file}${stamp}")
endif()
endforeach()
# Custom target to drive all update commands.
add_custom_target(${target} ALL DEPENDS ${files})
endfunction()
function(ExternalData_expand_arguments target outArgsVar)
# Replace DATA{} references with real arguments.
set(data_regex "DATA{([^{}\r\n]*)}")
set(other_regex "([^D]|D[^A]|DA[^T]|DAT[^A]|DATA[^{])+|.")
set(outArgs "")
foreach(arg IN LISTS ARGN)
if("x${arg}" MATCHES "${data_regex}")
# Split argument into DATA{}-pieces and other pieces.
string(REGEX MATCHALL "${data_regex}|${other_regex}" pieces "${arg}")
# Compose output argument with DATA{}-pieces replaced.
set(outArg "")
foreach(piece IN LISTS pieces)
if("x${piece}" MATCHES "^x${data_regex}$")
# Replace this DATA{}-piece with a file path.
string(REGEX REPLACE "${data_regex}" "\\1" data "${piece}")
_ExternalData_arg("${target}" "${piece}" "${data}" file)
set(outArg "${outArg}${file}")
else()
# No replacement needed for this piece.
set(outArg "${outArg}${piece}")
endif()
endforeach()
list(APPEND outArgs "${outArg}")
else()
# No replacements needed in this argument.
list(APPEND outArgs "${arg}")
endif()
endforeach()
set("${outArgsVar}" "${outArgs}" PARENT_SCOPE)
endfunction()
#-----------------------------------------------------------------------------
# Private helper interface
set(_ExternalData_REGEX_ALGO "MD5|SHA1|SHA224|SHA256|SHA384|SHA512")
set(_ExternalData_REGEX_EXT "md5|sha1|sha224|sha256|sha384|sha512")
set(_ExternalData_SELF "${CMAKE_CURRENT_LIST_FILE}")
get_filename_component(_ExternalData_SELF_DIR "${_ExternalData_SELF}" PATH)
function(_ExternalData_compute_hash var_hash algo file)
if("${algo}" MATCHES "^${_ExternalData_REGEX_ALGO}$")
file("${algo}" "${file}" hash)
set("${var_hash}" "${hash}" PARENT_SCOPE)
else()
message(FATAL_ERROR "Hash algorithm ${algo} unimplemented.")
endif()
endfunction()
function(_ExternalData_random var)
string(RANDOM LENGTH 6 random)
set("${var}" "${random}" PARENT_SCOPE)
endfunction()
function(_ExternalData_exact_regex regex_var string)
string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" regex "${string}")
set("${regex_var}" "${regex}" PARENT_SCOPE)
endfunction()
function(_ExternalData_atomic_write file content)
_ExternalData_random(random)
set(tmp "${file}.tmp${random}")
file(WRITE "${tmp}" "${content}")
file(RENAME "${tmp}" "${file}")
endfunction()
function(_ExternalData_link_content name var_ext)
if("${ExternalData_LINK_CONTENT}" MATCHES "^(${_ExternalData_REGEX_ALGO})$")
set(algo "${ExternalData_LINK_CONTENT}")
else()
message(FATAL_ERROR
"Unknown hash algorithm specified by ExternalData_LINK_CONTENT:\n"
" ${ExternalData_LINK_CONTENT}")
endif()
_ExternalData_compute_hash(hash "${algo}" "${name}")
get_filename_component(dir "${name}" PATH)
set(staged "${dir}/.ExternalData_${algo}_${hash}")
string(TOLOWER ".${algo}" ext)
_ExternalData_atomic_write("${name}${ext}" "${hash}\n")
file(RENAME "${name}" "${staged}")
set("${var_ext}" "${ext}" PARENT_SCOPE)
file(RELATIVE_PATH relname "${ExternalData_SOURCE_ROOT}" "${name}${ext}")
message(STATUS "Linked ${relname} to ExternalData ${algo}/${hash}")
endfunction()
function(_ExternalData_arg target arg options var_file)
# Separate data path from the options.
string(REPLACE "," ";" options "${options}")
list(GET options 0 data)
list(REMOVE_AT options 0)
# Interpret trailing slashes as directories.
set(data_is_directory 0)
if("x${data}" MATCHES "^x(.*)([/\\])$")
set(data_is_directory 1)
set(data "${CMAKE_MATCH_1}")
endif()
# Convert to full path.
if(IS_ABSOLUTE "${data}")
set(absdata "${data}")
else()
set(absdata "${CMAKE_CURRENT_SOURCE_DIR}/${data}")
endif()
get_filename_component(absdata "${absdata}" ABSOLUTE)
# Convert to relative path under the source tree.
if(NOT ExternalData_SOURCE_ROOT)
set(ExternalData_SOURCE_ROOT "${CMAKE_SOURCE_DIR}")
endif()
set(top_src "${ExternalData_SOURCE_ROOT}")
file(RELATIVE_PATH reldata "${top_src}" "${absdata}")
if(IS_ABSOLUTE "${reldata}" OR "${reldata}" MATCHES "^\\.\\./")
message(FATAL_ERROR "Data file referenced by argument\n"
" ${arg}\n"
"does not lie under the top-level source directory\n"
" ${top_src}\n")
endif()
if(data_is_directory AND NOT IS_DIRECTORY "${top_src}/${reldata}")
message(FATAL_ERROR "Data directory referenced by argument\n"
" ${arg}\n"
"corresponds to source tree path\n"
" ${reldata}\n"
"that does not exist as a directory!")
endif()
if(NOT ExternalData_BINARY_ROOT)
set(ExternalData_BINARY_ROOT "${CMAKE_BINARY_DIR}")
endif()
set(top_bin "${ExternalData_BINARY_ROOT}")
# Handle in-source builds gracefully.
if("${top_src}" STREQUAL "${top_bin}")
if(ExternalData_LINK_CONTENT)
message(WARNING "ExternalData_LINK_CONTENT cannot be used in-source")
set(ExternalData_LINK_CONTENT 0)
endif()
set(top_same 1)
endif()
set(external "") # Entries external to the source tree.
set(internal "") # Entries internal to the source tree.
set(have_original ${data_is_directory})
# Process options.
set(series_option "")
set(associated_files "")
set(associated_regex "")
foreach(opt ${options})
if("x${opt}" MATCHES "^xREGEX:[^:/]+$")
# Regular expression to match associated files.
string(REGEX REPLACE "^REGEX:" "" regex "${opt}")
list(APPEND associated_regex "${regex}")
elseif("x${opt}" MATCHES "^x:$")
# Activate series matching.
set(series_option "${opt}")
elseif("x${opt}" MATCHES "^[^][:/*?]+$")
# Specific associated file.
list(APPEND associated_files "${opt}")
else()
message(FATAL_ERROR "Unknown option \"${opt}\" in argument\n"
" ${arg}\n")
endif()
endforeach()
if(series_option)
if(data_is_directory)
message(FATAL_ERROR "Series option \"${series_option}\" not allowed with directories.")
endif()
if(associated_files OR associated_regex)
message(FATAL_ERROR "Series option \"${series_option}\" not allowed with associated files.")
endif()
# Load a whole file series.
_ExternalData_arg_series()
elseif(data_is_directory)
if(associated_files OR associated_regex)
# Load listed/matching associated files in the directory.
_ExternalData_arg_associated()
else()
message(FATAL_ERROR "Data directory referenced by argument\n"
" ${arg}\n"
"must list associated files.")
endif()
else()
# Load the named data file.
_ExternalData_arg_single()
if(associated_files OR associated_regex)
# Load listed/matching associated files.
_ExternalData_arg_associated()
endif()
endif()
if(NOT have_original)
message(FATAL_ERROR "Data file referenced by argument\n"
" ${arg}\n"
"corresponds to source tree path\n"
" ${reldata}\n"
"that does not exist as a file (with or without an extension)!")
endif()
if(external)
# Make the series available in the build tree.
set_property(GLOBAL APPEND PROPERTY
_ExternalData_${target}_FETCH "${external}")
set_property(GLOBAL APPEND PROPERTY
_ExternalData_${target}_LOCAL "${internal}")
set("${var_file}" "${top_bin}/${reldata}" PARENT_SCOPE)
else()
# The whole series is in the source tree.
set("${var_file}" "${top_src}/${reldata}" PARENT_SCOPE)
endif()
endfunction()
macro(_ExternalData_arg_associated)
# Associated files lie in the same directory.
if(data_is_directory)
set(reldir "${reldata}")
else()
get_filename_component(reldir "${reldata}" PATH)
endif()
if(reldir)
set(reldir "${reldir}/")
endif()
_ExternalData_exact_regex(reldir_regex "${reldir}")
# Find files named explicitly.
foreach(file ${associated_files})
_ExternalData_exact_regex(file_regex "${file}")
_ExternalData_arg_find_files("${reldir}${file}" "${reldir_regex}${file_regex}")
endforeach()
# Find files matching the given regular expressions.
set(all "")
set(sep "")
foreach(regex ${associated_regex})
set(all "${all}${sep}${reldir_regex}${regex}")
set(sep "|")
endforeach()
_ExternalData_arg_find_files("${reldir}" "${all}")
endmacro()
macro(_ExternalData_arg_single)
# Match only the named data by itself.
_ExternalData_exact_regex(data_regex "${reldata}")
_ExternalData_arg_find_files("${reldata}" "${data_regex}")
endmacro()
macro(_ExternalData_arg_series)
# Configure series parsing and matching.
set(series_parse_prefix "")
set(series_parse_number "\\1")
set(series_parse_suffix "\\2")
if(ExternalData_SERIES_PARSE)
if(ExternalData_SERIES_PARSE_NUMBER AND ExternalData_SERIES_PARSE_SUFFIX)
if(ExternalData_SERIES_PARSE_PREFIX)
set(series_parse_prefix "\\${ExternalData_SERIES_PARSE_PREFIX}")
endif()
set(series_parse_number "\\${ExternalData_SERIES_PARSE_NUMBER}")
set(series_parse_suffix "\\${ExternalData_SERIES_PARSE_SUFFIX}")
elseif(NOT "x${ExternalData_SERIES_PARSE}" MATCHES "^x\\([^()]*\\)\\([^()]*\\)\\$$")
message(FATAL_ERROR
"ExternalData_SERIES_PARSE is set to\n"
" ${ExternalData_SERIES_PARSE}\n"
"which is not of the form\n"
" (<number>)(<suffix>)$\n"
"Fix the regular expression or set variables\n"
" ExternalData_SERIES_PARSE_PREFIX = <prefix> regex group number, if any\n"
" ExternalData_SERIES_PARSE_NUMBER = <number> regex group number\n"
" ExternalData_SERIES_PARSE_SUFFIX = <suffix> regex group number\n"
)
endif()
set(series_parse "${ExternalData_SERIES_PARSE}")
else()
set(series_parse "([0-9]*)(\\.[^./]*)$")
endif()
if(ExternalData_SERIES_MATCH)
set(series_match "${ExternalData_SERIES_MATCH}")
else()
set(series_match "[_.-]?[0-9]*")
endif()
# Parse the base, number, and extension components of the series.
string(REGEX REPLACE "${series_parse}" "${series_parse_prefix};${series_parse_number};${series_parse_suffix}" tuple "${reldata}")
list(LENGTH tuple len)
if(NOT "${len}" EQUAL 3)
message(FATAL_ERROR "Data file referenced by argument\n"
" ${arg}\n"
"corresponds to path\n"
" ${reldata}\n"
"that does not match regular expression\n"
" ${series_parse}")
endif()
list(GET tuple 0 relbase)
list(GET tuple 2 ext)
# Glob files that might match the series.
# Then match base, number, and extension.
_ExternalData_exact_regex(series_base "${relbase}")
_ExternalData_exact_regex(series_ext "${ext}")
_ExternalData_arg_find_files("${relbase}*${ext}"
"${series_base}${series_match}${series_ext}")
endmacro()
function(_ExternalData_arg_find_files pattern regex)
file(GLOB globbed RELATIVE "${top_src}" "${top_src}/${pattern}*")
foreach(entry IN LISTS globbed)
if("x${entry}" MATCHES "^x(.*)(\\.(${_ExternalData_REGEX_EXT}))$")
set(relname "${CMAKE_MATCH_1}")
set(alg "${CMAKE_MATCH_2}")
else()
set(relname "${entry}")
set(alg "")
endif()
if("x${relname}" MATCHES "^x${regex}$" AND NOT IS_DIRECTORY "${top_src}/${entry}")
set(name "${top_src}/${relname}")
set(file "${top_bin}/${relname}")
if(alg)
list(APPEND external "${file}|${name}|${alg}")
elseif(ExternalData_LINK_CONTENT)
_ExternalData_link_content("${name}" alg)
list(APPEND external "${file}|${name}|${alg}")
elseif(NOT top_same)
list(APPEND internal "${file}|${name}")
endif()
if("${relname}" STREQUAL "${reldata}")
set(have_original 1)
endif()
endif()
endforeach()
set(external "${external}" PARENT_SCOPE)
set(internal "${internal}" PARENT_SCOPE)
set(have_original "${have_original}" PARENT_SCOPE)
endfunction()
#-----------------------------------------------------------------------------
# Private script mode interface
if(CMAKE_GENERATOR OR NOT ExternalData_ACTION)
return()
endif()
if(ExternalData_CONFIG)
include(${ExternalData_CONFIG})
endif()
if(NOT ExternalData_URL_TEMPLATES)
message(FATAL_ERROR "No ExternalData_URL_TEMPLATES set!")
endif()
function(_ExternalData_link_or_copy src dst)
# Create a temporary file first.
get_filename_component(dst_dir "${dst}" PATH)
file(MAKE_DIRECTORY "${dst_dir}")
_ExternalData_random(random)
set(tmp "${dst}.tmp${random}")
if(UNIX)
# Create a symbolic link.
set(tgt "${src}")
if(relative_top)
# Use relative path if files are close enough.
file(RELATIVE_PATH relsrc "${relative_top}" "${src}")
file(RELATIVE_PATH relfile "${relative_top}" "${dst}")
if(NOT IS_ABSOLUTE "${relsrc}" AND NOT "${relsrc}" MATCHES "^\\.\\./" AND
NOT IS_ABSOLUTE "${reldst}" AND NOT "${reldst}" MATCHES "^\\.\\./")
file(RELATIVE_PATH tgt "${dst_dir}" "${src}")
endif()
endif()
execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${tgt}" "${tmp}" RESULT_VARIABLE result)
else()
# Create a copy.
execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${src}" "${tmp}" RESULT_VARIABLE result)
endif()
if(result)
file(REMOVE "${tmp}")
message(FATAL_ERROR "Failed to create\n ${tmp}\nfrom\n ${obj}")
endif()
# Atomically create/replace the real destination.
file(RENAME "${tmp}" "${dst}")
endfunction()
function(_ExternalData_download_file url file err_var msg_var)
set(retry 3)
while(retry)
math(EXPR retry "${retry} - 1")
if(ExternalData_TIMEOUT_INACTIVITY)
set(inactivity_timeout INACTIVITY_TIMEOUT ${ExternalData_TIMEOUT_INACTIVITY})
elseif(NOT "${ExternalData_TIMEOUT_INACTIVITY}" EQUAL 0)
set(inactivity_timeout INACTIVITY_TIMEOUT 60)
else()
set(inactivity_timeout "")
endif()
if(ExternalData_TIMEOUT_ABSOLUTE)
set(absolute_timeout TIMEOUT ${ExternalData_TIMEOUT_ABSOLUTE})
elseif(NOT "${ExternalData_TIMEOUT_ABSOLUTE}" EQUAL 0)
set(absolute_timeout TIMEOUT 300)
else()
set(absolute_timeout "")
endif()
file(DOWNLOAD "${url}" "${file}" STATUS status LOG log ${inactivity_timeout} ${absolute_timeout} SHOW_PROGRESS)
list(GET status 0 err)
list(GET status 1 msg)
if(err)
if("${msg}" MATCHES "HTTP response code said error" AND
"${log}" MATCHES "error: 503")
set(msg "temporarily unavailable")
endif()
elseif("${log}" MATCHES "\nHTTP[^\n]* 503")
set(err TRUE)
set(msg "temporarily unavailable")
endif()
if(NOT err OR NOT "${msg}" MATCHES "partial|timeout|temporarily")
break()
elseif(retry)
message(STATUS "[download terminated: ${msg}, retries left: ${retry}]")
endif()
endwhile()
set("${err_var}" "${err}" PARENT_SCOPE)
set("${msg_var}" "${msg}" PARENT_SCOPE)
endfunction()
function(_ExternalData_download_object name hash algo var_obj)
# Search all object stores for an existing object.
foreach(dir ${ExternalData_OBJECT_STORES})
set(obj "${dir}/${algo}/${hash}")
if(EXISTS "${obj}")
message(STATUS "Found object: \"${obj}\"")
set("${var_obj}" "${obj}" PARENT_SCOPE)
return()
endif()
endforeach()
# Download object to the first store.
list(GET ExternalData_OBJECT_STORES 0 store)
set(obj "${store}/${algo}/${hash}")
_ExternalData_random(random)
set(tmp "${obj}.tmp${random}")
set(found 0)
set(tried "")
foreach(url_template IN LISTS ExternalData_URL_TEMPLATES)
string(REPLACE "%(hash)" "${hash}" url_tmp "${url_template}")
string(REPLACE "%(algo)" "${algo}" url "${url_tmp}")
message(STATUS "Fetching \"${url}\"")
_ExternalData_download_file("${url}" "${tmp}" err errMsg)
set(tried "${tried}\n ${url}")
if(err)
set(tried "${tried} (${errMsg})")
else()
# Verify downloaded object.
_ExternalData_compute_hash(dl_hash "${algo}" "${tmp}")
if("${dl_hash}" STREQUAL "${hash}")
set(found 1)
break()
else()
set(tried "${tried} (wrong hash ${algo}=${dl_hash})")
if("$ENV{ExternalData_DEBUG_DOWNLOAD}" MATCHES ".")
file(RENAME "${tmp}" "${store}/${algo}/${dl_hash}")
endif()
endif()
endif()
file(REMOVE "${tmp}")
endforeach()
get_filename_component(dir "${name}" PATH)
set(staged "${dir}/.ExternalData_${algo}_${hash}")
if(found)
file(RENAME "${tmp}" "${obj}")
message(STATUS "Downloaded object: \"${obj}\"")
elseif(EXISTS "${staged}")
set(obj "${staged}")
message(STATUS "Staged object: \"${obj}\"")
else()
message(FATAL_ERROR "Object ${algo}=${hash} not found at:${tried}")
endif()
set("${var_obj}" "${obj}" PARENT_SCOPE)
endfunction()
if("${ExternalData_ACTION}" STREQUAL "fetch")
foreach(v ExternalData_OBJECT_STORES file name ext)
if(NOT DEFINED "${v}")
message(FATAL_ERROR "No \"-D${v}=\" value provided!")
endif()
endforeach()
file(READ "${name}${ext}" hash)
string(STRIP "${hash}" hash)
if("${ext}" MATCHES "^\\.(${_ExternalData_REGEX_EXT})$")
string(TOUPPER "${CMAKE_MATCH_1}" algo)
else()
message(FATAL_ERROR "Unknown hash algorithm extension \"${ext}\"")
endif()
_ExternalData_download_object("${name}" "${hash}" "${algo}" obj)
# Check if file already corresponds to the object.
set(stamp "${ext}-stamp")
set(file_up_to_date 0)
if(EXISTS "${file}" AND EXISTS "${file}${stamp}")
file(READ "${file}${stamp}" f_hash)
string(STRIP "${f_hash}" f_hash)
if("${f_hash}" STREQUAL "${hash}")
#message(STATUS "File already corresponds to object")
set(file_up_to_date 1)
endif()
endif()
if(file_up_to_date)
# Touch the file to convince the build system it is up to date.
execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${file}")
else()
_ExternalData_link_or_copy("${obj}" "${file}")
endif()
# Atomically update the hash/timestamp file to record the object referenced.
_ExternalData_atomic_write("${file}${stamp}" "${hash}\n")
elseif("${ExternalData_ACTION}" STREQUAL "local")
foreach(v file name)
if(NOT DEFINED "${v}")
message(FATAL_ERROR "No \"-D${v}=\" value provided!")
endif()
endforeach()
_ExternalData_link_or_copy("${name}" "${file}")
else()
message(FATAL_ERROR "Unknown ExternalData_ACTION=[${ExternalData_ACTION}]")
endif()

View File

@ -0,0 +1,4 @@
set(ExternalData_OBJECT_STORES "@ExternalData_OBJECT_STORES@")
set(ExternalData_URL_TEMPLATES "@ExternalData_URL_TEMPLATES@")
set(ExternalData_TIMEOUT_INACTIVITY "@ExternalData_TIMEOUT_INACTIVITY@")
set(ExternalData_TIMEOUT_ABSOLUTE "@ExternalData_TIMEOUT_ABSOLUTE@")

View File

@ -1559,8 +1559,11 @@ function(_ep_add_configure_command name)
set(file_deps)
get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
foreach(dep IN LISTS deps)
get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT)
if(is_ep)
_ep_get_step_stampfile(${dep} "done" done_stamp_file)
list(APPEND file_deps ${done_stamp_file})
endif()
endforeach()
get_property(cmd_set TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND SET)

View File

@ -439,28 +439,19 @@ list(APPEND GTK2_LIBRARIES ${FREETYPE_LIBRARIES})
foreach(_GTK2_component ${GTK2_FIND_COMPONENTS})
if(_GTK2_component STREQUAL "gtk")
_GTK2_FIND_INCLUDE_DIR(GTK2_GLIB_INCLUDE_DIR glib.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GLIBCONFIG_INCLUDE_DIR glibconfig.h)
_GTK2_FIND_LIBRARY (GTK2_GLIB_LIBRARY glib false true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GOBJECT_INCLUDE_DIR gobject/gobject.h)
_GTK2_FIND_LIBRARY (GTK2_GOBJECT_LIBRARY gobject false true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GDK_PIXBUF_INCLUDE_DIR gdk-pixbuf/gdk-pixbuf.h)
_GTK2_FIND_LIBRARY (GTK2_GDK_PIXBUF_LIBRARY gdk_pixbuf false true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GDK_INCLUDE_DIR gdk/gdk.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GDKCONFIG_INCLUDE_DIR gdkconfig.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GTK_INCLUDE_DIR gtk/gtk.h)
if(UNIX)
_GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-x11 false true)
_GTK2_FIND_LIBRARY (GTK2_GTK_LIBRARY gtk-x11 false true)
_GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-x11 false true)
else()
_GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-win32 false true)
_GTK2_FIND_LIBRARY (GTK2_GTK_LIBRARY gtk-win32 false true)
_GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-win32 false true)
endif()
_GTK2_FIND_INCLUDE_DIR(GTK2_GDK_INCLUDE_DIR gdk/gdk.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GDKCONFIG_INCLUDE_DIR gdkconfig.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_CAIRO_INCLUDE_DIR cairo.h)
_GTK2_FIND_LIBRARY (GTK2_CAIRO_LIBRARY cairo false false)
@ -469,35 +460,40 @@ foreach(_GTK2_component ${GTK2_FIND_COMPONENTS})
_GTK2_FIND_INCLUDE_DIR(GTK2_PANGO_INCLUDE_DIR pango/pango.h)
_GTK2_FIND_LIBRARY (GTK2_PANGO_LIBRARY pango false true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GDK_PIXBUF_INCLUDE_DIR gdk-pixbuf/gdk-pixbuf.h)
_GTK2_FIND_LIBRARY (GTK2_GDK_PIXBUF_LIBRARY gdk_pixbuf false true)
_GTK2_FIND_LIBRARY (GTK2_GIO_LIBRARY gio false true)
_GTK2_FIND_INCLUDE_DIR(GTK2_ATK_INCLUDE_DIR atk/atk.h)
_GTK2_FIND_LIBRARY (GTK2_ATK_LIBRARY atk false true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GOBJECT_INCLUDE_DIR gobject/gobject.h)
_GTK2_FIND_LIBRARY (GTK2_GOBJECT_LIBRARY gobject false true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GLIB_INCLUDE_DIR glib.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GLIBCONFIG_INCLUDE_DIR glibconfig.h)
_GTK2_FIND_LIBRARY (GTK2_GLIB_LIBRARY glib false true)
elseif(_GTK2_component STREQUAL "gtkmm")
_GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMM_INCLUDE_DIR glibmm.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMMCONFIG_INCLUDE_DIR glibmmconfig.h)
_GTK2_FIND_LIBRARY (GTK2_GLIBMM_LIBRARY glibmm true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GDKMM_INCLUDE_DIR gdkmm.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GDKMMCONFIG_INCLUDE_DIR gdkmmconfig.h)
_GTK2_FIND_LIBRARY (GTK2_GDKMM_LIBRARY gdkmm true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GTKMM_INCLUDE_DIR gtkmm.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GTKMMCONFIG_INCLUDE_DIR gtkmmconfig.h)
_GTK2_FIND_LIBRARY (GTK2_GTKMM_LIBRARY gtkmm true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMM_INCLUDE_DIR cairomm/cairomm.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMMCONFIG_INCLUDE_DIR cairommconfig.h)
_GTK2_FIND_LIBRARY (GTK2_CAIROMM_LIBRARY cairomm true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GDKMM_INCLUDE_DIR gdkmm.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GDKMMCONFIG_INCLUDE_DIR gdkmmconfig.h)
_GTK2_FIND_LIBRARY (GTK2_GDKMM_LIBRARY gdkmm true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMM_INCLUDE_DIR pangomm.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMMCONFIG_INCLUDE_DIR pangommconfig.h)
_GTK2_FIND_LIBRARY (GTK2_PANGOMM_LIBRARY pangomm true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++_INCLUDE_DIR sigc++/sigc++.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++CONFIG_INCLUDE_DIR sigc++config.h)
_GTK2_FIND_LIBRARY (GTK2_SIGC++_LIBRARY sigc true true)
_GTK2_FIND_LIBRARY (GTK2_PANGOCAIRO_LIBRARY pangocairo true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMM_INCLUDE_DIR cairomm/cairomm.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMMCONFIG_INCLUDE_DIR cairommconfig.h)
_GTK2_FIND_LIBRARY (GTK2_CAIROMM_LIBRARY cairomm true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GIOMM_INCLUDE_DIR giomm.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GIOMMCONFIG_INCLUDE_DIR giommconfig.h)
@ -506,6 +502,15 @@ foreach(_GTK2_component ${GTK2_FIND_COMPONENTS})
_GTK2_FIND_INCLUDE_DIR(GTK2_ATKMM_INCLUDE_DIR atkmm.h)
_GTK2_FIND_LIBRARY (GTK2_ATKMM_LIBRARY atkmm true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMM_INCLUDE_DIR glibmm.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMMCONFIG_INCLUDE_DIR glibmmconfig.h)
_GTK2_FIND_LIBRARY (GTK2_GLIBMM_LIBRARY glibmm true true)
_GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++_INCLUDE_DIR sigc++/sigc++.h)
_GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++CONFIG_INCLUDE_DIR sigc++config.h)
_GTK2_FIND_LIBRARY (GTK2_SIGC++_LIBRARY sigc true true)
elseif(_GTK2_component STREQUAL "glade")
_GTK2_FIND_INCLUDE_DIR(GTK2_GLADE_INCLUDE_DIR glade/glade.h)
@ -549,13 +554,13 @@ foreach(_GTK2_component ${GTK2_FIND_COMPONENTS})
GTK2_GTK_LIBRARY
GTK2_GTK_INCLUDE_DIR
GTK2_GLIB_INCLUDE_DIR
GTK2_GLIBCONFIG_INCLUDE_DIR
GTK2_GLIB_LIBRARY
GTK2_GDK_INCLUDE_DIR
GTK2_GDKCONFIG_INCLUDE_DIR
GTK2_GDK_LIBRARY
GTK2_GLIB_INCLUDE_DIR
GTK2_GLIBCONFIG_INCLUDE_DIR
GTK2_GLIB_LIBRARY
)
elseif(_GTK2_component STREQUAL "gtkmm")
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK2_${_COMPONENT_UPPER} "Some or all of the gtkmm libraries were not found."
@ -563,13 +568,14 @@ foreach(_GTK2_component ${GTK2_FIND_COMPONENTS})
GTK2_GTKMM_INCLUDE_DIR
GTK2_GTKMMCONFIG_INCLUDE_DIR
GTK2_GDKMM_INCLUDE_DIR
GTK2_GDKMMCONFIG_INCLUDE_DIR
GTK2_GDKMM_LIBRARY
GTK2_GLIBMM_INCLUDE_DIR
GTK2_GLIBMMCONFIG_INCLUDE_DIR
GTK2_GLIBMM_LIBRARY
GTK2_GDKMM_INCLUDE_DIR
GTK2_GDKMMCONFIG_INCLUDE_DIR
GTK2_GDKMM_LIBRARY
)
elseif(_GTK2_component STREQUAL "glade")
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK2_${_COMPONENT_UPPER} "The glade library was not found."

View File

@ -65,6 +65,12 @@
# is much more flexible, but requires that FindQt4.cmake is executed before
# such an exported dependency file is processed.
#
# Note that if using IMPORTED targets, the qtmain.lib static library is
# automatically linked on Windows. To disable that globally, set the
# QT4_NO_LINK_QTMAIN variable before finding Qt4. To disable that for a
# particular executable, set the QT4_NO_LINK_QTMAIN target property to
# True on the executable.
#
# QT_INCLUDE_DIRS_NO_SYSTEM
# If this variable is set to TRUE, the Qt include directories
# in the QT_USE_FILE will NOT have the SYSTEM keyword set.
@ -1009,7 +1015,14 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
# platform dependent libraries
if(Q_WS_WIN)
_QT4_ADJUST_LIB_VARS(qtmain)
_QT4_ADJUST_LIB_VARS(QAxServer)
set_property(TARGET Qt4::QAxServer PROPERTY
INTERFACE_QT4_NO_LINK_QTMAIN ON
)
set_property(TARGET Qt4::QAxServer APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL QT4_NO_LINK_QTMAIN)
_QT4_ADJUST_LIB_VARS(QAxContainer)
endif()
@ -1049,6 +1062,21 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
_qt4_add_target_private_depends(phonon DBus)
endif()
if (WIN32 AND NOT QT4_NO_LINK_QTMAIN)
set(_isExe $<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>)
set(_isWin32 $<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>)
set(_isNotExcluded $<NOT:$<BOOL:$<TARGET_PROPERTY:QT4_NO_LINK_QTMAIN>>>)
set(_isPolicyNEW $<TARGET_POLICY:CMP0020>)
set_property(TARGET Qt4::QtCore APPEND PROPERTY
IMPORTED_LINK_INTERFACE_LIBRARIES
$<$<AND:${_isExe},${_isWin32},${_isNotExcluded},${_isPolicyNEW}>:Qt4::qtmain>
)
unset(_isExe)
unset(_isWin32)
unset(_isNotExcluded)
unset(_isPolicyNEW)
endif()
#######################################
#
# Check the executables of Qt

View File

@ -41,6 +41,7 @@ set(WIN32 1)
if(CMAKE_SYSTEM_NAME MATCHES "WindowsCE")
set(CMAKE_CREATE_WIN32_EXE "/subsystem:windowsce /entry:WinMainCRTStartup")
set(CMAKE_CREATE_CONSOLE_EXE "/subsystem:windowsce /entry:mainACRTStartup")
set(WINCE 1)
else()
set(CMAKE_CREATE_WIN32_EXE "/subsystem:windows")
set(CMAKE_CREATE_CONSOLE_EXE "/subsystem:console")
@ -122,7 +123,7 @@ endif()
# default to Debug builds
set(CMAKE_BUILD_TYPE_INIT Debug)
if(CMAKE_SYSTEM_NAME MATCHES "WindowsCE")
if(WINCE)
string(TOUPPER "${MSVC_C_ARCHITECTURE_ID}" _MSVC_C_ARCHITECTURE_ID_UPPER)
string(TOUPPER "${MSVC_CXX_ARCHITECTURE_ID}" _MSVC_CXX_ARCHITECTURE_ID_UPPER)
@ -170,7 +171,7 @@ set(_MACHINE_ARCH_FLAG ${MSVC_C_ARCHITECTURE_ID})
if(NOT _MACHINE_ARCH_FLAG)
set(_MACHINE_ARCH_FLAG ${MSVC_CXX_ARCHITECTURE_ID})
endif()
if(CMAKE_SYSTEM_NAME MATCHES "WindowsCE")
if(WINCE)
if(_MACHINE_ARCH_FLAG MATCHES "ARM")
set(_MACHINE_ARCH_FLAG "THUMB")
elseif(_MACHINE_ARCH_FLAG MATCHES "SH")

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 20130118)
set(CMake_VERSION_TWEAK 20130205)
#set(CMake_VERSION_RC 1)

View File

@ -47,9 +47,24 @@
" $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \
" $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \
"\n" \
" $<TARGET_PROPERTY:tgt,prop> = The value of the property prop\n" \
"on the target tgt. Note that tgt is not added as a dependency of\n" \
"the target this expression is evaluated on.\n" \
" $<TARGET_PROPERTY:tgt,prop> = The value of the property prop " \
"on the target tgt.\n" \
"Note that tgt is not added as a dependency of the target this " \
"expression is evaluated on.\n" \
" $<LINKED:item> = An empty string if item is not a " \
"target. If item is a target then the " \
"INTERFACE_INCLUDE_DIRECTORIES or INTERFACE_COMPILE_DEFINITIONS " \
"content is read from the target. " \
"This generator expression can only be used in evaluation of the " \
"INCLUDE_DIRECTORIES or COMPILE_DEFINITIONS property. Note that " \
"this expression is for internal use and may be changed or removed " \
"in the future.\n" \
" $<TARGET_POLICY:pol> = '1' if the policy was NEW when " \
"the 'head' target was created, else '0'. If the policy was not " \
"set, the warning message for the policy will be emitted. This " \
"generator expression only works for a subset of policies.\n" \
" $<INSTALL_PREFIX> = Content of the install prefix when " \
"the target is exported via INSTALL(EXPORT) and empty otherwise.\n" \
"Boolean expressions:\n" \
" $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \
" $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \
@ -60,7 +75,7 @@
#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \
CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
"Expressions with an implicit 'this' target:\n" \
" $<TARGET_PROPERTY:prop> = The value of the property prop on\n" \
" $<TARGET_PROPERTY:prop> = The value of the property prop on " \
"the target on which the generator expression is evaluated.\n" \
""

View File

@ -74,6 +74,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
this->GenerateInterfaceProperties(te, os, properties);
}

View File

@ -21,9 +21,12 @@
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmVersion.h"
#include "cmComputeLinkInformation.h"
#include <cmsys/auto_ptr.hxx>
#include "assert.h"
//----------------------------------------------------------------------------
cmExportFileGenerator::cmExportFileGenerator()
{
@ -81,16 +84,16 @@ bool cmExportFileGenerator::GenerateImportFile()
// Protect that file against use with older CMake versions.
os << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
os << "IF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
<< " MESSAGE(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
<< "ENDIF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n";
os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
<< " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
<< "endif()\n";
// Isolate the file policy level.
// We use 2.6 here instead of the current version because newer
// versions of CMake should be able to export files imported by 2.6
// until the import format changes.
os << "CMAKE_POLICY(PUSH)\n"
<< "CMAKE_POLICY(VERSION 2.6)\n";
os << "cmake_policy(PUSH)\n"
<< "cmake_policy(VERSION 2.6)\n";
// Start with the import file header.
this->GenerateImportHeaderCode(os);
@ -100,7 +103,7 @@ bool cmExportFileGenerator::GenerateImportFile()
// End with the import file footer.
this->GenerateImportFooterCode(os);
os << "CMAKE_POLICY(POP)\n";
os << "cmake_policy(POP)\n";
return result;
}
@ -159,7 +162,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
preprocessRule);
if (!prepro.empty())
{
this->ResolveTargetsInGeneratorExpressions(prepro, target,
this->ResolveTargetsInGeneratorExpressions(prepro, target, propName,
missingTargets);
properties[outputName] = prepro;
}
@ -177,6 +180,85 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
properties, missingTargets);
}
//----------------------------------------------------------------------------
void getPropertyContents(cmTarget *tgt, const char *prop,
std::set<std::string> &ifaceProperties)
{
const char *p = tgt->GetProperty(prop);
if (!p)
{
return;
}
std::vector<std::string> content;
cmSystemTools::ExpandListArgument(p, content);
for (std::vector<std::string>::const_iterator ci = content.begin();
ci != content.end(); ++ci)
{
ifaceProperties.insert(*ci);
}
}
//----------------------------------------------------------------------------
void getCompatibleInterfaceProperties(cmTarget *target,
std::set<std::string> &ifaceProperties,
const char *config)
{
cmComputeLinkInformation *info = target->GetLinkInformation(config);
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator li =
deps.begin();
li != deps.end(); ++li)
{
if (!li->Target)
{
continue;
}
getPropertyContents(li->Target,
"COMPATIBLE_INTERFACE_BOOL",
ifaceProperties);
getPropertyContents(li->Target,
"COMPATIBLE_INTERFACE_STRING",
ifaceProperties);
}
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
cmTarget *target,
ImportPropertyMap &properties)
{
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL",
target, properties);
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING",
target, properties);
std::set<std::string> ifaceProperties;
getPropertyContents(target, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties);
getPropertyContents(target, "COMPATIBLE_INTERFACE_STRING", ifaceProperties);
getCompatibleInterfaceProperties(target, ifaceProperties, 0);
std::vector<std::string> configNames;
target->GetMakefile()->GetConfigurations(configNames);
for (std::vector<std::string>::const_iterator ci = configNames.begin();
ci != configNames.end(); ++ci)
{
getCompatibleInterfaceProperties(target, ifaceProperties, ci->c_str());
}
for (std::set<std::string>::const_iterator it = ifaceProperties.begin();
it != ifaceProperties.end(); ++it)
{
this->PopulateInterfaceProperty(("INTERFACE_" + *it).c_str(),
target, properties);
}
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
std::ostream& os,
@ -184,15 +266,16 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
{
if (!properties.empty())
{
os << "if(NOT ${CMAKE_FIND_PACKAGE_NAME}_NO_INTERFACES)\n";
std::string targetName = this->Namespace;
targetName += target->GetName();
os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
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";
os << " )\nendif()\n\n";
}
}
@ -243,13 +326,14 @@ static bool isGeneratorExpression(const std::string &lib)
void
cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
std::string &input,
cmTarget* target,
cmTarget* target, const char *propName,
std::vector<std::string> &missingTargets,
FreeTargetsReplace replace)
{
if (replace == NoReplaceFreeTargets)
{
this->ResolveTargetsInGeneratorExpression(input, target, missingTargets);
this->ResolveTargetsInGeneratorExpression(input, target, propName,
missingTargets);
return;
}
std::vector<std::string> parts;
@ -268,7 +352,7 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
{
this->ResolveTargetsInGeneratorExpression(
*li,
target,
target, propName,
missingTargets);
}
input += sep + *li;
@ -280,14 +364,13 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
void
cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
std::string &input,
cmTarget* target,
cmTarget* target, const char *propName,
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)
{
@ -308,14 +391,58 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
std::string targetName = input.substr(nameStartPos,
commaPos - nameStartPos);
if (!this->AddTargetNamespace(targetName, target, missingTargets))
if (this->AddTargetNamespace(targetName, target, missingTargets))
{
errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires "
"its first parameter to be a reachable target.";
input.replace(nameStartPos, commaPos - nameStartPos, targetName);
}
lastPos = nameStartPos + targetName.size() + 1;
}
std::string errorString;
pos = 0;
lastPos = pos;
while((pos = input.find("$<LINKED:", lastPos)) != input.npos)
{
std::string::size_type nameStartPos = pos + sizeof("$<LINKED:") - 1;
std::string::size_type endPos = input.find(">", nameStartPos);
if (endPos == input.npos)
{
errorString = "$<LINKED:...> expression incomplete";
break;
}
input.replace(nameStartPos, commaPos - nameStartPos, targetName);
lastPos = pos + targetName.size();
std::string targetName = input.substr(nameStartPos,
endPos - nameStartPos);
if(targetName.find("$<") != input.npos)
{
errorString = "$<LINKED:...> requires its parameter to be a "
"literal.";
break;
}
if (this->AddTargetNamespace(targetName, target, missingTargets))
{
assert(propName); // The link libraries strings will
// never contain $<LINKED>
std::string replacement = "$<TARGET_PROPERTY:"
+ targetName + "," + propName;
input.replace(pos, endPos - pos, replacement);
lastPos = pos + replacement.size() + 1;
}
else
{
if (pos != 0)
{
if (input[pos - 1] == ';')
{
--pos;
}
}
else if (input[endPos + 1] == ';')
{
++endPos;
}
input.replace(pos, endPos - pos + 1, "");
lastPos = pos;
}
}
if (!errorString.empty())
{
@ -351,12 +478,22 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
input.replace(pos, endPos - pos + 1, targetName);
lastPos = endPos;
}
this->ReplaceInstallPrefix(input);
if (!errorString.empty())
{
mf->IssueMessage(cmake::FATAL_ERROR, errorString);
}
}
//----------------------------------------------------------------------------
void
cmExportFileGenerator::ReplaceInstallPrefix(std::string &)
{
// Do nothing
}
//----------------------------------------------------------------------------
void
cmExportFileGenerator
@ -408,7 +545,7 @@ cmExportFileGenerator
preprocessRule);
if (!prepro.empty())
{
this->ResolveTargetsInGeneratorExpressions(prepro, target,
this->ResolveTargetsInGeneratorExpressions(prepro, target, 0,
missingTargets,
ReplaceFreeTargets);
properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
@ -536,7 +673,7 @@ void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
{
os << "# Commands beyond this point should not need to know the version.\n"
<< "SET(CMAKE_IMPORT_FILE_VERSION)\n";
<< "set(CMAKE_IMPORT_FILE_VERSION)\n";
}
//----------------------------------------------------------------------------
@ -545,7 +682,7 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
// Store an import file format version. This will let us change the
// format later while still allowing old import files to work.
os << "# Commands may need to know the format version.\n"
<< "SET(CMAKE_IMPORT_FILE_VERSION 1)\n"
<< "set(CMAKE_IMPORT_FILE_VERSION 1)\n"
<< "\n";
}
@ -553,31 +690,31 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os,
const std::string &expectedTargets)
{
os << "SET(_targetsDefined)\n"
"SET(_targetsNotDefined)\n"
"SET(_expectedTargets)\n"
"FOREACH(_expectedTarget " << expectedTargets << ")\n"
" LIST(APPEND _expectedTargets ${_expectedTarget})\n"
" IF(NOT TARGET ${_expectedTarget})\n"
" LIST(APPEND _targetsNotDefined ${_expectedTarget})\n"
" ENDIF(NOT TARGET ${_expectedTarget})\n"
" IF(TARGET ${_expectedTarget})\n"
" LIST(APPEND _targetsDefined ${_expectedTarget})\n"
" ENDIF(TARGET ${_expectedTarget})\n"
"ENDFOREACH(_expectedTarget)\n"
"IF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
" SET(CMAKE_IMPORT_FILE_VERSION)\n"
" CMAKE_POLICY(POP)\n"
" RETURN()\n"
"ENDIF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
"IF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
" MESSAGE(FATAL_ERROR \"Some (but not all) targets in this export "
os << "set(_targetsDefined)\n"
"set(_targetsNotDefined)\n"
"set(_expectedTargets)\n"
"foreach(_expectedTarget " << expectedTargets << ")\n"
" list(APPEND _expectedTargets ${_expectedTarget})\n"
" if(NOT TARGET ${_expectedTarget})\n"
" list(APPEND _targetsNotDefined ${_expectedTarget})\n"
" endif()\n"
" if(TARGET ${_expectedTarget})\n"
" list(APPEND _targetsDefined ${_expectedTarget})\n"
" endif()\n"
"endforeach()\n"
"if(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
" set(CMAKE_IMPORT_FILE_VERSION)\n"
" cmake_policy(POP)\n"
" return()\n"
"endif()\n"
"if(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
" message(FATAL_ERROR \"Some (but not all) targets in this export "
"set were already defined.\\nTargets Defined: ${_targetsDefined}\\n"
"Targets not yet defined: ${_targetsNotDefined}\\n\")\n"
"ENDIF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
"UNSET(_targetsDefined)\n"
"UNSET(_targetsNotDefined)\n"
"UNSET(_expectedTargets)\n"
"endif()\n"
"unset(_targetsDefined)\n"
"unset(_targetsNotDefined)\n"
"unset(_expectedTargets)\n"
"\n\n";
}
//----------------------------------------------------------------------------
@ -594,16 +731,16 @@ cmExportFileGenerator
switch(target->GetType())
{
case cmTarget::EXECUTABLE:
os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n";
os << "add_executable(" << targetName << " IMPORTED)\n";
break;
case cmTarget::STATIC_LIBRARY:
os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n";
os << "add_library(" << targetName << " STATIC IMPORTED)\n";
break;
case cmTarget::SHARED_LIBRARY:
os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n";
os << "add_library(" << targetName << " SHARED IMPORTED)\n";
break;
case cmTarget::MODULE_LIBRARY:
os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n";
os << "add_library(" << targetName << " MODULE IMPORTED)\n";
break;
default: // should never happen
break;
@ -612,27 +749,27 @@ cmExportFileGenerator
// Mark the imported executable if it has exports.
if(target->IsExecutableWithExports())
{
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " PROPERTY ENABLE_EXPORTS 1)\n";
}
// Mark the imported library if it is a framework.
if(target->IsFrameworkOnApple())
{
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " PROPERTY FRAMEWORK 1)\n";
}
// Mark the imported executable if it is an application bundle.
if(target->IsAppBundleOnApple())
{
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " PROPERTY MACOSX_BUNDLE 1)\n";
}
if (target->IsCFBundleOnApple())
{
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " PROPERTY BUNDLE 1)\n";
}
os << "\n";
@ -652,7 +789,7 @@ cmExportFileGenerator
// Set the import properties.
os << "# Import target \"" << targetName << "\" for configuration \""
<< config << "\"\n";
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
if(config && *config)
{
@ -663,7 +800,7 @@ cmExportFileGenerator
os << "NOCONFIG";
}
os << ")\n";
os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
os << "set_target_properties(" << targetName << " PROPERTIES\n";
for(ImportPropertyMap::const_iterator pi = properties.begin();
pi != properties.end(); ++pi)
{
@ -689,17 +826,17 @@ void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
{
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 "
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 \\\""
<< " else()\n"
<< " message(FATAL_ERROR \"Required imported target \\\""
<< missingTargets[i] << "\\\" not found ! \")\n"
<< " ENDIF()\n"
<< "ENDIF()\n";
<< " endif()\n"
<< "endif()\n";
}
}
os << "\n";
@ -718,10 +855,10 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
// on SUSE with a mysql pkg-config file, which claimed everything is fine,
// but the development package was not installed.).
os << "# Loop over all imported files and verify that they actually exist\n"
"FOREACH(target ${_IMPORT_CHECK_TARGETS} )\n"
" FOREACH(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
" IF(NOT EXISTS \"${file}\" )\n"
" MESSAGE(FATAL_ERROR \"The imported target \\\"${target}\\\""
"foreach(target ${_IMPORT_CHECK_TARGETS} )\n"
" foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
" if(NOT EXISTS \"${file}\" )\n"
" message(FATAL_ERROR \"The imported target \\\"${target}\\\""
" references the file\n"
" \\\"${file}\\\"\n"
"but this file does not exist. Possible reasons include:\n"
@ -731,11 +868,11 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
" \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n"
"but not all the files it references.\n"
"\")\n"
" ENDIF()\n"
" ENDFOREACH()\n"
" UNSET(_IMPORT_CHECK_FILES_FOR_${target})\n"
"ENDFOREACH()\n"
"UNSET(_IMPORT_CHECK_TARGETS)\n"
" endif()\n"
" endforeach()\n"
" unset(_IMPORT_CHECK_FILES_FOR_${target})\n"
"endforeach()\n"
"unset(_IMPORT_CHECK_TARGETS)\n"
"\n";
}
@ -751,8 +888,8 @@ cmExportFileGenerator
std::string targetName = this->Namespace;
targetName += target->GetName();
os << "LIST(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
"LIST(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
"list(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
for(std::set<std::string>::const_iterator li = importedLocations.begin();
li != importedLocations.end();

View File

@ -103,6 +103,8 @@ protected:
std::vector<std::string> &missingTargets);
void PopulateInterfaceProperty(const char *propName, cmTarget *target,
ImportPropertyMap &properties);
void PopulateCompatibleInterfaceProperties(cmTarget *target,
ImportPropertyMap &properties);
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
const ImportPropertyMap &properties);
@ -117,7 +119,7 @@ protected:
};
void ResolveTargetsInGeneratorExpressions(std::string &input,
cmTarget* target,
cmTarget* target, const char *propName,
std::vector<std::string> &missingTargets,
FreeTargetsReplace replace = NoReplaceFreeTargets);
@ -148,8 +150,10 @@ private:
std::vector<std::string> &missingTargets);
void ResolveTargetsInGeneratorExpression(std::string &input,
cmTarget* target,
cmTarget* target, const char *propName,
std::vector<std::string> &missingTargets);
virtual void ReplaceInstallPrefix(std::string &input);
};
#endif

View File

@ -57,7 +57,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
else
{
cmOStringStream e;
e << "INSTALL(EXPORT \""
e << "install(EXPORT \""
<< this->IEGen->GetExportSet()->GetName()
<< "\" ...) " << "includes target \"" << te->Target->GetName()
<< "\" more than once in the export set.";
@ -69,6 +69,27 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->GenerateExpectedTargetsCode(os, expectedTargets);
}
// Add code to compute the installation prefix relative to the
// import file location.
const char* installDest = this->IEGen->GetDestination();
if(!cmSystemTools::FileIsFullPath(installDest))
{
std::string dest = installDest;
os << "# Compute the installation prefix relative to this file.\n"
<< "get_filename_component(_IMPORT_PREFIX "
<< "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
while(!dest.empty())
{
os <<
"get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
dest = cmSystemTools::GetFilenamePath(dest);
}
os << "\n";
// Import location properties may reference this variable.
this->ImportPrefix = "${_IMPORT_PREFIX}/";
}
std::vector<std::string> missingTargets;
// Create all the imported targets.
@ -91,6 +112,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
this->GenerateInterfaceProperties(te, os, properties);
}
@ -98,14 +120,21 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
// 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"
<< "FILE(GLOB CONFIG_FILES \"${_DIR}/"
<< "get_filename_component(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
<< "file(GLOB CONFIG_FILES \"${_DIR}/"
<< this->GetConfigImportFileGlob() << "\")\n"
<< "FOREACH(f ${CONFIG_FILES})\n"
<< " INCLUDE(${f})\n"
<< "ENDFOREACH(f)\n"
<< "foreach(f ${CONFIG_FILES})\n"
<< " include(${f})\n"
<< "endforeach()\n"
<< "\n";
// Cleanup the import prefix variable.
if(!this->ImportPrefix.empty())
{
os << "# Cleanup temporary variables.\n"
<< "set(_IMPORT_PREFIX)\n"
<< "\n";
}
this->GenerateImportedFileCheckLoop(os);
// Generate an import file for each configuration.
@ -125,6 +154,21 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
return result;
}
//----------------------------------------------------------------------------
void
cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string &input)
{
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
while((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != input.npos)
{
std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1;
input.replace(pos, endPos - pos, "${_IMPORT_PREFIX}");
lastPos = endPos;
}
}
//----------------------------------------------------------------------------
bool
cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config,
@ -186,27 +230,6 @@ cmExportInstallFileGenerator
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.
const char* installDest = this->IEGen->GetDestination();
if(!cmSystemTools::FileIsFullPath(installDest))
{
std::string dest = installDest;
os << "# Compute the installation prefix relative to this file.\n"
<< "GET_FILENAME_COMPONENT(_IMPORT_PREFIX "
<< "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
while(!dest.empty())
{
os <<
"GET_FILENAME_COMPONENT(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
dest = cmSystemTools::GetFilenamePath(dest);
}
os << "\n";
// Import location properties may reference this variable.
this->ImportPrefix = "${_IMPORT_PREFIX}/";
}
// Add each target in the set to the export.
for(std::vector<cmTargetExport*>::const_iterator
tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
@ -252,14 +275,6 @@ cmExportInstallFileGenerator
importedLocations);
}
}
// Cleanup the import prefix variable.
if(!this->ImportPrefix.empty())
{
os << "# Cleanup temporary variables.\n"
<< "SET(_IMPORT_PREFIX)\n"
<< "\n";
}
}
//----------------------------------------------------------------------------
@ -427,7 +442,7 @@ cmExportInstallFileGenerator
{
const char* installDest = this->IEGen->GetDestination();
cmOStringStream e;
e << "INSTALL(EXPORT \""
e << "install(EXPORT \""
<< this->IEGen->GetExportSet()->GetName()
<< "\") given absolute "
<< "DESTINATION \"" << installDest << "\" but the export "
@ -445,7 +460,7 @@ cmExportInstallFileGenerator
int occurrences)
{
cmOStringStream e;
e << "INSTALL(EXPORT \""
e << "install(EXPORT \""
<< this->IEGen->GetExportSet()->GetName()
<< "\" ...) "
<< "includes target \"" << depender->GetName()

View File

@ -64,6 +64,8 @@ protected:
cmTarget* depender,
cmTarget* dependee);
virtual void ReplaceInstallPrefix(std::string &input);
void ComplainAboutMissingTarget(cmTarget* depender,
cmTarget* dependee,
int occurrences);

View File

@ -621,7 +621,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
->GetGeneratorTarget(target);
// the compilerdefines for this target
std::string cdefs = gtgt->GetCompileDefinitions();
std::string cdefs = target->GetCompileDefinitions();
if(!cdefs.empty())
{

View File

@ -37,9 +37,13 @@ bool cmFLTKWrapUICommand
// get the list of GUI files from which .cxx and .h will be generated
std::string outputDirectory = this->Makefile->GetCurrentOutputDirectory();
{
// Some of the generated files are *.h so the directory "GUI"
// where they are created have to be added to the include path
this->Makefile->AddIncludeDirectory( outputDirectory.c_str() );
std::vector<std::string> outputDirectories;
outputDirectories.push_back(outputDirectory);
this->Makefile->AddIncludeDirectories( outputDirectories );
}
for(std::vector<std::string>::iterator i = (newArgs.begin() + 1);
i != newArgs.end(); i++)

View File

@ -376,6 +376,26 @@ void cmFindPackageCommand::GenerateDocumentation()
"The package configuration file may set <package>_FOUND to false "
"to tell find_package that component requirements are not satisfied."
"\n"
"A package configuration file may include() a <package>Targets.cmake "
"file, created by install(EXPORT) in the upstream source, to import "
"targets into the downstream consumer. "
"When a new version of the upstream adds INTERFACE properties not "
"present in a previous version it can change behavior for existing "
"downstreams. "
"In order to remain source compatible the upstream package configuration "
"file may set <package>_NO_INTERFACES to disable INTERFACE properties. "
"For example, code of the form:\n"
" if(<package>_FIND_VERSION VERSION_LESS <new-version>\n"
" AND NOT <package>_INTERFACES)\n"
" set(<package>_NO_INTERFACES 1)\n"
" endif()\n"
" include(\"${CMAKE_CURRENT_LIST_DIR}/<package>Targets.cmake\")\n"
"tells <package>Targets.cmake not to provide the INTERFACE properties "
"unless the downstream requests at least <new-version> or sets "
"<package>_INTERFACES to explicitly request them. "
"This allows consumers to decide when to enable the new interfaces when "
"upgrading."
"\n"
"See the cmake_policy() command documentation for discussion of the "
"NO_POLICY_SCOPE option."
;

View File

@ -88,6 +88,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
context.Config = config;
context.Quiet = quiet;
context.HadError = false;
context.HadContextSensitiveCondition = false;
context.HeadTarget = headTarget;
context.CurrentTarget = currentTarget ? currentTarget : headTarget;
context.Backtrace = this->Backtrace;
@ -109,6 +110,10 @@ const char *cmCompiledGeneratorExpression::Evaluate(
break;
}
}
if (!context.HadError)
{
this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
}
this->Targets = context.Targets;
// TODO: Return a std::string from here instead?
@ -118,7 +123,8 @@ const char *cmCompiledGeneratorExpression::Evaluate(
cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
cmListFileBacktrace const& backtrace,
const char *input)
: Backtrace(backtrace), Input(input ? input : "")
: Backtrace(backtrace), Input(input ? input : ""),
HadContextSensitiveCondition(false)
{
cmGeneratorExpressionLexer l;
std::vector<cmGeneratorExpressionToken> tokens =

View File

@ -100,6 +100,10 @@ public:
{
return this->Backtrace;
}
bool GetHadContextSensitiveCondition() const
{
return this->HadContextSensitiveCondition;
}
private:
cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
@ -118,6 +122,7 @@ private:
mutable std::set<cmTarget*> Targets;
mutable std::map<cmStdString, cmStdString> SeenTargetProperties;
mutable std::string Output;
mutable bool HadContextSensitiveCondition;
};
#endif

View File

@ -24,7 +24,33 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
: Parent(parent), Target(target), Property(property),
Content(content), Backtrace(backtrace)
{
const cmGeneratorExpressionDAGChecker *top = this;
const cmGeneratorExpressionDAGChecker *p = this->Parent;
while (p)
{
top = p;
p = p->Parent;
}
this->CheckResult = this->checkGraph();
if (CheckResult == DAG && (top->Property == "INCLUDE_DIRECTORIES"
|| top->Property == "COMPILE_DEFINITIONS") )
{
std::map<cmStdString, std::set<cmStdString> >::const_iterator it
= top->Seen.find(target);
if (it != top->Seen.end())
{
const std::set<cmStdString> &propSet = it->second;
const std::set<cmStdString>::const_iterator i = propSet.find(property);
if (i != propSet.end())
{
this->CheckResult = ALREADY_SEEN;
return;
}
}
const_cast<cmGeneratorExpressionDAGChecker *>(top)
->Seen[target].insert(property);
}
}
//----------------------------------------------------------------------------
@ -106,3 +132,38 @@ cmGeneratorExpressionDAGChecker::checkGraph() const
}
return DAG;
}
//----------------------------------------------------------------------------
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries()
{
const cmGeneratorExpressionDAGChecker *top = this;
const cmGeneratorExpressionDAGChecker *parent = this->Parent;
while (parent)
{
top = parent;
parent = parent->Parent;
}
const char *prop = top->Property.c_str();
return (strcmp(prop, "LINK_LIBRARIES") == 0
|| strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0
|| strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
|| strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 26) == 0
|| strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 35) == 0);
}
//----------------------------------------------------------------------------
bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories()
{
const char *prop = this->Property.c_str();
return (strcmp(prop, "INCLUDE_DIRECTORIES") == 0
|| strcmp(prop, "INTERFACE_INCLUDE_DIRECTORIES") == 0 );
}
//----------------------------------------------------------------------------
bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions()
{
const char *prop = this->Property.c_str();
return (strcmp(prop, "COMPILE_DEFINITIONS") == 0
|| strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0 );
}

View File

@ -28,13 +28,19 @@ struct cmGeneratorExpressionDAGChecker
enum Result {
DAG,
SELF_REFERENCE,
CYCLIC_REFERENCE
CYCLIC_REFERENCE,
ALREADY_SEEN
};
Result check() const;
void reportError(cmGeneratorExpressionContext *context,
const std::string &expr);
bool EvaluatingLinkLibraries();
bool EvaluatingIncludeDirectories();
bool EvaluatingCompileDefinitions();
private:
Result checkGraph() const;
@ -42,6 +48,7 @@ private:
const cmGeneratorExpressionDAGChecker * const Parent;
const std::string Target;
const std::string Property;
std::map<cmStdString, std::set<cmStdString> > Seen;
const GeneratorExpressionContent * const Content;
const cmListFileBacktrace Backtrace;
Result CheckResult;

View File

@ -238,6 +238,7 @@ static const struct ConfigurationNode : public cmGeneratorExpressionNode
const GeneratorExpressionContent *,
cmGeneratorExpressionDAGChecker *) const
{
context->HadContextSensitiveCondition = true;
return context->Config ? context->Config : "";
}
} configurationNode;
@ -262,6 +263,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
"Expression syntax not recognized.");
return std::string();
}
context->HadContextSensitiveCondition = true;
if (!context->Config)
{
return parameters.front().empty() ? "1" : "0";
@ -435,6 +437,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
// No error. We just skip cyclic references.
return std::string();
case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
// No error. We're not going to find anything new here.
return std::string();
case cmGeneratorExpressionDAGChecker::DAG:
break;
}
@ -442,6 +447,39 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
const char *prop = target->GetProperty(propertyName.c_str());
if (!prop)
{
if (target->IsImported())
{
return std::string();
}
if (dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
{
return std::string();
}
if (propertyName == "POSITION_INDEPENDENT_CODE")
{
context->HadContextSensitiveCondition = true;
return target->GetLinkInterfaceDependentBoolProperty(
"POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0";
}
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
context->Config))
{
context->HadContextSensitiveCondition = true;
return target->GetLinkInterfaceDependentBoolProperty(
propertyName,
context->Config) ? "1" : "0";
}
if (target->IsLinkInterfaceDependentStringProperty(propertyName,
context->Config))
{
context->HadContextSensitiveCondition = true;
const char *propContent =
target->GetLinkInterfaceDependentStringProperty(
propertyName,
context->Config);
return propContent ? propContent : "";
}
return std::string();
}
@ -453,12 +491,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
if (targetPropertyTransitiveWhitelist[i] == propertyName)
{
cmGeneratorExpression ge(context->Backtrace);
return ge.Parse(prop)->Evaluate(context->Makefile,
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
std::string result = cge->Evaluate(context->Makefile,
context->Config,
context->Quiet,
context->HeadTarget,
target,
&dagChecker);
if (cge->GetHadContextSensitiveCondition())
{
context->HadContextSensitiveCondition = true;
}
return result;
}
}
return prop;
@ -487,6 +532,221 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
} targetNameNode;
//----------------------------------------------------------------------------
static const char* targetPolicyWhitelist[] = {
"CMP0003"
, "CMP0004"
, "CMP0008"
, "CMP0020"
};
cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy)
{
#define RETURN_POLICY(POLICY) \
if (strcmp(policy, #POLICY) == 0) \
{ \
return tgt->GetPolicyStatus ## POLICY (); \
} \
RETURN_POLICY(CMP0003)
RETURN_POLICY(CMP0004)
RETURN_POLICY(CMP0008)
RETURN_POLICY(CMP0020)
#undef RETURN_POLICY
assert("!Unreachable code. Not a valid policy");
return cmPolicies::WARN;
}
cmPolicies::PolicyID policyForString(const char *policy_id)
{
#define RETURN_POLICY_ID(POLICY_ID) \
if (strcmp(policy_id, #POLICY_ID) == 0) \
{ \
return cmPolicies:: POLICY_ID; \
} \
RETURN_POLICY_ID(CMP0003)
RETURN_POLICY_ID(CMP0004)
RETURN_POLICY_ID(CMP0008)
RETURN_POLICY_ID(CMP0020)
#undef RETURN_POLICY_ID
assert("!Unreachable code. Not a valid policy");
return cmPolicies::CMP0002;
}
//----------------------------------------------------------------------------
static const struct TargetPolicyNode : public cmGeneratorExpressionNode
{
TargetPolicyNode() {}
virtual int NumExpectedParameters() const { return 1; }
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context ,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *) const
{
if (!context->HeadTarget)
{
reportError(context, content->GetOriginalExpression(),
"$<TARGET_POLICY:prop> may only be used with targets. It may not "
"be used with add_custom_command.");
return std::string();
}
context->HadContextSensitiveCondition = true;
for (size_t i = 0;
i < (sizeof(targetPolicyWhitelist) /
sizeof(*targetPolicyWhitelist));
++i)
{
const char *policy = targetPolicyWhitelist[i];
if (parameters.front() == policy)
{
cmMakefile *mf = context->HeadTarget->GetMakefile();
switch(statusForTarget(context->HeadTarget, policy))
{
case cmPolicies::WARN:
mf->IssueMessage(cmake::AUTHOR_WARNING,
mf->GetPolicies()->
GetPolicyWarning(policyForString(policy)));
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::OLD:
return "0";
case cmPolicies::NEW:
return "1";
}
}
}
reportError(context, content->GetOriginalExpression(),
"$<TARGET_POLICY:prop> may only be used with a limited number of "
"policies. Currently it may be used with policies CMP0003, CMP0004, "
"CMP0008 and CMP0020."
);
return std::string();
}
} targetPolicyNode;
//----------------------------------------------------------------------------
static const struct InstallPrefixNode : public cmGeneratorExpressionNode
{
InstallPrefixNode() {}
virtual bool GeneratesContent() const { return true; }
virtual int NumExpectedParameters() const { return 0; }
std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *) const
{
reportError(context, content->GetOriginalExpression(),
"INSTALL_PREFIX is a marker for install(EXPORT) only. It "
"should never be evaluated.");
return std::string();
}
} installPrefixNode;
//----------------------------------------------------------------------------
static const struct LinkedNode : public cmGeneratorExpressionNode
{
LinkedNode() {}
virtual bool GeneratesContent() const { return true; }
virtual int NumExpectedParameters() const { return 1; }
virtual bool RequiresLiteralInput() const { return true; }
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *dagChecker) const
{
if (dagChecker->EvaluatingIncludeDirectories())
{
return this->GetInterfaceProperty(parameters.front(),
"INCLUDE_DIRECTORIES",
context, content, dagChecker);
}
if (dagChecker->EvaluatingCompileDefinitions())
{
return this->GetInterfaceProperty(parameters.front(),
"COMPILE_DEFINITIONS",
context, content, dagChecker);
}
reportError(context, content->GetOriginalExpression(),
"$<LINKED:...> may only be used in INCLUDE_DIRECTORIES and "
"COMPILE_DEFINITIONS properties.");
return std::string();
}
private:
std::string GetInterfaceProperty(const std::string &item,
const std::string &prop,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *dagCheckerParent) const
{
cmTarget *target = context->CurrentTarget
->GetMakefile()->FindTargetToUse(item.c_str());
if (!target)
{
return std::string();
}
std::string propertyName = "INTERFACE_" + prop;
const char *propContent = target->GetProperty(propertyName.c_str());
if (!propContent)
{
return std::string();
}
cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
target->GetName(),
propertyName,
content,
dagCheckerParent);
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::ALREADY_SEEN:
// No error. We're not going to find anything new here.
return std::string();
case cmGeneratorExpressionDAGChecker::DAG:
break;
}
cmGeneratorExpression ge(context->Backtrace);
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propContent);
std::string result = cge->Evaluate(context->Makefile,
context->Config,
context->Quiet,
context->HeadTarget,
target,
&dagChecker);
if (cge->GetHadContextSensitiveCondition())
{
context->HadContextSensitiveCondition = true;
}
return result;
}
} linkedNode;
//----------------------------------------------------------------------------
template<bool linker, bool soname>
struct TargetFilesystemArtifactResultCreator
@ -714,12 +974,18 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &targetPropertyNode;
else if (identifier == "TARGET_NAME")
return &targetNameNode;
else if (identifier == "TARGET_POLICY")
return &targetPolicyNode;
else if (identifier == "BUILD_INTERFACE")
return &buildInterfaceNode;
else if (identifier == "INSTALL_INTERFACE")
return &installInterfaceNode;
else if (identifier == "TARGET_DEFINED")
return &targetDefinedNode;
else if (identifier == "INSTALL_PREFIX")
return &installPrefixNode;
else if (identifier == "LINKED")
return &linkedNode;
return 0;
}

View File

@ -32,6 +32,7 @@ struct cmGeneratorExpressionContext
// directly or indirectly in the property.
bool Quiet;
bool HadError;
bool HadContextSensitiveCondition;
};
struct cmGeneratorExpressionDAGChecker;

View File

@ -254,32 +254,3 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
{
return this->Target->GetIncludeDirectories(config);
}
//----------------------------------------------------------------------------
std::string cmGeneratorTarget::GetCompileDefinitions(const char *config)
{
std::string defPropName = "COMPILE_DEFINITIONS";
if (config)
{
defPropName += "_" + cmSystemTools::UpperCase(config);
}
const char *prop = this->Target->GetProperty(defPropName.c_str());
if (!prop)
{
return "";
}
cmListFileBacktrace lfbt;
cmGeneratorExpression ge(lfbt);
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
this->GetName(),
defPropName, 0, 0);
return ge.Parse(prop)->Evaluate(this->Makefile,
config,
false,
this->Target,
&dagChecker);
}

View File

@ -68,8 +68,6 @@ public:
/** Get the include directories for this target. */
std::vector<std::string> GetIncludeDirectories(const char *config);
std::string GetCompileDefinitions(const char *config = 0);
private:
void ClassifySources();
void LookupObjectLibraries();

View File

@ -994,6 +994,7 @@ void cmGlobalGenerator::Generate()
// Generate project files
for (i = 0; i < this->LocalGenerators.size(); ++i)
{
this->LocalGenerators[i]->GetMakefile()->SetGeneratingBuildSystem();
this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
this->LocalGenerators[i]->Generate();
this->LocalGenerators[i]->GenerateInstallRules();
@ -1077,7 +1078,8 @@ void cmGlobalGenerator::CreateAutomocTargets()
if(target.GetType() == cmTarget::EXECUTABLE ||
target.GetType() == cmTarget::STATIC_LIBRARY ||
target.GetType() == cmTarget::SHARED_LIBRARY ||
target.GetType() == cmTarget::MODULE_LIBRARY)
target.GetType() == cmTarget::MODULE_LIBRARY ||
target.GetType() == cmTarget::OBJECT_LIBRARY)
{
if(target.GetPropertyAsBool("AUTOMOC") && !target.IsImported())
{

View File

@ -1700,11 +1700,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
this->AppendDefines(ppDefs, exportMacro);
}
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
this->AppendDefines(ppDefs, gtgt->GetCompileDefinitions().c_str());
this->AppendDefines(ppDefs, target.GetCompileDefinitions().c_str());
if(configName)
{
this->AppendDefines(ppDefs,
gtgt->GetCompileDefinitions(configName).c_str());
target.GetCompileDefinitions(configName).c_str());
}
buildSettings->AddAttribute
("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());

View File

@ -36,6 +36,10 @@ bool cmIncludeDirectoryCommand
++i;
}
std::vector<std::string> beforeIncludes;
std::vector<std::string> afterIncludes;
std::set<cmStdString> systemIncludes;
for(; i != args.end(); ++i)
{
if(*i == "SYSTEM")
@ -49,9 +53,37 @@ bool cmIncludeDirectoryCommand
return false;
}
this->AddDirectory(i->c_str(),before,system);
std::vector<std::string> includes;
GetIncludes(*i, includes);
if (before)
{
beforeIncludes.insert(beforeIncludes.end(),
includes.begin(),
includes.end());
}
else
{
afterIncludes.insert(afterIncludes.end(),
includes.begin(),
includes.end());
}
if (system)
{
for (std::vector<std::string>::const_iterator li = includes.begin();
li != includes.end(); ++li)
{
systemIncludes.insert(*li);
}
}
}
std::reverse(beforeIncludes.begin(), beforeIncludes.end());
this->Makefile->AddIncludeDirectories(afterIncludes);
this->Makefile->AddIncludeDirectories(beforeIncludes, before);
this->Makefile->AddSystemIncludeDirectories(systemIncludes);
return true;
}
@ -72,57 +104,49 @@ static bool StartsWithGeneratorExpression(const std::string &input)
// output from a program and passing it into a command the cleanup doesn't
// always happen
//
void cmIncludeDirectoryCommand::AddDirectory(const char *i,
bool before,
bool system)
void cmIncludeDirectoryCommand::GetIncludes(const std::string &arg,
std::vector<std::string> &incs)
{
// break apart any line feed arguments
std::string ret = i;
std::string::size_type pos = 0;
if((pos = ret.find('\n', pos)) != std::string::npos)
std::string::size_type lastPos = 0;
while((pos = arg.find('\n', lastPos)) != std::string::npos)
{
if (pos)
{
this->AddDirectory(ret.substr(0,pos).c_str(), before, system);
std::string inc = arg.substr(lastPos,pos);
NormalizeInclude(inc);
incs.push_back(inc);
}
if (ret.size()-pos-1)
{
this->AddDirectory(ret.substr(pos+1,ret.size()-pos-1).c_str(),
before, system);
lastPos = pos + 1;
}
return;
std::string inc = arg.substr(lastPos);
NormalizeInclude(inc);
incs.push_back(inc);
}
// remove any leading or trailing spaces and \r
std::string::size_type b = ret.find_first_not_of(" \r");
std::string::size_type e = ret.find_last_not_of(" \r");
if ((b!=ret.npos) && (e!=ret.npos))
void cmIncludeDirectoryCommand::NormalizeInclude(std::string &inc)
{
ret.assign(ret, b, 1+e-b); // copy the remaining substring
}
else
std::string::size_type b = inc.find_first_not_of(" \r");
std::string::size_type e = inc.find_last_not_of(" \r");
if ((b!=inc.npos) && (e!=inc.npos))
{
return; // if we get here, we had only whitespace in the string
inc.assign(inc, b, 1+e-b); // copy the remaining substring
}
if (!cmSystemTools::IsOff(ret.c_str()))
if (!cmSystemTools::IsOff(inc.c_str()))
{
cmSystemTools::ConvertToUnixSlashes(ret);
if(!cmSystemTools::FileIsFullPath(ret.c_str()))
cmSystemTools::ConvertToUnixSlashes(inc);
if(!cmSystemTools::FileIsFullPath(inc.c_str()))
{
if(!StartsWithGeneratorExpression(ret))
if(!StartsWithGeneratorExpression(inc))
{
std::string tmp = this->Makefile->GetStartDirectory();
tmp += "/";
tmp += ret;
ret = tmp;
tmp += inc;
inc = tmp;
}
}
}
this->Makefile->AddIncludeDirectory(ret.c_str(), before);
if(system)
{
this->Makefile->AddSystemIncludeDirectory(ret.c_str());
}
}

View File

@ -59,8 +59,9 @@ public:
return
" include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)\n"
"Add the given directories to those the compiler uses to search "
"for include files. "
"These directories are added to the directory property "
"for include files. Relative paths are interpreted as relative to "
"the current source directory. \n"
"The include directories are added to the directory property "
"INCLUDE_DIRECTORIES for the current CMakeLists file. "
"They are also added to the target property INCLUDE_DIRECTORIES "
"for each target in the current CMakeLists file. "
@ -84,7 +85,8 @@ public:
protected:
// used internally
void AddDirectory(const char *arg, bool before, bool system);
void GetIncludes(const std::string &arg, std::vector<std::string> &incs);
void NormalizeInclude(std::string &inc);
};

View File

@ -62,10 +62,8 @@ public:
" link_directories(directory1 directory2 ...)\n"
"Specify the paths in which the linker should search for libraries. "
"The command will apply only to targets created after it is called. "
"For historical reasons, relative paths given to this command are "
"passed to the linker unchanged "
"(unlike many CMake commands which interpret them relative to the "
"current source directory).\n"
"Relative paths given to this command are interpreted as relative to "
"the current source directory, see CMP0015. \n"
"Note that this command is rarely necessary. Library locations "
"returned by find_package() and find_library() are absolute paths. "
"Pass these absolute library file paths directly to the "

View File

@ -325,6 +325,9 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
if(!cmSystemTools::FileExists(source.c_str()))
{
cmSystemTools::ReplaceString(source, "$(IntDir)/", "");
// Make sure the path exists for the file
std::string path = cmSystemTools::GetFilenamePath(source);
cmSystemTools::MakeDirectory(path.c_str());
#if defined(_WIN32) || defined(__CYGWIN__)
std::ofstream sourceFout(source.c_str(),
std::ios::binary | std::ios::out
@ -1697,25 +1700,21 @@ void cmLocalVisualStudio6Generator
std::set<std::string> minsizeDefinesSet;
std::set<std::string> debugrelDefinesSet;
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
this->AppendDefines(
definesSet,
gt->GetCompileDefinitions());
target.GetCompileDefinitions());
this->AppendDefines(
debugDefinesSet,
gt->GetCompileDefinitions("DEBUG"));
target.GetCompileDefinitions("DEBUG"));
this->AppendDefines(
releaseDefinesSet,
gt->GetCompileDefinitions("RELEASE"));
target.GetCompileDefinitions("RELEASE"));
this->AppendDefines(
minsizeDefinesSet,
gt->GetCompileDefinitions("MINSIZEREL"));
target.GetCompileDefinitions("MINSIZEREL"));
this->AppendDefines(
debugrelDefinesSet,
gt->GetCompileDefinitions("RELWITHDEBINFO"));
target.GetCompileDefinitions("RELWITHDEBINFO"));
std::string defines = " ";
std::string debugDefines = " ";

View File

@ -745,8 +745,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
targetOptions.ParseFinish();
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
targetOptions.AddDefines(gt->GetCompileDefinitions().c_str());
targetOptions.AddDefines(gt->GetCompileDefinitions(configName).c_str());
targetOptions.AddDefines(target.GetCompileDefinitions().c_str());
targetOptions.AddDefines(target.GetCompileDefinitions(configName).c_str());
targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));

View File

@ -99,6 +99,7 @@ cmMakefile::cmMakefile(): Internal(new Internals)
this->AddDefaultDefinitions();
this->Initialize();
this->PreOrder = false;
this->GeneratingBuildSystem = false;
}
cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
@ -1616,20 +1617,31 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath,
}
//----------------------------------------------------------------------------
void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
void cmMakefile::AddIncludeDirectories(const std::vector<std::string> &incs,
bool before)
{
if (!inc)
if (incs.empty())
{
return;
}
std::string incString;
std::string sep;
for(std::vector<std::string>::const_iterator li = incs.begin();
li != incs.end(); ++li)
{
incString += sep + *li;
sep = ";";
}
std::vector<IncludeDirectoriesEntry>::iterator position =
before ? this->IncludeDirectoriesEntries.begin()
: this->IncludeDirectoriesEntries.end();
cmListFileBacktrace lfbt;
this->GetBacktrace(lfbt);
IncludeDirectoriesEntry entry(inc, lfbt);
IncludeDirectoriesEntry entry(incString, lfbt);
this->IncludeDirectoriesEntries.insert(position, entry);
// Property on each target:
@ -1642,9 +1654,14 @@ void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
}
//----------------------------------------------------------------------------
void cmMakefile::AddSystemIncludeDirectory(const char* dir)
void
cmMakefile::AddSystemIncludeDirectories(const std::set<cmStdString> &incs)
{
this->SystemIncludeDirectories.insert(dir);
for(std::set<cmStdString>::const_iterator li = incs.begin();
li != incs.end(); ++li)
{
this->SystemIncludeDirectories.insert(*li);
}
}
//----------------------------------------------------------------------------
@ -2243,7 +2260,7 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName)
{
return true;
}
// If we are doing an in-source build, than the test will always fail
// If we are doing an in-source build, then the test will always fail
if ( cmSystemTools::SameFile(this->GetHomeDirectory(),
this->GetHomeOutputDirectory()) )
{
@ -2254,8 +2271,8 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName)
return true;
}
// Check if this is subdirectory of the source tree but not a
// subdirectory of a build tree
// Check if this is a subdirectory of the source tree but not a
// subdirectory of the build tree
if ( cmSystemTools::IsSubDirectory(fileName,
this->GetHomeDirectory()) &&
!cmSystemTools::IsSubDirectory(fileName,

View File

@ -287,7 +287,8 @@ public:
/**
* Add an include directory to the build.
*/
void AddIncludeDirectory(const char*, bool before = false);
void AddIncludeDirectories(const std::vector<std::string> &incs,
bool before = false);
/**
* Add a variable definition to the build. This variable
@ -545,7 +546,7 @@ public:
/**
* Mark include directories as system directories.
*/
void AddSystemIncludeDirectory(const char* dir);
void AddSystemIncludeDirectories(const std::set<cmStdString> &incs);
bool IsSystemIncludeDirectory(const char* dir);
/** Expand out any arguements in the vector that have ; separated
@ -869,6 +870,9 @@ public:
return this->IncludeDirectoriesEntries;
}
bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; }
void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; }
protected:
// add link libraries and directories to the target
void AddGlobalLinkInformation(const char* name, cmTarget& target);
@ -1018,6 +1022,9 @@ private:
// Enforce rules about CMakeLists.txt files.
void EnforceDirectoryLevelRules();
bool GeneratingBuildSystem;
};
//----------------------------------------------------------------------------

View File

@ -303,10 +303,10 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
// Add preprocessor definitions for this target and configuration.
this->LocalGenerator->AppendDefines
(defines, this->GeneratorTarget->GetCompileDefinitions());
(defines, this->Target->GetCompileDefinitions());
this->LocalGenerator->AppendDefines
(defines, this->GeneratorTarget->GetCompileDefinitions(
(defines, this->Target->GetCompileDefinitions(
this->LocalGenerator->ConfigurationName.c_str()));
std::string definesString;

View File

@ -190,7 +190,7 @@ cmNinjaNormalTargetGenerator
linkOptionVar += cmTarget::GetTargetTypeName(targetType);
const std::string linkOption =
GetMakefile()->GetSafeDefinition(linkOptionVar.c_str());
rspcontent = "$in " + linkOption + " $LINK_PATH $LINK_LIBRARIES";
rspcontent = "$in_newline "+linkOption+" $LINK_PATH $LINK_LIBRARIES";
vars.Objects = responseFlag.c_str();
vars.LinkLibraries = "";
}

View File

@ -228,7 +228,7 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
// Add preprocessor definitions for this target and configuration.
this->LocalGenerator->AppendDefines
(defines,
this->GeneratorTarget->GetCompileDefinitions());
this->Target->GetCompileDefinitions());
this->LocalGenerator->AppendDefines
(defines,
source->GetProperty("COMPILE_DEFINITIONS"));
@ -237,7 +237,7 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
defPropName += cmSystemTools::UpperCase(this->GetConfigName());
this->LocalGenerator->AppendDefines
(defines,
this->GeneratorTarget->GetCompileDefinitions(this->GetConfigName()));
this->Target->GetCompileDefinitions(this->GetConfigName()));
this->LocalGenerator->AppendDefines
(defines,
source->GetProperty(defPropName.c_str()));

View File

@ -508,6 +508,27 @@ cmPolicies::cmPolicies()
"for strict compatibility. "
"The NEW behavior for this policy is to leave the values untouched.",
2,8,11,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0020, "CMP0020",
"Automatically link Qt executables to qtmain target on Windows.",
"CMake 2.8.10 and lower required users of Qt to always specify a link "
"dependency to the qtmain.lib static library manually on Windows. CMake "
"2.8.11 gained the ability to evaluate generator expressions while "
"determining the link dependencies from IMPORTED targets. This allows "
"CMake itself to automatically link executables which link to Qt to the "
"qtmain.lib library when using IMPORTED Qt targets. For applications "
"already linking to qtmain.lib, this should have little impact. For "
"applications which supply their own alternative WinMain implementation "
"and for applications which use the QAxServer library, this automatic "
"linking will need to be disabled as per the documentation."
"\n"
"The OLD behavior for this policy is not to link executables to "
"qtmain.lib automatically when they link to the QtCore IMPORTED"
"target. "
"The NEW behavior for this policy is to link executables to "
"qtmain.lib automatically when they link to QtCore IMPORTED target.",
2,8,11,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()

View File

@ -69,6 +69,7 @@ public:
/// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
/// instead.
CMP0019, ///< No variable re-expansion in include and link info
CMP0020, ///< Automatically link Qt executables to qtmain target
/** \brief Always the last entry.
*

View File

@ -229,7 +229,11 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
}
const char* tmp = target->GetProperty("COMPILE_DEFINITIONS");
std::string _moc_compile_defs = (tmp!=0 ? tmp : "");
std::string _moc_compile_defs;
if (tmp)
{
_moc_compile_defs = target->GetCompileDefinitions();
}
tmp = makefile->GetProperty("COMPILE_DEFINITIONS");
if (tmp)
{

View File

@ -1180,46 +1180,35 @@ bool cmSystemTools::CopyFileIfDifferent(const char* source,
bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
{
#ifdef _WIN32
/* On Windows the move functions will not replace existing files.
Check if the destination exists. */
struct stat newFile;
if(stat(newname, &newFile) == 0)
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
# endif
/* Windows MoveFileEx may not replace read-only or in-use files. If it
fails then remove the read-only attribute from any existing destination.
Try multiple times since we may be racing against another process
creating/opening the destination file just before our MoveFileEx. */
int tries = 5;
while(!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) && --tries)
{
/* The destination exists. We have to replace it carefully. The
MoveFileEx function does what we need but is not available on
Win9x. */
OSVERSIONINFO osv;
DWORD attrs;
/* Make sure the destination is not read only. */
attrs = GetFileAttributes(newname);
if(attrs & FILE_ATTRIBUTE_READONLY)
// Try again only if failure was due to access permissions.
if(GetLastError() != ERROR_ACCESS_DENIED)
{
return false;
}
DWORD attrs = GetFileAttributes(newname);
if((attrs != INVALID_FILE_ATTRIBUTES) &&
(attrs & FILE_ATTRIBUTE_READONLY))
{
// Remove the read-only attribute from the destination file.
SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
}
/* Check the windows version number. */
osv.dwOSVersionInfoSize = sizeof(osv);
GetVersionEx(&osv);
if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
/* This is Win9x. There is no MoveFileEx implementation. We
cannot quite rename the file atomically. Just delete the
destination and then move the file. */
DeleteFile(newname);
return MoveFile(oldname, newname) != 0;
}
else
{
/* This is not Win9x. Use the MoveFileEx implementation. */
return MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) != 0;
// The file may be temporarily in use so wait a bit.
cmSystemTools::Delay(100);
}
}
else
{
/* The destination does not exist. Just move the file. */
return MoveFile(oldname, newname) != 0;
}
return tries > 0;
#else
/* On UNIX we have an OS-provided call to do this atomically. */
return rename(oldname, newname) == 0;

View File

@ -134,6 +134,7 @@ public:
: ge(cge)
{}
const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
std::vector<std::string> CachedIncludes;
};
std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
};
@ -145,12 +146,14 @@ cmTarget::cmTarget()
this->PolicyStatusCMP0003 = cmPolicies::WARN;
this->PolicyStatusCMP0004 = cmPolicies::WARN;
this->PolicyStatusCMP0008 = cmPolicies::WARN;
this->PolicyStatusCMP0020 = cmPolicies::WARN;
this->LinkLibrariesAnalyzed = false;
this->HaveInstallRule = false;
this->DLLPlatform = false;
this->IsApple = false;
this->IsImportedTarget = false;
this->BuildInterfaceIncludesAppended = false;
this->DebugIncludesDone = false;
}
//----------------------------------------------------------------------------
@ -905,6 +908,17 @@ void cmTarget::DefineProperties(cmake *cm)
"then it must have the same boolean value as all others, and if the "
"property is not set, then it is ignored.");
cm->DefineProperty
("COMPATIBLE_INTERFACE_STRING", cmProperty::TARGET,
"Properties which must be string-compatible with their link interface",
"The COMPATIBLE_INTERFACE_STRING property may contain a list of "
"properties for this target which must be the same when evaluated as "
"a string in the INTERFACE of all linked dependencies. For example, "
"if a property \"FOO\" appears in the list, then the \"INTERFACE_FOO\" "
"property content in all dependencies must be equal with each "
"other, and with the \"FOO\" property in this target. If the "
"property is not set, then it is ignored.");
cm->DefineProperty
("POST_INSTALL_SCRIPT", cmProperty::TARGET,
"Deprecated install support.",
@ -1499,6 +1513,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->Makefile->GetPolicyStatus(cmPolicies::CMP0004);
this->PolicyStatusCMP0008 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0008);
this->PolicyStatusCMP0020 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0020);
}
//----------------------------------------------------------------------------
@ -1520,6 +1536,13 @@ void cmTarget::ClearLinkMaps()
this->Internal->LinkImplMap.clear();
this->Internal->LinkInterfaceMap.clear();
this->Internal->LinkClosureMap.clear();
for (cmTargetLinkInformationMap::const_iterator it
= this->LinkInformation.begin();
it != this->LinkInformation.end(); ++it)
{
delete it->second;
}
this->LinkInformation.clear();
}
//----------------------------------------------------------------------------
@ -2269,7 +2292,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
const bool isNonImportedTarget = tgt && !tgt->IsImported();
std::string libName = isNonImportedTarget ? targetNameGenex(lib)
const std::string libName = (isNonImportedTarget && llt != GENERAL)
? targetNameGenex(lib)
: std::string(lib);
this->AppendProperty("LINK_LIBRARIES",
this->GetDebugGeneratorExpressions(libName,
@ -2739,52 +2763,105 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
cmSystemTools::ExpandListArgument(debugProp, debugProperties);
}
bool debugIncludes = std::find(debugProperties.begin(),
bool debugIncludes = !this->DebugIncludesDone
&& std::find(debugProperties.begin(),
debugProperties.end(),
"INCLUDE_DIRECTORIES")
!= debugProperties.end();
if (this->Makefile->IsGeneratingBuildSystem())
{
this->DebugIncludesDone = true;
}
for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
it = this->Internal->IncludeDirectoriesEntries.begin(),
end = this->Internal->IncludeDirectoriesEntries.end();
it != end; ++it)
{
std::vector<std::string> entryIncludes;
bool testIsOff = true;
bool cacheIncludes = false;
std::vector<std::string> entryIncludes = (*it)->CachedIncludes;
if(!entryIncludes.empty())
{
testIsOff = false;
}
else
{
cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile,
config,
false,
this,
&dagChecker),
entryIncludes);
if (!(*it)->ge->GetHadContextSensitiveCondition())
{
cacheIncludes = true;
}
}
std::string usedIncludes;
for(std::vector<std::string>::const_iterator
for(std::vector<std::string>::iterator
li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
{
std::string inc = *li;
if (!cmSystemTools::IsOff(inc.c_str()))
if (testIsOff && !cmSystemTools::IsOff(li->c_str()))
{
cmSystemTools::ConvertToUnixSlashes(inc);
cmSystemTools::ConvertToUnixSlashes(*li);
}
std::string inc = *li;
if(uniqueIncludes.insert(inc).second)
{
includes.push_back(*li);
includes.push_back(inc);
if (debugIncludes)
{
usedIncludes += " * " + *li + "\n";
usedIncludes += " * " + inc + "\n";
}
}
}
if (cacheIncludes)
{
(*it)->CachedIncludes = entryIncludes;
}
if (!usedIncludes.empty())
{
this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG,
"Used includes:\n" + usedIncludes,
(*it)->ge->GetBacktrace());
"Used includes for target " + this->Name + ":\n"
+ usedIncludes, (*it)->ge->GetBacktrace());
}
}
return includes;
}
//----------------------------------------------------------------------------
std::string cmTarget::GetCompileDefinitions(const char *config)
{
std::string defPropName = "COMPILE_DEFINITIONS";
if (config)
{
defPropName += "_" + cmSystemTools::UpperCase(config);
}
const char *prop = this->GetProperty(defPropName.c_str());
if (!prop)
{
return "";
}
cmListFileBacktrace lfbt;
cmGeneratorExpression ge(lfbt);
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
this->GetName(),
defPropName, 0, 0);
return ge.Parse(prop)->Evaluate(this->Makefile,
config,
false,
this,
&dagChecker);
}
//----------------------------------------------------------------------------
void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
{
@ -4482,22 +4559,69 @@ void cmTarget::AddLinkDependentTargetsForProperties(
}
//----------------------------------------------------------------------------
bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config)
template<typename PropertyType>
PropertyType getTypedProperty(cmTarget *tgt, const char *prop,
PropertyType *);
//----------------------------------------------------------------------------
template<>
bool getTypedProperty<bool>(cmTarget *tgt, const char *prop, bool *)
{
bool propContent = this->GetPropertyAsBool(p.c_str());
const bool explicitlySet = this->GetProperties()
return tgt->GetPropertyAsBool(prop);
}
//----------------------------------------------------------------------------
template<>
const char *getTypedProperty<const char *>(cmTarget *tgt, const char *prop,
const char **)
{
return tgt->GetProperty(prop);
}
//----------------------------------------------------------------------------
template<typename PropertyType>
bool consistentProperty(PropertyType lhs, PropertyType rhs);
//----------------------------------------------------------------------------
template<>
bool consistentProperty(bool lhs, bool rhs)
{
return lhs == rhs;
}
//----------------------------------------------------------------------------
template<>
bool consistentProperty(const char *lhs, const char *rhs)
{
if (!lhs && !rhs)
return true;
if (!lhs || !rhs)
return false;
return strcmp(lhs, rhs) == 0;
}
//----------------------------------------------------------------------------
template<typename PropertyType>
PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt,
const std::string &p,
const char *config,
const char *defaultValue,
PropertyType *)
{
PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(),
0);
const bool explicitlySet = tgt->GetProperties()
.find(p.c_str())
!= this->GetProperties().end();
!= tgt->GetProperties().end();
std::set<std::string> dependentTargets;
this->GetLinkDependentTargetsForProperty(p,
tgt->GetLinkDependentTargetsForProperty(p,
dependentTargets);
const bool impliedByUse =
this->IsNullImpliedByLinkLibraries(p);
tgt->IsNullImpliedByLinkLibraries(p);
assert((impliedByUse ^ explicitlySet)
|| (!impliedByUse && !explicitlySet));
cmComputeLinkInformation *info = this->GetLinkInformation(config);
cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
bool propInitialized = explicitlySet;
@ -4519,20 +4643,22 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
const bool ifaceIsSet = li->Target->GetProperties()
.find("INTERFACE_" + p)
!= li->Target->GetProperties().end();
const bool ifacePropContent = li->Target->GetPropertyAsBool(
("INTERFACE_" + p).c_str());
PropertyType ifacePropContent =
getTypedProperty<PropertyType>(li->Target,
("INTERFACE_" + p).c_str(), 0);
if (explicitlySet)
{
if (ifaceIsSet)
{
if (propContent != ifacePropContent)
if (!consistentProperty(propContent, ifacePropContent))
{
cmOStringStream e;
e << "Property " << p << " on target \""
<< this->GetName() << "\" does\nnot match the "
<< tgt->GetName() << "\" does\nnot match the "
"INTERFACE_" << p << " property requirement\nof "
"dependency \"" << li->Target->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str());
break;
}
else
{
@ -4550,15 +4676,16 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
{
if (ifaceIsSet)
{
if (propContent != ifacePropContent)
if (!consistentProperty(propContent, ifacePropContent))
{
cmOStringStream e;
e << "Property " << p << " on target \""
<< this->GetName() << "\" is\nimplied to be FALSE because it "
"was used to determine the link libraries\nalready. The "
"INTERFACE_" << p << " property on\ndependency \""
<< tgt->GetName() << "\" is\nimplied to be " << defaultValue
<< " because it was used to determine the link libraries\n"
"already. The INTERFACE_" << p << " property on\ndependency \""
<< li->Target->GetName() << "\" is in conflict.\n";
cmSystemTools::Error(e.str().c_str());
break;
}
else
{
@ -4578,14 +4705,15 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
{
if (propInitialized)
{
if (propContent != ifacePropContent)
if (!consistentProperty(propContent, ifacePropContent))
{
cmOStringStream e;
e << "The INTERFACE_" << p << " property of \""
<< li->Target->GetName() << "\" does\nnot agree with the value "
"of " << p << " already determined\nfor \""
<< this->GetName() << "\".\n";
<< tgt->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str());
break;
}
else
{
@ -4609,6 +4737,80 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
return propContent;
}
//----------------------------------------------------------------------------
bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config)
{
return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
0);
}
//----------------------------------------------------------------------------
const char * cmTarget::GetLinkInterfaceDependentStringProperty(
const std::string &p,
const char *config)
{
return checkInterfacePropertyCompatibility<const char *>(this,
p,
config,
"empty", 0);
}
//----------------------------------------------------------------------------
bool isLinkDependentProperty(cmTarget *tgt, const std::string &p,
const char *interfaceProperty,
const char *config)
{
cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator li =
deps.begin();
li != deps.end(); ++li)
{
if (!li->Target)
{
continue;
}
const char *prop = li->Target->GetProperty(interfaceProperty);
if (!prop)
{
continue;
}
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(prop, props);
for(std::vector<std::string>::iterator pi = props.begin();
pi != props.end(); ++pi)
{
if (*pi == p)
{
return true;
}
}
}
return false;
}
//----------------------------------------------------------------------------
bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config)
{
return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL",
config);
}
//----------------------------------------------------------------------------
bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p,
const char *config)
{
return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING",
config);
}
//----------------------------------------------------------------------------
void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
{
@ -5349,6 +5551,73 @@ std::string cmTarget::CheckCMP0004(std::string const& item)
return lib;
}
template<typename PropertyType>
PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt,
const std::string prop,
const char *config,
PropertyType *);
template<>
bool getLinkInterfaceDependentProperty(cmTarget *tgt,
const std::string prop,
const char *config, bool *)
{
return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
}
template<>
const char * getLinkInterfaceDependentProperty(cmTarget *tgt,
const std::string prop,
const char *config,
const char **)
{
return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
}
//----------------------------------------------------------------------------
template<typename PropertyType>
void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee,
const char *propName,
std::set<cmStdString> &emitted,
const char *config,
PropertyType *)
{
const char *prop = dependee->GetProperty(propName);
if (!prop)
{
return;
}
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(prop, props);
for(std::vector<std::string>::iterator pi = props.begin();
pi != props.end(); ++pi)
{
if (depender->GetMakefile()->GetCMakeInstance()
->GetIsPropertyDefined(pi->c_str(),
cmProperty::TARGET))
{
cmOStringStream e;
e << "Target \"" << dependee->GetName() << "\" has property \""
<< *pi << "\" listed in its " << propName << " property. "
"This is not allowed. Only user-defined properties may appear "
"listed in the " << propName << " property.";
depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
if(emitted.insert(*pi).second)
{
getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config,
0);
if (cmSystemTools::GetErrorOccuredFlag())
{
return;
}
}
}
}
//----------------------------------------------------------------------------
void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
const char* config)
@ -5365,38 +5634,20 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
{
continue;
}
const char *prop = li->Target->GetProperty("COMPATIBLE_INTERFACE_BOOL");
if (!prop)
{
continue;
}
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(prop, props);
for(std::vector<std::string>::iterator pi = props.begin();
pi != props.end(); ++pi)
{
if (this->Makefile->GetCMakeInstance()
->GetIsPropertyDefined(pi->c_str(),
cmProperty::TARGET))
{
cmOStringStream e;
e << "Target \"" << li->Target->GetName() << "\" has property \""
<< *pi << "\" listed in its COMPATIBLE_INTERFACE_BOOL property. "
"This is not allowed. Only user-defined properties may appear "
"listed in the COMPATIBLE_INTERFACE_BOOL property.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
if(emitted.insert(*pi).second)
{
this->GetLinkInterfaceDependentBoolProperty(*pi, config);
checkPropertyConsistency<bool>(this, li->Target,
"COMPATIBLE_INTERFACE_BOOL",
emitted, config, 0);
if (cmSystemTools::GetErrorOccuredFlag())
{
return;
}
}
checkPropertyConsistency<const char *>(this, li->Target,
"COMPATIBLE_INTERFACE_STRING",
emitted, config, 0);
if (cmSystemTools::GetErrorOccuredFlag())
{
return;
}
}
}
@ -5422,14 +5673,14 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head)
info = 0;
}
// Store the information for this configuration.
cmTargetLinkInformationMap::value_type entry(key, info);
i = this->LinkInformation.insert(entry).first;
if (info)
{
this->CheckPropertyCompatibility(info, config);
}
// Store the information for this configuration.
cmTargetLinkInformationMap::value_type entry(key, info);
i = this->LinkInformation.insert(entry).first;
}
return i->second;
}

View File

@ -102,6 +102,10 @@ public:
cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const
{ return this->PolicyStatusCMP0008; }
/** Get the status of policy CMP0020 when the target was created. */
cmPolicies::PolicyStatus GetPolicyStatusCMP0020() const
{ return this->PolicyStatusCMP0020; }
/**
* Get the list of the custom commands for this target
*/
@ -426,6 +430,8 @@ public:
If no macro should be defined null is returned. */
const char* GetExportMacro();
std::string GetCompileDefinitions(const char *config = 0);
// Compute the set of languages compiled by the target. This is
// computed every time it is called because the languages can change
// when source file properties are changed and we do not have enough
@ -495,12 +501,22 @@ public:
void GetLinkDependentTargetsForProperty(const std::string &p,
std::set<std::string> &targets);
bool IsNullImpliedByLinkLibraries(const std::string &p);
bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config);
bool IsLinkInterfaceDependentStringProperty(const std::string &p,
const char *config);
void AddLinkDependentTargetsForProperties(
const std::map<cmStdString, cmStdString> &map);
bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config);
const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
const char *config);
std::string GetDebugGeneratorExpressions(const std::string &value,
cmTarget::LinkLibraryType llt);
private:
/**
* A list of direct dependencies. Use in conjunction with DependencyMap.
@ -610,6 +626,7 @@ private:
bool DLLPlatform;
bool IsApple;
bool IsImportedTarget;
bool DebugIncludesDone;
mutable std::map<cmStdString, std::set<std::string> >
LinkDependentProperties;
mutable std::set<std::string> LinkImplicitNullProperties;
@ -645,9 +662,6 @@ 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;
@ -656,6 +670,7 @@ private:
cmPolicies::PolicyStatus PolicyStatusCMP0003;
cmPolicies::PolicyStatus PolicyStatusCMP0004;
cmPolicies::PolicyStatus PolicyStatusCMP0008;
cmPolicies::PolicyStatus PolicyStatusCMP0020;
// Internal representation details.
friend class cmTargetInternals;

View File

@ -20,13 +20,11 @@ bool cmTargetCompileDefinitionsCommand
}
void cmTargetCompileDefinitionsCommand
::HandleImportedTargetInvalidScope(const std::string &scope,
const std::string &tgt)
::HandleImportedTarget(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.";
e << "Cannot specify compile definitions for imported target \""
<< tgt << "\".";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
@ -39,19 +37,32 @@ void cmTargetCompileDefinitionsCommand
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 &)
//----------------------------------------------------------------------------
std::string cmTargetCompileDefinitionsCommand
::Join(const std::vector<std::string> &content)
{
content += sep + entry;
return true;
std::string defs;
std::string sep;
for(std::vector<std::string>::const_iterator it = content.begin();
it != content.end(); ++it)
{
if (strncmp(it->c_str(), "-D", 2) == 0)
{
defs += sep + it->substr(2);
}
else
{
defs += sep + *it;
}
sep = ";";
}
return defs;
}
//----------------------------------------------------------------------------
void cmTargetCompileDefinitionsCommand
::HandleDirectContent(cmTarget *tgt, const std::string &content,
::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
bool)
{
tgt->AppendProperty("COMPILE_DEFINITIONS", content.c_str());
tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
}

View File

@ -59,7 +59,7 @@ public:
"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. "
"add_executable or add_library and must not be an IMPORTED target. "
"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 "
@ -75,20 +75,16 @@ public:
;
}
cmTypeMacro(cmTargetCompileDefinitionsCommand, cmCommand);
cmTypeMacro(cmTargetCompileDefinitionsCommand, cmTargetPropCommandBase);
private:
virtual void HandleImportedTargetInvalidScope(const std::string &scope,
const std::string &tgt);
virtual void HandleImportedTarget(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,
virtual void HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content,
bool prepend);
virtual std::string Join(const std::vector<std::string> &content);
};
#endif

View File

@ -22,13 +22,11 @@ bool cmTargetIncludeDirectoriesCommand
//----------------------------------------------------------------------------
void cmTargetIncludeDirectoriesCommand
::HandleImportedTargetInvalidScope(const std::string &tgt,
const std::string &scope)
::HandleImportedTarget(const std::string &tgt)
{
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.";
e << "Cannot specify include directories for imported target \""
<< tgt << "\".";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
@ -43,32 +41,44 @@ void cmTargetIncludeDirectoriesCommand
}
//----------------------------------------------------------------------------
bool cmTargetIncludeDirectoriesCommand
::HandleNonTargetArg(std::string &content,
const std::string &sep,
const std::string &entry,
const std::string &tgt)
static bool isGeneratorExpression(const std::string &lib)
{
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;
const std::string::size_type openpos = lib.find("$<");
return (openpos != std::string::npos)
&& (lib.find(">", openpos) != std::string::npos);
}
content += sep + entry;
return true;
//----------------------------------------------------------------------------
std::string cmTargetIncludeDirectoriesCommand
::Join(const std::vector<std::string> &content)
{
std::string dirs;
std::string sep;
std::string prefix = this->Makefile->GetStartDirectory() + std::string("/");
for(std::vector<std::string>::const_iterator it = content.begin();
it != content.end(); ++it)
{
if (cmSystemTools::FileIsFullPath(it->c_str())
|| isGeneratorExpression(*it))
{
dirs += sep + *it;
}
else
{
dirs += sep + prefix + *it;
}
sep = ";";
}
return dirs;
}
//----------------------------------------------------------------------------
void cmTargetIncludeDirectoriesCommand
::HandleDirectContent(cmTarget *tgt, const std::string &content,
::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
bool prepend)
{
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmMakefileIncludeDirectoriesEntry entry(content, lfbt);
cmMakefileIncludeDirectoriesEntry entry(this->Join(content), lfbt);
tgt->InsertInclude(entry, prepend);
}

View File

@ -60,7 +60,7 @@ public:
"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"
"add_executable or add_library and must not be an IMPORTED target.\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 "
@ -79,20 +79,16 @@ public:
;
}
cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmCommand);
cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmTargetPropCommandBase);
private:
virtual void HandleImportedTargetInvalidScope(const std::string &tgt,
const std::string &scope);
virtual void HandleImportedTarget(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,
virtual void HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content,
bool prepend);
virtual std::string Join(const std::vector<std::string> &content);
};
#endif

View File

@ -33,10 +33,6 @@ 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
@ -253,24 +249,55 @@ cmTargetLinkLibrariesCommand
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
}
//----------------------------------------------------------------------------
static std::string compileProperty(cmTarget *tgt, const std::string &lib,
bool isGenex,
const std::string &property,
cmTarget::LinkLibraryType llt)
{
std::string value = !isGenex ? "$<LINKED:" + lib + ">"
: "$<$<TARGET_DEFINED:" + lib + ">:" +
"$<TARGET_PROPERTY:" + lib +
",INTERFACE_" + property + ">"
">";
return tgt->GetDebugGeneratorExpressions(value, llt);
}
//----------------------------------------------------------------------------
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
cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
cmTarget::LinkLibraryType llt)
{
const bool isGenex = isGeneratorExpression(lib);
cmsys::RegularExpression targetNameValidator;
targetNameValidator.compile("^[A-Za-z0-9_.:-]+$");
const bool potentialTargetName = targetNameValidator.find(lib);
if (potentialTargetName || isGenex)
{
this->Target->AppendProperty("INCLUDE_DIRECTORIES",
compileProperty(this->Target, lib,
isGenex,
"INCLUDE_DIRECTORIES", llt).c_str());
this->Target->AppendProperty("COMPILE_DEFINITIONS",
compileProperty(this->Target, lib,
isGenex,
"COMPILE_DEFINITIONS", llt).c_str());
}
// 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)
@ -280,6 +307,18 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
}
}
if (potentialTargetName || isGenex)
{
this->Target->AppendProperty("INTERFACE_COMPILE_DEFINITIONS",
compileProperty(this->Target, lib,
isGenex,
"COMPILE_DEFINITIONS", llt).c_str());
this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
compileProperty(this->Target, lib,
isGenex,
"INCLUDE_DIRECTORIES", llt).c_str());
}
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> const& debugConfigs =
this->Makefile->GetCMakeInstance()->GetDebugConfigs();

View File

@ -94,6 +94,17 @@ public:
"target too. "
"See the LINK_INTERFACE_LIBRARIES target property to override the "
"set of transitive link dependencies for a target. "
"Calls to other signatures of this command may set the property "
"making any libraries linked exclusively by this signature private."
"\n"
"Target usage requirements are also consumed by this command. If the "
"<target> is linked to another target which has "
"a populated INTERFACE_INCLUDE_DIRECTORIES, the content of it is "
"appended to the INCLUDE_DIRECTORIES of <target>. Similarly, the "
"INTERFACE_COMPILE_DEFINITONS of a dependee are added to the "
"COMPILE_DEFINITONS of <target>, and the "
"INTERFACE_POSITION_INDEPENDENT_CODE property is used to determine the "
"POSITION_INDEPENDENT_CODE property of <target>."
"\n"
" target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
" [[debug|optimized|general] <lib>] ...)\n"

View File

@ -80,17 +80,16 @@ bool cmTargetPropCommandBase
return false;
}
if(this->Target->IsImported() && scope != "INTERFACE")
if(this->Target->IsImported())
{
this->HandleImportedTargetInvalidScope(args[0], scope);
this->HandleImportedTarget(args[0]);
return false;
}
++argIndex;
std::string content;
std::vector<std::string> content;
std::string sep;
for(unsigned int i=argIndex; i < args.size(); ++i, ++argIndex)
{
if(args[i] == "PUBLIC"
@ -100,16 +99,7 @@ bool cmTargetPropCommandBase
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 = ";";
content.push_back(args[i]);
}
this->PopulateTargetProperies(scope, content, prepend);
return true;
@ -118,7 +108,8 @@ bool cmTargetPropCommandBase
//----------------------------------------------------------------------------
void cmTargetPropCommandBase
::PopulateTargetProperies(const std::string &scope,
const std::string &content, bool prepend)
const std::vector<std::string> &content,
bool prepend)
{
if (scope == "PRIVATE" || scope == "PUBLIC")
{
@ -130,7 +121,7 @@ void cmTargetPropCommandBase
{
const std::string propName = std::string("INTERFACE_") + this->Property;
const char *propValue = this->Target->GetProperty(propName.c_str());
const std::string totalContent = content + (propValue
const std::string totalContent = this->Join(content) + (propValue
? std::string(";") + propValue
: std::string());
this->Target->SetProperty(propName.c_str(), totalContent.c_str());
@ -138,7 +129,7 @@ void cmTargetPropCommandBase
else
{
this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(),
content.c_str());
this->Join(content).c_str());
}
}
}

View File

@ -31,28 +31,25 @@ public:
bool HandleArguments(std::vector<std::string> const& args,
const char *prop, ArgumentFlags flags = NO_FLAGS);
cmTypeMacro(cmTargetPropCommandBase, cmCommand);
protected:
std::string Property;
cmTarget *Target;
private:
virtual void HandleImportedTargetInvalidScope(const std::string &tgt,
const std::string &scope) = 0;
virtual void HandleImportedTarget(const std::string &tgt) = 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,
const std::vector<std::string> &content,
bool prepend) = 0;
virtual std::string Join(const std::vector<std::string> &content) = 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;
const std::vector<std::string> &content,
bool prepend);
};
#endif

View File

@ -1221,8 +1221,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.Parse(flags.c_str());
clOptions.Parse(defineFlags.c_str());
clOptions.AddDefines(
this->GeneratorTarget->GetCompileDefinitions().c_str());
clOptions.AddDefines(this->GeneratorTarget->GetCompileDefinitions(
this->Target->GetCompileDefinitions().c_str());
clOptions.AddDefines(this->Target->GetCompileDefinitions(
configName.c_str()).c_str());
clOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));

View File

@ -4449,6 +4449,10 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text,
isError = true;
msg << "CMake Internal Error (please report a bug)";
}
else if(t == cmake::LOG)
{
msg << "CMake Debug Log";
}
else
{
msg << "CMake Warning";

View File

@ -428,6 +428,58 @@ const char* DynamicLoader::LastError()
} // namespace KWSYS_NAMESPACE
#endif
#ifdef __MINT__
#define DYNAMICLOADER_DEFINED 1
#define _GNU_SOURCE /* for program_invocation_name */
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <dld.h>
namespace KWSYS_NAMESPACE
{
//----------------------------------------------------------------------------
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
{
char *name = (char *)calloc(1, strlen(libname) + 1);
dld_init(program_invocation_name);
strncpy(name, libname, strlen(libname));
dld_link(libname);
return (void *)name;
}
//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
dld_unlink_by_file((char *)lib, 0);
free(lib);
return 0;
}
//----------------------------------------------------------------------------
DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
DynamicLoader::LibraryHandle lib, const char* sym)
{
// Hack to cast pointer-to-data to pointer-to-function.
union
{
void* pvoid;
DynamicLoader::SymbolPointer psym;
} result;
result.pvoid = dld_get_symbol(sym);
return result.psym;
}
//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
return dld_strerror(dld_errno);
}
} // namespace KWSYS_NAMESPACE
#endif
// ---------------------------------------------------------------
// 6. Implementation for default UNIX machines.
// if nothing has been defined then use this

View File

@ -272,6 +272,7 @@ namespace KWSYS_NAMESPACE
// Create one public symbol in this object file to avoid warnings from
// archivers.
void IOStreamSymbolToAvoidWarning();
void IOStreamSymbolToAvoidWarning()
{
}

View File

@ -102,7 +102,7 @@ static inline void kwsysProcess_usleep(unsigned int msec)
* pipes' file handles to be non-blocking and just poll them directly
* without select().
*/
#if !defined(__BEOS__) && !defined(__VMS)
#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__)
# define KWSYSPE_USE_SELECT 1
#endif

View File

@ -2466,7 +2466,9 @@ bool SystemInformationImplementation::RetrieveCPUPowerManagement()
#endif
}
void SystemInformationStripLeadingSpace(kwsys_stl::string& str)
#if USE_CPUID
// Used only in USE_CPUID implementation below.
static void SystemInformationStripLeadingSpace(kwsys_stl::string& str)
{
// Because some manufacturers have leading white space - we have to post-process the name.
kwsys_stl::string::size_type pos = str.find_first_not_of(" ");
@ -2475,6 +2477,7 @@ void SystemInformationStripLeadingSpace(kwsys_stl::string& str)
str = str.substr(pos);
}
}
#endif
/** */
bool SystemInformationImplementation::RetrieveExtendedCPUIdentity()

View File

@ -3037,7 +3037,7 @@ void SystemTools::CheckTranslationPath(kwsys_stl::string & path)
path.erase(path.end()-1, path.end());
}
void
static void
SystemToolsAppendComponents(
kwsys_stl::vector<kwsys_stl::string>& out_components,
kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
@ -4704,7 +4704,7 @@ bool SystemTools::ParseURL( const kwsys_stl::string& URL,
// ----------------------------------------------------------------------
// These must NOT be initialized. Default initialization to zero is
// necessary.
unsigned int SystemToolsManagerCount;
static unsigned int SystemToolsManagerCount;
SystemToolsTranslationMap *SystemTools::TranslationMap;
SystemToolsTranslationMap *SystemTools::LongPathMap;
#ifdef __CYGWIN__

View File

@ -24,9 +24,9 @@
#include <stddef.h> /* size_t */
#include <string.h> /* strcmp */
void* random_ptr = reinterpret_cast<void*>(0x123);
static void* random_ptr = reinterpret_cast<void*>(0x123);
int argument(const char* arg, const char* value, void* call_data)
static int argument(const char* arg, const char* value, void* call_data)
{
kwsys_ios::cout << "Got argument: \"" << arg << "\" value: \"" << (value?value:"(null)") << "\"" << kwsys_ios::endl;
if ( call_data != random_ptr )
@ -37,7 +37,7 @@ int argument(const char* arg, const char* value, void* call_data)
return 1;
}
int unknown_argument(const char* argument, void* call_data)
static int unknown_argument(const char* argument, void* call_data)
{
kwsys_ios::cout << "Got unknown argument: \"" << argument << "\"" << kwsys_ios::endl;
if ( call_data != random_ptr )
@ -48,12 +48,12 @@ int unknown_argument(const char* argument, void* call_data)
return 1;
}
bool CompareTwoItemsOnList(bool i1, bool i2) { return i1 == i2; }
bool CompareTwoItemsOnList(int i1, int i2) { return i1 == i2; }
bool CompareTwoItemsOnList(double i1, double i2) { return i1 == i2; }
bool CompareTwoItemsOnList(const char* i1,
static bool CompareTwoItemsOnList(bool i1, bool i2) { return i1 == i2; }
static bool CompareTwoItemsOnList(int i1, int i2) { return i1 == i2; }
static bool CompareTwoItemsOnList(double i1, double i2) { return i1 == i2; }
static bool CompareTwoItemsOnList(const char* i1,
const char* i2) { return strcmp(i1, i2) == 0; }
bool CompareTwoItemsOnList(const kwsys_stl::string& i1,
static bool CompareTwoItemsOnList(const kwsys_stl::string& i1,
const kwsys_stl::string& i2) { return i1 == i2; }
int testCommandLineArguments(int argc, char* argv[])

View File

@ -35,7 +35,7 @@
// left on disk.
#include <testSystemTools.h>
kwsys_stl::string GetLibName(const char* lname)
static kwsys_stl::string GetLibName(const char* lname)
{
// Construct proper name of lib
kwsys_stl::string slname;

View File

@ -47,7 +47,7 @@ int runChild(const char* cmd[], int state, int exception, int value,
int share, int output, int delay, double timeout, int poll,
int repeat, int disown);
int test1(int argc, const char* argv[])
static int test1(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout from test returning 0.\n");
@ -55,7 +55,7 @@ int test1(int argc, const char* argv[])
return 0;
}
int test2(int argc, const char* argv[])
static int test2(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout from test returning 123.\n");
@ -63,7 +63,7 @@ int test2(int argc, const char* argv[])
return 123;
}
int test3(int argc, const char* argv[])
static int test3(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output before sleep on stdout from timeout test.\n");
@ -80,7 +80,7 @@ int test3(int argc, const char* argv[])
return 0;
}
int test4(int argc, const char* argv[])
static int test4(int argc, const char* argv[])
{
/* Prepare a pointer to an invalid address. Don't use null, because
dereferencing null is undefined behaviour and compilers are free to
@ -109,7 +109,7 @@ int test4(int argc, const char* argv[])
return 0;
}
int test5(int argc, const char* argv[])
static int test5(int argc, const char* argv[])
{
int r;
const char* cmd[4];
@ -132,7 +132,7 @@ int test5(int argc, const char* argv[])
}
#define TEST6_SIZE (4096*2)
void test6(int argc, const char* argv[])
static void test6(int argc, const char* argv[])
{
int i;
char runaway[TEST6_SIZE+1];
@ -156,7 +156,7 @@ void test6(int argc, const char* argv[])
delaying 1/10th of a second should ever have to poll. */
#define MINPOLL 5
#define MAXPOLL 20
int test7(int argc, const char* argv[])
static int test7(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout before sleep.\n");
@ -176,7 +176,7 @@ int test7(int argc, const char* argv[])
return 0;
}
int test8(int argc, const char* argv[])
static int test8(int argc, const char* argv[])
{
/* Create a disowned grandchild to test handling of processes
that exit before their children. */
@ -200,7 +200,7 @@ int test8(int argc, const char* argv[])
return r;
}
int test8_grandchild(int argc, const char* argv[])
static int test8_grandchild(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
@ -221,7 +221,7 @@ int test8_grandchild(int argc, const char* argv[])
return 0;
}
int runChild2(kwsysProcess* kp,
static int runChild2(kwsysProcess* kp,
const char* cmd[], int state, int exception, int value,
int share, int output, int delay, double timeout,
int poll, int disown)
@ -505,7 +505,7 @@ int main(int argc, const char* argv[])
fprintf(stderr, "Output on stderr after test %d.\n", n);
fflush(stdout);
fflush(stderr);
#if _WIN32
#if defined(_WIN32)
if(argv0) { free(argv0); }
#endif
return r;

View File

@ -32,7 +32,7 @@
#include <string.h> /* strcmp */
//----------------------------------------------------------------------------
const char* toUnixPaths[][2] =
static const char* toUnixPaths[][2] =
{
{ "/usr/local/bin/passwd", "/usr/local/bin/passwd" },
{ "/usr/lo cal/bin/pa sswd", "/usr/lo cal/bin/pa sswd" },
@ -52,7 +52,7 @@ const char* toUnixPaths[][2] =
{0, 0}
};
bool CheckConvertToUnixSlashes(kwsys_stl::string input,
static bool CheckConvertToUnixSlashes(kwsys_stl::string input,
kwsys_stl::string output)
{
kwsys_stl::string result = input;
@ -69,14 +69,14 @@ bool CheckConvertToUnixSlashes(kwsys_stl::string input,
}
//----------------------------------------------------------------------------
const char* checkEscapeChars[][4] =
static const char* checkEscapeChars[][4] =
{
{ "1 foo 2 bar 2", "12", "\\", "\\1 foo \\2 bar \\2"},
{ " {} ", "{}", "#", " #{#} "},
{0, 0, 0, 0}
};
bool CheckEscapeChars(kwsys_stl::string input,
static bool CheckEscapeChars(kwsys_stl::string input,
const char *chars_to_escape,
char escape_char,
kwsys_stl::string output)
@ -95,7 +95,7 @@ bool CheckEscapeChars(kwsys_stl::string input,
}
//----------------------------------------------------------------------------
bool CheckFileOperations()
static bool CheckFileOperations()
{
bool res = true;
@ -129,7 +129,7 @@ bool CheckFileOperations()
}
//----------------------------------------------------------------------------
bool CheckStringOperations()
static bool CheckStringOperations()
{
bool res = true;
@ -329,7 +329,7 @@ bool CheckStringOperations()
//----------------------------------------------------------------------------
bool CheckPutEnv(const char* env, const char* name, const char* value)
static bool CheckPutEnv(const char* env, const char* name, const char* value)
{
if(!kwsys::SystemTools::PutEnv(env))
{
@ -348,7 +348,7 @@ bool CheckPutEnv(const char* env, const char* name, const char* value)
return true;
}
bool CheckUnPutEnv(const char* env, const char* name)
static bool CheckUnPutEnv(const char* env, const char* name)
{
if(!kwsys::SystemTools::UnPutEnv(env))
{
@ -365,7 +365,7 @@ bool CheckUnPutEnv(const char* env, const char* name)
return true;
}
bool CheckEnvironmentOperations()
static bool CheckEnvironmentOperations()
{
bool res = true;
res &= CheckPutEnv("A=B", "A", "B");

View File

@ -12,17 +12,19 @@ target_compile_definitions(target_compile_definitions
INTERFACE MY_INTERFACE_DEFINE
)
add_library(importedlib UNKNOWN IMPORTED)
target_compile_definitions(importedlib
INTERFACE MY_IMPORTEDINTERFACE_DEFINE
)
add_executable(consumer
"${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
)
add_library(linked UNKNOWN IMPORTED)
set_property(TARGET linked PROPERTY
INTERFACE_COMPILE_DEFINITIONS "MY_LINKED_DEFINE")
target_compile_definitions(consumer
PRIVATE target_compile_definitions importedlib
PRIVATE $<TARGET_PROPERTY:target_compile_definitions,INTERFACE_COMPILE_DEFINITIONS>
$<$<TARGET_DEFINED:notdefined>:SHOULD_NOT_BE_DEFINED>
$<$<TARGET_DEFINED:importedlib>:SHOULD_BE_DEFINED>
$<$<TARGET_DEFINED:target_compile_definitions>:SHOULD_BE_DEFINED>
$<LINKED:linked>
-DDASH_D_DEFINE
)

View File

@ -11,10 +11,6 @@
#error Expected MY_INTERFACE_DEFINE
#endif
#ifndef MY_IMPORTEDINTERFACE_DEFINE
#error Expected MY_IMPORTEDINTERFACE_DEFINE
#endif
#ifdef SHOULD_NOT_BE_DEFINED
#error Unexpected SHOULD_NOT_BE_DEFINED
#endif
@ -23,4 +19,12 @@
#error Expected SHOULD_BE_DEFINED
#endif
#ifndef DASH_D_DEFINE
#error Expected DASH_D_DEFINE
#endif
#ifndef MY_LINKED_DEFINE
#error Expected MY_LINKED_DEFINE
#endif
int main() { return 0; }

View File

@ -11,15 +11,15 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/publicinclude/publicinclude.h" "#define
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude/interfaceinclude.h" "#define INTERFACEINCLUDE_DEFINE\n")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude/importedinterfaceinclude.h" "#define IMPORTEDINTERFACEINCLUDE_DEFINE\n")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/poison")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/poison/common.h" "#error Should not be included\n")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/cure")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cure/common.h" "#define CURE_DEFINE\n")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/linkedinclude")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/linkedinclude/linkedinclude.h" "#define LINKEDINCLUDE_DEFINE\n")
add_executable(target_include_directories
"${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
)
@ -33,18 +33,25 @@ target_include_directories(target_include_directories
PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/poison"
)
target_include_directories(target_include_directories
BEFORE PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/cure"
BEFORE PUBLIC "$<$<TARGET_DEFINED:target_include_directories>:${CMAKE_CURRENT_BINARY_DIR}/cure>"
)
add_library(importedlib UNKNOWN IMPORTED)
target_include_directories(importedlib
INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude"
# Has no effect because the target is not defined:
target_include_directories(target_include_directories
BEFORE PUBLIC "$<$<TARGET_DEFINED:notdefined>:${CMAKE_CURRENT_BINARY_DIR}/poison>"
)
add_executable(consumer
"${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
)
add_library(linked UNKNOWN IMPORTED)
set_property(TARGET linked PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/linkedinclude")
target_include_directories(consumer
PRIVATE target_include_directories importedlib
PRIVATE
$<TARGET_PROPERTY:target_include_directories,INTERFACE_INCLUDE_DIRECTORIES>
$<LINKED:linked>
relative_dir
)

View File

@ -2,7 +2,8 @@
#include "common.h"
#include "publicinclude.h"
#include "interfaceinclude.h"
#include "importedinterfaceinclude.h"
#include "relative_dir.h"
#include "linkedinclude.h"
#ifdef PRIVATEINCLUDE_DEFINE
#error Unexpected PRIVATEINCLUDE_DEFINE
@ -16,12 +17,16 @@
#error Expected INTERFACEINCLUDE_DEFINE
#endif
#ifndef IMPORTEDINTERFACEINCLUDE_DEFINE
#error Expected IMPORTEDINTERFACEINCLUDE_DEFINE
#endif
#ifndef CURE_DEFINE
#error Expected CURE_DEFINE
#endif
#ifndef RELATIVE_DIR_DEFINE
#error Expected RELATIVE_DIR_DEFINE
#endif
#ifndef LINKEDINCLUDE_DEFINE
#error Expected LINKEDINCLUDE_DEFINE
#endif
int main() { return 0; }

View File

@ -0,0 +1,2 @@
#define RELATIVE_DIR_DEFINE

View File

@ -29,9 +29,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_library(depA SHARED depA.cpp)
generate_export_header(depA)
add_library(importedlib UNKNOWN IMPORTED)
target_link_libraries(importedlib LINK_INTERFACE_LIBRARIES depA)
add_library(depB SHARED depB.cpp)
generate_export_header(depB)
@ -65,10 +62,6 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "")
add_subdirectory(subdir)
target_link_libraries(targetA subdirlib)
set_property(TARGET targetA APPEND PROPERTY
INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:subdirlib,INTERFACE_INCLUDE_DIRECTORIES>
)
target_link_libraries(targetA depB depC)
@ -90,3 +83,24 @@ set_property(TARGET depD APPEND PROPERTY
add_executable(targetB targetB.cpp)
target_link_libraries(targetB depD)
macro(create_header _name)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_name}")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_name}/${_name}.h" "//${_name}.h\n")
endmacro()
create_header(foo)
create_header(bar)
add_library(depG SHARED depG.cpp)
generate_export_header(depG)
target_include_directories(depG INTERFACE
"${CMAKE_CURRENT_BINARY_DIR}/foo"
"${CMAKE_CURRENT_BINARY_DIR}/bar"
)
target_compile_definitions(depG INTERFACE
TEST_DEF
)
add_executable(targetC targetC.cpp)
target_link_libraries(targetC depG)

View File

@ -0,0 +1,7 @@
#include "depG.h"
int DepG::foo()
{
return 0;
}

View File

@ -0,0 +1,7 @@
#include "depg_export.h"
struct DEPG_EXPORT DepG
{
int foo();
};

View File

@ -0,0 +1,16 @@
#include "depG.h"
#include "foo.h"
#include "bar.h"
#ifndef TEST_DEF
#error Expected TEST_DEF definition
#endif
int main(int argc, char **argv)
{
DepG g;
return g.foo();
}

View File

@ -216,6 +216,7 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(PolicyScope PolicyScope)
ADD_TEST_MACRO(EmptyLibrary EmptyLibrary)
ADD_TEST_MACRO(CompileDefinitions CompileDefinitions)
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
set_tests_properties(EmptyLibrary PROPERTIES
PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target:test")
ADD_TEST_MACRO(CrossCompile CrossCompile)
@ -311,6 +312,19 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(Module.CheckTypeSize CheckTypeSize)
add_test(Module.ExternalData ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/Module/ExternalData"
"${CMake_BINARY_DIR}/Tests/Module/ExternalData"
--build-generator ${CMAKE_TEST_GENERATOR}
--build-project ExternalDataTest
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
--build-noclean
--force-new-ctest-process
--test-command ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} -V
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Module/ExternalData")
ADD_TEST_MACRO(Module.GenerateExportHeader GenerateExportHeader)
if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
@ -1976,6 +1990,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
--output-log "${CMake_BINARY_DIR}/Tests/CTestTestParallel/testOutput.log"
)
set(CTestLimitDashJ_EXTRA_OPTIONS --force-new-ctest-process)
add_test_macro(CTestLimitDashJ ${CMAKE_CTEST_COMMAND} -j 4
--output-on-failure -C "\${CTestTest_CONFIG}")

View File

@ -4,7 +4,8 @@ set(CMAKE_EXECUTABLE "${CMake_BIN_DIR}/cmake")
macro(AddCMakeTest TestName PreArgs)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${TestName}Test.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" @ONLY IMMEDIATE)
add_test(CMake.${TestName} ${CMAKE_EXECUTABLE} ${PreArgs}
add_test(NAME CMake.${TestName}
COMMAND ${CMAKE_EXECUTABLE} ${PreArgs}
-P "${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" ${ARGN})
endmacro()
@ -28,7 +29,7 @@ AddCMakeTest(String "")
AddCMakeTest(Math "")
AddCMakeTest(CMakeMinimumRequired "")
AddCMakeTest(CompilerIdVendor "")
AddCMakeTest(ProcessorCount "")
AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>")
AddCMakeTest(PushCheckState "")
AddCMakeTest(While "")

View File

@ -9,10 +9,17 @@ message("### 3. ProcessorCount(...) function call is emitting output that it sho
message("processor_count='${processor_count}'")
execute_process(
COMMAND "@CMAKE_BINARY_DIR@/Source/kwsys/$ENV{CMAKE_CONFIG_TYPE}/cmsysTestsCxx"
COMMAND "${KWSYS_TEST_EXE}"
testSystemInformation
OUTPUT_VARIABLE tsi_out
ERROR_VARIABLE tsi_err)
ERROR_VARIABLE tsi_err
RESULT_VARIABLE tsi_res
)
if (tsi_res)
message("executing \"${KWSYS_TEST_EXE}\" failed")
message(FATAL_ERROR "output: ${tsi_res}")
endif ()
string(REGEX REPLACE "(.*)GetNumberOfPhysicalCPU:.([0-9]*)(.*)" "\\2"
system_info_processor_count "${tsi_out}")

View File

@ -0,0 +1,69 @@
cmake_minimum_required(VERSION 2.8)
project(CompatibleInterface)
include(GenerateExportHeader)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_library(iface1 empty.cpp)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL
BOOL_PROP1
BOOL_PROP2
BOOL_PROP3
BOOL_PROP4
)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING
STRING_PROP1
STRING_PROP2
STRING_PROP3
)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP1 ON)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP2 ON)
set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP1 prop1)
set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP2 prop2)
add_executable(CompatibleInterface main.cpp)
target_link_libraries(CompatibleInterface iface1)
set_property(TARGET CompatibleInterface PROPERTY BOOL_PROP2 ON)
set_property(TARGET CompatibleInterface PROPERTY BOOL_PROP3 ON)
set_property(TARGET CompatibleInterface PROPERTY STRING_PROP2 prop2)
set_property(TARGET CompatibleInterface PROPERTY STRING_PROP3 prop3)
target_compile_definitions(CompatibleInterface
PRIVATE
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP1>>:BOOL_PROP1>
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP2>>:BOOL_PROP2>
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP3>>:BOOL_PROP3>
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP1>,prop1>:STRING_PROP1>
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP2>,prop2>:STRING_PROP2>
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP3>,prop3>:STRING_PROP3>
)
add_library(iface2 SHARED iface2.cpp)
generate_export_header(iface2)
set_property(TARGET iface2 APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING
Iface2_PROP
)
# For the LINK_LIBRARIES and related properties, we should not evaluate
# properties defined only in the interface - they should be implicitly zero
set_property(TARGET iface2
APPEND PROPERTY
LINK_INTERFACE_LIBRARIES $<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP4>>:nonexistant>
)
target_link_libraries(CompatibleInterface iface2
$<$<BOOL:$<TARGET_PROPERTY:Iface2_PROP>>:nonexistant>
)
# Test that this does not segfault:
target_compile_definitions(CompatibleInterface
PRIVATE
$<$<BOOL:$<TARGET_PROPERTY:Iface2_PROP>>:SOME_DEFINE>
)

View File

@ -0,0 +1 @@
// no content

View File

@ -0,0 +1,7 @@
#include "iface2.h"
int Iface2::foo()
{
return 0;
}

View File

@ -0,0 +1,13 @@
#ifndef IFACE2_H
#define IFACE2_H
#include "iface2_export.h"
class IFACE2_EXPORT Iface2
{
public:
int foo();
};
#endif

View File

@ -0,0 +1,32 @@
#ifndef BOOL_PROP1
#error Expected BOOL_PROP1
#endif
#ifndef BOOL_PROP2
#error Expected BOOL_PROP2
#endif
#ifndef BOOL_PROP3
#error Expected BOOL_PROP3
#endif
#ifndef STRING_PROP1
#error Expected STRING_PROP1
#endif
#ifndef STRING_PROP2
#error Expected STRING_PROP2
#endif
#ifndef STRING_PROP3
#error Expected STRING_PROP3
#endif
#include "iface2.h"
int main(int argc, char **argv)
{
Iface2 if2;
return if2.foo();
}

View File

@ -90,32 +90,23 @@ set_property(TARGET testLibCycleA PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
# Test exporting dependent libraries into different exports
add_library(testLibRequired testLibRequired.c)
add_library(testLibDepends testLibDepends.c)
set_property(TARGET testLibDepends APPEND PROPERTY
INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:testLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
)
set_property(TARGET testLibDepends APPEND PROPERTY
COMPILE_DEFINITIONS
$<TARGET_PROPERTY:testLibRequired,INTERFACE_COMPILE_DEFINITIONS>
)
set_property(TARGET testLibDepends APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:testLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
)
set_property(TARGET testLibDepends APPEND PROPERTY
INTERFACE_COMPILE_DEFINITIONS
$<TARGET_PROPERTY:testLibRequired,INTERFACE_COMPILE_DEFINITIONS>
)
target_link_libraries(testLibDepends testLibRequired)
target_link_libraries(testLibDepends LINK_PUBLIC testLibRequired)
macro(add_include_lib _libName)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c" "// no content\n")
add_library(${_libName} "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_libName}")
set_property(TARGET ${_libName} APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/${_libName}")
INTERFACE_INCLUDE_DIRECTORIES
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/${_libName}>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/${_libName}>"
)
if (NOT "${ARGV1}" STREQUAL "NO_HEADER")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}/${_libName}.h" "// no content\n")
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${_libName}/${_libName}.h"
DESTINATION include/${_libName}
)
endif()
endmacro()
@ -129,6 +120,10 @@ add_include_lib(testLibIncludeRequired3 NO_HEADER)
# but we are testing that the INSTALL_INTERFACE causes it not to be used
# at build time.
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired3/testLibIncludeRequired4.h" "#error Should not be included\n")
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired3/testLibIncludeRequired4.h"
DESTINATION include/testLibIncludeRequired3
)
add_include_lib(testLibIncludeRequired4)
add_include_lib(testLibIncludeRequired5 NO_HEADER)
# Generate testLibIncludeRequired6 in the testLibIncludeRequired5 directory
@ -139,6 +134,10 @@ add_include_lib(testLibIncludeRequired5 NO_HEADER)
# the Import side of this unit test, the '6' include from the '5' directory
# will not be used because it is in the BUILD_INTERFACE only.
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired5/testLibIncludeRequired6.h" "#error Should not be included\n")
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired5/testLibIncludeRequired6.h"
DESTINATION include/testLibIncludeRequired5
)
add_include_lib(testLibIncludeRequired6)
set_property(TARGET testLibRequired APPEND PROPERTY
@ -149,6 +148,8 @@ set_property(TARGET testLibRequired APPEND PROPERTY
$<BUILD_INTERFACE:$<TARGET_PROPERTY:testLibIncludeRequired4,INTERFACE_INCLUDE_DIRECTORIES>>
$<BUILD_INTERFACE:$<TARGET_PROPERTY:testLibIncludeRequired5,INTERFACE_INCLUDE_DIRECTORIES>>
$<INSTALL_INTERFACE:$<TARGET_PROPERTY:testLibIncludeRequired6,INTERFACE_INCLUDE_DIRECTORIES>>
# Test that the below is non-fatal
$<$<TARGET_DEFINED:not_a_target>:$<TARGET_PROPERTY:not_a_target,INTERFACE_INCLUDE_DIRECTORIES>>
)
set_property(TARGET testLibRequired APPEND PROPERTY
@ -173,6 +174,22 @@ set_property(TARGET testSharedLibRequired APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
)
set_property(TARGET testSharedLibRequired
APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL CUSTOM_PROP
)
set_property(TARGET testSharedLibRequired
PROPERTY
INTERFACE_CUSTOM_PROP ON
)
set_property(TARGET testSharedLibRequired
APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING CUSTOM_STRING
)
set_property(TARGET testSharedLibRequired
PROPERTY
INTERFACE_CUSTOM_STRING testcontent
)
add_library(testSharedLibDepends SHARED testSharedLibDepends.cpp)
set_property(TARGET testSharedLibDepends APPEND PROPERTY
@ -201,11 +218,30 @@ install(TARGETS testLibRequired
testLibIncludeRequired6
testSharedLibRequired
EXPORT RequiredExp DESTINATION lib )
install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired)
install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredTargets.cmake DESTINATION lib/cmake/testLibRequired)
install(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib )
install(EXPORT DependsExp FILE testLibDependsConfig.cmake DESTINATION lib/cmake/testLibDepends)
install(EXPORT DependsExp FILE testLibDependsTargets.cmake DESTINATION lib/cmake/testLibDepends)
file(WRITE
"${CMAKE_CURRENT_BINARY_DIR}/testLibRequiredConfig.cmake"
"
if(\${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION VERSION_LESS 2.3 AND NOT \${CMAKE_FIND_PACKAGE_NAME}_INTERFACES)
set(\${CMAKE_FIND_PACKAGE_NAME}_NO_INTERFACES 1)
endif()
include(\"\${CMAKE_CURRENT_LIST_DIR}/testLibRequiredTargets.cmake\")
set(\${CMAKE_FIND_PACKAGE_NAME}_INCLUDE_DIRS \"${CMAKE_CURRENT_BINARY_DIR}\" \"${CMAKE_CURRENT_SOURCE_DIR}\" )
"
)
include(CMakePackageConfigHelpers)
write_basic_package_version_file( testLibRequiredConfigVersion.cmake VERSION 2.5 COMPATIBILITY AnyNewerVersion)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/testLibRequiredConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/testLibRequiredConfigVersion.cmake"
DESTINATION lib/cmake/testLibRequired
)
# Install and export from install tree.
install(

View File

@ -5,8 +5,8 @@ include(${Import_BINARY_DIR}/../Export/ExportBuildTree.cmake)
include(${CMAKE_INSTALL_PREFIX}/lib/exp/exp.cmake)
# Import two exports, where the Depends one depends on an exported target from the Required one:
include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibRequired/testLibRequiredConfig.cmake)
include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibDepends/testLibDependsConfig.cmake)
include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibRequired/testLibRequiredTargets.cmake)
include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibDepends/testLibDependsTargets.cmake)
# Try referencing an executable imported from the install tree.
add_custom_command(
@ -159,13 +159,15 @@ endif()
add_executable(deps_iface deps_iface.c)
target_link_libraries(deps_iface testLibDepends)
target_include_directories(deps_iface PRIVATE testLibDepends)
target_compile_definitions(deps_iface PRIVATE testLibDepends)
add_executable(deps_shared_iface deps_shared_iface.cpp)
target_link_libraries(deps_shared_iface testSharedLibDepends)
target_include_directories(deps_shared_iface PRIVATE testSharedLibDepends)
target_compile_definitions(deps_shared_iface PRIVATE testSharedLibDepends)
target_compile_definitions(deps_shared_iface
PRIVATE
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
$<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>
)
if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
include(CheckCXXCompilerFlag)
@ -191,7 +193,9 @@ endif()
add_executable(deps_shared_iface2 deps_shared_iface.cpp)
target_link_libraries(deps_shared_iface2 bld_testSharedLibDepends bld_subdirlib)
target_include_directories(deps_shared_iface2 PRIVATE bld_testSharedLibDepends bld_subdirlib)
target_compile_definitions(deps_shared_iface2
PRIVATE bld_testSharedLibDepends TEST_SUBDIR_LIB
PRIVATE TEST_SUBDIR_LIB
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
$<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>
)

View File

@ -8,6 +8,18 @@
#endif
#endif
#ifndef PIC_PROPERTY_IS_ON
#error Expected PIC_PROPERTY_IS_ON
#endif
#ifndef CUSTOM_PROPERTY_IS_ON
#error Expected CUSTOM_PROPERTY_IS_ON
#endif
#ifndef CUSTOM_STRING_IS_MATCH
#error Expected CUSTOM_STRING_IS_MATCH
#endif
#ifdef TEST_SUBDIR_LIB
#include "subdir.h"
#endif

View File

@ -17,3 +17,8 @@ add_executable(imp_testTransExe1 imp_testTransExe1.c)
target_link_libraries(imp_testTransExe1 imp_lib1)
add_executable(imp_testTransExe1b imp_testTransExe1.c)
target_link_libraries(imp_testTransExe1b imp_lib1b)
# Test package INTERFACE controls
add_subdirectory(package_old_old)
add_subdirectory(package_new_old)
add_subdirectory(package_new_new)

View File

@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 2.8)
find_package(testLibRequired 2.5 REQUIRED)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
"
#include \"testSharedLibRequired.h\"
int main(int argc, char **argv)
{
TestSharedLibRequired req;
return req.foo();
}
"
)
get_target_property(prop Req::testSharedLibRequired INTERFACE_INCLUDE_DIRECTORIES)
if (NOT prop)
message(SEND_ERROR "Interface of Req::testSharedLibRequired should not be empty")
endif()
add_executable(new_new_test "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
target_link_libraries(new_new_test Req::testSharedLibRequired)

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 2.8)
find_package(testLibRequired 2.5 REQUIRED)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
"
#include \"testSharedLibRequired.h\"
int main(int argc, char **argv)
{
TestSharedLibRequired req;
return req.foo();
}
"
)
get_target_property(prop Req::testSharedLibRequired INTERFACE_INCLUDE_DIRECTORIES)
if ("${prop}" STREQUAL "")
message(SEND_ERROR "Interface of Req::testSharedLibRequired should not be empty")
endif()
add_executable(new_old_test "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
target_link_libraries(new_old_test Req::testSharedLibRequired)
include_directories(${testLibRequired_INCLUDE_DIRS})

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 2.8)
find_package(testLibRequired 2.1 REQUIRED)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
"
#include \"testSharedLibRequired.h\"
int main(int argc, char **argv)
{
TestSharedLibRequired req;
return req.foo();
}
"
)
get_target_property(prop Req::testSharedLibRequired INTERFACE_INCLUDE_DIRECTORIES)
if (prop)
message(SEND_ERROR "Interface of Req::testSharedLibRequired should be empty, but is ${prop}")
endif()
add_executable(old_old_test "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
target_link_libraries(old_old_test Req::testSharedLibRequired)
include_directories(${testLibRequired_INCLUDE_DIRS})

View File

@ -50,6 +50,8 @@ if(NOT DEFINED can_build_tutorial_step5)
endif()
endif()
add_custom_target(NonExternalProjectTarget
COMMAND ${CMAKE_COMMAND} -E echo NonExternalProjectTarget)
# Empty projects that test all the known ExternalProject_Add argument key words:
#
@ -94,7 +96,7 @@ ExternalProject_Add(${proj}
CVS_REPOSITORY ""
CVS_MODULE ""
CVS_TAG ""
DEPENDS "MinimalNoOpProject"
DEPENDS "MinimalNoOpProject" NonExternalProjectTarget
DOWNLOAD_COMMAND ""
INSTALL_COMMAND ""
PATCH_COMMAND ""

View File

@ -82,3 +82,44 @@ add_custom_target(test_custom_target
$<TARGET_PROPERTY:TargetIncludeDirectories,COMPILE_DEFINITIONS>
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bad")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/bad/common.h" "#error Should not be included\n")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/good")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/good/common.h" "#include \"othergood.h\"\n")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/othergood")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/othergood/othergood.h" "// No error\n")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libothergood.cpp" "// No content \n")
add_library(libothergood "${CMAKE_CURRENT_BINARY_DIR}/libothergood.cpp")
set_property(TARGET libothergood APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/othergood"
)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libgood.cpp" "// No content \n")
add_library(libgood "${CMAKE_CURRENT_BINARY_DIR}/libgood.cpp")
set_property(TARGET libgood APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES
"${CMAKE_CURRENT_BINARY_DIR}/good;$<TARGET_PROPERTY:libothergood,INTERFACE_INCLUDE_DIRECTORIES>"
)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libbad.cpp" "// No content \n")
add_library(libbad "${CMAKE_CURRENT_BINARY_DIR}/libbad.cpp")
set_property(TARGET libbad APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/bad"
)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp" "#include \"common.h\"\n")
add_library(lib5 "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp")
# Assuming the link order must be:
target_link_libraries(lib5 libbad libgood)
# Oops!.
# As include directory order and link order are the same when using target_link_libraries, we have to
# get the libgood includes in before the libbad includes.
# We do that with this command:
target_include_directories(lib5
BEFORE PRIVATE $<LINKED:libgood>
)

View File

@ -0,0 +1,38 @@
cmake_minimum_required(VERSION 2.8.10.20130115)
project(ExternalDataTest NONE)
include(CTest)
include(ExternalData)
if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/")
set(slash /)
endif()
set(ExternalData_URL_TEMPLATES
"file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/%(algo)/%(hash)"
)
set(ExternalData_BINARY_ROOT "${CMAKE_CURRENT_BINARY_DIR}/ExternalData")
file(REMOVE_RECURSE ${ExternalData_BINARY_ROOT}) # clean test
ExternalData_Add_Test(Data1
NAME Data1Check
COMMAND ${CMAKE_COMMAND}
-D Data=DATA{Data.dat}
-D SeriesA=DATA{SeriesA.dat,:}
-D SeriesB=DATA{SeriesB.dat,:}
-D SeriesC=DATA{SeriesC.dat,:}
-D SeriesD=DATA{SeriesD.dat,:}
-D SeriesAn=DATA{SeriesAn1.dat,:}
-D SeriesBn=DATA{SeriesBn_1.dat,:}
-D SeriesCn=DATA{SeriesCn.1.dat,:}
-D SeriesDn=DATA{SeriesDn-1.dat,:}
-D SeriesMixed=DATA{SeriesMixed.1.dat,:}
-D Paired=DATA{PairedA.dat,PairedB.dat}
-D Meta=DATA{MetaTop.dat,REGEX:Meta[ABC].dat}
-D Directory=DATA{Directory/,A.dat,REGEX:[BC].dat}
-P ${CMAKE_CURRENT_SOURCE_DIR}/Data1Check.cmake
)
ExternalData_Add_Target(Data1)
add_subdirectory(Data2)
add_subdirectory(Data3)

View File

@ -0,0 +1 @@
8c018830e3efa5caf3c7415028335a57

View File

@ -0,0 +1,52 @@
file(STRINGS "${Data}" lines LIMIT_INPUT 1024)
if(NOT "x${lines}" STREQUAL "xInput file already transformed.")
message(SEND_ERROR "Input file:\n ${Data}\ndoes not have expected content, but [[${lines}]]")
endif()
set(SeriesAn1 "1\\.dat")
set(SeriesBn1 "_1\\.dat")
set(SeriesCn1 "\\.1\\.dat")
set(SeriesDn1 "-1\\.dat")
set(SeriesAl 1 2 3)
set(SeriesBl _1 _2 _3)
set(SeriesCl .1 .2 .3)
set(SeriesDl -1 -2 -3)
foreach(s A B C D)
foreach(n "" ${Series${s}l})
string(REGEX REPLACE "\\.dat$" "${n}.dat" file "${Series${s}}")
if(NOT EXISTS "${file}")
message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
endif()
endforeach()
endforeach()
foreach(s A B C D)
foreach(n ${Series${s}l})
string(REGEX REPLACE "${Series${s}n1}$" "${n}.dat" file "${Series${s}n}")
if(NOT EXISTS "${file}")
message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
endif()
endforeach()
endforeach()
foreach(n .1 .2 .3 .4)
string(REGEX REPLACE "\\.1\\.dat$" "${n}.dat" file "${SeriesMixed}")
if(NOT EXISTS "${file}")
message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
endif()
endforeach()
foreach(n A B)
string(REGEX REPLACE "A\\.dat$" "${n}.dat" file "${Paired}")
if(NOT EXISTS "${file}")
message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
endif()
endforeach()
foreach(n Top A B C)
string(REGEX REPLACE "Top\\.dat$" "${n}.dat" file "${Meta}")
if(NOT EXISTS "${file}")
message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
endif()
endforeach()
foreach(n A B C)
set(file "${Directory}/${n}.dat")
if(NOT EXISTS "${file}")
message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
endif()
endforeach()

View File

@ -0,0 +1 @@
8c018830e3efa5caf3c7415028335a57

View File

@ -0,0 +1,11 @@
set(ExternalData_SERIES_PARSE "([0-9]+)(_\\.my\\.dat)$")
set(ExternalData_SERIES_MATCH "([0-9]+)")
ExternalData_Add_Test(Data2
NAME Data2Check
COMMAND ${CMAKE_COMMAND}
-D Data2=DATA{../Data2.dat}
-D Data2b=DATA{${CMAKE_CURRENT_SOURCE_DIR}/../Data2b.dat}
-D SeriesC=DATA{SeriesC_1_.my.dat,:}
-P ${CMAKE_CURRENT_SOURCE_DIR}/Data2Check.cmake
)
ExternalData_Add_Target(Data2)

View File

@ -0,0 +1,12 @@
foreach(d "${Data2}" "${Data2b}")
file(STRINGS "${d}" lines LIMIT_INPUT 1024)
if(NOT "x${lines}" STREQUAL "xInput file already transformed.")
message(SEND_ERROR "Input file:\n ${d}\ndoes not have expected content, but [[${lines}]]")
endif()
endforeach()
foreach(n 1 2 3)
string(REGEX REPLACE "_1_\\.my\\.dat$" "_${n}_.my.dat" SeriesCFile "${SeriesC}")
if(NOT EXISTS "${SeriesCFile}")
message(SEND_ERROR "Input file:\n ${SeriesCFile}\ndoes not exist!")
endif()
endforeach()

View File

@ -0,0 +1 @@
31eff09e84fca01415f8cd9d82ec432b

View File

@ -0,0 +1 @@
f7ab5a04aae9cb9a520e70b20b9c8ed7

View File

@ -0,0 +1 @@
30ba0acdee9096b3b9fc6c69362c6b42

View File

@ -0,0 +1 @@
8c018830e3efa5caf3c7415028335a57

View File

@ -0,0 +1,14 @@
set(Store0 ${CMAKE_BINARY_DIR}/ExternalData/Other)
set(Store1 ${CMAKE_BINARY_DIR}/ExternalData/Objects)
set(ExternalData_OBJECT_STORES ${Store0} ${Store1})
ExternalData_Add_Test(Data3
NAME Data3Check
COMMAND ${CMAKE_COMMAND}
-D Data=DATA{Data.dat}
-D Other=DATA{Other.dat}
-D Store0=${Store0}
-D Store1=${Store1}
-P ${CMAKE_CURRENT_SOURCE_DIR}/Data3Check.cmake
)
ExternalData_Add_Target(Data3)
add_dependencies(Data3 Data1 Data2)

View File

@ -0,0 +1 @@
8c018830e3efa5caf3c7415028335a57

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