I am having issue with correctly linking/including a library in my c++ project. I have followed other posts and used add_subdirectory, target_include_directories, and target_link_libraries in CMakeLists.txt.
But I am still getting the following error during make.
test_app/main.cc:3:10: fatal error: icalendar.h: No such file or directory
#include "icalendar.h"
^~~~~~~~~~~~~
compilation terminated.
CMakeFiles/program.dir/build.make:75: recipe for target 'CMakeFiles/program.dir/main.cc.o' failed
make[2]: *** [CMakeFiles/program.dir/main.cc.o] Error 1
CMakeFiles/Makefile2:117: recipe for target 'CMakeFiles/program.dir/all' failed
make[1]: *** [CMakeFiles/program.dir/all] Error 2
Makefile:90: recipe for target 'all' failed
make: *** [all] Error 2
The project structure looks like this:
.
├── CMakeLists.txt
├── icalendarlib
│  ├── CMakeLists.txt
│  ├── date.cpp
│  ├── date.h
│  ├── icalendar.cpp
│  ├── icalendar.h
│  ├── README.rst
│  ├── test
│  │  ├── calendar.ics
│  │  ├── CMakeLists.txt
│  │  └── iCalendarTest.cpp
│  ├── types.cpp
│  ├── types.h
│  └── wxwrapper.h
└── main.cc
The project’s CMake looks like this:
#./CMakeLists.txt
cmake_minimum_required(VERSION 3.6)
project(test_app)
add_subdirectory(icalendarlib)
add_executable (program main.cc)
target_link_libraries(program ${LIB_OUTPUT_NAME})
The library’s cmake looks like this:
#./icalendarlib/CMakeLists.txt
project(iCalendarlib)
set(LIB_OUTPUT_NAME iCalendar)
set(CFLAGS "-g")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CFLAGS}")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CFLAGS}")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_library(${LIB_OUTPUT_NAME} SHARED
date.cpp
date.h
icalendar.cpp
icalendar.h
types.cpp
types.h
)
target_include_directories(${LIB_OUTPUT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/icalendarlib)
main.cc looks like this
#include "icalendar.h" // << fatal error: icalendar.h: No such file or directory
int main () {
return 0;
}
I am running these commands under build folder
cmake ..
make
>Solution :
There’s a rule I try to follow in CMake: don’t use variables if you don’t really have to.
For example, you could just link to the library directly instead of using a variable equals to the name of your library:
target_link_libraries(program iCalendar)
But here’s the problem: variables in CMake are scoped by directory. When you do this
target_link_libraries(program ${LIB_OUTPUT_NAME})
You’re not linking to any library since you set the value in the subdirectory only.