hermes-windows-x64
This commit is contained in:
parent
06e7413d36
commit
2c60a9483f
@ -135,6 +135,30 @@ static char *read_file(const char *filename, size_t *sz) {
|
||||
size_t sz; char *xlsx_full_min_js = read_file("xlsx.full.min.js", &sz);
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
|
||||
For Windows applications, the string must be null-terminated:
|
||||
|
||||
```cpp
|
||||
/* Hermes-Windows requires the null terminator */
|
||||
static char *read_file_null(const char *filename, size_t *sz) {
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if(!f) return NULL;
|
||||
long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f) + 1; fseek(f, 0, SEEK_SET); }
|
||||
char *buf = (char *)malloc(fsize * sizeof(char));
|
||||
*sz = fread((void *) buf, 1, fsize, f);
|
||||
buf[fsize - 1] = 0;
|
||||
fclose(f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// ...
|
||||
/* read SheetJS library from filesystem */
|
||||
size_t sz; char *xlsx_full_min_js = read_file_null("xlsx.full.min.js", &sz);
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
_Hermes Wrapper_
|
||||
|
||||
Hermes does not provide a friendly way to prepare JavaScript code stored in a
|
||||
@ -343,13 +367,20 @@ This demo was tested in the following deployments:
|
||||
| `linux-x64` | `49e1930` | 2023-09-22 |
|
||||
| `linux-arm` | `70af78b` | 2023-08-27 |
|
||||
|
||||
The main Hermes source tree does not have Windows support. The `hermes-windows`
|
||||
fork, which powers React Native for Windows, does have built-in support[^5]
|
||||
|
||||
| Architecture | Git Commit | Date |
|
||||
|:-------------|:-----------|:-----------|
|
||||
| `win10-x64` | `c7a4a82` | 2023-09-27 |
|
||||
|
||||
:::
|
||||
|
||||
0) Install [dependencies](https://hermesengine.dev/docs/building-and-running/#dependencies)
|
||||
|
||||
<details><summary><b>Installation Notes</b> (click to show)</summary>
|
||||
|
||||
The official guidance[^5] has been verified in macOS and HoloOS (Linux).
|
||||
The official guidance[^6] has been verified in macOS and HoloOS (Linux).
|
||||
|
||||
On macOS:
|
||||
|
||||
@ -424,6 +455,158 @@ curl -LO https://sheetjs.com/pres.numbers`}
|
||||
If successful, the program will print the library version number and the
|
||||
contents of the first sheet as CSV rows.
|
||||
|
||||
### Windows Example
|
||||
|
||||
0) Install dependencies.
|
||||
|
||||
<details><summary><b>Installation Notes</b> (click to show)</summary>
|
||||
|
||||
CMake and Visual Studio with "Desktop development with C++" workload must be
|
||||
installed. In addition, the following Spectre-mitigated libs must be added:
|
||||
|
||||
- MSVC C++ Spectre-mitigated libs (Latest)
|
||||
- C++ ATL for latest build tools with Spectre Mitigations
|
||||
- C++ MFC for latest build tools with Spectre Mitigations
|
||||
|
||||
The easiest way to install is to select "Individual components" and search for
|
||||
"spectre latest" (no quotation marks). Pick each option for the relevant CPU.
|
||||
|
||||
</details>
|
||||
|
||||
1) Set up `depot_tools`.
|
||||
|
||||
[`depot_tools.zip`](https://storage.googleapis.com/chrome-infra/depot_tools.zip)
|
||||
must be downloaded and extracted to `c:\src\depot_tools\`.
|
||||
|
||||
:::note pass
|
||||
|
||||
This ZIP has a number of hidden files and folders (including `.git`) which
|
||||
should be extracted along with the normal files.
|
||||
|
||||
:::
|
||||
|
||||
Add the path `c:\src\depot_tools\` to the User `PATH` environment variable
|
||||
|
||||
<details><summary><b>Environment Variable Setup</b> (click to show)</summary>
|
||||
|
||||
Type `env` in the search bar and select "Edit the system environment variables".
|
||||
|
||||
In the new window, click the "Environment Variables..." button.
|
||||
|
||||
In the new window, look for the "User variables" section. Select "Path" in the
|
||||
list and click "Edit".
|
||||
|
||||
In the new window, click "New" and type `c:\src\depot_tools` and press Enter.
|
||||
|
||||
Select the row and repeatedly click "Move Up" until it is the first entry.
|
||||
|
||||
Click "OK" in each window (3 windows) and restart your computer.
|
||||
|
||||
</details>
|
||||
|
||||
2) Delete `c:\src\depot_tools\ninja` if it exists, then download the
|
||||
[official Windows release](https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip)
|
||||
and move the `ninja.exe` into `c:\src\depot_tools`. If a `ninja.exe` exists in
|
||||
the folder, replace the existing program.
|
||||
|
||||
3) Make a project directory:
|
||||
|
||||
```bash
|
||||
mkdir sheetjs-hermes
|
||||
cd sheetjs-hermes
|
||||
```
|
||||
|
||||
4) Clone the `hermes-windows` repo:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/microsoft/hermes-windows
|
||||
cd hermes-windows
|
||||
git checkout c7a4a82
|
||||
cd ..
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
If there are errors related to SSL or certificates or `CApath`, temporarily
|
||||
disable SSL in Git:
|
||||
|
||||
```bash
|
||||
git config --global http.sslVerify false
|
||||
git clone https://github.com/microsoft/hermes-windows
|
||||
git config --global http.sslVerify true
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
5) Build the library:
|
||||
|
||||
```bash
|
||||
cd hermes-windows
|
||||
.\.ado\scripts\cibuild.ps1 -AppPlatform win32 -Platform x64 -ToolsPlatform x64
|
||||
cd ..
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
The script may fail with the message:
|
||||
|
||||
> cannot be loaded because running scripts is disabled on this system
|
||||
|
||||
In a "Run as Administrator" powershell window, run the following command:
|
||||
|
||||
```
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
6) Copy every generated `.lib` and `.dll` file into the main folder:
|
||||
|
||||
```powershell
|
||||
dir -r -Path .\hermes-windows\workspace\build\win32-x64-debug\ -Filter "*.dll" | Copy-Item -Destination .\
|
||||
dir -r -Path .\hermes-windows\workspace\build\win32-x64-debug\ -Filter "*.lib" | Copy-Item -Destination .\
|
||||
```
|
||||
|
||||
7) Download [`sheetjs-hermes.cpp`](pathname:///hermes/sheetjs-hermesw.cpp):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/hermes/sheetjs-hermesw.cpp
|
||||
```
|
||||
|
||||
8) Build the application:
|
||||
|
||||
```powershell
|
||||
cl /MDd sheetjs-hermesw.cpp DbgHelp.lib *.lib /I hermes-windows\API /I hermes-windows\include /I hermes-windows\public\ /I hermes-windows\API\jsi
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
|
||||
If `cl` is not found, run the command in the "Native Tools Command Prompt"
|
||||
|
||||
:::
|
||||
|
||||
9) Download the SheetJS Standalone script and the test file. Save both files in
|
||||
the project directory:
|
||||
|
||||
<ul>
|
||||
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
|
||||
<li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li>
|
||||
</ul>
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl -LO https://sheetjs.com/pres.numbers`}
|
||||
</CodeBlock>
|
||||
|
||||
10) Run the application:
|
||||
|
||||
```bash
|
||||
.\sheetjs-hermesw.exe pres.numbers
|
||||
```
|
||||
|
||||
If successful, the program will print the library version number and the
|
||||
contents of the first sheet as CSV rows.
|
||||
|
||||
### CLI Test
|
||||
|
||||
:::note
|
||||
@ -493,4 +676,5 @@ If successful, the script will print CSV data from the test file.
|
||||
[^2]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^3]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^4]: See [`sheet_to_csv` in "Utilities"](/docs/api/utilities/csv#csv-output)
|
||||
[^5]: See ["Dependencies" in "Building and Running"](https://hermesengine.dev/docs/building-and-running/#dependencies) in the Hermes Documentation
|
||||
[^5]: See [`microsoft/hermes-windows`](https://github.com/microsoft/hermes-windows) on GitHub
|
||||
[^6]: See ["Dependencies" in "Building and Running"](https://hermesengine.dev/docs/building-and-running/#dependencies) in the Hermes Documentation
|
@ -55,7 +55,7 @@ only be used when there is no safe way to pass `ArrayBuffer` or `Uint8Array`.
|
||||
|
||||
**Byte Conventions**
|
||||
|
||||
Java has no native concept of unsigned bytes. Values in a `byte[]` are clamped
|
||||
Java has no native concept of unsigned bytes. Values in a `byte[]` are limited
|
||||
to the range `-128 .. 127`. They need to be fixed within the JS engine.
|
||||
|
||||
Some engines support typed arrays. The `Uint8Array` constructor will fix values:
|
||||
|
117
docz/static/hermes/sheetjs-hermesw.cpp
Normal file
117
docz/static/hermes/sheetjs-hermesw.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/* sheetjs-hermesw.cpp Copyright (c) SheetJS LLC. */
|
||||
#include <iostream>
|
||||
#include "hermes/hermes.h"
|
||||
|
||||
static char *read_file(const char *filename, size_t *sz) {
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if(!f) return NULL;
|
||||
long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fseek(f, 0, SEEK_SET); }
|
||||
char *buf = (char *)malloc(fsize * sizeof(char));
|
||||
*sz = fread((void *) buf, 1, fsize, f);
|
||||
fclose(f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Hermes-Windows requires the null terminator */
|
||||
static char *read_file_null(const char *filename, size_t *sz) {
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if(!f) return NULL;
|
||||
long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f) + 1; fseek(f, 0, SEEK_SET); }
|
||||
char *buf = (char *)malloc(fsize * sizeof(char));
|
||||
*sz = fread((void *) buf, 1, fsize, f);
|
||||
buf[fsize - 1] = 0;
|
||||
fclose(f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Unfortunately the library provides no C-friendly Buffer classes */
|
||||
class CBuffer : public facebook::jsi::Buffer {
|
||||
public:
|
||||
CBuffer(const uint8_t *data, size_t size) : buf(data), sz(size) {}
|
||||
size_t size() const override { return sz; }
|
||||
const uint8_t *data() const override { return buf; }
|
||||
|
||||
private:
|
||||
const uint8_t *buf;
|
||||
size_t sz;
|
||||
};
|
||||
/* ArrayBuffer constructor expects MutableBuffer*/
|
||||
class CMutableBuffer : public facebook::jsi::MutableBuffer {
|
||||
public:
|
||||
CMutableBuffer(uint8_t *data, size_t size) : buf(data), sz(size) {}
|
||||
size_t size() const override { return sz; }
|
||||
uint8_t *data() override { return buf; }
|
||||
|
||||
private:
|
||||
uint8_t *buf;
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
std::unique_ptr<facebook::jsi::Runtime> rt(facebook::hermes::makeHermesRuntime());
|
||||
|
||||
/* setup */
|
||||
try {
|
||||
auto src = std::make_shared<facebook::jsi::StringBuffer>(
|
||||
"var global = (function(){ return this; }).call(null);"
|
||||
"var console = { log: function(x) { print(x); } };"
|
||||
);
|
||||
auto js = rt->prepareJavaScript(src, std::string("<eval>"));
|
||||
rt->evaluatePreparedJavaScript(js);
|
||||
} catch (const facebook::jsi::JSIException &e) {
|
||||
std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n';
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* load SheetJS library */
|
||||
try {
|
||||
size_t sz; char *xlsx_full_min_js = read_file_null("xlsx.full.min.js", &sz);
|
||||
auto src = std::make_shared<CBuffer>(CBuffer((uint8_t *)xlsx_full_min_js, sz));
|
||||
auto js = rt->prepareJavaScript(src, std::string("xlsx.full.min.js"));
|
||||
rt->evaluatePreparedJavaScript(js);
|
||||
} catch (const facebook::jsi::JSIException &e) {
|
||||
std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n';
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* print library version */
|
||||
try {
|
||||
auto src = std::make_shared<facebook::jsi::StringBuffer>(
|
||||
"console.log('SheetJS Library Version: ' + XLSX.version)"
|
||||
);
|
||||
auto js = rt->prepareJavaScript(src, std::string("<eval>"));
|
||||
rt->evaluatePreparedJavaScript(js);
|
||||
} catch (const facebook::jsi::JSIException &e) {
|
||||
std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n';
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
/* load payload as ArrayBuffer */
|
||||
size_t sz; char *data = read_file(argv[1], &sz);
|
||||
auto payload = std::make_shared<CMutableBuffer>(CMutableBuffer((uint8_t *)data, sz));
|
||||
auto ab = facebook::jsi::ArrayBuffer(*rt, payload);
|
||||
|
||||
/* define stub function to read and convert first sheet to CSV */
|
||||
auto src = std::make_shared<facebook::jsi::StringBuffer>(
|
||||
"(function(buf) {"
|
||||
"var wb = XLSX.read(buf);"
|
||||
"return XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);"
|
||||
"})"
|
||||
);
|
||||
auto js = rt->prepareJavaScript(src, std::string("<eval>"));
|
||||
auto func = rt->evaluatePreparedJavaScript(js);
|
||||
|
||||
/* call stub function and capture result */
|
||||
auto csv = func.asObject(*rt).asFunction(*rt).call(*rt, ab);
|
||||
|
||||
/* interpret as utf8 and print to stdout */
|
||||
std::string str = csv.getString(*rt).utf8(*rt);
|
||||
std::cout << str << std::endl;
|
||||
} catch (const facebook::jsi::JSIException &e) {
|
||||
std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user