From bb399cd140e1b22f46b019f9b0bc14e62b270ab7 Mon Sep 17 00:00:00 2001 From: Wolfgang Bauer Date: Tue, 14 Dec 2021 17:02:22 +0100 Subject: [PATCH] Revert "Exiv2 is now released with exported targets using cmake rules. No need to have a dedicated find exiv2 cmake script. Bump minimal version to 0.27.1" This reverts commit 06e77271d72fe5e4abeb38641f3addc2cfbff126. Also, it replaces the use of `Exiv2::XmpData::eraseFamily()` (new in exiv2-0.27) with inline code copied from exiv2-0.27.5. Fixes build on Leap 15.x which only have exiv2 0.26. --- core/CMakeLists.txt | 14 +-- core/app/DigikamCoreTarget.cmake | 2 +- core/cmake/modules/FindExiv2.cmake | 116 ++++++++++++++++++ core/libs/metadataengine/CMakeLists.txt | 10 +- .../metadataengine/engine/metaengine_xmp.cpp | 23 +++- 5 files changed, 148 insertions(+), 17 deletions(-) create mode 100644 core/cmake/modules/FindExiv2.cmake diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 16bba83335..174dc3c683 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -16,7 +16,7 @@ message(STATUS "") set(KF5_MIN_VERSION "5.5.0") set(QT_MIN_VERSION "5.9.0") -set(EXIV2_MIN_VERSION "0.27.0") +set(EXIV2_MIN_VERSION "0.26") set(OPENCV_MIN_VERSION "3.3.0") set(LENSFUN_MIN_VERSION "0.2.6.0") # For Lens auto-correction plugin set(QTAV_MIN_VERSION "1.12.0") # For video support. @@ -180,19 +180,15 @@ if(NOT X265_FOUND) set(X265_LIBRARIES "") endif() -find_package(exiv2 REQUIRED) +find_package(Exiv2 ${EXIV2_MIN_VERSION} REQUIRED) -set_package_properties("exiv2" PROPERTIES +set_package_properties("Exiv2" PROPERTIES DESCRIPTION "Required to build digiKam" URL "https://www.exiv2.org" TYPE RECOMMENDED PURPOSE "Library to manage image metadata" ) -if("${exiv2_VERSION}" VERSION_LESS ${EXIV2_MIN_VERSION}) - message(FATAL_ERROR "Exiv2 version is too old (${exiv2_VERSION})! Minimal version required:${EXIV2_MIN_VERSION}.") -endif() - # -- check Media player -------------------------------------------------------- find_package(FFmpeg COMPONENTS AVCODEC AVDEVICE AVFILTER AVFORMAT AVUTIL SWSCALE) @@ -579,7 +575,7 @@ PRINT_COMPONENT_COMPILE_STATUS("QWebEngine Support" ENABLE_QWEBENGINE) # ============================================================================== PRINT_LIBRARY_STATUS("libboostgraph" "https://www.boost.org/doc/libs" "(version >= 1.43.0)" Boost_FOUND) -PRINT_LIBRARY_STATUS("libexiv2" "https://www.exiv2.org" "(version >= ${EXIV2_MIN_VERSION}" exiv2_FOUND) +PRINT_LIBRARY_STATUS("libexiv2" "https://www.exiv2.org" "(version >= ${EXIV2_MIN_VERSION}" Exiv2_FOUND) PRINT_LIBRARY_STATUS("libexpat" "https://libexpat.github.io" "(version >= 2.0.0)" EXPAT_FOUND) PRINT_LIBRARY_STATUS("libjpeg" "https://github.com/libjpeg-turbo/libjpeg-turbo" "(version >= 6b)" JPEG_FOUND) PRINT_LIBRARY_STATUS("libkde" "https://www.kde.org" "(version >= ${KF5_MIN_VERSION})" KF5_FOUND) @@ -622,7 +618,7 @@ PRINT_OPTIONAL_LIBRARY_STATUS("libqtxmlpatterns" "https://www.qt.io" # ============================================================================== if(Boost_FOUND AND - exiv2_FOUND AND + Exiv2_FOUND AND EXPAT_FOUND AND JPEG_FOUND AND KF5_FOUND AND diff --git a/core/app/DigikamCoreTarget.cmake b/core/app/DigikamCoreTarget.cmake index b9ec794684..d11ebc9120 100644 --- a/core/app/DigikamCoreTarget.cmake +++ b/core/app/DigikamCoreTarget.cmake @@ -145,7 +145,7 @@ target_link_libraries(digikamcore ${TIFF_LIBRARIES} PNG::PNG ${JPEG_LIBRARIES} - exiv2lib + ${EXIV2_LIBRARIES} ${FFMPEG_LIBRARIES} diff --git a/core/cmake/modules/FindExiv2.cmake b/core/cmake/modules/FindExiv2.cmake new file mode 100644 index 0000000000..912ffaee0c --- /dev/null +++ b/core/cmake/modules/FindExiv2.cmake @@ -0,0 +1,116 @@ +# - Try to find the Exiv2 library +# +# EXIV2_MIN_VERSION - You can set this variable to the minimum version you need +# before doing FIND_PACKAGE(Exiv2). The default is 0.26. +# +# Once done this will define +# +# EXIV2_FOUND - system has libexiv2 +# EXIV2_VERSION - the version of libexiv2 +# EXIV2_INCLUDE_DIR - the libexiv2 include directory +# EXIV2_LIBRARIES - Link these to use libexiv2 +# EXIV2_DEFINITIONS - Compiler switches required for using libexiv2 +# +# The minimum required version of Exiv2 can be specified using the +# standard syntax, e.g. find_package(Exiv2 0.26) +# +# For compatibility, also the variable EXIV2_MIN_VERSION can be set to the minimum version +# you need before doing FIND_PACKAGE(Exiv2). The default is 0.26. +# +# Copyright (c) 2010, Alexander Neundorf, +# Copyright (c) 2008-2019, Gilles Caulier, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +# Support EXIV2_MIN_VERSION for compatibility: + +if(NOT Exiv2_FIND_VERSION) + + set(Exiv2_FIND_VERSION "${EXIV2_MIN_VERSION}") + +endif() + +# The minimum version of exiv2 we require +if(NOT Exiv2_FIND_VERSION) + + set(Exiv2_FIND_VERSION "0.26") + +endif() + +if(NOT WIN32) + + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + pkg_check_modules(PC_EXIV2 QUIET exiv2) + set(EXIV2_DEFINITIONS ${PC_EXIV2_CFLAGS_OTHER}) + +endif() + +find_path(EXIV2_INCLUDE_DIR NAMES exiv2/exif.hpp + HINTS + ${PC_EXIV2_INCLUDEDIR} + ${PC_EXIV2_INCLUDE_DIRS} + ) + +find_library(EXIV2_LIBRARY NAMES exiv2 libexiv2 exiv2lib + HINTS + ${PC_EXIV2_LIBDIR} + ${PC_EXIV2_LIBRARY_DIRS} + ) + +if (EXIV2_INCLUDE_DIR AND NOT EXIV2_VERSION) + + # For Exiv2 <= 0.26, get the version number from exiv2/version.hpp and store it in the cache: + + file(READ ${EXIV2_INCLUDE_DIR}/exiv2/version.hpp EXIV2_VERSION_CONTENT) + string(REGEX MATCH "#define EXIV2_MAJOR_VERSION +\\( *([0-9]+) *\\)" _dummy "${EXIV2_VERSION_CONTENT}") + set(EXIV2_VERSION_MAJOR "${CMAKE_MATCH_1}") + + string(REGEX MATCH "#define EXIV2_MINOR_VERSION +\\( *([0-9]+) *\\)" _dummy "${EXIV2_VERSION_CONTENT}") + set(EXIV2_VERSION_MINOR "${CMAKE_MATCH_1}") + + string(REGEX MATCH "#define EXIV2_PATCH_VERSION +\\( *([0-9]+) *\\)" _dummy "${EXIV2_VERSION_CONTENT}") + set(EXIV2_VERSION_PATCH "${CMAKE_MATCH_1}") + + if(NOT "${EXIV2_VERSION_MAJOR}" STREQUAL "" AND + NOT "${EXIV2_VERSION_MINOR}" STREQUAL "" AND + NOT "${EXIV2_VERSION_PATCH}" STREQUAL "") + + set(EXIV2_VERSION "${EXIV2_VERSION_MAJOR}.${EXIV2_VERSION_MINOR}.${EXIV2_VERSION_PATCH}" + CACHE STRING "Version number of Exiv2" FORCE) + else() + + # For Exiv2 >= 0.27, get the version number from exiv2/exv_conf.h and store it in the cache: + + file(READ ${EXIV2_INCLUDE_DIR}/exiv2/exv_conf.h EXIV2_VERSION_CONTENT) + string(REGEX MATCH "#define EXIV2_MAJOR_VERSION +\\( *([0-9]+) *\\)" _dummy "${EXIV2_VERSION_CONTENT}") + set(EXIV2_VERSION_MAJOR "${CMAKE_MATCH_1}") + + string(REGEX MATCH "#define EXIV2_MINOR_VERSION +\\( *([0-9]+) *\\)" _dummy "${EXIV2_VERSION_CONTENT}") + set(EXIV2_VERSION_MINOR "${CMAKE_MATCH_1}") + + string(REGEX MATCH "#define EXIV2_PATCH_VERSION +\\( *([0-9]+) *\\)" _dummy "${EXIV2_VERSION_CONTENT}") + set(EXIV2_VERSION_PATCH "${CMAKE_MATCH_1}") + + set(EXIV2_VERSION "${EXIV2_VERSION_MAJOR}.${EXIV2_VERSION_MINOR}.${EXIV2_VERSION_PATCH}" + CACHE STRING "Version number of Exiv2" FORCE) + + endif() + +endif() + +set(EXIV2_LIBRARIES "${EXIV2_LIBRARY}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Exiv2 REQUIRED_VARS EXIV2_LIBRARY EXIV2_INCLUDE_DIR + VERSION_VAR EXIV2_VERSION) + +MESSAGE(STATUS "EXIV2_FOUND = ${EXIV2_FOUND}") +MESSAGE(STATUS "EXIV2_VERSION = ${EXIV2_VERSION}") +MESSAGE(STATUS "EXIV2_INCLUDE_DIR = ${EXIV2_INCLUDE_DIR}") +MESSAGE(STATUS "EXIV2_LIBRARY = ${EXIV2_LIBRARY}") +MESSAGE(STATUS "EXIV2_DEFINITIONS = ${EXIV2_DEFINITIONS}") + +mark_as_advanced(EXIV2_INCLUDE_DIR EXIV2_LIBRARY) diff --git a/core/libs/metadataengine/CMakeLists.txt b/core/libs/metadataengine/CMakeLists.txt index 9e3a026035..596c701516 100644 --- a/core/libs/metadataengine/CMakeLists.txt +++ b/core/libs/metadataengine/CMakeLists.txt @@ -9,16 +9,15 @@ APPLY_COMMON_POLICIES() kde_enable_exceptions() -# TODO: How to extract exiv2lib definitions properties with cmake import interface? -#add_definitions($) +add_definitions(${EXIV2_DEFINITIONS}) if(WIN32) - add_definitions(-DEXV_HAVE_DLL) + add_definitions( -DEXV_HAVE_DLL ) endif() # Exiv2 version < 0.28 use auto_ptr instead unique_ptr which is deprecated. -if("${exiv2_VERSION}" VERSION_LESS "0.27.99") +if("${EXIV2_VERSION}" VERSION_LESS "0.27.99") DISABLE_GCC_COMPILER_WARNINGS("5.99.99" "-Wno-deprecated") @@ -90,14 +89,13 @@ set(libdmetadata_SRCS ) include_directories( + ${EXIV2_INCLUDE_DIR} $ $ $ $ $ - - $ ) # Used by digikamcore diff --git a/core/libs/metadataengine/engine/metaengine_xmp.cpp b/core/libs/metadataengine/engine/metaengine_xmp.cpp index f5d694dfc9..ff7771001a 100644 --- a/core/libs/metadataengine/engine/metaengine_xmp.cpp +++ b/core/libs/metadataengine/engine/metaengine_xmp.cpp @@ -1234,7 +1234,28 @@ bool MetaEngine::removeXmpTag(const char* xmpTagName, bool family) const } else { - d->xmpMetadata().eraseFamily(it); + // https://github.com/Exiv2/exiv2/issues/521 + // delete 'children' of XMP composites (XmpSeq and XmpBag) + + // I build a StringVector of keys to remove + // Then I remove them with erase(....) + // erase() has nasty side effects on its argument + // The side effects are avoided by the two-step approach + // https://github.com/Exiv2/exiv2/issues/560 + std::string key(it->key()); + Exiv2::StringVector keys; + while ( it != d->xmpMetadata().end() ) { + if ( it->key().find(key)==0 ) { + keys.push_back(it->key()); + it++; + } else { + break; + } + } + // now erase the family! + for ( Exiv2::StringVector_i i = keys.begin() ; i != keys.end() ; i++ ) { + d->xmpMetadata().erase(d->xmpMetadata().findKey(Exiv2::XmpKey(*i))); + } } return true; -- 2.31.1