feat(build): Implement system-wide symbol visibility for Windows#1141
Conversation
There was a problem hiding this comment.
Thanks! Overall it looks good to me now. Two minor comments, one see above, second: the commit message is wrong.
And as I am not familiar with swig could you briefly explain the swig changes and why they are needed? Did you test them?
Next steps:
- I like to test this change on our Kdenlive pipelines to verify it doesn't cause regressions on any platform
- Final review
One note for the future: it would be nice if you could just update the existing PR for iterations like this instead of making a new one. It would make it easier to keep track of the review and discussions. (I am not talking about earlier new PRs they were fine, just this one and maybe the one before)
src/framework/CMakeLists.txt
Outdated
| generate_export_header(mlt | ||
| EXPORT_MACRO_NAME MLT_EXPORT | ||
| ) |
There was a problem hiding this comment.
We can just do
| generate_export_header(mlt | |
| EXPORT_MACRO_NAME MLT_EXPORT | |
| ) | |
| generate_export_header(mlt) |
everywhere now
This commit introduces a comprehensive, system-wide solution for managing API symbol visibility, enabling robust shared library builds on Windows/MSVC. - `generate_export_header()` is now used for the core framework and for every individual module to create dedicated export macros using CMake's default naming convention. - Module entry points (`mlt_register`) are now correctly prefixed with their module-specific export macro, resolving `dllimport` errors. - The SWIG interface (`mlt.i`) is updated with `%define` directives for all new export macros to make them invisible to SWIG's parser, preventing syntax errors during wrapper generation.
|
Hi @jlskuz, thank you so much for the detailed review! My apologies for misunderstanding the scope of the simplification before. I've just pushed a new commit that should address all of your points:
Regarding the SWIG changes, here is the brief explanation you asked for:
I'm looking forward to the results from the Kdenlive pipeline tests! And thanks for the tip about updating PRs. I'll stick to force-pushing on the same branch for any further iterations. |
| ${GLAX_SOURCES} | ||
| ) | ||
|
|
||
| generate_export_header(mltglaxnimate) |
There was a problem hiding this comment.
| generate_export_header(mltglaxnimate) | |
| generate_export_header(${ARG_TARGET}) |
this means we need to do #ifdef in glaxnimate_producer.cpp probably best with the Qt version as condition
src/modules/qt/CMakeLists.txt
Outdated
| # Note: We explicitly define a common macro and file name here because this | ||
| # function creates two separate targets (mltqt and mltqt6) that share the | ||
| # same source code. This ensures a single, consistent export macro can be | ||
| # used throughout the C++ files. |
There was a problem hiding this comment.
But this will fail if MLT will be built against both Qt versions or do I miss something?
Introduces conditional export macro definitions to support multiple build targets and reduce macro conflicts. Improves compatibility with both Qt5/Qt6 modules and addresses SWIG parsing issues by hiding compiler-specific keywords. Enhances maintainability and cross-platform support for modular extensions.
|
Hi @jlskuz, You were absolutely right to question my approach for the I have now pushed a new commit that implements the correct, robust solution:
This approach is much more robust and correctly handles the simultaneous build scenario. Thank you. |
|
Great! I can't find where the |
Updates export header generation to replace dashes with underscores in macro names and header files, ensuring consistency and preventing potential macro definition issues when building modules with hyphens in their names.
|
Hi @jlskuz, |
|
Thanks for always being quick in making corrections and in responses! One thing I still don't understand is where e.g. |
|
Hi @jlskuz, that's an excellent and very important question! |
|
That's some hidden CMake magic I am not familiar with, so apologies if I am completely wrong. However I just had a quick look at the code of GenerateExportHeaders and I wonder if It is reliable to use |
|
Hi @jlskuz, great question! You're right, the EXPORTS macro only handles the dllexport case. |
jlskuz
left a comment
There was a problem hiding this comment.
Okay, I suspect it is fine as it is as it only affects modules and not the framework.
Overall it looks good to me now and is proofed to build on the Kdenlive CD pipeline on all platforms.
| ${GLAX_SOURCES} | ||
| ) | ||
|
|
||
| string(REPLACE "-" "_" EXPORT_MACRO_PREFIX ${ARG_TARGET}) |
There was a problem hiding this comment.
| string(REPLACE "-" "_" EXPORT_MACRO_PREFIX ${ARG_TARGET}) | |
| string(MAKE_C_IDENTIFIER ${ARG_TARGET} EXPORT_MACRO_PREFIX) |
that is what GenerateExportHeaders uses internally too
|
Shouldn't they be created in the build dir only? Or do you use in-source builds? |
@bmatherly I think you are still using the build scripts, right? We can them to make build directories. Some of the repos I already do that. It is pretty easy for cmake; start with that. Otherwise, try adding |
|
Thanks for the comments, everyone. I tried to build out of source by adding "-B build" to the cmake command. This causes a "build" folder to be created with everything in it. But then the build fails with this error (and many more like it): I suppose that is because the build dir is not in the include path? Has anyone else been able to get an out-of-source build to work?
I'm sure that will work. But I would prefer to save that for "Plan B". |
yes, all of my local builds use a “build” sub-folder like you did. I did not do anything special to work around a problem like you are having. Also, 2 of the GitHub Actions workflows that are run on PRs are using build directories with no workaround. |

This pull request implements a comprehensive, system-wide solution for managing API symbol visibility, which is crucial for enabling robust shared library builds on Windows with MSVC.
This PR follows the final architecture proposed in the previous discussion (#1139 ) and resolves the
dllimportcompilation errors encountered when building modules. The changes are submitted as a single, unified commit as the logic is interdependent.Key Architectural Changes:
Standardized Export Macro: The core API macro has been renamed from
MLT_APItoMLT_EXPORTto align with CMake's default naming conventions, improving clarity and consistency.Per-Module Export Headers:
generate_export_header()is now invoked for the core framework and for every individual module. This creates dedicated export macros (e.g.,MLTDECKLINK_EXPORT), which is the key to correctly handling symbol imports into modules while simultaneously exporting symbols from them.Module Entry Point Fix: The
MLT_REPOSITORYmacro inmlt_repository.hhas been reverted to its original state (without any export keywords). Module registration functions (mlt_register) are now correctly prefixed with their own module-specific export macro (e.g.,MLTDECKLINK_EXPORT MLT_REPOSITORY).SWIG Compatibility: The
mlt.iinterface file has been updated with%definedirectives for all new export macros to ensure the language bindings can be generated without syntax errors.This foundational change provides a clean, maintainable, and correct solution for symbol visibility across the entire project. Subsequent PRs will build upon this to add further MSVC compatibility fixes and build system improvements.