cmakebotan

How do I link botan in cmake?


I am trying to write a program in c++ using botan but I don't know how to properly use it. Take for example the following code:

Botan::AutoSeeded_RNG rng;
Botan::UUID uuid = Botan::UUID(rng);
std::cout << uuid.to_string() << std::endl;

If I try to run this it throws an error which seems to be an issue with botan not being linked. But I'm not sure how I can link this using CMake. In CMakeList.txt I have

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
find_package(BOTAN REQUIRED)

based on this, and in modules, I have a file FindBOTAN.cmake.

But this throws the error Could NOT find Botan (missing: BOTAN_LIBRARIES BOTAN_INCLUDE_DIRS), the warning

The package name passed to `find_package_handle_standard_args` (PkgConfig)
does not match the name of the calling package (BOTAN).  This can lead to
problems in calling code that expects `find_package` result variables
(e.g., `_FOUND`) to follow a certain pattern.

and fails to find botan.

I have barely any experience using CMake hence I've based it on someone else's but now I've got the problem that I don't know what is going wrong.


Solution

  • That find module is totally wrong. You should point whoever wrote it to this answer. Here's something better (but could still be improved, e.g. by validating the version):

    find_package(PkgConfig REQUIRED)
    
    if (NOT TARGET Botan::Botan)
      pkg_check_modules(Botan QUIET IMPORTED_TARGET botan-2)
      if (TARGET PkgConfig::Botan)
        add_library(Botan::Botan ALIAS PkgConfig::Botan)
      endif ()
    endif ()
    
    if (NOT TARGET Botan::Botan)
      find_path(Botan_INCLUDE_DIRS NAMES botan/botan.h
                PATH_SUFFIXES botan-2
                DOC "The Botan include directory")
    
      find_library(Botan_LIBRARIES NAMES botan botan-2
                   DOC "The Botan library")
    
      mark_as_advanced(Botan_INCLUDE_DIRS Botan_LIBRARIES)
    
      add_library(Botan::Botan IMPORTED UNKNOWN)
      set_target_properties(
        Botan::Botan
        PROPERTIES
        IMPORTED_LOCATION "${Botan_LIBRARIES}"
        INTERFACE_INCLUDE_DIRECTORIES "${Botan_INCLUDE_DIRS}"
      )
    endif ()
    
    include(FindPackageHandleStandardArgs)
    find_package_handle_standard_args(
      Botan
      REQUIRED_VARS Botan_LIBRARIES Botan_INCLUDE_DIRS
    )
    

    Put this file in cmake/FindBotan.cmake and then you can use it from your top-level CMakeLists.txt like so:

    cmake_minimum_required(VERSION 3.23)
    project(botan_example)
    
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
    find_package(Botan REQUIRED)
    
    add_executable(botan_example main.cpp)
    target_link_libraries(botan_example PRIVATE Botan::Botan)
    

    As always, you should endeavor to link to imported targets, like the Botan::Botan target that my revised find module defines. For main.cpp, I wrapped your code up like so:

    #include <botan/botan.h>
    #include <botan/uuid.h>
    #include <iostream>
    
    int main() {
      Botan::AutoSeeded_RNG rng;
      Botan::UUID uuid = Botan::UUID(rng);
      std::cout << uuid.to_string() << std::endl;
    }
    

    And I confirmed that it does indeed build:

    alex@alex-ubuntu:~/test$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
    -- The C compiler identification is GNU 9.4.0
    -- The CXX compiler identification is GNU 9.4.0
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Check for working C compiler: /usr/bin/cc - skipped
    -- Detecting C compile features
    -- Detecting C compile features - done
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Check for working CXX compiler: /usr/bin/c++ - skipped
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    -- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1") 
    -- Checking for module 'botan-2'
    --   Found botan-2, version 2.12.1
    -- Found Botan: botan-2  
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /home/alex/test/build
    
    alex@alex-ubuntu:~/test$ cmake --build build/
    [ 50%] Building CXX object CMakeFiles/botan_example.dir/main.cpp.o
    [100%] Linking CXX executable botan_example
    [100%] Built target botan_example
    
    alex@alex-ubuntu:~/test$ ./build/botan_example 
    6ACD38C7-3B70-4B57-A0F8-DEDCDCEF4D34