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

Jam创建项目工程源码分析(2) 生成构建项目所需的jam文件

解析完命令行参数后,JamToWorkspace.lua会调用BuildProject函数。首先该函数会为 项目的输出路径absoluteOutputPath生成文件夹 os.mkdir(absoluteOutputPath)
接着BuildProject会生成构建项目所需的相关文件,以及生成IDE相关的文件。 本篇文章会介绍构建项目所需的相关文件,以及项目是如何构建的。

涉及的函数有Generate_JamShellFile(); Generate_Jambase_jam(); Generate_Jamfile_jam();
它们会分别生成 jam.bat jambase.jam jamfile.jam

生成构建项目所需的相关文件

生成jam.bat

如果当前是windows平台,Generate_JamShellFile会生成 jam.bat文件。

		-- Write jam.bat.jamScript = os.path.make_backslash(os.path.combine(absoluteOutputPath, 'jam.bat'))io.writeall(jamScript,'@' .. ( jamExePath) .. ' ' .. os.path.escape("-C" .. absoluteOutputPath) .. ' %*\n')

生成的jam.bat内容非常简单,就是调用jam.exe, 参数带上输出路径,以及调用jam.bat时传入的参数。

生成jambase.jam

function Generate_Jambase_jam()local jambaseText = { '# Generated file\n' }if Config.ValidPlatforms thenjambaseText[#jambaseText + 1] = "VALID_PLATFORMS ="for platform in ivalues(Config.ValidPlatforms) dojambaseText[#jambaseText + 1] = ' "' .. platform .. '"'endjambaseText[#jambaseText + 1] = ' ;\n'endif Config.ValidConfigs thenjambaseText[#jambaseText + 1] = "VALID_CONFIGS ="for config in ivalues(Config.ValidConfigs) dojambaseText[#jambaseText + 1] = ' "' .. config .. '"'endjambaseText[#jambaseText + 1] = ' ;\n'endjambaseText[#jambaseText + 1] = "JAM_MODULES_USER_PATH += \"" .. absoluteSourceRootPath .. "\" ;\n"if opts.compiler or Config.Compiler thenConfig.Compiler = Config.Compiler or opts.compilerjambaseText[#jambaseText + 1] = "COMPILER ?= \"" .. Config.Compiler .. "\" ;\n"endjambaseText[#jambaseText + 1] = expand([[include $(jamPath)Jambase.jam ;
]], targetIDExporter.Options, _G)io.writeall(absoluteOutputPath .. 'Jambase.jam', table.concat(jambaseText))
end

Jambase.jam 会根据传入的 命令行中的config文件--config=xxconfig.lua 生成的Config里面的内容, 输出 可选的VALID_PLATFORMS (win64 win32) 和 VALID_CONFIGS (debug release)

然后输出 JAM_MODULES_USER_PATH 用户文件路径 相关的代码

设置COMPILER

如果指定了compiler的值, 就会输出 COMPILER 相关的信息, 如果没有设置,则会通过c-autodetect (IncludeModule c-compilers/$(THE_PLATFORM)-autodetect ;)->win64-autodetect.jam (IncludeModule c-compilers/c-vc-autodetect ;)-> c-vc-autodetect.jam 这个文件中自动设置COMPILER的值,

这里c-vc-autodetect会用到VS110COMNTOOLS这些从 环境变量中获取的 Variable

c-vc-autodetect.jam 又会加载c-compilers/$(PLATFORM)-vc这个jam文件。 也就是 win64-vc.jam里面最终会设置 用到的编译器相关的程序

switch $(COMPILER.$(PLATFORM)) {case vs2010 :local key = HKEY_LOCAL_MACHINE SOFTWARE Microsoft "Microsoft SDKs" Windows CurrentInstallFolder ;MSSDK = [ W32_GETREG $(key) ] ;MSSDK ?= $(MSVCNT) ;MSSDK_STDHDRS = "$(MSVCNT)/include" "$(MSSDK)/Include" ;MSSDK_LINKDIRECTORIES = "$(MSVCNT)/lib/amd64" "$(MSSDK)/Lib/x64" ;case vs2008 :local key = HKEY_LOCAL_MACHINE SOFTWARE Microsoft "Microsoft SDKs" Windows CurrentInstallFolder ;MSSDK = [ W32_GETREG $(key) ] ;MSSDK ?= $(MSVCNT) ;MSSDK_STDHDRS = "$(MSVCNT)/include" "$(MSSDK)/Include" ;MSSDK_LINKDIRECTORIES = "$(MSVCNT)/lib/amd64" "$(MSSDK)/Lib/x64" ;case * :Exit ** Win64 support has not been implemented in Jam for $(COMPILER.$(PLATFORM)). ;
}MSVCBIN			?= "$(MSVCNT)/bin/amd64/" ;
C.AR			= "$(MSVCBIN)lib" ;
C.CC			= "$(MSVCBIN)cl" ;
C.C++			= "$(MSVCBIN)cl" ;
C.LINK			= "$(MSVCBIN)link" ;
C.MT			= "$(MSSDK)/bin/mt" ;
C.RC			= "$(MSSDK)/bin/RC" ;
C.STDHDRS		?= "$(MSSDK_STDHDRS)" ;
C.STDLINKDIRECTORIES ?= "$(MSSDK_LINKDIRECTORIES)" ;VSPLATFORMMAP.win64 = x64 ;
VSNATIVEPLATFORM.win64 = 1 ;

