229 lines
8.5 KiB
CMake
Executable File
229 lines
8.5 KiB
CMake
Executable File
# Create rule for obtain one file by copying another one
|
|
function(rule_copy_file target_file source_file)
|
|
add_custom_command(OUTPUT ${target_file}
|
|
COMMAND cp -p ${source_file} ${target_file}
|
|
DEPENDS ${source_file}
|
|
)
|
|
endfunction(rule_copy_file target_file source_file)
|
|
|
|
# rule_copy_source([source_dir] file ...)
|
|
#
|
|
# Create rule for obtain file(s) in binary tree by copiing it from source tree.
|
|
#
|
|
# Files are given relative to ${source_dir}, if it is set, or
|
|
# relative to ${CMAKE_CURRENT_SOURCE_DIR}.
|
|
#
|
|
# Files will be copied into ${CMAKE_CURRENT_BINARY_DIR} with same
|
|
# relative paths.
|
|
#
|
|
# ${source_dir} should be absolute path(that is, starts from '/').
|
|
# Otherwise first argument is treated as first file to copy.
|
|
function(rule_copy_source file)
|
|
string(REGEX MATCH "^/" is_abs_path ${file})
|
|
if(is_abs_path)
|
|
set(source_dir ${file})
|
|
set(files ${ARGN})
|
|
else(is_abs_path)
|
|
set(source_dir ${CMAKE_CURRENT_SOURCE_DIR})
|
|
set(files ${file} ${ARGN})
|
|
endif(is_abs_path)
|
|
|
|
foreach(file_real ${files})
|
|
rule_copy_file("${CMAKE_CURRENT_BINARY_DIR}/${file_real}"
|
|
${source_dir}/${file_real})
|
|
endforeach(file_real ${files})
|
|
endfunction(rule_copy_source file)
|
|
|
|
# to_abs_path(output_var path [...])
|
|
#
|
|
# Convert relative path of file to absolute path:
|
|
# use path in source tree, if file already exist there.
|
|
# otherwise use path in binary tree.
|
|
# If initial path already absolute, return it.
|
|
function(to_abs_path output_var)
|
|
set(result)
|
|
foreach(path ${ARGN})
|
|
string(REGEX MATCH "^/" _is_abs_path ${path})
|
|
if(_is_abs_path)
|
|
list(APPEND result ${path})
|
|
else(_is_abs_path)
|
|
file(GLOB to_abs_path_file
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/${path}"
|
|
)
|
|
if(NOT to_abs_path_file)
|
|
set (to_abs_path_file "${CMAKE_CURRENT_BINARY_DIR}/${path}")
|
|
endif(NOT to_abs_path_file)
|
|
list(APPEND result ${to_abs_path_file})
|
|
endif(_is_abs_path)
|
|
endforeach(path ${ARGN})
|
|
set("${output_var}" ${result} PARENT_SCOPE)
|
|
endfunction(to_abs_path output_var path)
|
|
|
|
# is_path_inside_dir(output_var dir path)
|
|
#
|
|
# Set output_var to true if path is absolute path inside given directory.
|
|
# NOTE: Path should be absolute.
|
|
macro(is_path_inside_dir output_var dir path)
|
|
file(RELATIVE_PATH _rel_path ${dir} ${path})
|
|
string(REGEX MATCH "^\\.\\." _is_not_inside_dir ${_rel_path})
|
|
if(_is_not_inside_dir)
|
|
set(${output_var} "FALSE")
|
|
else(_is_not_inside_dir)
|
|
set(${output_var} "TRUE")
|
|
endif(_is_not_inside_dir)
|
|
endmacro(is_path_inside_dir output_var dir path)
|
|
|
|
|
|
# Write given content to the file.
|
|
#
|
|
# If file is already exists and its content is same as written one, file
|
|
# is not rewritten, so its write timestamp remains unchanged.
|
|
function(file_update filename content)
|
|
if(EXISTS "${filename}")
|
|
file(READ "${filename}" old_content)
|
|
if(old_content STREQUAL "${content}")
|
|
return()
|
|
endif(old_content STREQUAL "${content}")
|
|
endif(EXISTS "${filename}")
|
|
# File doesn't exists or its content differ.
|
|
file(WRITE "${filename}" "${content}")
|
|
endfunction(file_update filename content)
|
|
|
|
|
|
# Write given content to the file in APPEND mode.
|
|
#
|
|
# For append we use position variable <pos> which should be initialized
|
|
# to 0 for every new build process and which is updated every time when
|
|
# this function is called.
|
|
# If file is already exists and its content at given <pos> is same as
|
|
# written one, file is not rewritten, so its write timestamp remains unchanged.
|
|
#
|
|
# Note, that file will not be rewritten if new build process issues less
|
|
# APPEND actions than one which create file.
|
|
# But similar problem exists for file_update() and even for built-in
|
|
# configure_file() command: file will not be removed if new build process
|
|
# do not call configure_file() for it.
|
|
function(file_update_append filename content POS)
|
|
set(pos "${${POS}}")
|
|
string(LENGTH "${content}" len)
|
|
# Update output variable first.
|
|
# This allows to use return() when need not to do anything
|
|
math(EXPR pos_new "${pos}+${len}")
|
|
set(${POS} "${pos_new}" PARENT_SCOPE)
|
|
if(EXISTS "${filename}")
|
|
file(READ "${filename}" old_content LIMIT "${len}" OFFSET "${pos}")
|
|
if(old_content STREQUAL "${content}")
|
|
return()
|
|
elseif(old_content STREQUAL "")
|
|
file(APPEND "${filename}" "${content}")
|
|
return()
|
|
endif(old_content STREQUAL "${content}")
|
|
else(EXISTS "${filename}")
|
|
if(NOT pos EQUAL 0)
|
|
message(FATAL_ERROR "Appending to non-zero position to non-existent file.")
|
|
endif(NOT pos EQUAL 0)
|
|
endif(EXISTS "${filename}")
|
|
# File doesn't exists or its content differ.
|
|
if(NOT pos EQUAL 0)
|
|
file(READ "${filename}" prefix LIMIT "${pos}")
|
|
else(NOT pos EQUAL 0)
|
|
set(prefix)
|
|
endif(NOT pos EQUAL 0)
|
|
file(WRITE "${filename}" "${prefix}${content}")
|
|
endfunction(file_update_append filename content POS)
|
|
|
|
|
|
# Common mechanism for output status message
|
|
# when checking different aspects.
|
|
#
|
|
# Normal using:
|
|
#
|
|
# check_begin("Checking <...>")
|
|
# if(NOT <check-already-has-been-done>)
|
|
# check_try() # Here message is printed
|
|
# # Perform check(try_compile(), etc.)
|
|
# endif(NOT <check-already-has-been-done>)
|
|
# check_end("<check-result>") # Here message is printed with result.
|
|
|
|
# Should be called (unconditionally) when new cheking is issued.
|
|
# Note, that given @status_msg is not printed at that step.
|
|
function(check_begin status_msg)
|
|
set(_check_status_msg ${status_msg} PARENT_SCOPE)
|
|
set(_check_has_tries PARENT_SCOPE)
|
|
endfunction(check_begin status_msg)
|
|
|
|
# Should be called before every real checking, that is which is not come
|
|
# from cache variables comparision.
|
|
#
|
|
# First call of that function is trigger printing of @status_msg,
|
|
# passed to check_begin().
|
|
function(check_try)
|
|
if(NOT _check_has_tries)
|
|
message(STATUS "${_check_status_msg}")
|
|
set(_check_has_tries "1" PARENT_SCOPE)
|
|
endif(NOT _check_has_tries)
|
|
endfunction(check_try)
|
|
|
|
# Should be called when cheking is end, and @result_msg should be short
|
|
# description of check result.
|
|
# If any check_try() has been issued before,
|
|
# "@status_msg - @result_msg"
|
|
# will be printed.
|
|
# Otherwise,
|
|
# "@status_msg - [cached] @result_msg"
|
|
# will be printed, at it will be the only message for that check.
|
|
function(check_end result_msg)
|
|
if(NOT _check_has_tries)
|
|
message(STATUS "${_check_status_msg} [cached] - ${result_msg}")
|
|
else(NOT _check_has_tries)
|
|
message(STATUS "${_check_status_msg} - ${result_msg}")
|
|
endif(NOT _check_has_tries)
|
|
set(_check_status_msg PARENT_SCOPE)
|
|
set(_check_has_tries PARENT_SCOPE)
|
|
endfunction(check_end result_msg)
|
|
|
|
# set_bool_string(var true_string false_string value [CACHE ... | PARENT_SCOPE])
|
|
#
|
|
# Set variable to one of two string according to true property of some value.
|
|
#
|
|
# If 'value' is true-evaluated, 'var' will be set to 'true_string',
|
|
# otherwise to 'var' will be set to 'false_string'.
|
|
# Like standard set(), macro accept CACHE and PARENT_SCOPE modifiers.
|
|
#
|
|
# Useful for form meaningful value for cache variables, contained result
|
|
# of some operation.
|
|
# Also may be used for form message for check_end().
|
|
macro(set_bool_string var true_string false_string value)
|
|
# Macro parameters are not a variables, so them cannot be tested
|
|
# using 'if(value)'.
|
|
# Usage 'if(${value})' leads to warnings since 2.6.4 when ${val}
|
|
# is boolean constant
|
|
# (because until 2.6.4 'if(value)' always dereference val).
|
|
# So copy 'value' to local variable for test it.
|
|
set(_set_bool_string_value ${value})
|
|
if(_set_bool_string_value)
|
|
set(${var} "${true_string}" ${ARGN})
|
|
else()
|
|
set(${var} "${false_string}" ${ARGN})
|
|
endif()
|
|
endmacro(set_bool_string)
|
|
|
|
# set_zero_string(var true_string false_string value [CACHE ... | PARENT_SCOPE])
|
|
#
|
|
# Set variable to one of two string according to zero property of some value.
|
|
#
|
|
# If 'value' is '0' (presizely), 'var' will be set to 'zero_string',
|
|
# otherwise to 'var' will be set to 'nonzero_string'.
|
|
# Like standard set(), macro accept CACHE and PARENT_SCOPE modifiers.
|
|
#
|
|
# Useful for form meaningful value for cache variables, contained result
|
|
# of execute_process().
|
|
# Also may be used for form message for check_end().
|
|
macro(set_zero_string var zero_string nonzero_string value)
|
|
set(_set_zero_string_value ${value})
|
|
if(_set_zero_string_value EQUAL "0")
|
|
set(${var} ${zero_string} ${ARGN})
|
|
else()
|
|
set(${var} ${nonzero_string} ${ARGN})
|
|
endif()
|
|
endmacro(set_zero_string) |