开搞
创建文件//tools/gn/tutorial/BUILD.gn
declare_args() {
enable_teleporter = true
enable_doom_melon = false
}
shared_library("hello") {
sources = [
"hello.cc",
]
all_dependent_configs = [
":hello_config"
]
}
executable("say_hello") {
sources = [
"say_hello.cc",
]
deps = [
":hello",
]
}
config("hello_config") {
defines = [
"TWO_PEOPLE",
]
}
修改//BUILD.gn
diff --git a/BUILD.gn b/BUILD.gn
index a1249eda399b..c93ffbd7f34c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -80,6 +80,7 @@ group("gn_all") {
"//tools/binary_size:binary_size_trybot_py",
"//tools/ipc_fuzzer:ipc_fuzzer_all",
"//tools/metrics:metrics_metadata",
+ "//tools/gn/tutorial:say_hello",
"//ui/base:ui_base_unittests",
"//ui/gfx:gfx_unittests",
"//url:url_unittests",
运行命令
gn gen out/Default
ninja -C out/Default say_hello
报错了
ninja: Entering directory `out/Default'
[1/1] Regenerating ninja files
[2/2] LINK ./say_hello
FAILED: say_hello
TOOL_VERSION=1567226261 ../../build/toolchain/mac/linker_driver.py -Wcrl,strippath,/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip ../../third_party/llvm-build/Release+Asserts/bin/clang++ -B /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ -Wl,-fatal_warnings -stdlib=libc++ -arch x86_64 -segprot PROTECTED_MEMORY rw r -Werror -nostdlib++ -isysroot ../../../../../../../Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -mmacosx-version-min=10.10.0 -Wl,-ObjC -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/../../.. -o "./say_hello" -Wl,-filelist,"./say_hello.rsp" ./libhello.dylib ./libc++.dylib
Undefined symbols for architecture x86_64:
"Hello(char const*, char const*)", referenced from:
_main in say_hello.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
思考发现,缺少编译动态链接库的选项
-Wl,-undefined -Wl,dynamic_lookup
or
clang -shared -undefined dynamic_lookup -o libfoo.so foo.c
尝试修改BUILD.gn, 添加ldflags
executable("say_hello") {
sources = [
"say_hello.cc",
]
deps = [
":hello",
]
ldflags = [
"-Wl,-undefined",
"-Wl,dynamic_lookup",
]
}
编译通过,但是运行报错
WTF!! 为啥,为啥??
编译一个依赖base动态库的可执行程序,貌似没有这种问题。对比检查编译参数。完全一样的,有木有!!
经过冷静思考,突然想起//base/baseexport.h这个文件。符号被隐藏了!!
赶紧在函数名前面追加`_attribute((visibility(_"default"_
)))`,链接通过了!!
查看base库的编译选项,发现了问题根源-fvisibility=hidden
gn desc out/Default "base:base" cflags --all
加—blame参数,查找定义位置
gn desc out/Default "base:base" cflags --all --blame
OK, 目前为止,原因已经弄清楚了,模仿base_export.h,写一个头文件就好了。
解决方案一
运行命令
gn desc out/Default "tools/gn/tutorial/linking_demo:simple" cflags --all --tree --blame
发现
From //build/config/gcc:symbol_visibility_hidden
(Added by //build/config/BUILDCONFIG.gn:456)
-fvisibility=hidden
更改设置即可
configs -= [
"//build/config/gcc:symbol_visibility_hidden",
]
解决方案二
模仿base库,添加宏定义SIMPLE_IMPLEMENTATION
config("simple_implementation") {
defines = [ "SIMPLE_IMPLEMENTATION" ]
configs = [ "//build/config/compiler:wexit_time_destructors" ]
}
在目标中依赖添加该设置
shared_library("simple") {
sources = [
"simple.cc",
"simple.h",
]
configs += [
":simple_implementation",
]
}
OK, 添加export.h
#ifndef TOOLS_GN_TUTORIAL_LINKING_DEMO_EXPORT_H_
#define TOOLS_GN_TUTORIAL_LINKING_DEMO_EXPORT_H_
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
#if defined(SIMPLE_IMPLEMENTATION)
#define SIMPLE_EXPORT __declspec(dllexport)
#else
#define SIMPLE_EXPORT __declspec(dllimport)
#endif // defined(SIMPLE_IMPLEMENTATION)
#else // defined(WIN32)
#if defined(SIMPLE_IMPLEMENTATION)
#define SIMPLE_EXPORT __attribute__((visibility("default")))
#else
#define SIMPLE_EXPORT
#endif // defined(SIMPLE_IMPLEMENTATION)
#endif
#else // defined(COMPONENT_BUILD)
#define SIMPLE_EXPORT
#endif
#endif // TOOLS_GN_TUTORIAL_LINKING_DEMO_EXPORT_H_
修改头文件
#ifndef TOOLS_GN_TUTORIAL_LINKING_DEMO_SIMPLE_H
#define TOOLS_GN_TUTORIAL_LINKING_DEMO_SIMPLE_H
#include "tools/gn/tutorial/linking_demo/export.h"
void SIMPLE_EXPORT simpleCall(void);
#endif // TOOLS_GN_TUTORIAL_LINKING_DEMO_SIMPLE_H
参考
https://stackoverflow.com/questions/21907504/how-to-compile-shared-lib-with-clang-on-osx