1#
2# Removes source after build
3#
4# To use it add that line to conf/local.conf:
5#
6# INHERIT += "rm_work"
7#
8# To inhibit rm_work for some recipes, specify them in RM_WORK_EXCLUDE.
9# For example, in conf/local.conf:
10#
11# RM_WORK_EXCLUDE += "icu-native icu busybox"
12#
13# Recipes can also configure which entries in their ${WORKDIR}
14# are preserved besides temp, which already gets excluded by default
15# because it contains logs:
16# do_install_append () {
17#     echo "bar" >${WORKDIR}/foo
18# }
19# RM_WORK_EXCLUDE_ITEMS += "foo"
20RM_WORK_EXCLUDE_ITEMS = "temp"
21
22# Use the completion scheduler by default when rm_work is active
23# to try and reduce disk usage
24BB_SCHEDULER ?= "completion"
25
26# Run the rm_work task in the idle scheduling class
27BB_TASK_IONICE_LEVEL_task-rm_work = "3.0"
28
29do_rm_work () {
30    # If the recipe name is in the RM_WORK_EXCLUDE, skip the recipe.
31    for p in ${RM_WORK_EXCLUDE}; do
32        if [ "$p" = "${PN}" ]; then
33            bbnote "rm_work: Skipping ${PN} since it is in RM_WORK_EXCLUDE"
34            exit 0
35        fi
36    done
37
38    # Need to add pseudo back or subsqeuent work in this workdir
39    # might fail since setscene may not rerun to recreate it
40    mkdir -p ${WORKDIR}/pseudo/
41
42    excludes='${RM_WORK_EXCLUDE_ITEMS}'
43
44    # Change normal stamps into setscene stamps as they better reflect the
45    # fact WORKDIR is now empty
46    # Also leave noexec stamps since setscene stamps don't cover them
47    cd `dirname ${STAMP}`
48    for i in `basename ${STAMP}`*
49    do
50        case $i in
51        *sigdata*|*sigbasedata*)
52            # Save/skip anything that looks like a signature data file.
53            ;;
54        *do_image_complete_setscene*|*do_image_qa_setscene*)
55            # Ensure we don't 'stack' setscene extensions to these stamps with the sections below
56            ;;
57        *do_image_complete*)
58            # Promote do_image_complete stamps to setscene versions (ahead of *do_image* below)
59            mv $i `echo $i | sed -e "s#do_image_complete#do_image_complete_setscene#"`
60            ;;
61        *do_image_qa*)
62            # Promote do_image_qa stamps to setscene versions (ahead of *do_image* below)
63            mv $i `echo $i | sed -e "s#do_image_qa#do_image_qa_setscene#"`
64            ;;
65        *do_package_write*|*do_rootfs*|*do_image*|*do_bootimg*|*do_write_qemuboot_conf*|*do_build*)
66            ;;
67        *do_addto_recipe_sysroot*)
68            # Preserve recipe-sysroot-native if do_addto_recipe_sysroot has been used
69            excludes="$excludes recipe-sysroot-native"
70            ;;
71        *do_package|*do_package.*|*do_package_setscene.*)
72            # We remove do_package entirely, including any
73            # sstate version since otherwise we'd need to leave 'plaindirs' around
74            # such as 'packages' and 'packages-split' and these can be large. No end
75            # of chain tasks depend directly on do_package anymore.
76            rm -f $i;
77            ;;
78        *_setscene*)
79            # Skip stamps which are already setscene versions
80            ;;
81        *)
82            # For everything else: if suitable, promote the stamp to a setscene
83            # version, otherwise remove it
84            for j in ${SSTATETASKS} do_shared_workdir
85            do
86                case $i in
87                *$j|*$j.*)
88                    mv $i `echo $i | sed -e "s#${j}#${j}_setscene#"`
89                    break
90                    ;;
91                esac
92            done
93            rm -f $i
94        esac
95    done
96
97    cd ${WORKDIR}
98    for dir in *
99    do
100        # Retain only logs and other files in temp, safely ignore
101        # failures of removing pseudo folers on NFS2/3 server.
102        if [ $dir = 'pseudo' ]; then
103            rm -rf $dir 2> /dev/null || true
104        elif ! echo "$excludes" | grep -q -w "$dir"; then
105            rm -rf $dir
106        fi
107    done
108}
109do_rm_work_all () {
110    :
111}
112do_rm_work_all[recrdeptask] = "do_rm_work"
113do_rm_work_all[noexec] = "1"
114addtask rm_work_all before do_build
115
116do_populate_sdk[postfuncs] += "rm_work_populatesdk"
117rm_work_populatesdk () {
118    :
119}
120rm_work_populatesdk[cleandirs] = "${WORKDIR}/sdk"
121
122do_image_complete[postfuncs] += "rm_work_rootfs"
123rm_work_rootfs () {
124    :
125}
126rm_work_rootfs[cleandirs] = "${WORKDIR}/rootfs"
127
128# This task can be used instead of do_build to trigger building
129# without also invoking do_rm_work. It only exists when rm_work.bbclass
130# is active, otherwise do_build needs to be used.
131#
132# The intended usage is
133# ${@ d.getVar('RM_WORK_BUILD_WITHOUT') or 'do_build'}
134# in places that previously used just 'do_build'.
135RM_WORK_BUILD_WITHOUT = "do_build_without_rm_work"
136do_build_without_rm_work () {
137    :
138}
139do_build_without_rm_work[noexec] = "1"
140
141# We have to add these tasks already now, because all tasks are
142# meant to be defined before the RecipeTaskPreProcess event triggers.
143# The inject_rm_work event handler then merely changes task dependencies.
144addtask do_rm_work
145addtask do_build_without_rm_work
146addhandler inject_rm_work
147inject_rm_work[eventmask] = "bb.event.RecipeTaskPreProcess"
148python inject_rm_work() {
149    if bb.data.inherits_class('kernel', d):
150        d.appendVar("RM_WORK_EXCLUDE", ' ' + d.getVar("PN"))
151    # If the recipe name is in the RM_WORK_EXCLUDE, skip the recipe.
152    excludes = (d.getVar("RM_WORK_EXCLUDE") or "").split()
153    pn = d.getVar("PN")
154
155    # Determine what do_build depends upon, without including do_build
156    # itself or our own special do_rm_work_all.
157    deps = sorted((set(bb.build.preceedtask('do_build', True, d))).difference(('do_build', 'do_rm_work_all')) or "")
158
159    # deps can be empty if do_build doesn't exist, e.g. *-inital recipes
160    if not deps:
161        deps = ["do_populate_sysroot", "do_populate_lic"]
162
163    if pn in excludes:
164        d.delVarFlag('rm_work_rootfs', 'cleandirs')
165        d.delVarFlag('rm_work_populatesdk', 'cleandirs')
166    else:
167        # Inject do_rm_work into the tasks of the current recipe such that do_build
168        # depends on it and that it runs after all other tasks that block do_build,
169        # i.e. after all work on the current recipe is done. The reason for taking
170        # this approach instead of making do_rm_work depend on do_build is that
171        # do_build inherits additional runtime dependencies on
172        # other recipes and thus will typically run much later than completion of
173        # work in the recipe itself.
174        # In practice, addtask() here merely updates the dependencies.
175        bb.build.addtask('do_rm_work', 'do_build', ' '.join(deps), d)
176
177    # Always update do_build_without_rm_work dependencies.
178    bb.build.addtask('do_build_without_rm_work', '', ' '.join(deps), d)
179}
180