源服务器

源服务器使客户端能够检索用于构建应用程序的源文件的确切版本。 由于模块的源代码多年来可能会在不同版本之间发生变化,因此查看构建相关模块版本时存在的源代码非常重要。

源服务器从源代码管理中检索相应的文件。 为了使用源服务器,必须为应用程序编制源索引。

源索引

源索引系统是可执行文件和 Perl 脚本的集合。 Perl 脚本需要 Perl 5.6 或更高版本。

通常,二进制文件会在应用程序构建后的构建过程中进行源索引。 源服务器所需的信息存储在 PDB 文件中。

源服务器当前附带的脚本应适用于以下源代码管理系统。

  • Team Foundation Server
  • Perforce
  • Visual SourceSafe
  • CVS
  • Subversion

你还可以创建自定义脚本以针对不同的源代码管理系统为您的代码编制索引。

下表列出了源服务器工具。

工具 说明
Srcsrv.ini 此文件是所有源代码管理服务器的主列表。 每个条目都采用以下格式:MYSERVER=serverinfo
使用 Perforce 时,服务器信息由服务器的完整网络路径组成,后跟冒号,然后是它所使用的端口号。 例如:
MYSERVER=machine.corp.company.com:1666
可以在运行调试器的计算机上安装此文件。 源服务器启动时,它会查看 Srcsrv.ini 中的值;这些值将替代 PDB 文件中包含的信息。 这使用户能够将调试器配置为在调试时使用备用源代码管理服务器。
有关详细信息,请参阅随源服务器工具一起安装的 Srcsrv.ini 示例。
Ssindex.cmd 此脚本将生成签入源代码管理的文件列表以及每个文件的版本信息。 它将这些信息的子集存储在构建应用程序时生成的 .pdb 文件中。 该脚本使用以下 Perl 模块之一与源代码管理交互:P4.pm (Perforce) 或 Vss.pm (Visual Source Safe)。有关详细信息,请使用 -? 或 -?? (详细帮助)选项运行该脚本,或检查该脚本。
Srctool.exe 此实用工具列出在 .pdb 文件中编制索引的所有文件。 对于每个文件,它将列出文件的完整路径、源代码管理服务器和版本号。 你可以使用此信息在不使用源服务器的情况下检索文件。有关详细信息,请使用 /? 运行该实用工具。
Pdbstr.exe 索引脚本使用此实用程序将版本控制信息插入到目标 .pdb 文件的“srcsrv”备用流中。 它还可以从 .pdb 文件中读取任何流。 你可以使用此信息来验证索引脚本是否正常工作。有关详细信息,请使用 /? 运行该实用工具。

 

检索源文件

DbgHelp API 通过 SymGetSourceFile 函数提供对源服务器功能的访问权限。 若要检索要检索的源文件的名称,请调用 SymEnumSourceFilesSymGetLineFromAddr64 函数。

将源服务器与调试器配合使用

若要将源服务器与 WinDbg、KD、NTSD 或 CDB 配合使用,请确保已安装了最新版本的 Windows 调试工具包(版本 6.3 或更高版本)。 然后,在 .srcpath 命令中包含 srv*,如下所示:

.srcpath srv*;c:\mysource

请注意,此示例还包括传统的源路径。 如果调试器无法从源服务器检索文件,它将搜索指定的路径。

如果源服务器检索了源文件,则调试会话结束后,源文件将保留在硬盘驱动器上。 源文件存储在 Windows 安装目录调试工具的 src 子目录中。

源服务器数据块

源服务器依赖于 PDB 文件中的两个数据块。

  • 源文件列表。 如果生成模块,则会自动创建用于生成模块的源文件的完全限定路径列表。
  • 数据块。 如果为源编制索引(如前所述),则会将备用流添加到名为“srcsrv”的 PDB 文件中。 插入此数据的脚本依赖于正在使用的特定生成过程和源代码管理系统。

在语言规范版本 1 中,数据块分为以下三个部分:ini、变量和源文件。 它具有以下语法。

SRCSRV: ini ------------------------------------------------ 
VERSION=1
VERCTRL=<source_control_str>
DATETIME=<date_time_str>
SRCSRV: variables ------------------------------------------ 
SRCSRVTRG=%sdtrg% 
SRCSRVCMD=%sdcmd% 
SRCSRVENV=var1=string1\bvar2=string2 
DEPOT=//depot 
SDCMD=sd.exe -p %fnvar%(%var2%) print -o %srcsrvtrg% -q %depot%/%var3%#%var4%
SDTRG=%targ%\%var2%\%fnbksl%(%var3%)\%var4%\%fnfile%(%var1%) 
WIN_SDKTOOLS= sserver.microsoft.com:4444 
SRCSRV: source files --------------------------------------- 
<path1>*<var2>*<var3>*<var4> 
<path2>*<var2>*<var3>*<var4> 
<path3>*<var2>*<var3>*<var4> 
<path4>*<var2>*<var3>*<var4> 
SRCSRV: end ------------------------------------------------

除百分号 (%) 括起来的文本外,所有文本均按字面解释。 用百分号括起来的文本被视为要递归解析的变量名,除非它是以下函数之一:

%fnvar%()

参数文本应括在百分比符号中,并被视为要展开的变量。

%fnbksl%()

参数文本中的所有正斜杠 (/) 都应替换为反斜杠 (\)。

%fnfile%()

参数文本中的所有路径信息都应去除,只保留文件名。

ini 节包含描述要求的变量。 索引脚本可以将任意数量的变量添加到此部分中。 以下是一些示例:

版本

