Include problems when using CMake with Gnu on Qt project - c++

I am starting a multiplatform (Win Xp, Linux) qt project. I want to use an out of source build so my directory structure is as followed:
project/
CMakeLists.txt (global CMake file, includes other CMakeLists)
build/ (my build directory)
libA/
CMakeLists.txt
mystuff/
subprojectA/
CMakeLists.txt
subprojectB/
CMakeLists.txt
So when I use that on Windows with the Visual Studio generator everything builds fine.
If I use the same structure and CMakeLists on Linux or under Windows with the MinGW generator I get compile errors because the qt generated files (through moc and uic) lying under the build directory cannot find my header files in my subprojects. Some of the qt generated header/source files are dependent on my header/source files because I use promoted widgets in my .ui files which point to the implementation in my source. Again under Visual Studio / NMake everything compiles fine.
As a workaround I can use an in source build which runs fine or I can add the following on the global CMakeLists.txt:
include_directories(
mystuff/subprojectA
mystuff/subprojectB
)
But what is the right solution? Thank you very much!!

I have a similar problem, with includes for out of source builds on unix (although I am not using QT), and in each effected projected I added:
include_directories( . )
Not the most elegant but I worked for me.

In a project I'm working on I use this statement to handle includes in my CMakeLists.txt :
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${QT_INCLUDES} ${OPENSSL_INCLUDE_DIR})
The keyword is ${CMAKE_CURRENT_BINARY_DIR}, hope that helps.
Side note, if you are using gcc 4.4.x with exceptions enabled, you might want to use this so it wouldn't link against libgcc_s_sjlj-1.dll on windows.
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-static-libgcc")

Related

Migrating a Visual Studio C++ Project to Linux and CMake

