当前位置:   article > 正文

chromium net android移植_use of typeid requires -frtti

use of typeid requires -frtti

Chromium net是chromium浏览器及ChromeOS中,用于从网络获取资源的模块。这个网络库是用C++编写的,且用了大量的C++11特性。它广泛地支持当前互联网环境中用到的大量的网络协议,如HTTP/1.1,SPDY,HTTP/2,FTP,QUIC,WebSockets等;在安全性方面也有良好的支持,如SSL等;同时,针对性能,它也有诸多的优化,如引入libevent的基于事件驱动的设计。从而,将chromium net库移植到android平台上并用起来,以提升我们的APP的网络访问性能成为了一件非常有价值的事情。

这里我们就尝试将chromium net移植到android平台上并用起来。但由于庞大的chromium项目有着自己比较特别的开发流程,开发方式,而给我们的移植工作制造了一些障碍。具体地说是:

  • gn/gyp + ninja的构建方式;
  • 为了方便开发,chromium的仓库中包含了构建所需的完整的工具链,包括编译、链接的工具,android的SDK和NDK,甚至是STL。这个工具链与我们惯常用在项目中的工具链多少还是有一点点区别的,这会给我们的编译链接等制造一些困扰。

但好在Google出品比较具有hack风,因而移植工作的难度变得可控。比如gn工具,可以让我们比较方便地对工程做更多的探索,我们可以通过这个工具来了解我们编译一个模块时,整个环境的配置,该模块具体包含了哪些源文件,模块导出的头文件,编译链接时都用了什么样的参数等等。

在具体移植开始之前,先设定我们移植的目标:

  • 让chromium的net模块可以单独地在android平台上跑起来,可以通过JNI的方式进行调用;
  • 将chromium net模块从整个的chromium代码库中抽离,依然基于gn + ninja,建立独立的开发环境,可以进行配置、构建,以方便后续针对chromium net的开发。
  • 针对与移动端上受限的资源,及项目的需要,对chromium net进行一些裁剪瘦身,比如对ftp协议的支持就没有太大的必要,砍掉这些用不到的东西以节省资源,提升效能。

这里主要就基于我们的目标,来探索移植的方法。本文不是一份呈送给老板们看的final summary,只能包含简短的需要做的正确的事情。而是从工程师的直觉出发,逐步的探索整个的移植过程,以方便后续可以轻松地复制移植的过程。本文会记录遇到的每个问题,并给出出错的提示,比如编译器报的error,链接器报的error,运行时崩溃抓到的backtrace等等,还会给出对问题的基本分析与定位,及问题的解决方法。

编译chromium net模块

首先要做的事情就是下载完整的chromium代码,这可以参考Chromium Android编译指南来完成。然后执行(假设当前目录是chromium代码库的根目录)命令:

  1. $ gclient runhooks
  2. $ cd src
  3. $ ./build/install-build-deps.sh
  4. $ ./build/install-build-deps-android.sh
  • 1
  • 2
  • 3
  • 4

下载构建chromium所需的系统工具。

之后需要对编译进行配置。编辑out/Default/args.gn文件,并参照Chromium Android编译指南中的说明,输入如下内容:

  1. target_os = "android"
  2. target_cpu = "arm" # (default)
  3. is_debug = true # (default)
  4. # Other args you may want to set:
  5. is_component_build = true
  6. is_clang = true
  7. symbol_level = 1 # Faster build with fewer symbols. -g1 rather than -g2
  8. enable_incremental_javac = true # Much faster; experimental
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

保存退出之后,执行:

$ gn gen out/Default
  • 1

产生ninja构建所需的各个模块的ninja文件。随后输入如下命令编译net模块:

$ ninja -C out/Default net
  • 1

这个命令会编译net模块,及其依赖的所有模块,包括base,crypto,borringssl,protobuf,icu,url等。可以看一下我们编译的成果:

  1. $ ls -alh out/Default/ | grep so$
  2. -rwxrwxr-x 1 chrome chrome 1.2M 810 20:55 libbase.cr.so
  3. -rwxrwxr-x 1 chrome chrome 98K 810 20:55 libbase_i18n.cr.so
  4. -rwxrwxr-x 1 chrome chrome 773K 810 20:54 libboringssl.cr.so
  5. -rwxrwxr-x 1 chrome chrome 74K 810 20:55 libcrcrypto.cr.so
  6. -rwxrwxr-x 1 chrome chrome 1.3M 810 20:55 libicui18n.cr.so
  7. -rwxrwxr-x 1 chrome chrome 902K 810 20:55 libicuuc.cr.so
  8. -rwxrwxr-x 1 chrome chrome 4.1M 810 20:59 libnet.cr.so
  9. -rwxrwxr-x 1 chrome chrome 122K 810 20:55 libprefs.cr.so
  10. -rwxrwxr-x 1 chrome chrome 182K 810 20:55 libprotobuf_lite.cr.so
  11. -rwxrwxr-x 1 chrome chrome 90K 810 20:59 liburl.cr.so
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

总共10个共享库文件。

在我们的工程的app模块的jni目录下为chromium创建文件夹app/src/main/jni/third_party/chromium/libsapp/src/main/jni/third_party/chromium/include,分别用于存放我们编译出来的共享库文件和net等模块导出的头文件及这些头文件include的其它头文件。

