2015-10-01 2 views
5

In Kürze: unterstützt llvm/clang 'schwach' Attribut?Unterstützt llvm/clang das Attribut 'weak' für schwache Links?

Ich lerne einige Arduino Bibliothek Quellen (HardwareSerial.cpp ausführlichere zu sein), und ich habe einige interessante Attribut weak gefunden, dass ich nie benutzt habe vor:

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

ich habe es gefunden interessant und ich habe gelesen, dass Linker sollte es auf NULL setzen, wenn es nicht definiert ist.

In meinen Tests mit clang kann ich es jedoch nicht verwenden.

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; 
} 

wenn ich g++ lib.cpp main.cpp -o main -DDEFINE_WEAK verwende ich bin in der Lage, es zu benutzen:

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

aber wenn ich g++ lib.cpp main.cpp -o main verwende ich bin nicht in der Lage, die App zu verknüpfen:

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) 

über Klirren detaillierteren Um:

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 

Was soll ich tun? Wird weak Attribut von llvm/clang unterstützt?

PS. Ich habe bereits versucht lib.cpp in die Art und Weise Apple describes und immer noch die gleichen Linker-Fehler neu zu schreiben:

#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(); 
} 
+0

Welche Version von xcode verwenden Sie ('xcodebuild -version')? Und welche Version von OSX ('sw_vers')? – Alec

+0

MBA-Anton: avr-clang asmirnov $ xcodebuild -version Xcode 7.2 Build-Version 7C68 – 4ntoine

Antwort

4

Es scheint, dass (am besten als ich sagen kann), Apples Beschreibung schwacher Verknüpfung irreführend ist. Ich hatte nur Erfolg, eine Funktion als schwach/schwach_import zu markieren, wenn die Definition tatsächlich zur Verbindungszeit verfügbar ist. Dies ist dem normalen Linux-Verhalten entgegengesetzt, bei dem ein schwach verknüpftes Symbol nicht zur Verknüpfungszeit definiert werden muss.

Zum Beispiel die folgenden compiliert auf Ubuntu 14.04 mit gcc 4.8.2, aber nicht auf OS X 10.9.5 mit Klirren

/* test.c */ 
int weakfunc() __attribute__((weak)); 

int main() 
{ 
    if (weakfunc) return weakfunc(); 
    else  return -1; 
} 

Die einfachste Abhilfe, die ich gefunden habe, ist ausdrücklich den Linker zu sagen, lasse das betreffende Symbol undefiniert. Zum Beispiel clang test.c -Wl,-U,_myfunc. Beachten Sie, dass der Name des Symbols sich zwischen C und C++ unterscheidet. In C (zumindest für mich, ich nehme an, das ist konsistent), hat der Symbolname einen Unterstrich wie hier gezeigt. In C++ ist der Name verstümmelt, also bekommst du etwas wie __Z8weakfuncv (nicht unbedingt konsistent - ich bekomme nur einen führenden Unterstrich auf dem entstellten Namen auf meiner Ubuntu-Box).

Wenn die Funktion zur Laufzeit definiert wird (z. B. durch eine Bibliothek, die durch Setzen der Umgebungsvariablen DYLD_INSERT_LIBRARIES vorinstalliert wurde oder wenn die Version einer Shared Library-Abhängigkeit zur Laufzeit anders ist als zur Build-Zeit), das Symbol wird aufgelöst und die Funktion wie gewünscht aufgerufen.Wenn das Symbol zur Laufzeit nicht definiert ist, schlägt die Überprüfung der Funktion fehl und wir geben weiterhin -1 zurück, wie gewünscht.

Eine etwas komplexere Lösung ist die Verknüpfung mit einer Dummy-Bibliothek, die eine Implementierung der betreffenden Funktion bereitstellt. Zum Beispiel, wenn Sie den folgenden als libdummy.dylib im gleichen Verzeichnis kompilieren:

int weakfunc() 
{ 
    return 1; 
} 

können Sie verknüpfen schwach dagegen

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

Das Symbol dann zu Verbindungszeitpunkt definiert ist, so dass die Linker ist glücklich und wird in der resultierenden Binärdatei als schwach verknüpft markiert. Durch die Verknüpfung von libdummy.dylib mit -weak_library anstatt mit der Standardverknüpfung -l/-L ist die Bibliotheksabhängigkeit selbst schwach, so dass die ausführbare Datei auch dann ausgeführt wird, wenn libdummy.dylib zur Laufzeit nicht verfügbar ist.

Das Argument -flat_namespace weist den Linker an, einen "flachen" Namespace anstelle eines "zweistufigen" Namespace zu verwenden, der anscheinend der Standard unter OS X ist. In einem zweistufigen Namespace ist jedes verknüpfte Symbol mit dem Symbol gekennzeichnet Bibliothek, von der es kam, also würde der Linker nur eine Version von weakfunc aus einer Bibliothek namens libdummy.dylib akzeptieren. Beachten Sie, dass im ersten Fall der Markierung des Symbols als undefiniert dieses Symbol als aus einem flachen Namespace behandelt wird, da der Linker keine Ahnung hat, welche Bibliothek es zur Laufzeit sein könnte.

+0

, die mich denken lässt, dass Clang tatsächlich keine schwache Verknüpfung oder einen Fehler – 4ntoine

+1

Ich stimme zu, dass es einen Fehler gibt, aber ich denke Es ist in der OS X-Version von ld statt Clam. Wenn Sie die generierten Binärdateien ('dyldinfo -build a.out') mit einer dieser Problemumgehungen untersuchen, glaube ich, dass das Symbol als" schwacher Import "angezeigt wird, was Sie wollen. Das Problem ist nur, dass ld ein schwach importiertes Symbol nicht richtig handhabt, wenn es zur Build-Zeit nicht definiert ist. – Alec

+0

Danke, die '-Wl, -U, _myfunc' funktioniert super! Ich brauchte nur ein wenig Zeit, um herauszufinden, wie ich es von Xcode aus konfigurieren kann, das heißt: füge '-Wl, -U, _myfunc' zu" Other Linker Flags "hinzu. – Elist

Verwandte Themen