I have the following project structure:
project/
├─ CMakeLists.txt
├─ src/
├─ libraries/
│ ├─ directxtk/
│ │ ├─ CMakeLists.txt
│ ├─ zlib/
│ │ ├─ CMakeLists.txt
project/CMakeLists.txt is my main executable. I want to utilize zlib in it.
In this CMakeLists.txt, i have the following lines:
target_include_directories(Project PUBLIC ${EXTERNAL_HEADERS_DIR})
add_subdirectory("${LINK_LIBRARY_DIR}/zlib")
add_subdirectory("${LINK_LIBRARY_DIR}/directxtk")
target_link_libraries(Project LINK_PUBLIC zlib)
target_link_libraries(Project LINK_PUBLIC DirectXTK)
EXTERNAL_HEADERS_DIR and LINK_LIBRARY_DIR both point to Project/Libraries.
I include zlib the following way: #include <zlib/zlib.h>
When I try to build and run now, I receive the following compile error:
...\Project\Libraries\zlib/zlib.h(34): fatal error C1083: Cannot open include file: 'zconf.h': No such file or directory
apparently, CMake seems to rename zconf.h to zconf.h.included!?
How can I properly build this whole thing?
Edit: I have copy&paste'd zlib/CMakeLists.txt from the public website of zlib
Related
I have a project with structure like this:
project/
├─ src/
│ ├─ main.cpp
│ ├─ CMakeLists.txt
├─ lib/
│ ├─ libapi.so
├─ CMakeLists.txt
├─ dep/
│ ├─ api/
│ │ ├─ api_types.h
In the main CMakeLists I have:
add_subdirectory(dep)
add_executable("my_${PROJECT_NAME}")
add_subdirectory(src)
And in CMakeLists inside src folder:
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
add_library(api SHARED IMPORTED)
set_property(TARGET api PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/lib/libapi.so")
target_sources("my_${PROJECT_NAME}" PRIVATE main.cpp)
In main.cpp I do #include <api_types.h> but I get this error during compile:
api_types.h: No such file or directory
How can I fix it?
First - add_subdirectory in fact just looks for CMakeLists.txt in
the specified directory to apply the sub-set of the rules to the
parent project. If the specified folder doesn't contain any
CMakeLists.txt this command does nothing (i.e. the command
add_subdirectory(dep)).
Second - target_include_directories expects a target object to link against (not the project name). Assuming ${PROJECT_NAME} is not a name of any of your targets (and the code given in the question reveals only two targets my_${PROJECT_NAME} and api) the command target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) does nothing sensible.
Last - you don't specify path to your actual headers anywhere. CMAKE_CURRENT_SOURCE_DIR refers to the current folder CMakeLists.txt is located in. You should specify path to the folder the headers are located in.
Putting all the said info together, the desired content for the top-level CMakeLists.txt should be something like that:
cmake_minimum_required(VERSION 3.20)
set(PROJECT_NAME Hello)
project(${PROJECT_NAME})
add_executable(my_${PROJECT_NAME})
add_subdirectory(src)
And for src's file it's apparently something like that:
target_include_directories(my_${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/dep/api)
target_sources(my_${PROJECT_NAME} PRIVATE main.cpp)
This solution, however, doesn't resolve another mistake in your code - the CMake files you provided don't link the library itself to the executable target. However this is not the question asked, and with respect to the members of the community, I suggest referring to answers to another related question here.
target_include_directories requires your executable as target, in this case my_${PROJECT_NAME}.
You can try
target_include_directories(my_${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
As alternative I would recommend following structure
project/
├─ src/
│ ├─ main.cpp
├─ lib/
│ ├─ libapi.so
├─ CMakeLists.txt
├─ include/
│ ├─ api/
│ │ ├─ api_types.h
with following CMakeList.txt
add_executable(my_${PROJECT_NAME} src/main.cpp)
target_include_directories(my_${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
link_directories(${CMAKE_SOURCE_DIR}/lib)
target_link_libraries(my_${PROJECT_NAME} libapi)
I have a repository with 2 Projects, which both link a single (self-made) library which is also contained in the repository. I also include some dependencies, which both projects use.
The project structure is as follows:
repo/
├─ dependencies/
│ ├─ audeo/
│ ├─ argparse/
│ ├─ json
├─ my-library/
│ ├─ CMakeLists.txt
│ ├─ ...
├─ projet2/
│ ├─ CMakeLists.txt
│ ├─ ...
├─ projet1/
│ ├─ CMakeLists.txt
│ ├─ ...
├─ CMakeLists.txt
I don't know how to utilize this. I already tried to set up a project, but I ran into numerous problems, which I don't want to further go into detail about.
My question is whether there are examples of this kind of project structure or if you have good practice advice, or if this problem has a common name that I can research.
Edit:
I will post my CMake files and the link to the current state of the source code (Disclaimer: the second project is not already included).
Content of repo/CMakeLists.txt:
cmake_minimum_required(VERSION 3.11)
project(root)
set(CMAKE_CXX_STANDARD 20)
# dependencies
add_subdirectory(dependencies/dep1)
add_subdirectory(dependencies/dep2)
add_subdirectory(dependencies/dep3)
# sub-projects
add_subdirectory(my-library)
add_subdirectory(project1)
add_subdirectory(project2)
Content of my-library/CMakeLists.txt:
cmake_minimum_required(VERSION 3.11)
project(my-library)
set(CMAKE_CXX_STANDARD 20)
add_library(my-library STATIC
src/World.cpp include/World.h
include/Player.h
include/Position.h
include/Audio/Effect.h
include/Audio/Music.h
include/Audio/Audio.h)
target_link_libraries(my-library PRIVATE
dep1::dep1
dep2::dep2)
Content of projet1/CMakeLists.txt:
cmake_minimum_required(VERSION 3.11)
project(project1)
set(CMAKE_CXX_STANDARD 20)
add_executable(project1 main.cpp)
target_link_libraries(project1 PRIVATE
dep1::dep1
dep3::dep3
)
Content of projet2/CMakeLists.txt:
cmake_minimum_required(VERSION 3.11)
project(project2)
set(CMAKE_CXX_STANDARD 20)
add_executable(project2 main.cpp)
target_link_libraries(project2 PRIVATE
dep2::dep2
)
Since my source code is open source anyway I will post the link to my repository. But please note that the names of the projects may differ as well as the structure.
Problem
My Problem is, that I cannot include one dependency (warning! this is a translation):
fatal error: dep1/dep1.hpp: file or directory not found
11 | #include <dep1/dep1.hpp>
And I want to be able to include my library in Angle-bracket form.
I have a project where I need to run one application on multiple boards. To do this I have two exectuables that share a main.c, but are compiled with a different board.c. The directory tree is as follows:
CMakeLists.txt
src/
├─ board/
│ ├─ board_a/
│ │ ├─ board.c
| | ├─ CMakeLists.txt
│ ├─ board_b/
│ │ ├─ board.c
| | ├─ CMakeLists.txt
├─ app/
│ ├─ main.c
├─ lib/
│ ├─ somelib/
│ │ ├─ somelib.h
│ │ ├─ somelib.c
In an attempt to make the root CMakeLists.txt smaller and more maintainable, I've created a CMakeLists.txt for both boards, and would like to compile each board as an object library for the main executable in the root CMakeLists.txt to add_subdirectory on and link in.
My problem is that board.c (as well as main.c) depends on somelib. How can I add this dependency to the subdirectory CMakeLists.txt? Is there a way I can do that without hard-coding a path to somelib? My feeling is that I should create a CMakeLists.txt in somelib, and I feel this would be easy if I were handling the library linking from the root CMakeLists.txt, but my confusion is that board is adjacent to lib. I'm relatively new to CMake and am not sure how to best structure these dependencies.
My problem is that board.c (as well as main.c) depends on somelib. How can I add this dependency to the subdirectory CMakeLists.txt? Is there a way I can do that without hard-coding a path to somelib? My feeling is that I should create a CMakeLists.txt in somelib, and I feel this would be easy if I were handling the library linking from the root CMakeLists.txt, but my confusion is that board is adjacent to lib. I'm relatively new to CMake and am not sure how to best structure these dependencies.
This is very straightforward start by linking each board_<X> to somelib's target.
# in each board_<X>/CMakeLists.txt
add_library(board_<X> OBJECT ...)
target_link_libraries(board_<X> PUBLIC proj::somelib)
then create the target for somelib:
# src/lib/somelib/CMakeLists.txt
add_library(somelib somelib.c)
add_library(proj::somelib ALIAS somelib)
target_include_directories(
somelib PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
As long as the top-level CMakeLists.txt includes these subdirectories via add_subdirectory (multiple levels is fine), then other targets can #include <somelib.h> and CMake will handle linking.
I have a problem building my Qt5 project via cmake.
I run the command cmake .. && make from the directory build and I receive the following error:
/usr/bin/ld: cannot find -lengine-lib
collect2: error: ld returned 1 exit status
make[2]: *** [src/CMakeFiles/blacklist-engine-cli.dir/build.make:102: src/blacklist-engine-cli] Error 1
make[1]: *** [CMakeFiles/Makefile2:117: src/CMakeFiles/blacklist-engine-cli.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
I have searched this topic briefly, however when I ran this project without Qt5Sql, using only Qt5Core I have no problem at all building the project. In order to build the project without Qt5Sql I just have to remove the db folder, and delete lines referring to that in my other CMakeLists.txt files. My question is:
Why does it work if I want to include only Qt5Core, and why does it not work when I also include Qt5Sql? What am I doing wrong including Qt5Sql?
Please do not include answers related to QtCreator, or Qt installation errors. I have checked my Qt installation folder, and I have Qt5Core and Qt5Sql on the same directory level installed.
I am using Ubuntu 20.04, cmake version 3.16.3, Qt version 5.12.8
ls /usr/lib/x86_64-linux-gnu/cmake
Qt5 Qt5Core Qt5Gui Qt5OpenGL Qt5PrintSupport Qt5Test Qt5Xml
Qt5Concurrent Qt5DBus Qt5Network Qt5OpenGLExtensions Qt5Sql Qt5Widgets
I have the following structure in my project:
root
├── CMakeModules
│ └── Qt.cmake
├── build
├── src
│ ├── db
│ │ ├── dbmanager.cpp
│ │ ├── dbmanager.h
│ │ └── CMakeLists.txt
│ ├── engine
│ │ ├── scanner.cpp
│ │ ├── scanner.h
│ │ └── CMakeLists.txt
│ ├── CMakeLists.txt
│ └── main.cpp
└── CMakeLists.txt
CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(blacklist-engine)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules)
add_subdirectory(src)
CMakeModules/Qt.cmake:
set(CMAKE_AUTOMOC ON)
find_package(Qt5 REQUIRED COMPONENTS Core Sql)
src/CMakeLists.txt:
include(Qt)
add_subdirectory(
db
engine
)
add_executable(blacklist-engine-cli main.cpp)
target_link_libraries(
blacklist-engine-cli
Qt5::Core
Qt5::Sql
engine-lib
db-lib
)
src/main.cpp:
#include <QtCore>
#include "db/dbmanager.h"
#include "engine/scanner.h"
...
src/db/CMakeLists.txt (updated):
set (db-lib-source
dbmanager.h
dbmanager.cpp
)
add_library(db-lib ${db-lib-source})
target_link_libraries(
db-lib
Qt5::Sql
)
src/db/dbmanager.h:
#include <QtSql/QSqlDatabase>
...
src/db/dbmanager.cpp:
#include "dbmanager.h"
#include <QtSql/QSqlQuery>
...
src/engine/CMakeLists.txt:
set(engine-lib-source
scanner.h
scanner.cpp
)
add_library(engine-lib ${engine-lib-source})
src/engine/scanner.h:
#include <QtCore>
...
src/engine/scanner.cpp:
#include "scanner.h"
...
The reason for the error is because engine-lib is never built, and its CMake file is never even processed. The offending line in your CMake file is this one:
add_subdirectory(
db
engine
)
When using add_subdirectory in this manner, the second argument becomes the binary directory for the generated content related to db. As a result, you may notice that CMake placed some build artifacts in your src/engine directory, which is probably not what you want.
To fix this, you must call add_subdirectory consecutive times for including multiple sub-directories.
add_subdirectory(db)
add_subdirectory(engine)
I'm trying to learn CMake, but I can't get to grips with the tutorials that are available.
Let's say my project has the structure below, and I want to make my_lib available through its CMakeLists file and use it in my main.cpp, what would my CMakeLists files look like?
├── CMakeLists.txt
├── externals
│ └── my_lib
│ └── src
│ ├── CMakeLists.txt
│ ├── MyClass.h
│ └── MyClass.cpp
└── main.cpp
Should I use include_directories or add_subdirectory?
To match the directory structure you indicated, your CMakeLists.txt files could look like this:
/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(Main)
add_subdirectory(externals/my_lib/src)
add_executable(my_main main.cpp)
target_link_libraries(my_main my_lib)
/externals/my_lib/src/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(MyLib)
add_library(my_lib MyClass.cpp MyClass.h)
target_include_directories(my_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
Using PUBLIC in the target_include_directories call means that not only does your library have this as an "include path", but so does any target linking to it.
The downside with this setup however is that you're also going to expose any internal headers of my_lib to consuming targets too. Say you also have an "Internal.h" as part of my_lib which you don't want to expose. You can do this by moving the intentionally-public headers into a separate folder, e.g. "include":
├── CMakeLists.txt
├── externals
│ └── my_lib
│ ├── CMakeLists.txt
│ ├── include
│ │ └── MyClass.h
│ └── src
│ ├── Internal.h
│ └── MyClass.cpp
└── main.cpp
Your top-level CMakeLists.txt wouldn't change, but /externals/my_lib/CMakeLists.txt (which has moved up a level) now reads:
cmake_minimum_required(VERSION 3.0)
project(MyLib)
add_library(my_lib src/MyClass.cpp src/Internal.h include/MyClass.h)
target_include_directories(my_lib
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
)
Now, since your library's "src" folder is PRIVATE to my_lib, main.cpp won't be able to #include "Internal.h".