Undefined reference errors when trying to compile and simple ImageMagick program

386 Views Asked by At

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

enter image description here

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!

2

There are 2 best solutions below

0
sigma On

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.

0
HII On

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: enter image description here

  • 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