Functions to find libraries and include directories

The qibuild CMake framework contains several -config.cmake files when upstream Find-.cmake files are not correct or missing.

For instance, the canonical FindFoo.cmake looks like:

include(FindPackageHandleStandardArgs.cmake)

find_path(FOO_INCLUDE_DIR foo/foo.h)
find_library(FOO_LIBRARY foo)

find_package_handle_standard_args(FOO
 DEFAULT_MSG
  FOO_INCLUDE_DIR
  FOO_LIBRARY
)

mark_as_advanced(FOO_LIBRARY FOO_INCLUDE_DIR)

if(FOO_FOUND)
  set(FOO_LIBRARIES    ${FOO_LIBRARY})
  set(FOO_INCLUDE_DIRS ${FOO_INCLUDE_DIR})
endif()

There is a lot of boilerplate code here, and it’s not easy to know the names of the variables (is it FOO_INCLUDE_DIR or FOO_INCLUDE_DIRS ?)

For qibuild, we use the concept of PREFIX and exported variables will always be ${${PREFIX}_INCLUDE_DIRS} and ${${PREFIX}_LIBRARIES}

Thus, foo-config.cmake can simply be rewritten as:

clean(FOO)
fpath(FOO foo/foo.h)
flib(FOO  foo)
export(FOO)

Note that the exported variables will always be all upper-case, will contain no version number and will have the plural form.

  • FOO_INCLUDE_DIRS
  • FOO_LIBRARIES

Also note that FOO_LIBRARIES will equal either:

"general;/path/to/foo.so"

if flib() was called with no specific argument or:

"debug;/path/to/foo_d.lib;optimized;/path/to/foo.lib"

if both flib(FOO OPTIMIZED ...) and flib(FOO DEBUG ...) have been called.

So this variable can be used directly in the target_link_libraries() call

clean(prefix)
Arguments:
  • prefix – The prefix of the variables to clean

Cleanup variables related to a library/executable/source-only library Use this at the start of the ${prefix}-config.cmake file

fpath(prefix path [<remaining args> ...]
)
Arguments:
  • prefix – The prefix of the exported variables. Must match the argument of clean() and export_lib() (or export_header for a header-only library) calls.
  • path – The path of one of the headers inside the include directory.
  • args (remaining) – The remaining arguments will be passed to find_path

Search for an include directory

A small example, assuming /usr/local/include/foo/foo.h exists.

If you use:

fpath(FOO foo/foo.h)

FOO_INCLUDE_DIRS will equal /usr/local/include, so you will have to use

#include <foo/foo.h>

Whereas if you use

fpath(FOO foo.h PATH_SUFFIXES foo)

FOO_INCLUDE_DIRS will equal usr/local/include/foo, so you will have to use

#include <foo.h>
flib(prefix name [DEBUG]
    [OPTIMIZED]
    [<remaining args> ...]
)
Arguments:
  • prefix – The prefix of the exported variables. Must match the argument of clean() and export() calls.
  • name – The name of the library
  • DEBUG – find a library that will be used for a debug build
  • OPTIMIZED – find a library that will be used for an optimized build
  • args (remaining) – The remaining arguments will be passed to find_library

Search for a library

If the library has a different name in debug and in release, you should use:

flib(foo DEBUG     foo_d)
flib(foo OPTIMIZED foo)

If the library has different names, you should call flib() just once

flib(foo foo foo3 foo3.4)

If you want to link with several libraries in one step (for instance foo-bar depends on foo-core but you just want to do qi_use_lib(.. FOO), you must call flib() several times:

flib(foo foo-bar)
flib(foo foo-core)
fprogram(prefix)
Arguments:
  • prefix – Prefix of the variables to export. Must match the calls to clean() and export_bin() calls.

Search for an executable

export_lib(prefix)
Arguments:
  • prefix – The prefix of the exported variables

Export the variables related to a library

Use this at the end of the ${prefix}-config.cmake find_package_handle_standard_args will be called to make sure ${prefix}_LIBRARIES and ${prefix}_INCLUDE_DIRS have been found.

export_lib_pkgconfig()

Helper function to use with pkgconfig.

Usage, assuming foo-1.0.pc is somewhere in PKG_CONFIG_PATH

clean(FOO)
find_package(PkgConfig)
pkg_check_modules(FOO foo-1.0)
export_lib_pkgconfig(FOO)
export_bin(prefix)
Arguments:
  • prefix – The prefix of the variables to export

Export the variables related to an executable

Use at the end of foo-config.cmake

fprogram(FOO RELEASE foo)
fprogram(FOO OPTIMIZED foo_d)
export_bin(FOO)

Here, FOO_EXECUTABLE will be set to ‘/path/to/foo.exe’, and FOO_EXECUTABLE_DEBUG to ‘path/to/foo_d.exe’

export_header(prefix)
Arguments:
  • prefix – The prefix of the variables to export

Export the variables related to an header-only library

Use at the end of foo-config.cmake

clean(FOO)
fpath(FOO foo/foo.h)
export_header(FOO)