c++makefilecmakeimagemagickmagickwand

how to get CMake to add MagickWand library linking automatically everywhere


I want to use CMake in my software that uses MagickWand.

CMake works on my machine and generates a useful Makefile. On another machine, I have to manually add

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lMagickWand-6.Q16 -lMagickCore-6.Q16")

otherwise the linker can't find MagickWandGenesis() and other functions.

I found that -l flags via pkg-config --cflags --libs MagickWand.

Shouldn't CMake already generate linker flags for me with TARGET_LINK_LIBRARIES?

Did I miss something obvious, or why is this not working everywhere?


I have this code in CMakeLists.txt:

FIND_PACKAGE(ImageMagick
  REQUIRED
  COMPONENTS MagickWand
)

[...]

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16")

[...]

INCLUDE_DIRECTORIES(
  ${Boost_INCLUDE_DIR}
  ${ImageMagick_INCLUDE_DIRS}
  ${ImageMagick_MagickWand_INCLUDE_DIRS}
)

[...]

TARGET_LINK_LIBRARIES(application_name
  [...]
  ${Boost_LIBRARIES}
  ${CURL_LIBRARIES}
  ${ImageMagick_LIBRARIES}
  ${ImageMagick_MagickWand_LIBRARY}
)

That last ${ImageMagick_MagickWand_LIBRARY} shouldn't even be necessary.

Using Magick 6.8.9.9, CMake 3.0.2 on both machines (Debian Jessie).


Solution

  • Short answer: the package ImageMagick is buggy.

    Looking in CMake's sources, the REQUIRED mechanism is handled exclusively through the variable package-_FOUND, independently of the required components.

    Looking in the package ImageMagick here, ImageMagick_FOUND is set as follows:

    set(ImageMagick_FOUND ${IMAGEMAGICK_FOUND})
    

    But IMAGEMAGICK_FOUND is not set anywhere in the package, so the call will always unset ImageMagick_FOUND, and it will always be evaluated to true (not actively set to false), wether or not the components are effectively found.

    You can either debug the package (and propose a pull request) or check the component variable:

    if(NOT ImageMagick_MagickWand_FOUND)
        message(FATAL_ERROR "MagickWand not found")
    endif()
    

    I guess the test will fail on your second machine.


    By the way, you should only use ImageMagick_INCLUDE_DIRS and ImageMagick_LIBRARIES to link to the library (the ImageMagick_MagickWand* variables are here redundant). If you choose to debug the package, you may also declare imported targets.