首页
社区
课程
招聘
[原创] (py)?graphviz 64bit (for IDA7.0) windows 编译安装
发表于: 2018-11-15 10:51 3069

[原创] (py)?graphviz 64bit (for IDA7.0) windows 编译安装

2018-11-15 10:51
3069

在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删除后重新编译安装

五、源码补齐和修正
(1)补充缺失文件
对于VS2008的编译,会缺失以下三个文件,将附加相应三文件复制到 D:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include 即可
stdbool.h
inttypes.h
stdint.h

在附近中提供,其中stdint.h和inttypes.h 来源于
https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/msinttypes/msinttypes-r26.zip
VS2017也有,但可以会拔出萝卜带出泥,还是用上面的
//D:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\Linux\include\usr\include\inttypes.h
//D:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\Linux\include\usr\lib\gcc\x86_64-linux-gnu\5\include\stdint.h
而 stdbool.h则直接来自于VS2017
D:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\Linux\include\usr\lib\gcc\x86_64-linux-gnu\5\include\stdbool.h

(2)log2 缺失 和 snprintf符号
对于VS2008的编译,链接库不存在log2函数(只有新版有),这里在使用log2的源码 D:\graphviz-git\lib\ortho\trapezoid.c 中直接实现log2函数

#ifndef log2
//add definition of log2  by tritium 2018/11/14 11:55 
double log2(double n){
    //log(n)/log(2) is log2;
    return log(n)/log(2);
}
#endif

D:\graphviz-git\plugin\pango\gvrender_pango.c

//add by tritium 2018/11/14 snprintf symbol not found
#if _MSC_VER
#define snprintf _snprintf
#endif

(3)余下的编译错误全部来自于C99,C11的编译器实现问题。
即函数(或模块)区域内,变量的声明不允许穿插在代码中间。
修正的时候,将穿插在代码之间的"声明和赋值"一体的语句拆分出声明部分(放置到区域开始)和赋值部分(放置原来位置)即可。
附件中modifed文件夹包含了所有需要修正的源码的修正版,替换原来的即可。

#lack definition of log2
D:\graphviz-git\lib\ortho\trapezoid.c
#change snprintf as _snprintf
D:\graphviz-git\plugin\pango\gvrender_pango.c
D:\graphviz-git\lib\gvc\gvdevice.c
#split declarations of variables.
else


│  inttypes.h
│  stdbool.h
│  stdint.h
│
├─lib
│  ├─common
│  │      htmltable.c
│  │
│  ├─dotgen
│  │      position.c
│  │
│  ├─gvc
│  │      gvdevice.c
│  │
│  ├─ortho
│  │      trapezoid.c
│  │
│  ├─sparse
│  │      DotIO.c
│  │      SparseMatrix.c
│  │
│  └─spine
│          quad.c
│          spine.c
│          subset.c
│
└─plugin
    └─pango
            gvrender_pango.c

六、ANN 64bit编译
下载解压ANN到D:\ANN\ann_1.1.2,然后执行以下命令即可编译
在D:ANN\ann_1.1.2\MS_Win32\bin得到结果
我们这里将D:\ANN\ann_1.1.2\include头文件目录也复制到D:ANN\ann_1.1.2\MS_Win32\bin中,方便发行
cd D:\ANN\ann_1.1.2\MS_Win32\dll
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\ANN.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\bd_fix_rad_search.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\bd_pr_search.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\bd_search.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\bd_tree.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\brute.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\kd_dump.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\kd_fix_rad_search.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\kd_pr_search.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\kd_search.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\kd_split.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\kd_tree.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\kd_util.cpp
cl -c /MD /EHsc /DWIN32 /DNDEBUG /D_WINDOWS /D_MBCS /D_USRDLL /DDLL_EXPORTS /I..\..\include /I..\..\src ..\..\src\perf.cpp

