Создание экосистемы свободного ПО для процессоров «Эльбрус»
В ТАСС состоится пресс-конференция, посвященная развитию экосистемы свободно-распространяемого ПО для платформы «Эльбрус».
( читать дальше... )
>>> Подробности
В ТАСС состоится пресс-конференция, посвященная развитию экосистемы свободно-распространяемого ПО для платформы «Эльбрус».
( читать дальше... )
>>> Подробности
Нажатие на «глаз» открывает ссылку www.linux.org.ru/# и не подписывает на тред. Пробовал отключать js, но ничего не поменялось. Когда-то работало
Наговнокодил вот, может кому пригодится, работает под
LuaJit
Lua5.1
с дополнительным внешним модулем bit32
Lua5.2
Lua5.3
Lua5.4
Пример:
local base64 = require("base64")
local base = base64.encode("Hello World!")
local text = base64.decode("SGVsbG8gV29ybGQh")
print(base,text)
Свой алфавит кодирования
local base64 = require("base64")
local basename = 'mybase64'
local alphabet = 'ABCDEFGcdefghijHIJKLMN0123456789*?abkOPQRSTUVWXYZlmnopqrstuvwxyz'
local endcode = '@'
assert(base64.register(basename,alphabet,endcode))
local base = base64.encode("Hello World!","mybase64")
local text = base64.decode("KGNV5Gw*Nqxm5GI?","mybase64")
print(base,text)
Днищекод:
Вроде правильно работает.
Всякую фигню принимал в base64
из сети, вроде норм.
Досвиданья
Перемещено leave из talks
Каким образом можно создать еще одну секцию кода в эльф файле , на Си ? На Асме оно понятно как, т.е.
.code
...
.code1
..
а как здесь? Или невозможно?
Ой всё! Устал, надоело пока, ничего не работает! Наверное заброшу но буду пытаться!, поэтому вываливаю как есть.
Работает кое-как только под Cinnamon
и конечно X11
Валва она же Wallwa это дура на Lua
которая позволяет запускать окошечки в режиме «обоев», это скрипт использующий другие программы для свое работы, может жрать ссылки, видеофайлы, картинки и прочее что умеет жрать mpv
и показывать как живые обои, запускать просто программы и программы в прозрачном терминале. После запуска приложения хранит их состояния, можно поставить всё на паузу, закрыть и открыть разом, вернуть в обычный режим для позиционирования, позиционировать выжделением мышкой, прозрачность там, центрирование и прочее. Каждой программе даётся имя начинающиеся с @
а далее либо имя программы, либо ссылка или файл. Для запуска программы в прозрачном терминале нужно написать +
передименем программы.
Видео презентация на память
Негодники (+пердолинг со сборкой вспомогательных утилит там ещё)
Расписывать и описывать что да как лень, один фиг это не до конца готовое, поэтому просто скопирую сюда выхлоп --help
.
Usage: wallwa [URL|FILE|APPLICATION|+APPLICATION]
This utilite execute GUI application or open mediafile
or execute CLI application in transparent terminal and
move any this variants to desktop background like wallpaper.
Working only under X11 Xorg.
Wallwa command line options give maximum 2 arguments
first afrument is string ID started at '@' symbol it
wallwa item name, after item can be URL,FILE or executable app
wallwa use mpv for play mediacontent every time in fullscreen mode
as wallpaper, wallwa use urxvt terminal in transparent mode for CLI.
If first argument not set, automanicly set and use @default item
Arguments:
-h --help Show this help message
-i --info Show items list
-l --load Load selected item
-la --load-all Load all items
-m --mouse Select item position and size uses mouse
-g --get Get selected item as normal window
-ga --get-all Get all active items as normal window
-s --set Set selected item to background
-s --set-all Set all active items to background
-t --top In background mode move selected item to up
-t --top-all In background mode restack all items in forward range
-b --back In background mode move selected item to down
-b --back-all In background mode restack all items in backward range
-k --kill Kill selected item
-ka --kill-all Kill all active items
-d --del Delete selected item and kill
-da --del-all Delete all items and kill
-p --pause Pause selected item
-pa --pause-all Pause all active items
-r --resume Resume selected item
-ra --resume-all Resume all items from "pause"
-c --center Reposition selected item in screen center
-ca --center-all Rereposition all items in screen center
-f --full Resize selected item to fullscreen
-fa --full-all Resize all items in fullscreen
[FILE] Open mediafile in mpv
[URL] Open mediastream in mpv
application Execute any* GUI applications in background mode
+application Execute any CLI applications in transparent terminal
[NUMBER]% Set opacity for selected item
[NUMBER]%% Set opacity for all items
[NUMBER]x[NUMBER] Set size for selected item
[NUMBER]:[NUMBER] Set pose for selected item
[NUMBER]x[NUMBER]-center Set item size for selected item
and centred item in screen
*[NUMBER]x[NUMBER] Relative change size for selected item
*[NUMBER]:[NUMBER] Relative change pose for selected item
In relative mode +[NUMBER] add value, -[NUMBER] sub value, [0] no change
For example:
@itemname *+50:0 #move window to left on 50px
@itemname *-10x+20 #sub in window width size 10px and add 20px height
More examples:
This example show case when you have live video wallpaper and htop in
background mode, you have 2 items @default and @wallpaper and manipulate
this items resize, move, restack, pause, resume, close and open again, you
can make many @items and manipulate each individually or all of them at once
wallwa +htop #execute htop in transparent terminal as @default item
wallwa -m #resize and repose htop window
wallwa -k #kill @default item
wallwa -l #load again @default item
wallwa @wallpaper w.mp4 #play video wallpaper in fullscreen mode
wallwa @default -t #raise htop above the wallpaper
wallwa @wallpaper 50% #set transparent value for wallpaper
wallwa -pa #pause @default and @wallpaper
wallwa -ra #resume @default and @wallpaper
wallwa -ka #close
wallwa -la #run again
wallwa -da #delete all items and start playing again :D
If you command for wallwa have multiple words use quotes
For example you can run another (not urxvt) terminal
wallwa @myhtop "xterm -fg white -bg black -e htop"
Wallwa save size and cood position for item you can
execute another application in current pose and size item
./wallwa @myhtop "xterm -fg white -bg black -e htop"
./wallwa @myhtop "xterm -fg red -bg blue -e htop"
./wallwa @myhtop +htop
./wallwa @myhtop +btop
./wallwa @myhtop "xterm -e top"
Current wallwa implemented as Lua script and uses
other awesome applications for its work such as
* mpv for playing any media content
* urxvt for transparent terminal for CLI applications
* ps for get PIDs
* slop for use mouse for repose and resize item window
* xprop for set and get window parameters
* wmctrl for get WID from PID (no used now)
* xwidpid for get WID from PID (used now)
* xlower for move window to low stack
* xdotool for relative change size and pose
* xwininfo for information about window visible
* realpath for give absolute path for files and applications
Notice:
WALLWA EXECUTE PROGRAMS FROM COMMAND LINE, NO RUN DANGER
COMMANDS, YOU SELF CHECK VALID URL, PLEASE BE CAREFUL WHAT
COMMANDS YOU PASS TO RUN. This doesn't just apply to any terminal input.
wallwa can make "Bad Window" erros, becouse Xorg async.
If you see "Bad Window" error try
#reload all items
wallwa -ka ; #kill all
wallwa -la ; #load all
#or delete all items
wallwa -da
*Some GUI applications work uncorrect in background mode, for example
chromium,firefox,tilix,gnome-terminal and maybe other applications
not work correctly in background mode or no change state to background
This windows have multiple WID`s and now correctly spawn in background
but uncorrect behavior with options -g, -s, -b, -t manipulations.
If window have single WID all works fine
wallwa is prototype util, maybe reimplemented in future.
Под Cinnamon
тоже есть косяки, иногда окно продолжает держать фокус
и нужно кликнуть по рабочему столу куда-то. С другими WM/DE
бедные беды
на большиснтве идёт перекрытие рабочего стола, в xfce4
всё проваливается под него.
Там делает кто как у некоторых рабочие столы без _NET_WM_WINDOW_TYPE_DESKTOP
пашут.
Не всё так красиво под иксами тоже. Пока думаю, может чего и придумаю. Идеи есть, но…
А иногда всё нормально, может генерировать Bad Window
Может быть кому-то пригодится
Досвиданья :(
Запускаю через скрипт приложение
(appname 2>&1 > /dev/null) & echo $!
$!
получив PID
отпочковавшейся дочкиwmctrl -lp
ищу в строке PID
и забираю соответствующий WID
WID
манипулировать окном и пришибать процесс через PID
точно зная что есть активная пара PID
/WID
и я не пришибу случайно что-то иное.Всё работает. Но с некоторыми приложениями например glxgears
беда. PID
я его получаю, а вот WID
найти не могу, да я могу wmctrl
без параметров запустить, мышкой кликнуть на окошечко и получить WID
, но это не то, не получается зная лишь PID
получить WID
. С большинством приложений проблем нет, а тут уже не знаю где искать. Сейчас ситуация такая что я запускаю приложеньку, жду несколько секунд пытаясь получить WID
окна, если не получилось, грохаю процесс, ну и типа фиг с ним, не судьба :(
Не сообщает _NET_WM_PID
оно, жопка такая. Выхода нет? Ключ поверни и по-ле-те-ли И однозначно не определить?
Варианты поиска по заголовкам окон и по содержанию командной строки не прокатят, заголовка может не быть вовсе и могут быть много окон с пустыми заголовками. Блин :(
Решение:
В прошлый раз данные на домашних ПеКа захренакались, настало время их расхренакать обратно с помощью квинтэссенции говнокода, обычно все хвалятся что пишут brainfuck
интерпретатор там в 200
байт, а то и меньше, но у инвалидов мозга типа меня своя олимпиада, поэтому размер интерпретатора 1200+ строк и 45+ килобайт весом. И это я ещё сократил, оставив попытки раскручивать циклы поняв что это глупая затея лишь тогда когда сделал действительно корректную раскрутку циклов во время исполнения через собственно генерацию раскрученных трасс циклов. Ну и ладно.
Собственно вот зачем интерпретатор
Для возможности непрерывно исполнять код который генерируется через Браинфакалка данных вашего ПеКа по мере его генерации , а не просто загрузить всё и потом выполнять.
Конечно Lua
не для этого и тормоза, но в режиме исполнения под Luajit
вполне себе терпимо
mandelbrot.b
- 10.9
s кодgolden.b
- 0.25
s кодnahoi.b
- 1.6
s кодДа, это в режиме тупой транcляции в Lua
код и его исполнения.
Всё вроде бы я наигрался, эксперимент закончен. Может кому надо, есть утилита и модуль который можно использовать самостоятельно, дебаг, трассировка исполнения, возможность отключать часть или все оптимизации, и запускать из под разных реализаций Lua
не через правку исходника, а через ключик. Всякая хрень с учётом типа конца строк EOL
,\r
,\r\n
,\n
и поведения окончания данных EOF
ибо некоторые браинфук программы хотят специфичных вещей.
Описание параметров
Usage: braintractor -i [FILE] -o [FILE]
braintractor -e ',+.+.+.+.+.+.+'
cat mandelbrot.bf | braintractor
Execute input brainfuck code with or without
different optimisations like transplitter to
lua code and execute him, repeated operations
optimisation and cycles jump optimisation.
Cheking brainfuck syntax is correct.
Handle debug symbol `#` and allow trace all code
in execution time with trace lua function.
This brainfuck language interpretor not very faster but flexibly.
Arguments:
-h --help This help information
- Execute brainfuck source code from stdin
-i [FILE] Execute filename with brainfuck source code
-e [TEXT] Execute brainfuck source code from string
-o [FILE] Output filename for write execution output
if output not set out writed to stdout
-fi [FILE] Send data to brainfuck programm from file
-si [TEXT] Send data to brainfuck programm from string
-dj Disable cycles jump optimisation
-dr Disable repeated operations optimisation
-dt Disable transplitter to lua optimisation
-dz Disable zero cell [+] [-] [<] [>] optimisations
-da Disable all optimisations
-ds Disable stream execution
-dl Disable set newline after terminal ouput
-dd Disable '#' symbol in brainfuck source code
-do Disable (force) any output (tracer worked)
-sb [NUMBER] Source buffer size for stream execution
minimum=1, maximum=2^31. (Default:100)
If posible braintractor execute this
chunks size or load more source code
-tr [TEXT] Lua function for trace brainfuck execution
-dn Disable check newline in input reader.
By default enabled checking '\n' if
input data ended but no have '\n' force
add this EOL LF symbol as last input symbol
this useful for varian set input as string
like -s 'someinput' -> 'someinput\n' you
can set other variant for EOL not '\n'
-l [TEXT] Select lua implementation for execute
lua5.1, lua5.2, lua5.3, lua5.4, luajit
By default used system '#!/usr/bin/env lua'
Some brainfuck programs expect different behavior for
end of line. Setting bottom transparent fix input for
different behavior end of line. LF , CR, CRLF. You can
enable only one variant. If set more last disable other
By default enabled -eof_lf if input no have '\n' in line end
force added '\n' in last input data. Use -dn for disable it
-eol_lf Enable check end of line and force set LF == '\n'
if input have '\r' or '\r\n' this option
change it to single '\n'. (nix way)
-eol_cr Enable check end of line and force set CR == '\r'
if input have '\n' or '\r\n' this option
change it to single '\r'. (old osx way)
-eol_crlf Enable check end of line and force set CRLF == '\r\n'
if input have '\n' or '\r' this option change
it to two end of line symbols '\r\n'. (windows way)
Some brainfuck programs expect different behavior for end of file
some expect write '0' in memory cell, some need save cell value
and skip write other value in cell and some needed write -1 in cell
Options bottom can enable one of varians. By default enabled -eol_zero
You can enable only one varian. If set more last disable other.
-eof_zero If no have data to read, write 0 in memory cell m[i]=0
-eof_eof If no have data to read, write -1 in memory cell m[i]=-1
-eof_skip if no have data save cell value m[i]=m[i] (it like clamp)
-eof_same same as -eof_skip, just alias, it's easier to remember :)
Notice about default execution mode and configuration:
By default execute source maked in strem mode, brainfuck
source load in small chunck, chunck optimised and executed
this makes it possible to execute code as it is received,
without waiting for it to be fully loaded. Also, this is
only possible if it is possible to isolate independent parts
from the flow that are not included in the body of any loop
You can set minimal buffer for load or disable stream mode
By default debug symbol '#' executed, you can disable it
No cell memory limit, you can use over 30000 cells
No memory position limit, brainfuck code can use
negative cell indexes. If you need check memory limit
or check index allowed ranges you can use tracer -tr
Notice about optimisations:
By default all optimisations is enabled.
You can disable some one or all. The more
you disable, the slower the code will run
Notice about input data variants:
If input data taked from PIPE and brainfuck
have read ',' command need use -fi or -si options
for send data in brainfuck reader ',' command.
If input data from file -i or string -e
brainfuck read from stdin. Imposible
use PIPE for load source code and for
take input for brainfuck code. Or or.
braintractor -e ',..' # ok - you take interactive input
braintractor -i code.b # ok - you take interactive input
echo ',..' | braintractor -fi /dev/tty # ok - you take interactive input
echo ',..' | braintractor -fi input.txt # ok - input from file
echo ',..' | braintractor -si 'a' # ok - input from string
echo ',..' | braintractor # error, stdin empty after PIPE
# need direct send input data
# need directly use -f or -s
About trace function:
If you set trace function, this function be executed
in brainfuck execution loop for any operations. But
if you no disable repeater optimisation -dr, tracer miss
some repeated operations, for example this code
'+++.+++' in tracer show 3 trace becouse +++ combine
to single '+' next one '.' and again single '+'
if you set -dr tracer show full 7 operations per symbol.
Example tracer:
c - brainfuck code symbol
i - brainfuck cell memory index
v - brainfuck cell memory value
r - repeated counter after operations or 1
p - source code position, depend of optimisations, set -da -ds for correct
-tr 'function(c,i,v,r,p) print(c,i,v,r,p) end'
For example you can disable output -do and all optimisations
and just use custom tracer debugger for you brainfuck code
For example check memory usage no more 10 cells, and check negative index
-tr 'function(_,i) if i > 10 then error('MEM OVERFLOW!') end end'
-tr 'function(_,i) if i < 0 then error('NEGATIVE INDEX!') end end'
Warning: tracer execute any lua code, ANY LUA CODE! This mean
you need set correct code, no use copypaste code from internet.
If tracer function incorrect this application crashed.
Код и документация тут:
Запускать можно прям из каталога, модуль подхватится который рядом лежит.
Локальные установка и удаление в $HOME/.local/
#Установка
make PREFIX=$HOME/.local install install-cli
#Удаление
make PREFIX=$HOME/.local uninstall uninstall-cli
Баги и чиcтка кода, оооой всё потом. Потому что нет времени очередная поделочка в процессе. Так и живём, тяп ляп и готово :)
Досвиданья.
В преддверии конференции C++Russia 2024 организаторы выложили на YouTube записи докладов с прошлогодней C++Russia 2023. Публикация прошлогодних докладов началась месяца три назад но по одному докладу в неделю, а пару дней назад вроде как выложили вообще все.
На данный момент на канале конференции доступны следующие видео (если к докладу прилагались слайды, то рядом приведена и ссылка на PDF-ку):
Евгений Григорчук — GPU Driven Rendering Pipeline, или Как пишется графика в современных видеоиграх, PDF
Юрий Грибов — Как правильно писать компараторы, PDF
Илья Казаков — Кастомизируем ASIO, PDF
Дмитрий Мельник — Безопасный компилятор: надежная оптимизация и улучшение защищенности кода, PDF
Эрнест Асанов — Модель асинхронности в C++: теория и практика
Антон Сысоев — Dynamic Libraries for Bare Metal, PDF
Илья Шишков — Что-то у меня тормозит: заглядываем внутрь С++ контейнеров, PDF
Тот самый стендап от Павла Филонова на C++ Russia 2023
Дмитрий Ермолов — Roren — С++ фреймворк для описания пайплайнов распределенных вычислений, PDF
Ростислав Михеев — Эффективное использование GPU на примере разработки игр, PDF
Олег Сенин — Sizecoding: взгляд изнутри
Максим Кита — Техники оптимизации производительности, PDF
Александр Еналдиев — C++ Experiments: The Battle Continues: Cpp2 vs Carbon, PDF
Иван Смирнов — YsonStruct: дешевая сериализация иерархических JSON-структур, PDF
Владимир Ситников — B-tree индексы в базах данных на примере SQLite и PostgreSQL
Артем Хорошев — Ускоряем синтез: от TensorRT до CUDA C++, PDF
Аяз Салихов — Имплементируем класс tuple в 100 строк кода, PDF
Ashot Vardanian — Advanced Linux Kernel Bypass Techniques in 2023
Егор Суворов — Санитайзеры и стандарт не спасут, PDF
Александр Ганюхин — Машина состояний: непридуманная история
Rainer Grimm — Concurrency Patterns, PDF
Денис Легезо — Злые фреймворки и генерируемый ими позиционно-независимый код, PDF
Елена Веселовская — Как перейти от ученичества к работе, PDF
Андрей Аксенов — Про алгоритмы в поисковых движках
Техническое интервью: Архитектурная секция
Сергей Ларин, Владислав Столяров — Как сделать фронтенд компилятора в домашних условиях, PDF
Антон Потапов, Антон Малахов — Учим Кукушку Летать, или ConcurrentHashMap with Seqlocks, PDF
Александр Фокин — Designing Robust APIs: C++ Code that’s Safe, Extensible, Efficient & Easy to Use, PDF
Дмитрий Стародубцев, Ольга Кузьмичева — Практическое применение dev-контейнеров, PDF
Степан Дятковский — Почти полноценный RTTI с контролируемым overhead, PDF
Иван Афанасьев — Loop unrolling в деталях, PDF
Александр Ляпунов — Максимально быстрый и максимально удобный С++ msgpack-кодек
Марсель Галимуллин — Back to Basics: Lock-free, PDF
Алексей Степанов, Евгений Зуев — Исходный код: скрытое знание и как его показать?, PDF
Павел Новиков — Про flat_map, PDF
Антон Ласточкин — Мониторим FSM во встраиваемом ПО, PDF
Александр Бычук — Производство ПО глазами разработчика и менеджера, PDF
Константин Владимиров — Семантические процессы в C++
Александр Кирсанов — nocc — распределенный компилятор для гигантских проектов на C++, PDF
Евгений Ерохин — Back Deep to Basics: Наследование и виртуальность в C++ (Часть 1), PDF
Евгений Опарин — Опыт использования Bazel
Семен Буденков — С Conan за кроссплатформенностью, PDF
Сергей Талантов — С++ и безопасность: правда ли все так плохо?, PDF
Александр Боргардт — Колоночное хранилище в памяти: void* и шаблоны
Петр Советов — Автоматизация программирования в СССР. Трансляторы (60–70-е годы), PDF
Александр Корнилов — Идея по улучшению многопоточного кода, PDF
Александр Кухаренко — Демосцена: в погоне за wow-фактором, PDF
Виктор Шампаров — Компилятор LCC и оптимизация слияния кода, PDF
Евгений Зощук — Вперед в прошлое, или Разрабатываем фреймворк под Windows 95 в 2023 году, PDF
Михаил Лукин — Практика программирования тензорных ядер
Вадим Винник — Элементы функционального программирования в языке C++, PDF
Антон Соснин — С++ в мемах, PDF
Антон Полухин — C++ трюки из userver
PS. Практически все доклады перечислены в том порядке, в котором их мне показывает YouTube, никакой сортировки по какому-либо принципу здесь нет.
PPS. Сам ничего из этого не смотрел, никаких рекомендаций на тему «интересно/не интересно» дать не могу.
Договнокодил очередное ненужно. А именно транслятор произвольных данных в код на brainfuck
который будучи исполненным выводит закодированные в нём данные. Текст, картинка, чво угодно.
Типа cat /dev/random | brainfucktor -o bigbrainfuck.b
Или устроить «матрицу» brainfucktor -i /dev/random
Так то это просто ради экспериментов, но может кому надо я фиг знаю, кодировщик в виде модуля Lua
конечно же и утилита командной строки покрывающая все его возможности, из возможностей просто игра генерирования разного brainfuck
кода из одних и тех же данных. Работает на любой версии Lua
от 5.1
до 5.4+
Код тормоз, такой же как и я. Для оптимизации его надо целиком переписывать и на Сях, но в этом нет смысла, это забава для небольших данных, хотя жрать может любые размеры, перегнать 10 мегабайт уже вечность, так что это просто для мелочи, если вдруг надо :D
Описание параметров
Usage: brainfucktor -i [FILE] -o [FILE]
brainfucktor -e 'encode this text to brainfuck'
cat file | brainfucktor - #read from pipe
brainfuck photo.png -o photo.bf
Encode input data to code in brainfuck language
Arguments:
-h --help This help information
- Input read from stdin
-i [FILE] Input filename for read
-o [FILE] Output filename for write
-e [TEXT] Input from command line argument
-cb [NUMBER] Cycle body size factor (>=1 default=2 )
-cs [NUMBER] Cycle split factor (>=1 default=16)
-cd [NUMBER] Cycle distance factor (>=1 default=64)
-vd [NUMBER] Value distance factor (>=1 default=8 )
-ch [NUMBER] Separate input by chunks size (>=1 default=1024 bytes)
-ml [NUMBER] Set max line size for split output ( >=1 default 80 bytes)
-sl Create single line output (this disabled -ml option)
-pc Print currect configuration for code generation
You can skip -i option and just set filename, but filename expect first
Пример вывода Hello World!
с немного разными настройками генерации
brainfucktor -e 'Hello World!'
+++++++++++[>+++++++<-]>-----.>+++++[<++++++>-]<-.+++++++..+++.>+++++++[>+++++<
-]>---.>++++++++++[<++++++>-]<-----.>+++++[<+++++>-]<-.+++.------.--------.>+++
+++[>++++++<-]>---.
brainfucktor -e 'Hello World!' -vd 50
+++++++++++[>+++++++<-]>-----.+++++++++++++++++++++++++++++.+++++++..+++.>+++++
++[>+++++<-]>---.>++++++++++[<++++++>-]<-----.++++++++++++++++++++++++.+++.----
--.--------.>++++++[>++++++<-]>---.
brainfucktor -e 'Hello World!' -cd 4
+++++++++++[>+++++++<-]>-----.>++++++++++++[>+++++++++<-]>-------.+++++++..+++.
>+++++++[>+++++<-]>---.>++++++++++[>+++++++++<-]>---.>+++++++++++++[>+++++++++<
-]>------.+++.------.--------.>++++++[>++++++<-]>---.
brainfucktor -e "Hello World!" -vd 128
+++++++++++[>+++++++<-]>-----.+++++++++++++++++++++++++++++.+++++++..+++.-------
------------------------------------------------------------------------.+++++++
++++++++++++++++++++++++++++++++++++++++++++++++.++++++++++++++++++++++++.+++.--
----.--------.------------------------------------------------------------------
-.
brainfucktor -e "Hello World!" -vd 1 -cs 8
>+++[<++++>-]<-[>+++++++<-]>-----.>+++++[<++++++>-]<-.>+++[<+++>-]<--..>+[<+++>-
]<.>+++++++[>+++++<-]>---.>++++++++++[<++++++>-]<-----.>+++++[<+++++>-]<-.>+[<++
+>-]<.>++[<--->-]<.>+++[<--->-]<+.>++++++[>++++++<-]>---.
Если использовать модуль напрямую, то он гибкий, может жрать таблицу, файл, строку
и выплёвывать возвратом строки от функции или писать в таблицу, файл, функцию.
Ввод обрабатывается поблочно, чанками его размер регулируется от 1
до 2^31
.
Сгенерированный код при исполнении жрёт ячеек памяти в максимуме N*2
где N
количество
закодированных байт, в минимуме жрёт всего 2
ячейки памяти, а дальше их переиспользует.
Для исполнения больших 50+
мегебайт блоков кода с циклами нужен интерпретатор brainfuck
без ограничений на память в 30000
ячеек. :D
Код жирный, прям как я, поэтому сюда не влезет несмотря на то что я влез.
Как мы недавно узнали нейроидиоты не могут в браинфук,
а это значит у нас есть средство борьбы со скайнетом, когда терминаторы придут и роботы заполонят эту плонету, мы будем общаться на этом простом и красивом языке :)
- использовать на свой страх и риск
Код и документация тут
Запускать можно прям из каталога, модуль подхватится который рядом лежит.
Локальные установка и удаление в $HOME/.local/
#Установка
make PREFIX=$HOME/.local install install-cli
#Удаление
make PREFIX=$HOME/.local uninstall uninstall-cli
Хоп и твой дистрибутив стал почти как Slackware
:D
Изначально было всего 15
строчек. Но я нахлобучил дублирующегося кода и лапши на if
ах до ~500
строк :D
Двойные комментарии ваще шедевр, надо было ещё и на китайском написать лол. Вроде всё.
Досвиданья.
Я внезапно открыл для себя утилиту slop
, очень удобная и полезная в домашних делах. Ага я слоупок.
Надо было записать кусочек экрана несколько раз и удобно выделять мышкой область на экране для записи видео.
Наваял вот, может кому пригодится.
use_recorder
задаёт то чем вы ходите записывать
ffmpeg
recordmydesktop
record --no-sound
если используется recordmydesktop
Ключи под себя
ffmpeg
быстро пишет и сразу кодирует без звука.recordmydesktop
со звуком и отложенным долгим кодированиемСам использую нубский recordmydesktop
так как вокруг него не надо с бубном бегать по поводу звука (он меня сломан на ПК и чисто программный идёт по сети)
touch $HOME/.local/bin/record
#copy-paste code
chmod +x $HOME/.local/bin/record
ctrl+C
Если кажется многословным перепишете на bash, всё можно переписать на bash :)
#!/usr/bin/env lua
-----------------------------------------
-- Depends for recordmydesktop: ogv out
-- apt install lua slop recordmydesktop
-----------------------------------------
-- Depends for ffmpeg: mp4 out
-- apt install lua slop ffmpeg
-----------------------------------------
-- Use ffmpeg or recordmydesktop recorder
--local use_recorder = 'ffmpeg'
local use_recorder = 'recordmydesktop'
-------------------------------------------------------------------------------
local separator = ' '
local arguments = table.concat({...},separator)
local visualfmt = '-b 5 -c 0.5,1.0,0.5,0.8 -o'
local slop_pipe = io.popen('slop -f "%x %y %w %h" '..visualfmt)
local x,y , w,h = slop_pipe:read('*l'):match('(%d+) (%d+) (%d+) (%d+)')
-------------------------------------------------------------------------------
local out_filename = os.date('%Y-%m-%H-%M-%S');
-------------------------------------------------------------------------------
local command = {};
-------------------------------------------------------------------------------
if use_recorder == 'ffmpeg' then
command = table.concat(
{
'ffmpeg ','-f x11grab';
'-video_size',w..'x'..h;
'-grab_x',x;
'-grab_y',y;
'-i :0.0';
'-framerate 60';
'-vcodec libx264';
arguments;
out_filename..'.mp4';
},separator)
print('Run command:\n'..command)
os.execute(command)
return 0
end
-------------------------------------------------------------------------------
if use_recorder == 'recordmydesktop' then
command = table.concat(
{
'recordmydesktop','-x='..x;
'-y='..y;
'--width='..w;
'--height='..h;
'--fps=60';
arguments;
'-o',out_filename..'.ogv';
},separator)
print('Run command:\n'..command)
os.execute(command)
return 0
end
-------------------------------------------------------------------------------
print("[ERROR]: Bad 'use_recorder' value.")
return 1
Вроде мелочёвка, а очень и очень удобно.
Всё. Досвиданья.
Беседа с физиком теоретиком: Анатолием Григорьевичем Шкловским и его теоретические выкладки по поводу отрицательной массы и как она проявляется. Влияя и объясняя как фундаментальные так и макроскопические процессы и явления.
Кратко – Допущение существования элементарных частиц с отрицательной массой. И объяснение через них таких вещей к примеру как наличие воды на земле как косвенное следствие вытеснения протонов из земного ядра и регистрируемые сверх энергетические космические лучи с энергиями в терраэлектронвольт и многое многое другое включая прямое объяснение огромного количества других уже существующих физических эффектов, явлений, наблюдений. То есть при должной теоретической части уже подтверждается текущими экспериментами (вернее теория объясняет то что в них происходит)
Исходя из описания имеет базу достаточную для экспериментальной проверки, а так же имеет теоретический фундамент вписывающийся в текущую фундаментальную модель мира, дополняя её, но явно заявленная как альтернативная теория в качестве основы которой стоит принцип наименьшего действия по модулю из которого следует лавина эффектов проявляющаяся в виде того что мы называем вселенная и тех явлений что мы пытаемся объяснить через науку называемую физикой. Принцип наименьшего действия по модулю это ключевая особенность теории (по мнению меня) позволяющая не нарушая законов и не создавая парадоксов дать новый взгляд (или проявить истинный) на фундаментальные механизмы образования и строения материи как таковой.
Ты физик? Жопа горит? :) Опровергни или бабабол :D
Дискас.
Драсти опять я к вам со своим lua
говнокодом. Товарищ superuser скоромно сбросил в толксы свою качалку на баше. Не будем скромничать код по ссылке Coub закрывается (комментарий) Более того он ещё патчи исправления скидывает, похвала. Я взял смелость и переписал на
lua
немножко расширив список возможностей и теперь у нас конкурирующий бизънес! :D Вот вы хихи да хаха, а люди за скачивание даже платят, пруфов не дам :o) Скрипт качалка ниже совместим с версией от superuser по части хранения coub`ов.
Как пользоваться.
В качестве входных параметров может выступать
https://coub.com/view/2ppitj
2dnd59
Дело_говорит_Симпсоны
~/COUB/Дело_говорит_Симпсоны
14ns7i,https://coub.com/view/2djrec,Дело_говорит_Симпсоны,2cljbw
cat mycoubs.txt | coub -
или через ls
из каталогаКлюч -l
задаёт количество повторений inf
бесконечность
-l
если для последовательности coub’ов задан -l inf
то каждый из ниж будет проигрываться вечно, при это наглядевшись на один нужно руками закрыть окно плеера откроется следующее видео и также будет по кругу идти, это удобно так как coub’ы часто смотрят по многу раз.Ключ -d
говорит о том что нужно просто скачать один или несколько coub’ов, проигрываться ничего не будет
Скрипт не ищет на coub по названиям типа Дело_говорит_Симпсоны
этот запрос к программе для поиска локального файла.
Коубы указанные идентификатором или ссылкой всегда скачиваются, нет проверки был ли уже скачан коуб.
Для уже скачанных используйте названия из ~/home/$USER/COUB
.
Обработка параметров идёт через жъёпу! В начале ключи потом ссылки/id/имена или -
.
Значения разделены от ключей пробелом -l 3
, урлы,id,имена запятыми без пробелов
Зависимости apt install lua wget
лол
#! /bin/env lua
local coub = {} -- initial table for export like module
---------------------------------------------------------
coub.config =
{ -- coub save location, you can play from this dir
storages = '/home/'..os.getenv('USER')..'/COUB';
-- mp3, mp4 donwnload location, maybe userfull
download = '/home/'..os.getenv('USER')..'/COUB/DATA';
}
---------------------------------------------------------
function coub.msg(text)
print("\x1b[32m"..text.."\x1b[39m")
end
function coub.err(text)
print("\x1b[31m"..text.."\x1b[39m")
end
---------------------------------------------------------
function coub.usage()
help = [[
Use: coub [-h] [-l Num] source
Options:
-h - Help and exit;
-l - Repeat audio Num times or inf for infinity;
-d - Download only
- - Read coub or coub list from stdin
you can use full url or coub id
source - url | id | file.mp4
Examples:
# play single coub
coub https://coub.com/view/38yafx
# play single coub from storage
coub ~/COUB/Don_t_be_egoistic
# play single looped coub
coub -l inf 38yafx
# download single coub, no play this
coub -d https://coub.com/view/38yafx
# download multiply coubs with separated
coub -d 38yafx,https://coub.com/view/38yafx
coub -d 38yafx[newline]https://coub.com/view/38yafx
cat mycoubs.txt | coub -d -
# download and play multiply coubs (no looped)
coub -d 38yafx,38yafx
# play multiply coubs from file id list
cat mycoubs | coub -
]]
print(help)
end
-----------------------------------------------------------
local function filter_get_between(body,a,b)
local s , e = 1 , 1;
local out = ""
s,e = body:find(a,1,true);
if s == nil or e == nil then return end
local ss,ee = body:find(b,s,true);
if ss == nil or ee == nil then return end
out = out .. body:sub(e+1,ss-1);
body = body:sub(ee,#body)
return out;
end
-----------------------------------------------------------
function coub:run()
-- stupid handle va_args
for k,v in ipairs(arg) do
if self.xoop then self.loop = v; self.xoop = nil; end
if v == '-h' then self.usage(); end
if v == '-l' then self.xoop = 1; end
if v == '-d' then self.dl_only = 1; end
self.resource = v
end
if not self.loop then
self.loop = 0;
elseif self.loop == 'inf' then
-- do nothing
else
self.loop = tonumber(self.loop);
if self.loop > 0 then
self.loop = self.loop - 1;
end
end
-- decrement loop value becouse loop value = N+1
-- mpv --loop=0 is once play and --loop=1 twoo play
if not self.resource then
coub.err("Bad coub: no have input");
coub.usage()
end
-- read input from stdin
local cnt = 1;
if self.resource == '-' then
self.resource = io.read("*all");
end
-- check is resource contains data
-- min 2 symbol coub id (yea?)
if #self.resource < 2 then
coub.err('Bad data: Input source is empty');
return;
end
-- tokenization play lists, and concat to URL
-- тут ещё нужно проверить может нужные коубы уже скачаны
self.playlist = {}
for resource in string.gmatch(self.resource, '([^,\n]+)') do
if resource:find('https',1,true) then
self.playlist[cnt] = resource;
elseif resource:find('/',1,true) or resource:find('.',1,true) then
self.playlist[cnt] = resource;
else
self.playlist[cnt] = 'https://coub.com/view/'..resource;
end
cnt = cnt + 1;
end
-- always make needed directory
assert(os.execute('mkdir -p '..self.config.storages),"Storage no writable");
assert(os.execute('mkdir -p '..self.config.download),"Storage no writable");
-- download coubs & play coubs --------------------------------------------
for i,v in ipairs(self.playlist) do
local exec = io.popen('wget -q -O- '..v);
local html = exec:read('*all'); exec:close();
-- wget
if html:match('%a+') then
local json = filter_get_between(html,"<script id='coubPageCoubJson' type='text/json'>",'</script>');
local url_video = filter_get_between(json,'"video":{"higher":{"url":',',');
-- some video no have higher resulution
-- try get lowless
if not url_video then
url_video = filter_get_between(json,'"video":{"high":{"url":',',');
end
local url_audio = filter_get_between(json,'"audio":{"high":{"url":',',');
local coubtitle = filter_get_between(json,'"title":"','",');
coubtitle = coubtitle:gsub('[%p+%s+]','_');
local coubid = v:gsub('https://coub.com/view/','');
coub.msg('Download:['..i..'] '..v..' | '..coubtitle)
-- check file format befor try handle data
if url_video and url_video:find('.mp4',1,true) and url_audio and url_audio:find('.mp3',1,true) then
local file_to_save = self.config.download..'/'..coubid;
os.execute('wget -q -Y off -c -O '..file_to_save..'.mp4 '..url_video);
os.execute('wget -q -Y off -c -O '..file_to_save..'.mp3 '..url_audio);
os.execute('ln -s '..file_to_save..'.mp4 '..self.config.storages..'/'..coubtitle..' 2>/dev/null');
-- do not play if need just download video
if not self.dl_only then
-- play audio in background with infinity loop
os.execute('( mpv --loop=inf '..file_to_save..'.mp3 ) 1> /dev/null & '..
-- play video, after video ends we kill previos mpv
-- stdout to /dev/null becouse kill broke terminal stdin
-- maybe becouse mpv use '\r' for output info about playing
' mpv --loop='..self.loop..' '..file_to_save..'.mp4 1> /dev/null ; kill -INT $! ');
end
else
coub.err('Bad coub:['..i..'] file formats no mp3 and mp4 '..v);
end
else
if v:find('~',1,true) then
v = v:gsub('~',os.getenv('HOME'))
else
v = self.config.storages..'/'..v:gsub('https://coub.com/view/','');
end
local justplay = io.open(v,'r');
if justplay then
justplay:close();
if not self.dl_only then
coub.msg('PlayFile:['..i..'] '..v)
local link = io.popen(' readlink -e '..v);
local file = link:read('*all'); link:close();
os.execute('( mpv --loop=inf '..file:gsub('mp4','mp3')..' ) 1>/dev/null & '..
' mpv --loop='..self.loop..' '..file..' 1>/dev/null ; kill -INT $! ');
else
coub.msg('Ignore..:['..i..'] coub '..v..' is downloaded')
end
else
coub.err('Bad coub:['..i..'] coub not found '..v);
coub.err('Bad coub:['..i..'] coub not found https://coub.com/view/'..
v:gsub(os.getenv('HOME')..self.config.storages,''));
end
end
end
end
coub:run()
- Баги косяки, тупак, есть?
- Да.
- Исправлять будешь?
- Нет.
- А почему?
- Ну модет потом...
- А нахера всё это?
- А тебе не пофиг?
- Пофиг
- Ну и всё
- Ну и ладно
- Ненужно!
- Согласен
- А зачем тогда?
- Потому что.
- Потому что что?
- Потому что понедельник!
- Ой всё.
- Вот и я о том.
Подборочка
coub yaik,s08ov,8ek0p,7aenz,bslpw,5g1j9,wm3bk,14zilh,7l1rdrfc,2b5izx,2aatx2,29jdfr,29k4yq
coub 29n55n,29j3j1,10a9jk,297dvo,280v0q,29adcz,29aon6,29gzt6,1qrxao,334db,15egdcy8,lvd3c
Обычно все программы используют autotools, и там всё из коробке. Но вот попалась программа, которая собирается просто при помощи Makefile (и это очень простой файл, не следует никаким соглашениям).
Что надо сделать с Makefile, чтобы он стал пригодным для опакечивания? И как потом к нему писать .ebuild? Есть ли статьи на эту тему?
В то же время, насколько я знаю, для Gentoo надо, чтобы поддерживалась переменная DESTDIR, для того, чтобы можно было собирать программы в PREFIX.
О том, что можно писа́ть
make prefix=/usr
а не только
PREFIX=/usr make
сказано в пункте 9.5 Overriding Variables руководства по GNU make.
«If you specify a value in this way, all ordinary assignments of the same variable in the makefile are ignored; we say they have been overridden by the command line argument.»
В каких случаях как надо делать:
make --prefix=/usr
PREFIX=/usr make
make prefix=/usr
make PREFIX=/usr
первое не сработает, потому что параметры make принимает другие
второе не сработает, потому что буквы заглавные, а не строчные
четвёртое тоже не сработает
Почему PREFIX
и prefix
пишут то большими, то маленькими буквами?
Маленькими буквами написан пример в пункте 16.5 Variables for Installation Directories
«Installers are expected to override these values when calling make (e.g., make prefix=/usr install) or configure (e.g., configure –prefix=/usr).»
И пришло такое написание в руководство GNU make из пункта 7.2.5 Variables for Installation Directories документа GNU Coding Standards
Большими буквами называется переменная окружения EPREFIX, описанная в Gentoo wiki.
В autotools.eclass существует функция eautoreconf, которая вызывает что-то там…
«autotools_run_tool –at-m4flags autoconf «$@»»
Пример использования eautoreconf в ebuild-файле:
src_configure() {
# Вызывать autoreconf должны авторы распространяемого архива
# где-то внутри make dist
# Но если автор ебилда пробует архив стянуть с github, то
# отсутствие документации для make dist вручную это косяк Gentoo
# не проводить же сначала локальную сборку архива make dist
# а затем распаковку и всё это только чтобы вызов make прошел
# Просто поместить eautoreconf билде недостаточно
econf
}
функции autotools_src_configure не видно, поэтому явный вызов eautoreconf
надо (если надо) вписывать в текст .ebuild-файла.
В документации на ./configure пишут:
«There are two ways to change the default: when creating configure, and when running it.»
«To accomplish that, use the AC_PREFIX_DEFAULT macro.»
«The user of configure can select a different prefix using the –prefix and –exec-prefix options.»
И написано там это маленькими буквами:
# AC_PREFIX_DEFAULT(PREFIX) # ------------------------- AC_DEFUN([AC_PREFIX_DEFAULT], [m4_divert_text([DEFAULTS], [ac_default_prefix=$1])])
Вызвать только eautoreconf недостаточно, ещё можно вызвать пару функций из autotools.eclass
eautoconf
Runs autoconf.
eautomake
Runs automake.
Вызов программы ./configure выполняется при помощи функции econf
внутри src_configure
Передача переменной окружения EPREFIX через параметр --prefix
задокументирована в руководстве по разработке ебилдов:
«econf is designed to work with configure scripts generated by GNU Autoconf. It first passes the default options listed below to the configure script, followed by any additional parameters passed to econf.
--prefix="${EPREFIX}"/usr
--libdir
is set from the value of the LIBDIR_${ABI} variable in profiles.
Как параметр –prefix обрабатывается внутри ./configure остаётся загадкой. Но из написанного можно предположить, что название PREFIX заглавными буквами (без первой буквы E) это фантазия и нигде не используется.
Зачем в Gentoo назвали переменную EPREFIX, если переменной c именем PREFIX нигде нет? Зачем было добавлять лишнюю букву?
https://devmanual.gentoo.org/ebuild-writing/variables/index.html
EPREFIX
The normalised offset-prefix path of an offset installation. See Gentoo Prefix Technical Documentation for more information.
но там тоже про PREFIX ничего нет.
Зато есть в вопросах у пользователей Ubuntu - https://askubuntu.com/questions/891835/what-does-prefix-do-exactly-when-used-in-configure
вероятно негентушные дистрибутивы всё-таки имеют слово PREFIX заглавными буквами? Что там в документации по Debian? И в примере попроще и в примере посложнее используются конкретные значения, переменная окружения PREFIX не упоминается.
Может GNU make не учитывает регистр в названиях переменных?
В пункте 6 How to Use Variables написано:
«Variable names are case-sensitive.»
В пункте 6.10 Variables from the Environment написано:
«Every environment variable that make sees when it starts up is transformed into a make variable with the same name and value.»
А вот здесь мало того, что предлагают использовать заглавные буквы, так ещё и пишут, что это работает. Странно, не должно бы.
И по факту не работает:
$ cat Makefile
.SILENT: all
.PHONY: all
all:
echo prefix=$(prefix)
$ make prefix=/usr
prefix=/usr
$ PREFIX=/usr make
prefix=
Где вообще описан «стандарт» установки программ при помощи
./configure
make
make install
Почему надо делать именно так? В большом количестве книг? Пользователи привыкли? Так GNU Make не единственная, есть другие, (но они хуже, к ним не пользователи не привыкли)
Использование emake прописано прямо в Package Manager Specification (PMS).
Поэтому использование операционной системы Gentoo тормозит прогресс и переход на Cmake.
Интересует не частичная прозрачность равномерно всего окна, а использование альфа-канала в SDL-приложении, так чтобы было видно нижележащие окна.
Такое вообще возможно? Какой нужен композитор? Где читать/смотреть примеры? Кто делал?
Смеркалось.
Потребовалось мне SDL-приложение на Rockchip RK3588 борде. На нее есть дебиан и убунта, и, соответственно, тулчейн есть прямо на плате, казалось бы, че тут собирать, просто собери так же как и на десктоп. Так-то оно так, собрал и работает, но – под иксами.
А как правильно собирать в бездесктопное? SDL поддерживает в качестве бекэндов много всякого, мне, если я правильно помню удавалось заводить в конфигурации SDL2 + directfb без иксов. Но директфби – еще, блин хуже. Как надо-то? У кого выведать, где почитать? Через OpenGL ES собранный под этот чип? Или еще куда? ЗА день нагуглить даже 100% рабочего направлдения не удалось.
Обсчем, взываю к коллективному разуму
Сидел вот тут ковырялся, пересобирал и пердолился.
Подумал что стоит выложить, дабы другие пердолились поменьше.
Ниже описание, я его для себя писал и ещё ниже сам Makefile
.
Никаких изысков и красивостей. Собирает и ладно.
Кому надо под себя поправите, а кому не неадо, тому не надо.
- ИСПОЛЬЗОВАТЬ НА СВОЙ СТРАХ И РИСК, Я НЕ НЕСУ НИКАКОЙ ОТВЕТСТВЕННОСТИ
- ВСЁ ПРЕДОСТАВЛЯЕТСЯ КАК ЕСТЬ, ЛЮБЫЕ СОМНЕНИЯ ДОЛЖНЫ ВЕСТИ
- К ОТКАЗУ ОТ ИСПОЛЬЗОВАНИЯ, НЕ ПОНИМАЕШЬ ЧТО ЭТО, НЕ ТРОГАЙ
Makefile
упрощающий создание готовых Love2D
сборок c включением вашего приложения
позволяет
apk
файл для Androidlove
файл для всехAppImage
файл для Linux x86_64
Положить Makefile
в корень Love2D
программы и отредактировать
app_name=имя программы
description=однострочное описание
Для Android
дополнительно поправить
android_app_version_name=версия.приложения
любаяandroid_app_version_code=число
целое числоВажно android_app_version_code
должно иметь значение
всегда увеличивающееся на 1
при каждой новой сборке, это
требуется для того чтобы при установке на Android
apk
файла, уже установленное приложение обновлялось. Иначе
установка не произойдёт с выводом ошибки или вообще без неё.
Теперь однократно нужно развернуть зависимости для Android
make android-depends
Предполагается что sudo
настроен, нужно установить java
и
прочие мелочи, на запрос пароля ввести пароль для sudo
затем
будут сгенерированны два ключа подписей и предварительно пароль
debug.keystore
release.keystore
.android_pass
На вопросы всякие можно просто нажимать ENTER
, а когда спросят
всё ли верно Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
написать yes
и снова нажать ENTER
. sdkmanager
тоже спросит, Review licenses that have not been accepted (y/N)?
согласны ли вы с условиями предоставления иструментов
для Android SDK/NDK
тоже написать y
и нажать ENTER
Ключи и пароль можно подменить на свои готовые
(только молю бога не совать основные ЗАТРЁТСЯ МОЖЕТ БЫТЬ!)
Пусть сгенерируется всё само. Суть в том что без подписей пакетов
Android
просто молча не установит apk
, просто не даст установить.
А вот теперь уже можно, редактировать свой код и пересобирать
make lovefile
просто обычный app.love
make android
выполнить сборку app.apk
, app.abb
make appimage
выполнить сборку app.AppImage
Первый раз apk
будет собираться долго, но все последующие уже быстро
так как компиляции уже не будет, а просто будут обновляться lua
файлики
из проекта. Вроде всё.
Проблемы
make android
валится с ошибкой
Решенияmake android
ещё раз и ещё раз. Бывает отпускает.java
killall java
(там несколько процессов может быть)
и ещё раз запустить make android
/.love-android-build-dir
и заного выполнить
make android-depends
подготовку зависимостейmake android
попытку сборки apk
Нельзя отменять сборку через CTRL+C
это сломает всё,
придётся вышеописанный квест пройти опять, с большой долей вероятности.
Перемудрёные механизмы системы сборки для Android
дают о себе знать. :3
SRC=$(shell pwd)
app_name=appname
description=app short description
##########################################################
android_app_name=$(app_name) for Android
android_app_version_name=0.1
android_app_version_code=1
android_enableJetifier=true
android_useAndroidX=true
android_app_application_id=org.$(app_name).android
android_app_orientation=portrait
#########################################################
SECRET_PASSWORD_FOR_KEYGEN=$(HOME)/.android_pass
#########################################################
android_sign_release=true
##########################################################
DEVELOPMENT_ROOT_DIR=$(HOME)/.love-android-build-dir
DEVELOPMENT_KEYS_DIR=$(HOME)/.love-android-keys-dir
##########################################################
ANDROID_SDK_ROOT_DIR=$(DEVELOPMENT_ROOT_DIR)/ANDROID-SDK/
ANDROID_LOVE_ROOT_DIR=$(DEVELOPMENT_ROOT_DIR)/LOVE-ANDROID/
APPIMAGE_LOVE_ROOT_DIR=$(DEVELOPMENT_ROOT_DIR)/APPIMAGE/
##########################################################
PROPERTIES=$(ANDROID_LOVE_ROOT_DIR)/gradle.properties
all:
echo "make android-depends - create depends for android apk build"
echo "make android - build android apk/aabb pakages"
echo "make lovefile - create portable app.love file"
echo "make appimage - create portable x86_64 executable file"
android-depends:
$(MAKE) install-love-android;
$(MAKE) install-system-depends;
$(MAKE) install-android-sdk-ndk;
$(MAKE) generate-android-debug-keys;
$(MAKE) generate-android-release-keys;
android:
$(MAKE) generate-android-properties;
$(MAKE) generate-application-icons;
$(MAKE) packeges-build;
$(MAKE) packeges-copy;
ifeq ($(android_sign_release),true)
$(MAKE) packeges-sign-release;
else
$(MAKE) packeges-sign-debug;
endif
$(MAKE) packeges-sign-verify;
lovefile:
zip -9 -r $(app_name).love . -x Makefile -x ./*.apk -x ./*.aab -x ./*.AppImage
SRC_IMAGE_ICON="NONE"
ifneq ($(wildcard $(SRC)/icon.png),)
SRC_IMAGE_ICON=$(SRC)/icon.png
DST_IMAGE_PATH=$(ANDROID_LOVE_ROOT_DIR)/app/src/main/res/drawable
endif
ifneq ($(wildcard $(SRC)/assets/icon.png),)
SRC_IMAGE_ICON=$(SRC)/assets/icon.png
DST_IMAGE_PATH=$(ANDROID_LOVE_ROOT_DIR)/app/src/main/res/drawable
endif
ifneq ($(wildcard $(SRC)/assets/images/icon.png),)
SRC_IMAGE_ICON=$(SRC)/assets/images/icon.png
DST_IMAGE_PATH=$(ANDROID_LOVE_ROOT_DIR)/app/src/main/res/drawable
endif
appimage:lovefile
mkdir -p $(APPIMAGE_LOVE_ROOT_DIR);
ifeq ($(wildcard $(APPIMAGE_LOVE_ROOT_DIR)/love-11.5-x86_64.AppImage),)
wget https://github.com/love2d/love/releases/download/11.5/love-11.5-x86_64.AppImage -O $(APPIMAGE_LOVE_ROOT_DIR)/love-11.5-x86_64.AppImage
wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O $(APPIMAGE_LOVE_ROOT_DIR)/appimagetool-x86_64.AppImage
endif
cd $(APPIMAGE_LOVE_ROOT_DIR); \
-rm -rd squashfs-root; \
chmod +x love-11.5-x86_64.AppImage; \
chmod +x appimagetool-x86_64.AppImage; \
./love-11.5-x86_64.AppImage --appimage-extract; \
cat squashfs-root/bin/love $(SRC)/$(app_name).love > squashfs-root/bin/$(app_name); \
rm squashfs-root/bin/love; \
chmod +x squashfs-root/bin/$(app_name); \
sed 's/love/$(app_name)/g' -i squashfs-root/AppRun; \
convert $(SRC_IMAGE_ICON) -resize 256x256 squashfs-root/$(app_name).png; \
echo "" > squashfs-root/love.desktop; \
echo "[Desktop Entry]" >> squashfs-root/love.desktop; \
echo "Name=$(app_name)" >> squashfs-root/love.desktop; \
echo "Comment=$(description)" >> squashfs-root/love.desktop; \
echo "MimeType=application/x-love-game;" >> squashfs-root/love.desktop; \
echo "Exec=$(app_name) %f" >> squashfs-root/love.desktop; \
echo "Type=Application" >> squashfs-root/love.desktop; \
echo "Categories=Game;" >> squashfs-root/love.desktop; \
echo "Terminal=false" >> squashfs-root/love.desktop; \
echo "Icon=/$(app_name)" >> squashfs-root/love.desktop; \
echo "NoDisplay=true" >> squashfs-root/love.desktop; \
./appimagetool-x86_64.AppImage squashfs-root $(SRC)/$(app_name).AppImage;
install-love-android:
-`git clone --recurse-submodules https://github.com/love2d/love-android/ $(ANDROID_LOVE_ROOT_DIR)`
generate-android-properties:
echo "" > $(PROPERTIES)
echo "app.name=$(android_app_name)" >> $(PROPERTIES)
echo "app.version_name=$(android_app_version_name)" >> $(PROPERTIES)
echo "app.version_code=$(android_app_version_code)" >> $(PROPERTIES)
echo "android.enableJetifier=$(android_enableJetifier)" >> $(PROPERTIES)
echo "android.useAndroidX=$(android_useAndroidX)" >> $(PROPERTIES)
echo "app.application_id=$(android_app_application_id)" >> $(PROPERTIES)
echo "app.orientation=$(android_app_orientation)" >> $(PROPERTIES)
install-system-depends:
sudo apt install imagemagick openjdk-17-jdk openjdk-17-jre-headless sdkmanager
install-android-sdk-ndk:
mkdir -p $(ANDROID_SDK_ROOT_DIR); \
export ANDROID_SDK_ROOT=$(ANDROID_SDK_ROOT_DIR); \
sdkmanager --install "platforms;android-33"; \
sdkmanager --install "ndk;23.2.8568313"; \
sdkmanager --install "platform-tools;33.0.0"; \
sdkmanager --install "build-tools;33.0.0"; \
sdkmanager --install "cmdline-tools;latest"; \
sdkmanager --licenses;
generate-android-debug-keys:
mkdir -p $(DEVELOPMENT_KEYS_DIR);
ifeq ($(wildcard $(SECRET_PASSWORD_FOR_KEYGEN)),"")
uuidgen > $(SECRET_PASSWORD_FOR_KEYGEN)
endif
ifeq ($(wildcard $(DEVELOPMENT_KEYS_DIR)/debug.keystore),"")
keytool -genkey \
-v -keystore $(DEVELOPMENT_KEYS_DIR)/debug.keystore \
-storepass:file $(SECRET_PASSWORD_FOR_KEYGEN) \
-alias debug \
-keyalg RSA \
-keysize 2048 \
-validity 100000
endif
generate-android-release-keys:
mkdir -p $(DEVELOPMENT_KEYS_DIR);
ifeq ($(wildcard $(SECRET_PASSWORD_FOR_KEYGEN)),"")
uuidgen > $(SECRET_PASSWORD_FOR_KEYGEN)
endif
ifeq ("$(wildcard $(DEVELOPMENT_KEYS_DIR)/release.keystore)","")
keytool -genkey \
-v -keystore $(DEVELOPMENT_KEYS_DIR)/release.keystore \
-storepass:file $(SECRET_PASSWORD_FOR_KEYGEN) \
-alias release \
-keyalg RSA \
-keysize 2048 \
-validity 100000
endif
generate-application-icons:
ifneq ($(SRC_IMAGE_ICON),"NONE")
convert $(SRC_IMAGE_ICON) -resize 72x72 $(DST_IMAGE_PATH)-hdpi/love.png
convert $(SRC_IMAGE_ICON) -resize 48x48 $(DST_IMAGE_PATH)-mdpi/love.png
convert $(SRC_IMAGE_ICON) -resize 96x96 $(DST_IMAGE_PATH)-xhdpi/love.png
convert $(SRC_IMAGE_ICON) -resize 144x144 $(DST_IMAGE_PATH)-xxhdpi/love.png
convert $(SRC_IMAGE_ICON) -resize 192x192 $(DST_IMAGE_PATH)-xxxhdpi/love.png
endif
packeges-build:
rm $(SRC)/*.apk; \
rm $(SRC)/*.aab; \
rm $(SRC)/*.love; \
rm $(SRC)/*.AppImage; \
export ANDROID_SDK_ROOT=$(ANDROID_SDK_ROOT_DIR); \
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64; \
cp /bin/python3 $(HOME)/.local/bin/python; \
rm -rd $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets; \
mkdir -p $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets; \
cp -r $(SRC)/* $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets; \
rm $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets/Makefile; \
cp $(ANDROID_LOVE_ROOT_DIR)/license.txt $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets/love-licenses.txt;\
cd $(ANDROID_LOVE_ROOT_DIR); \
chmod +x gradlew; \
./gradlew assembleNormalRecord; \
./gradlew assembleEmbedNoRecordRelease; \
./gradlew bundleEmbedNoRecordRelease;
packeges-copy:
cp $(ANDROID_LOVE_ROOT_DIR)/app/build/outputs/apk/embedNoRecord/release/app-embed-noRecord-release-unsigned.apk $(SRC)/;
cp $(ANDROID_LOVE_ROOT_DIR)/app/build/outputs/bundle/embedNoRecordRelease/app-embed-noRecord-release.aab $(SRC)/;
cp $(ANDROID_LOVE_ROOT_DIR)/app/build/outputs/apk/normalRecord/release/app-normal-record-release-unsigned.apk $(SRC)/;
packeges-sign-debug:
jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/debug.keystore -storepass:file $(SECRET_PASSWORD_FOR_KEYGEN) $(SRC)/app-embed-noRecord-release-unsigned.apk debug;
jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/debug.keystore -storepass:file $(SECRET_PASSWORD_FOR_KEYGEN) $(SRC)/app-embed-noRecord-release.aab debug;
jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/debug.keystore -storepass:file $(SECRET_PASSWORD_FOR_KEYGEN) $(SRC)/app-normal-record-release-unsigned.apk debug;
packeges-sign-release:
jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/release.keystore -storepass:file $(SECRET_PASSWORD_FOR_KEYGEN) $(SRC)/app-embed-noRecord-release-unsigned.apk release;
jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/release.keystore -storepass:file $(SECRET_PASSWORD_FOR_KEYGEN) $(SRC)/app-embed-noRecord-release.aab release;
jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/release.keystore -storepass:file $(SECRET_PASSWORD_FOR_KEYGEN) $(SRC)/app-normal-record-release-unsigned.apk release;
packeges-sign-verify:
jarsigner -verify $(SRC)/app-embed-noRecord-release-unsigned.apk release;
jarsigner -verify $(SRC)/app-embed-noRecord-release.aab release;
jarsigner -verify $(SRC)/app-normal-record-release-unsigned.apk release;
.SILENT:all
Проблема проста. Есть ноутбук подключенный к сети через WiFi.
Надо обеспечить доступ виртуальной машины на QEMU в эту же сеть.
Я понимаю, что для этого теоретически, надо создать tap сетевой адаптер и создать мост включающий его и сетевую карту, через которую реальная машина подключена к сети.
Вот тут и проблема - нельзя просто взять и создать мост с WiFi картой. Или как-то можно?
Подскажите пожалуйста. Возможно есть другие пути?
Виртуалка просто должна работать в реальной сети как еще один компьютер.
Интересует именно QEMU, как это сделать с Virtualbox я знаю, но он не подходит.
#####РЕШЕНИЕ#######
Спасибо Pinkbyte! Я осилил по твоему совету.
Включаем Proxy ARP
# sysctl net.ipv4.conf.all.proxy_arp=1
Включаем IP Forwarding
# sysctl net.ipv4.ip_forward=1
Создаем tap сетевой интерфейс, доступный для пользователя (важно! qemu работает от пользователя !)
# tunctl -p -t tap0 -u <username>
Создаем маршрут для ip адреса виртуалки через tap0
ip route add 192.168.1.199 dev tap0
Запускаем QEMU с параметрами сети
-netdev tap,id=mynet0,ifname=tap0,script=no,downscript=no -device virtio-net-pci,netdev=mynet0
На гостевой системе - настраиваем статический ip адрес 192.168.1.199.
После этого все работает, виртуалка видна по своему адресу снаружи как отдельный компьютер.
Некоторые, наверное, уже заметили, что я начал войну с ветряными мельницами дублирующимися тегами. Извините, если вам вдруг придёт десяток уведомлений по какому-нибудь невезучему тегу. Не хочу повторить историю с cetjs2.
Кидайте в эту тему дублирующиеся теги, которые нужно почистить.
Например, были теги «параноя», «паранойа», «паранойя», остался только «паранойя», «rubyonrails» -> «ruby on rails» и т.д.
- АХТУНГ, ВАХТУНГ, БАХТУНГ, ДРЯХТУНГ, АЛЯРМ, ВНИМАНИЕ
- ЭТОТ СКРИПТ ПРЕДОСТАВЛЯЕТСЯ КАК ЕСТЬ, Я НЕ НЕСУ НИКАКОЙ
- ОТВЕТСТВЕННОСТИ ЯВНОЙ ИЛИ КОСВЕННОЙ, ВАМ ЛИБО КОМУ ТО ЕЩЁ
- ПО ПРИЧИНЕ, ПОРЧИ И/ИЛИ УНИЧТОЖЕНИИ ВАШИХ ДАННЫХ
- ЕСЛИ ВЫ НЕСОГЛАСНЫ, Я ЗАПРЕЩАЮ ВАМ ЗАПУСКАТЬ ЭТОТ КОД
- ДЕЙСТВУЙТЕ НА СВОЙ СТРАХ И РИСК, ВАШИ ЛЮБЫЕ СОМНЕНИЯ
- КАСАТЕЛЬНО СКРИПТА ДОЛЖНЫ ВЕСТИ К ОТКАЗУ ОТ ЕГО ИСПОЛЬЗОВАНИЯ
Всё, теперь если у вас что-то пойдёт не так, то я чист.
И меня никто не будет ругать, гы :) Просто будте внимательный с тем,
какой каталог указывается для сохранения бекапов. А то ведь так и затереть
чего важного можно случайно.
Вопщем решил поделится прост. Пусть будет.
Простой скрипт ручного бекапа наиболее важных файлов, использует
rsync
и zip
Настройка производится внутри стрипта. Описание
настройки бекапа тоже распологается внутри скрипта.
Типичное использование это ручной запуск в конце дня или по
завершению какой либо важной работы или перед сном :)
Используйте для бекапа, отдельный диск где нет ничего кроме бекапа!
Просто иначе, в бекапе нет никакого смысла.
Лично я просто на панельку кнопочку сделал, и перед отплытием в люльку тыкаю кнопочку.
Комп я не выключаю обычно, а если выключаю до явно дожидаюсь окончания бекапа, не проверял что
будет если увести в сон во время бекапа, так что, лучше дождаться окончания.
mkdir zip rsync notify-send lua
Настроить скрипт, после чего просто его запускать. Так как вам удобно.
source
каталог или файл источникdest
каталог приёмникsecure
применить пароль (требуется zip=true
)zip
сжать в архивmirror
сделать точную копию и обновить им текущий каталог бекапа( или архив если zip=true
)versions
сделать точную копию и пометить датой в отдельном каталоге (или архиве если zip=true
)Пример поля конфигурации:
{secure=true, zip=true, versions=true, source='~/.ssh/', dest='ssh'};
Значит что нужно сделать рекурсивный бекап каталога с ключами ssh
и расположить
бекап в каталоге с именем ssh
. secure=true
означает что данные будут запаролены, а
zip
что будут сжаты, versions=true
означает что каждый новый бекап будет
создавать новую копию ~/.ssh
помеченную датой. Описание того какие есть ключи
и как они работают друг с другом есть внутри скрипта, вместе с примерами уже
готовой настройки.
Ключи можно опускать (не указывать) обязательными являются только source
и dest
Не указанные ключи считаются заданными как false
так что вот такая запись валидна
{source='~/Изображения/', dest='картинки'}
И означает сделать копию каталога ~/Изображения
в каталоге картинки
внутри общего
каталога бекапа backup_path=...
при этом если это второй или последующий бекап и в
каталоге ~/Изображения/
была удалена картинка, она не будет удалена в каталоге
картинки
это сделано специально, дабы максимизировать сохраняемые данные.
Если нужна точная копия с удалением того чего уже нет в каталоге источнике то нужно
дополнительно явно указать опцию mirror=true
это же правило работает
если включить флаг zip=true
будет всё тоже самое, но уже в виде архива.
В каталоге относительно котрого исполняется скрипт будет лог бекапа, на рабочий стол будут приходить
уведомление о текущем статусе выполнения, в случае ошибки будет показaн код возврата
В лог попадает информация о том какая именно команда потерпела неудачу, пароль присутцвующий в команде
заменяется на звёздочки. В зависимости от типа настроенного бекапа(первый бекап будет всегда долгим),
а вот последующие при отсуцтвии изменений будут быстрыми исключение это mirror
и versions
оба
создают точную копию с нуля, а не пытаются обновить текущее содержимое бекапа. В случае если любая
программа вернёт код возврата отличный от 0
выполнение всего бекапа прерывается, и повторно он не
запустится пока не будет удалён lock файл, это сделано специально, чтобы выяснить причину, исправить её
и в ручном режиме удалить lock файл название котрого есть в срипте, в логах и уведомлении на рабочий стол.:
Если вы бекапите например ~./vimrc
в dest
каталог myvimrc
то он будет там лежать как есть, с точкой.
Так что так же чтобы его увидеть в каталоге бекапа нужно нажимать ctrl+h
. Ну, я так. На всякий случай.
Удалять из бекапов лишнее, и вообще контролировать влезет ли всё, это ваша забота =)
Нет опции отключения уведомлений. Предпочитаю явно знать что всё прошло гладко.
Логи бекапа тоже руками удалять.
Дадада, пароль на zip
для ssh
и gpg
ключей хахахаха, но хоть что-то.
Сам внешний накопитель держите шифрованным если туда важное сохраняется.
Сам сриптик. Взял его как есть.
#!/usr/env lua
local backup_rule =
{
--каталог куда будут размещаться все бекапы
backup_path = '/media/$USER/STORAGE_SSD/backup';
--пароль если используется secure=true, лучше использовать файл с паролем
backup_pass = nil;
--пароль для важныйх файлов, можно записать в файл дабы не светить
backup_pass_file = "/home/$USER/Документы/backup_pass";
---------------------------------------------------------------------------
backup_list =
{
-- backup critical --
{secure=true, zip=true, versions=true, source='~/.ssh/', dest='ssh' };
{secure=true, zip=true, versions=true, source='~/.gnupg/', dest='gpg' };
{secure=true, zip=true, mirror=true, source='~/.config/', dest='cfg' };
{secure=true, zip=true, mirror=true, source='~/.mozilla/', dest='firefox'};
{secure=true, zip=true, mirror=true, source='~/Документы/',dest='doc' };
-- diffrerent media --
{secure=false,zip=true, mirror=true, source='~/Книги/', dest='book'};
{secure=false,zip=true, mirror=true, source='~/Музыка/',dest='music'};
-- backup multimedia --
{secure=false, zip=false, versions=false, source='~/FAMILY_ARCHIVE/', dest='family'};
-- backup dev stuff --
{secure=false, zip=false, versions=true, source='~/.gitconfig',dest='gitconfig'};
{secure=false, zip=false, versions=true, source='~/.vimrc', dest='vimrc'};
{secure=false, zip=false, versions=true, source='~/.bashrc', dest='bashrc'};
{secure=false, zip=true, versions=true, source='~/.vim/', dest='vim'};
-- backups source code --
{secure=false, zip=true, mirror=true, source='/mnt/STORAGE/', dest='code'};
};
};
-------------------------------------------------------------------------------
-- :secure=true - шифровать ли сжатый бекап с паролем.
-- создать архив и запаролить, zip должен быть zip=true
-- явное указание zip=false или отсуцтвие ключа создаст ошибку
-- ----------------------------------------------------------------------------
-- :secure=false - тоже самое поведение что и при zip=false
-- ----------------------------------------------------------------------------
-- :zip=true - создать архив и добавить в него файлы если их нет в архиве
-- если version=false то обновлять архив, добавляя новые
-- файлы и обновля существующие, не удаляет отсуцтвующие
-------------------------------------------------------------------------------
-- :zip=false - создавать бекап в каталоге dest если versions=false
-- то клонировать source в dest, при повторном бекапе добавлять
-- новые файлы и обновлять текущие, не удалять отсуцтвующие
-- если versions=true создавать отдельный бекап в новом
-- каталоге с датой бекапа, полностью отельный бекап.
-------------------------------------------------------------------------------
-- :versions=true - если zip=false то создать новый каталог с датой бекапа
-- если zip=true то создать новый архив с датой бекапа
-------------------------------------------------------------------------------
-- :mirror=true - если zip=true то создаётся точная сжатая копия источника
-- если при этом versions=false то текущий архив удаляет из
-- себя файлы которых больше нет в источнике
-- если zip=false то вместо архива создаётся точная копия
-- источника с удалением файлов из каталога бекапа если их
-- нет в источнике, тоже самое зеркалирование/клонирование
-------------------------------------------------------------------------------
-- :source - файл или каталог который нужно бекапить, каталоги
-- обрабатываются рекурсивно бекапя всё что есть
-------------------------------------------------------------------------------
-- :dest - каталог внутри носителя для бекапа, оно же префикс
-- добавляющийся к каталогам и/или архивам при versions=true
-- отражает то бекап чего делается ОБЯЗАН БЫТЬ УНИКАЛЬНЫМ!!!!
-------------------------------------------------------------------------------
-- Если какого либо ключа нет то он считается равным false
-------------------------------------------------------------------------------
-- В случае если zip mkdir или rsync завершаться с кодом отличным от нуля
-- бекап тут же прекращается с уведомлением на рабочий стол и в лог ошибок
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
---- исполняет все команды, в случае ошибки прерывает всю работу
-------------------------------------------------------------------------------
local function execute(rule,command,exit_if_fail)
local success, meta, code = os.execute(command..' >> backup-info.log');
if (not success) then
-- hide pass from output
-- info log and messages
if rule.backup_pass then
command = command:gsub(rule.backup_pass,"********");
end
local msg = string.format('BACKUP ERROR %s %s %s',command,meta,code);
io.stderr:write(msg..'\n');
io.open('backup-error.log','a+'):write(msg);
execute({},'notify-send "'..msg..'" -u critical',false);
if (exit_if_fail == true) then
os.exit(127);
end
return success;
end
return success;
end
-------------------------------------------------------------------------------
--- информирует об ошибке и прерывает всю работу
-------------------------------------------------------------------------------
local function backup_fail(msg)
io.stderr:write(msg..'\n');
io.open('backup-error.log','a+'):write('\n'..msg..'\n');
execute({},'notify-send -u critical "'..msg..'"',false);
os.exit(127);
end
-------------------------------------------------------------------------------
--- просто информирует
-------------------------------------------------------------------------------
local function backup_info(msg)
io.stdout:write(msg..'\n');
local log = io.open('backup-info.log','a+');
log:write('\n'..msg..'\n');
log:close();
execute({},'notify-send -u normal "'..msg..'"',false);
end
-------------------------------------------------------------------------------
--- проверяет используется ли в конфигурации пароль
-------------------------------------------------------------------------------
function check_need_pass(rule)
for name,val in pairs(rule.backup_list) do
if val.secure and val.secure == true then
return true;
end
end
return false;
end
-------------------------------------------------------------------------------
--- делает бекап K.O. :)
-------------------------------------------------------------------------------
local function make_backup(rule)
if (rule.backup_path) then
-- replaice $USER in path if we have ite
rule.backup_path = rule.backup_path:gsub('$USER',os.getenv('USER'));
else
backup_fail('BACKUP ERROR backup_path not set, no place to save backup',true);
end
-- we use password?
if (check_need_pass(rule) == true) then
-- check pass contained in configuration
if not rule.backup_pass and not rule.backup_pass_file then
backup_fail('BACKUP ERROR you use secure option but backup_pass or backup_pass_file no set!',true);
end
-- if pass_file set read the password
-- and override/write rule.backup_pass
if (rule.backup_pass_file) then
-- replaice $USER in path if we have ite
rule.backup_pass_file = rule.backup_pass_file:gsub('$USER',os.getenv('USER'));
local pass_file = io.open(rule.backup_pass_file);
if (pass_file) then
if rule.backup_pass then
backup_info('BACKUP WARNING rewrite backup_pass from backup_pass_file');
end
rule.backup_pass = pass_file:read('*l');
else
backup_fail('BACKUP ERROR '..rule.backup_pass_file..' no readable!',true);
end
pass_file:close();
end
-- maybe pass use only numbers force to string
rule.backup_pass = tostring(rule.backup_pass);
-- check small pass, no need but jut be
if not rule.backup_pass or #rule.backup_pass <= 4 then -- kek cheburek
backup_info('BACKUP WARNING you backup_pass small, less or equal 4 symbols');
end
end
-- info about starting
backup_info("BACKUP START "..os.date());
--first check, we have storage and access?
execute(rule,'mkdir -p '..rule.backup_path, true);
-- lockfile + uuid for exclude collisions
local lockfile = '.lock-938448fc-1742-43e9-bff8-e2acf6d29710';
-- check/create lock file
-- if backup failed you self
-- delete lock file your hands
if not io.open(rule.backup_path..'/'..lockfile,'r') then
io.open(rule.backup_path..'/'..lockfile,'w'):write('lock');
else
backup_fail("OTHER BACKUP PROCESS IS WORKING, SKIPPING THIS PROCESS\n"..
"IF YOU SURE DELETE LOCK FILE "..rule.backup_path..'/'..lockfile..'\n',true);
----------------------------------------------------------------------
-- uncomment if after backup error no need locked backup for fix error
----------------------------------------------------------------------
-- os.remove(rule.backup_path..'/'..lockfile);
end
for id,item in pairs(rule.backup_list) do
local date = os.date("%Y-%m-%d_%X");
local path = rule.backup_path;
local pass = rule.backup_pass;
local dest = item.dest;
local source = item.source;
if (not source) then
backup_fail('BACKUP ERROR source path not set, what files backup?',true)
end
if (not dest) then
backup_fail('BACKUP ERROR dest path not set, wheare dir name to save?',true)
end
execute(rule,'mkdir -p '..path..'/'..dest,true);
backup_info('BACKUP: '..source);
------------------- secure: versionize backup data ---------------------
------------------------------------------------------------------------
if (item.secure and item.zip and item.versions) then
local target = string.format('%s/%s/%s-%s.zip',path,dest,dest,date);
execute(rule,'zip -r9P '..pass..' '..target..' '..source,true);
goto next_item;
end
---------------- secure: update and append backup data -----------------
------------------------------------------------------------------------
if (item.secure and item.zip and not item.versions) then
local target = string.format('%s/%s/%s.zip',path,dest,dest);
local opts = item.mirror and ' -rFS9P ' or ' -ru9P ';
execute(rule,'zip '..opts..' '..pass..' '..target..' '..source,true);
goto next_item;
end
----------- no secure: zipped update and append backup data ------------
------------------------------------------------------------------------
if (not item.secure and item.zip and not item.versions) then
local target = string.format('%s/%s/%s.zip',path,dest,dest);
local opts = item.mirror and ' -rFS9 ' or ' -ru9 ';
execute(rule,'zip '..opts..' '..target..' '..source,true);
goto next_item;
end
----- no secure: zipped, versionize update and append backup data ------
------------------------------------------------------------------------
if (not item.secure and item.zip and item.versions ) then
local target = string.format('%s/%s/%s-%s.zip',path,dest,dest,date);
execute(rule,'zip -r9 '..target..' '..source,true);
goto next_item;
end
--------- no secure: versionize update and append, no delete -----------
------------------------------------------------------------------------
if (not item.secure and not item.zip and item.versions ) then
local target = string.format('%s/%s/%s-%s/',path,dest,dest,date);
execute(rule,'mkdir -p '..target);
execute(rule,'rsync -arv '..source..' '..target,true);
goto next_item;
end
----------------- no secure: update and append, no delete --------------
------------------------------------------------------------------------
if (not item.secure and not item.zip and not item.versions) then
local target = string.format('%s/%s/',path,dest);
execute(rule,'mkdir -p '..target);
local opts = item.mirror and ' -arv --delete ' or ' -arv ';
execute(rule,'rsync '..opts..' '..source..' '..target,true);
goto next_item;
end
------------------------------------------------------------------------
if (item.secure and not item.zip) then
backup_fail('BACKUP ERROR UNSUPPORT SECURE WITCHOUT ZIP ARCHIVE :(');
end
::next_item::
end
backup_info("BACKUP END "..os.date());
os.remove(rule.backup_path..'/'..lockfile);
end
-- check depends
execute({},"zip --version",true);
execute({},"rsync --version",true);
--execute({},"mkdir --version",true);
execute({},"notify-send --version",true);
-- start backup now
make_backup(backup_rule)
Всё. Досвиданья.
-- Зависимости -
---------------------------------------
-- curl - загрузка ёлочек -
-- scrot - снимок рабочего стола -
-- love2d - запуск снежка и ёлочек -
---------------------------------------
-- Создать каталог `новый_год` -
-- Создать в каталоге файл `main.lua` -
-- Скопировать в файл этот код. -
-- Используя терминал запутсить из -
-- созданного каталога программу -
-- -
-- Вот так запустить `love .` -
---------------------------------------
-- Управление -
---------------------------------------
-- Нажать 1 - установит фон рабочего -
-- стола в программе, как -
-- будто на нём идёт снег -
---------------------------------------
-- Нажать 2 - убрать сугробы, но снег -
-- то падает и они вырастут-
-- снова, но другие уже :) -
---------------------------------------
-- Нажать 3 - Загрузить и отобразить -
-- просту ёлочку -
---------------------------------------
-- Нажать 4 - Загрузить и установить -
-- нарядную новогоднюю ёлку-
---------------------------------------
-- Нажать 5 - Вернуть чёрный фон -
---------------------------------------
-- Нажать esc или q для выхода -
---------------------------------------
-- Программа проверяет время и если -
---------------------------------------
-- Время 23:45 - Загружается и отобра -
-- жается простая ёлочка-
---------------------------------------
-- Время 00:00 - Загружается и отобра -
-- жается нарядная ёлка -
---------------------------------------
-- Эти действия по времени происходят -
-- автоматически предупреждая о под- -
-- ходе и наступлении нового года гы -
---------------------------------------
-- Устанавливать ли фон автоматически -
---------------------------------------
local autobackround = false; --вкл/выкл
---------------------------------------
local sugrob = {}
local snow = {};
local snow_opacity = 0;
local screen_width = 0;
local screen_height= 0;
local tree_image = nil;
local background = nil;
local tree_opacity = 0;
local tree_url =
{
[1] = 'https://i.ibb.co/f24xCMp/1.png';
[2] = 'https://i.ibb.co/KLpSKdZ/2.png';
};
local once_call_tree_1 = true;
local once_call_tree_2 = true;
----------------------------------------
function get_app_path()
return love.filesystem.getSaveDirectory()..'/';
end
function load_tree(id)
if love.system.getOS() == 'Android' then
if id == 1 then
tree_image = love.graphics.newImage('tree_1.png');
end
if id == 2 then
tree_image = love.graphics.newImage('tree_2.png');
end
tree_opacity = 0;
return;
end
local path = get_app_path();
os.execute('curl '..tree_url[id]..' --output '..path..'tree.png');
if love.filesystem.getInfo('tree.png') then
tree_image = love.graphics.newImage('tree.png');
tree_opacity = 0;
end
end
function draw_tree()
if tree_image then
local w = love.graphics.getWidth()
local h = love.graphics.getHeight()
local sx,sy = w/tree_image:getWidth(),h/tree_image:getHeight();
love.graphics.setColor(1,1,1,tree_opacity);
love.graphics.draw(tree_image,0,0,0,sx,sy);
end
end
function update_tree(dt)
if tree_opacity < 1 then
tree_opacity = tree_opacity + 0.1 * dt;
end
end
function create_sugrob()
if love.system.getOS() == 'Android' then
return;
end
local x = love.graphics.getWidth()
local y = love.graphics.getHeight()
local s = x/y;
for i=1,50 do
local xp = love.math.random(0,x);
local cs = love.math.random(s*25,s*75);
table.insert(sugrob,{'fill',xp,y,cs,150})
end
end
function draw_sugrob()
if love.system.getOS() == 'Android' then
return;
end
love.graphics.setColor(0.95,0.95,1,1);
for i=1,#sugrob do
love.graphics.circle(sugrob[i][1],sugrob[i][2],sugrob[i][3]+sugrob[i][5],sugrob[i][4]);
end
end
function update_sugrob(dt)
local x,y = love.window.getMode();
for i=1,#sugrob do
if sugrob[i][5] > 0 then
sugrob[i][5] = sugrob[i][5] - love.math.random(0.0,i*0.05)
end
end
end
function create_snow()
local x = love.graphics.getWidth()
local y = love.graphics.getHeight()
local s = x/y;
for i=1,60 do
local xp = love.math.random(0,x);
local xy = love.math.random(0,y);
local cs = love.math.random(s*1,s*10);
table.insert(snow,{'fill',xp,xy,cs,0})
end
end
function draw_snow()
for i=1,#snow do
love.graphics.setColor(0.95,0.95,1,snow_opacity);
love.graphics.circle(snow[i][1],snow[i][2],snow[i][3],snow[i][4]+snow_opacity);
end
end
function lerp(from, to, t)
return t < 0.5 and from + (to-from)*t or to + (from-to)*(1-t)
end
function update_snow(dt)
local x,y = love.window.getMode();
if snow_opacity < 0.7 then
snow_opacity = snow_opacity + 0.1 * dt;
end
for i=1,#snow do
snow[i][3] = snow[i][3] + i * 0.5;
if snow[i][5] == 1 then
snow[i][2] = snow[i][2] + i * 0.25 + i * 0.5 + love.math.random(0,3);
elseif snow[i][5] == 0 then
snow[i][2] = snow[i][2] - i * 0.25 + i * 0.5 + love.math.random(0,3);
end
if(snow[i][3] > y + snow[i][4]) then
snow[i][3] = -snow[i][4];
snow[i][2] = love.math.random(0,x);
snow[i][5] = love.math.random(-1,1);
end
end
end
local button_colors =
{
{0.5,0.0,0.0,1},
{0.0,0.5,1.0,1},
{0.0,0.0,1.0,1},
{0.5,0.5,1.0,1},
{0.0,0.5,1.0,1},
}
local button_circles = {}
local show_controls = false;
function create_controls()
local x = love.graphics.getWidth()
local y = love.graphics.getHeight()
local pose_y = (y * 0.5);
local radius = (x * 0.01) * 5;
for i=1,5 do
local pose_x = radius*i * 3.5;
table.insert(button_circles,{'fill',pose_x,pose_y,radius,button_colors[i]})
end
end
function draw_controls()
if show_controls then
local b = button_circles;
for i=1,#button_circles do
love.graphics.setColor(unpack(b[i][5]));
love.graphics.circle(b[i][1],b[i][2],b[i][3],b[i][4]);
end
end
end
function update_controls(px,py)
if show_controls then
local b = button_circles;
for i=1,#button_circles do
local cx,cy,cr = b[i][2],b[i][3],b[i][4];
if((px - cx)^2 + (py - cy)^2 < cr^2) then
if i == 1 then set_background(); end
if i == 2 then sugrob = {}; create_sugrob(); end
if i == 3 then load_tree(1); end
if i == 4 then load_tree(2); end
if i == 5 then background=nil; end
end
end
end
end
function love.displayrotated(index, orientation)
sugrob = {};
create_sugrob();
snow = {};
create_snow();
snow_opacity = 0;
tree_opacity = 0;
button_circles = {};
create_controls();
end
function love.mousepressed(x,y)
if love.system.getOS() ~= 'Android' then
update_controls(x,y)
show_controls = not show_controls;
end
end
function love.touchpressed(b,x,y)
update_controls(x,y)
show_controls = not show_controls;
end
function love.load()
love.filesystem.write('init','x',1);
if love.filesystem.getInfo('icon.png') then
love.window.setIcon(love.image.newImageData('icon.png'));
end
love.window.setTitle("Маааленькой ёёёлочке холодно зимооой.")
if love.system.getOS() == 'Android' then
love.window.setMode(1280,720,{fullscreen=true,resizable=true,vsync=true});
screen_width = love.graphics.getWidth()
screen_height = love.graphics.getHeight()
else
love.window.setMode(0,0,{resizable=true,borderless=true})
love.window.setFullscreen(true,'desktop');
screen_width = love.graphics.getWidth()
screen_height = love.graphics.getHeight()
love.window.setMode(0,0,{resizable=true,borderless=true})
love.window.maximize()
end
create_sugrob()
create_snow()
create_controls()
end
function set_background()
if love.system.getOS() == 'Android' then
return;
end
local x,y = love.window.getMode();
love.window.minimize()
love.timer.sleep(1)
local path = get_app_path()
local status = os.execute('scrot -a '..screen_width-x..','..screen_height-y..','..x..','..y..' -o '..path..'screen.png');
love.window.restore()
love.window.maximize()
if love.filesystem.getInfo('screen.png') then
background = love.graphics.newImage('screen.png');
end
end
if autobackround then
set_background()
end
function love.keypressed(key)
if key == 'q' or key == 'escape' then
love.event.quit()
end
if key == '1' then set_background(); end
if key == '2' then sugrob = {}; create_sugrob(); end
if key == '3' then load_tree(1); end
if key == '4' then load_tree(2); end
if key == '5' then background=nil; end
end
function love.update(dt)
if os.date('%H%M') == '2345' then
if once_call_tree_1 then
load_tree(1);
once_call_tree_1 = false;
end
end
if os.date('%H%M') == '0000' then
if once_call_tree_2 then
load_tree(2);
once_call_tree_2 = false;
end
end
update_snow(dt)
update_tree(dt)
update_sugrob(dt)
end
function love.draw()
if background then
love.graphics.setColor(1,1,1,1);
love.graphics.draw(background)
end
draw_tree();
draw_sugrob();
draw_snow();
draw_controls();
end
Внешний вид. Видео. Досвиданья.
По просьбе apt_install_lrzsz сборки
Android Без сугробов и криво armeabi-v7a
, arm64-v8a
, x86
, x86_64
Appimage x86_64
LoveFile для ПК Любая ОС и архитекрута где есть Love2D
Добавил кнопки появляются и исчезают по нажатию на экране.
Как альтернатива нажатия 1
,2
,3
,4
,5
.
На Андроиде
часть не работает.
В истории правок этого сообщения есть прошлая версия, если с этой пробелмы, но прошлая только для ПК.
← предыдущие | следующие → |