Darwin targets do not have a protected visibility function attribute, see LLVM explanation. This means that the AX_GCC_FUNC_ATTRIBUTE check for visibility fails:
0configure:24513: checking for __attribute__((visibility))
1configure:24537: g++ -std=c++11 -o conftest -g -O2 -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS -DMAC_OSX -DOBJC_OLD_DISPATCH_PROTOTYPES=0 -Wl,-headerpad_max_install_names conftest.cpp >&5
2conftest.cpp:35:56: warning: target does not support 'protected' visibility; using 'default' [-Wunsupported-visibility]
3 int foo_pro( void ) __attribute__((visibility("protected")));
4 ^
51 warning generated.
6configure:24537: $? = 0
7configure:24550: result: no
This leads to EXPORT_SYMBOL being defined to nothing, as HAVE_FUNC_ATTRIBUTE_VISIBILITY is not defined, and when building with reduced exports, you end up with a libbitcoinconsensus.dylib that doesn’t export any _bitcoinconsensus_* symbols.
0➜ git:(master) nm -C src/.libs/libbitcoinconsensus.dylib | rg _bitcoinconsensus_
1➜ git:(master)
We do have a second check for the visibility attribute, which works for Darwin as it’s only testing for default visibility, however the result of this check isn’t used at all. It was added in #4725, along with the --enable-reduce-exports option, however when libbitcoinconsensus was added in #5235, it used the results of the added AX_GCC_FUNC_ATTRIBUTE calls.
This PR removes our usage of the AX_GCC_FUNC_ATTRIBUTE macro entirely, in favour of our own checks in configure. This meant adding a check for dllexport, which I’ve tested as working with both GCC and Clang when building for Windows. I haven’t added an equivalent check for dllimport, as we weren’t actually using the result of that check, we’re just testing that MSC_VER was defined before using.
With these changes building a libbitcoinconsensus with reduced exports, when targeting Darwin, works as expected:
0./autogen.sh
1./configure --disable-tests --disable-bench --with-utils=no --with-daemon=no --with-gui=no --disable-wallet --with-libs=yes --enable-reduce-exports
2make -j8
3...
4nm -C src/.libs/libbitcoinconsensus.dylib | rg _bitcoinconsensus_
5000000000000a340 T _bitcoinconsensus_verify_script
600000000000097e0 T _bitcoinconsensus_verify_script_with_amount
7000000000000a3c0 T _bitcoinconsensus_version
0>>> import ctypes
1>>> consensus = ctypes.CDLL("src/.libs/libbitcoinconsensus.dylib")
2>>> print(consensus.bitcoinconsensus_version())
31
4>>> exit()
TODO: Modify a CI job to compile with –enable-reduce-exports and check for symbols in shared lib?