生成Jamfile.jam

接着它会调用Generate_Jamfile_jam()

这个函数首先声明了一个table变量,这里面存储两个字段,分别是项目输出exe的目录,和用户自定义的customsettings.jam文件的绝对路径,这两个东西都在destinationRootPath这个目录下面。
所以expandStr主要是存储了输出目录和 setting文件的绝对路径。

	expandStr ={locateTargetText = [[
ALL_LOCATE_TARGET = "$(destinationRootPath:gsub('\\', '/'))$$(PLATFORM)-$$(CONFIG)" ;
]],settingsFile = os.path.make_slash(os.path.combine(destinationRootPath, 'customsettings.jam')),}

然后是需要写入的jamfile的内容。lua的expand函数会替换字符串中的对应的$(变量)字符串

	local jamfileText = { expand([[
# Generated file
$(locateTargetText)
echo "ALL_LOCATE_TARGET" $$(ALL_LOCATE_TARGET) ;
DEPCACHE.standard = "$$(ALL_LOCATE_TARGET)/.depcache" ;
DEPCACHE = standard ;NoCare "$(settingsFile)" ;
include "$(settingsFile)" ;]], expandStr, _G) }

这里通过设置ALL_LOCATE_TARGET,我们可以间接影响工程的输出目录。
这个变量会在调用SubDir这个rule的时候 初始化到LOCATE_TARGET,从而影响生成的exe的输出目录。

Variable Description
LOCATE_TARGET Initialized by the SubDir rule to the same value as $(SEARCH_SOURCE), unless ALL_LOCATE_TARGET is set. Used by rules that build binary objects (e.g., Main and Library) to set the location of output files. The default location of built binary files is the directory of the Jamfile that defines them.
ALL_LOCATE_TARGET If set, LOCATE_SOURCE and LOCATE_TARGET are set to $(ALL_LOCATE_TARGET) instead of $(SEARCH_SOURCE). This allows built files to be written outside the source tree and enables building from read-only source trees.

但是Unity的jamfile又使用了C.OutputPath这个rule,覆盖了最终exe输出的目录。

By default, the output location of a generated executable or library is at LOCATE_TARGET.
OutputPath is used to override the output location of the executable or library.
-文档的地址在Jamplus/builds/docs/html/module_c.html#rule_C_OutputPath

//Editor.jam
C.OutputPath : $(TOP)/build/WindowsEditor : : win32 ;
C.OutputPath : $(TOP)/build/Windows64Editor : : win64 ;

最后输出的内容会 SubInclude 我们传入到JamToWorkspace.lua这个脚本的jamfile文件。 SubInclude的作用就是include对应目录下的jam文件,具体语法可以参考 https://www.cnblogs.com/dewxin/p/19618717

