summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/buildinfohelper.py
diff options
context:
space:
mode:
authorElliot Smith <elliot.smith@intel.com>2016-07-12 15:54:46 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-07-19 08:56:51 +0100
commit4125da7763ffc70cc77578c677bb7e5fc7ebaf57 (patch)
tree3c303f0070365d73217950b96ef234cfe9bcc022 /bitbake/lib/bb/ui/buildinfohelper.py
parente9808576daad137695bdedd0883ee0a35b7d870a (diff)
downloadpoky-4125da7763ffc70cc77578c677bb7e5fc7ebaf57.tar.gz
bitbake: toaster: attach kernel artifacts to targets
The bzImage and modules files were previously attached to a build, rather than to the target which produced them. This meant it was not possible to determine which kernel artifact produced by a build came from which target; which in turn made it difficult to associate existing kernel artifact with targets when those targets didn't produce artifacts (e.g. if the same machine + target combination was built again and didn't produce a bzImage or modules file because those files already existed). By associating kernel artifacts with the target (via a new TargetArtifactFile model), we make it possible to find all the artifacts for a given machine + target combination. Then, in cases where a build is completed but its targets don't produce any artifacts, we can find a previous Target object with the same machine + target and copy its artifacts to the targets for a just-completed build. Note that this doesn't cover SDK artifacts yet, which are still retrieved in toaster.bbclass and show up as "Other artifacts", lumped together for the whole build rather than by target. [YOCTO #8556] (Bitbake rev: 9b151416e428c2565a27d89116439f9a8d578e3d) Signed-off-by: Elliot Smith <elliot.smith@intel.com> Signed-off-by: bavery <brian.avery@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/ui/buildinfohelper.py')
-rw-r--r--bitbake/lib/bb/ui/buildinfohelper.py85
1 files changed, 56 insertions, 29 deletions
diff --git a/bitbake/lib/bb/ui/buildinfohelper.py b/bitbake/lib/bb/ui/buildinfohelper.py
index 8bdc9cc0a7..a5b22379aa 100644
--- a/bitbake/lib/bb/ui/buildinfohelper.py
+++ b/bitbake/lib/bb/ui/buildinfohelper.py
@@ -37,7 +37,7 @@ os.environ["DJANGO_SETTINGS_MODULE"] =\
37django.setup() 37django.setup()
38 38
39from orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage, HelpText 39from orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage, HelpText
40from orm.models import Target_Image_File, BuildArtifact 40from orm.models import Target_Image_File, BuildArtifact, TargetArtifactFile
41from orm.models import Variable, VariableHistory 41from orm.models import Variable, VariableHistory
42from orm.models import Package, Package_File, Target_Installed_Package, Target_File 42from orm.models import Package, Package_File, Target_Installed_Package, Target_File
43from orm.models import Task_Dependency, Package_Dependency 43from orm.models import Task_Dependency, Package_Dependency
@@ -121,6 +121,13 @@ class ORMWrapper(object):
121 121
122 return vars(self)[dictname][key] 122 return vars(self)[dictname][key]
123 123
124 def get_similar_target_with_image_files(self, target):
125 """
126 Get a Target object "similar" to target; i.e. with the same target
127 name ('core-image-minimal' etc.) and machine.
128 """
129 return target.get_similar_target_with_image_files()
130
124 def _timestamp_to_datetime(self, secs): 131 def _timestamp_to_datetime(self, secs):
125 """ 132 """
126 Convert timestamp in seconds to Python datetime 133 Convert timestamp in seconds to Python datetime
@@ -678,27 +685,32 @@ class ORMWrapper(object):
678 file_name = file_name, 685 file_name = file_name,
679 file_size = file_size) 686 file_size = file_size)
680 687
681 def save_artifact_information_no_dedupe(self, build_obj, file_name, file_size): 688 def save_target_artifact_file(self, target_obj, file_name, file_size):
682 """ 689 """
683 Save artifact information without checking for duplicate paths; 690 Save artifact file information for a Target target_obj.
684 this is used when we are saving data about an artifact which was 691
685 generated by a previous build but which is also relevant to this build, 692 Note that this doesn't include SDK artifacts, only images and
686 e.g. a bzImage file. 693 related files (e.g. bzImage).
687 """ 694 """
688 BuildArtifact.objects.create(build=build_obj, file_name=file_name, 695 TargetArtifactFile.objects.create(target=target_obj,
689 file_size=file_size) 696 file_name=file_name, file_size=file_size)
690 697
691 def save_artifact_information(self, build_obj, file_name, file_size): 698 def save_artifact_information(self, build_obj, file_name, file_size):
692 # we skip the image files from other builds 699 """
693 if Target_Image_File.objects.filter(file_name = file_name).count() > 0: 700 TODO this is currently used to save SDK artifacts to the database,
694 return 701 but will be replaced in future once SDK artifacts are associated with
695 702 Target objects (as they eventually should be)
703 """
696 # do not update artifacts found in other builds 704 # do not update artifacts found in other builds
697 if BuildArtifact.objects.filter(file_name = file_name).count() > 0: 705 if BuildArtifact.objects.filter(file_name = file_name).count() > 0:
698 return 706 return
699 707
700 self.save_artifact_information_no_dedupe(self, build_obj, file_name, 708 # do not update artifact if already a target artifact file for that path
701 file_size) 709 if TargetArtifactFile.objects.filter(file_name = file_name).count() > 0:
710 return
711
712 BuildArtifact.objects.create(build=build_obj, file_name=file_name,
713 file_size=file_size)
702 714
703 def create_logmessage(self, log_information): 715 def create_logmessage(self, log_information):
704 assert 'build' in log_information 716 assert 'build' in log_information
@@ -1496,7 +1508,7 @@ class BuildInfoHelper(object):
1496 1508
1497 self.orm_wrapper.create_logmessage(log_information) 1509 self.orm_wrapper.create_logmessage(log_information)
1498 1510
1499 def _get_files_from_image_license(self, image_license_manifest_path): 1511 def _get_filenames_from_image_license(self, image_license_manifest_path):
1500 """ 1512 """
1501 Find the FILES line in the image_license.manifest file, 1513 Find the FILES line in the image_license.manifest file,
1502 which has the basenames of the bzImage and modules files 1514 which has the basenames of the bzImage and modules files
@@ -1567,19 +1579,20 @@ class BuildInfoHelper(object):
1567 1579
1568 OR 1580 OR
1569 1581
1570 2. There are no files for the target, so copy them from a 1582 2. There are no new files for the target (they were already produced by
1571 previous build with the same target + machine. 1583 a previous build), so copy them from the most recent previous build with
1584 the same target, task and machine.
1572 """ 1585 """
1573 deploy_dir_image = \ 1586 deploy_dir_image = \
1574 self.server.runCommand(['getVariable', 'DEPLOY_DIR_IMAGE'])[0] 1587 self.server.runCommand(['getVariable', 'DEPLOY_DIR_IMAGE'])[0]
1575 1588
1576 # if there's no DEPLOY_DIR_IMAGE, there aren't going to be 1589 # if there's no DEPLOY_DIR_IMAGE, there aren't going to be
1577 # any build artifacts, so we can return immediately 1590 # any image artifacts, so we can return immediately
1578 if not deploy_dir_image: 1591 if not deploy_dir_image:
1579 return 1592 return
1580 1593
1581 buildname = self.server.runCommand(['getVariable', 'BUILDNAME'])[0] 1594 buildname = self.server.runCommand(['getVariable', 'BUILDNAME'])[0]
1582 machine = self.server.runCommand(['getVariable', 'MACHINE'])[0] 1595 machine = self.server.runCommand(['getVariable', 'MACHINE'])[0]
1583 image_name = self.server.runCommand(['getVariable', 'IMAGE_NAME'])[0] 1596 image_name = self.server.runCommand(['getVariable', 'IMAGE_NAME'])[0]
1584 1597
1585 # location of the image_license.manifest files for this build; 1598 # location of the image_license.manifest files for this build;
@@ -1597,7 +1610,10 @@ class BuildInfoHelper(object):
1597 image_file_extensions_unique = set(image_file_extensions.split(' ')) 1610 image_file_extensions_unique = set(image_file_extensions.split(' '))
1598 1611
1599 targets = self.internal_state['targets'] 1612 targets = self.internal_state['targets']
1613
1614 # filter out anything which isn't an image target
1600 image_targets = [target for target in targets if target.is_image] 1615 image_targets = [target for target in targets if target.is_image]
1616
1601 for target in image_targets: 1617 for target in image_targets:
1602 # this is set to True if we find at least one file relating to 1618 # this is set to True if we find at least one file relating to
1603 # this target; if this remains False after the scan, we copy the 1619 # this target; if this remains False after the scan, we copy the
@@ -1625,16 +1641,17 @@ class BuildInfoHelper(object):
1625 if os.path.isfile(image_license_manifest_path): 1641 if os.path.isfile(image_license_manifest_path):
1626 has_files = True 1642 has_files = True
1627 1643
1628 basenames = self._get_files_from_image_license( 1644 basenames = self._get_filenames_from_image_license(
1629 image_license_manifest_path) 1645 image_license_manifest_path)
1630 1646
1631 for basename in basenames: 1647 for basename in basenames:
1632 artifact_path = os.path.join(deploy_dir_image, basename) 1648 artifact_path = os.path.join(deploy_dir_image, basename)
1633 artifact_size = os.stat(artifact_path).st_size 1649 artifact_size = os.stat(artifact_path).st_size
1634 1650
1635 self.orm_wrapper.save_artifact_information_no_dedupe( 1651 # note that the artifact will only be saved against this
1636 self.internal_state['build'], artifact_path, 1652 # build if it hasn't been already
1637 artifact_size) 1653 self.orm_wrapper.save_target_artifact_file(target,
1654 artifact_path, artifact_size)
1638 1655
1639 # store the license manifest path on the target 1656 # store the license manifest path on the target
1640 # (this file is also created any time an image file is created) 1657 # (this file is also created any time an image file is created)
@@ -1648,7 +1665,10 @@ class BuildInfoHelper(object):
1648 # (via real_image_name); note that we don't have to set 1665 # (via real_image_name); note that we don't have to set
1649 # has_files = True, as searching for the license manifest file 1666 # has_files = True, as searching for the license manifest file
1650 # will already have set it to true if at least one image file was 1667 # will already have set it to true if at least one image file was
1651 # produced 1668 # produced; note that the real_image_name includes BUILDNAME, which
1669 # in turn includes a timestamp; so if no files were produced for
1670 # this timestamp (i.e. the build reused existing image files already
1671 # in the directory), no files will be recorded against this target
1652 image_files = self._get_image_files(deploy_dir_image, 1672 image_files = self._get_image_files(deploy_dir_image,
1653 real_image_name, image_file_extensions_unique) 1673 real_image_name, image_file_extensions_unique)
1654 1674
@@ -1657,11 +1677,18 @@ class BuildInfoHelper(object):
1657 target, image_file['path'], image_file['size']) 1677 target, image_file['path'], image_file['size'])
1658 1678
1659 if not has_files: 1679 if not has_files:
1660 # TODO copy artifact and image files from the 1680 # copy image files and build artifacts from the
1661 # most-recently-built Target with the same target + machine 1681 # most-recently-built Target with the
1662 # as this Target; also copy the license manifest path, 1682 # same target + machine as this Target; also copy the license
1663 # as that is treated differently 1683 # manifest path, as that is not treated as an artifact and needs
1664 pass 1684 # to be set separately
1685 most_recent = \
1686 self.orm_wrapper.get_similar_target_with_image_files(target)
1687
1688 if most_recent:
1689 logger.info('image artifacts for target %s cloned from ' \
1690 'target %s' % (target.pk, most_recent.pk))
1691 target.clone_artifacts_from(most_recent)
1665 1692
1666 def close(self, errorcode): 1693 def close(self, errorcode):
1667 if self.brbe is not None: 1694 if self.brbe is not None: