cmake_minimum_required(VERSION 3.18)
project(Yerbacon VERSION 0.0.1 LANGUAGES C CXX)
set(EXENAME "ybcon")

if (NOT DEFINED CODENAME)
    set(CODENAME "Unknown")
    if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/misc/codename.txt")
        file(READ "${CMAKE_CURRENT_SOURCE_DIR}/misc/codename.txt" CODENAME)
    endif()
endif()

set(EXEDESC "Transpiler for the yerbacon language.")
string(TIMESTAMP SHORT_BUILD_TIMESTAMP "%Y%m")
string(SUBSTRING ${SHORT_BUILD_TIMESTAMP} 2 4 SHORT_BUILD_TIMESTAMP)
string(ASCII 169 CopyrightCharacter)
string(TIMESTAMP LEGALCOPYRIGHT "Copyright ${CopyrightCharacter} 2020-%Y. Available under the MPL-2.0 license.")
file(COPY "resources/${PROJECT_NAME}.ico" DESTINATION "processed")
configure_file("resources/${PROJECT_NAME}.manifest" "processed/${PROJECT_NAME}.manifest" @ONLY)
configure_file("resources/${PROJECT_NAME}.rc" "processed/${PROJECT_NAME}.rc" @ONLY)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
include(CheckPIESupported)
check_pie_supported(OUTPUT_VARIABLE pie_output LANGUAGES CXX)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
if (NOT CMAKE_CXX_LINK_PIE_SUPPORTED)
    message(WARNING "Link-time PIE not supported: ${pie_output}.\n")
endif()
set(CMAKE_CXX_FLAGS "-Wall")

if (NOT MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
    set(CMAKE_CXX_FLAGS_RELEASE "-Os")
endif()

if ((${CMAKE_CXX_COMPILER_ID} STREQUAL GNU) OR (${CMAKE_CXX_COMPILER_ID} STREQUAL Clang))
    if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0)
        message(WARNING "A ${CMAKE_CXX_COMPILER_ID} compiler version of preferably 11 or higher should be used.")
    endif()
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc")
    set(CMAKE_CXX_FLAGS "-flto ${CMAKE_CXX_FLAGS} -pipe -fstack-protector-strong -fstack-clash-protection")
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ftree-vectorize")
    include(CheckCXXCompilerFlag)
    CHECK_CXX_COMPILER_FLAG("-fcf-protection" CF_PROTECTION_SUPPORTED)
    if (CF_PROTECTION_SUPPORTED)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcf-protection")
    endif()
endif()

if (${CMAKE_CXX_COMPILER_ID} STREQUAL GNU)
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fira-loop-pressure -ftree-loop-distribution -floop-interchange -fipa-pta -fivopts -s")
    set(CMAKE_CXX_FLAGS "-fno-use-linker-plugin -fwhole-program ${CMAKE_CXX_FLAGS}")
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
    set(CMAKE_CXX_FLAGS "-fwhole-program-vtables ${CMAKE_CXX_FLAGS}")
endif()

if (MINGW OR MSVC)
    if (UNIX)
        SET(CMAKE_RC_COMPILE_OBJECT
                "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
        SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
    endif()
    ENABLE_LANGUAGE(RC)
endif()

# CPack configuration
set(CPACK_THREADS 0) # Used by CMake 3.20+
set(CPACK_ARCHIVE_THREADS ${CPACK_THREADS})
set(CPACK_STRIP_FILES TRUE)
set(CPACK_VERBATIM_VARIABLES TRUE)
string(TIMESTAMP TIME "%Y.%m+%d")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}-${TIME}")
set(CPACK_PACKAGE_VENDOR "Contributor(s)")
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/resources/Yerbacon.png")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/misc/desc.txt")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${EXEDESC}")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")
set(CPACK_PACKAGE_CONTACT "Username404 <w.iron.zombie@gmail.com>")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Yerbacon ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${CMAKE_PROJECT_VERSION}-${TIME}")

include_directories(${CMAKE_CURRENT_LIST_DIR})
add_executable(${EXENAME} src/main.cpp ${CMAKE_CURRENT_BINARY_DIR}/processed/${PROJECT_NAME}.rc src/parser/MainParse.cpp src/transpiler/MainTranspile.cpp src/etc/filefuncs.cpp src/etc/lexer.cpp src/headers/lex.hpp src/headers/misc.hpp src/headers/parsing/ParseComponents.hpp src/headers/transpiler/Target.hpp src/headers/transpiler/implementations/Lua.hpp src/headers/transpiler/implementations/Js.hpp src/headers/transpiler/implementations/Py.hpp src/headers/parsing/Parser.hpp src/headers/Yerbacon.hpp)
target_compile_definitions(ybcon PRIVATE YBCON_VERSION="${CODENAME} ${PROJECT_VERSION}")

