Third Party Libraries¶
Third party libraries come in three flavors based on the CMake support provided by the project and the CMake community as a whole: no Cmake support, CMake’s Find* modules, and First Class project support.
No CMake Support¶
Some libraries have no support for easily importing their CMake targets into external projects, either through properly exporting their targets themselves or the CMake community has not written a Find module that eases this work.
BLT provides a blt_import_library macro allows you to reuse all information needed
for an external dependency under a single name. This includes any include
directories, libraries, compile flags, link flags, defines, etc. You can also
hide any warnings created by their headers by setting the
TREAT_INCLUDES_AS_SYSTEM
argument.
We will use Lua as an example of this because up until recently (CMake version 3.18), there was no Find module. This provides us a great example on how to show two ways of importing the same library’s targets.
The following example shows how to find a library, Lua this time, manually. By first,
searching for the include directories and then for the library itself. Finally it calls
blt_import_library to bundle that information under one easy to remember name, lua
:
# first Check for LUA_DIR
if (NOT EXISTS "${LUA_DIR}")
message(FATAL_ERROR "Given LUA_DIR does not exist: ${LUA_DIR}")
endif()
if (NOT IS_DIRECTORY "${LUA_DIR}")
message(FATAL_ERROR "Given LUA_DIR is not a directory: ${LUA_DIR}")
endif()
# Find includes directory
find_path( LUA_INCLUDE_DIR lua.hpp
PATHS ${LUA_DIR}/include/
${LUA_DIR}/include/lua
NO_DEFAULT_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_CMAKE_PATH
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH)
# Find libraries
find_library( LUA_LIBRARY NAMES lua liblua
PATHS ${LUA_DIR}/lib
NO_DEFAULT_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_CMAKE_PATH
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH)
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(LUA DEFAULT_MSG
LUA_INCLUDE_DIR
LUA_LIBRARY )
if(NOT LUA_FOUND)
message(FATAL_ERROR "LUA_DIR is not a path to a valid Lua install")
endif()
message(STATUS "Lua Includes: ${LUA_INCLUDE_DIR}")
message(STATUS "Lua Libraries: ${LUA_LIBRARY}")
blt_import_library(NAME lua
TREAT_INCLUDES_AS_SYSTEM ON
DEFINES HAVE_LUA=1
INCLUDES ${LUA_INCLUDE_DIR}
LIBRARIES ${LUA_LIBRARY}
EXPORTABLE ON)
Then lua
is available to be used in the DEPENDS_ON
list in the following
blt_add_executable or blt_add_library calls, or in any CMake command that accepts a target.
Note
CMake targets created by blt_import_library are INTERFACE
libraries that can be installed
and exported if the EXPORTABLE
option is enabled. For example, if the calc_pi
project depends on
Lua, it could export its lua
target. To avoid introducing target name conflicts for users of the
calc_pi
project who might also create a target called lua
, lua
should be exported as
calc_pi\:\:lua
.
Note
Because CMake targets are only accessible from within the directory they were defined (including
subdirectories), the include()
command should be preferred to the add_subdirectory()
command
for adding CMake files that create imported library targets needed in other directories. The GLOBAL
option to blt_import_library can also be used to manage visibility.
CMake’s Find Modules¶
This time we will do exactly the same thing but using the new CMake provided FindLua.cmake
module.
Instead of calling having to ensure correctness and calling find_path
and find_library
, we
only have to call find_package
and it handles this for us. Each Find module outputs differently
named variables so it is important to read the documentation on CMake’s website. This is where
blt_import_library shines because you only have to figure those variables once then use the
new imported library’s NAME
in the rest of your project.
# FindLua.cmake takes in LUA_DIR as an environment variable, which is the directory
# where Lua was installed to and fills variables: LUA_FOUND, LUA_LIBRARIES, and LUA_INCLUDE_DIR
set(ENV{LUA_DIR} ${LUA_DIR})
find_package(Lua)
if (NOT LUA_FOUND)
MESSAGE(FATAL_ERROR "Could not find Lua in the provided LUA_DIR: ${LUA_DIR}")
endif()
blt_import_library(NAME lua
TREAT_INCLUDES_AS_SYSTEM ON
DEFINES HAVE_LUA=1
INCLUDES ${LUA_INCLUDE_DIR}
LIBRARIES ${LUA_LIBRARIES}
EXPORTABLE ON)
First Class Project Support¶
Some projects provide what we call First Class support. They have gone through the effort of
properly exporting all necessary targets to use their project and
install the necessary configuration files inside of their install directory, usually something
like <install dir>\lib\cmake\<Project Name>Config.cmake
.
LLNL’s Axom project exports all targets that can be easily imported into your project with a single CMake function call:
# use the provided PATH directory and create a cmake target named 'axom'
find_package(axom REQUIRED)
You can then add the created CMake target, axom
, to any DEPENDS_ON
list or use any other
regular CMake function to change it.