Better way to include a directory in CMakeLists.txt - c++

For my current CMake-project, i'm in need for the numpy/ndarrayobject.h-library. At first the project didn't compile and complained about numpy/ndarrayobject.h not being found in the include-path.
So what i did was sudo find / -type f -name 'ndarrayobject.h' and it spit out:
/usr/lib/python3.8/site-packages/numpy/core/include/numpy/ndarrayobject.h
which i included in CMakeLists.txt:
include_directories(/usr/lib/python3.8/site-packages/numpy/core/include/)
So, there is no actual error here. The project compiles and works as i expected it to. However, i think there must be a smarter way to find the directory. I have seen CMake-projects use
find_package(PythonLibs 3 REQUIRED)
find_package(OpenCV REQUIRED)
or something along these lines. So my initial thought is to learn about such macros to include the numpy-directory a bit smarter.
What are those macros called? Where are they defined? Where can i learn about them? Does such a macro exist for the above mentioned directory?
Is this maybe the wrong approach and there is a cleaner way to find and include the above mentioned directory?

However, i think there must be a smarter way
Yes, you are right, and you are on the right track.
What are those macros called? Where are they defined? Where can i learn about them?
Those are called "find modules", and are usually located in (assuming Unix/Linux): /usr/local/share/cmake-<version>. You can learn about them in the official documentation: https://cmake.org/cmake/help/v3.14/manual/cmake-developer.7.html#find-modules
However: The ability to find NumPy seems to have been added in CMake 3.14: https://cmake.org/cmake/help/v3.14/module/FindPython3.html.
So, assuming you are using CMake 3.14 or later, this should do the trick:
find_package(Python3 REQUIRED COMPONENTS NumPy)
# Use PUBLIC or INTERFACE scope if you need to
# propagate the include folder to dependents
target_include_directories(<your target> PRIVATE ${Python3_NumPy_INCLUDE_DIRS})
Here we use FindPython3.cmake, which exports a whole heap of variables related to Python, including the one you need: Python3_NumPy_INCLUDE_DIRS.
Edit: As #Pedro correctly pointed out, you can also link to NumPy and get access to its include that way. This is actually preferable, since you may have to link to NumPy libraries anyway when building your application, and this saves you from having to issue two separate commands.
target_link_libraries(<your target> Python3::NumPy)
Now you can include said header: #include <numpy/ndarrayobject.h>
If you are unable to use CMake 3.14 or newer, you can consult the latest find modules to see how it's done and simply write your own module, or build the latest CMake from source (which is trivial).

Related

How to fix "Could not find a package configuration file ..." error in CMake?

