Undefined reference errors when trying to compile and simple ImageMagick program - c++

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

Related

Cmake does not find include /libaries (SDL2, GLEW,...)

I want to include SDL2 and GLEW to my Cmake project
The scr files are in C:\libs\src and I createt all the libaries in CMAKE with PATH CMAKE_Install_PRÄFIX like in this documentation:
Download and install CMake ( https://cmake.org/ ) and Visual Studio Community Edition ( https://visualstudio.microsoft.com/de/ )
Create a directory libs or libraries (whatever suits you) where you install all your libraries. It is reasonable to have this on a low level as in the future you might want to add further libraries and use this folder also for other projects. The following explanations assume that you use C:/libs. If you want to use another directory, just adapt the directory the way you need it.
Add C:/libs and C:/libs/bin to the Environment Variable Path ( https://www.computerhope.com/issues/ch000549.htm ).
Create a subdirectory libs/src, copy all the libraries from cgAdvancedFramework/deps/ to this folder and extract them.
SDL2:
Open cmake-gui
Source code: C:/libs/src/SDL2-2.0.12
Binaries: C:/libs/src/SDL2-2.0.12/build
Add entry
Name: CMAKE_INSTALL_PREFIX
Type: PATH
Value: C:\libs
Ok
Configure
Accept creating build directory
Use default native compiler --> Finish
Generate
Open Project (this should start Visual Studio)
Visual Studio
Solution Configuration: Debug
right-click ALL_BUILD --> Build (if errors appear, here you might have done something wrong before)
right-click INSTALL --> Build (if errors appear, ...)
do the same for Solution Configuration: RelWithDebInfo (optional but recommended)
My Project is locatet C:\Users\Documents...\dvs\volren
and the build dir is locatet
C:\Users\Documents...\dvs\build and
C:\libs\include\GL
C:\libs\include\SDL2
...
main.cpp:
#include <iostream>
#pragma once
#define NOMINMAX
#include <SDL2.h> //dont find
#include <GL/glew.h> //dont find
#include <vtk3DS.h> // find
CMakelist.txt:
cmake_minimum_required(VERSION 2.8)
PROJECT(volren)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
find_package(GLEW REQUIRED)
include_directories(${GLEW_INCLUDE_DIRS})
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
add_executable(volren MACOSX_BUNDLE main.cpp Camera.hpp Math.hpp Image.hpp)
target_link_libraries(volren ${VTK_LIBRARIES} ${GLEW_LIBRARIES} ${VTK_LIBRARIES})
Error: Can not open source file GL/glew.h
Where is my mistake ?
It seems that you are on Windows, so why add MACOSX_BUNDLE in your add_executable ?
Also, are you sure GLEW_INCLUDE_DIRS, SDL2_INCLUDE_DIRS are the correct variable to use ? Did you check if they were populated ?

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.

dyld not loading Ogre library

I am trying to setup an environment to develop an Ogre3D application. I have manually compiled Ogre into folder /opt/Ogre3D/ogre-1.11.5/build and created a CMake project in CLion with this content:
cmake_minimum_required(VERSION 3.13)
project(sample)
set(CMAKE_CXX_STANDARD 14)
set(OGRE_DIR /opt/Ogre3D/ogre-1.11.5/build/sdk/cmake)
# specify which version and components you need
find_package(OGRE 1.11 REQUIRED COMPONENTS Bites RTShaderSystem)
# copy resource.cfg next to our binaries where OGRE looks for it
file(COPY ${OGRE_CONFIG_DIR}/resources.cfg DESTINATION ${CMAKE_BINARY_DIR})
add_executable(sample main.cpp)
target_link_libraries(sample ${OGRE_LIBRARIES})
when I try to run it, compilation is OK but then it can't execute it:
/Users/diego/CLionProjects/ogre/sample/cmake-build-debug/sample
dyld: Library not loaded: #executable_path/../Frameworks/OgreBites.framework/Versions/1.11.5/OgreBites
Referenced from: /Users/diego/CLionProjects/ogre/sample/cmake-build-debug/sample
Reason: image not found
Process finished with exit code 6
I have looked at otool -l /opt/Ogre3D/ogre-1.11.5/build/lib/macosx/OgreBites.framework/Versions/1.11.5/OgreBites and there is a command LC_ID_DYLIB with the name #executable_path/../Frameworks/OgreBites.framework/Versions/1.11.5/OgreBites, which matches the path given in the runtime error. However I don't know which step to take now as I have few experience with native library resolution on macOS.
Update:
Executing the command install_name_tool makes the linker find the library, but then it fails with the next one. I suppose/hope there is an option in CMake to pass it to the compiler so the binary files created during Ogre's compilation do not use the #execute_path directive?
I'm faced with the same problem, when using clion to build ogre in macos.
I found the symbolic links were invalid in the directory cmake-build-debug/bin/SampleBrowser.app/Contents/Frameworks.
I guess these symbolic links should point to
these frameworks int the cmake-build-debug/lib/macosx. So I modified the file where executed ln to create these symbolic links.
In the file Samples/Browser/CMakeLists.txt, change
set(OGRE_OSX_BUILD_CONFIGURATION "${CMAKE_OSX_SYSROOT}/$(CONFIGURATION)")
into
set(OGRE_OSX_BUILD_CONFIGURATION "macosx")
And clean and rebuild, then the problem will disappear.

Setup Boost in Clion

How to use Boost library in Clion with MinGW ? I have downloaded and unzipped boost_1_60_0.zip to C:\boost_1_60_0. What am I supposed to do now ? Do I have to install something ? Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.3)
project(server_client)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -s -O3")
set(CMAKE_EXE_LINKER_FLAGS -static)
set(BOOST_ROOT "C:/boost_1_60_0")
set(BOOSTROOT "C:/boost_1_60_0")
find_package(Boost 1.60.0)
if(NOT Boost_FOUND)
message(FATAL_ERROR "Could not find boost!")
endif()
set(SOURCE_FILES chat_server.cpp)
add_executable(server_client ${SOURCE_FILES})
Can not find Boost:
I use MinGW distro by Stephan T. Lavavej with Boost libraries prebuilt.
In my cmaklist.txt I added this
set(Boost_INCLUDE_DIR c:/mingw/include/)
set(Boost_LIBRARY_DIR c:/mingw/lib/)
find_package(Boost COMPONENTS system filesystem REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
This post help me get it going. How to include external library (boost) into CLion C++ project with CMake?
Here's example project for CLion that uses Boost's regex library. It references to this tutorial.
Goal: with CLion create .exe that process jayne.txt as shown in Boost's tutorial.
My example revolves around building Boost Library Binary with GCC, configuring project in CLion and using CMake. It's quite expressive, maybe even an overkill, but I believe you can adapt. On the other hand I'll try to make project itself as system independent as its possible.
Configuration:
OS: Windows 8.1
CLion: 2018.2.4
Boost: 1.68.0
compiler: GCC-6.3.0 (provided by MinGW)
MinGW was configured according to its instructions and JetBrains's suggestions. (I downloaded setup for MinGW 14/10/2018 if that matters.)
A word about tools structure
I decided to create following structure for Boost and things aroung it:
D:\
SDK\
boost\
boost_1_68_0\ # untouched Boost root
boost\
rst.css
...other directories and files...
1_68_0\
build\ # dir for Boost.Build, b2.exe
buildDir\ # intermediate dir for creating libraries
stageDir\ # dir for libraries
lib\
MinGW\
bin\
...other directories...
I left Boost root untouched -- I didn't create any additional directories. This separates Boost sources from created tools and libraries so I can show how to specify these directories explicitly.
Obtain Boost Library Binary
I decided to build libraries from source with GCC.
Download and unpack Boost ("D:\SDK\boost\boost_1_68_0");
Build libraries (5.2):
Open command prompt at \tools\build of Boost root ("D:\SDK\boost\boost_1_68_0\tools\build")
Run bootstrap.bat
Run b2 install --prefix="D:\SDK\boost\1_68_0\build" --toolset=gcc-6.3.0. This creates b2.exe under "D:\SDK\boost\1_68_0\build\bin"
Move command prompt to Boost root (cd "D:\SDK\boost\boost_1_68_0")
(You can consider using "D:\SDK\boost\1_68_0\build\bin\b2.exe --show-directories". It's worth to specify libraries to build (--with-library-name) in the following command, because this step can take a while.) Run "D:\SDK\boost\1_68_0\build\bin\b2" --build-dir="D:\SDK\boost\1_68_0\buildDir" toolset=gcc-6.3.0 --build-type=complete stage --stagedir="D:\SDK\boost\1_68_0\stageDir" --with-regex. It creates following files under D:\SDK\boost\1_68_0\stageDir\lib directory:
libboost_regex-mgw63-mt-d-x32-1_68.a
libboost_regex-mgw63-mt-d-x32-1_68.dll
libboost_regex-mgw63-mt-d-x32-1_68.dll.a
libboost_regex-mgw63-mt-sd-x32-1_68.a
libboost_regex-mgw63-mt-s-x32-1_68.a
libboost_regex-mgw63-mt-x32-1_68.a
libboost_regex-mgw63-mt-x32-1_68.dll
libboost_regex-mgw63-mt-x32-1_68.dll.a
CMake looks for files with specific names in library folder, so be sure to (copy and) change name for one of .a files there. For this example, I changed libboost_regex-mgw63-mt-x32-1_68.a to boost_regex.a.
Create CLion project
Create a new project (for this example its name is CLionBoostRegex) and put content to main.cpp (6):
#include <boost/regex.hpp>
#include <iostream>
#include <string>
int main()
{
std::string line;
boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" );
while (std::cin)
{
std::getline(std::cin, line);
boost::smatch matches;
if (boost::regex_match(line, matches, pat))
std::cout << matches[2] << std::endl;
}
}
Configure CLion
Go to (on Windows) File -> Settings -> Build, Execution, Deployment -> CMake, and in CMake options add path to Boost root directory with -DBOOST_ROOT=, i.e.: -DBOOST_ROOT="D:\SDK\boost\boost_1_68_0". If directory with built libraries is placed outside Boost root, add it with -DBOOST_LIBRARYDIR=, i.e.: -DBOOST_LIBRARYDIR="D:\SDK\boost\1_68_0\stageDir\lib". Commands are space separated.
Decide if you want static or dynamic linking.
Option 1: Static linking
For static linking your CMakeLists.txt should look like this:
cmake_minimum_required(VERSION 3.12)
project(CLionBoostRegex)
set(CMAKE_CXX_STANDARD 98)
find_package(Boost REQUIRED COMPONENTS regex)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(CLionBoostRegex main.cpp)
target_link_libraries(CLionBoostRegex -static)
target_link_libraries(CLionBoostRegex ${Boost_LIBRARIES})
Option 2: Dynamic linking
CMakeLists.txt should look like for static linking, but remove target_link_libraries(CLionBoostRegex -static) line.
After building your project make sure to copy .dll library to directory with executable (libboost_regex-mgw63-mt-x32-1_68.dll) along with libstdc++-6.dll from MinGW\bin directory (D:\SDK\MinGW\bin) (or consider including target_link_libraries(CLionBoostRegex -static-libstdc++) line in CMakeLists.txt or add -DCMAKE_CXX_FLAGS="-static-libstdc++" to CMake options in settings).
Run your program (6.4)
Build your target (it creates cmake-build-debug\ directory with default config) (if you picked dynamic linking make sure to add necessary .dlls)
In directory with your executable create jayne.txt file with following content:
To: George Shmidlap
From: Rita Marlowe
Subject: Will Success Spoil Rock Hunter?
---
See subject.
Open command prompt there
Run CLionBoostRegex.exe < jayne.txt
Program should output Will Success Spoil Rock Hunter? as shown in tutorial.
Notes
Changing name for an .a library and choosing -static linking causes the least effort afterwards - you won't have to copy any additional libraries at the price of bigger executable size. When executable size is more important, you can change name for .dll library in Boost libraries directory instead and then copy missing .dlls for your .exe (i.e.: libboost_regex-mgw63-mt-x32-1_68.dll and libstdc++-6.dll).
You can include set(Boost_DEBUG ON) line in your CMakeLists.txt or -DBoost_DEBUG=1 to CMake options to get some precious info.
I used other questions to write this post, most notably: 1, 2, 3, 4.

ITK installation and sample program

I am new to ITK and I did the following step to install ITK and use it to programme in VS2010
Downloaded ITK 4.3.1 and build it with CMAKE
The build was successful and I had a lib->Debug folder containing the libs.
Added the bin folder path to environmental vairable path.
Following is my simple code...
#include <iostream>
#include <Core/Common/include/itkImage.h>
using namespace itk;
using namespace std;
int main()
{
return 0;
}
the above code returns
Cannot open include file: 'itkConfigure.h'
I tried searching for that header but no luck. However in C:\InsightToolkit-4.3.1\Modules\Core\Common\src I found itkConfigure.h.in file. I am really clueless about how to go about this .in file. Any help is most welcome..
The easiest way to set up your project is to use CMake again. Try creating a project with just a CMakeLists.txt and main.cpp. The CMakeLists.txt should have something like:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(ItkTest)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
add_executable(MyTest main.cpp)
target_link_libraries(MyTest ITKCommon)
So say you create these 2 files in a dir called ItkProject, then from a Visual Studio Command Prompt just do:
cd <path to ItkProject>
mkdir build
cd build
cmake .. -DITK_DIR="<path to build dir of ITK>"
The <path to build dir of ITK> is where you ran CMake from to configure the ITK project. It will contain the ITK.sln file, but critically it should also contain a file called ITKConfig.cmake. It is this file which is searched for in the cmake command find_package(ITK REQUIRED) - if CMake can't find it the configuring will fail.
Once that's been found, it sets a bunch of CMake variables which you can then use in your own CMakeLists.txt, including ITK_USE_FILE.
When you then invoke include(${ITK_USE_FILE}), this goes on to set up things like your includes paths, library search paths, and compiler flags. The path <path to ItkProject>/Core/Common/include will be added to the includes dirs, so in your main.cpp, you just need to do:
#include <Core/Common/include/itkImage.h>
#include "itkImage.h"
Anyway, the end result after running CMake should be solution file <path to ItkProject>\build\ItkTest.sln which is set up ready to use ITK.
I checked \ItkConfig.cmake and paths defined there should match physical paths, this is the case if ITK build has been untouched (directory wasn't renamed).
# The ITK source tree.
# For backward compatibility issues we still need to define this variable, although
# it is highly probable that it will cause more harm than being useful.
# Use ITK_INCLUDE_DIRS instead, since ITK_SOURCE_DIR may point to non-existent directory
IF(NOT ITK_LEGACY_REMOVE)
SET(ITK_SOURCE_DIR "C:/ITK320")
ENDIF(NOT ITK_LEGACY_REMOVE)
# The ITK include file directories.
SET(ITK_INCLUDE_DIRS "C:/ITK320-build;C:/ITK320/Code/Algorithms;C:/ITK320/Code/BasicFilters;C:/ITK320/Code/Common;C:/ITK320/Code/Numerics;C:/ITK320/Code/IO;C:/ITK320/Code/Numerics/FEM;C:/ITK320/Code/Numerics/NeuralNetworks;C:/ITK320/Code/SpatialObject;C:/ITK320/Utilities/MetaIO;C:/ITK320/Utilities/NrrdIO;C:/ITK320-build/Utilities/NrrdIO;C:/ITK320/Utilities/DICOMParser;C:/ITK320-build/Utilities/DICOMParser;C:/ITK320-build/Utilities/expat;C:/ITK320/Utilities/expat;C:/ITK320/Utilities/nifti/niftilib;C:/ITK320/Utilities/nifti/znzlib;C:/ITK320/Utilities/itkExtHdrs;C:/ITK320-build/Utilities;C:/ITK320/Utilities;C:/ITK320/Code/Numerics/Statistics;C:/ITK320/Utilities/vxl/v3p/netlib;C:/ITK320/Utilities/vxl/vcl;C:/ITK320/Utilities/vxl/core;C:/ITK320-build/Utilities/vxl/v3p/netlib;C:/ITK320-build/Utilities/vxl/vcl;C:/ITK320-build/Utilities/vxl/core;C:/ITK320-build/Utilities/gdcm;C:/ITK320/Utilities/gdcm/src")
# The ITK library directories.
SET(ITK_LIBRARY_DIRS "C:/ITK320-build/bin")