1#!/usr/bin/env python3 2# ex:ts=4:sw=4:sts=4:et 3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- 4# 5# Generate Toaster Fixtures for 'poky.xml' and 'oe-core.xml' 6# 7# Copyright (C) 2022 Wind River Systems 8# SPDX-License-Identifier: GPL-2.0-only 9# 10# Edit the 'current_releases' table for each new release cycle 11# 12# Usage: ./get_fixtures --all 13# 14 15import os 16import sys 17import argparse 18 19verbose = False 20 21#################################### 22# Releases 23# 24# https://wiki.yoctoproject.org/wiki/Releases 25# 26# NOTE: for the current releases table, it helps to keep continuing releases 27# in the same table positions since this minimizes the patch diff for review. 28# The order of the table does not matter since Toaster presents them sorted. 29# 30# Traditionally, the two most current releases are included in addition to the 31# 'master' branch and the local installation's 'HEAD'. 32# It is also policy to include all active LTS releases. 33# 34 35# [Codename, Yocto Project Version, Release Date, Current Version, Support Level, Poky Version, BitBake branch] 36current_releases = [ 37 # Release slot #1 38 ['Scarthgap','5.0','April 2024','5.0.0 (April 2024)','Long Term Support (until April 2028)','','2.8'], 39 # Release slot #2 'local' 40 ['HEAD','HEAD','','Local Yocto Project','HEAD','','HEAD'], 41 # Release slot #3 'master' 42 ['Master','master','','Yocto Project master','master','','master'], 43 # Release slot #4 44 ['Whinlatter','5.3','October 2025','5.3.0 (October 2024)','Support for 7 months (until May 2026)','','2.14'], 45 ['Walnascar','5.2','April 2025','5.2.0 (April 2025)','Support for 7 months (until October 2025)','','2.12'], 46 #['Styhead','5.1','November 2024','5.1.0 (November 2024)','Support for 7 months (until May 2025)','','2.10'], 47 #['Nanbield','4.3','November 2023','4.3.0 (November 2023)','Support for 7 months (until May 2024)','','2.6'], 48 #['Mickledore','4.2','April 2023','4.2.0 (April 2023)','Support for 7 months (until October 2023)','','2.4'], 49 #['Langdale','4.1','October 2022','4.1.2 (January 2023)','Support for 7 months (until May 2023)','','2.2'], 50 ['Kirkstone','4.0','April 2022','4.0.8 (March 2023)','Stable - Long Term Support (until Apr. 2024)','','2.0'], 51 #['Honister','3.4','October 2021','3.4.2 (February 2022)','Support for 7 months (until May 2022)','26.0','1.52'], 52 #['Hardknott','3.3','April 2021','3.3.5 (March 2022)','Stable - Support for 13 months (until Apr. 2022)','25.0','1.50'], 53 #['Gatesgarth','3.2','Oct 2020','3.2.4 (May 2021)','EOL','24.0','1.48'], 54 #['Dunfell','3.1','April 2020','3.1.23 (February 2023)','Stable - Long Term Support (until Apr. 2024)','23.0','1.46'], 55] 56 57default_poky_layers = [ 58 'openembedded-core', 59 'meta-poky', 60 'meta-yocto-bsp', 61] 62 63default_oe_core_layers = [ 64 'openembedded-core', 65] 66 67#################################### 68# Templates 69 70prolog_template = '''\ 71<?xml version="1.0" encoding="utf-8"?> 72<django-objects version="1.0"> 73 <!-- Set the project default value for DISTRO --> 74 <object model="orm.toastersetting" pk="1"> 75 <field type="CharField" name="name">DEFCONF_DISTRO</field> 76 <field type="CharField" name="value">{{distro}}</field> 77 </object> 78''' 79 80#<!-- Bitbake versions which correspond to the metadata release -->') 81bitbakeversion_poky_template = '''\ 82 <object model="orm.bitbakeversion" pk="{{bitbake_id}}"> 83 <field type="CharField" name="name">{{name}}</field> 84 <field type="CharField" name="giturl">git://git.yoctoproject.org/poky</field> 85 <field type="CharField" name="branch">{{branch}}</field> 86 <field type="CharField" name="dirpath">bitbake</field> 87 </object> 88''' 89bitbakeversion_oecore_template = '''\ 90 <object model="orm.bitbakeversion" pk="{{bitbake_id}}"> 91 <field type="CharField" name="name">{{name}}</field> 92 <field type="CharField" name="giturl">git://git.openembedded.org/bitbake</field> 93 <field type="CharField" name="branch">{{bitbakeversion}}</field> 94 </object> 95''' 96 97# <!-- Releases available --> 98releases_available_template = '''\ 99 <object model="orm.release" pk="{{ra_count}}"> 100 <field type="CharField" name="name">{{name}}</field> 101 <field type="CharField" name="description">{{description}}</field> 102 <field rel="ManyToOneRel" to="orm.bitbakeversion" name="bitbake_version">{{ra_count}}</field> 103 <field type="CharField" name="branch_name">{{release}}</field> 104 <field type="TextField" name="helptext">Toaster will run your builds {{help_source}}.</field> 105 </object> 106''' 107 108# <!-- Default project layers for each release --> 109default_layers_template = '''\ 110 <object model="orm.releasedefaultlayer" pk="{{rdl_count}}"> 111 <field rel="ManyToOneRel" to="orm.release" name="release">{{release_id}}</field> 112 <field type="CharField" name="layer_name">{{layer}}</field> 113 </object> 114''' 115 116default_layers_preface = '''\ 117 <!-- Default layers provided by poky 118 openembedded-core 119 meta-poky 120 meta-yocto-bsp 121 --> 122''' 123 124layer_poky_template = '''\ 125 <object model="orm.layer" pk="{{layer_id}}"> 126 <field type="CharField" name="name">{{layer}}</field> 127 <field type="CharField" name="layer_index_url"></field> 128 <field type="CharField" name="vcs_url">{{vcs_url}}</field> 129 <field type="CharField" name="vcs_web_url">{{vcs_web_url}}</field> 130 <field type="CharField" name="vcs_web_tree_base_url">{{vcs_web_tree_base_url}}</field> 131 <field type="CharField" name="vcs_web_file_base_url">{{vcs_web_file_base_url}}</field> 132 </object> 133''' 134 135layer_oe_core_template = '''\ 136 <object model="orm.layer" pk="{{layer_id}}"> 137 <field type="CharField" name="name">{{layer}}</field> 138 <field type="CharField" name="vcs_url">{{vcs_url}}</field> 139 <field type="CharField" name="vcs_web_url">{{vcs_web_url}}</field> 140 <field type="CharField" name="vcs_web_tree_base_url">{{vcs_web_tree_base_url}}</field> 141 <field type="CharField" name="vcs_web_file_base_url">{{vcs_web_file_base_url}}</field> 142 </object> 143''' 144 145layer_version_template = '''\ 146 <object model="orm.layer_version" pk="{{lv_count}}"> 147 <field rel="ManyToOneRel" to="orm.layer" name="layer">{{layer_id}}</field> 148 <field type="IntegerField" name="layer_source">0</field> 149 <field rel="ManyToOneRel" to="orm.release" name="release">{{release_id}}</field> 150 <field type="CharField" name="branch">{{branch}}</field> 151 <field type="CharField" name="dirpath">{{dirpath}}</field> 152 </object> 153''' 154 155layer_version_HEAD_template = '''\ 156 <object model="orm.layer_version" pk="{{lv_count}}"> 157 <field rel="ManyToOneRel" to="orm.layer" name="layer">{{layer_id}}</field> 158 <field type="IntegerField" name="layer_source">0</field> 159 <field rel="ManyToOneRel" to="orm.release" name="release">{{release_id}}</field> 160 <field type="CharField" name="branch">{{branch}}</field> 161 <field type="CharField" name="commit">{{commit}}</field> 162 <field type="CharField" name="dirpath">{{dirpath}}</field> 163 </object> 164''' 165 166layer_version_oe_core_template = '''\ 167 <object model="orm.layer_version" pk="1"> 168 <field rel="ManyToOneRel" to="orm.layer" name="layer">1</field> 169 <field rel="ManyToOneRel" to="orm.release" name="release">2</field> 170 <field type="CharField" name="local_path">OE-CORE-LAYER-DIR</field> 171 <field type="CharField" name="branch">HEAD</field> 172 <field type="CharField" name="dirpath">meta</field> 173 <field type="IntegerField" name="layer_source">0</field> 174 </object> 175''' 176 177epilog_template = '''\ 178</django-objects> 179''' 180 181################################# 182# Helper Routines 183# 184 185def print_str(str,fd): 186 # Avoid extra newline at end 187 if str and (str[-1] == '\n'): 188 str = str[0:-1] 189 print(str,file=fd) 190 191def print_template(template,params,fd): 192 for line in template.split('\n'): 193 p = line.find('{{') 194 while p > 0: 195 q = line.find('}}') 196 key = line[p+2:q] 197 if key in params: 198 line = line[0:p] + params[key] + line[q+2:] 199 else: 200 line = line[0:p] + '?' + key + '?' + line[q+2:] 201 p = line.find('{{') 202 if line: 203 print(line,file=fd) 204 205################################# 206# Generate poky.xml 207# 208 209def generate_poky(): 210 fd = open('poky.xml','w') 211 212 params = {} 213 params['distro'] = 'poky' 214 print_template(prolog_template,params,fd) 215 print_str('',fd) 216 217 print_str(' <!-- Bitbake versions which correspond to the metadata release -->',fd) 218 for i,release in enumerate(current_releases): 219 params = {} 220 params['release'] = release[0] 221 params['Release'] = release[0] 222 params['release_version'] = release[1] 223 if not (params['release'] in ('HEAD')): # 'master', 224 params['release'] = params['release'][0].lower() + params['release'][1:] 225 params['name'] = params['release'] 226 params['bitbake_id'] = str(i+1) 227 params['branch'] = params['release'] 228 print_template(bitbakeversion_poky_template,params,fd) 229 print_str('',fd) 230 231 print_str('',fd) 232 print_str(' <!-- Releases available -->',fd) 233 for i,release in enumerate(current_releases): 234 params = {} 235 params['release'] = release[0] 236 params['Release'] = release[0] 237 params['release_version'] = release[1] 238 if not (params['release'] in ('HEAD')): #'master', 239 params['release'] = params['release'][0].lower() + params['release'][1:] 240 params['h_release'] = '?h={{release}}' 241 params['name'] = params['release'] 242 params['ra_count'] = str(i+1) 243 params['branch'] = params['release'] 244 245 if 'HEAD' == params['release']: 246 params['help_source'] = 'with the version of the Yocto Project you have cloned or downloaded to your computer' 247 params['description'] = 'Local Yocto Project' 248 params['name'] = 'local' 249 else: 250 params['help_source'] = 'using the tip of the <a href="https://git.yoctoproject.org/cgit/cgit.cgi/poky/log/{{h_release}}">Yocto Project {{Release}} branch</a>' 251 params['description'] = 'Yocto Project {{release_version}} "{{Release}}"' 252 if 'master' == params['release']: 253 params['h_release'] = '' 254 params['description'] = 'Yocto Project master' 255 256 print_template(releases_available_template,params,fd) 257 print_str('',fd) 258 259 print_str(' <!-- Default project layers for each release -->',fd) 260 rdl_count = 1 261 for i,release in enumerate(current_releases): 262 for j,layer in enumerate(default_poky_layers): 263 params = {} 264 params['layer'] = layer 265 params['release'] = release[0] 266 params['Release'] = release[0] 267 params['release_version'] = release[1] 268 if not (params['release'] in ('master','HEAD')): 269 params['release'] = params['release'][0].lower() + params['release'][1:] 270 params['release_id'] = str(i+1) 271 params['rdl_count'] = str(rdl_count) 272 params['branch'] = params['release'] 273 print_template(default_layers_template,params,fd) 274 rdl_count += 1 275 print_str('',fd) 276 277 print_str(default_layers_preface,fd) 278 lv_count = 1 279 for i,layer in enumerate(default_poky_layers): 280 params = {} 281 params['layer'] = layer 282 params['layer_id'] = str(i+1) 283 params['vcs_url'] = 'git://git.yoctoproject.org/poky' 284 params['vcs_web_url'] = 'https://git.yoctoproject.org/cgit/cgit.cgi/poky' 285 params['vcs_web_tree_base_url'] = 'https://git.yoctoproject.org/cgit/cgit.cgi/poky/tree/%path%?h=%branch%' 286 params['vcs_web_file_base_url'] = 'https://git.yoctoproject.org/cgit/cgit.cgi/poky/tree/%path%?h=%branch%' 287 288 if i: 289 print_str('',fd) 290 print_template(layer_poky_template,params,fd) 291 for j,release in enumerate(current_releases): 292 params['release'] = release[0] 293 params['Release'] = release[0] 294 params['release_version'] = release[1] 295 if not (params['release'] in ('master','HEAD')): 296 params['release'] = params['release'][0].lower() + params['release'][1:] 297 params['release_id'] = str(j+1) 298 params['lv_count'] = str(lv_count) 299 params['branch'] = params['release'] 300 params['commit'] = params['release'] 301 302 params['dirpath'] = params['layer'] 303 if params['layer'] in ('openembedded-core'): #'openembedded-core', 304 params['dirpath'] = 'meta' 305 306 if 'HEAD' == params['release']: 307 print_template(layer_version_HEAD_template,params,fd) 308 else: 309 print_template(layer_version_template,params,fd) 310 lv_count += 1 311 312 print_str(epilog_template,fd) 313 fd.close() 314 315################################# 316# Generate oe-core.xml 317# 318 319def generate_oe_core(): 320 fd = open('oe-core.xml','w') 321 322 params = {} 323 params['distro'] = 'nodistro' 324 print_template(prolog_template,params,fd) 325 print_str('',fd) 326 327 print_str(' <!-- Bitbake versions which correspond to the metadata release -->',fd) 328 for i,release in enumerate(current_releases): 329 params = {} 330 params['release'] = release[0] 331 params['Release'] = release[0] 332 params['bitbakeversion'] = release[6] 333 params['release_version'] = release[1] 334 if not (params['release'] in ('HEAD')): # 'master', 335 params['release'] = params['release'][0].lower() + params['release'][1:] 336 params['name'] = params['release'] 337 params['bitbake_id'] = str(i+1) 338 params['branch'] = params['release'] 339 print_template(bitbakeversion_oecore_template,params,fd) 340 print_str('',fd) 341 342 print_str(' <!-- Releases available -->',fd) 343 for i,release in enumerate(current_releases): 344 params = {} 345 params['release'] = release[0] 346 params['Release'] = release[0] 347 params['release_version'] = release[1] 348 if not (params['release'] in ('HEAD')): #'master', 349 params['release'] = params['release'][0].lower() + params['release'][1:] 350 params['h_release'] = '?h={{release}}' 351 params['name'] = params['release'] 352 params['ra_count'] = str(i+1) 353 params['branch'] = params['release'] 354 355 if 'HEAD' == params['release']: 356 params['help_source'] = 'with the version of OpenEmbedded that you have cloned or downloaded to your computer' 357 params['description'] = 'Local Openembedded' 358 params['name'] = 'local' 359 else: 360 params['help_source'] = 'using the tip of the <a href=\\"https://cgit.openembedded.org/openembedded-core/log/{{h_release}}\\">OpenEmbedded {{Release}}</a> branch' 361 params['description'] = 'Openembedded {{Release}}' 362 if 'master' == params['release']: 363 params['h_release'] = '' 364 params['description'] = 'OpenEmbedded core master' 365 params['Release'] = params['release'] 366 367 print_template(releases_available_template,params,fd) 368 print_str('',fd) 369 370 print_str(' <!-- Default layers for each release -->',fd) 371 rdl_count = 1 372 for i,release in enumerate(current_releases): 373 for j,layer in enumerate(default_oe_core_layers): 374 params = {} 375 params['layer'] = layer 376 params['release'] = release[0] 377 params['Release'] = release[0] 378 params['release_version'] = release[1] 379 if not (params['release'] in ('master','HEAD')): 380 params['release'] = params['release'][0].lower() + params['release'][1:] 381 params['release_id'] = str(i+1) 382 params['rdl_count'] = str(rdl_count) 383 params['branch'] = params['release'] 384 print_template(default_layers_template,params,fd) 385 rdl_count += 1 386 print_str('',fd) 387 388 print_str('',fd) 389 print_str(' <!-- Layer for the Local release -->',fd) 390 lv_count = 1 391 for i,layer in enumerate(default_oe_core_layers): 392 params = {} 393 params['layer'] = layer 394 params['layer_id'] = str(i+1) 395 params['vcs_url'] = 'git://git.openembedded.org/openembedded-core' 396 params['vcs_web_url'] = 'https://cgit.openembedded.org/openembedded-core' 397 params['vcs_web_tree_base_url'] = 'https://cgit.openembedded.org/openembedded-core/tree/%path%?h=%branch%' 398 params['vcs_web_file_base_url'] = 'https://cgit.openembedded.org/openembedded-core/tree/%path%?h=%branch%' 399 if i: 400 print_str('',fd) 401 print_template(layer_oe_core_template,params,fd) 402 403 print_template(layer_version_oe_core_template,params,fd) 404 print_str('',fd) 405 406 print_str(epilog_template,fd) 407 fd.close() 408 409################################# 410# Help 411# 412 413def list_releases(): 414 print("Release ReleaseVer BitbakeVer Support Level") 415 print("========== =========== ========== ==============================================") 416 for release in current_releases: 417 print("%10s %10s %11s %s" % (release[0],release[1],release[6],release[4])) 418 419################################# 420# main 421# 422 423def main(argv): 424 global verbose 425 426 parser = argparse.ArgumentParser(description='gen_fixtures.py: table generate the fixture files') 427 parser.add_argument('--poky', '-p', action='store_const', const='poky', dest='command', help='Generate the poky.xml file') 428 parser.add_argument('--oe-core', '-o', action='store_const', const='oe_core', dest='command', help='Generate the oe-core.xml file') 429 parser.add_argument('--all', '-a', action='store_const', const='all', dest='command', help='Generate all fixture files') 430 parser.add_argument('--list', '-l', action='store_const', const='list', dest='command', help='List the release table') 431 parser.add_argument('--verbose', '-v', action='store_true', dest='verbose', help='Enable verbose debugging output') 432 args = parser.parse_args() 433 434 verbose = args.verbose 435 if 'poky' == args.command: 436 generate_poky() 437 elif 'oe_core' == args.command: 438 generate_oe_core() 439 elif 'all' == args.command: 440 generate_poky() 441 generate_oe_core() 442 elif 'all' == args.command: 443 list_releases() 444 elif 'list' == args.command: 445 list_releases() 446 447 else: 448 print("No command for 'gen_fixtures.py' selected") 449 450if __name__ == '__main__': 451 main(sys.argv[1:]) 452