Exiv2/exiv2

Build failure due to `strerror_r` type mismatch

Opened this issue · 1 comments

Describe the bug

I'm building exiv2 for Android to use it with rexiv2, a Rust crate that wraps gexiv2.

However, the exiv2 build failed due to a type error. See the following:

Build script:
#!/usr/bin/env fish

set -x SDK_HOME $HOME/Android/Sdk
set -x NDK_HOME $SDK_HOME/ndk/27.1.12297006

set -x ANDROID_SDK_HOME $SDK_HOME
set -x ANDROID_NDK_HOME $NDK_HOME

set -x TOOLCHAIN $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
set -x SYSROOT $TOOLCHAIN/sysroot
set -x PATH $TOOLCHAIN/bin $PATH

set -x PKG_CONFIG_ALLOW_CROSS 1
set -x TARGET x86_64-linux-android

cd build
cd exiv2
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$SYSROOT/usr \
-DCMAKE_TOOLCHAIN_FILE=$NDK_HOME/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=x86_64 \
-DANDROID_PLATFORM=android-28 \
-DEXIV2_ENABLE_XMP=ON \
-DEXIV2_ENABLE_PNG=ON \
-DEXIV2_ENABLE_WEBREADY=ON \
-DCMAKE_BUILD_TYPE=Release
cmake --build build
cmake --install build
cd ../..
Output:
barrett@farts ~/D/p/backdrop (main)> ./build_android/build_exiv2.fish
-- Iconv_INCLUDE_DIRS : /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include
-- Iconv_LIBRARIES : /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/libiconv.so
-- inih_INCLUDE_DIRS : /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include
-- inih_LIBRARIES : /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/libinih.so
-- inih_inireader_INCLUDE_DIRS : /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include
-- inih_inireader_LIBRARIES : /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/libINIReader.so
-- Install prefix:    /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr
-- ------------------------------------------------------------------
-- CMake Generator:   Unix Makefiles
-- CMAKE_BUILD_TYPE:  Release
-- Compiler info: Clang (/home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++) ; version: 18.0.2
-- CMAKE_CXX_STANDARD:17
--  --- Compiler flags --- 
-- General:           -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security  
	 -fstack-clash-protection
	 -fcf-protection
	 -fstack-protector-strong
	 -Wp,-D_GLIBCXX_ASSERTIONS
	 -Wp,-D_FORTIFY_SOURCE=2
	 -Wall
	 -Wcast-align
	 -Wpointer-arith
	 -Wformat-security
	 -Wmissing-format-attribute
	 -Woverloaded-virtual
	 -W
	 -Wno-error=format-nonliteral
-- Extra:              
-- Debug:             -g3 -gstrict-dwarf -O0
-- Release:           -O3 -DNDEBUG 
-- RelWithDebInfo:    -O2 -g -DNDEBUG
-- MinSizeRel:        -Os -DNDEBUG
--  --- Linker flags --- 
-- General:           -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments  
-- Debug:             
-- Release:           -Wl,--gc-sections 
-- RelWithDebInfo:    -Wl,--gc-sections 
-- MinSizeRel:        -Wl,--gc-sections 
-- 
-- Compiler Options
-- Warnings as errors:                 NO
-- Use extra compiler warning flags:   NO
-- 
-- ------------------------------------------------------------------
-- Building shared library:            YES
-- Building PNG support:               YES
-- XMP metadata support:               YES
-- Building BMFF support:              YES
-- Brotli support for JPEG XL:         YES
-- Native language support:            NO
-- Building video support:             YES
-- Nikon lens database:                YES
-- Building webready support:          YES
-- USE Libcurl for HttpIo:             NO
-- Building exiv2 command:             YES
-- Building samples:                   NO
-- Building unit tests:                NO
-- Building fuzz tests:                NO
-- Building doc:                       NO
-- Building with coverage flags:       NO
-- Building with filesystem access     YES
-- Using ccache:                       NO
-- Configuring done (0.1s)
-- Generating done (0.0s)
-- Build files have been written to: /home/barrett/Documents/projects/backdrop/build/exiv2/build
[ 17%] Built target exiv2-xmp
[ 46%] Built target exiv2lib_int
[ 47%] Building CXX object src/CMakeFiles/exiv2lib.dir/convert.cpp.o
[ 48%] Building CXX object src/CMakeFiles/exiv2lib.dir/cr2image.cpp.o
[ 49%] Building CXX object src/CMakeFiles/exiv2lib.dir/crwimage.cpp.o
[ 50%] Building CXX object src/CMakeFiles/exiv2lib.dir/datasets.cpp.o
[ 51%] Building CXX object src/CMakeFiles/exiv2lib.dir/easyaccess.cpp.o
[ 52%] Building CXX object src/CMakeFiles/exiv2lib.dir/epsimage.cpp.o
[ 53%] Building CXX object src/CMakeFiles/exiv2lib.dir/error.cpp.o
[ 55%] Building CXX object src/CMakeFiles/exiv2lib.dir/exif.cpp.o
[ 56%] Building CXX object src/CMakeFiles/exiv2lib.dir/futils.cpp.o
/home/barrett/Documents/projects/backdrop/build/exiv2/src/futils.cpp:253:13: error: cannot initialize a variable of type 'const int' with an rvalue of type 'char * _Nonnull'
  253 |   const int ret = strerror_r(error, buf, n);
      |             ^     ~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