I'm currently trying to move from Windows 10 to Linux (Pop!_OS), but I'm having trouble getting my C++ Project to compile and run correctly on the latter. My C++ project was created using Visual Studio, where I also specified the include folders, library folders, what should be linked, etc in the solution properties. I now want to switch to writing my code using Neovim and not Visual Studio (or Visual Studio Code) and have tried compiling it via G++. I quickly noticed that my include files weren't recognized, so I tried to use CMake and created a CMakeLists.txt. I tried using both
INCLUDE_DIRECTORIES()
and
TARGET_INCLUDE_DIRECTORIES()
but no matter what path I enter, my included files were not recognized. Even when I used a path to the specific include file that caused the first error, it still wasn't recognized.
My goal would be that I can specify an include folder and a library folder, so that I can just add files and folders in these and that the new files and folders automatically get recognized when compiling (i.e I would not have to edit the CMakeLists.txt in the future). Is that even possible with CMake and if yes, does anyone know where i can find further information about that or does anyone have a CMakeLists.txt file that does this? If no, would I have to specify each and every file and folder in the CMakeLists.txt file and do the same for every new include and library?
Project structure:
Overall folder
\- build
\- include
---> includeFolder1
---> includeFolder2
---> ...
\- libs
---> library1.lib
---> library2.lib
---> ...
\- src
--> main.cpp
--> other .cpp's and .h's
--> other folders with .cpp's and .h's
I've tried compiling with G++ and CMake, but both did not work, no matter what I specified as the include and library paths.
I have found the problem that caused my errors. The problem wasn't with CMake, it was with Windows and Linux specific details. I always received errors like "<foo\foo.h> no such file or directory", which led me to think that CMake couldn't find the include directory or the files in it. The problem, however, is with the include path itself. On Windows, paths can be given with a backslash ('\') but on Linux, paths are denominated with a forward slash ('/'). So in my example, the path to the file was "../foo/foo.h" but my code had "#include <foo\foo.h>". So when migrating a project from Windows to Linux, be sure to watch out for backslashes in your #include statements!
Below is a template CMakeLists.txt, that should be a good starting point if you want to migrate your Visual Studio project to Linux. I've used glfw (+ glad) as an example library:
cmake_minimum_required(VERSION 3.20)
project(ExampleProject)
add_executable(${PROJECT_NAME} src/glad.c src/main.cpp)
target_include_directories(${PROJECT_NAME} PRIVATE include)
target_link_libraries(${PROJECT_NAME} GL dl glfw)

How to setup SFML on Windows 10 with Visual Studio 2022 and CMake?

I am trying to figure out how to get SFML to work with CMake and Visual Studio 2022 on Windows 10.
So far I have
Downloaded and installed Visual Studio 2022
Downloaded a zip file containing what I believe to be the SFML libs and headers which I need to include/link against
Compiled a hello world program with VS2022
There is a file in my sfml folder SFMLConfig.cmake. I need to use this in combination with find_package (cmake) but I have no idea how to do this.
I don't understand where I am supposed to put the SFML folder which I downloaded. I have put it in the root directory of my project (or at least one level lower) it seems like the root is just a place for the first CMakeLists.txt file to live, which just calls add_subdirectory.
I've added a screenshot of VS and the sfml folder containing the .cmake files.
The sfml folder is structured something like this - if you've used SFML before you are probably familiar with it.
sfml/
bin/
openal32.dll
...
include/
sfml/
Audio/
Graphics/
...
lib/
cmake/
SFML/
SFMLConfig.cmake
...
sfml-audio.lib
sfml-audio-d.lib
...
share/
You just need to set SFML_ROOT to X:\REDACTED\source\repos\REDACTED\REDACTED\sfml. It is not appropriate to hard-code such a path in the CMakeLists.txt, but you can put it in a preset. This works either as a CMake variable or as an environment variable.
Please read the full documentation for find_package, the Config-Mode Search Procedure in particular: https://cmake.org/cmake/help/latest/command/find_package.html
Also worth noting: it is much easier to manage dependencies on Windows using vcpkg than littering dubious ("what I believe to be") binaries across your filesystem.

Binaries missing after successful build?

I have a CMake project that I use to generate a Visual Studio solution, which I then try to compile. For some reason, the library file after compilation is nonexistent. I've searched my entire project folder, and cannot find any library files. Here's my CMake setup:
Project root:
cmake_minimum_required(VERSION 3.22)
project(ShadowContainers)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
include_directories(include/)
add_subdirectory(library)
...
library subdirectory:
add_library(libShadows shadows.tpp ../include/shadows.hpp)
set_target_properties(libShadows PROPERTIES LINKER_LANGUAGE CXX) # a tpp and an hpp aren't enough to make the system certain it's c++
target_compile_features(libShadows PRIVATE cxx_std_23)
The MSbuild output contains these lines:
Done Building Project "C:\Users\[..]\projects\Shadow Array\library\libShadows.vcxproj" (default targets).
Done Building Project "C:\Users\[..]\projects\Shadow Array\library\libShadows.vcxproj.metaproj" (default targets).
Even if libShadows is the only target in my project, it's nowhere in my project directory.
Has anybody else had this experience? Any help is appreciated. Thanks!
Edit:
To compile the project, I have tried:
My typical process (working directory = the project root):
cmake .
msbuild ShadowContainers.sln
An alternate process (working directory also project root):
mkdir build
cd build
cmake ..
cmake --build .
Both have produced the same result, albeit with VS and CMake files in different places. No library is outputted either way.
I was able to find the issue. CMake (and conventions for that matter) do not see a .tpp as a code file (similarly to how they treat header files). Thus, I was trying to compile a target with no legitimate code files. Template-only libraries are not libraries at all, so I should not be attempting to compile this standalone, and should instead put the .hpp and .tpp as the include in my projects!

Need sample CMake project that uses Xerces-C++ 3 on Windows with Visual Studio

I am trying to use xerces-c-3.2.2 on Windows 10 from the sample in xerces-c-3.2.2\samples\src\SAXPrint, the sample used as a Visual Studio 2019 project.
Before, I used xerces-c_2_8_0 successfully with xerces-c-src_2_8_0\samples\SAX2Print as a Visual Studio 2019 project with Visual Studio configurations (not CMake). When trying the same with xerces-c-3.2.2 and the according sample, I get the 'error MSB6006: "CL.exe" exited with code 2'.
Note: I have built xerces-c-3.2.2 myself, as there are no binaries for it available. After the build of xerces-c-3.2.2, I get the files xerces-c_3.exp, xerces-c_3.lib, and xerces-c_3_2.dll in C:\Xerces\xerces-c-3.2.2\src\Release, and the include files are in C:\Xerces\xerces-c-3.2.2\xerces-c-3.2.2\src.
On https://developercommunity.visualstudio.com/content/problem/405001/error-msb6006-clexe-exited-with-code-2.html, it was suggested to use Clang as a compiler, as the mentioned "MSB6006" error should be a compiler bug that has not been fixed by Microsoft yet. For using Clang, one has to use CMake in the current version of Visual Studio (I would prefer CMake anyway, for other reasons), and I could not figure out how to setup the project with CMake correctly. The problem is how to tell CMake about the Xerces library files (with xerces-c-3.2.2, there seems to be the only one library file xerces-c_3.lib).
So my top-level CMakeLists.txt (without linking) is:
cmake_minimum_required (VERSION 3.8)
project ("SAXPrint")
include_directories("C:\\Xerces\\xerces-c-3.2.2\\xerces-c-3.2.2\\src")
add_subdirectory ("SAXPrint")
The CMakeLists.txt in the subdirectory is
cmake_minimum_required (VERSION 3.8)
add_executable(SAXPrint "SAXPrint.cpp" "SAXPrint.hpp")
(Yes, I know I should use the absolute paths as arguments to CMake, but that should not be the point here.)
To inform CMake about the xerces library file, I tried
link_directories("C:\\Xerces\\xerces-c-3.2.2\\xerces-c-3.2.2\\src\\Release")
in top-level CMakeLists.txt and I tried
target_link_libraries(SAXPrint "C:\\Xerces\\xerces-c-3.2.2\\xerces-c-3.2.2\\src\\Release")
(this last one does not seem to be accepted, as Visual Studio then keeps displaying the message "generate CMake cache to refresh") and I have read something about the CMake "find_library" command that I did not understand.
The error message I get is
Error LNK2019 unresolved external symbol "__declspec(dllimport) public: static char const * const xercesc_3_2::XMLUni::fgXercescDefaultLocale" (__imp_?fgXercescDefaultLocale#XMLUni#xercesc_3_2##2QBDB) referenced in function main C:\Users\stefan\source\repos\SAXPrint C:\Users\stefan\source\repos\SAXPrint.cpp.obj 1
So any comment how to use the Xerces library file is really welcome, but even better would be if someone had a whole sample CMake project that works with Xerces Version 3 and Visual Studio 2019. I would prefer a CMake project, as this seems to be a better choice for what I would like to accomplish. Thanks.
I found a working solution for the simple "SAXPrint" example, and it is actually really simple if you do not try to use to add whole directories or try to let CMake find installed libaries of some kind:
Top-level CMakeLists.txt:
cmake_minimum_required (VERSION 3.8)
project(SAXPrint)
add_subdirectory ("SAXPrint")
CMakeLists.txt in subdirectory "SAXPrint" with the sample source files:
cmake_minimum_required (VERSION 3.8)
include_directories("C:\\Xerces\\xerces-c-3.2.2\\xerces-c-3.2.2\\src")
add_executable(SAXPrint "SAXPrintHandlers.cpp" "SAXPrint.cpp")
target_link_libraries(SAXPrint "C:\\Xerces\\xerces-c-3.2.2\\xerces-c-3.2.2\\src\\Release\\xerces-c_3.lib")
(Yes, one should avoid absolute paths in the CMakeLists.txt, but this is separate issue and should be easily solved e.g. by giving the path to Xerces as an argument to CMake.)
So I just give the absolute path to the one library file of Xerces 3 as an argument in target_link_libraries. I guess, if I use another library file I just add another path (so I add e.g. many library files for Xerces 2 that uses many of them)? But what about dependencies of those libraries? Maybe this solution is not really how it is expected to be used, I guess CMake has to know about dependencies and just giving a list of library files does not solve it in the general case?
Please note that in my case Xerces is not "installed" in any way, it is (and for my means should) just be a directory containing the needed files in some subdirectories without e.g. any environment variables pointing to it. So I guess find_package is not something I could use, what about find_library?
Or if I just continue to use target_link_libraries (which actually should use the result of e.g. find_package as I understand it) in what order should the library files be listed so dependencies are respected?

ITK: Can't find ITKCommon-x.xx.dll when executing HelloWorld Example

i successfully built ITK 4.13 (as 'Release') on Windows 10 with the latest Visual Studio version (Visual Studio 15 2017 Win64 compiler). Then i tried to built the ITKHelloWorld example using the following CMakeLists.txt (as shown in the example by ITK):
#CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(HelloWorld)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
add_executable(HelloWorld HelloWorld.cxx)
target_link_libraries(HelloWorld ${ITK_LIBRARIES})
Built runs without errors or warnings. Running the generated HelloWorld.exe file result in an ITKCommon-4.13.dll not found error.
The ITKCommon-4.13.dll was built by ITK, thus, i think i have to change something in the CMakeList file, but don't know what.
Any guess or solution?
Edit: The include(${ITK_USE_FILE}) expression in CMakeLists searches for UseITK.cmake, but this file is located in the source of ITK not in the build folder. Could this be a source of the error?
Edit2: Running a VTK Example also shows errors caused by not finding required .dlls.
There is no problem with your project. Windows can use dll libraries on runtime only if they are in PATH location. So there are two options: either you add bin/Release directory of ITK library to Windows's PATH system variable (the directory that contains all the ddls), or you just copy all the dlls from that directory to the one that contains your new application.
Precisely, you don't need to copy all the dlls, you can check by e.g. Dependency Walker, which ones are really needed.