aboutsummaryrefslogtreecommitdiff
path: root/docs/creating_a_rock.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/creating_a_rock.md')
-rw-r--r--docs/creating_a_rock.md438
1 files changed, 438 insertions, 0 deletions
diff --git a/docs/creating_a_rock.md b/docs/creating_a_rock.md
new file mode 100644
index 00000000..e93505ac
--- /dev/null
+++ b/docs/creating_a_rock.md
@@ -0,0 +1,438 @@
1# Creating a rock
2
3So, you wrote a Lua package (containing one or more modules) and want to make
4it available to users through LuaRocks. The process consists essentially of
5the following steps:
6
7* Writing a rockspec file
8* Publishing your code online
9* Submitting a rockspec for inclusion in the rocks server
10
11## Writing a rockspec
12
13A rockspec file is the metadata file for your package, containing all the
14information LuaRocks needs in order to fetch, build and install your package.
15The [Rockspec format](rockspec_format.md) supports various kinds of build
16systems, but in this tutorial we'll use LuaRocks' own built-in build system --
17that's why we're listing "Writing a rockspec" as the first step. We'll use the
18rockspec in place of a Makefile.
19
20A rockspec is actually a Lua file, but it is loaded in an empty environment,
21so there are no Lua functions available. A skeleton for a basic rockspec looks
22can be written by hand or generated using [luarocks write_rockspec](luarocks_write_rockspec.md).
23It may look like this:
24
25```lua
26package = "LuaFruits"
27version = "1.0-1"
28source = {
29 url = "..." -- We don't have one yet
30}
31description = {
32 summary = "An example for the LuaRocks tutorial.",
33 detailed = [[
34 This is an example for the LuaRocks tutorial.
35 Here we would put a detailed, typically
36 paragraph-long description.
37 ]],
38 homepage = "http://...", -- We don't have one yet
39 license = "MIT/X11" -- or whatever you like
40}
41dependencies = {
42 "lua >= 5.1, < 5.4"
43 -- If you depend on other rocks, add them here
44}
45build = {
46 -- We'll start here.
47}
48```
49
50This should be saved in a file called luafruits-1.0-1.rockspec. The name must
51contain lowercase versions of the "package" and "version" fields, or else
52LuaRocks will complain.
53
54There is some missing stuff in our rockspec which we will fill later, such as
55the source.url and description.homepage fields. We'll add those when we upload
56our sources whatever server you choose to.
57
58Right now our focus will be on the "build" section.
59
60### Building a module
61
62LuaRocks supports a number of "build types": "make" for using Makefiles,
63"cmake" for using CMake, etc. In this tutorial, however, we'll use its
64built-in build system, called the "builtin" type.
65
66```lua
67build = {
68 type = "builtin"
69 -- Now we need to tell it what to build.
70}
71```
72
73In the "builtin" type, we add a subtable called "modules", in which keys are
74module names in Lua notation, and values indicate how to build them. This
75example shows the various possibilities supported:
76
77```lua
78build = {
79 type = "builtin",
80 modules = {
81 -- A simple module written in Lua
82 apricot = "src/apricot.lua",
83
84 -- Note the required Lua syntax when listing submodules as keys
85 ["apricot.seeds"]("apricot.seeds") = "src/apricot/seeds.lua",
86
87 -- A simple module written in C
88 banana = "src/banana.c",
89
90 -- C modules can span multiple files.
91 cherry = {"src/cherry.c", "src/cherry_pie.c"},
92
93 -- C modules also support an extended syntax, supporting
94 -- cross-platform specifications of C defines, libraries and
95 -- paths for external dependencies.
96 date = {
97 sources = {"src/date.c", "src/cali_date.c", "src/arab_date.c"},
98 defines = {"MAX_DATES_PER_MEAL=50"},
99 libraries = {"date"},
100 incdirs = {"$(LIBDATE_INCDIR)"},
101 libdirs = {"$(LIBDATE_LIBDIR)"}
102 }
103 }
104}
105```
106
107Since modules written in Lua do not need to be compiled, LuaRocks only needs
108to know where they are in your source directory tree in order to copy them to
109the proper place on installation (see the "apricot" and "apricot.seeds" in the
110above example).
111
112Similarly, for C code with no dependencies on external libraries, it suffices
113to say where the sources are and LuaRocks will invoke the appropriate compiler
114and linker for the platform. You can use a simple string value for single-file
115modules, such as the "banana" example above or an array value for multiple
116source files (as in the "cherry" example).
117
118To make writing rocks for projects with a common directory layout even easier,
119the "builtin" build type recursively copies all files and directories it finds
120in a folder called "./lua" (if it exists) to the same place as other Lua
121files. It's almost as if an entry had been added to `modules` for every file
122in `lua`, except that the files will only be copied - files ending in ".c"
123won't be compiled.
124
125#### Depending on other rocks
126
127You can specify that your code depends on other rocks, so you can use modules
128from other rocks in your code and have them be automatically downloaded and
129installed when a user installs your rock.
130
131Suppose we need the modules from the "luaknife" rock, in order to cut our
132fruits. But we need version later than 2.3 of luaknife, because we're using
133functions that were introduced in that version. We'll add that to our
134dependencies table:
135
136```lua
137dependencies = {
138 "lua >= 5.1, < 5.4",
139 "luaknife >= 2.3"
140}
141```
142
143Note that the dependency on Lua itself is also given in that table, and that
144it uses two constraints on its version at once: `>= 5.1` and `< 5.4`. When
145several constraints are used like this, they all have to be satisfied.
146Therefore, `lua >= 5.1, < 5.4` means that our rock supports Lua `5.1`, `5.2`,
147and `5.3`, but not yet-to-be-released `5.4`. There are a few other operators
148for specifying version constraints, see
149[Rockspec format](rockspec_format.md#dependency-information).
150
151#### C modules linking to external libraries
152
153*If your code does not use third-party libraries, you may skip this subsection.*
154
155For building C code that links to C libraries, you can use the long syntax
156given in the "date" example above, in which sources are listed in the
157"sources" subtable. You need to specify the libraries to be linked in the
158"libraries" subtable. The library name is specified in a platform-independent
159way: in the above example, `libraries={"date"}` will result in `-ldate` for
160GCC on Unix and `DATE.LIB` for MSVC on Windows. (Note that if this is not
161appropriate, the rockspec format allows [per-platform
162overrides](platform_overrides.md).) If you need to link code that uses
163libraries, you need to tell LuaRocks where to find them. You do this by adding
164a new section to the rockspec:
165
166```lua
167external_dependencies = {
168 LIBDATE = {
169 header = "libdate.h"
170 }
171}
172```
173
174Adding the "external_dependencies" table will make LuaRocks search for the
175external dependencies in its lookup path (on Unix the defaults are
176`/usr/local` and `/usr`; on Windows, which doesn't have a standard for
177development trees, you'll probably have to specify it yourself through the
178[Config file format](config_file_format.md) or the [luarocks](luarocks.md) when
179invoking "luarocks"). We give a hint to LuaRocks, the `libdate.h` header, so
180it can test whether the development package is really there (on many Linux
181distros, one needs to install "-dev" packages in order to have all headers and
182libraries needed for compilation available, so header files are a good hint).
183In this case, for example, it would look for `/usr/local/include/libdate.h`
184and `/usr/include/libdate.h` on Unix. If you (or your users) have LibDate
185installed elsewhere, it's always possible to tell LuaRocks so through the
186command-line, passing for example `LIBDATE_DIR=/opt/libdate` as an argument.
187
188When LuaRocks succeeds finding an external dependency, it creates special
189variables for it which can be used in incdirs and libdirs fields. The example
190above shows two such variables, `LIBDATE_INCDIR` and `LIBDATE_LIBDIR` being
191use. It's important to always pass those variables: if LibDate happened to be
192in the system lookup path of your compiler, compilation would succeed without
193those variables, but they would fail in a user's system where they are
194somewhere else, such as in the `LIBDATE_DIR=/opt/libdate` example given
195earlier.
196
197### Using LuaRocks as a build system
198
199Now that your build section is written, you can use LuaRocks as a build system
200and have it compile and install your code as a rock. Just type:
201
202```
203luarocks make
204```
205
206and it will do its thing. Like "make", it will look for the appropriate rules
207file (in our case, the rockspec) in the current directory and then will
208proceed to build and install the package in your rocks tree, assuming the
209sources are in the current directory as well.
210
211### Including documentation and other files
212
213In the build section you can include arbitrary files through the
214"copy_directories" table. In this table you can list directories in your rock
215that will be copied to the target rocktree during installation.
216
217```lua
218 copy_directories = { "doc", "test" }
219```
220
221A special case for these is the "doc" directory for locally installed
222documentation. Documentation installed this way will be available on the
223target system through
224
225```
226luarocks doc ROCKNAME
227```
228
229## Publishing your code online
230
231Now, to complete the rockspec for public consumption we need to fill the
232sources.url field. For that, we need the code to be available online. We have
233two approaches for that: if you have your source code in an online repository
234such as [GitHub](GitHub)(https://github.com), you may use that directly.
235Alternatively, you can publish a tarball with the sources on the web.
236
237### Method 1: using a repository such as Github
238
239Make sure your release is tagged in your repository. Failing to use a tag will
240make LuaRocks point at your latest development code, making it a "moving
241target". LuaRocks users should be directed to a specific version of your code.
242(If you want to make a rockspec pointing at your repository's HEAD, use "scm"
243as the version number of your rockspec -- this will identify it as a rockspec
244for the "unstable" version.)
245
246In the `source.url` field, enter the URL for your repository using your SCM tool
247as the protocol. For git repositories, you don't need use the .git extension.
248Then, use the `source.tag` entry to specify your tag. For example, this is how
249our source section would look like if we hosted LuaFruits on Github:
250
251```lua
252source = {
253 url = "git://github.com/me/luafruits",
254 tag = "v1.0",
255}
256```
257
258To tag a release in Git, use the "git tag" command, and remember to pass the
259"--tags" flag to "git push":
260
261```
262git tag v1.0
263git push --tags
264```
265
266Or use GitHub's "Releases" interface.
267
268LuaRocks also supports other source control management systems, such as CVS
269(cvs://), Subversion (svn://) and Mercurial (hg://).
270
271Don't worry about deployment complications when using this method. When you
272submit a rock for inclusion in the LuaRocks repository, a .src.rock file is
273generated which contains a copy of the source code, so LuaRocks users won't
274need to have Git or any other such tool installed to use your rock.
275
276### Method 2: publishing a tarball
277
278When using a zip or tarball, by default LuaRocks expects it to contain a
279top-level directory with your code. This directory should be named the same as
280the tarball itself (but without the .zip or .tar.gz extension) and its
281recommended that this name be the lowercase name of the package with its
282version number (but without the LuaRocks revision number). If your code is
283located in a different directory, please see [Rockspec
284format](rockspec_format.md) for instructions. In our example, we should make a
285tarball with the following contents:
286
287```
288luafruits-1.0/
289luafruits-1.0/src/apricot.lua
290luafruits-1.0/src/apricot/seeds.lua
291luafruits-1.0/src/banana.c
292luafruits-1.0/src/cherry.c
293luafruits-1.0/src/cherry_pie.c
294luafruits-1.0/src/date.c
295luafruits-1.0/src/cali_date.c
296luafruits-1.0/src/arab_date.c
297```
298
299Note that the rockspec itself doesn't need to be stored in the tarball
300(actually, storing the final rockspec inside the package is a chicken-egg
301problem because rockspecs can contain the source.md5 field with a checksum of
302the tarball).
303
304It's important to note that LuaRocks does not enforce the internal structure.
305Our example only has a src/ subdirectory because the build rules listed above
306used it (we could have done without it if we wanted to). The tarball could
307contain other files as well, such as licenses and documentation. The only
308convention used here is the top level directory name, and if desired this can
309be overridden in the rockspec using the sources.dir field. So, now we pack our
310code. On Unix, for example, that would be:
311
312```
313tar czvpf luafruits-1.0.tar.gz luafruits-1.0/
314```
315
316And now we're ready to publish the tarball online. You can upload it to any
317public web server; if you need hosting space, you can use the Pages feature
318from [GitHub](GitHub)(https://github.com). Your source section would then look
319something like this:
320
321```lua
322source = {
323 url = "http://me.github.com/luafruits/luafruits-1.0.tar.gz"
324}
325```
326
327## The completed rockspec
328
329We're ready to complete our rockspec. By now it will look like this:
330
331```lua
332package = "LuaFruits"
333version = "1.0-1"
334source = {
335 url = "git://github.com/me/luafruits",
336 tag = "v1.0",
337}
338description = {
339 summary = "An example for the LuaRocks tutorial.",
340 detailed = [[
341 This is an example for the LuaRocks tutorial.
342 Here we would put a detailed, typically
343 paragraph-long description.
344 ]],
345 homepage = "http://me.github.com/luafruits",
346 license = "MIT/X11"
347}
348dependencies = {
349 "lua >= 5.1, < 5.4",
350 "luaknife >= 2.3"
351}
352external_dependencies = {
353 LIBDATE = {
354 header = "libdate.h"
355 }
356}
357build = {
358 type = "builtin",
359 modules = {
360 apricot = "src/apricot.lua",
361 ["apricot.seeds"]("apricot.seeds") = "src/apricot/seeds.lua",
362 banana = "src/banana.c",
363 cherry = {"src/cherry.c", "src/cherry_pie.c"},
364 date = {
365 sources = {"src/date.c", "src/cali_date.c", "src/arab_date.c"},
366 defines = {"MAX_DATES_PER_MEAL=50"}
367 libraries = {"date"},
368 incdirs = {"$(LIBDATE_INCDIR)"},
369 libdirs = {"$(LIBDATE_LIBDIR)"}
370 }
371 },
372 copy_directories = { "doc", "test" }
373}
374```
375
376## Submitting a rockspec for inclusion in the rocks server
377
378### Web upload
379
380This is the simplest step: just create an account at
381https://luarocks.org/register and upload your rockspec. It will automatically
382be included in the public LuaRocks repository once the mirror propagates the
383change. Users of LuaRocks >= 2.2 will be able to download your package
384immediately. We will usually publish both the .rockspec file and the
385appropriate .rock file in the server.
386
387### Pack command
388
389You can also create .rock files yourself. If you run the [luarocks
390pack](luarocks_pack.md) command on your rockspec, like this:
391
392```
393luarocks pack luafruits-1.0-1.rockspec
394```
395
396you will get a file called luafruits-1.0-1.src.rock, which contains the
397rockspec itself and your sources. Since it contains the source code, users
398won't need to use Git or whatever tool specified in source.url to fetch the
399code; it's all in the rock.
400
401If you have the rock installed in your local tree, you can also pack the
402binaries you just built:
403
404```
405luarocks pack luafruits
406```
407
408(The version is optional, latest is assumed.) This will create a file with a
409name such as luafruits-1.0-1.linux-x86.rock.
410
411### Upload command
412
413When you've verified that creating the rock works, you can upload it to the
414LuaRocks server with the [luarocks upload](luarocks_upload.md) command:
415
416```
417luarocks upload luafruits-1.0-1.rockspec --api-key=<your API key>
418```
419
420You can get an API from the [settings page of your account on the LuaRocks web
421site](https://luarocks.org/settings/api-keys).
422
423## Conclusion
424
425And we're done -- by writing a simple rules file which simply describes which
426sources compose the project and which libraries they use, we actually achieved
427a lot behind the scenes: LuaRocks takes care of using the right compiler for
428your platform (GCC? MSVC?), passing the right flags (-fpic? -shared? -bundle
429-undefined dynamic_lookup?) and checking external dependencies (/usr/lib?
430/usr/local/lib? Is it really there?). Getting all these little portability
431details right is not always easy to do on hand-written Makefiles, so that's
432why we recommend using LuaRocks's own build system whenever possible. There
433are many other features of LuaRocks we haven't covered in this tutorial
434(per-platform overrides, support for command-line scripts, etc.), but this
435should get you started.
436
437
438