大量 vcproj 构建顺序管理工具的实现(一)

来源:互联网 发布:js中循环遍历json对象 编辑:程序博客网 时间:2024/06/06 04:04

1.引入问题

公司产品有大量模块(vcproj)需要在日常和出货时构建,有一个专门的批处理(BuildOrder_XXX.bat)去管理这些模块的构建顺序,每个开发者在写新模块后,都需要将它加入批处理文件内某一行,这没问题。但后续某个模块增加了对其它模块的隐式依赖(一般是使用了其它模块的导出函数)后,如果忘记也修改 vcproj 在批处理里的顺序,就会导致编译报错,需要跑几遍批处理,而且顺序也不太好调整。受困于此,我们可以引入构建顺序管理工具,专门用来分析和管理各模块的构建顺序。

2.分析问题

如何知道模块之间的隐式依赖关系呢?

首先想到的是 solution 文件内的项目依赖,但是如果开发者没有设置依赖关系怎么办?或者两个vcproj根本没有在同一个solution内怎么办?所以此办法无法解决问题。

接着想到的是 Dependency Walker,这个软件用来查看模块间的隐式依赖关系,是通过分析 PE 文件的导入表得来,需要先有编好的可执行文件,这个可以满足。网上查找到怎么获取PE导入表的代码如下:

HRESULT ParseFilePEDependency(LPCSTR szPEPath){HMODULE hMod = LoadLibraryExA(szPEPath, NULL, DONT_RESOLVE_DLL_REFERENCES);if( !hMod )return S_OK;//输出文件不存在std::string sModDepend;do{// Import tableIMAGE_DOS_HEADER* IDH = (IMAGE_DOS_HEADER*)hMod;if( !IDH )break;IMAGE_OPTIONAL_HEADER* IOH = (IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + IDH->e_lfanew + 24);if( !IOH )break;IMAGE_IMPORT_DESCRIPTOR* IID = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hMod + IOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);if( !IID )break;while(IID->FirstThunk){IMAGE_THUNK_DATA* ITD =(IMAGE_THUNK_DATA*)((BYTE*)hMod+ IID->OriginalFirstThunk);if( IsBadReadPtr(ITD, sizeof(IMAGE_THUNK_DATA)) )break;sModDepend = ((char const *)hMod + IID->Name);//这个 sModDepend 就是每一个被 szPEPath 所隐式依赖的 DLL 名字了++IID;}}while(0);FreeLibrary(hMod);return S_OK;}
实际跑起来后,发现另一个问题,sModDepend 会有许多 windows 自己的 DLL,例如 ntdll.dll, kernel32.dll 等,还有其它的我们不关心的无源码的第三方库,这些都可以排除。实际做法有两个:

第一个是从配置文件内读一个排除列表,这个方法比较麻烦,而且维护不易,因为外部DLL太多了,维护不易,废弃。

第二个是只记在批处理内的模块输出的可执行文件,这个方法比较好,但需要保证所有模块不能有相同的可执行模块名(相信每个大型软件都可以做到)。

想实现第二个办法,需要解析批处理文件、.sln文件和.vcproj文件。


0 0
原创粉丝点击