xamarin - 获取 iOS、Android 和 OS X 上的 Xamarin 程序集构建日期

标签 xamarin build linker timestamp

在我的代码中,我需要 Xamarin 程序集构建日期。在 Windows 上我可以使用 linker time stamp 。然而在 iOS 上这不起作用。我猜它在 OS X 上也不起作用,因为可移植可执行文件头是 Windows 特有的。

还有一个选项可以嵌入带有日期的资源,但是我想避免在此特定项目中使用资源。

有没有办法找到适用于 iOS、Android 和 OS X 的 Xamarin 程序集构建日期?

最佳答案

一种方法是使用 MSBuild 任务将构建时间替换为应用程序属性返回的字符串。我们在具有 Xamarin.Forms、Xamarin.Android 和 Xamarin.iOS 项目的应用中成功使用了此方法。

如果使用 msbuild,这可以是 MSBuild 内联任务,而在 Mac 上使用 xbuild,则需要是为 Mono 编译的 MSBuild 自定义任务。

编辑:

通过将所有逻辑移至构建任务中并使用 Regex 而不是简单的字符串替换来进行简化,以便每次构建都可以修改文件而无需“重置”。

MSBuild 内联任务定义(在本示例中保存在 Xamarin.Forms 项目本地的 SetBuildDate.targets 文件中):

<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="12.0">

  <UsingTask TaskName="SetBuildDate" TaskFactory="CodeTaskFactory" 
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
    <ParameterGroup>
      <FilePath ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Code Type="Fragment" Language="cs"><![CDATA[

        DateTime now = DateTime.UtcNow;
        string buildDate = now.ToString("F");
        string replacement = string.Format("BuildDate => \"{0}\"", buildDate);
        string pattern = @"BuildDate => ""([^""]*)""";
        string content = File.ReadAllText(FilePath);
        System.Text.RegularExpressions.Regex rgx = new System.Text.RegularExpressions.Regex(pattern);
        content = rgx.Replace(content, replacement);
        File.WriteAllText(FilePath, content);
        File.SetLastWriteTimeUtc(FilePath, now);

   ]]></Code>
    </Task>
  </UsingTask>

</Project>

编辑:

添加了 MSBuild Exec 步骤以删除只读属性。一定会喜欢 TFS。

在目标 BeforeBuild 的 Xamarin.Forms csproj 文件中调用 MSBuild 任务(内联或编译,内联方法针对 xbuild 进行注释):

  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.  -->
  <!--<Import Project="SetBuildDate.targets" />-->
  <UsingTask AssemblyFile="$(MSBuildProjectDirectory)\BI.Framework.BuildExtensions.dll" TaskName="Some.Framework.BuildExtensions.BuildDateTask" />
  <Target Name="BeforeBuild">
    <Exec Command="attrib $(MSBuildProjectDirectory)\BuildMetadata.cs -r" />
    <!--<SetBuildDate FilePath="$(MSBuildProjectDirectory)\BuildMetadata.cs" />-->
    <BuildDateTask FilePath="$(MSBuildProjectDirectory)\BuildMetadata.cs" />
  </Target>

FilePath 属性设置为 Xamarin.Forms 项目中的 BuildMetadata.cs 文件,该文件包含一个带有字符串属性 BuildDate 的简单类>,构建时间将被替换为:

public class BuildMetadata
{
    public static string BuildDate => "This can be any arbitrary string";
}

将此文件 BuildMetadata.cs 添加到项目中。每次构建都会对其进行修改,但修改方式允许重复构建(重复替换),因此您可以根据需要在源代码管理中包含或省略它。

添加:

下面是一个自定义 MSBuild 任务,用于替换在 Mac 上使用 xbuild 进行构建时的 MSBuild 内联任务:

using System;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Some.Framework.BuildExtensions
{
    public class BuildDateTask : Task
    {
        #region Methods

        /// <summary>
        /// Called automatically when the task is run.
        /// </summary>
        /// <returns><c>true</c>for task success, <c>false</c> otherwise.</returns>
        public override bool Execute()
        {
            const string pattern = @"BuildDate => ""([^""]*)""";
            var now = DateTime.UtcNow;
            var buildDate = now.ToString("F");
            var replacement = $"BuildDate => \"{buildDate}\"";
            var content = File.ReadAllText(FilePath);
            var rgx = new Regex(pattern);
            content = rgx.Replace(content, replacement);
            File.WriteAllText(FilePath, content);
            File.SetLastWriteTimeUtc(FilePath, now);
            return true;
        }

        #endregion Methods

        #region Properties

        [Required]
        public string FilePath { get; set; }

        #endregion Properties
    }
}

通过 xbuild 为 Release 构建此自定义任务,然后将输出自定义任务 dll 复制到要为其设置构建日期的项目的项目目录。

关于xamarin - 获取 iOS、Android 和 OS X 上的 Xamarin 程序集构建日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37119859/

相关文章:

c++ - 解析和编译命名法

build - 更改maven插件执行顺序

c++ - AOSP - 错误 : undefined reference to <function-name> during build

iphone - AVFoundation 函数在arm6/arm7中未定义

android - Xamarin PCL 嵌入式资源

c# - 如何从 TableView 传递数据? (Xamarin.iOS)

c# - 从按钮立即响应。单击

ios - Xamarin Forms 中的 VNDocumentCameraViewController 卡住

java - 像 eclipse 一样运行 Tomcat 应用程序,但不使用 eclipse

android - 链接器剥离未使用的类