Package: qemu-runner
QEMU RunnerThis project allows creation of self-contained runner for QEMU with embedded command line arguments. Command line arguments are described in files calledlayers. They are simple INI files that can be combined together to express more complex command lines.>cat./arm_virt.ini[general]engine=qemu-system-arm[machine]@=virt

>cat./ram_2G.ini[general]memory=2G

>qemu_make_runner-l./arm_virt.ini./ram_2G.ini-o./my_runner.pyz
>python./my_runner.pyz--dry-runkernel.elfarg1arg2# --dry-run to see effective command line instead of running QEMUqemu-system-arm-machinevirt-kernelkernel.elf-append'arg1 arg2'Resultingmy_runner.pyzfile is ZIP file withqemu_runnerpackage and layers. Runner has no extra dependencies, using only Python 3.8+ standard library. QEMU is found according to search precedence described below.Existing runner can be used as base for next runner.Derived runnerwill contain all layers from base runner along with additional layers specified when deriving. This features allows extending base runner with project specific settings without being aware of base settings.>cat./semihosting.ini[semihosting-config]enable=ontarget=native

>python./my_runner.pyz--layers./semihosting.ini--derive./derived.pyz
>python./derived.pyz--dry-runkernel.elfarg1arg2# --dry-run to see effective command line instead of running QEMUqemu-system-arm-machinevirt-semihosting-configenable=on,target=native-kernelkernel.elf-append'arg1 arg2'Runner provides following features, consult--helpoutput for details:GDB server settingsStart with CPU haltedInspect command lineQEMU search precedenceIf environment variableQEMU_DEVis set, it is used as path to QEMU executable.
If environment variableQEMU_DEVis not set but argument--qemuis specified it is used as path to QEMU executable.IfQEMU_DEVis not set, directories are searched for QEMU executable with name specified asenginein
combined layer:Directory specified byQEMU_DIRenvironment variableDirectory specified by--qemu-dirargumentEach ancestor directory containing runner, up to the root directory andqemusubdirectory at each level.
If runner's path isc:\dir1\dir2\runner.pyz, then following directories are checked:c:\dir1\dir2c:\dir1\dir2\qemuc:\dir1\c:\dir1\qemuc:\c:\qemuRepeat step 2 with path of base runner in case of derived runners with--tract-qemuoption.Repeat step 2 with path of passed as--qemu-dirwhen runner was derived.Directories inPATHenvironment variable.On Windows,PATHEXTvariable is used to determine executable extension.Environment variablesSeveral environment variables influences the way QEMU command line is constructed:QEMU_FLAGS- arguments to be added to the QEMU command line during executionQEMU_RUNNER_FLAGS- arguments will be interpreted exactly as if they were added to runner execution.Example:shell>QEMU_FLAGS='-d int'QEMU_RUNNER_FLAGS='--halted'./runner.pyz--dry-runkernel.elf
qemu-system-arm-machinevirt-dint-S-kernelkernel.elfLayer search precedenceIf layer path is absolute and file is not found, search process fails immediately.If layer path is relative, following directories are searched:Current directoryPackages declaring entry pointqemu_runner_layer_packages(see below)Layer file formatLayersare plain INI files with sections describing QEMU command line. Layers can be combined together allowing user to build bigger command line from simpler building blocks.Values are interpreted as strings unless specified otherwise. When value is described as boolean, values1,yes,trueandonare interpreted as true, values0,no,falseandoffare interpreted as false. Other values are invalid.Section[general]Section[general]describes most common QEMU arguments.Available settings:engine- Name of QEMU executable (e.g.:qemu-system-arm,qemu-system-sparc)cpu- CPU to use in machine (-cpu option)memory- RAM memory size, supports suffixes likeM,G(e.g.20M,4G)gdb(boolean) - If true QEMU will be started with gdbserver enabled.gdb_dev- Use specified value as gdbserver listend address. If not used, default QEMU address will be used (tcp::1234at the time this document is written). Note that specifing onlygdb_devdoes not enable gdbserver.halted- Freeze QEMU CPU at startup.Section[name]Each section corresponds to single QEMU argument, e.g. section[machine]corresponds to-machineargument. Value specified as@key will be used as direct argument value (machine name, device type, etc). Remaining arguments will be added as key-value properties (note: foridproperty see next section).For example, layer:[machine]@=virtusb=ongic-version=2will be translated into-machine virt,usb=on,gic-version=2Section[name:id]As INI file syntax does not allow duplicated section names it is not possible to describe many QEMU arguments without additional syntax:-device,-netdev, etc. These arguments can be differentiated byidproperty which can be specified as section name in formatargument_name:id.For example, layer:[device:d1]@=type1arg1=10arg2=20[device:d2]@=type1arg1=10arg2=20[device:d3]@=type2arg3=10arg4=20translates into:-device type1,id=d1,arg1=10,arg2=20 -device type1,id=d2,arg1=10,arg2=20 -device type2,id=d3,arg3=10,arg4=20Variable resolutionIn sections[name]and[name:id]it is possible to use variables which will be resolved directly before building complete command lines. Variables are in form${VARIABLE_NAME}.Currently available variables:Variable nameValueKERNEL_DIRDirectory containing kernel executable (path is not normalized)How layers are combinedLayers can be combined by applying one layer on top of the another. Operation 'build layerLResultby applying layerLAddon top ofLBase' is defined as follows:[general](exceptcmdline) -LResultcontains all settings from layersLAddandLBase, values inLAddoverride values inLBase[general],cmdlinevalue  -LResultcontainscmdlinefromLBasefollowed byLAdd(command line arguments are combined)[name]IfLBasedoes not contain section[name],LResultwill contain section fromLAdd.IfLBasecontains section[name],LResultwill contain[name]with all settings fromLBaseandLAdd, values inLAddoverride values inLBase.[name:id]The same rules as with section[name]applies,idis treated as part of section name.Note:It is not possible to remove section by applying another layerIt is not possible to changeidpropertyIt is not possible to remove argument from sectionPutting layers into pip-installable packageIt is possible to distribute layers as pure Python package that can be installed usingpip. Layers distributes in that way are always visible and there is no need to specify full path to file.Creating package with layers:Create Python packagelayers_pkg, add empty__init__.pyfile.Put layer files intolayers_pkg/layersfolder, it is possible to use more complex directory structure.AddMANIFEST.infile withrecursive-include layers_pkg/layers *.iniin it.Addsetup.pyfile:fromsetuptoolsimportsetupsetup(name='layers-pkg',version='1.0.0',packages=['layers_pkg'],zip_safe=True,include_package_data=True,entry_points={'qemu_runner_layer_packages':['layers_pkg=layers_pkg']# Always use `package_name=package_name`})Create Python package using tools of your choice (python setup.pyorpyproject-build)Package might contain other files, as it is normal Python package.NOTE:This is simplified process of creating Python package, refer to Python documentation for more details.qemu_runnertools usesqemu_runner_layer_packagesentry point to discover all registered packages, from each entry point module portion is used in search for layers.