Reputation: 503
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 #include
s 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
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