cmake_minimum_required(VERSION 3.20)
project(m2comp VERSION 0.5.4 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(PkgConfig REQUIRED)
pkg_check_modules(LV2 REQUIRED lv2)
pkg_check_modules(CAIRO REQUIRED cairo)
pkg_check_modules(FFTW3 REQUIRED fftw3)

add_library(${PROJECT_NAME} MODULE
    src/m2comp.cpp
    src/ui/inline_display.cpp
    src/ui/crossover_response.cpp
)

target_include_directories(${PROJECT_NAME} PRIVATE
    ${CMAKE_SOURCE_DIR}/src
    ${LV2_INCLUDE_DIRS}
    ${CAIRO_INCLUDE_DIRS}
    ${FFTW3_INCLUDE_DIRS}
)

target_link_libraries(${PROJECT_NAME} PRIVATE
    ${CAIRO_LIBRARIES}
    ${FFTW3_LIBRARIES}
)

set_target_properties(${PROJECT_NAME} PROPERTIES
    PREFIX ""
    SUFFIX ".so"
    INTERPROCEDURAL_OPTIMIZATION TRUE
)

target_compile_options(${PROJECT_NAME} PRIVATE
    -O3
    -march=native
    -mtune=native
    -fno-math-errno
    -funroll-loops
    -fomit-frame-pointer
    -fno-exceptions
    -fno-rtti
    -fvisibility=hidden
    -Wall -Wextra
    -ffp-contract=off
)

# x86-64 only: enable AVX2/FMA explicitly (also implied by -march=native
# on AVX2-capable CPUs, but kept explicit for older toolchains).
if(CMAKE_SYSTEM_PROCESSOR MATCHES "[Xx]86|[Aa][Mm][Dd]64")
    target_compile_options(${PROJECT_NAME} PRIVATE -mavx2 -mfma)
endif()

target_link_options(${PROJECT_NAME} PRIVATE
    -Wl,-O1
    -Wl,--as-needed
    -Wl,--strip-all
)

#---test---------#

enable_testing()

function(m2comp_add_test name)
    add_executable(${name} tests/${name}.cpp)
    target_include_directories(${name} PRIVATE
        ${CMAKE_SOURCE_DIR}/src
        ${FFTW3_INCLUDE_DIRS}
    )
    target_compile_options(${name} PRIVATE
        -O2
        -ffp-contract=off
        -Wall -Wextra
        # Tests rely on assert() for validation. Release builds define
        # NDEBUG, which disables assert() entirely. Undefine it so the
        # assertions actually run and the test suite is meaningful.
        -UNDEBUG
    )
    target_link_libraries(${name} PRIVATE ${FFTW3_LIBRARIES})
    add_test(NAME ${name} COMMAND ${name})
endfunction()

m2comp_add_test(test_crossover)
m2comp_add_test(test_upsampler)
m2comp_add_test(test_integration)
m2comp_add_test(test_compressor)
m2comp_add_test(test_multiband)
m2comp_add_test(test_stereo)
m2comp_add_test(test_mono)

#------------------------------------#

set(LV2_INSTALL_DIR "$ENV{HOME}/.lv2/${PROJECT_NAME}.lv2")

install(TARGETS ${PROJECT_NAME}
    LIBRARY DESTINATION ${LV2_INSTALL_DIR}
)

install(FILES
    ttl/manifest.ttl
    ttl/m2comp.ttl
    ttl/m2comp_mono.ttl
    DESTINATION ${LV2_INSTALL_DIR}
)

add_custom_target(build_and_install
    DEPENDS ${PROJECT_NAME}
    COMMAND ${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR}
    COMMENT "Building and installing ${PROJECT_NAME}.lv2 to ${LV2_INSTALL_DIR}"
)
