Qt - How to write a FindXXX.cmake file for a certain Qt library - c++

So I really want to start developing my Qt project inside a different IDE (Clion to be exact). I've written my CMake file for the project. It successfully finds Qt Core, Widgets and other libraries but when it comes to including Qt Charts Cmake throws an error:
CMake Error at CMakeLists.txt:44 (find_package):
By not providing "FindQt5Charts.cmake" in CMAKE_MODULE_PATH this project
has asked CMake to find a package configuration file provided by
"Qt5Charts", but CMake did not find one.
This error is successfully removed when I add by hand a "FindQt5Charts.cmake" file in my CLion>bin>Cmake>share>modules (where FindQt.cmake and othere search package files are) but as of now this file is empty.
The Cmake compiles successfully but since it hasn't found the library I'm looking for, my project won't compile. I need your help to write "FindQt5Charts.cmake" file because I'm not 100% sure of its syntax.
NOTE: Qt Charts is installed and its folder could be found in Qt's installation directory. I just need the code for the FindQt5Charts.cmake.
Here's a reference to the FindQt.cmake file
Here is how the beggining of my project's cmake looks:
#Pull needed header files generated by QT first
set(QT_GENERATED qtGenerated)
add_custom_target(${QT_GENERATED})
#Get all header files in the directory
file(GLOB QT_GEN_HEADERS ${QT_BIN}/*.h)
#Copy them to the project dir
foreach (QT_GEN_HEADERS ${QT_GEN_HEADERS})
add_custom_command(TARGET ${QT_GENERATED} PRE_BUILD COMMAND
${CMAKE_COMMAND} -E copy_if_different
${QT_GEN_HEADERS} ${CMAKE_SOURCE_DIR})
endforeach ()
# Find the Qt libraries
foreach (QT_LIBRARIES_REQUIRED ${QT_LIBRARIES_REQUIRED})
find_package(${QT_LIBRARIES_REQUIRED} REQUIRED)
endforeach ()

Related

Undefined reference errors when trying to compile and simple ImageMagick program

I've been searching for a solution to this problem for a long time to no avail.
I am trying to compile this simple program:
#include <iostream>
#include <Magick++.h>
#include <Magick++/Image.h>
using namespace std;
using namespace Magick;
int main(int argc,char **argv) {
InitializeMagick("D:\\Programming\\CPPProjects\\NoteScripts\\Dependencies\\magick\\include");
Image image;
// image.read("arch");
// image.write("test.png");
}
Upon building, I get the following error:
CMakeFiles\main.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x1c): undefined reference to `Magick::InitializeMagick(char const*)'
CMakeFiles\main.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x28): undefined reference to `Magick::Image::Image()'
CMakeFiles\main.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x34): undefined reference to `Magick::Image::~Image()'
collect2.exe: error: ld returned 1 exit status
From what I can tell, this is a linker error but I have no idea where I am going wrong with linking the libs needed.
I installed ImageMagick on Windows 10 from the ImageMagick downloads page with this installer: ImageMagick-7.1.0-50-Q16-HDRI-x64-dll.exe
I then copied the lib files from the lib folder under the installation directory into my project and then copied the include folder under the installtion directory into my project.
Here is what the project hierarchy looks like (Source Directory is NoteScripts):
My CMakeLists.txt consists of:
cmake_minimum_required(VERSION 3.10)
set( CMAKE_CXX_COMPILER "C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/g++.exe")
set( CMAKE_C_COMPILER "C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/gcc.exe" )
# set the project name
project("Notes")
include_directories(D:/Programming/CPPProjects/NoteScripts/Dependencies/magick/include)
# add the executable
add_executable(main main.cpp)
target_link_libraries(main D:/Programming/CPPProjects/NoteScripts/Dependencies/magick/lib/CORE_RL_Magick++_.lib)
target_link_libraries(main D:/Programming/CPPProjects/NoteScripts/Dependencies/magick/lib/CORE_RL_MagickCore_.lib)
target_link_libraries(main D:/Programming/CPPProjects/NoteScripts/Dependencies/magick/lib/CORE_RL_MagickWand_.lib)
If I comment out lines 9 and 10 where InitializeMagick() is called and where Image image is declared, the program compiles without error. I'm also aware that the order of the static libs listed out matters but trying out multiple combinations has resulted in the same error. I have also verfied the dependency order by sifting through the original source code and the reference path is Magick++ -> MagickCore -> MagickWand.
I am relatively new to the process of adding external dependencies to my C++ projects so this is unfamiliar territory (coming from languages with clean package managers). Any help as to how to fix this issue is greatly appreciated!
The typical (and easiest) way of handling dependencies in CMake is using its find_package command:
find_package(ImageMagick REQUIRED COMPONENTS MagickCore MagickWand Magick++)
// ...
target_link_libraries(main ${ImageMagick_LIBRARIES})
This method is available for ImageMagick with your CMake version. I'm not familiar with CMake on Windows, but find_package by default searches a number of standard (system) locations for the package's files. Since you have a custom setup, it should also be possible to specify a nonstandard search prefix to the command. Additionally, you could download external dependencies in a portable way with the FetchContent commands.
First of all, it is a pain to setup this thing if you are a newbie like me.
Now to the steps to dynamically link imagemagick libs with your C app:
go to https://github.com/ImageMagick/ImageMagick-Windows and follow the instructions there (Install Visual Studio dependencies - Clone the dependencies - Build configure.exe- Build ImageMagick)
in the step Build configure.exe, when running configure.exe, keep the default option selected when asked about the output library type (keep it set to dynamic)
in the Build ImageMagick step, when you open VisualDynamicMT.sln in visual studio, before you start the build, select all the solutions in the project, and right-click -> properties -> General -> C Language Standard -> choose Default (Legacy MSVC). After that, click on the top-most solution that contains all the other 196 solutions, and build it. watch the console for errors, I didn't get any errors with the configuration above.
After the latter step, go the VisualMagick folder (created from steps before), and you will see lib folder and bin folder. You're done, your dlls are in bin and your .lib file are in bin folder. Note that these files will be corresponding to build or release environments depending on what you selected in visual studio at the build step.
How do you use imagemagick now in your project regardless if you have imagemagick app installed on your pc or not? Lets create a new project in vscode, call it demo.
Create this project structure:
inside src you will put your C code.
inside deps create ImageMagick/lib and ImageMagick/bin and ImageMagick/include
inside ImageMagick/include place the same include files you said you got in your question.
inside ImageMagick/lib place the .lib files you got from above
inside ImageMagick/bin place the .dll files you got from above
now add this to your CMakeLists.txt:
cmake_minimum_required(VERSION 3.23)
project(demo-app C)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
file(GLOB SOURCE_FILES src/*.c)
add_executable(demo ${SOURCE_FILES})
include_directories(src)
# ImageMagick
if(WIN32)
add_definitions( -DMAGICKCORE_QUANTUM_DEPTH=16 )
add_definitions( -DMAGICKCORE_HDRI_ENABLE=0 )
include_directories(deps/ImageMagick/include)
target_link_directories(demo PRIVATE deps/ImageMagick/lib)
file(GLOB IMAGEMAGICK_LIBS deps/ImageMagick/lib/*.lib)
target_link_libraries(demo
"${IMAGEMAGICK_LIBS}"
)
add_custom_command(TARGET demo POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${PROJECT_SOURCE_DIR}/deps/ImageMagick/bin"
$<TARGET_FILE_DIR:demo>)
endif()
(The add_custom_command will copy the dlls to your executables path after every build)
Now write some magick code in you src directory.
ctrl + shift + A -> CMake select kit -> choose the Visual Studio community 2022 release -amd64 or change to what fits you if it doesn't work
ctrl + shift + A -> CMake Clean Rebuild
ctrl + shift + A -> CMake run without debugging

How wxWidgets cmake find in window

I can't find wxWidget on window. The error is:
CMake Error at E:/Program Files/JetBrains/CLion 2020.2.1/bin/cmake/win/share/cmake-3.17/Modules/FindPackageHandleStandardArgs.cmake:164 (message):
Could NOT find wxWidgets (missing: wxWidgets_LIBRARIES
wxWidgets_INCLUDE_DIRS)`
My Env:
win10
cmake 3.17
wxWidgets 3.1.4
I use cmake to build and install the wxWidgets
mkdir build
cd build
cmake .. -config Release
cmake --build .
cmake --install .
Which install wxWidgets in D:/Program Files(x86)/wxWidgets.
The I set the env variable wxWidgets_ROOT_DIR to D:\Program Files (x86), because that's a code snnipt in cmake's script FindWxWidgets.cmake.
find_path(wxWidgets_ROOT_DIR
NAMES include/wx/wx.h
PATHS
ENV wxWidgets_ROOT_DIR
ENV WXWIN
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\wxWidgets_is1;Inno Setup: App Path]" # WX 2.6.x
C:/
D:/
ENV ProgramFiles
PATH_SUFFIXES
wxWidgets-3.1.0
wxWidgets-3.0.2
wxWidgets-3.0.1
wxWidgets-3.0.0
wxWidgets-2.9.5
wxWidgets-2.9.4
wxWidgets-2.9.3
wxWidgets-2.9.2
wxWidgets-2.9.1
wxWidgets-2.9.0
wxWidgets-2.8.9
wxWidgets-2.8.8
wxWidgets-2.8.7
wxWidgets-2.8.6
wxWidgets-2.8.5
wxWidgets-2.8.4
wxWidgets-2.8.3
wxWidgets-2.8.2
wxWidgets-2.8.1
wxWidgets-2.8.0
wxWidgets-2.7.4
wxWidgets-2.7.3
wxWidgets-2.7.2
wxWidgets-2.7.1
wxWidgets-2.7.0
wxWidgets-2.7.0-1
wxWidgets-2.6.4
wxWidgets-2.6.3
wxWidgets-2.6.2
wxWidgets-2.6.1
wxWidgets-2.5.4
wxWidgets-2.5.3
wxWidgets-2.5.2
wxWidgets-2.5.1
wxWidgets
DOC "wxWidgets base/installation directory"
)
I think I have config right the wxWidgets_ROOT_DIR. Because I message the varialbe message(wxWidgets_ROOT_DIR " " ${wxWidgets_ROOT_DIR}) and It show the right value:
D:/Program Files(x86)/wxWidgets
The I use find_libarray(wxWidgets Required) in my project to find wxWidgets, and it shows the above error.
My question is:
How to fix it.
Or what find_package(xxx) do on window?
Update:
I finally find it's clion issue that use his cmake not the stand cmake. I use the stand cmake with vscode. And they works fine.
I also had problems with wxWidgets installation on Windows and CLion, I' ve followed these steps:
Download MinGW(32) and set as the default compiler for CLion (I had problems with other compilers)
Download the windows installer of wxWidgets from the official site (https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.4/wxMSW-3.1.4-Setup.exe)
The installer will download all the files of the library in "C:\wxWidgets-3.1.4" and will also create the environment variable WXWIN that will contain the path of the folder "C:\wxWidgets-3.1.4"
Compile the library following this tutorial for MinGW https://wiki.wxwidgets.org/Compiling_wxWidgets_with_MinGW (make a coffee, it will take a while)
The compiler will but object files in "C:\wxWidgets-3.1.4\lib\gcc_dll", in "C:\wxWidgets-3.1.4\build\msw\gcc_mswudll" and probably in other places based on the instruction files in the "C:\wxWidgets-3.1.3\build" folder
After the compilation you need to add "C:/wxWidgets-3.1.4/lib/gcc_dll" in the environment variable PATH of the OS
After a restart write this code in the CMakeLists of your project:
cmake_minimum_required(VERSION 3.17)
project(your project name)
set(CMAKE_CXX_STANDARD 20)
SET(wxWidgets_USE_LIBS)
#for using RichTextCtrl
FIND_PACKAGE(wxWidgets REQUIRED richtext aui adv html core xml net base)
IF(wxWidgets_FOUND)
INCLUDE("${wxWidgets_USE_FILE}")
add_executable(your list of executables)
TARGET_LINK_LIBRARIES(note ${wxWidgets_LIBRARIES})
ELSE(wxWidgets_FOUND)
#for convenience. When we cannot continue,inform the user
MESSAGE("wxWidgets not found!")
ENDIF(wxWidgets_FOUND)
And now wxWidgets should work
I was able to build the samples using CLion and CMake on Mac OS, but much of what I learned should be similar, given CLion's cross-platform nature. The directions are very long, so here is a link:
https://forums.wxwidgets.org/viewtopic.php?p=197038#p187276

CMake GLOB not returning any source files?

I am trying to automatically have my Makefiles written for my C++ project using CMake with GLOB. The code and headers are however located in two separate folders.
/Users/username/Coding/Major Projects/ProjectName/Backend
and
/Users/username/Coding/Major Projects/ProjectName/Terminal
The backend has platform independent code. Just a bunch of c and c++ source files. And the Terminal folder has some code that uses the objects specified in Backend to run some tests on them. The reason these are in separate folders is that the Backend code is Multiplatform. So an Xcode project imports it etc. The Terminal folder has the testing code because that is the only one that is trying to compile it into a linux binary.
Anywho, I have the following CMakeList.txt file that I am trying to build to generate the Makefile.
cmake_minimum_required(VERSION 2.8.9)
project(terminalTest)
set(MainSource "/Users/username/Coding/Major Projects/ProjectName/Backend")
set(TerminalSource "/Users/username/Coding/Major Projects/ProjectName/Terminal")
#Bring the headers, such as Student.h into the project
include_directories(${MainSource} ${TerminalSource})
#Can manually add the sources using the set command as follows:
#set(SOURCES src/mainapp.cpp src/Student.cpp)
#However, the file(GLOB...) allows for wildcard additions:
file(GLOB SOURCES "./{${MainSource},${TerminalSource}}/*.cpp")
add_executable(terminalTest ${SOURCES})
And the result of this when I run this from the CMake GUI is a successful configure but an error No SOURCES given to target: terminalTest meaning that my file() command is not working properly.
I think it could have something to do with the fact that I have spaces in my paths but that doesn't seem to do it either. By the way I am putting this file in the Terminal folder and attempting to build from Terminal/Build.
Is there any way to debug and see what sources the GLOB command is bringing in? Can I actually do a multi directory GLOB like this?
Your file(GLOB ...) path looks malformed. You can list the paths to your sources separately in this command to grab all the source files in both directories.
file(GLOB SOURCES
${MainSource}/*.cpp
${TerminalSource}/*.cpp
)

cmake + cpp: No such file or directory

I've I'm trying to build this "Hello World" wxWidgets example on Linux, using the following cmake script:
cmake_minimum_required (VERSION 2.6)
project (wxL)
find_package(wxWidgets 3.0.0 REQUIRED
COMPONENTS base core net xml html adv qa richtext
)
file(GLOB SOURCES "src/*.cpp")
add_executable(wxL ${SOURCES})
Building the project yields this error:
src/wxL.cpp:3:10: fatal error: wx/wxprec.h: No such file or directory
The file specified in the include, wx/wxprec.h can be found on disk at this location:
/usr/include/wx-3.0/wx/wxprec.h
Furthermore, another program that I have built from source includes the same file (also using cmake) and builds just fine.
So, how do I use cmake to tell the compiler that the file should be included from somewhere in the system directories?
I know I'm missing something basic, but I can't figure out what.
Although you've found the package, your executable does not know anything about it.
For the executable to compile correctly, it needs to find header files for your package together with the .so / .a files. Following example should get you started:
include_directories(${wxWidgets_INCLUDE_DIRS})
add_executable(wxL <add-source-files-here>)
target_link_libraries(wxL ${wxWidgets_LIBRARIES}) // links wxWidgets libraries to your executable
Please note that using glob is not a recommended way of adding source files to your project.

CMake - finding external libraries

I have a project with the following structure:
projectName-master/
data/
source/
thirdparty/ (here is placed FindSFML.cmake file)
.gitignore
CMakeLists.txt
README.md
SOURCES.md
TODO.md
I use CMake 2.8.11.1 (cmake-gui) to generate visual studio sln file. Paths are set this way:
where is the source code: E:/projectName-master
where to build the binaries: E:/projectName-master/source (1.Can I choose other directory or it should be set to the directory which contains source files: h, cpp etc. ?)
Next I choose: Configure -> "Specify the generator for this project = Visual Studio 11, Use default native compilers" -> Finish
Then I get an info: Error in configuration process, project files may be invalid
CMake Gui contains following informations:
Name: CMAKE_INSTALL_PREFIX Value C:/Program Files(x86)/projectName
Name: SFML_INCLUDE_DIR Value SFML_INCLUDE_DIR-NOTFOUND
CMake Error at thirdparty/FindSFML.cmake:165 (message):
Could NOT find SFML (missing: SFML_SYSTEM_LIBRARY SFML_WINDOW_LIBRARY
SFML_AUDIO_LIBRARY SFML_NETWORK_LIBRARY SFML_GRAPHICS_LIBRARY)
Call Stack (most recent call first):
CMakeLists.txt:63 (find_package)
I downloaded SFML and set SFML_INCLUDE_DIR (in CMake Gui): C:/OpenGL/SFML-2.1/include/SFML but I still get that error. 2. How to fix that ? What about lib files and dll's ?
Edit1:
I downloaded SFML from the official site
FindSFML.cmake from the project doesn't contain any SFML_ROOT entry, but SFML_INCLUDE_DIR looks like this:
# find the SFML include directory
find_path(SFML_INCLUDE_DIR SFML/Config.hpp
PATH_SUFFIXES include
PATHS
${SFMLDIR}
$ENV{SFMLDIR}
~/Library/Frameworks
/Library/Frameworks
/usr/local/
/usr/
/sw # Fink
/opt/local/ # DarwinPorts
/opt/csw/ # Blastwave
/opt/)
So how to set SFML_ROOT ? Do I need to add some entries (records) to that file ? How it will look like ?
Edit2: A part of the new FindSFML.cmake with a path to SFML (C:/OpenGL/SFML-2.1/)
find_path(SFML_INCLUDE_DIR SFML/Config.hpp
PATH_SUFFIXES include
PATHS
${SFML_ROOT}
$ENV{SFML_ROOT}
C:/OpenGL/SFML-2.1/
~/Library/Frameworks
/Library/Frameworks
/usr/local/
/usr/
/sw # Fink
/opt/local/ # DarwinPorts
/opt/csw/ # Blastwave
/opt/)
First of all, SFML is not CMake standard module, so it would be nice to provide link to sources. I hope you mean this product. Take a look at the FindSFML file:
# If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable
# to tell CMake where SFML is.
So you probably simply need to set SFML_ROOT variable, but not SFML_INCLUDE_DIR.
What about lib files and dll's?
I think this may be helpful:
# By default, the dynamic libraries of SFML will be found. To find the static ones instead,
# you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...).
Can I choose other directory or it should be set to the directory which contains source files: h, cpp etc.
It is highly recommended to use a separate directory.