#!/usr/bin/env omake #---------------------------------------------------------------------------- # Project: Horizon # File: testutil.om # # Copyright 2007-2009 Nintendo. All rights reserved. # # These coded instructions, statements, and computer programs contain # proprietary information of Nintendo of America Inc. and/or Nintendo # Company Ltd., and are protected by Federal copyright law. They may # not be disclosed to third parties or copied or duplicated in any form, # in whole or in part, without the prior written consent of Nintendo. # # $Date:: 2010-08-20#$ # $Rev: 24283 $ # $Author: takiguchi_shinichi $ #---------------------------------------------------------------------------- LOADRUN = $(absname $(ROOT_TOOLS)$(DIRSEP)CommandLineTools$(DIRSEP)ctr_loadrunf32.exe) DEFAULT_RUN_TIMEOUT = 60 DEFAULT_EXIT_PATTERN= $"CU_TEST_EXIT|KernelPanic|nn::svc::Break\(" # UNIQUE_ID を指定して cia を生成します。 public.MakeCiaByID(filename, id, sources, rsf) = depends = CTR_APPTYPE = NAND objects[] = target_program = $(filename) UNIQUE_ID = 0x$(id) MAKEROMFLAGS += -DUNIQUE_ID=$(UNIQUE_ID) TITLE = $(filename) ROM_SPEC_FILE = $(rsf) if $(not $(defined DESCRIPTOR)) DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/Application.desc export section if $(defined TESTCIA_ROMFS_ROOT) ROMFS_ROOT = $(TESTCIA_ROMFS_ROOT) export ROMFS_ROOT else ROMFS_ROOT = export ROMFS_ROOT foreach(target, $(BUILDER.getTargets $(SUPPORTED_TARGETS))) if $(defined UserRunProcess) depends += $(UserRunProcess $(target), $(target_program), $(sources) $(objects)) export depends else depends += $(UserProcess $(target), $(target_program), $(sources) $(objects)) export depends export depends export depends return $(filter %$(EXT_CIA), $(depends)) # UNIQUE_ID の範囲を指定して cia を生成します。 public.MakeCiaByIDRange(id_s, id_e, sources, rsf) = depends = id_s_denary = $(int 0x$(id_s)) id_e_denary = $(int 0x$(id_e)) idx = $(id_s_denary) while $(lt $(idx), $(add $(id_e_denary), 1)) id_hex = $(sprintf $"%05X", $(idx)) depends += $(MakeCiaByID $(id_hex), $(id_hex), $(sources), $(rsf)) idx = $(add $(idx), 1) return $(depends) # cfa を作成します。(出力先指定付) public.FileArchiveWithOutdir(srcdir, outdir, rsf) = name = $(basename $(srcdir)) SOURCES_BASE_ROOT = $(dirname $(srcdir)) CFAFile = $(makeDirectory $(outdir))$(DIRSEP)$(name)$(EXT_CFA) if $(not $(defined ARCHIVE_DEPENDENCIES)) ARCHIVE_DEPENDENCIES = $(ls -R, $(dir $(srcdir))) export ARCHIVE_DEPENDENCIES += $(rsf) $(CFAFile): $(makeDirectory $(dirname $(CFAFile))) $(CFAFile): $(srcdir) $(MAKEROM) $(rsf) $(ARCHIVE_DEPENDENCIES) $(MAKEROM) -o $@ -DROMFS_ROOT=$(srcdir) $(MAKEROMFLAGS) -f data -rsf $(rsf) return $(CFAFile) # コンテンツを含む cia を生成します。 public.MakeCiaWithContents(filename, contents, rsf) = depends = CTR_APPTYPE = NAND title_contents[] = target_title = $(filename) TITLE = $(filename) UNIQUE_ID = 0xFE000 MAKEROMFLAGS += -DUNIQUE_ID=$(UNIQUE_ID) ROM_SPEC_FILE = $(rsf) idx = 0 foreach(content, $(contents)) title_contents += $(idx)>$(content) idx = $(add $(idx), 1) export if $(defined Title) foreach(target, $(BUILDER.getTargets $(SUPPORTED_TARGETS))) depends += $(Title $(target), $(target_title), $(title_contents)) export depends export depends return $(depends) # マニュアルを含む cia を生成します。 public.MakeCiaWithManual(filename, id, sources, rsf, manualdir) = section MANUAL_DIR = $(manualdir) return $(MakeCiaByID $(filename), $(id), $(sources), $(rsf)) # 任意の大きさのファイルを生成します。 public.MakeSpecifiedSizeFile(datafile, filesize) = filedir = $(dirname $(datafile)) $(datafile): $(makeDirectory $(filedir)) section rm -f $(filedir)/* f = $(fopen $@, w) try lseek($(f), $(sub $(filesize), 3), SEEK_SET) fprint($(f), end) catch RuntimeException(e) idx = 0 while $(lt $(idx), $(filesize)) fprint($(f), A) idx = $(add $(idx), 1) close($(f)) return $(datafile) # romfs に任意の大きさのファイルをもつ cia を生成します。 public.MakeCiaWithRomfs(filename, id, filesize, sources, rsf) = section TESTCIA_ROMFS_ROOT = $(getOutputBaseDirectory)/$(SUBDIR_OBJECTS)/$(getModuleSubDirectory)/files_$(id) datafile = $(TESTCIA_ROMFS_ROOT)/data.txt ROMFS_DEPENDENCIES = $(MakeSpecifiedSizeFile $(datafile), $(filesize)) return $(MakeCiaByID $(filename), $(id), $(sources), $(rsf)) # ファイルを romfs_dir へコピーします。 public.CopyIntoRomfsroot(romfs_dir, srces) = copiedfiles = foreach(TARGET, $(BUILDER.getTargets $(SUPPORTED_TARGETS))) foreach(src, $(srces)) filename = $(basename $(src)) romfsroot = $(TARGET.getImageDirectory false)/$(romfs_dir) copiedfile = $(romfsroot)/$(filename) copiedfiles += $(copiedfile) $(copiedfile): $(src) $(makeDirectory $(romfsroot)) cp $(src) $(copiedfile) export copiedfiles export copiedfiles return $(copiedfiles) # ターゲット別に生成されているファイルを romfs_dir へコピーします。 public.CopyIntoRomfsrootFilteredByTarget(romfs_dir, srces) = copiedfiles = foreach(TARGET, $(BUILDER.getTargets $(SUPPORTED_TARGETS))) target_srces = foreach(src, $(srces)) dirs = $(split /, $(split \\, $(src))) if $(and $(mem $(TARGET.getFullnameWithSystem Process), $(dirs)), $(mem $(TARGET.buildtype), $(dirs))) target_srces += $(src) export target_srces export target_srces foreach(src, $(target_srces)) filename = $(basename $(src)) romfsroot = $(TARGET.getImageDirectory false)/$(romfs_dir) copiedfile = $(romfsroot)/$(filename) copiedfiles += $(copiedfile) $(copiedfile): $(src) $(makeDirectory $(romfsroot)) cp $(src) $(copiedfile) export copiedfiles export copiedfiles return $(copiedfiles) # ファイルを開き、一行ずつ読み込みます。 public.ReadFileLine(filename) = f = $(fopen $(filename), r) result = while true try result += $(input-line $(f)) export result catch RuntimeException(e) break() export result close($(f)) return $(result) GetARM11Kernel(config) = kernel = $(config.getSuitableKernelFilename) kernel_arm11 = $(gsub $(kernel),Kernel\.ARM946ES\.,Kernel.MPCore.) return $(kernel_arm11) GetProcessList(config) = return $(dirname $(GetARM11Kernel $(config)))$(DIRSEP)process.list GetARM9Kernel(config) = kernel = $(config.getSuitableKernelFilename) kernel_arm9 = $(gsub $(kernel),Kernel\.MPCore\.,Kernel.ARM946ES.) if $(not $(and $(defined TEST_DEBUG_ARM9), $(TEST_DEBUG_ARM9))) kernel_arm9 = $(gsub $(kernel_arm9),Development,Release) kernel_arm9 = $(gsub $(kernel_arm9),Debug,Release) export # PC上のプログラムを実行するクラスです。 HostProgramRunner. = class HostProgramRunner program = new(program) = this.program = $(program) return $(this) run() = $(program) & public.MakeHostProgramRunner(program) = return $(HostProgramRunner.new $(program)) ProgramRunner. = class ProgramRunner new(program, exitpattern, timeout, depends) = this.program = $(program) this.exitPattern = $(exitpattern) this.timeOut = $(timeout) this.depends = $(depends) return $(this) GetDepends() = if $(not $(SKIP_BUILD)) ret[] = $(program) $(depends) return $(ret) return $(EMPTY) run(options, logfile) = dependsoption = foreach( depend, $(depends)) if $(not $(equal $(depend), "")) dependsoption += -rp $(depend) export dependsoption export dependsoption echo $(LOADRUN) $(options) $(dependsoption) -re $(program) -e $(exitPattern) -t $(timeOut) | tee $(logfile) $(LOADRUN) $(options) $(dependsoption) -re $(program) -e $(exitPattern) -t $(timeOut) | tee $(logfile) public.MakeProgramRunnerWithDepends(program, exitpattern, timeout, deps) = return $(ProgramRunner.new $(program),$(exitpattern),$(timeout), $(deps)) public.MakeProgramRunner(program, exitpattern, timeout) = return $(ProgramRunner.new $(program),$(exitpattern),$(timeout), "") public.GetToolPath(programName, ext) = return $(HORIZON_ROOT_IMAGES)$(DIRSEP)tools$(DIRSEP)$(programName)$(DIRSEP)$`(TARGET.getFullnameWithSystem Process)$(DIRSEP)$`(TARGET.buildtype)$(DIRSEP)$(programName)$(ext) # 指定された名前のプロセスの CDI のパスを返します。 public.GetProcessCdiPath(processName) = return @$(GetProcessCdiPathPlain $(processName)) # GetProcessCdiPathの、@付でないパスを返す版 public.GetProcessCdiPathPlain(processName) = if $(filter NuiShell TestMenu, $(processName)) return $(HORIZON_ROOT_IMAGES)$(DIRSEP)processes$(DIRSEP)CTR$(DIRSEP)$(processName)$(DIRSEP)$`(TARGET.getFullnameWithSystem Process)$(DIRSEP)$`(TARGET.buildtype)$(DIRSEP)$(processName).cdi return $(HORIZON_ROOT_IMAGES)$(DIRSEP)processes$(DIRSEP)$(processName)$(DIRSEP)$`(TARGET.getFullnameWithSystem Process)$(DIRSEP)$`(TARGET.buildtype)$(DIRSEP)$(processName).cdi # 指定された複数のプロセスのCDIのパスを返します。 # # 例: # DEPEND_PROCESSES[] = # test_XXXX>$(GetProcessCdiPathList ptm cfg spi) # public.GetProcessCdiPathList(processNames) = pathlist = $(GetProcessCdiPath $(nth 0, $(processNames))) foreach(proc, $(nth-tl 1, $(processNames))) pathlist =$(pathlist),$(GetProcessCdiPath $(proc)) export return $(pathlist) public.GetLoadrunOptionsForTool() = options = if $(and $(defined RUN_NOWAIT), $(RUN_NOWAIT)) options += --no-wait export options return $(options) # 複数ターゲットでプログラムを走らせるためのオブジェクトを作ります。 # DefineMultiTargetTest で使います。 # TODO: 他のテスト実行系と統合する MakeMultiTargetRunner(program, depends, timeOut) = #program = $`(config.getBinaryPath $,(program), $(EXT_CCI)) return $(MultiTargetRunner.new $(program), $(depends), $(DEFAULT_EXIT_PATTERN), $(timeOut)) MultiTargetRunner. = class MultiTargetRunner new(runProgram, cdiDepends, exitPattern, timeOut) = this.runProgram = $(runProgram) this.exitPattern = $(exitPattern) this.cdiDepends = $(cdiDepends) this.timeOut = $(timeOut) return $(this) getOption(config) = option = option += -c0 esc -c0 init # カーネル option += -k11 $(GetARM11Kernel $(config)) option += -k9 $(GetARM9Kernel $(config)) # process.list option += -pl $(GetProcessList $(config)) #プログラム option += foreach( depend, $(cdiDepends) ) value $(array -rp $(depend)) if $(equal $(suffix $(runProgram)), .cdi) option += -rp $(runProgram) export option else option += -re $(runProgram) export option # exitpattern, timeout option += -t $(timeOut) -e $(exitPattern) option += $(GetLoadrunOptionsForTool) return $(option) needLog() = return true getDepends(config) = depends = if $(not $(and $(defined SKIP_BUILD),$(SKIP_BUILD))) depends += $(array $(GetARM11Kernel $(config)) $(GetARM9Kernel $(config)) $(runProgram) $(cdiDepends)) export return $(depends) getLogfilePath(config) = return $(addsuffix .multi.log, $(removesuffix $(runProgram))) # 複数ターゲットに対するテストの実行ルールを定義します。 DefineMultiTargetTest(runners) = BUILD_TESTS = true if $(eq 0,$(length $(filter dotests-multi, $(TARGETS)))) return foreach(TARGET, $(BUILDER.getTargets $(SUPPORTED_TARGETS))) config = $(TARGET) depends = foreach( runner, $(runners) ) value $(runner.getDepends $(config)) outputs = foreach( runner, $(runners) ) value $(runner.getLogfilePath $(config)) if $(not $(defined CTR_RUN_DEVICES)) eprintln(複数ターゲットを使ったテストを実行するには CTR_RUN_DEVICES でターゲットを指定してください。) exit(1) num_runners = $(length $(runners)) devices = $(split $":", $(CTR_RUN_DEVICES)) num_devices = $(length $(devices)) if $(not $(le $(num_runners), $(num_devices))) eprintln(実行したいプログラムの数に対して CTR_RUN_DEVICES に設定されているデバイスの数が足りません。) exit(1) options = foreach( runner, $(runners) ) value $(quote-argv $(runner.getOption $(config))) logfiles = foreach( runner, $(runners) ) value $(runner.getLogfilePath $(config)) dotests-multi: $(depends) :effects: $(outputs) $(LOADRUN) section: i = 0 while $(lt $i, $(num_runners)) option = $(split $" ",$(nth $(i),$(options))) logfile = $(nth $(i),$(logfiles)) device = $(nth $(i),$(devices)) echo loadrunf $(option) -d $(device) $(LOADRUN) $,(option) -d $(device) | tee $(logfile) & sleep 3 i = $(add $i, 1) CategoryParam. = class CategoryParam category = Normal cannot_execution = false # 実行不可 system = false # システム require_batch_update = false # 一括アップデートが必要 not_require_user_approval = false # ユーザ同意が不要 not_require_right_for_mount = false # マウントに権限不要 can_skip_convert_jump_id = false # JumpId 変換スキップ可能 descparam[] = makeromflags = ccflags = new(category, params) = this.category = $(category) foreach(param, $(params)) param_seq = $(split :, $(param)) paramname = $(nth 0, $(param_seq)) val = true if $(equal $(length $(param_seq)), 2) val = $(nth 1, $(param_seq)) export val switch $(paramname) case CannotExecution this.cannot_execution = $(val) export case System this.system = $(val) export case RequireBatchUpdate this.require_batch_update = $(val) export case NotRequireUserApproval this.not_require_user_approval = $(val) export case NotRequireRightForMount this.not_require_right_for_mount = $(val) export case CanSkipConvertJumpId this.can_skip_convert_jump_id = $(val) export default echo $"[testutil.om CategoryParam] Undefined Parameter:" $(paramname) export this.descparam[] += CategoryFlags+=$(this.category) this.makeromflags += -DCATEGORYFLAGS0="- $(this.category)" this.ccflags += -DINFOVIEW_CATEGORY0=\"$(this.category)\" idx = 1 if $(this.cannot_execution) this.descparam[] += CategoryFlags+=CannotExecution this.makeromflags += -DCATEGORYFLAGS$(idx)=$"- CannotExecution" this.ccflags += -DINFOVIEW_CATEGORY1 idx = $(add $(idx), 1) export if $(this.system) this.descparam[] += CategoryFlags+=System this.makeromflags += -DCATEGORYFLAGS$(idx)=$"- System" this.ccflags += -DINFOVIEW_CATEGORY2 idx = $(add $(idx), 1) export if $(this.require_batch_update) this.descparam[] += CategoryFlags+=RequireBatchUpdate this.makeromflags += -DCATEGORYFLAGS$(idx)=$"- RequireBatchUpdate" this.ccflags += -DINFOVIEW_CATEGORY3 idx = $(add $(idx), 1) export if $(this.not_require_user_approval) this.descparam[] += CategoryFlags+=NotRequireUserApproval this.makeromflags += -DCATEGORYFLAGS$(idx)=$"- NotRequireUserApproval" this.ccflags += -DINFOVIEW_CATEGORY4 idx = $(add $(idx), 1) export if $(this.not_require_right_for_mount) this.descparam[] += CategoryFlags+=NotRequireRightForMount this.makeromflags += -DCATEGORYFLAGS$(idx)=$"- NotRequireRightForMount" this.ccflags += -DINFOVIEW_CATEGORY5 idx = $(add $(idx), 1) export if $(this.can_skip_convert_jump_id) this.descparam[] += CategoryFlags+=CanSkipConvertJumpId this.makeromflags += -DCATEGORYFLAGS$(idx)=$"- CanSkipConvertJumpId" this.ccflags += -DINFOVIEW_CATEGORY6 idx = $(add $(idx), 1) export return $(this) isSystem() = if $(this.system) return true return false isContents() = if $(equal $(this.category), Contents) return true return false getDesc() = desc = $(HORIZON_ROOT)/resources/specfiles/Application.desc if $(equal $(this.category), DlpChild) desc = $(HORIZON_ROOT)/resources/specfiles/DlpChild.desc export desc if $(equal $(this.category), Trial) desc = $(HORIZON_ROOT)/resources/specfiles/Trial.desc export desc if $(this.isSystem) desc = $(HORIZON_ROOT)/resources/specfiles/_private/SystemTest.desc export desc return $(desc) # MakeDummyCia に指定する category を作成します。 public.MakeCategoryParam(category, params) = return $(CategoryParam.new $(category), $(params)) # ダミーコンテンツを生成します。 public.MakeDummyContents(name, category, unique_id, contents_dir, numcontents, data_size) = contents[] = testutil_dir = $(ROOT_SOURCES)/libraries/test/util idx_cfa = 0 while $(lt $(idx_cfa), $(numcontents)) section MAKEROMFLAGS += -DUNIQUE_ID=$(unique_id) if $(category.isSystem) MAKEROMFLAGS += -keyfile $(GetSystemFixedKeyFile) export MAKEROMFLAGS if $(category.isContents) MAKEROMFLAGS += -DCONTENTSINDEX=$(idx_cfa) export MAKEROMFLAGS else MAKEROMFLAGS += -DCONTENTSINDEX=0 export MAKEROMFLAGS MAKEROMFLAGS += $(category.makeromflags) cfa_name = content_$(idx_cfa) cfa_dir = $(contents_dir)/$(name)/cfafiles cfa_file = $(cfa_dir)/$(cfa_name)$(EXT_CFA) data_file = $(MakeSpecifiedSizeFile $(contents_dir)/$(name)/$(cfa_name)/data.txt, $(data_size)) $(cfa_file): $(data_file) contents += $(FileArchiveWithOutdir $(dirname $(data_file)), $(cfa_dir), $(testutil_dir)/dummycontent.rsf) idx_cfa = $(add $(idx_cfa), 1) export contents idx_cfa return $(contents) # ダミータイトルを生成します。 public.MakeDummyCia(tar, name, category, unique_id, variation, major_version, minor_version, micro_version, numcontents, titlesize, save_data_size) = cia_file = if $(equal $(tar), CTR) cia_file = $(MakeDummyCiaCtr $(name), $(category), $(unique_id), $(variation), $(major_version), $(minor_version), $(micro_version), $(numcontents), $(titlesize), $(save_data_size)) export cia_file if $(equal $(tar), TWL) cia_file = $(MakeDummyCiaTwl $(name), $(category), $(unique_id), $(variation), $(major_version), $(minor_version), $(micro_version), $(numcontents), $(titlesize), $(save_data_size)) export cia_file return $(cia_file) # CTR用ダミータイトルを生成します。 public.MakeDummyCiaCtr(name, category, unique_id, variation, major_version, minor_version, micro_version, numcontents, titlesize, save_data_size) = objects_dir = $(getOutputBaseDirectory)/$(SUBDIR_OBJECTS)/$(getModuleSubDirectory) testutil_dir = $(ROOT_SOURCES)/libraries/test/util cia_files = # コンテンツを作成します。 contents = if $(gt $(numcontents), 0) data_size = $(div $(titlesize) $(numcontents)) contents = $(MakeDummyContents $(name), $(category), $(unique_id), $(objects_dir), $(numcontents), $(data_size)) export contents foreach(target, $(BUILDER.getTargets $(SUPPORTED_TARGETS))) cia_file = $(target.getImageDirectory false)/$(name)$(EXT_CIA) infoviewer_cxi = if $(not $(category.isContents)) # テストプログラム(パラメータ表示用)を作成します。 infoviewer_name = InfoViewer_$(name) infoviewer_cxi = $(target.getImageDirectory false)/$(infoviewer_name)$(EXT_CXI) srccppfile = $(testutil_dir)/InfoViewer.cpp copycpp = $(target.getObjectDirectory)/$(infoviewer_name).cpp $(copycpp): $(srccppfile) $(makeDirectory $(dirname $(copycpp))) cp $(srccppfile) $(copycpp) sources[] = $(copycpp) LIBS += libnn_demoLite target_program = $(infoviewer_name) TITLE = $(infoviewer_name) ROM_SPEC_FILE = $(testutil_dir)/dummyaxf.rsf ROMFS_DEPENDENCIES = ROMFS_ROOT = MAKEROMFLAGS += -DUNIQUE_ID=$(unique_id) \ -DSAVEDATASIZE=$(save_data_size) \ -DREMASTERVERSION=$(major_version) CCFLAGS += -DINFOVIEW_FILENAME=\"$(basename $(cia_file))\" \ -DINFOVIEW_UNIQUE_ID=\"$(unique_id)\" \ -DINFOVIEW_TITLESIZE=\"$(titlesize)\" \ -DINFOVIEW_SAVEDATASIZE=\"$(save_data_size)\" \ -DINFOVIEW_NUMCONTENTS=\"$(numcontents)\" \ -DINFOVIEW_VARIATION=\"$(variation)\" \ -DINFOVIEW_REMASTERVERSION=\"$(major_version)\" \ -DINFOVIEW_TMDVERSION=\"$(major_version).$(minor_version).$(micro_version)\" \ $(category.ccflags) DESCRIPTOR = $(category.getDesc) DESC_PARAM[] = $(category.descparam) MAKEROMFLAGS += $(category.makeromflags) if $(equal $(category.category), DlpChild) MAKEROMFLAGS += -DVERSION=0 \ -DCHILDINDEX=$(variation) export MAKEROMFLAGS else MAKEROMFLAGS += -DVERSION=$(variation) \ -DCHILDINDEX=0 export MAKEROMFLAGS if $(defined UserRunProcess) infoviewer_files = $(UserRunProcess $(target), $(target_program), $(sources)) else infoviewer_files = $(UserProcess $(target), $(target_program), $(sources)) export infoviewer_cxi # CIA を生成します。 makeciaflags = content_files = idx = 0 if $(infoviewer_cxi) makeciaflags += -i $(join $(infoviewer_cxi), :$(idx)) content_files += $(infoviewer_cxi) idx = $(add $(idx), 1) export makeciaflags content_files idx foreach(content, $(contents)) makeciaflags += -i $(join $(content), :$(idx)) content_files += $(content) idx = $(add $(idx), 1) export makeciaflags content_files idx makeciaflags += -minor $(minor_version) -micro $(micro_version) if $(category.isSystem) makeciaflags += -cxikey $(GetSystemFixedKeyFile) export makeciaflags if $(category.isContents) makeciaflags += -major $(major_version) export makeciaflags $(cia_file): $(content_files) $(makeDirectory $(dirname $(cia_file))) $(MAKECIA) $(MAKECIA) -o $@ $(makeciaflags) cia_files += $(cia_file) export cia_files return $(cia_files) # TWL用ダミータイトルを生成します。 public.MakeDummyCiaTwl(name, category, unique_id, variation, major_version, minor_version, micro_version, numcontents, titlesize, save_data_size) = objects_dir = $(getOutputBaseDirectory)/$(SUBDIR_OBJECTS)/$(getModuleSubDirectory) cia_files = # TWL用ダミーファイルを作成します。 twl_data = $(objects_dir)/twl/twldata.dat if $(not $(file-exists $(twl_data))) twl_data = $(MakeSpecifiedSizeFile $(twl_data), 1024) foreach(target, $(BUILDER.getTargets $(SUPPORTED_TARGETS))) # タイトルを生成します。 cia_file = $(target.getImageDirectory false)/$(name)$(EXT_CIA) content_files = $(twl_data) makeciaflags = -major $(major_version) \ -minor $(minor_version) \ -micro $(micro_version) \ -p $(unique_id) \ -padding $(cia_file): $(content_files) $(makeDirectory $(dirname $(cia_file))) $(MAKECIA) $(MAKECIA) -a $(content_files) -o $@ $(makeciaflags) cia_files += $(cia_file) export cia_files return $(cia_files)