开搞
创建文件//tools/gn/tutorial/BUILD.gn
declare_args() {enable_teleporter = trueenable_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.gnindex 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/Defaultninja -C out/Default say_hello
报错了
ninja: Entering directory `out/Default'[1/1] Regenerating ninja files[2/2] LINK ./say_helloFAILED: say_helloTOOL_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++.dylibUndefined symbols for architecture x86_64:"Hello(char const*, char const*)", referenced from:_main in say_hello.old: symbol(s) not found for architecture x86_64clang: 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
