Calling a shared library in C++ results in ld.lld: error: undefined symbol:

928 views
Skip to first unread message

Simon Wentley

unread,
Jan 5, 2023, 4:49:15 PM1/5/23
to gn-dev
Can anyone suggest why I am getting undefined symbol? thanks!

Using C++, my goal is to call a function from my own shared library from within Chromium.

When I compile, I get 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.
   :ubuntu:~/chromium/src>


For my shared library, outside Chroimium I created a C++ source file my_class.cpp


    ubuntu:~/learn> cat 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 << ".";
    }

For my shared library, outside Chromium I created a C++ header file my_class.h

    :ubuntu:~/learn> cat 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

For my shared library, outside Chromium I created a CMakeLists.txt

    :ubuntu:~/learn> cat CMakeLists.txt
    cmake_minimum_required(VERSION 3.15)
    
    project(MyProject)
    
    add_library(myexample SHARED my_class.cpp)
    
    :ubuntu:~/learn>


In the Chromium third_party directory named "dude4" I created a directory so Chromium can access my shared library:

    third_party % find dude4
    dude4
    dude4/BUILD.gn
    dude4/include
    dude4/include/my_class.h
    third_party % 

The BUILD.gn contains:


    config("my_class_import") {
      include_dirs = ["include"]
      libs = ["/home/ubuntu/learn/build/libmyexample.so"]
    }
    
    group("my_class") {
      public_configs = [":my_class_import"]
    }

I want to call my shared library from within Chromium, so I add the following lines at the bottom of the header lines in delegated_frame_host.cc

    #include "third_party/dude4/include/my_class.h"
    
    //using namespace N;
    bool my_class::initialised = false;
    int my_class::some_number = 999;

And also in delegated_frame_host.cc I add some code to call my shared library:

    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();
    (code of this function continues.......)



K. Moon

unread,
Jan 5, 2023, 4:58:51 PM1/5/23
to Simon Wentley, gn-dev
Did you add a dependency from the target that builds content/browser/renderer_host/delegated_frame_host.cc to the target that defines your library? If not, it won't be linked.

Simon Wentley

unread,
Jan 5, 2023, 5:02:22 PM1/5/23
to gn-dev, gn-dev
Hello thanks for your reply.

I'm not sure actually.  Can I ask would you mind giving detail on exactly what I would need to change to try this?  I'm a chromium and C++ beginner.

Thanks!

K. Moon

unread,
Jan 5, 2023, 5:14:53 PM1/5/23
to Simon Wentley, gn-dev
A full explanation would be involved, but you could start reading here:

Simon Wentley

unread,
Jan 5, 2023, 5:17:40 PM1/5/23
to gn-dev, km...@chromium.org, gn-dev, Simon Wentley
OK I'll read that.  Anything further you can do to steer me in the right direction would be appreciated as I have spent 5 days straight so far trying everything I can to resolve it, directions and hints greatly appreciated!

K. Moon

unread,
Jan 5, 2023, 5:23:20 PM1/5/23
to Simon Wentley, gn-dev
I think once you understand how the target and dependency concepts work, then the rest will be clearer. Until then, I don't think any explanation would make much sense.

Simon Wentley

unread,
Jan 5, 2023, 8:02:44 PM1/5/23
to gn-dev, km...@chromium.org, gn-dev, Simon Wentley
Thank you! I changed line 3185 of src/content/browser/BUILD.gn

from
deps += [ "//ui/compositor" ]

to
deps += [ "//ui/compositor", "//third_party/dude4:my_class" ]

and it appears to work so far - the linker error has gone anyway.

Thanks heaps I was just totally stuck on that for days - it was painful.

K. Moon

unread,
Jan 6, 2023, 1:19:03 PM1/6/23
to Simon Wentley, gn-dev
Glad you were able to figure it out!

Simon Wentley

unread,
Jan 6, 2023, 2:21:18 PM1/6/23
to gn-dev, km...@chromium.org, gn-dev, Simon Wentley
To explain, this is in fact the third time I posted this question, the first two went to chromium-dev where they did not appear for a long time, maybe days, I was not sure why not, maybe being moderated, but in the end I think this was the more appropriate list to post to thanks and apologies for the cross posting.
Reply all
Reply to author
Forward
0 new messages