Andrei Yankovich
Andrei Yankovich24 березня 2020 р. 09:50

Випуск утиліти для розгортання додатків C++/Qt і QML CQtDeployer версії 1.4.0 (двійкова коробка)

Майже півроку вийшло велике оновлення утиліти розгортання CQtDeployer.
У цьому оновленні багато нововведень, але основний акцент робиться на створення пакетів.


CQtDeployer 1.4.0

Виправлення

  • Виправлено виведення довідки в консоль, перед виведенням перераховується реальний розмір консолі, що дозволяє коректно передавати текст.
  • Виправлено роботу з деплоєм плагінів Qt. Тепер плагіни отримують не всі системні залежності, а тільки qt. Вилучення системних залежностей призводило до збою додатків через несумісні бібліотеки плагінів.
  • Дрібні виправлення помилок та покращення.

Нові особливості

  • Додана підтримка пошуку qmake із системного середовища.
  • Додана можливість ініціалізувати репозиторій для подальшого пакування, аналогічно git init.
  • Додана підтримка пакетів Qt Install Framework. Тепер можна запакувати дистрибутив у установник.
  • Додана можливість розбивати кінцевий дистрибутив на кілька пакетів.
  • Додано можливість уніфікувати створення пакетів для фінальної роздачі.
  • Додана підтримка додавання скриптів користувача в скрипти запуску додатків.
  • Додано підтримку вилучення системних залежностей для Windows.
  • Додана підтримка RPATH для Linux. Тепер cqtdeployer може самостійно визначити необхідний qmake для розгортання програми.
  • Додана підтримка пошуку потрібної залежності на ім'я бібліотеки.
  • Додана підтримка бібліотек Qt із репозиторіїв дистрибутивів Linux.
  • Доданий новий псевдонім для команди запуску (cqt та cqtdeployer.cqt) для швидкого розгортання програм.
  • Додано підтримку нативного імені команди для windows. Тепер можна запустити cqtdeployer з команди cqtdeployer в cmd і powershell.

Нові опції

  • init – ініціалізує файл cqtdeployer.json (файл конфігурації). Наприклад: cqtdeployer init — для ініціалізації конфігурації базового пакета. cqtdeployer -init multi - для ініціалізації конфігурації декількох пакетів.
  • noCheckRPATH - відключає автоматичний пошук шляхів до qmake у файлах (тільки для Linux).
  • noCheckPATH - відключає автоматичний пошук шляхів до qmake у системному оточенні.
  • ExtractPlugins – примусово витягує всі залежності плагінів.
    -qif - Створює установник в кінці розгортання.
  • extraLibs - додає шаблон для додаткової бібліотеки, яка має бути включена до дистрибутиву.
  • customScript - додає скрипт користувача в скрипт запуску програми.
    --targetPackage [пакет; tar1, пакет; tar2] - використовується для формування пакетів, позначає списки цільових файлів для конкретних пакетів.
    — recOut — вказує, до якої папки буде додано ресурси після розгортання.
  • name – задає ім'я пакета.
  • description - встановлює опис пакету
  • deployVersion – встановлює версію пакету
  • releaseDate – встановлює дату випуску пакета.
  • icon - задає піктограму пакета.
  • publisher – встановлює видавця пакета.
  • qifStyle - Задає шлях до файлу стилів CSS або задає стиль за промовчанням. Доступні стилі: квазар
  • qifBanner - Встановлює шлях до png-файлу банера.
  • qifLogo - Встановлює шлях до png-файлу логотипу.

Посилання для скачування

Установник:

Інсталятор можна завантажити на соціальній сторінці github

Знімок

Отримати його з Snap Store

Увага

У снап-версії обов'язково дайте програмі доступ до читання інших процесів. Тому що це необхідно для створення установника та коректного пошуку qt.

Детальний розбір найцікавіших змін.

Перше, на що слід звернути увагу, це те, що CQtDeployer навчився працювати з RPATH (лише для Linux) та PATH. Це означає, що якщо ваша програма зібрана за допомогою RPATH (а RPATH в qt включений за замовчуванням) або ваш qmake прописаний в PATH, то вам не потрібно вказувати шлях до qmake. CQtDeployer сам знайде qmake.

Перевіримо практично.
Я створив простий консольний додаток за допомогою Qt.

#include <QString>
#include <QDebug>
int main(int, char *[])
{
    QString str = "hello CQtDeployer 1.4";
    qInfo() << str;
    return 0;
}

