diff options
Diffstat (limited to 'meta')
-rw-r--r-- | meta/classes/reproducible_build.bbclass | 49 |
1 files changed, 22 insertions, 27 deletions
diff --git a/meta/classes/reproducible_build.bbclass b/meta/classes/reproducible_build.bbclass index 268b5fb8f1..4e8850fb83 100644 --- a/meta/classes/reproducible_build.bbclass +++ b/meta/classes/reproducible_build.bbclass | |||
@@ -1,33 +1,32 @@ | |||
1 | # | ||
2 | # reproducible_build.bbclass | 1 | # reproducible_build.bbclass |
3 | # | 2 | # |
4 | # This bbclass is mainly responsible to determine SOURCE_DATE_EPOCH on a per recipe base. | 3 | # Sets SOURCE_DATE_EPOCH in each component's build environment. |
5 | # We need to set a recipe specific SOURCE_DATE_EPOCH in each recipe environment for various tasks. | 4 | # Upstream components (generally) respect this environment variable, |
6 | # One way would be to modify all recipes one-by-one to specify SOURCE_DATE_EPOCH explicitly, | 5 | # using it in place of the "current" date and time. |
7 | # but that is not realistic as there are hundreds (probably thousands) of recipes in various meta-layers. | 6 | # See https://reproducible-builds.org/specs/source-date-epoch/ |
8 | # Therefore we do it this class. | 7 | # |
9 | # After sources are unpacked but before they are patched, we try to determine the value for SOURCE_DATE_EPOCH. | 8 | # After sources are unpacked but before they are patched, we set a reproducible value for SOURCE_DATE_EPOCH. |
9 | # This value should be reproducible for anyone who builds the same revision from the same sources. | ||
10 | # | 10 | # |
11 | # There are 4 ways to determine SOURCE_DATE_EPOCH: | 11 | # There are 4 ways we determine SOURCE_DATE_EPOCH: |
12 | # | 12 | # |
13 | # 1. Use value from __source_date_epoch.txt file if this file exists. | 13 | # 1. Use the value from __source_date_epoch.txt file if this file exists. |
14 | # This file was most likely created in the previous build by one of the following methods 2,3,4. | 14 | # This file was most likely created in the previous build by one of the following methods 2,3,4. |
15 | # In principle, it could actually provided by a recipe via SRC_URI | 15 | # Alternatively, it can be provided by a recipe via SRC_URI. |
16 | # | 16 | # |
17 | # If the file does not exist, first try to determine the value for SOURCE_DATE_EPOCH: | 17 | # If the file does not exist: |
18 | # | 18 | # |
19 | # 2. If we detected a folder .git, use .git last commit date timestamp, as git does not allow checking out | 19 | # 2. If there is a git checkout, use the last git commit timestamp. |
20 | # files and preserving their timestamps. | 20 | # Git does not preserve file timestamps on checkout. |
21 | # | 21 | # |
22 | # 3. Use the mtime of "known" files such as NEWS, CHANGLELOG, ... | 22 | # 3. Use the mtime of "known" files such as NEWS, CHANGLELOG, ... |
23 | # This will work fine for any well kept repository distributed via tarballs. | 23 | # This works for well-kept repositories distributed via tarball. |
24 | # | 24 | # |
25 | # 4. If the above steps fail, we need to check all package source files and use the youngest file of the source tree. | 25 | # 4. If the above steps fail, use the modification time of the youngest file in the source tree. |
26 | # | 26 | # |
27 | # Once the value of SOURCE_DATE_EPOCH is determined, it is stored in the recipe ${WORKDIR}/source_date_epoch folder | 27 | # Once the value of SOURCE_DATE_EPOCH is determined, it is stored in the recipe's ${SDE_FILE}. |
28 | # in a text file "__source_date_epoch.txt'. If this file is found by other recipe task, the value is exported in | 28 | # If this file is found by other tasks, the value is exported in the SOURCE_DATE_EPOCH variable. |
29 | # the SOURCE_DATE_EPOCH variable in the task environment. This is done in an anonymous python function, | 29 | # SOURCE_DATE_EPOCH is set for all tasks that might use it (do_configure, do_compile, do_package, ...) |
30 | # so SOURCE_DATE_EPOCH is guaranteed to exist for all tasks the may use it (do_configure, do_compile, do_package, ...) | ||
31 | 30 | ||
32 | BUILD_REPRODUCIBLE_BINARIES ??= '1' | 31 | BUILD_REPRODUCIBLE_BINARIES ??= '1' |
33 | inherit ${@oe.utils.ifelse(d.getVar('BUILD_REPRODUCIBLE_BINARIES') == '1', 'reproducible_build_simple', '')} | 32 | inherit ${@oe.utils.ifelse(d.getVar('BUILD_REPRODUCIBLE_BINARIES') == '1', 'reproducible_build_simple', '')} |
@@ -67,9 +66,8 @@ def find_git_folder(path): | |||
67 | for root, dirs, files in os.walk(path, topdown=True): | 66 | for root, dirs, files in os.walk(path, topdown=True): |
68 | dirs[:] = [d for d in dirs if d not in exclude] | 67 | dirs[:] = [d for d in dirs if d not in exclude] |
69 | if '.git' in dirs: | 68 | if '.git' in dirs: |
70 | #bb.warn("found root:%s" % (str(root))) | ||
71 | return root | 69 | return root |
72 | 70 | ||
73 | def get_source_date_epoch_git(d, path): | 71 | def get_source_date_epoch_git(d, path): |
74 | source_date_epoch = 0 | 72 | source_date_epoch = 0 |
75 | if "git://" in d.getVar('SRC_URI'): | 73 | if "git://" in d.getVar('SRC_URI'): |
@@ -79,15 +77,13 @@ def get_source_date_epoch_git(d, path): | |||
79 | if os.path.isdir(os.path.join(gitpath,".git")): | 77 | if os.path.isdir(os.path.join(gitpath,".git")): |
80 | try: | 78 | try: |
81 | source_date_epoch = int(subprocess.check_output(['git','log','-1','--pretty=%ct'], cwd=path)) | 79 | source_date_epoch = int(subprocess.check_output(['git','log','-1','--pretty=%ct'], cwd=path)) |
82 | #bb.warn("JB *** gitpath:%s sde: %d" % (gitpath,source_date_epoch)) | ||
83 | bb.debug(1, "git repo path:%s sde: %d" % (gitpath,source_date_epoch)) | 80 | bb.debug(1, "git repo path:%s sde: %d" % (gitpath,source_date_epoch)) |
84 | except subprocess.CalledProcessError as grepexc: | 81 | except subprocess.CalledProcessError as grepexc: |
85 | #bb.warn( "Expected git repository not found, (path: %s) error:%d" % (gitpath, grepexc.returncode)) | ||
86 | bb.debug(1, "Expected git repository not found, (path: %s) error:%d" % (gitpath, grepexc.returncode)) | 82 | bb.debug(1, "Expected git repository not found, (path: %s) error:%d" % (gitpath, grepexc.returncode)) |
87 | else: | 83 | else: |
88 | bb.warn("Failed to find a git repository for path:%s" % (path)) | 84 | bb.warn("Failed to find a git repository for path:%s" % (path)) |
89 | return source_date_epoch | 85 | return source_date_epoch |
90 | 86 | ||
91 | python do_create_source_date_epoch_stamp() { | 87 | python do_create_source_date_epoch_stamp() { |
92 | path = d.getVar('S') | 88 | path = d.getVar('S') |
93 | if not os.path.isdir(path): | 89 | if not os.path.isdir(path): |
@@ -98,8 +94,7 @@ python do_create_source_date_epoch_stamp() { | |||
98 | if os.path.isfile(epochfile): | 94 | if os.path.isfile(epochfile): |
99 | bb.debug(1, " path: %s reusing __source_date_epoch.txt" % epochfile) | 95 | bb.debug(1, " path: %s reusing __source_date_epoch.txt" % epochfile) |
100 | return | 96 | return |
101 | 97 | ||
102 | # Try to detect/find a git repository | ||
103 | source_date_epoch = get_source_date_epoch_git(d, path) | 98 | source_date_epoch = get_source_date_epoch_git(d, path) |
104 | if source_date_epoch == 0: | 99 | if source_date_epoch == 0: |
105 | source_date_epoch = get_source_date_epoch_known_files(d, path) | 100 | source_date_epoch = get_source_date_epoch_known_files(d, path) |