图形化VS201x工程中的项目依赖关系

2023-05-16

目录

1. 背景

2. 入手

2.1 分析sln文件

2.2 给出正则表达式

3 程序

4. demo

5. 补充 - 另外一种情况

6. 补充 - 完整代码


1. 背景

       初次接手一个大工程时, 往往因为复杂的项目依赖而遇到各种编译问题, 同时如果能图形化其中的依赖关系对理解整个项目有莫大的帮助, 就像能从山顶俯瞰大陆的感觉. 本文即着重于实现此功能. 
 

2. 入手

2.1 分析sln文件

下面给出了两个Project, 其中project1的GUID为E37ACEB3-9187-43F7-AA78-000000000001

project2的GUID为E37ACEB3-9187-43F7-AA78-000000000002, 

postProject部分给出了依赖关系: project2依赖于project1

Project("{2150E333-AAAA-42A3-9474-1A3956D46DE9}") = "project1", "project1.vcxproj", "{E37ACEB3-9187-43F7-AA78-000000000001}"
EndProject

Project("{2150E333-AAAA-42A3-9474-1A3956D46DE9}") = "project2", "project2.vcxproj", "{E37ACEB3-9187-43F7-AA78-000000000002}"
	ProjectSection(ProjectDependencies) = postProject
		{E37ACEB3-9187-43F7-AA78-000000000001} = {E37ACEB3-9187-43F7-AA78-000000000001}
	EndProjectSection
EndProject

2.2 给出正则表达式

Python正则表达式解析project: r'Project[^=]+=\s*"([^"]+)"\s*,\s*"([^"]+)"\s*,\s*"\{([^"]+)\}"'

                   group(1)为project_name, group(2)为project_vcproj, group(3)为GUID

Python正则表达式解析postProject: r'\{([\w-]+)\}\s=\s\{([\w-]+)\}'

                   group(1)应该等于group(2), 都是依赖的项目的GUID.

3 程序

      请见visual_Project_dependency-Python工具类资源-CSDN下载

4. demo

      

5. 补充 - 另外一种情况

还有一种依赖关系保存在project文件里,形式如下:

<ProjectReference Include="..\MsgCreator\MsgCreator.vcxproj">
      <Project>{d3eada85-50f9-4a1d-a2f7-18612358b436}</Project>
      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>

表示当前工程依赖MsgCreator. vcxproj其实是个XML文件,直接用BeautifulSoup打开查找<Project>项即可。

6. 补充 - 完整代码

#!/usr/bin/python
# -*- coding: gb2312 -*-

#########################################################################
#2022-09-24 support case 2: denpendency in vcxproj.
#2018-08-01 born 
########################################################################

import sys,re

from bs4 import BeautifulSoup
import os
#import os for opening project file to search below kind of dependencies(case 2).
#<ProjectReference Include="..\MsgCreator\MsgCreator.vcxproj">
#      <Project>{d3eada85-50f9-4a1d-a2f7-18612358b436}</Project>
#      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
#</ProjectReference>

projectsCommentMap = {
	'project1':'comment1'
	,'project2': r'comment2: <BR/>aaa'
}

class Project:
	def __init__(self, projectStr, slnpath):
		self.comments = ''
		projectNameGUIDpattern = r'Project[^=]+=\s*"([^"]+)"\s*,\s*"([^"]+)"\s*,\s*"\{([^"]+)\}"'
		m = re.search(projectNameGUIDpattern,projectStr)
		self.name = m.group(1)
		self.GUID = m.group(3).upper()
		self._fullpath = os.path.join(slnpath,m.group(2))

		#case 1: dependency specified in solution file.
		projectDependenciesPattern = r'\{([\w-]+)\}\s=\s\{([\w-]+)\}'
		m = re.findall(projectDependenciesPattern,projectStr)
		self.dependencyList = []
		for match in m:
			if(match[0]==match[1]):
				upperDep = match[0].upper()
				self.dependencyList.append(upperDep)

		#case 2: denpendency specified in specific project file.
		# <ProjectReference Include="..\MsgCreator\MsgCreator.vcxproj">
		#      <Project>{d3eada85-50f9-4a1d-a2f7-18612358b436}</Project>
		#      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
		# </ProjectReference>
		with open(self._fullpath, "r") as file:
			contents = file.read()
			projxml = BeautifulSoup(contents, "xml")
			find_depen = projxml.find_all('Project')
			for dep in find_depen:
				if dep.parent and dep.parent.name=='ProjectReference':
					parentProjGUID = dep.text.strip('{}')
					self.dependencyList.append(parentProjGUID.upper())

		self.dependencyProjects = []

	def __hash__(self):
		return hash(self.GUID)
	def __eq__(self,other):
		if(self.name==other.name and  self.GUID==other.GUID):
			return True
		return False
	
	