这里我们将编译出来的所有so文件拷贝到app/src/main/jni/third_party/chromium/libs/armeabiapp/src/main/jni/third_party/chromium/libs/armeabi-v7a目录下:

  1. cp out/Default/*.so /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/libs/armeabi/
  2. cp out/Default/*.so /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/libs/armeabi-v7a/
  • 1
  • 2

编译共享库似乎挺顺利。

提取导出头文件

为了使用net模块提供的API,我们不可避免地要将net导出的头文件引入我们的项目。要做到这些,我们首先就需要从chromium工程中提取net导出的头文件。不像许多其它的C++项目,源代码文件、私有头文件及导出头文件存放的位置被很好地做了区隔,chromium各个模块的所有头文件和源代码文件都是放在一起的。这还是给我们提取导出头文件的工作带来了一点麻烦。

这里我们借助于gn工具提供的desc功能(关于gn工具的用法,可以参考GN的使用 - GN工具一文),输出中如下的这两段:

  1. $ gn desc out/Default/ net
  2. Target //net:net
  3. Type: shared_library
  4. Toolchain: //build/toolchain/android:arm
  5. sources
  6. //net/base/address_family.cc
  7. //net/base/address_family.h
  8. ......
  9. public
  10. [All headers listed in the sources are public.]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

编写脚本来实现。

我们可以传入[chromium代码库的src目录路径][输出目录的路径][模块名],及[保存头文件的目标目录路径]作为参数,来提取模块的所有导出头文件,[保存头文件的目标目录路径]参数缺失时默认使用当前目录,比如:

  1. $ cd /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include
  2. $ chromium_mod_headers_extracter.py ~/data/chromium_android/src out/Default net
  • 1
  • 2

这里一并将该脚本的完整内容贴出来:

  1. #!/usr/bin/env python
  2. import os
  3. import shutil
  4. import sys
  5. def print_usage_and_exit():
  6. print sys.argv[0] + " [chromium_src_root]" + "[out_dir]" + " [target_name]" + " [targetroot]"
  7. exit(1)
  8. def copy_file(src_file_path, target_file_path):
  9. if os.path.exists(target_file_path):
  10. return
  11. if not os.path.exists(src_file_path):
  12. return
  13. target_dir_path = os.path.dirname(target_file_path)
  14. if not os.path.exists(target_dir_path):
  15. os.makedirs(target_dir_path)
  16. shutil.copy(src_file_path, target_dir_path)
  17. def copy_all_files(source_dir, all_files, target_dir):
  18. for one_file in all_files:
  19. source_path = source_dir + os.path.sep + one_file
  20. target_path = target_dir + os.path.sep + one_file
  21. copy_file(source_path, target_path)
  22. if __name__ == "__main__":
  23. if len(sys.argv) < 4 or len(sys.argv) > 5:
  24. print_usage_and_exit()
  25. chromium_src_root = sys.argv[1]
  26. out_dir = sys.argv[2]
  27. target_name = sys.argv[3]
  28. target_root_path = "."
  29. if len(sys.argv) == 5:
  30. target_root_path = sys.argv[4]
  31. target_root_path = os.path.abspath(target_root_path)
  32. os.chdir(chromium_src_root)
  33. cmd = "gn desc " + out_dir + " " + target_name
  34. outputs = os.popen(cmd).readlines()
  35. source_start = False
  36. all_headers = []
  37. public_start = False
  38. public_headers = []
  39. for output_line in outputs:
  40. output_line = output_line.strip()
  41. if output_line.startswith("sources"):
  42. source_start = True
  43. continue
  44. elif source_start and len(output_line) == 0:
  45. source_start = False
  46. continue
  47. elif source_start and output_line.endswith(".h"):
  48. output_line = output_line[1:]
  49. all_headers.append(output_line)
  50. elif output_line == "public":
  51. public_start = True
  52. continue
  53. elif public_start and len(output_line) == 0:
  54. public_start = False
  55. continue
  56. elif public_start:
  57. public_headers.append(output_line)
  58. if len(public_headers) == 1:
  59. public_headers = all_headers
  60. if len(public_headers) > 1:
  61. copy_all_files(chromium_src_root, public_headers, target_dir=target_root_path)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

Chromium net的简单使用

参照chromium/src/net/tools/get_server_time/get_server_time.cc的代码,来编写简单的示例程序。首先是JNI(JNI的用法,可以参考android app中使用JNI)的Java层代码:

  1. package com.example.hanpfei0306.myapplication;
  2. public class NetUtils {
  3. static {
  4. System.loadLibrary("neteasenet");
  5. }
  6. private static native void nativeSendRequest(String url);
  7. public static void sendRequest(String url) {
  8. nativeSendRequest(url);
  9. }
  10. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

然后是native层的JNI代码,MyApplication/app/src/main/jni/src/NetJni.cpp

  1. //
  2. // Created by hanpfei0306 on 16-8-4.
  3. //
  4. #include <stdio.h>
  5. #include <net/base/network_delegate_impl.h>
  6. #include "jni.h"
  7. #include "base/at_exit.h"
  8. #include "base/json/json_writer.h"
  9. #include "base/message_loop/message_loop.h"
  10. #include "base/memory/ptr_util.h"
  11. #include "base/run_loop.h"
  12. #include "base/values.h"
  13. #include "net/http/http_response_headers.h"
  14. #include "net/proxy/proxy_config_service_fixed.h"
  15. #include "net/url_request/url_fetcher.h"
  16. #include "net/url_request/url_fetcher_delegate.h"
  17. #include "net/url_request/url_request_context.h"
  18. #include "net/url_request/url_request_context_builder.h"
  19. #include "net/url_request/url_request_context_getter.h"
  20. #include "net/url_request/url_request.h"
  21. #include "JNIHelper.h"
  22. #define TAG "NetUtils"
  23. // Simply quits the current message loop when finished. Used to make
  24. // URLFetcher synchronous.
  25. class QuitDelegate : public net::URLFetcherDelegate {
  26. public:
  27. QuitDelegate() {}
  28. ~QuitDelegate() override {}
  29. // net::URLFetcherDelegate implementation.
  30. void OnURLFetchComplete(const net::URLFetcher* source) override {
  31. LOGE("OnURLFetchComplete");
  32. base::MessageLoop::current()->QuitWhenIdle();
  33. int responseCode = source->GetResponseCode();
  34. const net::URLRequestStatus status = source->GetStatus();
  35. if (status.status() != net::URLRequestStatus::SUCCESS) {
  36. LOGW("Request failed with error code: %s", net::ErrorToString(status.error()).c_str());
  37. return;
  38. }
  39. const net::HttpResponseHeaders* const headers = source->GetResponseHeaders();
  40. if (!headers) {
  41. LOGW("Response does not have any headers");
  42. return;
  43. }
  44. size_t iter = 0;
  45. std::string header_name;
  46. std::string date_header;
  47. while (headers->EnumerateHeaderLines(&iter, &header_name, &date_header)) {
  48. LOGW("Got %s header: %s\n", header_name.c_str(), date_header.c_str());
  49. }
  50. std::string responseStr;
  51. if(!source->GetResponseAsString(&responseStr)) {
  52. LOGW("Get response as string failed!");
  53. }
  54. LOGI("Content len = %lld, response code = %d, response = %s",
  55. source->GetReceivedResponseContentLength(),
  56. source->GetResponseCode(),
  57. responseStr.c_str());
  58. }
  59. void OnURLFetchDownloadProgress(const net::URLFetcher* source,
  60. int64_t current,
  61. int64_t total) override {
  62. LOGE("OnURLFetchDownloadProgress");
  63. }
  64. void OnURLFetchUploadProgress(const net::URLFetcher* source,
  65. int64_t current,
  66. int64_t total) override {
  67. LOGE("OnURLFetchUploadProgress");
  68. }
  69. private:
  70. DISALLOW_COPY_AND_ASSIGN(QuitDelegate);
  71. };
  72. // NetLog::ThreadSafeObserver implementation that simply prints events
  73. // to the logs.
  74. class PrintingLogObserver : public net::NetLog::ThreadSafeObserver {
  75. public:
  76. PrintingLogObserver() {}
  77. ~PrintingLogObserver() override {
  78. // This is guaranteed to be safe as this program is single threaded.
  79. net_log()->DeprecatedRemoveObserver(this);
  80. }
  81. // NetLog::ThreadSafeObserver implementation:
  82. void OnAddEntry(const net::NetLog::Entry& entry) override {
  83. // The log level of the entry is unknown, so just assume it maps
  84. // to VLOG(1).
  85. const char* const source_type = net::NetLog::SourceTypeToString(entry.source().type);
  86. const char* const event_type = net::NetLog::EventTypeToString(entry.type());
  87. const char* const event_phase = net::NetLog::EventPhaseToString(entry.phase());
  88. std::unique_ptr<base::Value> params(entry.ParametersToValue());
  89. std::string params_str;
  90. if (params.get()) {
  91. base::JSONWriter::Write(*params, &params_str);
  92. params_str.insert(0, ": ");
  93. }
  94. #ifdef DEBUG_ALL
  95. LOGI("source_type = %s (id = %u): entry_type = %s : event_phase = %s params_str = %s",
  96. source_type, entry.source().id, event_type, event_phase, params_str.c_str());
  97. #endif
  98. }
  99. private:
  100. DISALLOW_COPY_AND_ASSIGN(PrintingLogObserver);
  101. };
  102. // Builds a URLRequestContext assuming there's only a single loop.
  103. static std::unique_ptr<net::URLRequestContext> BuildURLRequestContext(net::NetLog *net_log) {
  104. net::URLRequestContextBuilder builder;
  105. builder.set_net_log(net_log);
  106. //#if defined(OS_LINUX)
  107. // On Linux, use a fixed ProxyConfigService, since the default one
  108. // depends on glib.
  109. //
  110. // TODO(akalin): Remove this once http://crbug.com/146421 is fixed.
  111. builder.set_proxy_config_service(
  112. base::WrapUnique(new net::ProxyConfigServiceFixed(net::ProxyConfig())));
  113. //#endif
  114. std::unique_ptr<net::URLRequestContext> context(builder.Build());
  115. context->set_net_log(net_log);
  116. return context;
  117. }
  118. static void NetUtils_nativeSendRequest(JNIEnv* env, jclass, jstring javaUrl) {
  119. const char* native_url = env->GetStringUTFChars(javaUrl, NULL);
  120. LOGW("Url: %s", native_url);
  121. base::AtExitManager exit_manager;
  122. LOGW("Url: %s", native_url);
  123. GURL url(native_url);
  124. if (!url.is_valid() || (url.scheme() != "http" && url.scheme() != "https")) {
  125. LOGW("Not valid url: %s", native_url);
  126. return;
  127. }
  128. LOGW("Url: %s", native_url);
  129. base::MessageLoopForIO main_loop;
  130. QuitDelegate delegate;
  131. std::unique_ptr<net::URLFetcher> fetcher =
  132. net::URLFetcher::Create(url, net::URLFetcher::GET, &delegate);
  133. net::NetLog *net_log = nullptr;
  134. #ifdef DEBUG_ALL
  135. net_log = new net::NetLog;
  136. PrintingLogObserver printing_log_observer;
  137. net_log->DeprecatedAddObserver(&printing_log_observer,
  138. net::NetLogCaptureMode::IncludeSocketBytes());
  139. #endif
  140. std::unique_ptr<net::URLRequestContext> url_request_context(BuildURLRequestContext(net_log));
  141. fetcher->SetRequestContext(
  142. // Since there's only a single thread, there's no need to worry
  143. // about when the URLRequestContext gets created.
  144. // The URLFetcher will take a reference on the object, and hence
  145. // implicitly take ownership.
  146. new net::TrivialURLRequestContextGetter(url_request_context.get(),
  147. main_loop.task_runner()));
  148. fetcher->Start();
  149. // |delegate| quits |main_loop| when the request is done.
  150. main_loop.Run();
  151. env->ReleaseStringUTFChars(javaUrl, native_url);
  152. }
  153. int jniRegisterNativeMethods(JNIEnv* env, const char *classPathName, JNINativeMethod *nativeMethods, jint nMethods) {
  154. jclass clazz;
  155. clazz = env->FindClass(classPathName);
  156. if (clazz == NULL) {
  157. return JNI_FALSE;
  158. }
  159. if (env->RegisterNatives(clazz, nativeMethods, nMethods) < 0) {
  160. return JNI_FALSE;
  161. }
  162. return JNI_TRUE;
  163. }
  164. static JNINativeMethod gNetUtilsMethods[] = {
  165. NATIVE_METHOD(NetUtils, nativeSendRequest, "(Ljava/lang/String;)V"),
  166. };
  167. void register_com_netease_volleydemo_NetUtils(JNIEnv* env) {
  168. jniRegisterNativeMethods(env, "com/example/hanpfei0306/myapplication/NetUtils",
  169. gNetUtilsMethods, NELEM(gNetUtilsMethods));
  170. }
  171. // DalvikVM calls this on startup, so we can statically register all our native methods.
  172. jint JNI_OnLoad(JavaVM* vm, void*) {
  173. JNIEnv* env;
  174. if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
  175. LOGE("JavaVM::GetEnv() failed");
  176. abort();
  177. }
  178. register_com_netease_volleydemo_NetUtils(env);
  179. return JNI_VERSION_1_6;
  180. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212

这个文件里,在nativeSendRequest()函数中调用chromium net做了网络请求,获取响应,并打印出响应的headers及响应的content。

MyApplication/app/src/main/jni/src/JNIHelper.h中定义了一些宏,以方便native methods的注册,其具体内容则为:

  1. #ifndef CANDYWEBCACHE_JNIHELPER_H
  2. #define CANDYWEBCACHE_JNIHELPER_H
  3. #include <android/log.h>
  4. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
  5. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__)
  6. #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__)
  7. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)
  8. #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)
  9. #ifndef NELEM
  10. # define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
  11. #endif
  12. #define NATIVE_METHOD(className, functionName, signature) \
  13. { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
  14. #endif //CANDYWEBCACHE_JNIHELPER_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

配置Gradle

要在Android Studio中使用JNI,还需要对Gralde做一些特别的配置,具体可以参考在Android Studio中使用NDK/JNI - 实验版插件用户指南一文。这里需要对MyApplication/build.gradleMyApplication/gradle/wrapper/gradle-wrapper.properties,和MyApplication/app/build.gradle这几个文件做修改。

修改MyApplication/build.gradle文件,最终的内容为:

  1. // Top-level build file where you can add configuration options common to all sub-projects/modules.
  2. buildscript {
  3. repositories {
  4. jcenter()
  5. }
  6. dependencies {
  7. classpath 'com.android.tools.build:gradle-experimental:0.7.0'
  8. // NOTE: Do not place your application dependencies here; they belong
  9. // in the individual module build.gradle files
  10. }
  11. }
  12. allprojects {
  13. repositories {
  14. jcenter()
  15. }
  16. }
  17. task clean(type: Delete) {
  18. delete rootProject.buildDir
  19. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在这个文件中配置gradle插件的版本为gradle-experimental:0.7.0

修改MyApplication/gradle/wrapper/gradle-wrapper.properties文件,最终的内容为:

  1. #Mon Dec 28 10:00:20 PST 2015
  2. distributionBase=GRADLE_USER_HOME
  3. distributionPath=wrapper/dists
  4. zipStoreBase=GRADLE_USER_HOME
  5. zipStorePath=wrapper/dists
  6. distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这个文件中配置gradle的版本。

修改MyApplication/app/build.gradle文件,最终的内容为:

  1. apply plugin: 'com.android.model.application'
  2. model {
  3. repositories {
  4. libs(PrebuiltLibraries) {
  5. chromium_net {
  6. headers.srcDir "src/main/jni/third_party/chromium/include"
  7. binaries.withType(SharedLibraryBinary) {
  8. sharedLibraryFile = file("src/main/jni/third_party/chromium/libs/${targetPlatform.getName()}/libnet.cr.so")
  9. }
  10. }
  11. }
  12. }
  13. android {
  14. compileSdkVersion 23
  15. buildToolsVersion "23.0.3"
  16. defaultConfig {
  17. applicationId "com.example.hanpfei0306.myapplication"
  18. minSdkVersion.apiLevel 19
  19. targetSdkVersion.apiLevel 21
  20. versionCode 1
  21. versionName "1.0"
  22. }
  23. ndk {
  24. moduleName "neteasenet"
  25. CFlags.addAll(['-I' + file('src/main/jni/third_party/chromium/include/'),])
  26. cppFlags.addAll(['-I' + file('src/main/jni/third_party/chromium/include'),])
  27. ldLibs.add("android")
  28. ldLibs.add("log")
  29. ldLibs.add("z")
  30. }
  31. sources {
  32. main {
  33. java {
  34. source {
  35. srcDir "src/main/java"
  36. }
  37. }
  38. jni {
  39. source {
  40. srcDirs = ["src/main/jni",]
  41. }
  42. dependencies {
  43. library 'chromium_net' linkage 'shared'
  44. }
  45. }
  46. jniLibs {
  47. source {
  48. srcDirs =["src/main/jni/third_party/chromium/libs",]
  49. }
  50. }
  51. }
  52. }
  53. buildTypes {
  54. debug {
  55. ndk {
  56. abiFilters.add("armeabi")
  57. abiFilters.add("armeabi-v7a")
  58. }
  59. }
  60. release {
  61. minifyEnabled false
  62. proguardFiles.add(file("proguard-rules.pro"))
  63. ndk {
  64. abiFilters.add("armeabi")
  65. abiFilters.add("armeabi-v7a")
  66. }
  67. }
  68. }
  69. }
  70. android.packagingOptions {
  71. exclude 'META-INF/INDEX.LIST'
  72. exclude 'META-INF/io.netty.versions.properties'
  73. }
  74. }
  75. dependencies {
  76. compile fileTree(dir: 'libs', include: ['*.jar'])
  77. testCompile 'junit:junit:4.12'
  78. compile 'com.jcraft:jzlib:1.1.2'
  79. compile 'com.android.support:appcompat-v7:23.4.0'
  80. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

我们在这里对native代码的整个编译、链接做配置。这包括,编译要包含哪些源文件,编译时头文件的搜索路径,我们的native代码依赖的要链接的系统共享库/静态库,我们的native代码依赖的要链接的预编译的共享库/静态库,比如我们的chromium net等。配置编译出来的共享库的文件名。同时还要为buildTypes配置abiFilters,以防止构建系统尝试为其它我们不打算支持的ABI,如arm64-v8a、mips、mips64、x86和x86_64,构建共享库,而发生找不到响应的chromium net的so文件的错误。

应用工程编译

做了上面的配置之后,我们怀着激动的心情,小心翼翼地点击“Rebuild Project”菜单项,并期待奇迹发生。编译过程启动之后,很快就终止了,报出了如下的error:

  1. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp
  2. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp
  3. Information:(6) (Unknown) In file included
  4. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h
  5. Error:(10, 35) base/strings/string16.h: No such file or directory
  6. compilation terminated.
  7. Error:Execution failed for task ':app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp'.
  8. > A build operation failed.
  9. C++ compiler failed while compiling NetJni.cpp.
  10. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp/output.txt
  11. Information:BUILD FAILED
  12. Information:Total time: 4.239 secs
  13. Information:2 errors
  14. Information:0 warnings
  15. Information:See complete output in console
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

提示找不到base模块的头文件base/strings/string16.h。base模块是chromium项目中大多数模块都会依赖的模块,它提供了许多基本的功能,比如字符串,文件操作,消息队列MessageQueue,内存管理的一些操作等等。net模块的头文件include了base的头文件的地方还不少,而在我们自己的JNI native层代码中,也难免要引用到base定义的一些组件,因而我们需要将base模块导出的头文件一并引入我们的工程。提取base的头文件并引入我们的工程:

  1. $ cd /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include
  2. $ chromium_mod_headers_extracter.py ~/data/chromium_android/src out/Default base
  • 1
  • 2

配置stl

引入了base模块的头文件之后,再次编译我们的应用工程。又报error了:

  1. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp
  2. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h
  3. Information:(10) (Unknown) In file included
  4. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/strings/string16.h
  5. Error:(33, 22) functional: No such file or directory
  6. compilation terminated.
  7. Error:Execution failed for task ':app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp'.
  8. > A build operation failed.
  9. C++ compiler failed while compiling NetJni.cpp.
  10. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp/output.txt
  11. Information:BUILD FAILED
  12. Information:Total time: 10.702 secs
  13. Information:2 errors
  14. Information:0 warnings
  15. Information:See complete output in console
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这里是提示找不到STL的头文件。在MyApplication/app/build.gradle中配置stl:

            stl "gnustl_static"
  • 1

引入chromium的build配置头文件

配置了stl之后,再次编译我们的应用工程。接着报error:

  1. 18:52:21: Executing external task 'assembleDebug'...
  2. Observed package id 'build-tools;20.0.0' in inconsistent location '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/android-4.4W' (Expected '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/20.0.0')
  3. Incremental java compilation is an incubating feature.
  4. In file included from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h:10:0,
  5. from /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:6:
  6. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/strings/string16.h:37:32: fatal error: build/build_config.h: No such file or directory
  7. #include "build/build_config.h"
  8. ^
  9. compilation terminated.
  10. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp FAILED
  11. FAILURE: Build failed with an exception.
  12. * What went wrong:
  13. Execution failed for task ':app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp'.
  14. > A build operation failed.
  15. C++ compiler failed while compiling NetJni.cpp.
  16. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp/output.txt
  17. * Try:
  18. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  19. BUILD FAILED
  20. Total time: 2.773 secs
  21. C++ compiler failed while compiling NetJni.cpp.
  22. 18:52:24: External task execution finished 'assembleDebug'.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

提示找不到"build/build_config.h"文件。这个文件定义了一些全局性的宏,以对编译做一些全局的控制。这次直接将chromium代码库中的对应文件拷贝过来。

引入遗漏的头文件

再次编译我们的应用工程。接着报error:

  1. 18:55:46: Executing external task 'assembleDebug'...
  2. Observed package id 'build-tools;20.0.0' in inconsistent location '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/android-4.4W' (Expected '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/20.0.0')
  3. Incremental java compilation is an incubating feature.
  4. In file included from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/completion_callback.h:10:0,
  5. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h:11,
  6. from /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:6:
  7. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/callback.h:8:35: fatal error: base/callback_forward.h: No such file or directory
  8. #include "base/callback_forward.h"
  9. ^
  10. compilation terminated.
  11. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp FAILED
  12. FAILURE: Build failed with an exception.
  13. * What went wrong:
  14. Execution failed for task ':app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp'.
  15. > A build operation failed.
  16. C++ compiler failed while compiling NetJni.cpp.
  17. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp/output.txt
  18. * Try:
  19. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  20. BUILD FAILED
  21. Total time: 0.663 secs
  22. C++ compiler failed while compiling NetJni.cpp.
  23. 18:55:47: External task execution finished 'assembleDebug'.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

提示找不到base模块的头文件base/callback_forward.h。直接将chromium代码库中的对应文件拷贝过来。我们似乎是被gn desc的输出欺骗了,它似乎并没有将一个模块导出的所有的头文件都告诉我们。像 base/callback_forward.h 一样,逃过了gn desc 的眼睛,同时也逃过了我们提取模块头文件的脚本的眼睛的头文件还有如下的这些:

  1. base/message_loop/timer_slack.h
  2. base/files/file.h
  3. net/cert/cert_status_flags_list.h
  4. net/cert/cert_type.h
  5. net/base/privacy_mode.h
  6. net/websockets/websocket_event_interface.h
  7. net/quic/quic_alarm_factory.h
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这里我们就不将缺少这些文件导致的错误的错误输出列出来了,内容与前面看到的缺少base/callback_forward.h文件导致的错误的错误输出类似,解决的方法也相同。

算下来,我们提取模块的头文件的脚本遗漏了8个头文件。不能不让人感慨,移植这个事情真是个体力活啊。不过还好遗漏的不是80个文件,或800个,要不然真是要把人逼疯了。

引入url模块的导出头文件

引入了那些遗漏的头文件之后,再次编译。继续报错:

  1. 18:57:46: Executing external task 'assembleDebug'...
  2. Observed package id 'build-tools;20.0.0' in inconsistent location '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/android-4.4W' (Expected '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/20.0.0')
  3. Incremental java compilation is an incubating feature.
  4. In file included from /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/atomic:38:0,
  5. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/atomicops_internals_portable.h:35,
  6. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/atomicops.h:152,
  7. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/atomic_ref_count.h:11,
  8. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/callback_internal.h:11,
  9. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/callback.h:9,
  10. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/completion_callback.h:10,
  11. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h:11,
  12. from /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:6:
  13. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
  14. #error This file requires compiler and library support for the \
  15. ^
  16. In file included from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate.h:15:0,
  17. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h:12,
  18. from /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:6:
  19. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/auth.h:13:24: fatal error: url/origin.h: No such file or directory
  20. #include "url/origin.h"
  21. ^
  22. compilation terminated.
  23. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp FAILED
  24. FAILURE: Build failed with an exception.
  25. * What went wrong:
  26. Execution failed for task ':app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp'.
  27. > A build operation failed.
  28. C++ compiler failed while compiling NetJni.cpp.
  29. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp/output.txt
  30. * Try:
  31. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  32. BUILD FAILED
  33. Total time: 0.722 secs
  34. C++ compiler failed while compiling NetJni.cpp.
  35. 18:57:47: External task execution finished 'assembleDebug'.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

这次是提示找不到url模块的头文件url/origin.h。url模块与我们要用的net联系紧密,同样不可避免地要在我们的native层代码中引用到。因而我们要将url模块导出的头文件一并引入我们的工程。提取url的导出头文件并引入我们的工程:

  1. $ cd /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include
  2. $ chromium_mod_headers_extracter.py ~/data/chromium_android/src out/Default url
  • 1
  • 2

注释掉gtest相关代码

引入了url模块的导出头文件之后,再次编译。继续报错:

  1. 19:00:48: Executing external task 'assembleDebug'...
  2. Observed package id 'build-tools;20.0.0' in inconsistent location '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/android-4.4W' (Expected '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/20.0.0')
  3. Incremental java compilation is an incubating feature.
  4. In file included from /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/atomic:38:0,
  5. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/atomicops_internals_portable.h:35,
  6. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/atomicops.h:152,
  7. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/atomic_ref_count.h:11,
  8. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/callback_internal.h:11,
  9. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/callback.h:9,
  10. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/completion_callback.h:10,
  11. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h:11,
  12. from /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:6:
  13. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
  14. #error This file requires compiler and library support for the \
  15. ^
  16. In file included from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/cookies/canonical_cookie.h:12:0,
  17. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate.h:17,
  18. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h:12,
  19. from /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:6:
  20. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/gtest_prod_util.h:8:52: fatal error: testing/gtest/include/gtest/gtest_prod.h: No such file or directory
  21. #include "testing/gtest/include/gtest/gtest_prod.h"
  22. ^
  23. compilation terminated.
  24. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp FAILED
  25. FAILURE: Build failed with an exception.
  26. * What went wrong:
  27. Execution failed for task ':app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp'.
  28. > A build operation failed.
  29. C++ compiler failed while compiling NetJni.cpp.
  30. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp/output.txt
  31. * Try:
  32. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  33. BUILD FAILED
  34. Total time: 0.66 secs
  35. C++ compiler failed while compiling NetJni.cpp.
  36. 19:00:49: External task execution finished 'assembleDebug'.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

这一次是提示找不到gtest的头文件。暂时我们还无需借助于gtest来做单元测试,因而这个include显得没有必要。我们将MyApplication/app/src/main/jni/third_party/chromium/include/base/gtest_prod_util.h文件中对"testing/gtest/include/gtest/gtest_prod.h"的include注释掉,同时修改FRIEND_TEST_ALL_PREFIXES宏的定义:

  1. #if 0
  2. #define FRIEND_TEST_ALL_PREFIXES(test_case_name, test_name) \
  3. FRIEND_TEST(test_case_name, test_name); \
  4. FRIEND_TEST(test_case_name, DISABLED_##test_name); \
  5. FRIEND_TEST(test_case_name, FLAKY_##test_name)
  6. #else
  7. #define FRIEND_TEST_ALL_PREFIXES(test_case_name, test_name)
  8. #endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这样就可以注释掉类定义中专门为gtest插入的那些代码了。

配置C++11

再次编译,继续报错:

  1. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:166:5: error: 'unique_ptr' is not a member of 'std'
  2. std::unique_ptr<net::URLRequestContext> url_request_context(BuildURLRequestContext(net_log));
  3. ^
  4. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:166:43: error: expected primary-expression before '>' token
  5. std::unique_ptr<net::URLRequestContext> url_request_context(BuildURLRequestContext(net_log));
  6. ^
  7. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:166:95: error: 'BuildURLRequestContext' was not declared in this scope
  8. std::unique_ptr<net::URLRequestContext> url_request_context(BuildURLRequestContext(net_log));
  9. ^
  10. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:166:96: error: 'url_request_context' was not declared in this scope
  11. std::unique_ptr<net::URLRequestContext> url_request_context(BuildURLRequestContext(net_log));
  12. ^
  13. In file included from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/files/file_path.h:113:0,
  14. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/files/file.h:13,
  15. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/net_errors.h:11,
  16. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/proxy/proxy_config_service_fixed.h:9,
  17. from /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:16:
  18. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/containers/hash_tables.h: In instantiation of 'std::size_t base_hash::hash<T>::operator()(const T&) const [with T = std::basic_string<char>; std::size_t = unsigned int]':
  19. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/files/file_path.h:473:56: required from here
  20. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/containers/hash_tables.h:28:77: error: no match for call to '(std::hash) (const std::basic_string<char>&)'
  21. std::size_t operator()(const T& value) const { return std::hash<T>()(value); }
  22. ^
  23. In file included from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h:10:0,
  24. from /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:6:
  25. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/strings/string16.h:194:8: note: candidate is:
  26. struct hash<base::string16> {
  27. ^
  28. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/strings/string16.h:195:15: note: std::size_t std::hash::operator()(const string16&) const
  29. std::size_t operator()(const base::string16& s) const {
  30. ^
  31. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/strings/string16.h:195:15: note: no known conversion for argument 1 from 'const std::basic_string<char>' to 'const string16& {aka const std::basic_string<short unsigned int, base::string16_char_traits>&}'
  32. In file included from /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/atomic:41:0,
  33. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/atomicops_internals_portable.h:35,
  34. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/atomicops.h:152,
  35. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/atomic_ref_count.h:11,
  36. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/callback_internal.h:11,
  37. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/callback.h:9,
  38. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/completion_callback.h:10,
  39. from /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/net/base/network_delegate_impl.h:11,
  40. from /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:6:
  41. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/atomic_base.h: At global scope:
  42. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/atomic_base.h:588:7: warning: inline function 'bool std::__atomic_base<_IntTp>::compare_exchange_strong(std::__atomic_base<_IntTp>::__int_type&, std::__atomic_base<_IntTp>::__int_type, std::memory_order, std::memory_order) volatile [with _ITp = int; std::__atomic_base<_IntTp>::__int_type = int; std::memory_order = std::memory_order]' used but never defined
  43. compare_exchange_strong(__int_type& __i1, __int_type __i2,
  44. ^
  45. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/atomic_base.h:525:7: warning: inline function 'std::__atomic_base<_IntTp>::__int_type std::__atomic_base<_IntTp>::exchange(std::__atomic_base<_IntTp>::__int_type, std::memory_order) volatile [with _ITp = int; std::__atomic_base<_IntTp>::__int_type = int; std::memory_order = std::memory_order]' used but never defined
  46. exchange(__int_type __i,
  47. ^
  48. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/atomic_base.h:624:7: warning: inline function 'std::__atomic_base<_IntTp>::__int_type std::__atomic_base<_IntTp>::fetch_add(std::__atomic_base<_IntTp>::__int_type, std::memory_order) volatile [with _ITp = int; std::__atomic_base<_IntTp>::__int_type = int; std::memory_order = std::memory_order]' used but never defined
  49. fetch_add(__int_type __i,
  50. ^
  51. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/atomic_base.h:485:7: warning: inline function 'void std::__atomic_base<_IntTp>::store(std::__atomic_base<_IntTp>::__int_type, std::memory_order) volatile [with _ITp = int; std::__atomic_base<_IntTp>::__int_type = int; std::memory_order = std::memory_order]' used but never defined
  52. store(__int_type __i,
  53. ^
  54. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/atomic_base.h:507:7: warning: inline function 'std::__atomic_base<_IntTp>::__int_type std::__atomic_base<_IntTp>::load(std::memory_order) const volatile [with _ITp = int; std::__atomic_base<_IntTp>::__int_type = int; std::memory_order = std::memory_order]' used but never defined
  55. load(memory_order __m = memory_order_seq_cst) const volatile noexcept
  56. ^
  57. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp FAILED
  58. FAILURE: Build failed with an exception.
  59. * What went wrong:
  60. Execution failed for task ':app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp'.
  61. > A build operation failed.
  62. C++ compiler failed while compiling NetJni.cpp.
  63. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp/output.txt
  64. * Try:
  65. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  66. BUILD FAILED
  67. Total time: 1.482 secs
  68. C++ compiler failed while compiling NetJni.cpp.
  69. 19:19:25: External task execution finished 'assembleDebug'.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

这里提示std命名空间中没有unique_ptr,没有hash等,前者是C++11中新添加的智能指针模板,而后者则是哈希模板,它定义一个函数对象,实现散列函数。chromium net中,像这样用到了C++11的特性的地方还有很多,这里的这个错误是由于build.gradle中没有进行C++11的配置。我们在MyApplication/app/build.gradle中配置C++11:

            cppFlags.addAll(['-std=gnu++11'])
  • 1

不过在前面,我们也有看到如下这样的错误消息:

  1. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/gnu-libstdc++/4.9/include/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
  2. #error This file requires compiler and library support for the \
  3. ^
  • 1
  • 2
  • 3

如果我们能早些注意到这样的错误消息,做了C++11的配置,大概这里的这个error还是可以避免的。

链接

做了C++11的配置之后,再次编译,继续报错:

  1. 19:29:04: Executing external task 'assembleDebug'...
  2. Observed package id 'build-tools;20.0.0' in inconsistent location '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/android-4.4W' (Expected '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/20.0.0')
  3. Incremental java compilation is an incubating feature.
  4. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp
  5. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/message_loop/message_loop.h:650: error: undefined reference to 'base::MessageLoop::MessageLoop(base::MessageLoop::Type)'
  6. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:39: error: undefined reference to 'base::MessageLoop::current()'
  7. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:39: error: undefined reference to 'base::MessageLoop::QuitWhenIdle()'
  8. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:56: error: undefined reference to 'net::HttpResponseHeaders::EnumerateHeaderLines(unsigned int*, std::string*, std::string*) const'
  9. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:140: error: undefined reference to 'base::BasicStringPiece<std::string>::BasicStringPiece(char const*)'
  10. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:140: error: undefined reference to 'GURL::GURL(base::BasicStringPiece<std::string>)'
  11. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:171: error: undefined reference to 'base::MessageLoop::Run()'
  12. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:147: error: undefined reference to 'GURL::~GURL()'
  13. /media/data/MyProjects/MyApplication/app/build/intermediates/objectFiles/armeabi-v7aDebugSharedLibrary/neteasenetMainCpp/9a4xqrdajtunvcxs263gsxl2i/NetJni.o:NetJni.cpp:vtable for base::MessageLoopForIO: error: undefined reference to 'base::MessageLoop::DoWork()'
  14. /media/data/MyProjects/MyApplication/app/build/intermediates/objectFiles/armeabi-v7aDebugSharedLibrary/neteasenetMainCpp/9a4xqrdajtunvcxs263gsxl2i/NetJni.o:NetJni.cpp:vtable for base::MessageLoopForIO: error: undefined reference to 'base::MessageLoop::DoDelayedWork(base::TimeTicks*)'
  15. /media/data/MyProjects/MyApplication/app/build/intermediates/objectFiles/armeabi-v7aDebugSharedLibrary/neteasenetMainCpp/9a4xqrdajtunvcxs263gsxl2i/NetJni.o:NetJni.cpp:vtable for base::MessageLoopForIO: error: undefined reference to 'base::MessageLoop::DoIdleWork()'
  16. /media/data/MyProjects/MyApplication/app/build/intermediates/objectFiles/armeabi-v7aDebugSharedLibrary/neteasenetMainCpp/9a4xqrdajtunvcxs263gsxl2i/NetJni.o:NetJni.cpp:vtable for base::MessageLoopForIO: error: undefined reference to 'base::MessageLoop::IsType(base::MessageLoop::Type) const'
  17. /media/data/MyProjects/MyApplication/app/src/main/jni/third_party/chromium/include/base/message_loop/message_loop.h:645: error: undefined reference to 'base::MessageLoop::~MessageLoop()'
  18. collect2: error: ld returned 1 exit status
  19. :app:linkNeteasenetArmeabi-v7aDebugSharedLibrary FAILED
  20. FAILURE: Build failed with an exception.
  21. * What went wrong:
  22. Execution failed for task ':app:linkNeteasenetArmeabi-v7aDebugSharedLibrary'.
  23. > A build operation failed.
  24. Linker failed while linking libneteasenet.so.
  25. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/linkNeteasenetArmeabi-v7aDebugSharedLibrary/output.txt
  26. * Try:
  27. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  28. BUILD FAILED
  29. Total time: 4.835 secs
  30. Linker failed while linking libneteasenet.so.
  31. 19:29:09: External task execution finished 'assembleDebug'.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

这次是链接错误,提示找不到base库和url库中的符号base::MessageLoop::MessageLoop(base::MessageLoop::Type)GURL::~GURL()base::MessageLoop::DoIdleWork()等。看来经过前面的各种艰难险阻,我们总算是将native层的cpp文件编译为了.o文件。

为了解决这个问题,我们还需要在MyApplication/app/build.gradle中添加对base和url这两个库的依赖:

  1. chromium_base {
  2. headers.srcDir "src/main/jni/third_party/chromium/include"
  3. binaries.withType(SharedLibraryBinary) {
  4. sharedLibraryFile = file("src/main/jni/third_party/chromium/libs/${targetPlatform.getName()}/libbase.cr.so")
  5. }
  6. }
  7. chromium_url {
  8. headers.srcDir "src/main/jni/third_party/chromium/include"
  9. binaries.withType(SharedLibraryBinary) {
  10. sharedLibraryFile = file("src/main/jni/third_party/chromium/libs/${targetPlatform.getName()}/liburl.cr.so")
  11. }
  12. }
  13. ......
  14. dependencies {
  15. library 'chromium_base' linkage 'shared'
  16. library 'chromium_url' linkage 'shared'
  17. library 'chromium_net' linkage 'shared'
  18. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

选择正确的STL库

经过了前面的修改,再次编译,然而......继续报错:

  1. 19:35:16: Executing external task 'assembleDebug'...
  2. Observed package id 'build-tools;20.0.0' in inconsistent location '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/android-4.4W' (Expected '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/20.0.0')
  3. Incremental java compilation is an incubating feature.
  4. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp UP-TO-DATE
  5. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:56: error: undefined reference to 'net::HttpResponseHeaders::EnumerateHeaderLines(unsigned int*, std::string*, std::string*) const'
  6. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:140: error: undefined reference to 'base::BasicStringPiece<std::string>::BasicStringPiece(char const*)'
  7. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:140: error: undefined reference to 'GURL::GURL(base::BasicStringPiece<std::string>)'
  8. collect2: error: ld returned 1 exit status
  9. :app:linkNeteasenetArmeabi-v7aDebugSharedLibrary FAILED
  10. FAILURE: Build failed with an exception.
  11. * What went wrong:
  12. Execution failed for task ':app:linkNeteasenetArmeabi-v7aDebugSharedLibrary'.
  13. > A build operation failed.
  14. Linker failed while linking libneteasenet.so.
  15. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/linkNeteasenetArmeabi-v7aDebugSharedLibrary/output.txt
  16. * Try:
  17. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  18. BUILD FAILED
  19. Total time: 1.171 secs
  20. Linker failed while linking libneteasenet.so.
  21. 19:35:17: External task execution finished 'assembleDebug'.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

这次是提示找不到符号'net::HttpResponseHeaders::EnumerateHeaderLines(unsigned int, std::string, std::string*) const''base::BasicStringPiece<std::string>::BasicStringPiece(char const*)''GURL::GURL(base::BasicStringPiece<std::string>)'。这个问题还真够诡异。我们对相关的这些模块,base,net和url的gn配置文件,gypi配置文件进行反复的检查,可以百分百地确认,相关的这些文件都是有被编译进so的。

可是為什麼能引用不到这些符号呢?那so中到底有没有相关的这些class呢?通过GNU的binutils工具包中的readelf工具可以查看so中的所有符号,无论是函数符号,还是引用的未定义符号。而且编译器在编译C++文件时,符号都是会被修饰的,以便于支持函数重载等C++的一些特性。binutils工具包还提供了工具c++filt,以帮助我们将修饰后的符号,还原回编译前的样子。

我们利用这些工具,来检查那些so中是否真的没有包含未找到的那些符号:

  1. $ readelf -s -W libbase.cr.so | grep BasicStringPiece | xargs c++filt | grep BasicStringPiece
  2. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece(char const*)
  3. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece(char const*, unsigned int)
  4. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece(std::__1::__wrap_iter<char const*> const&, std::__1::__wrap_iter<char const*> const&)
  5. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
  6. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece()
  7. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece(char const*)
  8. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece(char const*, unsigned int)
  9. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece(std::__1::__wrap_iter<char const*> const&, std::__1::__wrap_iter<char const*> const&)
  10. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
  11. base::BasicStringPiece<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::BasicStringPiece()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

so还真的没有我们的代码中要引用的那些符号。那到底是怎么一回事呢?对比编译我们的工程时报的错,实际情况似乎是,在so中包含了我们需要的函数,但两边修饰后的符号不一致,从而导致链接出错。主要是std中的符号,在so中引用的std的符号,其命名空间都增加了一级"__1"。

这似乎与stl有关。NDK可用的stl库大体有如下的这些:

  1. libstdc++
  2. gabi++_static
  3. gabi++_shared
  4. stlport_static
  5. stlport_shared
  6. gnustl_static
  7. gnustl_shared
  8. c++_static
  9. c++_shared
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

逐个地对这些标准库进行尝试。除了我们前面配置的gnustl_static,上面列出的前面的5种,甚至都找不到头文件<atomic>gnustl_shared报出了与gnustl_static相同的问题。这就只剩下c++_staticc++_shared可选了。

我们首先尝试c++_static,但依然报了错:

  1. 20:00:36: Executing external task 'assembleDebug'...
  2. Observed package id 'build-tools;20.0.0' in inconsistent location '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/android-4.4W' (Expected '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/20.0.0')
  3. Incremental java compilation is an incubating feature.
  4. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp
  5. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:56: error: undefined reference to 'net::HttpResponseHeaders::EnumerateHeaderLines(unsigned int*, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >*, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >*) const'
  6. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:140: error: undefined reference to 'base::BasicStringPiece<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >::BasicStringPiece(char const*)'
  7. /media/data/MyProjects/MyApplication/app/src/main/jni/src/NetJni.cpp:140: error: undefined reference to 'GURL::GURL(base::BasicStringPiece<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >)'
  8. collect2: error: ld returned 1 exit status
  9. :app:linkNeteasenetArmeabi-v7aDebugSharedLibrary FAILED
  10. FAILURE: Build failed with an exception.
  11. * What went wrong:
  12. Execution failed for task ':app:linkNeteasenetArmeabi-v7aDebugSharedLibrary'.
  13. > A build operation failed.
  14. Linker failed while linking libneteasenet.so.
  15. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/linkNeteasenetArmeabi-v7aDebugSharedLibrary/output.txt
  16. * Try:
  17. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  18. BUILD FAILED
  19. Total time: 4.385 secs
  20. Linker failed while linking libneteasenet.so.
  21. 20:00:41: External task execution finished 'assembleDebug'.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

情况发生了变化。尽管依然报了undefined reference to的error,但这次引用不到的符号却已经与我们在so中抓出来的那些符号非常接近了。c++_staticc++_shared是LLVM libc++ runtime,编译我们的JNI时使用的这个STL的实现似乎与编译chromium代码时使用的那个不太一样,但无疑编译chromium时使用的是LLVM libc++ runtime。

我们随便打开一个std的头文件来一窥究竟,比如声明std::string的头文件android-ndk-r12b/sources/cxx-stl/llvm-libc++/libcxx/include/iosfwd,我们注意到了如下的这几行:

  1. _LIBCPP_BEGIN_NAMESPACE_STD
  2. ......
  3. _LIBCPP_END_NAMESPACE_STD
  • 1
  • 2
  • 3
  • 4

这个宏的定义在android-ndk-r12b/sources/cxx-stl/llvm-libc++/libcxx/include/__config:

  1. #define _LIBCPP_ABI_VERSION 1
  2. #define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y
  3. #define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y)
  4. #define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__ndk,_LIBCPP_ABI_VERSION)
  5. ......
  6. #define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { namespace _LIBCPP_NAMESPACE {
  7. #define _LIBCPP_END_NAMESPACE_STD } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

由此我们终于揭开了引用的符号,中间插入的那一级命名空间__ndk1的秘密。这是LLVM libc++ runtime加的。

但编译出来的so中的符号又是怎么回事呢?chromium的代码库中,有完整的构建工具链,包括android的NDK和SDK,它们位于chromium/src/third_party/android_tools。我们打开文件chromium/src/third_party/android_tools/ndk/sources/cxx-stl/llvm-libc++/libcxx/include/__config,可以看到如下这样的宏定义:

  1. #define _LIBCPP_ABI_VERSION 1
  2. #define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y
  3. #define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y)
  4. #define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__,_LIBCPP_ABI_VERSION)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

至此,这个链接过程中符号找不到的问题终于被厘清——chromium中的NDK不是标准NDK。

这样的话解法也就显而易见了,编译我们的工程时,stl用c++_static,同时定制编译chromium所用的NDK。

采用标准NDK编译chromium net

为了解决编译chromium时所用的NDK与编译我们的工程时所用的NDK不一致,导致的链接错误,我们需要定制编译chromium时所用的NDK。这需要重新对chromium的构建进行配置,并再次编译chromium net。首先需要修改out/Default/args.gn,修改后的样子如下:

  1. target_os = "android"
  2. target_cpu = "arm" # (default)
  3. is_debug = true # (default)
  4. # Other args you may want to set:
  5. is_component_build = true
  6. is_clang = true
  7. symbol_level = 1 # Faster build with fewer symbols. -g1 rather than -g2
  8. enable_incremental_javac = true # Much faster; experimental
  9. android_ndk_root = "~/data/dev_tools/Android/android-ndk-r12b"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

然后,通过如下的命令,再次编译chromium net。但出错了:

  1. $ gn gen out/Default/
  2. Generating files...
  3. Done. Wrote 11150 targets from 881 files in 2166ms
  4. $ ninja -C out/Default/ net
  5. ninja: Entering directory `out/Default/'
  6. ninja: error: '../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9/libgcc.a', needed by 'obj/base/third_party/dynamic_annotations/libdynamic_annotations.a', missing and no known rule to make it
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这次是找不到ndk的一个文件android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9/libgcc.a。我们发现android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9目录不存在,但是android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x是存在的,我们直接将4.9.x复制到4.9。

再次编译,在链接生成libbase.cr.so时,出错了:

  1. $ ninja -C out/Default/ net
  2. ninja: Entering directory `out/Default/'
  3. [1349/2009] SOLINK ./libbase.cr.so
  4. FAILED: libbase.cr.so libbase.cr.so.TOC lib.unstripped/libbase.cr.so
  5. python "/media/data/chromium_android/src/build/toolchain/gcc_solink_wrapper.py" --readelf="../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-readelf" --nm="../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-nm" --strip=../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip --sofile="./lib.unstripped/libbase.cr.so" --tocfile="./libbase.cr.so.TOC" --output="./libbase.cr.so" -- ../../third_party/llvm-build/Release+Asserts/bin/clang++ -shared -Wl,--fatal-warnings -fPIC -Wl,-z,noexecstack -Wl,-z,now -Wl,-z,relro -Wl,-z,defs -fuse-ld=gold --gcc-toolchain=../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 -Wl,--icf=all -Wl,--build-id=sha1 -Wl,--no-undefined -Wl,--exclude-libs=libgcc.a -Wl,--exclude-libs=libc++_static.a -Wl,--exclude-libs=libvpx_assembly_arm.a --target=arm-linux-androideabi -Wl,--warn-shared-textrel -Wl,-O1 -Wl,--as-needed -nostdlib -Wl,--warn-shared-textrel --sysroot=../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/platforms/android-16/arch-arm -Wl,-wrap,calloc -Wl,-wrap,free -Wl,-wrap,malloc -Wl,-wrap,memalign -Wl,-wrap,posix_memalign -Wl,-wrap,pvalloc -Wl,-wrap,realloc -Wl,-wrap,valloc -L/home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a -o "./lib.unstripped/libbase.cr.so" -Wl,-soname="libbase.cr.so" @"./libbase.cr.so.rsp"
  6. ../../base/debug/stack_trace_android.cc:39: error: undefined reference to '_Unwind_GetIP'
  7. clang: error: linker command failed with exit code 1 (use -v to see invocation)
  8. [1358/2009] CXX obj/third_party/protobuf/protobuf_lite/extension_set.o
  9. ninja: build stopped: subcommand failed.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这次提示找不到符号_Unwind_GetIP,这个符号是libunwind中的。我们还需要修改base/BUILD.gn,在为android编译时,添加对libunwind的依赖:

  1. if (is_android) {
  2. config("android_system_libs") {
  3. libs = [ "log", "unwind" ] # Used by logging.cc.
  4. }
  5. }
  • 1
  • 2
  • 3
  • 4
  • 5

再次编译时依然出错了:

  1. $ gn args out/Default/
  2. Waiting for editor on "/media/data/chromium_android/src/out/Default/args.gn"...
  3. Generating files...
  4. Done. Wrote 11150 targets from 881 files in 2196ms
  5. $ ninja -C out/Default/ net
  6. ninja: Entering directory `out/Default/'
  7. [27/640] SOLINK ./libicuuc.cr.so
  8. FAILED: libicuuc.cr.so libicuuc.cr.so.TOC lib.unstripped/libicuuc.cr.so
  9. python "/media/data/chromium_android/src/build/toolchain/gcc_solink_wrapper.py" --readelf="../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-readelf" --nm="../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-nm" --strip=../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip --sofile="./lib.unstripped/libicuuc.cr.so" --tocfile="./libicuuc.cr.so.TOC" --output="./libicuuc.cr.so" -- ../../third_party/llvm-build/Release+Asserts/bin/clang++ -shared -Wl,--fatal-warnings -fPIC -Wl,-z,noexecstack -Wl,-z,now -Wl,-z,relro -Wl,-z,defs -fuse-ld=gold --gcc-toolchain=../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 -Wl,--icf=all -Wl,--build-id=sha1 -Wl,--no-undefined -Wl,--exclude-libs=libgcc.a -Wl,--exclude-libs=libc++_static.a -Wl,--exclude-libs=libvpx_assembly_arm.a --target=arm-linux-androideabi -Wl,--warn-shared-textrel -Wl,-O1 -Wl,--as-needed -nostdlib -Wl,--warn-shared-textrel --sysroot=../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/platforms/android-16/arch-arm -L/home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a -o "./lib.unstripped/libicuuc.cr.so" -Wl,-soname="libicuuc.cr.so" @"./libicuuc.cr.so.rsp"
  10. ../../third_party/icu/source/common/rbbi.cpp:324: error: undefined reference to '__cxa_bad_typeid'
  11. ../../third_party/icu/source/common/schriter.cpp:90: error: undefined reference to '__cxa_bad_typeid'
  12. ../../third_party/icu/source/common/stringtriebuilder.cpp:386: error: undefined reference to '__cxa_bad_typeid'
  13. ../../third_party/icu/source/common/uchriter.cpp:72: error: undefined reference to '__cxa_bad_typeid'
  14. clang: error: linker command failed with exit code 1 (use -v to see invocation)
  15. [36/640] CXX obj/url/url/url_util.o
  16. ninja: build stopped: subcommand failed.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这是在编译icu时,找不到符号__cxa_bad_typeid。这需要重新配置编译环境,更改所用的工具链,不能是clang,修改之后的out/Default/args.gn如下:

  1. target_os = "android"
  2. target_cpu = "arm" # (default)
  3. is_debug = true # (default)
  4. # Other args you may want to set:
  5. is_component_build = true
  6. is_clang = false
  7. symbol_level = 1 # Faster build with fewer symbols. -g1 rather than -g2
  8. enable_incremental_javac = true # Much faster; experimental
  9. android_ndk_root = "/home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

重新配置chromium的构建环境,并再次编译net。

这终于编译好了。将编译出来的so文件拷贝进我们的工程。再次编译我们的工程。但依然在报错:

  1. 21:02:17: Executing external task 'assembleDebug'...
  2. Observed package id 'build-tools;20.0.0' in inconsistent location '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/android-4.4W' (Expected '/home/hanpfei0306/data/dev_tools/Android/sdk/build-tools/20.0.0')
  3. Incremental java compilation is an incubating feature.
  4. :app:compileNeteasenetArmeabi-v7aDebugSharedLibraryNeteasenetMainCpp
  5. :app:linkNeteasenetArmeabi-v7aDebugSharedLibrary
  6. :app:neteasenetArmeabi-v7aDebugSharedLibrary
  7. :app:stripSymbolsArmeabi-v7aDebugSharedLibrary
  8. :app:ndkBuildArmeabi-v7aDebugSharedLibrary
  9. :app:ndkBuildArmeabi-v7aDebugStaticLibrary UP-TO-DATE
  10. :app:compileNeteasenetArmeabiDebugSharedLibraryNeteasenetMainCpp
  11. /usr/local/google/buildbot/src/android/ndk-r12-release/ndk/sources/cxx-stl/llvm-libc++/libcxx/include/atomic:922: error: undefined reference to '__atomic_fetch_add_4'
  12. /usr/local/google/buildbot/src/android/ndk-r12-release/ndk/sources/cxx-stl/llvm-libc++abi/libcxxabi/src/cxa_handlers.cpp:112: error: undefined reference to '__atomic_exchange_4'
  13. /usr/local/google/buildbot/src/android/ndk-r12-release/ndk/sources/cxx-stl/llvm-libc++abi/libcxxabi/src/cxa_default_handlers.cpp:106: error: undefined reference to '__atomic_exchange_4'
  14. /usr/local/google/buildbot/src/android/ndk-r12-release/ndk/sources/cxx-stl/llvm-libc++abi/libcxxabi/src/cxa_default_handlers.cpp:117: error: undefined reference to '__atomic_exchange_4'
  15. collect2: error: ld returned 1 exit status
  16. :app:linkNeteasenetArmeabiDebugSharedLibrary FAILED
  17. FAILURE: Build failed with an exception.
  18. * What went wrong:
  19. Execution failed for task ':app:linkNeteasenetArmeabiDebugSharedLibrary'.
  20. > A build operation failed.
  21. Linker failed while linking libneteasenet.so.
  22. See the complete log at: file:///media/data/MyProjects/MyApplication/app/build/tmp/linkNeteasenetArmeabiDebugSharedLibrary/output.txt
  23. * Try:
  24. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  25. BUILD FAILED
  26. Total time: 6.648 secs
  27. Linker failed while linking libneteasenet.so.
  28. 21:02:24: External task execution finished 'assembleDebug'.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

不过这次已经不是找不到chromium的库中的符号了,而是标准库中的一些符号。这需要我们修改依赖的stl为c++_shared,而不是c++_static。再次编译,终于build pass。

编译链接的标记设置

chromium中,有许多feature的开关是通过预定义宏来控制的,它的整个的编译链接都有它独特的参数。如果在编译我们的工程时,预定义的宏与编译chromium时预定义的宏不一致,就很容易出现两边的class实际的定义不一样的问题。比如net::URLRequestContextBuilder类的定义:

  1. private:
  2. std::string accept_language_;
  3. std::string user_agent_;
  4. // Include support for data:// requests.
  5. bool data_enabled_;
  6. #if !defined(DISABLE_FILE_SUPPORT)
  7. // Include support for file:// requests.
  8. bool file_enabled_;
  9. #endif
  10. #if !defined(DISABLE_FTP_SUPPORT)
  11. // Include support for ftp:// requests.
  12. bool ftp_enabled_;
  13. #endif
  14. bool http_cache_enabled_;
  15. bool throttling_enabled_;
  16. bool backoff_enabled_;
  17. bool sdch_enabled_;
  18. bool cookie_store_set_by_client_;
  19. scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
  20. HttpCacheParams http_cache_params_;
  21. HttpNetworkSessionParams http_network_session_params_;
  22. base::FilePath transport_security_persister_path_;
  23. NetLog* net_log_;
  24. std::unique_ptr<HostResolver> host_resolver_;
  25. std::unique_ptr<ChannelIDService> channel_id_service_;
  26. std::unique_ptr<ProxyConfigService> proxy_config_service_;
  27. std::unique_ptr<ProxyService> proxy_service_;
  28. std::unique_ptr<NetworkDelegate> network_delegate_;
  29. std::unique_ptr<ProxyDelegate> proxy_delegate_;
  30. std::unique_ptr<CookieStore> cookie_store_;
  31. #if !defined(DISABLE_FTP_SUPPORT)
  32. std::unique_ptr<FtpTransactionFactory> ftp_transaction_factory_;
  33. #endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

会根据宏定义来确定某些字段是否存在,如ftp_enabled_等。如果两边的宏定义不同,则会导致两边对net::URLRequestContextBuilder对象的处理不同。对于定义了宏DISABLE_FTP_SUPPORT的一边,它在为net::URLRequestContextBuilder对象分配内存空间时,将小于另一边看到的相同类对象的内存空间大小,可想而知,在运行期该会要出现什么样的奇怪问题了。

比如,我们在我们的工程中,定义了宏DISABLE_FTP_SUPPORT,而在编译chromium net时没有定义这个宏。在我们的native代码里,在栈上创建了一个net::URLRequestContextBuilder对象,内存将由我们的工程的编译器分配。而在运行期,分配的这块内存会被传递给类的构造函数,该构造函数则是在chromium net的so中,而它对这块内存空间的预期要大于我们的工程的编译器分配的大小,则在初始化的过程中,难免要踩坏周围的内存的。

为了避免这个问题,最好的方法就是将相关的这些编译、连接,预定义宏等,在两边保持一致。gn工具在这个问题上也可以帮到我们,同样是gn desc,我们需要从输出的如下这些段中提取我们要的参数:

  1. $ gn desc out/Default/ net
  2. ......
  3. cflags
  4. -fno-strict-aliasing
  5. --param=ssp-buffer-size=4
  6. -fstack-protector
  7. -funwind-tables
  8. -fPIC
  9. -pipe
  10. -ffunction-sections
  11. -fno-short-enums
  12. -finline-limit=64
  13. -march=armv7-a
  14. -mfloat-abi=softfp
  15. -mthumb
  16. -mthumb-interwork
  17. -mtune=generic-armv7-a
  18. -fno-tree-sra
  19. -fno-caller-saves
  20. -mfpu=neon
  21. -Wall
  22. -Werror
  23. -Wno-psabi
  24. -Wno-unused-local-typedefs
  25. -Wno-maybe-uninitialized
  26. -Wno-missing-field-initializers
  27. -Wno-unused-parameter
  28. -Os
  29. -fdata-sections
  30. -ffunction-sections
  31. -fomit-frame-pointer
  32. -g1
  33. --sysroot=../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/platforms/android-16/arch-arm
  34. -fvisibility=hidden
  35. cflags_cc
  36. -fno-threadsafe-statics
  37. -fvisibility-inlines-hidden
  38. -std=gnu++11
  39. -Wno-narrowing
  40. -fno-rtti
  41. -isystem../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/llvm-libc++/libcxx/include
  42. -isystem../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/llvm-libc++abi/libcxxabi/include
  43. -isystem../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/android/support/include
  44. -fno-exceptions
  45. ......
  46. defines
  47. V8_DEPRECATION_WARNINGS
  48. ENABLE_NOTIFICATIONS
  49. ENABLE_BROWSER_CDMS
  50. ENABLE_PRINTING=1
  51. ENABLE_BASIC_PRINTING=1
  52. ENABLE_SPELLCHECK=1
  53. USE_BROWSER_SPELLCHECKER=1
  54. USE_OPENSSL_CERTS=1
  55. NO_TCMALLOC
  56. USE_EXTERNAL_POPUP_MENU=1
  57. ENABLE_WEBRTC=1
  58. DISABLE_NACL
  59. ENABLE_SUPERVISED_USERS=1
  60. VIDEO_HOLE=1
  61. SAFE_BROWSING_DB_REMOTE
  62. CHROMIUM_BUILD
  63. ENABLE_MEDIA_ROUTER=1
  64. ENABLE_WEBVR
  65. FIELDTRIAL_TESTING_ENABLED
  66. _FILE_OFFSET_BITS=64
  67. ANDROID
  68. HAVE_SYS_UIO_H
  69. ANDROID_NDK_VERSION=r10e
  70. __STDC_CONSTANT_MACROS
  71. __STDC_FORMAT_MACROS
  72. COMPONENT_BUILD
  73. __GNU_SOURCE=1
  74. _DEBUG
  75. DYNAMIC_ANNOTATIONS_ENABLED=1
  76. WTF_USE_DYNAMIC_ANNOTATIONS=1
  77. DLOPEN_KERBEROS
  78. NET_IMPLEMENTATION
  79. USE_KERBEROS
  80. ENABLE_BUILT_IN_DNS
  81. POSIX_AVOID_MMAP
  82. ENABLE_WEBSOCKETS
  83. GOOGLE_PROTOBUF_NO_RTTI
  84. GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
  85. HAVE_PTHREAD
  86. PROTOBUF_USE_DLLS
  87. BORINGSSL_SHARED_LIBRARY
  88. U_USING_ICU_NAMESPACE=0
  89. U_ENABLE_DYLOAD=0
  90. U_NOEXCEPT=
  91. ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE
  92. ......
  93. ldflags
  94. -Wl,--fatal-warnings
  95. -fPIC
  96. -Wl,-z,noexecstack
  97. -Wl,-z,now
  98. -Wl,-z,relro
  99. -Wl,-z,defs
  100. -fuse-ld=gold
  101. -Wl,--icf=all
  102. -Wl,--build-id=sha1
  103. -Wl,--no-undefined
  104. -Wl,--exclude-libs=libgcc.a
  105. -Wl,--exclude-libs=libc++_static.a
  106. -Wl,--exclude-libs=libvpx_assembly_arm.a
  107. -Wl,--warn-shared-textrel
  108. -Wl,-O1
  109. -Wl,--as-needed
  110. -nostdlib
  111. -Wl,--warn-shared-textrel
  112. --sysroot=../../../../../../home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/platforms/android-16/arch-arm
  113. -Wl,-wrap,calloc
  114. -Wl,-wrap,free
  115. -Wl,-wrap,malloc
  116. -Wl,-wrap,memalign
  117. -Wl,-wrap,posix_memalign
  118. -Wl,-wrap,pvalloc
  119. -Wl,-wrap,realloc
  120. -Wl,-wrap,valloc
  121. ......
  122. libs
  123. c++_shared
  124. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9/libgcc.a
  125. c
  126. atomic
  127. dl
  128. m
  129. log
  130. unwind
  131. lib_dirs
  132. /home/hanpfei0306/data/dev_tools/Android/android-ndk-r12b/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141

最终,我们的MyApplication/app/build.gradle文件将如下面这样:

  1. apply plugin: 'com.android.model.application'
  2. model {
  3. repositories {
  4. libs(PrebuiltLibraries) {
  5. chromium_net {
  6. headers.srcDir "src/main/jni/third_party/chromium/include"
  7. binaries.withType(SharedLibraryBinary) {
  8. sharedLibraryFile = file("src/main/jni/third_party/chromium/libs/${targetPlatform.getName()}/libnet.cr.so")
  9. }
  10. }
  11. chromium_base {
  12. headers.srcDir "src/main/jni/third_party/chromium/include"
  13. binaries.withType(SharedLibraryBinary) {
  14. sharedLibraryFile = file("src/main/jni/third_party/chromium/libs/${targetPlatform.getName()}/libbase.cr.so")
  15. }
  16. }
  17. chromium_url {
  18. headers.srcDir "src/main/jni/third_party/chromium/include"
  19. binaries.withType(SharedLibraryBinary) {
  20. sharedLibraryFile = file("src/main/jni/third_party/chromium/libs/${targetPlatform.getName()}/liburl.cr.so")
  21. }
  22. }
  23. }
  24. }
  25. android {
  26. compileSdkVersion 23
  27. buildToolsVersion "23.0.3"
  28. defaultConfig {
  29. applicationId "com.example.hanpfei0306.myapplication"
  30. minSdkVersion.apiLevel 19
  31. targetSdkVersion.apiLevel 21
  32. versionCode 1
  33. versionName "1.0"
  34. }
  35. ndk {
  36. moduleName "neteasenet"
  37. toolchain "clang"
  38. CFlags.addAll(["-fno-strict-aliasing",
  39. "--param=ssp-buffer-size=4",
  40. "-fstack-protector",
  41. "-funwind-tables",
  42. "-fPIC",
  43. "-pipe",
  44. "-ffunction-sections",
  45. "-fno-short-enums",
  46. "-finline-limit=64",
  47. "-mfloat-abi=softfp",
  48. "-mfpu=neon",
  49. "-Os",
  50. "-fdata-sections",
  51. "-ffunction-sections",
  52. "-fomit-frame-pointer",
  53. "-g1",
  54. "-fvisibility=hidden"
  55. ])
  56. CFlags.addAll(['-I' + file('src/main/jni/third_party/chromium/include/'),])
  57. cppFlags.addAll(["-fno-threadsafe-statics",
  58. "-fvisibility-inlines-hidden",
  59. "-std=gnu++11",
  60. "-Wno-narrowing",
  61. "-fno-rtti",
  62. ])
  63. cppFlags.addAll(["-DV8_DEPRECATION_WARNINGS",
  64. "-DENABLE_NOTIFICATIONS",
  65. "-DENABLE_BROWSER_CDMS",
  66. "-DENABLE_PRINTING=1",
  67. "-DENABLE_BASIC_PRINTING=1",
  68. "-DENABLE_SPELLCHECK=1",
  69. "-DUSE_BROWSER_SPELLCHECKER=1",
  70. "-DUSE_OPENSSL_CERTS=1",
  71. "-DNO_TCMALLOC",
  72. "-DUSE_EXTERNAL_POPUP_MENU=1",
  73. "-DDISABLE_NACL",
  74. "-DENABLE_SUPERVISED_USERS=1",
  75. "-DCHROMIUM_BUILD",
  76. "-D_FILE_OFFSET_BITS=64",
  77. "-DANDROID",
  78. "-DHAVE_SYS_UIO_H",
  79. "-D__STDC_CONSTANT_MACROS",
  80. "-D__STDC_FORMAT_MACROS",
  81. "-D_FORTIFY_SOURCE=2",
  82. "-DCOMPONENT_BUILD",
  83. "-D__GNU_SOURCE=1",
  84. "-D_DEBUG",
  85. "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
  86. "-DWTF_USE_DYNAMIC_ANNOTATIONS=1",
  87. "-DDLOPEN_KERBEROS",
  88. "-DNET_IMPLEMENTATION",
  89. "-DUSE_KERBEROS",
  90. "-DENABLE_BUILT_IN_DNS",
  91. "-DPOSIX_AVOID_MMAP",
  92. "-DENABLE_WEBSOCKETS",
  93. "-DGOOGLE_PROTOBUF_NO_RTTI",
  94. "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
  95. "-DHAVE_PTHREAD",
  96. "-DPROTOBUF_USE_DLLS",
  97. "-DBORINGSSL_SHARED_LIBRARY",
  98. "-DU_USING_ICU_NAMESPACE=0",
  99. "-DU_ENABLE_DYLOAD=0",
  100. ])
  101. cppFlags.addAll(['-I' + file('src/main/jni/third_party/chromium/include'), ])
  102. ldLibs.add("android")
  103. ldLibs.add("log")
  104. ldLibs.add("z")
  105. stl "c++_shared"
  106. }
  107. sources {
  108. main {
  109. java {
  110. source {
  111. srcDir "src/main/java"
  112. }
  113. }
  114. jni {
  115. source {
  116. srcDirs = ["src/main/jni",]
  117. }
  118. dependencies {
  119. library 'chromium_base' linkage 'shared'
  120. library 'chromium_url' linkage 'shared'
  121. library 'chromium_net' linkage 'shared'
  122. }
  123. }
  124. jniLibs {
  125. source {
  126. srcDirs =["src/main/jni/third_party/chromium/libs",]
  127. }
  128. }
  129. }
  130. }
  131. buildTypes {
  132. debug {
  133. ndk {
  134. abiFilters.add("armeabi")
  135. abiFilters.add("armeabi-v7a")
  136. }
  137. }
  138. release {
  139. minifyEnabled false
  140. proguardFiles.add(file("proguard-rules.pro"))
  141. ndk {
  142. abiFilters.add("armeabi")
  143. abiFilters.add("armeabi-v7a")
  144. }
  145. }
  146. }
  147. }
  148. }
  149. dependencies {
  150. compile fileTree(dir: 'libs', include: ['*.jar'])
  151. testCompile 'junit:junit:4.12'
  152. compile 'com.android.support:appcompat-v7:23.4.0'
  153. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/261903
推荐阅读
相关标签
  

闽ICP备14008679号