在VS2017、MSYS2、VS2008、MD\MDd之间徘徊多此编译验证,终于是可以正常跑起来。
颇为曲折,也折射出一些需要编译安装的python模块的注意事项。
主要包括编译器选用、源码缺失与错误的补齐和修改(C99,C11)等问题。
一、在windows上,python需要编译安装的模块,python官方推荐配置是VS2008(msvcr90),对此一直不以为然,以为版本越新越好。
直到本次VS2017对graphviz和pygraphviz的编译安装后,遭遇了如下滑铁卢。
使用VS2017编译好graphviz,并配置编译安装pygraphviz后,在执行以下测试代码时。
在 write_dot 函数总是没有任何错误提示后退出了python交互
类似的,下述执行 A.string() 函数也会出现同样退出情形。
#------- ------- -------- ------- ------- ------- -------
from ctypes import *
windll.kernel32.GetCurrentProcessId() #show pid for vs2017 to attach debug C\C++ and python codes
import networkx as nx
#import pygraphviz
G = nx.complete_graph(5)
fh = open(r'.\Gf.gv','wb') #msvcr90._fsopen
nx.nx_agraph.write_dot(G,fh)
#------- ------- -------- ------- ------- ------- -------
在 write_dot 函数总是没有任何错误提示后退出了python交互
类似的,下述执行 A.string() 函数也会出现同样退出情形。
#------- ------- -------- ------- ------- ------- -------
import pygraphviz as pgv
A=pgv.AGraph(directed=True,strict=True)
A.add_edge(1,2)
A.add_edge(1,3)
print A.string()
#------- ------- -------- ------- ------- ------- -------
通过跟踪调试,异常出现在 ucrtbase.fputs 函数在尝试进入锁定文件句柄代码等代码过程中,
执行RtlEnterCriticalSection进入互斥代码片段时,RtlEnterCriticalSection访问异常。
这是在不同版本的运行库之间交互冲突所致。
python的官方版是msvcr90(VS2008),在涉及文件句柄(包括标准输入输出)时,如上述的open,
其底层调用的是 msvcr90._fsopen,若后续操作用 msvcr90.fputs输出是不存在问题的。
而此次的问题就出在graphviz用的是VS2017编译的(/MD),输出选用的是ucrtbase.fputs。
由此产生冲突异常,直接导致python崩溃退出。
因为string()最终需要调用stdout输出,同样是文件句柄fputs操作,就会有同样的问题。
以此类推,但凡涉及安装模块与python其它之间的交互,涉及文件句柄,都很可能会出现此问题。
由此可见,最好还是遵循python对于版官方推荐使用的编译器如VS2008。
二、我们先完成 graphviz 64bit版本的编译安装
主要参考官方的编译说明进行
进入 graphviz 主页面
http://www.graphviz.org/
选择 download 进入下载页面
http://www.graphviz.org/download/
在 Windows 部分
选择 Development Windows install packages 进入不同编译配置选项页面
我们针对 python (64 bit)
选择 Environment: build_system=cmake, generator=Visual Studio 14 2015; Configuration: Release 进入配置编译指令页面
选择 The last 2,000 lines of the build log are shown. Display or download complete log. 中的 Display 显示"所有“作为编译参考。
我们主要针对 Environment: build_system=cmake, generator=Visual Studio 14 2015; Configuration: Release进行改动分解执行编译
即我们用cmake,"Visual Studio 9 2008 Win64" 构建 Release版本(Debug版本类似)
(1)下载
git clone -v --depth=25 --branch=master https://gitlab.com/graphviz/graphviz.git D:\graphviz-git
(2)并选择master分支
cd D:\graphviz-git
git checkout master
//若提示 HEAD detached at 452f46c 类似错误,碰巧碰到作者们在更新一个说明文档
//可以合并
git branch temp 452f46c
git checkout master
git merge temp
git branch -d temp
(3)下载依赖模块,这个很方便,否则需要自行下载flex,bison,awk等编译依赖并配置
git submodule update --init
Submodule 'dependencies/criterion' (https://github.com/Snaipe/Criterion.git) registered for path 'dependencies/criterion'
Submodule 'windows/dependencies/graphviz-build-utilities' (https://github.com/ErwinJanssen/graphviz-build-utilities.git) registered for path 'windows/dependencies/graphviz-build-utilities'
Submodule 'windows/dependencies/libraries' (https://github.com/ErwinJanssen/graphviz-windows-dependencies.git) registered for path 'windows/dependencies/libraries'
Cloning into 'D:/graphviz-git/dependencies/criterion'...
Cloning into 'D:/graphviz-git/windows/dependencies/graphviz-build-utilities'...
Cloning into 'D:/graphviz-git/windows/dependencies/libraries'...
Submodule path 'dependencies/criterion': checked out '301d143ea42c024f22b673b69c72a4cb3c8d151f'
Submodule path 'windows/dependencies/graphviz-build-utilities': checked out '050fff84ce195e0740878748760fd801eeb07b23'
Submodule path 'windows/dependencies/libraries': checked out '141d3a21be904fa8dc2ae3ed01d36684db07a35d'
(4)配置必要依赖,完成cmake配置
(4.1)命令行执行,VS2008编译环境初始化
D:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\amd64\vcvarsamd64.bat
(4.2)设置cmake和perl路径,(需要另行安装)
set path=D:\ProgramData\CMake\bin;%path%
set path=D:\Program Files (x86)\Perl\bin;%path%
(4.3)配置 64bit python 的相关路径
set path=D:\ProgramData\Anaconda2;D:\ProgramData\Anaconda2\Scripts;D:\ProgramData\Anaconda2\Library\bin;%path%
set PYTHONPATH=D:\ProgramData\Anaconda2;D:\ProgramData\Anaconda2\DLLs;
(4.4)配置 awk,bison,flex,rxspencer必须的依赖项,上述git submocule下载安装的部分,如非必要,不需令行配置安装。
set PATH=D:\graphviz-git\windows\dependencies\graphviz-build-utilities;%PATH%
(4.5)配置可选项 ANN,其64位编译参考本文后续描述
set include=D:\ANN\ann_1.1.2\MS_Win32\bin\include;%include%
set lib=D:\ANN\ann_1.1.2\MS_Win32\bin;%lib%
set path=D:\ANN\ann_1.1.2\MS_Win32\bin;%path%
(4.6)配置可选项 PkgConfig,可考虑直接安装现成版本32位应该也可以,然后配置路径。如要折腾自己的64位版本参考本文后续编译描述。
set path=D:\pkg-config-git\release\x64;%path%
(4.7)配置可选项 GD,其64位编译参考本文后续描述
set include=D:\libgd-git\src;%include%
set lib=D:\libgd-git\build\Bin\Release;%lib%
set path=D:\libgd-git\build\Bin\Release;%path%
(4.8)配置可选项 NSIS,下载现成的安装即可
set path=D:\Program Files (x86)\NSIS\Bin;%path%
上述可选配置可有可无,根据实情按需配置。
在源码目录 D:\graphviz-git 中建立build目录,进入后执行cmake进行自动配置
mkdir build
cd build
cmake -G "Visual Studio 9 2008 Win64" ..
-- Selecting Windows SDK version 10.0.16299.0 to target Windows 10.0.17134.
-- Found GD: D:/libgd-git/build/Bin/Release/libgd.lib
-- Graphviz version: 2.41.20181110.0011
-- The following OPTIONAL packages have been found:
* ANN
* Cairo
* PkgConfig
* EXPAT
* GD
* LTDL
* PangoCairo
* ZLIB
* NSIS
* PythonInterp
-- The following REQUIRED packages have been found:
* AWK
* BISON
* FLEX
* Git
* Perl
* RxSpencer
-- Configuring done
-- Generating done
-- Build files have been written to: D:/graphviz-git/build
三、cmake配置完成后,编译安装 graphviz
(在执行编译前,先参考【五、】中的对源码的修改,或在编译中针对相应错误进行修正)
在 D:\graphviz-git\build
Relase版编译:cmake --build . --config Release
Debug版编译:cmake --build . --config Debug
编译完成后,即可通过下述命令安装(这里选择D:\ProgramData\graphviz_my目录,也是我们后续编译pygraphviz需要配置的目录)和卸载
cmake -DCMAKE_INSTALL_PREFIX=D:\ProgramData\graphviz_my -DCMAKE_INSTALL_CONFIG_NAME=Release -P cmake_install.cmake
cmake -DCMAKE_INSTALL_PREFIX=D:\ProgramData\graphviz_my -DCMAKE_INSTALL_CONFIG_NAME=Release -P cmake_uninstall.cmake
cmake -DCMAKE_INSTALL_PREFIX=D:\ProgramData\graphviz_my -DCMAKE_INSTALL_CONFIG_NAME=Debug -P cmake_install.cmake
cmake -DCMAKE_INSTALL_PREFIX=D:\ProgramData\graphviz_my -DCMAKE_INSTALL_CONFIG_NAME=Debug -P cmake_uninstall.cmake
四、编译安装pygraphviz
有了graphviz,这个就比较简单。
我们设置相关依赖目录
set lib=D:\ProgramData\graphviz_my\lib;%lib%
set path=D:\ProgramData\graphviz_my\bin;%path%
set include=D:\ProgramData\graphviz_my\include;%include%
最后 pip install pygraphviz 即可
pip install pygraphviz
Collecting pygraphviz
Using cached https://files.pythonhosted.org/packages/7e/b1/d6d849ddaf6f11036f9980d433f383d4c13d1ebcfc3cd09bc845bda7e433/pygraphviz-1.5.zip
Building wheels for collected packages: pygraphviz
Running setup.py bdist_wheel for pygraphviz ... done
Stored in directory: C:\Users\yourname\AppData\Local\pip\Cache\wheels\65\54\69\1aee9e66ab19916293208d4c9de0d3898adebe6b2eeff6476b
Successfully built pygraphviz
Installing collected packages: pygraphviz
Successfully installed pygraphviz-1.5
You are using pip version 9.0.1, however version 18.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.
若之前已经编译了错误版本,应先将
C:\Users\用户名\AppData\Local\pip\Cache\wheels\65\54\69\1aee9e66ab19916293208d4c9de0d3898adebe6b2eeff6476b目录的whl删除后重新编译安装