# lpkg = linux package, wpkg = windows package
set(PNAME ${PROJECT_NAME}-${CODENAME}-${TIME})
if (UNIX AND NOT MINGW)
    include(GNUInstallDirs)
    set(CMAKE_INSTALL_PREFIX "/usr")
    set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
    set(CPACK_PACKAGE_FILE_NAME "${PNAME}_lpkg")
    set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
    configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/postinst" "processed/postinst" @ONLY)
    set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE  "${CMAKE_CURRENT_BINARY_DIR}/processed/postinst")
    set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA ${CPACK_RPM_POST_INSTALL_SCRIPT_FILE})
    set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.14), libstdc++6 (>= 9)")
    set(CPACK_DEBIAN_COMPRESSION_TYPE xz)
    set(CPACK_RPM_COMPRESSION_TYPE ${CPACK_DEBIAN_COMPRESSION_TYPE})
    set(CPACK_RPM_PACKAGE_AUTOREQ YES)
    set(CPACK_RPM_PACKAGE_LICENSE "MPL-2.0")
    set(CPACK_RPM_CHANGELOG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/changelog")
    if (NOT APPLE)
        set(GZNAME "changelog.Debian.gz")
        add_custom_command(
            OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${GZNAME}"
            COMMAND gzip -c -k -n -9 "${CMAKE_CURRENT_SOURCE_DIR}/changelog" > ${CMAKE_CURRENT_BINARY_DIR}/${GZNAME}
            WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
            DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/changelog"
            COMMENT "Compressing the changelog file"
        )
        add_custom_target(changelog ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${GZNAME}")
        string(TOLOWER "${CMAKE_INSTALL_DOCDIR}" DEB_CHANGELOG_DEST_DIR) # Lowercase characters are needed because GNUInstallDirs uses the PROJECT_NAME variable.
        install(
            FILES "${CMAKE_CURRENT_BINARY_DIR}/${GZNAME}"
            DESTINATION ${DEB_CHANGELOG_DEST_DIR}
        )
    endif()
    set(CPACK_RPM_PACKAGE_VERSION ${PROJECT_VERSION})
    set(CPACK_RPM_PACKAGE_RELEASE ${TIME})
    set(CPACK_RPM_PACKAGE_RELEASE_DIST ON)
    if (CPACK_RPM_PACKAGE_SOURCES)
        set(CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX "/")
        set(CPACK_GENERATOR RPM)
        set(CPACK_RPM_BUILDREQUIRES "cmake >= 3.18, clang >= 11.0.0")
        install(DIRECTORY src DESTINATION ${CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX})
        install(DIRECTORY resources DESTINATION ${CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX})
        install(DIRECTORY scripts DESTINATION ${CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX})
        install(FILES CMakeLists.txt misc/desc.txt LICENSE.txt README.md changelog DESTINATION ${CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX})
    else()
        if (NOT DEFINED CPACK_GENERATOR)
            set(CPACK_GENERATOR TGZ;STGZ;RPM;DEB)
        endif()
        install(PROGRAMS
                ${CMAKE_CURRENT_BINARY_DIR}/ybcon
                DESTINATION ${CMAKE_INSTALL_LIBEXECDIR})
        install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts/completions DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/ybcon.d)
        install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/ybcon
                DESTINATION ${CMAKE_INSTALL_BINDIR})
    endif()
elseif(MINGW OR MSVC)
    set(CMAKE_INSTALL_PREFIX "C:\\progs\\${PROJECT_NAME}")
    set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CODENAME})
    set(CPACK_NSIS_INSTALL_ROOT "${CMAKE_INSTALL_PREFIX}")
    set(CMAKE_EXE_LINKER_FLAGS "-static -static-libstdc++ ${CMAKE_EXE_LINKER_FLAGS}")
    set(CPACK_PACKAGE_FILE_NAME "${PNAME}_wpkg")
    set(CPACK_NSIS_COMPRESSOR "/SOLID lzma")
    set(CPACK_NSIS_MANIFEST_DPI_AWARE true)
    set(CPACK_NSIS_PACKAGE_NAME "${PROJECT_NAME} ${CODENAME}-${PROJECT_VERSION}")
    set(CPACK_NSIS_WELCOME_TITLE_3LINES ON)
    set(CPACK_NSIS_URL_INFO_ABOUT "https://gits.username404.fr/Username404-59/Yerbacon")
    set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/resources/${PROJECT_NAME}.ico")
    set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/resources/${PROJECT_NAME}.ico")
    set(CPACK_NSIS_DEFINES "RequestExecutionLevel highest")
    set(CPACK_SYSTEM_NAME "Win32-${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}")
    set(CPACK_TOPLEVEL_TAG "Win32-${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}")
    set(CPACK_NSIS_MODIFY_PATH ON)
    set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
    set(CPACK_GENERATOR ZIP;NSIS)
    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ybcon.exe DESTINATION bin)
endif()
include(CPack)