1

Good day, here is my code

#include <iostream>
#include <Magick++.h>
using namespace std;
using namespace Magick;
int main(int argc, char **argv) {
  InitializeMagick(*argv);
  Image image;
  try {
    image.read(argv[1]);
  } 
  catch( Exception &error_ ) {
    cout << "Caught exception: " << error_.what() << endl; 
      return 1; 
  } 
  int x = image.columns();
  cout<<"your picture's width is "<< x << "px"<<endl;
  return 0; 
}

I use KDevelop(which uses CMake as builder), when I try to compile the app, it throws me an error

main.cpp:25: undefined reference to `Magick::Image::columns() const'

Here's what my CMakeLists.txt contains.

cmake_minimum_required(VERSION 3.5)
project(hello)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(SOURCE_FILES main.cpp)

add_executable(hello ${SOURCE_FILES})
add_definitions( -DMAGICKCORE_QUANTUM_DEPTH=16 )
add_definitions( -DMAGICKCORE_HDRI_ENABLE=0 )
find_package(ImageMagick COMPONENTS Magick++)
include_directories(${ImageMagick_INCLUDE_DIRS})
target_link_libraries(hello ${ImageMagick_LIBRARIES})

I figured out that there're often issues with undefined references when CMakeLists isn't written correctly, but I made it according to this About Magick++, how to write the CMakeLists?

where am I wrong? I can add any information needed.

UPD 1. version of magick++, 8:6.8.9.9-7ubuntu5.7

system info: Description: Linux Mint 18.1 Serena

UPD 2. I just removed parenthesis and when tryed to compile with

size_t x = image.columns;
size_t y = image.rows;

KDevelop threw me

main.cpp:25:22: error: cannot convert ‘Magick::Image::columns’ from type ‘size_t (Magick::Image::)() const {aka long unsigned int (Magick::Image::)() const}’ to type ‘size_t {aka long unsigned int}’

even when

auto x = image.columns;
auto y = image.rows;

it throws

main.cpp:25:20: error: cannot convert ‘Magick::Image::columns’ from type ‘size_t (Magick::Image::)() const {aka long unsigned int (Magick::Image::)() const}’ to type ‘long unsigned int (Magick::Image::*)() const’

what's happening?

P.S. hooray, this is my first question on stackoverflow! :-)

4
  • Try switching int x to size_t x. Can you also tell use about the system & version of ImageMagick installed? Commented Jun 8, 2017 at 12:55
  • @emcconville thanks for tip, but it didn't help, still same error thrown Commented Jun 8, 2017 at 15:30
  • The error message you're getting without the parentheses says that it can't convert a method ((Magick::Image::)), which takes no arguments (()) and returns size_t, into a value (of type size_t). In other words, you need the parentheses, since it's a function you're supposed to call. (And with auto, it can't convert a method to a method pointer (Magick::Image::*).) Commented Oct 6, 2018 at 6:10
  • Could you try compiling with g++ main.cpp `Magick++-config --cxxflags --cppflags --ldflags --libs` and see whether it works? Commented Oct 6, 2018 at 7:55

2 Answers 2

1

If you are able to compile your program without CMake using g++ main.cpp `Magick++-config --cxxflags --cppflags --ldflags --libs` (but for some reason cannot use ${ImageMagick_LIBRARIES} in CMake), then you can make use of Magick++-config in your CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)
project(hello LANGUAGES CXX)

add_executable(hello main.cpp)
target_compile_features(hello PRIVATE cxx_std_11)
find_package(ImageMagick REQUIRED COMPONENTS Magick++)
target_compile_definitions(hello PRIVATE
  MAGICKCORE_QUANTUM_DEPTH=16
  MAGICKCORE_HDRI_ENABLE=0
)
target_include_directories(hello PRIVATE ${ImageMagick_INCLUDE_DIRS})

execute_process(COMMAND Magick++-config --ldflags
  OUTPUT_VARIABLE ImageMagick_LINK_FLAGS
  OUTPUT_STRIP_TRAILING_WHITESPACE
)
target_link_libraries(hello PRIVATE ${ImageMagick_LINK_FLAGS})

Here, execute_process allows us to get the result of Magick++-config --ldflags into a variable, which we can pass as flags to the linker through target_link_libraries.

Also, note how I've used target_compile_features rather than setting the global CMAKE_CXX_FLAGS variable, target_compile_definitions rather than add_definitions and target_include_directories rather than include_directories. It's better to use local (target-based) commands rather than modifying global state, both in programming and in CMake, since they can have unforeseen repercussions down the line -- in the context of CMake, those global commands would have affected nested sub-projects.

Sign up to request clarification or add additional context in comments.

Comments

0

ForgottenUbrella 's version which I adapted didn't quite work for me, copying a line in from another project fixed it. Note, I'm using c++20 not 11.

I had the following error:

..... undefined reference to symbol 'pthread_create@@GLIBC_2.2.5'

and the line that fixed it:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2a -pthread")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.