QtCreator CMake project - how to show all project files - c++

I use QtCreator to open CMake project. Some directories apart from CMakeLists.txt contains only headers files *.h and for those directories QtCreator in the project tree view shows only CMakeLists.txt. How to fix that ? I need to see all project files from QtCreator.

Viewing project as a file system is not a solution at all cause your project editor settings for example would not apply.
And I do not like to add headers to executable target, cause they do not actually belong there. You effectively cripple the project file to work nicely with one particular IDE... not good.
The cleaner option IMHO would be:
FILE(GLOB_RECURSE LibFiles "include/*.hpp")
add_custom_target(headers SOURCES ${LibFiles})
As a bonus you get your includes shown in a separate folder.
(borrowed from https://cmake.org/pipermail/cmake/2012-August/051811.html)

I would suggest you switching your project view to File System. This would display a view where you could view any file you want:
You might want to split your project view into two by clicking the second to right button, if you still desire the Projects mode.

You should add header files to the list of your source files: add_executable(${Executable} ${Sources} ${headers})
You can use GLOB_RECURSE if have many header files:
FILE(GLOB_RECURSE INC_ALL "headers/*.h")
include_directories("headers")
add_executable(main "main.cpp" ${INC_ALL})
Don't forget to run CMake again (Build>Run Cmake).

Based on another thread asking the same question, I found a generic solution to the problem, working for all IDE's (at least tested with QtCreator and Visual Studio).
Can be found here : https://github.com/sauter-hq/cmake-ide-support
# \brief adds for the given target a fake executable targets which allows all
# headers and symbols to be shown in IDEs.
# \param target_name Which target properties should be added to the IDE support target.
function(target_add_ide_support target_name)
if (NOT TARGET ${target_name})
message(FATAL_ERROR "No target defined with name ${target_name}, cannot target_add_ide_support it.")
endif()
set (target_for_ide "${target_name}_ide_support")
if (NOT TARGET ${target_for_ide})
file(GLOB_RECURSE target_for_ide_srcs "*.h" "*.hpp" "*.hxx" "*.c" "*.cpp" "*.cxx")
add_executable(${target_for_ide} ${target_for_ide_srcs})
set_target_properties(${target_for_ide} PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
endif()
get_target_property(dirs ${target_name} INCLUDE_DIRECTORIES)
target_include_directories(${target_for_ide} PRIVATE ${dirs})
endfunction(target_add_ide_support)
Usage is then for any targets in the CMakeLists, add the following call (can be made in top-most CMakeLists.txt after all add_subdirectory :
include(add_ide_support.cmake)
target_add_ide_support(some-target)

You can try CMakeProjectManager2. Code to display all files already propagated to upstream as a proof of concept. Concept applied but code can't be applied as-is for some reasons. So, simple wait feature in upstream.

There is a closed bug report about this issue: CMake project shows no files.
In that particular case the issue was with the chosen generator, Ninja, which is not well supported by QtCreator.
Please change that to "CodeBlocks - Ninja". Creator needs the CodeBlocks extra generator.
You should see a warning about that when hovering the kit (and the kit should have a warning icon in front of its name).
Using CodeBlocks - Ninja solved it for me too.
Overall, it may help to try up a few generators...

Related

cmake + VS = "Microsoft.VisualStudio.ProjectSystem.References.UnresolvedBuildDependencyProjectReference"

I have a very simple CMake solution with one shared library and one executable.
CMakeLists.txt:
cmake_minimum_required(VERSION 3.24)
project(Test)
add_subdirectory(A)
add_subdirectory(B)
A/CMakeLists.txt:
cmake_minimum_required(VERSION 3.24)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(A)
file(GLOB_RECURSE Hdr CONFIGURE_DEPENDS inc/*)
file(GLOB_RECURSE Src CONFIGURE_DEPENDS src/*)
add_library(${PROJECT_NAME} SHARED ${Hdr} ${Src})
target_include_directories(${PROJECT_NAME} BEFORE PUBLIC inc PRIVATE src)
set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY PUBLIC_HEADER ${Hdr})
A/CMakeLists.txt:
cmake_minimum_required(VERSION 3.24)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(B)
file(GLOB_RECURSE Src CONFIGURE_DEPENDS src/*)
add_executable(${PROJECT_NAME} ${Hdr} ${Src})
target_include_directories(${PROJECT_NAME} BEFORE PUBLIC inc PRIVATE src)
target_link_libraries(${PROJECT_NAME} PRIVATE A)
I use all these to generate a VS2022 solution and open it:
cmake.exe -S . -B tmp
start tmp\Test.sln
The CMake target "A" seems to be taken into consideration because I see the public headers folder (A/inc) amongst "Additional Include Directories" of VS project "B".
When I navigate in VS to B/References I see a reference to project "A" as expected:
but when I double-click it or try to see its properties , I get:
"Microsoft.VisualStudio.ProjectSystem.References.UnresolvedBuildDependencyProjectReference"
Is there a CMake+VS bug? or I do something wrong?
NOTE: if I create the entire solution by hand from Visual Studio (without CMake), it works fine!
I'm using CMake 3.24.1 and VS2019 and I'm facing the same problem. From what I see on my PC, I can conclude it's certainly not a CMake issue. That's because, after having used CMake to generate my VS Solution, I'm able to get rid of the problem by simply modifying the vcxproj file(s) inside my solution. However, there still is one thing I don't understand yet and what makes me to suspect VS having some kind of problem. Here is what I see/do.
My CMake generated solution contains one console application that depends on a number of static library projects: the projects are added to the application's References section. Now, when I double click on one of them I get the following message:
The Full Path property of the referenced project inside the Properties pane shows the same message.
To fix this I open the console application's vcxproj file and look for the following entry:
I remove the complete ProjectReferences element for each configuration, save the vcxproj file and restart my solution. In my case the problem is then solved: no more annoying message and the Full path property resolves to a valid path. But ...
Since I removed this ProjectReferences element the Link Library Dependencies property now defaults to Yes. I can verify this by opening the Property window and check the proper field. It shows Yes.
Now, I my case CMake generated a solution in which LinkLibraryDependencies was set to false. Therefore, I again open my console application's Property pane and set the Link Library Dependencies property back to false. I close the Property window and try rebuilding my project: no problem. Running the application: no problem.
When, after updating the Link Library Dependencies property with false inside the Property pane, I save my project and then open the vcxproj file using a text editor, I notice the ProjectReferences element has been added again. It's set to false. That is as expected. But, when close and I re-open the solution the initial problem is back again. However, when I change the ProjectReferences property value from false to true inside the vcxproj file using a text editor, the problem stays away after opening the solution!!
Based on the experience with my VS Solution, I come to the following conclusion:
I can get rid of the problem by removing the complete ProjectReferences element from the vcxproj file (use text editor) and then re-open the solution. But then the Link Library Dependencies property defaults to Yes
I can then change the Link Library Dependencies property back and forth to Yes and No without the problem shows up again. (Note: what I find strange is that the vcxproj file is not updated when I modify some properties and close the Property window.
When the application's project is saved to disk (vcxproj file gets updated), re-opening the solution will bring back the problem but only in case the Link Library Dependencies property was saved as false.
Maybe I overlook something, but this looks as a VS problem to me. Not a showstopper but annoying it is.

CMake not building a library when added as a subdirectory

I added the xgboost library as a git submodule of my project and I'm trying to add it to cmake as a subdirectory. Unfortunately it's not working. A simple hello world project with the following CMakeLists.txt replicates the error that I'm getting.
cmake_minimum_required(VERSION 3.2)
project(foo)
add_subdirectory(xgboost)
add_executable(${PROJECT_NAME} foo.cpp)
target_link_libraries(${PROJECT_NAME} xgboost)
After building the library there is nothing in the xgboost/lib directory so I get the following error.
clang: error: no such file or directory:
'/Users/.../myproject/xgboost/lib/libxgboost.dylib'
I think that the problem is generated in their CMakeLists file since they have two different targets. Maybe cmake is choosing the wrong target but I'm not familiar enough with cmake to figure it out. The following code is from xgboost's CMakeLists.
# Executable
add_executable(runxgboost $<TARGET_OBJECTS:objxgboost> src/cli_main.cc)
set_target_properties(runxgboost PROPERTIES
OUTPUT_NAME xgboost
)
set_output_directory(runxgboost ${PROJECT_SOURCE_DIR})
target_link_libraries(runxgboost ${LINK_LIBRARIES})
# Shared library
add_library(xgboost SHARED $<TARGET_OBJECTS:objxgboost>)
target_link_libraries(xgboost ${LINK_LIBRARIES})
set_output_directory(xgboost ${PROJECT_SOURCE_DIR}/lib)
#Ensure these two targets do not build simultaneously, as they produce outputs with conflicting names
add_dependencies(xgboost runxgboost)
My questions in order of importance are:
Is there any way to fix it without modifying xgboost's CMakeLists.txt file?
Is it reasonable to try to add xgboost to my project as a git submodule?
Is there any reason cmake is not instructing to build the library?
Note: There were several edits to this question since I tried to narrow down the problem and to provide more information.
(I would love to ask for few things beforehand in the comment section, but I have too low reputation to do so, so I will just give it a shot ;))
I have few suspects, and one of them is ${CMAKE_SOURCE_DIR} of the submodule's root CMakeLists.txt. Although the paths are set properly when you run that CMakeLists.txt alone, cmake gets confused the moment you add it as your subdirectory. Have you looked into another directories for your output binaries?
First I would suggest testing this hypothesis, and then I would suggest writing similar, but separate CMakeLists.txt file for xgboost library, and then substitute it in the project temporarily. Unfortunately the CMakeLists.txt filename is hardcoded and there is no possibility to have two files of that kind in one directory; so it seems that the answer to 1) is, that you rather have to change the file.
For the 2): as long as it does not require huge additional logic in your CMakeLists.txt, it makes sense. Other viable option is to create an install target, which you can use to install your xgboost library locally (using CMAKE_INSTALL_PREFIX(doc) variable), and then add the installation path to your CMAKE_LIBRARY_PATH(doc).

How to make include directories added with AUTOUIC available to downstream targets?

I have a problem with CMake's AUTOUIC option in my qt project.
I have a target that has *.ui qt-form files and changed it to use the AUTOUIC option to automatically generate the corresponding ui_*.h files and add their location to the target's include directory.
The problem is, that I inlcude the generated "ui_*.h" file in a header of the target, which is then included in another test-target. The test-target however does not have the directory with the generated files set to its include directories and therefore will not find the ui_*.h file.
So is there any way to get the directory of the generated files so I can add it to the INTERFACE_INCLUDE_DIRECTORIES of my first target. When I do this using hardcoded names It solves my compile errors, but I would rather do this by getting that directory from some target property or so. I failed with that because the AUTOUIC include dirs seem to be added only after processing all the CMakeLists files.
Btw., I am currently using CMake 3.8.2, but updating to 3.9 is an option if the problem has been solved there.
From CMake version 3.9 onwards you can use the following snippet to add the autogenerated headers to a target's build interface include directories:
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(_isMultiConfig)
set(AUTOGEN_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_autogen/include_$<CONFIG>)
else()
set(AUTOGEN_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_autogen/include)
endif()
target_include_directories(${TARGET_NAME} INTERFACE
$<BUILD_INTERFACE:${AUTOGEN_INCLUDE_DIR}>
)
See:
Use GENERATOR_IS_MULTI_CONFIG to detect multi-config generators
AUTOUIC
GENERATOR_IS_MULTI_CONFIG
AUTOGEN_BUILD_DIR
I have the same issue - it looks like a bug in CMAKE (I'm using version 3.10 rc5)
and have opened a bug report to CMAKE here: https://gitlab.kitware.com/cmake/cmake/issues/17456
In the meantime you can copy the autgenerated header files to your project source directory by using the following commands after autouic has been run.
SET(AUTOGEN_BUILD_DIR "${CMAKE_BUILD_DIR}/<project>_autogen/include_${CONFIG}")
file(COPY "${AUTOGEN_BUILD_DIR}/ui_xxxx.h" DESTINATION "${CMAKE_SOURCE_DIR}/headers")
where ${CONFIG} is the type of build (Debug/Release)

CMake and VisualStudio: Group files in solution explorer

To finish a long coding session on a project, I wanted to test if my CPP project is compilable on an arrangement of OS'es.
I've been working in Win10 all the time. Compiles fine.
I've tried a Raspberry Pi. Compiles fine.
I re-download a seperate copy of my project to a Win10 client, run cmake-gui, and open the project: My folder structure in the solution explorer all gone.
So I started digging around, and apparently this structure is kept in CMakeLists.txt with the command source_group. So I start adding more source_groupings to my cmake lists, and for some reason my groupings won't take.
Example:
source_group("game\\entitysystem" FILES ${entitysystem_SRC}) // Existing grouping
source_group("game\\entitysystem\\components" FILES ${components_SRC}) // My new grouping
My glob would be this:
file(GLOB components_SRC
"game/components/*.h"
"game/components/*.cpp"
)
file(GLOB entitysystem_SRC
"game/entitysystem/*.h"
"game/entitysystem/*.cpp"
)
I do believe my GLOB's are correct since the new project-clone compiles fine. It's just that every part of the new structure in Visual Studio's Solution Explorer seems lost. Yes, I have cleared Cmake's cache and regenerated the project. Doesn't change it.
Original structure:
Cloned project structure:
Edit:
I did make a mistake in my source_group as in that it should not put components beneath entitysystem, but still, why aren't there any filters created in Visual Studio?
First, make sure you are setting set_property(GLOBAL PROPERTY USE_FOLDERS ON).
Second, it is not recommended to use GLOB to collect a list of source files. From the file(GLOB documentation:
We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
The recommended way to list project files is to add them by hand to CMakeLists.txt.
If you still want to GLOB, it looks like you want to mirror the directory structure in your source tree. You can use a macro such as this every place you define a library or executable to automatically sort them for you:
foreach(FILE ${SRCS})
# Get the directory of the source file
get_filename_component(PARENT_DIR "${FILE}" DIRECTORY)
# Remove common directory prefix to make the group
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "" GROUP "${PARENT_DIR}")
# Make sure we are using windows slashes
string(REPLACE "/" "\\" GROUP "${GROUP}")
# Group into "Source Files" and "Header Files"
if ("${FILE}" MATCHES ".*\\.cpp")
set(GROUP "Source Files${GROUP}")
elseif("${FILE}" MATCHES ".*\\.h")
set(GROUP "Header Files${GROUP}")
endif()
source_group("${GROUP}" FILES "${FILE}")
endforeach()

C++ CMake (add non-built files)

I am using cmake to configure my project. I visualize project's files using qtcreator which read the CMakeLists.txt.
I have a few text files (non-code: config files, log, ..) and I would like to add them to my cmake project without (of course) compiling/linking them. Is it possible ?
The main goal it to open them automatically in the tree of my project with qtcreator and edit them ...
Thanks for help.
You should be able to just add them to your list of sources in whichever add_executable or add_library call is appropriate and they will appear in the IDE.
I believe CMake uses the files' extensions to determine if they are actual source files, so if yours have extensions like ".txt" or ".log" they won't be compiled.
Instead of adding files which are not directly needed to build your library or executable, you can create a custom target to make these files appear in you IDE:
add_custom_target(myapp-doc
SOURCES readme.txt)
Hi I've created this kind of function:
cmake_minimum_required(VERSION 3.5)
# cmake_parse_arguments needs cmake 3.5
##
# This function always adds sources to target, but when "WHEN" condition is not meet
# source is excluded from build process.
# This doesn't break build, but source is always visible for the project, what is
# very handy when working with muti-platform project with sources needed
# only for specific platform
#
# Usage:
# target_optional_sources(WHEN <condition>
# TARGET <target>
# <INTERFACE|PUBLIC|PRIVATE> [items2...]
# [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
##
function(target_optional_sources)
set(options OPTIONAL "")
set(oneValueArgs WHEN TARGET)
set(multiValueArgs PUBLIC PRIVATE INTERFACE)
cmake_parse_arguments(target_optional_sources
"${options}" "${oneValueArgs}" "${multiValueArgs}"
${ARGN})
target_sources(${target_optional_sources_TARGET}
PUBLIC ${target_optional_sources_PUBLIC}
PRIVATE ${target_optional_sources_PRIVATE}
INTERFACE ${target_optional_sources_INTERFACE})
if (NOT ${target_optional_sources_WHEN})
set_source_files_properties(${target_optional_sources_PUBLIC}
PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties(${target_optional_sources_PRIVATE}
PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties(${target_optional_sources_INTERFACE}
PROPERTIES HEADER_FILE_ONLY TRUE)
endif(NOT ${target_optional_sources_WHEN})
endfunction(target_optional_sources)
On one hand it works as it is desired, on other hand some error is reported, so still working on that. Issu turn out to be problem how I used the function not how it is written. Now it works perfectly.