1 | "use strict";
|
2 |
|
3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
4 |
|
5 | var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
6 |
|
7 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
8 |
|
9 | const path = require('path');
|
10 |
|
11 | const commandExists = require('command-exists');
|
12 |
|
13 | const childProcess = require('child_process');
|
14 |
|
15 | const _require = require('@parcel/utils'),
|
16 | promisify = _require.promisify;
|
17 |
|
18 | const exec = promisify(childProcess.execFile);
|
19 |
|
20 | const toml = require('@iarna/toml');
|
21 |
|
22 | const fs = require('@parcel/fs');
|
23 |
|
24 | const Asset = require('../Asset');
|
25 |
|
26 | const config = require('../utils/config');
|
27 |
|
28 | const pipeSpawn = require('../utils/pipeSpawn');
|
29 |
|
30 | const md5 = require('../utils/md5');
|
31 |
|
32 | const RUST_TARGET = 'wasm32-unknown-unknown';
|
33 | const MAIN_FILES = ['src/lib.rs', 'src/main.rs'];
|
34 |
|
35 | let rustInstalled = false;
|
36 |
|
37 | class RustAsset extends Asset {
|
38 | constructor(name, options) {
|
39 | super(name, options);
|
40 | this.type = 'wasm';
|
41 | }
|
42 |
|
43 | process() {
|
44 |
|
45 |
|
46 |
|
47 | if (this.options.isWarmUp) {
|
48 | return;
|
49 | }
|
50 |
|
51 | return super.process();
|
52 | }
|
53 |
|
54 | parse() {
|
55 | var _this = this;
|
56 |
|
57 | return (0, _asyncToGenerator2.default)(function* () {
|
58 |
|
59 | yield _this.installRust();
|
60 |
|
61 | let cargoConfig = yield _this.getConfig(['Cargo.toml']);
|
62 | let cargoDir;
|
63 | let isMainFile = false;
|
64 |
|
65 | if (cargoConfig) {
|
66 | const mainFiles = MAIN_FILES.slice();
|
67 |
|
68 | if (cargoConfig.lib && cargoConfig.lib.path) {
|
69 | mainFiles.push(cargoConfig.lib.path);
|
70 | }
|
71 |
|
72 | cargoDir = path.dirname((yield config.resolve(_this.name, ['Cargo.toml'])));
|
73 | isMainFile = mainFiles.some(file => path.join(cargoDir, file) === _this.name);
|
74 | }
|
75 |
|
76 |
|
77 |
|
78 | if (isMainFile) {
|
79 | yield _this.cargoBuild(cargoConfig, cargoDir);
|
80 | } else {
|
81 | yield _this.rustcBuild();
|
82 | }
|
83 | })();
|
84 | }
|
85 |
|
86 | installRust() {
|
87 | return (0, _asyncToGenerator2.default)(function* () {
|
88 | if (rustInstalled) {
|
89 | return;
|
90 | }
|
91 |
|
92 |
|
93 | try {
|
94 | yield commandExists('rustup');
|
95 | } catch (e) {
|
96 | throw new Error("Rust isn't installed. Visit https://www.rustup.rs/ for more info");
|
97 | }
|
98 |
|
99 |
|
100 | let _ref = yield exec('rustup', ['show']),
|
101 | _ref2 = (0, _slicedToArray2.default)(_ref, 1),
|
102 | stdout = _ref2[0];
|
103 |
|
104 | if (!stdout.includes('nightly')) {
|
105 | yield pipeSpawn('rustup', ['update']);
|
106 | yield pipeSpawn('rustup', ['toolchain', 'install', 'nightly']);
|
107 | }
|
108 |
|
109 |
|
110 | var _ref3 = yield exec('rustup', ['target', 'list', '--toolchain', 'nightly']);
|
111 |
|
112 | var _ref4 = (0, _slicedToArray2.default)(_ref3, 1);
|
113 |
|
114 | stdout = _ref4[0];
|
115 |
|
116 | if (!stdout.includes(RUST_TARGET + ' (installed)')) {
|
117 | yield pipeSpawn('rustup', ['target', 'add', RUST_TARGET, '--toolchain', 'nightly']);
|
118 | }
|
119 |
|
120 | rustInstalled = true;
|
121 | })();
|
122 | }
|
123 |
|
124 | cargoBuild(cargoConfig, cargoDir) {
|
125 | var _this2 = this;
|
126 |
|
127 | return (0, _asyncToGenerator2.default)(function* () {
|
128 |
|
129 | if (!cargoConfig.lib) {
|
130 | cargoConfig.lib = {};
|
131 | }
|
132 |
|
133 | if (!Array.isArray(cargoConfig.lib['crate-type'])) {
|
134 | cargoConfig.lib['crate-type'] = [];
|
135 | }
|
136 |
|
137 | if (!cargoConfig.lib['crate-type'].includes('cdylib')) {
|
138 | cargoConfig.lib['crate-type'].push('cdylib');
|
139 | yield fs.writeFile(path.join(cargoDir, 'Cargo.toml'), toml.stringify(cargoConfig));
|
140 | }
|
141 |
|
142 |
|
143 | let args = ['+nightly', 'build', '--target', RUST_TARGET, '--release'];
|
144 | yield exec('cargo', args, {
|
145 | cwd: cargoDir
|
146 | });
|
147 |
|
148 | let _ref5 = yield exec('cargo', ['metadata', '--format-version', '1'], {
|
149 | cwd: cargoDir
|
150 | }),
|
151 | _ref6 = (0, _slicedToArray2.default)(_ref5, 1),
|
152 | stdout = _ref6[0];
|
153 |
|
154 | const cargoMetadata = JSON.parse(stdout);
|
155 | const cargoTargetDir = cargoMetadata.target_directory;
|
156 | let outDir = path.join(cargoTargetDir, RUST_TARGET, 'release');
|
157 |
|
158 | let rustName = cargoConfig.package.name.replace(/-/g, '_');
|
159 | _this2.wasmPath = path.join(outDir, rustName + '.wasm');
|
160 | _this2.depsPath = path.join(outDir, rustName + '.d');
|
161 | })();
|
162 | }
|
163 |
|
164 | rustcBuild() {
|
165 | var _this3 = this;
|
166 |
|
167 | return (0, _asyncToGenerator2.default)(function* () {
|
168 |
|
169 | yield fs.mkdirp(_this3.options.cacheDir);
|
170 | let name = md5(_this3.name);
|
171 | _this3.wasmPath = path.join(_this3.options.cacheDir, name + '.wasm');
|
172 |
|
173 | const args = ['+nightly', '--target', RUST_TARGET, '-O', '--crate-type=cdylib', _this3.name, '-o', _this3.wasmPath];
|
174 | yield exec('rustc', args);
|
175 |
|
176 | _this3.depsPath = path.join(_this3.options.cacheDir, name + '.d');
|
177 | yield exec('rustc', [_this3.name, '--emit=dep-info', '-o', _this3.depsPath]);
|
178 | })();
|
179 | }
|
180 |
|
181 | collectDependencies() {
|
182 | var _this4 = this;
|
183 |
|
184 | return (0, _asyncToGenerator2.default)(function* () {
|
185 |
|
186 | let contents = yield fs.readFile(_this4.depsPath, 'utf8');
|
187 | let dir = path.dirname(_this4.name);
|
188 | let deps = contents.split('\n').filter(Boolean).slice(1);
|
189 | var _iteratorNormalCompletion = true;
|
190 | var _didIteratorError = false;
|
191 | var _iteratorError = undefined;
|
192 |
|
193 | try {
|
194 | for (var _iterator = deps[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
195 | let dep = _step.value;
|
196 | dep = path.resolve(dir, dep.slice(0, dep.indexOf(': ')));
|
197 |
|
198 | if (dep !== _this4.name) {
|
199 | _this4.addDependency(dep, {
|
200 | includedInParent: true
|
201 | });
|
202 | }
|
203 | }
|
204 | } catch (err) {
|
205 | _didIteratorError = true;
|
206 | _iteratorError = err;
|
207 | } finally {
|
208 | try {
|
209 | if (!_iteratorNormalCompletion && _iterator.return != null) {
|
210 | _iterator.return();
|
211 | }
|
212 | } finally {
|
213 | if (_didIteratorError) {
|
214 | throw _iteratorError;
|
215 | }
|
216 | }
|
217 | }
|
218 | })();
|
219 | }
|
220 |
|
221 | generate() {
|
222 | var _this5 = this;
|
223 |
|
224 | return (0, _asyncToGenerator2.default)(function* () {
|
225 | return {
|
226 | wasm: {
|
227 | path: _this5.wasmPath,
|
228 |
|
229 | mtime: Date.now()
|
230 |
|
231 | }
|
232 | };
|
233 | })();
|
234 | }
|
235 |
|
236 | }
|
237 |
|
238 | module.exports = RustAsset; |
\ | No newline at end of file |