Я використовуватиму систему складання cmake, тому що вона більш актуальна, ніж qmake.

andrei@HP:~/Hello$ tree 
.
├── CMakeLists.txt
├── CMakeLists.txt.user
└── main.cpp

0 directories, 3 files

Створіть папку для збирання.

andrei@HP:~/Hello$ mkdir build 

Запустіть cmake у створеній папці.

andrei@HP:~/Hello/build$ cmake .. -DCMAKE_PREFIX_PATH=~/Qt/5.14.1/gcc_64
-- Configuring done
-- Generating done
-- Build files have been written to: /home/andrei/Hello/build

створення проекту

andrei@HP:~/Hello/build$ make 
Scanning dependencies of target Hello_autogen
[ 25%] Automatic MOC and UIC for target Hello
[ 25%] Built target Hello_autogen
Scanning dependencies of target Hello
[ 50%] Building CXX object CMakeFiles/Hello.dir/Hello_autogen/mocs_compilation.cpp.o
[ 75%] Building CXX object CMakeFiles/Hello.dir/main.cpp.o
[100%] Linking CXX executable Hello
[100%] Built target Hello

Перевіряємо нашу програму.

andrei@HP:~/Hello/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  Hello  Hello_autogen  Makefile

І запускаємо cqtdeployer минаючи його програму без qmake.

andrei@HP:~/Hello/build$ cqtdeployer -bin Hello 
Deploy ...
flag targetDir not  used. use default target dir : "/home/andrei/Hello/build/DistributionKit"
target deploy started!!
copy : "/home/andrei/Hello/build/Hello"
extract lib : "/home/andrei/Hello/build/DistributionKit//bin//Hello"
copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libQt5Core.so.5"
copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicuuc.so.56"
copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicui18n.so.56"
copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicudata.so.56"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ar.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_bg.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ca.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_cs.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_da.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_de.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_en.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_es.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_fi.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_fr.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_gd.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_he.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_hu.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_it.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ja.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ko.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_lv.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_pl.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ru.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_sk.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_uk.qm"
copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_zh_TW.qm"
try deploy msvc
deploy done!

О диво, тепер наша програма повністю автономна.
Перевірте це.

andrei@HP:~/Hello/build$ cd DistributionKit/
andrei@HP:~/Hello/build/DistributionKit$ tree 
.
├── bin
│   ├── Hello
│   └── qt.conf
├── Hello.sh
├── lib
│   ├── libicudata.so.56
│   ├── libicui18n.so.56
│   ├── libicuuc.so.56
│   └── libQt5Core.so.5
└── translations
    ├── qtbase_ar.qm
    ├── qtbase_bg.qm
    ├── qtbase_ca.qm
    ├── qtbase_cs.qm
    ├── qtbase_da.qm
    ├── qtbase_de.qm
    ├── qtbase_en.qm
    ├── qtbase_es.qm
    ├── qtbase_fi.qm
    ├── qtbase_fr.qm
    ├── qtbase_gd.qm
    ├── qtbase_he.qm
    ├── qtbase_hu.qm
    ├── qtbase_it.qm
    ├── qtbase_ja.qm
    ├── qtbase_ko.qm
    ├── qtbase_lv.qm
    ├── qtbase_pl.qm
    ├── qtbase_ru.qm
    ├── qtbase_sk.qm
    ├── qtbase_uk.qm
    └── qtbase_zh_TW.qm

3 directories, 29 files
andrei@HP:~/Hello/build/DistributionKit$ 

Корінь програми:

image

Бібліотеки, необхідні для роботи програми:

image

Як видно з прикладу, програма повністю зібрана.

Каркас установника Qt

Друга новація, про яку варто знати, - це можливість формувати QIF-установники з коробки. Все, що потрібно для прикладу, це додати опцію qif в команду упаковки.

Приклад використання.

andrei@HP:~/Hello/build$ cqtdeployer -bin Hello qif 

Всього одна проста команда і програма набуває презентабельного вигляду.

image

Цей установник підтримує мінімальну інтеграцію дистрибутивів Linux та Windows. А саме: створення ярликів, та реєстрація програми в ОС.
Якщо вас з якоїсь причини не влаштовує зовнішній вигляд цього установника, ви можете змінити його за допомогою qifStyle прапора. На момент версії 1.4 cqtdeployer підтримує лише 2 стилі (native та quasar).

Приклад стилю квазара:

image

