mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-23 22:06:12 +03:00
Add Cronet CGO SDK builder
bidi_example.cc does not work in cross compile yet, because libstdc++-dev is not installed in cross compile sysroots.
This commit is contained in:
parent
7804341572
commit
57f567c2b9
@ -53,6 +53,7 @@ group("gn_all") {
|
|||||||
deps = [
|
deps = [
|
||||||
":gn_visibility",
|
":gn_visibility",
|
||||||
"//net",
|
"//net",
|
||||||
|
"//components/cronet",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
# found in the LICENSE file.
|
# found in the LICENSE file.
|
||||||
|
|
||||||
import("//build/buildflag_header.gni")
|
import("//build/buildflag_header.gni")
|
||||||
|
import("//build/config/c++/c++.gni")
|
||||||
import("//build/toolchain/toolchain.gni")
|
import("//build/toolchain/toolchain.gni")
|
||||||
import("//build/util/lastchange.gni")
|
import("//build/util/lastchange.gni")
|
||||||
import("//build/util/process_version.gni")
|
import("//build/util/process_version.gni")
|
||||||
@ -76,7 +77,7 @@ source_set("metrics_util") {
|
|||||||
# For platforms on which the native Cronet library is used, build the library,
|
# For platforms on which the native Cronet library is used, build the library,
|
||||||
# a cronet_tests binary that exercises it, and a unit-tests binary.
|
# a cronet_tests binary that exercises it, and a unit-tests binary.
|
||||||
# Android and iOS have their own platform-specific rules to build Cronet.
|
# Android and iOS have their own platform-specific rules to build Cronet.
|
||||||
if (is_android) {
|
if (false) {
|
||||||
group("cronet_package") {
|
group("cronet_package") {
|
||||||
testonly = true
|
testonly = true
|
||||||
deps = [ "//components/cronet/android:cronet_package_android" ]
|
deps = [ "//components/cronet/android:cronet_package_android" ]
|
||||||
@ -86,6 +87,104 @@ if (is_android) {
|
|||||||
deps = [ "//components/cronet/ios:cronet_package_ios" ]
|
deps = [ "//components/cronet/ios:cronet_package_ios" ]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
static_library("cronet_static") {
|
||||||
|
deps = [
|
||||||
|
"//base",
|
||||||
|
"//components/cronet:cronet_common",
|
||||||
|
"//components/cronet/native:cronet_native_impl",
|
||||||
|
"//net",
|
||||||
|
]
|
||||||
|
|
||||||
|
if (use_custom_libcxx) {
|
||||||
|
deps += [
|
||||||
|
# Add shared_library_deps to include custom libc++ into dependencies.
|
||||||
|
# They are by default only added to executable(), loadable_module(), and
|
||||||
|
# shared_library() targets, but cronet_static_complete library needs it as well to
|
||||||
|
# avoid linking with different versions of libc++.
|
||||||
|
"//build/config:shared_library_deps",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
sources = [ "cronet_global_state_stubs.cc" ]
|
||||||
|
|
||||||
|
complete_static_lib = true
|
||||||
|
configs -= [ "//build/config/compiler:thin_archive" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
executable("cronet_example_external") {
|
||||||
|
testonly = true
|
||||||
|
no_default_deps = true
|
||||||
|
sources = [ "native/sample/bidi_example.cc" ]
|
||||||
|
deps = [ ":cronet" ]
|
||||||
|
configs -= [
|
||||||
|
"//build/config:feature_flags",
|
||||||
|
"//build/config/compiler:afdo",
|
||||||
|
"//build/config/compiler:afdo_optimize_size",
|
||||||
|
"//build/config/compiler:cet_shadow_stack",
|
||||||
|
"//build/config/compiler:chromium_code",
|
||||||
|
"//build/config/compiler:default_include_dirs",
|
||||||
|
"//build/config/compiler:default_init_stack_vars",
|
||||||
|
"//build/config/compiler:default_optimization",
|
||||||
|
"//build/config/compiler:default_stack_frames",
|
||||||
|
"//build/config/compiler:default_symbols",
|
||||||
|
"//build/config/compiler:no_exceptions",
|
||||||
|
"//build/config/compiler:no_rtti",
|
||||||
|
"//build/config/compiler:prevent_unsafe_narrowing",
|
||||||
|
"//build/config/compiler:runtime_library",
|
||||||
|
"//build/config/compiler:thin_archive",
|
||||||
|
"//build/config/compiler/pgo:default_pgo_flags",
|
||||||
|
"//build/config/coverage:default_coverage",
|
||||||
|
"//build/config/sanitizers:default_sanitizer_flags",
|
||||||
|
"//build/config/clang:find_bad_constructs",
|
||||||
|
"//build/config/clang:extra_warnings",
|
||||||
|
]
|
||||||
|
configs += [ "//components/cronet/native:cronet_native_include_config" ]
|
||||||
|
if (is_linux) {
|
||||||
|
configs += [ "//build/config/linux:runtime_library" ]
|
||||||
|
} else if (is_mac) {
|
||||||
|
configs += [ "//build/config/mac:runtime_library" ]
|
||||||
|
} else if (is_android) {
|
||||||
|
configs += [ "//build/config/android:runtime_library" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
executable("cronet_example_external_static") {
|
||||||
|
testonly = true
|
||||||
|
no_default_deps = true
|
||||||
|
sources = [ "native/sample/bidi_example.cc" ]
|
||||||
|
deps = [ ":cronet_static" ]
|
||||||
|
configs -= [
|
||||||
|
"//build/config:feature_flags",
|
||||||
|
"//build/config/compiler:afdo",
|
||||||
|
"//build/config/compiler:afdo_optimize_size",
|
||||||
|
"//build/config/compiler:cet_shadow_stack",
|
||||||
|
"//build/config/compiler:chromium_code",
|
||||||
|
"//build/config/compiler:default_include_dirs",
|
||||||
|
"//build/config/compiler:default_init_stack_vars",
|
||||||
|
"//build/config/compiler:default_optimization",
|
||||||
|
"//build/config/compiler:default_stack_frames",
|
||||||
|
"//build/config/compiler:default_symbols",
|
||||||
|
"//build/config/compiler:no_exceptions",
|
||||||
|
"//build/config/compiler:no_rtti",
|
||||||
|
"//build/config/compiler:prevent_unsafe_narrowing",
|
||||||
|
"//build/config/compiler:runtime_library",
|
||||||
|
"//build/config/compiler:thin_archive",
|
||||||
|
"//build/config/compiler/pgo:default_pgo_flags",
|
||||||
|
"//build/config/coverage:default_coverage",
|
||||||
|
"//build/config/sanitizers:default_sanitizer_flags",
|
||||||
|
"//build/config/clang:find_bad_constructs",
|
||||||
|
"//build/config/clang:extra_warnings",
|
||||||
|
]
|
||||||
|
configs += [ "//components/cronet/native:cronet_native_include_config" ]
|
||||||
|
if (is_linux) {
|
||||||
|
configs += [ "//build/config/linux:runtime_library" ]
|
||||||
|
} else if (is_mac) {
|
||||||
|
configs += [ "//build/config/mac:runtime_library" ]
|
||||||
|
} else if (is_android) {
|
||||||
|
configs += [ "//build/config/android:runtime_library" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
config("shared_library_public_config") {
|
config("shared_library_public_config") {
|
||||||
if (is_mac && !is_component_build) {
|
if (is_mac && !is_component_build) {
|
||||||
# Executable targets that depend on the shared libraries below need to have
|
# Executable targets that depend on the shared libraries below need to have
|
||||||
@ -94,7 +193,7 @@ if (is_android) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_cronet_shared_lib_name = "cronet.$chrome_version_full"
|
_cronet_shared_lib_name = "cronet"
|
||||||
_cronet_shared_lib_file_name =
|
_cronet_shared_lib_file_name =
|
||||||
"$shlib_prefix$_cronet_shared_lib_name$shlib_extension"
|
"$shlib_prefix$_cronet_shared_lib_name$shlib_extension"
|
||||||
|
|
||||||
|
153
src/components/cronet/native/go-build.sh
Executable file
153
src/components/cronet/native/go-build.sh
Executable file
@ -0,0 +1,153 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
WINDOWS_LLVM_VERSION=13.0.1
|
||||||
|
MAC_SDK_VERSION=12.1
|
||||||
|
|
||||||
|
# CGO does not support relative path very well. TODO: better way to handle this using SRCDIR?
|
||||||
|
# for i in go_env.sh link_shared.go link_static.go; do
|
||||||
|
# sed "s#\./sysroot#$PWD/sysroot#g" $i >$i.1
|
||||||
|
# mv $i.1 $i
|
||||||
|
# done
|
||||||
|
|
||||||
|
# Imports environment variables: GOOS, GOARCH, GOMIPS, CGO_CFLAGS, CGO_LDFLAGS
|
||||||
|
# Imports bash variables: ARCH, target_cpu, CLANG_REVISION, WITH_CLANG, WITH_QEMU, WITH_ANDROID_IMG, buildmode_flag
|
||||||
|
. ./go_env.sh
|
||||||
|
|
||||||
|
if [ "$ARCH" = 'Windows' ]; then
|
||||||
|
alias ln='MSYS=winsymlinks:nativestrict ln'
|
||||||
|
exe_extension=.exe
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Gets LLVM
|
||||||
|
# Recommends copying cached content to here to avoid repeatedly downloading from googleapis.com.
|
||||||
|
if [ ! -d ./llvm/bin ]; then
|
||||||
|
if [ -d ../../../third_party/llvm-build/Release+Asserts/bin ]; then
|
||||||
|
# Reuses existing toolchain if running in naiveproxy build tree
|
||||||
|
ln -sfn $PWD/../../../third_party/llvm-build/Release+Asserts ./llvm
|
||||||
|
else
|
||||||
|
mkdir -p ./llvm
|
||||||
|
clang_path="clang-$CLANG_REVISION.tgz"
|
||||||
|
clang_url="https://commondatastorage.googleapis.com/chromium-browser-clang/$WITH_CLANG/$clang_path"
|
||||||
|
curl "$clang_url" | tar xzf - -C ./llvm
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ARCH" = 'Windows' ]; then
|
||||||
|
ln -sfn "C:/Program Files/LLVM/lib/clang/$WINDOWS_LLVM_VERSION" ./llvm/lib/clang/
|
||||||
|
cat >lld-link.cc <<EOF
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
std::string cmd = "lld-link-old";
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
fprintf(stderr, "argv[%d]: %s\n", i, argv[i]);
|
||||||
|
if (strcmp(argv[i], "--tsaware") == 0) continue;
|
||||||
|
if (strcmp(argv[i], "--nxcompat") == 0) continue;
|
||||||
|
if (strstr(argv[i], "--major-os-version=") == argv[i]) continue;
|
||||||
|
if (strstr(argv[i], "--minor-os-version=") == argv[i]) continue;
|
||||||
|
if (strstr(argv[i], "--major-subsystem-version=") == argv[i]) continue;
|
||||||
|
if (strstr(argv[i], "--minor-subsystem-version=") == argv[i]) continue;
|
||||||
|
if (strcmp(argv[i], "--dynamicbase") == 0) continue;
|
||||||
|
if (strcmp(argv[i], "--high-entropy-va") == 0) continue;
|
||||||
|
if (strcmp(argv[i], "-T") == 0) {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(argv[i], "--start-group") == 0) continue;
|
||||||
|
if (strcmp(argv[i], "mingwex.lib") == 0) continue;
|
||||||
|
if (strcmp(argv[i], "mingw32.lib") == 0) continue;
|
||||||
|
if (strcmp(argv[i], "--end-group") == 0) continue;
|
||||||
|
if (strchr(argv[i], ' ') != nullptr) {
|
||||||
|
cmd.append(" \"").append(argv[i]).append("\"");
|
||||||
|
} else {
|
||||||
|
cmd.append(" ").append(argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, "cmd: %s\n", cmd.c_str());
|
||||||
|
return system(cmd.c_str());
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if [ ! -f ./llvm/bin/lld-link-old.exe ]; then
|
||||||
|
cp 'C:\Program Files\LLVM\bin\clang.exe' ./llvm/bin/
|
||||||
|
mv ./llvm/bin/lld-link.exe ./llvm/bin/lld-link-old.exe
|
||||||
|
clang lld-link.cc -o ./llvm/bin/lld-link.exe
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Finds Mac SDK path for sysroot, following build/mac/find_sdk.py.
|
||||||
|
if [ "$ARCH" = 'Darwin' ]; then
|
||||||
|
mac_sdk_path="$(xcode-select -print-path)"/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$MAC_SDK_VERSION.sdk
|
||||||
|
if [ ! -e "$mac_sdk_path" ]; then
|
||||||
|
echo 'MacOS SDK not found'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ln -sfn "$mac_sdk_path" ./sysroot
|
||||||
|
fi
|
||||||
|
|
||||||
|
export PATH="$PWD/llvm/bin:$PATH"
|
||||||
|
export CC=clang
|
||||||
|
export CGO_ENABLED=1
|
||||||
|
export CGO_LDFLAGS_ALLOW=.*
|
||||||
|
|
||||||
|
run_cronet_example() {
|
||||||
|
local rootfs=./sysroot
|
||||||
|
if [ "$WITH_ANDROID_IMG" ]; then
|
||||||
|
# Only supports testing in tree because the rootfs is very large and the script to download it is not trivial.
|
||||||
|
rootfs="$PWD/../../../out/sysroot-build/android/$WITH_ANDROID_IMG"
|
||||||
|
if [ ! -d "$rootfs" ]; then
|
||||||
|
echo 'Skips testing cronet_example due to missing Android rootfs'
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$WITH_QEMU" ]; then
|
||||||
|
if [ "$target_cpu" = "x64" -o "$target_cpu" = "x86" ]; then
|
||||||
|
cp libcronet.so cronet_example "$rootfs"
|
||||||
|
bwrap --bind "$rootfs" / --proc /proc --dev /dev --setenv LD_LIBRARY_PATH / /cronet_example "$@"
|
||||||
|
rm -f "$rootfs"/libcronet.so "$rootfs"/cronet_example
|
||||||
|
else
|
||||||
|
# Older qemu-user cannot run CGO binaries in MIPS, see https://github.com/golang/go/issues/33746.
|
||||||
|
# Newer qemu-user-static can be separately installed.
|
||||||
|
qemu-$WITH_QEMU-static -L "$rootfs" ./cronet_example "$@"
|
||||||
|
fi
|
||||||
|
elif [ "$target_cpu" = "arm64" -a "$ARCH" = "Darwin" ]; then
|
||||||
|
echo 'Skips testing cronet_example'
|
||||||
|
elif [ "$target_cpu" = "arm64" -a "$ARCH" = "Windows" ]; then
|
||||||
|
echo 'Skips testing cronet_example'
|
||||||
|
else
|
||||||
|
./cronet_example "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
go build $buildmode_flag cronet_example.go link_shared.go
|
||||||
|
run_cronet_example http://example.com
|
||||||
|
if [ "$ARCH" = "Linux" ]; then
|
||||||
|
./llvm/bin/llvm-strip cronet_example
|
||||||
|
fi
|
||||||
|
ls -l cronet_example${exe_extension}
|
||||||
|
rm -f cronet_example${exe_extension}
|
||||||
|
|
||||||
|
go build $buildmode_flag cronet_example.go link_static.go
|
||||||
|
run_cronet_example http://example.com
|
||||||
|
if [ "$ARCH" = "Linux" ]; then
|
||||||
|
./llvm/bin/llvm-strip cronet_example
|
||||||
|
fi
|
||||||
|
ls -l cronet_example${exe_extension}
|
||||||
|
rm -f cronet_example${exe_extension}
|
||||||
|
|
||||||
|
# If it is a symlink, it points to pre-installed toolchain. Avoids packaging it.
|
||||||
|
if [ -h ./sysroot ]; then
|
||||||
|
rm -f ./sysroot
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If it is a symlink, it points to pre-installed toolchain. Avoids packaging it.
|
||||||
|
if [ -h ./llvm ]; then
|
||||||
|
rm -f ./llvm
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generated by ThinLTO linking.
|
||||||
|
rm -rf ./thinlto-cache
|
139
src/components/cronet/native/sample/bidi_example.cc
Normal file
139
src/components/cronet/native/sample/bidi_example.cc
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "bidirectional_stream_c.h"
|
||||||
|
#include "cronet_c.h"
|
||||||
|
|
||||||
|
class BidirectionalStreamCallback {
|
||||||
|
public:
|
||||||
|
bidirectional_stream* stream = nullptr;
|
||||||
|
char read_buffer[10240];
|
||||||
|
std::atomic<bool> done = false;
|
||||||
|
|
||||||
|
bidirectional_stream_callback* callback() const { return &s_callback; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static BidirectionalStreamCallback* FromStream(bidirectional_stream* stream) {
|
||||||
|
return reinterpret_cast<BidirectionalStreamCallback*>(stream->annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// C callbacks.
|
||||||
|
static void on_stream_ready_callback(bidirectional_stream* stream) {
|
||||||
|
puts("on_stream_ready_callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_response_headers_received_callback(
|
||||||
|
bidirectional_stream* stream,
|
||||||
|
const bidirectional_stream_header_array* headers,
|
||||||
|
const char* negotiated_protocol) {
|
||||||
|
printf("on_response_headers_received_callback negotiated_protocol=%s\n",
|
||||||
|
negotiated_protocol);
|
||||||
|
BidirectionalStreamCallback* self = FromStream(stream);
|
||||||
|
for (size_t i = 0; i < headers->count; ++i) {
|
||||||
|
if (headers->headers[i].key[0] == '\0')
|
||||||
|
continue;
|
||||||
|
printf("%s: %s\n", headers->headers[i].key, headers->headers[i].value);
|
||||||
|
}
|
||||||
|
bidirectional_stream_read(stream, self->read_buffer,
|
||||||
|
sizeof(self->read_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_read_completed_callback(bidirectional_stream* stream,
|
||||||
|
char* data,
|
||||||
|
int count) {
|
||||||
|
printf("on_read_completed_callback %d\n", count);
|
||||||
|
BidirectionalStreamCallback* self = FromStream(stream);
|
||||||
|
if (count == 0)
|
||||||
|
return;
|
||||||
|
fwrite(data, 1, count, stdout);
|
||||||
|
puts("");
|
||||||
|
bidirectional_stream_read(stream, self->read_buffer,
|
||||||
|
sizeof(self->read_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_write_completed_callback(bidirectional_stream* stream,
|
||||||
|
const char* data) {
|
||||||
|
puts("on_write_completed_callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_response_trailers_received_callback(
|
||||||
|
bidirectional_stream* stream,
|
||||||
|
const bidirectional_stream_header_array* trailers) {
|
||||||
|
puts("on_response_trailers_received_callback");
|
||||||
|
for (size_t i = 0; i < trailers->count; ++i) {
|
||||||
|
printf("%s: %s\n", trailers->headers[i].key, trailers->headers[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_succeded_callback(bidirectional_stream* stream) {
|
||||||
|
puts("on_succeded_callback");
|
||||||
|
BidirectionalStreamCallback* self = FromStream(stream);
|
||||||
|
self->done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_failed_callback(bidirectional_stream* stream, int net_error) {
|
||||||
|
printf("on_failed_callback %d\n", net_error);
|
||||||
|
BidirectionalStreamCallback* self = FromStream(stream);
|
||||||
|
self->done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_canceled_callback(bidirectional_stream* stream) {
|
||||||
|
puts("on_canceled_callback");
|
||||||
|
BidirectionalStreamCallback* self = FromStream(stream);
|
||||||
|
self->done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bidirectional_stream_callback s_callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
bidirectional_stream_callback BidirectionalStreamCallback::s_callback = {
|
||||||
|
on_stream_ready_callback,
|
||||||
|
on_response_headers_received_callback,
|
||||||
|
on_read_completed_callback,
|
||||||
|
on_write_completed_callback,
|
||||||
|
on_response_trailers_received_callback,
|
||||||
|
on_succeded_callback,
|
||||||
|
on_failed_callback,
|
||||||
|
on_canceled_callback,
|
||||||
|
};
|
||||||
|
|
||||||
|
Cronet_EnginePtr CreateCronetEngine() {
|
||||||
|
Cronet_EnginePtr cronet_engine = Cronet_Engine_Create();
|
||||||
|
Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create();
|
||||||
|
Cronet_EngineParams_user_agent_set(engine_params, "Cronet");
|
||||||
|
Cronet_Engine_StartWithParams(cronet_engine, engine_params);
|
||||||
|
Cronet_EngineParams_Destroy(engine_params);
|
||||||
|
return cronet_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: %s url\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const char* url = argv[1];
|
||||||
|
Cronet_EnginePtr cronet_engine = CreateCronetEngine();
|
||||||
|
stream_engine* cronet_stream_engine =
|
||||||
|
Cronet_Engine_GetStreamEngine(cronet_engine);
|
||||||
|
|
||||||
|
BidirectionalStreamCallback stream_callback;
|
||||||
|
stream_callback.stream = bidirectional_stream_create(
|
||||||
|
cronet_stream_engine, &stream_callback, stream_callback.callback());
|
||||||
|
bidirectional_stream_start(stream_callback.stream, url, 0, "GET", nullptr,
|
||||||
|
true);
|
||||||
|
puts("bidirectional_stream_start");
|
||||||
|
while (!stream_callback.done) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
}
|
||||||
|
bidirectional_stream_destroy(stream_callback.stream);
|
||||||
|
|
||||||
|
Cronet_Engine_Shutdown(cronet_engine);
|
||||||
|
Cronet_Engine_Destroy(cronet_engine);
|
||||||
|
return 0;
|
||||||
|
}
|
133
src/components/cronet/native/sample/cronet_example.go
Normal file
133
src/components/cronet/native/sample/cronet_example.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
// #include <stdbool.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
// #include "cronet_c.h"
|
||||||
|
// #include "bidirectional_stream_c.h"
|
||||||
|
// extern void _on_stream_ready(bidirectional_stream* stream);
|
||||||
|
// extern void _on_response_headers_received(bidirectional_stream* stream, bidirectional_stream_header_array* headers, char* negotiated_protocol);
|
||||||
|
// extern void _on_read_completed(bidirectional_stream* stream, char* data, int bytes_read);
|
||||||
|
// extern void _on_write_completed(bidirectional_stream* stream, char* data);
|
||||||
|
// extern void _on_response_trailers_received(bidirectional_stream* stream, bidirectional_stream_header_array* trailers);
|
||||||
|
// extern void _on_succeded(bidirectional_stream* stream);
|
||||||
|
// extern void _on_failed(bidirectional_stream* stream, int net_error);
|
||||||
|
// extern void _on_canceled(bidirectional_stream* stream);
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var wait sync.WaitGroup
|
||||||
|
|
||||||
|
var readBuffer unsafe.Pointer
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cronetEngine := C.Cronet_Engine_Create()
|
||||||
|
|
||||||
|
engineParams := C.Cronet_EngineParams_Create()
|
||||||
|
userAgentC := C.CString("Cronet")
|
||||||
|
C.Cronet_EngineParams_user_agent_set(engineParams, userAgentC)
|
||||||
|
C.Cronet_Engine_StartWithParams(cronetEngine, engineParams)
|
||||||
|
C.free(unsafe.Pointer(userAgentC))
|
||||||
|
C.Cronet_EngineParams_Destroy(engineParams)
|
||||||
|
|
||||||
|
streamEngine := C.Cronet_Engine_GetStreamEngine(cronetEngine)
|
||||||
|
|
||||||
|
var callback C.bidirectional_stream_callback
|
||||||
|
callback.on_stream_ready = (*[0]byte)(C._on_stream_ready)
|
||||||
|
callback.on_response_headers_received = (*[0]byte)(C._on_response_headers_received)
|
||||||
|
callback.on_read_completed = (*[0]byte)(C._on_read_completed)
|
||||||
|
callback.on_response_trailers_received = (*[0]byte)(C._on_response_trailers_received)
|
||||||
|
callback.on_succeded = (*[0]byte)(C._on_succeded)
|
||||||
|
callback.on_failed = (*[0]byte)(C._on_failed)
|
||||||
|
callback.on_canceled = (*[0]byte)(C._on_canceled)
|
||||||
|
|
||||||
|
stream := C.bidirectional_stream_create(streamEngine, nil, &callback)
|
||||||
|
|
||||||
|
url := C.CString(os.Args[1])
|
||||||
|
defer C.free(unsafe.Pointer(url))
|
||||||
|
|
||||||
|
method := C.CString("GET")
|
||||||
|
defer C.free(unsafe.Pointer(method))
|
||||||
|
|
||||||
|
readBuffer = C.malloc(32768)
|
||||||
|
|
||||||
|
wait.Add(1)
|
||||||
|
|
||||||
|
C.bidirectional_stream_start(stream, url, 0, method, nil, true)
|
||||||
|
|
||||||
|
wait.Wait()
|
||||||
|
|
||||||
|
C.free(readBuffer)
|
||||||
|
C.bidirectional_stream_destroy(stream)
|
||||||
|
C.Cronet_Engine_Shutdown(cronetEngine)
|
||||||
|
C.Cronet_Engine_Destroy(cronetEngine)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export _on_stream_ready
|
||||||
|
func _on_stream_ready(stream *C.bidirectional_stream) {
|
||||||
|
log.Println("on_stream_ready_callback")
|
||||||
|
}
|
||||||
|
|
||||||
|
//export _on_response_headers_received
|
||||||
|
func _on_response_headers_received(stream *C.bidirectional_stream, headers *C.bidirectional_stream_header_array, negotiated_protocol *C.char) {
|
||||||
|
log.Println("on_response_headers_received, negotiated_protocol=", C.GoString(negotiated_protocol))
|
||||||
|
var hdrP *C.bidirectional_stream_header
|
||||||
|
hdrP = headers.headers
|
||||||
|
|
||||||
|
headersSlice := unsafe.Slice(hdrP, int(headers.count))
|
||||||
|
for _, header := range headersSlice {
|
||||||
|
key := C.GoString(header.key)
|
||||||
|
if len(key) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value := C.GoString(header.value)
|
||||||
|
log.Println(key + ": " + value)
|
||||||
|
}
|
||||||
|
|
||||||
|
C.bidirectional_stream_read(stream, (*C.char)(readBuffer), 32768)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export _on_read_completed
|
||||||
|
func _on_read_completed(stream *C.bidirectional_stream, data *C.char, bytesRead C.int) {
|
||||||
|
log.Println("on_read_completed")
|
||||||
|
|
||||||
|
dataSlice := C.GoBytes(readBuffer, bytesRead)
|
||||||
|
log.Println(string(dataSlice))
|
||||||
|
|
||||||
|
C.bidirectional_stream_read(stream, (*C.char)(readBuffer), 32768)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export _on_write_completed
|
||||||
|
func _on_write_completed(stream *C.bidirectional_stream, data *C.char) {
|
||||||
|
log.Println("on_write_completed")
|
||||||
|
}
|
||||||
|
|
||||||
|
//export _on_response_trailers_received
|
||||||
|
func _on_response_trailers_received(stream *C.bidirectional_stream, trailers *C.bidirectional_stream_header_array) {
|
||||||
|
log.Println("on_response_trailers_received")
|
||||||
|
}
|
||||||
|
|
||||||
|
//export _on_succeded
|
||||||
|
func _on_succeded(stream *C.bidirectional_stream) {
|
||||||
|
log.Println("on_succeded")
|
||||||
|
wait.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
//export _on_failed
|
||||||
|
func _on_failed(stream *C.bidirectional_stream, net_error C.int) {
|
||||||
|
log.Println("on_failed")
|
||||||
|
log.Println("net error ", strconv.Itoa(int(net_error)))
|
||||||
|
wait.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
//export _on_canceled
|
||||||
|
func _on_canceled(stream *C.bidirectional_stream) {
|
||||||
|
log.Println("on_canceled")
|
||||||
|
wait.Done()
|
||||||
|
}
|
255
src/make-cronet-cgo-sdk.sh
Executable file
255
src/make-cronet-cgo-sdk.sh
Executable file
@ -0,0 +1,255 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. ./get-sysroot.sh
|
||||||
|
|
||||||
|
case "$ARCH" in
|
||||||
|
Linux)
|
||||||
|
WITH_GOOS=linux
|
||||||
|
if [ "$target_os" = 'android' ]; then
|
||||||
|
WITH_GOOS=android
|
||||||
|
fi
|
||||||
|
case "$target_cpu" in
|
||||||
|
x64) WITH_GOARCH=amd64;;
|
||||||
|
x86) WITH_GOARCH=386;;
|
||||||
|
arm64) WITH_GOARCH=arm64;;
|
||||||
|
arm) WITH_GOARCH=arm;;
|
||||||
|
mipsel) WITH_GOARCH=mipsle;;
|
||||||
|
mips64el) WITH_GOARCH=mips64le;;
|
||||||
|
esac
|
||||||
|
shared_lib_name='libcronet.so'
|
||||||
|
static_lib_name='libcronet_static.a'
|
||||||
|
;;
|
||||||
|
Windows)
|
||||||
|
WITH_GOOS=windows
|
||||||
|
case "$target_cpu" in
|
||||||
|
x64) WITH_GOARCH=amd64;;
|
||||||
|
x86) WITH_GOARCH=386;;
|
||||||
|
arm64) WITH_GOARCH=arm64;;
|
||||||
|
esac
|
||||||
|
shared_lib_name='cronet.dll.lib'
|
||||||
|
dll_name='cronet.dll'
|
||||||
|
static_lib_name='cronet_static.lib'
|
||||||
|
;;
|
||||||
|
Darwin)
|
||||||
|
WITH_GOOS=darwin
|
||||||
|
case "$target_cpu" in
|
||||||
|
x64) WITH_GOARCH=amd64;;
|
||||||
|
arm64) WITH_GOARCH=arm64;;
|
||||||
|
esac
|
||||||
|
shared_lib_name='libcronet.dylib'
|
||||||
|
static_lib_name='libcronet_static.a'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
mkdir -p out/Release/cronet
|
||||||
|
|
||||||
|
getflag() {
|
||||||
|
local ninjafile=./out/Release/obj/components/cronet/$1.ninja
|
||||||
|
local flagname="$2"
|
||||||
|
grep "\<$flagname = " $ninjafile | cut -d= -f2- | sed 's/\$:/:/g;s/\\%/%/g;s/\\\$\$/\$/g' | sed "s#=\.\./#=$PWD/out/Release/../#g"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$target_os" = 'android' ]; then
|
||||||
|
WITH_SYSROOT='third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extracts this manually because the sysroot flag generated by Chromium is bundled with other irrelevant stuff.
|
||||||
|
if [ "$WITH_SYSROOT" ]; then
|
||||||
|
cgo_sysroot_flag='--sysroot=$PWD/sysroot'
|
||||||
|
link_sysroot_flag='--sysroot=${SRCDIR}/sysroot'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mac SDK path should be detected in the CGO builder.
|
||||||
|
if [ "$ARCH" = 'Darwin' ]; then
|
||||||
|
cgo_sysroot_flag='-isysroot $PWD/sysroot'
|
||||||
|
link_sysroot_flag='-isysroot ${SRCDIR}/sysroot'
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp -a out/Release/$shared_lib_name out/Release/cronet/
|
||||||
|
if [ "$ARCH" = 'Windows' ]; then
|
||||||
|
cp -a out/Release/$dll_name out/Release/cronet/
|
||||||
|
fi
|
||||||
|
cp -a out/Release/obj/components/cronet/$static_lib_name out/Release/cronet/
|
||||||
|
cp -a components/cronet/native/sample/cronet_example.go out/Release/cronet/
|
||||||
|
cp -a components/cronet/native/generated/cronet.idl_c.h out/Release/cronet/
|
||||||
|
cp -a components/cronet/native/include/cronet_c.h out/Release/cronet/
|
||||||
|
cp -a components/cronet/native/include/cronet_export.h out/Release/cronet/
|
||||||
|
cp -a components/grpc_support/include/bidirectional_stream_c.h out/Release/cronet/
|
||||||
|
if [ "$WITH_SYSROOT" ]; then
|
||||||
|
cp -a "$PWD/$WITH_SYSROOT" out/Release/cronet/sysroot
|
||||||
|
fi
|
||||||
|
if [ "$target_os" = 'android' ]; then
|
||||||
|
# Included by base/BUILD.gn
|
||||||
|
cp -a base/android/library_loader/anchor_functions.lds out/Release/cronet
|
||||||
|
fi
|
||||||
|
cp -a components/cronet/native/go-build.sh out/Release/cronet/
|
||||||
|
|
||||||
|
# CGO's intermediate C files are very small. They need no optimization and only very basic flags.
|
||||||
|
getcgoflags() {
|
||||||
|
# -mllvm: avoid confusion with -m*; we don't use this flag in cgo flags anyway.
|
||||||
|
# ' -march= ': artifact during OpenWrt build
|
||||||
|
# -arch xyz: Mac specific
|
||||||
|
# -fmsc-version=: Windows specific
|
||||||
|
# -Wl,--dynamic-linker=: OpenWrt specific
|
||||||
|
# --unwindlib=: Android specific
|
||||||
|
sed 's/-mllvm[ :][^ ]*//g;s/ -march= / /g' | grep -Eo ' (-fuse-ld=|--target=|-m|-arch |-fmsc-version=|-Wl,--dynamic-linker=|--unwindlib=)[^ ]*' | tr -d '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
cgo_cflags="$(getflag cronet_example_external cflags | getcgoflags) $cgo_sysroot_flag"
|
||||||
|
cgo_ldflags="$(getflag cronet_example_external ldflags | getcgoflags) $cgo_sysroot_flag"
|
||||||
|
# sysroot: It helps cronet_example_external compile, but CGO uses manually constructed sysroot option.
|
||||||
|
# NATVIS: Windows specific; cannot be turned off cleanly with GN flags, so removes it manually here.
|
||||||
|
shared_ldflags="$(getflag cronet_example_external ldflags | sed 's/-isysroot [^ ]*//g;s#/NATVIS:[^ ]*##g') $link_sysroot_flag"
|
||||||
|
static_ldflags="$(getflag cronet_example_external_static ldflags | sed 's/-isysroot [^ ]*//g;s#/NATVIS:[^ ]*##g') $link_sysroot_flag"
|
||||||
|
shared_solibs="$(getflag cronet_example_external solibs)"
|
||||||
|
static_solibs="$(getflag cronet_example_external_static solibs)"
|
||||||
|
shared_libs="$(getflag cronet_example_external libs)"
|
||||||
|
static_libs="$(getflag cronet_example_external_static libs)"
|
||||||
|
shared_frameworks="$(getflag cronet_example_external frameworks)"
|
||||||
|
static_frameworks="$(getflag cronet_example_external_static frameworks)"
|
||||||
|
|
||||||
|
if [ "$ARCH" = 'Linux' ]; then
|
||||||
|
static_libs="./$static_lib_name $static_libs"
|
||||||
|
# Regular Linux seems to require this.
|
||||||
|
if [ ! "$target_os" ]; then
|
||||||
|
static_libs="$static_libs -lm"
|
||||||
|
fi
|
||||||
|
if [ "$target_os" = 'android' ]; then
|
||||||
|
static_libs="$(echo $static_libs | sed 's#[^ ]*/anchor_functions.lds#./anchor_functions.lds#')"
|
||||||
|
fi
|
||||||
|
elif [ "$ARCH" = 'Windows' ]; then
|
||||||
|
# -Wno-dll-attribute-on-redeclaration: https://github.com/golang/go/issues/46502
|
||||||
|
cgo_cflags="$cgo_cflags -Wno-dll-attribute-on-redeclaration"
|
||||||
|
|
||||||
|
# Chromium uses clang-cl.exe, but CGO officially only supports GCC/MinGW on Windows. See https://github.com/golang/go/issues/17014.
|
||||||
|
# 1. CGO hardcodes GCC options incompatible with clang-cl, so an extra clang.exe is required (Chromium only provides clang-cl.exe).
|
||||||
|
# 2. We need CGO to link LLVM bitcode from Chromium, so ld cannot work and lld is required.
|
||||||
|
# 3. CGO passes GCC options incompatible with lld, so an extra lld wrapper is required to remove those options.
|
||||||
|
# 4. I didn't figure out a way to make the whole pipeline use lld-link-wrapper cleanly:
|
||||||
|
# * `-fuse-ld=lld --ld-path=lld-link-wrapper` reports `--ld-path` is an unknown argument.
|
||||||
|
# * `-fuse-ld=.../lld-link-wrapper.exe` creates garbled linker path.
|
||||||
|
# So uses a hack to rename lld-link.exe to lld-link-old.exe which is called from the wrapper "lld-link.exe".
|
||||||
|
# 5. lld-13 does not work with bitcode produced by Chromium's lld-15.
|
||||||
|
# So copies clang-13 from environment to Chromium's LLVM bin directory, and uses clang-13 together with lld-15.
|
||||||
|
cgo_ldflags="-fuse-ld=lld $cgo_ldflags"
|
||||||
|
|
||||||
|
# Helps clang find architecture-specific libpath.
|
||||||
|
# Chromium uses setup_toolchain.py to create -libpath flags. It's too complicated.
|
||||||
|
# This option is already in cflags.
|
||||||
|
if [ "$target_cpu" = 'arm64' ]; then
|
||||||
|
cgo_ldflags="$cgo_ldflags --target=arm64-windows"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Hardcodes sys_lib_flags values from build/toolchain/win/BUILD.gn instead of extracting it from GN artifacts.
|
||||||
|
case "$target_cpu" in
|
||||||
|
x64) cgo_ldflags="$cgo_ldflags -Wl,/MACHINE:X64";;
|
||||||
|
x86) cgo_ldflags="$cgo_ldflags -Wl,/MACHINE:X86";;
|
||||||
|
arm64) cgo_ldflags="$cgo_ldflags -Wl,/MACHINE:ARM64";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Chromium enables /SAFESEH for x86 with clang-cl, but CGO compiles gcc_386.S with GCC which does not support /SAFESEH.
|
||||||
|
# So has to remove /SAFESEH for x86.
|
||||||
|
if [ "$target_cpu" = 'x86' ]; then
|
||||||
|
cgo_ldflags="$cgo_ldflags -Wl,/SAFESEH:NO"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Chromium uses lld-link separately, but CGO calls lld-link through clang, so linker options must be wrapped in clang options.
|
||||||
|
escapelinkerflags() {
|
||||||
|
for i in "$@"; do
|
||||||
|
if echo "$i" | grep -q ','; then
|
||||||
|
echo -n " -Xlinker $i"
|
||||||
|
else
|
||||||
|
echo -n " -Wl,$i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
shared_ldflags="$cgo_ldflags $(escapelinkerflags $shared_ldflags)"
|
||||||
|
static_ldflags="$cgo_ldflags $(escapelinkerflags $static_ldflags)"
|
||||||
|
|
||||||
|
# xyz.lib must be wrapped in clang options
|
||||||
|
shared_libs="./$shared_lib_name $(echo $shared_libs | sed 's/\([a-z0-9_]*\)\.lib/-l\1/g' )"
|
||||||
|
static_libs="./$static_lib_name $(echo $static_libs | sed 's/\([a-z0-9_]*\)\.lib/-l\1/g' )"
|
||||||
|
elif [ "$ARCH" = 'Darwin' ]; then
|
||||||
|
static_libs="./$static_lib_name $static_libs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ARCH" = 'Linux' ]; then
|
||||||
|
# Follows the order of tool("link") from build/toolchain/gcc_toolchain.gni
|
||||||
|
shared_ldflags="$shared_ldflags $shared_solibs $shared_libs"
|
||||||
|
static_ldflags="$static_ldflags $static_solibs $static_libs"
|
||||||
|
elif [ "$ARCH" = 'Windows' ]; then
|
||||||
|
# Follows the order of tool("link") from build/toolchain/win/toolchain.gni
|
||||||
|
shared_ldflags="$sys_lib_flags $shared_libs $shared_solibs $shared_ldflags"
|
||||||
|
static_ldflags="$sys_lib_flags $static_libs $static_solibs $static_ldflags"
|
||||||
|
elif [ "$ARCH" = 'Darwin' ]; then
|
||||||
|
# Follows the order of tool("link") from build/toolchain/apple/toolchain.gni
|
||||||
|
shared_ldflags="$shared_ldflags $shared_frameworks $shared_solibs $shared_libs"
|
||||||
|
static_ldflags="$static_ldflags $static_frameworks $static_solibs $static_libs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# CGO adds -marm, which conflicts with -mthumb used by various OpenWrt targets.
|
||||||
|
if [ "$target_cpu" = 'arm' ]; then
|
||||||
|
cgo_cflags=$(echo "$cgo_cflags" | sed 's/ -mthumb / /g')
|
||||||
|
fi
|
||||||
|
|
||||||
|
buildmode_flag='-buildmode=pie'
|
||||||
|
|
||||||
|
if [ "$target_cpu" = 'mipsel' -o "$target_cpu" = 'mips64el' ]; then
|
||||||
|
# CGO does not support PIE for linux/mipsle,mipe64le.
|
||||||
|
buildmode_flag=
|
||||||
|
elif [ "$target_cpu" = 'arm64' -a "$ARCH" = 'Windows' ]; then
|
||||||
|
# CGO does not support PIE for windows/arm64.
|
||||||
|
buildmode_flag=
|
||||||
|
elif [ "$target_cpu" = 'x86' -a "$target_os" != 'android' ]; then
|
||||||
|
# Segfaults if built with PIE in regular Linux. TODO: Find out why.
|
||||||
|
buildmode_flag=
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Requires explicit -nopie otherwise clang adds -pie to lld sometime.
|
||||||
|
if [ ! "$buildmode_flag" ]; then
|
||||||
|
shared_ldflags="$(echo "$shared_ldflags" | sed 's/ -pie / /g') -nopie"
|
||||||
|
static_ldflags="$(echo "$static_ldflags" | sed 's/ -pie / /g') -nopie"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Avoids section type mismatch for .debug_info etc on MIPS.
|
||||||
|
# This is probably caused by different expectation between LLVM and CGO's GCC.
|
||||||
|
if [ "$target_cpu" = 'mipsel' -o "$target_cpu" = 'mips64el' ]; then
|
||||||
|
shared_ldflags="$shared_ldflags -Wl,--strip-debug"
|
||||||
|
static_ldflags="$static_ldflags -Wl,--strip-debug"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Allows running cronet_example test case without explicit LD_LIBRARY_PATH.
|
||||||
|
if [ "$ARCH" = 'Linux' ]; then
|
||||||
|
shared_ldflags="$shared_ldflags -Wl,-rpath,\$ORIGIN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >out/Release/cronet/go_env.sh <<EOF
|
||||||
|
ARCH=$ARCH
|
||||||
|
target_cpu=$target_cpu
|
||||||
|
CLANG_REVISION=$CLANG_REVISION
|
||||||
|
WITH_CLANG=$WITH_CLANG
|
||||||
|
WITH_QEMU=$WITH_QEMU
|
||||||
|
WITH_ANDROID_IMG=$WITH_ANDROID_IMG
|
||||||
|
buildmode_flag=$buildmode_flag
|
||||||
|
[ "$WITH_GOOS" -a "$WITH_GOARCH" ] && export GOOS="$WITH_GOOS"
|
||||||
|
[ "$WITH_GOARCH" -a "$WITH_GOARCH" ] && export GOARCH="$WITH_GOARCH"
|
||||||
|
[ "$mips_float_abi" = "soft" ] && export GOMIPS=softfloat
|
||||||
|
export CGO_CFLAGS="$cgo_cflags"
|
||||||
|
export CGO_LDFLAGS="$cgo_ldflags"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >out/Release/cronet/link_shared.go <<EOF
|
||||||
|
package main
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: $shared_ldflags
|
||||||
|
import "C"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >out/Release/cronet/link_static.go <<EOF
|
||||||
|
package main
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: $static_ldflags
|
||||||
|
import "C"
|
||||||
|
EOF
|
Loading…
Reference in New Issue
Block a user