link /DLL /OUT:..\bin\ANN.dll /PDB:..\bin\ANN.pdb /IMPLIB:..\bin\ANN.lib *.obj

cd D:\ANN\ann_1.1.2\MS_Win32\sample
cl  /MD /EHsc /DWIN32 /DNDEBUG /D_CONSOLE /DANN_NO_RANDOM /D_CRT_SECURE_NO_DEPRECATE /I..\..\include /I..\..\src ..\..\sample\ann_sample.cpp /link /OUT:..\bin\ann_sample.exe ..\bin\ANN.lib

cd D:\ANN\ann_1.1.2\MS_Win32\ann2fig
cl   /MD /EHsc /DWIN32 /DNDEBUG /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /I..\..\include /I..\..\src ..\..\ann2fig\ann2fig.cpp /link /OUT:..\bin\ann2fig.exe ..\bin\ANN.lib

cd D:\ANN\ann_1.1.2\MS_Win32\test
cl -c /DNDEBUG /DPREP /MD /EHsc /DWIN32 /D_CONSOLE /DANN_NO_RANDOM /I..\..\include /I..\..\src ..\..\test\ann_test.cpp
cl -c /DNDEBUG /DPREP /MD /EHsc /DWIN32 /D_CONSOLE /DANN_NO_RANDOM /I..\..\include /I..\..\src ..\..\test\rand.cpp

link /OUT:..\bin\ann_test.exe *.obj ..\bin\ANN.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

七、PckConfig 64bit编译
32bit的已经可以满足需求,并不是非64bit不可。
PkgConfig的编译直接使用了现成的编译发行版glib_2.26.1-1_win64\bin

由于直接编译libgw32c的64位可能性不大(貌似不支持),放弃lintntl-8.dll的编译
未尝试 libiconv
失败 libgw32c (for developing with the LibIntl library)
直接使用了MSYS2的linintl-8.dll模块
D:\ProgramData\msys32\mingw64\bin
  linintl-8.dll
    libiconv-2.dll
glib_2.26.1-1_win64\bin
    gspawn-win64-helper-console.exe
    gspawn-win64-helper.exe
    libgio-2.0-0.dll
    libglib-2.0-0.dll
    libgmodule-2.0-0.dll
    libgobject-2.0-0.dll

八、GD 64bit编译
git clone  --depth=25 --branch=master https://github.com/libgd/libgd.git D:\libgd-git
git checkout master

cd D:\libgd-git
mkdir build
cd build
然后配置编译即可
cmake -G "Visual Studio 9 2008 Win64" ..
cmake --build . --config Release

附件分别为:
graphviz_my_VS2008_MD_Release.rar 为python 2.7 64bit 兼容的graphviz,
解压释放到自选目录,然后在在系统环境变量path中添加其中的bin目录,即可使用。
若用于编译(其它C\C++代码或pygraphviz),则将其中的lib和include目录分别添加到lib和include环境变量中。
注:应该屏蔽bin目录中的msvc*90.dll,如下
msvcm90.dll.bak
msvcp90.dll.bak
msvcr90.dll.bak
若不屏蔽,而在path中,bin目录在所有其它目录之前,会导致IDA7.0启动加载运行时库异常的情形,
虽然不影响IDA启动,但不美观。

graphviz_patch.zip 用于自行编译graphviz需要修补的graphviz源码,

pygraphviz-1.5-cp27-cp27m-win_amd64.whl  编译版pygraphviz(需要上述graphviz配置到path才能运行)


如有不妥之处,还望斧正,谢谢!
------- by tritium 2018-11-15 -------

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-11-15 11:00 被tritium编辑 ,原因: 修正措辞
上传的附件:
收藏
免费 4
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  junkboy   +1.00 2018/11/16
最新回复 (2)
雪    币: 1535
活跃值: (695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2018-11-15 10:52
1
雪    币: 11716
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
支持
2018-11-16 17:37
1
游客
登录 | 注册 方可回帖
返回
//