Ви також можете використовувати власну таблицю стилів qss. Для цього передайте шлях до файлу qss або css замість імені стилю.
Наприклад, розглянемо таку таблицю стилів qss.

Style.qss:

QWidget
{
    color: white;
    background-color: rgb(65, 65, 65);
}

QPushButton
{
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(150, 150, 150, 60%), stop:1 rgba(50, 50, 50, 60%));
    border-color: rgb(60, 60, 60);
    border-style: solid;
    border-width: 2px;
    border-radius: 9px;
    min-height: 20px;
    max-height: 20px;
    min-width: 60px;
    max-width: 60px;
    padding-left: 15px;
    padding-right: 15px;
}

QPushButton:pressed, QPushButton:checked
{
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 60%), stop:1 rgba(150, 150, 150, 60%));
}

Перевіримо, що ми отримуємо в цьому випадку.

cqtdeployer -bin Hello qif -qifStyle ./../style.qss

image

Ось, власне, і темна тема інсталятора.

Розбивка на пакети

І, напевно, останнє важливе оновлення, про яке варто знати, це можливість розбивати великий мультибінарний проект на підпроекти.

Ця функція найскладніша з усіх перерахованих, тому що для її використання потрібно багато тексту. Тому я рекомендую використовувати конфігураційний файл.

Для початку ускладнимо наш проект, додавши в нього ще 2 виконувані файли. Я не став морочитися і просто зробив дві копії своєї утиліти Hello.

Для полегшення роботи з пакетами необхідно ініціалізувати каталог.

cqtdeployer init

Це ще одна нова функція, яка створює файл CQtDeployer.json, в який ми будемо писати наші конфігурації замість того, щоб передавати параметри утиліті.

{
    "binDir": ".",
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5
}

Тепер зробимо 2 пакети з трьох наших програм. Для цього вкажіть:

{
    "binDir": ".",
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "targetPackage": [
        ["Dstro1", "Hello1"],
        ["Dstro2", "Hello2"],
        ["Dstro2", "Hello3"]
    ]
}

Зверніть увагу, що мені довелося явно вказати прив'язку Dstro2 Hello2 Hello3. На жаль, під час версії 1.4 cqtdeployer було неможливо аналізувати цільові перерахування. Зверніть увагу, що якщо я напишу замість Hello1 Hello, то відбір буде проводитись за всіма збігами та будуть обрані всі 3 програми.
Тож давайте подивимося, що сталося.

cqtdeployer

.
├── Dstro1
│   ├── bin
│   │   ├── Hello1
│   │   └── qt.conf
│   ├── Hello1.sh
│   ├── lib
│   │   ├── libicudata.so.56
│   │   ├── libicui18n.so.56
│   │   ├── libicuuc.so.56
│   │   └── libQt5Core.so.5
│   └── translations
│       ├── qtbase_ar.qm
│       ├── qtbase_bg.qm
│       ├── qtbase_ca.qm
│       ├── qtbase_cs.qm
│       ├── qtbase_da.qm
│       ├── qtbase_de.qm
│       ├── qtbase_en.qm
│       ├── qtbase_es.qm
│       ├── qtbase_fi.qm
│       ├── qtbase_fr.qm
│       ├── qtbase_gd.qm
│       ├── qtbase_he.qm
│       ├── qtbase_hu.qm
│       ├── qtbase_it.qm
│       ├── qtbase_ja.qm
│       ├── qtbase_ko.qm
│       ├── qtbase_lv.qm
│       ├── qtbase_pl.qm
│       ├── qtbase_ru.qm
│       ├── qtbase_sk.qm
│       ├── qtbase_uk.qm
│       └── qtbase_zh_TW.qm
└── Dstro2
    ├── bin
    │   ├── Hello2
    │   ├── Hello3
    │   └── qt.conf
    ├── Hello2.sh
    ├── Hello3.sh
    ├── lib
    │   ├── libicudata.so.56
    │   ├── libicui18n.so.56
    │   ├── libicuuc.so.56
    │   └── libQt5Core.so.5
    └── translations
        ├── qtbase_ar.qm
        ├── qtbase_bg.qm
        ├── qtbase_ca.qm
        ├── qtbase_cs.qm
        ├── qtbase_da.qm
        ├── qtbase_de.qm
        ├── qtbase_en.qm
        ├── qtbase_es.qm
        ├── qtbase_fi.qm
        ├── qtbase_fr.qm
        ├── qtbase_gd.qm
        ├── qtbase_he.qm
        ├── qtbase_hu.qm
        ├── qtbase_it.qm
        ├── qtbase_ja.qm
        ├── qtbase_ko.qm
        ├── qtbase_lv.qm
        ├── qtbase_pl.qm
        ├── qtbase_ru.qm
        ├── qtbase_sk.qm
        ├── qtbase_uk.qm
        └── qtbase_zh_TW.qm

