I'm attempting to learn CMake by building a small application using CMake and SFML in Visual Studio. However, I am having difficulties pointing my .hpp files to where my SFML headers are. It seems like CMake doesn't consider header files as targets, so it is not adding these external include directories to my headers. Therefore, I can't use the SFML modules in my headers to define classes and whatnot. Here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Euclid)
set(SFML_INCLUDE_DIR "C:\\Program Files (x86)\\SFML\\include")
set(SFML_LIBRARY_DIR "C:\\Program Files (x86)\\SFML\\lib")
set(SRC
${PROJECT_SOURCE_DIR}/Block.cpp
${PROJECT_SOURCE_DIR}/Block.hpp
${PROJECT_SOURCE_DIR}/Main.cpp
)
add_executable(Main ${SRC})
target_include_directories(Main PUBLIC ${SFML_INCLUDE_DIR})
target_link_libraries(Main PUBLIC ${SFML_LIBRARY_DIR})
Related
I've tried looking for an answer to this question. There are similar questions but none that answer mine.
I am trying to create a library that depends on a couple other external libraries. I have the external libraries as git submodules and compile them myself in CMake using add_subdirectory followed by target_link_library.
After doing that, I am able to use the external libraries and include their header files in any source file in my library that I have added using target_sources and also in any header file that at least one of these source files include.
For example, I have an external library glm and call target_sources(myLib PRIVATE Application.cpp) in my library. The header files in my library are added to the project using target_include_directories.
Now, I can do #include <glm/glm.hpp> in the Application.cpp file with no problems.
I also have an Application.hpp file that is included in the Application.cpp file. Because it is included, that allows me to do #include <glm/glm.hpp> in the Application.hpp file as well.
However, now I also have a Core.hpp file without a corresponding Core.cpp file. Because the Core.hpp file is not included in any source files, doing #include <glm/glm.hpp> throws an error that the file cannot be found.
This is my root CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(Ivory)
set(CMAKE_CXX_STANDARD 20)
add_library(${PROJECT_NAME} SHARED)
# Determine compiler platform (x32 or x64)
math(EXPR PLATFORM_BITS "8*${CMAKE_SIZEOF_VOID_P}")
set(PLATFORM "x${PLATFORM_BITS}")
# Determine target build platform
target_compile_definitions(${PROJECT_NAME}
PUBLIC
IVORY_WINDOWS
PRIVATE
IVORY_BUILD_DLL
)
# Set output directory
set(OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${CMAKE_SYSTEM_NAME}-${CMAKE_BUILD_TYPE}-${PLATFORM})
# Subdirectories
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(executables)
target_include_directories(${PROJECT_NAME} PUBLIC include)
# External Libraries #
set(BUILD_SHARED_LIBS OFF)
# GLM
add_subdirectory(lib/glm)
target_link_libraries(${PROJECT_NAME} PRIVATE glm)
# GLEW
add_subdirectory(lib/glew)
target_link_libraries(${PROJECT_NAME} PRIVATE libglew_static)
# SFML
add_subdirectory(lib/SFML)
target_link_libraries(${PROJECT_NAME} PRIVATE sfml-window sfml-audio)
# SPDLOG
add_subdirectory(lib/spdlog)
target_link_libraries(${PROJECT_NAME} PRIVATE spdlog)
# MinGW
target_link_libraries(${PROJECT_NAME} PRIVATE -static)
# Output Location
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY})
This is the src CMakeLists.txt:
target_sources(${PROJECT_NAME}
PRIVATE
Application.cpp
)
I am using CLion on Windows 10 with MinGW 7.3 compiler (64 bit).
What am I doing wrong?
If the Core.hpp header is meant to be included by clients and glm headers are called from this header the glm dependency in the target_link_libraries command must be PUBLIC not PRIVATE.
For the CMake documentation see here. For a more detailed explanation of the PUBLIC, PRIVATE, and INTERFACE keywords with examples see here.
File Structure:
CMakeLists.txt
src/
evolution.cpp
evolution.h
main.cpp
helpers/
disposable.h
engine/
game.h
game.cpp
CMakeLists.txt:
cmake_minimum_required(VERSION 3.17)
project(evolution)
add_library(helpers
src/helpers/disposable.h)
set_target_properties(helpers PROPERTIES LINKER_LANGUAGE CXX)
add_library(engine
src/engine/game.h
src/engine/game.cpp)
add_executable(evolution src/main.cpp)
target_link_libraries(evolution engine helpers)
The Game class (game.h) inherits from Diposable (disposable.h), but I am unable to build the project with a simple #include "disposable.h" in the game.h file.
How do I configure CMake so that the engine library can see the helpers library?
CMake error:
[ 20%] Building CXX object CMakeFiles/engine.dir/src/engine/game.cpp.o
In file included from /home/shane/projects/evolution/src/engine/game.cpp:1:
/home/shane/projects/evolution/src/engine/game.h:4:10: fatal error: disposable.h: No such file or directory
4 | #include "disposable.h"
| ^~~~~~~~~~~~~~
compilation terminated.
Adding headers to a project really only helps IDEs find the headers. It doesn't change the build instructions. Instead you need to use target_include_directories() with a INTERFACE or PUBLIC section to get any libraries that link to this to add the include directories to itself.
Your helpers library is more of an interface for now. To get this minimum example working do this:
cmake_minimum_required(VERSION 3.17)
project(evolution)
add_library(helpers INTERFACE) # INTERFACE is good for header-only libraries
target_include_directories(helpers INTERFACE src/helpers)
add_library(engine
src/engine/game.h
src/engine/game.cpp)
add_executable(evolution src/main.cpp)
target_link_libraries(evolution engine helpers)
Now include with angular brackets: #include <disposable.h>
If your library becomes more complicated (more than just header files), then replace INTERFACE in add_library with your sources. To make include directories available to the helpers library and any library that links to it, change INTERFACE to PUBLIC in target_include_directories.
cmake_minimum_required(VERSION 3.17)
project(evolution)
add_library(helpers src/helpers/helper.cpp)
target_include_directories(helpers PUBLIC src/helpers)
add_library(engine
src/engine/game.h
src/engine/game.cpp)
add_executable(evolution src/main.cpp)
target_link_libraries(evolution engine helpers)
I'm using the submodule GitHub inside my project and now I want to use the target_include_directories for including the file inside the my project class
This is my cmake configuration
cmake_minimum_required(VERSION 3.9)
project(SpyCBlock)
set(CMAKE_CXX_STANDARD 14)
#bitcoin rpc lib
find_library(bitcoinapi 0.3 REQUIRED)
target_include_directories(rapidjson PUBLIC include/rapidjson/include)
target_include_directories(spycblockrpc PUBLIC include/spycblockrpc)
target_include_directories(btccryptography PUBLIC include/bitcoin-cryptography-library)
add_executable(
${PROJECT_NAME}
#other inclusion file cpp
#cpp-properties file include
include/cpp-properties/src/Properties.cpp
include/cpp-properties/src/PropertiesParser.cpp
include/cpp-properties/src/PropertiesUtils.cpp
#include bitcoin-cryptography-library
include/bitcoin-cryptography-library/cpp/Sha256.cpp
include/bitcoin-cryptography-library/cpp/Sha256Hash.cpp
include/bitcoin-cryptography-library/cpp/Utils.cpp
#include spycblocrpc
include/spycblockrpc/core/graph/TransactionGraph.cpp
include/spycblockrpc/core/graph/WrapperInformations.cpp
include/spycblockrpc/ConfiguratorSingleton.cpp
include/spycblockrpc/commands/DecodeScriptCommand.cpp
include/spycblockrpc/commands/DecodeRawTransaction.cpp
include/spycblockrpc/commands/HeightBlockchainCommand.cpp
include/spycblockrpc/commands/DecodeBlockAtIndexCommand.cpp
)
#bitcoin rpc lib
target_link_libraries(SpyCBlockTests bitcoinapi)
target_link_libraries(${PROJECT_NAME} bitcoinapi)
When run CMake I have this error
Starting to parse CMake project.
CMake Error at CMakeLists.txt:20 (target_include_directories):
Cannot specify include directories for target "rapidjson" which is not
built by this project.
CMake Error at CMakeLists.txt:22 (target_include_directories):
Cannot specify include directories for target "spycblockrpc" which is not
built by this project.
CMake Error at CMakeLists.txt:24 (target_include_directories):
Cannot specify include directories for target "btccryptography" which is
not built by this project.
CMake Error at CMakeLists.txt:26 (target_compile_definitions):
Cannot specify compile definitions for target "cppproperties" which is not
built by this project.
I'm new with the C++ and the cmake and I can't understand what I'm wrong
I want to add the solution to this problem, as suggested in the comments, the code has two problems:
target_include_directories(${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/include/rapidjson/include)
The first argument of the target must be the name of the executable, so in this case, is SpyCBlock
The second problem is the definition of the target before the declaration of the target, the target_include_directories(SpyCBlock ...) is defined before the add_executable(${PROJECT_NAME} ...)
A minimal correct example is:
add_executable(
${PROJECT_NAME}
#other inclusion file cpp
#cpp-properties file include
include/cpp-properties/src/Properties.cpp
include/cpp-properties/src/PropertiesParser.cpp
include/cpp-properties/src/PropertiesUtils.cpp
#include bitcoin-cryptography-library
include/bitcoin-cryptography-library/cpp/Sha256.cpp
include/bitcoin-cryptography-library/cpp/Sha256Hash.cpp
include/bitcoin-cryptography-library/cpp/Utils.cpp
#include spycblocrpc
include/spycblockrpc/core/graph/TransactionGraph.cpp
include/spycblockrpc/core/graph/WrapperInformations.cpp
include/spycblockrpc/ConfiguratorSingleton.cpp
include/spycblockrpc/commands/DecodeScriptCommand.cpp
include/spycblockrpc/commands/DecodeRawTransaction.cpp
include/spycblockrpc/commands/HeightBlockchainCommand.cpp
include/spycblockrpc/commands/DecodeBlockAtIndexCommand.cpp
)
target_include_directories(${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/include/rapidjson/include)
Now I can include the library like this <bitcoin-cryptography-library/Sha256.h>.
If I have .h and .cpp files in the directory src, where the .cpp files include the .h files, using these commands in CMake:
aux_source_directory(src SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
And opening that CMake file in Qt Creator, gets all the files (sources + headers) in the list of project files (the file tree on the left by default).
Now, on the other hand, if I put all the .h files in a directory include, and use this:
include_directories(include)
aux_source_directory(src SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
The header files disappear from the project files!
How can I keep the header files in that directory, and still have them listed in Qt Creator's project files?
You shouldn't use aux_source_directory() for your task. That command is for something different. Just list the source files (or put them in a variable).
You shouldn't use include_directory() for defining include directories any more. This command will just populate the -I flag of the compiler. Define a variable with the header files and add that to the executable.
In case you don't want to list every file manually, use file(GLOB ...). But be aware of the caveats mentioned frequently all over the web with using that command.
Afterwards, tell CMake to populate the -I flag only for that executable with the include directory. That way, other targets don't get polluted by includes, they shouldn't use.
set(SOURCES
src/main.cpp
src/whatever.cpp)
set(HEADERS
include/whatever.h)
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC include)
I add my header files always explicit to avoid any surprise.
But on MacOS using QtCreator 4.2.0 and cmake 3.7.1 I can't reproduce your issue.
However I recommend to use following structure to know which files are within project and to trigger update of cmake's data during update of CMakeLists.txt.
In project/CMakeLists.txt:
add_subdirectory(src)
include_directory(include)
add_executable(foo ${SRC_LIST})
In project/src/CMakeLists.txt:
set(SRC_LIST
${SRC_LIST}
${CMAKE_CURRENT_SOURCE_DIR}/a.cpp
${CMAKE_CURRENT_SOURCE_DIR}/b.cpp
PARENT_SCOPE
)
I'm building a cmake based build system for our product. The problem is that Visual Studio project, generated by cmake, doesn't display header files in solution browser.
What I need to add in CMakeList.txt to list header files?
The preferred solution is where no need to list each particular header file.
Solution
Here is a solution I came with:
file(GLOB_RECURSE INCS "*.h")
add_library(myLib ${SRCS} ${INCS})
Thanks
Just add the header files along with the source files:
PROJECT (Test)
ADD_EXECUTABLE(Test test.cpp test.h)
Or using variables:
PROJECT (Test)
SET(SOURCE
test.cpp
)
SET(HEADERS
test.h
)
ADD_EXECUTABLE(Test ${SOURCE} ${HEADERS})
The basic trick to this is to add the header files to one of the targets (either executable or library). This is particularly irritating because cmake already knows all the header file dependencies and should take care of this for us. You can organize it further using the source_group command:
source_group("My Headers" FILES ${MY_HDRS})
Note that you have to do the same thing in Xcode too.
I had the same problem while working at a build system for a Qt project and I came out with this solution, thanks to the other posts on this page. I included a complete example adapted from my makefiles. Hope this helps!
cmake_minimum_required (VERSION 2.6)
project (DemoSolution)
find_package(Qt4 REQUIRED)
include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})
include_directories (../../include/)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
file(GLOB Demo_SOURCES *.cpp)
file(GLOB Demo_HEADERS *.hpp)
file(GLOB Demo_FORMS *.ui)
file(GLOB Demo_RESOURCES resources.qrc)
qt4_wrap_cpp(Demo_MOC ${Demo_HEADERS})
qt4_wrap_ui(Demo_FORMS_HEADERS ${Demo_FORMS})
qt4_add_resources(Demo_RESOURCES_RCC ${Demo_RESOURCES})
source_group("Headers" FILES ${Demo_HEADERS})
source_group("MOC" FILES ${Demo_MOC})
set(QT_USE_QTNETWORK, true)
set(QT_USE_QTSQL, true)
set(QT_USE_QTXML, true)
add_library(Demo SHARED
${Demo_SOURCES}
${Demo_HEADERS}
${Demo_MOC}
${Demo_FORMS_HEADERS}
${Demo_RESOURCES_RCC}
)
target_link_libraries(Demo ${QT_LIBRARIES})
add_definitions(-D_DEMO_EXPORTS)
I know this answer is really late to the game, but in more recent versions of visual studio you can change the view from "CMake Target Mode" to a "Folder View"
In this folder view you will be able to see all of your header files.
To be honest i'd take simply changing the view in Visual Studio over modifying CMake files with Windows specific hacks any day.