feat: Improve shared linkage support#719
Conversation
|
If helpful for local debugging you might want to try setting this up through Meson, as that work is a lot simpler than what CMake requires. I think we used to even have this set up back in #531 but reverted due to some issues |
|
Love the individual commit names - really takes you along for the ride as a reader. Hope all is well! |
|
@assignUser I hate to bug you again, but there's quite a big change to the CMake that would benefit from your 👀 if you have the bandwidth! |
| #if (defined _WIN32 || defined __CYGWIN__) && defined(NANOARROW_BUILD_DLL) | ||
| #if defined(NANOARROW_EXPORT_DLL) | ||
| #define NANOARROW_DLL __declspec(dllexport) | ||
| #else | ||
| #define NANOARROW_DLL __declspec(dllimport) | ||
| #endif // defined(NANOARROW_EXPORT_DLL) | ||
| #elif !defined(NANOARROW_DLL) | ||
| #if __GNUC__ >= 4 | ||
| #define NANOARROW_DLL __attribute__((visibility("default"))) | ||
| #else | ||
| #define NANOARROW_DLL | ||
| #endif // __GNUC__ >= 4 | ||
| #endif |
There was a problem hiding this comment.
To avoid keeping this up to date, I would recommend the usage of https://cmake.org/cmake/help/latest/module/GenerateExportHeader.html which creates this code via cmake.
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
generate_export_header(nanoarrow)
install(FILES
${PROJECT_BINARY_DIR}/nanoarrow_export.h DESTINATION ${INCLUDE_INSTALL_DIR}
)
class NANOARROW_EXPORT SomeClass { ... }
I do think that with this we get away with one exported target (no nanoarrow_shared target, or is there a reason we want to install static and shared in parallel?) and less boilerplate code to maintain
There was a problem hiding this comment.
Thanks for taking a look!
To avoid keeping this up to date, I would recommend the usage of GenerateExportHeader
I think the main reason I'd like to avoid this is that CMake is one of three supported ways of consuming nanoarrow (CMake, meson, make a single-file bundle and use your existing build system).
is there a reason we want to install static and shared in parallel
This seems to be what other libraries of our size/function are doing (e.g., zstd, ADBC, Arrow), and I think installing both in parallel works well for distributing via something like Homebrew (which often provides shared and static options to link against so that you can use it to distribute things like R packages and Python wheels). I think the main advantage comes when trying to link against a library from something that is not CMake but I'm not an expert here.
There was a problem hiding this comment.
Yes distributing both .a and .so is certainly not uncommon.
There was a problem hiding this comment.
if cross-build-system support is a concern, I am with you the current approach is better 👍
There was a problem hiding this comment.
I have some thoughts about target naming and such but I need to take some more time and think about it and look some things up.
One thing is that I see a bunch of repeating stuff that should probably be refactored in a function, but that's true in general (see L436 onwards) so that could be done as a follow up.
In general I think this is mergable so don't wait for me ^^
CMakeLists.txt
Outdated
| target_compile_definitions(${target} PUBLIC "$<$<CONFIG:Debug>:NANOARROW_DEBUG>") | ||
|
|
||
| # Ensure NANOARROW_DLL is set when building and linking to the library | ||
| if(target MATCHES "_shared$") |
There was a problem hiding this comment.
Targets have a TYPE property that you could check here instead of the name: https://cmake.org/cmake/help/latest/prop_tgt/TYPE.html
| # This example doesn't seem to work on Windows | ||
| if: matrix.config.label != 'windows' |
There was a problem hiding this comment.
@WillAyd I'll open an issue for this! I think it works but needs some environment-on-ci debugging!
Let me know here or elsewhere when you have time to circle back!
Great point! I've opened an issue to track this one: #726 . |
|
I think you should change if(BUILD_SHARED_LIBS)
add_library(nanoarrow::nanoarrow ALIAS nanoarrow_shared)
else()
add_library(nanoarrow::nanoarrow ALIAS nanoarrow_static)
endif()This is mostly relevant when nanoarrow is built as a subproject. You could also add an option that allows toggling the building of either version (gflags does that). That way I don't have to compile everything twice if I only care about static. For packaging the shared bit could be made a component that also changes which target gets the main alias. (again something gflags does nit: You should be able to create an INTERFACE target for the sources and use that instead of variables: https://cmake.org/cmake/help/latest/prop_tgt/INTERFACE_SOURCES.html I haven't used an interface target but it's a nice solution to avoid raw variables (which I am always happy about...) |
Done! I do like this better. I also added configurable test linkage for better feedback if this breaks for some reason.
This is also sort of a breaking change (
I'll leave this one for now since it doesn't affect the interface and because our compile times are very low but it's a great point that the average we-use-nanoarrow-as-a-subproject only needs one of the two.
I'll add a note about this one in #726 since it's in the category of nice-to-have CMake improvements that I don't quite understand yet 🙂 |
|
Thanks for all the work! For my understanding, for downstream libraries that link to nanoarrow, this will mean to be used like this: and there's no generic target that takes whatever has been built? I'm asking as I never had the need to build static AND shared libraries side-by-side but had the need to build either one or the other depending on the target platform (e.g. shared for linux, static for ios) and for these cases the short version is nice in terms of readability. |
Ok, I added this + tests to make sure it works in both the fetch and installed cases. You and @m-kuhn are right that this is sort of annoying if you want the value of BUILD_SHARED_LIBS to do the work for you.
It would probably be more like the |
|
Thank you all for the reviews here! |
This PR makes linking to the usual targets static linkage and adds a paired
_sharedtarget for users that want to opt in to shared nanoarrow linkage. This is intended to mirror what ADBC and Arrow do (with separated_sharedand_statictargets), except nanoarrow already had some existing targets that were intended to be used with static linkage anyway, so those target names were left as is.This PR also adds the appropriate import/export attribute for Windows (most of the changed lines in this PR).
While I had my Windows machine fired up I also fixed a few compiler warnings, and I added a Windows and MacOS run for the
examplesworkflow.Closes #495, closes #718