Merge branch 'clang_compiler_fix' into 'main'

fix: Resolve compilation failures and warnings with Clang

See merge request citron/emulator!83
This commit is contained in:
Zephyron
2025-10-06 10:41:06 +10:00
5 changed files with 160 additions and 4 deletions

View File

@@ -414,6 +414,28 @@ if(USE_DISCORD_PRESENCE)
endif()
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
message(STATUS "Applying custom patch to submodule's mcl for Clang compatibility...")
set(MCL_PATCH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/patches/mcl_clang_template_fix.patch")
set(MCL_PATCH_TARGET_DIR "${CMAKE_CURRENT_SOURCE_DIR}/externals/dynarmic/externals/mcl")
if(EXISTS "${MCL_PATCH_TARGET_DIR}")
execute_process(
COMMAND git apply --ignore-whitespace "${MCL_PATCH_FILE}"
WORKING_DIRECTORY "${MCL_PATCH_TARGET_DIR}"
RESULT_VARIABLE MCL_PATCH_RESULT
OUTPUT_QUIET
ERROR_QUIET
)
if(NOT MCL_PATCH_RESULT EQUAL 0)
message(WARNING "Failed to apply mcl Clang compatibility patch! This might be okay if it's already applied.")
endif()
else()
message(WARNING "Could not find mcl directory to patch. It may not have been downloaded yet.")
endif()
endif()
if (ENABLE_QT)
if (NOT USE_SYSTEM_QT)
@@ -681,7 +703,7 @@ if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
)
endif()
if (CITRON_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (CITRON_USE_FASTER_LD AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
# We will assume that if the compiler is GCC, it will attempt to use ld.bfd by default.
# Try to pick a faster linker.
find_program(LLD lld)
@@ -749,3 +771,19 @@ if(ENABLE_QT AND UNIX AND NOT APPLE)
install(FILES "dist/org.citron_emu.citron.metainfo.xml"
DESTINATION "share/metainfo")
endif()
# Final linker cleanup for Clang LTO.
# This forcefully removes any stray "-fuse-ld=bfd" flags that may have been
# incorrectly added by other parts of the build system.
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CITRON_ENABLE_LTO)
message(STATUS "Performing final linker flag cleanup for Clang LTO...")
foreach(target citron citron-cmd citron-room)
if(TARGET ${target})
get_target_property(link_options ${target} LINK_OPTIONS)
if(link_options)
string(REPLACE "-fuse-ld=bfd" "" link_options "${link_options}")
set_target_properties(${target} PROPERTIES LINK_OPTIONS "${link_options}")
endif()
endif()
endforeach()
endif()

View File

@@ -0,0 +1,112 @@
diff --git a/externals/mcl/include/mcl/mp/metafunction/map.hpp b/externals/mcl/include/mcl/mp/metafunction/map.hpp
index 13fcaecd..6bbe1a23 100644
--- a/externals/mcl/include/mcl/mp/metafunction/map.hpp
+++ b/externals/mcl/include/mcl/mp/metafunction/map.hpp
@@ -4,22 +4,32 @@
#pragma once
+#include "mcl/mp/typelist/list.hpp"
+
namespace mcl::mp {
-namespace detail {
+ namespace detail {
+
+ template<template<class...> class F, class L>
+ struct map_impl;
+
+ template<template<class...> class F, template<class...> class LT, class... Es>
+ struct map_impl<F, LT<Es...>> {
+ using type = LT<F<Es>...>;
+ };
-template<template<class...> class F, class L>
-struct map_impl;
-template<template<class...> class F, template<class...> class LT, class... Es>
-struct map_impl<F, LT<Es...>> {
- using type = LT<F<Es>...>;
-};
+ #if defined(__clang__) && !defined(_MSC_VER)
+ template <template<class...> class F, class... Es>
+ struct map_impl<F, mcl::mp::list<Es...>> {
+ using type = mcl::mp::list<F<Es>...>;
+ };
+ #endif
-} // namespace detail
+ } // namespace detail
-/// Applies each element of list L to metafunction F
-template<template<class...> class F, class L>
-using map = typename detail::map_impl<F, L>::type;
+ /// Applies each element of list L to metafunction F
+ template<template<class...> class F, class L>
+ using map = typename detail::map_impl<F, L>::type;
} // namespace mcl::mp
diff --git a/externals/mcl/include/mcl/mp/typelist/lift_sequence.hpp b/externals/mcl/include/mcl/mp/typelist/lift_sequence.hpp
index ba2617b8..10f7d6c5 100644
--- a/externals/mcl/include/mcl/mp/typelist/lift_sequence.hpp
+++ b/externals/mcl/include/mcl/mp/typelist/lift_sequence.hpp
@@ -5,25 +5,36 @@
#pragma once
#include <type_traits>
+#include <utility>
#include "mcl/mp/typelist/list.hpp"
namespace mcl::mp {
-namespace detail {
+ namespace detail {
-template<class VL>
-struct lift_sequence_impl;
+ template <class VL>
+ struct lift_sequence_impl; // Forward declaration
-template<class T, template<class, T...> class VLT, T... values>
-struct lift_sequence_impl<VLT<T, values...>> {
- using type = list<std::integral_constant<T, values>...>;
-};
+ // Original specialization (works for GCC/MSVC)
+ template <class T, template <class, T...> class VLT, T... values>
+ struct lift_sequence_impl<VLT<T, values...>> {
+ using type = list<std::integral_constant<T, values>...>;
+ };
-} // namespace detail
+ // Clang-specific fix: Add a more explicit specialization that Clang can match.
+ // We check for __clang__ but not _MSC_VER, as clang-cl on Windows might not need this.
+ #if defined(__clang__) && !defined(_MSC_VER)
+ template <class T, T... Ints>
+ struct lift_sequence_impl<std::integer_sequence<T, Ints...>> {
+ using type = list<std::integral_constant<T, Ints>...>;
+ };
+ #endif
-/// Lifts values in value list VL to create a type list.
-template<class VL>
-using lift_sequence = typename detail::lift_sequence_impl<VL>::type;
+ } // namespace detail
+
+ /// Lifts values in value list VL to create a type list.
+ template <class VL>
+ using lift_sequence = typename detail::lift_sequence_impl<VL>::type;
} // namespace mcl::mp
diff --git a/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp b/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp
index b8aa3eb6..b6eda4e4 100644
--- a/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp
+++ b/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp
@@ -1285,6 +1285,7 @@ void EmitX64::EmitFPVectorMul64(EmitContext& ctx, IR::Inst* inst) {
template<typename FPT, bool needs_rounding_correction, bool needs_nan_correction>
static void EmitFPVectorMulAddFallback(VectorArray<FPT>& result, const VectorArray<FPT>& addend, const VectorArray<FPT>& op1, const VectorArray<FPT>& op2, FP::FPCR fpcr, [[maybe_unused]] FP::FPSR& fpsr) {
+ #pragma clang loop vectorize(enable)
for (size_t i = 0; i < result.size(); i++) {
if constexpr (needs_rounding_correction) {
constexpr FPT non_sign_mask = FP::FPInfo<FPT>::exponent_mask | FP::FPInfo<FPT>::mantissa_mask;

View File

@@ -21,7 +21,7 @@ namespace Core {
class System;
}
namespace VkDeviceInfo {
struct Record;
class Record;
}
namespace Ui {
class ConfigureDialog;

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
@@ -41,7 +42,9 @@ PerfStats::~PerfStats() {
const auto path = Common::FS::GetCitronPath(Common::FS::CitronPath::LogDir);
// %F Date format expanded is "%Y-%m-%d"
const auto filename = fmt::format("{:%F-%H-%M}_{:016X}.csv", *std::localtime(&t), title_id);
char time_buf[128];
std::strftime(time_buf, sizeof(time_buf), "%F-%H-%M", std::localtime(&t));
const auto filename = fmt::format("{}_{:016X}.csv", time_buf, title_id);
const auto filepath = path / filename;
if (Common::FS::CreateParentDir(filepath)) {

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <ctime>
@@ -33,7 +34,9 @@ std::filesystem::path GetPath(std::string_view type, u64 title_id, std::string_v
std::string GetTimestamp() {
const auto time = std::time(nullptr);
return fmt::format("{:%FT%H-%M-%S}", *std::localtime(&time));
char time_buf[128];
std::strftime(time_buf, sizeof(time_buf), "%FT%H-%M-%S", std::localtime(&time));
return std::string(time_buf);
}
using namespace nlohmann;