From 6b62f126b4f3717734f545c4d629605c6456153c Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Wed, 29 Nov 2023 11:40:06 +0100 Subject: [PATCH] Redefine avif_internal. Now define avif_obj on which avif and avif_internal depend. There is only one compilation happening. Only symbol export is different between the two libs --- CMakeLists.txt | 73 ++++++++++++++++++++++++++--------------- include/avif/internal.h | 4 +++ tests/CMakeLists.txt | 2 +- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18629ae4c7..da6b6821d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -676,23 +676,32 @@ if(NOT AVIF_CODEC_AOM message(WARNING "libavif: No decoding library is enabled.") endif() -add_library(avif ${AVIF_SRCS}) -set_target_properties(avif PROPERTIES VERSION ${LIBRARY_VERSION} SOVERSION ${LIBRARY_SOVERSION} C_VISIBILITY_PRESET hidden) -target_compile_definitions(avif PRIVATE ${AVIF_PLATFORM_DEFINITIONS} ${AVIF_CODEC_DEFINITIONS}) -target_link_libraries(avif PRIVATE ${AVIF_CODEC_LIBRARIES} ${AVIF_PLATFORM_LIBRARIES}) -target_include_directories(avif PUBLIC $ $) -target_include_directories(avif PRIVATE ${AVIF_PLATFORM_INCLUDES} ${AVIF_CODEC_INCLUDES}) -target_include_directories(avif SYSTEM PRIVATE ${AVIF_PLATFORM_SYSTEM_INCLUDES} ${AVIF_CODEC_SYSTEM_INCLUDES}) +add_library(avif_obj OBJECT ${AVIF_SRCS}) +set_target_properties(avif_obj PROPERTIES C_VISIBILITY_PRESET hidden) +set_property(TARGET avif_obj PROPERTY POSITION_INDEPENDENT_CODE ON) +target_compile_definitions(avif_obj PRIVATE ${AVIF_PLATFORM_DEFINITIONS} ${AVIF_CODEC_DEFINITIONS}) +target_link_libraries(avif_obj PRIVATE ${AVIF_CODEC_LIBRARIES} ${AVIF_PLATFORM_LIBRARIES}) +target_include_directories(avif_obj PUBLIC ${libavif_SOURCE_DIR}/include) +target_include_directories(avif_obj PRIVATE ${AVIF_PLATFORM_INCLUDES} ${AVIF_CODEC_INCLUDES}) +target_include_directories(avif_obj SYSTEM PRIVATE ${AVIF_PLATFORM_SYSTEM_INCLUDES} ${AVIF_CODEC_SYSTEM_INCLUDES}) if(NOT libyuv_FOUND) - target_include_directories(avif PRIVATE ${libavif_SOURCE_DIR}/third_party/libyuv/include/) + target_include_directories(avif_obj PRIVATE ${libavif_SOURCE_DIR}/third_party/libyuv/include/) endif() if(AVIF_ENABLE_COMPLIANCE_WARDEN) - target_include_directories(avif PRIVATE ${libavif_SOURCE_DIR}/ext/ComplianceWarden/src/utils/) + target_include_directories(avif_obj PRIVATE ${libavif_SOURCE_DIR}/ext/ComplianceWarden/src/utils/) endif() set(AVIF_PKG_CONFIG_EXTRA_CFLAGS "") if(BUILD_SHARED_LIBS) - target_compile_definitions(avif PUBLIC AVIF_DLL PRIVATE AVIF_BUILDING_SHARED_LIBS) + target_compile_definitions(avif_obj PUBLIC AVIF_DLL PRIVATE AVIF_BUILDING_SHARED_LIBS) set(AVIF_PKG_CONFIG_EXTRA_CFLAGS " -DAVIF_DLL") +endif() + +# Main library. +add_library(avif $) +set_target_properties(avif PROPERTIES VERSION ${LIBRARY_VERSION} SOVERSION ${LIBRARY_SOVERSION} C_VISIBILITY_PRESET hidden) +target_link_libraries(avif PRIVATE "$") +target_include_directories(avif PUBLIC $ $) +if(BUILD_SHARED_LIBS) if(AVIF_USE_CXX) set_target_properties(avif PROPERTIES LINKER_LANGUAGE "CXX") endif() @@ -701,16 +710,12 @@ endif() # Give access to functions defined in internal.h when BUILD_SHARED_LIBS is ON, to tests for example. # The avif_internal target should not be used by external code. if(BUILD_SHARED_LIBS) - add_library(avif_internal STATIC ${AVIF_SRCS}) - # Copy or duplicate most properties from the public avif library target. - target_compile_definitions(avif_internal PRIVATE "$") - target_link_libraries(avif_internal PRIVATE "$") + add_library(avif_internal STATIC $) + target_link_libraries(avif_internal PRIVATE "$") target_include_directories(avif_internal PUBLIC ${libavif_SOURCE_DIR}/include) - target_include_directories(avif_internal PRIVATE ${AVIF_PLATFORM_INCLUDES} ${AVIF_CODEC_INCLUDES}) - target_include_directories(avif_internal SYSTEM PRIVATE ${AVIF_PLATFORM_SYSTEM_INCLUDES} ${AVIF_CODEC_SYSTEM_INCLUDES}) - if(NOT libyuv_FOUND) - target_include_directories(avif_internal PRIVATE ${libavif_SOURCE_DIR}/third_party/libyuv/include/) - endif() + # Define the following to avoid linking against the two at the same time. + target_compile_definitions(avif PUBLIC $) + target_compile_definitions(avif_internal PUBLIC AVIF_BUILDING_STATIC_LIBS) else() add_library(avif_internal ALIAS avif) include(merge_static_libs) @@ -774,28 +779,42 @@ if(AVIF_BUILD_APPS OR (AVIF_BUILD_TESTS AND (AVIF_ENABLE_FUZZTEST OR AVIF_ENABLE endif() add_library( - avif_apps STATIC apps/shared/avifexif.c apps/shared/avifjpeg.c apps/shared/avifpng.c apps/shared/avifutil.c - apps/shared/iccmaker.c apps/shared/y4m.c third_party/iccjpeg/iccjpeg.c + avif_apps_obj OBJECT $ apps/shared/avifexif.c apps/shared/avifjpeg.c apps/shared/avifpng.c + apps/shared/avifutil.c apps/shared/iccmaker.c apps/shared/y4m.c third_party/iccjpeg/iccjpeg.c ) - target_link_libraries(avif_apps avif ${AVIF_PLATFORM_LIBRARIES} ${PNG_LIBRARY} ${ZLIB_LIBRARY} ${JPEG_LIBRARY}) + set_property(TARGET avif_apps_obj PROPERTY POSITION_INDEPENDENT_CODE ON) + target_link_libraries(avif_apps_obj ${AVIF_PLATFORM_LIBRARIES} ${PNG_LIBRARY} ${ZLIB_LIBRARY} ${JPEG_LIBRARY}) # In GitHub CI's macos-latest os image, /usr/local/include has not only the headers of libpng # and libjpeg but also the headers of an older version of libavif. Put the avif include # directory before ${PNG_PNG_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} to prevent picking up old libavif # headers from /usr/local/include. - target_include_directories(avif_apps PRIVATE $ third_party/iccjpeg) - target_include_directories(avif_apps SYSTEM PRIVATE ${PNG_PNG_INCLUDE_DIR} ${JPEG_INCLUDE_DIR}) - target_include_directories(avif_apps INTERFACE apps/shared) + target_include_directories(avif_apps_obj PRIVATE $ third_party/iccjpeg) + target_include_directories(avif_apps_obj SYSTEM PRIVATE ${PNG_PNG_INCLUDE_DIR} ${JPEG_INCLUDE_DIR}) if(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP) if(LIBXML2_FOUND) set(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION TRUE) add_compile_definitions(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) - target_link_libraries(avif_apps ${LIBXML2_LIBRARY}) - target_include_directories(avif_apps SYSTEM PRIVATE ${LIBXML2_INCLUDE_DIR}) + target_link_libraries(avif_apps_obj ${LIBXML2_LIBRARY}) + target_include_directories(avif_apps_obj SYSTEM PRIVATE ${LIBXML2_INCLUDE_DIR}) else() message(STATUS "libavif: libxml2 not found; avifenc will ignore any gain map in jpeg files") endif() endif() + + # Main avif_apps library. + add_library(avif_apps $) + target_link_libraries(avif_apps PUBLIC avif PRIVATE "$") + target_include_directories(avif_apps INTERFACE apps/shared) + + # avif_apps_internal is to use when linking to avif_internal. + if(BUILD_SHARED_LIBS) + add_library(avif_apps_internal STATIC $) + target_link_libraries(avif_apps_internal PUBLIC avif_internal PRIVATE "$") + target_include_directories(avif_apps_internal INTERFACE apps/shared) + else() + add_library(avif_apps_internal ALIAS avif_apps) + endif() endif() if(AVIF_BUILD_APPS) diff --git a/include/avif/internal.h b/include/avif/internal.h index c13e298bec..d14cbe99ec 100644 --- a/include/avif/internal.h +++ b/include/avif/internal.h @@ -656,6 +656,10 @@ AVIF_NODISCARD avifBool avifSequenceHeaderParse(avifSequenceHeader * header, con #define AVIF_INDEFINITE_DURATION64 UINT64_MAX #define AVIF_INDEFINITE_DURATION32 UINT32_MAX +#if defined(AVIF_BUILDING_SHARED_LIBS) && defined(AVIF_BUILDING_STATIC_LIBS) +#error "Your target is linking against avif and avif_internal: only one should be chosen" +#endif + #ifdef __cplusplus } // extern "C" #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d174e0536c..95d930b9d3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -41,7 +41,7 @@ endforeach() if(AVIF_ENABLE_FUZZTEST OR AVIF_ENABLE_GTEST OR AVIF_BUILD_APPS) add_library(aviftest_helpers OBJECT gtest/aviftest_helpers.cc) - target_link_libraries(aviftest_helpers avif_apps avif_internal) + target_link_libraries(aviftest_helpers avif_apps_internal avif_internal) endif() # Fuzz target without any fuzzing engine dependency. For easy reproduction of oss-fuzz issues.