Skip to content

Commit

Permalink
Fix a build issue when compiling with -fno-rtti (#606)
Browse files Browse the repository at this point in the history
  • Loading branch information
odygrd authored Oct 10, 2024
1 parent ca0e581 commit 602fdb5
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 56 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ jobs:
with_tests: ON
install: sudo apt -o Acquire::Retries=5 install g++-13

# Builds with no exceptions
# Builds the examples with no exceptions
- cxx: g++-10
build_type: Release
std: 17
os: ubuntu-20.04
with_tests: OFF
cmake_options: -DQUILL_NO_EXCEPTIONS=ON
cmake_options: -DQUILL_NO_EXCEPTIONS=ON -DQUILL_BUILD_TESTS=ON

# Build and test with valgrind
- cxx: g++-10
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ jobs:
with_tests: [ ON ]

include:
# Builds with no exceptions
# Builds the examples with no exceptions
- os: windows-2022
platform: x64
build_type: Release
std: 17
with_tests: "OFF"
cmake_options: -DQUILL_NO_EXCEPTIONS=ON
cmake_options: -DQUILL_NO_EXCEPTIONS=ON -DQUILL_BUILD_TESTS=ON

# Builds for ARM
- os: windows-2022
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@

- Added accessors to `Logger` for sinks, user clock source, clock source type, and pattern formatter options that can be
used to create another `Logger` with similar configuration
- Fixed a build issue when compiling with `-fno-rtti`. This ensures compatibility with projects that disable
`RTTI` ([#604](https://github.com/odygrd/quill/issues/604))

## v7.3.0

Expand Down
12 changes: 9 additions & 3 deletions cmake/QuillUtils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,15 @@ function(set_common_compile_options target_name)
-Wall -Wextra -pedantic -Werror>
$<$<CXX_COMPILER_ID:MSVC>:/bigobj /WX /W4 /wd4324 /wd4996>)

# Additional MSVC specific options
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
if (NOT QUILL_NO_EXCEPTIONS)
if (QUILL_NO_EXCEPTIONS)
# Add flags -fno-exceptions -fno-rtti to make sure we support them
target_compile_options(${target_name} ${COMPILE_OPTIONS_VISIBILITY}
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
-fno-exceptions -fno-rtti>
$<$<CXX_COMPILER_ID:MSVC>:/wd4702 /GR- /EHs-c- /D_HAS_EXCEPTIONS=0>)
else ()
# Additional MSVC specific options
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(${target_name} ${COMPILE_OPTIONS_VISIBILITY} /EHsc)
endif ()
endif ()
Expand Down
6 changes: 5 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ set(EXAMPLE_TARGETS
quill_example_csv_writing
quill_example_json_file_logging
quill_example_user_defined_types_logging
quill_example_user_defined_types_multi_format
)

# Add additional examples that are using exceptions in the example code
if (NOT QUILL_NO_EXCEPTIONS)
list(APPEND EXAMPLE_TARGETS quill_example_user_defined_types_multi_format)
endif ()

# Add example executables
foreach (example_target ${EXAMPLE_TARGETS})
# Determine the source file from the target name
Expand Down
9 changes: 8 additions & 1 deletion include/quill/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,20 @@ class FrontendImpl
{
assert(logger_base);

// MSVC can complain that another variable with the same name hides this variable
#if QUILL_USE_RTTI
// MSVC may warn that a variable with the same name is hidden by this declaration,
// so the variable is prefixed with an underscore ('_') to avoid shadowing.
auto* _logger_cast = dynamic_cast<logger_t*>(logger_base);

if (QUILL_UNLIKELY(!_logger_cast))
{
QUILL_THROW(QuillError{"Failed to cast logger. Invalid logger type."});
}
#else
// MSVC may warn that a variable with the same name is hidden by this declaration,
// so the variable is prefixed with an underscore ('_') to avoid shadowing.
auto* _logger_cast = static_cast<logger_t*>(logger_base);
#endif

return _logger_cast;
}
Expand Down
140 changes: 93 additions & 47 deletions include/quill/core/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,65 @@
}
#endif

/**
* __has_feature
*/
#ifndef QUILL_HAS_FEATURE
#ifdef __has_feature
#define QUILL_HAS_FEATURE(x) __has_feature(x)
#else
#define QUILL_HAS_FEATURE(x) 0
#endif
#endif

/**
* __has_attribute
*/
#ifdef __has_attribute
#define QUILL_HAS_ATTRIBUTE(x) __has_attribute(x)
#else
#define QUILL_HAS_ATTRIBUTE(x) 0
#ifndef QUILL_HAS_ATTRIBUTE
#ifdef __has_attribute
#define QUILL_HAS_ATTRIBUTE(x) __has_attribute(x)
#else
#define QUILL_HAS_ATTRIBUTE(x) 0
#endif
#endif

/**
* __has_cpp_attribute
*/
#if defined(__cplusplus) && defined(__has_cpp_attribute)
#define QUILL_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
#define QUILL_HAS_CPP_ATTRIBUTE(x) 0
#ifndef QUILL_HAS_CPP_ATTRIBUTE
#if defined(__cplusplus) && defined(__has_cpp_attribute)
#define QUILL_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
#define QUILL_HAS_CPP_ATTRIBUTE(x) 0
#endif
#endif

/**
* Portable no discard warnings
*/
#if QUILL_HAS_CPP_ATTRIBUTE(nodiscard)
#define QUILL_NODISCARD [[nodiscard]]
#elif QUILL_HAS_CPP_ATTRIBUTE(gnu::warn_unused_result)
#define QUILL_NODISCARD [[gnu::warn_unused_result]]
#else
#define QUILL_NODISCARD
#ifndef QUILL_NODISCARD
#if QUILL_HAS_CPP_ATTRIBUTE(nodiscard)
#define QUILL_NODISCARD [[nodiscard]]
#elif QUILL_HAS_CPP_ATTRIBUTE(gnu::warn_unused_result)
#define QUILL_NODISCARD [[gnu::warn_unused_result]]
#else
#define QUILL_NODISCARD
#endif
#endif

/**
* Portable maybe_unused
*/
#if QUILL_HAS_CPP_ATTRIBUTE(maybe_unused) && (defined(_HAS_CXX17) && _HAS_CXX17 == 1)
#define QUILL_MAYBE_UNUSED [[maybe_unused]]
#elif QUILL_HAS_ATTRIBUTE(__unused__) || defined(__GNUC__)
#define QUILL_MAYBE_UNUSED __attribute__((__unused__))
#elif defined(_MSC_VER)
#define QUILL_MAYBE_UNUSED __pragma(warning(suppress : 4100))
#else
#define QUILL_MAYBE_UNUSED
#ifndef QUILL_MAYBE_UNUSED
#if QUILL_HAS_CPP_ATTRIBUTE(maybe_unused) && (defined(_HAS_CXX17) && _HAS_CXX17 == 1)
#define QUILL_MAYBE_UNUSED [[maybe_unused]]
#elif QUILL_HAS_ATTRIBUTE(__unused__) || defined(__GNUC__)
#define QUILL_MAYBE_UNUSED __attribute__((__unused__))
#elif defined(_MSC_VER)
#define QUILL_MAYBE_UNUSED __pragma(warning(suppress : 4100))
#else
#define QUILL_MAYBE_UNUSED
#endif
#endif

/**
Expand All @@ -65,43 +84,70 @@
* improve static analysis, i.e. a conditional branch to a cold function
* is likely to be not-taken.
*/
#if QUILL_HAS_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__))
#define QUILL_ATTRIBUTE_HOT __attribute__((hot))
#else
#define QUILL_ATTRIBUTE_HOT
#ifndef QUILL_ATTRIBUTE_HOT
#if QUILL_HAS_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__))
#define QUILL_ATTRIBUTE_HOT __attribute__((hot))
#else
#define QUILL_ATTRIBUTE_HOT
#endif
#endif

#if QUILL_HAS_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__))
#define QUILL_ATTRIBUTE_COLD __attribute__((cold))
#else
#define QUILL_ATTRIBUTE_COLD
#ifndef QUILL_ATTRIBUTE_COLD
#if QUILL_HAS_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__))
#define QUILL_ATTRIBUTE_COLD __attribute__((cold))
#else
#define QUILL_ATTRIBUTE_COLD
#endif
#endif

/**
* Likely
*/
#if defined(__GNUC__)
#define QUILL_LIKELY(x) (__builtin_expect((x), 1))
#define QUILL_UNLIKELY(x) (__builtin_expect((x), 0))
#else
#define QUILL_LIKELY(x) (x)
#define QUILL_UNLIKELY(x) (x)
#ifndef QUILL_LIKELY
#if defined(__GNUC__)
#define QUILL_LIKELY(x) (__builtin_expect((x), 1))
#else
#define QUILL_LIKELY(x) (x)
#endif
#endif

#ifndef QUILL_UNLIKELY
#if defined(__GNUC__)
#define QUILL_UNLIKELY(x) (__builtin_expect((x), 0))
#else
#define QUILL_UNLIKELY(x) (x)
#endif
#endif

/**
* Visibility
*/
#if defined(_WIN32) && defined(_MSC_VER)
#if defined(QUILL_DLL_EXPORT)
#define QUILL_EXPORT __declspec(dllexport) // Exporting symbols when building the library
#elif defined(QUILL_DLL_IMPORT)
#define QUILL_EXPORT __declspec(dllimport) // Importing symbols when using the library
#ifndef QUILL_EXPORT
#if defined(_WIN32) && defined(_MSC_VER)
#if defined(QUILL_DLL_EXPORT)
#define QUILL_EXPORT __declspec(dllexport) // Exporting symbols when building the library
#elif defined(QUILL_DLL_IMPORT)
#define QUILL_EXPORT __declspec(dllimport) // Importing symbols when using the library
#else
#define QUILL_EXPORT // No special attribute needed for static or other builds
#endif
#elif defined(__GNUC__) || defined(__clang__)
#define QUILL_EXPORT \
__attribute__((visibility("default"))) // Using GCC/Clang visibility attribute
#else
#define QUILL_EXPORT // Default for other compilers
#endif
#endif

/**
* Check RTTI is available
*/
#ifndef QUILL_USE_RTTI
// __RTTI is for EDG compilers. _CPPRTTI is for MSVC.
#if defined(__GXX_RTTI) || QUILL_HAS_FEATURE(cxx_rtti) || defined(_CPPRTTI) || \
defined(__INTEL_RTTI__) || defined(__RTTI)
#define QUILL_USE_RTTI 1
#else
#define QUILL_EXPORT // No special attribute needed for static or other builds
#define QUILL_USE_RTTI 0
#endif
#elif defined(__GNUC__) || defined(__clang__)
#define QUILL_EXPORT \
__attribute__((visibility("default"))) // Using GCC/Clang visibility attribute
#else
#define QUILL_EXPORT // Default for other compilers
#endif

0 comments on commit 602fdb5

Please sign in to comment.