cmake_minimum_required(VERSION 3.16)
project(eilik VERSION 0.3.0 LANGUAGES C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
add_compile_options(-Wall -Wextra)

# Building a Python wheel does not need the test executables, and building
# them there would slow every `pip install` from source for no benefit.
option(EILIK_BUILD_TESTS "Build the test executables" ON)

add_library(eilik src/frame.c src/servo.c src/display.c src/link.c src/eilik.c)
target_include_directories(eilik
    PUBLIC  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# Only the functions marked EILIK_API in include/eilik.h are exported. The
# framer, link and servo helpers are implementation detail: exporting them
# would advertise a way round the API and freeze their signatures into the ABI.
set_target_properties(eilik PROPERTIES
    C_VISIBILITY_PRESET       hidden
    VISIBILITY_INLINES_HIDDEN ON)
if(APPLE)
    target_link_libraries(eilik PRIVATE "-framework IOKit")
endif()

if(EILIK_BUILD_TESTS)
enable_testing()

add_executable(test_frame tests/test_frame.c src/frame.c)
target_include_directories(test_frame PRIVATE src)
add_test(NAME frame COMMAND test_frame)

add_executable(test_servo tests/test_servo.c src/servo.c)
target_include_directories(test_servo PRIVATE src)
add_test(NAME servo COMMAND test_servo)

add_executable(test_display tests/test_display.c src/display.c)
target_include_directories(test_display PRIVATE src)
add_test(NAME display COMMAND test_display)

add_executable(test_link tests/test_link.c src/link.c src/frame.c)
target_include_directories(test_link PRIVATE src)
add_test(NAME link COMMAND test_link)
if(APPLE)
    target_link_libraries(test_link PRIVATE "-framework IOKit")
endif()

add_executable(test_api tests/test_api.c src/eilik.c src/link.c src/frame.c src/servo.c src/display.c)
target_include_directories(test_api PRIVATE src include)
add_test(NAME api COMMAND test_api)
if(APPLE)
    target_link_libraries(test_api PRIVATE "-framework IOKit")
endif()

# Includes src/eilik.c rather than linking it, to see struct eilik.
add_executable(test_stage tests/test_stage.c src/link.c src/frame.c src/servo.c src/display.c)
target_include_directories(test_stage PRIVATE src include)
add_test(NAME stage COMMAND test_stage)
if(APPLE)
    target_link_libraries(test_stage PRIVATE "-framework IOKit")
endif()
endif()  # EILIK_BUILD_TESTS

include(GNUInstallDirs)

set_target_properties(eilik PROPERTIES
    VERSION   ${PROJECT_VERSION}
    SOVERSION ${PROJECT_VERSION_MAJOR}
    PUBLIC_HEADER include/eilik.h)

configure_file(eilik.pc.in eilik.pc @ONLY)

if(SKBUILD)
    # Building a Python wheel. The shared library travels inside the package
    # directory, which is the first place python/eilik/_lib.py looks, so an
    # installed wheel works with no system install and no EILIK_LIBRARY set.
    # The header and the pkg-config file are for C consumers and have no place
    # in a wheel, so they are not installed here.
    install(TARGETS eilik LIBRARY DESTINATION ${SKBUILD_PLATLIB_DIR}/eilik)
else()
    install(TARGETS eilik
        LIBRARY       DESTINATION ${CMAKE_INSTALL_LIBDIR}
        ARCHIVE       DESTINATION ${CMAKE_INSTALL_LIBDIR}
        PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eilik.pc
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