new_node_nocomment = '''%d [shape=none label=<<table border="0" cellspacing="0"><tr><td port="port1" border="1" color="red"><B>%s</B></td></tr></table>>]\n'''
new_node_withcomment = '''%d [shape=none label=<<table border="0" cellspacing="0"><tr><td port="port1" border="1" bgcolor="green"><B>%s</B></td></tr><tr><td port="port2" border="1">%s</td></tr></table>>]\n'''
if __name__ == '__main__':
	'''Usage: this_file 2010_sln_file'''
	slnFileName = sys.argv[1]
	#slnFileName = r'C:\cpp\xalan-c-Xalan-C_1_11_0\Projects\Win32\VC15\Xalan.sln'
	import os
	slnpath = os.path.dirname(slnFileName)

	slnFile = open(slnFileName,'r')
	slnStr = slnFile.read()
	print(len(slnStr))
	
	projectStartPos = 0
	projectEndPos = 0
	PROJECT_START_CONSTANT = 'Project("{'
	PROJECT_END_CONSTANT = 'EndProject'
	project_list = []
	while(1):
		projectStartPos = slnStr.find(PROJECT_START_CONSTANT,projectStartPos)
		if(projectStartPos<0):
			break;
		projectEndPos = slnStr.find(PROJECT_END_CONSTANT,projectStartPos)
		if(projectEndPos<0):
			print('NO EndProject closes the project')
			break;
		project_string = slnStr[projectStartPos:projectEndPos]
		project_list.append(Project(project_string, slnpath))
		
		projectStartPos = projectEndPos
		
	print("Total# of projects: %d"%(len(project_list)))
	
	
	guid2ProjectMap = {}
	for project in project_list:
		guid2ProjectMap[project.GUID] = project
	#update dependencyProjects
	for project in project_list:
		for dependGuid in project.dependencyList:
			if dependGuid in guid2ProjectMap:
				project.dependencyProjects.append(guid2ProjectMap[dependGuid])
			else:
				print('project %s depend on a project not in solution:%s'%(project.name, dependGuid))
	
	#generate DOT file
	dot_file_name = 'temp.dot'
	dot = open(dot_file_name,'w+')
	dot.write("digraph Tree {\n")
	#dot.write('node [shape=record color=blue fontname="bold"] ;\n')
	#generate ID for project
	project2IDMap = {}
	refProjectList = set([])
	i = 0
	for project in project_list:
		project2IDMap[project]=i
		i+=1;
	for project in project_list:
		if(len(project.dependencyProjects)>0):
			refProjectList.add(project)
			for dependProject in project.dependencyProjects:
				refProjectList.add(dependProject)
				
	singlefile = open('single.txt','w+')
	for project in project_list:
		if(project in refProjectList):
			if(project.name in projectsCommentMap):
				projectcomments = projectsCommentMap[project.name]
				dot.write(new_node_withcomment%(project2IDMap[project], project.name,projectcomments))
			else:
				dot.write(new_node_nocomment%(project2IDMap[project], project.name))
			if(len(project.dependencyProjects)>0):
				for depend_project in project.dependencyProjects:
					dot.write("%d -> %d ;\n"%(project2IDMap[depend_project],project2IDMap[project]))
		else:
			singlefile.write(project.name)
			singlefile.write('\n')
	dot.write("}")
	dot.close()
	singlefile.close()
	

最后附一张开源库Xalan的项目依赖关系图:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图形化VS201x工程中的项目依赖关系 的相关文章

