[CMake] Writing a custom Find*.cmake file for Pantheios

Michael Wild themiwi at gmail.com
Tue Jul 17 03:41:36 EDT 2012


A few comments:

* transform all CMake commands to lower case names: s/IF/if/g,
s/ELSE/else/g, s/ENDIF/endif/g, s/SET/set/g etc.

* spelling: s/Settung/Setting/g

* docs list a component "NFrontEnd", but that string doesn't show up in
the actual code. Typo?

* just set the default front- and backends before parsing the
Pantheios_FIND_COMPONENTS. Then you can also just drop the
PANTHEIOS_HAVE_{FRONT,BACK}END variables. Much simpler that way.

* set the default for PANTHEIOS_WIDESTRING before the
if(Pantheios_FIND_COMPONENTS), then you can remove the else() block.

* when defaulting PANTHEIOS_ROOT, use the
get_filename_component(PANTHEIOS_ROOT "${PANTHEIOS_INCLUDE_DIR}" PATH)
idiom. Also, don't compare PANTHEIOS_INCLUDE_DIR against the empty
string. In a previous run, if not found, it can be set to
PANTHEIOS_INCLUDE_DIR_NOT-FOUND, which is not the empty string! Just use
if(PANTHEIOS_INCLUDE_DIR) instead. Marking the PANTHEIOS_ROOT variable
as advanced when not being in the cache is useless too.

* using $ENV{PANTHEIOS_ROOT}/include in the HINTS is dangerous since if
the environment variable is not set, it will evaluate to /include which
exists on *NIX systems. Better to use

find_path(PANTHEIOS_INCLUDE_DIR pantheios/pantheios.h
  PATH_SUFFIXES include
  HINTS ${PANTHEIOS_ROOT}
  ENV PANTHEIOS_ROOT)

* Don't set PANTHEIOS_INCLUDE_DIRS to the variable *name*
PANTHEIOS_INCLUDE_DIR. You have to dereference the variable:

set(PANTHEIOS_INCLUDE_DIRS "${PANTHEIOS_INCLUDE_DIR}")

* Again, comparing "${PANTHEIOS_INCLUDE_DIR}" against the empty string
is wrong! CMake will set its value to ..._NOT-FOUND in case of failure.
Just use

if(PANTHEIOS_INCLUDE_DIR)

and skip the whole message() stuff.

* Using file(GLOB ...) is almost certainly wrong. You'll need to find
out how the Pantheios library naming scheme works. From your example,
i'd think you could use the following when using Visual Studio:

# No idea what the UNIXEm stuff is, so I don't handle it here...
set(_P_COMP_TAG)
set(_P_OS_TAG)
set(_P_ARCH_TAG)
if(MSVC)
  if(MSVC60)
    set(_P_COMP_TAG vc6)
  elseif(MSVC70)
    set(_P_COMP_TAG vc7)
  elseif(MSVC71)
    set(_P_COMP_TAG vc71)
  elseif(MSVC80)
    set(_P_COMP_TAG vc8)
    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
      set(_P_ARCH_TAG .x64)
    endif()
  elseif(MSVC90)
    set(_P_COMP_TAG vc9)
    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
      set(_P_ARCH_TAG .x64)
    endif()
  elseif(MSVC10)
    set(_P_COMP_TAG vc10)
    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
      set(_P_ARCH_TAG .x64)
    endif()
  endif()
elseif(...)
  ...
endif()

set(_P_LIB_TAG ${_P_COMP_TAG}${_P_OS_TAG}${_P_ARCH_TAG})


Once you have that, you can continue finding the libraries (you missed
all the local and remote backends, and also you missed the actual
globbing in the backend and frontend libraries...)


if(PANTHEIOS_INCLUDE_DIR)
  get_filename_component(PANTHEIOS_ROOT_HINT
    "${PANTHEIOS_INCLUDE_DIR}" PATH)
endif()

set(_P_REQUIRED_LIBVARS)

