• CMakeLists.txt
  • cmake_minimum_required(VERSION 3.25)
    
    include_directories(include)
    include_directories(src/include)
    
    add_definitions("-DFLAC__NO_DLL")
    cmake_minimum_required(VERSION 3.12...3.31)
    
    if(NOT (CMAKE_BUILD_TYPE OR CMAKE_CONFIGURATION_TYPES OR DEFINED ENV{CFLAGS} OR DEFINED ENV{CXXFLAGS}))
        set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo")
    endif()
    
    set(WITH_FORTIFY_SOURCE ON)
    set(WITH_STACK_PROTECTOR ON)
    set(WITH_OGG ON)
    set(ENABLE_MULTITHREADING ON)
    
    if(NOT UNIX)
        # This is to make sure testing works when building with a DLL
        set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/objs)
        set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/objs)
    endif()
    
    set(OGG_PACKAGE "ogg")
    
    if(NOT WIN32)
        find_package(Iconv)
        set(HAVE_ICONV ${Iconv_FOUND})
    endif()
    
    if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
        set(CMAKE_C_FLAGS "-Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return -Wcast-align -Wnested-externs -Wshadow -Wundef -Wmissing-declarations -Winline ${CMAKE_C_FLAGS}")
        set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG ${CMAKE_C_FLAGS_RELEASE}")
    endif()
    if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
        set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wcast-align -Wshadow -Wwrite-strings -Wctor-dtor-privacy -Wnon-virtual-dtor -Wreorder -Wsign-promo -Wundef ${CMAKE_CXX_FLAGS}")
        set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${CMAKE_CXX_FLAGS_RELEASE}")
    endif()
    if(MSVC)
        set(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /Oi /Ot /Oy /DNDEBUG ${CMAKE_C_FLAGS_RELEASE}")
    endif()
    
    include(CMakePackageConfigHelpers)
    include(CheckCCompilerFlag)
    include(CheckCXXCompilerFlag)
    include(CheckSymbolExists)
    include(CheckFunctionExists)
    include(CheckIncludeFile)
    include(CheckCSourceCompiles)
    include(CheckCXXSourceCompiles)
    include(CheckLibraryExists)
    include(GNUInstallDirs)
    include(TestBigEndian)
    
    check_include_file("byteswap.h" HAVE_BYTESWAP_H)
    check_include_file("inttypes.h" HAVE_INTTYPES_H)
    check_include_file("stdint.h" HAVE_STDINT_H)
    check_include_file("stdbool.h" HAVE_STDBOOL_H)
    check_include_file("arm_neon.h" FLAC__HAS_NEONINTRIN)
    
    if(NOT HAVE_STDINT_H OR NOT HAVE_STDBOOL_H)
        message(SEND_ERROR "Header stdint.h and/or stdbool.h not found")
    endif()
    
    if(MSVC)
        check_include_file("intrin.h" FLAC__HAS_X86INTRIN)
    else()
        check_include_file("x86intrin.h" FLAC__HAS_X86INTRIN)
    endif()
    
    
    check_function_exists(fseeko HAVE_FSEEKO)
    
    check_c_source_compiles("int main() { return __builtin_bswap16 (0) ; }" HAVE_BSWAP16)
    check_c_source_compiles("int main() { return __builtin_bswap32 (0) ; }" HAVE_BSWAP32)
    check_c_source_compiles("
        #include <langinfo.h>
        int main()
        {
            char* cs = nl_langinfo(CODESET);
            return !cs;
        }"
        HAVE_LANGINFO_CODESET)
    
    test_big_endian(CPU_IS_BIG_ENDIAN)
    
    check_c_compiler_flag(-Werror HAVE_WERROR_FLAG)
    check_c_compiler_flag(-Wdeclaration-after-statement HAVE_DECL_AFTER_STMT_FLAG)
    check_c_compiler_flag(-mstackrealign HAVE_STACKREALIGN_FLAG)
    check_cxx_compiler_flag(-Weffc++ HAVE_WEFFCXX_FLAG)
    
    if(MINGW AND (WITH_FORTIFY_SOURCE OR WITH_STACK_PROTECTOR))
      check_library_exists("ssp.a"  __stack_chk_fail "" HAVE_LIBSSP)
      if(NOT HAVE_LIBSSP)
        message(WARNING "Could not find libssp in MinGW, stack protection and/or FORTIFY_SOURCE are unavailable")
      else()
        link_libraries("ssp.a")
        # static libraries don't carry over other static libraries in mingw
        # we need to export it in the pkg-config
        set(FLAC_STATIC_LIBS "-lssp")
      endif()
    elseif(NOT MSVC)
      set(HAVE_LIBSSP 1)
    endif()
    
    if(WITH_STACK_PROTECTOR)
      if(NOT MSVC AND NOT EMSCRIPTEN)
        check_c_compiler_flag("-fstack-protector-strong" HAVE_STACK_PROTECTOR_FLAG)
      endif()
    endif()
    
    add_compile_options(
        $<$<BOOL:${MSVC}>:/wd4267>
        $<$<BOOL:${MSVC}>:/wd4996>
        $<$<BOOL:${ENABLE_WERROR}>:-Werror>
        $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<BOOL:${HAVE_WEFFCXX_FLAG}>>:-Weffc++>
        $<$<AND:$<COMPILE_LANGUAGE:C>,$<BOOL:${HAVE_DECL_AFTER_STMT_FLAG}>>:-Wdeclaration-after-statement>)
    
    if(WITH_FORTIFY_SOURCE AND HAVE_LIBSSP)
      add_definitions(-D_FORTIFY_SOURCE=2)
    endif()
    
    if(HAVE_STACK_PROTECTOR_FLAG AND HAVE_LIBSSP)
        add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fstack-protector-strong>)
    endif()
    
    if(CMAKE_SYSTEM_PROCESSOR STREQUAL "i686" AND HAVE_STACKREALIGN_FLAG)
        add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-mstackrealign>)
    endif()
    
    add_definitions(-DHAVE_CONFIG_H)
    
    if(MSVC)
        add_definitions(
            -D_CRT_SECURE_NO_WARNINGS
            -D_USE_MATH_DEFINES)
    endif()
    
    if(CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
        add_definitions(-DFLAC__OVERFLOW_DETECT)
    endif()
    
    set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
    set(THREADS_PREFER_PTHREAD_FLAG TRUE)
    find_package(Threads)
    if(CMAKE_USE_PTHREADS_INIT)
        set(HAVE_PTHREAD 1)
    endif()
    
    configure_file(config.cmake.h.in ${CMAKE_CURRENT_LIST_DIR}/src/include/config.h)
    
    add_library(flac STATIC
        src/bitmath.c
        src/bitreader.c
        src/bitwriter.c
        src/cpu.c
        src/crc.c
        src/fixed.c
        src/float.c
        src/format.c
        src/lpc.c
        src/md5.c
        src/memory.c
        src/metadata_iterators.c
        src/metadata_object.c
        src/stream_decoder.c
        src/stream_encoder.c
        src/stream_encoder_framing.c
        src/window.c
        src/fixed_intrin_sse2.c
        src/fixed_intrin_ssse3.c
        src/fixed_intrin_sse42.c
        src/fixed_intrin_avx2.c
        src/lpc_intrin_neon.c
        src/lpc_intrin_sse2.c
        src/lpc_intrin_sse41.c
        src/lpc_intrin_avx2.c
        src/lpc_intrin_fma.c
        src/stream_encoder_intrin_sse2.c
        src/stream_encoder_intrin_ssse3.c
        src/stream_encoder_intrin_avx2.c
        src/stream_encoder_framing.c
        $<$<BOOL:${WIN32}>:include/share/win_utf8_io.h>
        $<$<BOOL:${WIN32}>:src/win_utf8_io.c>
        $<$<BOOL:${OGG_FOUND}>:src/ogg_decoder_aspect.c>
        $<$<BOOL:${OGG_FOUND}>:src/ogg_encoder_aspect.c>
        $<$<BOOL:${OGG_FOUND}>:src/ogg_helper.c>
        $<$<BOOL:${OGG_FOUND}>:src/ogg_mapping.c>)
    
    target_link_libraries(flac ogg)
    
    target_include_directories(flac PRIVATE src/include include)
    
    IF(WIN32)
        set_target_properties(flac PROPERTIES
            DEBUG_OUTPUT_NAME flac_d
            RELWITHDEBINFO_OUTPUT_NAME  flac_rd
            MINSIZEREL_OUTPUT_NAME  flac_min
        )
    ENDIF()
    
    install(TARGETS flac
        EXPORT GorgonTargets
        ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
        PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}/Gorgon"
    )
    
    export(TARGETS flac APPEND FILE "${PROJECT_PACKAGE_DIR}/GorgonTargets.cmake")