diff options
author | Damien Martin-Guillerez <dmarting@google.com> | 2017-11-21 04:09:16 -0800 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2017-11-21 04:11:34 -0800 |
commit | 4d09a1de6a60c6f90cc88978151bcde83c8000d4 (patch) | |
tree | a01b49c6d3c8fe5b598594cb0fec1bb7156dc9f4 | |
parent | 0fd76922d60bd1a39dd57d56b42c94edc2674243 (diff) |
SOURCE_DATE_EPOCH environment variable override the timestamp
This is applying the version 1.1 of the specification (https://reproducible-builds.org/specs/source-date-epoch/)
where the only timestamp that Bazel puts in the final targets is overridden by the value of SOURCE_DATE_EPOCH.
This change also remove the legacy SOURCE_DATE_EPOCH handling which wasn't really following
the spec.
Note that Bazel itself tries hard to remove all timestamps from intermediary binaries and
overridde SOURCE_DATE_EPOCH in most action, which is a not according to the version 1.0 of the spec
but according to the expected change for version 1.1.
RELNOTES: SOURCE_DATE_EPOCH (https://reproducible-builds.org/specs/source-date-epoch/) can
be used to override the timestamp used for stamped target (when using --stamp).
Fixes #2240.
Change-Id: I074e7905fa6745cc706f7391340aeae9188909ca
PiperOrigin-RevId: 176489717
7 files changed, 91 insertions, 36 deletions
diff --git a/scripts/bootstrap/bootstrap.sh b/scripts/bootstrap/bootstrap.sh index 3f8ba74da2..57b5332863 100755 --- a/scripts/bootstrap/bootstrap.sh +++ b/scripts/bootstrap/bootstrap.sh @@ -27,9 +27,6 @@ EMBED_LABEL_ARG=() if [ -n "${EMBED_LABEL}" ]; then EMBED_LABEL_ARG=(--stamp --embed_label "${EMBED_LABEL}") - if [ -n "${SOURCE_DATE_EPOCH}" ]; then - EMBED_LABEL_ARG+=(--experimental_embed_timestamp_epoch "${SOURCE_DATE_EPOCH}") - fi fi : ${JAVA_VERSION:="1.8"} diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildInfo.java index 7af9837012..b4ab9ee171 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BuildInfo.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildInfo.java @@ -24,9 +24,6 @@ public class BuildInfo { */ public static final String BUILD_EMBED_LABEL = "BUILD_EMBED_LABEL"; - /** Named constant for the reference timestamp to be included. */ - public static final String SOURCE_DATE_EPOCH = "SOURCE_DATE_EPOCH"; - /** * The name of the user that performs the build. */ diff --git a/src/main/java/com/google/devtools/build/lib/analysis/WorkspaceStatusAction.java b/src/main/java/com/google/devtools/build/lib/analysis/WorkspaceStatusAction.java index e5f2499f04..ae70debbf6 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/WorkspaceStatusAction.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/WorkspaceStatusAction.java @@ -69,15 +69,6 @@ public abstract class WorkspaceStatusAction extends AbstractAction { public String embedLabel; @Option( - name = "experimental_embed_timestamp_epoch", - defaultValue = "-1", - documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, - effectTags = {OptionEffectTag.UNKNOWN}, - help = "Alternative timestamp to be used in stamping the binary" - ) - public long embedTimestampEpoch; - - @Option( name = "workspace_status_command", defaultValue = "", category = "misc", diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java index 234465e553..363b282ebb 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java @@ -78,6 +78,7 @@ public class BazelWorkspaceStatusModule extends BlazeModule { private final String username; private final String hostname; private final com.google.devtools.build.lib.shell.Command getWorkspaceStatusCommand; + private final Map<String, String> clientEnv; private BazelWorkspaceStatusAction( WorkspaceStatusAction.Options options, @@ -95,6 +96,7 @@ public class BazelWorkspaceStatusModule extends BlazeModule { this.volatileStatus = volatileStatus; this.username = USER_NAME.value(); this.hostname = hostname; + this.clientEnv = clientEnv; this.getWorkspaceStatusCommand = options.workspaceStatusCommand.equals(PathFragment.EMPTY_FRAGMENT) ? null @@ -198,19 +200,7 @@ public class BazelWorkspaceStatusModule extends BlazeModule { stableMap.put(BuildInfo.BUILD_EMBED_LABEL, options.embedLabel); stableMap.put(BuildInfo.BUILD_HOST, hostname); stableMap.put(BuildInfo.BUILD_USER, username); - // TODO(#2240): We currently take the timestamp from an option. This is very - // explicit and in line with the way the embedded label is passed to bazel. - // While this approach solves the problem of properly packaging bazel, there is the - // expectation that the value be taken from the SOURCE_DATE_EPOCH environment variable. - // However, currently there is no clear understanding on which environment to be taken; - // it could be the client environment or the action environment which is controlled - // by the --action_env options. (We almost certainly do not want the server environment.) - // So, to avoid surprises, we take an explicit option till a satisfying design is found; - // the latter should be designed and implemented eventually. - if (options.embedTimestampEpoch >= 0) { - stableMap.put(BuildInfo.SOURCE_DATE_EPOCH, Long.toString(options.embedTimestampEpoch)); - } - volatileMap.put(BuildInfo.BUILD_TIMESTAMP, Long.toString(System.currentTimeMillis())); + volatileMap.put(BuildInfo.BUILD_TIMESTAMP, Long.toString(getCurrentTimeMillis())); Map<String, String> overallMap = new TreeMap<>(); overallMap.putAll(volatileMap); @@ -236,6 +226,24 @@ public class BazelWorkspaceStatusModule extends BlazeModule { return ActionResult.EMPTY; } + /** + * This method returns the current time for stamping, using SOURCE_DATE_EPOCH + * (https://reproducible-builds.org/specs/source-date-epoch/) if provided. + */ + private long getCurrentTimeMillis() { + if (clientEnv.containsKey("SOURCE_DATE_EPOCH")) { + String value = clientEnv.get("SOURCE_DATE_EPOCH").trim(); + if (!value.isEmpty()) { + try { + return Long.parseLong(value) * 1000; + } catch (NumberFormatException ex) { + // Fall-back to use the current time if SOURCE_DATE_EPOCH is not a long. + } + } + } + return System.currentTimeMillis(); + } + @Override public boolean equals(Object o) { if (!(o instanceof BazelWorkspaceStatusAction)) { @@ -334,11 +342,6 @@ public class BazelWorkspaceStatusModule extends BlazeModule { BuildInfo.BUILD_EMBED_LABEL, Key.of(KeyType.STRING, options.embedLabel, "redacted")); builder.put(BuildInfo.BUILD_HOST, Key.of(KeyType.STRING, "hostname", "redacted")); builder.put(BuildInfo.BUILD_USER, Key.of(KeyType.STRING, "username", "redacted")); - if (options.embedTimestampEpoch >= 0) { - builder.put( - BuildInfo.SOURCE_DATE_EPOCH, - Key.of(KeyType.STRING, Long.toString(options.embedTimestampEpoch), "0")); - } return builder.build(); } @@ -391,4 +394,5 @@ public class BazelWorkspaceStatusModule extends BlazeModule { public void executorInit(CommandEnvironment env, BuildRequest request, ExecutorBuilder builder) { builder.addActionContext(new BazelWorkspaceStatusActionContext(options)); } + } diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/WriteBuildInfoPropertiesAction.java b/src/main/java/com/google/devtools/build/lib/rules/java/WriteBuildInfoPropertiesAction.java index 7b8195e6a5..26be2aba3f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/WriteBuildInfoPropertiesAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/WriteBuildInfoPropertiesAction.java @@ -158,9 +158,8 @@ public class WriteBuildInfoPropertiesAction extends AbstractFileWriteAction { if (includeVolatile) { addValues(keys, values, context.getVolatileKeys()); long timeMillis = timestamp; - Key sourceDateEpoch = context.getStableKeys().get(BuildInfo.SOURCE_DATE_EPOCH); - if (sourceDateEpoch != null) { - timeMillis = Long.valueOf(sourceDateEpoch.getDefaultValue()) * 1000L; + if (values.containsKey(BuildInfo.BUILD_TIMESTAMP)) { + timeMillis = Long.valueOf(values.get(BuildInfo.BUILD_TIMESTAMP)) * 1000L; } keys.put("BUILD_TIMESTAMP", Long.toString(timeMillis / 1000)); keys.put("BUILD_TIME", timestampFormatter.format(timeMillis)); diff --git a/src/test/shell/integration/BUILD b/src/test/shell/integration/BUILD index b2d9439542..75471033f2 100644 --- a/src/test/shell/integration/BUILD +++ b/src/test/shell/integration/BUILD @@ -204,6 +204,13 @@ sh_library( ) sh_test( + name = "stamping_test", + size = "medium", + srcs = ["stamping_test.sh"], + data = [":test-deps"], +) + +sh_test( name = "discard_graph_edges_test", size = "medium", srcs = ["discard_graph_edges_test.sh"], diff --git a/src/test/shell/integration/stamping_test.sh b/src/test/shell/integration/stamping_test.sh new file mode 100755 index 0000000000..829cbe04bb --- /dev/null +++ b/src/test/shell/integration/stamping_test.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# An end-to-end test that Bazel's experimental UI produces reasonable output. + +# Load the test setup defined in the parent directory +CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${CURRENT_DIR}/../integration_test_setup.sh" \ + || { echo "integration_test_setup.sh not found!" >&2; exit 1; } + +set -e + +function set_up() { + mkdir -p pkg + cat > pkg/BUILD <<EOF +genrule( + name = "stamped", + outs = ["stamped.txt"], + cmd = "grep BUILD_TIMESTAMP volatile-status.txt | cut -d 2 -f ' ' >$@", + stamp = True, +) + +genrule( + name = "unstamped", + outs = ["unstamped.txt"], + cmd = "grep BUILD_TIMESTAMP volatile-status.txt | cut -d 2 -f ' ' >$@", + stamp = False, +) +EOF +} + +function test_source_date_epoch() { + bazel clean --expunge &> $TEST_log + bazel build --nostamp //pkg:* &> $TEST_log || fail "failed to build //pkg:*" + expect_equals 0 $(cat bazel-genfiles/pkg/stamped.txt) + expect_equals 0 $(cat bazel-genfiles/pkg/unstamped.txt) + + bazel clean --expunge &> $TEST_log + SOURCE_DATE_EPOCH=0 bazel build --stamp //pkg:* &> $TEST_log || fail "failed to build //pkg:*" + expect_equals 0 $(cat bazel-genfiles/pkg/stamped.txt) + expect_equals 0 $(cat bazel-genfiles/pkg/unstamped.txt) + + bazel clean --expunge &> $TEST_log + SOURCE_DATE_EPOCH=10 bazel build --stamp //pkg:* &> $TEST_log || fail "failed to build //pkg:*" + expect_equals 10 $(cat bazel-genfiles/pkg/stamped.txt) + expect_equals 0 $(cat bazel-genfiles/pkg/unstamped.txt) +} |