You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Bazel正确链接ICU外部依赖?构建测试遇符号缺失问题

M1 Mac下Bazel集成ICU依赖时符号缺失问题

环境

  • M1 Mac
  • Homebrew安装的Bazel
  • Xcode clang编译器
  • ICU 73.1版本,通过http_archive引入,使用其自带BUILD文件

现象

  • 可正常构建//:utils和//:utils_test目标
  • 运行bazel test //:utils_test时出现动态链接符号缺失错误
  • 构建//:app时出现链接阶段符号未定义错误

错误详情

测试执行错误(bazel test //:utils_test)

INFO: From Testing //:utils_test:
==================== Test output for //:utils_test:
dyld[15553]: symbol not found in flat namespace '__ZN6icu_738ByteSink15GetAppendBufferEiiPciPi'
================================================================================
Target //:utils_test up-to-date:
  bazel-bin/utils_test
INFO: Elapsed time: 0.275s, Critical Path: 0.20s
INFO: 2 processes: 2 darwin-sandbox.
INFO: Build completed, 1 test FAILED, 2 total actions
//:utils_test                                                            FAILED in 0.1s

构建app错误(bazel build //:app)

ERROR: /Users/default/Projects/icu-demo/BUILD:10:10: Linking app failed: (Exit 1): cc_wrapper.sh failed: error executing command (from target //:app) external/local_config_cc/cc_wrapper.sh @bazel-out/darwin_arm64-fastbuild/bin/app-2.params

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
Undefined symbols for architecture arm64:
  "icu_73::UnicodeString::toLower()", referenced from:
      ToLower(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&) in libutils.a(utils.o)
  "icu_73::ByteSink::GetAppendBuffer(int, int, char*, int, int*)", referenced from:
      vtable for icu_73::StringByteSink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>> in libutils.a(utils.o)
  "icu_73::ByteSink::Flush()", referenced from:
      vtable for icu_73::StringByteSink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>> in libutils.a(utils.o)
  "icu_73::ByteSink::~ByteSink()", referenced from:
      icu_73::StringByteSink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::StringByteSink(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*, int) in libutils.a(utils.o)
      icu_73::StringByteSink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>::~StringByteSink() in libutils.a(utils.o)
  "typeinfo for icu_73::ByteSink", referenced from:
      typeinfo for icu_73::StringByteSink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>> in libutils.a(utils.o)
  "vtable for icu_73::ByteSink", referenced from:
      icu_73::ByteSink::ByteSink() in libutils.a(utils.o)
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error in child process '/usr/bin/xcrun'. 1
Target //:app failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 0.168s, Critical Path: 0.11s
INFO: 2 processes: 2 internal.
FAILED: Build did NOT complete successfully

相关配置文件

WORKSPACE

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "icu",
    sha256 = "a457431de164b4aa7eca00ed134d00dfbf88a77c6986a10ae7774fc076bb8c45",
    strip_prefix = "icu",
    urls = ["https://github.com/unicode-org/icu/releases/download/release-73-1/icu4c-73_1-src.tgz"],
)

http_archive(
    name = "tinytest",
    sha256 = "71f366e680606e18268e6b9673a65c44c9e672f7356a61ffbcd3502c6a8eea0b",
    strip_prefix = "TinyTest-460c9492d927689b9db7f28d8742705dc0bbee62",
    urls = ["https://github.com/headhunter45/TinyTest/archive/460c9492d927689b9db7f28d8742705dc0bbee62.zip"],
)

BUILD

load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")

cc_library(
    name = "utils",
    srcs = ["utils.cpp"],
    hdrs = ["utils.h"],
    deps = ["@icu//source/common:platform"],
)

cc_binary(
    name = "app",
    srcs = ["app.cpp"],
    deps = ["utils"],
)

cc_test(
    name = "utils_test",
    srcs = ["utils_test.cpp"],
    deps = [
        "utils",
        "@tinytest",
    ],
)

utils.h

#include <string>

std::string ToLower(const std::string& text);

utils.cpp

#include "utils.h"

#include <string>

#include "unicode/unistr.h"

using icu::UnicodeString;
using std::string;

string ToLower(const string& text) {
  UnicodeString ustr = UnicodeString::fromUTF8(text);
  string result;
  ustr.toLower();
  ustr.toUTF8String(result);
  return result;
}

utils_test.cpp

#include "utils.h"

#include <string>
#include <tuple>

#include "tinytest.h"

using namespace TinyTest;
using namespace std;

int main(int argc, char* argv[]) {
  TestResults results;

  results += execute_suite(make_test_suite(
      "ToLower(const std::string&)", ToLower,
      {
          make_test("should get an empty string", (string) "", make_tuple("")),
          make_test("should get the same string", (string) "the same string",
                    make_tuple("the same string")),
          make_test("should get a lowercase string",
                    (string) "a lowercase string",
                    make_tuple("A lOwErCaSe StRiNg")),
      }));

  return results.failed() + results.errors();
}

app.cpp

#include <iostream>
#include <string>

#include "utils.h"

using namespace std;

int main(int argc, char* argv[]) {
  string original = "ThIs Is A nOrMaL sTrInG.";

  cout << "original:  " << original << endl;
  cout << "lowercase: " << ToLower(original) << endl;
  return 0;
}

解决方案

问题根源在于ICU依赖目标选择错误:当前utils仅依赖@icu//source/common:platform,该目标仅包含平台基础代码,未涵盖UnicodeString、ByteSink等核心功能的实现库。

修改BUILD文件中的utils库定义,替换为ICU核心字符处理库:

cc_library(
    name = "utils",
    srcs = ["utils.cpp"],
    hdrs = ["utils.h"],
    deps = [
        "@icu//source/common:icuuc",  # ICU核心字符处理库,包含所有核心功能实现
    ],
)

替换后验证:

  1. 执行bazel build //:app,构建成功
  2. 执行bazel test //:utils_test,测试运行成功

内容的提问来源于stack exchange,提问作者majinnaibu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 20:24:56