Skip to content

Commit

Permalink
FPHSA: detect package name mismatches
Browse files Browse the repository at this point in the history
The `FPHSA_NAME_MISMATCHED` variable may be set if this is intentional
(but should be cleared after the call to not affect other FPHSA calls).
It may also be passed via the `NAME_MISMATCHED` option for new-signature
FPHSA calls.
  • Loading branch information
mathstuf committed Jan 14, 2020
1 parent 93526fd commit ee4673c
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 3 deletions.
5 changes: 5 additions & 0 deletions Help/release/dev/fphsa-detect-name-mismatch.rst
@@ -0,0 +1,5 @@
fphsa-name-mismatch
-------------------

* The :module:`FindPackageHandleStandardArgs` module learned to check the
package name passed in for typo mistakes.
56 changes: 53 additions & 3 deletions Modules/FindPackageHandleStandardArgs.cmake
Expand Up @@ -27,6 +27,7 @@ valid filepaths.
[VERSION_VAR <version-var>]
[HANDLE_COMPONENTS]
[CONFIG_MODE]
[NAME_MISMATCHED]
[REASON_FAILURE_MESSAGE <reason-failure-message>]
[FAIL_MESSAGE <custom-failure-message>]
)
Expand Down Expand Up @@ -90,6 +91,12 @@ valid filepaths.
Specify a custom failure message instead of using the default
generated message. Not recommended.

``NAME_MISMATCHED``
Indicate that the ``<PackageName>`` does not match
``${CMAKE_FIND_PACKAGE_NAME}``. This is usually a mistake and raises a
warning, but it may be intentional for usage of the command for components
of a larger package.

Example for the simple signature:

.. code-block:: cmake
Expand All @@ -106,6 +113,17 @@ used or not. If it is found, success will be reported, including
the content of the first ``<required-var>``. On repeated CMake runs,
the same message will not be printed again.

.. note::

If ``<PackageName>`` does not match ``CMAKE_FIND_PACKAGE_NAME`` for the
calling module, a warning that there is a mismatch is given. The
``FPHSA_NAME_MISMATCHED`` variable may be set to bypass the warning if using
the old signature and the ``NAME_MISMATCHED`` argument using the new
signature. To avoid forcing the caller to require newer versions of CMake for
usage, the variable's value will be used if defined when the
``NAME_MISMATCHED`` argument is not passed for the new signature (but using
both is an error)..

Example for the full signature:

.. code-block:: cmake
Expand Down Expand Up @@ -190,15 +208,32 @@ endmacro()

function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)

# Set up the arguments for `cmake_parse_arguments`.
set(options CONFIG_MODE HANDLE_COMPONENTS)
# Set up the arguments for `cmake_parse_arguments`.
set(options CONFIG_MODE HANDLE_COMPONENTS NAME_MISMATCHED)
set(oneValueArgs FAIL_MESSAGE REASON_FAILURE_MESSAGE VERSION_VAR FOUND_VAR)
set(multiValueArgs REQUIRED_VARS)

# Check whether we are in 'simple' or 'extended' mode:
# Check whether we are in 'simple' or 'extended' mode:
set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)

unset(FPHSA_NAME_MISMATCHED_override)
if (DEFINED FPHSA_NAME_MISMATCHED)
# If the variable NAME_MISMATCHED variable is set, error if it is passed as
# an argument. The former is for old signatures, the latter is for new
# signatures.
list(FIND ARGN "NAME_MISMATCHED" name_mismatched_idx)
if (NOT name_mismatched_idx EQUAL "-1")
message(FATAL_ERROR
"The `NAME_MISMATCHED` argument may only be specified by the argument or "
"the variable, not both.")
endif ()

# But use the variable if it is not an argument to avoid forcing minimum
# CMake version bumps for calling modules.
set(FPHSA_NAME_MISMATCHED_override "${FPHSA_NAME_MISMATCHED}")
endif ()

if(${INDEX} EQUAL -1)
set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
set(FPHSA_REQUIRED_VARS ${ARGN})
Expand Down Expand Up @@ -227,6 +262,21 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
endif()
endif()

if (DEFINED FPHSA_NAME_MISMATCHED_override)
set(FPHSA_NAME_MISMATCHED "${FPHSA_NAME_MISMATCHED_override}")
endif ()

