Search code examples
windowsvisual-c++python-extensionsapr

Linking with Apache Portable Runtime on MS Windows


I'm trying to build a Python extension which links to APR. And this time it's on MS Windows... (It works on Linux).

Here's where the build fails, the command, and the output formatted for readability:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe
    /nologo
    /INCREMENTAL:NO
    /LTCG
    /DLL
    /MANIFEST:EMBED,ID=2
    /MANIFESTUAC:NO
    /LIBPATH:c:\dev\protopy\lib/apr
    /LIBPATH:c:\bin\python\Libs
    /LIBPATH:c:\dev\protopy\.venv\libs
    /LIBPATH:c:\dev\protopy\.venv\PCbuild\amd64
    "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB\amd64"
    "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.10240.0\ucrt\x64"
    "/LIBPATH:C:\Program Files (x86)\Windows Kits\8.1\lib\winv6.3\um\x64"
    apr-1.lib
    /EXPORT:PyInit_wrapped build\temp.win-amd64-3.6\Release\protopy/lib/descriptors.obj
    build\temp.win-amd64-3.6\Release\protopy/lib/binparser.obj
    build\temp.win-amd64-3.6\Release\protopy/lib/defparser.obj
    build\temp.win-amd64-3.6\Release\protopy/lib/protopy.lex.obj
    build\temp.win-amd64-3.6\Release\protopy/lib/protopy.tab.obj
    build\temp.win-amd64-3.6\Release\protopy/lib/pyhelpers.obj
    build\temp.win-amd64-3.6\Release\protopy/lib/list.obj
    build\temp.win-amd64-3.6\Release\protopy/wrapper.obj
    /OUT:build\lib.win-amd64-3.6\protopy\wrapped.cp36-win_amd64.pyd
    /IMPLIB:build\temp.win-amd64-3.6\Release\protopy/lib\wrapped.cp36-win_amd64.lib

wrapper.obj : warning LNK4197: export 'PyInit_wrapped' specified multiple times; using first specification
   Creating library build\temp.win-amd64-3.6\Release\protopy/lib\wrapped.cp36-win_amd64.lib \
   and object build\temp.win-amd64-3.6\Release\protopy/lib\wrapped.cp36-win_amd64.exp
descriptors.obj : error LNK2001: unresolved external symbol \
    __imp_apr_hash_set

(it actually misses all symbols I've used, not just this one).

I've built the apr-1.lib by running nmake -f Makefile.win in APR's top-level directory before, and this is how I produced libapr-1.lib. Then I renamed to apr-1.lib it and put it in c:\dev\protopy\lib/apr, so the linker is actually able to find it, but it cannot find the required symbols...

Question 1

How can I see what symbols are in the library? (Maybe I compiled something wrong?)


OK, I found dumpbin.exe, but now I see that the symbol in the apr-1.lib is called __imp__apr_hash_set (notice the second double underscore), but the linker looks for __imp_apr_hash_set (single underscore). What gives? They were compiled with the same compiler / linker...

Question 2

Is there anything specific to building Python extensions on MS Windows that makes it work in this way? (I only tried this once in my life, and couldn't get it to work, but for different reasons).


Solution

  • According to APR project document

    choose either aprutil or libaprutil (for static or dynamic libraries)

    means apr-1.lib-->static and libapr-1.lib -->dynamic and

    To target the static .lib versions of the library, the consuming compiliation must define the macros APR_DECLARE_STATIC and APU_DECLARE_STATIC. This prevents the apr and apr-util symbols from being tagged as __declspec(dllimport), eliminating compiliation warnings and speeding up execution.