gmake[2]: *** [src/CMakeFiles/exiv2lib.dir/build.make:244: src/CMakeFiles/exiv2lib.dir/futils.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:972: src/CMakeFiles/exiv2lib.dir/all] Error 2
gmake: *** [Makefile:146: all] Error 2
-- Install configuration: "Release"
-- Up-to-date: /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/pkgconfig/exiv2.pc
-- Up-to-date: /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/share/man/man1/exiv2.1
CMake Error at build/src/cmake_install.cmake:52 (file):
  file INSTALL cannot find
  "/home/barrett/Documents/projects/backdrop/build/exiv2/build/lib/libexiv2.so":
  No such file or directory.
Call Stack (most recent call first):
  build/cmake_install.cmake:56 (include)

To Reproduce

Steps to reproduce the behavior:

  1. Have a weird system using a non-compliant implementation of strerror_r.
  2. Build exiv2 with typical settings.

Expected behavior

The build should succeed without requiring manual changes to the source.

Desktop (please complete the following information):

  • OS and version: Linux (Fedora 40 Workstation); Android (NDK 27.1.12297006)
  • Exiv2 version and source: 0.28.x, GitHub; Commit: a6a79ef0
  • Compiler and version:
barrett@farts ~/A/S/n/2/t/l/p/l/bin> ./x86_64-linux-android28-clang++ --version
Android (12285214, +pgo, +bolt, +lto, +mlgo, based on r522817b) clang version 18.0.2 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)
Target: x86_64-unknown-linux-android28
Thread model: posix
InstalledDir: /home/barrett/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/.
  • Compilation mode and/or compiler flags: See build script. (but nothing too special I think?)

Additional context

I was able to bypass the issue by changing `exiv2/src/futils.cpp:253.

Before:

const int ret = strerror_r(error, buf, n);

After:

const int ret = *strerror_r(error, buf, n);

I'm not extremely knowledgeable about what the surrounding code is doing, but I remember facing this problem in the past.

I think there are different implementations of the function?

Yep, there are the POSIX and GNU ones: https://linux.die.net/man/3/strerror_r

We already try to detect which one is supported here:

}" EXV_STRERROR_R_CHAR_P )

(and equivalently if building w/ Meson...)

That seems to be correctly used here:

exiv2/src/futils.cpp

Lines 249 to 256 in 902c154

#ifdef EXV_STRERROR_R_CHAR_P
char buf2[n] = {};
auto buf = strerror_r(error, buf2, n);
#else
char buf[n] = {};
const int ret = strerror_r(error, buf, n);
Internal::enforce(ret != ERANGE, Exiv2::ErrorCode::kerCallFailed);
#endif

So it looks like you'll need to figure out why EXV_HAVE_STRERROR_R is not being set correctly when building for Android?