Teaches LibFindMacros to find version from 'const int NAME = 42;'

coverity_scan^2
Roman Proskuryakov 9 years ago
parent 63784bfb50
commit 57b75d2cd1

@ -3,6 +3,8 @@
# Maintained at https://github.com/Tronic/cmake-modules # Maintained at https://github.com/Tronic/cmake-modules
# Please send your improvements as pull requests on Github. # Please send your improvements as pull requests on Github.
include(CMakeParseArguments)
# Find another package and make it a dependency of the current package. # Find another package and make it a dependency of the current package.
# This also automatically forwards the "REQUIRED" argument. # This also automatically forwards the "REQUIRED" argument.
# Usage: libfind_package(<prefix> <another package> [extra args to find_package]) # Usage: libfind_package(<prefix> <another package> [extra args to find_package])
@ -54,43 +56,138 @@ function (libfind_pkg_detect PREFIX)
endif() endif()
endfunction() endfunction()
# Extracts a version #define from a version.h file, output stored to <PREFIX>_VERSION. # libfind_header_path(<PREFIX> [PATHS <path> [<path> ...]] NAMES <name> [name ...] VAR <out_var> [QUIET])
# Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR) # Get fullpath of the first found header looking inside <PREFIX>_INCLUDE_DIR or in the given PATHS
# Fourth argument "QUIET" may be used for silently testing different define names. # Usage: libfind_header_path(Foobar NAMES foobar/version.h VAR filepath)
function (libfind_header_path PREFIX)
set(options QUIET)
set(one_value_keywords VAR PATH)
set(multi_value_keywords NAMES PATHS)
CMAKE_PARSE_ARGUMENTS(OPT "${options}" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN})
if (NOT OPT_VAR OR NOT OPT_NAMES)
message(FATAL_ERROR "Arguments VAR, NAMES are required!")
endif()
if (OPT_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Calling function with unused arguments '${OPT_UNPARSED_ARGUMENTS}'!")
endif()
if (OPT_QUIET OR ${PREFIX}_FIND_QUIETLY)
set(quiet TRUE)
endif()
set(paths ${OPT_PATHS} ${PREFIX}_INCLUDE_DIR)
foreach(name ${OPT_NAMES})
foreach(path ${paths})
set(filepath "${${path}}/${name}")
# check for existance
if (EXISTS ${filepath})
set(${OPT_VAR} ${filepath} PARENT_SCOPE) # export path
return()
endif()
endforeach()
endforeach()
# report error if not found
set(${OPT_VAR} NOTFOUND PARENT_SCOPE)
if (NOT quiet)
message(AUTHOR_WARNING "Unable to find '${OPT_NAMES}'")
endif()
endfunction()
# libfind_version_n_header(<PREFIX>
# NAMES <name> [<name> ...]
# DEFINES <define> [<define> ...] | CONSTANTS <const> [<const> ...]
# [PATHS <path> [<path> ...]]
# [QUIET]
# )
# Collect all defines|constants from a header inside <PREFIX>_INCLUDE_DIR or in the given PATHS
# output stored to <PREFIX>_VERSION.
# This function does nothing if the version variable is already defined. # This function does nothing if the version variable is already defined.
function (libfind_version_header PREFIX VERSION_H DEFINE_NAME) # Usage: libfind_version_n_header(Foobar NAMES foobar/version.h DEFINES FOOBAR_VERSION_MAJOR FOOBAR_VERSION_MINOR)
# Skip processing if we already have a version or if the include dir was not found function (libfind_version_n_header PREFIX)
if (${PREFIX}_VERSION OR NOT ${PREFIX}_INCLUDE_DIR) # Skip processing if we already have a version
if (${PREFIX}_VERSION)
return() return()
endif() endif()
set(quiet ${${PREFIX}_FIND_QUIETLY})
# Process optional arguments set(options QUIET)
foreach(arg ${ARGN}) set(one_value_keywords )
if (arg STREQUAL "QUIET") set(multi_value_keywords NAMES PATHS DEFINES CONSTANTS)
set(quiet TRUE) CMAKE_PARSE_ARGUMENTS(OPT "${options}" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN})
if (NOT OPT_NAMES OR (NOT OPT_DEFINES AND NOT OPT_CONSTANTS))
message(FATAL_ERROR "Arguments NAMES, DEFINES|CONSTANTS are required!")
endif()
if (OPT_DEFINES AND OPT_CONSTANTS)
message(FATAL_ERROR "Either DEFINES or CONSTANTS must be set!")
endif()
if (OPT_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Calling function with unused arguments '${OPT_UNPARSED_ARGUMENTS}'!")
endif()
if (OPT_QUIET OR ${PREFIX}_FIND_QUIETLY)
set(quiet TRUE)
set(force_quiet "QUIET") # to propagate argument QUIET
endif()
# Read the header
libfind_header_path(${PREFIX} NAMES ${OPT_NAMES} PATHS ${OPT_PATHS} VAR filename ${force_quiet})
if (NOT filename)
return()
endif()
file(READ "${filename}" header)
# Parse for version number
unset(version_parts)
foreach(define_name ${OPT_DEFINES})
string(REGEX MATCH "# *define +${define_name} +((\"([^\n]*)\")|([^ \n]*))" match "${header}")
# No regex match?
if (NOT match OR match STREQUAL header)
if (NOT quiet)
message(AUTHOR_WARNING "Unable to find \#define ${define_name} \"<version>\" from ${filename}")
endif()
return()
else() else()
message(AUTHOR_WARNING "Unknown argument ${arg} to libfind_version_header ignored.") list(APPEND version_parts "${CMAKE_MATCH_3}${CMAKE_MATCH_4}")
endif() endif()
endforeach() endforeach()
# Read the header and parse for version number foreach(constant_name ${OPT_CONSTANTS})
set(filename "${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") string(REGEX MATCH "${constant_name} *= *((\"([^\;]*)\")|([^ \;]*))" match "${header}")
if (NOT EXISTS ${filename}) # No regex match?
if (NOT quiet) if (NOT match OR match STREQUAL header)
message(AUTHOR_WARNING "Unable to find ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") if (NOT quiet)
message(AUTHOR_WARNING "Unable to find ${constant_name} = \"<version>\" from ${filename}")
endif()
return()
else()
list(APPEND version_parts "${CMAKE_MATCH_3}${CMAKE_MATCH_4}")
endif() endif()
endforeach()
# Export the version string
string(REPLACE ";" "." version "${version_parts}")
set(${PREFIX}_VERSION "${version}" PARENT_SCOPE)
endfunction()
# libfind_version_header(<PREFIX> <HEADER> <DEFINE_NAME> [PATHS <path> [<path> ...]] [QUIET])
# Extracts a version #define from a version.h file, output stored to <PREFIX>_VERSION.
# This function does nothing if the version variable is already defined.
# Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR)
function (libfind_version_header PREFIX VERSION_H DEFINE_NAME)
# Skip processing if we already have a version
if (${PREFIX}_VERSION)
return() return()
endif() endif()
file(READ "${filename}" header)
string(REGEX MATCH ".*#[ \t]*define[ \t]+${DEFINE_NAME}[ \t]+((\"([^\n]*)\")|([^\n]*))" match "${header}") set(options QUIET)
# No regex match? set(one_value_keywords )
if (match STREQUAL header) set(multi_value_keywords PATHS)
if (NOT quiet) CMAKE_PARSE_ARGUMENTS(OPT "${options}" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN})
message(AUTHOR_WARNING "Unable to find \#define ${DEFINE_NAME} \"<version>\" from ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") if (OPT_UNPARSED_ARGUMENTS)
endif() message(FATAL_ERROR "Calling function with unused arguments '${OPT_UNPARSED_ARGUMENTS}'!")
return()
endif() endif()
# Export the version string if (OPT_QUIET OR ${PREFIX}_FIND_QUIETLY)
set(${PREFIX}_VERSION "${CMAKE_MATCH_3}${CMAKE_MATCH_4}" PARENT_SCOPE) set(force_quiet "QUIET") # to propagate argument QUIET
endif()
libfind_version_n_header(${PREFIX} NAMES ${VERSION_H} PATHS ${OPT_PATHS} DEFINES ${DEFINE_NAME} ${force_quiet})
set(${PREFIX}_VERSION "${${PREFIX}_VERSION}" PARENT_SCOPE)
endfunction() endfunction()
# Do the final processing once the paths have been detected. # Do the final processing once the paths have been detected.

Loading…
Cancel
Save