使用 boost asio waitable_operators 在废弃部分定义链接器错误

问题描述 投票:0回答:1

包含有关您目标的详细信息

我想在 Docker 容器中构建这个项目

描述预期和实际结果

在 docker 容器中以发布模式构建时,链接器报告错误:

Deploying '<unknown> Dockerfile: Dockerfile'…
Building image…
Preparing build context archive…
[==================================================>]151/151 files
Done

Sending build context to Docker daemon…
[==================================================>] 145.5kB
Done

Step 1/10 : FROM conanio/gcc13-ubuntu16.04
 ---> 4ed52a5da755
Step 2/10 : COPY src /home/conan/cxx_template/src
 ---> Using cache
 ---> 4f985f400a74
Step 3/10 : COPY CMakeLists.txt /home/conan/cxx_template
 ---> Using cache
 ---> 428b77440f02
Step 4/10 : COPY conanfile.py /home/conan/cxx_template
 ---> Using cache
 ---> baf0737e4cc9
Step 5/10 : COPY main.cxx /home/conan/cxx_template
 ---> Using cache
 ---> ba6f9aed868f
Step 6/10 : WORKDIR /home/conan/cxx_template
 ---> Using cache
 ---> 88ed7f05cf32
Step 7/10 : RUN sudo chown -R conan /home/conan  && conan remote add artifactory http://195.128.100.39:8081/artifactory/api/conan/conan-local && conan install . --output-folder=build --settings build_type=Release  --settings compiler.cppstd=gnu20 --build=missing
 ---> Using cache
 ---> 3ca072904555
Step 8/10 : WORKDIR /home/conan/cxx_template/build
 ---> Using cache
 ---> 053ee0731c7e
Step 9/10 : RUN cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -D CMAKE_BUILD_TYPE=Release
 ---> Using cache
 ---> c57340482eed
Step 10/10 : RUN cmake --build .
 ---> Running in 0bf73846ac2f
Scanning dependencies of target cxx_template
[ 25%] Building CXX object src/CMakeFiles/cxx_template.dir/hello.cxx.o
/home/conan/cxx_template/src/hello.cxx: In function 'boost::asio::awaitable<void> helloWorld()':
/home/conan/cxx_template/src/hello.cxx:11:1: warning: no return statement in function returning non-void [-Wreturn-type]
   11 | }
      | ^
