Pull to refresh

Comments 20

В чём смысл добавления ресурсов подобным образом? Можно же просто генерировать c-array с данными ресурса в PreBuild скрипте.
Хороший способ, но не универсальный. Если у Вас много маленьких файлов, то исходник с ресурсами будет содержать кучи текста, который будет значительно замедлять компиляцию.

Хотя, если нужно добавить всего один или два файла в ресурсы, то Ваш способ, пожалуй, проще будет.
Пересобираться данный файл будет только при обновлении файлов-ресурсов — т.е довольно редко.
Так-то да. Но, всё же, долго. Кроме того, если программа в разработке и делается несколькими людьми, то добавлять ресурсы в неё будут не так уж и редко. И каждое такое добавление заставит всех, кто скачает злополучный коммит, снова ждать пересборки файла ресурсов.
Разработка с использованием Qt сопровождается именно таким способом использования ресурсов. Я бы не сказал, что это оказывает сколь-либо заметное влияние на время сборки проекта, особенно на фоне тормозов MinGW (если сборка идет под Windows). Конечно мне не приходилось сталкиваться с проектом, содержащим тысячи файлов ресурсов. Вполне допускаю, что в этом случае будет все как вы говорите.
Мне приходилось, это решается просто разбиением на отдельные .qrc-файлы, в каждом из которых будет разумное число ресурсов. Будут пересобираться только те сравнительно небольшие файлы, которые изменились (а меняются они намноого реже, чем код).
Тоже хороший вариант, но я, к сожалению, работаю без Qt. Во всяком случае, данный способ я искал именно исходя из требования максимально возможной универсальности.

PS: Хотя против Qt я ничего не имею и очень даже его люблю.
Ну да, понятно, что Qt — там много всего, и может быть много лишнего, для вашей какой-то конкретной задачи целый Qt может быть избыточен. Я о самой идее, что можно не один исходник на все ресурсы генерировать, а разбивать их на разные исходники, будут пересобираться только те, которые реально изменились — в ответ вот на это возражение:

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

Естественно, что для более узких задач можно придумать более удобные способы работы с ресурсами. И эти способы будут и проще и быстрее на своих задачах, но они не будут универсальны.

В ходе своих поисков я рассматривал все эти способы и, если это будет кому-то интересно, возможно сделаю в будущем статьи и по другим способам работы с ресурсами в программах для Linux.

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


И еще, а нельзя ли сделать секцию в ELF с кастомным именем и засунуть ресурс в нее?

Явно указывать имя ресурса было бы неплохо. По сути ради этого все эти «кривые скрипты» и написаны. А если бы они ещё и заголовочник для ресурсов генерировали, то вообще офигенно было бы. Но такого функционала я, в частности, в официальных манах не нашёл. Возможно плохо искал.

PS: И по поводу правки символов: а что Вам конкретно не нравится? Если Вы видите в моих скриптах ошибки или потенциально опасные места, то пожалуйста поделитесь со всеми. Если же Вам просто не нравится использование скриптов, при сборке, то, хочу заметить, что это лишь дело вкуса.
Я бы не заморачивался и накидал бы скрипт например на lua что бы он генерировал все необходимые бинарные данные.
Типа такого
[gen-res.lua]
function gen(data,name,h,c)
	local size,buf_size,buf,w,i,a,la,line
	size=data:seek("end") data:seek("set",0)
	h:write("enum { "..name.."_size="..size.." };\n")
	h:write("extern const unsigned char "..name.."["..name.."_size];\n")
	c:write("const unsigned char "..name.."[]={\n")
	a=0 w=16 buf_size=32 buf={}
	while buf do
		la=1
		while la<=#buf do
			line="\t"
			for i=1,w do
				if la>#buf then break end
				line=line..string.format("%3d",buf:byte(la))
				a=a+1 la=la+1
				if a<size then line=line.."," end
			end
			c:write(line.."\n")
		end
		buf=data:read(buf_size)
	end
	c:write"};\n"
end
function gen_list(list,hdr,src)
	local h,c,d
	hdr=hdr or "res.h" 
	src=src or "res.c" 
	h=io.open(hdr,"w+") or error "unable to create header"
	c=io.open(src,"w+") or error "unable to create source"
	h:write("// "..hdr.." : autogenerated file\n")
	h:write"#pragma once\n"
	for line in io.lines(list) do
		local name,fn=line:match"%s*(%S+)%s+(.+)%s*"
		if fn then 
			d=io.open(fn,"rb") or error("unable to open "..fn)
			gen(d,name,h,c)
			d:close()
		end
	end
	c:close()
	h:close()
end

gen_list "list.txt"

[list.txt]
res1 file1.dat
res2 file2.dat
res3 file3.dat

Хорошая штука. Но я искал максимально универсальный метод. Для изложенного мною метода нужно всего две вещи: GCC и BASH. Всё! Оба есть на любом Linux. Я понимаю, что можно придумать кучи специализированных методов работы с ресурсами, которые будут лучше во всём. Но они не будут универсальны. Мне нужен был именно универсальный метод. Я его нашёл. Подумал, что он ещё кому-то может быть нужен (ну мало-ли).

Вы немножко усложнили себе жизнь на ровном месте. Если давать ld относительные адреса и правильно устанавливать cwd, то получаются действительно нормальные символы:


~ 
➜ ld -r -b binary -o blob.o some/dir/to/blob.png               

~ 
➜ objdump -t blob.o                       

blob.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 g       .data  0000000000000000 _binary_some_dir_to_blob_png_end
0000000000000000 g       .data  0000000000000000 _binary_some_dir_to_blob_png_start
0000000000000000 g       *ABS*  0000000000000000 _binary_some_dir_to_blob_png_size

А если использовать абсолютные, то да, и символы будут с абсолютным путём
~ 
➜ ld -r -b binary -o blob.o $(realpath some/dir/to/blob.png)

~ 
➜ objdump -t blob.o                                         

blob.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 g       *ABS*  0000000000000000 _binary__home_prok_some_dir_to_blob_png_size
0000000000000000 g       .data  0000000000000000 _binary__home_prok_some_dir_to_blob_png_end
0000000000000000 g       .data  0000000000000000 _binary__home_prok_some_dir_to_blob_png_start

Не совсем в тему, просто забавный факт: GIMP умеет экспортировать картинки в сишный исходник:


/* GIMP RGB C-Source image dump (test.c) */

static const struct {
  guint          width;
  guint          height;
  guint          bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ 
  guint8         pixel_data[100 * 100 * 3 + 1];
} gimp_image = {
  100, 100, 3,
  "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
  "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
...

Спасибо! Красивое решение.

Sign up to leave a comment.

Articles

Change theme settings