0
mirror of https://github.com/valentineus/popov.link.git synced 2025-07-03 16:10:26 +03:00

Initial Astro project

This commit is contained in:
2024-09-04 21:16:37 +00:00
parent ecf9a15e77
commit 7eff3fde57
66 changed files with 7118 additions and 2173 deletions

View File

@ -0,0 +1,51 @@
---
title: 'Create ".lib" file from ".dll" (archive)'
author: "Adrian Henke"
pubDate: "2023-05-04"
description: "Learn how to generate a *.lib file from a *.dll with this comprehensive guide. Using the Visual Studio Command Prompt and Microsoft's recommended tools, this article walks you through the steps for a seamless process. Perfect for developers working with 3rd party win dll's."
---
> This's a copy of a non-my post. The original article [is here](https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/) ([archive](https://web.archive.org/web/20161118122539/https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/)).
When working with 3rd party win dll's you sometimes miss the according to the `*.lib` file required to compile against it. There is an [Microsoft KB-Q131313](http://support.microsoft.com/?scid=kb%3Ben-us%3B131313&x=1&y=15) ([archive](https://jeffpar.github.io/kbarchive/kb/131/Q131313/)) article showing how to generate a `*.lib` file from a `*.dll` however the required steps are not described detailed enough I think. So here is my quick guide.
Open the "Visual Studio Command Prompt", you find its shortcut in "_Start_" -> "_Programs_" -> "_Microsoft Visual Studio Tools_". Now run the `dumpbin` command to get a list of all exported functions of your dll:
```bash
dumpbin /exports C:\\yourpath\\yourlib.dll
```
This will print quite a bit of text to the console. However, we are only interested in the functions:
```
ordinal hint RVA name
1 0 00017770 jcopy_block_row
2 1 00017710 jcopy_sample_rows
3 2 000176C0 jdiv_round_up
4 3 000156D0 jinit_1pass_quantizer
5 4 00016D90 jinit_2pass_quantizer
6 5 00005750 jinit_c_coef_controller
...etc
```
Now copy all those function names (only the names!) and paste them into a new text file. Name the next file `yourlib.def` and put the line "EXPORTS" at its top. My `yourlib.def` file looks like this:
```
EXPORTS
jcopy_block_row
jcopy_sample_rows
jdiv_round_up
jinit_1pass_quantizer
jinit_2pass_quantizer
jinit_c_coef_controller
...
```
Now from that definition file, we can finally create the `*.lib` file. We use the `lib` tool for this, so run this command in your "Visual Studio Command Prompt":
```bash
lib /def:C:\\mypath\\mylib.def /OUT:C:\\mypath\\mylib.lib
```
That's it, happy coding 🙂

View File

@ -0,0 +1,60 @@
---
title: "Горячая перезагрузка ElectronJS приложения"
author: "Valentin Popov"
pubDate: "2019-08-15"
description: "Руководство по автоматической перезагрузке приложений на Electron с помощью пакетов electron-reload и electron-webpack. Обход проблем с совместимостью и использование HMR для renderer процесса."
---
## Main процесс
Для перезагрузки основного процесса можно использовать готовый пакет [electron-reload]. Или перезагружать приложение средствами пакета [electron-webpack].
Если сборщик кода отличный от WebPack или нет возможности использовать вышеуказанные пакеты, можно обойтись инструментом [nodemon]. Команда запуска будет выглядеть следующим образом:
```bash
nodemon --watch ./assets/main.js --exec 'electron .'
```
Приложение будет автоматически перезапускаться при модификациях указанного файла.
## Renderer процесс
Для обновления renderer процесса, перезагружать полностью приложение нет необходимости. Достаточно обновить страницу. Самый простой способ, горячие клавиши: `Ctrl` + `F5`. Так как рендер процесс по своей сути является обычным окном браузера, можно настроить [HMR] технологию. Конечно, если используются соответствующие инструменты.
Мне симпатичен способ использования пакета [electron-reload]. В алгоритме пакета лежит простое слежение за каталогом файлов и обновление активных окон приложения.
Но мною была найдена досадная [проблема], не позволяющая использовать версии `1.5.0` и `1.4.1` со сборщиком WebPack, который используется в проекте.
Решение было продублировать основной функционал пакета в проекте:
```javascript
import { app } from "electron";
import chokidar from "chokidar";
const browserWindows = [];
app.on("browser-window-created", (event, window) => {
browserWindows.push(window);
window.on("closed", () => {
const index = browserWindows.indexOf(window);
browserWindows.splice(index, 1);
});
});
if (process.env.NODE_ENV !== "production") {
const watcher = chokidar.watch(__dirname, { ignored: [/node_modules|[/\\]\./] });
watcher.on("change", () => {
browserWindows.forEach((window) => {
window.webContents.reloadIgnoringCache();
});
});
}
```
[HMR]: https://webpack.js.org/concepts/hot-module-replacement/
[electron-reload]: https://www.npmjs.com/package/electron-reload
[electron-webpack]: https://www.npmjs.com/package/electron-webpack
[nodemon]: https://www.npmjs.com/package/nodemon
[проблема]: https://github.com/yan-foto/electron-reload/issues/66

