diff --git a/CMakeLists.txt b/CMakeLists.txt index 38de60e831..a26ade555a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,16 @@ if (NOT CMAKE_OSX_ARCHITECTURES) set(CMAKE_OSX_ARCHITECTURES x86_64) endif() +# FIXME: this reports an unused architecture if only vms are built. +# We may not be able to avoid this for now without doing a huge rewrite +# of this file. +# FIXME: this reports an unused compiler if only vms are built. +# We cannot avoid this for now without doing a huge rewrite of this files +# since we also set useless flags using informations provided by this. +if (NOT (BUILD_CLIENT OR BUILD_TTY_CLIENT OR BUILD_SERVER OR BUILD_DUMMY_APP)) + message(NOTICE "You can safely ignore the following reported architecture, it is not used.") + message(NOTICE "You can safely ignore the following reported compilers, they are unused.") +endif() include(DaemonPlatform) if (Daemon_OUT) @@ -288,8 +298,17 @@ endif() # Compile and link flags ################################################################################ +# FIXME: This sets unused flags for an unused compiler if only nacl vms +# are built and we are not yet running the chainloaded build. We cannot +# avoid this for now or we would have to do a large rewrite of that file. +# FIXME: This defines the try_flag function that is used in +# Unvanquished CMakeLists.txt even if the engine is not built, +# meaning we have to detect useless engine compiler to set +# useless engine flags when only building vms. include(DaemonFlags) +# FIXME: Once engine flags would be only set when building the engine +# this would be likely unused by vms as they are built by DaemonGame. # Warning options (for Daemon only) # Note the different scopes used for warning options: # * set_c_cxx_flag(xxx) or try_c_cxx_flag(xxx) sets it for all code including dependencies @@ -396,9 +415,16 @@ function(ADD_PRECOMPILED_HEADER Target) set(Header ${COMMON_DIR}/Common.h) # Compiler-specific PCH support - if (CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR NACL) + try_c_cxx_flag(PCH "-pch") + + if (PCH) + # CMAKE_CXX_COMPILER_ARG1 is used with compilers using subcommands. + # For example when doing: cmake -D'CMAKE_CXX_COMPILER'='zig;c++' + # CMAKE_CXX_COMPILER will be "zig", + # CMAKE_CXX_COMPILER_ARG1 will be "c++". add_custom_command(OUTPUT "${OBJ_DIR}/${Target}.h.gch" - COMMAND ${PNACLPYTHON_PREFIX2} ${CMAKE_CXX_COMPILER} ${Defs} ${Flags} -x c++-header ${Header} -o "${OBJ_DIR}/${Target}.h.gch" + COMMAND ${PNACLPYTHON_PREFIX2} ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} + ${Defs} ${Flags} -x c++-header ${Header} -o "${OBJ_DIR}/${Target}.h.gch" DEPENDS ${Header} IMPLICIT_DEPENDS CXX ${Header} ) @@ -407,10 +433,10 @@ function(ADD_PRECOMPILED_HEADER Target) add_dependencies(${Target} ${Target}-pch) # PNaCl clang doesn't support -include-pch properly - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND NOT NACL) - set_property(TARGET ${Target} APPEND PROPERTY COMPILE_OPTIONS "-include-pch;${OBJ_DIR}/${Target}.h.gch") - else() + if (DAEMON_CXX_COMPILER_NAME STREQUAL "PNaCl") set_property(TARGET ${Target} APPEND PROPERTY COMPILE_OPTIONS "-include;${OBJ_DIR}/${Target}.h;-Winvalid-pch") + else() + set_property(TARGET ${Target} APPEND PROPERTY COMPILE_OPTIONS "-include-pch;${OBJ_DIR}/${Target}.h.gch") endif() elseif (MSVC) # /Fp sets the PCH path used by either of the /Yc and /Yu options. diff --git a/cmake/DaemonCompiler.cmake b/cmake/DaemonCompiler.cmake new file mode 100644 index 0000000000..1766b9bbfd --- /dev/null +++ b/cmake/DaemonCompiler.cmake @@ -0,0 +1,240 @@ +# Daemon BSD Source Code +# Copyright (c) 2024, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +################################################################################ +# Determine compiler +################################################################################ + +# FIXME: Force -W#pragma-messages and -Wno-error +# In case there is -Wno-#pragma-messages or -Werror in CFLAGS/CXXFLAGS + +function(detect_daemon_compiler lang) + set(C_NAME "C") + set(CXX_NAME "C++") + set(C_EXT ".c") + set(CXX_EXT ".cpp") + + try_compile(BUILD_RESULT + "${CMAKE_BINARY_DIR}" + "${DAEMON_DIR}/cmake/DaemonCompiler/DaemonCompiler${${lang}_EXT}" + CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} + OUTPUT_VARIABLE BUILD_LOG + ) + + get_filename_component(compiler_basename "${CMAKE_${lang}_COMPILER}" NAME) + + if (NOT BUILD_RESULT) + message(WARNING "Failed to build DaemonCompiler${${lang}_EXT}, relying on CMake builtin detection.") + set(compiler_name "Unknown") + else() + set(BUILD_LOG "\n${BUILD_LOG}\n") + string(REGEX REPLACE "\n[^\n]*REPORT>[^\n]*\n" "\n" BUILD_LOG "${BUILD_LOG}") + + string(REGEX REPLACE ".*\nDAEMON_COMPILER_NAME=([^\n]*)\n.*" "\\1" + compiler_name "${BUILD_LOG}") + + foreach(name GCC;Clang;generic;${compiler_name}) + set(compatibility_regex ".*\nDAEMON_COMPILER_${name}_COMPATIBILITY=([^\n]*)\n.*") + if ("${BUILD_LOG}" MATCHES ${compatibility_regex}) + string(REGEX REPLACE ${compatibility_regex} "\\1" + compiler_${name}_compatibility "${BUILD_LOG}") + endif() + + set(version_regex ".*\nDAEMON_COMPILER_${name}_VERSION=([^\n]*)\n.*") + if ("${BUILD_LOG}" MATCHES ${version_regex}) + string(REGEX REPLACE ${version_regex} "\\1" + compiler_${name}_version "${BUILD_LOG}") + endif() + + set(version_string_regex ".*\nDAEMON_COMPILER_${name}_VERSION_STRING=([^\n]*)\n.*") + if ("${BUILD_LOG}" MATCHES ${version_string_regex}) + string(REGEX REPLACE ${version_string_regex} "\\1" + compiler_${name}_version_string "${BUILD_LOG}") + endif() + + set(DAEMON_${lang}_COMPILER_${name}_VERSION + "${compiler_${name}_version}" + PARENT_SCOPE) + + set(DAEMON_${lang}_COMPILER_${name}_COMPATIBILITY + "${compiler_${name}_compatibility}" + PARENT_SCOPE) + endforeach() + endif() + + if (compiler_name STREQUAL "Unknown") + if (CMAKE_${lang}_COMPILER_ID) + set(compiler_name "${CMAKE_${lang}_COMPILER_ID}") + # Compiler version is done below. + else() + message(WARNING "Unknown ${${lang}_NAME} compiler") + endif() + endif() + + # AOCC + if (compiler_Clang_version_string) + set(aocc_version_regex ".*CLANG: AOCC_([^ )]+).*") + if (compiler_Clang_version_string MATCHES ${aocc_version_regex}) + set(compiler_name "AOCC") + string(REGEX REPLACE ${aocc_version_regex} "\\1" + compiler_AOCC_version "${compiler_Clang_version_string}") + string(REGEX REPLACE "(.*)-Build.*" "\\1" + compiler_AOCC_version "${compiler_AOCC_version}") + endif() + endif() + + # Zig + if (compiler_Clang_version_string) + set(zig_version_regex ".*[(]https://github.com/ziglang/zig-bootstrap .*[)]") + if (compiler_Clang_version_string MATCHES ${zig_version_regex}) + set(compiler_name "Zig") + endif() + + # Parse “zig version” + execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" version + OUTPUT_VARIABLE CUSTOM_${lang}_ZIG_OUTPUT + RESULT_VARIABLE CUSTOM_${lang}_ZIG_RETURN_CODE + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if (NOT CUSTOM_${lang}_ZIG_RETURN_CODE) # Success + set(compiler_Zig_version "${CUSTOM_${lang}_ZIG_OUTPUT}") + endif() + endif() + + # Compilers that use underlying Clang version as their own version. + foreach(name in AppleClang) + if (compiler_name STREQUAL "${name}") + set(compiler_${name}_version "${compiler_Clang_version}") + endif() + endforeach() + + # Compilers that write the version number at the beginning of the VERSION string. + set(string_version_regex "([^ ]+).*") + foreach(name in PNaCl) + if (compiler_name STREQUAL "${name}") + if (compiler_generic_version_string) + if (compiler_generic_version_string MATCHES ${string_version_regex}) + string(REGEX REPLACE ${string_version_regex} "\\1" + compiler_${name}_version "${compiler_generic_version_string}") + endif() + endif() + endif() + endforeach() + + if (compiler_ARMClang_version_string) + # There is no __armclang_patchlevel__ so we should parse __armclang_version__ to get it. + if (compiler_ARMClang_version_string MATCHES ${string_version_regex}) + string(REGEX REPLACE ${string_version_regex} "\\1" + compiler_ARMClang_version "${compiler_ARMClang_version_string}") + endif() + endif() + + if (compiler_ICX_version) + # 20240000 becomes 2024.0.0 + string(REGEX REPLACE "(....)(..)(..)" "\\1.\\2.\\3" + compiler_ICX_version "${compiler_ICX_version}") + string(REGEX REPLACE "\\.0" "." + compiler_ICX_version "${compiler_ICX_version}") + endif() + + if (compiler_${compiler_name}_version) + set(compiler_version "${compiler_${compiler_name}_version}") + elseif (CMAKE_${lang}_COMPILER_VERSION) + set(compiler_version "${CMAKE_${lang}_COMPILER_VERSION}") + else() + set(compiler_version "Unknown") + message(WARNING "Unknown ${${lang}_NAME} compiler version") + endif() + + set(DAEMON_${lang}_COMPILER_BASENAME "${compiler_basename}" PARENT_SCOPE) + set(DAEMON_${lang}_COMPILER_NAME "${compiler_name}" PARENT_SCOPE) + set(DAEMON_${lang}_COMPILER_VERSION "${compiler_version}" PARENT_SCOPE) +endfunction() + +message(STATUS "CMake generator: ${CMAKE_GENERATOR}") + +foreach(lang C;CXX) + set(C_NAME "C") + set(CXX_NAME "C++") + + if (MSVC) + # Let CMake do the job, it does it very well, + # and there is probably no variant to take care about. + set(DAEMON_${lang}_COMPILER_NAME "${CMAKE_${lang}_COMPILER_ID}") + set(DAEMON_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}") + get_filename_component(DAEMON_${lang}_COMPILER_BASENAME "${CMAKE_${lang}_COMPILER}" NAME) + else() + detect_daemon_compiler(${lang}) + + if (DAEMON_${lang}_COMPILER_Clang_COMPATIBILITY) + if (NOT DAEMON_${lang}_COMPILER_NAME STREQUAL "Clang") + set(DAEMON_${lang}_COMPILER_EXTENDED_VERSION + "${DAEMON_${lang}_COMPILER_VERSION}/clang-${DAEMON_${lang}_COMPILER_Clang_VERSION}") + endif() + elseif (DAEMON_${lang}_COMPILER_GCC_COMPATIBILITY) + if (NOT DAEMON_${lang}_COMPILER_NAME STREQUAL "GCC") + # Almost all compilers on Earth pretend to be GCC compatible. + # So we first have to check it's really a GCC variant. + # Parse “ -v” + execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" -v + ERROR_VARIABLE CUSTOM_${lang}_GCC_OUTPUT + RESULT_VARIABLE CUSTOM_${lang}_GCC_RETURN_CODE + OUTPUT_QUIET) + + if (NOT CUSTOM_${lang}_GCC_RETURN_CODE) # Success + # The existence of this string tells us it's a GCC variant. + # The version in this string is the same as __VERSION__, + # the version of the GCC variant, not the version of the upstream + # GCC we are looking for. + if ("${CUSTOM_${lang}_GCC_OUTPUT}" MATCHES "\ngcc version ") + set(DAEMON_${lang}_COMPILER_EXTENDED_VERSION + "${DAEMON_${lang}_COMPILER_VERSION}/gcc-${DAEMON_${lang}_COMPILER_GCC_VERSION}") + endif() + endif() + endif() + endif() + endif() + + if (NOT DAEMON_${lang}_COMPILER_EXTENDED_VERSION) + set(DAEMON_${lang}_COMPILER_EXTENDED_VERSION "${DAEMON_${lang}_COMPILER_VERSION}") + endif() + + set(DAEMON_${lang}_COMPILER_STRING + "${DAEMON_${lang}_COMPILER_NAME} ${DAEMON_${lang}_COMPILER_EXTENDED_VERSION} ${DAEMON_${lang}_COMPILER_BASENAME}") + + message(STATUS "Detected ${${lang}_NAME} compiler: ${DAEMON_${lang}_COMPILER_STRING}") + + add_definitions(-DDAEMON_${lang}_COMPILER_${DAEMON_${lang}_COMPILER_NAME}=1) + + # Preprocessor definitions containing '#' may not be passed on the compiler + # command line because many compilers do not support it. + string(REGEX REPLACE "\#" "~" DAEMON_DEFINE_${lang}_COMPILER_STRING "${DAEMON_${lang}_COMPILER_STRING}") + + # Quotes cannot be part of the define as support for them is not reliable. + add_definitions(-DDAEMON_${lang}_COMPILER_STRING=${DAEMON_DEFINE_${lang}_COMPILER_STRING}) +endforeach() diff --git a/cmake/DaemonCompiler/DaemonCompiler.c b/cmake/DaemonCompiler/DaemonCompiler.c new file mode 100644 index 0000000000..4414d1584d --- /dev/null +++ b/cmake/DaemonCompiler/DaemonCompiler.c @@ -0,0 +1,165 @@ +/* +=========================================================================== +Daemon BSD Source Code +Copyright (c) 2024, Daemon Developers +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Daemon developers nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=========================================================================== +*/ + +#define STRING(s) #s +#define XSTRING(s) STRING(s) + +#define REPORT(key, value) \ + "REPORT>" +#define REPORT_VERSION_3(name, major, minor, patch) \ + REPORT(name "_VERSION", XSTRING(major) "." XSTRING(minor) "." XSTRING(patch)) +#define REPORT_VERSION_2(name, major, minor) \ + REPORT(name "_VERSION", XSTRING(major) "." XSTRING(minor)) +#define REPORT_VERSION_1(name, major) \ + REPORT(name "_VERSION", XSTRING(major)) +#define REPORT_VERSION_STRING(name, value) \ + REPORT(name "_VERSION_STRING", value) +#define REPORT_COMPATIBILITY(name) \ + REPORT(name "_COMPATIBILITY", "ON") +#define REPORT_NAME(name) \ + REPORT("NAME", name) + +// GCC + +#if defined(__GNUC__) + #pragma message(REPORT_COMPATIBILITY("GCC")) +#endif + +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) + #pragma message(REPORT_VERSION_3("GCC", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)) +#endif + +// Clang + +#if defined(__clang__) + #pragma message(REPORT_COMPATIBILITY("Clang")) +#endif + +#if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) + #pragma message(REPORT_VERSION_3("Clang", __clang_major__, __clang_minor__, __clang_patchlevel__)) +#endif + +#if defined(__clang_version__) + #pragma message(REPORT_VERSION_STRING("Clang", __clang_version__)) +#endif + +// ICC + +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) + #pragma message(REPORT_VERSION_2("ICC", __INTEL_COMPILER, __INTEL_COMPILER_UPDATE)) +#elif defined(_ICC) + #pragma message(REPORT_VERSION_1("ICC", __ICC)) +#endif + +// ICX + +#if defined(__INTEL_CLANG_COMPILER) + // This requires extra parsing since it's in the form 20240000 for 2024.0.0. + #pragma message(REPORT_VERSION_1("ICX", __INTEL_CLANG_COMPILER)) +#elif defined(__INTEL_LLVM_COMPILER) + // This requires extra parsing since it's in the form 20240000 for 2024.0.0. + #pragma message(REPORT_VERSION_1("ICX", __INTEL_LLVM_COMPILER)) +#endif + +// ArmClang + +#if defined(__armclang_major__) && defined(__armclang_minor__) + // There is no __armclang_patchlevel__, 23.04.1 is reported as 23.04. + #pragma message(REPORT_VERSION_2("ARMClang", __armclang_major__, __armclang_minor__)) +#endif + +#if defined(__armclang_version__) + // This string contains the version patch level and requires extra parsing. + // #define __armclang_major__ 23 + // #define __armclang_minor__ 04 + // #define __armclang_version__ "23.04.1 (build number 14)" + #pragma message(REPORT_VERSION_STRING("ARMClang", __armclang_version__)) +#endif + +// Generic + +#if defined(__VERSION__) + #pragma message(REPORT_VERSION_STRING("generic", __VERSION__)) +#endif + +// Selection + +// There is no Zig specific version definition, we can detect its usage by parsing +// other definitions, and then use the `zig version` command to get the version: +// #define __VERSION__ "Clang 18.1.6 (https://github.com/ziglang/zig-bootstrap 98bc6bf4fc4009888d33941daf6b600d20a42a56)" +// #define __clang_version__ "18.1.6 (https://github.com/ziglang/zig-bootstrap 98bc6bf4fc4009888d33941daf6b600d20a42a56)" + +// There is no Saigo specific version definition, we reuse the clang version instead +// of parsing the version strings: +// #define __VERSION__ "Clang 19.0.0git (https://chromium.googlesource.com/a/native_client/nacl-llvm-project-v10.git e25355fddbdece2ef08747ead05b7f69f3bc6dca)" +// #define __clang_version__ "19.0.0git (https://chromium.googlesource.com/a/native_client/nacl-llvm-project-v10.git e25355fddbdece2ef08747ead05b7f69f3bc6dca)" + +// There is no PNaCl specific version definition, we should parse another definition: +// #define __VERSION__ "4.2.1 Compatible Clang 3.6.0 (https://chromium.googlesource.com/a/native_client/pnacl-clang.git 96b3da27dcefc9d152e51cf54280989b2206d789) (https://chromium.googlesource.com/a/native_client/pnacl-llvm.git d0089f0b008e03cfd141f05c80e3b628c2df75c1)" + +// There is no AOCC specific version definition, we should parse another definition: +// #define __VERSION__ "AMD Clang 14.0.6 (CLANG: AOCC_4.0.0-Build#434 2022_10_28)" +// #define __clang_version__ "14.0.6 (CLANG: AOCC_4.0.0-Build#434 2022_10_28)" + +// There is no usable AppleClang version definitions, +// It reports an old GCC version but reuses the LLVM version as its owns: +// #define __GNUC__ 4.2.1 +// #define __APPLE_CC_ 6000 +// #define __apple_build_version__ 10010046 +// #define __VERSION__ "4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.46.4)" + +#if defined(__INTEL_COMPILER) || defined(__ICC) + #pragma message(REPORT_NAME("ICC")) // Intel +#elif defined(__INTEL_CLANG_COMPILER) || defined(__INTEL_LLVM_COMPILER) + #pragma message(REPORT_NAME("ICX")) // IntelLLVM +#elif defined(__wasi__) + #pragma message(REPORT_NAME("WASI")) +#elif defined(__saigo__) + #pragma message(REPORT_NAME("Saigo")) +#elif defined(__pnacl__) + #pragma message(REPORT_NAME("PNaCl")) +#elif defined(__MINGW64__) || defined(__MINGW32__) + #pragma message(REPORT_NAME("MinGW")) +#elif defined(__armclang_major__) || defined(__armclang_version__) + #pragma message(REPORT_NAME("ARMClang")) +#elif defined(__clang__) && (defined(__APPLE_CC__) || defined(__apple_build_version__)) + #pragma message(REPORT_NAME("AppleClang")) +#elif defined(__clang__) + #pragma message(REPORT_NAME("Clang")) +#elif defined(__GNUC__) + #pragma message(REPORT_NAME("GCC")) // GNU +#else + #pragma message(REPORT_NAME("Unknown")) +#endif + +// Make the compilation succeeds if architecture is supported. +int main(int, char**) { + return 0; +} diff --git a/cmake/DaemonCompiler/DaemonCompiler.cpp b/cmake/DaemonCompiler/DaemonCompiler.cpp new file mode 100644 index 0000000000..4b3d5f846a --- /dev/null +++ b/cmake/DaemonCompiler/DaemonCompiler.cpp @@ -0,0 +1 @@ +#include "DaemonCompiler.c" diff --git a/cmake/DaemonCompiler/DaemonCompiler.sh b/cmake/DaemonCompiler/DaemonCompiler.sh new file mode 100755 index 0000000000..d93cae3c44 --- /dev/null +++ b/cmake/DaemonCompiler/DaemonCompiler.sh @@ -0,0 +1,49 @@ +#! /usr/bin/env bash + +# Daemon BSD Source Code +# Copyright (c) 2024, Daemon Developers +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Test script not used by the CMake build system. Usage example: +# ./DaemonCompiler.sh gcc + +set -ueo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +file_path="${script_dir}/DaemonCompiler.c" + +# PNaCl doesn't work with “-o /dev/null” as it uses the output path as a +# pattern for temporary files and then the parent folder should be writable. +# Zig caches the build if both the source and the output don't change. Since +# the /dev/null file never changes, Zig skips the compilation once done once. +# So we need to use a randomly named path in a writable directory. +temp_file="$(mktemp)" + +"${@}" "${file_path}" -o "${temp_file}" 2>&1 \ + | grep 'REPORT>.*//' \ +|| "${@}" "${file_path}" -o "${temp_file}" + +rm "${temp_file}" diff --git a/cmake/DaemonFlags.cmake b/cmake/DaemonFlags.cmake index 83cd34728f..7baa84efa6 100644 --- a/cmake/DaemonFlags.cmake +++ b/cmake/DaemonFlags.cmake @@ -438,7 +438,13 @@ elseif (NOT NACL) if (ARCH STREQUAL "amd64") # K8 or EM64T minimum: AMD Athlon 64 ClawHammer, Intel Xeon Nocona, Intel Pentium 4 model F (Prescott revision EO), VIA Nano. - set(GCC_GENERIC_ARCH "x86-64") + if ("${DAEMON_CXX_COMPILER_NAME}" STREQUAL "ICC") + set(GCC_GENERIC_ARCH "pentium4") + elseif ("${DAEMON_CXX_COMPILER_NAME}" STREQUAL "Zig") + set(GCC_GENERIC_ARCH "x86_64") + else() + set(GCC_GENERIC_ARCH "x86-64") + endif() set(GCC_GENERIC_TUNE "generic") elseif (ARCH STREQUAL "i686") # P6 or K6 minimum: Intel Pentium Pro, AMD K6, Via Cyrix III, Via C3. @@ -468,6 +474,10 @@ elseif (NOT NACL) message(WARNING "Unknown architecture ${ARCH}") endif() + if ("${DAEMON_CXX_COMPILER_NAME}" STREQUAL "Zig") + unset(GCC_GENERIC_TUNE) + endif() + option(USE_CPU_GENERIC_ARCHITECTURE "Enforce generic -march and -mtune compiler options" ON) if (USE_CPU_GENERIC_ARCHITECTURE) try_c_cxx_flag_werror(MARCH "-march=${GCC_GENERIC_ARCH}") diff --git a/cmake/DaemonGame.cmake b/cmake/DaemonGame.cmake index 7ce783a737..aebe523faf 100644 --- a/cmake/DaemonGame.cmake +++ b/cmake/DaemonGame.cmake @@ -25,9 +25,14 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include_directories(${MOUNT_DIR} ${LIB_DIR} ${LIB_DIR}/zlib) -include(DaemonPlatform) -include(DaemonNacl) -include(DaemonFlags) + +# Do not report unused native compiler if native vms are not built. +# If only NACL vms are built, this will be reported in chainloaded build. +if (BUILD_GAME_NATIVE_DLL OR BUILD_GAME_NATIVE_EXE OR NACL) + include(DaemonPlatform) + include(DaemonNacl) + include(DaemonFlags) +endif() # Function to setup all the Sgame/Cgame libraries include(CMakeParseArguments) diff --git a/cmake/DaemonPlatform.cmake b/cmake/DaemonPlatform.cmake index 28de5c51db..be8f5f1c81 100644 --- a/cmake/DaemonPlatform.cmake +++ b/cmake/DaemonPlatform.cmake @@ -50,3 +50,4 @@ endif() include(DaemonArchitecture) +include(DaemonCompiler) diff --git a/src/engine/framework/System.cpp b/src/engine/framework/System.cpp index 8595e4654a..a3bee316d8 100644 --- a/src/engine/framework/System.cpp +++ b/src/engine/framework/System.cpp @@ -681,7 +681,8 @@ static void Init(int argc, char** argv) #endif // Print a banner and a copy of the command-line arguments - Log::Notice(Q3_VERSION " " PLATFORM_STRING " " XSTRING(ARCH_STRING) " " __DATE__); + Log::Notice(Q3_VERSION " " PLATFORM_STRING " " XSTRING(ARCH_STRING) " (" XSTRING(DAEMON_CXX_COMPILER_STRING) ") " __DATE__); + std::string argsString = "cmdline:"; for (int i = 1; i < argc; i++) { argsString.push_back(' ');