开搞

创建文件//tools/gn/tutorial/BUILD.gn

  1. declare_args() {
  2. enable_teleporter = true
  3. enable_doom_melon = false
  4. }
  5. shared_library("hello") {
  6. sources = [
  7. "hello.cc",
  8. ]
  9. all_dependent_configs = [
  10. ":hello_config"
  11. ]
  12. }
  13. executable("say_hello") {
  14. sources = [
  15. "say_hello.cc",
  16. ]
  17. deps = [
  18. ":hello",
  19. ]
  20. }
  21. config("hello_config") {
  22. defines = [
  23. "TWO_PEOPLE",
  24. ]
  25. }

修改//BUILD.gn

  1. diff --git a/BUILD.gn b/BUILD.gn
  2. index a1249eda399b..c93ffbd7f34c 100644
  3. --- a/BUILD.gn
  4. +++ b/BUILD.gn
  5. @@ -80,6 +80,7 @@ group("gn_all") {
  6. "//tools/binary_size:binary_size_trybot_py",
  7. "//tools/ipc_fuzzer:ipc_fuzzer_all",
  8. "//tools/metrics:metrics_metadata",
  9. + "//tools/gn/tutorial:say_hello",
  10. "//ui/base:ui_base_unittests",
  11. "//ui/gfx:gfx_unittests",
  12. "//url:url_unittests",

运行命令

  1. gn gen out/Default
  2. ninja -C out/Default say_hello

报错了

  1. ninja: Entering directory `out/Default'
  2. [1/1] Regenerating ninja files
  3. [2/2] LINK ./say_hello
  4. FAILED: say_hello
  5. 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
  6. Undefined symbols for architecture x86_64:
  7. "Hello(char const*, char const*)", referenced from:
  8. _main in say_hello.o
  9. ld: symbol(s) not found for architecture x86_64
  10. clang: error: linker command failed with exit code 1 (use -v to see invocation)

思考发现,缺少编译动态链接库的选项

  1. -Wl,-undefined -Wl,dynamic_lookup

or

  1. clang -shared -undefined dynamic_lookup -o libfoo.so foo.c

尝试修改BUILD.gn, 添加ldflags

  1. executable("say_hello") {
  2. sources = [
  3. "say_hello.cc",
  4. ]
  5. deps = [
  6. ":hello",
  7. ]
  8. ldflags = [
  9. "-Wl,-undefined",
  10. "-Wl,dynamic_lookup",
  11. ]
  12. }

编译通过,但是运行报错
Screen Shot 2019-10-18 at 10.22.14 PM.png

WTF!! 为啥,为啥??

编译一个依赖base动态库的可执行程序,貌似没有这种问题。对比检查编译参数。完全一样的,有木有!!
Screen Shot 2019-10-22 at 8.21.20 AM.png

经过冷静思考,突然想起//base/baseexport.h这个文件。符号被隐藏了!!
赶紧在函数名前面追加`_attribute((visibility(
_"default"_)))`链接通过了!!

查看base库的编译选项,发现了问题根源-fvisibility=hidden

  1. gn desc out/Default "base:base" cflags --all

加—blame参数,查找定义位置

  1. gn desc out/Default "base:base" cflags --all --blame

Screen Shot 2019-10-22 at 8.32.28 AM.png

OK, 目前为止,原因已经弄清楚了,模仿base_export.h,写一个头文件就好了。

解决方案一

运行命令

  1. gn desc out/Default "tools/gn/tutorial/linking_demo:simple" cflags --all --tree --blame

发现

  1. From //build/config/gcc:symbol_visibility_hidden
  2. (Added by //build/config/BUILDCONFIG.gn:456)
  3. -fvisibility=hidden

更改设置即可

  1. configs -= [
  2. "//build/config/gcc:symbol_visibility_hidden",
  3. ]

解决方案二

模仿base库,添加宏定义SIMPLE_IMPLEMENTATION

  1. config("simple_implementation") {
  2. defines = [ "SIMPLE_IMPLEMENTATION" ]
  3. configs = [ "//build/config/compiler:wexit_time_destructors" ]
  4. }

在目标中依赖添加该设置

  1. shared_library("simple") {
  2. sources = [
  3. "simple.cc",
  4. "simple.h",
  5. ]
  6. configs += [
  7. ":simple_implementation",
  8. ]
  9. }

OK, 添加export.h

  1. #ifndef TOOLS_GN_TUTORIAL_LINKING_DEMO_EXPORT_H_
  2. #define TOOLS_GN_TUTORIAL_LINKING_DEMO_EXPORT_H_
  3. #if defined(COMPONENT_BUILD)
  4. #if defined(WIN32)
  5. #if defined(SIMPLE_IMPLEMENTATION)
  6. #define SIMPLE_EXPORT __declspec(dllexport)
  7. #else
  8. #define SIMPLE_EXPORT __declspec(dllimport)
  9. #endif // defined(SIMPLE_IMPLEMENTATION)
  10. #else // defined(WIN32)
  11. #if defined(SIMPLE_IMPLEMENTATION)
  12. #define SIMPLE_EXPORT __attribute__((visibility("default")))
  13. #else
  14. #define SIMPLE_EXPORT
  15. #endif // defined(SIMPLE_IMPLEMENTATION)
  16. #endif
  17. #else // defined(COMPONENT_BUILD)
  18. #define SIMPLE_EXPORT
  19. #endif
  20. #endif // TOOLS_GN_TUTORIAL_LINKING_DEMO_EXPORT_H_

修改头文件

  1. #ifndef TOOLS_GN_TUTORIAL_LINKING_DEMO_SIMPLE_H
  2. #define TOOLS_GN_TUTORIAL_LINKING_DEMO_SIMPLE_H
  3. #include "tools/gn/tutorial/linking_demo/export.h"
  4. void SIMPLE_EXPORT simpleCall(void);
  5. #endif // TOOLS_GN_TUTORIAL_LINKING_DEMO_SIMPLE_H

参考

https://stackoverflow.com/questions/21907504/how-to-compile-shared-lib-with-clang-on-osx