语言规范版本。 此变量是必需的。

VERCTL

一个描述源代码管理产品的字符串。 此变量是可选变量。

DATETIME

一个指示 PDB 文件处理日期和时间的字符串。 此变量是可选变量。

变量部分包含描述如何从源代码管理中提取文件的变量。 它还可以用于将常用文本定义为变量,以减少数据块的大小。

SRCSRVTRG

介绍如何为提取的文件生成目标路径。 这是必需的变量。

SRCSRVCMD

介绍如何生成命令以从源代码管理中提取文件。 这包括可执行文件的名称及其命令行参数。 这是必需的变量。

SRCSRVENV

一个列出要在文件提取过程中创建的环境变量的字符串。 使用退格字符 (\b) 分隔多个条目。 这是一个可选变量。

源文件部分包含已索引的每个源文件的条目。 每行的内容均被解释为名称为 VAR1、VAR2、VAR3 等直到 VAR10 的变量。 变量由星号分隔。 VAR1 必须指定 PDB 文件中其他位置列出的源文件的完全限定路径。 例如,以下行:

c:\proj\src\file.cpp*TOOLS_PRJ*tools/mytool/src/file.cpp*3

解释如下:

VAR1=c:\proj\src\file.cpp
VAR2=TOOLS_PRJ
VAR3=tools/mytool/src/file.cpp
VAR4=3

在此示例中,VAR4 是版本号。 但是,大多数源代码管理系统支持以某种方式标记文件,以便可以还原给定版本的源状态。 因此,你可以替代使用版本标签。 可以修改示例数据块以包含如下所示的变量:

LABEL=BUILD47

然后,假设源代码管理系统使用 at 符号 (@) 来指示标签,你可以按如下方式修改 SRCSRVCMD 变量:

sd.exe -p %fnvar%(%var2%) print -o %srcsrvtrg% -q %depot%/%var3%@%label%

源服务器的工作原理

源服务器客户端在 Symsrv.dll 中实现。 此客户端并不直接从 PDB 文件中提取信息;它使用符号处理程序,例如在 Dbghelp.dll 中实现的符号处理程序。 它本质上是一个递归变量替换引擎,用于创建一个命令行,此命令行可用于从源控制系统中提取正确的源文件。 代码不应直接调用 Symsrv.dll。 若要将其功能集成到应用程序中,请使用 SymGetSourceFile 函数。

源服务器的第一个版本的工作方式如下。 此行为在将来的版本中可能会更改。

  • 此客户端调用 SrcSrvInit 函数,并将目标路径用作所有源文件提取的基础路径。 它将此路径存储在 TARG 变量中。
  • 当加载模块 PDB 并调用 SrcSrvLoadModule 函数将数据块传递给源服务器时,此客户端会从 PDB 中提取 Srcsrv 流。
  • 当 Dbghelp 检索源文件时,此客户端会调用 SrcSrvGetFile 函数以从源代码管理中检索源文件。
  • 源服务器会在数据块内的源文件条目中搜索与请求的文件匹配的条目。 它用源文件条目的内容填充 VAR1 到 VARn。 接下来,它将使用 VAR1 到 VARn 来扩展 SRCSRVTRG 变量。 如果文件已在此位置中,则会将此位置返回到调用方。 否则,它会扩展 SRCSRVCMD 变量以生成从源代码管理检索文件并将其复制到目标位置所需的命令。 最后,它将执行此命令。

创建源代码管理提供程序模块

源服务器包括 Perforce (p4.pm) 和 Visual Source Safe (vss.pm) 的提供程序模块。 若要创建你自己的提供程序模块,必须实现以下接口集。

$module::SimpleUsage()

目的:向 STDOUT 显示简单的模块使用情况信息。

参数:无

返回值:无

$module::VerboseUsage()

目的:向 STDOUT 显示深层的模块使用情况信息。

参数:无

返回值:无

$objref = $module::new(@CommandArguments)

目的:初始化提供程序模块的实例。

参数:所有未被 SSIndex.cmd 识别为通用参数的 @ARGV 参数。

返回值:可在后续操作中使用的引用。

$objref->GatherFileInformation($SourcePath, $ServerHashReference)

目的:使模块能够收集 $SourcePath 参数指定的目录的所需源索引信息。 此模块不应假设只会为每个对象实例调用一次该条目,因为 SSIndex.cmd 可能会针对不同的路径调用它多次。

参数:(1) 包含要索引的源的本地目录。 (2) 对包含指定 Srcsrv.ini 文件中的所有条目的哈希的引用。

返回值:无

($VariableHashReference, $FileEntry) = $objref->GetFileInfo($LocalFile)

目的:提供从源代码控制系统中提取单个特定文件所需的信息。

参数:完全限定的文件名

返回值:(1) 解释返回的 $FileEntry 所需的变量的哈希引用。 SSIndex.cmd 会为单个调试文件使用的每个源文件缓存这些变量,以减少写入源索引流的信息量。 (2) 要写入源索引流以允许 SrcSrv.dll 从源代码管理中提取该文件的文件条目。 该行的确切格式特定于源代码控制系统。

$TextString = $objref->LongName()

目的:提供描述性字符串以向最终用户标识源代码管理提供程序。

参数:无

返回值:源代码管理系统的描述性名称。

@StreamVariableLines = $objref->SourceStreamVariables()

目的:使源代码管理提供程序能够将源代码管理特定变量添加到每个调试文件的源流中。 示例模块使用此方法编写所需的 EXTRACT_CMD 和 EXTRACT_TARGET 变量。

参数:无

返回值:源流变量的条目列表。