# This program source code file is part of KiCad, a free EDA CAD application.
#
# Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors.
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.

# Search paths for protoc when generating code
set( Protobuf_IMPORT_DIRS ${Protobuf_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/proto )

set( KIAPI_PROTO_SRCS
    common/envelope.proto

    common/types/base_types.proto
    common/types/enums.proto
    common/types/project_settings.proto

    common/commands/base_commands.proto
    common/commands/editor_commands.proto
    common/commands/project_commands.proto

    board/board.proto
    board/board_commands.proto
    board/board_types.proto

    schematic/schematic_types.proto
    schematic/schematic_commands.proto
    )

# Generated C++ code must be in the build dir; it is dependent on the version of protoc installed
set( KIAPI_CPP_BASEPATH ${CMAKE_CURRENT_BINARY_DIR}/cpp/api )

foreach( PROTO_SRC ${KIAPI_PROTO_SRCS} )
    string( REGEX REPLACE "\.proto$" ".pb.cc" CPP_SRC ${PROTO_SRC} )
    string( REGEX REPLACE "\.proto$" ".pb.h" CPP_HEADER ${PROTO_SRC} )
    set( KIAPI_CPP_SRCS ${KIAPI_CPP_SRCS} ${KIAPI_CPP_BASEPATH}/${CPP_SRC} )
    set( KIAPI_CPP_HEADERS ${KIAPI_CPP_HEADERS} ${KIAPI_CPP_BASEPATH}/${CPP_HEADER} )
    set( KIAPI_PROTO_SRC_FULLPATHS ${KIAPI_PROTO_SRC_FULLPATHS} ${CMAKE_CURRENT_SOURCE_DIR}/proto/${PROTO_SRC} )
endforeach ()

add_custom_command( COMMAND ${CMAKE_COMMAND} -E make_directory ${KIAPI_CPP_BASEPATH}
    COMMAND ${Protobuf_PROTOC_EXECUTABLE}
    --cpp_out=dllexport_decl=KIAPI_IMPORTEXPORT:${KIAPI_CPP_BASEPATH}
    --proto_path=${CMAKE_CURRENT_SOURCE_DIR}/proto
    ${KIAPI_PROTO_SRCS}
    COMMENT "Generating API protobuf source files from proto definitions..."
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    DEPENDS ${KIAPI_PROTO_SRC_FULLPATHS}
    OUTPUT ${KIAPI_CPP_SRCS} ${KIAPI_CPP_HEADERS}
    )

# kiapi must be a shared DLL because the protobuf messages can only be initialized once
add_library( kiapi SHARED
    ${CMAKE_CURRENT_SOURCE_DIR}/../include/import_export.h
    ${KIAPI_CPP_SRCS}
    ${KIAPI_CPP_HEADERS}
    )

target_compile_definitions( kiapi PRIVATE KIAPI_IMPORTEXPORT=APIEXPORT )
target_compile_definitions( kiapi INTERFACE KIAPI_IMPORTEXPORT=APIIMPORT )

# https://groups.google.com/g/protobuf/c/PDR1bqRazts
if(MSVC)
    target_compile_options( kiapi PRIVATE /FI${CMAKE_CURRENT_SOURCE_DIR}/../include/import_export.h )
else()
    add_definitions( -include ${CMAKE_CURRENT_SOURCE_DIR}/../include/import_export.h )
endif()

if( APPLE )
    # puts library into the main kicad.app bundle in build tree
    set_target_properties( kiapi PROPERTIES
            LIBRARY_OUTPUT_DIRECTORY "${OSX_BUNDLE_BUILD_LIB_DIR}"
            INSTALL_NAME_DIR "${OSX_BUNDLE_BUILD_LIB_DIR}"
            )
endif()

install( TARGETS
    kiapi
    RUNTIME DESTINATION ${KICAD_LIB}
    LIBRARY DESTINATION ${KICAD_LIB}
    COMPONENT binary
    )

if( KICAD_WIN32_INSTALL_PDBS )
    # Get the PDBs to copy over for MSVC
    install(FILES $<TARGET_PDB_FILE:kiapi> DESTINATION ${KICAD_BIN})
endif()

# Because CMake doesn't guess this from the .cc extension generated by protoc
set_target_properties( kiapi PROPERTIES LINKER_LANGUAGE CXX )

include( ${KICAD_CMAKE_MODULE_PATH}/KiCadVersion.cmake )

# Extract the major and minor build version as a string
string( REGEX MATCH
        "([0-9]+)\\.([0-9]+)\\.([0-9]+)"
        KICAD_MAJOR_MINOR_PATCH_VERSION
        "${KICAD_VERSION}"
    )

set_target_properties( kiapi PROPERTIES SOVERSION ${KICAD_MAJOR_MINOR_PATCH_VERSION} )

target_include_directories( kiapi SYSTEM PUBLIC ${Protobuf_INCLUDE_DIRS} )

target_link_libraries( kiapi protobuf::libprotobuf )

target_include_directories( kiapi INTERFACE
    ${CMAKE_CURRENT_BINARY_DIR}/cpp     # Leaving off the /api/ to make #include statments less ambiguous
    )

# Because when building internally, the generated files do not include the "api" base path
target_include_directories( kiapi PUBLIC ${KIAPI_CPP_BASEPATH} )

if( APPLE )
    # puts library into the main kicad.app bundle in build tree
    set_target_properties( kiapi PROPERTIES
        LIBRARY_OUTPUT_DIRECTORY "${OSX_BUNDLE_BUILD_LIB_DIR}"
        INSTALL_NAME_DIR "${OSX_BUNDLE_BUILD_LIB_DIR}"
    )
    set_target_properties( kiapi PROPERTIES INSTALL_RPATH
            "@executable_path/../Frameworks" )
    set_target_properties( kiapi PROPERTIES BUILD_WITH_INSTALL_RPATH 1 )
endif()