Does llvm / clang support a โ€œweakโ€ attribute for weak communications?

In short: will llvm / clang support a "weak" attribute?

I am studying some sources of the Arduino library (a more detailed description of HardwareSerial.cpp), and I found an interesting weak attribute that I had never used before:

 #if defined(HAVE_HWSERIAL0) void serialEvent() __attribute__((weak)); bool Serial0_available() __attribute__((weak)); #endif 

I found this interesting, and I read that the linker should set it to NULL if it is not defined.

However, in my tests with clang I cannot use it.

lib.cpp:

 #include "lib.h" #include <stdio.h> void my_weak_func() __attribute__((weak)); void lib_func() { printf("lib_func()\n"); if (my_weak_func) my_weak_func(); } 

lib.h:

 #ifndef LIB_FUNC #define LIB_FUNC void lib_func(); #endif 

main.cpp:

 #include "lib.h" #include <stdio.h> #ifdef DEFINE_WEAK void my_weak_func() { printf("my_weak_func()\n"); } #endif int main() { lib_func(); printf("finished\n"); return 0; } 

If I use g++ lib.cpp main.cpp -o main -DDEFINE_WEAK , I can use it:

 MBA-Anton:Weak_issue asmirnov$ ./main lib_func() my_weak_func() finished 

but if I use g++ lib.cpp main.cpp -o main , I cannot bind the application:

 Undefined symbols for architecture x86_64: "my_weak_func()", referenced from: lib_func() in lib-ceb555.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) 

More about clang:

 MBA-Anton:Weak_issue asmirnov$ g++ --version Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/c++/4.2.1 Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) Target: x86_64-apple-darwin14.3.0 Thread model: posix 

What should I do? Is weak attribute supported by llvm / clang?

PS. I already tried to rewrite lib.cpp like this: Apple also describes the same linker error:

 #include "lib.h" #include <stdio.h> extern void my_weak_func() __attribute__((weak_import)); void lib_func() { printf("lib_func()\n"); if (my_weak_func != NULL) my_weak_func(); } 
+5
source share
1 answer

It seems that (best of all, as far as I can tell), Apple's description of weak binding is misleading. I only had success designating the function as weak / weak_import if the definition is really available at the time of the link. This is contrary to the usual behavior of Linux when a loosely coupled character does not need to be detected during communication.

For example, the following compilations on Ubuntu 14.04 with gcc 4.8.2, but not on OS X 10.9.5 with clang

 /* test.c */ int weakfunc() __attribute__((weak)); int main() { if (weakfunc) return weakfunc(); else return -1; } 

The easiest workaround I have found is to explicitly tell the linker to leave this character undefined. For example, clang test.c -Wl,-U,_myfunc . Note that the character name will be different from C and C ++. In C (at least for me, I assume this is consistent), the symbol name has an underscore, as shown here. In C ++, the name is distorted, so you get something like __Z8weakfuncv (not necessarily consistent - I get only one underscore over the changed name in my Ubuntu field).

Following this approach, if a function is defined at run time (for example, through a library preloaded by setting the environment variable DYLD_INSERT_LIBRARIES or if the version of the dependencies in the shared library at run time is different from the time set at build time), the character will be enabled and the function will be summoned at will. If the character is not defined at runtime, then the function is not checked, and we continue to return -1 as desired.

A slightly more complex solution is a link to a dummy library that provides the implementation of the function in question. For example, if you compile the following as libdummy.dylib in the same directory:

 int weakfunc() { return 1; } 

You can weakly refer to it

clang test.c -weak_library ./libdummy.dylib -flat_namespace

The character is then determined during the link, so the linker is happy and will be marked as loosely coupled in the resulting binary. By linking libdummy.dylib to -weak_library , rather than the standard -l/-L binding, the library dependency itself is weak, so the executable will still work, even if libdummy.dylib is not available at run time.

The -flat_namespace argument tells the linker to use a โ€œflatโ€ namespace rather than a โ€œtwo-levelโ€ namespace, which is apparently the default value for OS X. In a two-level namespace, each associated character is tagged with the library from which it came, so without it the linker would only accept the version of weakfunc from the libdummy.dylib library. Please note that in the first case of marking a character as undefined, this character is considered to be from a flat namespace, since the linker has no idea which library it may be in at runtime.

+4
source

Source: https://habr.com/ru/post/1232670/


All Articles