c++cmakecmake-modules

Path mismatch when including libraries with CMake


I am trying to include two libraries into my project to use them. I'm using CMake with CLion.

The two libraries are: https://github.com/herumi/bls and https://github.com/herumi/mcl

I got the following project setup:

enter image description here

This is the main CMake file:

cmake_minimum_required(VERSION 3.17)
project(blsbenchmark)

set(CMAKE_CXX_STANDARD 14)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

set(SOURCE_FILES src/main.cpp)
add_executable(blsbenchmark ${SOURCE_FILES})

include(FindPkgConfig)
find_package(bls REQUIRED)
include_directories(${BLS_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${BLS_LIBRARY})

find_package(mcl REQUIRED)
include_directories(${MCL_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${MCL_LIBRARY})

The Findbls.cmake:

set(FIND_BLS_PATHS
        /opt/bls)

find_path(BLS_INCLUDE_DIR bls.h
        PATH_SUFFIXES include
        PATHS ${FIND_BLS_PATHS})

find_library(BLS_LIBRARY
        NAMES bls384_256
        PATH_SUFFIXES lib
        PATHS ${FIND_BLS_PATHS})

The Findmcl.cmake:

set(FIND_MCL_PATHS
        /opt/mcl)

find_path(MCL_INCLUDE_DIR bn_c384_256.h, bn.h
        PATH_SUFFIXES include
        PATHS ${FIND_MCL_PATHS})

find_library(MCL_LIBRARY
        NAMES mclbn384_256
        PATH_SUFFIXES lib
        PATHS ${FIND_MCL_PATHS})

This setup allows me to include the files of the library very nicely in my project:

enter image description here

However, problems arise because, as you can see, I can link the library files directly in my main (bn.h and bls.h) without their prefixes (bls/bls.h or mcl/bn.h).

Thus, when trying to build this I get a:

fatal error: mcl/bn.h: No such file or directory
   11 | #include <mcl/bn.h>
      |          ^~~~~~~~~~

because the library itself requires the prefix "mcl/bn.h" path.

enter image description here

Thus, the question is how I can include these two libraries (mcl and bls) into my project with the prefix in the path such that this also is compatible with the two libraries.


Solution

  • As discussed in the Q&A here, you have to provide a different path to the include_directories() command. In your case, you can provide the parent directory to those found in your custom Find Modules.

    For example, for the mcl repository, the header is located here mcl/include/mcl/bn.h. This is how you've defined the include directories now:

    mcl/include/mcl/      bn.h
    ^                     ^
    include directory     #include header
    

    To achieve what you want, this is how you should split this up:

    mcl/include/          mcl/bn.h
    ^                     ^
    include directory     #include header
    

    So, use the parent directory to the one actually containing the header file.

    set(FIND_MCL_PATHS
            /opt/mcl)
    
    # Find the path containing the header.
    find_path(MCL_HEADER_DIR bn_c384_256.h, bn.h
            PATH_SUFFIXES include
            PATHS ${FIND_MCL_PATHS})
    
    # If path with header file was found, set MCL_INCLUDE_DIR to the parent directory.
    if(MCL_HEADER_DIR)
        # Grab the parent directory to MCL_HEADER_DIR.
        get_filename_component(PARENT_DIR ${MCL_HEADER_DIR} DIRECTORY)
        set(MCL_INCLUDE_DIR ${PARENT_DIR} CACHE PATH "MCL include directory" FORCE)
    endif()
    
    find_library(MCL_LIBRARY
            NAMES mclbn384_256
            PATH_SUFFIXES lib
            PATHS ${FIND_MCL_PATHS})
    

    Now, you should be able to compile using the following include in your code:

    #include <mcl/bn.h>