From 824e352da1443eb0e62adfcecbc48fc0d4f8be5e Mon Sep 17 00:00:00 2001 From: Mike Solar Date: Sun, 2 Aug 2026 17:44:51 +0800 Subject: [PATCH] ci: declare all oakengine handle types opaque for Qt metatypes; defer gtest discovery on Windows - Linux GCC rejects QMetaType instantiation over incomplete types (static_assert(sizeof(T))); Q_DECLARE_OPAQUE_POINTER every opaque OakEngine* handle in the public headers so QList etc compile - Windows: gtest discovery ran the fresh exe before the DLLs were next to it; use DISCOVERY_MODE PRE_TEST on WIN32 and copy the DLLs for ctest time --- core/tests/CMakeLists.txt | 9 ++++++--- engine/CMakeLists.txt | 9 ++++++--- engine/include/oakengine/audio.h | 1 + engine/include/oakengine/color.h | 3 +++ engine/include/oakengine/encoding.h | 1 + engine/include/oakengine/footage.h | 1 + engine/include/oakengine/node.h | 3 +++ engine/include/oakengine/playback.h | 1 + engine/include/oakengine/preview.h | 1 + engine/include/oakengine/project.h | 4 ++++ engine/include/oakengine/renderer.h | 3 +++ engine/include/oakengine/serializer.h | 2 ++ engine/include/oakengine/task.h | 1 + engine/include/oakengine/timeline.h | 10 ++++++++-- engine/include/oakengine/traverse.h | 1 + engine/include/oakengine/viewer.h | 4 ++++ 16 files changed, 46 insertions(+), 8 deletions(-) diff --git a/core/tests/CMakeLists.txt b/core/tests/CMakeLists.txt index 605cde22b..b362934ce 100644 --- a/core/tests/CMakeLists.txt +++ b/core/tests/CMakeLists.txt @@ -31,11 +31,14 @@ target_include_directories(oakcore_gtest PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../include/olive/core" ) -gtest_discover_tests(oakcore_gtest) - if (WIN32) - # gtest discovery executes the binary at build time; it needs the DLL next to it + # gtest discovery would run the freshly linked exe at build time before the + # DLLs are copied; defer discovery to ctest time on Windows. + gtest_discover_tests(oakcore_gtest DISCOVERY_MODE PRE_TEST) + # The test exe needs the DLL next to it (both for ctest and discovery) add_custom_command(TARGET oakcore_gtest POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $) +else () + gtest_discover_tests(oakcore_gtest) endif () diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 915ed4b4f..3987fb61a 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -291,10 +291,11 @@ if (BUILD_TESTS) endif () # Freshly linked binaries can exceed the 5s default discovery # timeout on first run (dyld cold cache + Qt/OCIO init) - gtest_discover_tests(${name} DISCOVERY_TIMEOUT 60) if (WIN32) - # gtest discovery executes the binary at build time; it needs - # the engine DLLs next to it + # Defer discovery to ctest time; at build time the DLLs are not + # next to the exe yet (copied below). + gtest_discover_tests(${name} DISCOVERY_TIMEOUT 60 + DISCOVERY_MODE PRE_TEST) add_custom_command(TARGET ${name} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ @@ -302,6 +303,8 @@ if (BUILD_TESTS) $ $ COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $) + else () + gtest_discover_tests(${name} DISCOVERY_TIMEOUT 60) endif () endfunction() diff --git a/engine/include/oakengine/audio.h b/engine/include/oakengine/audio.h index 306d2f298..b6000727d 100644 --- a/engine/include/oakengine/audio.h +++ b/engine/include/oakengine/audio.h @@ -325,6 +325,7 @@ OAKENGINE_API OakAudioParams *oakengine_audio_processor_output_params( #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEngineAudioProcessor *) #endif #endif /* OAKENGINE_AUDIO_H */ diff --git a/engine/include/oakengine/color.h b/engine/include/oakengine/color.h index d3b9ac986..9152178b9 100644 --- a/engine/include/oakengine/color.h +++ b/engine/include/oakengine/color.h @@ -292,6 +292,9 @@ OAKENGINE_API int oakengine_color_transform_job_set_processor( #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEngineColorManager *) +Q_DECLARE_OPAQUE_POINTER(OakEngineColorProcessor *) +Q_DECLARE_OPAQUE_POINTER(OakEngineColorConfig *) #endif #endif /* OAKENGINE_COLOR_H */ diff --git a/engine/include/oakengine/encoding.h b/engine/include/oakengine/encoding.h index 1972867a4..fe3dc5bd5 100644 --- a/engine/include/oakengine/encoding.h +++ b/engine/include/oakengine/encoding.h @@ -500,6 +500,7 @@ oakengine_encoding_start_audio_recording(const OakEngineEncodingParams *params, #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEngineEncodingParams *) #endif #endif /* OAKENGINE_ENCODING_H */ diff --git a/engine/include/oakengine/footage.h b/engine/include/oakengine/footage.h index ecd5afba0..1352bd5e2 100644 --- a/engine/include/oakengine/footage.h +++ b/engine/include/oakengine/footage.h @@ -511,6 +511,7 @@ OAKENGINE_API int oakengine_footage_invalidate(OakEngineFootage *self); #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEngineFootage *) #endif #endif /* OAKENGINE_FOOTAGE_H */ diff --git a/engine/include/oakengine/node.h b/engine/include/oakengine/node.h index e2dafcedb..8e8cf8125 100644 --- a/engine/include/oakengine/node.h +++ b/engine/include/oakengine/node.h @@ -2087,6 +2087,9 @@ oakengine_node_get_video_frame_cache(const OakEngineNode *self); Q_DECLARE_OPAQUE_POINTER(OakEngineNode *) Q_DECLARE_OPAQUE_POINTER(OakEngineKeyframe *) Q_DECLARE_OPAQUE_POINTER(OakEngineNodeDragger *) +Q_DECLARE_OPAQUE_POINTER(OakEngineFrameCache *) +Q_DECLARE_OPAQUE_POINTER(OakEngineThumbnailCache *) +Q_DECLARE_OPAQUE_POINTER(OakEngineWaveformCache *) #endif #endif /* OAKENGINE_NODE_H */ diff --git a/engine/include/oakengine/playback.h b/engine/include/oakengine/playback.h index c08bbd864..9cc06a23c 100644 --- a/engine/include/oakengine/playback.h +++ b/engine/include/oakengine/playback.h @@ -213,6 +213,7 @@ OAKENGINE_API int oakengine_playback_last_error( #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEnginePlayback *) #endif #endif /* OAKENGINE_PLAYBACK_H */ diff --git a/engine/include/oakengine/preview.h b/engine/include/oakengine/preview.h index f9f9f525c..7005fb81d 100644 --- a/engine/include/oakengine/preview.h +++ b/engine/include/oakengine/preview.h @@ -246,6 +246,7 @@ OAKENGINE_API void oakengine_preview_request_free( #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEnginePreviewRequest *) #endif #endif /* OAKENGINE_PREVIEW_H */ diff --git a/engine/include/oakengine/project.h b/engine/include/oakengine/project.h index 2be1df91d..b3066680e 100644 --- a/engine/include/oakengine/project.h +++ b/engine/include/oakengine/project.h @@ -339,6 +339,10 @@ OAKENGINE_API int oakengine_project_set_color_reference_space( #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEngineNode *) +Q_DECLARE_OPAQUE_POINTER(OakEnginePlaybackCache *) +Q_DECLARE_OPAQUE_POINTER(OakEngineProject *) +Q_DECLARE_OPAQUE_POINTER(OakEngineSequence *) #endif #endif /* OAKENGINE_PROJECT_H */ diff --git a/engine/include/oakengine/renderer.h b/engine/include/oakengine/renderer.h index 67af56135..e9f47dc12 100644 --- a/engine/include/oakengine/renderer.h +++ b/engine/include/oakengine/renderer.h @@ -245,6 +245,9 @@ OAKENGINE_API void oakengine_audio_free(OakEngineAudioBuffer *self); #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEngineRenderer *) +Q_DECLARE_OPAQUE_POINTER(OakEngineFrame *) +Q_DECLARE_OPAQUE_POINTER(OakEngineAudioBuffer *) #endif #endif /* OAKENGINE_RENDERER_H */ diff --git a/engine/include/oakengine/serializer.h b/engine/include/oakengine/serializer.h index e12bc1bcd..632ceca22 100644 --- a/engine/include/oakengine/serializer.h +++ b/engine/include/oakengine/serializer.h @@ -249,6 +249,8 @@ OAKENGINE_API int oakengine_clipboard_foreach_connection( #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEngineClipboard *) +Q_DECLARE_OPAQUE_POINTER(OakEngineMarker *) #endif #endif /* OAKENGINE_SERIALIZER_H */ diff --git a/engine/include/oakengine/task.h b/engine/include/oakengine/task.h index 9310177fb..4b870bd7b 100644 --- a/engine/include/oakengine/task.h +++ b/engine/include/oakengine/task.h @@ -288,6 +288,7 @@ oakengine_task_save_get_project(OakEngineTask *task); #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEngineTask *) #endif #endif /* OAKENGINE_TASK_H */ diff --git a/engine/include/oakengine/timeline.h b/engine/include/oakengine/timeline.h index 2f774e3cb..ecc732434 100644 --- a/engine/include/oakengine/timeline.h +++ b/engine/include/oakengine/timeline.h @@ -1310,9 +1310,15 @@ oakengine_clip_get_connected_viewer(const OakEngineBlock *clip); } // Qt6 on some toolchains requires complete types in meta-type instantiations -// (e.g. QList in TimelinePanel signals); declare the handle -// opaque instead of pulling the engine definition into the public header. +// (e.g. QList in TimelinePanel signals); declare the handles +// opaque instead of pulling the engine definitions into the public header. Q_DECLARE_OPAQUE_POINTER(OakEngineBlock *) +Q_DECLARE_OPAQUE_POINTER(OakEngineClip *) +Q_DECLARE_OPAQUE_POINTER(OakEngineMarkerList *) +Q_DECLARE_OPAQUE_POINTER(OakEngineMarker *) +Q_DECLARE_OPAQUE_POINTER(OakEngineWorkarea *) +Q_DECLARE_OPAQUE_POINTER(OakEngineTrack *) +Q_DECLARE_OPAQUE_POINTER(OakEngineTrackList *) #endif #endif /* OAKENGINE_TIMELINE_H */ diff --git a/engine/include/oakengine/traverse.h b/engine/include/oakengine/traverse.h index b920f127f..189971f45 100644 --- a/engine/include/oakengine/traverse.h +++ b/engine/include/oakengine/traverse.h @@ -162,6 +162,7 @@ OAKENGINE_API int oakengine_traverse_transform( #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEngineTraverseDb *) #endif #endif /* OAKENGINE_TRAVERSE_H */ diff --git a/engine/include/oakengine/viewer.h b/engine/include/oakengine/viewer.h index 0c6a8cd77..a801447b8 100644 --- a/engine/include/oakengine/viewer.h +++ b/engine/include/oakengine/viewer.h @@ -440,6 +440,10 @@ OAKENGINE_API int oakengine_waveform_cache_get_summary( #ifdef __cplusplus } +Q_DECLARE_OPAQUE_POINTER(OakEnginePlaybackCache *) +Q_DECLARE_OPAQUE_POINTER(OakEngineFrameCache *) +Q_DECLARE_OPAQUE_POINTER(OakEngineThumbnailCache *) +Q_DECLARE_OPAQUE_POINTER(OakEngineWaveformCache *) #endif #endif /* OAKENGINE_VIEWER_H */