find_package: <PackageName>_DIR environment variable is invalid for packages with hyphens
Scenario
Suppose I write a CMakeLists.txt
with
find_package(yaml-cpp REQUIRED)
but don't have that package installed anywhere. I will get:
CMake Error at CMakeLists.txt:NN (find_package):
By not providing "Findyaml-cpp.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "yaml-cpp",
but CMake did not find one.
Could not find a package configuration file provided by "yaml-cpp" with any
of the following names:
yaml-cppConfig.cmake
yaml-cpp-config.cmake
Add the installation prefix of "yaml-cpp" to CMAKE_PREFIX_PATH or set
"yaml-cpp_DIR" to a directory containing one of the above files. If
"yaml-cpp" provides a separate development package or SDK, be sure it has
been installed.
Suppose I wanted to go the route of specifying a directory in an environment variable. Well, I can't! yaml-cpp_DIR
is not a valid environment variable name:
$ export yaml-cpp_DIR=foo
-bash: export: `yaml-cpp_DIR=foo': not a valid identifier
(using bash 4.2.46(2) ).
The underlying problem
CMake generates an expected environment variable name from the package name disregarding the set of characters allowed in environment variable names:
Environment variable names used by the utilities in the Shell and Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase letters, digits, and the '_' (underscore) from the characters defined in Portable Character Set and do not begin with a digit. Other characters may be permitted by an implementation; applications shall tolerate the presence of such names.
Source: The Open Group. Quoted in this StackOverflow answer.
It is true that other characters are not all strictly forbidden, but effectively - the above is what's usable.
The solution
Package names undergo the equivalent of tr "[a-z-]" "[A-Z_]"
. For yaml-cpp, this would mean CMake expects YAML_CPP_DIR
rather than yaml-cpp_DIR
. For compatibility, it could still check the non-transformed name, in case somehow the user was able to provide it (and it will work for lowercase letter, which typically are supported by bash).