8 directories, 60 files

Як видно з дерева результатів, у нас вийшло 2 дистрибутиви.
1. Dstro1 - містить додаток Hello1
2. Dstro2 - містить 2, що залишилися.

Тепер перевіримо, що буде, якщо це запакувати установщиком. Додайте для параметра qif значення true у CQtDeployer.json: qif: true, .

{
    "binDir": ".",
    "clear": true,
    "qif": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "targetPackage": [
        ["Dstro1", "Hello1"],
        ["Dstro2", "Hello2"],
        ["Dstro2", "Hello3"]
    ]

image

Як видно зі скріншота, тепер у нас 2 пакети при встановленні.

Нові псевдоніми

І останнє невелике, але приємне доповнення: тепер до cqtdeployer додані нові команди.

  • сqt — це швидкий спосіб розгорнути вашу програму. Це полегшує виклик розгортання.
  • Приклад:
    cqt myApp — це те саме, що cqtdeployer -bin myApp .

  • cqtdeployer.cqt - те саме, що і cqt, але для пакета snap.

  • У windows-версії тепер не потрібно додавати знак % для виклику утиліти.

  • У версії для windows тепер немає потреби додавати знак % для виклику утиліти.
    Тепер виклик виглядає як у Linux. (cqtdeployer)

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

o
  • 24 березня 2020 р. 14:51

спасибо, за обзор!

Andrei Yankovich
  • 24 березня 2020 р. 15:29

Если будут вопросы, пишите. Найдем решение)

Ruslan Polupan
  • 26 березня 2020 р. 07:47

Супер. Спасибо!

D
  • 26 березня 2020 р. 08:50

Добрый день. У меня есть приложение с библиотеками собранными отдельно. Как мне сделать так, чтобы эти библиотеки помещались в установщик и при установке приложение были вместе с исполняемым файлом? И почему утилита при использовании -bin или -bindir создает ярылки для каких-то библиотек, но не для исполняемого файла? Я использую Windows.

Andrei Yankovich
  • 26 березня 2020 р. 09:27
  • (відредаговано)
  1. Откройте cmd, перейдите в папку с вашими проектами, запустите cqtdeployer init.
  2. Должен появится файл CQtDeployer.json, откройте его.
{
    "bin": [
        "./path/to/my/file.exe",
    ],
    "qmake": "C:/path/to/my/qmake.exe",
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "qif": true
}

Если все ваши библиотеки требуются для работы ./path/to/my/file.exe т они автоматически попадут в инсталятор. если ваши библиотеки очень далеко запрятаны от расположения json файла то можете по больше выставить значение "recursiveDepth": 5,
путь "./path/to/my/file.exe", должен обязательно начинается с "." и быть относительным от json файла.

Обратите внимание на то что в Windows версии все еще нужно явно указывать путь к qmake которым был собран проект.
Исключение составляет тот факт что если qmake уже прописан у вас в окружении PATH, тогда cqtdeployer будет использовать значение из PATH.
затем сохраняете ваш файл и повторно запускаете cqtdeployer.

что касается ярлыков на библиотеки то звучит как ошибка. Собирите максимум информации о ваших дествиях и опишите ошибку на GitHub

Andrei Yankovich
  • 26 березня 2020 р. 10:29

можно еще так:

cqtdeployer -bin "path/to/my/file.exe" -qmake "C:/path/to/my/qmake.exe" -libDir "./" -recursiveDepth 5 qif

это тоже самое, просто гораздо удобнее когда инициализация будет у вас записана в файл, и вам не придется постоянно водить эту длинную строку для развертывания.

D
  • 26 березня 2020 р. 11:56

LibDir вообще не видит библиотеки. Пробовал разные попытки записи, исходя из вашего сообщения. Библиотеки лежат рядом с исполняемым файлом, json там же. Если использовать binDir вместо bin тогда библиотеки добавляются. А при установке создадутся ярлыки на все библиотеки, но не на исполняемый файл. Оно так и должно работать?

Andrei Yankovich
  • 26 березня 2020 р. 12:39
  • (відредаговано)

