'Is it possible to get current time at compile time for dart/flutter projects?

While writing add to app (Flutter embedding) for a complex iOS app, I run into the issue of sometimes derivedData not deleting properly, or odd things that make it so that we don't know whether or not any new changes to code got into the app when doing an end-to-end compilation.

Outside of manually updating timestamp/minor changes to the UI so that we're sure that the code changes actually got in, is there a way to retrieve the compilation date/time into a constant in a dart/flutter project?



Solution 1:[1]

You could use the build package (officially supported by the Dart team), to transform your source code during compilation. Simply insert the current time of day into a global, and you'll have what you need.

Solution 2:[2]

I also wanted to generate build-time timestamps into my Dart web app. After tinkering for a few hours, here's the working solution I found (which leverages Dart's Build package). It's not pretty, but hey, it works.

First, create a Dart file somewhere in your source folder to contain just the build timestamp, e.g. lib/src/utils/build_info.dart;

const String BUILD_TIMESTAMP = '';

Second, create another Dart file (in this example, I used src/utils/build_tool.dart) in your source folder that will write the timestamp to the above build_info.dart file:

import 'dart:async';
import 'dart:io';
import 'package:build/build.dart';

bool wroteBuildTimestamp = false;
String outputFilePath = 'lib/src/utils/build_info.dart';

Builder myTimestampBuilderFactory(BuilderOptions options) {
  //print('myTimestampBuilderFactory() called...');

  if (!wroteBuildTimestamp) {
    /// Write the current timestamp to the given file.
    print('myTimestampBuilderFactory(): Writing timestamp to file "${outputFilePath}" ...');

    String outputContents = 'const String BUILD_TIMESTAMP = \'${DateTime.now().toIso8601String()}\';\r\n';

    File dartFile = File(outputFilePath);
    dartFile = await dartFile.writeAsString(outputContents, flush: true);  /// truncates the file if it already exists.

    wroteBuildTimestamp = true;
  }

  return MyTimestampBuilder ();
}

/// This class isn't really used. We just need it to convince build_runner to call our myTimestampBuilderFactory() method at build-time.
class MyTimestampBuilder extends Builder {
  /// IMPORTANT: build() only gets called for files that been updated (or if the whole build has been cleaned), since build_runner does incremental builds by default. So we can't rely on this method being called for every build.
  @override
  Future<FutureOr<void>> build(BuildStep buildStep) async {
  }

  @override
  Map<String, List<String>> get buildExtensions {
    return const {
      '.dart': ['.dart_whatever']
    };    
  }
}

Third, in your build.yaml file, add this:

builders:
  my_timestamp_builder:
    import: "package:my_package/src/utils/build_tool.dart"
    builder_factories: ["myTimestampBuilderFactory"]
    build_extensions: {".dart": [".dart_whatever"]}
    auto_apply: all_packages

Fourth, use BUILD_TIMESTAMP in your code wherever you please. I currently display mine in an "About" popup dialog.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Randal Schwartz
Solution 2