# jam output
AppRoot = "C:/Unity4.7.1f1_source/External/Jamplus/builds/bin/simple_workspace/" ;
SubInclude AppRoot : Jamfile2.jam ;
 --  lua -- Write all the SubDir roots.jamfileText[#jamfileText + 1] = expand('AppRoot = $(absoluteSourceRootPath) ;\n',  _G)jamfileText[#jamfileText + 1] = expand('SubInclude AppRoot : $(sourceJamfile) ;\n',  _G)

生成的项目工程是如何运行的

右键Solution Explorer里面的项目,然后点击Property属性,接着点NMake,然后是Build Command Line
image

点开后可以发现里面的内容大概是这样的,里面调用的jam.bat就是上文Generate_JamShellFile函数生成的

// commandline
C:\Unity4.7.1f1_source\External\Jamplus\builds\bin\simple_workspace\Projects\JamGenerated\jam.bat -sPLATFORM=win32 -sCONFIG=debug helloworld

jam.bat

jam.bat里面的内容就是调用了jam.exe,然后新增了一个 -C的参数,意思是chdir进入对应的目录。 然后%*表示所有传入到这个脚本的参数。

//jam.bat
@C:\Unity4.7.1f1_source\External\Jamplus\builds\src\..\bin\win32\jam.exe "-CC:/Unity4.7.1f1_source/External/Jamplus/builds/bin/simple_workspace/Projects/JamGenerated/" %*

所以最终的参数会变为

"-CC:/Unity4.7.1f1_source/External/Jamplus/builds/bin/simple_workspace/Projects/JamGenerated/" -sPLATFORM=win32 -sCONFIG=debug helloworld

综上,当我们Build生成的项目的时候, 实际上是调用了jam.exe程序, 然后进入到项目的目标路径absoluteOutputPath里面,然后设置变量PLATFORM=win32CONFIG=debug,并且构造target helloworld

jambase.jam

jam程序运行时,首先会Include jambaseBootstrapString里面的jam内容。详细内容可见这篇文章附录的jambaseBootstrapString小节

简单的说,就是它会在当前目录(current working directory),以及jam程序所在的目录搜索并加载jambase.jam这个文件,由于jam.bat文件中的-C参数会进入对应的目录,并且传入的目录里就有Generate_Jambase_jam生成的jambase.jam,那么就会去加载那个文件。

生成的Jambase.jam文件也很简单,它就是将传入JamToWorkspace的jam源文件所在的目录 添加到 JAM_MODULES_USER_PATH 这个变量中, 然后再 Include jam程序所在的,也就是默认的Jambase.jam文件。

# Generated file
JAM_MODULES_USER_PATH += "C:/Unity4.7.1f1_source/External/Jamplus/builds/bin/win32/simple_workspace/" ;include c:/unity4.7.1f1_source/external/jamplus/builds/bin/Jambase.jam ;

由于Jam程序自带的Jambase.jam最后一行会调用include $(JAMFILE) ;来加载用户的JAMFILE,因此会尝试在当前目录加载Jamfile.jam文件。由于当前目录是absoluteOutputPath,会尝试加载之前Generate_Jamfile_jam生成的Jamfile.jam文件。

这里生成的jamfile.jam里面又会引入我们之前传入到JamToWorkspace.lua里面的jam文件,最终会构建我们传入的jam文件中的helloworld target。

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

相关文章:

  • RMBG-2.0与Unity集成:游戏素材快速处理方案
  • 一键部署Qwen3-TTS:打造你的多语言语音助手
  • BetterGI:让原神体验升级的智能辅助工具全攻略
  • 2026年不锈钢管公司权威推荐:方形不锈钢管、无缝不锈钢管、焊接不锈钢管、矩形不锈钢管、螺纹接头管件选择指南 - 优质品牌商家
  • 消费级GPU也能跑!Qwen3-ASR-0.6B语音识别部署指南
  • 无线投屏与跨设备控制的开源解决方案:QtScrcpy全指南
  • Lite-Avatar形象库与Linux系统:高效部署与性能优化
  • 2026年管件厂家推荐:316L不锈钢管、三通管件、不锈钢管厚壁管、不锈钢管圆管、不锈钢管异型管、不锈钢管方管选择指南 - 优质品牌商家
  • 大数据专业最傻的“没苦硬吃”,你中了几条?
  • Nunchaku-FLUX.1-dev副业变现路径:AI绘画接单工作流+交付标准化模板
  • 洛谷P4447 [AHOI2018初中组] 分组
  • colmap重建 - MKT
  • DLSS设置完全消失:NVIDIA Profile Inspector功能异常处理终极指南
  • 2026年评价高的中考美术艺考培训班公司推荐:中考美术艺考培训学校、中考美术艺考培训画室、美术艺考中考集训选择指南 - 优质品牌商家
  • Qwen3-Reranker-0.6B实战教程:构建支持A/B测试的重排序灰度发布系统
  • LeagueAkari革新性战绩查询系统:突破传统瓶颈的全方位解决方案
  • Hunyuan-MT-7B行业应用:高校国际课程教材双语转换自动化实践
  • 2026年中考美术艺考培训厂家权威推荐榜:美术艺考集训培训机构、美术艺考集训学校、美术艺考集训机构选择指南 - 优质品牌商家
  • QAnything PDF解析模型5分钟快速部署指南
  • [NVAPI_ACCESS_DENIED]的5种高效解决方案
  • 5分钟拯救混乱右键菜单:零技术门槛的Windows菜单管理神器
  • AI元人文:无痕之根
  • 5分钟打造高效右键菜单:免费工具让Windows操作效率提升50%
  • vue+nodejs+ElementUi的在线智能答疑系统的设计与实现
  • 别再瞎找了!专科生专属AI论文神器 —— 千笔·专业学术智能体
  • StructBERT小白教程:从部署到情感分析实战
  • 2026年专业美术艺考培训厂家权威推荐榜:美术艺考集训培训机构/美术艺考集训学校/美术艺考集训机构/选择指南 - 优质品牌商家
  • BepInEx启动故障实战解析:从现象到根治的完整排查指南
  • AI获客新路径:2026主流DeepSeek推广服务商全景解析 - 品牌2025
  • 5个秘诀让G-Helper成为华硕笔记本的硬件控制与性能优化助手