[ 50%] Linking CXX static library libcxx_template.a
[ 50%] Built target cxx_template
Scanning dependencies of target run_server
[ 75%] Building CXX object CMakeFiles/run_server.dir/main.cxx.o
[100%] Linking CXX executable run_server
`_ZN5boost4asio12experimental19awaitable_operatorsaaEPZNS2_aaINS0_15any_io_executorEEENS0_9awaitableIvT_EES7_S7_E108_ZN5boost4asio12experimental19awaitable_operatorsaaINS0_15any_io_executorEEENS0_9awaitableIvT_EES7_S7_.Frame.destroy' referenced in section `.rodata.cst8' of src/libcxx_template.a(hello.cxx.o): defined in discarded section `.text._ZN5boost4asio12experimental19awaitable_operatorsaaEPZNS2_aaINS0_15any_io_executorEEENS0_9awaitableIvT_EES7_S7_E108_ZN5boost4asio12experimental19awaitable_operatorsaaINS0_15any_io_executorEEENS0_9awaitableIvT_EES7_S7_.Frame.destroy[_ZN5boost4asio12experimental19awaitable_operatorsaaINS0_15any_io_executorEEENS0_9awaitableIvT_EES7_S7_]' of src/libcxx_template.a(hello.cxx.o)
`_ZN5boost4asio6detail20co_spawn_entry_pointEPZNS1_20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm0ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEEE464_ZN5boost4asio6detail20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm0ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEE.Frame.destroy' referenced in section `.rodata.cst8' of src/libcxx_template.a(hello.cxx.o): defined in discarded section `.text._ZN5boost4asio6detail20co_spawn_entry_pointEPZNS1_20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm0ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEEE464_ZN5boost4asio6detail20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm0ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEE.Frame.destroy[_ZN5boost4asio6detail20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm0ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEE]' of src/libcxx_template.a(hello.cxx.o)
`_ZN5boost4asio6detail20co_spawn_entry_pointEPZNS1_20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm1ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEEE464_ZN5boost4asio6detail20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm1ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEE.Frame.destroy' referenced in section `.rodata.cst8' of src/libcxx_template.a(hello.cxx.o): defined in discarded section `.text._ZN5boost4asio6detail20co_spawn_entry_pointEPZNS1_20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm1ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEEE464_ZN5boost4asio6detail20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm1ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEE.Frame.destroy[_ZN5boost4asio6detail20co_spawn_entry_pointINS0_12experimental6detail25parallel_group_op_handlerILm1ENS3_18wait_for_one_errorENS1_26awaitable_async_op_handlerIFvSt5arrayImLm2EENSt15__exception_ptr13exception_ptrESB_ENS0_15any_io_executorEEEJNS0_24deferred_async_operationIFvSB_ENS1_17initiate_co_spawnISD_EEJNS1_21awaitable_as_functionIvSD_EEEEESL_EEESD_SK_EENS0_9awaitableINS1_28awaitable_thread_entry_pointET0_EEPNSN_IvSP_EENS1_14co_spawn_stateIT_SP_T1_vEE]' of src/libcxx_template.a(hello.cxx.o)
collect2: error: ld returned 1 exit status
CMakeFiles/run_server.dir/build.make:84: recipe for target 'run_server' failed
make[2]: *** [run_server] Error 1
CMakeFiles/Makefile2:76: recipe for target 'CMakeFiles/run_server.dir/all' failed
make[1]: *** [CMakeFiles/run_server.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
Error response from daemon: The command '/bin/sh -c cmake --build .' returned a non-zero code: 2
Failed to deploy '<unknown> Dockerfile: Dockerfile': Can't retrieve image ID from build stream

当我不在 docker 容器中构建此项目时,它会在发布和调试中构建。
当我在 docker 容器中以调试模式构建此项目时,它会构建。
当我在 docker 容器中以发布模式构建此项目时,它不会构建,并且链接器报告上述错误。

我希望它能够在容器内和容器外的发布和调试中构建。 或者不要在 docker 容器之外和 docker 容器中构建版本。

描述您尝试过的内容
我减少了我的实际项目并创建了一个“最小的、可重现的示例”。
我在互联网上搜索“在丢弃的部分中定义”,但我不明白我的代码到底出了什么问题以及如何调试/修复这个问题。

如何重现:

git clone -b defined_in_discarded_section  https://github.com/werto87/cxx_template.git && cd cxx_template && docker build .

EDIT1(对 Alan Birtles 的第一条评论做出反应)试图使问题自成一体,而不是依赖外部链接

项目

项目结构:

[walde@laptop cxx_template]$ tree
.
├── CMakeLists.txt
├── conanfile.py
├── Dockerfile
├── main.cxx
└── src
    ├── CMakeLists.txt
    ├── hello.cxx
    └── hello.hxx

CMakeLists.txt

cmake_minimum_required(VERSION 3.15.7)
set(CMAKE_CXX_STANDARD 20)
project(myproject)
add_subdirectory(src)
add_executable(run_server main.cxx)
target_link_libraries(run_server cxx_template)

conanfile.py

from conan import ConanFile


class Project(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeToolchain", "CMakeDeps"

    def configure(self):
        self.options["boost"].header_only = True

    def requirements(self):
        self.requires("boost/1.84.0")

Dockerfile

FROM conanio/gcc13-ubuntu16.04

COPY src /home/conan/cxx_template/src
COPY CMakeLists.txt /home/conan/cxx_template
COPY conanfile.py /home/conan/cxx_template
COPY main.cxx /home/conan/cxx_template


WORKDIR /home/conan/cxx_template

RUN sudo chown -R conan /home/conan && conan install . --output-folder=build --settings build_type=Release  --settings compiler.cppstd=gnu20 --build=missing

WORKDIR /home/conan/cxx_template/build

RUN cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -D CMAKE_BUILD_TYPE=Release

RUN cmake --build .

main.cxx

#include "src/hello.hxx"
#include <boost/asio.hpp>
#include <boost/asio/experimental/awaitable_operators.hpp>
int
main ()
{
  using namespace boost::asio::experimental::awaitable_operators;
  auto ioContext = boost::asio::io_context{};
  boost::asio::ip::tcp::socket socket (ioContext);
  auto test = socket.async_connect ({}, boost::asio::use_awaitable) && socket.async_connect ({}, boost::asio::use_awaitable);
  abc ();
}

src/CMakeLists.txt

add_library(cxx_template hello.cxx)
find_package(Boost)
target_link_libraries(cxx_template PUBLIC
        pthread
        boost::boost
        )
target_include_directories(cxx_template INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
        $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>)
target_compile_features(cxx_template PUBLIC cxx_std_20)

src/hello.cxx

#include "hello.hxx"
#include <boost/asio.hpp>
#include <boost/asio/experimental/awaitable_operators.hpp>

boost::asio::awaitable<void> helloWorld() {
  using namespace boost::asio::experimental::awaitable_operators;
  auto ioContext = boost::asio::io_context{};
  boost::asio::ip::tcp::socket socket(ioContext);
  auto test = socket.async_connect({}, boost::asio::use_awaitable) &&
              socket.async_connect({}, boost::asio::use_awaitable);
}

int abc() { return 42; }

src/hello.hxx

#pragma once
#include <boost/asio/awaitable.hpp>
int abc();

docker gcc版本

conan@4ebb90d4c85a:~/matchmaking_proxy/build$ gcc --version
gcc (GCC) 13.1.0

EDIT2:删除不需要在 docker 文件中添加远程

c++ gcc linker boost-asio ld
1个回答
0
投票

因此,有两个关键组成部分:

  • 两个独立的链接器对象(主程序和库)实例化一组模板实例
  • 图书馆里的那本因未使用而被丢弃

重现这一点的关键是延迟异步操作的确切实例在主程序和库实现细节中都匹配。对我来说,这很可能是编译器问题。

我重新编写了 main/lib 源代码以删除非典型的内容:

  • 无论如何,coro 缺少返回声明,所以调用了 UB
  • 没有实际等待的并行组延迟操作,我担心这会导致比其他方式更多的符号被丢弃,所以我添加了这些。
  • 文件

    main.cxx

     #include "src/hello.hxx"
     #include <boost/asio.hpp>
     #include <boost/asio/experimental/awaitable_operators.hpp>
    
     int main() {
         namespace asio = boost::asio;
         using asio::ip::tcp;
         using namespace asio::experimental::awaitable_operators;
    
         asio::io_context ioc;
         tcp::socket      s(ioc);
    
         auto token = asio::use_awaitable;
         co_spawn(
             ioc,
             (s.async_connect({}, token) && s.async_connect({}, token)),
             asio::detached);
         abc();
     }
    
  • 文件

    src/hello.cxx

     #include "hello.hxx"
     #include <boost/asio.hpp>
     #include <boost/asio/experimental/awaitable_operators.hpp>
    
     boost::asio::awaitable<void> helloWorld() {
         namespace asio = boost::asio;
         using asio::ip::tcp;
         using namespace asio::experimental::awaitable_operators;
    
         tcp::socket s(co_await asio::this_coro::executor);
         auto token = asio::use_awaitable;
         co_await (s.async_connect({}, token) && s.async_connect({}, token));
    
         co_return;
     }
    
     int abc() { return 42; }
    

验证假设

如果您将两个翻译单元之一中的标记更改为例如

auto token = as_tuple(asio::use_awaitable);

链接者满意

解决方法

就像我说的,我认为这可能是与 c++20 协程机制有关的编译器错误。但是,由于创建自己的令牌确实可以解决这个问题,因此我会考虑重复实现:

struct my_token_t : boost::asio::use_awaitable_t<> { } static inline constexpr my_token;
template <typename... Sigs>
struct boost::asio::async_result<my_token_t, Sigs...> : async_result<use_awaitable_t<>, Sigs...> {};

现在避免了冲突:https://github.com/werto87/cxx_template/pull/1

哎呀。我说得太早了。我不小心误解了构建输出,可能忘记了

hello.cxx
没有保存。看来有问题的模板实例与令牌更间接相关,并且必须复制更多内容才能隐藏问题。我会看看我是否能做到这一点。仍然考虑报告编译器问题,或者如果您无法获得关注,请在 https://github.com/chriskohlhoff/asio/issues

进行报告

更简单的缓解方法

甚至没有解决方法:您可以通过将它们设置为文件静态来完全避免发出冲突的符号。例如。使

helloWorld
静态或将其包含在匿名命名空间中:


namespace /*anon*/ {
    /*static*/ boost::asio::awaitable<void> helloWorld() {
        namespace asio = boost::asio;
        using asio::ip::tcp;
        using namespace asio::experimental::awaitable_operators;

        tcp::socket s(co_await asio::this_coro::executor);
        auto token = asio::use_awaitable;
        co_await (s.async_connect({}, token) && s.async_connect({}, token));

        co_return;
    }
}

这会在您的容器中构建。

© www.soinside.com 2019 - 2024. All rights reserved.