View File

@ -0,0 +1,133 @@
---
title: "Example Content"
author: "Example User"
pubDate: "2018-01-01"
description: "Howdy! This is an example blog post that shows several types of HTML content supported in this theme."
---
Cum sociis natoque penatibus et magnis <a href="#">dis parturient montes</a>, nascetur ridiculus mus. _Aenean eu leo quam._ Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras mattis consectetur purus sit amet fermentum.
> Curabitur blandit tempus porttitor. Nullam quis risus eget urna mollis ornare vel eu leo. Nullam id dolor id nibh ultricies vehicula ut id elit.
Etiam porta **sem malesuada magna** mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.
## Inline HTML elements
HTML defines a long list of available inline tags, a complete list of which can be found on the [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/HTML/Element).
- **To bold text**, use `<strong>`.
- _To italicize text_, use `<em>`.
- Abbreviations, like <abbr title="HyperText Markup Langage">HTML</abbr> should use `<abbr>`, with an optional `title` attribute for the full phrase.
- Citations, like <cite>&mdash; Mark otto</cite>, should use `<cite>`.
- <del>Deleted</del> text should use `<del>` and <ins>inserted</ins> text should use `<ins>`.
- Superscript <sup>text</sup> uses `<sup>` and subscript <sub>text</sub> uses `<sub>`.
Most of these elements are styled by browsers with few modifications on our part.
## Heading
Vivamus sagittis lacus vel augue rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
### Code
Cum sociis natoque penatibus et magnis dis `code element` montes, nascetur ridiculus mus.
```js
// Example can be run directly in your JavaScript console
// Create a function that takes two arguments and returns the sum of those arguments
var adder = new Function("a", "b", "return a + b");
// Call the function
adder(2, 6);
// > 8
```
Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.
### Gists via GitHub Pages
Vestibulum id ligula porta felis euismod semper. Nullam quis risus eget urna mollis ornare vel eu leo. Donec sed odio dui.
{% gist 5555251 gist.md %}
Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec sed odio dui. Vestibulum id ligula porta felis euismod semper.
### Lists
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.
- Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
- Donec id elit non mi porta gravida at eget metus.
- Nulla vitae elit libero, a pharetra augue.
Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue.
1. Vestibulum id ligula porta felis euismod semper.
2. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
3. Maecenas sed diam eget risus varius blandit sit amet non magna.
Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis.
<dl>
<dt>HyperText Markup Language (HTML)</dt>
<dd>The language used to describe and define the content of a Web page</dd>
<dt>Cascading Style Sheets (CSS)</dt>
<dd>Used to describe the appearance of Web content</dd>
<dt>JavaScript (JS)</dt>
<dd>The programming language used to build advanced Web sites and applications</dd>
</dl>
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Nullam quis risus eget urna mollis ornare vel eu leo.
### Images
Quisque consequat sapien eget quam rhoncus, sit amet laoreet diam tempus. Aliquam aliquam metus erat, a pulvinar turpis suscipit at.
![placeholder](http://placehold.it/800x400 "Large example image") ![placeholder](http://placehold.it/400x200 "Medium example image") ![placeholder](http://placehold.it/200x200 "Small example image")
### Tables
Aenean lacinia bibendum nulla sed consectetur. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Upvotes</th>
<th>Downvotes</th>
</tr>
</thead>
<tfoot>
<tr>
<td>Totals</td>
<td>21</td>
<td>23</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>Alice</td>
<td>10</td>
<td>11</td>
</tr>
<tr>
<td>Bob</td>
<td>4</td>
<td>3</td>
</tr>
<tr>
<td>Charlie</td>
<td>7</td>
<td>9</td>
</tr>
</tbody>
</table>
Nullam id dolor id nibh ultricies vehicula ut id elit. Sed posuere consectetur est at lobortis. Nullam quis risus eget urna mollis ornare vel eu leo.
---
Want to see something else added? <a href="https://github.com/poole/poole/issues/new">Open an issue.</a>

View File

@ -0,0 +1,185 @@
---
title: 'Получение исходного кода "Chromium Projects"'
author: "Valentin Popov"
pubDate: "2012-01-30"
description: "Изучение исходных кодов Chromium: подготовка системы и установка необходимых программных компонентов. Руководство для начинающих разработчиков. Получите инструкции по установке Microsoft Visual Studio, Cygwin, Python и других инструментов. Действительно на январь-февраль 2012 года."
---
> Перенос [оригинальной статьи](https://adeptus-mechanicus.blogspot.com/2012/01/chromium-projects.html) 2012 года из моего [старого блога](https://adeptus-mechanicus.blogspot.com/) ([зеркало](https://web.archive.org/web/20160217052148/http://adeptus-mechanicus.blogspot.com/)).
**Добрый день, уважаемые читатели!**
В последние дни выдалось свободное время, и я решил изучить исходные коды "[The Chromium Projects](http://www.chromium.org/)". Чтобы посмотреть исходники, оказалось недостаточным просто скачать архив с исходным кодом и начать работать с ним в "Visual Studio 2010". Я был крайне опечален отсутствием нормальной русской документации для начинающих, поэтому восполню пробел и переведу всю инструкцию по получению исходных кодов.
**\_P.S.** Chromium является быстроразвивающимся Open Sources проектом.\_ анная инструкция актуальна на январь-февраль 2012 года._
Для начала немного введения. Весь процесс от подготовки системы, до работы с исходными кодами я условно разделю на четыре пункта, это:
- Подготовка операционной системы, установка стандартных программных комплектов разработчика;
- Установка и настройка программы "Cygwin";
- Установка и настройка пакета "depot_tools";
- Получение и подготовка для работы исходных кодов "Chromium";
## Подготовка начального набора программ
Ниже приведу список и краткое описание программного обеспечения, которое требуется установить перед работой с исходными кодами:
- "**Microsoft Visual Studio 2010**" — Среда разработки, требуется для работы с исходным кодом. Имеется возможность использовать Microsoft Visual Studio 2008 и Microsoft Visual C++ Express 2010'го и 2008'го годов соответственно. Бесплатные Express версии продуктов можно взять на [официальном сайте](http://www.microsoft.com/express) Microsoft.
- "**Microsoft Windows SDK**" — Пакет для предоставления заголовочных файлов, библиотек, компиляторов и пр. для разработчиков программного обеспечения под операционную систему Windows. Требуется для успешной сборки и компиляции проекта под Windows систему. Бесплатно можно скачать с [официальной страницы](https://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b).
- "**Microsoft DirectX SDK**" — Пакет с библиотеками мультимедийной подсистемы DirectX. Требуется для успешной сборки и компиляции проекта. Бесплатно доступен на [официальном сайте](http://msdn.microsoft.com/en-us/directx/default.aspx).
- "**Python 2.x**" — Высокоуровневый язык программирования. Требуется для начальной подготовки исходных кодов. Установка не обязательная, но желательная. Про третью версию Python официальной информации нет, у меня установлены обе версии для опытов и "Path" системы направлен на вторую версию. Установку Python коротко разберу ниже. Python бесплатно можно взять на [официальном сайте](http://python.org/).
- "**Cygwin**" — Unix-подобная среда и интерфейс командной строки для систем Microsoft Windows. Требуется для работы с исходными кодами, их подготовки, обновлением и проверки на ошибки. Сам инструмент бесплатно доступен на [официальной странице](http://www.cygwin.com/). Его установку я распишу в следующих пунктах.
- "**TortoiseSVN**" — Клиент Subversion под систему Windows. Установка не обязательная, но желательная. Требуется для более простого обновления пакета "depot_tools" из официального репозитория SVN от корпорации Google. Бесплатно доступен на [официальной странице](http://tortoisesvn.net/).
Над установкой Microsoft Visual Studio, Microsoft Windows SDK и Microsoft DirectX SDK я подробно останавливаться не буду. Установка данных программных комплектов проста, и особой сложности вызывать не должна. В случае возникновения каких-либо проблем, имеются огромные сообщества разработчиков, которые помогут с установкой.
**На установке пакета Python'а я остановлюсь поподробнее:**
Во-первых, путь установки Python'а не должен содержать русскоязычный текст, это может вызвать много ошибок.
Во-вторых, после установки основного пакета, не забудьте добавить имя каталога в список путей, по которому операционная система ищет исполняемые файлы. Чтобы это сделать, требуется:
1. Запустите "_Панель Управления_" и выберите пиктограмму "_Система_";
2. Выберите "_Дополнительные настройки системы_";
3. Перейдите во вкладку "_Дополнительно_" и щёлкните на кнопке "_Переменные среды_";
4. В содержимом окна "_Системные переменные_" найдите строку "_Path_";
5. Добавьте туда путь до вашего каталога Python.
В моём случае этот путь выглядел так: `C:\Program Files (x86)\Python2`. Пути каталогов должны разделяться знаком `;`, по этому не забудьте перед последним записанным каталогом дописать `;` (без кавычек);
Чтобы проверить работоспособность языка Python в Вашей системе сразу после установки, откройте командную строку Windows и введите команду:
```bash
python --version
```
На экране должно появиться сообщение с версией Python, которая используется в Вашей системе по-умолчанию.
**Теперь подготовим каталоги.** Каталог исходных кодов в моём случае располагается на диске `C:\`, потому что желательно не использовать пробелы в пути адреса до исходных кодов и мой пользователь в операционной системе состоит из русскоязычных символов.
На диске `C:\` я создал каталог `OpenSource`, в нём я создал каталог `ChromiumProjects`, в котором появилось два подкаталога `depot_tools` и `trunk`. Т.е. система каталогов выглядит так:
- `C:\OpenSource\ChromiumProjects\depot_tools` — Пакет для работы с исходным кодом;
- `C:\OpenSource\ChromiumProjects\trunk` — Место хранения исходных кодов;
В случае использование других каталогов в вашей системе, используйте собственные пути, подставляя их в мои примеры.
Так же крайне рекомендуется отключить индексирование системы в данных каталогах, потому что это вызовет фатальные ошибки работы пакета "depot*tools". Чтобы это сделать, откройте "*Панель управления*", выберите пиктограмму "*Параметры индексирования*", нажмите на кнопку "*Изменить\_" и снимите галочку с каталога, содержащий утилиту "depot_tools".
Первоначальную установку и настройку системы можно считать оконченной. Переходим к следующему шагу.
## Установка программы "Cygwin"
Первым делом получите установочный файл последней версии по этой [ссылке](http://cygwin.com/setup.exe). Установочный файл во время установки скачивает необходимые пакеты из интернета. Когда запустите файл, следуйте инструкциям. После выбор зеркала пакетов, Вам покажут список доступных пакетов с зеркала. Требуется найти и отметить для установки следующие пакеты:
- `apache`;
- `bc`;
- `bison`;
- `curl`;
- `diffutils`;
- `e2fsprogs`;
- `emacs`;
- `flex`;
- `gcc`;
- `gperf`;
- `keychain`;
- `make`;
- `nano`;
- `openssh`;
- `patch`;
- `perl`;
- `perl-libwin32`;
- `python`;
- `rebase`;
- `rsync`;
- `ruby`;
- `subversion`;
- `unzip`;
- `vim`;
- `zip`;
Имена пакетов должны полностью совпадать. Воспользуйтесь поиском по пакетам, включённым в саму программу установки. Это должно сильно облегчить задачу.
Актуальный список пакетов, требующихся для установки, Вы всегда можете найти в [официальном скрипте](http://trac.webkit.org/browser/trunk/Tools/CygwinDownloader/cygwin-downloader.py) установки, в поле `required_packages`.
После установки приложения, требуется внести путь до папки с исполняемыми файлами в переменную "Path". Сделать это можно в точности, как после установки пакета Python'а, описанного чуть выше в данной статье. Только в отличии от Python'а, требуется указать путь до папки `bin`, находящейся в корневом каталоге приложения "Cygwin". В моём случае этот путь выглядел так: `C:\Program Files (x86)\Cygwin\bin`.
После установки и проверки приложения "Cygwin", можно переходить к следующему шагу, настройке и установки пакета "depot_tools".
## Установка пакета "depot_tools"
1. Перейдите в каталог, который Вы определили для хранения пакета "depot_tools";
2. Находясь в папке, нажмите правую кнопку мыши в любом свободном месте и контекстном меню выберите пункт "_SVN Checkout_";
3. В пути URL репозитория, указывайте путь: `http://src.chromium.org/svn/trunk/tools/depot_tools`;
Если проблем не возникнет, пойдёт установка последней ревизии данного пакета. По окончанию скачивания пакета, путь до исполняемых файлов пакета следует указать в переменной "Path", по аналогии с программой "Cygwin" и пакетом "Python". В моём случае, путь выглядел так: `C:\OpenSource\ChromiumProjects\depot_tools`.
Если всё прошло успешно, можно перейти к заключительной части статьи, получения и подготовка исходных кодов браузера "Chromium".
## Получение и подготовка исходных кодов
Перейдите по данной [ссылке](http://chromium-browser-source.commondatastorage.googleapis.com/chromium_tarball.html) и скачайте архив с исходными кодами. Вы получите архив с именем "_chromium.r**XXXXX**.tgz_", где **XXXXX** — номер стабильной последней версии.
Распакуйте из архива папку `src` в наш каталог `trunk`. Процесс займёт продолжительное время, потому что объём исходных кодов ~4 Гб. По окончанию распаковки, откройте терминал "Cygwin".
В открытом терминале теперь необходимо пройти в каталог `src`, который получится после распаковки исходных кодов. Переход по каталогам в терминале осуществляется программой `cd`. Чтобы попасть на диск `C:\`, требуется в терминале набрать команду:
```bash
cd "C:/"
```
Чтобы вернуться на каталог выше, требуется набрать команду:
```bash
cd ..
```
В Unix-терминалах для работы с каталогами используется обратная косая черта. По этому, чтобы перейти в требуемый каталог, на моём примере, команда будет выглядеть так:
```bash
cd "C:/OpenSource/ChromiumProjects/trunk/src"
```
Теперь, когда мы в требуемой папке, надо применить команду для первоначальной настройки исходных кодов. Для этого ведите команду:
```bash
gclient sync --force
```
После выполнения данной команды, требуется подготовить исходные коды для работы с "_Visual Studio 2010_". Для этого вводим команду:
```bash
gclient runhooks --force
```
По окончанию выполнения данной команды, мы получаем готовые к работе исходные коды. Чтобы начать с ними работу, откройте Вашу "Visual Studio", выберите "_Открыть проект_" и откройте файл `chrome.sln`, который находится в папке `chrome`, находящейся в папке исходных кодов. В моём случае, полный путь до файла выглядит так: `C:\OpenSource\ChromiumProjects\trunk\src\chrome\chrome.sln`.
На этом работу можно считать законченной.
## Обновление
Чтобы обновить пакет "depot*tools", требуется зайти в каталог, содержащий данный пакет, щёлкнуть правой кнопкой мыши и в контекстном меню выбрать "\_SVN Update*". "TortoiseSVN" обновит данные каталога до последней ревизии пакета.
Для обновления исходных кодов "Chromium", требуется открыть терминал "Cygwin", перейти в каталог с исходными кодами и ввести команду:
```bash
gclient sync
```
## Заключение
Спасибо, что прочитали и большое спасибо, если воспользовались моей инструкцией. Я всегда рад Вашим комментариям с вопросами, уточнениями и предложениями.
## Полезные ссылки
- [http://dev.chromium.org/Home](http://dev.chromium.org/Home) — Официальная страница проекта "The Chromium Projects";
- [http://dev.chromium.org/developers/how-tos/build-instructions-windows](http://dev.chromium.org/developers/how-tos/build-instructions-windows) — Официальная страница по подготовке операционной системы Windows, перед работой с исходными кодами;
- [http://dev.chromium.org/developers/how-tos/get-the-code](http://dev.chromium.org/developers/how-tos/get-the-code) — Официальная инструкция по получению, настройке и подготовке исходных кодов проекта "The Chromium Projects";
- [http://dev.chromium.org/developers/how-tos/install-depot-tools](http://dev.chromium.org/developers/how-tos/install-depot-tools) — Официальная инструкция по установке и настройке пакета "depot_tools";
- [http://dev.chromium.org/developers/how-tos/cygwin](http://dev.chromium.org/developers/how-tos/cygwin) — Страница по установки и настройке терминала "Cygwin";
- [http://groups.google.com/a/chromium.org/group/chromium-discuss/topics](http://groups.google.com/a/chromium.org/group/chromium-discuss/topics) — Официальная дискуссия разработчиков браузера "Chromium";

View File

@ -0,0 +1,23 @@
---
title: "Установка Moodle в Fedora"
author: "Valentin Popov"
pubDate: "2018-07-23"
description: "Решение проблем установки Moodle из-за SELinux: как настроить правила доступа для устранения ошибок в веб-интерфейсе и при работе с cURL. Практические советы и команды."
---
Во время установки Moodle, сталкиваешься со следующими проблемами:
- Веб-интерфейс не продолжает установку после настройки базы данных;
- Если установить через консольный интерфейс, проявляются артефакты;
- Нет доступа к сети, появляется ошибка `unexpected cURL error`.
Главная причина, это [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux). Решение, это настроить правила доступа:
```bash
# Доступ к сторонним каталогам и сети
/usr/sbin/setsebool -P httpd_can_network_connect true
/usr/sbin/setsebool -P httpd_enable_homedirs true
# Смена контекста безопасности
/usr/bin/chcon -R -h -t httpd_sys_content_t /path/to/moodle
/usr/bin/chcon -R -h -t httpd_sys_script_rw_t /path/to/moodle_data
```

View File

@ -0,0 +1,172 @@
---
title: "Компиляция Rust на TL-MR3020"
author: "Valentin Popov"
pubDate: "2023-05-01"
description: 'Как настроить и оптимизировать проект Rust для кросс-компиляции на TP-Link TL-MR3020 с использованием Fedora Linux 38 и OpenWrt 22.03.4. Шаг за шагом от базового "Hello, World!" до асинхронного TCP сервера.'
---
Информация в статье актуальна для дистрибутива [Fedora Linux 38](https://docs.fedoraproject.org/en-US/releases/f38/), прошивки [OpenWrt 22.03.4](https://openwrt.org/releases/22.03/notes-22.03.4) и устройства [TP-Link TL-MR3020](https://www.tp-link.com/en/home-networking/3g-4g-router/tl-mr3020/) ревизии v3.20.
Потребуется:
- Установленный [rustup](https://rustup.rs/) инструментарий.
- Установленный пакет [cross-rs](https://github.com/cross-rs/cross) для кросс-компиляции.
- Упаковщик исполняемых файлов [upx](https://github.com/upx/upx).
- Контейнеризатор [Docker](https://docs.docker.com/engine/install/) (рекомендуется) или [Podman](https://podman.io/getting-started/installation).
- SSH подключение к маршрутизатору.
- Установленный [SFTP сервер](https://openwrt.org/docs/guide-user/services/nas/sftp.server) на TL-MR3020.
> Требуется rustup инструментарий с официального сайта. Rust и Cargo из репозитория дистрибутива не подойдут. Пакет кросс-компиляции требует rustup, который в репозиториях дистрибутива отсутствует.
## "Hello, World!" ver. 1
Начнем с базы. Соберем и запустим "Hello, World" на маршрутизаторе. Инициализируем проект на Rust:
```bash
cargo init --bin ramips-rs
```
Далее, чтобы выполнить кросс-компиляцию, определим архитектуру процессора:
```bash
cat /proc/cpuinfo
# system type : MediaTek MT7628AN ver:1 eco:2
# machine : TP-Link TL-MR3020 v3
# processor : 0
# cpu model : MIPS 24KEc V5.5
# BogoMIPS : 385.84
# wait instruction : yes
# microsecond timers : yes
# tlb_entries : 32
# extra interrupt vector : yes
# hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
# isa : mips1 mips2 mips32r1 mips32r2
# ASEs implemented : mips16 dsp
# Options implemented : tlb 4kex 4k_cache prefetch mcheck ejtag llsc pindexed_dcache userlocal vint perf_cntr_intr_bit perf
# shadow register sets : 1
# kscratch registers : 0
# package : 0
# core : 0
# VCED exceptions : not available
# VCEI exceptions : not available
```
Видим, что процессор архитектуры MIPS. Теперь определим целевую архитектуру для компиляции:
```bash
rustup target list | grep mips
# mips-unknown-linux-gnu
# mips-unknown-linux-musl
# mips64-unknown-linux-gnuabi64
# mips64-unknown-linux-muslabi64
# mips64el-unknown-linux-gnuabi64
# mips64el-unknown-linux-muslabi64
# mipsel-unknown-linux-gnu
# mipsel-unknown-linux-musl
```
Опытным путем определяем, что в случае с TL-MR3020 v3.20 подходит архитектура `mipsel-unknown-linux-musl`. Далее компилируем проект под целевую архитектуру:
```bash
cross build --release --target mipsel-unknown-linux-musl
```
Получаем исполняемый бинарный файл, который загружаем и запускаем на маршрутизаторе. Выгружаем в раздел `/tmp`, потому что доступной памяти на основном разделе меньше двух мегабайт.
```bash
scp ./target/mipsel-unknown-linux-musl/release/ramips-rs openwrt:/tmp/
ssh openwrt /tmp/ramips-rs
# Hello, world!
```
## Оптимизация размера бинарника
После сборки и запуска "Hello, World" можно обратить внимание, что исполняемый файл весит **4.1 мегабайта**. Для устройства с 8 мегабайтами постоянной памяти это катастрофически много.
Уменьшим размер исполняемого файла до приемлемого минимума. Для этого настроим release профиль сборки и компиляции проекта. Дополним Cargo.toml файл:
```toml
[profile.release]
strip = true # Уменьшает бинарник до 383K
lto = "fat" # Уменьшает бинарник до 334K
opt-level = "z" # Уменьшает бинарник до 326K
panic = "abort" # Уменьшает бинарник да 332K
codegen-units = 1 # Включает дополнительные оптимизации кода
```
Получаем исполняемый файл размером в **332 килобайта**. Далее сжимаем исполняемый файл инструментом upx:
```bash
upx --best --lzma target/mipsel-unknown-linux-musl/release/ramips-rs
```
И получаем исходный файл размером в **118 килобайт**. Приемлемый результат.
Сильнее уменьшить бинарник можно отказом от стандартной std библиотеки и другими экстремальными unsafe приемами, что не подходит в моем случае.
## "Hello, World!" ver. 2
Теперь сделаем пример посерьезней. Например, асинхронный TCP сервер. Подключаем зависимости:
```toml
[dependencies]
hyper = { version = "1.0.0-rc.3", features = ["full"] }
tokio = { version = "1", features = ["full"] }
http-body-util = "0.1.0-rc.2"
```
Пишем код:
```rust
use std::convert::Infallible;
use std::net::SocketAddr;
use http_body_util::Full;
use hyper::body::Bytes;
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper::{Request, Response};
use tokio::net::TcpListener;
async fn hello(_: Request<hyper::body::Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
Ok(Response::new(Full::new(Bytes::from("Hello, World!"))))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
let listener = TcpListener::bind(addr).await?;
loop {
let (stream, _) = listener.accept().await?;
tokio::task::spawn(async move {
if let Err(err) = http1::Builder::new()
.serve_connection(stream, service_fn(hello))
.await
{
println!("Error serving connection: {:?}", err);
}
});
}
}
```
Проверяем, компилируем и сжимаем. Получаем бинарник размером в **236 килобайт**. Теперь загружаем в устройство, запускаем и проверяем:
```bash
scp ./target/mipsel-unknown-linux-musl/release/ramips-rs openwrt:/tmp/
ssh openwrt /tmp/ramips-rs
curl -L "http://10.0.0.2:3000"
# Hello, World!
```
Работает как и задумано.
## Полезные ссылки и источники
- [Building Rust code for my OpenWrt Wi-Fi router](https://blog.dend.ro/building-rust-for-routers/)
- [Cross Compile Rust For OpenWRT](https://www.kiloleaf.com/posts/cross-compile-rust-for-openwrt/)
- [Minimizing Rust Binary Size](https://github.com/johnthagen/min-sized-rust)
- [Кросс-компиляция программ Rust для запуска на маршрутизаторе](https://dzen.ru/media/nuancesprog.ru/krosskompiliaciia-programm-rust-dlia-zapuska-na-marshrutizatore-5f6457b8bdfa745d402cd1ec)

13
src/content/config.ts Normal file
View File

@ -0,0 +1,13 @@
import { defineCollection, z } from "astro:content";
const blog = defineCollection({
type: "content",
schema: z.object({
author: z.string(),
description: z.string(),
pubDate: z.coerce.date(),
title: z.string(),
}),
});
export const collections = { blog };

1
src/env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference path="../.astro/types.d.ts" />

View File

@ -0,0 +1,27 @@
---
---
<html>
<head>
<!-- Meta tags -->
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
<meta content="width=device-width, initial-scale=1" name="viewport" />
<meta content="index, follow" name="robots" />
<!-- Title / Description -->
<meta content="Description" name="description" />
<title>Title</title>
<!-- RSS -->
<link href="#" rel="alternate" title="RSS" type="application/atom+xml" />
<!-- Canonical URL -->
<link href="#" rel="canonical" />
</head>
<body>
<slot />
</body>
</html>

View File

@ -0,0 +1,7 @@
---
import BaseLayout from "./BaseLayout.astro";
---
<BaseLayout>
<slot />
</BaseLayout>

View File

@ -0,0 +1,7 @@
---
import BaseLayout from "../layouts/BaseLayout.astro";
---
<BaseLayout>
<slot />
</BaseLayout>

View File

@ -0,0 +1,20 @@
---
import { type CollectionEntry, getCollection } from "astro:content";
import Layout from "../../layouts/PostLayout.astro";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.slug },
props: post,
}));
}
type Props = CollectionEntry<"blog">;
const post = Astro.props;
const { Content } = await post.render();
---
<Layout>
<Content />
</Layout>

18
src/pages/index.astro Normal file
View File

@ -0,0 +1,18 @@
---
import Layout from "../layouts/PageLayout.astro";
import { getCollection } from "astro:content";
const posts = await getCollection("blog");
---
<Layout>
<ul>
{
posts.map((post) => (
<li>
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
</li>
))
}
</ul>
</Layout>