构建在Linux上使用和MinGW GCC在Windows上的共享库 [英] Building a shared library using gcc on Linux and MinGW on Windows

查看:258
本文介绍了构建在Linux上使用和MinGW GCC在Windows上的共享库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在与生成,允许共享要建在Linux和Windows两种分别使用gcc和MinGW,图书馆构建设置的麻烦。在Linux中,共享库没有解决在编译时所有的依赖;然而,这似乎在Windows的情况。这里的问题是设置:

I'm having trouble with generating a build setup that allows shared libraries to be built in both Linux and Windows using gcc and MinGW, respectively. In Linux, a shared library doesn't have to resolve all dependencies at compile time; whereas, this appears to the case in Windows. Here is the problem setup:

$ cat foo.h 
#ifndef FOO_H
#define FOO_H
void printme();
#endif


$ cat foo.c
#include "foo.h"
#include <stdio.h>
void printme() {
    printf("Hello World!\n");
}


$ cat bar.h
#ifndef BAR_H
#define BAR_H
void printme2();
#endif


$ cat bar.c
#include "bar.h"
#include "foo.h"
void printme2() {
    printme();
    printme();
}


$ cat main.c
#include "bar.h"
int main(){
    printme2();
}


$ cat Makefile 
.c.o:
        gcc -fPIC -c $<

all: foo.o bar.o main.o
        gcc -shared foo.o -o libfoo.so
        gcc -shared bar.o -o libbar.so
        gcc main.o  -Wl,-rpath=. -L . -lbar -lfoo -o main


现在,在Linux中,这个编译并运行就好了:


Now, in Linux, this compiles and runs just fine:

$ make
gcc -fPIC -c foo.c
gcc -fPIC -c bar.c
gcc -fPIC -c main.c
gcc -shared foo.o -o libfoo.so
gcc -shared bar.o -o libbar.so
gcc main.o  -Wl,-rpath=. -L . -lbar -lfoo -o main

$ ./main 
Hello World!
Hello World!

在Windows中,我们需要这样改变的dll,这是次要的和精致的:

In Windows, we need to change so to dll, which is minor and fine:

$ cat Makefile 
.c.o:
        gcc -fPIC -c $<

all: foo.o bar.o main.o
        gcc -shared foo.o -o libfoo.dll
        gcc -shared bar.o -o libbar.dll
        gcc main.o  -Wl,-rpath=. -L . -lbar -lfoo -o main

然而,当我们试图建立,我们得到以下错误:

However, when we try to build, we get the following error:

$ make
gcc -fPIC -c foo.c
foo.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c bar.c
bar.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c main.c
main.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o -o libbar.dll
bar.o:bar.c:(.text+0x7): undefined reference to `printme'
bar.o:bar.c:(.text+0xc): undefined reference to `printme'
collect2.exe: error: ld returned 1 exit status
make: *** [all] Error 1

现在,我们可以简单地通过包括来自foo.o的对象为libbar.dll修复错误:

Now, we can fix the error by simply including the objects from foo.o into libbar.dll:

$ cat Makefile 
.c.o:
        gcc -fPIC -c $<

all: foo.o bar.o main.o
        gcc -shared foo.o -o libfoo.dll
        gcc -shared bar.o foo.o -o libbar.dll
        gcc main.o  -Wl,-rpath=. -L . -lbar -lfoo -o main

$ make
gcc -fPIC -c foo.c
foo.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c bar.c
bar.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c main.c
main.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o foo.o -o libbar.dll
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main 

$ ./main 
Hello World!
Hello World!

不过,我不喜欢这种方法,因为现在libbar.dll包含两个foo和bar的符号。在Linux中,它仅包含巴符号。这种分离是很重要的情况,其中一个库依赖于像BLAS一些标准的数字图书馆。我希望能够部署共享库,并把它依赖于数字图书馆的优化版本在用户的机器上,而不是我自己的。

However, I don't like this approach since libbar.dll now contains symbols for both foo and bar. In Linux, it only contains symbols for bar. This separation is important for situations where a library depends on some standard numerical library like BLAS. I'd like to be able to deploy the shared library and have it depend on the optimized version of the numerical library on the user's machine and not my own.

在任何情况下,什么是正确的步骤来创建一个共享的图书馆,不是所有的符号都是在编译时present?

In any case, what's the proper procedure to create a shared library where not all of the symbols are present at compile time?

在这重要的情况下,我用gcc编译4.6.3这些例子在Linux和MinGW-GET-研究所-20120426.exe用gcc 4.7.2在Windows上。

In case it matters, I compiled these examples with gcc 4.6.3 on Linux and mingw-get-inst-20120426.exe with gcc 4.7.2 on Windows.

推荐答案

在Windows中,您需要创建一个导入库的的DLL。导入库看起来像一个静态库,因为它定义了所有需要的符号,但它不具有实际功能的实现,它只是有存根。同时避免静态链接导入库将解决未定义的引用的错误。

On Windows, you need to create an import library for the DLL. An import library looks like a static library, in that it defines all of the needed symbols, but it doesn't have the actual function implementations, it just has stubs. The import library will resolve the "undefined reference" errors while avoiding static linking.

要创建MinGW的导入库,按照说明这里。最关键的是建立DLL时,您必须通过选项轮候册, - 出IMPLIB,libexample_dll.a 来链接器生成导入库 libexample_dll.a

To create an import library with MinGW, follow the instructions here. The key is that when building the DLL, you must pass the option -Wl,--out-implib,libexample_dll.a to the linker to generate the import library libexample_dll.a.

然后,当您编译主可执行文件,您可以使用 -lexample_dll 选项(使用 -L一起。 )针对导入库链接。因此,与您的code,我觉得这应该工作:

Then, when you compile your main executable, you use the -lexample_dll option (along with -L.) to link against the import library. So with your code, I think this should work:

all: foo.o bar.o main.o
    gcc -shared foo.o -o libfoo.dll -Wl,--out-implib,libfoo.a
    gcc -shared bar.o foo.o -o libbar.dll -Wl,--out-implib,libbar.a
    gcc main.o  -Wl,-rpath=. -L. -lbar -lfoo -o main

另外请注意,在Windows上,在DLL导出函数的调用约定几乎总是 __ STDCALL ,而不是默认 __ CDECL ,所以如果你想你的DLL被其他软件是可用的,我建议让他们 __ CDECL 。但是,这并不是严格的要求,只要两个DLL中的code和头文件的调用约定是同意的。

Also, note that on Windows, the calling convention for exported functions in DLL is almost always __stdcall, not the default __cdecl, so if you want your DLLs to be usable by other software, I'd recommend making them __cdecl. But that's not strictly requires, as long as both the code in the DLL and the header files agree on what the calling convention is.

这篇关于构建在Linux上使用和MinGW GCC在Windows上的共享库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