1

I have managed to build a static CPython library on Windows 10 by starting with the project here as a base (built around Visual C++ 2008):

https://github.com/zeha/python-superstatic

First, by using the prescribed instructions, I was able to get the library built in VS2015 by finding the workarounds listed beneath.

Once the library was built, I set about compiling and linking the supplied example c source, but soon reduced this to the following test code:

#include <stdio.h>
#include <Python.h>

int main()
{
    Py_Initialize();
    return 0;
}

I had to remove the bit in pyconfig.h which does this:

pragma comment(lib,"python27.lib")

so that it would look for the symbols in my static lib.

This does not compile, because the linker complains:

Source.obj : error LNK2001: unresolved external symbol __imp__Py_Initialize

I have added the path to the generated static library, pythonembed.lib, in:

Properties->Linker->General->Additional Library Directories

This is set to :

/workspace/superstatic-python/Python-2.7.3/PCbuild

I have also specified the library in (tried both bare lib name and absolute path):

Properties->Linker->Input->Additional Dependencies 

This is set to:

pythonembed.lib

Running the command:

dumpbin.exe /all pythonembed.lib 

shows that there is a symbol named _Py_Initialize. I have verified that both the static library and test project are built using the v140 toolset as a release build for 32 bit.

Have I missed any steps getting VC++ to link correctly?

The interesting bit is that the code calls Py_Initialise, the linker is looking for __imp__Py_Initialize, but the static library has the symbol: _Py_Initialize.

Does this point to the solution?

ISSUES to resolve to build the static library on Windows 10 with VS2015:

GNU Patch

GNU patch didn't work for me. It triggers UAC and loads in a new console, and does nothing. Seems to be triggering this behaviour because it's named 'patch.exe'. I found various work-arounds mentioned for this, but instead I used Cygwin's patch and put the Cygwin bin folder in the path.

Neither versions of 7zip downloaded came with a 7za.exe, so it was necessary to rename 7z.exe to 7za.exe

Nasm

nasm didn't install in the path supposed by instructions. Instead I used :

SET PATH=C:\Program Files\7-Zip;C:\Users\james\AppData\Local\nasm;%PATH%

Build environment

Instead of calling the VC++ 2008 SetEnv command to create the command line build environment, I used 'Developer Command Prompt for VS2015'.

PS: I started by getting this built in a VC++ 2008 environment, where all the above applied, but in addition, I had to solve the issue below. Once I had resolved this, I had the same linking issues as with the VS2015 build.

There is an issue installing the 7.1 SDK on Windows 10 due to a non-recognised .NET version in the registry. See:

Cannot install Windows SDK 7.1 on Windows 10

To install the 7.1 SDK with the full MSBuild tools, it was necessary to alter all locations in the registry (8, not the 2 reported, need to search) where the version of the installed .NET software is recorded:

Community
  • 1
  • 1
  • Is it possible for you to show the Additional dependency directories/Linker options? That would be more helpful. – iamrameshkumar Apr 10 '16 at 12:25
  • I have updated the question to show the values I believe you're asking for. Note the correction to the first property name. If I change the lib name to a non-existent file, it causes an error saying 'cannot open input file', so I believe these settings are leading the linker to the right file. – simple simon Apr 10 '16 at 14:30
  • Looking into the issue of where the __imp prefix comes from, this is when the linker wants to link to a DLL, so thinks that the .lib provided is an import library for the DLL. I did all sorts of tests with options passed to cl.exe and link.exe, but couldn't change this behaviour. It turns out that there are some defines in pyconfig.h which control the link behaviour. I have now got further, but it seems there may be some more trouble ahead. See [this python-dev thread](https://mail.python.org/pipermail/python-dev/2004-July/046499.html) I'll answer later if I get anywhere – simple simon Apr 10 '16 at 17:03
  • Have you configured in the linker options anything about delay loaded dlls?, could you please update the complete snapshot of your linker options? – iamrameshkumar Apr 11 '16 at 08:10
  • Are you sure that the python library is a static library????. for dynamic libraries also you will have .lib files to make linker aware that the symbols will be part of dynamic libraries. – iamrameshkumar Apr 11 '16 at 08:17
  • I think we are getting closer to the solution. – iamrameshkumar Apr 11 '16 at 08:18
  • It is the macros in pyconfig.h which are telling the library to look for the methods in the header libs, not the VC++ settings. Yes it's a static library. I built it myself so I know. Plus I ran lib.exe on it to double check, and all the obj files are contained within. It turns out that Github page is complemented with a blog post with more info on things: [blog post](http://christian.hofstaedtler.name/blog/2013/01/embedding-python-on-win32.html) – simple simon Apr 11 '16 at 17:41
  • I didn't make it clear, but I got beyond the initial undefined symbol error, but now face more. Update to follow. – simple simon Apr 11 '16 at 17:51

1 Answers1

1

In order to get an executable linking successfully to the generated static Python library, it was necessary to set some extra compiler options and to include a few Windows libraries.

Anyone who wants to accomplish the build themselves can start with this test code (save as simple.c):

#include <stdio.h>
#include <Python.h>

int main()
{
    Py_Initialize();
    PyRun_SimpleString(
        "print 'This program contains a static version of Python."
    );
    Py_Finalize();
    return 0;
}

and the following Makefile I created:

PYTHON_V=2.7.3
OPENSSL_V=1.0.1c
ROOT=..\\

CFLAGS=/c /GF /MP4 /nologo /EHsc /I$(ROOT)openssl-$(OPENSSL_V)\inc32 \
    /I$(ROOT)Python-$(PYTHON_V)\Include /I$(ROOT)Python-$(PYTHON_V)\PC \
    /D Py_NO_ENABLE_SHARED /D Py_BUILD_CORE \
    /DPy_BUILD_CORE /MD /W4 /O2
LINKFLAGS=/MACHINE:X86 /RELEASE /LTCG /NODEFAULTLIB:LIBCMT
LIBS=$(ROOT)openssl-$(OPENSSL_V)\out32\libeay32.lib \
    $(ROOT)openssl-$(OPENSSL_V)\out32\ssleay32.lib \
    $(ROOT)Python-$(PYTHON_V)\PCbuild\pythonembed.lib ws2_32.lib msvcrt.lib user32.lib shell32.lib advapi32.lib oleaut32.lib Gdi32.Lib Ole32.lib
CC= cl
LINK= link

all: simple.exe 

simple.obj:
  $(CC) $(CFLAGS) simple.c

simple.exe: simple.obj
  $(LINK) $(LINKFLAGS) -out:simple.exe simple.obj $(LIBS)

These should go in a new folder under the Superstatic Python base folder, then from the windows 7.1 SDK build environment, just run

nmake

With any luck, you should now have simple.exe in your folder, which for me was 3.7 MB, and ran as expected.