user5876164
user5876164

Reputation: 503

CMake: No such file or directory error with a custom library

I am trying to make a library using CMake. I would like the library to work as many library widely being used, so I mimicked several structures of CMake files in the internet and finally made a structure described below, if possible. Also, I want to use the #includes as shown in the code snippet.

However, I get a fatal error from lib1.cpp which says "lib1.hpp: no such file or directory".

I am pretty sure this error is not the only error I will get, after fixing the current error. What am I doing wrong?

Here are the list of directories, CMake files, and sources.

LIB_ROOT
  CMakeLists.txt // mainCMake
  + lib
  |  CMakeLists.hpp // libCMake
  |  mainlib.hpp
  |  + include
  |  |  lib1.hpp
  |  |  lib2.hpp
  |  |  ...
  |  + src
  |  |  lib1.cpp
  |  |  lib2.cpp
  |  |  ...
  + test
  |  CMakeLists.txt // testCMake
  |  test.cpp

mainCMake:

cmake_minimum_required(VERSION 3.10)
project(LIB)

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})

set(CMAKE_CXX_STANDARD 20)

add_subdirectory(lib)
add_subdirectory(test)

libCMake:

add_library(LIB

        mainlib.hpp

        #include
        include/lib1.hpp
        include/lib2.hpp
        ...

        #src
        src/lib1.cpp
        src/lib2.cpp
        ...
)

target_include_directories(LIB PUBLIC ${CMAKE_CURRENT_DIR}/include ${CMAKE_CURRENT_DIR}/src)

testCMake:

add_executable(Test test.cc)

target_link_libraries(Test LINK_PUBLIC LIB)

lib1.hpp

#ifndef lib1
#define lib1
namespace lib {}
#endif

lib1.cpp

#include "lib1.hpp"

mainlib.hpp

#include <include/lib1.hpp>

test.cpp

#include <mainlib.hpp>
int main() {}

Upvotes: 0

Views: 2183

Answers (1)

Alex Reinking
Alex Reinking

Reputation: 19916

There is no such variable as ${CMAKE_CURRENT_DIR}. You surely mean ${CMAKE_CURRENT_SOURCE_DIR}. Please see the documentation for the list of CMake variables, here: https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html

For CMAKE_CURRENT_SOURCE_DIR, the documentation is here: https://cmake.org/cmake/help/latest/variable/CMAKE_CURRENT_SOURCE_DIR.html


There is also no such argument as LINK_PUBLIC, as in here:

# WRONG
target_link_libraries(Test LINK_PUBLIC LIB)

The line you meant to write was

target_link_libraries(Test PRIVATE LIB)

There is a PUBLIC keyword, but it makes no sense on executables since you can't link to an executable*. There are three visibility specifiers in CMake: PRIVATE, INTERFACE, and PUBLIC. PUBLIC is exactly the same as both PRIVATE and INTERFACE. PRIVATE means that the property is only relevant to the target; INTERFACE means that the property is only relevant to targets linking to this target. So you want PRIVATE here.

* sort of... there's a whole ENABLE_EXPORTS thing that's used for writing plugins, but it is relatively rare.


Also, this line makes no sense:

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})

Unless you have custom CMake modules in the root of your project, this is pointless and overrides a user's ability to set CMAKE_MODULE_PATH themselves. Something like

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

is a bit more common, but still pointless unless you actually do have custom modules.


I am trying to make a library using CMake. I would like the library to work as many library widely being used, so I mimicked several structures of CMake files in the internet

I'm sorry to be the one to let you know, but imitating existing CMake builds is a terrible approach. Many of them were written in the CMake stone age (versions less than 3.14... you should use the newest one for new code) and use bad or out of date practices. Look for talks at CppCon and Meeting C++ by Craig Scott and Deniz Bahadir for better advice. Craig Scott's book, "Professional CMake", while not free, is the most comprehensive resource there is at the moment. I highly recommend it.

Upvotes: 1

Related Questions