From b33eed393d5ce57d6a4100f8500695cd78ca6f85 Mon Sep 17 00:00:00 2001 From: Kai Blaschke Date: Sat, 6 Dec 2025 19:35:04 +0100 Subject: [PATCH] Fix CXX interface exports and headers Added separate export header, export macros for all required classes and functions and installing the headers in the correct directory structure. --- CMakeLists.txt | 10 --- src/api/CMakeLists.txt | 20 ++++++ src/libprojectM/Audio/CMakeLists.txt | 16 ++++- src/libprojectM/Audio/FrameAudioData.hpp | 4 +- src/libprojectM/Audio/Loudness.hpp | 8 ++- src/libprojectM/Audio/MilkdropFFT.hpp | 5 +- src/libprojectM/Audio/PCM.hpp | 14 ++-- src/libprojectM/Audio/WaveformAligner.hpp | 8 ++- src/libprojectM/CMakeLists.txt | 65 ++++++++++++++----- src/libprojectM/Logging.hpp | 18 ++--- src/libprojectM/MilkdropPreset/CMakeLists.txt | 21 ++++-- src/libprojectM/ProjectM.hpp | 13 +++- src/libprojectM/ProjectMCWrapper.cpp | 4 +- src/libprojectM/Renderer/CMakeLists.txt | 20 ++++++ src/libprojectM/Renderer/RenderContext.hpp | 4 +- src/libprojectM/UserSprites/CMakeLists.txt | 20 ++++++ vendor/hlslparser/CMakeLists.txt | 5 ++ 17 files changed, 195 insertions(+), 60 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32000a1bb..b0268b90a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,16 +199,6 @@ else() endif() endif() -if(ENABLE_CXX_INTERFACE) - set(CMAKE_C_VISIBILITY_PRESET default) - set(CMAKE_CXX_VISIBILITY_PRESET default) - set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF) -else() - set(CMAKE_C_VISIBILITY_PRESET hidden) - set(CMAKE_CXX_VISIBILITY_PRESET hidden) - set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) -endif() - # Disable trace/debug logging in release builds unless explicitly requested add_compile_definitions( $<$,$>:ENABLE_DEBUG_LOGGING> diff --git a/src/api/CMakeLists.txt b/src/api/CMakeLists.txt index e01e643f8..0a94bfffd 100644 --- a/src/api/CMakeLists.txt +++ b/src/api/CMakeLists.txt @@ -11,6 +11,14 @@ generate_export_header(projectM_api EXPORT_FILE_NAME "${PROJECTM_EXPORT_HEADER}" ) +# Always generate the header, but we only install it if the C++ interface is actually enabled. +set(PROJECTM_CXX_EXPORT_HEADER "${CMAKE_CURRENT_BINARY_DIR}/include/projectM-4/projectM_cxx_export.h") + +generate_export_header(projectM_api + BASE_NAME projectM_CXX + EXPORT_FILE_NAME "${PROJECTM_CXX_EXPORT_HEADER}" + ) + set(PROJECTM_PUBLIC_HEADERS "${PROJECTM_EXPORT_HEADER}" "${CMAKE_CURRENT_BINARY_DIR}/include/projectM-4/version.h" @@ -28,6 +36,10 @@ set(PROJECTM_PUBLIC_HEADERS include/projectM-4/user_sprites.h ) +if(ENABLE_CXX_INTERFACE) + list(APPEND PROJECTM_PUBLIC_HEADERS ${PROJECTM_CXX_EXPORT_HEADER}) +endif() + target_sources(projectM_api PRIVATE ${PROJECTM_PUBLIC_HEADERS} @@ -46,6 +58,14 @@ target_include_directories(projectM_api "$" ) +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(projectM_api + INTERFACE + PROJECTM_STATIC_DEFINE + PROJECTM_CXX_STATIC_DEFINE + ) +endif() + add_library(libprojectM::API ALIAS projectM_api) diff --git a/src/libprojectM/Audio/CMakeLists.txt b/src/libprojectM/Audio/CMakeLists.txt index 99685b95c..e5b14d56f 100644 --- a/src/libprojectM/Audio/CMakeLists.txt +++ b/src/libprojectM/Audio/CMakeLists.txt @@ -20,4 +20,18 @@ target_include_directories(Audio target_link_libraries(Audio PUBLIC libprojectM::API - ) \ No newline at end of file + ) + +if(BUILD_SHARED_LIBS) + if(ENABLE_CXX_INTERFACE) + target_compile_definitions(Audio + PRIVATE + projectM_api_EXPORTS + ) + else() + target_compile_definitions(Audio + PRIVATE + PROJECTM_CXX_STATIC_DEFINE + ) + endif() +endif() diff --git a/src/libprojectM/Audio/FrameAudioData.hpp b/src/libprojectM/Audio/FrameAudioData.hpp index 98ed4177a..bde4245a9 100644 --- a/src/libprojectM/Audio/FrameAudioData.hpp +++ b/src/libprojectM/Audio/FrameAudioData.hpp @@ -8,14 +8,14 @@ #include "Audio/AudioConstants.hpp" -#include +#include #include namespace libprojectM { namespace Audio { -class PROJECTM_EXPORT FrameAudioData +class PROJECTM_CXX_EXPORT FrameAudioData { public: float bass{0.f}; diff --git a/src/libprojectM/Audio/Loudness.hpp b/src/libprojectM/Audio/Loudness.hpp index 7d453bd29..011a7fe27 100644 --- a/src/libprojectM/Audio/Loudness.hpp +++ b/src/libprojectM/Audio/Loudness.hpp @@ -7,6 +7,8 @@ #include "Audio/AudioConstants.hpp" +#include + #include #include @@ -16,14 +18,14 @@ namespace Audio { /** * @brief Calculates beat-detection loudness relative to the previous frame(s). */ -class Loudness +class PROJECTM_CXX_EXPORT Loudness { public: /** * @brief Frequency bands. * Only the first half of the spectrum is used for these bands, each using one third of this half. */ - enum class Band : int + enum class Band : std::uint8_t { Bass = 0, //!< Bass band (first sixth of the spectrum) Middles = 1, //!< Middles band (second sixth of the spectrum) @@ -76,7 +78,7 @@ private: void UpdateBandAverage(double secondsSinceLastFrame, uint32_t frame); /** - * @brief Adjusts the dampening rate according the the current FPS. + * @brief Adjusts the dampening rate according to the current FPS. * @param rate The rate to be dampened. * @param secondsSinceLastFrame (Fractional) seconds passed since the last frame. * @return The dampened rate value. diff --git a/src/libprojectM/Audio/MilkdropFFT.hpp b/src/libprojectM/Audio/MilkdropFFT.hpp index cf2806c79..f9474df58 100644 --- a/src/libprojectM/Audio/MilkdropFFT.hpp +++ b/src/libprojectM/Audio/MilkdropFFT.hpp @@ -29,7 +29,10 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once +#include + #include +#include #include namespace libprojectM { @@ -40,7 +43,7 @@ namespace Audio { * Also applies an equalizer pattern with an envelope curve to the resulting data to smooth out * certain artifacts. */ -class MilkdropFFT +class PROJECTM_CXX_EXPORT MilkdropFFT { public: /** diff --git a/src/libprojectM/Audio/PCM.hpp b/src/libprojectM/Audio/PCM.hpp index bfda1a423..26871954d 100755 --- a/src/libprojectM/Audio/PCM.hpp +++ b/src/libprojectM/Audio/PCM.hpp @@ -13,7 +13,7 @@ #include "Audio/MilkdropFFT.hpp" #include "Audio/WaveformAligner.hpp" -#include +#include #include #include @@ -23,7 +23,7 @@ namespace libprojectM { namespace Audio { -class PCM +class PROJECTM_CXX_EXPORT PCM { public: /** @@ -33,7 +33,7 @@ public: * @param channels The number of channels in the input data. * @param count The amount of samples in the buffer */ - PROJECTM_EXPORT void Add(const float* samples, uint32_t channels, size_t count); + void Add(const float* samples, uint32_t channels, size_t count); /** * @brief Adds new mono unsigned 8-bit PCM data to the storage @@ -42,7 +42,7 @@ public: * @param channels The number of channels in the input data. * @param count The amount of samples in the buffer */ - PROJECTM_EXPORT void Add(const uint8_t* samples, uint32_t channels, size_t count); + void Add(const uint8_t* samples, uint32_t channels, size_t count); /** * @brief Adds new mono signed 16-bit PCM data to the storage @@ -51,7 +51,7 @@ public: * @param channels The number of channels in the input data. * @param count The amount of samples in the buffer */ - PROJECTM_EXPORT void Add(const int16_t* samples, uint32_t channels, size_t count); + void Add(const int16_t* samples, uint32_t channels, size_t count); /** * @brief Updates the internal audio data values for rendering the next frame. @@ -64,13 +64,13 @@ public: * @param secondsSinceLastFrame Time passed since rendering the last frame. Basically 1.0/FPS. * @param frame Frames rendered since projectM was started. */ - PROJECTM_EXPORT void UpdateFrameAudioData(double secondsSinceLastFrame, uint32_t frame); + void UpdateFrameAudioData(double secondsSinceLastFrame, uint32_t frame); /** * @brief Returns a class holding a copy of the current frame audio data. * @return A FrameAudioData class with waveform, spectrum and other derived values. */ - PROJECTM_EXPORT auto GetFrameAudioData() const -> FrameAudioData; + auto GetFrameAudioData() const -> FrameAudioData; private: template< diff --git a/src/libprojectM/Audio/WaveformAligner.hpp b/src/libprojectM/Audio/WaveformAligner.hpp index 9c0950b4f..5e12acfd7 100644 --- a/src/libprojectM/Audio/WaveformAligner.hpp +++ b/src/libprojectM/Audio/WaveformAligner.hpp @@ -7,7 +7,9 @@ #include "Audio/AudioConstants.hpp" -#include +#include + +#include #include #include @@ -23,7 +25,7 @@ namespace Audio { * This will keep similar features in-place instead of randomly jumping around on each frame and creates * for a smoother-looking waveform visualization. */ -class WaveformAligner +class PROJECTM_CXX_EXPORT WaveformAligner { public: WaveformAligner(); @@ -36,7 +38,7 @@ public: protected: void GenerateWeights(); - int CalculateOffset(std::vector& newWaveformMips); + auto CalculateOffset(std::vector& newWaveformMips) -> int; void ResampleOctaves(std::vector& dstWaveformMips, WaveformBuffer& newWaveform); bool m_alignWaveReady{false}; //!< Alignment needs special treatment for the first buffer fill. diff --git a/src/libprojectM/CMakeLists.txt b/src/libprojectM/CMakeLists.txt index 2fc1c3160..60e015bef 100644 --- a/src/libprojectM/CMakeLists.txt +++ b/src/libprojectM/CMakeLists.txt @@ -77,6 +77,13 @@ target_include_directories(projectM "$" ) +if(ENABLE_CXX_INTERFACE) + target_include_directories(projectM + PUBLIC + "$" + ) +endif() + target_link_libraries(projectM PUBLIC ${PROJECTM_OPENGL_LIBRARIES} @@ -99,10 +106,25 @@ set_target_properties(projectM PROPERTIES ) if(BUILD_SHARED_LIBS) - target_compile_definitions(projectM_main - PRIVATE - projectM_api_EXPORTS - ) + # If the C++ interface was requested, enable all exports. Otherwise, + # we only enable API exports for the C wrapper, and disable it for all other files. + if(ENABLE_CXX_INTERFACE) + target_compile_definitions(projectM_main + PRIVATE + projectM_api_EXPORTS + ) + else() + # Using PROJECTM_CXX_STATIC_DEFINE has precedence over projectM_api_EXPORTS, + # so all PROJECTM_CXX_EXPORT macros are removed. + target_compile_definitions(projectM_main + PRIVATE + PROJECTM_CXX_STATIC_DEFINE + ) + + set_source_files_properties(ProjectMCWrapper.cpp PROPERTIES + COMPILE_DEFINITIONS projectM_api_EXPORTS + ) + endif() target_link_libraries(projectM PUBLIC @@ -112,6 +134,13 @@ else() target_compile_definitions(projectM_main PUBLIC PROJECTM_STATIC_DEFINE + PROJECTM_CXX_STATIC_DEFINE + ) + + target_compile_definitions(projectM + INTERFACE + PROJECTM_STATIC_DEFINE + PROJECTM_CXX_STATIC_DEFINE ) set_target_properties(projectM PROPERTIES @@ -134,24 +163,30 @@ if(ENABLE_INSTALL) if(ENABLE_CXX_INTERFACE) install(FILES + Audio/AudioConstants.hpp + Audio/FrameAudioData.hpp + Audio/Loudness.hpp + Audio/MilkdropFFT.hpp Audio/PCM.hpp + Audio/WaveformAligner.hpp + DESTINATION "${PROJECTM_INCLUDE_DIR}/projectM-4/Audio" + COMPONENT Devel + ) + + install(FILES + Renderer/RenderContext.hpp + DESTINATION "${PROJECTM_INCLUDE_DIR}/projectM-4/Renderer" + COMPONENT Devel + ) + + install(FILES + Logging.hpp ProjectM.hpp DESTINATION "${PROJECTM_INCLUDE_DIR}/projectM-4" COMPONENT Devel ) - else() - # Set PROJECTM_STATIC_EXPORT for C++ implementations to use project default visibility - # and no dllimport/dllexport. - set_source_files_properties(ProjectM.cpp Audio/PCM.cpp PROPERTIES - COMPILE_DEFINITIONS PROJECTM_STATIC_DEFINE - ) - target_compile_definitions(projectM - INTERFACE - PROJECTM_STATIC_DEFINE - ) endif() - # CMake target exports # For use from a local projectM build tree (without installing) diff --git a/src/libprojectM/Logging.hpp b/src/libprojectM/Logging.hpp index 1b0ce021b..25f870fcc 100644 --- a/src/libprojectM/Logging.hpp +++ b/src/libprojectM/Logging.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include @@ -48,38 +50,38 @@ public: * Sets the global callback function pointer used across all threads. * @param callback A UserCallback struct with the new function and user data pointers. */ - static void SetGlobalCallback(UserCallback callback); + PROJECTM_CXX_EXPORT static void SetGlobalCallback(UserCallback callback); /** * Sets the thread-specific callback function pointer only used in the thread which registered it. * @param callback A UserCallback struct with the new function and user data pointers. */ - static void SetThreadCallback(UserCallback callback); + PROJECTM_CXX_EXPORT static void SetThreadCallback(UserCallback callback); /** * Sets the global log level used across all threads. * @param logLevel The log level to use. If set to LogLevel::NotSet, the value of m_defaultLogLevel is used. */ - static void SetGlobalLogLevel(LogLevel logLevel); + PROJECTM_CXX_EXPORT static void SetGlobalLogLevel(LogLevel logLevel); /** * Sets the thread-specific log level only used in the thread which set it. * @param logLevel The log level to use. If set to LogLevel::NotSet, the value of m_defaultLogLevel is used. */ - static void SetThreadLogLevel(LogLevel logLevel); + PROJECTM_CXX_EXPORT static void SetThreadLogLevel(LogLevel logLevel); /** * Returns the effective log level for the current thread. * @return The log level set for this thread, or, if LogLevel::NotSet, the global log level. * If no global log level is set, it returns the value of m_defaultLogLevel. */ - static auto GetLogLevel() -> LogLevel; + PROJECTM_CXX_EXPORT static auto GetLogLevel() -> LogLevel; /** * Returns whether a callback is registered or not. * @return true if a callback is registered for the current thread or globally, false if none is registered. */ - static auto HasCallback() -> bool; + PROJECTM_CXX_EXPORT static auto HasCallback() -> bool; /** * @brief Passes a log message with the given severity to the active thread or global callback. @@ -87,12 +89,12 @@ public: * @param message * @param severity */ - static void Log(const std::string& message, LogLevel severity); + PROJECTM_CXX_EXPORT static void Log(const std::string& message, LogLevel severity); /** * The default log level used if no log level is set (LogLevel::Information) */ - static const LogLevel m_defaultLogLevel; + PROJECTM_CXX_EXPORT static const LogLevel m_defaultLogLevel; private: /** diff --git a/src/libprojectM/MilkdropPreset/CMakeLists.txt b/src/libprojectM/MilkdropPreset/CMakeLists.txt index 6889d8ad2..f8d8657cf 100644 --- a/src/libprojectM/MilkdropPreset/CMakeLists.txt +++ b/src/libprojectM/MilkdropPreset/CMakeLists.txt @@ -143,11 +143,24 @@ target_link_libraries(MilkdropPreset ${PROJECTM_OPENGL_LIBRARIES} ) -if(NOT BUILD_SHARED_LIBS) +if(BUILD_SHARED_LIBS) + if(ENABLE_CXX_INTERFACE) + target_compile_definitions(MilkdropPreset + PRIVATE + projectM_api_EXPORTS + ) + else() + target_compile_definitions(MilkdropPreset + PRIVATE + PROJECTM_CXX_STATIC_DEFINE + ) + endif() +else() target_compile_definitions(MilkdropPreset - PRIVATE - PROJECTM_STATIC_DEFINE - ) + PRIVATE + PROJECTM_STATIC_DEFINE + PROJECTM_CXX_STATIC_DEFINE + ) endif() set_target_properties(MilkdropPreset PROPERTIES diff --git a/src/libprojectM/ProjectM.hpp b/src/libprojectM/ProjectM.hpp index 7b293b45b..f321a05b1 100644 --- a/src/libprojectM/ProjectM.hpp +++ b/src/libprojectM/ProjectM.hpp @@ -20,12 +20,14 @@ */ #pragma once -#include +#include #include #include