emscripten链接全局命名符号多重定义
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了emscripten链接全局命名符号多重定义相关的知识,希望对你有一定的参考价值。
我有一个c ++ CMAKE(版本3.10.2 -std = c ++ 17)项目,我可以编译该项目并与购买的gcc和clang链接。购买它们会产生可以按预期工作的目标二进制文件。最近,我决定尝试添加另一个目标,即webassembly。该项目正在按预期进行编译,但是当执行EMscripten构建时,即在链接阶段,出现以下错误:
Elapsed time: 1 s. (time), 0.002241 s. (clock)
[100%] Linking CXX executable wasmExec.js
cd /Projects/time/time.cpp/build/src/wasm && /usr/bin/cmake -E cmake_link_script CMakeFiles/wasmExec.dir/link.txt --verbose=1
/Projects/emscripten/emsdk/emscripten/1.38.12/em++ -s WASM=1 -s NO_EXIT_RUNTIME=1 -s VERBOSE=1 --pre-js /Projects/time/time.cpp/src/wasm/preModule.js -s DEMANGLE_SUPPORT=1 -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0 @CMakeFiles/wasmExec.dir/objects1.rsp -o wasmExec.js @CMakeFiles/wasmExec.dir/linklibs.rsp
error: Linking globals named '_ZTVN9timeproto3time8defaults20TimeDefaultParametersE': symbol multiply defined!
WARNING:root:Note: Input file "@/tmp/tmpUeJ6zc.response" did not exist.
ERROR:root:Failed to run llvm optimizations:
当我这样做
c++filt _ZTVN9timeproto3time8defaults20TimeDefaultParametersE
我得到
vtable for timeproto::time::defaults::TimeDefaultParameters
来自Stackoverflow的另一个答案,即
Possible reasons for symbol multiply defined other than 'extern'
我确实知道我再定义一次该类,但是我的问题是我无法找到第二个定义出错的地方。在上一个答案中,此人有提示,即cpp文件,在该文件中他犯了这个错误,但就我而言,管教者并不那么慷慨。
此类在许多文件中的代码库中广泛使用,并且经过长时间的手动搜索,我无法找到任何至少可以使我指向第二个定义的位置的东西。因此,我希望有人可以帮助我解决以下问题
1)如何进一步排除故障,以查找确切地在哪里发生了该类的第二个定义,可能是gcc或clang的标志?2)为什么仅当我尝试编译/构建webassmbly目标时才会显示此错误。常规的Linux64构建目标为successefull,并且测试也正常进行。
3)我正在使用以下“ add_definitions”来运行cmake,即
if(UNIX)
add_definitions(" -pedantic -pedantic-errors -W ")
add_definitions(" -Wall -Wextra -Werror -Wshadow -Wnon-virtual-dtor ")
add_definitions(" -v ")
# add_definitions(" -Worl-style-cast -Wcast-align ")
# add_definitions(" -Wunused -Woverloaded-virtual ")
add_definitions(" -g ")
endif(UNIX)
如果TimeDefaultParameters已经定义了很多,那么一次不应该对上面的“ add_definitions”进行linux构建不抱怨吗?
这里是TimeDefaultParameters.cpp下面的代码。这是一个非常简单的文件,不包含任何对象,而是具有43个“ static const uint32_t”变量。
#include "TimeDefaultParameters.h"
namespace timeproto::time::defaults
{
TimeDefaultParameters::TimeDefaultParameters() {
}
TimeDefaultParameters::~TimeDefaultParameters() {
}
const uint32_t TimeDefaultParameters::SIGNED_SHORT_MAX_VALUE = 32767;
.... (another 42 static const uint32_t)
}
和头文件TimeDefaultParameters.h:
#ifndef _TIME_DEFAULT_PARAMETERS_
#define _TIME_DEFAULT_PARAMETERS_
#include <stdint.h>
namespace timeproto::time::defaults
{
class TimeDefaultParameters final
{
public:
explicit TimeDefaultParameters();
virtual ~TimeDefaultParameters();
static const uint32_t SIGNED_SHORT_MAX_VALUE;
.....
.... (another 42 static const uint32_t)
};
}
#endif //#ifndef _TIME_DEFAULT_PARAMETERS_
在cmake中,我已设置了我的目标属性,例如:
set_target_properties(wasmExec PROPERTIES LINK_FLAGS "-s WASM=1 -s NO_EXIT_RUNTIME=1 -s VERBOSE=1 --pre-js /Projects/time/time.cpp/src/wasm/preModule.js -s DEMANGLE_SUPPORT=1 -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0" )
这是我如何调用cmake来从构建目录中进行构建
emconfigure cmake -DCMAKE_BUILD_TYPE=Emscripten -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=/Projects/emscripten/emsdk/emscripten/1.38.12/cmake/Modules/Platform/Emscripten.cmake ../
make -j8
任何想法都将不胜感激。
添加日期:2020年1月5日
我能够找到解决此问题的方法,但是我仍然对错误的性质提出了一些疑问。
所讨论的类是动态创建和加载的档案的一部分,即我在CMAKE部分中使用的此库“ set(LIB_TYPE SHARED)”。这是完整示例,说明cmake如何生成该存档,即CMakeLists.txt。
set( TIME_DEFAULTS_SRC
...
TimeDefaultParameters.h TimeDefaultParameters.cpp
...
)
set(LIB_TYPE STATIC)
#set(LIB_TYPE SHARED)
add_library(time_defaults ${LIB_TYPE} ${TIME_DEFAULTS_SRC} )
target_include_directories(time_defaults PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/")
我已经从动态更改为静态,并且我能够创建wasm而未显示任何错误。在编译期间,我还看到了在编译过程之间的某个警告,即:
WARNING:root:When Emscripten compiles to a typical native suffix for shared libraries (.so, .dylib, .dll) then it emits an LLVM bitcode file. You should then compile that to an emscripten SIDE_MODULE (using that flag) with suffix .wasm (for wasm) or .js (for asm.js). (You may also want to adapt your build system to emit the more standard suffix for a file with LLVM bitcode, '.bc', which would avoid this warning.)
此警告现在已消失。但是,很容易监督类似的事情,尤其是在编译过程花费很长时间的情况下。但是我的理解是,第一个错误消息告诉我们,“看起来您已经在代码中对某些符号进行了重复定义,请找到位置并确保该类仅定义一次”。那正是我正在做的事情,即在代码库中搜索重复的定义。因此,现在的问题是:为什么emscripten在动态链接方面存在问题,即我知道它已得到正式支持,即
https://webassembly.org/docs/dynamic-linking/
这是错误的根源,还是其他原因?为什么当我更改为静态时此错误消失。我可以通过简单地更改库类型来重现它!
我想我已经在这里找到了答案
因此,在我的情况下,解决方案是在CMAKE文件中查找动态添加了库的事件,并将其更改为静态链接,即。
#set(LIB_TYPE SHARED)
set(LIB_TYPE STATIC)
以上是关于emscripten链接全局命名符号多重定义的主要内容,如果未能解决你的问题,请参考以下文章