12390b1b6SPatrick Williams#
22390b1b6SPatrick Williams# Copyright OpenEmbedded Contributors
32390b1b6SPatrick Williams#
42390b1b6SPatrick Williams# SPDX-License-Identifier: MIT
52390b1b6SPatrick Williams#
62390b1b6SPatrick Williams
72390b1b6SPatrick Williams##
82390b1b6SPatrick Williams## Purpose:
92390b1b6SPatrick Williams## This class is used to update the list of crates in SRC_URI
102390b1b6SPatrick Williams## by reading Cargo.lock in the source tree.
112390b1b6SPatrick Williams##
122390b1b6SPatrick Williams## See meta/recipes-devtools/python/python3-bcrypt_*.bb for an example
132390b1b6SPatrick Williams##
142390b1b6SPatrick Williams## To perform the update: bitbake -c update_crates recipe-name
152390b1b6SPatrick Williams
162390b1b6SPatrick Williamsaddtask do_update_crates after do_patch
172390b1b6SPatrick Williamsdo_update_crates[depends] = "python3-native:do_populate_sysroot"
18c5535c91SAndrew Geisslerdo_update_crates[nostamp] = "1"
19*fc113eadSAndrew Geisslerdo_update_crates[doc] = "Update the recipe by reading Cargo.lock and write in ${THISDIR}/${BPN}-crates.inc"
202390b1b6SPatrick Williams
212390b1b6SPatrick Williams# The directory where to search for Cargo.lock files
222390b1b6SPatrick WilliamsCARGO_LOCK_SRC_DIR ??= "${S}"
232390b1b6SPatrick Williams
242390b1b6SPatrick Williamsdo_update_crates() {
25*fc113eadSAndrew Geissler    TARGET_FILE="${THISDIR}/${BPN}-crates.inc"
26*fc113eadSAndrew Geissler
272390b1b6SPatrick Williams    nativepython3 - <<EOF
282390b1b6SPatrick Williams
292390b1b6SPatrick Williamsdef get_crates(f):
302390b1b6SPatrick Williams    import tomllib
312390b1b6SPatrick Williams    c_list = '# from %s' % os.path.relpath(f, '${CARGO_LOCK_SRC_DIR}')
322390b1b6SPatrick Williams    c_list += '\nSRC_URI += " \\\'
332390b1b6SPatrick Williams    crates = tomllib.load(open(f, 'rb'))
34*fc113eadSAndrew Geissler
35*fc113eadSAndrew Geissler    # Build a list with crates info that have crates.io in the source
36*fc113eadSAndrew Geissler    crates_candidates = list(filter(lambda c: 'crates.io' in c.get('source', ''), crates['package']))
37*fc113eadSAndrew Geissler
38*fc113eadSAndrew Geissler    if not crates_candidates:
39*fc113eadSAndrew Geissler        raise ValueError("Unable to find any candidate crates that use crates.io")
40*fc113eadSAndrew Geissler
41*fc113eadSAndrew Geissler    # Build a list of crates name that have multiple version
42*fc113eadSAndrew Geissler    crates_multiple_vers = []
43*fc113eadSAndrew Geissler    tmp = []
44*fc113eadSAndrew Geissler    for c in crates_candidates:
45*fc113eadSAndrew Geissler        if c['name'] in tmp:
46*fc113eadSAndrew Geissler            crates_multiple_vers.append(c['name'])
47*fc113eadSAndrew Geissler        else:
48*fc113eadSAndrew Geissler            tmp.append(c['name'])
49*fc113eadSAndrew Geissler
50*fc113eadSAndrew Geissler    # Update crates uri and their checksum, to avoid name clashing on the checksum
51*fc113eadSAndrew Geissler    # we need to rename crates of the same name but different version
52*fc113eadSAndrew Geissler    cksum_list = ''
53*fc113eadSAndrew Geissler    for c in crates_candidates:
54*fc113eadSAndrew Geissler        if c['name'] in crates_multiple_vers:
55*fc113eadSAndrew Geissler            rename = "%s-%s" % (c['name'], c['version'])
56*fc113eadSAndrew Geissler            c_list += '\n    crate://crates.io/%s/%s;name=%s \\\' % (c['name'], c['version'], rename)
57*fc113eadSAndrew Geissler        else:
58*fc113eadSAndrew Geissler            rename = c['name']
592390b1b6SPatrick Williams            c_list += '\n    crate://crates.io/%s/%s \\\' % (c['name'], c['version'])
60*fc113eadSAndrew Geissler        if 'checksum' in c:
61*fc113eadSAndrew Geissler            cksum_list += '\nSRC_URI[%s.sha256sum] = "%s"' % (rename, c['checksum'])
62*fc113eadSAndrew Geissler
632390b1b6SPatrick Williams    c_list += '\n"\n'
64*fc113eadSAndrew Geissler    c_list += cksum_list
65*fc113eadSAndrew Geissler    c_list += '\n'
662390b1b6SPatrick Williams    return c_list
672390b1b6SPatrick Williams
682390b1b6SPatrick Williamsimport os
692390b1b6SPatrick Williamscrates = "# Autogenerated with 'bitbake -c update_crates ${PN}'\n\n"
70*fc113eadSAndrew Geisslerfound = False
712390b1b6SPatrick Williamsfor root, dirs, files in os.walk('${CARGO_LOCK_SRC_DIR}'):
722390b1b6SPatrick Williams    for file in files:
732390b1b6SPatrick Williams        if file == 'Cargo.lock':
742390b1b6SPatrick Williams            crates += get_crates(os.path.join(root, file))
75*fc113eadSAndrew Geissler            found = True
76*fc113eadSAndrew Geisslerif not found:
77*fc113eadSAndrew Geissler    raise ValueError("Unable to find Cargo.lock in ${CARGO_LOCK_SRC_DIR}")
78*fc113eadSAndrew Geissleropen("${TARGET_FILE}", 'w').write(crates)
792390b1b6SPatrick WilliamsEOF
80*fc113eadSAndrew Geissler
81*fc113eadSAndrew Geissler    bbnote "Successfully update crates inside '${TARGET_FILE}'"
822390b1b6SPatrick Williams}
83