1

我从头开始,并遵循以下主要步骤:

1.构建并安装交叉编译器工具链(主机Linux,目标Win64):

获取此MXE 版本,仅更改plugins/gcc6/gcc6-overlay.mk

$(PKG)_VERSION  := 6.3.0
$(PKG)_CHECKSUM := f06ae7f3f790fbf0f018f6d40e844451e6bc3b7bc96e128e63b09825c1f8b29f

然后很简单(只需要一些时间,make --jobs=X JOBS=Y用来加速):

setenv MXE_SRC /path/to/where/you/extracted/mxe

cd $MXE_SRC
make MXE_TARGETS='x86_64-w64-mingw32.shared x86_64-w64-mingw32.static' MXE_PLUGIN_DIRS=plugins/gcc6 pthreads
setenv PATH $MXE_SRC/usr/bin:$PATH

2. 交叉编译和安装SystemC 2.3.3 库

这同样简单(但要快得多!):

setenv SYSTEMC_SRC                  /path/to/where/you/extracted/systemc/
setenv SYSTEMC_STATICTOOLCHAIN_DEST /this/is/your/choice

cd $SYSTEMC_SRC
./configure --prefix=$SYSTEMC_STATICTOOLCHAIN_DEST --host=x86_64-w64-mingw32.static
make install

3. 构建一个简单的可执行文件

写几行代码sc_main.cpp

#include "systemc.h"

int sc_main (int argc, char* argv[])
{
  sc_clock clk("CLOCK", 1, SC_NS, 0.5);
  sc_start();
  return 0;
}

现在通过最后一步进行构建:

x86_64-w64-mingw32.static-g++ sc_main.cpp -I$SYSTEMC_STATICTOOLCHAIN_DEST/include -L$SYSTEMC_STATICTOOLCHAIN_DEST/lib-mingw64 -lsystemc

我得到一大堆

libsystemc.a(sc_prim_channel.o):sc_prim_channel.cpp:(.text+0x44): undefined reference to `__imp_pthread_mutex_unlock'

(以及相同的变体)。

谁能重现并解释发生了什么?

当 SystemCconfigure完成时,它清楚地表明它不会使用 Posix 线程,而是使用 WinFiber,所以看到这些未解决的对 phread 的依赖关系我有点惊讶(为了记录,-lpthread在命令行末尾添加仍然会产生结果相同)

4. 以不同方式构建 SystemC 库的奖励实验

如果我使用本机 Win64 工具链构建 SystemC 库,然后使用相同的命令行构建我的可执行文件:

 setenv SYSTEMC_NATIVETOOLCHAIN_DEST /path/to/systemc/libraries/built/with/native/toolchain
 x86_64-w64-mingw32.static-g++ sc_main.cpp -I$SYSTEMC_NATIVETOOLCHAIN_DEST/include -L$SYSTEMC_NATIVETOOLCHAIN_DEST/lib-mingw64 -lsystemc

然后一切正常,正如预期的那样。

cmake此外,如果我使用而不是交叉编译和安装 SystemC 库configure

cd $SYSTEMC_SRC
mkdir build && cd build && x86_64-w64-mingw32.static-cmake .. -DBUILD_SHARED_LIBS=OFF -DCMAKE_CXX_STANDARD=14 -DINSTALL_TO_LIB_TARGET_ARCH_DIR=ON -DCMAKE_INSTALL_PREFIX=$SYSTEMC_STATICTOOLCHAIN_DEST
make install

x86_64-w64-mingw32.static-g++ sc_main.cpp -I$SYSTEMC_STATICTOOLCHAIN_DEST/include -L$SYSTEMC_STATICTOOLCHAIN_DEST/lib-mingw64 -lsystemc

然后,正如预期的那样,一切都运行良好。

我怀疑交叉编译时没有正确生成 SystemC 库。任何人都可以确认/否认吗?

4

2 回答 2

0

这不会是一个正确的答案,但至少我可以描述导致问题的端到端机制。我对 MingW、winpthread 等的所有复杂性还不够熟悉……无法准确地说出谁做错了,但我会把它留给专家 ;-)

所以这一切都从 SystemC 开始,configure它生成 Makefiles 配方定义DLL_EXPORT. 乍一看,定义 似乎很合理DLL_EXPORT,因为目标是建立一个库。

但实际上,DLL_EXPORT在 SystemC 的代码中没有引用任何地方,所以它的意图不是很清楚(事实上,cmake基于 SystemC 的流程没有定义它)。但是,如果我相信评论configure,那是有充分理由的某种黑客行为。

接下来,随着 SystemC 源文件被编译,mingw-w64-libraries/winpthreads/include/pthread.h在某些时候被包含(通过sc_host_mutex.h<mutex>)。

此时编译器会看到以下内容:

#if defined DLL_EXPORT
#      ifdef IN_WINPTHREAD
#            define WINPTHREAD_API __declspec(dllexport)
#      else
#            define WINPTHREAD_API __declspec(dllimport)
#      endif
#else
#      define WINPTHREAD_API
#endif

mingw-w64-libraries/winpthreads/include/sched.h请注意,和中有类似的代码mingw-w64-libraries/winpthreads/include/semaphore.h

假设IN_WINPTHREAD没有定义(我猜除了在构建 libwinpthread.dll 时总是如此),从 SystemC 库对 pthread API 的调用被声明为“dllimport”,最终导致臭名昭著:

libsystemc.a(sc_prim_channel.o):sc_prim_channel.cpp:(.text+0x44): undefined reference to `__imp_pthread_mutex_unlock'
  

我想知道 mingw-w64 标头的意图是否有点不同,可能类似于:

#ifdef IN_WINPTHREAD
#    if defined DLL_EXPORT
#        define WINPTHREAD_API __declspec(dllexport)
#    else
#        define WINPTHREAD_API __declspec(dllimport)
#    endif
#else
#    define WINPTHREAD_API
#endif 

甚至

#if defined DLL_EXPORT
#      ifdef IN_WINPTHREAD
#            define WINPTHREAD_API __declspec(dllexport)
#      else
#            define WINPTHREAD_API
#      endif
#else
#      define WINPTHREAD_API
#endif

最终我无法在以下之间做出决定:

  • SystemC 是罪魁祸首,configure不应定义DLL_EXPORT
  • MinGW-w64 是罪魁祸首,pthread.h应该提供不同的机制,以便对 pthread API 的调用不会自动转换为“dllimport”,但可能默认为正常的静态链接(DLL_IMPORT也可以引入显式机制)。
  • 以上两种
  • 别的东西
于 2021-09-16T15:13:18.570 回答
0

在过去的几天里,我学到了很多关于 libtool 以及如何以一致的方式使用 DLLEXPORT 的知识

它让我意识到问题的根本原因是最终用户(我自己),一如既往......

公平地configure说,SystemC 附带的脚本中有一些不一致的地方。下面:

./configure --host=x86_64-w64-mingw32.static
  • 将按预期构建一个静态库(libsystemc.a)
  • 但默认情况下它会很乐意使用共享库的设置(假设--enable-shared

它使最终用户相信一切都很好……但事实并非如此。

一旦您理解了这一点并明确指定与构建静态库一致的设置:

./configure --host=x86_64-w64-mingw32.static --disable-shared

然后一切正常。

SystemCcmake流程更加健壮。如果您尝试使用默认设置以 Windows 为目标,则会引发错误,这使您别无选择,只能-DBUILD_SHARED_LIBS=OFF在命令行上指定。

于 2021-09-21T00:53:17.160 回答