OS X 10.11 中定义的 __eprintf 符号在哪里?
Where is the __eprintf symbol defined in OS X 10.11?
我正在用 -arch i386 -isysroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -mmacosx-version-min=10.4
编译一些断言。因此,断言代码不使用 __assert_rtn
,而是使用 __eprintf
。
来自assert.h的相关片段:
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1070)
#define __assert(e, file, line) \
__eprintf ("%s:%u: failed assertion `%s'\n", file, line, e)
#else
/* 8462256: modified __assert_rtn() replaces deprecated __eprintf() */
#define __assert(e, file, line) \
__assert_rtn ((const char *)-1L, file, line, e)
#endif
到目前为止一切顺利,除了链接时间到了,它没有找到 __eprintf
。这是在哪个库中定义的?
一种将 __eprintf
重现为 assert
的方法:
cat <<EOF >/tmp/x.c
#include <assert.h>
#ifdef __clang__
# if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) <= 1040)
# if ! __DARWIN_UNIX03
# warning "compiling for 10.4 (not __DARWIN_UNIX03), with __eprintf"
# endif
# endif
#endif
int xxx( int a)
{
assert( a);
return( a);
}
EOF
clang -E -arch i386 -mmacosx-version-min=10.4 -isysroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -o /tmp/x.txt /tmp/x.c
利用上面的方法,制作一个dylib并观察问题:
clang -c -arch i386 -mmacosx-version-min=10.4 -isysroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -O0 -o /tmp/x.o /tmp/x.c
ld -arch i386 -macosx_version_min 10.4.0 -syslibroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -t -o /tmp/x.dylib -ldylib1.o /tmp/x.o -lSystem -lgcc_s.10.4
These calls are destilled down from what xcodebuild
produces.
感谢您提供有用的回复。
在我的具体情况下,答案是 /Applications/Xcode-7.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/7.0.2/lib/darwin/libclang_rt.10.4.a
。
这是一个由 clang
自己在幕后添加的库 (DarwinClang::AddLinkRuntimeLibArgs)。请注意,此库仅适用于 10.4 代码,并且似乎与编译器版本相关。
我不知道 linker 是通过什么魔法(在调用中看不到)来决定它需要 link 的编译器版本的。
最简单的解决方案是定义自己的 __eprintf
,而不是乱用工具链:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) <= 1040)
# if ! __DARWIN_UNIX03
__attribute__((visibility("hidden")))
void __eprintf( const char* format, const char* file,
unsigned line, const char *expr)
{
fprintf( stderr, format, file, line, expr);
abort();
}
# endif
#endif
int main( int argc, char *argv[])
{
assert( argc == 2);
return( 0);
}
我正在用 -arch i386 -isysroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -mmacosx-version-min=10.4
编译一些断言。因此,断言代码不使用 __assert_rtn
,而是使用 __eprintf
。
来自assert.h的相关片段:
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1070)
#define __assert(e, file, line) \
__eprintf ("%s:%u: failed assertion `%s'\n", file, line, e)
#else
/* 8462256: modified __assert_rtn() replaces deprecated __eprintf() */
#define __assert(e, file, line) \
__assert_rtn ((const char *)-1L, file, line, e)
#endif
到目前为止一切顺利,除了链接时间到了,它没有找到 __eprintf
。这是在哪个库中定义的?
一种将 __eprintf
重现为 assert
的方法:
cat <<EOF >/tmp/x.c
#include <assert.h>
#ifdef __clang__
# if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) <= 1040)
# if ! __DARWIN_UNIX03
# warning "compiling for 10.4 (not __DARWIN_UNIX03), with __eprintf"
# endif
# endif
#endif
int xxx( int a)
{
assert( a);
return( a);
}
EOF
clang -E -arch i386 -mmacosx-version-min=10.4 -isysroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -o /tmp/x.txt /tmp/x.c
利用上面的方法,制作一个dylib并观察问题:
clang -c -arch i386 -mmacosx-version-min=10.4 -isysroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -O0 -o /tmp/x.o /tmp/x.c
ld -arch i386 -macosx_version_min 10.4.0 -syslibroot /Applications/Xcode-7.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -t -o /tmp/x.dylib -ldylib1.o /tmp/x.o -lSystem -lgcc_s.10.4
These calls are destilled down from what
xcodebuild
produces.
感谢您提供有用的回复。
在我的具体情况下,答案是 /Applications/Xcode-7.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/7.0.2/lib/darwin/libclang_rt.10.4.a
。
这是一个由 clang
自己在幕后添加的库 (DarwinClang::AddLinkRuntimeLibArgs)。请注意,此库仅适用于 10.4 代码,并且似乎与编译器版本相关。
我不知道 linker 是通过什么魔法(在调用中看不到)来决定它需要 link 的编译器版本的。
最简单的解决方案是定义自己的 __eprintf
,而不是乱用工具链:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) <= 1040)
# if ! __DARWIN_UNIX03
__attribute__((visibility("hidden")))
void __eprintf( const char* format, const char* file,
unsigned line, const char *expr)
{
fprintf( stderr, format, file, line, expr);
abort();
}
# endif
#endif
int main( int argc, char *argv[])
{
assert( argc == 2);
return( 0);
}