From 4e5adba4ba52e63afaab75cce1d1f6461ba5e866 Mon Sep 17 00:00:00 2001 From: klzgrad Date: Wed, 4 May 2022 01:47:06 +0800 Subject: [PATCH] Cronet build --- .github/workflows/build.yml | 169 ++++++++---- src/BUILD.gn | 1 + src/build.sh | 16 ++ src/components/cronet/BUILD.gn | 195 +++++++------- src/components/cronet/native/BUILD.gn | 26 -- src/components/cronet/native/go-build.sh | 149 +++++++++++ .../cronet/native/sample/bidi_example.cc | 139 ++++++++++ .../cronet/native/sample/cronet_example.go | 133 +++++++++ src/components/grpc_support/BUILD.gn | 29 -- src/components/prefs/BUILD.gn | 52 ---- src/get-sysroot.sh | 1 + src/make-go-buildflags.sh | 253 ++++++++++++++++++ tests/basic.sh | 19 ++ tools/build_test.sh | 102 +++---- 14 files changed, 988 insertions(+), 296 deletions(-) create mode 100755 src/components/cronet/native/go-build.sh create mode 100644 src/components/cronet/native/sample/bidi_example.cc create mode 100644 src/components/cronet/native/sample/cronet_example.go create mode 100755 src/make-go-buildflags.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 27e89480d9..25a080f75d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -96,9 +96,13 @@ jobs: arch: [x64, x86, arm64, arm, mipsel, mips64el] env: EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}"' - BUNDLE: 'naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }}' + BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} + CRONET_BUNDLE: cronet-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} steps: - uses: actions/checkout@v2 + - uses: actions/setup-go@v3 + with: + go-version: '^1.18.1' - name: Cache toolchains (Linux, OpenWrt, Android) uses: actions/cache@v2 with: @@ -126,24 +130,35 @@ jobs: restore-keys: ccache-linux-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}- - run: sudo apt update - run: sudo apt install ninja-build pkg-config qemu-user ccache + - run: sudo apt remove -y qemu-user-binfmt + - run: wget https://snapshot.debian.org/archive/debian/20220515T152741Z/pool/main/q/qemu/qemu-user-static_7.0%2Bdfsg-6_amd64.deb + - run: sudo dpkg -i qemu-user-static_7.0+dfsg-6_amd64.deb # libc6-i386 interferes with x86 build - run: sudo apt remove libc6-i386 - run: ./get-clang.sh - run: ccache -s - run: ./build.sh - run: ccache -s + - run: ./go-build.sh + working-directory: src/out/Release/cronet - run: ../tests/basic.sh out/Release/naive - - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} - - run: tar cJf ../${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} - - uses: actions/upload-release-asset@v1 + - name: Pack and upload naiveproxy assets if: ${{ github.event_name == 'release' }} + run: | + mkdir ${{ env.BUNDLE }} + cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + tar cJf ${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} + hub release edit -a ${{ env.BUNDLE }}.tar.xz -m "" "${GITHUB_REF##*/}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Pack and upload cronet assets + if: ${{ github.event_name == 'release' }} + run: | + mv out/Release/cronet ${{ env.CRONET_BUNDLE }} + tar cJf ${{ env.CRONET_BUNDLE }}.tar.xz ${{ env.CRONET_BUNDLE }} + hub release edit -a ${{ env.CRONET_BUNDLE }}.tar.xz -m "" "${GITHUB_REF##*/}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ${{ env.BUNDLE }}.tar.xz - asset_name: ${{ env.BUNDLE }}.tar.xz - asset_content_type: application/octet-stream - run: openssl sha256 out/Release/naive >sha256sum.txt - run: echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV - uses: actions/upload-artifact@v2 @@ -159,9 +174,13 @@ jobs: arch: [x64, x86, arm64, arm] env: EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}" target_os="android"' - BUNDLE: 'naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }}' + BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} + CRONET_BUNDLE: cronet-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} steps: - uses: actions/checkout@v2 + - uses: actions/setup-go@v3 + with: + go-version: '^1.18.1' - name: Cache toolchains (Linux, OpenWrt, Android) uses: actions/cache@v2 with: @@ -194,26 +213,36 @@ jobs: restore-keys: ccache-android-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}- - run: sudo apt update - run: sudo apt install ninja-build pkg-config qemu-user ccache + - run: sudo apt remove -y qemu-user-binfmt + - run: wget https://snapshot.debian.org/archive/debian/20220515T152741Z/pool/main/q/qemu/qemu-user-static_7.0%2Bdfsg-6_amd64.deb + - run: sudo dpkg -i qemu-user-static_7.0+dfsg-6_amd64.deb # libc6-i386 interferes with x86 build - run: sudo apt remove libc6-i386 - run: ./get-clang.sh - run: ccache -s - run: ./build.sh - run: ccache -s - - run: ./get-android-sys.sh && ../tests/basic.sh out/Release/naive - # qemu-user segfaults with x64 or x86 android builds here. - if: ${{ matrix.arch != 'x64' && matrix.arch != 'x86' }} - - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} - - run: tar cJf ../${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} - - uses: actions/upload-release-asset@v1 + - run: ./get-android-sys.sh + - run: ./go-build.sh + working-directory: src/out/Release/cronet + - run: ../tests/basic.sh out/Release/naive + - name: Pack and upload naiveproxy assets if: ${{ github.event_name == 'release' }} + run: | + mkdir ${{ env.BUNDLE }} + cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + tar cJf ${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} + hub release edit -a ${{ env.BUNDLE }}.tar.xz -m "" "${GITHUB_REF##*/}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Pack and upload cronet assets + if: ${{ github.event_name == 'release' }} + run: | + mv out/Release/cronet ${{ env.CRONET_BUNDLE }} + tar cJf ${{ env.CRONET_BUNDLE }}.tar.xz ${{ env.CRONET_BUNDLE }} + hub release edit -a ${{ env.CRONET_BUNDLE }}.tar.xz -m "" "${GITHUB_REF##*/}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ${{ env.BUNDLE }}.tar.xz - asset_name: ${{ env.BUNDLE }}.tar.xz - asset_content_type: application/octet-stream - run: openssl sha256 out/Release/naive >sha256sum.txt - run: echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV - uses: actions/upload-artifact@v2 @@ -229,9 +258,13 @@ jobs: arch: [x64, x86, arm64] env: EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}"' - BUNDLE: 'naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }}' + BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} + CRONET_BUNDLE: cronet-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} steps: - uses: actions/checkout@v2 + - uses: actions/setup-go@v3 + with: + go-version: '^1.18.1' - name: Cache toolchains uses: actions/cache@v2 with: @@ -265,20 +298,28 @@ jobs: - run: ~/.cargo/bin/sccache -s - run: ./build.sh - run: ~/.cargo/bin/sccache -s + - run: ./go-build.sh + working-directory: src/out/Release/cronet - run: ../tests/basic.sh out/Release/naive # No real or emulated environment is available to test this. if: ${{ matrix.arch != 'arm64' }} - - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive.exe config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} - - run: 7z a ../${{ env.BUNDLE }}.zip ${{ env.BUNDLE }} - - uses: actions/upload-release-asset@v1 + - name: Pack and upload naiveproxy assets if: ${{ github.event_name == 'release' }} + run: | + mkdir ${{ env.BUNDLE }} + cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + 7z a ../${{ env.BUNDLE }}.zip ${{ env.BUNDLE }} + hub release edit -a ${{ env.BUNDLE }}.zip -m "" "${GITHUB_REF##*/}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Pack and upload cronet assets + if: ${{ github.event_name == 'release' }} + run: | + mv out/Release/cronet ${{ env.CRONET_BUNDLE }} + 7z a ../${{ env.CRONET_BUNDLE }}.zip ${{ env.CRONET_BUNDLE }} + hub release edit -a ${{ env.CRONET_BUNDLE }}.zip -m "" "${GITHUB_REF##*/}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ${{ env.BUNDLE }}.zip - asset_name: ${{ env.BUNDLE }}.zip - asset_content_type: application/octet-stream - run: openssl sha256 out/Release/naive.exe >sha256sum.txt - run: echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV - uses: actions/upload-artifact@v2 @@ -294,9 +335,13 @@ jobs: arch: [x64, arm64] env: EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}"' - BUNDLE: 'naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }}' + BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} + CRONET_BUNDLE: cronet-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} steps: - uses: actions/checkout@v2 + - uses: actions/setup-go@v3 + with: + go-version: '^1.18.1' - name: Cache toolchains and PGO uses: actions/cache@v2 with: @@ -319,20 +364,28 @@ jobs: - run: ccache -s - run: ./build.sh - run: ccache -s + - run: ./go-build.sh + working-directory: src/out/Release/cronet - run: ../tests/basic.sh out/Release/naive # No real or emulated environment is available to test this. if: ${{ matrix.arch != 'arm64' }} - - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} - - run: tar cJf ../${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} - - uses: actions/upload-release-asset@v1 + - name: Pack and upload naiveproxy assets if: ${{ github.event_name == 'release' }} + run: | + mkdir ${{ env.BUNDLE }} + cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + tar cJf ${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} + hub release edit -a ${{ env.BUNDLE }}.tar.xz -m "" "${GITHUB_REF##*/}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Pack and upload cronet assets + if: ${{ github.event_name == 'release' }} + run: | + mv out/Release/cronet ${{ env.CRONET_BUNDLE }} + tar cJf ${{ env.CRONET_BUNDLE }}.tar.xz ${{ env.CRONET_BUNDLE }} + hub release edit -a ${{ env.CRONET_BUNDLE }}.tar.xz -m "" "${GITHUB_REF##*/}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ${{ env.BUNDLE }}.tar.xz - asset_name: ${{ env.BUNDLE }}.tar.xz - asset_content_type: application/octet-stream - run: openssl sha256 out/Release/naive >sha256sum.txt - run: echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV - uses: actions/upload-artifact@v2 @@ -426,21 +479,25 @@ jobs: - arch: mipsel_24kc openwrt: 'target=ramips subtarget=rt305x' target_cpu: mipsel - extra: 'mips_arch_variant="r2" mips_float_abi="soft" mips_tune="24kc" use_lld=false use_gold=false use_thin_lto=false chrome_pgo_phase=0' + extra: 'mips_arch_variant="r2" mips_float_abi="soft" mips_tune="24kc"' - arch: mipsel_74kc openwrt: 'target=ramips subtarget=rt3883' target_cpu: mipsel - extra: 'mips_arch_variant="r2" mips_float_abi="soft" mips_tune="74kc" use_lld=false use_gold=false use_thin_lto=false chrome_pgo_phase=0' + extra: 'mips_arch_variant="r2" mips_float_abi="soft" mips_tune="74kc"' - arch: mipsel_mips32 openwrt: 'target=bcm47xx subtarget=generic' target_cpu: mipsel - extra: 'mips_arch_variant="r1" mips_float_abi="soft" use_lld=false use_gold=false use_thin_lto=false chrome_pgo_phase=0' + extra: 'mips_arch_variant="r1" mips_float_abi="soft"' env: EXTRA_FLAGS: target_cpu="${{ matrix.target_cpu }}" target_os="openwrt" use_allocator="none" use_allocator_shim=false use_partition_alloc=false ${{ matrix.extra }} OPENWRT_FLAGS: arch=${{ matrix.arch }} release=21.02.2 gcc_ver=8.4.0 ${{ matrix.openwrt }} BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} + CRONET_BUNDLE: cronet-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} steps: - uses: actions/checkout@v2 + - uses: actions/setup-go@v3 + with: + go-version: '^1.18.1' - name: Cache toolchains (Linux, OpenWrt, Android) uses: actions/cache@v2 with: @@ -468,24 +525,36 @@ jobs: restore-keys: ccache-openwrt-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}- - run: sudo apt update - run: sudo apt install ninja-build pkg-config qemu-user ccache + - run: sudo apt remove -y qemu-user-binfmt + - run: wget https://snapshot.debian.org/archive/debian/20220515T152741Z/pool/main/q/qemu/qemu-user-static_7.0%2Bdfsg-6_amd64.deb + - run: sudo dpkg -i qemu-user-static_7.0+dfsg-6_amd64.deb # libc6-i386 interferes with x86 build - run: sudo apt remove libc6-i386 - run: ./get-clang.sh - run: ccache -s - run: ./build.sh - run: ccache -s + - run: ./go-build.sh + working-directory: src/out/Release/cronet + if: ${{ ! contains(matrix.extra, 'build_static=true') }} - run: ../tests/basic.sh out/Release/naive - - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} - - run: tar cJf ../${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} - - uses: actions/upload-release-asset@v1 + - name: Pack and upload naiveproxy assets if: ${{ github.event_name == 'release' }} + run: | + mkdir ${{ env.BUNDLE }} + cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + tar cJf ${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} + hub release edit -a ${{ env.BUNDLE }}.tar.xz -m "" "${GITHUB_REF##*/}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Pack and upload cronet assets + if: ${{ github.event_name == 'release' && ! contains(matrix.extra, 'build_static=true') }} + run: | + mv out/Release/cronet ${{ env.CRONET_BUNDLE }} + tar cJf ${{ env.CRONET_BUNDLE }}.tar.xz ${{ env.CRONET_BUNDLE }} + hub release edit -a ${{ env.CRONET_BUNDLE }}.tar.xz -m "" "${GITHUB_REF##*/}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ${{ env.BUNDLE }}.tar.xz - asset_name: ${{ env.BUNDLE }}.tar.xz - asset_content_type: application/octet-stream - run: openssl sha256 out/Release/naive >sha256sum.txt - run: echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV - uses: actions/upload-artifact@v2 diff --git a/src/BUILD.gn b/src/BUILD.gn index 250ac16619..100ced007d 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -53,6 +53,7 @@ group("gn_all") { deps = [ ":gn_visibility", "//net", + "//components/cronet", ] } diff --git a/src/build.sh b/src/build.sh index e79c38d28d..584799fa46 100755 --- a/src/build.sh +++ b/src/build.sh @@ -61,6 +61,17 @@ if [ "$USE_AFDO" ]; then clang_sample_profile_path="//chrome/android/profiles/afdo.prof"' fi +if [ "$ARCH" = "Darwin" ]; then + flags="$flags"' + enable_dsyms=false' +fi + +if [ "$target_cpu" = "mipsel" -o "$target_cpu" = "mips64el" ]; then + flags="$flags"' + use_thin_lto=false + chrome_pgo_phase=0' +fi + rm -rf "./$out" mkdir -p out @@ -69,3 +80,8 @@ export DEPOT_TOOLS_WIN_TOOLCHAIN=0 ./gn/out/gn gen "$out" --args="$flags $EXTRA_FLAGS" --script-executable=$PYTHON ninja -C "$out" naive + +if echo "$EXTRA_FLAGS" | grep -vq "build_static=true"; then + ninja -C "$out" cronet cronet_static + ./make-go-buildflags.sh +fi diff --git a/src/components/cronet/BUILD.gn b/src/components/cronet/BUILD.gn index 636e66b4f0..36afb8b244 100644 --- a/src/components/cronet/BUILD.gn +++ b/src/components/cronet/BUILD.gn @@ -3,21 +3,21 @@ # found in the LICENSE file. import("//build/buildflag_header.gni") +import("//build/config/c++/c++.gni") import("//build/toolchain/toolchain.gni") import("//build/util/lastchange.gni") import("//build/util/process_version.gni") import("//build/util/version.gni") import("//components/cronet/native/include/headers.gni") import("//components/grpc_support/include/headers.gni") -import("//testing/test.gni") declare_args() { # If set to true, this will remove histogram manager to reduce binary size. - disable_histogram_support = is_mac || is_win + disable_histogram_support = true } # Disable histogram support is not allowed on Android. -assert(!disable_histogram_support || !is_android) +#assert(!disable_histogram_support || !is_android) buildflag_header("cronet_buildflags") { header = "cronet_buildflags.h" @@ -59,7 +59,6 @@ source_set("cronet_common") { "//base", "//components/prefs:prefs", "//net", - "//third_party/metrics_proto", ] if (!disable_histogram_support) { @@ -75,28 +74,10 @@ source_set("metrics_util") { deps = [ "//base" ] } -# Unit tests for Cronet common implementation. -source_set("cronet_common_unittests") { - testonly = true - - deps = [ - ":cronet_common", - "//components/prefs:test_support", - "//net:test_support", - ] - - sources = [ - "host_cache_persistence_manager_unittest.cc", - "network_tasks_unittest.cc", - "stale_host_resolver_unittest.cc", - "url_request_context_config_unittest.cc", - ] -} - # 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. # Android and iOS have their own platform-specific rules to build Cronet. -if (is_android) { +if (false) { group("cronet_package") { testonly = true deps = [ "//components/cronet/android:cronet_package_android" ] @@ -114,10 +95,108 @@ if (is_android) { } } - _cronet_shared_lib_name = "cronet.$chrome_version_full" + _cronet_shared_lib_name = "cronet" _cronet_shared_lib_file_name = "$shlib_prefix$_cronet_shared_lib_name$shlib_extension" + 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" ] + } + } + shared_library("cronet") { output_name = _cronet_shared_lib_name @@ -143,50 +222,6 @@ if (is_android) { } } - test("cronet_tests") { - deps = [ - ":cronet_common", - "//base", - "//base/test:test_support", - "//components/cronet/native:cronet_native_impl", - "//components/cronet/native/test:cronet_native_tests", - "//net", - ] - - sources = [ - "cronet_global_state_stubs.cc", - "run_all_unittests.cc", - ] - - defines = [ "CRONET_TESTS_IMPLEMENTATION" ] - - if ((is_linux || is_chromeos) && !is_component_build) { - public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } - - if (is_fuchsia) { - use_cfv2 = false - additional_manifest_fragments = - [ "//build/config/fuchsia/test/network_capabilities.test-cmx" ] - } - } - - test("cronet_unittests") { - deps = [ - ":cronet_common", - ":cronet_common_unittests", - "//base", - "//base/test:test_support", - "//components/cronet/native:cronet_native_unittests", - "//net", - ] - - sources = [ - "cronet_global_state_stubs.cc", - "run_all_unittests.cc", - ] - } - _package_dir = "$root_out_dir/cronet" # Generate LICENSE file by recursively joining all dependent licenses. @@ -232,22 +267,6 @@ if (is_android) { ] } - executable("cronet_native_perf_test") { - testonly = true - sources = [ - "native/perftest/main.cc", - "native/perftest/perf_test.cc", - ] - deps = [ - "//base", - "//components/cronet", - "//components/cronet/native:cronet_native_headers", - "//components/cronet/native/test:cronet_native_tests", - "//components/cronet/native/test:cronet_native_testutil", - "//net:test_support", - ] - } - executable("cronet_sample") { testonly = true sources = [ @@ -265,12 +284,4 @@ if (is_android) { public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] } } - - test("cronet_sample_test") { - sources = [ "native/sample/test/sample_test.cc" ] - deps = [ - ":cronet_sample", - "//testing/gtest:gtest", - ] - } } diff --git a/src/components/cronet/native/BUILD.gn b/src/components/cronet/native/BUILD.gn index 6ee1271cf3..c3bc307f27 100644 --- a/src/components/cronet/native/BUILD.gn +++ b/src/components/cronet/native/BUILD.gn @@ -4,7 +4,6 @@ import("//components/cronet/native/include/headers.gni") import("//components/grpc_support/include/headers.gni") -import("//testing/test.gni") config("cronet_native_include_config") { include_dirs = [ @@ -71,28 +70,3 @@ source_set("cronet_native_impl") { ] } -# Unit tests for Cronet native API. Depends on cronet_native_impl to test -# implementation details. -source_set("cronet_native_unittests") { - testonly = true - - deps = [ - ":cronet_native_impl", - "//base/test:test_support", - "//components/cronet/native/test:cronet_native_testutil", - "//net:test_support", - "//testing/gtest", - ] - - configs += [ ":cronet_native_include_config" ] - - sources = [ - "engine_unittest.cc", - "native_metrics_util_test.cc", - "runnables_unittest.cc", - - # Generated from cronet.idl. - "generated/cronet.idl_impl_interface_unittest.cc", - "generated/cronet.idl_impl_struct_unittest.cc", - ] -} diff --git a/src/components/cronet/native/go-build.sh b/src/components/cronet/native/go-build.sh new file mode 100755 index 0000000000..18198715b6 --- /dev/null +++ b/src/components/cronet/native/go-build.sh @@ -0,0 +1,149 @@ +#!/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 +if [ ! -d ./llvm ]; then + if [ -d ../../../third_party/llvm-build/Release+Asserts/bin ]; then + # Testing within 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 < +#include +#include +#include + +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" + mkdir -p "$rootfs"/dev "$rootfs"/proc + sudo mount --bind /dev "$rootfs"/dev + sudo mount -t proc proc "$rootfs"/proc + sudo LD_LIBRARY_PATH=/ chroot "$rootfs" /cronet_example "$@" + sudo umount "$rootfs"/dev "$rootfs"/proc + rm -rf "$rootfs"/dev "$rootfs"/proc + rm -f "$rootfs"/libcronet.so "$rootfs"/cronet_example + else + 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 [ -h ./sysroot ]; then + rm -f ./sysroot +fi +if [ -h ./llvm ]; then + rm -f ./llvm +fi \ No newline at end of file diff --git a/src/components/cronet/native/sample/bidi_example.cc b/src/components/cronet/native/sample/bidi_example.cc new file mode 100644 index 0000000000..2297ac9bcb --- /dev/null +++ b/src/components/cronet/native/sample/bidi_example.cc @@ -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 +#include +#include +#include + +#include "bidirectional_stream_c.h" +#include "cronet_c.h" + +class BidirectionalStreamCallback { + public: + bidirectional_stream* stream = nullptr; + char read_buffer[10240]; + std::atomic done = false; + + bidirectional_stream_callback* callback() const { return &s_callback; } + + private: + static BidirectionalStreamCallback* FromStream(bidirectional_stream* stream) { + return reinterpret_cast(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; +} diff --git a/src/components/cronet/native/sample/cronet_example.go b/src/components/cronet/native/sample/cronet_example.go new file mode 100644 index 0000000000..5ab4529e3d --- /dev/null +++ b/src/components/cronet/native/sample/cronet_example.go @@ -0,0 +1,133 @@ +package main + +// #include +// #include +// #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() +} \ No newline at end of file diff --git a/src/components/grpc_support/BUILD.gn b/src/components/grpc_support/BUILD.gn index 133aa30159..89fd8fde4e 100644 --- a/src/components/grpc_support/BUILD.gn +++ b/src/components/grpc_support/BUILD.gn @@ -18,32 +18,3 @@ source_set("grpc_support") { ] } -# Depends on ":grpc_support" implementation. -source_set("bidirectional_stream_unittest") { - testonly = true - sources = [ "bidirectional_stream_unittest.cc" ] - - deps = [ - ":grpc_support", - "//base", - "//net", - "//net:test_support", - ] - - public_deps = [ "//components/grpc_support/test:get_stream_engine_header" ] -} - -# Depends on ":headers" to avoid ":grpc_support" implementation. -source_set("bidirectional_stream_test") { - testonly = true - sources = [ "bidirectional_stream_unittest.cc" ] - - deps = [ - ":headers", - "//base", - "//net", - "//net:test_support", - ] - - public_deps = [ "//components/grpc_support/test:get_stream_engine_header" ] -} diff --git a/src/components/prefs/BUILD.gn b/src/components/prefs/BUILD.gn index 407095f6af..b4fb1694f0 100644 --- a/src/components/prefs/BUILD.gn +++ b/src/components/prefs/BUILD.gn @@ -66,55 +66,3 @@ component("prefs") { deps += [ "android:jni_headers" ] } } - -static_library("test_support") { - testonly = true - sources = [ - "mock_pref_change_callback.cc", - "mock_pref_change_callback.h", - "pref_store_observer_mock.cc", - "pref_store_observer_mock.h", - "pref_test_utils.cc", - "pref_test_utils.h", - "testing_pref_service.cc", - "testing_pref_service.h", - "testing_pref_store.cc", - "testing_pref_store.h", - ] - - public_deps = [ ":prefs" ] - deps = [ - "//base", - "//base/test:test_support", - "//testing/gmock", - "//testing/gtest", - ] -} - -source_set("unit_tests") { - testonly = true - sources = [ - "default_pref_store_unittest.cc", - "in_memory_pref_store_unittest.cc", - "json_pref_store_unittest.cc", - "overlay_user_pref_store_unittest.cc", - "persistent_pref_store_unittest.cc", - "persistent_pref_store_unittest.h", - "pref_change_registrar_unittest.cc", - "pref_member_unittest.cc", - "pref_notifier_impl_unittest.cc", - "pref_service_unittest.cc", - "pref_value_map_unittest.cc", - "pref_value_store_unittest.cc", - "scoped_user_pref_update_unittest.cc", - "segregated_pref_store_unittest.cc", - ] - - deps = [ - ":test_support", - "//base", - "//base/test:test_support", - "//testing/gmock", - "//testing/gtest", - ] -} diff --git a/src/get-sysroot.sh b/src/get-sysroot.sh index b5f0b50749..0d8ced8c68 100644 --- a/src/get-sysroot.sh +++ b/src/get-sysroot.sh @@ -52,6 +52,7 @@ case "$ARCH" in fi ;; MINGW*|MSYS*) + ARCH=Windows if [ -f "$HOME"/.cargo/bin/sccache* ]; then export PATH="$PATH:$HOME/.cargo/bin" CCACHE=sccache diff --git a/src/make-go-buildflags.sh b/src/make-go-buildflags.sh new file mode 100755 index 0000000000..5dc288d3a9 --- /dev/null +++ b/src/make-go-buildflags.sh @@ -0,0 +1,253 @@ +#!/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 + sysroot_flag='--sysroot=./sysroot' +fi + +# Mac SDK path should be detected in the CGO builder. +if [ "$ARCH" = 'Darwin' ]; then + sysroot_flag='-isysroot ./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) $sysroot_flag" +cgo_ldflags="$(getflag cronet_example_external ldflags | getcgoflags) $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') $sysroot_flag" +static_ldflags="$(getflag cronet_example_external_static ldflags | sed 's/-isysroot [^ ]*//g;s#/NATVIS:[^ ]*##g') $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" != '' ]; 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 <out/Release/cronet/link_shared.go <out/Release/cronet/link_static.go <