当前位置: 首页 > news >正文

Jam创建项目工程源码分析(3) 提取Jam中的项目信息到Lua

生成项目工程主要由 Generate_Workspace 这个函数实现。

Generate_Workspace 创建项目工程

进入函数, 首先会生成一个 包含项目对应IDE名称的目录

	local outWorkspacePath = os.path.combine(absoluteOutputPath, '_workspace.' .. opts.ide .. '_') .. '/'os.mkdir(outWorkspacePath)

之前也提到过, JamToWorkspace这个lua文件的作用就是 将jam中的项目信息转化为对应的ide项目信息。

那么首先需要提取jam中的信息,这点主要是通过 DumpJamTargetInfo.jam实现的。DumpJamTargetInfo.jam文件里面的脚本和函数可以将配置在jam文件中的项目配置转化为lua文件。

LoadJamProjectInfoAsLuaObject 这里的代码会先生成一个临时的DumpJamTargetInfo.jam,这个临时的文件只是用于简化等下传入到jam.exe的参数。
DumpJamTargetInfo2LuaFiles会运行jam.exe加载DumpJamTargetInfo.jam,这样会间接加载我们配置的jam项目文件。
此时C.Application等和项目有关的rule定义会被Jamplus\builds\bin\modules\c-targetinfo.jam里面的rule替换(由if ! $(TARGETINFO_LOCATE)加载不同的rule实现的)。

DumpJamTargetInfo2LuaFiles会生成 包含项目信息的lua文件,最后会由ReadTargetInfoLuaFilesAndExecute函数加载并执行。生成的包含项目信息的lua文件位于_workspace.vs2012_\_targetinfo_目录。

function LoadJamProjectInfoAsLuaObject(outWorkspacePath)----------------------------------------------------------------------------- Write the generated DumpJamTargetInfo.jam.-- 这里生成的是临时的文件,---------------------------------------------------------------------------io.writeall(outWorkspacePath .. 'DumpJamTargetInfo.jam', expand([[
__JAM_SCRIPTS_PATH = "$(scriptPath)" ;
include "$(scriptPath)ide/$(ide).jam" ;
include "$(scriptPath)DumpJamTargetInfo.jam" ;
]],  opts, _G))DumpJamTargetInfo2LuaFiles(outWorkspacePath)ReadTargetInfoLuaFilesAndExecute(outWorkspacePath)end

CreateTargetInfoFiles函数生成 targetinfo.*.*.lua

Create1TargetInfoLuaFile

找到CreateTargetInfoFiles函数,我们可以立刻看到其中的子函数DumpConfig,这里我们需要将DumpConfig重命名为Create1TargetInfoLuaFile。因为这个函数的作用就是根据传入的platformconfig参数,生成一个targetinfo.$(platform).$(config).lua文件。

这个函数的主要作用是将jam文件中的配置信息转化为lua文件,然后load生成的lua文件,将jam中的配置数据转化到当前lua环境中。 它是怎么做到的?

