В Fri, 17 Jan 2025 10:21:27 +0000 Pavel Krivitsky via R-package-devel <r-package-devel@r-project.org> пишет:
> 1. What is the best way to save this information? I have a > rudimentary implementation [1] For now, this is the best way we have. Export the ABI version as an include-time constant and as a registered callable. The LinkingTo reverse dependencies can give the include-time constant to the registered callable to compare the two versions. I agree that we could do better and introduce an ABIversion: field to the DESCRIPTION file. R CMD INSTALL would write down the current ABIversion of every package that the current package is LinkingTo (into the installed package's DESCRIPTION or Meta/features.rds). Later, the namespace loader would check the ABI versions and provide an informative message in case a LinkingTo dependency is updated with an incremented ABI version. A machine-readable list of ABI-level dependencies should simplify the lives of the binary package maintainers as well. (Related may be a problem with S4, where packages may end up caching parts of the classes from other packages they depend upon, which also breaks binary installations but self-heals upon reinstalling from source [1]. This still happens under R-devel. R could store and check some sort of hash when caching these classes and either reload them in full or prompt for the package to be reinstalled.) > 2. How to best test the C API without making updates impossible? Would abi-compliance-checker [2] have helped there? It's not exactly designed for static functions and R_GetCCallable(), but with abi-dumper -all or -dump-static it is possible to use it to demonstrate incompatibilities between (for example) Matrix_1.6-1.1 and Matrix_1.7. With either a separate build that exports the functions destined for R_RegisterCCallable() or some sort of filter for public symbols, this tool may help detect ABI incompatibilities early. > 3. What should be done in case of a mismatch? It's hard to guarantee anything when the ABI is broken. Maybe it's completely harmless because your code will know that the new structure member is not initialised. Maybe the wrong stack layout will crash the process due to a return address mismatch, dooming the process from the first function call. > 1. Is there a way for 'ergm' to detect when a package > LinkingTo it is being loaded? With inline functions, you could make your every API call perform ABI version checking, but that obviously comes with potential performance problems: // public header in mypackage #define MYPACKAGE_ABI_VERSION 2 static R_INLINE SEXP mypackage_frobnicate(SEXP arg) { ( (void (*)(int))R_GetCCallable("mypackage", "check_abi_version") )(MYPACKAGE_ABI_VERSION); // signals an error on mismatch return ( (SEXP (*)(SEXP))R_GetCCallable("mypackage", "frobnicate") )(arg); } > 2. What should happen if a mismatch is detected? Should the > loading be blocked (e.g., by having .onLoad() throw an error), or > should it lead to a "use at your own risk" type warning? The safest option would be to signal an error before any of the potentially incompatible functions are called. It's probably pragmatic to provide an "I know what I'm doing, void my warranty" emergency override. -- Best regards, Ivan [1] https://stat.ethz.ch/pipermail/r-devel/2023-August/082769.html [2] https://lvc.github.io/abi-compliance-checker/ ______________________________________________ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel