交叉编译 SystemC 库并链接到它们
Cross-compiling SystemC libraries and linking to them
我从头开始,并遵循以下主要步骤:
1.构建并安装交叉编译器工具链(主机Linux,目标Win64):
获取此 MXE version,仅将 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 libraries
这同样简单(但要快得多!):
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'
(及其变体)。
任何人都可以重现并解释发生了什么事吗?
当 SystemC configure
完成时,它清楚地表明它不会使用 Posix 线程,而是使用 WinFiber,所以我有点惊讶地看到这些未解决的 phread 依赖关系(对于记录,在命令行末尾添加 -lpthread
仍然产生相同的结果)
4.以不同方式构建 SystemC 库的额外实验
如果我使用 a native Win64 toolchain 构建 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
而不是 configure
交叉编译和安装 SystemC 库:
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 库在交叉编译时没有正确生成。任何人都可以 confirm/deny?
这不是一个正确的答案,但至少我可以描述导致问题的 end-to-end 机制。
我对 MingW、winpthread 等的所有错综复杂之处还不够熟悉……无法真正准确地说出谁做错了什么,但我会把它留给专家 ;-)
所以这一切都从 SystemC 的 configure
开始,它生成定义 DLL_EXPORT
的 Makefile 配方。乍一看,定义 DLL_EXPORT
似乎很合理,因为目标是构建一个库。
但在实践中,DLL_EXPORT
并未在 SystemC 代码中的任何地方被引用,因此其意图不是很清楚(事实上,SystemC 的基于 cmake
的流程并没有定义它)。不过,如果我相信 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 header 的意图是否有点不同,也许是这样的:
#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
的显式机制)。
- 以上两者
- 其他
在过去的几天里,我学到了很多关于 libtool 和 how DLLEXPORT is meant to be used in a consistent manner 的知识。
这让我意识到问题的根本原因是最终用户(我自己),一如既往...
公平地说,SystemC 附带的 configure
脚本中存在一些不一致的地方。以下:
./configure --host=x86_64-w64-mingw32.static
- 将按预期构建静态库 (libsystemc.a)
- 但默认情况下它会很乐意使用共享库的设置(假设
--enable-shared
)
它让最终用户相信一切都很好......但事实并非如此。
一旦您理解了这一点并明确指定了与构建静态库一致的设置:
./configure --host=x86_64-w64-mingw32.static --disable-shared
然后一切正常。
SystemC cmake
流程更健壮。如果您尝试使用默认设置定位 Windows,它会抛出一个错误,这让您别无选择,只能在命令行上指定 -DBUILD_SHARED_LIBS=OFF
。
我从头开始,并遵循以下主要步骤:
1.构建并安装交叉编译器工具链(主机Linux,目标Win64):
获取此 MXE version,仅将 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 libraries
这同样简单(但要快得多!):
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'
(及其变体)。
任何人都可以重现并解释发生了什么事吗?
当 SystemC configure
完成时,它清楚地表明它不会使用 Posix 线程,而是使用 WinFiber,所以我有点惊讶地看到这些未解决的 phread 依赖关系(对于记录,在命令行末尾添加 -lpthread
仍然产生相同的结果)
4.以不同方式构建 SystemC 库的额外实验
如果我使用 a native Win64 toolchain 构建 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
而不是 configure
交叉编译和安装 SystemC 库:
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 库在交叉编译时没有正确生成。任何人都可以 confirm/deny?
这不是一个正确的答案,但至少我可以描述导致问题的 end-to-end 机制。 我对 MingW、winpthread 等的所有错综复杂之处还不够熟悉……无法真正准确地说出谁做错了什么,但我会把它留给专家 ;-)
所以这一切都从 SystemC 的 configure
开始,它生成定义 DLL_EXPORT
的 Makefile 配方。乍一看,定义 DLL_EXPORT
似乎很合理,因为目标是构建一个库。
但在实践中,DLL_EXPORT
并未在 SystemC 代码中的任何地方被引用,因此其意图不是很清楚(事实上,SystemC 的基于 cmake
的流程并没有定义它)。不过,如果我相信 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 header 的意图是否有点不同,也许是这样的:
#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
的显式机制)。 - 以上两者
- 其他
在过去的几天里,我学到了很多关于 libtool 和 how DLLEXPORT is meant to be used in a consistent manner 的知识。
这让我意识到问题的根本原因是最终用户(我自己),一如既往...
公平地说,SystemC 附带的 configure
脚本中存在一些不一致的地方。以下:
./configure --host=x86_64-w64-mingw32.static
- 将按预期构建静态库 (libsystemc.a)
- 但默认情况下它会很乐意使用共享库的设置(假设
--enable-shared
)
它让最终用户相信一切都很好......但事实并非如此。
一旦您理解了这一点并明确指定了与构建静态库一致的设置:
./configure --host=x86_64-w64-mingw32.static --disable-shared
然后一切正常。
SystemC cmake
流程更健壮。如果您尝试使用默认设置定位 Windows,它会抛出一个错误,这让您别无选择,只能在命令行上指定 -DBUILD_SHARED_LIBS=OFF
。