在Chromium中调用自定义共享库出现未定义符号错误求助
Chromium编译时出现未定义符号
my_class::print_a_dot()的问题排查 问题背景
在Chromium中通过C++调用外部自定义共享库的函数,编译时触发链接错误:ld.lld: error: undefined symbol: my_class::print_a_dot()
编译错误详情
ubuntu:~/chromium/src> autoninja -C out/Default chrome ninja: Entering directory `out/Default' [16888/17733] SOLINK ./libcontent.so FAILED: libcontent.so libcontent.so.TOC python3 "../../build/toolchain/gcc_solink_wrapper.py" --readelf="../../third_party/llvm-build/Release+Asserts/bin/llvm-readelf" --nm="../../third_party/llvm-build/Release+Asserts/bin/llvm-nm" --sofile="./libcontent.so" --tocfile="./libcontent.so.TOC" --output="./libcontent.so" -- ../../third_party/llvm-build/Release+Asserts/bin/clang++ -shared -Wl,-soname="libcontent.so" -Werror -fuse-ld=lld -Wl,--fatal-warnings -Wl,--build-id -fPIC -Wl,-z,noexecstack -Wl,-z,relro -Wl,--color-diagnostics -Wl,--undefined-version -Wl,--no-call-graph-profile-sort -m64 -no-canonical-prefixes -Wl,--gdb-index -rdynamic -Wl,-z,defs -Wl,--as-needed -nostdlib++ --sysroot=../../build/linux/debian_bullseye_amd64-sysroot -Wl,-rpath=\$ORIGIN -o "./libcontent.so" @"./libcontent.so.rsp" ld.lld: error: undefined symbol: my_class::print_a_dot() >>> referenced by delegated_frame_host.cc:457 (../../content/browser/renderer_host/delegated_frame_host.cc:457) >>> obj/content/browser/browser/delegated_frame_host.o:(content::DelegatedFrameHost::DidCopyStaleContent(std::Cr::unique_ptr<viz::CopyOutputResult, std::Cr::default_delete<viz::CopyOutputResult>>)) clang++: error: linker command failed with exit code 1 (use -v to see invocation) [16913/17733] CXX irt_x64/obj/ipc/mojom/ipc.mojom.o ninja: build stopped: subcommand failed.
自定义共享库详情(~/learn目录)
1. my_class.cpp
#include <stdio.h> #include <iostream> #include <memory> #include <stdint.h> #include "my_class.h" extern void my_class::print_a_dot() { std::cout << "."; }
2. my_class.h
#ifndef MY_CLASS_H // To make sure you don't declare the function more than once by including the header multiple times. #define MY_CLASS_H class my_class { public: static int some_number; static bool initialised; void print_a_dot(); int init_encoder(); }; #endif
3. CMakeLists.txt
cmake_minimum_required(VERSION 3.15) project(MyProject) add_library(myexample SHARED my_class.cpp)
Chromium中的配置(third_party/dude4目录)
目录结构
third_party % find dude4 dude4 dude4/BUILD.gn dude4/include dude4/include/my_class.h
BUILD.gn内容
config("my_class_import") { include_dirs = ["include"] libs = ["/home/ubuntu/learn/build/libmyexample.so"] } group("my_class") { public_configs = [":my_class_import"] }
Chromium代码中的调用(delegated_frame_host.cc)
头部引用
#include "third_party/dude4/include/my_class.h" bool my_class::initialised = false; int my_class::some_number = 999;
函数内调用逻辑
void DelegatedFrameHost::DidCopyStaleContent( std::unique_ptr<viz::CopyOutputResult> result) { // host may have become visible by the time the request to capture surface is // completed. my_class mc; mc.initialised = false; std::cout << "my_class::some_number: "; std::cout << my_class::some_number << std::endl; my_class::some_number = 888; std::cout << "mc.some_number: "; std::cout << mc.some_number << std::endl; my_class nc; std::cout << "nc.some_number: "; std::cout << nc.some_number << std::endl; if (mc.initialised == false) { std::cout << "initialising encoder" << std::endl; mc.initialised = true; } mc.print_a_dot(); // 后续代码... }
错误原因分析及解决步骤
核心原因
- 成员函数定义语法错误:
my_class.cpp中extern void my_class::print_a_dot()的写法不符合C++类成员函数的定义规范,extern关键字在这里是多余的,会导致编译器无法正确识别这是类的成员函数实现,最终生成的共享库中缺少my_class::print_a_dot()的有效符号。 - 链接依赖未正确传递:Chromium的GN构建系统中,
group目标本身不会主动将依赖的库链接到最终目标,需要确保libcontent.so对应的构建目标(如content/browser:browser)明确添加对third_party/dude4:my_class的依赖,否则链接器不会去查找指定的共享库。
修复步骤
步骤1:修正共享库的函数定义
修改my_class.cpp,去掉多余的extern关键字:
#include <stdio.h> #include <iostream> #include <memory> #include <stdint.h> #include "my_class.h" void my_class::print_a_dot() { std::cout << "."; }
重新编译共享库:
cd ~/learn mkdir -p build && cd build cmake .. && make
步骤2:确保Chromium目标正确依赖自定义库
找到content/browser/BUILD.gn中构建libcontent.so的目标(通常是source_set("browser")或shared_library("content")),在其deps列表中添加"//third_party/dude4:my_class":
source_set("browser") { # 其他已有配置... deps = [ # 已有依赖项... "//third_party/dude4:my_class", ] }
步骤3:重新编译Chromium
autoninja -C out/Default chrome
内容的提问来源于stack exchange,提问作者Duke Dougal
相关产品推荐
相关产品推荐

