Skip to content

[bug] Abseil improper linkage when build_type=Debug #18167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
daviyan5 opened this issue Apr 23, 2025 · 0 comments
Open

[bug] Abseil improper linkage when build_type=Debug #18167

daviyan5 opened this issue Apr 23, 2025 · 0 comments
Assignees

Comments

@daviyan5
Copy link

Describe the bug

A while ago, I created issue #17993 to discuss linking issues when trying to cross-compile protobuf for the arm64 architecture of an Nvidia Jetson. At the end of the discussion, I was able to pinpoint the exact location of the problem: there is only a compilation error when the package is compiled with the build_type=Debug configuration. This time, I also brought a Dockerfile that creates an environment similar to the Jetson using QEMU so that the generated binary can be compiled and executed. I'm using podman, but the commands to run the container in docker should be very similar.

The error that appears when trying to compile the project is:

undefined reference to symbol '_ZN4absl12lts_2024072212log_internal21CheckOpMessageBuilder7ForVar2Ev'
build-conan-jetson/3rdparty/full_deploy/host/abseil/20240722.0/Debug/armv8/lib/libabsl_log_internal_check_op.so.2407.0.0: error adding symbols: DSO missing from command line

How to reproduce it

Here are all the files used in the project:

~/Documents/test$ tree
.
├── CMakeLists.txt
├── conanfile.py
├── Dockerfile
├── main.cpp
├── profiles
│   ├── jetson
│   └── x86
└── simple.proto

CMakeLists.txt:

cmake_minimum_required(VERSION 3.15)
project(Example)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_FLAGS "-g -Wall -Werror ${CMAKE_CXX_FLAGS}")
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)

find_package(Protobuf CONFIG REQUIRED)

protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS simple.proto)
add_library(simple_proto SHARED ${PROTO_SRCS})
target_link_libraries(simple_proto protobuf::protobuf)

install(TARGETS simple_proto DESTINATION lib)

add_executable(main main.cpp)
target_link_libraries(main PUBLIC simple_proto PRIVATE protobuf::protobuf)
target_include_directories(main PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

# ----- ***** ------
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
  set(protobuf_LIB_DIRS_ ${protobuf_LIB_DIRS_DEBUG})
  set(abseil_LIB_DIRS_ ${abseil_LIB_DIRS_DEBUG})
else()
  set(protobuf_LIB_DIRS_ ${protobuf_LIB_DIRS_RELEASE})
  set(abseil_LIB_DIRS_ ${abseil_LIB_DIRS_RELEASE})
endif()

file(GLOB PROTOBUF_OBJECTS
     ${protobuf_LIB_DIRS_}/*.so
     ${protobuf_LIB_DIRS_}/*.so.*)

file(GLOB ABSEIL_OBJECTS
     ${abseil_LIB_DIRS_}/*.so
     ${abseil_LIB_DIRS_}/*.so.*)

install(
  FILES
    ${PROTOBUF_OBJECTS} 
    ${ABSEIL_OBJECTS}
  DESTINATION lib)
# ----- ***** ------

install(TARGETS main DESTINATION bin)

conanfile.py:

from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain


class ExampleConan(ConanFile):
    name="example"
    version="0.1"
    settings="os", "compiler", "build_type", "arch"
    options = {
        "shared": [True, False]
    }
    default_options = {
        "shared": True
    }
    generators = "CMakeDeps"

    requires = "protobuf/5.27.0"
    tool_requires = "protobuf/5.27.0"

    def generate(self):
        tc = CMakeToolchain(self)
        tc.generate()

    def layout(self):
        cmake_layout(self)

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()
    
    def package(self):
        cmake = CMake(self)
        cmake.install()

x86 profile:

[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux

jetson profile:

[settings]
arch=armv8
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
 
[buildenv]
CC=aarch64-linux-gnu-gcc
CXX=aarch64-linux-gnu-g++
STRIP="aarch64-linux-gnu-strip"
OBJDUMP="aarch64-linux-gnu-objdump"
LD="aarch64-linux-gnu-ld"

main.cpp:

#include <iostream>
#include <string>

#include "simple.pb.h"


int main()
{
    MyMessage message;
    message.set_name("Hello, world!");

    std::string serialized;
    message.SerializeToString(&serialized);
    
    MyMessage new_message;
    new_message.ParseFromString(serialized);
    std::cout << "Deserialized: " << new_message.name() << std::endl;

    return 0;

}

simple.proto:

syntax = "proto3";

message MyMessage {
    string name = 1;
}

Dockerfile:

FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y gcc-aarch64-linux-gnu cmake
RUN apt update && apt install -y build-essential python3 python3-pip
RUN pip install conan
COPY profiles/x86 /root/.conan2/profiles/x86
COPY profiles/jetson /root/.conan2/profiles/jetson
WORKDIR ./test

The 'profile' files should go in a profiles directory on the current working directory. All the other files should be in the same directory.

Here are the compilation commands:

x86:
	rm -rf build 
	rm -rf stage/Debug/x86 
	conan build . -o *:shared=True -pr:h=x86 -pr:b=x86 --settings=build_type=Debug --build=missing 
	cmake --install build/Debug --prefix stage/Debug/x86
cross-jetson:
	rm -rf build
	rm -rf stage/Debug/aarch64 
	conan build . -o *:shared=True -pr:h=jetson -pr:b=x86 --settings=build_type=Debug --build=missing
	cmake --install build/Debug --prefix stage/Debug/aarch64
jetson:
	rm -rf build
	rm -rf stage/Debug/aarch64 
	conan build . -o *:shared=True -pr:h=jetson -pr:b=jetson --settings=build_type=Debug --build=missing 
	cmake --install build/Debug --prefix stage/Debug/aarch64

Running make jetson should be enough to reproduce the error.

To generate the docker image and run it, on Ubuntu:

sudo apt update
sudo apt install -y podman qemu-user-static binfmt-support
podman build -t ubuntu-arm64 --platform linux/arm64 . 
podman run --rm -it -v "$(pwd)":/test --arch=arm64 localhost/ubuntu-arm64

Then, inside the container:

make jetson

If you want to test cross-compilation instead of native compilation, simply change the container creation command to:

podman build -t ubuntu-amd64 --platform linux/amd64 . 
podman run --rm -it -v "$(pwd)":/test --arch=amd64 localhost/ubuntu-amd64

And run:

make cross-jetson
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants