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

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)

Related

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.

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?

Error : LNK1104 cannot open file 'pthread.lib'

I am trying to compile a native Linux C++ application in Windows using Visual Studio 2017. The app uses WebRtc's Acoustic Echo Cancellation(AEC) APIs to negate echo on wav files. Following is the CmakeLists.txt file:
cmake_minimum_required(VERSION 2.8)
project(wav-aec)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
add_subdirectory(gflags)
add_definitions("-DWEBRTC_NS_FLOAT -DWEBRTC_WIN -DNOMINMAX")
#-DWEBRTC_UNTRUSTED_DELAY -DWEBRTC_LINUX -DWEBRTC_POSIX
include_directories(
webrtc
webrtc/webrtc/common_audio/signal_processing/include
webrtc/webrtc/modules/audio_coding/codecs/isac/main/include
)
set(WEBRTC_SRC_
base/buffer.cc
base/checks.cc
...
...
#system_wrappers/source/rw_lock_posix.cc
system_wrappers/source/trace_impl.cc
#system_wrappers/source/trace_posix.cc
)
function(prepend_path var prefix)
set(listVar "")
foreach(f ${ARGN})
list(APPEND listVar "${prefix}/${f}")
endforeach(f)
set(${var} "${listVar}" PARENT_SCOPE)
endfunction(prepend_path)
prepend_path(WEBRTC_SRC webrtc/webrtc ${WEBRTC_SRC_})
add_executable(webrtc-audioproc webrtc-audioproc.cpp ${WEBRTC_SRC})
target_link_libraries(webrtc-audioproc gflags pthread)
When I try to build it, I get the following errror:
Error : LNK1104 cannot open file 'pthread.lib'
Here is the link to the only linux dependent source file(cpp) of the project:
https://github.com/lschilli/wav-aec/blob/master/webrtc-audioproc.cpp
What will be the right approach to port the code from Linux to windows?
Whats is Windows equivalent of gflags and pthread? And what necessary changes needs to go to CmakeLists.txt?
P.S: I have already added pthread header, dll and libs to Visual Studio directory manually.
If 'missing pthread library' is the only error, you can use pthread-w32. We have successfully used it in some of our cross-platform apps requiring pthread.
They have libraries for both 64-bit and 32-bit. You can download and add it into your project. You haven't mentioned your toolset - their libraries are named differently depending on your toolset (MSVC or GNU) so you need to pick the right one. Check out their FAQ.
Hope it helps.
You need to us the actual lib file which is typically not "pthread.lib". It's most likely "pthreadVC3.lib" or "pthreadVC2.lib". Find the actual name by looking in the lib directory of your source package. You might see other lib files in there like "pthreadVCE3.lib" and "pthreadVSE3.lib", but you want to link "pthreadVC3.lib".
You can either add this in the project settings, or add the following code:
#pragma comment(lib,"pthreadVC3.lib")
To add it to the project settings:
Go to project properties->Configuration Properties->Linker->General and add your library path to Additional Library Directories
Go to project properties->Configuration Properties->Linker->Input and add the lib file (such as "pthreadVC3.lib") to Additional Dependencies
Make sure you have the correct version of pthread to match your compile settings, ie x86/x64.
In my case, I am using VCPkg for package management and I installed pthreads using the following commands:
vcpkg install pthread:x86-windows
vcpkg install pthread:x64-windows
And my package lib directory is "C:\vcpkg\installed\x64-windows\lib"
I additionally had to add the following to my project settings as vcpkg wasn't integrating automatically:
Go to project properties->Configuration Properties->VC++ Directories and add "C:\vcpkg\installed\x64-windows\include" to Include Directories
Go to project properties->Configuration Properties->VC++ Directories and add "C:\vcpkg\installed\x64-windows\lib" to Library Directories

CLion indexer does not resolve some includes in the project directory

I have a CLion C++ project that has the following structure:
project
---->my_includes
| ----> my_own.hpp
---->source
----> my_app
----> my_src.cpp
The first line of my_src.cpp is
#include "my_includes/my_own.hpp"
I use an external build system that requires this inclusion format. The problem is if I use a function in my source file defined in the included header, CLion says "Cannot find my_own.hpp" if I try to hover over the inclusion.
I tried marking the include directory as containing Project Source or Headers but this didn't fix it. Any ideas?
You need to create a CMakeLists.txt for CLion to be happy. It is enough to declare all the source files, you don't have to convert your scons (or any other build system) to cmake.
You don't even have to write the CMakeLists.txt by hand, you can ask CLion to do it:
File | New CMake Project from Sources... (since CLion 2019.2)
File | Import project ... | (older CLion)
and then point at the directory containing your project.
Now edit the generated CMakeLists.txt and add a cmake command to tell CLion where to find the includes (actually to tell the compiler, and CLion will reuse that information).
Since your source files use the include as #include "my_includes/my_own.hpp", you need to tell cmake the base directory containing directory my_includes:
include_directories(.)
Where the dot means the same directory as the one containing the CMakeLists.txt.
I tested with a project reproducing your layout and from my_src.cpp I can navigate to my_own.hpp.
Then to build you still have to use scons in a console. It is also possible to add a cmake command, add_custom_target() that will call your scons (or your make, or whatever), so that you can also navigate from CLion to the build errors.
This should be a CMake-based project to open correctly in CLion.
Check CMake basics tutorial if you are new to CMake: https://www.jetbrains.com/help/clion/2016.1/quick-cmake-tutorial.html
And for MakeFile + gcc (g++) projects, you can add the flag -I /Dir/To/Your/Project.
If CLion still shows errors with #include after recompiling the make file, delete the .idea folder and restart CLion.

Include problems when using CMake with Gnu on Qt project

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