Emscripten 和 Ceres-Solver 的链接问题:“未定义的符号:ceres::CostFunction 的 typeinfo”

Linking Issue with Emscripten and Ceres-Solver: "undefined symbol: typeinfo for ceres::CostFunction"

提问人:aman 提问时间:8/30/2023 最后编辑:aman 更新时间:8/30/2023 访问量:47

问:

我正在做一个使用 Ceres-Solver 库的项目。使用常规 CMake 设置时,项目编译成功。但是,当我尝试使用 Emscripten 编译器编译它时,我遇到了链接问题。

我得到的错误是:

  em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libamd.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libamd.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libblas.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libblas.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libbtf.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libbtf.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libcamd.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libcamd.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libccolamd.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libccolamd.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libceres.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libceres.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libcholmod.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libcholmod.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libcolamd.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libcolamd.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libcxsparse.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libcxsparse.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libgflags.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libgflags.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libgpuqrengine.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libgpuqrengine.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libspex.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libspex.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libspqr.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libspqr.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libklu.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libklu.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libklu_cholmod.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libklu_cholmod.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libldl.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libldl.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libmongoose.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libmongoose.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/librbio.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/librbio.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libspqr_cuda.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libspqr_cuda.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/liblapack.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/liblapack.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libsuitesparseconfig.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libsuitesparseconfig.a: adding index [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libumfpack.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc]
    em++: warning: /rnd_ceres-solver/thirdparty/build/install/lib/libumfpack.a: adding index [-Wemcc]
    wasm-ld: error: CMakeFiles/simple_bundle_adjuster.dir/bundle_adjuster.cc.o: undefined symbol: typeinfo for ceres::CostFunction

另外,如何确保使用 emscripten 使档案是由 emar 而不是系统 ar 工具创建的?

重现步骤:

  1. 仅使用 emscripten 编译器从源代码构建 ceres-solver,所有依赖库也来自源代码。谷神星求解器安装

  2. 我现在正在尝试使用 Emscripten 和以下 shell 脚本构建它,该脚本设置 Emscripten 环境并执行和:emcmakemake

    #!/bin/bash
    echo "Setting up emsdk environment..."
    source ~/emsdk/emsdk_env.sh
    
    # Specify the directory where you want to create the build folder
    build_dir=build
    
    # Ensure we're in the same directory as the CMakeLists.txt file
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
    
    # Create the build directory if it doesn't exist
    mkdir -p "${script_dir}/${build_dir}"
    
    # Navigate into the build directory
    cd "${script_dir}/${build_dir}" || { echo "ERROR: Failed to navigate into build directory. Exiting..."; exit 1; }
    
    echo "Running emcmake and make..."
    emcmake cmake .. ; time make
    

CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)

project(simple_bundle_adjuster)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_definitions(-Wc++17-narrowing)

function(list_transform_prepend var prefix)
    set(temp "")
    foreach(f ${${var}})
        list(APPEND temp "${prefix}${f}")
    endforeach()
    set(${var} "${temp}" PARENT_SCOPE)
endfunction()

# Set the path to local packages
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/thirdparty/build/install")

include_directories("${CMAKE_SOURCE_DIR}/thirdparty/build/install/include")
include_directories("${CMAKE_SOURCE_DIR}/thirdparty/build/install/share/eigen3/cmake")
include_directories("${CMAKE_SOURCE_DIR}/thirdparty/build/install/include/eigen3")
# Manually specify the directory of Eigen3
set(Eigen3_DIR "${CMAKE_SOURCE_DIR}/thirdparty/build/install/share/eigen3/cmake")
# find_package(Eigen3 REQUIRED PATHS "${CMAKE_SOURCE_DIR}/thirdparty/build/install/share/eigen3/cmake")

set(AMDL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libamd.a")
set(BLASL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libblas.a")
set(BTF "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libbtf.a")
set(CAMDL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libcamd.a")
set(CCOLAMDL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libccolamd.a")
set(CERESL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libceres.a")
set(CHOLMODL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libcholmod.a")
set(COLAMDL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libcolamd.a")
set(CXSPARSEL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libcxsparse.a")
set(GFLAGS "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libgflags.a")
# set(GLOG "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libglog.dylib")
set(GPUQRENGINEL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libgpuqrengine.a")
set(SPEXL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libspex.a")
set(SPQRL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libspqr.a")
set(KLUL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libklu.a")
set(KLU_CHOLMODL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libklu_cholmod.a")
set(LDL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libldl.a")
set(MONGOOSE "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libmongoose.a")
set(RBIOL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/librbio.a")
set(SPQR_CUDA "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libspqr_cuda.a")
set(LAPACKL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/liblapack.a")
set(SuiteSparse_DEPENDENCY  "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libsuitesparseconfig.a")
set(UMFL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libumfpack.a")
set(CERESL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libceres.a")
# set(GRAPHBLASL "${CMAKE_SOURCE_DIR}/thirdparty/build/install/lib/libgraphblas.dylib")
# test

set(CERES_SOLVER_DEPENDENCIESL ${AMDL} ${BLASL} ${BTF} ${CAMDL} ${CCOLAMDL} ${CERESL} ${CHOLMODL} ${COLAMDL} ${CXSPARSEL} ${GFLAGS} ${GPUQRENGINEL} ${SPEXL} ${SPQRL} ${KLUL} ${KLU_CHOLMODL} ${LDL} ${MONGOOSE} ${RBIOL} ${SPQR_CUDA} ${LAPACKL} ${SuiteSparse_DEPENDENCY} ${UMFL} ${GRAPHBLASL})
list_transform_prepend(CERES_SOLVER_DEPENDENCIESL "") 
# set(CERES_SOLVER ${CERES_SOLVER_DEPENDENCIESL})

# Add source files
add_executable(simple_bundle_adjuster bundle_adjuster.cc)

# Link the libraries
target_link_libraries(simple_bundle_adjuster ${CERES_SOLVER_DEPENDENCIESL})

这会导致链接错误。

  • 我已经验证了链接过程中是否包含所有必要的库。
  • 我怀疑我需要传递一些 Emscripten 编译器标志,但我不确定哪些标志可以解决此问题。

相关代码:.cc

#include "ceres/ceres.h"

int main() {

    BALProblem bal_problem;

    if (!bal_problem.LoadData()) {
        std::cerr << "ERROR: unable to load data " << "\n";
        return 1;
    }

    const double* observations = bal_problem.observations();
    // Create residuals for each observation in the bundle adjustment problem. The
    // parameters for cameras and points are added automatically.
    ceres::Problem problem;
    for (int i = 0; i < bal_problem.num_observations(); ++i) {
        // Each Residual block takes a point and a camera as input and outputs a 2
        // dimensional residual. Internally, the cost function stores the observed
        // image location and compares the reprojection against the observation.
        ceres::CostFunction* cost_function =
            SnavelyReprojectionError::Create(observations[2 * i + 0],
                observations[2 * i + 1]);

        //ceres::LossFunction* loss_function = new ceres::TukeyLoss(10.0);      // MAH Robust method

        problem.AddResidualBlock(cost_function,
             NULL  /*squared loss */,
            bal_problem.mutable_camera_for_observation(i),
            bal_problem.mutable_point_for_observation(i));
            
    }
 }

我将不胜感激解决此问题的任何建议。谢谢。

cmake linker-errors emscripten ceres-solver

评论


答: 暂无答案