- resources can now have fixed sizes git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3056 a95241bf-73f2-0310-859d-f6bbb57e9c96
499 lines
19 KiB
HTML
499 lines
19 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<TITLE>Resource Compiler</TITLE>
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF">
|
|
|
|
<H1>The rc resource compiler</H1>
|
|
|
|
<H2>Table of contents</H2>
|
|
|
|
<UL>
|
|
<LI><A HREF="#intro">Introduction</A></LI>
|
|
<LI><A HREF="#install">How to install</A></LI>
|
|
<LI><A HREF="#scripts">Writing resource scripts</A></LI>
|
|
<LI><A HREF="#advanced">Big fat resources</A></LI>
|
|
<LI><A HREF="#app">Application resources</A></LI>
|
|
<LI><A HREF="#compile">Compiling</A></LI>
|
|
<LI><A HREF="#decompile">Decompiling</A></LI>
|
|
<LI><A HREF="#authors">Authors</A></LI>
|
|
<LI><A HREF="#license">License</A></LI>
|
|
</UL>
|
|
|
|
<!-- *********************************************************************** -->
|
|
|
|
<A NAME="intro"></A>
|
|
|
|
<H2>Introduction</H2>
|
|
|
|
<P>In the world of BeOS programming, a "resource" is data that is bundled with
|
|
your application. Typical examples are the application's icons and its
|
|
signature, but you can attach any data you want (bitmaps, text, cursors, etc).
|
|
You stuff this data into a .rsrc file that will be linked to your application
|
|
when it is compiled.</P>
|
|
|
|
<P>Because .rsrc files have a binary file format, you need to use special tools
|
|
to edit them, such as FileTypes, QuickRes, or Resourcer. Alternatively, you can
|
|
use a "resource compiler". This is a command line tool that takes a text-based
|
|
resource script and turns it into a .rsrc file.</P>
|
|
|
|
<P>With a resource compiler, you express your resources as ASCII text using a
|
|
special definition language, which makes the resource files much easier to edit
|
|
and maintain. You no longer need separate GUI tools to build your .rsrc files,
|
|
and you can even automate the whole process by calling the compiler from your
|
|
Makefile or Jamfile. Resource scripts will also make your life easier if you
|
|
use CVS, because CVS doesn't handle .rsrc files very well.</P>
|
|
|
|
<P>BeOS R5 comes with an (experimental) resource compiler called "beres", and a
|
|
corresponding decompiler called "deres". rc is an open source replacement (and
|
|
enhancement) of these tools. It is (mostly) backwards compatible, so you should
|
|
be able to compile your old .rdef files without any problems.</P>
|
|
|
|
<!-- *********************************************************************** -->
|
|
|
|
<A NAME="install"></A>
|
|
|
|
<H2>How to install</H2>
|
|
|
|
<OL>
|
|
<LI>Copy <CODE>rc</CODE> into <CODE>/boot/home/config/bin</CODE></LI>
|
|
<LI>Copy <CODE>librdef.so</CODE> into <CODE>/boot/home/config/lib</CODE></LI>
|
|
<LI>Let's party!</LI>
|
|
</OL>
|
|
|
|
<!-- *********************************************************************** -->
|
|
|
|
<A NAME="scripts"></A>
|
|
|
|
<H2>Writing resource scripts</H2>
|
|
|
|
<P>Writing resource scripts is not difficult, although the syntax may take some
|
|
getting used to. A resource script is a plain text file with one or more
|
|
resource definition statements. In addition, it may contain C or C++ style
|
|
comments. By convention, resource script files have the extension ".rdef".</P>
|
|
|
|
<P>Here is an example of a simple resource script:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(1) true; /* this is a comment */
|
|
resource(2) 123; // and so is this
|
|
resource(3) 3.14;
|
|
resource(4) "hello world";
|
|
resource(5) $"0123456789ABCDEF";</PRE></BLOCKQUOTE>
|
|
|
|
<P>When compiled, this script produces a resource file with five resources. The
|
|
above example also illustrates the types of data that resources are allowed to
|
|
have: boolean, integer, floating point, character string (UTF-8), and raw data
|
|
buffer (hexadecimal).</P>
|
|
|
|
<P>By default, integer data is stored as a 32-bit int, and floating point data
|
|
is stored as a 4-byte float. If you want to change the way the data is stored,
|
|
you have to cast it:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(6) (int8) 123;
|
|
resource(7) (double) 3.14;</PRE></BLOCKQUOTE>
|
|
|
|
<P>You can cast integer data to the following types: int8, uint8, int16,
|
|
uint16, int32, uint32, int64, uint64, ssize_t, size_t, off_t, time_t, float,
|
|
double, raw. You can cast floating point data to: float, double, raw. You are
|
|
not allowed to cast boolean, string, or raw data to other types.</P>
|
|
|
|
<P>In addition to casting, you can also change the resource's type code. This
|
|
does not change the way the data is stored, only what it is called. To change
|
|
the type code of a resource:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(8) #'dude' 123;</PRE></BLOCKQUOTE>
|
|
|
|
<P>This changes the type of resource 8 to the four-character-code 'dude'. If
|
|
you did not change it, it would be 'LONG', which stands for 32-bit integer. By
|
|
changing the type code, you assign a new meaning to the resource. You can also
|
|
specify type codes as decimal or hexadecimal numbers:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(9) #200 123;
|
|
resource(10) #0xC8 123;</PRE></BLOCKQUOTE>
|
|
|
|
<P>For historical reasons, you may also enclose the type code in parens, but
|
|
that is not the preferred notation. Type casts and type codes can be
|
|
combined:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(11) #'dude' (int8) 123;
|
|
resource(11) (#'dude') (int8) 123;</PRE></BLOCKQUOTE>
|
|
|
|
<P>In the above examples, we have given the resources numeric IDs. The
|
|
combination of ID and type code must be unique in the resource file; you cannot
|
|
have two int32 resources with ID 1, for example. However, it is perfectly fine
|
|
(but not necessarily a good idea) to do the following, because the data types
|
|
are different:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(12) 123;
|
|
resource(12) "w00t!";</PRE></BLOCKQUOTE>
|
|
|
|
<P>For your own convenience, you can also name resources. Unlike the ID/type
|
|
code combination, names do not have to be unique. </P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(13, "Friday") "Bad Luck";</PRE></BLOCKQUOTE>
|
|
|
|
<P>Since it is likely that you will be using these resources from a C/C++
|
|
program, it may be convenient to refer to them by symbolic names instead of
|
|
hardcoded numeric ID's. The rdef format allows you to do this:</P>
|
|
|
|
<BLOCKQUOTE><PRE>enum
|
|
{
|
|
R_AppName = 1,
|
|
R_SomeOtherThing = 2
|
|
};
|
|
|
|
resource(R_AppName) "MyKillerApp";</PRE></BLOCKQUOTE>
|
|
|
|
<P>The compiler will automatically substitute the symbol R_AppName with the
|
|
number 1. (You don't have to start these symbol names with the prefix R_, but
|
|
it is somewhat of a convention.)</P>
|
|
|
|
<P>Now how do you tell your C/C++ app about these symbolic names? You simply
|
|
put the enum into a header file that you include both from your application's
|
|
source code and your rdef file. The header file, which we'll call
|
|
"myresources.h", now looks like this:</P>
|
|
|
|
<BLOCKQUOTE><PRE>enum
|
|
{
|
|
R_AppName = 1,
|
|
R_SomeOtherThing = 2
|
|
};</PRE></BLOCKQUOTE>
|
|
|
|
<P>And the rdef file becomes this:</P>
|
|
|
|
<BLOCKQUOTE><PRE>#include "myresources.h"
|
|
|
|
resource(R_AppName) "MyKillerApp";</PRE></BLOCKQUOTE>
|
|
|
|
<P>Don't let the .h suffix fool you: the header file is still considered to be
|
|
an rdef file, and must contain valid rdef syntax. If you add any other C/C++
|
|
code, your resource script will fail to compile. Of course, you shouldn't add
|
|
any other rdef syntax to the header either (unless you want your C++ compiler
|
|
to start complaining). Besides comments, the only safe thing to put in that
|
|
header file is the enum statement, because both rdef and C/C++ understand
|
|
it.</P>
|
|
|
|
<P>Just like IDs, symbolic identifiers can be combined with a name:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(R_AppName, "AppName") "MyKillerApp";</PRE></BLOCKQUOTE>
|
|
|
|
<P>If you don't specify a name, and invoke the compiler with the
|
|
<CODE>--auto-names</CODE> option, it automatically uses the symbolic ID for the
|
|
name as well. So the ID of the following resource is 1 (because that is what
|
|
R_AppName corresponds to) and its name becomes "R_AppName":</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(R_AppName) "MyKillerApp";</PRE></BLOCKQUOTE>
|
|
|
|
<!-- *********************************************************************** -->
|
|
|
|
<A NAME="advanced"></A>
|
|
|
|
<H2>Big fat resources</H2>
|
|
|
|
<P>The resources we have made so far consisted of a single data item, but you
|
|
can also supply a collection of data values. The simplest of these compound
|
|
data structures is the array:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(20) array { 1234, 5678 };</PRE></BLOCKQUOTE>
|
|
|
|
<P>An array is nothing more than a raw buffer. The above statement takes the
|
|
two 32-bit integers 1234 and 5678 and stuffs them into a new 64-bit buffer. You
|
|
can put any kind of data into an array, even other arrays:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(21) array
|
|
{
|
|
"hello",
|
|
3.14,
|
|
true,
|
|
array { "a", "nested", "array" },
|
|
$"AABB"
|
|
};</PRE></BLOCKQUOTE>
|
|
|
|
<P>It is up to you to remember the structure of this array, because array
|
|
resources don't keep track of what kind of values you put into them and where
|
|
you put these values. For that, we have messages. A message resource is a
|
|
flattened BMessage:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(22) message('blah')
|
|
{
|
|
"Name" = "Santa Claus",
|
|
"Number" = 3.14,
|
|
"Array" = array { "a", "nested", "array" },
|
|
"Other Msg" = message { "field" = "value" }
|
|
};</PRE></BLOCKQUOTE>
|
|
|
|
<P>A message has an optional "what" code, in this case 'blah', and one or more
|
|
fields. A field has a name (between double quotes), a value, and a data type.
|
|
By default, the field assumes the type of its data, but you can also specify an
|
|
explicit data type and type code in front of the field name:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(23) message('bla2')
|
|
{
|
|
"integer1" = (int8) 123, // use cast to change data type
|
|
int16 "integer2" = 12345, // specify data type
|
|
#'dude' "buffer1" = $"aabbccdd", // specify a new type code
|
|
#'dude' raw "buffer2" = $"aabbccdd" // you can also combine them
|
|
};</PRE></BLOCKQUOTE>
|
|
|
|
<P>A special type of message is the "archive". The BeOS API allows you to take
|
|
a BArchivable class and flatten it into a BMessage. You can also add such
|
|
archives to your resource scripts:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(24) #'BBMP' archive BBitmap
|
|
{
|
|
"_frame" = rect { 0.0, 0.0, 63.0, 31.0 },
|
|
"_cspace" = 8200,
|
|
"_bmflags" = 1,
|
|
"_rowbytes" = 256,
|
|
"_data" = array
|
|
{
|
|
... /* here goes the bitmap data */ ...
|
|
}
|
|
};</PRE></BLOCKQUOTE>
|
|
|
|
<P>So what's this "rect" thing in the "_frame" field? Besides arrays and
|
|
messages, the compiler also supports a number of other data structures from the
|
|
BeAPI:</P>
|
|
|
|
<BLOCKQUOTE><TABLE BORDER="1">
|
|
<TR><TH>type</TH><TH>corresponds to</TH><TH>fields</TH></TR>
|
|
<TR><TD>point</TD><TD>BPoint, B_POINT_TYPE</TD><TD>float x, y</TD></TR>
|
|
<TR><TD>rect</TD><TD>BRect, B_RECT_TYPE</TD><TD>float left, top, right, bottom</TD></TR>
|
|
<TR><TD>rgb_color</TD><TD>rgb_color, B_RGB_COLOR_TYPE</TD><TD>uint8 red, green, blue, alpha</TD></TR>
|
|
</TABLE></BLOCKQUOTE>
|
|
|
|
<P>To add a color resource to your script, you can do:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(25) rgb_color { 255, 128, 0, 0 };</PRE></BLOCKQUOTE>
|
|
|
|
<P>Or you can use the field names, in which case the order of the fields does
|
|
not matter:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(26) rgb_color
|
|
{
|
|
blue = 0, green = 128, alpha = 0, red = 255
|
|
};</PRE></BLOCKQUOTE>
|
|
|
|
<P>You can also make your own data structures, or as we refer to them,
|
|
"user-defined types". Suppose that your application wants to store its GUI
|
|
elements in the resources:</P>
|
|
|
|
<BLOCKQUOTE><PRE>type #'menu' menu
|
|
{
|
|
string name,
|
|
int32 count, // how many items
|
|
array items // the menu items
|
|
};
|
|
|
|
type #'item' menuitem
|
|
{
|
|
string name,
|
|
message msg,
|
|
bool enabled = true // default value is "true"
|
|
};</PRE></BLOCKQUOTE>
|
|
|
|
<P>A type has a name, an optional type code, and one or more fields. You are
|
|
advised not to pick a type code that already belongs to one of the built-in
|
|
types, to avoid any confusion. Each field has a data type, a name, and a
|
|
default value. If you don't specify a default, it is typically 0 or empty. To
|
|
create a new menu resource using the types from the above example, you might
|
|
do:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(27) menu
|
|
{
|
|
name = "File",
|
|
count = 3,
|
|
items = array
|
|
{
|
|
menuitem { "New...", message('fnew') },
|
|
menuitem { "Print...", message('fprt'), false },
|
|
menuitem { "Exit", message('_QRQ') }
|
|
}
|
|
};</PRE></BLOCKQUOTE>
|
|
|
|
<P>Like an array, a type resource doesn't remember its internal structure. You
|
|
can regard types as fancy arrays that are easier to fill in, a template if you
|
|
will. User-defined types work under the same rules as the built-in types point,
|
|
rect, and rgb_color, so you can specify the fields in order or by their names.
|
|
If you don't specify a field, its default value will be used.</P>
|
|
|
|
<P>Types can also have a default resource ID and/or name. If you omit to give
|
|
the resource an ID or a name, it uses the defaults from its data type. For
|
|
example, this:</P>
|
|
|
|
<BLOCKQUOTE><PRE>type myint { int32 i };
|
|
resource(10, "MyName") myint { 123 };</PRE></BLOCKQUOTE>
|
|
|
|
<P>Is equivalent to this:</P>
|
|
|
|
<BLOCKQUOTE><PRE>type(10, "MyName") myint { int32 i };
|
|
resource myint { 123 };</PRE></BLOCKQUOTE>
|
|
|
|
<P>And to save you even more typing, simple types that have only one field can
|
|
also be specified as:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource myint 123;</PRE></BLOCKQUOTE>
|
|
|
|
<P>Most data types have a fixed size; a uint16 is always 2 bytes long, a float
|
|
always comprises 4 bytes, and so on. But the sizes of string and raw data
|
|
resources depend on what you put in them. Sometimes you may want to force
|
|
these kinds of resources to have a fixed size as well. You can do this as
|
|
follows:</P>
|
|
|
|
<BLOCKQUOTE><PRE>type fixed { string s[64] };</PRE></BLOCKQUOTE>
|
|
|
|
<P>Any resources with type "fixed" will always contain a 64-byte string, no
|
|
matter how many characters you actually specify. Too much data will be
|
|
truncated; too little data will be padded with zeroes. Note that string
|
|
resources are always terminated with a null character, so string "s" in the
|
|
above type only allows for 63 real characters. The number between the square
|
|
brackets always indicates bytes (unlike C/C++ arrays which use a similar
|
|
notation).</P>
|
|
|
|
<P>If you have (large) binary files that you want to include in the resources,
|
|
such as pictures of Buffy, you don't need to convert the binary data to text
|
|
form first. You can simply "import" the file:</P>
|
|
|
|
<BLOCKQUOTE><PRE>resource(22) #'PNG ' import "buffy.png";</PRE></BLOCKQUOTE>
|
|
|
|
<P>Imported resources are always arrays (raw data), and you can specify the
|
|
import statement everywhere that array data is valid.</P>
|
|
|
|
<!-- *********************************************************************** -->
|
|
|
|
<A NAME="app"></A>
|
|
|
|
<H2>Application resources</H2>
|
|
|
|
<P>All BeOS applications (except command line apps) have a basic set of
|
|
resources, such as a MIME signature, launch flags, icons, and a few others.
|
|
Adding these kinds of resources is easy, because rc also has a number of
|
|
built-in types for that:</P>
|
|
|
|
<BLOCKQUOTE><TABLE BORDER="1">
|
|
<TR><TH>type</TH><TH>corresponds to</TH><TH>fields</TH></TR>
|
|
|
|
<TR><TD>app_signature</TD><TD>the app's MIME signature</TD><TD>string
|
|
signature</TD></TR>
|
|
|
|
<TR><TD>app_flags</TD><TD>application launch flags</TD><TD>uint32
|
|
flags</TD></TR>
|
|
|
|
<TR><TD>app_version</TD><TD>version information</TD><TD>uint32 major, middle,
|
|
minor, variety, internal<BR>string short_info, long_info</TD></TR>
|
|
|
|
<TR><TD>large_icon</TD><TD>32x32 icon</TD><TD>array of 1024 bytes</TD></TR>
|
|
|
|
<TR><TD>mini_icon</TD><TD>16x16 icon</TD><TD>array of 256 bytes</TD></TR>
|
|
|
|
<TR><TD>file_types</TD><TD>supported file types</TD><TD>message</TD></TR>
|
|
|
|
</TABLE></BLOCKQUOTE>
|
|
|
|
<!-- examples on how to fill in these resources -->
|
|
|
|
<P>Filling in these application resources is a little tricky with the current
|
|
version of rc. A future version will make this easier, when the user-defined
|
|
types mechanism becomes more powerful. For now, see the file
|
|
<CODE>tests/builtin.rdef</CODE> for more info.</P>
|
|
|
|
<!-- *********************************************************************** -->
|
|
|
|
<A NAME="compile"></A>
|
|
|
|
<H2>Compiling</H2>
|
|
|
|
<P>rc is a command line tool, which means you must run it from a Terminal
|
|
window. Typical usage example:</P>
|
|
|
|
<BLOCKQUOTE><PRE>rc -o things.rsrc things.rdef</PRE></BLOCKQUOTE>
|
|
|
|
<P>This tells rc that you wish to compile the script "things.rdef" to the
|
|
resource file "things.rsrc". The default name for the output file is
|
|
"out.rsrc", but you can change that with the <CODE>-o</CODE> or
|
|
<CODE>--output</CODE> switch, just like we did here.</P>
|
|
|
|
<P>You can specify multiple rdef files if you wish, and they will all be
|
|
compiled into one big resource file. If your rdef files #include files that are
|
|
not in the current working directory, you can add include paths with the
|
|
<CODE>-I</CODE> or <CODE>--include</CODE> option. For a complete list of
|
|
options, type <CODE>rc --help</CODE>.</P>
|
|
|
|
<P>If your project uses a Makefile, you can have rc automatically generate
|
|
the resource file for you:</P>
|
|
|
|
<BLOCKQUOTE><PRE>things.rsrc: things.rdef
|
|
rc -o $@ $^</PRE></BLOCKQUOTE>
|
|
|
|
<!-- also: how to integrate rc in jamfiles -->
|
|
|
|
<!-- *********************************************************************** -->
|
|
|
|
<A NAME="decompile"></A>
|
|
|
|
<H2>Decompiling</H2>
|
|
|
|
<P>Of course you can write the resource scripts by hand, but if you already
|
|
have a .rsrc file you can tell rc to decompile it. This will produce a
|
|
ready-to-go rdef script, and save you some trouble. (Although in some cases
|
|
it may be necessary to edit the script a little to suit your needs.) Note that
|
|
rc isn't limited to just .rsrc files; you can decompile any file that has
|
|
resources, including applications.</P>
|
|
|
|
<P>For example, to decompile the file "things.rsrc" into "things.rdef", do:</P>
|
|
|
|
<BLOCKQUOTE><PRE>rc --decompile -o things.rdef things.rsrc</PRE></BLOCKQUOTE>
|
|
|
|
<P>The decompiler produces an rdef resource script with the name "out.rdef",
|
|
but you can change that name with the <CODE>-o</CODE> or <CODE>--output</CODE>
|
|
switches. If you specify the <CODE>--auto-names</CODE> option, rc will also
|
|
write a C/C++ header file. Any resources whose name is a valid C/C++
|
|
identifier will be added to the header file. Now your program can access the
|
|
resource using this symbolic name.</P>
|
|
|
|
<P>Note: Even though rc can decompile multiple .rsrc files into one script, it
|
|
does not detect conflicts in resource names or IDs. In such cases, the
|
|
resulting .rdef and/or .h files may give errors when you try to compile
|
|
them.</P>
|
|
|
|
<!-- *********************************************************************** -->
|
|
|
|
<A NAME="authors"></A>
|
|
|
|
<H2>Authors</H2>
|
|
|
|
<P>The rc resource compiler and its companion library librdef were written by
|
|
<A HREF="mailto:[email protected]">Matthijs Hollemans</A> for the
|
|
<A HREF="http://www.openbeos.org">OpenBeOS</A> project. Thanks to Ingo Weinhold
|
|
for the Jamfile and the Jam rules. Comments, bug reports, suggestions, and
|
|
patches are welcome!</P>
|
|
|
|
<!-- *********************************************************************** -->
|
|
|
|
<A NAME="license"></A>
|
|
|
|
<H2>License</H2>
|
|
|
|
<P>Copyright (c) 2003 Matthijs Hollemans</P>
|
|
|
|
<P>Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:</P>
|
|
|
|
<P>The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.</P>
|
|
|
|
<P>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
DEALINGS IN THE SOFTWARE.</P>
|
|
|
|
</BODY>
|
|
</HTML>
|