# core and util libraries
foreach(l core util)
  find_library(PANTHEIOS_${l}_${PANTHEIOS_LIB_LINKTYPE}_DEBUG_LIBRARY
    pantheios.1.core.${_P_LIB_TAG}.${PANTHEIOS_LIB_LINKTYPE}.debug
    PATH_SUFFIXES lib
    HINTS ${PANTHEIOS_ROOT_HINT} ${PANTHEIOS_ROOT}
    ENV PANTHEIOS_ROOT)

  find_library(PANTHEIOS_${l}_${PANTHEIOS_LIB_LINKTYPE}_LIBRARY
    pantheios.1.core.${_P_LIB_TAG}.${PANTHEIOS_LIB_LINKTYPE}
    PATH_SUFFIXES lib
    HINTS ${PANTHEIOS_ROOT_HINT} ${PANTHEIOS_ROOT}
    ENV PANTHEIOS_ROOT)

  list(APPEND _P_REQUIRED_LIBVARS
    PANTHEIOS_${l}_${PANTHEIOS_LIB_LINKTYPE}_DEBUG_LIBRARY
    PANTHEIOS_${l}_${PANTHEIOS_LIB_LINKTYPE}_LIBRARY)
endforeach()

# backend libraries (split, sole, local, remote and common)
set(_P_LT ${PANTHEIOS_LIB_LINKTYPE})
set(_P_BE ${PANTHEIOS_BACKEND})
find_library(PANTHEIOS_be_lrsplit_${_P_LT}_DEBUG_LIBRARY
  pantheios.1.be.lrsplit.${_P_LIB_TAG}.${_P_LT}.debug
  PATH_SUFFIXES lib
  HINTS ${PANTHEIOS_ROOT_HINT} ${PANTHEIOS_ROOT}
  ENV PANTHEIOS_ROOT)

find_library(PANTHEIOS_be_lrsplit_LIBRARY
  pantheios.1.be.lrsplit.${_P_LIB_TAG}.${_P_LT}
  PATH_SUFFIXES lib
  HINTS ${PANTHEIOS_ROOT_HINT} ${PANTHEIOS_ROOT}
  ENV PANTHEIOS_ROOT)

list(APPEND _P_REQUIRED_LIBVARS
  PANTHEIOS_be_lrsplit_${_P_LT}_DEBUG_LIBRARY
  PANTHEIOS_be_lrsplit_${_P_LT}_LIBRARY)

foreach(t be bel ber bec)
  find_library(PANTHEIOS_${t}_${_P_BE}_${_P_LT}_DEBUG_LIBRARY
    pantheios.1.${t}.${_P_BE}.${_P_LIB_TAG}.${_P_LT}.debug
    PATH_SUFFIXES lib
    HINTS ${PANTHEIOS_ROOT_HINT} ${PANTHEIOS_ROOT}
    ENV PANTHEIOS_ROOT)

  find_library(PANTHEIOS_${t}_${_P_BE}_${_P_LT}_LIBRARY
    pantheios.1.${t}.${_P_BE}.${_P_LIB_TAG}.${_P_LT}
    PATH_SUFFIXES lib
    HINTS ${PANTHEIOS_ROOT_HINT} ${PANTHEIOS_ROOT}
    ENV PANTHEIOS_ROOT)

  list(APPEND _P_REQUIRED_LIBVARS
    PANTHEIOS_${t}_${_P_BE}_${_P_LT}_DEBUG_LIBRARY
    PANTHEIOS_${t}_${_P_BE}_${_P_LT}_LIBRARY)
endforeach()

# frontent libraries
set(PANTHEIOS_fe_DEBUG_LIBRARY)
set(PANTHEIOS_fe_LIBRARY)
if(NOT PANTHEIOS_FRONTENT STREQUAL null)
  set(_P_FE ${PANTHEIOS_FRONTEND})
  find_library(PANTHEIOS_${_P_FE}_${_P_LT}_DEBUG_LIBRARY
    pantheios.1.fe.${_P_FE}.${_P_LIB_TAG}.${_P_LT}.debug
    PATH_SUFFIXES lib
    HINTS ${PANTHEIOS_ROOT_HINT} ${PANTHEIOS_ROOT}
    ENV PANTHEIOS_ROOT)
  find_library(PANTHEIOS_${_P_FE}_${_P_LT}_LIBRARY
    pantheios.1.fe.${_P_FE}.${_P_LIB_TAG}.${_P_LT}
    PATH_SUFFIXES lib
    HINTS ${PANTHEIOS_ROOT_HINT} ${PANTHEIOS_ROOT}
    ENV PANTHEIOS_ROOT)

  list(APPEND _P_REQUIRED_LIBVARS
    PANTHEIOS_${_P_FE}_${_P_LT}_DEBUG_LIBRARY
    PANTHEIOS_${_P_FE}_${_P_LT}_LIBRARY)
endif()

* You'll need to come up with something smarter when setting the
PANTHEOS_LIBRARIES variable if you intend to handle backend splitting.
Probably your COMPONENTS must be more sophisticated, e.g adding the
component LRSplit which then requires also the two components L<COMP1>
and R<COMP2> to be specified, where <COMP1> and <COMP2> are any of the
available backend components.

