CMake: Use packages by imported target where available

This is preferable because imported targets generally include
all of the relevant information specific to the particular
installation of each package, and without needing to hunt down
a bunch of variables to do it.

To do this, package_option() (which is starting to grow in scope
a little beyond just providing the package option, come to think
of it) is given a new IMPORTED_AS option, which tells the package
configuration system to look for one or more imported targets and
link against them instead.
This commit is contained in:
Sam Edwards 2018-09-21 16:24:48 -06:00
parent 1520d712d4
commit 968ca123d4
2 changed files with 64 additions and 27 deletions

View File

@ -15,6 +15,7 @@
# Usage: # Usage:
# package_option(package_name package_doc_string # package_option(package_name package_doc_string
# [DEFAULT ON | OFF] # [DEFAULT ON | OFF]
# [IMPORTED_AS CMake::Imported::Target [...]]
# [FOUND_AS find_name] # [FOUND_AS find_name]
# [LICENSE license]) # [LICENSE license])
# Examples: # Examples:
@ -28,6 +29,11 @@
# FOUND_AS indicates the name of the CMake find_package() module, which # FOUND_AS indicates the name of the CMake find_package() module, which
# may differ from Panda3D's internal name for that package. # may differ from Panda3D's internal name for that package.
# #
# IMPORTED_AS is used to indicate that the find_package() may have
# provided one or more IMPORTED targets, and that if at least one is
# found, the IMPORTED target(s) should be used instead of the
# variables provided by find_package()
#
# #
# Function: config_package # Function: config_package
# Usage: # Usage:
@ -62,6 +68,7 @@ function(package_option name)
set(command) set(command)
set(default) set(default)
set(found_as "${name}") set(found_as "${name}")
set(imported_as)
set(license "") set(license "")
set(cache_string) set(cache_string)
@ -87,6 +94,12 @@ function(package_option name)
elseif(arg STREQUAL "LICENSE") elseif(arg STREQUAL "LICENSE")
set(command "LICENSE") set(command "LICENSE")
elseif(arg STREQUAL "IMPORTED_AS")
set(command "IMPORTED_AS")
elseif(command STREQUAL "IMPORTED_AS")
list(APPEND imported_as "${arg}")
else() else()
# Yes, a list, because semicolons can be in there, and # Yes, a list, because semicolons can be in there, and
# that gets split up into multiple args, so we have to # that gets split up into multiple args, so we have to
@ -96,8 +109,8 @@ function(package_option name)
endif() endif()
endforeach() endforeach()
if(command STREQUAL "DEFAULT") if(command AND NOT command STREQUAL "IMPORTED_AS")
message(SEND_ERROR "DEFAULT in package_option takes an argument") message(SEND_ERROR "${command} in package_option takes an argument")
endif() endif()
# If the default is not set, we set it. # If the default is not set, we set it.
@ -142,31 +155,47 @@ function(package_option name)
set(PANDA_PACKAGE_DEFAULT_${name} "${default}" PARENT_SCOPE) set(PANDA_PACKAGE_DEFAULT_${name} "${default}" PARENT_SCOPE)
# Create the option. # Create the INTERFACE library used to depend on this package.
option("HAVE_${name}" "${cache_string}" "${default}")
# Create the library if the package is available.
add_library(PKG::${name} INTERFACE IMPORTED GLOBAL) add_library(PKG::${name} INTERFACE IMPORTED GLOBAL)
# Create the option, and if it actually is enabled, populate the INTERFACE
# library created above
option("HAVE_${name}" "${cache_string}" "${default}")
if(HAVE_${name}) if(HAVE_${name})
if(${found_as}_INCLUDE_DIRS) set(use_variables ON)
set(includes ${${found_as}_INCLUDE_DIRS})
else()
set(includes "${${found_as}_INCLUDE_DIR}")
endif()
if(${found_as}_LIBRARIES)
set(libs ${${found_as}_LIBRARIES})
else()
set(libs "${${found_as}_LIBRARY}")
endif()
target_link_libraries(PKG::${name} INTERFACE ${libs}) foreach(implib ${imported_as})
if(TARGET ${implib})
# We found one of the implibs, so we don't need to use variables
# (below) anymore
set(use_variables OFF)
# This is gross, but we actually want to hide package include directories # Yes, this is ugly. See below for an explanation.
# from Interrogate to make sure it relies on parser-inc instead, so we'll target_link_libraries(PKG::${name} INTERFACE
# use some generator expressions to do that. "$<$<NOT:$<BOOL:$<TARGET_PROPERTY:IS_INTERROGATE>>>:${implib}>")
set_target_properties(PKG::${name} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES endif()
"$<$<NOT:$<BOOL:$<TARGET_PROPERTY:IS_INTERROGATE>>>:${includes}>") endforeach(implib)
if(use_variables)
if(${found_as}_INCLUDE_DIRS)
set(includes ${${found_as}_INCLUDE_DIRS})
else()
set(includes "${${found_as}_INCLUDE_DIR}")
endif()
if(${found_as}_LIBRARIES)
set(libs ${${found_as}_LIBRARIES})
else()
set(libs "${${found_as}_LIBRARY}")
endif()
target_link_libraries(PKG::${name} INTERFACE ${libs})
# This is gross, but we actually want to hide package include directories
# from Interrogate to make sure it relies on parser-inc instead, so we'll
# use some generator expressions to do that.
set_target_properties(PKG::${name} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
"$<$<NOT:$<BOOL:$<TARGET_PROPERTY:IS_INTERROGATE>>>:${includes}>")
endif()
endif() endif()
endfunction(package_option) endfunction(package_option)

