Yerbacon/CMakeLists.txt

286 lines
15 KiB
CMake

cmake_minimum_required(VERSION 3.18)
project(Yerbacon VERSION 0.0.1 LANGUAGES C CXX)
set(EXENAME "ybcon")
string(TOLOWER "${PROJECT_NAME}" LOWERCASE_PROJECT_NAME)
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 LEGAL-COPYRIGHT "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)
if (NOT DEFINED CMAKE_UNITY_BUILD)
set(CMAKE_UNITY_BUILD TRUE)
endif()
include(CheckPIESupported)
check_pie_supported(LANGUAGES CXX)
set(USER_DEFINED_PIE (DEFINED CMAKE_POSITION_INDEPENDENT_CODE))
if (CMAKE_CXX_LINK_PIE_SUPPORTED)
if (NOT USER_DEFINED_PIE)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
endif()
elseif(USER_DEFINED_PIE AND CMAKE_POSITION_INDEPENDENT_CODE)
message(NOTICE "-- Could NOT manually enable Position-Independent Code (PIC) because it is not supported by the current toolchain")
endif()
if (DEFINED CXX_TARGET)
set(CMAKE_SYSTEM_PROCESSOR "${CXX_TARGET}")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "")
set(CMAKE_SYSTEM_PROCESSOR "${CMAKE_HOST_SYSTEM_PROCESSOR}")
endif()
set(CMAKE_CXX_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS_RELEASE "-Os")
set(CMAKE_COLOR_DIAGNOSTICS ON)
set(MINIMAL_GNU "11.0")
set(MINIMAL_CLANG "14.0.1")
set(MINIMAL_MSVC "19.30")
option(IGNORE_MINIMAL_COMPILER_VERSION "Whether or not to ignore the minimal compiler versions")
set(IS_GNU (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
set(IS_CLANG (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
option(NO_CCACHE "Disables CCache")
if (NOT NO_CCACHE)
find_program(CCACHE_PRESENT ccache)
if(CCACHE_PRESENT)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif()
endif()
find_package(Threads)
if (${IS_GNU} OR ${IS_CLANG})
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
if (Threads_FOUND AND NOT MINGW)
if (NOT ("${CMAKE_EXE_LINKER_FLAGS}" MATCHES -static))
include(FindOpenMP)
if (OpenMP_CXX_FOUND)
set(CMAKE_CXX_FLAGS "${OpenMP_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")
add_definitions(-D_GLIBCXX_PARALLEL)
endif()
endif()
endif()
if (NOT DEFINED EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-strong -fstack-clash-protection")
else()
set(CMAKE_EXE_LINKER_FLAGS "--closure 1 -sWASM=0 --memory-init-file 0 -sEXPORTED_FUNCTIONS=_main -sEXIT_RUNTIME=1 -sSINGLE_FILE=1 -sSAFE_HEAP=1 -sABORTING_MALLOC=0 -sJS_MATH=1 -sENVIRONMENT='web,webview,worker,node,shell' -sNODEJS_CATCH_EXIT=0 -sSTRICT=1 -sMINIMAL_RUNTIME=0 -sDISABLE_EXCEPTION_CATCHING=0 ${CMAKE_EXE_LINKER_FLAGS}")
if (CMAKE_USE_PTHREADS_INIT)
set(CMAKE_CXX_FLAGS "-pthread ${CMAKE_CXX_FLAGS}") # Emscripten requires the -pthread flag
set(CMAKE_EXE_LINKER_FLAGS "--closure-args=\"--compilation_level SIMPLE\" -sPROXY_TO_PTHREAD=1 ${CMAKE_EXE_LINKER_FLAGS}") # See https://github.com/emscripten-core/emscripten/issues/16706
endif()
endif()
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstrict-enums -pipe -funwind-tables -fasynchronous-unwind-tables -frtti -fexceptions")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections -fmerge-all-constants -ftree-vectorize -fno-math-errno")
include(CheckCXXCompilerFlag)
set(CF_PROTECTION "-fcf-protection")
check_cxx_compiler_flag("${CF_PROTECTION}" CF_PROTECTION_SUPPORTED)
if (CF_PROTECTION_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CF_PROTECTION}")
endif()
endif()
if (NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE)
set(USER_DEFINED_INTERPROCEDURAL_OPTIMIZATION_RELEASE NO)
include(CheckIPOSupported)
check_ipo_supported(RESULT CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE LANGUAGES CXX)
else()
set(USER_DEFINED_INTERPROCEDURAL_OPTIMIZATION_RELEASE YES)
endif()
if (${IS_GNU})
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${MINIMAL_GNU} AND NOT ${IGNORE_MINIMAL_COMPILER_VERSION})
message(FATAL_ERROR "G++ ${MINIMAL_GNU} or higher is required.")
endif()
if (Threads_FOUND)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ftree-parallelize-loops=2")
endif()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fvect-cost-model=unlimited -foptimize-strlen -fsched-pressure -flive-range-shrinkage -fpredictive-commoning -ftree-partial-pre -fzero-call-used-regs=used-gpr-arg -fira-loop-pressure -ftree-loop-distribution -floop-interchange -fsplit-paths -fgcse-las -fgcse-sm -fipa-pta -fstdarg-opt -fivopts -fweb")
if (${CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE})
set(CMAKE_CXX_FLAGS_RELEASE "-fwhole-program -flto-partition=none ${CMAKE_CXX_FLAGS_RELEASE}")
endif()
elseif(${IS_CLANG})
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${MINIMAL_CLANG} AND NOT ${IGNORE_MINIMAL_COMPILER_VERSION})
message(FATAL_ERROR "Clang ${MINIMAL_CLANG} or higher is required.")
endif()
if (MINGW AND NOT USER_DEFINED_INTERPROCEDURAL_OPTIMIZATION_RELEASE) # CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE is false on llvm-mingw toolchains even though it is supported
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE YES)
endif()
if (CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto=thin")
if (NOT DEFINED EMSCRIPTEN)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fwhole-program-vtables")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option -Wno-unqualified-std-cast-call -Wno-reinterpret-base-class")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fstrict-vtable-pointers")
elseif(MSVC)
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${MINIMAL_MSVC} AND NOT ${IGNORE_MINIMAL_COMPILER_VERSION})
message(FATAL_ERROR "MSVC ${MINIMAL_MSVC} or higher is required")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive- /Zc:twoPhase- /EHsc /GR /W3 /Zc:__cplusplus /Zc:preprocessor /Zc:throwingNew /Zc:inline")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
endif()
string(TOUPPER "${CMAKE_BUILD_TYPE}" UPPERCASE_BUILD_TYPE)
if (UPPERCASE_BUILD_TYPE STREQUAL "RELEASE")
add_definitions(-DYBCON_FLAGS="${CMAKE_CXX_FLAGS_RELEASE}")
endif()
add_definitions(-DYBCON_COMPILER="${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
if (MINGW OR MSVC)
if (UNIX)
SET(CMAKE_RC_COMPILE_OBJECT
"<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
if (NOT DEFINED CMAKE_RC_COMPILER)
SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
endif()
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/${PROJECT_NAME}.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 "${PROJECT_NAME} ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_FILE_NAME "${LOWERCASE_PROJECT_NAME}-${PROJECT_VERSION}-${TIME}.${CMAKE_SYSTEM_PROCESSOR}")
include_directories(${CMAKE_CURRENT_LIST_DIR})
add_executable(${EXENAME} src/main.cpp ${CMAKE_CURRENT_BINARY_DIR}/processed/${PROJECT_NAME}.rc 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/arguments.hpp src/headers/parsing/ReservedIdentifiers.hpp)
target_compile_definitions(${EXENAME} PRIVATE YBCON_VERSION="${CODENAME} ${PROJECT_VERSION}")
target_precompile_headers(${EXENAME} PRIVATE src/headers/Yerbacon.hpp)
if (Threads_FOUND)
target_link_libraries(${EXENAME} PRIVATE Threads::Threads)
endif()
option(NO_SELF_PACKER "Disables usage of a self-packer")
if (NOT (UPPERCASE_BUILD_TYPE STREQUAL "DEBUG" OR UPPERCASE_BUILD_TYPE STREQUAL "RELWITHDEBINFO" OR NO_SELF_PACKER OR DEFINED EMSCRIPTEN))
include(FindSelfPackers)
if (SELF_PACKER_FOR_EXECUTABLE MATCHES upx) # UPX version d61edc9 or higher is required when using a cross-compiler to target the musl C library
if (CMAKE_CXX_LINK_NO_PIE_SUPPORTED OR MINGW) # MINGW does not support PIE, yet the variable is set to NO.
set(SELF_PACKER_FOR_EXECUTABLE_FLAGS ${SELF_PACKER_FOR_EXECUTABLE_FLAGS} --ultra-brute --best)
if (USER_DEFINED_PIE AND CMAKE_POSITION_INDEPENDENT_CODE)
message(NOTICE "-- Could NOT manually enable PIE (UPX is in use)")
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE FALSE)
set_target_properties(${EXENAME} PROPERTIES POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE})
else()
set(SELF_PACKER_FOR_EXECUTABLE "SELF_PACKER_FOR_EXECUTABLE-NOTFOUND")
message(NOTICE "UPX usage has been disabled because position-dependent executables are unsupported by the current compiler")
endif()
endif()
if (NOT SELF_PACKER_FOR_EXECUTABLE STREQUAL "SELF_PACKER_FOR_EXECUTABLE-NOTFOUND")
add_custom_command(TARGET ${EXENAME} POST_BUILD COMMAND "${SELF_PACKER_FOR_EXECUTABLE}" ${SELF_PACKER_FOR_EXECUTABLE_FLAGS} $<TARGET_FILE:${EXENAME}> VERBATIM)
endif()
endif()
if (UNIX AND NOT (MINGW OR CMAKE_HOST_WIN32))
include(GNUInstallDirs)
set(CMAKE_INSTALL_PREFIX "/usr")
set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
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_SHLIBDEPS ON)
set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
set(CPACK_DEBIAN_COMPRESSION_TYPE xz)
set(CPACK_RPM_COMPRESSION_TYPE ${CPACK_DEBIAN_COMPRESSION_TYPE})
set(CPACK_RPM_PACKAGE_AUTOREQ YES)
set(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
set(CPACK_RPM_PACKAGE_LICENSE "MPL-2.0")
set(CPACK_RPM_CHANGELOG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/changelog")
if (CMAKE_VERSION STREQUAL "3.21.1")
message(WARNING "CPack ${CMAKE_VERSION} has a bug which causes rpm scripts to be unusable; please update or downgrade")
endif()
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}")
add_dependencies(${EXENAME} changelog)
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 >= ${CMAKE_MINIMUM_REQUIRED_VERSION}, clang >= ${MINIMAL_CLANG}.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}/${EXENAME}
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR})
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts/completions DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${EXENAME}.d)
install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/${EXENAME}
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}")
if (MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument")
set(CMAKE_EXE_LINKER_FLAGS "-static -static-libstdc++ -static-libgcc ${CMAKE_EXE_LINKER_FLAGS}")
endif()
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/${PROJECT_NAME}")
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")
set(CPACK_TOPLEVEL_TAG "Win32")
set(CPACK_NSIS_MODIFY_PATH ON)
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
if (CMAKE_HOST_WIN32)
# The two following variables require CMake 3.20 or higher
set(CPACK_NSIS_BRANDING_TEXT "NSIS Installer for ${PROJECT_NAME}")
set(CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION CENTER)
endif()
# CMake 3.22+ is required to ignore the NSIS license page
set(CPACK_NSIS_IGNORE_LICENSE_PAGE TRUE)
set(CPACK_GENERATOR ZIP;NSIS)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${EXENAME}.exe DESTINATION bin)
endif()
include(CPack)