* when calling the find_package_handle_standard_args() function, you can
then use my ${_P_REQUIRED_LIBVARS} variable:

find_package_handle_standard_args(Pantheios REQUIRED VARS
  PANTHEIOS_INCLUDE_DIR ${_P_REQ_LIBVARS})

* The VERSION_VAR and PANTHEIOS_VERSION_STRING variables are never set,
but you require them in the fphsa() call...

HTH

Michael

On 07/17/2012 04:11 AM, Philipp Berger wrote:
> I built a beta-version of the FindPantheios.cmake (see attached version,
> no copyright stuff, I'm sorry), it works - at least on windows and in my
> configuration.
> As I am new to this and this is my first try with Find* files, could
> those experienced in the art of CMakeing please have a look at it, give
> me some tips & tricks?
> Suggestions welcome ;)
> 
> Another thing: I understand the function find_library is to be used to
> "find" libs - the docs did not help me with understanding the naming
> scheme used. Is it possible to use find_library to locate e.g.
> "pantheios.1.core.vc10.x64.dll.debug.lib" if I have the string
> "pantheios.1.core" and also ".dll.debug"? I do not know anything about
> the part in the middle nor the ending. Sorry if this is a stupid question :/
> 
> My current solution is not very pretty and more of a hack and will only
> work in Windows as it uses FILE GLOB.
> 
> Third question: Is there an easy way to deal with the singular/plural
> variables, for example _INCLUDE_DIR and _INCLUDE_DIRS? How exactly is
> the syntax for setting those (String, List, etc)?
> 
> Thank you for your time, help and patience
> 
> Philipp Berger
> 
> Am 13.07.2012 08:30, schrieb Rolf Eike Beer:
>> Am Freitag, 13. Juli 2012, 02:41:50 schrieb Philipp Berger:
>>> Hello everybody,
>>>
>>> I'm relatively new to CMake, but managed to learn everything I needed,
>>> up until now.
>>> For a software project in C++ we want to use Pantheios (
>>> http://www.pantheios.org <http://www.pantheios.org/> ) as logging framework.
>>> Sadly, there is no FindPantheios.cmake file readily available, so I set of
>>> to write my own.
>>>
>>> The part for searching the include files/path was easy.
>>>
>>> The big problem I am facing and find myself unable to solve is the wide
>>> variety of library files.
>>> The amount of available lib files is huge, see the attached file for the
>>> list.
>>>
>>> For example, the core libs:
>>> pantheios.1.core.vc10.x64.dll.debug.lib
>>> pantheios.1.core.vc10.x64.dll.lib
>>> pantheios.1.core.vc10.x64.mt.debug.lib
>>> pantheios.1.core.vc10.x64.mt.lib
>>> pantheios.1.core.vc10.x64.widestring.dll.debug.lib
>>> pantheios.1.core.vc10.x64.widestring.dll.lib
>>> pantheios.1.core.vc10.x64.widestring.mt.debug.lib
>>> pantheios.1.core.vc10.x64.widestring.mt.lib
>>>
>>> I would like to have a checkbox to select Widestring capability yes/no.
>>>
>>> A main problem for me is to check that the selected libs are valid for
>>> the current configuration (if VC10 x64 was selected as compiler, only
>>> allow vc10.x64 libs) - is there a way to securely achieve that? Or
>>> should I rather let the user select arbitrary lib files and hope that
>>> they will work?
>>>
>>> What I need is six fields for the user to select lib files - the core
>>> lib, one frontend and a backend. And that for both Debug and Release. It
>>> would be much more useful if the user could select from a dropdown menu
>>> which Front-/Backend he would like together with the Widestring checkbox
>>> and the CMake file would assign the required Debug and Release libs to
>>> the variables, but as sated above, I do not know how to produce the
>>> required version string and how to create such mechanisms in CMake in
>>> general.
>> The debug/release stuff can be handled by CMake, just put both of them in the 
>> result variable prefixed with "debug" and "optimized". See what I've done 
>> recently in e.g. FindBZip2.cmake.
>>
>> I would put the backends in the COMPONENTS section, as well as the widestring, 
>> so you could do something like this:
>>
>> find_package(Pantheios COMPONENTS SomeBackend WideString)
> Thanks for the tip, I implemented that.
>> Choose one backend as default for the case the user does not select any and 
>> raise an error if more than one is specified (unless that actually makes sense, 
>> dunno).
>>
>> Eike




More information about the CMake mailing list