View File

@ -88,8 +88,10 @@ endif()
# #
find_package(OpenSSL COMPONENTS ssl crypto QUIET) find_package(OpenSSL COMPONENTS ssl crypto QUIET)
package_option(OPENSSL DEFAULT ON package_option(OPENSSL
"Enable OpenSSL support") DEFAULT ON
"Enable OpenSSL support"
IMPORTED_AS OpenSSL::SSL OpenSSL::Crypto)
option(REPORT_OPENSSL_ERRORS option(REPORT_OPENSSL_ERRORS
"Define this true to include the OpenSSL code to report verbose "Define this true to include the OpenSSL code to report verbose
@ -112,7 +114,10 @@ config_package(JPEG "libjpeg")
# PNG: # PNG:
find_package(PNG QUIET) find_package(PNG QUIET)
package_option(PNG DEFAULT ON "Enable support for loading .png images.") package_option(PNG
DEFAULT ON
"Enable support for loading .png images."
IMPORTED_AS PNG::PNG)
config_package(PNG "libpng") config_package(PNG "libpng")
# TIFF: # TIFF:
@ -201,7 +206,8 @@ config_package(VRPN "VRPN")
find_package(zlib QUIET) find_package(zlib QUIET)
package_option(ZLIB package_option(ZLIB
"Enables support for compression of Panda assets.") "Enables support for compression of Panda assets."
IMPORTED_AS ZLIB::ZLIB)
config_package(ZLIB "zlib") config_package(ZLIB "zlib")
@ -260,6 +266,7 @@ package_option(OPENAL
"This enables support for audio output via OpenAL. Some platforms, such as "This enables support for audio output via OpenAL. Some platforms, such as
macOS, provide their own OpenAL implementation, which Panda3D can use. But, macOS, provide their own OpenAL implementation, which Panda3D can use. But,
on most platforms this will imply OpenAL Soft, which is LGPL licensed." on most platforms this will imply OpenAL Soft, which is LGPL licensed."
IMPORTED_AS OpenAL::OpenAL
LICENSE "LGPL") LICENSE "LGPL")
config_package(OPENAL "OpenAL sound library") config_package(OPENAL "OpenAL sound library")
@ -272,7 +279,8 @@ find_package(Freetype QUIET)
package_option(FREETYPE package_option(FREETYPE
"This enables support for the FreeType font-rendering library. If disabled, "This enables support for the FreeType font-rendering library. If disabled,
Panda3D will only be able to read fonts specially made with egg-mkfont.") Panda3D will only be able to read fonts specially made with egg-mkfont."
IMPORTED_AS freetype)
config_package(FREETYPE "FreeType") config_package(FREETYPE "FreeType")