aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 5bf1335054d3986523313760d31e3c6e926c622b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# Overview

This is Common [IPS](http://www.oracle.com/technetwork/server-storage/solaris11/technologies/ips-323421.html)
Build System (CIBS). It intend to replace all userland-hell known from OpenSolaris and OpenIndiana.

CIBS is inspired by [Common Debian Build System](http://cdbs-doc.duckcorp.org/en/cdbs-doc.xhtml)

Major features are:

* Makefile-based (need GNU `make`)
* Modular design (include `autotools.mk` for GNU configure, or `cmake.mk` for CMake-based packages)
* Tracking build dependencies
* Building packages independently (no more terrible "consolidations" or "incorporations")


To create and publish an IPS package you need:

* CIBS package installed (`pkg:/developer/pkg/cibs`)
* `Makefile` describing what and how you are building
* At least one canonical IPS manifest.
 
 
Look into directory `examples` for examples.


# Best practices

## Split development file and runtime

In contrast to some crazy distributions (like Solaris or Arch Linux)
we *do* split runtime and development files (as Debian does).

Any shared library should be packaged into separate package reflecting
library's soname, e. g. `library/gmp10` includes libgmp.so.10. Nothing else.
But `library/gmp` includes headers, man pages, maybe static libraries etc. -
anything that required to build applications using GMP. Both packages -
`library/FOO` and `library/FOOxxx` are built from the same source, and
`library/FOO` must depend on `library/FOOxxx` in such a way:

    depend fmri=pkg:/library/FOOxxx@$(ips-version) type=require
    depend fmri=pkg:/library/FOOxxx@$(ips-version) type=incorporate

The trick is that IPS will use `library/FOOxxx` to fulfil runtime
dependencies, and we will be allowed to perform smooth migration
on newer library (e. g. `library/FOOyyy`) without breaking existing
packages. Of course, newer `library/FOO` will depend on `library/FOOyyy`,
but `library/FOOyyy` can be installed along with `library/FOOxxx`.
Again, `library/FOOyyy` and `library/FOOxxx` must be installable together
so none of them can ship docs, man pages or images or anything,
but a shared library itself.

Another example is Node.js or Python. Use `developer/nodejs` and
`runtime/nodejs` package for development files and runtime.
`runtime/nodejs` includes only the binary - `/usr/bin/nodejs` -
and maybe other runtime files, man pages etc.



# CIBS modules

## common.mk

This module defines common variables and targets. All other modules include this module,
and it should not be included directly, unless you are doing something really special.

### Targets provided by common.mk

All targets (but `clean`) provided by this module are abstract and
do nothing.  Other modules extend these targets. Each target has
its annex `target-stamp` which does the real job. Each `*-stamp` is
a file created with `touch` command. All internal dependencies are
implemented through these "stamps", but developer can use basename
for target, e. g. `make unpack` instead of `make unpack-stamp`.

Meaning of these targets depends on other included modules:

* `unpack` - put sources into the source directory (`./work/source` by default),
* `patch` - modify sources,
* `configure` - configure sources, e. g. execute GNU configure or CMake,
* `build` - build sources, e. g. compile with C compiler,
* `install` - install files into proto directory.

Each target in the list above depends on previous target. Yes, except `clean`.

`clean` has a [double-colon rule](http://www.gnu.org/software/make/manual/html_node/Double_002dColon.html)
and by default it is:

    clean::
        rm -f *-stamp
        rm -rf $(workdir)

### Building many variants

`common.mk` defines a macro `add-variant` to extend above targets and  to define
related variables such as `protodir.<variant>`. Calling `$(eval $(call add-variant,FOO))`
will add dependencies to configure-stamp, build-stamp,install-stamp and define
extra variables:

    variants += FOO
    protodir.FOO = $(workdir)/proto/FOO
    builddir.FOO = $(workdir)/build/FOO

    configure-stamp    : configure-FOO-stamp
    build-stamp        : build-FOO-stamp
    install-stamp      : install-FOO-stamp
    %-FOO-stamp: variant = FOO


The `add-variant` macro is used by `32.mk` and `64.mk` modules for
building 32-bit or 64-bit packages.  You may want to use it for any
other purpose, e. g. to compile Curl with OpenSSL or with GNU TLS.
Standard modules, such as `autotools.mk`, take care of every variant defined.
You can tune building by defining variables like `configure-options.FOO`, e. g.:

    $(eval $(call add-variant,ssl))
    $(eval $(call add-variant,gnu))

    configure-options.gnu = --without-ssl --with-gnutls
    configure-options.ssl = --with-ssl --without-gnutls

## autotools.mk

This module defines configure, build and install targets by GNU autotools.
These targets are implicit (e. g. `configure-%-stamp`), and you can completely
override any of them by explicit target (e. g. `configure-foo-stamp`) in the top Makefile.

Variable `configure` holds the name of the configure script ("$(sourcedir)/configure" by default).
You can redefine it if the configure script is not in the top source directory or has a different name.

Use the `configure-options` variable to append or replace options passed to the configure script.
Use the `configure-options.<variant>` to define variant specific options (see above).

Variable `configure-env` holds environment variables for the configure script,
such as CC, CFLAGS, LDFLAGS etc. As usual, you can append or completely replace them.
Use the `configure-env.<variant>` to define variant specific environment variant.

Build and install targets use target-specific variable `target` for invoking `make`.
This variable is empty for `build-%-stamp` and is set to "install" for `install-%-stamp`.
You can redefine it in the top Makefile to build/install only a subset of a package. E. g.
for NCurses with wide character support this will build and install only libraries (without
programs and terminal database):

    $(eval $(call add-variant,wide))
    build-wide-stamp: target = libs
    install-wide-stamp: target = install.libs

Another target-specific variable is "make-vars". The value of this variable
is appended to make command. By default it is set to `V=1`
for `build-%-stamp` (disable silent rules) and to `DESTDIR="$(protodir)"` for
`install-%-stamp`. You can append or completely replace "make-vars" to
make hacks or when you are using autotools.mk for packages which are not
actually use autotools, but some hand-made configure scripts.

## ips.mk

This module provides functions to work with IPS manifests and publish packages.

### Targets provided by ips.mk

* `publish` - publish IPS package into IPS repository
* `pre-publish` - make everything required to publish (including downloading archive,
patching, compiling, mogrifying manifests etc), but do not publish. Usefull for final
verifications what is going into IPS repository. All intermediate and final manifests
are in "work/manifests" directory.
* `build-dep` - install build dependencies

### Variables used by ips.mk

* `ips-repo` - IPS repository to publish, e. g. `make publish ips-repo=http://example.com:1234`

Any variable defined in Makefile will be passed to `pkgmogrify` and 
can be used in IPS manifests (*.p5m). This is especially useful
when with variable `ips-version`, which is by default `= version`.
Example is OpenSSL, where `version = 0.9.8x`, but `ips-version=0.9.8.23`
(because letters are not allowed by IPS).

These variables passed additionally:
`build32` = `#` or empty, and `build64` = `#` or empty. These variables can
be used to cut off some line in package manifest (by commenting out).
By default these vars are `#` (pound).
If module `32.mk` is included, `build32` becomes '' (empty), so lines like:

    $(build32) file path=usr/lib/libfoo.so.1

become uncommented. Same for modules `64.mk`.

Other automatic variables are `protodir.<variant>` and `builddir.<variant>`.
These variables hold paths to corresponding directories used to
install or build package. `<variant>` can be, for example, 32 or 64.
This allow exact specifying which file is requested, e. g.:

    file $(builddir.32)/libfoo.so.1 path=usr/lib/libfoo.so.1

## git.mk

Use this modules to get sources from Git repositories. With this module included
targets `download` and `unpack` mean the same thing - clone git reporitory into
source directory ("work/source"), then checkout given tag, commit or branch.

Makefile should define two variables:

* `git-url` - URL of Git repository, used as `git clone $(git-url) $(sourcedir)`
* `git-checkout` - Git tag, branch or commit; used as `git checkout $(git-checkout)`

For example see "examples/symlinks".

## hg.mk

Same as `git.mk`, but for [Mercurial](http://mercurial.selenic.com/)

Makefile should define two variables:

* `hg-url` - URL of mercurial repository, used as `hg clone $(hg-url) $(sourcedir)`
* `hg-update` - Mercurial tag, branch or commit; used as `hg update $(hg-update)`

## copy.mk

If this module is included, entire source tree will be copied
into all requested building directories. This is useful for
packages that do not support building out of source tree,
such as zlib or openssl.