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

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.

Related

Qt resources not displaying when building with cmake (windows)

I have a Visual Studio Qt solution that I am moving to Cmake.
Everything is compiling and working fine, except all icons (.png) that I have in *.qrc file are not displayed at all.
My CMakeLists.txt is standard for a Qt project:
...
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(SOURCE_FILES ...)
set(HEADER_FILES ...)
set(UI_FILES ...)
set(RESOURCE_FILES resources/res.qrc)
add_executable(project WIN32 ${SOURCE_FILES} ${HEADER_FILES} ${UI_FILES} ${RESOURCE_FILES})
find_package(Qt5 REQUIRED COMPONENTS ...)
target_link_libraries(project PRIVATE Qt5::Core etc...)
I think that all icons are in fact embedded into .exe, because:
1. If I remove all paths from the qrc file and recompile, the .exe size is decreased by the icons size
2. I checked the qrc_*.cpp generated by AUTORCC and all the images are there.
But when I am iterating over all my resources using this code snippet
QDirIterator it(":", QDirIterator::Subdirectories);
while (it.hasNext()) {
qDebug() << it.next();
}
the icons are NOT there.
I have tried an alternative approach with qt5_add_resources() instead of AUTORCC and the result is the same.
I also have all the iconengines, imageformats, platforms, styles folders on the same path as .exe.
Edit:
Added the whole Cmake part of the project to github.
Considering the discussion we had in your post comment, CMake works as expected and the resources are loaded into your application.
As you mentioned "When I run my app from clion it shows the images. If I copy the exe to a folder with *.dll etc it doesn't.", so either:
Some files are missing when you copy them, you should try to use windeployqt to correctly copy what's needed at runtime
Or the problem comes from the way the qrc is neing loaded, then, I suggest that you debug the content of qrc_*.cpp files (your can debug it after you copied it outside clion) and see why it fails to load the resource
Anyway this looks more like a deployment issue than a configuration/compilation issue.

Cant compile OpenCV Source file with my project

This question is a continuation of one I asked before
I have a project that uses the librealsense library and OpenCV. librealsense works but I cannot include OpenCV in my project for the life of me. There is currently only 1 CPP file and 1 HPP file, this is the cmake file of the root
project(peoplecounting)
add_subdirectory(libs/librealsense-master)
add_subdirectory(libs/opencv-4.3.0)
set(OpenCV_DIR ${CMAKE_BINARY_DIR}/libs/opencv-4.3.0)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable (CMakeRealSense "CMakeRealSense.cpp" "CMakeRealSense.h")
find_library(realsense2 HINTS libs/librealsense-master)
find_library(opencv HINTS ${CMAKE_BINARY_DIR}/libs/opencv-4.3.0)
target_link_libraries(CMakeRealSense ${OpenCV_LIBS} realsense2)
I have both source files in a libs folder(so directory would look like root/libs/opencv-4.3.0). I am new to cmake so I just might be missing something but its driving me nuts
Some extra notes
1, OpenCV does build the libs when I can build the project, if I remove any include from my self written code it wont make errors which lets me build the project. This does make the opencv librairys which makes me think the linking is the issue
2, If I dont add a project as a executable it does see a opencv include
3, I am doing this to make the project portable, it has to work on a rpi down the line so being able to build it all from source could make it much more portable
EDIT 1
So I did some diging in my files, the exe gets outputted into
root\out\build\x64-Debug\bin but this folder does not only contain the librealsense dll but also the opencv ones. This would make it seem that the exe knows about the library but doesnt want to use it some how? This is very strange to me too
EDIT 2
I managed to find_package(OpenCV) by setting
CMAKE_PREFIX_PATH to win-install which contained a config file, problem now is that iam missing the include dir in said folder
EDIT 3
New error seems to be
Target "opencv_highgui" INTERFACE_INCLUDE_DIRECTORIES property contains
path:
"root/opencv-4.3.0/modules/dnn/include"
which is prefixed in the source directory.
I read somewhere that OpenCV prevents source files being used or something to prevent corruption but now now again at a end when it comes to what iam suppose to be doing
Updated CMake file
project(peoplecounting)
add_subdirectory(librealsense-master)
add_subdirectory(opencv-4.3.0)
set(OpenCV_DIR ${CMAKE_BINARY_DIR})
set(INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/")
set(BUILD_SHARED_LIBS OFF)
find_package(OpenCV CONFIG REQUIRED)
add_library(opencv INTERFACE)
include_directories(${OpenCV_INCLUDE_DIRS})
#add_executable (CMakeRealSense "CMakeRealSense.cpp" "CMakeRealSense.h")
add_executable(RealSenseTest "TestRealSense.cpp")
find_library(realsense2 HINTS librealsense-master)
message(" cv_libs: " ${OpenCV_INSTALL_PATH})
message(" cv_includes: " ${OPENCV_INCLUDE_DIRS})
target_include_directories(opencv INTERFACE "${OpenCV_INCLUDE_DIRS}")
target_link_libraries(RealSenseTest "${OpenCV_LIBS}" realsense2)```

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()

QtCreator CMake project - how to show all project files

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...

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.