if (DEFINED CMAKE_FIND_PACKAGE_NAME
AND NOT FPHSA_NAME_MISMATCHED
AND NOT _NAME STREQUAL CMAKE_FIND_PACKAGE_NAME)
message(AUTHOR_WARNING
"The package name passed to `find_package_handle_standard_args` "
"(${_NAME}) does not match the name of the calling package "
"(${CMAKE_FIND_PACKAGE_NAME}). This can lead to problems in calling "
"code that expects `find_package` result variables (e.g., `_FOUND`) "
"to follow a certain pattern.")
endif ()

# now that we collected all arguments, process them

if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG")
Expand Down
4 changes: 4 additions & 0 deletions Tests/RunCMake/FPHSA/FindNameMismatch.cmake
@@ -0,0 +1,4 @@
set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NAMEMISMATCH REQUIRED_VARS "${CMAKE_FIND_PACKAGE_NAME}_MODULE")
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1)
4 changes: 4 additions & 0 deletions Tests/RunCMake/FPHSA/FindNameMismatchOld.cmake
@@ -0,0 +1,4 @@
set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NAMEMISMATCH "old signature" "${CMAKE_FIND_PACKAGE_NAME}_MODULE")
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1)
6 changes: 6 additions & 0 deletions Tests/RunCMake/FPHSA/FindNameMismatchSuppressed.cmake
@@ -0,0 +1,6 @@
set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}")
include(FindPackageHandleStandardArgs)
set(FPHSA_NAME_MISMATCHED 1)
find_package_handle_standard_args(NAMEMISMATCH "old signature" "${CMAKE_FIND_PACKAGE_NAME}_MODULE")
unset(FPHSA_NAME_MISMATCHED)
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1)
4 changes: 4 additions & 0 deletions Tests/RunCMake/FPHSA/FindNameMismatchSuppressedArg.cmake
@@ -0,0 +1,4 @@
set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NAMEMISMATCH NAME_MISMATCHED REQUIRED_VARS "${CMAKE_FIND_PACKAGE_NAME}_MODULE")
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1)
6 changes: 6 additions & 0 deletions Tests/RunCMake/FPHSA/FindNameMismatchSuppressedCompat.cmake
@@ -0,0 +1,6 @@
set("${CMAKE_FIND_PACKAGE_NAME}_MODULE" "${CMAKE_CURRENT_LIST_FILE}")
include(FindPackageHandleStandardArgs)
set(FPHSA_NAME_MISMATCHED 1)
find_package_handle_standard_args(NAMEMISMATCH REQUIRED_VARS "${CMAKE_FIND_PACKAGE_NAME}_MODULE")
unset(FPHSA_NAME_MISMATCHED)
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1)
23 changes: 23 additions & 0 deletions Tests/RunCMake/FPHSA/NameMismatch-stderr.txt
@@ -0,0 +1,23 @@
CMake Warning \(dev\) at .*/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\):
The package name passed to `find_package_handle_standard_args`
\(NAMEMISMATCH\) does not match the name of the calling package
\(NameMismatch\). This can lead to problems in calling code that expects
`find_package` result variables \(e.g., `_FOUND`\) to follow a certain
pattern.
Call Stack \(most recent call first\):
FindNameMismatch.cmake:3 \(find_package_handle_standard_args\)
NameMismatch.cmake:3 \(find_package\)
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.

CMake Warning \(dev\) at .*/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\):
The package name passed to `find_package_handle_standard_args`
\(NAMEMISMATCH\) does not match the name of the calling package
\(NameMismatchOld\). This can lead to problems in calling code that expects
`find_package` result variables \(e.g., `_FOUND`\) to follow a certain
pattern.
Call Stack \(most recent call first\):
FindNameMismatchOld.cmake:3 \(find_package_handle_standard_args\)
NameMismatch.cmake:4 \(find_package\)
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
7 changes: 7 additions & 0 deletions Tests/RunCMake/FPHSA/NameMismatch.cmake
@@ -0,0 +1,7 @@
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")

find_package(NameMismatch REQUIRED)
find_package(NameMismatchOld REQUIRED)
find_package(NameMismatchSuppressed REQUIRED)
find_package(NameMismatchSuppressedCompat REQUIRED)
find_package(NameMismatchSuppressedArg REQUIRED)
1 change: 1 addition & 0 deletions Tests/RunCMake/FPHSA/RunCMakeTest.cmake
@@ -1,6 +1,7 @@
include(RunCMake)

run_cmake(BadFoundVar)
run_cmake(NameMismatch)

# The pseudo module will "find" a package with the given version. Check if the
# version selection code in FPHSA works correctly.
Expand Down

0 comments on commit ee4673c

Please sign in to comment.