I have been working on a project which uses rplidar_sdk and in the beginning, I was facing this problem:
How can I link locally installed SDK's static library in my C++ project?
Basically, the SDK generates the library in its local directory, and in its Makefile, it does not have install rules. I mean I can run make but after that, if I run sudo make install then it gives make: *** No rule to make target 'install'. Stop. error.
So, with the help of this & this answer, I was able to build my local project. So far so good.
However, the main problem is that I have to hard-code the RPLidar SDK path in CMakeLists.txt of my repo. Now, whenever someone else in my team starts working on that repo (which is quite obvious) then he/she has to update the CMakeLists.txt first. This is not a good idea/practice!
To fix this, I updated the Makefile of RPLidar SDK as follow:
.
.
.
RPLIDAR_RELEASE_LIB := $(HOME_TREE)/output/Linux/Release/librplidar_sdk.a
install: $(RPLIDAR_RELEASE_LIB)
install -d $(DESTDIR)/usr/local/lib/rplidar/Release/
install -m 644 $(RPLIDAR_RELEASE_LIB) $(DESTDIR)/usr/local/lib/rplidar/Release/
RPLIDAR_DEBUG_LIB := $(HOME_TREE)/output/Linux/Debug/librplidar_sdk.a
install: $(RPLIDAR_DEBUG_LIB)
install -d $(DESTDIR)/usr/local/lib/rplidar/Debug/
install -m 644 $(RPLIDAR_DEBUG_LIB) $(DESTDIR)/usr/local/lib/rplidar/Debug/
RPLIDAR_HEADERS := $(HOME_TREE)/sdk/include
install: $(RPLIDAR_HEADERS)
install -d $(DESTDIR)/usr/local/include/rplidar/
cp -r $(RPLIDAR_HEADERS)/* $(DESTDIR)/usr/local/include/rplidar/
RPLIDAR_HEADERS_HAL := $(HOME_TREE)/sdk/src/hal
install: $(RPLIDAR_HEADERS_HAL)
install -d $(DESTDIR)/usr/local/include/rplidar/
cp -r $(RPLIDAR_HEADERS_HAL) $(DESTDIR)/usr/local/include/rplidar/
Due to this update, now, I can run sudo make install which basically copies the header files of RPLidar SDK from the local directory to /usr/local/rplidar/ directory. It also copies the lib file to /usr/local/lib/rplidar/<Debug> or <Release>/ directory.
Now, in my local project, I updated the CMakeLists.txt to as follow:
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(<project_name>)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
SET(CMAKE_CXX_FLAGS -pthread)
include_directories(include)
add_executable(${PROJECT_NAME} src/main.cpp src/another_src_file.cpp)
find_package(rplidar REQUIRED)
include_directories(${rplidar_INCLUDE_DIRS})
link_directories(${rplidar_LIBRARY_DIRS})
target_link_libraries(${PROJECT_NAME} ${rplidar_LIBRARY})
However, upon running cmake .. command, I'm getting this error:
.
.
.
CMake Error at CMakeLists.txt:12 (find_package):
By not providing "Findrplidar.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "rplidar", but
CMake did not find one.
Could not find a package configuration file provided by "rplidar" with any
of the following names:
rplidarConfig.cmake
rplidar-config.cmake
Add the installation prefix of "rplidar" to CMAKE_PREFIX_PATH or set
"rplidar_DIR" to a directory containing one of the above files. If
"rplidar" provides a separate development package or SDK, be sure it has
been installed.
-- Configuring incomplete, errors occurred!
As far as I know, RPLidar SDK does not have rplidarConfig.cmake or rplidar-config.cmake file.
How can I fix this error?
Rants from my soul:
It sucks when you have to use any library foo when the author fails to provide a foo-config.cmake for you to use easily by invoking find_package(foo). It's absolutely outrageous when a reasonably modern project still uses hand written Makefiles as its build system. I myself is stuck with a much worse constructed SDK than yours right now.
Short answer:
Since the author of the SDK fails to provide a config file to support your cmake usage, if you still insists on invoking find_package on the library (and you should!), you are required to write your own Module file to clean up their mess. (Yeah, you are doing the work for the library authors).
To truly achieve cross platform usage, you should write a Findrplidar.cmake module file to find the libraries for you.
To write a reasonable module file, you would most likely use API find_path for header files and find_library for libs. You should check out its docs and try using them, and maybe Google a few tutorials.
Here is my version of Findglog.cmake for your reference. (glog authors have updated their code and supports Config mode. Unfortunately, Ubuntu build doesn't use it, so I still have to write my own file)
find_path(glog_INCLUDE_DIR glog/logging.h)
message(STATUS "glog header found at: ${glog_INCLUDE_DIR}")
find_library(glog_LIB glog)
message(STATUS "libglog found at: ${glog_LIB}")
mark_as_advanced(glog_INCLUDE_DIR glog_LIB)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(glog REQUIRED_VARS
glog_INCLUDE_DIR
glog_LIB
)
if(glog_FOUND AND NOT TARGET glog::glog)
add_library(glog::glog SHARED IMPORTED)
set_target_properties(glog::glog PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
IMPORTED_LOCATION "${glog_LIB}"
INTERFACE_INCLUDE_DIRECTORIES
"${glog_INCLUDE_DIR}"
)
endif()
And you can use it like this:
find_package(glog)
target_link_libraries(main PRIVATE glog::glog)
Long answer:
The history of developers using cmake is an absolute nightmare. The internet is filled with bad practice/examples of how not to use cmake in your project, including the old official cmake tutorial (which still might be there). Mostly because no one really gives a **** (If I can build my project, who cares if it's cross platform). Another valid reason is that cmake documentations are really daunting to beginners.
This is why I am writing my own answer here, lest you get misguided by Googling elsewhere.
The nightmare is no more. The wait has ended. "The Messiah" of cmake (source) is come. He bringeth hope to asm/C/C++/CUDA projects written in 2020 and on. Here is The Word.
The link above points to the only way how cmake projects should be written and truly achieve cross platform once and for all. Note the material is not easy at all to follow for beginners. I myself spent an entire week to fully grasp what was covered in The Word, when I had become somewhat familiar with cmake concepts at the time (but lost in my old sinful ways).
The so-called "long answer" is actually shorter. It's just a pointer to the real answer. Good luck reading the Word. Embrace the Word, for anything against that is pure heresy.
Response of comment 1-5:
Good questions. A lot of those can be obtained from the Word. But the word is better digested when you become more familiar with CMake. Let me answer them in decreasing of relevance to your problem at hand.
For the ease of discussion, I'll just use libfoo as an example.
Let's say you always wants to use libfoo like this:
find_package(foo)
target_link_libraries(your_exe ... foo::foo)
Pretend foo is installed at the following location:
- /home/dev/libfoo-dev/
- include
- foo
- foo.h
- bar.h
- ...
- lib
- libfoo.so
- share
- foo/foo-config.cmake # This may or may not exist. See discussion.
Q: Only one .h file. Why?
A: Because in the case of libfoo (also true for glog), only one search of header location is necessary. Just like the example from libfoo,
where foo/foo.h and foo/bar.h are at the same location. So their output of find_path would be the same: /home/dev/libfoo-dev/include.
Q: Why I'm getting NOTFOUND for my headers and libs?
A: The function find_path and find_library only search locations specify in the documentations. By default they search system locations,
like /usr/include and /usr/lib respectively. Refer to the official docs for details on system locations. In the case of libfoo, however,
they reside in /home/dev/libfoo-dev. So you must specify these locations in cmake variable CMAKE_PREFIX_PATH. It's a ; seperated string.
One would do cmake -D CMAKE_PREFIX_PATH="/home/dev/libfoo-dev;/more/path/for/other/libs/;...;/even/more/path" .... on the command line.
One very important note: unlike Unix command find, find_path will only search specific paths inside /home/dev/libfoo-dev, not all the way down:
include (usually also include/{arch} where {arch} is sth like x86_64-linux-gnu for x86 Linux) for find_path; lib variant for find_library,
respectively. Unusual locations would require passing in more arguments, which is uncommon and most likely unnecessary.
For this very reason, for libfoo, calling find_path(... foo.h ...) is undesired. One would want find_path(... foo/foo.h ...). Refer to the docs
for more details. You can also try out yourself.
Also for this reason, it is desirable to organize libraries in the usual bin include lib share quad on Unix-like systems. I'm not familiar with Windows.
Q: Debug & Release
A: There are several options. The easiest one might be:
Prepare rplidar debug and release build in two different folders, /path/to/debug & /path/to/release for instance
Passing to Debug & Release build respectively (cmake -D CMAKE_PREFIX_PATH="/path/to/debugORrelease" ....)
There are definitely others ways, but perhaps requires special care in your Findrplidar.cmake script (maybe some if statements).
Q: Why glog::glog rather than glog?
A: It's just modern cmake practice, with small benefits. Not important right now. Refer to the Word if you are interested.
Q: You mentioned that you are writing rplidarConfig.cmake. Instead you should rename the file to Findrplidar.cmake.
A: CMake philosophy is as such:
Library authors should write foo-config.cmake or fooConfig.cmake
When they fail to provide one, it sucks. And according to the Messiah, it should be reported as a bug.
In this case, you as library user, should write Findfoo.cmake by guessing how to describe the dependencies for libfoo. For simple libraries, this is not so bad. For complex ones, like Boost, this sucks!
A few side note on this topic:
Note how Findfoo.cmake is written by library users, from guessing.
This is insane! Users shouldn't do this. This is the authors' fault, to put their users in this uncomfortable situation.
A foo-config.cmake file is extremely easy to write for authors of libfoo, IF they follow the Word exactly.
Extremely easy for the authors in the sense that: cmake can take care of everything. It will generate scripts automatically for the authors to use in their foo-config.cmake file.
Guaranteed to be cross-platform and easy to use by the users, thanks to cmake.
However, the reality sucks. Now you have to write Findfoo.cmake
Q: Why only find_package & target_link_libraries?
A: This is what the Word says. It's therefore good practice. Why the Word says so is something you have to find out yourself.
It's not possible for me to explain the gist of the Word in this answer, nor would it be convincing to you. I would just say the following:
It's very easy to write spaghetti CMakeLists that are next to impossible to maintain. The spirit of the Word helps you avoid that by
forcing you to carefully think about:
library structure: public vs private headers, for example. This makes you think about what to include in your headers and public APIs.
build specification: what is necessary to build a library you write (what to include; what to link)
usage requirement: what is necessary for others to use a library you write (what to include; what to link)
dependencies: what is the relationship of the library you write & its dependencies
Maybe more
If you think about it, these aspects are crucial to writing a cross-platform and maintainable library.
include_directories, link_directories and add_definitions are all very bad practice
(according to lots of sources, including the official documentations of these APIs). Bad practice tends to obscure the aspects above,
and causes problems later on when everything gets integrate together as a whole. E.g. include_directories will add -I to compiler for every
target written in the directory of that CMakeLists.txt. Read this sentence a few times and Spock will tell you it's illogical.
Don't worry. It's okay for now to use them when you are not familiar with the Word (Why else would this be in the last section). Once you know the Word, refactor your CMakeLists when you have time. Bad practice might cause problem later on, when your project becomes more complex. (In my professional experience, 5 very small groups of people is enough to cause a nightmare. By nightmare I mean hard code everything in CMakeLists; Create a git branch for every single different platform/device/environment; Fixing a bug meaning to cherry-pick one commit to each branch. I've been there before knowing the Word.)
The practice of the Word very well utilize the philosophy of modern CMake, to encapsulate build specifications and usage requirements inside
CMake targets. So when target_link_libraries is called, these properties gets propagated properly.

How to configure DBus dependencies with CMake

I am new to CMake and DBus. I am following along the guide here and make a basic program compile and execute.
The first problem that I ran into was my program will not find
<dbus/dbus.h>
I got around that issue by adding some include directories to my CMakeList.txt.
Currently, my CMakeLists.txt looks like this:
...
include_directories(/usr/lib/)
include_directories(/usr/include/dbus-1.0/)
include_directories(/usr/lib/x86_64-linux-gnu/dbus-1.0/include)
include_directories(/usr/include/glib-2.0)
include_directories(/usr/lib/x86_64-linux-gnu/glib-2.0/include/)
set (LIBS
dbus-1
dbus-glib-1
)
add_executable(mydbus mydbus.cpp)
target_link_libraries(mydbus ${LIBS} )
Now, my program is complaining about not being able to find dbus-arch-deps.h
/usr/include/dbus-1.0/dbus/dbus.h:29:33: fatal error: dbus/dbus-arch-deps.h: No such file or directory
#include <dbus/dbus-arch-deps.h>
I know that the solution for this is to use proper command line flags or pkg-config. As discussed here and numerous other posts.
However, I do not know how to configure CMakeLists.txt to have similar effect.
My guess would be to add something like find_package(dbus-1) to CMakeLists.txt. And if that is correct, I am going to have to write my own Finddbus-1.cmake. Does this sound correct? Or is there an easier way?
I will appreciate any pointers.
You may get an existing FindDBus.cmake script (e.g., this one), copy it into your project, and use as
find_package(DBus REQUIRED)
# Use results of find_package() call.
include_directories(${DBUS_INCLUDE_DIRS})
add_executable(mydbus mydbus.cpp)
target_link_libraries(mydbus ${DBUS_LIBRARIES})
Alternatively, as you know pkgconfig can find DBus, you may use CMake module PkgConfig. Actually, FindDBus.cmake script, referenced above, uses PkgConfig module in its implementation. Possible usage could be:
find_package(PkgConfig REQUIRED) # Include functions provided by PkgConfig module.
pkg_check_modules(DBUS REQUIRED dbus-1) # This calls pkgconfig with appropriate arguments
# Use results of pkg_check_modules() call.
include_directories(${DBUS_INCLUDE_DIRS})
link_directories(${DBUS_LIBRARY_DIRS})
add_executable(mydbus mydbus.cpp)
target_link_libraries(mydbus ${DBUS_LIBRARIES})
However, using link_directories is not recommended, it is better to use absolute paths to libraries in target_link_libraries() call. That is why it is better to combine pkg_check_modules with find_library, as it is done in the referenced Find script. That answer describes generic way for use result of pkgconfig in CMake.

How to have CMake show headers-that are not part of any binary target-in the IDE?

In our workflow, we can have a module A that is composed of several header files, module A not producing any binary (side note: it will obviously be used by other modules, that include some of the headers from module A to produce binaries).
A good example would be a header-only library, for which CMake 3 introduces a good support thanks to the notion of INTERFACE library (see this SO answer, and CMake's documentation of the feature).
We can make an interface library target out of module A:
add_library(module_A INTERFACE)
That gives us all the nice features of CMakes targets (it is possible to use it as another target's dependency, to export it, to transitively forward requirements etc.)
But in this case, the headers in module A do not show up in our IDE (Xcode, yet we expect it to be the same with most/every other IDE).
This proves to be a major drawback in the workflow, since we need the files composing module A to be shown in the IDE for edition. Is it possible to achieve that ?
Several months down the line, I did not find a way to directly list the header files for an INTERFACE library.
Since the question still has some views, here is what I ended up doing (i.e. what appears like the lesser hack currently available).
Imagine module A is a header only library. In the CMakeLists.txt declaring its target:
# Define 'modA_headers' variable to list all the header files
set(modA_headers
utility.h
moreUtilities.h
...)
add_library(moduleA INTERFACE) # 'moduleA' is an INTERFACE pseudo target
#
# From here, the target 'moduleA' can be customised
#
target_include_directories(moduleA ...) # Transitively forwarded
install(TARGETS moduleA ...)
#
# HACK: have the files showing in the IDE, under the name 'moduleA_ide'
#
add_custom_target(moduleA_ide SOURCES ${modA_headers})
I do not accept this answer, since I expect further releases of CMake to offer a more semantically correct approach, which will then be accepted : )
You can use the new target_sources command in CMake 3.1.
add_library(moduleA INTERFACE)
target_include_directories(moduleA INTERFACE ...)
target_sources(moduleA INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/utility.h
${CMAKE_CURRENT_SOURCE_DIR}/moreUtilities.h
)
It is also transitive.
http://www.cmake.org/cmake/help/v3.1/command/target_sources.html#command:target_sources
The limitation of not being able to export targets which have INTERFACE_SOURCES has been lifted for CMake 3.3.

How to do CMake modules

I try to learn c++ with cmake. I have done a project, and cmake runs, it compiles, it works, that is nice, ok. Now I started a new project in which I want to use some classes of the first one. I have tried to read some sourcecode and I have understand that I need to make a module that I can read from both the application. So this will be my repository:
/
/cmake
/modules/Network
/software/sw1
/software/sw2
both the projects sw1 and sw2 depends on the module Netowrk. In the folder cmake there has to be the FindNetwork.cmake file, and in sw1, sw2 and Network there has to be the CMakeList.txt .
But.. I messed up with include_directories and other cmake obscurities..
Can someone point me out to a nice overview how to easily organize a repository with softwares that depend on common modules?
This link will provide some examples for you.
In terms of how you are looking at the project/infrastructure then it's best to not confuse things too much. So here is a couple of points to get you started (I hope)
In c++ a module is a library (so refer to your Network module as a
library)
To include a library you need to link it and also make the
header files available.
In cmake this is two commands target_link_libraries and include_directories respectively.
With that in mind the project structure could be
/Network/include (api here)
/Network/src
/sw1/src
/sw2/src
with an example base CmakeLists.txt file for you: (place in root dir of project)
cmake_minimum_required(VERSION 2.7) // your choice
project(myproject) // change name
add_subdirectory(Network)
add_subdirectory(sw1)
add_subdirectory(sw2)
in the Network Directory you would have this
add_library(Network net1.cc net2.cc etc.)
In the sw1 dir
include_dirs(${MYPROJECT_SOURCE_DIR}/Network/include)
link_directories(${MYPROJECT_BINARY_DIR}/Network)
add_executable (sw1prog sw1.cc sw11.cc etc.)
target_link_libraries (sw1prog Network)
In the sw2 dir
include_dirs(${MYPROJECT_SOURCE_DIR}/Network/include)
link_directories(${MYPROJECT_BINARY_DIR}/Network)
add_executable (sw2prog sw2.cc sw21.cc etc.)
target_link_libraries (sw2prog Network)
This is a very simplified version of what you may require, it removes the need for a FindXXModule.cmake file to be created and refers to the library you create implicitly. I think this is the best mechanism for you, if you did want to create a FindXXModule.cmake then I would suggest it's when you actually install your libs to the machine and wish others to be able to find it, either that or have a mechanism for multiple projects to link to each other libraries.
I hope this is a little useful, please bear in mind the cmake site has some examples and cmake --help is your friend.

The right way to structure my c++ project with cmake?

I have been struggling with this for quite a while, and my adventures with cmake have only resulted in hackish solutions that I am pretty sure are not correct.
I created a library that consists of several files, as follows:
-libfolder
-codepart1folder
-CMakeLists.txt
-codepart1.cpp
-codepart1.hpp
-codepart2folder
-codepart3folder
-lib.cpp
-lib.hpp
-CMakeLists.txt
I wrote a CMakeLists file to compile the library (after some experimentation), and I can generate a lib.a file. Now I would like to include this code as a library in other projects, and access it through the interface in lib.hpp. What is the best way to do this, in terms of directory structure, and what I need to put into CMakeLists.txt in my root project?
My current attempt has been to add -libfolder as a subfolder to my current project, and add the commands:
include_directories(${PROJECT_SOURCE_DIR}/libfolder)
link_directories(${PROJECT_BINARY_DIR}/libfolder)
add_subdirectory(libfolder)
target_link_libraries(project lib)
When I run make, the library compiles fine, but when project.cpp compiles, it complains that it cannot find codepart1.hpp (which is included in lib.hpp, included from project.cpp).
I suspect that this is the wrong way about doing this, but I cannot wade through the CMake documentation and find a good tutorial on setting up projects like this. Please help, CMake gurus!
The clean way to import one CMake project into another is via the find_package command. The package declaration is done by using the export command. An advantage of using find_package is that it eliminates the need to hard-code paths to the package's files.
Regarding the missing hpp file, you didn't include codepart1folder, so it's not on the include path.
Ok, so after consulting a coworker of mine who is a CMake guru, it seems CMake does not have support for what I am trying to do, leaving one with 3 options:
Add all of the dependencies to the parent projects CMakeLists.txt - not very clean, but it will get the thing to work. You'll have to do this for every project you add the code to, and go back and fix things if your library changes.
clean up your library headers. This is done through some compiler hackery. The idea is to forward-declare every class, and use only pointers or boost::shared_ptr, and then include the dependencies only in the cpp file. That way you can build the cpp file using all the findpackage stuff, and you get the bonus of being able to use the lib by only including the header and linking to the library.
Look into build systems. Having portable code and fast code compilation with complex dependencies is not a solved problem! From my investigations it turned out to be quite complicated. I ended up adopting my coworkers build system which he created himself in cmake, using things he picked up from Google.
Looking at your post you don't seem to add 'codepart1folder' to the includes anywhere. How are you including codepart1.hpp as:
#include <codepart1.hpp>
#include "codepart1folder/codepart1.hpp"
I don't think there is a standard accepted way to structure cmake projects. I've looked at a bunch of cmake repos and they tend to have differences. Personally I do the following:
-project
CMakeLists.txt
-build
-cmake
OptionalCmakeModule.cmake
-src
-Main
Main.cpp
Main.hpp
-DataStructs
SomeTree.hpp
SomeObject.hpp
-Debug
Debug.hpp
-UI
Window.hpp
Window.cpp
Basically that dumps all the source code into 1 directory, then you perform an out of source build with: 'mkdir build && cd build && cmake .. && make' in the projects root folder.
If you have separate libs as part of your project, then you might want a separate libs directory with another subfolder for your specific lib.
I have some of my repos on: https://github.com/dcbishop/ if you want to look at the CMakeLists.txt files.
The main problems with my project structure are that I use the FILE_GLOB which is apparently the 'wrong' way to do things (if you add files after running 'cmake ..' then they won't be picked up hen you do a 'make'). I haven't figured out what the 'right' way to do it is (from what I can see it involves keeping a separate list of files) I also only use 1 CMakeLists.txt file.
Some projects also choose to separate their cpp and hpp files into separate directories. So you would have an include and src folders (at least for the hpp files that are intended to be used externally). I think that would mainly be for projects that are mainly large libraries. Would also make installing header files much easier.
You are probably missing
include_directories(${PROJECT_SOURCE_DIR}/libfolder/codepart1folder)
In such a case you might want to set( CMAKE_INCLUDE_CURRENT_DIR on) to add all folders to the include directory path variable.
Check cmake's output on the command line whether the correct include folders are set or not. Additionally you can always use message() as "print debugging" for cmake variables.
In case of include directories however you need to read the directory property to see what is actually in the include directories.
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("inc_dirs = ${inc_dirs}")
I hope this helps you figuring out what is missing.
Edit
I just saw your comment about added codepart1folder in the libfolder. It is only available in the libfolder's include_directory path and not propagated to the root folder.
Since the include codepart1.hpp is present in the lib.hpp however you need to have it also available in the project path otherwise you will get missing declaration errors when you build your project.