нет, так не должно быть, вы уверены что ваш исполняемый файл зависит от ваших библиотек ? или он подключает их как плагины?
а с ярлыками это точно ошибка, уже завел задачу на это .

Andrei Yankovich
  • 26 березня 2020 р. 12:42

@Den125 можно взгялнуть на ваш проект ?

D
  • 26 березня 2020 р. 12:51

Мой исполняемый файл не зависит от библиотек. Библиотеки подключаются при необходимости в процессе работы программы.

Andrei Yankovich
  • 26 березня 2020 р. 13:13
  • (відредаговано)

тогда это плагины )
для них есть отделный флаг extraPlugin

{
    "bin": [
        "./path/to/my/file.exe",
    ],
    "qmake": "C:/path/to/my/qmake.exe",
    "extraPlugin": [
        "./plugin1.dll",
        "./plugin2.dll",
    ],
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "qif": true
}
D
  • 26 березня 2020 р. 13:34

Это сработало, но библиотеки при установке находятся в папке plugins. А можно их вынести к исполняемому файлу? Можно ли в установщик закинуть файл не библиотеку и не исполняемый, например *.jar?

Andrei Yankovich
  • 26 березня 2020 р. 13:37

тогда переместите ваши библиотеки из extraPlugin в bin

{
    "bin": [
        "./path/to/my/file.exe",
        "./plugin1.dll",
        "./plugin2.dll",
    ],
    "qmake": "C:/path/to/my/qmake.exe",
    "clear": true,
    "libDir": "./",
    "recursiveDepth": 5,
    "qif": true
}
Andrei Yankovich
  • 26 березня 2020 р. 13:37

но появятся ярлыки, сейчас поправим

Andrei Yankovich
  • 27 березня 2020 р. 02:47

Ошибка с ярлыками в Windows исправлена в версиии 1.4.0.4

i
  • 08 листопада 2024 р. 15:43

can i buy priligy in usa Reprod Biomed Online 10 3 310 319

i
  • 15 листопада 2024 р. 02:27

optionally substituted alkoxy, optionally substituted alkenyloxy, optionally substituted alkynyloxy, optionally substituted aryloxy, OCH, OC H, OC H, OC H, OC H, OC H, OC H, O C CH, OCH CH OH, O CH O CH, O CH O CH, O CH CH CH, O CH CH CH, OCH CH F, OCH CHF, OCH CF, OCH CH Cl, OCH CH Br, OCH CH I, OCH CH CH F, O CH CH C O NH CH C O OH NH C O CH CH NH C O OH, O CH N CH O CH CH CH CH CH, O CH CH CH CH CH F, O CH C C CH CH, O CH C C CH CH F, O C H, O CH C H, O C1 C20 organic moiety where the organic moiety is, e priligy

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 11:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 11:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
i
innorwall15 листопада 2024 р. 13:27
Випуск утиліти для розгортання додатків C++/Qt і QML CQtDeployer версії 1.4.0 (двійкова коробка) optionally substituted alkoxy, optionally substituted alkenyloxy, optionally substituted alkynyloxy, optionally substituted aryloxy, OCH, OC H, OC H, OC H, OC H, OC H, OC H, O C CH, OCH CH OH, O…
i
innorwall15 листопада 2024 р. 08:26
Qt/C++ – Урок 031. QCustomPlot – Побудова діаграм з часом buy generic priligy We can just chat, and we will not lose too much time anyway
i
innorwall15 листопада 2024 р. 06:03
Qt/C++ - Урок 060. Налаштування зовнішнього вигляду програми під час виконання I didnt have an issue work colors priligy dapoxetine 60mg revia cost uk August 3, 2022 Reply
i
innorwall14 листопада 2024 р. 22:42
Як скопіювати файли в Linux If only females relatives with DZ offspring were considered these percentages were 23 order priligy online uk
Тепер обговоріть на форумі
i
innorwall14 листопада 2024 р. 14:39
добавить qlineseries в функции priligy amazon canada 93 GREB1 protein GREB1 AB011147 6
i
innorwall11 листопада 2024 р. 21:55
Всё ещё разбираюсь с кешем. priligy walgreens levitra dulcolax carbs The third ring was found to be made up of ultra relativistic electrons, which are also present in both the outer and inner rings
9
9Anonim25 жовтня 2024 р. 19:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
ИМ
Игорь Максимов03 жовтня 2024 р. 14:05
Реализация навигации по разделам Спасибо Евгений!

Слідкуйте за нами в соціальних мережах