随机推荐

  • 华为机试在线训练-牛客网(23)判断两个IP是否属于同一子网

    题目描述 子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据 子网掩码与IP地址结构相同 xff0c 是32位二进制数 xff0c 其中网络号部分全为 1 和主机号部分全为 0 利用子网掩码可以判断两台主机是否中同一子网中
  • APISIX Dashboard中文文档(二)

    2022年7月6日14 31 51 APISIX Dashboard中文文档 一 APISIX Dashboard中文文档 二 APISIX Dashboard中文文档 三 基本部署 在 Linux 上安装 Apache APISIX Da
  • FreeRTOS 任务调度原理(基于cortexM内核)

    目录 默认FreeRTOS调度策略 xff08 单核 xff09 FreeRTOS调度策略的实现 任务创建 任务调度的4种情景 xff1a 1 第一次启动任务调度器 2 任务主动触发调度 3 SystemTick时钟触发调度 4 因为中断而
  • Centos7命令行安装图形用户界面

    安装完成Centos7后 xff0c 重启后发现是命令行界面 xff0c 于是就想改成图形用户界面 安装了图形用户界面的话 xff1a 1 查看系统里是否已经安装了图形用户界面 使用ctrl 43 alt 43 fx xff0c x为123
  • STM32G070 DMA+SPI+LCD显示

    SPI HandleTypeDef hspi1 DMA HandleTypeDef hdma spi1 tx 描述 xff1a LCD的SPI引脚初始化 参数 xff1a 无 返回 xff1a 无 void LCD SPI Init voi
  • Linux 开启VNCSERVER

    尽管我们可以使用 SSH连接远程通过字符界面来操作Linux xff0c 但是对于更多熟悉图形人来说是很不方便的 xff0c 因此开启Linux的远程桌面还是很有必要的 目前有两种比较流行的方式 xff1a XDM X display ma
  • Ubuntu 代号引发的“崩溃”

    写这篇文章主要是因为在前几天 xff0c 因为向来不关心ubuntu代号的我而引发的一次 崩溃 xff08 人崩溃 xff09 xff0c 正如我们所知Ubuntu 每半年都会更新一个版本 xff0c 每两年都会发布一个TLS xff08
  • Prometheus(二)部署Prometheus和node_exporter

    软件包列表 Prometheus安装 解压部署 rm rf prometheus 2 28 1 linux amd64 tar xvf prometheus 2 28 1 linux amd64 tar gz rm usr local pr
  • Python学习之路_day_02(编程语言介绍及变量)

    一 编程语言介绍 1 机器语言 直接用二进制编程 xff0c 直接控制硬件 xff0c 需要掌握硬件的操作细节 优点 xff1a 执行效率高 缺点 xff1a 开发效率低 2 汇编语言 xff1a 用英文标签取代二进制指令去编写程序 xff
  • 解决linux系统read only system 解决办法

    首先确认系统属于非硬盘物理坏道引起 其次确认是否有root权限 下面我要阐述一个恢复实例 xff1a 一现象 xff1a 1 没有root权限 2 由于磁盘空间满溢导致分区表损坏 xff08 非物理坏道引起 xff09 3 重启后已经无法进
  • 哈希查找效率及应用场景

    数组的特点是 xff1a 寻址容易 xff0c 插入和删除困难 xff1b 而链表的特点是 xff1a 寻址困难 xff0c 插入和删除容易 那么我们能不能综合两者的特性 xff0c 做出一种寻址容易 xff0c 插入删除也容易的数据结构
  • 四位比较器

    四位比较器 一 xff0c 实验目的 通过使用比较四位二进制判断它的相对大小 二 xff0c 实验内容 四位比较器的实验 三 xff0c 实验代码 module Comp 2 str output A gt B A lt B A eq B
  • 程序员玩游戏之三--天天爱消除非暴力脚本

    评论 xff1a 此款游戏成功在其好友排名上 好友的分数超过了你无疑会增加你的斗志 中级策略 xff1a 七手八脚多人一起点 这相当于多个CPU处理一个大任务了 xff0c 哈哈 终极策略 xff1a 自动化 机器总是比人快的多 你两个人一
  • 程序员玩游戏之四--娱网棋牌大连打滚子记牌器

    话说大连人都爱打滚子 xff0c 所以本人就做了一个打滚子记牌器 基本原理同 程序员玩游戏之一 自动对对碰 xff0c 故此处不再赘述 xff0c 只留下一张截图吧 代码请见资源地址 xff1a http download csdn net
  • 为SIGSEGV设置handler有用吗?

    背景 最近几天看到先辈们30年前留下了一块代码 xff0c 为SIGSEGV设置了handler xff0c 所以心中有了两个疑问 xff1a 为SIGSEGV设置handler有没有用 xff1f 能否跳过引起崩溃的那一句指令 xff1f
  • GDB调试技巧实战--为优化版release版本的函数寻找参数值

    在上一篇 GDB调试技巧实战 为release版本的函数寻找参数值 中 xff0c 我们探讨了一种为函数找参数的办法 xff0c 但是 xff0c 那是最理想的情况 编译时没有使用 fomit frame pointer 编译时没有开启优化
  • 通过实例了解uprobe及其对性能的影响

    前言 uprobe是用户空间探针的意思 xff0c 可以用来给用户程序的任何地方下探针 xff0c 不仅仅是函数粒度层级的 所以异常灵活 如果不熟悉ftrace uprobe 可参考以下文档 xff1a https www kernel o
  • bpftrace各维度捕捉SIGKILL信号

    一 问题 Ftrace 几乎适配任何主流内核版本 xff09 和 bpftrace xff08 要求内核版本4 1以上 xff09 中都有两个现成的脚本execsnoop bt killsnoop bt 我经常用他们从外部 xff08 不去
  • 写个Python程序上下班抢个顺风单

    一 程序预览 本程序已经写了多年 很久没用 不过刚运行了下竟然还可以成功运行 先来张运行结果图 二 最近的滴滴APP已经可以支持设置自动抢单功能 这个小程序就没有那么大意义了 在此主要谈一下我当初的想法 1 这个小程序运行在电脑上 人在回家
  • 图形化VS201x工程中的项目依赖关系

    目录 1 背景 2 入手 2 1 分析sln文件 2 2 给出正则表达式 3 程序 4 demo 5 补充 另外一种情况 6 补充 完整代码 1 背景 初次接手一个大工程时 往往因为复杂的项目依赖而遇到各种编译问题 同时如果能图形化其中的依