From 16062c0cd181acdd4cae84f7db9f8da72914ffe7 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Thu, 29 Sep 2022 20:54:52 -0700 Subject: [PATCH] Implement new rules for release versions (#133) ## Summary We need to implement a simple versioning schema for hermes-windows releases from release branches and pre-releases from the main branch. Thanks a lot to @dannyvv who implemented the version generation for this PR. ## The versioning schema The versioning schema is described in the new `doc\WindowsVersioning.md ` document: - The **pre-release package versions** built in the `main` branch look like **0.0.0-2209.9002-8af7870c** where the `..` versions are always `'0.0.0'`, and the prerelease part that follows after `'-'` is `'yyMM.drrr-hhhhhhhh'`. Where `'yy'` are two numbers for the year, `'MM'` are two numbers for the month, `'d'` is the day without `0` prefix, `'rrr'` is a three digit number for the today's revision, and `'hhhhhhhh'` are the first 8 hexadecimal numbers from the source GitHub commit hash. - The **pre-release file versions** look like `0.0.2209.9002` where the the encoding is `'0.0.yyMM.drrr'`. Where numbers after `'0.0.'` have the same encoding as for the pre-release package version. - The **released package versions** use the usual semantic schema which is based on RNW release numbers like `0.70.1`, where the `'0.70'` is the `.` release of RNW and RN, and the last number is a `'patch'` number for that release. Note that the `'patch'` number will not match the `'patch'` number of the RNW. We are going to generate the `'patch'` number using ADO build revision with format `'r'` that avoids `0` prefixes for the version to be valid semantic version. - The `release file versions` look like `0.70.1.0` to match the version of the package. The last part of the file version number is always `0`. Note, that the release version is going to be generated by the release pipeline. We do not expect the release version to be set somewhere in the source files or by using the processes like beachball. ## Implementation details - The `publish.yml` has a new `Setup` job that generates version numbers for the package and files using the new `setVersionNumber.js` script. The result of this job is used by `jobs.yml` to create two new variables `semanticVersion` and `fileVersion`. One is used for package semantic version and the other for the DLL/EXE file versions. - The `semanticVersion` and `fileVersion` are passed to `cibuild.ps1` where they are used to update CMake project version and `package.json` version. The `fileVersion` is passed to CMake build as `HERMES_FILE_VERSION` definition. - We ensure that `hermes.dll`, `inspector.dll`, and `hermes.exe` projects have the `version.rc` generated with the product and file versions, and with other meta-data settings. - The generated Nuget packages pickup their versions from the `package.json` file. - We set back versions in `package.json` and `CMakeLists.txt` to `0.12.0` to match `facebook/hermes` repo. This is done to reduce the diff between the two repos. We are always going to generate these versions in our release pipeline. - The `ReactNative.Hermes.Windows.Fat.nuspec` is updated to match the `ReactNative.Hermes.Windows.nuspec` because it was missing some files such as `License`, and also had some unnecessary files such as `ninja` build scripts. Now the only extra files there are the symbol `*.pdb` files. --- .ado/ReactNative.Hermes.Windows.Fat.nuspec | 16 ++++- .ado/jobs.yml | 14 +++- .ado/publish.yml | 16 ++++- .ado/scripts/cibuild.ps1 | 48 ++++++++++++- .ado/scripts/setVersionNumber.js | 82 ++++++++++++++++++++++ API/CMakeLists.txt | 2 +- API/hermes/CMakeLists.txt | 13 ++-- API/hermes/version.rc.in | 11 ++- API/inspector/CMakeLists.txt | 10 ++- API/inspector/version.rc.in | 32 +++++++++ CMakeLists.txt | 16 ++++- doc/WindowsVersioning.md | 48 +++++++++++++ npm/package.json | 2 +- tools/hermes/CMakeLists.txt | 5 ++ tools/hermes/version.rc.in | 32 +++++++++ 15 files changed, 321 insertions(+), 26 deletions(-) create mode 100644 .ado/scripts/setVersionNumber.js create mode 100644 API/inspector/version.rc.in create mode 100644 doc/WindowsVersioning.md create mode 100644 tools/hermes/version.rc.in diff --git a/.ado/ReactNative.Hermes.Windows.Fat.nuspec b/.ado/ReactNative.Hermes.Windows.Fat.nuspec index 05e335e68..b45eebfd6 100644 --- a/.ado/ReactNative.Hermes.Windows.Fat.nuspec +++ b/.ado/ReactNative.Hermes.Windows.Fat.nuspec @@ -12,9 +12,19 @@ - - - + + + + + + + + + + + + + diff --git a/.ado/jobs.yml b/.ado/jobs.yml index 13dd5d7ce..b5af9d146 100644 --- a/.ado/jobs.yml +++ b/.ado/jobs.yml @@ -1,7 +1,15 @@ +parameters: + - name: dependsOnSetup + type: boolean + default : false + jobs: - job: Build timeoutInMinutes: 120 displayName: Build Hermes + dependsOn: + - ${{ if parameters.dependsOnSetup }}: + - Setup strategy: matrix: DebugX64: @@ -22,7 +30,9 @@ jobs: ReleaseARM64: BuildConfiguration: release BuildPlatform: arm64 - + variables: + semanticVersion: $[ dependencies.Setup.outputs['setVersions.semanticVersion'] ] + fileVersion: $[ dependencies.Setup.outputs['setVersions.fileVersion'] ] steps: - task: PowerShell@2 displayName: Run the build script for publish @@ -35,6 +45,8 @@ jobs: -Platform:$(BuildPlatform) -Configuration:$(BuildConfiguration) -AppPlatform:uwp + -ReleaseVersion:"$(semanticVersion)" + -FileVersion:"$(fileVersion)" - script: echo TODO - Add Tests here displayName: '[Test] - To be Added via bug #77' diff --git a/.ado/publish.yml b/.ado/publish.yml index c4e1f7baa..cd995b01d 100644 --- a/.ado/publish.yml +++ b/.ado/publish.yml @@ -1,3 +1,9 @@ +# The release branch versions start with the release number +# such as "0.69." or "0.70." and follow the revision number. +# name: 0.70.$(Rev:r) +# +# The main branch pre-release versions start with "0.0." +# and follow the date and revision number. name: 0.0.$(Date:yyMM.d)$(Rev:rrr) pr: none @@ -17,4 +23,12 @@ variables: value: production,externalfacing jobs: - - template: jobs.yml \ No newline at end of file + - job: Setup + steps: + - script: node .ado/scripts/setVersionNumber.js + name: setVersions + displayName: Compute version numbers + + - template: jobs.yml + parameters: + dependsOnSetup: true \ No newline at end of file diff --git a/.ado/scripts/cibuild.ps1 b/.ado/scripts/cibuild.ps1 index 5605ad502..9b2301ba8 100644 --- a/.ado/scripts/cibuild.ps1 +++ b/.ado/scripts/cibuild.ps1 @@ -20,7 +20,13 @@ param( # e.g. "10.0.17763.0" [String]$SDKVersion = "", - + + # e.g. "0.0.0-2209.28001-8af7870c" for pre-release or "0.70.2" for release + [String]$ReleaseVersion = "", + + # e.g. "0.0.2209.28001" for pre-release or "0.70.2.0" for release + [String]$FileVersion = "", + [switch]$RunTests, [switch]$Incremental, [switch]$UseVS, @@ -47,9 +53,9 @@ function Find-VS-Path() { } if (Test-Path $vsWhere) { - $versionJson = & $vsWhere -format json + $versionJson = & $vsWhere -format json $versionJson = & $vsWhere -format json -version 16 - $versionJson = $versionJson | ConvertFrom-Json + $versionJson = $versionJson | ConvertFrom-Json } else { $versionJson = @() } @@ -112,6 +118,34 @@ function Invoke-Environment($Command, $arg) { }} } +function Invoke-UpdateReleaseVersion($SourcesPath, $ReleaseVersion, $FileVersion) { + if ([String]::IsNullOrWhiteSpace($ReleaseVersion)) { + return + } + + $ProjectVersion = $ReleaseVersion + if ($ReleaseVersion.StartsWith("0.0.0")) { + # Use file version as a project version for pre-release builds + # because CMake does not accept our pre-release version format. + $ProjectVersion = $FileVersion + } + + $filePath1 = Join-Path $SourcesPath "CMakeLists.txt" + $versionRegex1 = ' VERSION .*' + $versionStr1 = ' VERSION ' + $ProjectVersion + $content1 = (Get-Content $filePath1) -replace $versionRegex1, $versionStr1 -join "`r`n" + [IO.File]::WriteAllText($filePath1, $content1) + + $filePath2 = Join-Path (Join-Path $SourcesPath "npm") "package.json" + $versionRegex2 = '"version": ".*",' + $versionStr2 = '"version": "' + $ReleaseVersion + '",' + $content2 = (Get-Content $filePath2) -replace $versionRegex2, $versionStr2 -join "`r`n" + [IO.File]::WriteAllText($filePath2, $content2) + + Write-Host "Release version set to $ReleaseVersion" + Write-Host "Project version set to $ProjectVersion" +} + function get-CommonArgs($Platform, $Configuration, $AppPlatform, [ref]$genArgs) { if ($UseVS.IsPresent) { # TODO: use VS version chosen before @@ -130,6 +164,12 @@ function get-CommonArgs($Platform, $Configuration, $AppPlatform, [ref]$genArgs) $genArgs.Value += '-DHERMESVM_PLATFORM_LOGGING=On' $genArgs.Value += '-DHERMESJSI_DISABLE_STATS_TIMER=On' + + if (![String]::IsNullOrWhiteSpace($FileVersion)) { + $genArgs.Value += '-DHERMES_FILE_VERSION=' + $FileVersion + } + + Write-Host "HERMES_FILE_VERSION is $FileVersion" } function Invoke-BuildImpl($SourcesPath, $buildPath, $genArgs, $targets, $incrementalBuild, $Platform, $Configuration, $AppPlatform) { @@ -425,6 +465,8 @@ if (!(Test-Path -Path $WorkSpacePath)) { Push-Location $WorkSpacePath try { + Invoke-UpdateReleaseVersion -SourcesPath $SourcesPath -ReleaseVersion $ReleaseVersion -FileVersion $FileVersion + # run the actual builds and copy artefacts foreach ($Plat in $Platform) { foreach ($Config in $Configuration) { diff --git a/.ado/scripts/setVersionNumber.js b/.ado/scripts/setVersionNumber.js new file mode 100644 index 000000000..21e9fb5f5 --- /dev/null +++ b/.ado/scripts/setVersionNumber.js @@ -0,0 +1,82 @@ +/* + * This script sets the version number for the rest of the build. + * After this script has run, other tasks can use the variable + * to retrieve the build number for their logic... + * + * See: https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml + * for environment variables used in this script to compute the version number. + */ +const env = process.env; + +function main() { + + if (env["Build_Reason"] === "PullRequest") { + fatalError("Build script is intended for CI pipeline and should not be used for pull requests."); + } + + const {semanticVersion, fileVersion} = computeVersion(); + console.log(`Semantic Version: ${semanticVersion}`); + console.log(`Windows File Version: ${fileVersion}`); + + if (!fileVersion.startsWith(semanticVersion)) { + // Update the pipeline build number to correlate it with the semantic version. + console.log(`##vso[build.updatebuildnumber]${fileVersion} -- ${semanticVersion}`); + } + + // Set the variables (as output) so that other jobs can use them. + console.log(`##vso[task.setvariable variable=semanticVersion;isOutput=true]${semanticVersion}`); + console.log(`##vso[task.setvariable variable=fileVersion;isOutput=true]${fileVersion}`); +} + +function computeVersion() { + // Compute base version; + const sourceBranch = env["Build_SourceBranch"]; + if (sourceBranch === "refs/heads/main") { + return computeMainVersion(); + } + if (sourceBranch.startsWith("refs/heads/rnw/0.")) { + return computeReleaseVersion(); + } + + fatalError(`Build script does not support source branch '${sourceBranch}'.`) +} + +function computeMainVersion() { + const buildNumber = env["Build_BuildNumber"]; + const buildNumberParts = buildNumber.split("."); + if (buildNumberParts.length !== 4 + || buildNumberParts[0] !== '0' + || buildNumberParts[1] !== '0' + || buildNumberParts[2].length !== 4 + || buildNumberParts[3].length < 4 + || buildNumberParts[3].length > 5) { + fatalError(`Unexpected pre-release build number format encountered: ${buildNumber}`) + } + + const shortGitHash = env["Build_SourceVersion"].substring(0, 8); + + return { + semanticVersion: `0.0.0-${buildNumberParts[2]}.${buildNumberParts[3]}-${shortGitHash}`, + fileVersion: buildNumber + } +} + +function computeReleaseVersion() { + const buildNumber = env["Build_BuildNumber"]; + const buildNumberParts = buildNumber.split("."); + if (buildNumberParts.length !== 3) { + fatalError(`Unexpected release build number format encountered: ${buildNumber}`) + } + + return { + semanticVersion: buildNumber, + fileVersion: buildNumber + '.0' + } +} + +function fatalError(message) { + console.log(`##[error]${message}`); + process.exit(1); +} + +main(); \ No newline at end of file diff --git a/API/CMakeLists.txt b/API/CMakeLists.txt index db1fcec99..38e0fb1fe 100644 --- a/API/CMakeLists.txt +++ b/API/CMakeLists.txt @@ -9,6 +9,6 @@ set(HERMES_ENABLE_RTTI ON) add_subdirectory(napi) add_subdirectory(hermes) -if (HERMES_ENABLE_DEBUGGER) +if (WIN32 AND HERMES_ENABLE_DEBUGGER) add_subdirectory(inspector) endif() diff --git a/API/hermes/CMakeLists.txt b/API/hermes/CMakeLists.txt index b7d094b37..927c5f01b 100644 --- a/API/hermes/CMakeLists.txt +++ b/API/hermes/CMakeLists.txt @@ -51,15 +51,12 @@ add_hermes_library(compileJS STATIC CompileJS.cpp LINK_LIBS hermesPublic) set(HERMES_ENABLE_EH ON) set(HERMES_ENABLE_RTTI ON) -set(HERMES_VER_MAJOR ${PROJECT_VERSION_MAJOR}) -set(HERMES_VER_MINOR ${PROJECT_VERSION_MINOR}) -set(HERMES_VER_BUILD ${PROJECT_VERSION_PATCH}) -set(HERMES_VER_REVISION ${VERSION_SUFFIX}) +add_library(libhermes SHARED ${api_sources}) -configure_file(version.rc.in version.rc @ONLY) - -add_library(libhermes SHARED ${api_sources} - ${CMAKE_CURRENT_BINARY_DIR}/version.rc) +if (WIN32) + configure_file(version.rc.in version.rc @ONLY) + target_sources(libhermes PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc) +endif() # This is configured using a cmake flag instead of a separate target, because # we need the output to be named "libhermes.so". diff --git a/API/hermes/version.rc.in b/API/hermes/version.rc.in index eb0ab40d8..3459e6a67 100644 --- a/API/hermes/version.rc.in +++ b/API/hermes/version.rc.in @@ -1,8 +1,8 @@ #include VS_VERSION_INFO VERSIONINFO -FILEVERSION @HERMES_VER_MAJOR@,@HERMES_VER_MINOR@,@HERMES_VER_BUILD@,0 -PRODUCTVERSION @HERMES_VER_MAJOR@,@HERMES_VER_MINOR@,@HERMES_VER_BUILD@,0 +FILEVERSION @HERMES_FILE_VERSION_BIN@ +PRODUCTVERSION @HERMES_FILE_VERSION_BIN@ FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -17,13 +17,12 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "FileDescription", "Hermes JavaScript Engine" - VALUE "FileVersion", "@HERMES_VER_MAJOR@.@HERMES_VER_MINOR@.@HERMES_VER_BUILD@.@HERMES_VER_REVISION@" + VALUE "FileDescription", "Hermes JavaScript Engine Library" + VALUE "FileVersion", "@HERMES_FILE_VERSION@" VALUE "InternalName", "hermes.dll" VALUE "OriginalFilename", "hermes.dll" VALUE "ProductName", "Hermes JavaScript Engine" - VALUE "ProductVersion", "@HERMES_VER_MAJOR@.@HERMES_VER_MINOR@.@HERMES_VER_BUILD@.@HERMES_VER_REVISION@" - VALUE "ProductShortName", "Hermes" + VALUE "ProductVersion", "@HERMES_RELEASE_VERSION@" END END BLOCK "VarFileInfo" diff --git a/API/inspector/CMakeLists.txt b/API/inspector/CMakeLists.txt index c8aafcc40..6a362a725 100644 --- a/API/inspector/CMakeLists.txt +++ b/API/inspector/CMakeLists.txt @@ -108,7 +108,15 @@ file(GLOB inspector_public_headers ${PROJECT_SOURCE_DIR}/public/hermes/Public/*. set(HERMES_ENABLE_EH ON) set(HERMES_ENABLE_RTTI ON) -add_library(hermesinspector SHARED ${inspector_sources} ${inspector_headers} ${folly_sources} ${inspector_public_headers}) +configure_file(version.rc.in version.rc @ONLY) + +add_library(hermesinspector SHARED + ${inspector_sources} + ${inspector_headers} + ${folly_sources} + ${inspector_public_headers} + ${CMAKE_CURRENT_BINARY_DIR}/version.rc) + target_link_libraries(hermesinspector hermesPublic jsi diff --git a/API/inspector/version.rc.in b/API/inspector/version.rc.in new file mode 100644 index 000000000..3d2d5db81 --- /dev/null +++ b/API/inspector/version.rc.in @@ -0,0 +1,32 @@ +#include + +VS_VERSION_INFO VERSIONINFO +FILEVERSION @HERMES_FILE_VERSION_BIN@ +PRODUCTVERSION @HERMES_FILE_VERSION_BIN@ +FILEFLAGSMASK 0x17L +#ifdef _DEBUG +FILEFLAGS 0x1L +#else +FILEFLAGS 0x0L +#endif +FILEOS 0x4L +FILETYPE 0x1L +FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Hermes JavaScript Engine Inspector" + VALUE "FileVersion", "@HERMES_FILE_VERSION@" + VALUE "InternalName", "inspector.dll" + VALUE "OriginalFilename", "inspector.dll" + VALUE "ProductName", "Hermes JavaScript Engine" + VALUE "ProductVersion", "@HERMES_RELEASE_VERSION@" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ac9dcbc5..f1c38b4e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,7 +62,7 @@ endif() # - npm/package.json # - hermes-engine.podspec project(Hermes - VERSION 0.71.0.20220908 + VERSION 0.12.0 LANGUAGES C CXX) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/") @@ -78,6 +78,15 @@ if(NOT DEFINED HERMES_RELEASE_VERSION) set(HERMES_RELEASE_VERSION ${PROJECT_VERSION}) endif() +# The version that we put inside of DLL files +if(NOT DEFINED HERMES_FILE_VERSION) + set(HERMES_FILE_VERSION "${PROJECT_VERSION}.0") +endif() + +# The file version convertible to number representation. +# We must replace dots with commas. +string(REPLACE "." "," HERMES_FILE_VERSION_BIN ${HERMES_FILE_VERSION}) + find_package(Python COMPONENTS Interpreter) if (NOT Python_Interpreter_FOUND) message(FATAL_ERROR "Unable to find Python interpreter, required for builds and testing. @@ -326,6 +335,11 @@ if(HERMES_RELEASE_VERSION) add_definitions(-DHERMES_RELEASE_VERSION="${HERMES_RELEASE_VERSION}") endif() +# Make the HERMES_FILE_VERSION accessible for version printing in C++. +if(HERMES_FILE_VERSION) + add_definitions(-DHERMES_FILE_VERSION="${HERMES_FILE_VERSION}") +endif() + if(HERMES_ENABLE_IR_INSTRUMENTATION) add_definitions(-DHERMES_ENABLE_IR_INSTRUMENTATION) endif() diff --git a/doc/WindowsVersioning.md b/doc/WindowsVersioning.md new file mode 100644 index 000000000..68498b66e --- /dev/null +++ b/doc/WindowsVersioning.md @@ -0,0 +1,48 @@ +--- +id: hermes-windows-versioning +title: Versioning of hermes-windows +--- + +## Overview + +In this document we outline the [microsoft/hermes-windows](https://github.com/microsoft/hermes-windows) +repo branches and the release versioning. + +## Branches + +- `main` - contains the latest code. Currently we manually sync it with +Meta hermes code. + +- `rnw/*` - the folder with release branches + + - `rnw/0.70-stable` - targets React Native for Windows (RNW) 0.70 release. + - `rnw/0.69-stable` - targets React Native for Windows (RNW) 0.69 release. + - `rnw/0.68-stable` - targets React Native for Windows (RNW) 0.68 release. + +- `meta/*` - the folder with `main` and release `rn/*` branches from [facebook/hermes](https://github.com/facebook/hermes) +repo. We have a nightly process that pulls code to these branch. They have +no other changes. The goal for these branches is to see the integration +history into the `main` branch. + +## Release versions + +We have the following versioning schema for the `hermes-windows` releases: + +- The **pre-release package versions** built in the `main` branch look like +**0.0.0-2209.9002-8af7870c** where the `..` versions are +always `'0.0.0'`, and the prerelease part that follows after `'-'` is +`'yyMM.drrr-hhhhhhhh'`. Where `'yy'` are two numbers for the year, `'MM'` are +two numbers for the month, `'d'` is the day without `0` prefix, `'rrr'` is a +three digit number for the today's revision, and `'hhhhhhhh'` are the first 8 +hexadecimal numbers from the source GitHub commit hash. +- The **pre-release file versions** look like `0.0.2209.9002` where the the +encoding is `'0.0.yyMM.drrr'`. Where numbers after `'0.0.'` have the same +encoding as for the pre-release package version. +- The **released package versions** use the usual semantic schema which is +based on RNW release numbers like `0.70.1`, where the `'0.70'` is the +`.` release of RNW and RN, and the last number is a `'patch'` +number for that release. Note that the `'patch'` number will not match the +`'patch'` number of the RNW. We are going to generate the `'patch'` number +using ADO build revision with format `'r'` that avoids `0` prefixes for the +version to be valid semantic version. +- The `release file versions` look like `0.70.1.0` to match the version of the package. The last part of the file version number is always `0`. diff --git a/npm/package.json b/npm/package.json index 34a50a1ff..5b8805afd 100644 --- a/npm/package.json +++ b/npm/package.json @@ -1,5 +1,5 @@ { - "version": "0.71.0.20220908", + "version": "0.12.0", "scripts": { "unpack-builds": "node unpack-builds.js", "unpack-builds-dev": "node unpack-builds.js --dev", diff --git a/tools/hermes/CMakeLists.txt b/tools/hermes/CMakeLists.txt index 5878b3e05..f3427fe5c 100644 --- a/tools/hermes/CMakeLists.txt +++ b/tools/hermes/CMakeLists.txt @@ -47,6 +47,11 @@ target_link_libraries(hermes ${LIBREADLINE} ) +if (WIN32) + configure_file(version.rc.in version.rc @ONLY) + target_sources(hermes PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc) +endif() + install(TARGETS hermes RUNTIME DESTINATION bin ) diff --git a/tools/hermes/version.rc.in b/tools/hermes/version.rc.in new file mode 100644 index 000000000..3b3db94a7 --- /dev/null +++ b/tools/hermes/version.rc.in @@ -0,0 +1,32 @@ +#include + +VS_VERSION_INFO VERSIONINFO +FILEVERSION @HERMES_FILE_VERSION_BIN@ +PRODUCTVERSION @HERMES_FILE_VERSION_BIN@ +FILEFLAGSMASK 0x17L +#ifdef _DEBUG +FILEFLAGS 0x1L +#else +FILEFLAGS 0x0L +#endif +FILEOS 0x4L +FILETYPE 0x1L +FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Hermes JavaScript Engine CLI" + VALUE "FileVersion", "@HERMES_FILE_VERSION@" + VALUE "InternalName", "hermes.exe" + VALUE "OriginalFilename", "hermes.exe" + VALUE "ProductName", "Hermes JavaScript Engine" + VALUE "ProductVersion", "@HERMES_RELEASE_VERSION@" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file