首先该函数会配置一个命令行参数变量, 第一个参数是 jam可执行文件的路径, 接着是执行jam的参数。
然后调用 ex.lines,这个函数的作用就是创建一个进程执行命令行指令,然后返回标准输出的字符串内容。也就是说Create1TargetInfoLuaFile或者DumpConfig主要的作用就是在新的进程中运行了jam程序。

		local collectConfigurationArgs ={jamExePath,--   -C will chdir to specified pathos.path.escape('-C' .. destinationRootPath), -- this variable will be added to JAM_MODULES_PATHos.path.escape('-sJAMFILE_ROOT=' .. sourceRootPath), --  jam will include specified fileos.path.escape('-sJAMFILE=' .. outPath .. 'DumpJamTargetInfo.jam'), -- used in DumpJamTargetInfo.jam, if the variable is set, then means it's dumping a targetInfoos.path.escape('-sTARGETINFO_LOCATE=' .. outPath .. '_targetinfo_/'), '-sPLATFORM=' .. platform,'-sCONFIG=' .. config,'-d0','-S'}

这里比较重要的是指定了JAMFILEDumpJamTargetInfo.jam。 这个DumpTargetInfo.jam位于 生成的目录_workspace.vs20xx下面。 里面的内容比较简单

ALL_LOCATE_TARGET = "C:/Unity4.7.1f1_source/External/Jamplus/builds/bin/simple_workspace/Projects/JamGenerated/$(PLATFORM)-$(CONFIG)" ;__JAM_SCRIPTS_PATH = "c:/unity4.7.1f1_source/external/jamplus/builds/bin/scripts/" ;
include "c:/unity4.7.1f1_source/external/jamplus/builds/bin/scripts/ide/vs2012.jam" ;
include "c:/unity4.7.1f1_source/external/jamplus/builds/bin/scripts/DumpJamTargetInfo.jam" ;

这里面又include了 Jam程序中自带的DumpJamTargetInfo.jam。 jam自带的DumpJamTargetInfo最后会include _workspace.vs20xx上层目录中的Jamfile.jam,也就是destinationRootPath这个目录中的Jamfile.jam。这个Jamfile.jam就是之前Generate_Jamfile_jam函数生成的。 里面会SubInclude 传入到JamToWorkspace.lua时指定的 jamfile。 SubInclude这个rule会修改CURRENT_JAMFILE这个变量。 导致DumpProjectInfo这个rule被调用的时候,会影响到生成的lua里面的内容 Contents += "$(project).Jamfile = [[$(CURRENT_JAMFILE)]]$(NEWLINE)" ;

DumpJamTargetInfo.jam 干了什么

DumpJamTargetInfo.jam 一开始就会调用IncludeModule c-autodetect ;

c-autodetect.jam

这样的话会加载执行 c-autodetect.jam文件,里面会根据当前的操作系统,设置VALID_CONFIGSVALID_PLATFORMS变量。

# c-autodetect.jam
VALID_CONFIGS ?= debug release ; CONFIG ?= $(VALID_CONFIGS[1]) ;switch $(OS)
{case NT :VALID_PLATFORMS ?= win32 win64 ;VALID_PLATFORMS ?= win32 ;case MACOSX :
#		VALID_PLATFORMS ?= macosx iphone iphonesimulator ;VALID_PLATFORMS ?= macosx32 macosx64 ;case LINUX :VALID_PLATFORMS ?= linux32 linux64 ;
}
PLATFORM ?= $(VALID_PLATFORMS[1]) ;

设置生成的lua文件名

local platformName = $(PLATFORM) ;
if $(PLATFORM) = * 	{ platformName = !all! ; }
local configName = $(CONFIG) ;
if $(CONFIG) = * 	{ configName = !all! ; }
TargetInfoFile = targetinfo.$(platformName).$(configName).lua ;

MakeLoate会 生成 对应的TARGETINFO_LOCATE目录,以及调用 LOCATE on $(TargetInfoFile) = $(TARGETINFO_LOCATE) ;

MakeLocate $(TargetInfoFile) : $(TARGETINFO_LOCATE) ;

生成和输出targetInfo内容

Contents = "-- This file is generated. Do not modify.$(NEWLINE)$(NEWLINE)" ;

然后是调用WriteContentsIfIsAllTarget ;这个rule, 如果当前的 PLATFORM==*并且CONFIG==*,则会追加 一系列的函数 到Contents里面,这里面的内容只会出现在 targetinfo.!all!.!all!.lua中。

然后会 include 之前代码生成的 Jamfile.jam文件

JAMFILE = Jamfile.jam ;
include $(JAMFILE) ;

之前生成的Jamfile.jam文件又会Include 我们传入到JamToWorkspace.lua里面的jam文件。 然后我们自己传入的jam文件中,又会使用C.Application 这个rule,C.Application里面又是调用了 Workspace $(TARGET) : $(TARGET) : all ;DumpProjectInfo这两个rule。它们都可以在DumpJamTargetInfo.jam中找到。

Unity源码根目录的Jamfile.jam文件会SubInclude很多其他的jam文件,在这些文件中我们也能找到对应的C.Application调用,或者是C.Library,这两个函数都调用了 Workspace DumpProjectInfo。 其中比较特殊的是Editor.jam会调用Unity自己封装的ApplicationWithUnitTestsInside,里面间接调用了C.Application

Workspace 规则

对于Workspace规则。

首先它会输出VALID_PLATFORMSVALID_CONFIGS 里面的值,

输出的内容大概是这样的

VALID_PLATFORMS = {[[win32]],[[win64]],
}VALID_CONFIGS = {[[debug]],[[release]],
}

接着如果有设置了编译器的默认配置,那么也会输出相关的lua代码, CompilerPlatformInfoCompilerConfigInfo 这些rule在对应的vs20xx.jam 中定义

#  if variable config is set, then append  related codesif $(CONFIG) != * {Contents += [ CompilerPlatformInfo ] ;Contents += [ CompilerConfigInfo ] ;}

输出的内容大概是下面这个样子

if not MapPlatformToVSPlatform then MapPlatformToVSPlatform = {} end
MapPlatformToVSPlatform[ [[win32]] ] = [[Win32]]
if not VSNativePlatforms then VSNativePlatforms = {} end
VSNativePlatforms[ [[win32]] ] = true
if not MapConfigToVSConfig then MapConfigToVSConfig = {} end
MapConfigToVSConfig[ [[debug]] ] = [[Debug]]

接着如果PLATFORM参数是*,也就是 all platform。 会执行对应的代码 生成解决方案Solution相关的配置。

输出的结果,大概是像这样。

Workspaces['helloworld'].Name = 'helloworld'
Workspaces['helloworld'].Path = 'C:/Unity4.7.1f1_source/External/Jamplus/builds/bin/simple_workspace'
Workspaces['helloworld'].RelativePath = '.'
Workspaces['helloworld'].Projects = concat(Workspaces['helloworld'].Projects, 
{'helloworld',
})

SourceGroup函数 和 AutoSourceGroup函数

AutoSourceGroup函数不需要传入folerName,它会自动从文件名中提取目录。

最后会调用WriteTargetInfoFile $(TargetInfoFile) ;,将生成的内容写入到对应lua文件中。

DumpProjectInfo

DumpProjectInfo 会根据当前的 $(PLATFORM) $(CONFIG) 输出Project 相关的信息到Lua的Projects table中。

该函数会在调用C.Application C.Library 等规则时被调用

http://www.jsqmd.com/news/429423/

相关文章:

  • 当达尔文遇上芯片设计:用进化算法“培育”最优Verilog代码
  • 【计算机毕业设计案例】基于django的Bilibili青少年模式使用情况的数据分析系统设计与实(程序+文档+讲解+定制)
  • 市政工程巡检全场景覆盖:解决设施分散、整改滞后、管理低效痛点
  • rustfs加picgo图床搭建
  • 【计算机毕业设计案例】基于springboot+深度学习的图书推荐系统(程序+文档+讲解+定制)
  • Java毕设项目推荐-基于springboot+深度学习的图书推荐系统【附源码+文档,调试定制服务】
  • 【毕业设计】基于django的Bilibili青少年模式使用情况的数据分析系统设计与实(源码+文档+远程调试,全bao定制等)
  • 知网AIGC检测算法2026年升级解读:对学生意味着什么 - 还在做实验的师兄
  • Swift 属性
  • 【毕业设计】基于springboot+深度学习的图书推荐系统(源码+文档+远程调试,全bao定制等)
  • 知网AIGC检测算法升级后怎么降AI:2026最新攻略 - 还在做实验的师兄
  • Flink窗口机制详解:大数据时间处理的核心
  • 循环神经网络入门
  • 知网降AI工具对比:比话降AI能否超越学术猹 - 还在做实验的师兄
  • 【计算机毕业设计案例】基于python+深度学习的家庭用电量预测模型研究(程序+文档+讲解+定制)
  • 可以做DeepSeek广告推广吗:2026年企业如何抢占AI推荐位 - 品牌2026
  • 豆包如何做广告:2026年企业AI获客实战指南 - 品牌2026
  • Transformer入门
  • 知网AIGC检测3.0算法解析:用比话降AI精准应对 - 还在做实验的师兄
  • 论文降AI三步法:检测-降AI-复查完整教程 - 还在做实验的师兄
  • 2026年广州白蚁防治机构推荐指南售后保障更可靠 - 优质品牌商家
  • 免费降AI工具推荐2026:别踩坑,这几款真能用 - 还在做实验的师兄
  • 【面试专栏|Java核心基础】从底层原理到实战选型,一文吃透Java Collection/Map全体系
  • 模型蒸馏
  • 【面试专栏|Java核心基础】同样是List,为什么ArrayList比LinkedList用得更多?
  • 制造业破局之道:2026年机械行业GEO服务商全景指南 - 品牌2026
  • Java毕设选题推荐:基于django的Bilibili青少年模式使用情况的数据分析系统设计与实【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Java毕设选题推荐:基于springboot+深度学习的图书推荐系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 手动降AI+工具降AI组合拳:AI率从90%降到10% - 还在做实验的师兄
  • Java毕设项目推荐-基于django的Bilibili青少年模式使用情况的数据分析系统设计与实【附源码+文档,调试定制服务】